Allocate a private PCB, kernel stack and interrupt stack for each processor.
As a result, the stack setup code in locore.s changes slightly in the MULTIPROCESSOR case. Also, make the stack redzone barrier (for debugging only) a per-CPU entity.
This commit is contained in:
parent
cae1a093d5
commit
b9d844a520
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: cpu.c,v 1.78 1998/10/09 10:08:52 pk Exp $ */
|
||||
/* $NetBSD: cpu.c,v 1.79 1998/10/11 14:46:46 pk Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1996
|
||||
@ -130,6 +130,7 @@ alloc_cpuinfo()
|
||||
vaddr_t low, high;
|
||||
vm_page_t m;
|
||||
struct pglist mlist;
|
||||
struct cpu_info *cpi;
|
||||
|
||||
/*
|
||||
* Allocate aligned KVA. `cpuinfo' resides at a fixed virtual
|
||||
@ -142,8 +143,13 @@ alloc_cpuinfo()
|
||||
/* Assumes `c_totalsize' is power of two */
|
||||
align = CACHEINFO.c_totalsize;
|
||||
|
||||
/* While we're here, allocate a pre-CPU kernel stack as well? */
|
||||
sz = sizeof(struct cpu_info)/* + USPACE*/;
|
||||
/*
|
||||
* While we're here, allocate a per-CPU idle PCB and
|
||||
* interrupt stack as well.
|
||||
*/
|
||||
sz = sizeof(struct cpu_info);
|
||||
sz += USPACE; /* `idle' u-area for this CPU */
|
||||
sz += INT_STACK_SIZE; /* interrupt stack for this CPU */
|
||||
|
||||
sz = (sz + NBPG - 1) & -NBPG;
|
||||
esz = sz + align - NBPG;
|
||||
@ -166,7 +172,7 @@ alloc_cpuinfo()
|
||||
if (uvm_pglistalloc(sz, low, high, NBPG, 0, &mlist, 1, 0) != 0)
|
||||
panic("alloc_cpuinfo: no pages");
|
||||
|
||||
sva = va; /* re-use sva */
|
||||
cpi = (struct cpu_info *)va;
|
||||
|
||||
/* Map the pages */
|
||||
for (m = TAILQ_FIRST(&mlist); m != NULL; m = TAILQ_NEXT(m,pageq)) {
|
||||
@ -176,11 +182,12 @@ alloc_cpuinfo()
|
||||
va += NBPG;
|
||||
}
|
||||
|
||||
bzero((void *)sva, sizeof(struct cpu_info));
|
||||
#if 0
|
||||
((struct cpu_info *)sva)->stack = sva + sz - USPACE;
|
||||
#endif
|
||||
return ((struct cpu_info *)sva);
|
||||
bzero((void *)cpi, sizeof(struct cpu_info));
|
||||
|
||||
cpi->eintstack = (void *)(sva + sz);
|
||||
cpi->idle_u = (void *)(sva + sz - INT_STACK_SIZE - USPACE);
|
||||
|
||||
return (cpi);
|
||||
}
|
||||
|
||||
#ifdef notdef
|
||||
@ -258,15 +265,22 @@ static int cpu_number;
|
||||
*/
|
||||
mid = getpropint(node, "mid", 0);
|
||||
if (bootcpu == NULL) {
|
||||
extern struct pcb idle_u[];
|
||||
bootcpu = sc;
|
||||
cpus = malloc(ncpu * sizeof(cpi), M_DEVBUF, M_NOWAIT);
|
||||
bzero(cpus, ncpu * sizeof(cpi));
|
||||
cpi = sc->sc_cpuinfo = (struct cpu_info *)CPUINFO_VA;
|
||||
cpi->master = 1;
|
||||
cpi->eintstack = eintstack;
|
||||
cpi->idle_u = idle_u;
|
||||
} else {
|
||||
cpi = sc->sc_cpuinfo = alloc_cpuinfo();
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
cpi->redzone = (void *)((long)cpi->idle_u + REDSIZE);
|
||||
#endif
|
||||
|
||||
cpus[cpu_number] = cpi;
|
||||
cpi->cpu_no = cpu_number++;
|
||||
cpi->mid = mid;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: cpuvar.h,v 1.15 1998/10/08 22:25:42 pk Exp $ */
|
||||
/* $NetBSD: cpuvar.h,v 1.16 1998/10/11 14:46:45 pk Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1996 The NetBSD Foundation, Inc.
|
||||
@ -195,11 +195,20 @@ struct cpu_info {
|
||||
* The following pointers point to processes that are somehow
|
||||
* associated with this CPU--running on it, using its FPU,
|
||||
* etc.
|
||||
*
|
||||
* XXXMP: much more needs to go here
|
||||
*/
|
||||
|
||||
struct proc *curproc; /* CPU owner */
|
||||
struct proc *fpproc; /* FPU owner */
|
||||
|
||||
/*
|
||||
* Idle PCB and Interrupt stack;
|
||||
*/
|
||||
void *eintstack; /* End of interrupt stack */
|
||||
#define INT_STACK_SIZE (128 * 128) /* 128 128-byte stack frames */
|
||||
struct pcb *idle_u;
|
||||
void *redzone; /* DEBUG: stack red zone */
|
||||
#define REDSIZE (8*96) /* some room for bouncing */
|
||||
|
||||
/*
|
||||
* The following are function pointers to do interesting CPU-dependent
|
||||
* things without having to do type-tests all the time
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $NetBSD: genassym.cf,v 1.13 1998/09/24 20:37:17 pk Exp $
|
||||
# $NetBSD: genassym.cf,v 1.14 1998/10/11 14:46:46 pk Exp $
|
||||
|
||||
#
|
||||
# Copyright (c) 1998 The NetBSD Foundation, Inc.
|
||||
@ -150,6 +150,10 @@ define CPUINFO_GETASYNCFLT offsetof(struct cpu_info, get_asyncflt)
|
||||
define CPUINFO_PURE_VCACHE_FLS offsetof(struct cpu_info, pure_vcache_flush)
|
||||
define CPUINFO_SYNCFLTDUMP offsetof(struct cpu_info, syncfltdump)
|
||||
define CPUINFO_INTREG offsetof(struct cpu_info, intreg_4m)
|
||||
define CPUINFO_EINTSTACK offsetof(struct cpu_info, eintstack)
|
||||
define INT_STACK_SIZE INT_STACK_SIZE
|
||||
define CPUINFO_REDZONE offsetof(struct cpu_info, redzone)
|
||||
define REDSIZE REDSIZE
|
||||
|
||||
# PTE bits and related information
|
||||
define PG_W PG_W
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: locore.s,v 1.96 1998/09/23 11:07:28 pk Exp $ */
|
||||
/* $NetBSD: locore.s,v 1.97 1998/10/11 14:46:46 pk Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1996 Paul Kranenburg
|
||||
@ -53,6 +53,7 @@
|
||||
#include "opt_ddb.h"
|
||||
#include "opt_uvm.h"
|
||||
#include "opt_compat_svr4.h"
|
||||
#include "opt_multiprocessor.h"
|
||||
|
||||
#include "assym.h"
|
||||
#include <machine/param.h>
|
||||
@ -1140,17 +1141,17 @@ trapbase_sun4m:
|
||||
.skip 4096
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
/*#ifdef DEBUG*/
|
||||
/*
|
||||
* A hardware red zone is impossible. We simulate one in software by
|
||||
* keeping a `red zone' pointer; if %sp becomes less than this, we panic.
|
||||
* This is expensive and is only enabled when debugging.
|
||||
*/
|
||||
#define REDSIZE (8*96) /* some room for bouncing */
|
||||
#define REDSTACK 2048 /* size of `panic: stack overflow' region */
|
||||
|
||||
/* `redzone' is located in the per-CPU information zone */
|
||||
_redzone = CPUINFO_VA + CPUINFO_REDZONE
|
||||
.data
|
||||
_redzone:
|
||||
.word _idle_u + REDSIZE
|
||||
#define REDSTACK 2048 /* size of `panic: stack overflow' region */
|
||||
_redstack:
|
||||
.skip REDSTACK
|
||||
.text
|
||||
@ -1170,6 +1171,14 @@ Lpanic_red:
|
||||
sethi %hi(_redzone), tmp2; \
|
||||
st tmp1, [tmp2 + %lo(_redzone)]
|
||||
|
||||
/* variant with a variable & offset */
|
||||
#define SET_SP_REDZONE_VAR(var, offset, tmp1, tmp2) \
|
||||
sethi %hi(var), tmp1; \
|
||||
ld [tmp1 + %lo(var)], tmp1; \
|
||||
sethi %hi(offset), tmp2; \
|
||||
add tmp1, tmp2, tmp1; \
|
||||
SET_SP_REDZONE(tmp1, tmp2)
|
||||
|
||||
/* check stack pointer against redzone (uses two temps) */
|
||||
#define CHECK_SP_REDZONE(t1, t2) \
|
||||
sethi %hi(_redzone), t1; \
|
||||
@ -1193,12 +1202,15 @@ Lpanic_red:
|
||||
call _panic; or %o0, %lo(Lpanic_red), %o0; \
|
||||
7:
|
||||
|
||||
#define XDEBUG
|
||||
#ifdef XDEBUG
|
||||
#else
|
||||
|
||||
#define SET_SP_REDZONE(base, tmp)
|
||||
#define SET_SP_REDZONE_CONST(const, t1, t2)
|
||||
#define SET_SP_REDZONE_VAR(base, t1, t2)
|
||||
#define CHECK_SP_REDZONE(t1, t2)
|
||||
#endif
|
||||
#endif /* DEBUG */
|
||||
|
||||
/*
|
||||
* The window code must verify user stack addresses before using them.
|
||||
@ -1478,6 +1490,56 @@ wmask: .skip 32 ! u_char wmask[0..31];
|
||||
* go to the interrupt stack if (a) we came from user mode or (b) we
|
||||
* came from kernel mode on the kernel stack.
|
||||
*/
|
||||
#ifdef MULTIPROCESSOR
|
||||
_EINTSTACK = CPUINFO_VA + CPUINFO_EINTSTACK
|
||||
#define INTR_SETUP(stackspace) \
|
||||
rd %wim, %l4; \
|
||||
mov 1, %l5; \
|
||||
sll %l5, %l0, %l5; \
|
||||
btst PSR_PS, %l0; \
|
||||
bz 1f; \
|
||||
btst %l5, %l4; \
|
||||
/* came from kernel mode; cond codes still indicate trap window */ \
|
||||
bz,a 0f; \
|
||||
sethi %hi(_EINTSTACK), %l7; \
|
||||
CALL_CLEAN_TRAP_WINDOW; \
|
||||
sethi %hi(_EINTSTACK), %l7; \
|
||||
0: /* now if not intstack > %fp >= eintstack, we were on the kernel stack */ \
|
||||
ld [%l7 + %lo(_EINTSTACK)], %l7; \
|
||||
cmp %fp, %l7; \
|
||||
bge,a 3f; /* %fp >= eintstack */ \
|
||||
add %l7, stackspace, %sp; /* so switch to intstack */ \
|
||||
sethi %hi(INT_STACK_SIZE), %l6; \
|
||||
sub %l7, %l6, %l7; \
|
||||
cmp %fp, %l7; \
|
||||
blu,a 3f; /* %fp < intstack */ \
|
||||
add %l7, stackspace, %sp; /* so switch to intstack */ \
|
||||
b 4f; \
|
||||
add %fp, stackspace, %sp; /* else stay on intstack */ \
|
||||
1: \
|
||||
/* came from user mode: compute pcb_nw */ \
|
||||
sethi %hi(_cpcb), %l6; \
|
||||
ld [%l6 + %lo(_cpcb)], %l6; \
|
||||
ld [%l6 + PCB_WIM], %l5; \
|
||||
and %l0, 31, %l4; \
|
||||
sub %l4, %l5, %l5; \
|
||||
set uwtab, %l4; \
|
||||
ldub [%l4 + %l5], %l5; \
|
||||
st %l5, [%l6 + PCB_UW]; \
|
||||
/* cond codes still indicate whether in trap window */ \
|
||||
bz,a 2f; \
|
||||
sethi %hi(_EINTSTACK), %l7; \
|
||||
/* yes, in trap window; must save regs */ \
|
||||
CALL_CLEAN_TRAP_WINDOW; \
|
||||
sethi %hi(_EINTSTACK), %l7; \
|
||||
2: \
|
||||
ld [%l7 + %lo(_EINTSTACK)], %l7; \
|
||||
add %l7, stackspace, %sp; \
|
||||
3: \
|
||||
SET_SP_REDZONE_VAR(_EINTSTACK, -INT_STACK_SIZE, %l6, %l5); \
|
||||
4: \
|
||||
CHECK_SP_REDZONE(%l6, %l5)
|
||||
#else /* MULTIPROCESSOR */
|
||||
#define INTR_SETUP(stackspace) \
|
||||
rd %wim, %l4; \
|
||||
mov 1, %l5; \
|
||||
@ -1518,6 +1580,7 @@ wmask: .skip 32 ! u_char wmask[0..31];
|
||||
SET_SP_REDZONE_CONST(_intstack, %l6, %l5); \
|
||||
4: \
|
||||
CHECK_SP_REDZONE(%l6, %l5)
|
||||
#endif /* MULTIPROCESSOR */
|
||||
|
||||
/*
|
||||
* Handler for making the trap window shiny clean.
|
||||
@ -2043,10 +2106,27 @@ Lslowtrap_reenter:
|
||||
* Lslowtrap_reenter above, but maybe after switching stacks....
|
||||
*/
|
||||
softtrap:
|
||||
#ifdef MULTIPROCESSOR
|
||||
/*
|
||||
* The interrupt stack is not at a fixed location
|
||||
* and %sp must be checked against both ends.
|
||||
*/
|
||||
sethi %hi(_EINTSTACK), %l7
|
||||
ld [%l7 + %lo(_EINTSTACK)], %l7
|
||||
cmp %sp, %l7
|
||||
bge Lslowtrap_reenter
|
||||
EMPTY
|
||||
set INT_STACK_SIZE, %l6
|
||||
sub %l7, %l6, %l7
|
||||
cmp %sp, %l7
|
||||
blu Lslowtrap_reenter
|
||||
EMPTY
|
||||
#else
|
||||
sethi %hi(_eintstack), %l7
|
||||
cmp %sp, %l7
|
||||
bge Lslowtrap_reenter
|
||||
EMPTY
|
||||
#endif
|
||||
sethi %hi(_cpcb), %l6
|
||||
ld [%l6 + %lo(_cpcb)], %l6
|
||||
set USPACE-CCFSZ-80, %l5
|
||||
|
Loading…
Reference in New Issue
Block a user