4

ラズベリーパイ用のおもちゃのOSを絞り、MMUをセットアップしようとしています。仮想メモリを 3G:1G に分割したいので、実行時にコードを 0x8000 にロードしながら、コードを 0xC0008000 にリンクする必要があると思います。(0x8000 は、Linux 用にビルドされているため、現在のブートローダーがカーネルを見つけると予想するアドレスです)。

objdump をいじってみるとうまくセットアップできていると思いますが、うまくいきません。qemu でデバッグした後、ブートローダーが私のコードをまったく見つけられないと思います。

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 loop$」は、相対ブランチを使用する代わりに「b·c0008000」として生成されるため、機能しません。しかし、その部分は気にしないでください。問題は、エントリに到達しないことです)。

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

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

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

これらは、3 つのソース ファイルのみです。Makefile には興味深いものは何もないはずですが、make からの出力は次のとおりです。

$ 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でのデバッグによって引き起こされます。ブレークポイントは、仮想アドレスによって設定されます。MMU が有効になっておらず、物理アドレスで実行しているときに gdb が仮想アドレスを考慮しているため、「b エントリ」は機能しません。

したがって、MMU を有効にする前に、「b *0x8000」を使用する必要があります。これにより、正しくヒットするブレークポイントが設定されます。ただし、GDB にはデバッグ情報が表示されない (のようなソース コードがない) ため、まだ混乱しているよう0x00008004 in ?? ()です。「objdump -D」によって生成されたリストがあるので、それは大きな問題ではありません。

MMU を有効にして main に分岐すると、gdb は完全に機能します。重要なのは、絶対分岐を使用して仮想アドレスにジャンプすることです。b/bl相対ジャンプを発行します。だから私は使用しますldr pc =mainbxも動作します。

4

1 に答える 1

1

最後にそれを解決しました...

コードとリンク スクリプトに問題はありません。私が使用したqemuでデバッグが機能していないように見えるだけです。VMA==LMA の場合は機能しますが、この場合、カーネルは既に実行されており、qemu はそれを認識していません。または、ブレークポイントが失われ、gdb によってキャッチされません。

とにかく、新たに開始してビットを1つずつ追加することで、rpi(実際のハードウェア)で動作し、qemuでも動作します(gdbはまだブレークポイントをキャッチしません)。

したがって、私の質問は、qemu/gdb を使用してそのようなシナリオをデバッグする方法です。

(私の元の問題は、「クライアント」を使用する代わりに「ドメイン」権限を「マネージャー」に変更することで解決されます。ええ、これはおそらく一時的なものであり、変数を別の場所に設定する必要があります)。

于 2013-03-30T10:16:49.480 に答える