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 exiting; /* shutdown */
|
||||||
int ispanic; /* shutdown in response to a panic */
|
int ispanic; /* shutdown in response to a panic */
|
||||||
int thunderbirdsarego; /* lets the added processors continue to schedinit */
|
int thunderbirdsarego; /* lets the added processors continue to schedinit */
|
||||||
|
int rebooting; /* about to rebooting another kernel */
|
||||||
}active;
|
}active;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -188,6 +188,7 @@ mach0init(void)
|
||||||
|
|
||||||
active.machs = 1;
|
active.machs = 1;
|
||||||
active.exiting = 0;
|
active.exiting = 0;
|
||||||
|
active.rebooting = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -936,8 +937,7 @@ shutdown(int ispanic)
|
||||||
delay(5*60*1000);
|
delay(5*60*1000);
|
||||||
else
|
else
|
||||||
delay(10000);
|
delay(10000);
|
||||||
}else
|
}
|
||||||
delay(1000);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -959,17 +959,21 @@ reboot(void *entry, void *code, ulong size)
|
||||||
sched();
|
sched();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lock(&active);
|
||||||
|
active.rebooting = 1;
|
||||||
|
unlock(&active);
|
||||||
|
|
||||||
shutdown(0);
|
shutdown(0);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* should be the only processor running now
|
* should be the only processor running now
|
||||||
*/
|
*/
|
||||||
if (m->machno != 0)
|
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)
|
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);
|
delay(200);
|
||||||
|
|
||||||
splhi();
|
splhi();
|
||||||
|
@ -993,11 +997,9 @@ reboot(void *entry, void *code, ulong size)
|
||||||
f = (void*)REBOOTADDR;
|
f = (void*)REBOOTADDR;
|
||||||
memmove(f, rebootcode, sizeof(rebootcode));
|
memmove(f, rebootcode, sizeof(rebootcode));
|
||||||
|
|
||||||
print("rebooting...\n");
|
|
||||||
|
|
||||||
/* off we go - never to return */
|
/* off we go - never to return */
|
||||||
coherence();
|
coherence();
|
||||||
(*f)(PADDR(entry), PADDR(code), size);
|
(*f)((ulong)entry & ~0xF0000000UL, PADDR(code), size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -622,23 +622,13 @@ mpshutdown(void)
|
||||||
{
|
{
|
||||||
static Lock shutdownlock;
|
static Lock shutdownlock;
|
||||||
|
|
||||||
/*
|
if(active.rebooting || !canlock(&shutdownlock)){
|
||||||
* To be done...
|
splhi();
|
||||||
*/
|
|
||||||
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 */
|
|
||||||
arch->introff();
|
arch->introff();
|
||||||
idle();
|
idle();
|
||||||
}
|
}
|
||||||
|
|
||||||
print("apshutdown: active = %#8.8ux\n", active.machs);
|
print("mpshutdown: active = %#8.8ux\n", active.machs);
|
||||||
delay(1000);
|
delay(1000);
|
||||||
splhi();
|
splhi();
|
||||||
|
|
||||||
|
@ -666,6 +656,5 @@ mpshutdown(void)
|
||||||
outb(0xCF9, 0x06);
|
outb(0xCF9, 0x06);
|
||||||
|
|
||||||
print("can't reset\n");
|
print("can't reset\n");
|
||||||
for(;;)
|
|
||||||
idle();
|
idle();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#include "mem.h"
|
#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.
|
* in physical memory. Then jumps the to start of the kernel.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
|
@ -244,6 +244,7 @@ struct
|
||||||
int exiting; /* shutdown */
|
int exiting; /* shutdown */
|
||||||
int ispanic; /* shutdown in response to a panic */
|
int ispanic; /* shutdown in response to a panic */
|
||||||
int thunderbirdsarego; /* lets the added processors continue to schedinit */
|
int thunderbirdsarego; /* lets the added processors continue to schedinit */
|
||||||
|
int rebooting; /* about to rebooting another kernel */
|
||||||
}active;
|
}active;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include "ureg.h"
|
#include "ureg.h"
|
||||||
#include "init.h"
|
#include "init.h"
|
||||||
#include "pool.h"
|
#include "pool.h"
|
||||||
|
#include "reboot.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Where configuration info is left for the loaded programme.
|
* Where configuration info is left for the loaded programme.
|
||||||
|
@ -133,6 +134,35 @@ getconf(char *name)
|
||||||
return 0;
|
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
|
void
|
||||||
confinit(void)
|
confinit(void)
|
||||||
{
|
{
|
||||||
|
@ -276,6 +306,7 @@ mach0init(void)
|
||||||
|
|
||||||
active.machs = 1;
|
active.machs = 1;
|
||||||
active.exiting = 0;
|
active.exiting = 0;
|
||||||
|
active.rebooting = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -525,8 +556,7 @@ shutdown(int ispanic)
|
||||||
delay(5*60*1000);
|
delay(5*60*1000);
|
||||||
else
|
else
|
||||||
delay(10000);
|
delay(10000);
|
||||||
}else
|
}
|
||||||
delay(1000);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -537,9 +567,63 @@ exit(int ispanic)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
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
|
KTZERO=0xffffffff80110000
|
||||||
APBOOTSTRAP=0xffffffff80003000
|
APBOOTSTRAP=0xffffffff80003000
|
||||||
|
REBOOTADDR=0x11000
|
||||||
|
|
||||||
DEVS=`{rc ../port/mkdevlist $CONF}
|
DEVS=`{rc ../port/mkdevlist $CONF}
|
||||||
|
|
||||||
|
@ -112,7 +113,7 @@ $SDEV: ../port/sd.h
|
||||||
sdiahci.$O: ahci.h
|
sdiahci.$O: ahci.h
|
||||||
devaoe.$O sdaoe.$O: ../port/aoe.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
|
devusb.$O usbuhci.$O usbohci.$O usbehci.$O: ../port/usb.h
|
||||||
usbehci.$O: usbehci.h uncached.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'
|
sed -e 's/^[0-9a-f]+ //' -e 's/ ([0-9a-f][0-9a-f])/0x\1,/g'
|
||||||
echo '};'} > init.h
|
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
|
apbootstrap.h: apbootstrap.s
|
||||||
$AS apbootstrap.s
|
$AS apbootstrap.s
|
||||||
$LD -l -R1 -s -o apbootstrap.out -T$APBOOTSTRAP apbootstrap.$O
|
$LD -l -R1 -s -o apbootstrap.out -T$APBOOTSTRAP apbootstrap.$O
|
||||||
|
@ -147,4 +157,4 @@ acid:V:
|
||||||
$CC -a -w main.c>acid
|
$CC -a -w main.c>acid
|
||||||
|
|
||||||
%.clean:V:
|
%.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)
|
if((active.machs&(1<<m->machno)) == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if(active.exiting) {
|
if(active.exiting)
|
||||||
print("someone's exiting\n");
|
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
|
||||||
|
|
||||||
if(m->machno == 0)
|
if(m->machno == 0)
|
||||||
checkalarms();
|
checkalarms();
|
||||||
|
|
|
@ -69,8 +69,16 @@ rebootcmd(int argc, char *argv[])
|
||||||
entry = l2be(exec.entry);
|
entry = l2be(exec.entry);
|
||||||
text = l2be(exec.text);
|
text = l2be(exec.text);
|
||||||
data = l2be(exec.data);
|
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);
|
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 */
|
/* round text out to page boundary */
|
||||||
rtext = PGROUND(entry+text)-entry;
|
rtext = PGROUND(entry+text)-entry;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue