xv6

port of xv6 to x86-64
git clone http://frotz.net/git/xv6.git
Log | Files | Refs | README | LICENSE

README.64BIT (4536B)


      1 
      2 While porting Xv6 to 64bit Intel/AMD platforms, the goal is to keep changes
      3 to the codebase as non-intrusive as possible, leaving it as short, clean,
      4 and readable as it was in the original 32bit version.  When possible,
      5 #ifdefs will be avoided, and the existing style will be maintained.  Also,
      6 it should continue to be possible to build, boot, and run Xv6 on 32bit
      7 platforms from the same codebase.
      8 
      9 
     10 DONE
     11  * Quick hack-and-slash modifications to get a buildable 64bit kernel.elf
     12    * stubbed out or quickly patched up assembly glue where it didn't build
     13    * temporarily turned off int-to-pointer and pointer-to-int warnings
     14      to make finding build breakages faster
     15    * chase down link errors due to too-large relocations
     16  * switch to cross-x86-64 compiler to avoid weirdness from host compiler
     17    * https://github.com/travisg/toolchains
     18  * make printf() and cprintf() use stdarg.h instead of rolling their own
     19    * x86-64's calling conventions for var-args are more complex
     20    * notably the first six arguments may be passed in registers
     21  * implement 32bit-to-64bit kernel entry glue (entry64.S)
     22    * qemu cannot load 64bit ELF kernels
     23    * sounds like most linux bootloaders don't support that yet either
     24    * implement a 32bit multiboot header and shim
     25    * setup an initial identity-mapped and kernel-address-mapped
     26      pagetable since you cannot enter 64bit mode without paging on
     27  * adjust syscall assembly for 64bit
     28  * implement 64bit task switch glue
     29  * introduce new type (currently 'uintp' for unsigned integer the size
     30    of a pointer) to use in all the places where Xv6 assumes pointers and
     31    integers are interchangeable.
     32    * almost all warnings squashed
     33    * consider a better name. addr_t?
     34  * implement 64bit GDT and TSS setup
     35  * implement 64bit interrupt support and IDT setup
     36  * adjust process entry code for 64bit
     37    * 64bit pointers and ABI (pass args in regs)
     38  * implement 64bit mmu support (vm64.c)
     39  * verify usermode works
     40  * turn back on pre-emption 
     41  * verify usertests work
     42  * update boot sector to support multiboot extended header
     43    * the ELF header no longer handles the entrypoint
     44  * get 32bit build working again
     45  * tidy up exec() for 64bit (argument passing, stack alignment)
     46  * test on real hardware
     47  * enable SMP and verify it
     48  * tidy up vm64.c
     49  * fix procdump for 64bit mode
     50  * figure out how to enumerate CPUs without BIOS MP table
     51    * had to implement minimal ACPI table parsing
     52 
     53 IN PROGRESS
     54 
     55 TODO
     56  * detect actual memory size, make PHYSTOP dynamic
     57  * handle >2GB ram
     58    * will have to move the linear map region below the kernel
     59      since we can only map 2GB from the kernel base to end of vram
     60  * fix validateint() of usertests for 64bit
     61 
     62 THINGS TO FIX LATER / NICE TO HAVE
     63  * I wish qemu had a "halt-on-exception" mode. Would help early bringup
     64  * gdb pukes when qemu switches from 32bit to 64bit mode
     65    * this made debugging the mode change entertaining
     66    * for now attach gdb after the switch
     67  * move userspace entry code to ulib
     68 
     69 LESSONS LEARNED / UNRESOLVED 
     70  * using 1GB pages in the initial page table did not work
     71  * In qemu you can do cheesy debugging by writing bytes to port 0x3f8
     72    (the first UART) without any normal UART setup.
     73  * Xv6:32 creates kernel mappings (separate copies) in every process's
     74    page table, roughly 70k pages worth, consuming about 280MB of ram
     75    for page tables.
     76  * Xv6:32's trick for cpu-local storage does not work on gcc x86-64
     77    - see README.CLS for an exploration of alternate options
     78  * Not sure why you're double/triple-faulting?
     79    drop some instrumentation code in qemu/target-i386/seg_helper.c's
     80    do_interrupt64() -- this is where all the validation on irq/trap
     81    entry happens
     82 
     83 IMPLEMENTATION NOTES
     84  * use "kernel" addressing mode for kernel compilation
     85  * kernel virtual address space 0xFFFFFFFF80000000:0xFFFFFFFFFF000000
     86  * linear-map first 1GB of RAM to kernel virtual address space
     87  * linear-map first 1GB of RAM 1:1 during boot
     88  * x64 has 4 levels of page tables instead of just 2
     89    * continue to return a 2nd-level page table from setupkvm()
     90      but actually create 4th, 3rd, and 2nd level tables
     91    * use the top two entries of the 2nd level table for backpointers
     92      to the 4th and 3rd level tables so that switchkvm(), switchuvm(),
     93      and freevm() can get at these when needed
     94    * use the top entry of the 4th level table to point to a shared
     95      (among all processes) 3rd level table which handles the kernel
     96      memory mapping (which is the same everywhere)
     97    * userland will have 4GB - 8KB address space
     98