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