pc64: amd64 kernel reboot support
This commit is contained in:
parent
105625e10b
commit
f2f46f4a33
10 changed files with 243 additions and 34 deletions
|
@ -279,6 +279,7 @@ struct
|
|||
int exiting; /* shutdown */
|
||||
int ispanic; /* shutdown in response to a panic */
|
||||
int thunderbirdsarego; /* lets the added processors continue to schedinit */
|
||||
int rebooting; /* about to rebooting another kernel */
|
||||
}active;
|
||||
|
||||
/*
|
||||
|
|
|
@ -188,6 +188,7 @@ mach0init(void)
|
|||
|
||||
active.machs = 1;
|
||||
active.exiting = 0;
|
||||
active.rebooting = 0;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -936,8 +937,7 @@ shutdown(int ispanic)
|
|||
delay(5*60*1000);
|
||||
else
|
||||
delay(10000);
|
||||
}else
|
||||
delay(1000);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -959,17 +959,21 @@ reboot(void *entry, void *code, ulong size)
|
|||
sched();
|
||||
}
|
||||
|
||||
lock(&active);
|
||||
active.rebooting = 1;
|
||||
unlock(&active);
|
||||
|
||||
shutdown(0);
|
||||
|
||||
/*
|
||||
* should be the only processor running now
|
||||
*/
|
||||
if (m->machno != 0)
|
||||
print("on cpu%d (not 0)!\n", m->machno);
|
||||
iprint("on cpu%d (not 0)!\n", m->machno);
|
||||
if (active.machs)
|
||||
print("still have active ap processors!\n");
|
||||
iprint("still have active ap processors!\n");
|
||||
|
||||
print("shutting down...\n");
|
||||
iprint("shutting down...\n");
|
||||
delay(200);
|
||||
|
||||
splhi();
|
||||
|
@ -993,11 +997,9 @@ reboot(void *entry, void *code, ulong size)
|
|||
f = (void*)REBOOTADDR;
|
||||
memmove(f, rebootcode, sizeof(rebootcode));
|
||||
|
||||
print("rebooting...\n");
|
||||
|
||||
/* off we go - never to return */
|
||||
coherence();
|
||||
(*f)(PADDR(entry), PADDR(code), size);
|
||||
(*f)((ulong)entry & ~0xF0000000UL, PADDR(code), size);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -622,23 +622,13 @@ mpshutdown(void)
|
|||
{
|
||||
static Lock shutdownlock;
|
||||
|
||||
/*
|
||||
* To be done...
|
||||
*/
|
||||
if(!canlock(&shutdownlock)){
|
||||
/*
|
||||
* If this processor received the CTRL-ALT-DEL from
|
||||
* the keyboard, acknowledge it. Send an INIT to self.
|
||||
*/
|
||||
#ifdef FIXTHIS
|
||||
if(lapicisr(VectorKBD))
|
||||
lapiceoi(VectorKBD);
|
||||
#endif /* FIX THIS */
|
||||
if(active.rebooting || !canlock(&shutdownlock)){
|
||||
splhi();
|
||||
arch->introff();
|
||||
idle();
|
||||
}
|
||||
|
||||
print("apshutdown: active = %#8.8ux\n", active.machs);
|
||||
print("mpshutdown: active = %#8.8ux\n", active.machs);
|
||||
delay(1000);
|
||||
splhi();
|
||||
|
||||
|
@ -666,6 +656,5 @@ mpshutdown(void)
|
|||
outb(0xCF9, 0x06);
|
||||
|
||||
print("can't reset\n");
|
||||
for(;;)
|
||||
idle();
|
||||
idle();
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#include "mem.h"
|
||||
|
||||
/*
|
||||
* Turn off MMU, then memmory the new kernel to its correct location
|
||||
* Turn off MMU, then memmove the new kernel to its correct location
|
||||
* in physical memory. Then jumps the to start of the kernel.
|
||||
*/
|
||||
|
||||
|
|
|
@ -244,6 +244,7 @@ struct
|
|||
int exiting; /* shutdown */
|
||||
int ispanic; /* shutdown in response to a panic */
|
||||
int thunderbirdsarego; /* lets the added processors continue to schedinit */
|
||||
int rebooting; /* about to rebooting another kernel */
|
||||
}active;
|
||||
|
||||
/*
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include "ureg.h"
|
||||
#include "init.h"
|
||||
#include "pool.h"
|
||||
#include "reboot.h"
|
||||
|
||||
/*
|
||||
* Where configuration info is left for the loaded programme.
|
||||
|
@ -133,6 +134,35 @@ getconf(char *name)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
writeconf(void)
|
||||
{
|
||||
char *p, *q;
|
||||
int n;
|
||||
|
||||
p = getconfenv();
|
||||
|
||||
if(waserror()) {
|
||||
free(p);
|
||||
nexterror();
|
||||
}
|
||||
|
||||
/* convert to name=value\n format */
|
||||
for(q=p; *q; q++) {
|
||||
q += strlen(q);
|
||||
*q = '=';
|
||||
q += strlen(q);
|
||||
*q = '\n';
|
||||
}
|
||||
n = q - p + 1;
|
||||
if(n >= BOOTARGSLEN)
|
||||
error("kernel configuration too large");
|
||||
memset(BOOTLINE, 0, BOOTLINELEN);
|
||||
memmove(BOOTARGS, p, n);
|
||||
poperror();
|
||||
free(p);
|
||||
}
|
||||
|
||||
void
|
||||
confinit(void)
|
||||
{
|
||||
|
@ -276,6 +306,7 @@ mach0init(void)
|
|||
|
||||
active.machs = 1;
|
||||
active.exiting = 0;
|
||||
active.rebooting = 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -525,8 +556,7 @@ shutdown(int ispanic)
|
|||
delay(5*60*1000);
|
||||
else
|
||||
delay(10000);
|
||||
}else
|
||||
delay(1000);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -537,9 +567,63 @@ exit(int ispanic)
|
|||
}
|
||||
|
||||
void
|
||||
reboot(void*, void*, ulong)
|
||||
reboot(void *entry, void *code, ulong size)
|
||||
{
|
||||
exit(0);
|
||||
void (*f)(uintptr, uintptr, ulong);
|
||||
|
||||
writeconf();
|
||||
|
||||
/*
|
||||
* 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();
|
||||
}
|
||||
|
||||
lock(&active);
|
||||
active.rebooting = 1;
|
||||
unlock(&active);
|
||||
|
||||
shutdown(0);
|
||||
|
||||
/*
|
||||
* should be the only processor running now
|
||||
*/
|
||||
if (m->machno != 0)
|
||||
iprint("on cpu%d (not 0)!\n", m->machno);
|
||||
if (active.machs)
|
||||
iprint("still have active ap processors!\n");
|
||||
|
||||
iprint("shutting down...\n");
|
||||
delay(200);
|
||||
|
||||
splhi();
|
||||
|
||||
/* turn off buffered serial console */
|
||||
serialoq = nil;
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -7,6 +7,7 @@ p=9
|
|||
|
||||
KTZERO=0xffffffff80110000
|
||||
APBOOTSTRAP=0xffffffff80003000
|
||||
REBOOTADDR=0x11000
|
||||
|
||||
DEVS=`{rc ../port/mkdevlist $CONF}
|
||||
|
||||
|
@ -112,7 +113,7 @@ $SDEV: ../port/sd.h
|
|||
sdiahci.$O: ahci.h
|
||||
devaoe.$O sdaoe.$O: ../port/aoe.h
|
||||
|
||||
main.$O: init.h
|
||||
main.$O: init.h reboot.h
|
||||
|
||||
devusb.$O usbuhci.$O usbohci.$O usbehci.$O: ../port/usb.h
|
||||
usbehci.$O: usbehci.h uncached.h
|
||||
|
@ -131,6 +132,15 @@ init.h:D: ../port/initcode.c ../pc/init9.c
|
|||
sed -e 's/^[0-9a-f]+ //' -e 's/ ([0-9a-f][0-9a-f])/0x\1,/g'
|
||||
echo '};'} > init.h
|
||||
|
||||
reboot.h: rebootcode.s
|
||||
$AS rebootcode.s
|
||||
$LD -l -R1 -s -o reboot.out -T$REBOOTADDR rebootcode.$O
|
||||
{echo 'uchar rebootcode[]={'
|
||||
dd -if reboot.out -bs 1 -iseek 40 |
|
||||
xd -1x |
|
||||
sed -e 's/^[0-9a-f]+ //' -e 's/ ([0-9a-f][0-9a-f])/0x\1,/g'
|
||||
echo '};'} > $target
|
||||
|
||||
apbootstrap.h: apbootstrap.s
|
||||
$AS apbootstrap.s
|
||||
$LD -l -R1 -s -o apbootstrap.out -T$APBOOTSTRAP apbootstrap.$O
|
||||
|
@ -147,4 +157,4 @@ acid:V:
|
|||
$CC -a -w main.c>acid
|
||||
|
||||
%.clean:V:
|
||||
rm -f $stem.c [9bz]$stem [9bz]$stem.gz boot$stem.* apbootstrap.h init.h $PCHEADERS
|
||||
rm -f $stem.c [9bz]$stem [9bz]$stem.gz boot$stem.* apbootstrap.h reboot.h init.h $PCHEADERS
|
||||
|
|
116
sys/src/9/pc64/rebootcode.s
Normal file
116
sys/src/9/pc64/rebootcode.s
Normal file
|
@ -0,0 +1,116 @@
|
|||
#include "mem.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), 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)
|
||||
RETFQ
|
||||
|
||||
MODE $32
|
||||
|
||||
TEXT _warp32<>(SB), 1, $-4
|
||||
|
||||
/* load 32bit data segments */
|
||||
MOVL $SELECTOR(2, SELGDT, 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:
|
||||
/* jump to entry point */
|
||||
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
|
||||
/* null descriptor */
|
||||
LONG $0
|
||||
LONG $0
|
||||
|
||||
/* (KESEG) 64 bit long mode exec segment */
|
||||
LONG $(0xFFFF)
|
||||
LONG $(SEGL|SEGG|SEGP|(0xF<<16)|SEGPL(0)|SEGEXEC|SEGR)
|
||||
|
||||
/* 32 bit data segment descriptor for 4 gigabytes (PL 0) */
|
||||
LONG $(0xFFFF)
|
||||
LONG $(SEGG|SEGB|(0xF<<16)|SEGP|SEGPL(0)|SEGDATA|SEGW)
|
||||
|
||||
/* 32 bit exec segment descriptor for 4 gigabytes (PL 0) */
|
||||
LONG $(0xFFFF)
|
||||
LONG $(SEGG|SEGD|(0xF<<16)|SEGP|SEGPL(0)|SEGEXEC|SEGR)
|
||||
|
||||
TEXT _gdtptr64p<>(SB), 1, $-4
|
||||
WORD $(4*8-1)
|
||||
QUAD $_gdt<>(SB)
|
||||
|
||||
TEXT _idtptr64p<>(SB), 1, $-4
|
||||
WORD $0
|
||||
QUAD $0
|
|
@ -148,10 +148,8 @@ hzclock(Ureg *ur)
|
|||
if((active.machs&(1<<m->machno)) == 0)
|
||||
return;
|
||||
|
||||
if(active.exiting) {
|
||||
print("someone's exiting\n");
|
||||
if(active.exiting)
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if(m->machno == 0)
|
||||
checkalarms();
|
||||
|
|
|
@ -69,9 +69,17 @@ rebootcmd(int argc, char *argv[])
|
|||
entry = l2be(exec.entry);
|
||||
text = l2be(exec.text);
|
||||
data = l2be(exec.data);
|
||||
if(magic != AOUT_MAGIC)
|
||||
|
||||
if(AOUT_MAGIC == S_MAGIC || AOUT_MAGIC == I_MAGIC){
|
||||
if(magic != S_MAGIC && magic != I_MAGIC)
|
||||
error(Ebadexec);
|
||||
} else if(magic != AOUT_MAGIC)
|
||||
error(Ebadexec);
|
||||
|
||||
/* amd64 extra header */
|
||||
if(magic == S_MAGIC)
|
||||
readn(c, &exec, 8);
|
||||
|
||||
/* round text out to page boundary */
|
||||
rtext = PGROUND(entry+text)-entry;
|
||||
size = rtext + data;
|
||||
|
|
Loading…
Reference in a new issue