Autor Thema: Speicherverwaltung  (Gelesen 49710 mal)

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« Antwort #40 am: 10. June 2008, 20:38 »
wie setze ich nur Paging mit nasm auf...  :roll:
Gibt doch genug Beispielcode dazu :roll: (zB. meinen beiden OS, siehe Signatur, beides higher half und beidesmal wird das in assemblercode initialisiert)
Nun ja, das Problem ist, dass die AT & T Syntax, oder wie auch immer mich immer verwirrt, weshalb dein Code mit nichts bringt.
Zitat
Stimmt doch garnicht, der pedigree Code ist nasm, siehe hier.

Zitat
Wie mach ich das jetzt?  :-D
siehe Link oben...
pedigree kernel @ 0xFF400000 (siehe auch hier)
lightOS
"Überlegen sie mal 'nen Augenblick, dann lösen sich die ganzen Widersprüche auf. Die Wut wird noch größer, aber die intellektuelle Verwirrung lässt nach.", Georg Schramm

ChristianF

  • Beiträge: 296
    • Profil anzeigen
    • DeutschOS - Betriebssystem Projekt
Gespeichert
« Antwort #41 am: 11. June 2008, 07:54 »
Nun das ist ja doch nicht so einfach, wie ich mir das gedacht habe.
bekomme ein Page not present von Bochs....
00008393105i[CPU0 ] (instruction unavailable) page not present
00008393105e[CPU0 ] exception(): 3rd (14) exception with no resolution, shutdown status is 00h, resetting

Folgenden Code habe ich mit Händen und Füßen geschrieben  :roll:
[BITS 32]

EXTERN __kernel_start__
EXTERN __kernel_end__
EXTERN main
EXTERN code, bss, end

global start
start:
; Points the Stack to the new stack area
mov esp, _sys_stack
jmp stublet

ALIGN 4
mboot:
; Multiboot macros make a few lines more readable
MULTIBOOT_PAGE_ALIGN equ 1<<0
MULTIBOOT_MEMORY_INFO equ 1<<1
MULTIBOOT_AOUT_KLUDGE equ 1<<16
MULTIBOOT_HEADER_MAGIC equ 0x1BADB002
MULTIBOOT_HEADER_FLAGS equ MULTIBOOT_PAGE_ALIGN | MULTIBOOT_MEMORY_INFO | MULTIBOOT_AOUT_KLUDGE
MULTIBOOT_CHECKSUM equ -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
KERNEL_VIRTUAL_BASE equ 0xC0000000
KERNEL_VIRTUAL_DIR_NUMBER equ (KERNEL_VIRTUAL_BASE >> 22)

dd MULTIBOOT_HEADER_MAGIC
dd MULTIBOOT_HEADER_FLAGS
dd MULTIBOOT_CHECKSUM

dd mboot
dd code
dd bss
dd end
dd start

boot_page_directory:
dd 0x00000083
times (KERNEL_VIRTUAL_DIR_NUMBER - 1) dd 0
dd 0x00000083
times (1024 - KERNEL_VIRTUAL_DIR_NUMBER - 1) dd 0

stublet:
mov ecx, (boot_page_directory - KERNEL_VIRTUAL_BASE)
mov cr3, ecx

mov ecx, cr4
or ecx, 0x00000010
mov cr4, ecx

mov ecx, cr0
or ecx, 0x80000000
mov cr0, ecx

lea ecx, [start_higher_half_kernel]
jmp ecx

start_higher_half_kernel:
;mov dword [boot_page_directory], 0
;invlpg[0]

; Parse the Magic number
push eax
; Parse the multiboot Structure
push ebx
; call main
;call _main

jmp $

SECTION .bss
resb 8192
_sys_stack:

Hier ist noch mein Linker-Script, dass ich nach meinen Bedürfnissen abgeändert habe:
OUTPUT_FORMAT("elf32-i386")
ENTRY(start)
phys = 0x00100000;
virt = 0xC0100000;
SECTIONS
{
. = virt;

.text virt : AT(phys)
{
__kernel_start__ = .;
code = .;
*(.text)
*(.rodata)
. = ALIGN(4096);
}
.data : AT(phys + (data - code))
{
data = .;
*(.data)
. = ALIGN(4096);
}
.bss : AT(phys + (bss - code))
{
bss = .;
*(.bss)
. = ALIGN(4096);
}
end = .;
__kernel_end__ = .;
}

Wo liegt mein Fehler?
Ich finde ihn nicht und meine nasm Kenntnisse, oder Generell Assemblerkenntnisse sind nicht so umwerfend gut.
Dann habe ich ausserdem noch eine Frage:
Kann ich anstatt der 4MB-Pages auch normale 4KB-Pages benutzen?
Oder hat das irgend einen Grund, dass in allen Code Stückern, die ich bis jetzt gesehen habe, die Page 4MB-Groß ist?
 
 
Gruß Christian
 
*EDIT*
Bei dem Code habe ich mich an dem Beispiel in der OSDev.org Wiki orientiert, allerdings nur das Paging.
« Letzte Änderung: 11. June 2008, 09:16 von ChristianF »

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« Antwort #42 am: 11. June 2008, 13:13 »
Ich würde erstmal vorschlagen, dass du die absoluten Calls/Jumps aus dem Assemblercode, der vor dem aktivieren des Pagings stattfindet, rausnimmst, da Labels an eine Adresse im Higher-Half zeigen und wenn du dahin springst kommt halt nur Mist raus.

Nun das ist ja doch nicht so einfach, wie ich mir das gedacht habe.
bekomme ein Page not present von Bochs....
Bei welcher Instruktion taucht denn das auf? Wäre wichtig zu wissen :wink:

Zitat
Kann ich anstatt der 4MB-Pages auch normale 4KB-Pages benutzen?
Natürlich kannst du das, aber da du (bzw. ich) sowieso später die 0-4MB nicht mehr gemappt haben möchtest, da der Kernel ja bei 0xC0000000 (bzw. halt irgendwo am oberen Ende) ist. Insofern sparst du dir den Aufwand eine page-table zu erstellen und am Ende sowieso wieder freizugeben. Das kommt natürlich nicht für lau, 4MB Pages sind erst ab dem Pentium 1 unterstützt und man muss bevor man sie verwendet Cr4.PSE (PSE = Page Size Extension, Bit 4) setzten.
lightOS
"Überlegen sie mal 'nen Augenblick, dann lösen sich die ganzen Widersprüche auf. Die Wut wird noch größer, aber die intellektuelle Verwirrung lässt nach.", Georg Schramm

ChristianF

  • Beiträge: 296
    • Profil anzeigen
    • DeutschOS - Betriebssystem Projekt
Gespeichert
« Antwort #43 am: 11. June 2008, 13:28 »
Moin
Ich habe das Higherhalf BareBones Tutorial von der OS-Dev Wiki gelesen,
und auch wenn meine Assemblerkenntnisse mehr schlecht als Recht sind, verstehe ich den Code soweit.
Link zum Tutorial
 
Ich werde den Code allerdings noch umschreiben, damit 4KB-Pages verwendet werden, damit der Code
auch auf einem älteren Prozessor läuft, vllt. auch i386  :roll: .

Dazu werde ich noch etwas Code einbauen müssen, der prüft, ob 4 MB RAM eingebaut sind. Wie ich das in ASM
realisiere, und wie ich Text mit Assembler im Protected Mode ausgebe, wenn keine 4 MB RAM installiert sind,
da werde ich schon noch dahinter kommen.
 
Kampfesgrüße Christian

nooooooooos

  • Beiträge: 734
    • Profil anzeigen
Gespeichert
« Antwort #44 am: 11. June 2008, 13:57 »
Hmm also i386 ist mal sicher nicht möglich... Paging funzt erst richtig ab einem i486...

Text in Asm kannst du ausgeben, wenn du ein Byte (Buchstabe) an jedes gerade Byte ab 0xb8000 ausgibst.

Also: mov [0xb8000],'a'
mov [0xb8002],'b'

Mit den ungeraden Bytes könntest du noch die Farben der Anzeige verändern....


Speicher auslesen geht am besten mit Grub, weil ders schon macht:D...Wenn dus selbst machen willst, musst du den int 0x15 mit ax=0xE820 nehmen, um ein brauchbares Resultat (d.h. mit Angaben die stimmen, wo du nichts essenzielles im Speicher kaputt machen könntest und wo auch Speicherbereiche angegeben sind, die du nicht brauchen darfst, weil von Hardware verwendet)...


Gruss
Noooooooooooos

ChristianF

  • Beiträge: 296
    • Profil anzeigen
    • DeutschOS - Betriebssystem Projekt
Gespeichert
« Antwort #45 am: 11. June 2008, 14:06 »
Ich hatte auch vor, das ganze mit GRUB zu machen.
Wie ich das mache, muss ich noch herausfinden. Ich kann mir ja mal die Beispiele anschaun.
 
Allerdings habe ich da noch eine Frage: Kann ich zum prüfen des RAMs einfach mem_upper, sowie mem_lower addieren?
Ich müsste dann nämlich prüfen, ob das Ergebnis größer oder gleich 4 MB ist.
Wenn es kleiner ist, wird eine Fehlermeldung ausgegeben, ansonsten geht es ganz normal weiter.

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« Antwort #46 am: 11. June 2008, 14:13 »
Hmm also i386 ist mal sicher nicht möglich... Paging funzt erst richtig ab einem i486...
Huh? Wie kommst du darauf?

Zitat
Allerdings habe ich da noch eine Frage: Kann ich zum prüfen des RAMs einfach mem_upper, sowie mem_lower addieren?
Ja, mem_lower und mem_upper sind grobe Werte wieviel Speicher vorhanden ist, aber die genauen Bereiche musst du dann in der (GRUB/BIOS) memory-map nachschauen. Die genauen Bereiche brauchst du dann halt zum initialisieren deiner Speicherverwaltung.
lightOS
"Überlegen sie mal 'nen Augenblick, dann lösen sich die ganzen Widersprüche auf. Die Wut wird noch größer, aber die intellektuelle Verwirrung lässt nach.", Georg Schramm

ChristianF

  • Beiträge: 296
    • Profil anzeigen
    • DeutschOS - Betriebssystem Projekt
Gespeichert
« Antwort #47 am: 11. June 2008, 14:27 »
Das heißt, ich muss in folgende Schritten machen:

  • ebx sichern
  • prüfe die ersten 4 Byte, ob mem_* benutzt werden kann (cmp ebx, (1<<0))
  • addiere 4 auf ebx
  • speichere den wert
  • addiere nochmals 4 zu ebx
  • speichere den wert wieder
  • addiere die beiden gesicherten werte
  • ebx wiederherstellen
  • prüfe, ob die Addition Größer 0x1000 ist
  • je nachdem dann Fehlermeldung ausgeben oder halt fortfahren

Habe ich was vergessen?
« Letzte Änderung: 11. June 2008, 14:41 von ChristianF »

nooooooooos

  • Beiträge: 734
    • Profil anzeigen
Gespeichert
« Antwort #48 am: 11. June 2008, 14:30 »
Hmm also i386 ist mal sicher nicht möglich... Paging funzt erst richtig ab einem i486...
Huh? Wie kommst du darauf?
Hatt ich mal irgendwie im Hinterkopf...aber anscheinend falsch...



EDIT: Das steht zum Beispiel in Homix' Paging Tutorial...(Ausgabe 8)

Gruss
Nooooooooooooos
« Letzte Änderung: 11. June 2008, 14:34 von nooooooooos »

ChristianF

  • Beiträge: 296
    • Profil anzeigen
    • DeutschOS - Betriebssystem Projekt
Gespeichert
« Antwort #49 am: 11. June 2008, 14:49 »
Habe mittlerweile folgenden Code:

; Check installed RAM
push ebx
push eax
cmp ebx, (1 << 0)
je error_no_mem_ul
xor eax, eax
add [ebx], 4
mov eax, ebx
add [ebx], 4
add eax, ebx
pop eax
pop ebx

Ich muss nun nur noch prüfen, ob der wert in eax größer ist als 4096, bzw. 0x1000.
Wie mache ich das, bzw. geht das mit Compair (cmp)?
« Letzte Änderung: 11. June 2008, 14:55 von ChristianF »

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« Antwort #50 am: 11. June 2008, 14:54 »
EDIT: Das steht zum Beispiel in Homix' Paging Tutorial...(Ausgabe 8)
Ist meines Erachtens nach trotzdem Unfug.

Zitat
Wie mache ich das, bzw. geht das mit Compair (cmp)?
Lern die Intel Manuals zu lesen oder lern zu googlen.
lightOS
"Überlegen sie mal 'nen Augenblick, dann lösen sich die ganzen Widersprüche auf. Die Wut wird noch größer, aber die intellektuelle Verwirrung lässt nach.", Georg Schramm

ChristianF

  • Beiträge: 296
    • Profil anzeigen
    • DeutschOS - Betriebssystem Projekt
Gespeichert
« Antwort #51 am: 11. June 2008, 15:49 »
Gut habs nun raus.

Eine Frage habe ich allerdings noch.
Und zwar muss ich prüfen, ob der Kernel von einem Multiboot Kompatiblen Bootloader geladen wurde.
Da ich GRUB benutze und das oberhalb als "define" stehen habe (0x1BADB002), habe ich mir gedacht, vergleiche ich das mit eax.
Wenn der vergleich schief läuft mache ich ein "Jump not equal" (jne) zur Fehlermeldung.
Das Funktioniert soweit auch, nur lasse ich meinen Kernel von GRUB laden, und es wird aber jedes mal ausgegeben, dass der Kernel nicht multiboot kompatibel ist.

hier noch ein bissel code:
MAGIC equ 0x1BADB002
....
....
cmp eax, MAGIC
jne error_not_multiboot

Wieso passiert das, wo der Kernel doch von Grub geladen wird ???

*EDIT*
Hat sich erledigt.
So was dummes...
ich hab das mit der Magic Number vom Multiboot Header verwechselt...
 
Richtig ist folgendes:
cmp eax, 0x2BADB002
« Letzte Änderung: 11. June 2008, 16:37 von ChristianF »

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #52 am: 11. June 2008, 17:01 »
Ich glaube, ich habe schonmal erwaehnt, dass du diese a.out-Kludge nicht brauchst, wenn du eh ELF nimmst. Magic, Flags und Pruefsumme sind absolut genug fuer einen Multiboot-ELF-Kernel. Mach die Sache nicht komplizierter als noetig.

Ach, und dass der 386 kein Paging kann, halte ich auch fuer ein Geruecht. Wahr ist aber (wenn ich mich nicht taeusche), dass erst der 486 ein invlpg kennt, beim 386 muss man den TLB immer komplett flushen.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

ChristianF

  • Beiträge: 296
    • Profil anzeigen
    • DeutschOS - Betriebssystem Projekt
Gespeichert
« Antwort #53 am: 11. June 2008, 18:03 »
Dieser ist entfernt worden.

Ach, und dass der 386 kein Paging kann, halte ich auch fuer ein Geruecht. Wahr ist aber (wenn ich mich nicht taeusche), dass erst der 486 ein invlpg kennt, beim 386 muss man den TLB immer komplett flushen.
Paging gibt es seit dem 386er.
Laut dieser Website: Link gibt es den Befehl invlpg erst ab dem 486er.
Wie ich den flush komplett von hand machen kann, dass der kernel auch theoretisch auf einem 386er läuft, finde ich wahrscheinlich über die Intel Docs raus, muss die mir mal intensiv zu gemüte führen.
 
Der Kernel wird geladen, ohne Reboot, mit 4 KB-Pages. Warum die physikalische Speicherverwaltung allerdings immer noch nicht funktioniert, ist mir ein Rätsel, das von mir gelöst werden will  :-D
 
Und, beinahe hätte ich es vergessen...  :-o
Vielen Dank für eure Geduld und Hilfe bei meinen "Problemchen"  :lol:

Gruß Christian

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #54 am: 11. June 2008, 18:29 »
Wie ich den flush komplett von hand machen kann, dass der kernel auch theoretisch auf einem 386er läuft, finde ich wahrscheinlich über die Intel Docs raus, muss die mir mal intensiv zu gemüte führen.
cr3 neu laden. Das solltest du allerdings wirklich nur auf einem 386 machen, es kostet im Vergleich zu invlpg sehr viel Performance, weil halt der gesamte TLB draufgeht.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

ChristianF

  • Beiträge: 296
    • Profil anzeigen
    • DeutschOS - Betriebssystem Projekt
Gespeichert
« Antwort #55 am: 11. June 2008, 18:57 »
Nun ja...
Das wird ja auch nur einmal kurz vor der Initialisierung des Kernels aufgerufen, sobald die multiboot_info_t Struktur kopiert wurde.
 
Mal so nebenbei, ist sonst noch etwas wichtiges in den ersten 4 MB, das unbedingt gesichert werden sollte?
 

Gruß Christian

*EDIT*
Ich habe mir das boot Page Directory als Pointer an die main-Funktion übergeben lassen.
Was geschieht jetzt genau, wenn ich den Eintrag 0 auf 0 setze.
Kommt das einem invlpg[0] gleich oder würde das theoretisch auch auf einem 386er laufen?
« Letzte Änderung: 11. June 2008, 19:11 von ChristianF »

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« Antwort #56 am: 11. June 2008, 20:33 »
Mal so nebenbei, ist sonst noch etwas wichtiges in den ersten 4 MB, das unbedingt gesichert werden sollte?
hm, das wirst du dann feststellen, wenn es knallt :-D btw. in der Multibootinfo Struktur sind auch Pointer, das musst du natürlich auch alles kopieren, wenn du es richtig machen willst. Oder das ganze eben solange gemappt lassen bis du fertig bist damit.
Ansonsten sind schon noch ein paar interessante Sachen in dem Bereich: BIOS Data Area und Extended BIOS Data Area, SMBIOS/SMP/ACPI floating pointer (und evtl. auch Teile der Tabellen). Aber die meisten Sachen kann man sich dann mappen, wenn man es denn benötigt.
hm... irgendwie hab ich grad ein Deja-vu... mir kommt es so vor als ob ich genau die gleiche Frage vor nicht allzu langer Zeit bereits beantwortet hätte, aber kA ob das in diesem Thread war oder überhaupt von dir gestellt wurde...

Zitat
Was geschieht jetzt genau, wenn ich den Eintrag 0 auf 0 setze.
Kommt das einem invlpg[0] gleich oder würde das theoretisch auch auf einem 386er laufen?
Ich denke das haben wir jetzt bereits in #lost geklärt oder?
lightOS
"Überlegen sie mal 'nen Augenblick, dann lösen sich die ganzen Widersprüche auf. Die Wut wird noch größer, aber die intellektuelle Verwirrung lässt nach.", Georg Schramm

ChristianF

  • Beiträge: 296
    • Profil anzeigen
    • DeutschOS - Betriebssystem Projekt
Gespeichert
« Antwort #57 am: 12. June 2008, 08:36 »
Ich habe das jetzt so geregelt, dass die erste Page Table überhaupt nicht gelöscht wird. Ich muss ja später das Boot Page Directory mit dem "richtigen" Page Directory ersetzen und solange kann ich dann darauf noch zugreifen.
Aus diesem Grund brauche ich auch vorerst kein invlpg und wenn, dann kann man das ja auch anders machen. :evil:
function:
    push eax
    mov eax, cr3
    mov cr3, eax
    pop eax

hm... irgendwie hab ich grad ein Deja-vu... mir kommt es so vor als ob ich genau die gleiche Frage vor nicht allzu langer Zeit bereits beantwortet hätte, aber kA ob das in diesem Thread war oder überhaupt von dir gestellt wurde...
Nein ich kann mich nicht entsinnen, diese Frage schonmal gestellt zu haben.  :-)
 
Gruß Christian

*EDIT*
Wie hoch ist die Wahrscheinlichkeit, dass mein Kernel mehr als 4 MB, bzw 3MB (der Kernel wird nach 0x00100000 geladen) platz braucht (Microkernel)?
Wenn das nämlich hoch sein sollte, müsste ich besser bis zu load_end_addr Speicher mappen.
Vielleicht mache ich das auch gleich so....  :roll:
« Letzte Änderung: 12. June 2008, 10:33 von ChristianF »

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« Antwort #58 am: 12. June 2008, 14:54 »
Wenn du einen Microkernel willst, dann nahe 0. Wenn du einen monolitischen Kernel mit dem meisten in extra ladbaren Modulen willst, dann auch eher gering. Wenn du alles in die Kernel-executable packen willst, vllt noch Debuginformationen, dann kann es schon passieren.
lightOS
"Überlegen sie mal 'nen Augenblick, dann lösen sich die ganzen Widersprüche auf. Die Wut wird noch größer, aber die intellektuelle Verwirrung lässt nach.", Georg Schramm

ChristianF

  • Beiträge: 296
    • Profil anzeigen
    • DeutschOS - Betriebssystem Projekt
Gespeichert
« Antwort #59 am: 17. June 2008, 10:58 »
Gut dann lass ich das so.
Allerdings habe ich gerade ein ganz komisches Problem:
 
Ich vergleiche in start.s mem_upper mit 0xC00 (3072).
Nun ist es so, dass in VMWare immer 1 MB fehlt.
Wenn ich 4 MB auswähle, hat mem_upper 2 MB anstatt 3 (umgerechnet). Benutze ich qemu oder Bochs, dann funktioniert alles so wie es soll.
 
Ist das normal?
Oder sollte ich statt jna(jump if not above) jb(jump if below) verwenden?
Hier der aktuelle code:
mov ecx, [ebx+8]
cmp ecx, 0xC00
jna error_to_less_mem


Gruß Christian
« Letzte Änderung: 17. June 2008, 11:05 von ChristianF »

 

Einloggen