2013-03-29 1 views
3

Я отжимаю игрушку ОС для моей малины pi и пытаюсь настроить MMU. Я хочу разделить виртуальную память между 3G: 1G, поэтому я думаю, что мой код должен быть связан с 0xC0008000, а при выполнении - 0x8000. (0x8000 - это адрес, который текущие загрузчики ожидают найти ядро ​​- поскольку они созданы для Linux).linkscript - другой адрес ссылки и адрес загрузки

Я думаю, что все настроено нормально, выкапывая с помощью objdump, но это не работает. После некоторой отладки с qemu я думаю, что загрузчик не находит мой код вообще.

Я считаю, что проблема связана с моим linkscript, так как ядро ​​запускается нормально, если я перемещаю исходный код в свой раздел, который связан и загружен с 0x8000.

Я извлек скрипт и минимальный код. В следующем,

$ cat kernel.ld 
ENTRY(_start) 

SECTIONS 
{ 
    /* must == KERNLINK */ 
    . = 0xC0008000; 

    .text : AT(0x8000) { 
     *(.text) 
    } 

    .bss : { 
     *(.bss) 
    } 

    .data : { 
     *(.data) 
    } 

    .rodata : { 
     *(.rodata) 
    } 
} 

-

$ cat source/entry.S 
#include "mem.h" 

.globl _start 
_start = V2P(entry) 

.globl entry 
entry: 
    loop$: 
    b loop$ 

(«B петля $» не будет работать, так как он генерируется, как «б · c0008000» вместо того, чтобы использовать относительную ветвь Но не возражаю, что часть. , проблема в том, что он никогда не доходит до входа).

$ cat source/mem.h 
#define KERNLOAD 0x8000 

#define KERNBASE 0xC0000000 
#define KERNLINK (KERNBASE+KERNLOAD) 

#define V2P(va) ((va) - KERNBASE) 

Это только три исходных файла. Там не должно быть ничего интересного в Makefile, но на выходе из косметики есть

$ make 
arm-none-eabi-gcc -g -Wall -c -o build/entry.o source/entry.S 
arm-none-eabi-ld --no-undefined -T kernel.ld build/entry.o -Map kernel.map -o build/output.elf 
arm-none-eabi-objcopy build/output.elf -O binary kernel.img 

И objdump,

$ arm-none-eabi-objdump -h build/output.elf 

build/output.elf:  file format elf32-littlearm 

Sections: 
Idx Name   Size  VMA  LMA  File off Algn 
    0 .text   00000004 c0008000 00008000 00008000 2**0 
        CONTENTS, ALLOC, LOAD, READONLY, CODE 
    1 .ARM.attributes 00000014 00000000 00000000 00008004 2**0 
        CONTENTS, READONLY 
    2 .debug_line 0000003c 00000000 00000000 00008018 2**0 
        CONTENTS, READONLY, DEBUGGING 
    3 .debug_info 00000054 00000000 00000000 00008054 2**0 
        CONTENTS, READONLY, DEBUGGING 
    4 .debug_abbrev 00000014 00000000 00000000 000080a8 2**0 
        CONTENTS, READONLY, DEBUGGING 
    5 .debug_aranges 00000020 00000000 00000000 000080c0 2**3 
        CONTENTS, READONLY, DEBUGGING 

Я начинаю верить, я проглядел некоторые очевидные еще драгоценные детали.

==== Обновление ====

Как было отмечено в моем ответе ниже, путаница вызвана отладки в QEMU. Точки останова устанавливаются виртуальными адресами. «b entry» не работает, потому что gdb думает о виртуальном адресе, в то время как MMU не включен, и мы работаем по физическому адресу.

Итак, до того, как MMU включен, мы должны использовать «b * 0x8000». Это устанавливает точную точку останова. Однако GDB все еще запутался, поскольку он не отображает информацию об отладке (нет исходного кода, например 0x00008004 in ??()). Это не большая проблема, так как у меня есть листинг, созданный «objdump-D».

После того, как MMU включен и мы переходим на главную, gdb работает отлично. Суть заключается в том, чтобы перейти к виртуальному адресу, используя абсолютную ветвь. b/bl выдаст относительные прыжки. Поэтому я использую ldr pc =main. bx работает тоже.

+1

Смотрите: [Gnu ld дает неожиданный груз] (http://stackoverflow.com/questions/14453996/gnu-linker-map-file-giving-unexpected-load-addresses). Я думаю, вы используете путаницу 'load'. Обычно у вас есть ПЗУ и вы хотите скопировать раздел в ОЗУ. 'LOAD' помещает его в двоичный файл. Он не заставляет код работать по этому адресу. Вам нужно написать относительный код 'PC' для части загрузки. –

+0

Кажется, проблема qemu. – jsz

+0

Возможно, вы должны поместить свой * bootstrap * не-MMU-код в отдельный раздел. Например, '. = 0x8000; .boot: {boot.o (.text)} '. Я также воспользовался секцией сценария ['memory' linker] (http://ftp.gnu.org/old-gnu/Manuals/ld-2.9.1/html_node/ld_16.html) и, возможно, назвал разделы вашей памяти 'phys' и' virt'. Используйте 'AT', чтобы сказать, что адрес загрузки находится на * 0x8000 *. –

ответ

1

наконец решил его ...

код и linkscript не имеют проблем. Просто отладка не работает на qemu, который я использовал. Он работает, когда VMA == LMA, но в этом случае ядро ​​уже работает, и qemu об этом не знает. Или точка останова теряется и никогда не попадает в gdb.

В любом случае, начиная с нуля и добавляя бит по одному, я работаю над своим rpi (реальным оборудованием), а затем он работает и с qemu (gdb все равно не поймает точку останова).

Итак, мой вопрос должен состоять в том, как отлаживать такой сценарий с помощью qemu/gdb.

(Моя первоначальная проблема решена путем изменения разрешения «домена» на «менеджер», вместо того, чтобы использовать «клиент». Да, я знаю, что это, вероятно, временно, и я должен установить переменную в другом месте).

Смежные вопросы