

1. Projektplanung
---------------------



2. Software-Auswahl
---------------------

Imendio Planner
Emacs

Emulator:
 - http://en.wikipedia.org/wiki/Comparison_of_virtual_machines
 + Qemu
     http://www.qemu.org/
 	- schneller: http://www.qemu.org/qemu-tech.html#SEC8
 	- stabiler?
 	- gute doku, weit verbreitet
 - Bochs
     http://bochs.sourceforge.net/doc/docbook/user/index.html
     http://bochs.sourceforge.net/doc/docbook/user/is-bochs-right-for-me.html
     http://bochs.sourceforge.net/doc/docbook/user/features.html
     	- "A few Pentium 4 features are incomplete,"
     	- gute doku
 - Flex ?


3. Qemu
----------------

Lesen:

  QuickStartGuide: 	http://kidsquid.com/cgi-bin/moin.cgi/QuickStartGuide
  Linux:		http://kidsquid.com/cgi-bin/moin.cgi/QemuOnLinux
  Manual:		http://www.qemu.org/qemu-doc.html
  mit gdb: 		http://www.qemu.org/qemu-doc.html#SEC36

Installieren auf tardis:

  kompilieren: 	http://www.qemu.org/qemu-doc.html#SEC65
  # ./configure --prefix=/home/sryffel/bin --enable-system --target-list=i386-softmmu




4. Bochs
-------------------

Lesen:

  Doku:			http://bochs.sourceforge.net/doc/docbook/user/index.html
  Installieren:		http://bochs.sourceforge.net/doc/docbook/user/installation.html
  

Installation:
  http://bochs.sourceforge.net/doc/docbook/user/compiling.html
  # ./configure --enable-cpu-level=3 --enable-apic--enable-all-optimizations   --with-wx --enable-gdb-stub --enable-vbe --enable-idle-hack --with-x11 --enable-fast-function-calls --prefix=/home/sr/work/ETH/2007SS/sa/code/bochs-2.3/install/i386
  # ./configure --enable-cpu-level=6 --enable-mmx --enable-sse=2 --enable-apic --enable-sep --enable-all-optimizations   --with-wx --enable-debugger --enable-disasm --enable-x86-debugger --enable-magic-breakpoints --enable-vbe --enable-idle-hack --with-x11 --enable-fast-function-calls --enable-show-ips --enable-new-pit --prefix=/home/sr/work/ETH/2007SS/sa/code/bochs-2.3/install/pentium/
  #  ./configure --enable-cpu-level=6 --enable-mmx --enable-sse=2 --enable-apic --enable-sep   --with-wx --enable-debugger --enable-disasm --enable-vbe --with-x11 --enable-show-ips --enable-new-pit --prefix=/home/sr/work/ETH/2007SS/sa/code/bochs-2.3/install/pentium/

no --enable-gdb-stub 


5. Boot
-------------------


"Not a bootable disk"
    http://en.wikipedia.org/wiki/Master_boot_record
    http://en.wikipedia.org/wiki/Boot_loader#Boot_loader
    http://mirror.href.com/thestarman/asm/mbr/STDMBR.htm#INTRO
    bochs/bios/rombios.c: int19_function(bseqnr) checks for 0xaa55 sequence
    	-> set: 000001f0: 0000 0000 0000 0000 0000 0000 0000 55aa

Bochs:
00001199988e[CPU0 ] prefetch: EIP [00010000] > CS.limit [0000ffff]
	00001200000i[CPU0 ] real mode
	00001200000i[CPU0 ] CS.d_b = 16 bit
	00001200000i[CPU0 ] SS.d_b = 16 bit
	00001200000i[CPU0 ] | EAX=00001062  EBX=0000ffcc  ECX=000e0000  EDX=00000001
	00001200000i[CPU0 ] | ESP=00002025  EBP=00000000  ESI=0000011c  EDI=00000004
	00001200000i[CPU0 ] | IOPL=0 id vip vif ac vm rf nt of df if tf sf ZF af PF cf
	00001200000i[CPU0 ] | SEG selector     base    limit G D
	00001200000i[CPU0 ] | SEG sltr(index|ti|rpl)     base    limit G D
	00001200000i[CPU0 ] |  CS:f000( 1e00| 0|  0) 000f0000 0000ffff 0 0
	00001200000i[CPU0 ] |  DS:0000( 0000| 0|  0) 00000000 0000ffff 0 0
	00001200000i[CPU0 ] |  SS:1e00( 0000| 0|  0) 0001e000 0000ffff 0 0
	00001200000i[CPU0 ] |  ES:0000( 0000| 0|  0) 00000000 0000ffff 0 0
	00001200000i[CPU0 ] |  FS:0000( 0000| 0|  0) 00000000 0000ffff 0 0
	00001200000i[CPU0 ] |  GS:0000( 0000| 0|  0) 00000000 0000ffff 0 0
	00001200000i[CPU0 ] | EIP=0000ffff (0000ffff)
	00001200000i[CPU0 ] | CR0=0x00000010 CR1=0 CR2=0x00000000
	00001200000i[CPU0 ] | CR3=0x00000000 CR4=0x00000000

Qemu:
-------------
EIP=0000ffcb
CR*=after Reset
EFL=00000206:
	- Parity Flag 1: 
	- Interrupt enabled
CS= 1000 00010000 0000ffff 00000000
SS= 1e00 0001e000 0000ffff 00000000

EAX: 00001056
EBX: 0
ECX: 00000002
EDX: 00000001
ESI: 0000011c "Source Index"
EDI: 0
ESP: 00002005 "Stack Pointer"
EBP: 0



6. Lesen
------------------------


TopsyV3.pdf
	8ff Übersicht Memory Management
	18 Bootstrapping

Using ld
	- was macht *(COMMON)?


7. Ausprobieren
-------------------------

1. Mit Debuginfos neu kompilieren:
 	- intel2gas, Makefile in "Topsy.386-pci/Boot/ia32/LowCore"
	- Files: coreboot.S, corebootmsg.S, coredisk.inc, corescrn.inc, asm.h, CoreLoad.h
	- Intel -> AT&T	
			- "BootMsg db      'C..."	: MootMsg: .ascii "adsf"
			- ".MODEL tiny"			: 
			- "ORG     00H"			: .org 0x0
			- "END     start"		: .end start
			- "OFFSET(BootMsg)"		: BootMsg
			- "RETF"			: lret
			- "seg ss"			: ss ...
	- Kompilieren mit gcc
	- Linken ???
    Bootet nicht...
	- Vergleich Disassembly coreboot.src und coreboot_orig.src
	
	
2. Neues CoreBoot.bin, analysiere Topsy.x386-pci
	- Bootet bis 0x8:0x4315
		- Protected Mode
		- Kernel Startup
---------------------------------------------------------------------------
GDT State: GDTR.limit: 0x30 // GDTR.base: 0x1000
IDT Alias Selector : 0x30
IDT State: IDTR.limit: 0x7FF // IDTR.base: 0x10000
Kernel TSS: 0x38 // TSS Alias: 0x40
USER TSS: 0x48 // TSS Alias: 0x50
TextSize = 53248
DataSize = 135168
Processor Exceptions   : IDT Vectors 0x00..0x1F
Memory Management {Topsy i386, v2.0}
Physical memory        : 0x00000000-0x02000000 = 32768KB (32MB)
Memory management      : 0x00000000-0x08000000 = 131072KB (128MB)
Control structures     : 0x00000000-0x00020000
Kernel space           : 0x00020000-0x0004E000
Hardware IO            : 0x000A0000-0x00100000
Not physically avail.  : 0x02000000-0x08000000

---------------------------------------------------------------------------
	- Crash nach:
		tmInit() (iret)-> 
		  schedule() ->  	Next Process is mmThread
		  restoreContext() -> 	switch to mmThread
		  -> schedule mmThread und tmThread abwechslungsweise...
		  	durch Einführen von Debuggingausgaben wird anderer Fehler getriggert
		  
		Errormessage von msgDispatcher() 	(TMIPC.c)
			- Caller sind mmThread und tmThread
			- Syscall = 1 (=SYSCALL_RECV_OP)
			- fixed break on line 556
		
		"**** PANIC [ mmThread, Memory/MMMain.c:130 ] message receive error!"
			
			- HASHNOTFOUND
				und msgPtr->from ist 0/SELF anstatt 1/ANY 
				SYSCALL / Software Interrupts werden in Threads/ia32/TMHal.c in _INTHandler() verarbeitet
				
				
	- neues CoreBoot.bin (0.16)
		- Fehler mit panic (0x2398)
			b bei 0x22398
			b bei 0x00026857 in ioConsolePutString, nachdem %esi gesetzt wird
		  String bekommen: "x /8hx ds:esi"
			- suchen in topsyimage
			=> "**** PANIC [ mmThread, :Memory/MMMain.c: ] message receive error!"




8. Topsy v3
-------------------------

Mache bootbares topsyimage
	- Anpassungen an CoreBoot, CoreLoad
	- mache DummyStartup.c
	- passe Makefiles an
	- Stub für ia32 VM-Hal
	- Anpassen von Init.c 
		- Alles mit Memory: segmap, 
		- "wieso ist ia32 so kompliziert?"
	- "SWITCHON=PCI_NO", da Treiber altes VM-Api verwenden
	- files: Threads/ia32/TMHal.c, Threads/ia32/TMHalAsm.S, Threads/ia32/TMHal.h, VMemory/vm_bootup.h, Makefiles/Platform.ia32.linux, Makefiles/Makefile.ia32.i386, Startup/DummyStartup.c, Startup/ia32/Init.c, Startup/ia32/start.S, Boot/ia32/Tools/KernPatch/Makefile, Config/bochsrc, IO/ia32/Debug.c, IO/ia32/Drivers/video.S, Memory/ia32/mmHalAsm.S, Memory/ia32/MemoryLayout.h, Makefile, Topsy/ia32/cpu.h
	- topsyimage kompiliert, _viele_ Warnungen mit gcc 4.1.1


Booten: exception
	GDT State: GDTR.limit: 0x30 // GDTR.base: 0x1000
		Message von Startup/ia32/Init.c im main()
			-> __get_GDTE() in Memory/ia32/mmHalAsm.S with pSelector=0x10, pGDTE=0xfffb0007

	--------------------------------------------------------------
	00005586704e[CPU0 ] write_virtual_checks(): write beyond limit, r/w
	00005586704e[CPU0 ] interrupt(): gate.type(3) != {5,6,7,14,15}
	00005586704e[CPU0 ] interrupt(): gate descriptor is not valid sys seg
	00005586704i[CPU0 ] protected mode
	00005586704i[CPU0 ] CS.d_b = 32 bit
	00005586704i[CPU0 ] SS.d_b = 32 bit
	00005586704i[CPU0 ] | EAX=00000028  EBX=00000010  ECX=00000008  EDX=00000000
	00005586704i[CPU0 ] | ESP=0007ff58  EBP=0007ff68  ESI=00000010  EDI=fffc0007
	00005586704i[CPU0 ] | IOPL=0 id vip vif ac vm RF nt of df if tf sf zf af pf cf
	00005586704i[CPU0 ] | SEG selector     base    limit G D
	00005586704i[CPU0 ] | SEG sltr(index|ti|rpl)     base    limit G D
	00005586704i[CPU0 ] |  CS:0008( 0001| 0|  0) 00020000 0000007f 1 1
	00005586704i[CPU0 ] |  DS:0028( 0005| 0|  0) 00001000 0000efff 0 1
	00005586704i[CPU0 ] |  SS:0010( 0002| 0|  0) 00020000 00007fdf 1 1
	00005586704i[CPU0 ] |  ES:0010( 0002| 0|  0) 00020000 00007fdf 1 1
	00005586704i[CPU0 ] |  FS:0010( 0002| 0|  0) 00020000 00007fdf 1 1
	00005586704i[CPU0 ] |  GS:0010( 0002| 0|  0) 00020000 00007fdf 1 1
	00005586704i[CPU0 ] | EIP=0000060c (0000060c)
	00005586704i[CPU0 ] | CR0=0x00000011 CR1=0 CR2=0x00000000
	00005586704i[CPU0 ] | CR3=0x00000000 CR4=0x00000000
	00005586704i[CPU0 ] >> rep movsb byte ptr es:[edi], byte ptr ds:[esi] : F3A4
	00005586704e[CPU0 ] exception(): 3rd (13) exception with no resolution, shutdown status is 00h, resetting
	--------------------------------------------------------------
	Debugging:
		GDT State: GDTR.limit: 0x30 // GDTR.base: 0x1000
		Startup/ia32/Init.c: GDTInit finished
		Memory/ia32/MMHal.c: Get_New_GDTE()
		Memory/ia32/MMHal.c: called __get_GDTR(), llimit=48, lbase=0x1000 
		Memory/ia32/MMHal.c: called Get_GDTE(), i=8
		Memory/ia32/MMHal.c: lGDTE=7f 0  0 0  29b c0 0
		Memory/ia32/MMHal.c: called Get_GDTE(), i=16
		Memory/ia32/MMHal.c: called Get_GDTE(), i=8
		Memory/ia32/MMHal.c: no free GDTE
		Memory/ia32/MMHal.c: called __get_GDTR(), llimit=48, lbase=0x1000 
		Memory/ia32/MMHal.c: calling __set_GDTR, llimit=56, lbase=0x1000 
		IDT Alias Selector : 0520
		IDT State: IDTR.limit: 0x7ff // IDTR.base: 0x10000
		Memory/ia32/MMHal.c: Get_New_GDTE()
		Memory/ia32/MMHal.c: called __get_GDTR(), llimit=56, lbase=0x1000 
		Memory/ia32/MMHal.c: called Get_GDTE(), i=8
		Memory/ia32/MMHal.c: lGDTE=7f 0  0 0  29b c0 0
		Memory/ia32/MMHal.c: called Get_GDTE(), i=16
		Memory/ia32/MMHal.c: called Get_GDTE(), i=8
		Memory/ia32/MMHal.c: no free GDTE
		Memory/ia32/MMHal.c: called __get_GDTR(), llimit=56, lbase=0x1000 
		Memory/ia32/MMHal.c: calling __set_GDTR, llimit=64, lbase=0x1000 
		Memory/ia32/MMHal.c: Get_New_GDTE()
		Memory/ia32/MMHal.c: called __get_GDTR(), llimit=64, lbase=0x1000 
		Memory/ia32/MMHal.c: called Get_GDTE(), i=8
		Memory/ia32/MMHal.c: lGDTE=7f 0  0 0  29b c0 0
		Memory/ia32/MMHal.c: called Get_GDTE(), i=16
		Memory/ia32/MMHal.c: called Get_GDTE(), i=8
		Memory/ia32/MMHal.c: called Get_GDTE(), i=8
		Memory/ia32/MMHal.c: called Get_GDTE(), i=8
	  - Resultat unterschiedlich mit gcc 3 und gcc 4...
	
	-> Lösung: Fix typo in mmHalAsm.S: "pushw   %esi" <==> "popl %esi"


Booten bis vor BuildSegMap() in Init.c

Doku zum Bootup in Bootup.txt


9. Memory
-------------------------

Lesen
	- Segmentation: GDT, LDT
	- Paging
	- Interrupts: IDT
	- Topsy v3 Memory Management
	- pmap Layer StrongArm

Andere Ports
	- VMemory/mips:
	    vm_pmap.c  		  : 
	    vm_bootup_hal.c	:
	    vm_hal.c  		  :	
	    vm_hal.h  		  :
	    vm_pmap_exc.c  	:
	    vm_pmap_hal.h	  :
	    
	- VMemory/ixp2400
      PMap.c          :
      PageCopyZero.h  :
      vm_hal.c        :
      vm_pmap_exc.c   :
      PageCopyZero.S  :
      vm_bootup_hal.c :
      vm_hal.h        :
      vm_pmap_hal.h   :
    

Dokumentation des Memory Layout in Memory-Layout.txt.

Implementation:
  - Chronologisch nach Bootsequenz
      vm_bootup_hal.c:
      vm_pmap.c:
      vm_pmap_asm.S:
      vm_pmap_exc.c:
    
  - TODO: 
     - vm_pmap:  
        vm_install_exception_handlers()
        page_fault_exeption_handler()
        mapSpecialRegions()
     - Elegantere Lösung für Umwandlung: lineare Adressen <-> virtuelle Adressen
        a) Makro LIN_TO_KDSEG(), KDSEG_TO_LIN()
        B) Kernel Daten Segment startet bei 0x0
        c) verwende lea in vm_pmap_*_enter()
     - benütze neuen Binary-Header topsyheader anstatt den BinFileDesc
        - füge tracksize hinzu
        - passe ia32 Port an
        -> nice to have / optional

Verschiebe Kernel Code und Daten Segmente nach 0x0 => virtuelle == lineare Adresse
  - Linker-Script: 
      Virtual Memory Address = 0x20000
      Load Memory Adress     = 0x0
  - Code Anpassungen
      cpu.h, MemoryLayout.h
        Makros anpassen
      creatgdt.inc
        Segment Definitionen
      coreload.inc
        Sprungadresse ins main() 
      Init.c
        KernelConcatenate(): Enferne Strings, welche nicht in den ersten 64KB sind
        viele kleinere Anpassungen
      vm_pmap
        viele kleinere Anpassungen
      VMemory
        entferne LIN_TO_KDSEG(); KDSEG_TO_LIN()
  - Dokumentation updaten
        
      
  
  
  
DEBUGGING
-------------------------

Stack Exception
  Output:
    Kernel Protection Domain: mapping regions ... 
        kernel text : kernel.bin  -> address 0x00020000, size 0x18000 offset 0
    vm_file_connect: offset 0
    addr(ProcContext) = 0x0003d8c0
    EAX  0xf00fffff  EBX  0x00000004  ECX  0x00000014  EDX  0x14000168
    CS   0x00000008  DS   0x00000010  ES   0x14000010  FS   0x00000010
    GS   0x00030010  SS   0x00000010  EIP  0x000245d1  EF   0x00010006
    ESP  0x0007fe90  EBP  0x1400018c  EDI  0x0000000a  ESI  0x14000168
    tSP  0x0007fe80  trp  0x0000000c  err  0x00000000  size 0x0000005c
    *** ERROR [ (in init) (*in exc*), IO/ia32/Debug.c:80 ] DISPLAYCONTEXT
  Trace:
    mainKernelPD = vm_domain_create_kernel(segmap, &kernel);
   
   
General Protection
  Output
    Kernel page stealer init...
    steal_init: sizeof(salloc_header) = 32
    Kernel heap memory init... 
    ===> pmap_region_entering: virt 0x10000000 => phys 0x00040000 (size = 4KB)
    WARNING: General Protection occured: 
    addr(ProcContext) = 0x0003d8c0
    EAX  0x00000001  EBX  0x0003da20  ECX  0x00001000  EDX  0x10001000
    CS   0x00000008  DS   0x00040010  ES   0x00040010  FS   0x00480010
    GS   0x00000010  SS   0x00040000  EIP  0x00024d59  EF   0x00010006
    ESP  0x0003dbe0  EBP  0x00000006  EDI  0x00040000  ESI  0x10000000
    tSP  0x0007ff10  trp  0x0000000d  err  0x00000000  size 0x0000005c
  Trace
    km_init()
    HeapAllocator_init()
      übergebene Adresse address ungültig!
  => fehlendes F in byte 6 im GDTE des Kernel Datensegment 4GB 
    
    
PANIC
  Output
    Kernel Protection Domain: mapping regions ... 
          kernel text : kernel.bin  -> address 0x00020000, size 0x18000 offset 0
    vm_file_connect: offset 0
    kernel data & bss : kernel.bin  -> address 0x00038000, size 0x7000 offset 0x18000

    vm_file_connect: offset 0x18000
     boot & INT stack : bootstack   -> address 0x0007e000, size 0x2000 offset 0
     internal VM heap : stealer     -> address 0x00800000, size 0x400000 offset 0
      VM static pages : anonymous   -> address 0x00000000, size 0x20000 offset 0
            mapping FAILED error -32
    **** PANIC [ (in init) (*in exc*), VMemory/vm_domain.c:215 ] vm_domain_create_ke
    rnel: set_region -> vm_region_add failed
  Trace:
    vm_domain_create_kernel()
    vm_region_add()
    vm_map_lookup_region() liefert VM_OUTOFMAP
      vm_map_lookup_region: hint->start  = 0x00000000, hint->end  = 0x0001ffff, 
                            header.start = 0x00010000, header.end = 0xffffffff
   => Ändere getSegStart()
      -> liegere 0x0 für KERNEL...
      ??? /* XXX room for pmap hacks, there should be only one kernel PD!!! */
      
   => vm_map_lookup_region: hint->start  = 0x00000000, hint->end  = 0x0001ffff, 
                            header.start = 0x00000000, header.end = 0xffffffff
      liefert VM_BADDESC, da Region gleichen start aber logischerweise ein anderes end hat als der header...
        -> ändere if zu: "if ( t->start == hint->start && !DOUBLEQ_FIRST(t, regionq) )"

General Protection Error
  Output
    RestoreContext Name: tmThread
    RestoreContext StackStart: 0xc0200ffc
    RestoreContext StackEnd: 0xc0101000
    RestoreContext ContextPtr: 0x00000010
    RestoreContext Context:
    addr(ProcContext) = 0x00000010
    Context Address looks strange to me: 0x00000010
    ... going to the real thing(tm)
  Trace
    EIP in __NEx_0D
  
  => threadBuild() fehlerhaft
  
Division by zero 
  Output
    addr(ProcContext) = 0x0003f1c0
    EAX  0x00000000  EBX  0x00000000  ECX  0x00000000  EDX  0x00000000
    CS   0x00000008  DS   0x00000010  ES   0x00000010  FS   0x00000010
    GS   0x00000010  SS   0x00000010  EIP  0x00032470  EF   0x00000202
    ESP  0xc0200fa4  EBP  0x00000000  EDI  0x00000000  ESI  0x00000000
    tSP  0x00000000  trp  0x00000000  err  0x00000000  size 0x0000005c
    *** ERROR [ tmThread (*in exc*), IO/ia32/Debug.c:80 ] DISPLAYCONTEXT
    ... going to the real thing(tm)
    WARNING: Division by zero occured: 
    addr(ProcContext) = 0x0003f1c0
    EAX  0x00000000  EBX  0x0003f220  ECX  0x00000000  EDX  0x00000000
    CS   0x00000008  DS   0x00000010  ES   0x00000010  FS   0x00000010
    GS   0x00000010  SS   0x00000000  EIP  0x000350e8  EF   0x00010082
    ESP  0x00000000  EBP  0x00000000  EDI  0x00000020  ESI  0x00000000
    tSP  0xc0200f00  trp  0x00000000  err  0x00000000  size 0x0000005c
    *** ERROR [ tmThread (*in exc*), IO/ia32/Debug.c:80 ] DISPLAYCONTEXT
    *** ERROR [ tmThread (*in exc*), Threads/ia32/TMError.c:67 ] Division by zero
  Trace
    _TimerISR() ???
      tFREQUENCY = (unsigned long)(1000 / TIMESLICE) = (unsigned long)(1000 / 100000) = 0!!!
      setClockValue(CLOCK0, TIMESLICE, RATEGENERATOR)
        TIMESLICE     = 50  how long a thread may run, in milliseconds
        RATEGENERATOR = clock mode
        -> divisor = fixrate * period / 1000
            1 < divisor < 2^16  =>  1/fixrate (838ns) < period < 54ms 
                                =>  1.9MHz            >   f    > 18.2Hz
        siehe - http://en.wikipedia.org/wiki/Intel_8254
              - http://www.intel.com/design/archives/periphrl/docs/7203.HTM
      (tFREQUENCY >> 2) > 0
    => ändere TIMESLICE auf 50ms
        -> tFREQUENCY = 5
      
Unknown "random" interrupt occured:
  Output
    Unknown "random" interrupt occured : 137625616 :-?
      currentThread: 
    addr(ProcContext) = 0x0003f1e0
    EAX  0x02080010  EBX  0x02080010  ECX  0x00000010  EDX  0x08340010
    CS   0x02080010  DS   0x02080010  ES   0x00000010  FS   0x08340010
    GS   0x02080010  SS   0x02080010  EIP  0x00000010  EF   0x08340010
    ESP  0x00000010  EBP  0x08340010  EDI  0x00000010  ESI  0x02080010
    tSP  0x00000010  trp  0x08340010  err  0x08340010  size 0x0000005c
  Context von mmThread ungültig -> ungültige Segmente cs und ds.
      mmThread: 0x3f180
      tmThread: 0x3f1e0
  Debug
    restoreContext() -> __contextBoundariesOK -> no __PRLChange -> magic...
    Page Fault Exception (0x0E) @?
    00059864285: exception (not softint) 0008:000209e4 (0x000209e4)
    00059864285: iret 0008:000209e4 (0x000209e4)
    immer sobald iret von restoreContext() ausgeführt wurde, kommt der nächste Interrupt vom Timer...
      -> Problem mit Bochs?
      -> Timer Konfiguration?
      -> APIC ausprobieren?
    => altes Statement TIMESLICE=55 nicht übernommen, da in .h File -> integer overflow
      
Page Fault in msgAdjust() -> msgAdjust() nicht mehr nötig, auskomentieren.

**** PANIC [ tmThread (*in exc*), Threads/ia32/TMHal.c:522 ] moveMessageToPD() not implemented
  => Implementation of moveMessageToPD() in TMHal.c
  
Page Fault in tmMsgRecv() in ./Topsy/ia32/SyscallMsg.S
  Output
    WARNING: Page Fault occured: 
    addr(ProcContext) = 0x0003f260
    EAX  0xc0200d34  EBX  0xffffffff  ECX  0x00000000  EDX  0xffffffff
    CS   0x00000008  DS   0x00030010  ES   0x00020010  FS   0xc0200010
    GS   0x10000010  SS   0x00000001  EIP  0x000201ae  EF   0x00010246
    ESP  0xe82ef000  EBP  0xc0200d0c  EDI  0xc0200d34  ESI  0xefd2f000
    tSP  0xc0200ce8  trp  0x0000000e  err  0x00000002  size 0x0000005c
  => Implement page remapping in _INTHandler()
    Löste Problem nicht:
  Backtrace:
    vmAllocateStack()
    genericSyscall()
    tmMsgRecv()
  Debug:
    Problem beim Speichern der ThreadID in msg.from
    Argumente von tmMsgRecv:
      ThreadID   = -1
      Message ID = 0
      &msg       = 0xefd2f000 => nicht in VM!
      timeOut    = -1
    genericSyscall()
      nach tmMsgSend() sind die Nachrichtenpointer verändert...


FPU Exception 
  Output
    WARNING: FPU error occured: 
    addr(ProcContext) = 0x0003f320
    EAX  0x00000010  EBX  0x00000010  ECX  0x00000010  EDX  0x00000010
    CS   0x00000010  DS   0x00000010  ES   0x00000010  FS   0x00000010
    GS   0x00000010  SS   0x00000010  EIP  0x00000010  EF   0x00000010
    ESP  0x00000010  EBP  0x00000010  EDI  0x00000010  ESI  0x00000010
    tSP  0x00000010  trp  0x00000010  err  0x00000010  size 0x0000005c
  Debug
    Tritt im mmThread nach dem Syscall in tmMsgRecv() auf:
      pop    %esi
      proviziert Stack-???
      ebp:0xc00fff00, esp:0xc00fff50
    Ist Page Fault?:
      eax:0x000201bb, ebx:0x00000001, ecx:0x00000000, edx:0xffffffff
      ebp:0xc00fff00, esp:0x0003f328, esi:0xc00fff50, edi:0xfffffff2
      eip:0x00020906, eflags:0x00000082, inhibit_mask:0
      cs:s=0x0008, dl=0x0000009f, dh=0x00c09b00, valid=1
      ss:s=0x0010, dl=0x0000ffff, dh=0x00cf9300, valid=7
      ds:s=0x0010, dl=0x0000ffff, dh=0x00cf9300, valid=1
      es:s=0x0010, dl=0x0000ffff, dh=0x00cf9300, valid=1
      fs:s=0x0010, dl=0x0000ffff, dh=0x00cf9300, valid=1
      gs:s=0x0010, dl=0x0000ffff, dh=0x00cf9300, valid=1
      ldtr:s=0x0000, dl=0x0000ffff, dh=0x00008200, valid=1
      tr:s=0x0038, dl=0xe0000067, dh=0x00008901, valid=1
      gdtr:base=0x00001000, limit=0x78
      idtr:base=0x00010000, limit=0x7ff
      dr0:0x00000000, dr1:0x00000000, dr2:0x00000000
      dr3:0x00000000, dr6:0xffff4ff0, dr7:0x00000400
      cr0:0x80000011, cr1:0x00000000, cr2:0xfffffff2
      cr3:0x00081000, cr4:0x00000000
    Restore Context:
      eax:0x0003f320, ebx:0x0003f3e0, ecx:0x00000000, edx:0x00000002
      ebp:0xc0200c7c, esp:0xc0200c7c, esi:0xc0200d6c, edi:0x00000030
      eip:0x000207d7, eflags:0x00000083, inhibit_mask:0
      cs:s=0x0008, dl=0x0000009f, dh=0x00c09b00, valid=1
      ss:s=0x0010, dl=0x0000ffff, dh=0x00cf9300, valid=7
      ds:s=0x0010, dl=0x0000ffff, dh=0x00cf9300, valid=7
      es:s=0x0010, dl=0x0000ffff, dh=0x00cf9300, valid=1
      fs:s=0x0010, dl=0x0000ffff, dh=0x00cf9300, valid=1
      gs:s=0x0010, dl=0x0000ffff, dh=0x00cf9300, valid=1
      ldtr:s=0x0000, dl=0x0000ffff, dh=0x00008200, valid=1
      tr:s=0x0038, dl=0xe0000067, dh=0x00008901, valid=1
      gdtr:base=0x00001000, limit=0x78
      idtr:base=0x00010000, limit=0x7ff
      dr0:0x00000000, dr1:0x00000000, dr2:0x00000000
      dr3:0x00000000, dr6:0xffff4ff0, dr7:0x00000400
      cr0:0x80000011, cr1:0x00000000, cr2:0x00000000
      cr3:0x00081000, cr4:0x00000000
      
      after mov %eax, &esp
         | STACK 0x0003f320 [0x00000010]
         | STACK 0x0003f324 [0xc00f0010]
         | STACK 0x0003f328 [0xffff0010]
         | STACK 0x0003f32c [0x00000010]
         | STACK 0x0003f330 [0x00000020]
         | STACK 0x0003f334 [0xc00fff8c]
         | STACK 0x0003f338 [0xc00fff50]
         | STACK 0x0003f33c [0xc00fff00]
         | STACK 0x0003f340 [0xc00fff40]
         | STACK 0x0003f344 [0x00000001]
         | STACK 0x0003f348 [0xffffffff]
         | STACK 0x0003f34c [0x00000000]
         | STACK 0x0003f350 [0x00000002]
         | STACK 0x0003f354 [0x00000000]
         | STACK 0x0003f358 [0x000201bb]
         | STACK 0x0003f35c [0x00000008]
      after popa
        eax:0x00000002, ebx:0x00000001, ecx:0x00000000, edx:0xffffffff
        ebp:0xc00fff00, esp:0x0003f354, esi:0xc00fff50, edi:0xc00fff8c
        eip:0x000207e3, eflags:0x00000002, inhibit_mask:0
        cs:s=0x0008, dl=0x0000009f, dh=0x00c09b00, valid=1
        ss:s=0x0010, dl=0x0000ffff, dh=0x00cf9300, valid=7
        ds:s=0x0010, dl=0x0000ffff, dh=0x00cf9300, valid=1
        es:s=0x0010, dl=0x0000ffff, dh=0x00cf9300, valid=1
        fs:s=0x0010, dl=0x0000ffff, dh=0x00cf9300, valid=1
        gs:s=0x0010, dl=0x0000ffff, dh=0x00cf9300, valid=1
        ldtr:s=0x0000, dl=0x0000ffff, dh=0x00008200, valid=1
        tr:s=0x0038, dl=0xe0000067, dh=0x00008901, valid=1
        gdtr:base=0x00001000, limit=0x78
        idtr:base=0x00010000, limit=0x7ff
        dr0:0x00000000, dr1:0x00000000, dr2:0x00000000
        dr3:0x00000000, dr6:0xffff4ff0, dr7:0x00000400
        cr0:0x80000011, cr1:0x00000000, cr2:0x00000000
        cr3:0x00081000, cr4:0x00000000
      add $4, %esp
       | STACK 0x0003f358 [0x000201bb]
       | STACK 0x0003f35c [0x00000008]
       | STACK 0x0003f360 [0x00000246]
       | STACK 0x0003f364 [0xfffffffe]
       | STACK 0x0003f368 [0x00000053]
       | STACK 0x0003f36c [0xffffffff]
       | STACK 0x0003f370 [0x00000000]
       | STACK 0x0003f374 [0x00000000]
       | STACK 0x0003f378 [0x7fffffff]
       | STACK 0x0003f37c [0x00000000]
       | STACK 0x0003f380 [0xc0200010]
       | STACK 0x0003f384 [0x00000010]
       | STACK 0x0003f388 [0x00020010]
       | STACK 0x0003f38c [0x00030010]
       | STACK 0x0003f390 [0x00000030]
       | STACK 0x0003f394 [0xc0200d34]
      after:
        (0) [0x000207eb] 0008:000207eb (unk. ctxt): jnz .+0x0000003b (0x00020828) ; 753b
        (0) [0x000207ed] 0008:000207ed (unk. ctxt): movl %edi, %ss:0x3e1c0    ; 36893dc0e10300
        (0) [0x000207f4] 0008:000207f4 (unk. ctxt): movl %ss:0xc(%esp), %edi  ; 8b7c240c
        (0) [0x000207f8] 0008:000207f8 (unk. ctxt): subl $0x0000000c, %edi    ; 83ef0c
        (0) [0x000207fb] 0008:000207fb (unk. ctxt): movl %eax, %ss:0x3e1c4    ; 36a3c4e10300
        (0) [0x00020801] 0008:00020801 (unk. ctxt): movl %ss:(%esp), %eax     ; 8b442400
        (0) [0x00020805] 0008:00020805 (unk. ctxt): movl %eax, %ss:(%edi)     ; 36894700
        02937687412i[CPU0 ] WARNING: HLT instruction with IF=0!
      ESP points to eip:
       | STACK 0x0003f358 [0x000201bb]  <- EIP
       | STACK 0x0003f35c [0x00000008]  <- CS
       | STACK 0x0003f360 [0x00000246]  <- EFlags
       | STACK 0x0003f364 [0xfffffffe]  <- ESP    !!!!! wrong, overwritten by?
       | STACK 0x0003f368 [0x00000053]  <- SS     !!!!!
       | STACK 0x0003f36c [0xffffffff]  <- tf_iomap_base, tf_debug_trap
       | STACK 0x0003f370 [0x00000000]  <- tf_ldt_seg
       | STACK 0x0003f374 [0x00000000]  <- tf_pdbr
       | STACK 0x0003f378 [0x7fffffff]  <- tf_tss_seg
       | STACK 0x0003f37c [0x00000000]  <- tf_tss_alias
       tmContext: 
       | STACK 0x0003f380 [0xc0200010]  <- 
       | STACK 0x0003f384 [0x00000010]
       | STACK 0x0003f388 [0x00020010]
       | STACK 0x0003f38c [0x00030010]
       | STACK 0x0003f390 [0x00000030]
       | STACK 0x0003f394 [0xc0200d34]
      byteCopy overwrites 0x0003f364
        => __general_ExceptionHandler und restoreContext() in TMHalAsm.S sind nicht auf neuen ProcContext_t aus TMHal.h angepasst!
        => KCSEL ist 0, da altes MemoryManagement auskommentiert...
            Repariere Segment-Code
        => Debugging Output in schedule() macht Funktion zu lange => Timer läfut zu früh ab.
            ohne Debugging Output: Page Fault in 
  Topsy hängt in __mutex()
    Backtrace:
      schedule()                                : print "scheduled" message...
      printf()
      ioConsolePutString()
      kprintc(), respektive ioConsolePutChar()  :  __mutex(&vMutex,KPRINTLOCK);
      __mutex()
    Lock holder:
      mmThread eip=0x00020cc1   => is schedulerRunning()
      tmThread eip=0x000201bb   => 
    => kommentiere printf() aus...
    
Page Fault in byteCopy() des tmThread
  Output:
    threadBuild:  stackBase : 0x7ffff000   mappedBase : 0x60000000
                  stackStart: 0x800feffc   mappedStart: 0x600ffffc
    WARNING: Page Fault occured: 
    addr(ProcContext) = 0x0003f520
    EAX  0x000000fe  EBX  0xc0200d44  ECX  0x00000000  EDX  0x00000018
    CS   0x00000008  DS   0x00020010  ES   0xffff0010  FS   0x00000010
    GS   0x00000010  SS   0x00000008  EIP  0x00021b69  EF   0x00010217
    ESP  0xc0200d10  EBP  0x10000894  EDI  0x00000030  ESI  0x600fffe0
    tSP  0xc0200d00  trp  0x0000000e  err  0x00000002  CR3  0x00081000
    size         80
  Backtrace
    threadBuild()
      byteCopy((char*)stackStartMappedAt - sizeof(Message), 
            &threadExitMsg,
            sizeof(Message));
    byteCopy()  
      targetAddress = 0xc0200d44
      sourceAddress = 0x600fffe0  => page fault!
      nbBytes       = 0x0000001c  => 28
  Problem
    Im Allgemeinen sind die PDs und damit die VM-Mappings des tmThreads und des Neuen verschieden.
      - TMHal.c:    tmSetReturnAddress(), tmSetArgument0(), tmSetArgument1()
      - TMThread.c: byteCopy() auf Stack
      -> Funktionen werden nur in threadBuild() verwendet. Es genügt also, in dieser 
         Funktion die erste Page des Stacks in den aktuellen (kernel???) PD zu mappen. ???
        TMHal.c macht regen Gebrauch der vm_pmap* Funktionen und vm-Variablen ???
          - ??? wenn tmThread und mmThread in verschiedenen PDs laufen, sind diese Variablen immer noch zugreifbar?
          - Müsste mit Messages implementiert werden: langsam
          - siehe auch moveMessageToPD() in TMHal.c, gleiche Lösung in allen anderen Architekturen
       - tmAdjustMachineDependentRegisters() ist überflüssig, ausser man würde Stack zuerst 
         in den Kernel VM mappen und in dieser Funktion wieder zurück. ???
    Implementiere schlauen Page Fault Handler
      - Alle Exception Handlers werden in tmInit() wieder gelöscht      
      -> Problem noch nicht gelöst...
    Was passiert bei vmAllocateStack(), wieso wird Mapping nicht eingetragen?
      vmAllocateStack(destPD, &stackBaseAddress, getSegEnd(USER), TM_DEFAULTTHREADSTACKSIZE, &stackBaseMapped) 
      Syscall VM_ALLOC_STACK
       1. vm_region_add_near:
        Stack wird als VM_MANAGER_ANON Region angelegt. Das Mapping wird bei diesem Typ erst beim ersten Zugriff eingetragen.
       2. vm_region_share_near:
        Lege "gleiche" region in pd des callers an
      
??? Boundaries Check in restoreContext() (TMHalAsm.s)
  - Ist dies nötig, was kann überhaupt ausgesagt werden?
    => auskommentiert...
        
Deadlock in __mutex()
  Backtrace
    msgDispatcher(): "msgDispatcher: from=...."
    printf()
    ioConsolePutString()
    kprintc()
    __mutex() mit vMutex

FPU Error
  Problem
    wieso und wo wird vm_region_free aufgerufen?  
      von vm_main(), aufgerufen von threadStart() => iO
    FPU Error, aber status word ist 0?
    Angebliche Adresse 0x55504620 des Frames ist nicht in VM...
    Laut bochs treten nur Page Faults auf
  Page Fault
    schedulerRunning() = 0x10000894
      procContext = 0x10000978
        0x10000978 <bogus+       0>:    0x00000010      0x00081000      0x0000000e      0x800fef98
        0x10000988 <bogus+      16>:    0x00000000      0x00000000      0x100009a4      0x00000000
        0x10000998 <bogus+      32>:    0x00000000      0x00000000      0x00036456      0x00000002
        0x100009a8 <bogus+      48>:    0x000207f6      0x00000008      0x00010092      0x00036456
        0x100009b8 <bogus+      64>:    0x00000008      0x00000202      0x800fefa4      0x00000010
      -> ioMain()
         pdbr = 0 !         kontrolliere tmSetMachineDependentRegisters()...
         esp = 0x800fefa4 
         ss = 0x10          
      Exception in "movl %eax, %ss:(%edi)" in restoreContext()
        (0) [0x000207f6] 0008:000207f6 (unk. ctxt): movl %eax, %ss:(%edi)     ; 36894700
        <bochs:646> info cpu
          eax:0x00036456, ebx:0x00000000, ecx:0x00000000, edx:0x00000000
          ebp:0x00000000, esp:0x100009b4, esi:0x00000000, edi:0x800fef98
          eip:0x000207f6, eflags:0x00000092, inhibit_mask:0
          cs:s=0x0008, dl=0x0000009f, dh=0x00c09b00, valid=1
          ss:s=0x0010, dl=0x0000ffff, dh=0x00cf9300, valid=7
          ds:s=0x0010, dl=0x0000ffff, dh=0x00cf9300, valid=1
          es:s=0x0010, dl=0x0000ffff, dh=0x00cf9300, valid=1
          fs:s=0x0010, dl=0x0000ffff, dh=0x00cf9300, valid=1
          gs:s=0x0010, dl=0x0000ffff, dh=0x00cf9300, valid=1
          ldtr:s=0x0000, dl=0x0000ffff, dh=0x00008200, valid=1
          tr:s=0x0038, dl=0xe0000067, dh=0x00008901, valid=1
          gdtr:base=0x00001000, limit=0x68
          idtr:base=0x00010000, limit=0x7ff
          dr0:0x00000000, dr1:0x00000000, dr2:0x00000000
          dr3:0x00000000, dr6:0xffff4ff0, dr7:0x00000400
          cr0:0x80000011, cr1:0x00000000, cr2:0x600fffe0
          cr3:0x00081000, cr4:0x00000000
        <bochs:648> info tab
          cr3: 00081000
          0x00000000-0x00010fff -> 0x00000000-0x00010fff
          0x00017000-0x0003ffff -> 0x00017000-0x0003ffff
          0x0007e000-0x0007ffff -> 0x0007e000-0x0007ffff
          0x00081000-0x005c2fff -> 0x00081000-0x005c2fff
          0x00800000-0x00800fff -> 0x00040000-0x00040fff
          0x00801000-0x0080bfff -> 0x00046000-0x00050fff
          0x10000000-0x10000fff -> 0x00041000-0x00041fff
          0x14000000-0x14000fff -> 0x00042000-0x00042fff
          0x18000000-0x18000fff -> 0x00043000-0x00043fff
          0x1c000000-0x1c000fff -> 0x00044000-0x00044fff
          0x20000000-0x20000fff -> 0x00045000-0x00045fff
          0x600ff000-0x600fffff -> 0x00053000-0x00053fff
          0xc00ff000-0xc00fffff -> 0x00051000-0x00051fff
          0xc0200000-0xc0200fff -> 0x00052000-0x00052fff
          0xfee00000-0xfee00fff -> 0xfee00000-0xfee00fff
      => Es sollte der neue Stack aufgesetzt werden. Dieser ist aber noch nicht gemappt. 
          esp zeigt im Moment noch auf %eip im ProcContext! Dieser wird beim Interrupt überschrieben...
          -> Page Fault
             in _INTHandler contextPtr=0x55504620, byteCopy()
              -> Page Fault
      => Lösungen
          a) Page Fault kontrolliert provozieren???
          b) Kontext nicht speichern, wenn Exception in restoreContext()???
          c) 
        TODO: Beim Anlegen eines neuen Stacks, sollte die erste Page gleich gemappt werden.
          
                        
ACPI
-------------------------

Initalisierung
  - Check for APIC
  - Aktiviere APIC
  - Get CPU-Infos
  
Timer Initalisierung
  - Kalibrierung des Timers über RTC
  
Finde CPU-Typ heraus
  - Brand String
    Erst ab Pentium 4
  - Brand Index
    ab späteren Versionen des Intel486
    wird von neuen Prozessoren nicht mehr unterstützt
    
Timer Implementation? 
  - setClockValue()
  - ApicTimerISR()
  ??? anderen Interrupt-Vektor für APIC Timer:
  - __endOf_APIC_IRQ(), Unterscheidung in _INTHandler() (TMHal.c)
    ??? nur korrekt, wenn nur entweder PIC oder APIC Timer! 
    Gilt zB auch beim Bootup: kein Timer-Interrupt wenn APIC noch nicht initialisiert. In Linux wird aber zB der PIC Timer (aber nicht Interrupt) für die Kalibrierung des APIC Timers verwendet...


ZWISCHENPRÄSENTATION
-------------------------
Vorbereitung
Nachbereitung


NEUES THREAD MANAGEMENT
-------------------------

Erarbeite Konzept

Starte Implementierung
  - versuche Grundstein für SMP zu legen
  - neue structs in TMHal.h
  - neue HAL-Funktionen:
      tmHalInit(), tmHalInitProcCtx()
  - passe TM-Funktionen an:
      threadStart(), threadBuild(), tmInit(), threadDestroy(), 
  - passe alte HAL-Funktionen in TMHal.c an neue structs an
  - benütze TSS, Kernel Mode Stacks
      -> neu sind die Stacks architekturabhängig und werden in tmHalInitProcCtx() angelegt
  - implementiere Kontext speichern 
  - implementiere Kontext Wechsel
      restoreContext(), __restoreContext()
  - implementiere neues Scheduling-Konzept im INTHandler

PROBLEME
  - Alignierung der Stacks noch ungelöst.
  - Viele Änderungen am architekturunabhängigen Teil.
     -> Stack Management wurde jetzt architekturabhängig.
  - Scheduling ungelöst.
  - nicht implementierte Syscalls:
      - vm_map_find_near
      - VM_REGION_SHARE
      - VM_REGION_ADD_NEAR unvollständig


FRAGEN???:
  - in vm_main: was ist das Problem mit VM_REGION_SHARE??? Wieso ist dies nicht implementiert?
  - wieso kein VM_ACCESS_KERNEL???
  - wieso wird in vm_create_stack() in vm_init() der mmStack und der tmStack anders angelegt als alle anderen?
      -> vm_create_stack() auskommentiert.
  - wieso kann in VM_REGION_ADD_NEAR kein hint übergeben werden?
  - wie sind berechtigungen für Syscalls implementiert?
  - Enveloppe an Message anhängen ist sehr teuer:
      1 Nachricht an mmThread -> 2 Kontext Wechsel
      kopieren aller Datenstrukturen in Enveloppe
      Enveloppe gegebenenfalls in Ziel-PD mappen
    Wieso wird diese Methode für "kleine" Messages schon ab 192 Bytes verwendet???
  - Bei TRAPS wird kein cli ausgeführt, wieso??? 
          => füge cli in IDTVEC()-Makro ein

Implementiere fehlende VM Syscalls
  - VM_MAP_FIND_NEAR:
      msg:
        id = VM_MAP_FIND_NEAR
        env:
          ThreadId pdId
          address_t hint
          size_t size
          Region_t region
          int direction
      reply: 
        id = VM_REPLY
        reply.msg.vm_reply.err  : Fehler
        reply.msg.vm_reply.ptr1 : region.start
        reply.msg.vm_reply.ptr2 : region.end
      
  - VM_REGION_SHARE
      msg:
        id = VM_REGION_SHARE
        env:
          ThreadId sourcePdId
          ThreadId destPdId
          Region_t region
          address_t hint
          int flags
          int direction
      reply
        id = VM_REPLY
        reply.msg.vm_reply.err  : Fehler
        reply.msg.vm_reply.ptr1 : region.start
        reply.msg.vm_reply.ptr2 : region.end
  - VM_REGION_ADD_NEAR
      msg:
        id = VM_REGION_ADD_NEAR
        env:
          ThreadId pdId
          Region_t region
          address_t hint
      reply
        id = VM_REPLY
        reply.msg.vm_reply.err  : Fehler
        reply.msg.vm_reply.ptr1 : region.start
        reply.msg.vm_reply.ptr2 : region.end
  - VM_REGION_ENTER
      msg:
        id = VM_REGION_ENTER
        msg.msg.vm_get.pdId : pd
        msg.msg.vm_get.hint : region
      reply
        id = VM_REPLY
        reply.msg.vm.reply.err : Fehler



DEBUGGING
-------------------------
Diverse kleine Bugs

Page Fault im vm_loader
  Beim Lesen der Segmap von user.bin 
   -> Page Fault, user.bin nicht gefunden mit vm_file_lookup()
   -> user.bin nicht in vmhash liste
   -> user.bin wird in vm_domain_create_kernel() aus dem segmap->optsegment gebildet
   -> segmap wird in vm_get_segmap() aus den Informationen des BinFileDesc gewonnen
        BinFileDesc hat kein optsegment, aber user.bin hat seinen eigenen BinFileDesc
   -> vm_loader liest 
  Lösung
   - Passe User-Link-Script an
   - vm_get_segmap() fügt user.bin als optsegment in segmap
   - stelle user.bin auf topsyheader um
   
Assert currentThread == schedulerRunning() nicht erfüllt...
    currentThread    = 0xc0000000, eip:0x00020191 in tmMsgSend, nested -> unterbrochen in schedulerRunning()!!!
    schedulerRunning = 0xc0004000, eip:0x00020191 in tmMsgSend
    andere: 1 eip:0x000201bb in tmMsgRecv
            2 eip:0x00033782 in tmIdleMain
  Lösung:
    cli vor scheduling()

Deadlock von schedLock
  a) Thrad im INTHandler in schedulerChangePriority() will Lock
  b) Thread vom Timer im INTHandler -> schedulerSetBlocked() -> in testAndSet() bei eip=popfl unterbrochen 
      eflags = 0x00000202
      Ablauf: user.bin -> Stack Fault bei 0x00200000 -> ... -> Timer
      -> führt zu deadlock in INTHandler bei schedulerChangePriority()
      
Stack Exception
  -> implement vm_stack_fault_exeption_handler()
  
Page Fault
  -> Addresse von ioOpen: 0x2052c2
      -> gemappte page ist zeroed out...
      -> physikalische addresse auch 0
      -> RM_LOAD in rm_load.inc erwartet BinFileDesc
  => stelle kernel.bin auf topsyheader um
  
shell wird in tmMsgRecv vom ioOpen nie mehr aufgeweckt
  -> speichere priority in schedulerChangePriority()
  
Page Fault in ioDeviceMain
  Parameter passing scheint nicht zu funktionieren
  KMS for Kernel Thrads:
    +----------------+
    | Message        |  Top
    | Exit Code      |
    | Argument 1     |
    | Argument 0     |
    | Return Addr    |  <- nach iret zeigt esp auf Return Addr
    | ProcStackFrame |  ProcStackFrame ohne tf_esp und tf_ss
    | Stack          |
    | :              |
    | Context        |
    | Thread         |  Bottom
    +----------------+ 
    
  KMS for User Threads
    +----------------+
    | ProcStackFrame |  ProcStackFrame mit tf_esp und tf_ss
    | Stack          |
    | :              |
    | Context        |
    | Thread         |  Bottom
    +----------------+   
    
  UMS 
    +----------------+
    | Message        |  Top
    | Exit Code      |
    | Argument 1     |
    | Argument 0     |
    | Return Addr    | <- tf_esp zeigt auf Return Addr
    | :              |
    +----------------+
  
  
Kein Keyboard Interrupt
  IO-Apic
    - Lesen: IO-Apic Datasheet, Multiprocessor Spezifikation
    - Implementation: 
        - Implementation, Initialisierung
        - Virtual Wire Mode: Interrupt routing
        - lokalen APIC anpassen
  
Fehler beim Linken???
  - CoW mit 0 initialisiert
  - Fehler in vm_pmap_page_copy()
  


Assert im HeapAllocator
  - Output:
       XXX TMProtectionDomain: adding PDId: 3
      vm_domain_init
      vm_pmap_create()
        ctxt->LastHeader->end 0x14004000  ctxt->TopOfMemSeg  0x14000000 oldsize 0x00003000 roundedsize 0x00001000
      vm_region_add_near: 0xc0018000 - 0xc0019fff, type 00a0
        ctxt->LastHeader->end 0x14005000  ctxt->TopOfMemSeg  0x14000000 oldsize 0x00004000 roundedsize 0x00001000
      ===> pmap_region_entering: virt 0x00000000 => phys 0x00000000 (size = 640KB)
      map Kernel into vm of user thread 0x00000000-0x000a0000  err 1
        ctxt->LastHeader->end 0x14006000  ctxt->TopOfMemSeg  0x14000000 oldsize 0x00005000 roundedsize 0x00001000
      ===> pmap_region_entering: virt 0x000a0000 => phys 0x000a0000 (size = 384KB)
      ===> pmap_region_entering: virt 0xfee00000 => phys 0xfee00000 (size = 4KB)
      ===> pmap_region_entering: virt 0xfec00000 => phys 0xfec00000 (size = 4KB)
        ctxt->LastHeader->end 0x14007000  ctxt->TopOfMemSeg  0x14000000 oldsize 0x00005000 roundedsize 0x00001000
      ###  ASSERT ((address_t)ctxt->LastHeader->end - (address_t)ctxt->TopOfMemSeg == oldsize + roundedsize) 
        in [mmThread, VMemory/HeapAllocator.c:422] failed
  - Backtrace:
      vm_main()
      vm_region_add_near()
      vm_map_create_region()
      vm_alloc_desc()
      km_alloc()
      HeapAllocator_alloc()
      allocate_block()
      error_assertion()
  - nicht reproduzierbar
  - unlock() erst nach Assert
  
Capslock triggert Interrupt 255 (spurious interrupt vom local APIC)
  - ist verschwunden ;) 
  - kommt vor, wenn nested exceptions zugelassen werden
   => lege spiv auf __NIR_0F, optimiertes Handling:
    APIC_SPIV_HANDLING_ISR:  ISR für spiv wird installiert, macht nichts
    APIC_SPIV_HANDLING_IRET: es wird sofort iret aufgerufen, minimaler overhead
  - registriere Error-ISR, Interrupt __NIR_0E
      was ist back-to-back write ??? (siehe intel.64.ia32.Arch.Soft.Devl.Man_Vol3A_System.Programming.Guide2006.pdf auf Seite 349)
  
Exception bei Beenden eines Threads
  Bugs in threadDestroy()
  
Schwarzer Bildschirm bei Aufruf von readChar()
  kein char wird eingelesen, nach ein paar Iterationen wird Bildschirm gelöscht. ???
  falsche Zeichen in der Ausgabe
  

Viele Nested Exceptions durch Timer
  - Scheduler Funktionen sind teuer: schedulerChangePriority(), schedulerSetBlocked(), 
  - Timer immer vor restoreContext() zurücksetzen?  ???


** WARNING [ mmThread (*in exc*), VMemory/vm_main.c:575 ] vm_main: got UNKNOWN message
  - Passiert ohne Nested Exceptions nicht
  - Verdacht 1: Thread wird unterbrochen während Arbeit mit MAP_PAGE_POS*, neuer Thread mappt andere Page an gleichen Ort, 
    beim Aufwachen wird beim Kopieren falsch gemappte page weiterverwendet.
    - Problemzonen:
        _INTHandler: vm_pmap_map_page_in_other_pmap() : MAP_PAGE_POS4
        kSend():     moveMessageToPD()                : MAP_PAGE_POS5
       weitere mögliche Problemzonen
        vm_pmap_page_copy                             : MAP_PAGE_POS1, MAP_PAGE_POS2
        vm_pmap_page_zero                             : MAP_PAGE_POS3
      => Verdacht bestätigt durch Tests
    - Lösungsansatz:
        Verwalte selber eine Menge von Pages (vm Funktionen haben kein Locking, sind ineffizient)
          - ist für multicore sowieso nötig
        Anzahl: N = 4*CPU
        Blockierung, wenn keine freie Page oder Mutex nicht frei
          - Lösung nicht trivial, kritische Fälle
              a) Thread mit kleinerer Priorität hält Mutex / Pages
                  => nicht möglich
              b) (Nested) Exception in kritischem Abschnitt 
                  => Interrupts ausmaskieren ???
              c) ???
    - Implementierung
        Alloziierung in vm_pmap_init() in vm_pmap.c
  - Verdacht 2: Message Queue nicht geschützt durch Lock. Zwei Threads können gleichzeitig eine Message reinkopieren. SchedInfos auch nicht geschützt durch Lock.
    - Problemzonen: 
        kSend(): moveMessageToPD()
                 addMessageInQueue()
        kRecv(): getMessageFromQueue()
                 kRecv() 
        msgDispatcher()
        INTHandler()
        vm_exception_lookup()
        -> schwierig zu verifizieren, da race condition. Fehler wird erst viel später entdeckt.
            Vorher passiert Nested Exception während byteCopy...
            Lock wird für Multicore sowieso nötig -> implementieren
    - Lösungsansatz
        Lock für Thread Datenstruktur, kritische Daten sind msgQueue und schedInfo.
        Benutze lock aus Lock.h
          Nachteile: kein Counter, besser wäre zB lock(&lock, thisThread)
        Fragen: 
          - Was machen im INTHandler, während Interrupts maskiert sind???
              - Interrupts im kritischen Bereich maskieren 
                -> kein Thread wird unterbrochen, während er das Lock hält
                -> cli für kRecv(), kSend() und kleiner Teil von msgDispatcher() und vm_exception_lookup()
              - Lock auch nach cli anfordern
                -> Verzögerung, aber kein Deadlock
          - threadDestroy() was machen mit Lock? 

__endOf_APIC_IRQ() muss nach cli ausgeführt werden, da sonst sofort nächster Interrupt kommt...

KEYECHO in _KeyboardISR() kann Deadlock provozieren ???
  keine gute Lösung!

shell wird nach einigen ioRead() nicht mehr aufgeweckt
  - alle Threads in tmMsgRecv()
  - auch ohne (Keyboard-)Aktivität 
     -> Problem liegt wahrscheinlich beim IPC/Thread-Management...
  - Debugging bisher nicht erfolgreich, scheint eine race-condition zu sein???
     -> nur mit Nested Exceptions
     -> auch mit Nested Exceptions Lite (nur 1 möglicher Unterbrechungspunkt)
  - Ablauf:
     - Reply von ttya wird geschickt
     - kommt nicht an
     - ...
     - vm_loader bekommt Nachricht vom Typ ANYMESSAGE
   - Output:
      kSend: queue pending filled
      kSend: Message not expected by thread 2:"ttya"
              message id 29 from thread 5
              expecting id 0 from thread 1
      -> Thread ist blockiert in tmMsgRecv, aber queue->msgPendingStatus==NOT_WAITING
      a) ohne Nested exceptions:
        ioRead()
          kSend: from  5 to  2 id 29  (msgPtr 0x00616d88)
          attachEnvMsg()
            kSend: from  2 to -1 id 87  (msgPtr 0xc0015ef8)
            kSend: from -1 to  2 id 88  (msgPtr 0xc0001f08)
              kRecv: from -1 to  2 id 0  (msgPtr 0xc0015ed8)
              kRecv: from  1 to -1 id 0  (msgPtr 0xc0001f28)
          kSend: from  2 to  5 id 35  (msgPtr 0xc0015f48)
            kRecv: from  1 to  2 id 0  (msgPtr 0xc0015f68)
            kRecv: from  2 to  5 id 0  (msgPtr 0x0061ad68)
          detachEnvMsg()
            kSend: from  5 to -1 id 89  (msgPtr 0x0061bd28)
            kSend: from -1 to  5 id 90  (msgPtr 0xc0001f08)
              kRecv: from  1 to -1 id 0  (msgPtr 0xc0001f28)
              kRecv: from -1 to  5 id 0  (msgPtr 0x0061dd08)
      b) mit Nested Exceptions
          Topsy Shell 3.0 (c) 1998, ETH Zurich, TIK
          ($Id: Shell.h 2924 2007-03-19 17:35
          detachEnvMsg()
            kSend:  2 -> -1  id 89 ... unblocked -1
            kSend: -1 ->  2  id 90 ... already ready 2
          kRecv:  2 <- -1  id  0 ... unblocked 2
          write reply
            kSend:  2 ->  5  id 36 ... already ready 5
            kRecv: -1 <-  1  id  0 ... blocked -1
            kRecv:  2 <-  1  id  0 ... blocked 2
            Nested Interrupt 0x00000020 thread 2
            kRecv:  5 <-  2  id  0 ... unblocked 5
          attachEnvMsg()
            kSend:  5 -> -1  id 87 ... unblocked -1
            kSend: -1 ->  5  id 88 ... already ready 5
            kRecv: -1 <-  1  id  0 ... blocked -1
            kRecv:  5 <- -1  id  0 ... unblocked 5
          io write
            kSend:  5 ->  2  id 30 ... 
            kSend: thread not waiting
            kSend: Message not expected by thread 2:"ttya"
                   message   id -2147483618 from thread 5
                   expecting id  0 from thread 1
            kRecv:  5 <-  2  id  0 ... blocked 5
  Problem:
    Ein Thread hängt in tmMsgRecv und wartet auf eine Nachricht. Dann tritt eine Nested Exception auf. Beim darauffolgenden schedule() wird ein anderer Thread drangenommen. Wenn nun später der Thread wieder dran kommt, wird in schedule() sein msgPendingStatus auf nicht wartend gestellt, obwohl die Nachricht noch nicht angekommen ist. Wenn nun die Nachricht entlich eintrifft, wird sie nicht übermittelt, da der Thread ja angeblich gar nicht darauf wartet. Dann bleibt er für immer blockiert.
  Lösung: 
    Setze msgPendingStatus nur zurück, wenn nächstes Stack Frame dasjenige ist, welches auf die Nachricht gewartet hat.


vm_region_loan_alloc() gibt VM_FAILED zurück
  - vm_map->loan == NULL -> nein
  - genericSyscall() liefert TM_MSGSENDFAILED
    tmMsgRecv() schlägt fehl:
      reply->id = 0x56, VM_REPLY    (VM_OK, 0xc0018000, 0xc0019fff)
                  dies ist die Antwort 
      id        = 0x58, VM_ATTACH_MSG_PAGE_REPLY
  - mmThread ist noch am Bearbeiten von VM_ATTACH_MSG_PAGE
    -> vm_loader wurde geweckt, obwohl Nachricht noch nicht verfügbar
  Problem:
    Ein Thread wird blockiert (zB nach tmMsgRecv) und anschliessend durch eine Nested Exception (zB Page Fault) gerade nochmals. Wenn der Thread nun wieder geweckt werden soll, wird immer nur das Stack Frame 0 geweckt...
  Lösung:
    Es mus klar sein, welches Stack Frame geweckt werden soll 
      -> neuer Parameter, welcher gewünschtes Stack Frame anhand der Unterbrechungsursache auswählt
      -> Jeder Thread darf nur ein mal von jeder Möglichkeit blockiert werden!

Ausgabe von binär anmutenden Zeichenfolgen
  - kSend() wird mit fehlerhaften Nachricht aufgerufen
      0x00610ce8 <bogus+       0>:    0x00000005      0x0000001e      0x60200e00      0x6000b000
      0x00610cf8 <bogus+      16>:    0x0000001d      0x60200d08      0x00206246      0x60200dc4
  - ???

Panic im Memory Management Thread
  Output:
    steal_alloc: requested size 28 rounded 32, ld 0, full 128 usage 75 lock 0
    steal_alloc: requested size 28 rounded 32, ld 0, full 128 usage 76 lock 0
    steal_alloc: requested size 28 rounded 32, ld 0, full 128 usage 75 lock 0
    steal_alloc: requested size 28 rounded 32, ld 0, full 128 usage 76 lock 0
    steal_alloc: requested size 28 rounded 32, ld 0, full 128 usage 77 lock 0
    steal_alloc: requested size 28 rounded 32, ld 0, full 128 usage 76 lock 0
    steal_alloc: requested size 28 rounded 32, ld 0, full 128 usage 77 lock 0
    steal_alloc: requested size 28 rounded 32, ld 0, full 128 usage 78 lock 0
    steal_alloc: requested size 28 rounded 32, ld 0, full 128 usage 77 lock 0
    steal_alloc: requested size 28 rounded 32, ld 0, full 128 usage 78 lock 0
    steal_alloc: requested size 28 rounded 32, ld 0, full 128 usage 79 lock 0
    try mask 0 0xffffffff
    try mask 32 0xffffffff
    try mask 64 0xffffffff
    try mask 96 0xffffffff
    steal_alloc: requested size 28 rounded 32, ld 0, full 128 usage 78 lock 0
    **** PANIC [ mmThread (*in exc*), VMemory/steal_alloc.c:329 ] No free slot found
  Backtrace:
    vm_main() in VM_REGION_ENTER
    vm_anon_lookup(0x140061a4, 0x0, 0x2, 0xc0001f54)
    steal_alloc(0xc0001eb0, 0x1c, 0x0)
    panic()
  -> usage und mask stimmen nicht überein!
    -> onhe Interrupts scheints zu stimmen, unkorrektes locking?
    -> Fehler ist in steal_free(): wenn steal_free() sofort returnt, tritt Fehler nicht auf...
        steal_free() wird nur in vm_anon.c verwendet
    -> zwei Fehler in steal_free gefixt
    
Random Crashtest hält System
  Problem
    Zufällig gewählte Destination existiert nicht, msgDispatcher panics
  Lösung
    a) Fehlerhaften Thread beenden?
    b) Fehlermeldung zurückgeben?
    - Dies ist architektur-unabhängiger Code, dieser Test schlägt also auf allen Architekturen fehl...
      ??? Wieso

Bug im Memory Management
  Problem
    Direct Mapped Memory wird vom Anonymous Memory Manager nicht als verwendet erkannt. 
  Lösung
    nimm direct mapped memory aus der physmap
      - Hardware IO Region
      - APIC
      - I/O-APIC
    ich bin offensichtlich der erste, welcher eine nicht zusammenhängende physmap verwendet...
      

VMWARE
-------------------------
Installation von SEPP nur auf speziellen Rechnern, Root-Rechte nötig
Installiere VMPlayer auf meinem Noti
Konfigueiere VMPlayer, mache Images, Makefile...


REPORT
-------------------------
schreiben...

Multicore:
  - inwiefern sollte Multicore erwähnt werden
  - Vorschlag für den Titel: "Portierung von Topsy v3 auf den Intel Pentium 4, Voraussetzungen für PC/AT-kompatible Multiprozessor-Unterstützung.
  - Neues Inhaltsverzeichnis

Diverses:
  - wo sollte auf die "kleinen Änderungen" eingegangen werden?
      topsyheader, cli im TRAP, 








