shithub: riscv

Download patch

ref: 4dee686ca51e20634aa66c989dabbb1cf460e32b
parent: b04ed2ae522a0d2f97d8ac7e5f3276223112ebe8
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Mon Nov 19 13:42:01 EST 2018

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.

--- a/sys/src/9/pc/main.c
+++ b/sys/src/9/pc/main.c
@@ -701,34 +701,13 @@
 	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 @@
 
 	/* off we go - never to return */
 	coherence();
-	(*f)((ulong)entry & ~0xF0000000UL, PADDR(code), size);
+	(*f)(entry, code, size);
+	for(;;);
 }
 
 
@@ -753,5 +733,36 @@
 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);
 }
--- a/sys/src/9/pc/rebootcode.s
+++ b/sys/src/9/pc/rebootcode.s
@@ -20,6 +20,13 @@
 	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 @@
 _startkernel:
 	ORL	AX, AX		/* NOP: avoid link bug */
 	JMP*	AX
+
+_idle:
+	HLT
+	JMP	_idle
--- a/sys/src/9/pc64/main.c
+++ b/sys/src/9/pc64/main.c
@@ -336,10 +336,39 @@
 	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();
 }
 
@@ -346,8 +375,6 @@
 void
 reboot(void *entry, void *code, ulong size)
 {
-	void (*f)(uintptr, uintptr, ulong);
-
 	writeconf();
 	vmxshutdown();
 
@@ -362,7 +389,7 @@
 		sched();
 	}
 	cpushutdown();
-
+	delay(1000);
 	splhi();
 
 	/* turn off buffered serial console */
@@ -370,22 +397,8 @@
 
 	/* 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);
 }
 
 /*
--- a/sys/src/9/pc64/rebootcode.s
+++ b/sys/src/9/pc64/rebootcode.s
@@ -20,9 +20,6 @@
 	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,7 +58,13 @@
 
 	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.
  * determine whether to copy forward or backwards
@@ -89,6 +92,10 @@
 	STD
 	REP;	MOVSB
 	JMP	_startkernel
+
+_idle:
+	HLT
+	JMP	_idle
 
 TEXT _gdt<>(SB), 1, $-4
 	/* null descriptor */