Beiträge anzeigen

Diese Sektion erlaubt es dir alle Beiträge dieses Mitglieds zu sehen. Beachte, dass du nur solche Beiträge sehen kannst, zu denen du auch Zugriffsrechte hast.


Nachrichten - Cheebi

Seiten: 1 [2] 3 4 5
21
sooo... Problem gelöst:

Ich habe vergessen, die GDT neu zu laden, nachdem ich einen neuen Descriptor (TSSDesc) angelegt habe. (also das Feld GDT.size musste mit Hilfe von lgdt [GDT] aktualisiert werden).

Ich habe aber immer noch eine Frage:

Ist es sinnvoll, die GDT von Anfang an mit Nulldescriptoren zu füllen und dementsprechend das Feld GDT.size gleich so zu setzen:
GDT.base = 0x0;
GDT.size = (sizeof(SDESCRIPTOR) * MAX_DESCS) - 1;
load_GDT(GDT);

Oder sollte man bei jedem neu angelegten Descriptor die GDT mit neuen Werten laden?

Gruß Cheebi
22
@bluecode:

ich hatte folgende Quelle:
http://en.skelix.org/skelixos/tutorial06.php

nach der ist das Granular-Bit zu setzen... Aber auch ohne es zu setzen, tritt bei mir ne GP auf.

dw 0x0068
dw 0x0000
db 0x00
db 0x89
db 0x40
db 0x00
Warum hast du ein reservierte Bit true gesetzt? (Das 7. Bit des 7. Bytes hast du true gesetzt [db 0x40])

gruß Cheebi
23
ohjee... warum bekomm' ich denn eine General-Protection-Fault-Exception, wenn ich folgenden Code ausführe?

  __asm__ volatile ("ltrw %%ax"::"a"(0x18));
  cli();
  for(;;);

Descriptor 3 der GDT ist der TSSDescriptor und hat folgende Werte:

Word1: 0x00000068
Word2: 0x05808900

Das heißt also:

Größe    = 104 Byte
Base     = 0x5000000
Busy     = false
DPL      = 0
Present  = true
Granular = true

Vom TSS selbst sind nur die beiden Einträge ss0 und esp0 mit Werten besetzt. Alle anderen Einträge tragen den Wert 0.

Warum komme ich also nie zu den Befehlen nach ltrw?

Gruß Cheebi
24
Lowlevel-Coding / Re: gcc und __stdcall, __cdecl etc
« am: 24. July 2007, 18:54 »
vielen dank!  :-D
25
Lowlevel-Coding / gcc und __stdcall, __cdecl etc
« am: 24. July 2007, 14:14 »
hey Leute,

wie sieht das denn bei gcc aus? gibts da auch die möglichkeit dem compiler irgendwie mitzuteilen, wie er ne funktion gestalten soll? so wie es bei den ms-compilern möglich is (__stdcall, __fastcall etc.)?
das wäre von vorteil beim programmieren von dispatchern in c... nur als beispiel...

gruß

Cheebi
26
Lowlevel-Coding / Re: Sprung in den C-Kernel
« am: 24. July 2007, 11:57 »
hey,

pass auf, probier einfach folgendes und versuch beim coden nachzuvollziehen, was genau passiert:

du hast einen bootloader, der den kernel lädt und dann in den pm springt. das sieht in etwa so aus:

;boot.asm

[BITS16]
org 0x7c00

start:
         ...; hier steht der code, der dir den kernel an eine bestimmte adresse lädt
         ...; du musst dabei darauf achten, dass du dir vorher überlegst, wohin du den kernel laden willst
         ...; sagen wir du hättest dir die lineare adresse  0x20000 ausgesucht
         ;
         ; so, jetzt steht der kernel bei 0x20000
         ; jetzt musst du in den pm schalten
         ;
         lgdt ...
         mov         eax, cr0
         or         eax, 1
         mov         cr0, eax
         jmp         0x8 : pmode
         ;
         ; das müsstest du ja soweit implementiert haben

[BITS32]
pmode:
         mov         eax, 0x10
         mov         ds, eax
         mov         es, eax
         mov         ss, eax
         mov         gs, eax
         mov         fs, eax
         mov         esp, stack_size

         ; na das kennst ja alles
         ; soooo

         ; das tolle ist, dass du weißt, wo dein kernel liegt. du hast ihn ja nach 0x20000 geladen
         ; da springen wir nun hin...
         jmp         0x8 : 0x20000
         ;
         ; fertig

jetzt brauchst du noch einen kernel...

// kernel.c

void main()
{
  // welcome
  for(;;);
}

jetzt noch etwas, das nicht unbedingt notwendig ist, aber manchmal ganz nützlich ist...

; asm32.asm

[BITS 32]

[global _stopsystem]
[extern _main]

_start:
         call         _main

_stopsystem:
         cli
         hlt

jetzt musst du nur noch gucken, wie das alles zusammen gehört.
also den bootlader assemblierst du ganz normal mit nasm:

   nasm -f bin -o boot.bin boot.asm

boot.bin schreibst in sektor null...

asm32.asm musst du anders assemblieren:

   nasm -f aout -o asm32.o asm32asm

jetzt hast du die erste objekt-datei asm32.o
den kernel kompilierst du so:

   gcc -ffreestanding -c -o kernel.o kernel.c

jetzt hast du die zweite objekt-datei.
um alles zusammen zu linken, brauchst du noch eine sogenannte linker-file:

OUTPUT_FORMAT("binary")
INPUT(asm32.o kernel.o)
ENTRY(_start)
SECTIONS
{
  .text  0x20000 : {
    *(.text)
  }
  .data  : {
    *(.data)
  }
  .bss  :
  {
    *(.bss)
  }
}
die datei erklärt sich ja sogut wie von selbst... wenn nicht, fragen!

das ganze muss nur noch gelinkt werden:

   ld -T link.ld -o kernel.bin

nach diesem befehl hast du eine datei namens kernel.bin, die der bootloader laden kann...

da du in der link.ld die reihenfolge INPUT(asm32.asm kernel.o) hast, ist der allererste befehl in kernel.bin "jmp _main"... dadurch ist sichergestellt, dass selbst wenn _main nicht ganz vorne anfängt, trotzdem der kernel-code aufgerufen wird.

gruß

Cheebi

ps: meld dich, wenns funktioniert... hab den code jetzt nicht getestet...
27
die tastatur ist der letzte üpll, der im ibm standard zu finden ist... ich hab wochen gebraucht, bis ich durchgestiegen bin... am besten, du verwendest einen einfachen scancode. problem ist nur, dass manche tastaturen nicht zu allen scancodes kompatibel sind. (naja.. probiern!)
was diese beschissenen sonder-scancodes betrifft, bleibt dir nur eine möglichkeit: du musst abspeichern, ob bereits ein scancode dieser art gesendet wurde; denn wie du bereits befürchtet hast, wird bei jedem scancode ein neuer irq0 ausgelöst... vorher kannst du den code nicht auslesen.

hier findest du einiges:


Cheebi
28
Lowlevel-Coding / Re: Multitasking, Stacks und Pagetables
« am: 18. July 2007, 00:07 »
also ich versteh jetzt gar nix mehr  :-D

wäre jemand so nett und erklärt mir bitte, was folgende funktion (egal ob man sie nun kmalloc() oder sonst wie nennt) machen muss?

create_task(ulong entrypoint, ulong stacksize, ulong codesize, etc.)
{
  newtask.esp = kmalloc(stacksize);
  newtask.eip = entrypoint;
  copy_code_to(kmalloc(codesize));
  ...
}

das ist nur pseudocode. mir geht es einzig und allein um die hier genannte funktion kmalloc(), die ich ja wohl unbedingt brauche...
tut mir leid, dass ich so auf dem schlauch stehe, aber ich versteh einfach gar nichts mehr...

zwischenfrage:
bei einer ringtransition, wird da auch automatisch cr3 des kernels geladen? (so wie automatisch ssX und espX (X=ring) geladen werden?)

gruß

Cheebi
29
Lowlevel-Coding / Re: Multitasking, Stacks und Pagetables
« am: 07. July 2007, 10:46 »

2) beim allozieren von speicher durch malloc() ist klar, dass ich zum beispiel die stackmethode wähle, um zu wissen welche pages noch unbenutzt sind.

malloc ist nichts, was der Kernel direkt macht, dazu müßte er bytegenau reservieren können. Der Kernel liefert normal nur komplette Pages und malloc arbeitet dann z.B. mit einer Freispeicherliste.
ohje... dann hab ich das falsch verstanden... ich dachte, das memorymenagement-modul des kernels kümmert sich um speicherreservierungen und stellt dafür malloc() zur verfügung. dabei dachte ich auch, dass der kernel die funktion malloc() benutzt, um beispielsweise einen prozess zu starten. angenomnmen ein prozess ist 100kb groß, dann müssen 100kb speicher für den code bereit stehen und ich brauche platz für die stacks (und evtl. noch einen datenbereich). deshalb dachte ich, der kernel würde malloc() aufrufen, um den speicher zu reservieren. wie macht der kernel das aber dann? er muss ja irgendwoher seinen speicher für den prozess beziehen...

Cheebi

30
Lowlevel-Coding / Multitasking, Stacks und Pagetables
« am: 06. July 2007, 00:26 »
hey Leute,

ich blicks immer noch nicht ganz... ich habe folgende fragen:

1) ich habe verstanden, warum ich für jeden prozess mindestens zwei stacks haben sollte (userstack ring3 & kernelstack ring0). aber ich weiß nicht, wie groß ich die stacks beim starten eines tasks bemessen soll, also wieviel byte malloc() allozieren soll. wenn ich den kerneltack zu groß bemesse, habe ich eine enorme speicherverschwendung (zb 10kb + pro Task). das sollte doch eigentlich nicht sein... wie löst ihr das problem?

2) beim allozieren von speicher durch malloc() ist klar, dass ich zum beispiel die stackmethode wähle, um zu wissen welche pages noch unbenutzt sind. aber ein problem ist doch, dass wenn eine anwendung beispielsweise 120kb anfordert, nicht nur 30 pages zur verfügung stehen müssen, sondern auch eine zusammenhängende folge von virtuellen adressen unbenutzt sein muss. zb virtueller speicherbereich von 0x0 bis 0x1000 ist belegt, 0x1500 bis 0x2000 belegt und bis 0x3000 ist der virtuelle speicher frei. wenn jetzt 0x1500 speicher gebraucht wird, dann ist zwar genug speicher frei, aber nicht zusammenhängend... wie kann da malloc() einen pointer auf einen zusammenhängenden speicherbereich liefern?

3) ich habe gelesen, dass man bei jedem taskswitch auch das cr3 ändert, also das pagedirectory... warum das? dann müsste ja jeder task 4mb(pagetables)+4kb(pagedirectory) haben... das ist doch auch vergeudung... oder setzt man dann das presentbit im pagedirectory nicht und spart so pagetables?

gruß

Cheebi
31
Lowlevel-Coding / Re: Paging aktivieren und VESA-Mode LFB
« am: 27. June 2007, 12:31 »
wenn ich raten soll, muss es 4096 und nicht 1024 in der zeile PageDirectory[i1]=(ulong)PageTable + (i1*1024); heissen.
WOW! nicht raten!!! das war der fehler.......... VIELEN DANK PorkChicken! *freu*

Cheebi
32
Lowlevel-Coding / Re: Paging aktivieren und VESA-Mode LFB
« am: 26. June 2007, 23:19 »
Zitat
Doch, dieser Speicher ist vorhanden. Es handelt sich nähmlich um den Video-Ram auf der Grafikkarte. Und der wird möglichst so eingebunden, dass er dem "normalen" Arbeitsspeicher nicht in die Quere kommt.
hm... muss ich dann diesen Adressraum aus meiner Pagetabelle heraus nehmen? oder wo kann das problem noch liegen?

  write_cr3((ulong)PageDirectory);
  put_PagingBit();
  sound(200);
  for(;;);
}
bei diesem code wird der sound ausgegeben. das zeigt eindeutig, dass das problem nicht beim code selbst sondern beim vesa-mode und dem grafik-speicher liegt...

Cheebi
33
Lowlevel-Coding / Re: Paging aktivieren
« am: 26. June 2007, 22:51 »
hi Leute,

ich habe (wohl) einen fehler gefunden... ich habe mir den zeiger des linear framebuffers vom vesa-mode (0118h) ausgeben lassen und festgestellt, dass er 0xf0000000 ist. das kannn in einem 128mb-ram-pc aber schlecht möglich sein.. es funktioniert aber!
warum ich also nichts mehr zu sehen bekomme, sobald paging aktiviert ist, ist, dass ich erstmal die ganzen 4gb mappe und alle pages present setze, deshalb gibt es die adresse 0xf0000000. dort kann ja aber nichts gespeichert werden.
kann es sein, dass schon (bevor ich paging aktiviere) eine art mapping des rams vorhanden ist? denn wie soll denn der linear framebuffer bei 0xf0000000 liegen und trotzdem auf dem bildschirm etwas abgespeichert werden? ich bin total verwirrt... helft mir bitte!!!

danke

Cheebi
34
Lowlevel-Coding / Re: Paging aktivieren
« am: 26. June 2007, 13:55 »
Zitat
Spontan fällt mir da auf, daß der PD-Eintrag auch gern ein gesetztes Present-Bit hätte.
das war der fehler für den reboot... danke! jetzt funktioniert es aber immer noch nicht...
ich scheine die pages nicht korrekt gefüllt zu haben... mal sehen

Cheebi
35
Lowlevel-Coding / Paging aktivieren und VESA-Mode LFB
« am: 25. June 2007, 01:34 »
hi Leute,

sorry, dass ich ständig neue threads öffne, aber ich hab einfach mehrere probleme gleichzeitg...
wenn ich paging aktiviere, dann muss ich doch zuvor ein pagedirectory und 1024 pagetables (angenommen ich setze alle pages auf present) anlegen, oder? das habe ich getan. folgender codeabschnitt sorgt dafür:

paging.h:
  #define adr_PageDirectory 0x120000
  #define adr_PageTables 0x121000

  typedef struct
  {
    ulong Entry[1024];
  } SPAGETABLE;
paging.c:
static ulong *PageDirectory = (ulong *)(adr_PageDirectory);
static SPAGETABLE *PageTable = (SPAGETABLE *)(adr_PageTables);

void setup_Paging()
{
  int i1, i2;
  ulong adr = 0;
  for (i1 = 0; i1 < 1024; i1++)
  {
    PageDirectory[i1]=(ulong)PageTable + (i1*1024);
    for (i2 = 0; i2 < 1024; i2++)
    {
      PageTable[i1].Entry[i2] = adr | 3;                                        // alle pages present
      adr += 4096;
    }
  }
  write_cr3((ulong)PageDirectory);
  put_PagingBit();
}

die funktion put_PagingBit() ist in asm geschrieben:
[global _put_PagingBit]
_put_PagingBit:
        mov              eax,       cr0
        or               eax,       080000000h
        mov              cr0,       eax
        jmp              $
        ret

das problem ist, dass noch vor dem jmp $ ein neustart ausgeführt wird... es kommt noch nicht einmal ein "page-fault". woran liegt das?
an der stelle, an der ich setup_Paging() ausführe, befinde ich mich bereits im pm und habe ein flaches speichermodell.

grüße

Cheebi
36
Lowlevel-Coding / Re: Sektoren lesen dauert so lange
« am: 24. June 2007, 13:49 »
ja... das hab ich auf deiner HP gefunden...
37
Lowlevel-Coding / Re: Sektoren lesen dauert so lange
« am: 24. June 2007, 00:59 »
@FreakyPenguin : nein...
38
Lowlevel-Coding / Re: Sektoren lesen dauert so lange
« am: 23. June 2007, 02:12 »
@ bluecode:
ich hab mir mal deinen fdc-treiber angesehen... prinzipiell funktioniert mein fdc-treiber genauso. ein paar Sekunden konnte ich eisparen, indem ich kleinere wartezeiten (zB für Motor an, etc) gewählt habe. ich könnte mir vorstellen, dass es am dateisystem-Modul hängt... das suchen der sektoren in der fat dauert ja auch (wenn auch nur kurz)
wie läuft dein fdc-treiber? ich konnte dein os nicht starten "failed to set scancode set 2"...

gruß

cheebi
39
Lowlevel-Coding / Re: Sektoren lesen dauert so lange
« am: 22. June 2007, 00:08 »
@korona: ich habe den DMA-Kanal gewählt, da ich mir dachte, das sei schneller als direkt über die Ports...

Wenn direkte Portzugriffe schneller sein sollen, dann wähle ich natürlich diese... aber die Frage stellt sich, wie regelt das BIOS das ganze? Weil der Unterschied 4 Sek. (über BIOS-Int) und 33 Sek. (über meine Funktion) ist schon enorm... Da hat das BIOS eindeutig eine genialere Methode...

Kann es daran liegen, dass ich mich genau wie im Datasheet beschrieben an den Ablauf des Sektoren-Lesens halte?

  • 1. Recalibrate
  • 2. Initialize DMA
  • 3. Read-Command
  • 4. Wait for IRQ
  • 5. Result ok?
  • 6. Complete

Natürlich schalte ich vorher den Motor an...

Grüße Cheebi
40
Lowlevel-Coding / Sektoren lesen dauert so lange
« am: 20. June 2007, 23:18 »
Hi leute,

ich habe meinen Disketten-Treiber umgeschrieben in Assembler (vorher C) weil ich dachte, ich könnte dadurch die Performance verbessern. Nun muss ich feststellen, dass auch in Assembler zu lange gebraucht wird, einen Sektor zu laden. Woran kann das liegen?
Mein Loader (Stage 2) lädt die Kerneldatei, die immerhin 49KB groß is, innheralb von vielleicht 4 Sekunden. Im Loader (16Bit-Code) benutze ich den BIOS-Int, der Sektoren liest (also keine Tracks!); meine eigengeshriebene Routine für das Lesen von Sektoren ist aber zu langsam (49KB -> 33 Sec). Woran liegt das? Wie genau lädt das BIOS die Sektoren? Wie lange brauchen eure Disketten-Treiber 98 Sektoren zu lesen?

Danke,

Cheebi
Seiten: 1 [2] 3 4 5

Einloggen