Autor Thema: Kernel an virtuelle Adresse laden  (Gelesen 17857 mal)

SSJ7Gohan

  • Beiträge: 398
    • Profil anzeigen
Gespeichert
« am: 21. May 2005, 19:50 »
Ich habe im Moment einen C Kernel, den ich mit GRUB an die physikalische Adresse 0x100000 laden lasse. Ich möchte jetzt den Kernel aber an die virtuelle Adresse 0xC0000000 laden lassen. Wie muss ich jetzt vorgehen um den Kernel an die Adresse 0xC0000000 mappen zu lassen? GRUB aktiviert ja soweit ich weiß kein Paging, und wenn ich in der linkfile 0xC0000000 angeben würde, dürfte der Kernel ja eigentlich nichtmehr funktionieren, da er die C-Funktionen die das Paging aktivieren nicht mehr findet, oder?

sp

  • Gast
Gespeichert
« Antwort #1 am: 21. May 2005, 19:59 »
Klingt so ein bisschen nach dem Henne-Ei-Problem :).
AFAIK kannst du das aber auch noch machen, nachdem der Kernel im Speicher liegt.
Sonst entweder einen eigenen Bootloader nutzen, oder ein extra Programm zwischen Grub und Kernel packen.

n3Ro

  • Beiträge: 288
    • Profil anzeigen
Gespeichert
« Antwort #2 am: 21. May 2005, 20:05 »
Hi,

du musst eigentlich nur 2 Dinge machen: 1. dein Linkfile so umändern, das es die physische Addressen für dein Coding (0x100000) UND die virtuellen Addressen (ab 0xc0000000) angibt,

Hier ein Bsp:

ENTRY(start)

g_virt = 0xc0000000;
g_phys = 0x00100000;

SECTIONS
{
    .text g_virt : AT(g_phys)
    {
g_code = .;_g_code = .;
*(.text)
*(.gnu.linkonce.t*)
*(.gnu.linkonce.r*)
*(.rodata*)
. = ALIGN(4096);
    }
    .data : AT(g_phys + (g_data - g_code))
    {
g_data = .;_g_data = .;
*(.data)
*(.gnu.linkonce.d*)
. = ALIGN(4096);
    }
    .bss : AT(g_phys + (g_bss - g_code))
    {
g_bss = .;_g_bss = .;
*(.bss)
*(COMMON)
*(.gnu.linkonce.b*)
. = ALIGN(4096);
g_end = .;_g_end = .;
    }
}


Als zweites musst du dafür sorgen, das dein Kernel als erstes das Paging hochfährt, sprich eine PageDirectory aufsetzen und Paging anschalten. Am besten du machst das im Assembler Coding, da weis man noch am besten was am ende rauskommt. Immer von Vorteil ist es dabei 4MB Pages zu verwenden, da du dir dadurch die PageTables ersparst.
Agieren statt Konsumieren!

SSJ7Gohan

  • Beiträge: 398
    • Profil anzeigen
Gespeichert
« Antwort #3 am: 21. May 2005, 22:13 »
Woher weiß der Prozessor denn dann ob die Addressen auf 0x10000 oder auf 0xc0000000 verweisen?

n3Ro

  • Beiträge: 288
    • Profil anzeigen
Gespeichert
« Antwort #4 am: 21. May 2005, 22:45 »
Der Prozessor nimmt die Addressen die reincompiliert sind, welche bei 0xc0000000 liegen, die physische Addresse ist nur im elf-binary vermerkt, damit GRUB weis, wo es das elf-binary hinladen soll; dort wird es auch ausgeführt! Das Problem ist nur, dass der Code bei 0x100000 läuft und alle Referenzen im Code auf 0xc0000000 zeigen, deswegen muss man auch in dieser Zeit auf alle Variablenzugriffe achten und die Addressen wenn nötig per Hand umrechnen lassen. Für Near-Jumps und -Calls ist das kein Problem, weil deren Sprungaddressen relative Werte sind und demnach unabhängig vom momentanen Instruction Pointer sind. D.h. kannst du beruhigt irgendwelche Funktionen aufrufen, solange alle Variablenzugriffe in diesen angepasst sind.
Agieren statt Konsumieren!

Roshl

  • Beiträge: 1 128
    • Profil anzeigen
    • http://www.lowlevel.net.tc
Gespeichert
« Antwort #5 am: 22. May 2005, 13:32 »
Nicht ganz korrekt Near-Jumps sind keine relativen angaben, dass ist nur bei Short jumps so;) near jump heisst, dass kein Selektor mit dazu angegeben wird. Near calls sind auch nicht relativ, short calls gibt es leider nicht.
Man müsste halt alles, ausser den shortjumps selbst umrechnen
[schild=1]Wieder ein wertvoller(?) Beitrag von Roshl[/schild]

n3Ro

  • Beiträge: 288
    • Profil anzeigen
Gespeichert
« Antwort #6 am: 22. May 2005, 14:28 »
erwischt ;-) Da hat doch jemand die Specs nicht richtig gelesen. Near Calls (Opcode 0xe8) und Near Jumps (Opcodes 0xeb und 0xe9) nehmen nur relative Angaben an! Es gibt noch absolute Angabemöglichkeiten (Opcode 0xff), nur da wird die Zieladdresse aus einem angegebenen Register oder einer angegebenen Speicherstelle geladen, sprich indirekt.
Wo immer absolute Addressen angegeben werden sind Far Jumps und Calls, sprich wenn noch der Segment Selector angegeben wird. Short Jumps sind ja nur eine Kurzform der NearJumps, die allerdings auch nur 127 bytes vor oder zurück im code springen können.

Aber das mit den nicht existenten ShortCalls stimmt :)
Agieren statt Konsumieren!

Roshl

  • Beiträge: 1 128
    • Profil anzeigen
    • http://www.lowlevel.net.tc
Gespeichert
« Antwort #7 am: 22. May 2005, 15:54 »
Ich hab die schon gelesen *grins*
Ist nur ne Bezeichnungsfrage hehe. Alles was relative Angaben annimmt bezeichne ich als short, was absolut annimmt aber kein Selektor/Segment als near und was absolut und selektor/segment nimmt als far.
Habs nur anders bezeichnet für mich (Und finde meine Einteilung auch logischer)
[schild=1]Wieder ein wertvoller(?) Beitrag von Roshl[/schild]

n3Ro

  • Beiträge: 288
    • Profil anzeigen
Gespeichert
« Antwort #8 am: 22. May 2005, 16:01 »
ist aber nicht die "offizielle" bezeichnung, sprich die die in den instruction set references steht ;-)
Agieren statt Konsumieren!

Roshl

  • Beiträge: 1 128
    • Profil anzeigen
    • http://www.lowlevel.net.tc
Gespeichert
« Antwort #9 am: 22. May 2005, 16:04 »
Da steht auch nicht drin, dass man lea zum rechnen benutzen kann, man machts aber trotzdem;)
[schild=1]Wieder ein wertvoller(?) Beitrag von Roshl[/schild]

n3Ro

  • Beiträge: 288
    • Profil anzeigen
Gespeichert
« Antwort #10 am: 22. May 2005, 16:10 »
naja, zumindest steht bei lea das man es zum berechnen von speicheraddressen benutzt, alles andere ist ja eigentlich nur zweckentfremdung
genauso gibt es ja auch kein kapitel wie man seinen rechner am besten freezt ( cli hlt )
Agieren statt Konsumieren!

Roshl

  • Beiträge: 1 128
    • Profil anzeigen
    • http://www.lowlevel.net.tc
Gespeichert
« Antwort #11 am: 22. May 2005, 16:24 »
cli;jmp $; ist lustiger da hat der prozessor wenigstens was zu tun;)
[schild=1]Wieder ein wertvoller(?) Beitrag von Roshl[/schild]

Legend

  • Beiträge: 635
    • Profil anzeigen
    • http://os.joachimnock.de
Gespeichert
« Antwort #12 am: 22. May 2005, 16:32 »
Generell kann man zumindestens beim GCC C-Code ohne globalen Variablen nehmen. Der ist PIC (Position Independant Code).
*post*

Roshl

  • Beiträge: 1 128
    • Profil anzeigen
    • http://www.lowlevel.net.tc
Gespeichert
« Antwort #13 am: 22. May 2005, 18:09 »
Eigentlich nicht, da bei C ja Call benutzt wird und das gibt es soweit ich weiss nicht mit relativen Adressen
[schild=1]Wieder ein wertvoller(?) Beitrag von Roshl[/schild]

DDR-RAM

  • Beiträge: 184
    • Profil anzeigen
Gespeichert
« Antwort #14 am: 22. May 2005, 18:12 »
Zitat von: Roshl
Eigentlich nicht, da bei C ja Call benutzt wird und das gibt es soweit ich weiss nicht mit relativen Adressen


near calls sind eip-relativ, genauso wie near jumps.

MfG
DDR-RAM

Roshl

  • Beiträge: 1 128
    • Profil anzeigen
    • http://www.lowlevel.net.tc
Gespeichert
« Antwort #15 am: 22. May 2005, 18:32 »
Ja die Calls vielleicht, aber wenn ich die Intel Doku richtig lese, dann wird auch beim relative near call die Rücksprungaddi absolut gespeichert. Und das könnte letzlich doch Probleme beim ret geben oder?
[schild=1]Wieder ein wertvoller(?) Beitrag von Roshl[/schild]

DDR-RAM

  • Beiträge: 184
    • Profil anzeigen
Gespeichert
« Antwort #16 am: 22. May 2005, 18:45 »
nein, es wird eip gespeichert.
Dieser ist absolut ja.
Wenn man den Speicher an diesem EIP verändert bzw. paging einschaltet und da was falsch macht, dann hat man Probleme, sonst nicht.

MfG
DDR-RAM

Legend

  • Beiträge: 635
    • Profil anzeigen
    • http://os.joachimnock.de
Gespeichert
« Antwort #17 am: 23. May 2005, 02:20 »
Genau. Den Wert den man da dann absolut auf den Stack gelegt bekommt, der stimmt ja auch! ;)
*post*

Svenska

  • Beiträge: 1 792
    • Profil anzeigen
Gespeichert
« Antwort #18 am: 23. May 2005, 10:41 »
Man könnte natuerlich auch den Kernel an eine gewisse Adresse laden, Paging einschalten und ihn dann an die gewünschte virtuelle Adresse kopieren :)
Dann hüpft man einfach rein und das Problem ist gelöst.

Kann GRUB den Kernel nicht irgendwoandershin laden?

Svenska

Legend

  • Beiträge: 635
    • Profil anzeigen
    • http://os.joachimnock.de
Gespeichert
« Antwort #19 am: 23. May 2005, 17:02 »
GRUB aktiviert Paging nicht, d.h. solange du nicht mehr als 3GB RAM hast, wirst du deinen Kernel wohl nicht an per GRUB an 0xC0000000 laden können! ;)
*post*

 

Einloggen