hot reboot for nix. big thanks to cinap for diagnosing my issue with trying to execute the header. D'oh! Reference: /n/atom/patch/applied/nixreboot Date: Sat Mar 22 02:02:38 CET 2014 Signed-off-by: quanstro@quanstro.net --- /sys/src/nix/k10/mkfile Sat Mar 22 02:02:03 2014 +++ /sys/src/nix/k10/mkfile Sat Mar 22 02:02:04 2014 @@ -43,7 +43,7 @@ fpu.$O: amd64.h fpu.$O: /$objtype/include/ureg.h ioapic.$O: apic.h io.h -main.$O: init.h +main.$O: init.h reboot.h memory.$O: amd64.h mmu.$O: amd64.h mp.$O: apic.h @@ -80,6 +80,8 @@ devacpi.$O: acpi.h physalloc.$O: acpi.h +main.$O: reboot.h + sipi.h:D: l64sipi.$O $LD -o l64sipi.out -T0xfffffffff0003000 -R4 -l -s $prereq {echo 'uchar sipihandler[]={' @@ -88,3 +90,11 @@ -e '1,2d' -e '3s/^ .. .. .. .. .. .. .. ..//' \ -e 's/ ([0-9a-f][0-9a-f])/0x\1,/g' echo '};'} > $target + +reboot.h:D: rebootcode.s amd64l.h + $AS rebootcode.s + $LD -l -s -T0x11000 -R1 -o reboot.out rebootcode.$O + {echo 'uchar rebootcode[]={' + dd -bs 1 -iseek 40 -if reboot.out | xd -1x | + sed -e 's/^[0-9a-f]+ //' -e 's/ ([0-9a-f][0-9a-f])/0x\1,/g' + echo '};'} > reboot.h --- /sys/src/nix/k10/main.c Sat Mar 22 02:02:06 2014 +++ /sys/src/nix/k10/main.c Sat Mar 22 02:02:07 2014 @@ -8,6 +8,9 @@ #include "io.h" #include "apic.h" +#include "amd64.h" +#include "reboot.h" + Sys* sys; char dbgflg[256]; @@ -154,11 +157,6 @@ mallocinit(); archpciinit(); - /* - * This is necessary with GRUB and QEMU. Without it an interrupt can occur - * at a weird vector, because the vector base is likely different, causing - * havoc. Do it before any APIC initialisation. - */ i8259init(32); if(getconf("*maxmach") != nil) maxmach = atoi(getconf("*maxmach")); @@ -337,12 +335,14 @@ i = (int)(uintptr)v; procwired(up, i); splhi(); + lapicpri(0xff); m->online = 0; adec(&active.nonline); ndnr(); } -#include "amd64.h" +#define REBOOTADDR (0x11000) + void reboot(void *entry, void *code, usize size) { @@ -350,7 +350,7 @@ uintptr a; void (*f)(uintmem, uintmem, usize); -// writeconf(); + writeconf(); procwired(up, 0); for(i = 1; i < active.nonline; i++) @@ -361,34 +361,33 @@ synccons(); devtabshutdown(); pcireset(); - splhi(); lapicpri(0xff); - outb(0x21, 0xff); /* 8259 pic 0: mask irqs */ - outb(0xa1, 0xff); /* 8259 pic 1: mask irqs */ - up = nil; - m->proc = nil; - /* flush mmu */ -// m->mmuptp[0] = 0 | PtePS | PteP | PteRW; -// m->pml4[0] = m->pml4[PTLX(KZERO, 3)]; - putcr3(m->pml4->pa); + if(up != nil){ + m->proc = nil; + mmurelease(up); + up = nil; + } -// f = (void*)REBOOTADDR; -// memmove(f, rebootcode, sizeof(rebootcode)); - f = (void*)0; + mmumap(0, 0, 6*1024*1024, PteP|PteRW); + putcr3(m->pml4->pa); - (*f)(PADDR(entry), PADDR(code), size); + f = UINT2PTR(REBOOTADDR); + memmove(f, rebootcode, sizeof(rebootcode)); + print("warp32...\n"); + f(PTR2UINT(entry), PADDR(code), size); } void exit(int ispanic) { - synccons(); + int ms; + synccons(); /* accounting */ if(!m->online) - ndnr(); + archreset(); /* exiting a second time; must not hang */ m->online = 0; iprint("cpu%d: exiting\n", m->machno); adec(&active.nonline); @@ -397,7 +396,7 @@ /* wait (terminals wait forever) */ if(ispanic && !cpuserver) ndnr(); - for(int ms = 0; ms < 5000; ms += 1){ + for(ms = 0; ms < 5000; ms += 1){ if(active.nonline == 0) break; delay(1); --- /sys/src/nix/k10/rebootcode.s Thu Jan 1 00:00:00 1970 +++ /sys/src/nix/k10/rebootcode.s Sat Mar 22 02:02:07 2014 @@ -0,0 +1,111 @@ +#include "mem.h" +#include "amd64l.h" + +MODE $64 + +/* + * Turn off MMU, then memmove the new kernel to its correct location + * in physical memory. Then jumps the to start of the kernel. + */ + +TEXT main(SB), 1, $-4 + MOVL RARG, DI /* destination */ + MOVL p2+8(FP), SI /* source */ + MOVL n+16(FP), BX /* byte count */ + + /* load zero length idt */ + MOVL $_idtptr64p<>(SB), AX + MOVL (AX), IDTR + + /* load temporary gdt */ + MOVL $_gdtptr64p<>(SB), CX + MOVL (CX), GDTR + /* move stack below destination */ + MOVL DI, SP + + /* load CS with 32bit code segment */ + PUSHQ $SSEL(SiU32CS, 0) + PUSHQ $_warp32<>(SB) + RETFQ +// +//TEXT wave(SB), 1, $-4 +// MOVL $0x3f8, DX +// MOVB $'X', AL +// OUTB +// MFENCE +// RET + +MODE $32 + +TEXT _warp32<>(SB), 1, $-4 + + /* load 32bit data segments */ + MOVL $SSEL(2, 0), AX + MOVW AX, DS + MOVW AX, ES + MOVW AX, FS + MOVW AX, GS + MOVW AX, SS + + /* turn off paging */ + MOVL CR0, AX + ANDL $0x7fffffff, AX /* ~(PG) */ + MOVL AX, CR0 + + MOVL $0, AX + MOVL AX, CR3 + + /* disable long mode */ + MOVL $0xc0000080, CX /* Extended Feature Enable */ + RDMSR + ANDL $0xfffffeff, AX /* Long Mode Disable */ + WRMSR + + /* diable pae */ + MOVL CR4, AX + ANDL $0xffffff5f, AX /* ~(PAE|PGE) */ + MOVL AX, CR4 + + MOVL BX, CX /* byte count */ + MOVL DI, AX /* save entry point */ + +/* + * the source and destination may overlap. + * determine whether to copy forward or backwards + */ + CMPL SI, DI + JGT _forward + MOVL SI, DX + ADDL CX, DX + CMPL DX, DI + JGT _back + +_forward: + CLD + REP; MOVSB + +_startkernel: + JMP* AX + +_back: + ADDL CX, DI + ADDL CX, SI + SUBL $1, DI + SUBL $1, SI + STD + REP; MOVSB + JMP _startkernel + +TEXT _gdt<>(SB), 1, $-4 + QUAD $0 + QUAD $(SdL|SdG|SdP|Sd4G|SdDPL0|SdS|SdCODE|SdR) /* 64-bit executable */ + QUAD $(SdG|SdD|Sd4G|SdP|SdDPL0|SdS|SdW) /* 32-bit data */ + QUAD $(SdG|SdD|Sd4G|SdP|SdDPL0|SdS|SdCODE|SdW) /* 32-bit exec */ + +TEXT _gdtptr64p<>(SB), 1, $-4 + WORD $(4*8-1) + QUAD $_gdt<>(SB) + +TEXT _idtptr64p<>(SB), 1, $-4 + WORD $0 + QUAD $0