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 - streetrunner

Seiten: 1 2 [3] 4
41
Lowlevel-Coding / DMA im LongMode
« am: 17. July 2013, 11:32 »
Guten Tag zusammen,

da ich gerade dabei bin meinen PMM zu programmieren hat sich mir die Frage gestellt in wie weit die DMA Funktionen der einzelnen Controller-Chips mit 64 Bit umgehen können. Dabei wäre eigendlich nur interressant zu wissen ob es sich lohnt den PMM so zu programmieren dass DMA-Geräte immer Speicher aus den ersten 4GB bekommen.

Gruß,
Streetrunner
42
Offtopic / Re: Logisim CPU
« am: 13. July 2013, 10:47 »
Zitat
Mhh der SRAM muss ja dann 1 MB groß sein oder? Ist das nicht etwas zu viel ?
Doch ist es, vor allem da es nicht 1MB sondern ganze 4MB sind (jede Adresse enthält 4 Byte um 32Bit Adressen aufnehmen zu können). Das Gute daran ist, das es wenn der SRAM einmal beschrieben ist es nie zu PageFaults kommen kann. Der riesengroße Nachteil ist dass es ewig dauert bis bei einem Taskwechsel der RAM neu beschrieben ist. Den SRAM verkleinern kann man leider auch nicht so ohne weiteres, da mann ja für jede virtuelle Adresse die von der CPU kommt einen Eintrag haben muss. Jetzt könnte man ja versuchen die Adressen auf weniger Einträge zu verteilen, womit wir dann wieder am Anfang wären.

Zitat
Naja hab eher an einen gemeinsamen Adressraum gedacht, wie wärs wenn ich den adressraum in 2 segmente unterteile(die größen der segmente sind immer gleich). Auf das erste Segment kann man nur im kernelmode zugreifen und auf das zweite kernelmode und usermode.
Das klingt wieder so kompliziert und gibt bei einem sehr kleinen Kernel sehr viel verschwendeten Platz. Ich würde eher dafür sorgen dass der Kernel bestimmen kann wann er in den Usermode wechselt, und das unabhängig davon wo er sich gerade befindet. Wichtig ist nur das der Usermode nicht einfach in den Kernelmode springen kann, das sollte dann nur über Interrupts geschehen, da der dann ausgeführte Code vom Kernel ist und nicht vom User.
43
Sieht gut aus, allerdings macht mir Dein Anschluss zum Tranformator etwas Sorgen, da guckt noch etwas zu viel unisoliertes Kabel raus. Wenn jetzt das Kabel mal unglücklich abknickt, warum auch immer, gibt das schnell mal nen schönen Kurzen. Am besten nimmst Du Schrumpfschlauch, damit geht das isolieren am besten bei so was.

Und sonst abermals meinen Respekt für das was Du da auf die Beine stellst.
44
Lowlevel-Coding / Re: Was genau ist ein Sprung?
« am: 26. June 2013, 10:47 »
MIPS ist deshalb sehr einfach, da der Compiler die komplizierte Arbeit macht. Das soll jetzt nicht heißen das andere Compiler nicht auch optimieren (der andauernde Gebrauch von "volatile" spricht da glaube ich Bände :-D), aber bei MIPS ist es so das man gefühlt versucht hat alles was kompliziert ist und Platz auf dem Die verbraucht in den Compiler zu verlagern. Das MIPS kein Out of Order hat stimmt dann nicht mehr so ganz, da sich dort der Compiler im vorhinein darum kümmert. Des weiteren meine ich gelesen zu haben dass bei bedingten Sprüngen der Compiler dafür Sorge zu tragen hat dass nach dem Sprung die Pipeline erst mal leer ist (NOP-Befehle).
45
Lowlevel-Coding / Re: Was genau ist ein Sprung?
« am: 25. June 2013, 21:24 »
Zitat
aber bei der Komplexität heutiger x86-Prozessoren würde ich das eher nicht wollen
Ich glaube x86 ist bei der Komplexität nicht alleine, letzten endlich dürfte jede CPU die mit Pipelines arbeitet davon betroffen sein wenn sie nicht wie z.B. MIPS oder Itanium auf SEHR VIEL Vorarbeit vom Compiler angewiesen ist.
46
Lowlevel-Coding / Re: 64 bit kernel mit grub 2 booten
« am: 25. June 2013, 11:48 »
Wie sehen denn deine Flags für den Compiler aus??? Eventuell fehlt da so was wie "-m64" oder "-mcmodel=large" (Wenn ich mich recht entsinne dann hatte ich den Fehler auch mal, und ich meine das ich ihn damals damit ausgebügelt habe).
47
Offtopic / Re: Logisim CPU
« am: 25. June 2013, 11:37 »
Ah, ok, und wieder um eine Abkürzung schlauer  :-D. Ich denke mal dass es für LRU am einfachsten wäre einen großen Zähler mitlaufen zu lassen, welcher startet wenn die CPU aktiviert wird, oder vielleicht wenn ein Taskwechsel stattfindet. Wenn man dann noch für jeden TLB-Eintrag ein Register vorsieht, in welchem man bei Zugriff auf den Eintrag den Inhalt des Zählers speichert, dann kann man bei einem Cache-Miss den kleinsten Wert in diesen Registern raussuchen und den dazu gehörigen Eintrag überschreiben.
48
Offtopic / Re: Logisim CPU
« am: 24. June 2013, 22:36 »
Zitat
Das ist doch dann sowieso das Problem der Software, oder?
Das kommt drauf an ob der TLB direkt beschreibbar ist oder nicht. Bei den meisten Architekturen geht das überhaupt nicht, die einzige Ausnahme stellt glaube ich Itanium, wo zumindest der L2-TLB von der Software aus beschrieben werden kann. Natürlich wäre es eine Idee, auch den L1-TLB beschreibbar zu gestalten. Das wäre vermutlich die einfachste Art einen TLB zu implementieren. Aber ob es auch die beste ist glaube ich nicht, da die Software zwar einen Überblick über die benötigten Seiten hat, allerding nichts davon weiß wie oft diese Seiten verwendet werden.

Zitat
ich würde für den Anfang ein simples LRU machen
Habe lange nachgedacht was LRU bedeuten könnte, aber wenn ich so auf meine Tastatur gucke dann denke ich das Du LFU meintest??? Ich glaube das ist auch nicht das gelbe vom Ei, da man hier für jeden Eintrag sowohl die Zugriffe als auch die Zeit benötigt, welche er im Cache existiert. Am einfachsten dürfte ein FIFO sein, realisiert mit einer Art Ringspeicher, bei dem immer ein Eintrag neu beschrieben wird, falls ein bestimmter Eintrag nicht im Cache vorhanden ist. Beim nächsten Cache-Miss wird dann der nächste Eintrag überschrieben. Von der Performance her ist das ab und an auch nicht wirklich super, aber wesentlich einfacher zu implementieren.
49
Lowlevel-Coding / Re: Kernel booten mit Grub2
« am: 20. June 2013, 21:45 »
Das sieht mir stark nach der Grub-eigenen Konsole aus, daraus kannst du manuell Deinen Kernel booten. Wenn du aber in der Konsole landest dann spricht das dafür dass Dein Eintrag in der Grub.cfg nicht geladen/ausgeführt wird
50
Meinen Respekt dass das alles funktioniert. Das erinnert mich irgendwie an meinen letzten Besuch beim Italiener  :-D.
51
Mich würde auch interessieren wie Du DMA umgesetzt hast, denn da müssen sich ja die CPU und der/die DMA-Controller den Speicherzugriff teilen.
52
Das Wiki / Re: Zwei Verständisfragen zu Wikiinhalten
« am: 15. June 2013, 22:27 »
Hallo,

wenn Du deine GDT anlegst dann schreibst Du neben der Basis und dem Limit auch einige andere Flags, u.a. in welchen Ring Du gerade arbeitest. Außerdem gibst Du eine Reihenfolge an. Segment 0 bleibt immer leer, in Segment 1 steht glaube ich dann das Code-Segment von Ring 0, in Segment 3 das Code-Segment von Ring 3 und in Segment 4 das Daten-Segment von Ring 3.
Da die Segmentregister aber nur 16 Bit haben, trägt man dort folgendes ein: Die unteren 2 Bit stehen für den Ring in dem man sich befinden möchte, also 0x0 für Ring 0 und 0x3 für Ring 3. Dann kommt ein Bit mit dem man angibt ob man mit GDT (Bit = 0) oder LDT (Bit = 1) arbeiten möchte. Die restlichen 13 Bit geben dann den Eintrag in Deine GDT/LDT an, also 0x1 für dein Code-Segment aus Ring 0. Da man aber die vorderen 3 Bit auch beachten sollte ergibt sich ein Wert von (0x1 << 3) | 0x0 = 0x8.  Für Ring 3 ergibt sich dann (0x3 << 3) | 0x3 = 0x18 -> 0x18 | 0x3 = 0x1B.

Zu deiner IDT-Frage: 0xF = 0b1111, 0xe = 0b1110. Normalerweise gelten die 3 Bit Werte, und mit denen wird auch nomalerweise auch gearbeitet (zumindest ich tue das). Mit 0xf und 0xe überschreibst du nämlich schon das nächste Flag. Dieses gib an, ob du im Real- oder im Prodected-Mode arbeitest. Dieses Bit würde ich immer extra setzten, da es wieder auf 0 gestzt wird wenn man im Long-Mode arbeitet. Wenn du nur die 3 Bit Werte genommen hast ohne dieses Flag zu beschreiben dann kann Dein Code nicht funktionieren, da Du dich im Protected-Mode befindest und Deine IDT für eine CPU im Real-Mode gedacht wäre.

Gruß,
Streetrunner
53
Offtopic / Re: Logisim CPU
« am: 13. June 2013, 22:07 »
Lies Dir dazu mal die Tutorials hier auf der Seite durch (OS-Dev für Einsteiger), da wird die MMU zu Beginn auch nicht benutzt und da steht auch drin was man machen muss um Multitasking ohne MMU zu implementieren.
54
Offtopic / Re: Logisim CPU
« am: 12. June 2013, 20:49 »
Naja, ich glaube eine "einfache" MMU gibt es nicht, denn ein paar grundlegende Dinge sollte jede MMU können:
Deine MMU sollte man Ein/Ausschalten können denn sonst wird es Probleme beim booten deines OS geben. Desweiteren muss sie auf den Speicher zugreifen können um die passenden Tabellen zu laden, dabei ist zu beachten dass die MMU der CPU evtl. den Busmaster "klauen" muss (Speicherzugriff auf eine Seite die nicht im TLB ist). Dann brauchst du noch eine Logik die deine Flags prüft (welcher Ring, lesen/schreiben, ...) und bei Bedarf einen Interrupt sendet. Als Ablauf dürfte dass dann so aussehen:

Die CPU gibt die gewünschte Adresse auf den Bus, welcher direkt in die MMU führt. Dort wird geprüft, ob die entsprechende Page bereits im TLB vorhanden ist (solltest du keinen TLB haben entfällt dieser Schritt). Ist die Page vorhanden so gibt man einfach den Inhalt des TLB-Eintrags auf den Adressbus und jut is. Sollte man keinen Treffer erziehlen so teilt man die Adresse der CPU in den Eintrag für das PD, den Eintrag für die PT und den Offset auf. Dann lädt man den Wert (Adresse vom PD) + (Offset im PD) in ein Register, und prüft ob der Eintrag dem man gerade geladen hat gültig ist und natürlich auch alle Flags. Dafür muss die CPU der MMU mitteilen was sie macht, d. h. ob sie schreiben oder lesen will, in welchen Ring der Task gerade ausgeführt wird, ...). Erhält man da Unstimmigkeiten so wird ein Interrupt ausgelöst. Passt alles, so ermittelt man aus dem geladenen Eintrag die Adresse der PT, und das ganze Spiel mit laden des Eintrags und checken usw. geht noch mal los. Passt dann immer noch alles so kann man aus dem geladenen Eintrag der PT und dem Offset der Adresse der CPU die gewünschte Speicheradresse bilden und auf den Adressbus legen. Dann sollte man der CPU evtl. noch mitteilen dass die MMU fertig ist und sie den Speicher anweisen kann Daten zu liefern oder entgegenzunehmen. Ich denke mal dass sich das sehr gut und einfach umsetzten lässt, auch größere Pages sind nicht schwer zu realisieren, man muss nur nach dem ersten "Laden und Checken" direkt zu "Gebe fertige Adresse aus" springen. Hardwaremäßig lässt sich das bestimmt wie eine Pipeline organisieren, also einfach hintereinander weg. Wenn du die MMU ausschaltest kannst du dann einfach die Adressen der CPU "drumherrum" direkt auf den Adressbus leiten.

Gruß,
Streetrunner
55
Offtopic / Re: Logisim CPU
« am: 04. June 2013, 11:53 »
So lange er nicht die Probleme von x86 mitnimmt (A20 lässt grüßen) kann er von mir aus gerne darauf schielen, denn letztenendlich funktionieren doch alle Architekturen die so im Umlauf sind irgendwie doch alle gleich (vllt. vom eigendlichen Kern mal abgesehen). Sie haben alle einen Cache und TLB und ob ich dann CISC (x86) oder RISC (ARM, x86_64 ist dann son Mischmasch) oder VLIW (Itanium) habe ist dann denke ich mal auch egal.

Wie viel Dein Simulator aushält ist dann die andere Frage, ich hab zwar nicht den kompletten Beitrag gelesen aber es wäre vllt. besser wenn man erst einmal nur den Kern debuggt und sich erst danach an Caches und dergleichen wagt.

Gruß,
Streetrunner
56
Offtopic / Re: Logisim CPU
« am: 03. June 2013, 17:22 »
Zu deiner MMU:
Ich denke mal Du versuchst folgendes: Du hast irgendwo ein Register in dem die Adresse Deiner "großen" Tabelle steht. Wenn nun ein Speicherzugriff erfolgt, braucht Deine MMU nur an "Adresse + Offset" nachsehen wohin es denn wirklich geht. In sofern funktioniert das, aber das Problem wird sein dass Du im Adressraum einen extrem großen Bereich (bei 32Bit, bei x86_64 im "Maximalausbau" dann 512GB) an zusammenhängendem Speicher reservieren musst, um dort Deine Tabelle abzulegen. Das ist in sofern unglücklich, da nun zwar jeder Prozess per Default extrem viel Speicher reservieren kann, ABER diesen vermutlich überhaubt nicht braucht (man überlege sich hier dass ein Prozess bei x86_64 allein 512GB für das Paging verschwendet, auch wenn er selbst nur 1MB wirklich braucht).

Und nun zum Cache:
Letztenendlich kommt es darauf an wie viel Aufwand Du betreiben möchtest. Geht man davon aus dass Deine CPU nur alleine arbeitet, dann ist Write-Allocation wohl die beste Wahl. Dabei wird bei einem Cache-Hit der Wert in den Cache geschrieben und mit dem sogenannten "Dirty-Bit" als "nicht mit dem Haubtspeicher übereinstimmend" markiert. Der Haubtspeicher wird dabei nicht angerührt. Bei einem Cache-Miss wird der Wert ebenfalls direkt in den Cache geschrieben, ist dieser voll muss halt irgendwas überschrieben werden (möglichst etwas was bereits im Haubtspeicher liegt). Sonst ist es wie beim Cache-Hit. Das Problem bei allen Varianten die den Zugriff auf den Haubtspeicher vermeiden ist, dass andere Geräte die auf den Haubtspeicher zugreifen (DMA, andere CPUs) eventuell mit den falschen Daten arbeiten. Das Problem mit den CPUs kann man relativ einfach umgehen, indem man einen großen (mittlerweile L3) Cache hat auf den alle CPUs zugreifen und mit dem alle CPUs ihre Daten abgleichen. Dauert zwar bei neu geschriebenen Daten (Cache-Miss) etwas länger, aber immer noch bedeutend kürzer als auf den RAM zuzugreifen. Mit DMA ist das dann etwas schwierieger, da müsstest Du Dir dann eine Lösung überlegen.

Gruß,
Streetrunner
57
Lowlevel-Coding / Re: ACPI-Version
« am: 01. June 2013, 13:33 »
Danke für die Antwort.

Ich nehme wie du beschrieben hast das Feld RSDP.revision . Allerdings hatte ich erwartet dass dort schon die "richtige" Version drinne steht und nicht nur angegeben wird welche felder in der RSDP entahlten sind. Da ich aber in der Zwischenzeit weiter programmiert habe ist mir auch aufgefallen, dass jede Tabelle ihren eigenen Eintrag für die Version hat. Da habe ich mir schon sowas gedacht von wegen "jetzt muss ich für jede Tabelle die Version prüfen  :x".

Gruß,
Streetrunner
58
Lowlevel-Coding / ACPI-Version
« am: 31. May 2013, 15:14 »
Hallo zusammen,

ich habe mir gestern ein paar Zeilen Code zusammengeschrieben/kopiert um mal zu sehen, ob ich den RSDP finde. Und siehe da, ich hatte Erfolg. Aber eins hat mich stutzig gemacht: Laut meinem Code ist die Version von ACPI bei Qemu = 0 (also Version 1). Wenn ich den Code auf meinem Rechner ausführe bekomme ich auch gesagt das Version 1 vorhanden ist. Nun ist mein Rechner zwar schon etwa 5 Jahre alt (X58 Board), aber Version 3-4 hätte ich da dann doch schon erwartet. Kann irgendwer diese Werte bestätigen (vllt. mit einem ähnlich altem Rechner) oder ist mein Code evtl. falsch???

Gruß,
Streetrunner
59
Offtopic / Re: Logisim CPU
« am: 27. May 2013, 11:34 »
Wie die lineare Adresse zustande kommt habe ich auch verstanden. Sieht man sich aber das Beispiel auf Wikipedia an (ich denke mal, Svenska meint das erste Schaubild), so erkennt man das dort nur eine große Tabelle existiert. Diese hat 2^n Einträge, auf Tufelix Bsp. angewandt ergeben sich damit 2^20 Einträge. Tufelix hat aber nur 2 x 2^10 = 2^11 Einträge. Irgendwo muss es also einen Haken geben, und dieser liegt darin dass in einem PT-Eintrag immer der selbe Wert steht, unabhängig vom PD-Eintrag. So steht z.B. im PT-Eintrag 127 immer der Wert 0x3FF, unabhängig davon welchen Eintrag ich im PD selektiert habe (vorausgesetzt natürlich ich habe auch wieder den Eintrag 127 im PT selektiert). Dies könnte aber unerwünscht sein, da eventuell der Wunsch aufkommen könnte, bei unterschiedlichen PD-Einträgen unterschiedliche PT-Werte im PT-Eintrag 127 zu haben.

Gruß,
Streetrunner
60
Offtopic / Re: Logisim CPU
« am: 26. May 2013, 20:44 »
Ziel einer MMU ist es aus einer virtuellen eine reale Speicheradresse zu machen. Das heißt u.U. das zwei unterschiedliche Adressen auf die selbe reale Adresse gemappt werden. Spielen wir dieses Beispiel einmal durch:

Angenommen die Adressen 0xFFF00xxx und 0xFFFFFxxx sollen auf die selbe Adresse gemappt werden.
Damit müssten sowohl der Eintrag 768 (die unteren 10Bit von F00) als auch der Eintrag 1023 (die unteren 10Bit von FFF) in der Page-Table den selben Wert enthalten. Leider ist es aber so dass man nur 10Bit hat um die insgesammt 1024 Einträge zu adressieren. Wenn nun aber 2 Einträge den selben Wert enthalten bleibt zwangsläufig ein Wert auf der Strecke, für den kein Platz in der Page-Table mehr ist. Daraus resultiert dann nicht addressierbarer Speicher, da die passenden (Teil)-Addressen einfach nicht in der Page-Table vorhanden sind. Gleiches gilt natürlich auch für das Page-Directory. Dabei ist es egal, wo jetzt Werte fehlen, der verschwendete Speicherplatz ist von der selben Größenordnung und beträgt (richtig gerechnet vorrausgesetzt) pro nicht vorhandenem Wert 4MB.

Hoffe mal ich hab da nichts übersehen, dann wäre das wahrscheinlich hinfällig.


Tante Edit sagte mir gerade dass das teilweise kompletter Unsinn ist was ich da oben geschrieben habe. Aber ich steh zu meinen Fehlern. :-D

Daher auf ein neues:
Wenn ein OS einen Neuen Task startet, dann legt es üblicherweise neue Paging-Tabllen an, damit der Task über den kompletten Adressraum verfügen kann, ohne irgendwem ins Handwerk zu pfuschen. Sinn dieser Tabellen ist nun neben der Adressumwandlung der MMU mitzuteilen, ob der betreffende Task überhaubt an diese Speicheradressen schreiben darf. Desweiteren fehlen manchmal Einträge, da diese entweder nicht in den Adressraum des Tasks gehören oder nicht im Speicher vorhanden sind (Swapping). Dies kann nun nur für eine einzige Page der Fall sein. Bei deiner Lösung müsste man dafür aber wieder einen kompletten Eintrag in deinen Tabellen löschen, womit sich direkt 4MB Speicher verabschieden.

Hoffe diesmal, das mir nicht im Nachhinein einfällt, dass das auch Unsinn ist....

Gruß,
Streetrunner
Seiten: 1 2 [3] 4

Einloggen