PrettyOS Fehler-/Testthread



  • Revision 256

    // pci.h revision 256
    #define PCIARRAYSIZE      1024
    
    // pci.c revision 256
    (...)
    pciDev_t pciDev_Array[50]; // <- nur 50 elemente !
    (...)
    void pciScan()
    {
     // array of devices, PCIARRAYSIZE for first tests
     for(uint32_t i=0;i<PCIARRAYSIZE;++i)
     {
         pciDev_Array[i].number = i;
     }
    (...)
    }
    

    Diese for-Schleifen (auch in der ckernel.c) gehen ziemlich heftig über die "Arraygrenze" hinaus.

    Dadurch zeigt z.B. VMWARE im "_DIAGNOSIS_"-Mode in der ckernel.c mehr Geräte an als "tatsächlich" vorhanden sind.

    Allerdings könnte das nur durch einen unglaublichen Zufall ein Grund für einen (bei mir bislang nicht) vorhandenen "Host System Error" sein.



  • +gjm+ schrieb:

    ... Diese for-Schleifen (auch in der ckernel.c) gehen ziemlich heftig über die "Arraygrenze" hinaus.

    Mit C++ hätte sowas nicht passieren können... 😉


  • Mod

    @+gjm+: Danke für den Hinweis! Dies war aber leider nicht die Fehlerursache.

    Wir schaffen es einfach nicht, bei extended capabilities im EHCI dem BIOS die Herrschaft zu entreißen! 🙄

    Siehe Rev. 258, da habe ich endlich mal richtig gecheckt, ob das überhaupt klappt. Vorher hatten wir da eine Fehlauswertung im Sinne von if(failed){print: alles ok}. Bei mir ergibt sich BIOS: 1 und OS: 0. Es macht auch keinen Sinn beides auf 1 zu zwingen, sonst hat man einen Gladiatorenkampf.

    XanClic sieht momentan keinen logischen Fehler im Code. Vielleicht ist mit einer Funktion (pci read/write) was falsch, oder wir kapieren etwas noch nicht.

    Wer mithelfen will: EHCI 1.0 spec, Kap. 5

    Problem ist hier (EDIT: gelöst, war bei PCI):

    void DeactivateLegacySupport(uint32_t num)
    {
        delay(2000000);settextcolor(9,0);
        printformat("\n>>> >>> function: DeactivateLegacySupport\n");
    	settextcolor(15,0);
    
    	bool failed = false;
    
        // pci bus data
        uint8_t bus  = pciDev_Array[num].bus;
        uint8_t dev  = pciDev_Array[num].device;
        uint8_t func = pciDev_Array[num].func;
    
        eecp = BYTE2(pCapRegs->HCCPARAMS);
        printformat("\nDeactivateLegacySupport: eecp = %x\n",eecp);
        /*
        cf. EHCI 1.0 spec, 2.2.4 HCCPARAMS - Capability Parameters, Bit 15:8 (BYTE2)
        EHCI Extended Capabilities Pointer (EECP). Default = Implementation Dependent.
        This optional field indicates the existence of a capabilities list.
        A value of 00h indicates no extended capabilities are implemented.
        A non-zero value in this register indicates the offset in PCI configuration space
        of the first EHCI extended capability. The pointer value must be 40h or greater
        if implemented to maintain the consistency of the PCI header defined for this class of device.
        */
        // cf. http://wiki.osdev.org/PCI#PCI_Device_Structure
    
        //                            eecp      // RO  - This field identifies the extended capability.
                                                //       01h identifies the capability as Legacy Support.
        uint32_t NextEHCIExtCapPtr  = eecp + 1; // RO  - 00h indicates end of the ext. cap. list.
        uint32_t BIOSownedSemaphore = eecp + 2; // R/W - only Bit 16 (Bit 23:17 Reserved, must be set to zero)
        uint32_t OSownedSemaphore   = eecp + 3; // R/W - only Bit 24 (Bit 31:25 Reserved, must be set to zero)
        uint32_t USBLEGCTLSTS       = eecp + 4; // USB Legacy Support Control/Status (DWORD, cf. EHCI 1.0 spec, 2.1.8)
    
        if (eecp >= 0x40)
        {
            int32_t eecp_id=0;
            while(eecp)
            {
                printformat("eecp = %x, ",eecp);
                eecp_id = pci_config_read( bus, dev, func, 0x0100/*length 1 byte*/ | (eecp + 0) );
                printformat("eecp_id = %x\n",eecp_id);
                if(eecp_id == 1)
                     break;
                eecp = pci_config_read( bus, dev, func, 0x0100 | NextEHCIExtCapPtr );
                if(eecp == 0xFF)
                    break;
            }
    
            // Legacy-Support-EC found? BIOS-Semaphore set?
            if( (eecp_id == 1) && ( pci_config_read( bus, dev, func, 0x0100 | BIOSownedSemaphore ) & 0x01) )
            {
                printformat("set OS-Semaphore.\n");
                pci_config_write_byte( bus, dev, func, OSownedSemaphore, 0x01 );
                failed = true;
    
                int32_t timeout=200;
                // Wait for BIOS-Semaphore being not set
                while( ( pci_config_read( bus, dev, func, 0x0100 | BIOSownedSemaphore ) & 0x01 ) && ( timeout>0 ) )
                {
                    printformat(".");
                    timeout--;
                    delay(20000);
                }
                if( !( pci_config_read( bus, dev, func, 0x0100 | BIOSownedSemaphore ) & 0x01) ) // not set
                {
                    printformat("BIOS-Semaphore being not set.\n");
                    timeout=200;
                    while( !( pci_config_read( bus, dev, func, 0x0100 | OSownedSemaphore ) & 0x01) && (timeout>0) )
                    {
                        printformat(".");
                        timeout--;
                        delay(20000);
                    }
                }
                if( pci_config_read( bus, dev, func, 0x0100 | OSownedSemaphore ) & 0x01 )
                {
                    failed = false;
                    printformat("OS-Semaphore being set.\n");
                }
                if(failed==false)
                {
                    /*
                    USB SMI Enable R/W. 0=Default.
                    When this bit is a one, and the SMI on USB Complete bit (above) in this register is a one,
                    the host controller will issue an SMI immediately.
                    */
                    pci_config_write_dword( bus, dev, func, USBLEGCTLSTS, 0x0 ); // USB SMI disabled
    
                    printformat("BIOSownedSemaphore: %d OSownedSemaphore: %d\n",
                                 pci_config_read( bus, dev, func, 0x0100 | BIOSownedSemaphore ),
                                 pci_config_read( bus, dev, func, 0x0100 | OSownedSemaphore   ) );
                    settextcolor(2,0);
                    printformat("Legacy Support Deactivated.\n");
                    settextcolor(15,0);
                }
                else
                {
                    settextcolor(4,0);
                    printformat("Legacy Support Deactivated failed.\n");
                    printformat("BIOSownedSemaphore: %d OSownedSemaphore: %d\n",
                                 pci_config_read( bus, dev, func, 0x0100 | BIOSownedSemaphore ),
                                 pci_config_read( bus, dev, func, 0x0100 | OSownedSemaphore   ) );
                    settextcolor(15,0);
                }
            }
        }
        else
        {
            printformat("No valid eecp found.\n");
        }
    }
    

    Bei manchen PC gibt es dennoch Host System Error beim Einschalten der Async.List


  • Mod

    Fehler war in der pci_write_byte-Fkt.



  • Also bei mir wird richtig BIOS owned 0 und OS owned 1 angezeigt, der Host System Error bleibt allerdings.



  • Revision 271

    Solange KERNEL und USER den gleichen "Videobereich" (0xB8000) für Ausgaben nutzen, sollte KERNEL nach erfolgreicher Ausführung von "elf_exec" auf eigene Ausgaben verzichten. Sonst gerät die Ausgabe vom USER u.U. völlig durcheinander:

    // file.c revision 271
    
    int32_t flpydsk_load(const char* name, const char* ext)
    {
    (...)
        if( elf_exec( file, f.size ) ) // <- falls erfolgreich ...
        {
        }
    (...)
    // printf("\n\n");                 // <- ... sollte auf ausgaben ab hier verzichtet werden
     flpydsk_control_motor(false);     // <- hier drin dann auch
     sleepSeconds(3);
     return 0;
    }
    

    (Betrifft aber nicht die Statuszeilen).

    Die Wirksamkeit des VirtualBox-Workaround kann ich nicht bestätigen. Bei mir hat VB ein Problem mit dem Host. Manchmal kann VB der gestarteten VM USB zur Verfügung stellen, manchmal aber auch nicht. Das hängt wahrscheinlich vom Wetter ab. Aber es liegt garantiert nicht am IRQ in der VM von VB. (Wäre ja erschreckend, wenn es so wäre).


  • Mod

    Danke für den Hinweis, wurde umgesetzt.

    VBox und Qemu (Version mit EHCI) laufen momentan am besten. Bei Bochs und VPC fehlen EHCI, und bei VMWare kommt leider nur 00h zurück im IN qTD anstelle 12h etc. Bei realer Hardware klappt es entweder gut oder erst nach einigen Anläufen. Bei Tobikings Laptop macht das BIOS Anstalten und gibt den Staffelstab nicht an den EHCI-Treiber ab, obwohl wir alles brav nach Lehrbuch (Intel PRM) durchführen.


  • Mod

    Solange KERNEL und USER den gleichen "Videobereich" (0xB8000) für Ausgaben nutzen

    Denkst Du man sollte hier einen umschaltbaren Bildschirm schaffen für verschiedene Tasks?



  • Du hast mich zwar nicht direkt gefragt, sag aber, wo Du es ansprichst, auch mal was dazu, ehenkes 😉

    Ich denke, wir brauchen langfristig mehrere Konsolen.
    Daher schlage ich vor: Eine Log-Konsole, wo alle Ausgabe außer der Statusleiste hinkommt.
    Plus n User-Konsolen, wo man Programme ausführen kann.

    Vlt. kann die Log-Konsole auch eine Steuerungskonsole sein, von der aus zusätzlich zur Log-Funktion Befehle ausgeführt werden, wobei Programme dabei in andere Konsolen umgeleitet werden, in die man dann umschalten kann.



  • Hoffentlich habe ich etwas im Quelltext von PrettyOS übersehen (oder nur nicht verstanden). Dann diesen Beitrag einfach ignorieren. 🙂

    Revision 277

    KERNEL und USER nutzen für die Ausgabe putch() in der video.c. KERNEL "direkt" und USER via syscall.

    ⚠ Innerhalb von putch() ist es aber nicht möglich herauszufinden, wer putch() aufgerufen hat. ⚠

    Somit kann man auch nicht festlegen, ob putch() direkt in den Videospeicher schreiben soll oder vorerst in einen Puffer (Array).

    Sollte das korrekt sein, dann sind umschaltbare Bildschirme (und somit mehrere Konsolen) z.Zt. nicht realisierbar.



  • Ich wär dafür, das auch der Kernel nicht unkontrolliert seine Nachrichten absetzt, sondern das Kernel-Output in einer separaten Konsole abläuft.

    Ich werde mal an etwas entsprechendem arbeiten und das dann vorzeigen.



  • Revision 281

    // FloppyImage.bin (Rootdir nach dem Schreiben)
    
    00002660  48 45 4C 4C 4F|[u]20 20 20[/u]|45 4C 46 20 00 01 BA A2  HELLO   ELF ..º¢
    00002670  1E 3B 5A 3B 00 00 3C 86 5A 3B 82 00 62 1C 00 00  .;Z;..<†Z;‚.b...
    00002680  34 30|[u]00 00 00 00 00 00[/u]|54 58 54 20 00 00 00 00  40......TXT ....
    00002690  00 00 00 00 00 00 00 00 00 00 91 00 04 10 00 00  ..........‘.....
    000026A0  38 30|[u]00 00 00 00 00 00[/u]|54 58 54 20 00 00 00 00  80......TXT ....
    000026B0  00 00 00 00 00 00 00 00 00 00 9A 00 04 10 00 00  ..........š.....
    

    Da fehlen noch die nachfolgenden Leerzeichen um auf "8" zu kommen. Seltsamerweise haben VMs damit keine Schwierigkeiten. 🙂



  • Seltsamerweise haben VMs damit keine Schwierigkeiten.

    Die VM hat damit gar nichts zu tun, nur der Code der die Daten liest!



  • VMs reagieren unterschiedlich auf gleichen Code. Wenn bei PrettyOS irgendwas auf Anhieb nicht funktioniert, ist bei mir erstmal die/eine VM dran schuld. Danach erst eventuelle geringfügige Programmierfehler im Quellcode. 🙂

    Zum Thema:
    Eine VM mit MS-DOS als "Gast" (oder wie das sonst heißt) kann die "neuen" Dateien auf der FloppyImage.bin nicht lesen, da ... siehe oben.



  • Revision 293

    Die Shell sieht nun aus wie eine bunte Kuh :). Aber sie ist nun um etliches besser als in vorherigen Revisionen.

    Sehr gute userfriendly Arbeit! 👍 Aber wie starte ich nun eine zweite (und dritte ...) Shell?



  • Danke für das Lob, +gjm+ 🙂

    Mehr Programme gehen bald (vmtl. rev 294). Derzeit gibts noch eine Blockade in der Shell, die das verhindert (Mit Absicht, sonst stören sich die Progs alle gegenseitig)

    EDIT: Seit Rev. 294 gehts.


  • Mod

    Erst ab Rev. 295 läuft das Multikonsolen-System von MrX sehr gut. Wir mussten die shell auf einen anderen Stackpointer setzen als die restlichen User-Programme. Das verstehen wir nicht wirklich. Hier das start.asm:

    ; start.asm
    
    [BITS 32]
    extern __bss_start
    extern __end
    extern _main
    extern _exit
    extern _test
    global _start
    
    _start:
        mov esp, 0x500000 ; stackpointer
        call _main	
    
    	call _exit	
    	call _test
    	jmp  $
    

    Bei den User-Programmen nehmen wir 0x600000.

    Setzt man Shell und die anderen Programme auf 0x500000, dann erlebt man so etwas:

    Page Fault ( user-mode) at 00000000h - EIP: 00000000h err_code: 00000005h address(eip): 00000000h edi: 00000001h esi: 01401688h ebp: 000000C8h eax: 004FFFAFh ebx: 004FFFAFh ecx: 00000000h edx: 00000006h cs: 0000001Bh ds: 00000023h es: 00000023h fs: 00000023h gs 00000023h ss 00000023h int_no 14 eflags 00000246h useresp 004FFF90h

    Ich hoffe auf die geniale "Spürnase" +gjm+

    Jarvix (im IRC) meint, dass es am User-Stack liegt, den wir nicht richtig für jede User-App allokieren. Die Methode in start.asm sei falsch für viele Programme.



  • Revision 295
    Es gibt tatsächlich ein Paging-Problem:

    ; user\user_tools\start.asm 295
    
    _start:
    ; mov esp, 0x600000 ; stackpointer
    
      mov esp, 0x01402000 ; <- solange das problem nicht beseitigt ist
    

    Wenn der Stack der USER mit Adresse 0x600000 inititialisiert wird, benutzen sämtliche USER einen identischen Stack (und somit auch identische lokale Variablen (was heißt Adresse und Wert sämtlicher lokalen Variablen sind bei sämtlichen USERN identisch (sofern man ein Programm mehrmals startet). ( <- Hoffentlich kam das verständlich rüber 🙂 .).

    Irgendwie wird Adresse 0x600000 (und KERNELs 0x500000) nicht korrekt "gepaged".

    Wenn KERNEL (Shell) und alle USER die 0x01402000 benutzen, gibt es keine Probleme. Ein (dann neues) Problem gäbe es erst, wenn die Shell und/oder die Userprogramme > 0x2000 Bytes wären.


  • Mod

    Irgendwie wird Adresse 0x600000 (und KERNELs 0x500000) nicht korrekt "gepaged".

    Das passiert hier in paging.c, line 262, in paging_install:

    // Setup 0x00400000 to 0x00600000 as writeable userspace
        kernel_pd->codes[1] |= MEM_USER | MEM_WRITE;
        for (int i=0; i<512; ++i)
            kernel_pd->tables[1]->pages[i] |= MEM_USER | MEM_WRITE;
    

    wobei wir nicht 0x600000, sondern 0x5fffff nehmen sollten.

    Die shell ist übrigens ein User_Programm und wird auch genauso gestartet.



  • Erhard Henkes schrieb:

    wobei wir nicht 0x600000, sondern 0x5fffff nehmen sollten.

    Nein, da ein PUSH zuerst ESP um vier verringert und dann den Wert auf den Stack legt. Somit führt ESP==0x600000 dazu, dass das erste PUSH den Wert nach 0x5FFFFC legt (im Übrigen sollte man wohl besser keinen unalignten Stack benutzen, der Wert sollte IMO besser immer an vier ausgerichtet sein).


Anmelden zum Antworten