diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2018-11-19 18:42:01 +0100 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2018-11-19 18:42:01 +0100 |
commit | 4dee686ca51e20634aa66c989dabbb1cf460e32b (patch) | |
tree | 70f6d5d2a679b579b31c81f2e4f8a8eedd275601 /sys/src | |
parent | b04ed2ae522a0d2f97d8ac7e5f3276223112ebe8 (diff) |
pc, pc64: park application processors in rebootcode with mmu off
instead of having application processors spin in mpshutdown()
with mmu on, and be subject to reboot() overriding kernel text
and modifying page tables, park the application processors in
rebootcode idle loop with the mmu off.
Diffstat (limited to 'sys/src')
-rw-r--r-- | sys/src/9/pc/main.c | 61 | ||||
-rw-r--r-- | sys/src/9/pc/rebootcode.s | 11 | ||||
-rw-r--r-- | sys/src/9/pc64/main.c | 49 | ||||
-rw-r--r-- | sys/src/9/pc64/rebootcode.s | 13 |
4 files changed, 88 insertions, 46 deletions
diff --git a/sys/src/9/pc/main.c b/sys/src/9/pc/main.c index b60329776..61db6f113 100644 --- a/sys/src/9/pc/main.c +++ b/sys/src/9/pc/main.c @@ -701,34 +701,13 @@ procsave(Proc *p) mmuflushtlb(PADDR(m->pdb)); } -void -reboot(void *entry, void *code, ulong size) +static void +rebootjump(uintptr entry, uintptr code, ulong size) { - void (*f)(ulong, ulong, ulong); + void (*f)(uintptr, uintptr, ulong); ulong *pdb; - writeconf(); - vmxshutdown(); - - /* - * the boot processor is cpu0. execute this function on it - * so that the new kernel has the same cpu0. this only matters - * because the hardware has a notion of which processor was the - * boot processor and we look at it at start up. - */ - if (m->machno != 0) { - procwired(up, 0); - sched(); - } - cpushutdown(); - splhi(); - - /* turn off buffered serial console */ - serialoq = nil; - - /* shutdown devices */ - chandevshutdown(); arch->introff(); /* @@ -745,7 +724,8 @@ reboot(void *entry, void *code, ulong size) /* off we go - never to return */ coherence(); - (*f)((ulong)entry & ~0xF0000000UL, PADDR(code), size); + (*f)(entry, code, size); + for(;;); } @@ -753,5 +733,36 @@ void exit(int) { cpushutdown(); + if(m->machno) + rebootjump(0, 0, 0); arch->reset(); } + +void +reboot(void *entry, void *code, ulong size) +{ + writeconf(); + vmxshutdown(); + + /* + * the boot processor is cpu0. execute this function on it + * so that the new kernel has the same cpu0. this only matters + * because the hardware has a notion of which processor was the + * boot processor and we look at it at start up. + */ + if (m->machno != 0) { + procwired(up, 0); + sched(); + } + cpushutdown(); + delay(1000); + splhi(); + + /* turn off buffered serial console */ + serialoq = nil; + + /* shutdown devices */ + chandevshutdown(); + + rebootjump((ulong)entry & ~0xF0000000UL, PADDR(code), size); +} diff --git a/sys/src/9/pc/rebootcode.s b/sys/src/9/pc/rebootcode.s index c7d0b1991..0b4a28481 100644 --- a/sys/src/9/pc/rebootcode.s +++ b/sys/src/9/pc/rebootcode.s @@ -20,6 +20,13 @@ TEXT main(SB),$0 MOVL $0, DX MOVL DX, CR3 + /* stack below entry point */ + MOVL AX, SP + + /* park cpu for zero entry point */ + ORL AX, AX + JZ _idle + /* * the source and destination may overlap. * determine whether to copy forward or backwards @@ -52,3 +59,7 @@ _back: _startkernel: ORL AX, AX /* NOP: avoid link bug */ JMP* AX + +_idle: + HLT + JMP _idle diff --git a/sys/src/9/pc64/main.c b/sys/src/9/pc64/main.c index fc1bfeb92..dd9e2d8f2 100644 --- a/sys/src/9/pc64/main.c +++ b/sys/src/9/pc64/main.c @@ -336,18 +336,45 @@ main() schedinit(); } +static void +rebootjump(uintptr entry, uintptr code, ulong size) +{ + void (*f)(uintptr, uintptr, ulong); + + splhi(); + arch->introff(); + + /* + * This allows the reboot code to turn off the page mapping + */ + *mmuwalk(m->pml4, 0, 3, 0) = *mmuwalk(m->pml4, KZERO, 3, 0); + *mmuwalk(m->pml4, 0, 2, 0) = *mmuwalk(m->pml4, KZERO, 2, 0); + mmuflushtlb(); + + /* setup reboot trampoline function */ + f = (void*)REBOOTADDR; + memmove(f, rebootcode, sizeof(rebootcode)); + + /* off we go - never to return */ + coherence(); + (*f)(entry, code, size); + + for(;;); +} + + void exit(int) { cpushutdown(); + if(m->machno) + rebootjump(0, 0, 0); arch->reset(); } void reboot(void *entry, void *code, ulong size) { - void (*f)(uintptr, uintptr, ulong); - writeconf(); vmxshutdown(); @@ -362,7 +389,7 @@ reboot(void *entry, void *code, ulong size) sched(); } cpushutdown(); - + delay(1000); splhi(); /* turn off buffered serial console */ @@ -370,22 +397,8 @@ reboot(void *entry, void *code, ulong size) /* shutdown devices */ chandevshutdown(); - arch->introff(); - - /* - * This allows the reboot code to turn off the page mapping - */ - *mmuwalk(m->pml4, 0, 3, 0) = *mmuwalk(m->pml4, KZERO, 3, 0); - *mmuwalk(m->pml4, 0, 2, 0) = *mmuwalk(m->pml4, KZERO, 2, 0); - mmuflushtlb(); - - /* setup reboot trampoline function */ - f = (void*)REBOOTADDR; - memmove(f, rebootcode, sizeof(rebootcode)); - /* off we go - never to return */ - coherence(); - (*f)((uintptr)entry & ~0xF0000000UL, (uintptr)PADDR(code), size); + rebootjump((uintptr)entry & ~0xF0000000UL, PADDR(code), size); } /* diff --git a/sys/src/9/pc64/rebootcode.s b/sys/src/9/pc64/rebootcode.s index 7b6d150f1..91c3c788d 100644 --- a/sys/src/9/pc64/rebootcode.s +++ b/sys/src/9/pc64/rebootcode.s @@ -20,9 +20,6 @@ TEXT main(SB), 1, $-4 MOVL $_gdtptr64p<>(SB), AX MOVL (AX), GDTR - /* move stack below destination */ - MOVL DI, SP - /* load CS with 32bit code segment */ PUSHQ $SELECTOR(3, SELGDT, 0) PUSHQ $_warp32<>(SB) @@ -61,6 +58,12 @@ TEXT _warp32<>(SB), 1, $-4 MOVL BX, CX /* byte count */ MOVL DI, AX /* save entry point */ + MOVL AX, SP /* move stack below entry */ + + /* park cpu for zero entry point */ + ORL AX, AX + JZ _idle + /* * the source and destination may overlap. @@ -90,6 +93,10 @@ _back: REP; MOVSB JMP _startkernel +_idle: + HLT + JMP _idle + TEXT _gdt<>(SB), 1, $-4 /* null descriptor */ LONG $0 |