Start reorganizing the kernel for MULTIPROCESSOR support.

This commit is contained in:
eeh 2000-06-12 23:32:46 +00:00
parent 65bca8bde2
commit fb0404cc75
8 changed files with 431 additions and 223 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: cpu.h,v 1.18 2000/06/12 05:29:43 mrg Exp $ */
/* $NetBSD: cpu.h,v 1.19 2000/06/12 23:32:46 eeh Exp $ */
/*
* Copyright (c) 1992, 1993
@ -74,14 +74,35 @@
#include <sparc64/sparc64/intreg.h>
#include <sys/sched.h>
/*
* The cpu_info structure is part of a 64KB structure mapped both the kernel
* pmap and a single locked TTE a CPUINFO_VA for that particular processor.
* Each processor's cpu_info is accessible at CPUINFO_VA only for that
* processor. Other processors can access that through an additional mapping
* in the kernel pmap.
*
* The 64KB page contains:
*
* cpu_info
* interrupt stack (all remaining space)
* idle PCB
* idle stack (STACKSPACE - sizeof(PCB))
* 32KB TSB
*/
struct cpu_info {
struct proc *ci_curproc;
struct pcb *ci_cpcb;
struct cpu_info *ci_next;
int ci_number;
struct schedstate_percpu ci_schedstate; /* scheduler state */
#if defined(DIAGNOSTIC) || defined(LOCKDEBUG)
u_long ci_spin_locks; /* # of spin locks held */
u_long ci_simple_locks; /* # of simple locks held */
u_long ci_spin_locks; /* # of spin locks held */
u_long ci_simple_locks;/* # of simple locks held */
#endif
};
extern struct cpu_info *cpus;
extern struct cpu_info cpu_info_store;
#define curcpu() (&cpu_info_store)
@ -93,7 +114,7 @@ extern struct cpu_info cpu_info_store;
#define cpu_swapin(p) /* nothing */
#define cpu_swapout(p) /* nothing */
#define cpu_wait(p) /* nothing */
#define cpu_number() 0
#define cpu_number() (curcpu()->ci_number)
/*
* Arguments to hardclock, softclock and gatherstats encapsulate the
@ -188,6 +209,8 @@ extern struct intrhand *intrlev[MAXINTNUM];
void intr_establish __P((int level, struct intrhand *));
/* cpu.c */
u_int64_t cpu_start __P((int));
/* disksubr.c */
struct dkbad;
int isbad __P((struct dkbad *bt, int, int, int));

View File

@ -1,4 +1,4 @@
/* $NetBSD: param.h,v 1.17 2000/05/22 02:35:24 mrg Exp $ */
/* $NetBSD: param.h,v 1.18 2000/06/12 23:32:46 eeh Exp $ */
/*
* Copyright (c) 1992, 1993
@ -120,8 +120,8 @@
extern int nbpg, pgofset, pgshift;
#endif
#define KERNBASE 0xf1000000 /* start of kernel virtual space */
#define KERNEND 0xfe000000 /* start of kernel virtual space */
#define KERNBASE 0x0f1000000 /* start of kernel virtual space */
#define KERNEND 0x0fe000000 /* end of kernel virtual space */
#define VM_MAX_KERNEL_BUF ((KERNEND-KERNBASE)/4)
#define DEV_BSIZE 512
@ -131,12 +131,18 @@ extern int nbpg, pgofset, pgshift;
#ifdef __arch64__
/* We get stack overflows w/8K stacks in 64-bit mode */
#define SSIZE 2 /* initial stack size in pages */
#define SSIZE 1 /* initial stack size in pages */
#else
#define SSIZE 1
#endif
#define USPACE (SSIZE*8192)
/*
* Here's the location of the interrupt stack and CPU structure.
*/
#define INTSTACK (KERNEND)
#define EINTSTACK (INTSTACK+USPACE
/*
* Constants related to network buffer management.
* MCLBYTES must be no larger than NBPG (the software page size), and,
@ -202,6 +208,7 @@ extern int nbpg, pgofset, pgshift;
*/
#ifdef _KERNEL
#ifndef _LOCORE
#if 0
extern vaddr_t dvma_base;
extern vaddr_t dvma_end;
extern struct map *dvmamap;
@ -215,6 +222,7 @@ extern struct map *dvmamap;
extern caddr_t kdvma_mapin __P((caddr_t, int, int));
extern caddr_t dvma_malloc __P((size_t, void *, int));
extern void dvma_free __P((caddr_t, size_t, void *));
#endif
extern void delay __P((unsigned int));
#define DELAY(n) delay(n)

View File

@ -1,4 +1,4 @@
/* $NetBSD: cpu.c,v 1.5 1999/11/06 20:18:13 eeh Exp $ */
/* $NetBSD: cpu.c,v 1.6 2000/06/12 23:32:47 eeh Exp $ */
/*
* Copyright (c) 1996
@ -56,6 +56,7 @@
#include <sys/device.h>
#include <vm/vm.h>
#include <vm/vm_kern.h>
#include <machine/autoconf.h>
#include <machine/cpu.h>
@ -69,6 +70,12 @@
/* This is declared here so that you must include a CPU for the cache code. */
struct cacheinfo cacheinfo;
/* Our exported CPU info; we have only one for now. */
struct cpu_info cpu_info_store;
/* Linked list of all CPUs in system. */
struct cpu_info *cpus = NULL;
/* The following are used externally (sysctl_hw). */
char machine[] = MACHINE; /* from <machine/param.h> */
char machine_arch[] = MACHINE_ARCH; /* from <machine/param.h> */
@ -118,18 +125,85 @@ static char *iu_vendor[16] = {
#endif
/*
* 4/110 comment: the 4/110 chops off the top 4 bits of an OBIO address.
* this confuses autoconf. for example, if you try and map
* 0xfe000000 in obio space on a 4/110 it actually maps 0x0e000000.
* this is easy to verify with the PROM. this causes problems
* with devices like "esp0 at obio0 addr 0xfa000000" because the
* 4/110 treats it as esp0 at obio0 addr 0x0a000000" which is the
* address of the 4/110's "sw0" scsi chip. the same thing happens
* between zs1 and zs2. since the sun4 line is "closed" and
* we know all the "obio" devices that will ever be on it we just
* put in some special case "if"'s in the match routines of esp,
* dma, and zs.
* Overhead involved in firing up a new CPU:
*
* Allocate a cpuinfo/interrupt stack
* Map that into the kernel
* Initialize the cpuinfo
* Return the TLB entry for the cpuinfo.
*/
u_int64_t
cpu_start(cpu_num)
int cpu_num;
{
struct cpu_info *ci;
u_int64_t pagesize;
u_int64_t pte;
vm_page_t m;
paddr_t pa;
psize_t size;
vaddr_t va;
struct pglist mlist;
int error;
size = NBPG; /* XXXX 8K, 64K, 512K, or 4MB */
TAILQ_INIT(&mlist);
if ((error = uvm_pglistalloc((psize_t)size, (paddr_t)0, (paddr_t)-1,
(paddr_t)size, (paddr_t)0, &mlist, 1, 0)) != 0)
panic("cpu_start: no memory, error %d", error);
va = uvm_km_valloc(kernel_map, size);
if (va == 0)
panic("cpu_start: no memory");
m = TAILQ_FIRST(&mlist);
pa = VM_PAGE_TO_PHYS(m);
pte = TSB_DATA(0 /* global */,
pagesize,
pa,
1 /* priv */,
1 /* Write */,
1 /* Cacheable */,
1 /* ALIAS -- Disable D$ */,
1 /* valid */,
0 /* IE */);
/* Map the pages */
for (; m != NULL; m = TAILQ_NEXT(m,pageq)) {
pa = VM_PAGE_TO_PHYS(m);
pmap_zero_page(pa);
pmap_enter(pmap_kernel(), va, pa | PMAP_NVC,
VM_PROT_READ|VM_PROT_WRITE,
VM_PROT_READ|VM_PROT_WRITE|PMAP_WIRED);
va += NBPG;
}
if (!cpus) cpus = (struct cpu_info *)va;
else {
for (ci = cpus; ci->ci_next; ci=ci->ci_next);
ci->ci_next = (struct cpu_info *)va;
}
switch (size) {
#define K *1024
case 8 K:
pagesize = TLB_8K;
break;
case 64 K:
pagesize = TLB_64K;
break;
case 512 K:
pagesize = TLB_512K;
break;
case 4 K K:
pagesize = TLB_4M;
break;
default:
panic("cpu_start: stack size %x not a machine page size\n",
size);
}
return (pte|TLB_L);
}
int
cpu_match(parent, cf, aux)

View File

@ -1,4 +1,4 @@
/* $NetBSD: intreg.h,v 1.2 2000/03/16 02:36:59 eeh Exp $ */
/* $NetBSD: intreg.h,v 1.3 2000/06/12 23:32:47 eeh Exp $ */
/*
* Copyright (c) 1992, 1993
@ -73,71 +73,5 @@
#ifndef _LOCORE
struct intrhand; /* This is in cpu.h if you need it. */
void send_softint __P((int cpu, int level, struct intrhand *ih));
#if 0
void ienab_bis __P((int bis)); /* set given bits */
void ienab_bic __P((int bic)); /* clear given bits */
#endif
#endif
#if 0
#if defined(SUN4M)
#ifdef notyet
#define IENAB_SYS ((_MAXNBPG * _MAXNCPU) + 0xc)
#define IENAB_P0 0x0008
#define IENAB_P1 0x1008
#define IENAB_P2 0x2008
#define IENAB_P3 0x3008
#endif /* notyet */
#endif
#if defined(SUN4M)
/*
* Interrupt Control Registers, located in IO space.
* (mapped to `locore' for now..)
* There are two sets of interrupt registers called `Processor Interrupts'
* and `System Interrupts'. The `Processor' set corresponds to the 15
* interrupt levels as seen by the CPU. The `System' set corresponds to
* a set of devices supported by the implementing chip-set.
*
* Briefly, the ICR_PI_* are per-processor interrupts; the ICR_SI_* are
* system-wide interrupts, and the ICR_ITR selects the processor to get
* the system's interrupts.
*/
#define ICR_PI_PEND (PI_INTR_VA + 0x0)
#define ICR_PI_CLR (PI_INTR_VA + 0x4)
#define ICR_PI_SET (PI_INTR_VA + 0x8)
#define ICR_SI_PEND (SI_INTR_VA)
#define ICR_SI_MASK (SI_INTR_VA + 0x4)
#define ICR_SI_CLR (SI_INTR_VA + 0x8)
#define ICR_SI_SET (SI_INTR_VA + 0xc)
#define ICR_ITR (SI_INTR_VA + 0x10)
/*
* Bits in interrupt registers. Software interrupt requests must
* be cleared in software. This is done in locore.s.
* There are separate registers for reading pending interrupts and
* setting/clearing (software) interrupts.
*/
#define PINTR_SINTRLEV(n) (1 << (16 + (n)))
#define PINTR_IC 0x8000 /* Level 15 clear */
#define SINTR_MA 0x80000000 /* Mask All interrupts */
#define SINTR_ME 0x40000000 /* Module Error (async) */
#define SINTR_I 0x20000000 /* MSI (MBus-SBus) */
#define SINTR_M 0x10000000 /* ECC Memory controller */
#define SINTR_RSVD2 0x0f800000
#define SINTR_F 0x00400000 /* Floppy */
#define SINTR_RSVD3 0x00200000
#define SINTR_V 0x00100000 /* Video (Supersparc only) */
#define SINTR_T 0x00080000 /* Level 10 counter */
#define SINTR_SC 0x00040000 /* SCSI */
#define SINTR_RSVD4 0x00020000
#define SINTR_E 0x00010000 /* Ethernet */
#define SINTR_S 0x00008000 /* Serial port */
#define SINTR_K 0x00004000 /* Keyboard/mouse */
#define SINTR_SBUSMASK 0x00003f80 /* SBus */
#define SINTR_SBUS(n) (((n) << 7) & 0x00003f80)
#define SINTR_RSVD5 0x0000007f
#endif
#endif

View File

@ -1,4 +1,4 @@
/* $NetBSD: locore.s,v 1.60 2000/05/31 05:09:19 thorpej Exp $ */
/* $NetBSD: locore.s,v 1.61 2000/06/12 23:32:47 eeh Exp $ */
/*
* Copyright (c) 1996-1999 Eduardo Horvath
* Copyright (c) 1996 Paul Kranenburg
@ -289,9 +289,15 @@ _C_LABEL(idle_u):
*
* This must be aligned on an 8 byte boundary.
*/
#if 0
.globl _C_LABEL(u0)
_C_LABEL(u0): .space (2*USPACE)
estack0:
#else
.globl _C_LABEL(u0)
_C_LABEL(u0): POINTER 0
estack0: POINTER 0
#endif
#ifdef KGDB
/*
@ -1424,8 +1430,8 @@ traceit:
brnz,pn %g4, 1f
lduw [%g2+TRACEPTR], %g3
rdpr %tl, %g4
set _C_LABEL(curproc), %g6
rdpr %tt, %g5
set _C_LABEL(curproc), %g6
cmp %g4, 1
sllx %g4, 13, %g4
bnz,a,pt %icc, 3f
@ -1454,8 +1460,8 @@ traceit:
or %g6, %g4, %g4
2:
rdpr %tstate, %g6
movnz %icc, %g0, %g3 ! Wrap buffer if needed
rdpr %tstate, %g6
rdpr %tpc, %g7
sth %g4, [%g2+%g3]
inc 2, %g3
@ -1780,13 +1786,13 @@ intr_setup_msg:
stx %i5, [%sp + CC64FSZ + BIAS + TF_O + (5*8)]; \
stx %i6, [%sp + CC64FSZ + BIAS + TF_O + (6*8)]; \
stx %i6, [%sp + CC64FSZ + BIAS + TF_G + (0*8)]; /* Save fp in clockframe->cf_fp */ \
stx %i7, [%sp + CC64FSZ + BIAS + TF_O + (7*8)]; \
rdpr %wstate, %g7; /* Find if we're from user mode */ \
stx %i7, [%sp + CC64FSZ + BIAS + TF_O + (7*8)]; \
cmp %g7, WSTATE_KERN; /* Compare & leave in register */ \
be,pn %icc, 1f; /* If we were in kernel mode start saving globals */ \
/* came from user mode -- switch to kernel mode stack */ \
rdpr %otherwin, %g5; /* Has this already been done? */ \
/* tst %g5; tnz %xcc, 1; nop; /* DEBUG -- this should _NEVER_ happen */ \
/* mov %g5, %g5; tst %g5; tnz %xcc, 1; nop; /* DEBUG -- this should _NEVER_ happen */ \
brnz,pn %g5, 1f; /* Don't set this twice */ \
rdpr %canrestore, %g5; /* Fixup register window state registers */ \
wrpr %g0, 0, %canrestore; \
@ -1912,8 +1918,8 @@ intr_setup_msg:
stx %i5, [%sp + CC64FSZ + STKB + TF_O + (5*8)]; \
stx %i6, [%sp + CC64FSZ + STKB + TF_O + (6*8)]; \
stx %i6, [%sp + CC64FSZ + STKB + TF_G + (0*8)]; /* Save fp in clockframe->cf_fp */ \
stx %i7, [%sp + CC64FSZ + STKB + TF_O + (7*8)]; \
rdpr %wstate, %g7; /* Find if we're from user mode */ \
stx %i7, [%sp + CC64FSZ + STKB + TF_O + (7*8)]; \
cmp %g7, WSTATE_KERN; /* Compare & leave in register */ \
be,pn %icc, 1f; /* If we were in kernel mode start saving globals */ \
/* came from user mode -- switch to kernel mode stack */ \
@ -2561,9 +2567,11 @@ winfixspill:
or %lo(2f), %o0, %o0
wrpr %g0, WSTATE_KERN, %wstate
#ifdef DEBUG
set panicstack-CC64FSZ, %sp ! Use panic stack.
set panicstack-CC64FSZ-STKB, %sp ! Use panic stack.
#else
set estack0-CC64FSZ, %sp ! Overwrite proc 0's stack.
set estack0, %sp
LDPTR [%sp], %sp
add %sp, -CC64FSZ-STKB, %sp ! Overwrite proc 0's stack.
#endif
ta 1; nop ! This helps out traptrace.
call _C_LABEL(panic) ! This needs to be fixed properly but we should panic here
@ -2824,6 +2832,7 @@ winfixsave:
* We should re-execute the trapping save.
*/
rdpr %wstate, %g3
mov %g3, %g3
cmp %g3, WSTATE_KERN
bne,pt %icc, 1f
nop
@ -3277,7 +3286,9 @@ slowtrap:
#ifdef DEBUG
set panicstack, %sp ! Kernel stack corrupt -- use panicstack
#else
set estack0, %sp ! Kernel stack corrupt -- use estack0
set estack0, %sp
LDPTR [%sp], %sp
add %sp, -CC64FSZ-STKB, %sp ! Overwrite proc 0's stack.
#endif
1:
rdpr %tt, %g4
@ -3860,11 +3871,11 @@ setup_sparcintr:
DLFLUSH(%g1, %g2)
mov %g5, %g2
CASPTR [%g1] ASI_N, %g0, %g2 ! Try a slot -- MPU safe
brz,pt %g2, 4f ! Available?
brz,pt %g2, 5f ! Available?
#else
DLFLUSH(%g1, %g2)
LDPTR [%g1], %g2 ! Try a slog
brz,a %g2, 4f ! Available?
brz,a %g2, 5f ! Available?
STPTR %g5, [%g1] ! Grab it
#endif
dec %g7
@ -3874,7 +3885,7 @@ setup_sparcintr:
!! If we get here we have a problem.
!! There were no available slots and the interrupt was lost.
!! We'll resort to polling in this case.
4:
5:
DLFLUSH(%g1, %g1) ! Prevent D$ pollution
#endif
set 1, %g7
@ -4098,7 +4109,25 @@ _C_LABEL(sparc_interrupt):
brz,pn %o3, 0f
LDPTR [%l2 + IH_ARG], %o0 ! ih->ih_arg
stx %g0, [%o3] ! Clear intr source
0:
#ifdef DEBUG
set _C_LABEL(intrdebug), %o3
ld [%o3], %o3
btst INTRDEBUG_FUNC, %o3
bz,a,pt %icc, 0f
nop
save %sp, -CC64FSZ, %sp
set 9f, %o0
mov %i0, %o2 ! arg
mov %i6, %o3 ! sp
GLOBTOLOC
call prom_printf
mov %i1, %o1 ! fun
LOCTOGLOB
restore
0:
#endif
jmpl %o1, %o7 ! handled = (*ih->ih_fun)(...)
movrz %o0, %o2, %o0 ! arg = (arg == 0) ? arg : tf
inc %l5
@ -4466,8 +4495,8 @@ rft_kernel:
sllx %g6, 9, %g6
or %g6, %g4, %g4
rdpr %tstate, %g6
movnz %icc, %g0, %g3 ! Wrap if needed
rdpr %tstate, %g6
rdpr %tpc, %g7
sth %g4, [%g2+%g3]
inc 2, %g3
@ -4810,8 +4839,8 @@ badregs:
sllx %g6, 9, %g6
or %g6, %g4, %g4
rdpr %tstate, %g6
movnz %icc, %g0, %g3 ! Wrap if needed
rdpr %tstate, %g6
rdpr %tpc, %g7
sth %g4, [%g2+%g3]
inc 2, %g3
@ -5069,23 +5098,21 @@ dostart:
STPTR %o4, [%o5] ! It's initialized data, I hope
/*
* Step 2: Set up a v8-like stack
* Step 2: Set up a v8-like stack if we need to
*/
!!! Make sure our stack's OK.
#define SAVE save %sp, -CC64FSZ, %sp
SAVE; SAVE; SAVE; SAVE; SAVE; SAVE; SAVE; SAVE; SAVE; SAVE
restore;restore;restore;restore;restore;restore;restore;restore;restore;restore
set estack0 - CC64FSZ - 80, %l0 ! via syscall(boot_me_up) or somesuch
#ifdef _LP64
andn %l0, 0x0f, %l0 ! Needs to be 16-byte aligned
sub %l0, BIAS, %l0 ! and biased
btst 1, %sp
bnz,pt %icc, 0f
nop
add %sp, -BIAS, %sp
#else
btst 1, %sp
bz,pt %icc, 0f
nop
add %sp, BIAS, %sp
#endif
save %g0, %l0, %sp
!!! Make sure our stack's OK.
SAVE; SAVE; SAVE; SAVE; SAVE; SAVE; SAVE; SAVE; SAVE; SAVE
restore;restore;restore;restore;restore;restore;restore;restore;restore;restore
0:
/*
* Step 3: clear BSS. This may just be paranoia; the boot
* loader might already do it for us; but what the hell.
@ -5129,6 +5156,26 @@ dostart:
call _C_LABEL(bootstrap)
inc %o0 ! and add 1 to discover maxctx
/*
* pmap_bootstrap should have allocated a stack for proc 0 and
* stored the start and end in u0 and estack0. Switch to that
* stack now.
*/
set _C_LABEL(main), %o0
/*
* Initialize a CPU. This is used both for bootstrapping the first CPU
* and spinning up each subsequent CPU. Basically:
*
* Establish the 4MB locked mappings for kernel data and text.
* Establish a locked mapping for interrupt stack.
* Switch to interrupt stack.
* Call the routine passed in in %o0
*/
_C_LABEL(cpu_init):
mov %o0, %l7 ! Save the routine we jump to
/*
* Step 3: install the permanent 4MB kernel mapping in both the
* immu and dmmu. We will clear out other mappings later.
@ -5142,7 +5189,7 @@ dostart:
* %l4 = tmp
* %l5 = tmp && TLB_TAG_ACCESS
* %l6 = tmp && CTX_PRIMARY
* %l7 = tmp && demap address
* %l7 = routine to jump to
*/
wrpr %g0, 0, %tl ! Make sure we're not in NUCLEUS mode
sethi %hi(KERNBASE), %l0 ! Find our xlation
@ -5205,12 +5252,12 @@ dostart:
#else
or %l1, TTE_L|TTE_CP|TTE_CV|TTE_P|TTE_W, %l2 ! And low bits: L=1|CP=1|CV=1|E=0|P=1|W=1(ugh)|G=0
#endif
set 1f, %l7
set 1f, %o5
stxa %l0, [%l5] ASI_DMMU ! Same for DMMU
membar #Sync ! We may need more membar #Sync in here
stxa %l2, [%g0] ASI_DMMU_DATA_IN ! Same for DMMU
membar #Sync ! We may need more membar #Sync in here
flush %l7 ! Make IMMU see this too
flush %o5 ! Make IMMU see this too
1:
#ifdef NODEF_DEBUG
set 1f, %o0 ! Debug printf
@ -5233,7 +5280,7 @@ dostart:
set TLB_TAG_ACCESS, %l5
or %l1, TTE_CP|TTE_P|TTE_W, %l2 ! And low bits: L=0|CP=1|CV=0|E=0|P=1|W=1(ugh)|G=0
or %l0, 1, %l4 ! Context = 1
set 1f, %l7
set 1f, %o5
stxa %l4, [%l5] ASI_DMMU ! Make DMMU point to it
membar #Sync ! We may need more membar #Sync in here
stxa %l2, [%g0] ASI_DMMU_DATA_IN ! Store it
@ -5243,17 +5290,17 @@ dostart:
flush %l0 ! Make IMMU see this too
stxa %l2, [%g0] ASI_IMMU_DATA_IN ! Store it
membar #Sync ! We may need more membar #Sync in here
flush %l7 ! Make IMMU see this too
flush %o5 ! Make IMMU see this too
1:
!!
!! Now load 1 as primary context
!!
mov 1, %l4
mov CTX_PRIMARY, %l6
set 1f, %l7
set 1f, %o5
stxa %l4, [%l6] ASI_DMMU
membar #Sync ! This probably should be a flush, but it works
flush %l7 ! This should be KERNBASE
flush %o5 ! This should be KERNBASE
1:
!!
@ -5266,7 +5313,7 @@ dostart:
0:
stxa %l5, [%l5] ASI_IMMU_DEMAP ! Demap it
membar #Sync
flush %l7 ! Assume low bits are benign
flush %o5 ! Assume low bits are benign
cmp %l5, %l3
bleu 0b ! Next page
add %l5, %l4, %l5
@ -5281,21 +5328,21 @@ dostart:
#else
or %l1, TTE_L|TTE_CP|TTE_CV|TTE_P|TTE_W, %l2 ! And low bits: L=1|CP=1|CV=1|E=0|P=1|W=1(ugh)|G=0
#endif
set 1f, %l7
set 1f, %o5
stxa %l0, [%l5] ASI_IMMU ! Make IMMU point to it
membar #Sync ! We may need more membar #Sync in here
stxa %l2, [%g0] ASI_IMMU_DATA_IN ! Store it
membar #Sync ! We may need more membar #Sync in here
flush %l7
flush %o5
1:
!!
!! Restore 0 as primary context
!!
mov CTX_PRIMARY, %l6
set 1f, %l7
set 1f, %o5
stxa %g0, [%l6] ASI_DMMU
membar #Sync ! No real reason for this XXXX
flush %l7
flush %o5
1:
!!
!! Now demap context 1
@ -5314,7 +5361,43 @@ dostart:
stxa %g0, [%l6] ASI_DMMU
membar #Sync
flush %l0
/*
* Get pointer to our cpu_info struct
*/
set _C_LABEL(cpu0paddr), %o0
LDPTR [%o0], %o0
!!
!! Now, map in the kernel as context==0
!!
set TLB_TAG_ACCESS, %l5
sethi %hi(INTSTACK), %l0
set 1f, %o5
stxa %l0, [%l5] ASI_IMMU ! Make IMMU point to it
membar #Sync ! We may need more membar #Sync in here
stxa %o0, [%g0] ASI_IMMU_DATA_IN ! Store it
membar #Sync ! We may need more membar #Sync in here
flush %o5
1:
!!! Make sure our stack's OK.
#define SAVE save %sp, -CC64FSZ, %sp
SAVE; SAVE; SAVE; SAVE; SAVE; SAVE; SAVE; SAVE; SAVE; SAVE
restore;restore;restore;restore;restore;restore;restore;restore;restore;restore
set _C_LABEL(estack0), %l0
LDPTR [%l0], %l0
add %l0, - CC64FSZ - 80, %l0 ! via syscall(boot_me_up) or somesuch
#ifdef _LP64
andn %l0, 0x0f, %l0 ! Needs to be 16-byte aligned
sub %l0, BIAS, %l0 ! and biased
#endif
save %g0, %l0, %sp
!!! Make sure our stack's OK.
SAVE; SAVE; SAVE; SAVE; SAVE; SAVE; SAVE; SAVE; SAVE; SAVE
restore;restore;restore;restore;restore;restore;restore;restore;restore;restore
#if 1
/*
* This should be handled in the CPU probe code
@ -5383,6 +5466,7 @@ dostart:
* user space. (If the exec fails, main() does not return.)
*/
call _C_LABEL(main)
! call %l7 ! Call routine
clr %o0 ! our frame arg is ignored
NOTREACHED
@ -5488,7 +5572,7 @@ _C_LABEL(openfirmware):
mov %g6, %l6
mov %g7, %l7
jmpl %o1, %o7
#if defined(_LP64) || defined(TRAPTRACE)
#if !defined(_LP64) || defined(TRAPTRACE)
wrpr %g0, PSTATE_PROM, %pstate ! Enable 64-bit addresses for the prom
#else
wrpr %g0, PSTATE_PROM|PSTATE_IE, %pstate ! Enable 64-bit addresses for the prom
@ -5750,7 +5834,7 @@ _C_LABEL(sigcode):
andn %l0, BLOCK_ALIGN, %l0 ! do a block store
stda %f0, [%l0] ASI_BLK_P
inc BLOCK_SIZE, %l0
stda %f16, [%l0] ASI_BLK_COMMIT_P
stda %f16, [%l0] ASI_BLK_P
1:
bz,pt %icc, 2f
rd %y, %l1 ! in any case, save %y
@ -5759,8 +5843,9 @@ _C_LABEL(sigcode):
add %l0, 2*BLOCK_SIZE, %l0 ! and skip what we already stored
stda %f32, [%l0] ASI_BLK_P
inc BLOCK_SIZE, %l0
stda %f48, [%l0] ASI_BLK_COMMIT_P
stda %f48, [%l0] ASI_BLK_P
2:
membar #StoreLoad
lduw [%fp + BIAS + CC64FSZ], %o0 ! sig
lduw [%fp + BIAS + CC64FSZ + 4], %o1 ! code
call %g1 ! (*sa->sa_handler)(sig,code,scp)
@ -9868,16 +9953,16 @@ Lfp_finish:
add %o2, 128, %o2 ! Skip a block
stda %f0, [%o2] ASI_BLK_P ! f->fs_f0 = etc;
stda %f0, [%o2] ASI_BLK_COMMIT_P ! f->fs_f0 = etc;
inc BLOCK_SIZE, %o2
stda %f16, [%o2] ASI_BLK_P
stda %f16, [%o2] ASI_BLK_COMMIT_P
inc BLOCK_SIZE, %o2
1:
btst FPRS_DU, %o5 ! Upper FPU clean?
bz,pt %icc, 2f ! Then skip it
nop
stda %f32, [%o2] ASI_BLK_P
stda %f32, [%o2] ASI_BLK_COMMIT_P
inc BLOCK_SIZE, %o2
stda %f48, [%o2] ASI_BLK_COMMIT_P
2:
@ -10333,6 +10418,7 @@ ENTRY(delay) ! %o0 = n
add %g1, %g2, %g2
! add %o5, %g2, %g2 ! But this gets complicated
rdpr %tick, %g1 ! Top of next itr
mov %g1, %g1 ! Erratum 50
1:
cmp %g1, %g2
bl,a,pn %xcc, 1b ! Done?

View File

@ -1,4 +1,4 @@
/* $NetBSD: machdep.c,v 1.65 2000/06/12 05:31:30 mrg Exp $ */
/* $NetBSD: machdep.c,v 1.66 2000/06/12 23:32:48 eeh Exp $ */
/*-
* Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc.
@ -129,8 +129,6 @@
/* #include "fb.h" */
/* Our exported CPU info; we have only one for now. */
struct cpu_info cpu_info_store;
int bus_space_debug = 0; /* This may be used by macros elsewhere. */
#ifdef DEBUG
#define DPRINTF(l, s) do { if (bus_space_debug & l) printf s; } while (0)

View File

@ -1,8 +1,8 @@
/* $NetBSD: pmap.c,v 1.53 2000/05/17 09:12:10 mrg Exp $ */
/* $NetBSD: pmap.c,v 1.54 2000/06/12 23:32:48 eeh Exp $ */
#undef NO_VCACHE /* Don't forget the locked TLB in dostart */
#define HWREF 1
#undef BOOT_DEBUG
#undef BOOT1_DEBUG
#undef BOOT_DEBUG
#undef BOOT1_DEBUG
/*
*
* Copyright (C) 1996-1999 Eduardo Horvath.
@ -37,6 +37,7 @@
#include <sys/systm.h>
#include <sys/msgbuf.h>
#include <sys/lock.h>
#include <sys/pool.h>
#include <sys/exec.h>
#include <sys/core.h>
#include <sys/kcore.h>
@ -68,6 +69,8 @@
#define db_printf printf
#endif
paddr_t cpu0paddr;/* XXXXXXXXXXXXXXXX */
/*
* Support for big page sizes. This maps the page size to the
* page bits. That is: these are the bits between 8K pages and
@ -189,6 +192,7 @@ typedef struct pv_entry {
#define PV_SETVA(pv,va) ((pv)->pv_va = (((va)&PV_VAMASK)|(((pv)->pv_va)&PV_MASK)))
pv_entry_t pv_table; /* array of entries, one per page */
static struct pool pv_pool;
extern void pmap_remove_pv __P((struct pmap *pm, vaddr_t va, paddr_t pa));
extern void pmap_enter_pv __P((struct pmap *pm, vaddr_t va, paddr_t pa));
extern void pmap_page_cache __P((paddr_t pa, int mode));
@ -212,15 +216,6 @@ int tsbsize; /* tsbents = 512 * 2^^tsbsize */
#define TSBENTS (512<<tsbsize)
#define TSBSIZE (TSBENTS * 16)
/*
* And here's the IOMMU TSB stuff, also allocated in pmap_bootstrap.
*/
int64_t *iotsb;
paddr_t iotsbp;
int iotsbsize; /* tsbents = 1024 * 2 ^^ tsbsize */
#define IOTSBENTS (1024<<iotsbsize)
#define IOTSBSIZE (IOTSBENTS * 8)
struct pmap kernel_pmap_;
int physmem;
@ -554,6 +549,15 @@ pmap_bootstrap(kernelstart, kernelend, maxctx)
/* Make sure all 4MB are mapped */
prom_map_phys(ksegp, 4*MEG, kernelstart, -1);
}
/*
* Allocate a 64MB page for the cpu_info structure now.
*/
if ((cpu0paddr = prom_alloc_phys(8*NBPG, 8*NBPG)) == 0 ) {
prom_printf("Cannot allocate new cpu_info\r\n");
OF_exit();
}
/*
* Find out how much RAM we have installed.
*/
@ -717,23 +721,17 @@ pmap_bootstrap(kernelstart, kernelend, maxctx)
prom_printf("TSB allocated at %p size %08x\r\n", (void*)tsb,
(int)TSBSIZE);
#endif
/*
* Allocate a single IOMMU TSB so they're all mapped coherently.
*/
iotsbsize = 0; /* We will only allocate an 8K TSB now */
valloc(iotsb, int64_t, IOTSBSIZE);
iotsbp = ((vaddr_t)iotsb) - kernelstart + ksegp;
bzero(iotsb, IOTSBSIZE); /* Invalidate all entries */
/* initialize pv_list stuff */
first_phys_addr = mem->start;
#if 0
valloc(pv_table, struct pv_entry, sizeof(struct pv_entry)*physmem);
bzero((caddr_t)pv_table, sizeof(struct pv_entry)*physmem);
#ifdef BOOT1_DEBUG
prom_printf("Allocating pv_table at %lx,%lx\r\n", (u_long)pv_table,
(u_long)sizeof(struct pv_entry)*physmem);
#endif
#endif
#ifdef BOOT1_DEBUG
prom_printf("firstaddr after pmap=%08lx\r\n", (u_long)firstaddr);
@ -1025,7 +1023,67 @@ pmap_bootstrap(kernelstart, kernelend, maxctx)
prom_printf("Done inserting PROM mappings into pmap_kernel()\r\n");
#endif
/*
* Fix up start of kernel heap.
*/
vmmap = (caddr_t)(ksegv + 4*MEG); /* Start after our locked TLB entry */
/* Let's keep 1 page of redzone after the kernel */
vmmap += NBPG;
/* Allocate some VAs for u0 */
{
extern vaddr_t u0[2];
paddr_t pa;
u0[0] = vmmap;
u0[1] = vmmap + 2*USPACE;
while (vmmap < u0[1]) {
pte_t tte;
vaddr_t va = (vaddr_t)vmmap;
paddr_t newp;
pmap_get_page(&pa);
prom_map_phys(phys_msgbuf, NBPG, va, -1);
#ifdef NO_VCACHE
tte.data.data = TSB_DATA(0 /* global */,
TLB_8K,
phys_msgbuf,
1 /* priv */,
1 /* Write */,
1 /* Cacheable */,
1 /* ALIAS -- Disable D$ */,
1 /* valid */,
0 /* IE */);
#else
tte.data.data = TSB_DATA(0 /* global */,
TLB_8K,
phys_msgbuf,
1 /* priv */,
1 /* Write */,
1 /* Cacheable */,
0 /* No ALIAS */,
1 /* valid */,
0 /* IE */);
#endif
newp = NULL;
while (pseg_set(pmap_kernel(), va, tte.data.data, newp)
!= NULL) {
pmap_get_page(&newp);
pmap_zero_page(newp);
#ifdef DEBUG
enter_stats.ptpneeded ++;
#endif
#ifdef BOOT1_DEBUG
prom_printf(
"pseg_set: pm=%p va=%p data=%lx newp %lx\r\n",
pmap_kernel(), va, (long)tte.data.
data, (long)newp);
{int i; for (i=0; i<140000000; i++) ;}
#endif
}
vmmap += NBPG;
}
}
/*
* Set up bounds of allocatable memory for vmstat et al.
*/
@ -1036,6 +1094,7 @@ pmap_bootstrap(kernelstart, kernelend, maxctx)
#ifdef DEBUG
pmapdebug = opmapdebug;
#endif
}
/*
@ -1045,13 +1104,94 @@ pmap_bootstrap(kernelstart, kernelend, maxctx)
void
pmap_init()
{
u_int64_t pagesize;
u_int64_t pte;
vm_page_t m;
paddr_t pa;
psize_t size;
vaddr_t va;
struct pglist mlist;
#ifdef NOTDEF_DEBUG
prom_printf("pmap_init()\r\n");
#endif
if (PAGE_SIZE != NBPG)
panic("pmap_init: CLSIZE!=1");
size = sizeof(struct pv_entry) * physmem;
TAILQ_INIT(&mlist);
if (uvm_pglistalloc((psize_t)size, (paddr_t)0, (paddr_t)-1,
(paddr_t)NBPG, (paddr_t)0, &mlist, 1, 0) != 0)
panic("cpu_start: no memory");
va = uvm_km_valloc(kernel_map, size);
if (va == 0)
panic("cpu_start: no memory");
pv_table = va;
m = TAILQ_FIRST(&mlist);
pa = VM_PAGE_TO_PHYS(m);
pte = TSB_DATA(0 /* global */,
pagesize,
pa,
1 /* priv */,
1 /* Write */,
1 /* Cacheable */,
1 /* ALIAS -- Disable D$ */,
1 /* valid */,
0 /* IE */);
/* Map the pages */
for (; m != NULL; m = TAILQ_NEXT(m,pageq)) {
paddr_t newp;
u_int64_t data;
pa = VM_PAGE_TO_PHYS(m);
pmap_zero_page(pa);
#ifdef NO_VCACHE
data = TSB_DATA(0 /* global */,
TLB_8K,
pa,
1 /* priv */,
1 /* Write */,
1 /* Cacheable */,
1 /* ALIAS -- Disable D$ */,
1 /* valid */,
0 /* IE */);
#else
data = TSB_DATA(0 /* global */,
TLB_8K,
pa,
1 /* priv */,
1 /* Write */,
1 /* Cacheable */,
0 /* No ALIAS */,
1 /* valid */,
0 /* IE */);
#endif
newp = NULL;
while (pseg_set(pmap_kernel(), va, data, newp)
!= NULL) {
pmap_get_page(&newp);
pmap_zero_page(newp);
#ifdef DEBUG
enter_stats.ptpneeded ++;
#endif
#ifdef BOOT1_DEBUG
prom_printf(
"pseg_set: pm=%p va=%p data=%lx newp %lx\r\n",
pmap_kernel(), va, (long)data, (long)newp);
{int i; for (i=0; i<140000000; i++) ;}
#endif
}
va += NBPG;
}
pmap_initialized = 1;
/* Setup a pool for additional pvlist structures */
pool_init(&pv_pool, sizeof(struct pv_entry), 0, 0, 0, "pv_entry", 0,
NULL, NULL, 0);
vm_first_phys = avail_start;
vm_num_phys = avail_end - avail_start;
}
@ -1066,11 +1206,6 @@ pmap_virtual_space(start, end)
/*
* Reserve one segment for kernel virtual memory
*/
vmmap = (caddr_t)(ksegv + 4*MEG); /* Start after our locked TLB entry */
#ifdef DIAGNOSTIC
/* Let's keep 1 page of redzone after the kernel */
vmmap += NBPG;
#endif
/* Reserve two pages for pmap_copy_page && /dev/mem */
*start = (vaddr_t)(vmmap + 2*NBPG);
*end = VM_MAX_KERNEL_ADDRESS;
@ -1802,8 +1937,7 @@ pmap_enter(pm, va, pa, prot, flags)
pm, va);
#endif
/* can this cause us to recurse forever? */
npv = (pv_entry_t)
malloc(sizeof *npv, M_VMPVENT, M_WAITOK);
npv = pool_get(&pv_pool, PR_WAITOK);
PV_SETVA(npv,va);
npv->pv_pmap = pm;
npv->pv_next = pv->pv_next;
@ -2972,7 +3106,7 @@ pmap_page_protect(pg, prot)
/* free the pv */
pv->pv_next = npv->pv_next;
free((caddr_t)npv, M_VMPVENT);
pool_put(&pv_pool, npv);
}
pv = firstpv;
@ -3029,7 +3163,7 @@ pmap_page_protect(pg, prot)
/* First save mod/ref bits */
npv->pv_va |= (pv->pv_va&PV_MASK);
*pv = *npv;
free((caddr_t)npv, M_VMPVENT);
pool_put(&pv_pool, npv);
} else {
pv->pv_pmap = NULL;
pv->pv_next = NULL;
@ -3249,8 +3383,7 @@ pmap_enter_pv(pmap, va, pa)
pmap, va);
#endif
/* can this cause us to recurse forever? */
npv = (pv_entry_t)
malloc(sizeof *npv, M_VMPVENT, M_NOWAIT);
npv = pool_get(&pv_pool, PR_NOWAIT);
if (npv == NULL)
panic("pmap_enter: new pv malloc() failed");
PV_SETVA(npv, va);
@ -3311,7 +3444,7 @@ pmap_remove_pv(pmap, va, pa)
/* First save mod/ref bits */
npv->pv_va |= (pv->pv_va&PV_MASK);
*pv = *npv;
free((caddr_t)npv, M_VMPVENT);
pool_put(&pv_pool, npv);
} else {
pv->pv_pmap = NULL;
pv->pv_next = NULL;
@ -3352,7 +3485,7 @@ pmap_remove_pv(pmap, va, pa)
* alias that may have occurred. However, that's a complicated
* operation involving multiple scans of the pv list.
*/
free((caddr_t)npv, M_VMPVENT);
pool_put(&pv_pool, npv);
}
/* Save ref/mod info */

View File

@ -1,4 +1,4 @@
/* $NetBSD: vaddrs.h,v 1.3 1998/09/05 23:57:29 eeh Exp $ */
/* $NetBSD: vaddrs.h,v 1.4 2000/06/12 23:32:48 eeh Exp $ */
/*
* Copyright (c) 1996
@ -69,66 +69,18 @@
*/
#ifndef IODEV_0
#define IODEV_0 0x0fe000000L /* must match VM_MAX_KERNEL_ADDRESS */
#define IODEV_0 0x0fe000000UL /* must match VM_MAX_KERNEL_ADDRESS */
#define _MAXNBPG 8192 /* fixed VAs, independent of actual NBPG */
#define _MAXNCPU 4 /* fixed VA allocation allows 4 CPUs */
#define _MAXNCPU 64
/* [4m:] interrupt and counter registers take (1 + NCPU) pages. */
#define TIMERREG_VA (IODEV_0)
#define COUNTERREG_VA ( TIMERREG_VA + _MAXNBPG*_MAXNCPU) /* [4m] */
#define ZS0_VA (COUNTERREG_VA + _MAXNBPG)
#define ZS1_VA ( ZS0_VA + _MAXNBPG)
#define AUXREG_VA ( ZS1_VA + _MAXNBPG)
#define CPUINFO_VA ( INTSTACK)
#define AUXREG_VA ( EINTSTACK)
#define TMPMAP_VA ( AUXREG_VA + _MAXNBPG)
#define MSGBUF_VA ( TMPMAP_VA + _MAXNBPG)
#define PI_INTR_VA ( MSGBUF_VA + _MAXNBPG) /* [4m] */
#define SI_INTR_VA ( PI_INTR_VA + _MAXNBPG*_MAXNCPU) /* [4m] */
#define IODEV_BASE ( SI_INTR_VA + _MAXNBPG)
#define IODEV_END 0x0ff000000L /* 16 MB of iospace */
/*
* The next constant defines the amount of reserved DVMA space on the
* Sun4m. The amount of space *must* be a multiple of 16MB, and thus
* (((u_int)0) - DVMA4M_BASE) must be divisible by 16*1024*1024!
* Note that pagetables must be allocated at a cost of 1k per MB of DVMA
* space, plus severe alignment restrictions. So don't make DVMA4M_BASE too
* low (max space = 2G).
*
* Since DVMA space overlaps with normal kernel address space (notably
* the device mappings and the PROM), we don't want to put any DVMA
* mappings where any of this useful stuff is (i.e. if we dvma_malloc
* a buffer, we want to still have a SRMMU mapping to it, and we can't
* have that if its on top of kernel code). Thus the last two
* constants define the actual DVMA addresses used. These can be anything
* as long as they are within the bounds setup by the first 2 constants.
* This is especially important on MP systems with cache coherency: to
* avoid consistency problems, DVMA addresses must map to the same place
* in both processor and IOMMU space.
*/
/*
* Actually, I don't know how much of this is really relevant to sun4u
* machines. I do know that IOMMU TSBs using 8K pages can map the
* following size segments:
*
* VA size VA base TSB size
* -------- -------- ---------
* 8MB ff800000 8K
* 16MB ff000000 16K
* 32MB fe000000 32K
* 64MB fc000000 64K
* 128MB f8000000 128K
* 256MB f0000000 256K
* 512MB e0000000 512K
* 1GB c0000000 1MB
*
* We will use the 8MB size for now.
*/
#define DVMA_BASE 0x0ff800000L /* can change subject to above rule */
#define DVMA_TOP 0x0ffffffffL /* do not modify */
#define DVMA_START 0x0ff800000L /* 8M of DVMA */
#define DVMA_END 0x0fff00000L /* XXX is this enough? */
#define IODEV_BASE ( MSGBUF_VA + _MAXNBPG)
#define IODEV_END 0x0ff000000UL /* 16 MB of iospace */
#endif /* IODEV_0 */