From c3028fb924d4d112293a885733da60e2e9a730f4 Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Mon, 3 Feb 2014 05:29:53 +0100 Subject: pc64: implement shutdown and idlehands just copies from pc kernel. should refactor into common pc code. --- sys/src/9/pc64/l.s | 38 ++++++++++++++++++++++++++----- sys/src/9/pc64/main.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 90 insertions(+), 11 deletions(-) diff --git a/sys/src/9/pc64/l.s b/sys/src/9/pc64/l.s index 65aebb07b..e1eb310b1 100644 --- a/sys/src/9/pc64/l.s +++ b/sys/src/9/pc64/l.s @@ -331,10 +331,20 @@ TEXT mb586(SB), 1, $-4 CPUID RET +/* + * Park a processor. Should never fall through a return from main to here, + * should only be called by application processors when shutting down. + */ +TEXT idle(SB), 1, $-4 +_idle: + STI + HLT + JMP _idle + /* * BIOS32. */ -TEXT bios32call(SB), 1, $-1 +TEXT bios32call(SB), 1, $-4 XORL AX, AX INCL AX RET @@ -526,14 +536,30 @@ TEXT setlabel(SB), 1, $-4 MOVL $0, AX /* return 0 */ RET -TEXT idle(SB), $0 -_idle: +TEXT halt(SB), 1, $-4 + CLI + CMPL nrdy(SB), $0 + JEQ _nothingready + STI + RET +_nothingready: STI HLT - JMP _idle + RET -TEXT halt(SB), 1, $-4 - HLT +TEXT mwait(SB), 1, $-4 + MOVQ RARG, AX + MOVL (AX), CX + ORL CX, CX + JNZ _mwaitdone + XORL DX, DX + BYTE $0x0f; BYTE $0x01; BYTE $0xc8 /* MONITOR */ + MOVL (AX), CX + ORL CX, CX + JNZ _mwaitdone + XORL AX, AX + BYTE $0x0f; BYTE $0x01; BYTE $0xc9 /* MWAIT */ +_mwaitdone: RET /* diff --git a/sys/src/9/pc64/main.c b/sys/src/9/pc64/main.c index 8c07566c7..8ad503288 100644 --- a/sys/src/9/pc64/main.c +++ b/sys/src/9/pc64/main.c @@ -26,6 +26,8 @@ char *confname[MAXCONF]; char *confval[MAXCONF]; int nconf; int delaylink; +int idle_spin; + uchar *sp; /* user stack of init proc */ extern void (*i8237alloc)(void); @@ -419,12 +421,56 @@ main() schedinit(); } +static void +shutdown(int ispanic) +{ + int ms, once; + + lock(&active); + if(ispanic) + active.ispanic = ispanic; + else if(m->machno == 0 && (active.machs & (1<machno)) == 0) + active.ispanic = 0; + once = active.machs & (1<machno); + /* + * setting exiting will make hzclock() on each processor call exit(0), + * which calls shutdown(0) and arch->reset(), which on mp systems is + * mpshutdown, from which there is no return: the processor is idled + * or initiates a reboot. clearing our bit in machs avoids calling + * exit(0) from hzclock() on this processor. + */ + active.machs &= ~(1<machno); + active.exiting = 1; + unlock(&active); + + if(once) + iprint("cpu%d: exiting\n", m->machno); + + /* wait for any other processors to shutdown */ + spllo(); + for(ms = 5*1000; ms > 0; ms -= TK2MS(2)){ + delay(TK2MS(2)); + if(active.machs == 0 && consactive() == 0) + break; + } + + if(active.ispanic){ + if(!cpuserver) + for(;;) + halt(); + if(getconf("*debug")) + delay(5*60*1000); + else + delay(10000); + }else + delay(1000); +} + void -exit(int) +exit(int ispanic) { - print("exit\n"); - splhi(); - for(;;); + shutdown(ispanic); + arch->reset(); } void @@ -436,7 +482,14 @@ reboot(void*, void*, ulong) void idlehands(void) { - halt(); + extern int nrdy; + + if(conf.nmach == 1) + halt(); + else if(m->cpuidcx & Monitor) + mwait(&nrdy); + else if(idle_spin == 0) + halt(); } /* -- cgit v1.2.3 From 6a55790197d8eed5b7e020a7b964ae260d0d205b Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Mon, 3 Feb 2014 06:24:31 +0100 Subject: pc/pc64: move common code to pc/devarch.c --- sys/src/9/pc/devarch.c | 59 +++++++++++++++++++++++++++ sys/src/9/pc/main.c | 106 ------------------------------------------------- sys/src/9/pc64/main.c | 46 --------------------- 3 files changed, 59 insertions(+), 152 deletions(-) diff --git a/sys/src/9/pc/devarch.c b/sys/src/9/pc/devarch.c index 71824f631..4c1ecb691 100644 --- a/sys/src/9/pc/devarch.c +++ b/sys/src/9/pc/devarch.c @@ -1133,3 +1133,62 @@ timerset(Tval x) if(doi8253set) (*arch->timerset)(x); } + +/* + * put the processor in the halt state if we've no processes to run. + * an interrupt will get us going again. + * + * halting in an smp system can result in a startup latency for + * processes that become ready. + * if idle_spin is zero, we care more about saving energy + * than reducing this latency. + * + * the performance loss with idle_spin == 0 seems to be slight + * and it reduces lock contention (thus system time and real time) + * on many-core systems with large values of NPROC. + */ +void +idlehands(void) +{ + extern int nrdy, idle_spin; + + if(conf.nmach == 1) + halt(); + else if(m->cpuidcx & Monitor) + mwait(&nrdy); + else if(idle_spin == 0) + halt(); +} + +int +isaconfig(char *class, int ctlrno, ISAConf *isa) +{ + char cc[32], *p; + int i; + + snprint(cc, sizeof cc, "%s%d", class, ctlrno); + p = getconf(cc); + if(p == nil) + return 0; + + isa->type = ""; + isa->nopt = tokenize(p, isa->opt, NISAOPT); + for(i = 0; i < isa->nopt; i++){ + p = isa->opt[i]; + if(cistrncmp(p, "type=", 5) == 0) + isa->type = p + 5; + else if(cistrncmp(p, "port=", 5) == 0) + isa->port = strtoul(p+5, &p, 0); + else if(cistrncmp(p, "irq=", 4) == 0) + isa->irq = strtoul(p+4, &p, 0); + else if(cistrncmp(p, "dma=", 4) == 0) + isa->dma = strtoul(p+4, &p, 0); + else if(cistrncmp(p, "mem=", 4) == 0) + isa->mem = strtoul(p+4, &p, 0); + else if(cistrncmp(p, "size=", 5) == 0) + isa->size = strtoul(p+5, &p, 0); + else if(cistrncmp(p, "freq=", 5) == 0) + isa->freq = strtoul(p+5, &p, 0); + } + return 1; +} diff --git a/sys/src/9/pc/main.c b/sys/src/9/pc/main.c index bc12d5608..d9fa45648 100644 --- a/sys/src/9/pc/main.c +++ b/sys/src/9/pc/main.c @@ -1000,109 +1000,3 @@ exit(int ispanic) shutdown(ispanic); arch->reset(); } - -int -isaconfig(char *class, int ctlrno, ISAConf *isa) -{ - char cc[32], *p; - int i; - - snprint(cc, sizeof cc, "%s%d", class, ctlrno); - p = getconf(cc); - if(p == nil) - return 0; - - isa->type = ""; - isa->nopt = tokenize(p, isa->opt, NISAOPT); - for(i = 0; i < isa->nopt; i++){ - p = isa->opt[i]; - if(cistrncmp(p, "type=", 5) == 0) - isa->type = p + 5; - else if(cistrncmp(p, "port=", 5) == 0) - isa->port = strtoul(p+5, &p, 0); - else if(cistrncmp(p, "irq=", 4) == 0) - isa->irq = strtoul(p+4, &p, 0); - else if(cistrncmp(p, "dma=", 4) == 0) - isa->dma = strtoul(p+4, &p, 0); - else if(cistrncmp(p, "mem=", 4) == 0) - isa->mem = strtoul(p+4, &p, 0); - else if(cistrncmp(p, "size=", 5) == 0) - isa->size = strtoul(p+5, &p, 0); - else if(cistrncmp(p, "freq=", 5) == 0) - isa->freq = strtoul(p+5, &p, 0); - } - return 1; -} - -int -cistrcmp(char *a, char *b) -{ - int ac, bc; - - for(;;){ - ac = *a++; - bc = *b++; - - if(ac >= 'A' && ac <= 'Z') - ac = 'a' + (ac - 'A'); - if(bc >= 'A' && bc <= 'Z') - bc = 'a' + (bc - 'A'); - ac -= bc; - if(ac) - return ac; - if(bc == 0) - break; - } - return 0; -} - -int -cistrncmp(char *a, char *b, int n) -{ - unsigned ac, bc; - - while(n > 0){ - ac = *a++; - bc = *b++; - n--; - - if(ac >= 'A' && ac <= 'Z') - ac = 'a' + (ac - 'A'); - if(bc >= 'A' && bc <= 'Z') - bc = 'a' + (bc - 'A'); - - ac -= bc; - if(ac) - return ac; - if(bc == 0) - break; - } - - return 0; -} - -/* - * put the processor in the halt state if we've no processes to run. - * an interrupt will get us going again. - * - * halting in an smp system can result in a startup latency for - * processes that become ready. - * if idle_spin is zero, we care more about saving energy - * than reducing this latency. - * - * the performance loss with idle_spin == 0 seems to be slight - * and it reduces lock contention (thus system time and real time) - * on many-core systems with large values of NPROC. - */ -void -idlehands(void) -{ - extern int nrdy; - - if(conf.nmach == 1) - halt(); - else if(m->cpuidcx & Monitor) - mwait(&nrdy); - else if(idle_spin == 0) - halt(); -} diff --git a/sys/src/9/pc64/main.c b/sys/src/9/pc64/main.c index 8ad503288..596aa0c48 100644 --- a/sys/src/9/pc64/main.c +++ b/sys/src/9/pc64/main.c @@ -479,19 +479,6 @@ reboot(void*, void*, ulong) exit(0); } -void -idlehands(void) -{ - extern int nrdy; - - if(conf.nmach == 1) - halt(); - else if(m->cpuidcx & Monitor) - mwait(&nrdy); - else if(idle_spin == 0) - halt(); -} - /* * SIMD Floating Point. * Assembler support to get at the individual instructions @@ -760,36 +747,3 @@ procsave(Proc *p) */ mmuflushtlb(); } - -int -isaconfig(char *class, int ctlrno, ISAConf *isa) -{ - char cc[32], *p; - int i; - - snprint(cc, sizeof cc, "%s%d", class, ctlrno); - p = getconf(cc); - if(p == nil) - return 0; - - isa->type = ""; - isa->nopt = tokenize(p, isa->opt, NISAOPT); - for(i = 0; i < isa->nopt; i++){ - p = isa->opt[i]; - if(cistrncmp(p, "type=", 5) == 0) - isa->type = p + 5; - else if(cistrncmp(p, "port=", 5) == 0) - isa->port = strtoul(p+5, &p, 0); - else if(cistrncmp(p, "irq=", 4) == 0) - isa->irq = strtoul(p+4, &p, 0); - else if(cistrncmp(p, "dma=", 4) == 0) - isa->dma = strtoul(p+4, &p, 0); - else if(cistrncmp(p, "mem=", 4) == 0) - isa->mem = strtoul(p+4, &p, 0); - else if(cistrncmp(p, "size=", 5) == 0) - isa->size = strtoul(p+5, &p, 0); - else if(cistrncmp(p, "freq=", 5) == 0) - isa->freq = strtoul(p+5, &p, 0); - } - return 1; -} -- cgit v1.2.3