diff --git a/sys/arch/sparc64/include/cpu.h b/sys/arch/sparc64/include/cpu.h index ef41d6590672..d522fa50b837 100644 --- a/sys/arch/sparc64/include/cpu.h +++ b/sys/arch/sparc64/include/cpu.h @@ -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 #include +/* + * 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)); diff --git a/sys/arch/sparc64/include/param.h b/sys/arch/sparc64/include/param.h index 1bea68b98116..e8f990ab9582 100644 --- a/sys/arch/sparc64/include/param.h +++ b/sys/arch/sparc64/include/param.h @@ -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) diff --git a/sys/arch/sparc64/sparc64/cpu.c b/sys/arch/sparc64/sparc64/cpu.c index b9bab245d196..40b94aee0af1 100644 --- a/sys/arch/sparc64/sparc64/cpu.c +++ b/sys/arch/sparc64/sparc64/cpu.c @@ -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 #include +#include #include #include @@ -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 */ char machine_arch[] = MACHINE_ARCH; /* from */ @@ -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) diff --git a/sys/arch/sparc64/sparc64/intreg.h b/sys/arch/sparc64/sparc64/intreg.h index d49939470b34..945b6c1b1c90 100644 --- a/sys/arch/sparc64/sparc64/intreg.h +++ b/sys/arch/sparc64/sparc64/intreg.h @@ -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 diff --git a/sys/arch/sparc64/sparc64/locore.s b/sys/arch/sparc64/sparc64/locore.s index fb7cb4688e9f..8dafcc0eb68a 100644 --- a/sys/arch/sparc64/sparc64/locore.s +++ b/sys/arch/sparc64/sparc64/locore.s @@ -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? diff --git a/sys/arch/sparc64/sparc64/machdep.c b/sys/arch/sparc64/sparc64/machdep.c index 244b27119d6e..faa9543ced85 100644 --- a/sys/arch/sparc64/sparc64/machdep.c +++ b/sys/arch/sparc64/sparc64/machdep.c @@ -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) diff --git a/sys/arch/sparc64/sparc64/pmap.c b/sys/arch/sparc64/sparc64/pmap.c index 10baaa017a7f..18a085c23f4e 100644 --- a/sys/arch/sparc64/sparc64/pmap.c +++ b/sys/arch/sparc64/sparc64/pmap.c @@ -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 #include #include +#include #include #include #include @@ -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<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 */ diff --git a/sys/arch/sparc64/sparc64/vaddrs.h b/sys/arch/sparc64/sparc64/vaddrs.h index 4e8af0007c74..0f79886da109 100644 --- a/sys/arch/sparc64/sparc64/vaddrs.h +++ b/sys/arch/sparc64/sparc64/vaddrs.h @@ -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 */