Autor Thema: Eigene CPU  (Gelesen 93040 mal)

XanClic

  • Beiträge: 261
    • Profil anzeigen
    • github
Gespeichert
« Antwort #80 am: 28. November 2010, 20:03 »
es geht mir um die Abwertung (als krank) die nicht rational begründet wurde.
Hm? Darf ich dich an deine Aussage bezüglich der Real-Mode-„Segmentierung“ erinnern?

und finde die Schei**.
Dem kann ich uneingeschränkt zustimmen.


Ich persönlich hätte mir da schon eine Erklärung gewünscht. :-)

erik.vikinger

  • Beiträge: 1 277
    • Profil anzeigen
Gespeichert
« Antwort #81 am: 28. November 2010, 20:26 »
Hallo,


Ich persönlich hätte mir da schon eine Erklärung gewünscht. :-)
dann schau mal 2 Beiträge davor:
Die Segmentierung im x86-Real-Mode ist auch grausam, da ist nichts dynamisches oder zumindest flexibles dran.
oder 4 Beiträge dahinter:
Die x86-Real-Mode-Segmentierung ist starr, da gibt es keine Flexibilität: ....

Wenn ich mich unklar/unvollständig ausgedrückt haben sollte schreibe ich dazu gerne noch ein paar detailliertere/weitere konkrete Punkte.


Sorry, aber so aus dem Kontext gerissen, ist auch nicht der richtige Weg. Meine Beiträge sind üblicherweise eh schon viel zu lang, da kann ich nicht auch noch jedes mal jeden Kram wiederholen.
Bezüglich der dynamischen Segmentierung des 386-PM hab ich hier in diesem Forum noch nicht ein einziges Argument gelesen!


Grüße
Erik
« Letzte Änderung: 29. November 2010, 10:43 von erik.vikinger »
Reality is that which, when you stop believing in it, doesn't go away.

Programm Noob

  • Gast
Gespeichert
« Antwort #82 am: 28. November 2010, 22:32 »
Moin

Irgendwie schweifen wir hier ziemlich vom Topic ab. Lasst uns die Segmentation Diskussion in einem extra Thread diskutieren.

PNoob

XanClic

  • Beiträge: 261
    • Profil anzeigen
    • github
Gespeichert
« Antwort #83 am: 28. November 2010, 23:11 »
Erik: Ich fand das nur komisch, weil du auch geschrieben hattest (wimre), dass die RM-Segmentierung lediglich ein merkwürdiger Weg zum Erhalten von einem MB Speicher mit 16-Bit-Adressen sei. Meiner Meinung nach ist das der einzige Zweck, und damit ist jede Dynamik nicht Sinn der Sache – inwiefern der Weg aber merkwürdig ist, erschloss sich mir nicht ganz. :-)
(Die Aussage von PNoob („Die Segmentierung ist Schei**“) klang für mich auch eher so wie „Wer hat sich das denn ausgedacht“ und nicht wie „Wieso kann die nicht so viel wie die x86-Segmentierung“)

PNoob: Da das hier angefangen wurde, schreib ich auch einfach hier rein und überlass den Rest frech den Mods. :-D

Programm Noob

  • Gast
Gespeichert
« Antwort #84 am: 29. November 2010, 00:03 »
Also da ja nun inzwischen alle mitbekommen haben dürften, das ich auch eine eigene Architektur entwickle, schreibe ich jetzt auch mal was dazu.

Den Namen, DPSKA (Dem PNoob Seine Kaputte Architektur), hat sich taljeth ausgedacht. Vieleh Dank nochmals dafür. Ich wäre nimals auf nen anständigen Namen gekommen.

Die CPU wird eine 64 Bit CPU mit 32 Bit Adressbus, was ich erstens für ausreichend halte und zweitens würde ich die CPU später mal in Hardware bauen. Also nicht nur in einem FPGA laufen lassen. Außerdem vereinfacht der 32 Bit adressbus breite das Speichermanagment. Als Speichermodell kommt bei mir FlatMemory zum einsatz. Der Speicherschutz wird mit Paging realisiert. Der Befehlssatz wird ein 3 Operanden Befehlssatz werden. Die kommunikation mit der Hardware läuft über das Klassische I/O Port Konzept ab. SMP mit bis zu 32 CPU's und 64 Kernen pro CPU ist geplant. Es gibt 256 IRQ lines, somit sollte es für jede Situation genügend freie IRQ lines geben, so das keine Geräte sich eine Line teilen müssen. Zur Systemsicherheit, gibt es 2 Privelege Level. In dem Usermode, lösen alle Befehle, mit der die möglichkeit besteht die kontrolle über das system zu erlangen, eine Exception aus.

Das war mal ein grobüberblick über meine Architektur. Wenn ihr Fragen habt, dann fragt.

PNoob

erik.vikinger

  • Beiträge: 1 277
    • Profil anzeigen
Gespeichert
« Antwort #85 am: 29. November 2010, 10:35 »
Hallo,


Irgendwie schweifen wir hier ziemlich vom Topic ab. Lasst uns die Segmentation Diskussion in einem extra Thread diskutieren.
Das fände ich auch gut, meinetwegen ab meinem Beitrag von Sonntag Vormittag.


Ich fand das nur komisch, weil du auch geschrieben hattest (wimre), dass die RM-Segmentierung lediglich ein merkwürdiger Weg zum Erhalten von einem MB Speicher mit 16-Bit-Adressen sei.
Ja, dieser Meinung bin ich (nebst dessen das sich das eigentlich nicht unbedingt Segmentierung nennen sollte aber egal). Eines der Probleme mit dem x86-Real-Mode ist das der Befehlssatz einem quasi dazu zwingt sehr häufig die Segment-Register neu zu laden (wenn das Programm mehr als 64kB benötigt), es sind nicht nur die RM-Segmente starr und unflexibel sondern auch der Befehlssatz (z.B. MOVS). Bei Flat-Memory (und im Prinzip ist ein RM-Programm das komplett in 64kB passt ja auch flach) ist das keine Einschränkung aber die Segmentierung wird bei x86 nur recht lieblos unterstützt (in allen Modi). Ich persönlich bin der Meinung das eine größere Verarbeitungsbreite der CPU, z.B. 32 Bit, oder flexiblere Befehle der bessere Weg wären aber das kostet beides auch mehr Transistoren auf dem Chip. Ich kann verstehen warum Intel damals diesen Weg gegangen ist aber toll find ich (als Programmierer) ihn trotzdem nicht (auch wenn diesem Weg vielleicht der 286-PM und damit auch der 386-PM zu verdanken ist).


Den Namen, DPSKA (Dem PNoob Seine Kaputte Architektur), hat sich taljeth ausgedacht. Vieleh Dank nochmals dafür.
Und genau da ist wieder dieses bestimmte Attribut "Kaputt". Wieso wird eine Idee bereits als kaputt bezeichnet (bewertet!) bevor überhaupt etwas konkretes bei raus gekommen ist? Hätte nicht erst mal DPSA gereicht?
PNoob: Bedanken solltest Du Dich für diesen Namen IMHO nicht.


Ich würde mich sehr freuen wenn diese spezielle Diskussion (um Meinungen und Wertungen) auf einem etwas sachlicherem Niveau weitergeführt werden würde. Es tut mir sehr Leid das ich mich Sonntag Vormittag nicht beherrschen konnte und mal ein unangenehmes Thema angeschnitten hab.


also wieder On-Topic (und das im Off-Topic-Board ;) ) :


.... schreibe ich jetzt auch mal was dazu.
Genau dazu war dieser Thread ja auch gedacht.

Die CPU wird eine 64 Bit CPU mit 32 Bit Adressbus, was ich erstens für ausreichend halte
Wenn die CPU intern mit 64Bit (virtuellen) Adressen umgehen kann aber extern nur 32Bit hergibt (also so ähnlich wie ein 386SX) dann ist das keine so schlechte Idee, auch wenn die 32Bit gemessen an aktuellen PCs sicher etwas knapp kalkuliert sind. Der Hyper-Transport von AMD unterstützt wimre auch nur 40Bit physische Adressen.

zweitens würde ich die CPU später mal in Hardware bauen. Also nicht nur in einem FPGA laufen lassen.
Was meinst Du mit "in Hardware bauen"? Wenn nicht in einem FPGA.

Die kommunikation mit der Hardware läuft über das Klassische I/O Port Konzept ab.
Also einen extra I/O-Adressraum und nicht über MMIO? Alle anderen CPU-Architekturen gehen von den I/O-Ports zu MMIO über (falls sie überhaupt mal I/O-Ports unterstützt haben). Kann dann die Peripherie per eigenständigem Busmastering auf den normalen RAM zugreifen? Das wäre sinnvoll da dort ja die Nutzdaten der User-Mode-Prozesse liegen und um die geht es doch schließlich. Soll die Peripherie überhaupt Speicherbereiche anbieten können (sowas wie der Frame-Buffer einer Grafikkarte)?

Es gibt 256 IRQ lines ...
Wirklich als eigenständige Leitungen? Bei PCI-Express hat man darauf komplett verzichtet (an den PCI-Express-Slots gibt es keine IRQ-Pins mehr). Schau Dir mal das MSI(-X) aus der PCI-Spec an, das hat ne Menge Vorteile gegenüber dedizierten IRQ-Signalen.

In dem Usermode, lösen alle Befehle, mit der die möglichkeit besteht die kontrolle über das system zu erlangen, eine Exception aus.
Dann solltest Du aber 2 verschiedene Register für den Flags vorsehen, eines wo die normalen Flags (C,S,N,O) drin sind und eines für Flags wie IE, damit nicht ständig normale Befehle potentiell gefährliche Sachen machen können (so wie PUSHF/POPF auf x86).


Grüße
Erik
Reality is that which, when you stop believing in it, doesn't go away.

Svenska

  • Beiträge: 1 792
    • Profil anzeigen
Gespeichert
« Antwort #86 am: 29. November 2010, 13:54 »
Die CPU wird eine 64 Bit CPU mit 32 Bit Adressbus, was ich erstens für ausreichend halte und zweitens würde ich die CPU später mal in Hardware bauen. Also nicht nur in einem FPGA laufen lassen.
Du hast also 64-Bit-Register, von denen die oberen 32 Bit nicht auf den Adressbus herausgeführt werden. Das ist in Ordnung. Vielleicht solltest du es aber vorsehen, dass man da ein paar Bits noch nachträglich rausführen kann - als Erweiterung.

Wie möchtest du das Teil bauen, wenn nicht im FPGA? Ein CPLD wird dafür definitiv zu klein sein und von TTL rate ich dir ab. Wenn du so nette Features wie Paging und verschiedene CPU-Modi hast, dann steigt der Aufwand enorm, außerdem musst du bei so breiten Bussen (64 Bit innerhalb der CPU!) und hohen Taktfrequenzen extrem auf die Latenzlaufzeiten aufpassen. Wenn die Leitungen verschieden lang (um eine Ecke legen!) sind, kommen die Signale zu verschiedenen Zeiten am Ende an, was das Auslesen zu einem Zeitpunkt unmöglich macht. Du müsstest also über einen gewissen Zeitraum integrieren (Kondensator), was die maximale Taktrate enorm absenkt.

Mal abgesehen davon sind mir TTL-Bausteine nur bis 50 MHz bekannt, bis etwa 20 MHz sind sie auch bezahlbar. Das gilt für ein einzelnes Gatter. Diese Zahl teilst du durch die Anzahl der Gatter, die ein Signal von Eingang bis Ausgang durchlaufen muss und erhältst dann ungefähr die reale Geschwindigkeit. Zum Vergleich: In einem (teuren) FPGA sind für ein Gatter bis zu 1 GHz möglich.

Außerdem vereinfacht der 32 Bit adressbus breite das Speichermanagment. Als Speichermodell kommt bei mir FlatMemory zum einsatz. Der Speicherschutz wird mit Paging realisiert. Der Befehlssatz wird ein 3 Operanden Befehlssatz werden.
Also an sich nichts neues.

Die kommunikation mit der Hardware läuft über das Klassische I/O Port Konzept ab.
Machbar, aber ich finde MMIO einfach angenehmer. Mit dem I/O-Konzept verzichtest du übrigens auf DMA... es sei denn, du hinterlegst den I/O-Bereich mit Speicher. Und um dann Vorteile daraus zu kriegen, müsstest du jeden CPU-Befehl doppelt implementieren: Einmal für MEM, einmal für I/O. Das heißt zwei vollständige Adressierungsdekoder und eine Opcodeverschwendung.

Machbar, aber imho unelegant.

SMP mit bis zu 32 CPU's und 64 Kernen pro CPU ist geplant.
Du weißt schon, was du dir damit aufhalst?

Es gibt 256 IRQ lines, somit sollte es für jede Situation genügend freie IRQ lines geben, so das keine Geräte sich eine Line teilen müssen. Zur Systemsicherheit, gibt es 2 Privelege Level. In dem Usermode, lösen alle Befehle, mit der die möglichkeit besteht die kontrolle über das system zu erlangen, eine Exception aus.
Besitzt die CPU bereits 256 IRQ-Leitungen oder wirst du einen speziellen IRQ-Controller benutzen?

Baust du 1 IRQ-Leitung an, dann ist das Prinzip wie bei heute üblichen CPUs (an dieser Leitung hängt ein IRQ-Controller). Baust du 8 Leitungen, um 256 IRQs zu verwalten, dann kann immer nur ein IRQ gleichzeitig aktiv sein. Oder du baust 256 Leitungen an die CPU an, was enorm viel Lötarbeit ist...

Gruß,
Svenska

MNemo

  • Beiträge: 547
    • Profil anzeigen
Gespeichert
« Antwort #87 am: 29. November 2010, 13:58 »
Wieso wird eine Idee bereits als kaputt bezeichnet (bewertet!) bevor überhaupt etwas konkretes bei raus gekommen ist?
IMHO ist eine unkonkrete Architektur per Definition Kaputt, bis sie konkret und voll funktionsfähig ist.

zweitens würde ich die CPU später mal in Hardware bauen. Also nicht nur in einem FPGA laufen lassen.
Der Sinn und Zweck von FPGAs ist das 'Hardware Bauen' zu vermeiden. Ein Chip in Hardware zu gießen kosten ein paar Millionen $. Und eine 64-Bit CPU lötet man sich auch nicht einfach mal so zusammen. Siehe mycpu.eu, was für ein Klotz, und das (wimre) für nur 8-Bit.
« Letzte Änderung: 29. November 2010, 14:26 von MNemo »
„Wichtig ist nicht, besser zu sein als alle anderen. Wichtig ist, besser zu sein als du gestern warst!“

erik.vikinger

  • Beiträge: 1 277
    • Profil anzeigen
Gespeichert
« Antwort #88 am: 29. November 2010, 15:00 »
Hallo,


Baust du 1 IRQ-Leitung an, dann ist das Prinzip wie bei heute üblichen CPUs (an dieser Leitung hängt ein IRQ-Controller). Baust du 8 Leitungen, um 256 IRQs zu verwalten, dann kann immer nur ein IRQ gleichzeitig aktiv sein. Oder du baust 256 Leitungen an die CPU an, was enorm viel Lötarbeit ist...
Oder er baut einen IRQ-BUS, sowas in der Art wie der dedizierte APIC-BUS den es mal zu PentiumPro-Zeiten gab, das ist wenig Lötarbeit und die Anzahl der verwaltbaren IRQs hängt nur vom Protokoll ab das da drauf läuft. Mit ein wenig Geschick bei der Protokoll-Entwicklung sollten auch die IRQ-Latenzen kaum darunter leiden. Oder er leitet die IRQs als Messages auf dem normalen Bus mit durch, dafür lohnt sich auch mal ein Blick in die Hyper-Transport-Spezifikation (AMD prahlt schließlich damit das der HT deutlich kleinere IRQ-Latenzen hat als PCI-Express, was auch mit Sicherheit nicht gelogen ist).


Ein Chip in Hardware zu gießen kosten ein paar Millionen $.
Wenn es nur was einfaches ist (was der Chip-Hersteller aus der Komponenten-Datenbank kurz zusammen klickt) kommt man eventuell auch für um die 500'000 $ zum fertigen Silizium. Aber da würde ich auf jeden Fall vorher die Preise und Leistungen der Chip-Gießereien vergleichen.
Wobei ich nicht denke das es das ist was PNoob im Sinn hatte.

Siehe mycpu.eu, was für ein Klotz, und das (wimre) für nur 8-Bit.
Ja, "nur" 8Bit, und trotzdem ist der Fuß kaputt wenn das Ding vom Tisch fällt. ;)


IMHO ist eine unkonkrete Architektur per Definition Kaputt, bis sie konkret und voll funktionsfähig ist.
Echt? Ich bin irgendwie sehr enttäuscht so etwas hier zu lesen. Die meisten Leute hier haben doch erst mal nur Ideen vorzuweisen.


Grüße
Erik
Reality is that which, when you stop believing in it, doesn't go away.

Programm Noob

  • Gast
Gespeichert
« Antwort #89 am: 29. November 2010, 20:21 »
Die CPU wird eine 64 Bit CPU mit 32 Bit Adressbus, was ich erstens für ausreichend halte
Wenn die CPU intern mit 64Bit (virtuellen) Adressen umgehen kann aber extern nur 32Bit hergibt (also so ähnlich wie ein 386SX) dann ist das keine so schlechte Idee, auch wenn die 32Bit gemessen an aktuellen PCs sicher etwas knapp kalkuliert sind. Der Hyper-Transport von AMD unterstützt wimre auch nur 40Bit physische Adressen.
Genau so war es gedacht. Die CPU später auf echte 64 Bit aufzubohren ist dann auch kein Problem.

zweitens würde ich die CPU später mal in Hardware bauen. Also nicht nur in einem FPGA laufen lassen.
Was meinst Du mit "in Hardware bauen"? Wenn nicht in einem FPGA.
Darüber habe ich mir noch keine Gedanken gemacht. TTL ist glaube ich etwas zu kompliziert dafür.

Die kommunikation mit der Hardware läuft über das Klassische I/O Port Konzept ab.
Also einen extra I/O-Adressraum und nicht über MMIO? Alle anderen CPU-Architekturen gehen von den I/O-Ports zu MMIO über (falls sie überhaupt mal I/O-Ports unterstützt haben). Kann dann die Peripherie per eigenständigem Busmastering auf den normalen RAM zugreifen? Das wäre sinnvoll da dort ja die Nutzdaten der User-Mode-Prozesse liegen und um die geht es doch schließlich. Soll die Peripherie überhaupt Speicherbereiche anbieten können (sowas wie der Frame-Buffer einer Grafikkarte)?
Also Die Geräte können alle selbständig auf den Speicher zugreifen.

Es gibt 256 IRQ lines ...
Wirklich als eigenständige Leitungen? Bei PCI-Express hat man darauf komplett verzichtet (an den PCI-Express-Slots gibt es keine IRQ-Pins mehr). Schau Dir mal das MSI(-X) aus der PCI-Spec an, das hat ne Menge Vorteile gegenüber dedizierten IRQ-Signalen.
Also die IRQ Lines werde nicht alle bis in die CPU geführt, sondern gehen an einen Controller, der die dann an die CPU meldet.

In dem Usermode, lösen alle Befehle, mit der die möglichkeit besteht die kontrolle über das system zu erlangen, eine Exception aus.
Dann solltest Du aber 2 verschiedene Register für den Flags vorsehen, eines wo die normalen Flags (C,S,N,O) drin sind und eines für Flags wie IE, damit nicht ständig normale Befehle potentiell gefährliche Sachen machen können (so wie PUSHF/POPF auf x86).
OK da hast du recht.

PNoob

erik.vikinger

  • Beiträge: 1 277
    • Profil anzeigen
Gespeichert
« Antwort #90 am: 30. November 2010, 12:29 »
Hallo,


Was meinst Du mit "in Hardware bauen"? Wenn nicht in einem FPGA.
Darüber habe ich mir noch keine Gedanken gemacht. TTL ist glaube ich etwas zu kompliziert dafür.
Darüber solltest du Dir aber mal Gedanken machen. Meiner persönlichen Meinung nach ist TTL keine echte Option (sorry Svenska), das macht extrem viel Aufwand und dürfte auch einiges an Geld verschlingen. Bei einer sehr simplen 8Bit-CPU kann TTL noch in die Kategorie "schwer aber realistisch" fallen aber für eine 64Bit CPU ist das wohl ganz offensichtlich nicht machbar.

Also Die Geräte können alle selbständig auf den Speicher zugreifen.
Dann nutze den Speicheradressraum auch für die Ressourcen welche von der HW angeboten werden, Du machst Dir damit vieles leichter.

Also die IRQ Lines werde nicht alle bis in die CPU geführt, sondern gehen an einen Controller, der die dann an die CPU meldet.
Wenn Du eh einen richtigen IRQ-Controller haben willst dann wäre es geschickter wenn Du die Interrupt-Vektoren (also die Einsprungspunkte Deiner SW-IRQ-Handler) gleich von diesem verwalten lässt und der CPU dann mitteilst wenn diese einen IRQ-Handler ausführen soll. Das hat den Vorteil das die CPU keine Tabelle dafür benötigt wo sie dann erst nachschauen muss von wo sie denn jetzt die Befehle holen soll (verringert die Latenz) und es ist der CPU völlig egal wie viele verschiedene IRQ-Handler es eigentlich gibt (das ist dann eine reine Design-Frage für den IRQ-Controller und damit flexibel ohne die CPU ändern zu müssen). Wenn Du aber ein Micro-Kernel-OS implementieren möchtest ist es auch OKay wenn es aus CPU-Sicht nur einen einzigen IRQ-Handler (im Kernel-Mode) gibt der dann die IRQ-Nummer als Parameter bekommt und damit nur noch eine asynchrone IPC-Message an den entsprechend registrierten IRQ-Handler vom User-Mode-Treiber schicken muss (diesen Weg möchte ich gehen).

.... damit nicht ständig normale Befehle potentiell gefährliche Sachen machen können (so wie PUSHF/POPF auf x86).
OK da hast du recht.
Du solltest generell dafür sorgen das normale Befehle möglichst wenige Möglichkeiten haben eine Exception auszulösen, wenn Du mehrere unabhängige Befehle hast die alle garantiert keine Exception werfen kannst du die gefahrlos parallel ausführen ohne komplizierte Dinge wie Registerrenaming zu benötigen. Wenn Du das schaffst ist auch Out-of-Order-Execution nicht mehr weit und damit bekommst Du einen enormen Performance-Schub.


Für meine CPU hab ich beschlossen erst mal nur den 60Bit-Befehlssatz fertig zu stellen und die kleineren Codierungen erst dann weiter zu bearbeiten wenn ich einen funktionierenden Assembler und einen funktionierenden Simulator hab, erst dann kann ich real existierenden Code analysieren um zu schauen welche Befehle und Varianten den überhaupt häufig genug sind damit sich dafür kürzere OpCodes lohnen. Ich hab zwar bereits verschiedene kleinere Algorithmen händisch compiliert und assembliert um zu analysieren wo kritische Punkte sind aber es wäre sicher von Vorteil das noch einmal mit einer breiteren Code-Basis zu tun bevor ich endgültige Entscheidungen treffe.


Grüße
Erik
Reality is that which, when you stop believing in it, doesn't go away.

Programm Noob

  • Gast
Gespeichert
« Antwort #91 am: 30. November 2010, 14:27 »
Moin

Also die IRQ Lines werde nicht alle bis in die CPU geführt, sondern gehen an einen Controller, der die dann an die CPU meldet.
Wenn Du eh einen richtigen IRQ-Controller haben willst dann wäre es geschickter wenn Du die Interrupt-Vektoren (also die Einsprungspunkte Deiner SW-IRQ-Handler) gleich von diesem verwalten lässt und der CPU dann mitteilst wenn diese einen IRQ-Handler ausführen soll. Das hat den Vorteil das die CPU keine Tabelle dafür benötigt wo sie dann erst nachschauen muss von wo sie denn jetzt die Befehle holen soll (verringert die Latenz) und es ist der CPU völlig egal wie viele verschiedene IRQ-Handler es eigentlich gibt (das ist dann eine reine Design-Frage für den IRQ-Controller und damit flexibel ohne die CPU ändern zu müssen). Wenn Du aber ein Micro-Kernel-OS implementieren möchtest ist es auch OKay wenn es aus CPU-Sicht nur einen einzigen IRQ-Handler (im Kernel-Mode) gibt der dann die IRQ-Nummer als Parameter bekommt und damit nur noch eine asynchrone IPC-Message an den entsprechend registrierten IRQ-Handler vom User-Mode-Treiber schicken muss (diesen Weg möchte ich gehen).
Also das es nur eine Funktion gibt, die dann als Parameter die IRQ Nummer bekommt. also nicht wie bei x86 wo es eine Tabelle, die IDT gibt, sondern nur eine Funktion?

PNoob

erik.vikinger

  • Beiträge: 1 277
    • Profil anzeigen
Gespeichert
« Antwort #92 am: 30. November 2010, 14:49 »
Hallo,


Also das es nur eine Funktion gibt, die dann als Parameter die IRQ Nummer bekommt. also nicht wie bei x86 wo es eine Tabelle, die IDT gibt, sondern nur eine Funktion?
Ja, genau das meinte ich mit der Idee für ein Micro-Kernel-OS. Aber wenn Du doch einen Monolithen haben willst ist diese Idee weniger gut geeignet, also kein KO-Kriterium aber kostet eben etwas Latenz. Wenn Du etwas mehr Flexibilität möchtest dann lieber die Variante wo der IRQ-Controller die Einsprungspunkte kennt und der CPU bei jedem IRQ sagt wo der zugehörige Handler ist (das kann auch immer der selbe sein). Für ein paar HW-Komponenten wirst du eventuell auch in einem Micro-Kernel-OS dedizierte Handler im Kernel-Mode haben wollen, z.B. für den HW-Timer wo der IRQ-Handler möglicherweise direkt in der Lage sein soll einen Thread auf zu wecken oder eine asynchrone IPC-Message zu versenden.

Die Interrupts für den Kontext-Switch würde ich auch mit nem eigenständigen (und reentranten wegen SMP) Handler erledigen, da ist Performance wichtig. Die Verwaltung der Zeitscheiben sollte auch nicht über den normalen Timer laufen sondern jede CPU sollte einen eigenen primitiven Counter haben der dann direkt diesen Kontext-Switch-Interrupt auslöst ohne Umweg über einen IRQ-Controller.

Dazu kommen in jedem Fall noch ein paar feste Handler für die Exceptions aber das dürfte recht überschaubar sein und ist auch nicht ganz so extrem performancekritisch. Aber der Syscall-Handler sollte schon einen eigenen Einsprungspunkt haben.


Grüße
Erik
Reality is that which, when you stop believing in it, doesn't go away.

Programm Noob

  • Gast
Gespeichert
« Antwort #93 am: 30. November 2010, 15:37 »
Moin

Also das es nur eine Funktion gibt, die dann als Parameter die IRQ Nummer bekommt. also nicht wie bei x86 wo es eine Tabelle, die IDT gibt, sondern nur eine Funktion?
Ja, genau das meinte ich mit der Idee für ein Micro-Kernel-OS. Aber wenn Du doch einen Monolithen haben willst ist diese Idee weniger gut geeignet, also kein KO-Kriterium aber kostet eben etwas Latenz. Wenn Du etwas mehr Flexibilität möchtest dann lieber die Variante wo der IRQ-Controller die Einsprungspunkte kennt und der CPU bei jedem IRQ sagt wo der zugehörige Handler ist (das kann auch immer der selbe sein). Für ein paar HW-Komponenten wirst du eventuell auch in einem Micro-Kernel-OS dedizierte Handler im Kernel-Mode haben wollen, z.B. für den HW-Timer wo der IRQ-Handler möglicherweise direkt in der Lage sein soll einen Thread auf zu wecken oder eine asynchrone IPC-Message zu versenden.
Das macht man doch momentan fast genauso. man legt für alle Interrupts einen stub an, der dann die eigentliche funktion aufruft. daher sollte man keinen unterschied merken.

PNoob

erik.vikinger

  • Beiträge: 1 277
    • Profil anzeigen
Gespeichert
« Antwort #94 am: 30. November 2010, 16:04 »
Hallo,


Das macht man doch momentan fast genauso. man legt für alle Interrupts einen stub an, der dann die eigentliche funktion aufruft. daher sollte man keinen unterschied merken.
Du meinst das man auf x86 256 winzige Assembler-Stubs anlegt die dann alle auf die selbe Funktion springen welche dann per switch wieder verzweigt? Auf x86 sicher ein guter Weg aber generell finde ich das eher unelegant.

Auf meiner CPU wird es etwa 20 Einsprungspunkte geben, und jeder Handler wird ein klein wenig anders sein. Der Handler für den Kontext-Switch-Interrupt wird so schnell als möglich alle Register sichern und dann den Scheduler anspringen, wogegen der Handler für den Syscall erst mal ein switch mit der übergebenen Syscall-Nummer macht (ohne irgendetwas zu sichern) und dann in jeder Funktion individuell entschieden wird ob überhaupt irgendwelche Register zu sichern sind (get_pid wird sicher gar nichts sichern sondern einfach nur die Prozess-ID aus dem Prozess-Decriptor auslesen und sofort nen IRET machen) und wenn ja wie viele Register (bei einem Syscall der blockiert wird natürlich alles direkt in den aktuellen Thread-Descriptor gesichert bevor der Scheduler aufgerufen wird ansonsten eher nur das was tatsächlich im Weg ist auf den Kernel-Mode-Stack). Wenn man viele Register hat muss man da etwas vorsichtiger sein.


Grüße
Erik
Reality is that which, when you stop believing in it, doesn't go away.

Svenska

  • Beiträge: 1 792
    • Profil anzeigen
Gespeichert
« Antwort #95 am: 01. December 2010, 10:35 »
Meiner persönlichen Meinung nach ist TTL keine echte Option (sorry Svenska), das macht extrem viel Aufwand und dürfte auch einiges an Geld verschlingen. Bei einer sehr simplen 8Bit-CPU kann TTL noch in die Kategorie "schwer aber realistisch" fallen aber für eine 64Bit CPU ist das wohl ganz offensichtlich nicht machbar.
Dem kann ich uneingeschränkt zustimmen.

Wenn Du eh einen richtigen IRQ-Controller haben willst dann wäre es geschickter wenn Du die Interrupt-Vektoren (also die Einsprungspunkte Deiner SW-IRQ-Handler) gleich von diesem verwalten lässt und der CPU dann mitteilst wenn diese einen IRQ-Handler ausführen soll.
Als Augenöffner könnte man die drei verschiedenen Interrupt-Modi des Z80 begutachten:

Modus 0: Der Interruptcontroller (bzw. die Hardware) legt ein Byte auf den Datenbus, welches von der CPU als Befehl betrachtet und ausgeführt wird. Für eingebettete Systeme mit fest eingebautem OS recht sinnvoll.

Modus 1: NMI und IRQ funktionieren ähnlich. Die CPU springt an Adresse 0066H (NMI) oder 0038H (IRQ). Der IRQ kann aber trotzdem maskiert werden. Für Minimalsysteme, wo es nur zwei Interruptquellen geben kann.

Modus 2: Der Interruptcontroller (bzw. die Hardware) legt ein Byte auf den Datenbus, welches die Interruptnummer darstellt (nur gerade Zahlen erlaubt). Diese Zahl gibt die unteren 8 Bit der IRQ-Handler-Adresse an, die oberen 8 Bit stehen im I-Register. Flexibel, für größere Systeme.

Eine Mischung aus Modus 1 und 2 wäre das, was Erik vorgeschlagen hat (IRQ-Nummer auf Datenbus, aber feste Sprungadresse - die Nummer taucht dann evtl. in einem Register auf). Die indirekte Variante (Modus 2 oder x86) mit einer Tabelle kostet etwas Speicher, kostet etwas Latenz, ist komplizierter zu implementieren, ist dafür aber maximal flexibel. Die schnellste Variante ist Modus 0; sinnvoll wäre z.B.: der IRQ-Controller erzeugt einen (für jeden IRQ konfigurierbaren?) Befehl, wenn ein entsprechender IRQ auftritt. Für den Timer (häufiger Einzeiler) ist das durchaus sinnvoll. Das setzt natürlich voraus, dass du in eine Befehlslänge auch eine Sprungadresse reinbekommst. Also wenn deine Befehle 32 Bit haben, dann kannst du bei 64-Bit-Datenworten deine IRQ-Handler nur in den ersten 4 GB (die restlichen 32 Datenbit) des Speichers haben. Unkonventionell, aber möglich.

Gruß,
Svenska

erik.vikinger

  • Beiträge: 1 277
    • Profil anzeigen
Gespeichert
« Antwort #96 am: 01. December 2010, 21:47 »
Hallo,


Als Augenöffner könnte man die drei verschiedenen Interrupt-Modi des Z80 begutachten:
Sorry, aber wir wollen uns doch nach vorne entwickeln, der Z80 war doch schon Überholt wo von uns noch keiner gelebt hat, ;)
Als nächstes kommst Du noch mit PDP-11 oder ähnlich alten Dinosauriern. Ich finde ja eher wir sollten uns an schlanken Systemen mittleren Alters orientieren: MIPS, ARM, SPARC oder PA-RISC (sortiert in absteigendem Alter und aufsteigender Komplexität). Vielleicht auch etwas deutlich Jüngeres wie der Itanium, wobei der gleich in doppelter Hinsicht kein Vorbild ist: erst mal ist der viel zu komplex und zweitens ist er genau so untergegangen wie seine namens- und seelenverwandte Titanik. Ein wirklich rundum empfehlenswertes CPU-Vorbild gibt es IMHO einfach nicht, da hilft wohl nur sich selber nen Kopf zu machen.

IRQ-Nummer auf Datenbus, aber feste Sprungadresse - die Nummer taucht dann evtl. in einem Register auf
Vielleicht sollte der IRQ-Controller trotzdem auch die Sprungadresse mit auf den Bus packen, dann hätte man maximale Flexibilität ohne damit die CPU belasten zu müssen (eine in der CPU implementierte Tabelle ist immer entweder zu groß oder zu klein, eben dafür sollte der IRQ-Controller zuständig sein). Die Interrupt-Nummer sollte dem Handler natürlich trotzdem (in einem System-Register) zur Verfügung stehen.

Ich hab noch mal bei meiner CPU nachgesehen: ich hab genau 8 Exception-Einsprungspunkte (die Adresse jeweils in einem globalen Register verwaltet), dazu kommen 2 verschiedene Interrupt-Einsprungspunkte (einmal für den Kontext-Switch der nicht über den IRQ-Controller geht und einmal für die normalen HW-IRQs) und dazu noch 2 Einsprungspunkte für den Syscall-Befehl (das es zwei sind hat den Grund das alle Syscall-Nummern kleiner als 1024 in einen extra Handler gehen sollen damit dieser ohne weitere Range-Checks usw. die richtige Funktion aus nem simplen Array holen kann, wegen der Performance). Alle diese Einsprungspunkte, außer der für die HW-IRQs, kommen aus 11 globalen Registern welche die CPU direkt zur Verfügung hat um eben eine möglichst kleine Latenz zu erreichen. Feste Adressen (wie bei ARM oder Z80) finde ich persönlich doof weil man dann dafür sorgen muss das an dieser Stelle auch wirklich RAM ist und weil dort eh nur ein Sprung auf den tatsächlichen Handler steht. Gerade in diesem Punkt möchte ich sehr flexibel bleiben und dem OS die Möglichkeit geben die CPU möglichst schnell direkt dort hin springen zu lassen wo dann auch wirklich der Handler liegt.

Ein weiterer wichtiger Designpunkt im Zusammenhang mit Interrupts ist die Frage ob es möglich sein soll innerhalb eines Handlers wieder neue Unterbrechungen an zu nehmen. Soll z.B. der Syscall-Handler durch externe IRQs oder durch Exceptions unterbrechbar sein? Wenn ja, dann muss die CPU in der Lage sein mehrere Kontexte ineinander verschachtelt zu sichern (eine CPU die eigenständig den Stack benutzen kann, so wie x86, ist da klar im Vorteil).

Fragen über Fragen, eine eigene Plattform zu entwickeln bringt einem eine ganze Reihe kniffliger Fragen auf den Tisch. Was soll z.B. alles passieren von dem Moment an wo das System mit elektrischer Energie versorgt wird bis zu dem Moment wo das OS dem User ein Login bietet? Soll es ein BIOS geben das die HW rudimentär in Betrieb nimmt und ein beliebiges OS von einem beliebigen Massenspeicher holt oder soll das OS tiefer im System verankert sein und alles selber machen?


Grüße
Erik
Reality is that which, when you stop believing in it, doesn't go away.

Programm Noob

  • Gast
Gespeichert
« Antwort #97 am: 01. December 2010, 21:51 »
Moin

Fragen über Fragen, eine eigene Plattform zu entwickeln bringt einem eine ganze Reihe kniffliger Fragen auf den Tisch. Was soll z.B. alles passieren von dem Moment an wo das System mit elektrischer Energie versorgt wird bis zu dem Moment wo das OS dem User ein Login bietet? Soll es ein BIOS geben das die HW rudimentär in Betrieb nimmt und ein beliebiges OS von einem beliebigen Massenspeicher holt oder soll das OS tiefer im System verankert sein und alles selber machen?
Ich habe das so geplant. wenn Strom kommt, dann wird als erstes ein BIOS geladen, welches den Speicher zählt und die wichtigsten komponenten auf Funktion prüft,  dann wird von einem Massenspeicher ein Bootloader geladen und dem die kontrolle übergeben. was dann kommt ist Systemspezifisch.

PNoob

erik.vikinger

  • Beiträge: 1 277
    • Profil anzeigen
Gespeichert
« Antwort #98 am: 01. December 2010, 22:01 »
Hallo,


welches den Speicher zählt und die wichtigsten komponenten auf Funktion prüft
Das klingt alles so einfach, ich hab da sicher etliche Monate drüber gebrütet um auch nur mal ein grobes Konzept zu haben.

dann wird von einem Massenspeicher ein Bootloader geladen
Also so wie bei x86. Was denkst du was alles nötig ist um überhaupt von einem Massenspeicher einen OS-Boot-Loader laden zu können? Soll dieser OS-Boot-Loader Dein BIOS auch benutzen können (was wie die BIOS-INTs auf x86) um eben auf Massenspeicher zuzugreifen oder ein paar Buchstaben auf den Bildschirm bringen zu können?

In meine Plattform wird es kein BIOS o.ä. geben, da liegt das OS in einem Flash der durch die CPU direkt angesprochen werden kann (als ganz normaler Speicher) und davor kommt ein minimaler Initial-Loader der einfach nur das Image sucht und anspringt. Wenn das OS-Image dann startet gibt es nichts weiter außer Stack und eben den Flash mit dem Code.


Grüße
Erik
Reality is that which, when you stop believing in it, doesn't go away.

Svenska

  • Beiträge: 1 792
    • Profil anzeigen
Gespeichert
« Antwort #99 am: 01. December 2010, 22:29 »
Als Augenöffner könnte man die drei verschiedenen Interrupt-Modi des Z80 begutachten:
Sorry, aber wir wollen uns doch nach vorne entwickeln, der Z80 war doch schon Überholt wo von uns noch keiner gelebt hat, ;)
Ich sprach vom Augen öffnen. Ob du nun ARM, MIPS oder x86 anschaust, dann hast du überall Vektorinterrupts, die von einem Interruptcontroller auf eine IRQ-Leitung plus das Bussystem gemultiplext werden. (Bei SoCs ist der Interruptcontroller natürlich auf dem Die mit drauf.) Der Z80 hatte da vollständig andere Ideen.

Geschichte wiederholt sich. Frühe CP/M- und Unixdateisysteme konnten keine Dateien vergrößern, wie deprimierend, untauglich und überholt. Das ISO-Dateisystem von CDs und DVDs kann das aber auch nicht... man soll die historischen Ideen nicht aus dem Auge verlieren. Die Technik mag komplett überholt sein - und ob du die Vektortabelle nun einsparst, weil dir der Platz im RAM zu knapp bemessen ist oder ob dir die Latenz zu hoch ist, spielt ja keine Rolle mehr. Aber die Idee ist da.

Ein wirklich rundum empfehlenswertes CPU-Vorbild gibt es IMHO einfach nicht, da hilft wohl nur sich selber nen Kopf zu machen.

IRQ-Nummer auf Datenbus, aber feste Sprungadresse - die Nummer taucht dann evtl. in einem Register auf
Vielleicht sollte der IRQ-Controller trotzdem auch die Sprungadresse mit auf den Bus packen, dann hätte man maximale Flexibilität ohne damit die CPU belasten zu müssen (eine in der CPU implementierte Tabelle ist immer entweder zu groß oder zu klein, eben dafür sollte der IRQ-Controller zuständig sein). Die Interrupt-Nummer sollte dem Handler natürlich trotzdem (in einem System-Register) zur Verfügung stehen.[/quote]Wozu? Jeder sinnvoll genutzte Interrupt ist dem System bekannt, also brauchst du in Hardware nicht doppelt arbeiten, um der CPU einmal eine interruptspezifische Funktion und die Interruptnummer mitteilen zu können.

Kostet nur Silizium und im Endeffekt nutzt du genau eine von beiden Möglichkeiten sinnvoll. Maximale Flexibilität ist aber richtig.

Feste Adressen (wie bei ARM oder Z80) finde ich persönlich doof weil man dann dafür sorgen muss das an dieser Stelle auch wirklich RAM ist und weil dort eh nur ein Sprung auf den tatsächlichen Handler steht.
Bei ARM weiß ich es grad nicht, aber beim Z80 sind die Adressen nicht fest. Sie liegen nur alle zusammen in einem (kleinen) Bereich. Man muss ja die historischen Beschränkungen nicht mit dem Konzept übernehmen, außerdem sind die Grenzen heute ganz andere. Wenn IRQ-Handler in den unteren 4 GB des Speichers liegen müssen, sehe ich da kein Problem. Wenn sie in den unteren 256 Bytes liegen müssen, schon...

Was soll z.B. alles passieren von dem Moment an wo das System mit elektrischer Energie versorgt wird bis zu dem Moment wo das OS dem User ein Login bietet? Soll es ein BIOS geben das die HW rudimentär in Betrieb nimmt und ein beliebiges OS von einem beliebigen Massenspeicher holt oder soll das OS tiefer im System verankert sein und alles selber machen?
Ich habe das so geplant. wenn Strom kommt, dann wird als erstes ein BIOS geladen, welches den Speicher zählt und die wichtigsten komponenten auf Funktion prüft,  dann wird von einem Massenspeicher ein Bootloader geladen und dem die kontrolle übergeben. was dann kommt ist Systemspezifisch.
Also das klassische Modell vom x86. Was ist an deinem Konzept eigentlich anders als der Rest? Jede Architektur zeichnet sich durch irgendetwas aus, was zeichnet deine aus?

Eriks Architektur geht ganz neuartig mit Speicher um, meine Architektur ist (theoretisch) in TTL realisierbar.

In meine Plattform wird es kein BIOS o.ä. geben, da liegt das OS in einem Flash der durch die CPU direkt angesprochen werden kann (als ganz normaler Speicher) und davor kommt ein minimaler Initial-Loader der einfach nur das Image sucht und anspringt.
Also baust du ein NOR-Flash an eine Stelle im Adressraum, wo die CPU nach dem Reset die Ausführung beginnt und dort legst du einen Bootloader für z.B. NAND/IDE hin, der Prüfsumme berechnet und startet?

Ein full-featured BIOS finde ich jedenfalls heutzutage übertrieben. Auf keiner modernen mir bekannten Architektur (außer x86) nutzt das Betriebssystem irgendwelche Firmware-Funktionen (bei x86: ACPI, APM und was damit zusammenhängt), mal von der Informationsbeschaffung (Flash-Partitionierung, CPU-Typ und RAM-Größe) abgesehen. Das OS implementiert in der Regel alle Treiber selbst.

Gruß,
Svenska

 

Einloggen