diff --git a/sys/sparc64/sparc64/locore.S b/sys/sparc64/sparc64/locore.S index 18e6e5436553..5d7e5d352627 100644 --- a/sys/sparc64/sparc64/locore.S +++ b/sys/sparc64/sparc64/locore.S @@ -28,8 +28,10 @@ #include +#include #include #include +#include #include "assym.s" @@ -39,30 +41,144 @@ .set kernbase,KERNBASE /* - * void _start(caddr_t metadata, u_long o1, u_long o2, u_long o3, + * void _start(caddr_t metadata, u_int *state, u_int mid, u_int bootmid, * u_long ofw_vec) + * + * XXX: in am smp system the other cpus are started in the loader, but since + * there's no way to look up a symbol there, we need to use the same entry + * point. So if the module id is not equal to bootcpu, jump to _mp_start. */ ENTRY(_start) - wrpr %g0, PSTATE_IE | PSTATE_PRIV | PSTATE_PEF, %pstate - mov %o0, %g1 - mov %o4, %g2 + /* + * Initialize misc state to known values. Interrupts disabled, normal + * globals, windows flushed (cr = 0, cs = nwindows - 1), no clean + * windows, pil 0, and floating point disabled. + */ + wrpr %g0, PSTATE_NORMAL, %pstate flushw - wrpr %g0, 1, %cwp wrpr %g0, 0, %cleanwin wrpr %g0, 0, %pil wr %g0, 0, %fprs - SET(kstack0 + KSTACK_PAGES * PAGE_SIZE - PCB_SIZEOF, %l0, %o0) - sub %o0, SPOFF + CCFSZ, %sp +#ifdef SMP + /* + * If we're not the boot processor, go do other stuff. + */ + cmp %o2, %o3 + be %xcc, 1f + nop + call _mp_start + nop + sir +1: +#endif - mov %g1, %o0 + /* + * Get onto our per-cpu panic stack, which precedes the struct pcpu in + * the per-cpu page. + */ + SET(pcpu0 + PAGE_SIZE - PC_SIZEOF, %l1, %l0) + sub %l0, SPOFF + CCFSZ, %sp + + /* + * Enable interrupts. + */ + wrpr %g0, PSTATE_KERNEL, %pstate + + /* + * Do initial bootstrap to setup pmap and thread0. + */ call sparc64_init - mov %g2, %o1 + nop + + /* + * Get onto thread0's kstack. + */ + sub PCB_REG, SPOFF + CCFSZ, %sp + + /* + * And away we go. This doesn't return. + */ call mi_startup nop + sir ! NOTREACHED END(_start) +/* + * void cpu_setregs(struct pcpu *pc) + */ +ENTRY(cpu_setregs) + ldx [%o0 + PC_CURTHREAD], %o1 + ldx [%o1 + TD_PCB], %o1 + + /* + * Disable interrupts, normal globals. + */ + wrpr %g0, PSTATE_NORMAL, %pstate + + /* + * Normal %g6 points to the current thread's pcb, and %g7 points to + * the per-cpu data structure. + */ + mov %o1, PCB_REG + mov %o0, PCPU_REG + + /* + * Alternate globals. + */ + wrpr %g0, PSTATE_ALT, %pstate + + /* + * Alternate %g5 points to a per-cpu panic stack, %g6 points to the + * current thread's pcb, and %g7 points to the per-cpu data structure. + */ + mov %o0, ASP_REG + mov %o1, PCB_REG + mov %o0, PCPU_REG + + /* + * Interrupt globals. + */ + wrpr %g0, PSTATE_INTR, %pstate + + /* + * Interrupt %g7 points to the per-cpu data structure. + */ + mov %o0, PCPU_REG + + /* + * MMU globals. + */ + wrpr %g0, PSTATE_MMU, %pstate + + /* + * MMU %g7 points to the user tsb. Initialize it to something sane + * here to catch invalid use. + */ + mov %g0, TSB_REG + + /* + * Normal globals again. + */ + wrpr %g0, PSTATE_NORMAL, %pstate + + /* + * Force trap level 1 and take over the trap table. + */ + SET(tl0_base, %o2, %o1) + wrpr %g0, 1, %tl + wrpr %o1, 0, %tba + + /* + * Re-enable interrupts. + */ + wrpr %g0, PSTATE_KERNEL, %pstate + + retl + nop +END(cpu_setregs) + /* * Signal trampoline, copied out to user stack. Must be 16 byte aligned or * the argv and envp pointers can become misaligned. diff --git a/sys/sparc64/sparc64/locore.s b/sys/sparc64/sparc64/locore.s index 18e6e5436553..5d7e5d352627 100644 --- a/sys/sparc64/sparc64/locore.s +++ b/sys/sparc64/sparc64/locore.s @@ -28,8 +28,10 @@ #include +#include #include #include +#include #include "assym.s" @@ -39,30 +41,144 @@ .set kernbase,KERNBASE /* - * void _start(caddr_t metadata, u_long o1, u_long o2, u_long o3, + * void _start(caddr_t metadata, u_int *state, u_int mid, u_int bootmid, * u_long ofw_vec) + * + * XXX: in am smp system the other cpus are started in the loader, but since + * there's no way to look up a symbol there, we need to use the same entry + * point. So if the module id is not equal to bootcpu, jump to _mp_start. */ ENTRY(_start) - wrpr %g0, PSTATE_IE | PSTATE_PRIV | PSTATE_PEF, %pstate - mov %o0, %g1 - mov %o4, %g2 + /* + * Initialize misc state to known values. Interrupts disabled, normal + * globals, windows flushed (cr = 0, cs = nwindows - 1), no clean + * windows, pil 0, and floating point disabled. + */ + wrpr %g0, PSTATE_NORMAL, %pstate flushw - wrpr %g0, 1, %cwp wrpr %g0, 0, %cleanwin wrpr %g0, 0, %pil wr %g0, 0, %fprs - SET(kstack0 + KSTACK_PAGES * PAGE_SIZE - PCB_SIZEOF, %l0, %o0) - sub %o0, SPOFF + CCFSZ, %sp +#ifdef SMP + /* + * If we're not the boot processor, go do other stuff. + */ + cmp %o2, %o3 + be %xcc, 1f + nop + call _mp_start + nop + sir +1: +#endif - mov %g1, %o0 + /* + * Get onto our per-cpu panic stack, which precedes the struct pcpu in + * the per-cpu page. + */ + SET(pcpu0 + PAGE_SIZE - PC_SIZEOF, %l1, %l0) + sub %l0, SPOFF + CCFSZ, %sp + + /* + * Enable interrupts. + */ + wrpr %g0, PSTATE_KERNEL, %pstate + + /* + * Do initial bootstrap to setup pmap and thread0. + */ call sparc64_init - mov %g2, %o1 + nop + + /* + * Get onto thread0's kstack. + */ + sub PCB_REG, SPOFF + CCFSZ, %sp + + /* + * And away we go. This doesn't return. + */ call mi_startup nop + sir ! NOTREACHED END(_start) +/* + * void cpu_setregs(struct pcpu *pc) + */ +ENTRY(cpu_setregs) + ldx [%o0 + PC_CURTHREAD], %o1 + ldx [%o1 + TD_PCB], %o1 + + /* + * Disable interrupts, normal globals. + */ + wrpr %g0, PSTATE_NORMAL, %pstate + + /* + * Normal %g6 points to the current thread's pcb, and %g7 points to + * the per-cpu data structure. + */ + mov %o1, PCB_REG + mov %o0, PCPU_REG + + /* + * Alternate globals. + */ + wrpr %g0, PSTATE_ALT, %pstate + + /* + * Alternate %g5 points to a per-cpu panic stack, %g6 points to the + * current thread's pcb, and %g7 points to the per-cpu data structure. + */ + mov %o0, ASP_REG + mov %o1, PCB_REG + mov %o0, PCPU_REG + + /* + * Interrupt globals. + */ + wrpr %g0, PSTATE_INTR, %pstate + + /* + * Interrupt %g7 points to the per-cpu data structure. + */ + mov %o0, PCPU_REG + + /* + * MMU globals. + */ + wrpr %g0, PSTATE_MMU, %pstate + + /* + * MMU %g7 points to the user tsb. Initialize it to something sane + * here to catch invalid use. + */ + mov %g0, TSB_REG + + /* + * Normal globals again. + */ + wrpr %g0, PSTATE_NORMAL, %pstate + + /* + * Force trap level 1 and take over the trap table. + */ + SET(tl0_base, %o2, %o1) + wrpr %g0, 1, %tl + wrpr %o1, 0, %tba + + /* + * Re-enable interrupts. + */ + wrpr %g0, PSTATE_KERNEL, %pstate + + retl + nop +END(cpu_setregs) + /* * Signal trampoline, copied out to user stack. Must be 16 byte aligned or * the argv and envp pointers can become misaligned. diff --git a/sys/sparc64/sparc64/machdep.c b/sys/sparc64/sparc64/machdep.c index 0632364bc3a7..ebeb5d724b58 100644 --- a/sys/sparc64/sparc64/machdep.c +++ b/sys/sparc64/sparc64/machdep.c @@ -106,33 +106,20 @@ typedef int ofw_vec_t(void *); -extern char tl0_base[]; - -extern char _end[]; - int physmem; int cold = 1; long dumplo; int Maxmem; -u_long debug_mask; - struct mtx Giant; struct mtx sched_lock; -static struct pcpu __pcpu; -/* - * This needs not be aligned as the other user areas, provided that process 0 - * does not have an fp state (which it doesn't normally). - * This constraint is only here for debugging. - */ -char kstack0[KSTACK_PAGES * PAGE_SIZE] __attribute__((aligned(64))); -static char uarea0[UAREA_PAGES * PAGE_SIZE] __attribute__((aligned(64))); -static struct trapframe frame0; -struct user *proc0uarea; -vm_offset_t proc0kstack; +char pcpu0[PAGE_SIZE]; +char uarea0[UAREA_PAGES * PAGE_SIZE]; +struct trapframe frame0; -char panic_stack[PANIC_STACK_PAGES * PAGE_SIZE]; +vm_offset_t kstack0; +vm_offset_t kstack0_phys; struct kva_md_info kmi; @@ -142,12 +129,15 @@ u_long ofw_tba; static struct timecounter tick_tc; static timecounter_get_t tick_get_timecount; -void sparc64_init(caddr_t mdp, ofw_vec_t *vec); +void sparc64_init(caddr_t mdp, u_int *state, u_int mid, u_int bootmid, + ofw_vec_t *vec); void sparc64_shutdown_final(void *dummy, int howto); static void cpu_startup(void *); SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL); +CTASSERT(sizeof(struct pcpu) <= (PAGE_SIZE / 2)); + static void cpu_startup(void *arg) { @@ -199,12 +189,13 @@ tick_get_timecount(struct timecounter *tc) } void -sparc64_init(caddr_t mdp, ofw_vec_t *vec) +sparc64_init(caddr_t mdp, u_int *state, u_int mid, u_int bootmid, + ofw_vec_t *vec) { + struct pcpu *pc; vm_offset_t end; vm_offset_t off; caddr_t kmdp; - u_long ps; end = 0; kmdp = NULL; @@ -276,20 +267,20 @@ sparc64_init(caddr_t mdp, ofw_vec_t *vec) */ tick_stop(); - /* Initialize the interrupt tables. */ + /* + * Initialize the interrupt tables. + */ intr_init(); - proc_linkup(&proc0); /* * Initialize proc0 stuff (p_contested needs to be done early). */ - proc0uarea = (struct user *)uarea0; - proc0kstack = (vm_offset_t)kstack0; + proc_linkup(&proc0); proc0.p_md.md_utrap = NULL; - proc0.p_uarea = proc0uarea; + proc0.p_uarea = (struct user *)uarea0; proc0.p_stats = &proc0.p_uarea->u_stats; thread0 = &proc0.p_thread; - thread0->td_kstack = proc0kstack; + thread0->td_kstack = kstack0; thread0->td_pcb = (struct pcb *) (thread0->td_kstack + KSTACK_PAGES * PAGE_SIZE) - 1; frame0.tf_tstate = TSTATE_IE | TSTATE_PEF; @@ -297,46 +288,20 @@ sparc64_init(caddr_t mdp, ofw_vec_t *vec) LIST_INIT(&thread0->td_contested); /* - * Force trap level 1 and take over the trap table. + * Prime our per-cpu data page for use. Note, we are using it for our + * stack, so don't pass the real size (PAGE_SIZE) to pcpu_init or + * it'll zero it out from under us. */ - ps = rdpr(pstate); - wrpr(pstate, ps, PSTATE_IE); - wrpr(tl, 0, 1); - wrpr(tba, tl0_base, 0); + pc = (struct pcpu *)(pcpu0 + PAGE_SIZE) - 1; + pcpu_init(pc, 0, sizeof(struct pcpu)); + pc->pc_curthread = thread0; + pc->pc_curpcb = thread0->td_pcb; + pc->pc_mid = mid; /* - * Setup preloaded globals. - * Normal %g7 points to the per-cpu data structure. + * Initialize global registers. */ - __asm __volatile("mov %0, %%g7" : : "r" (&__pcpu)); - - /* - * Alternate %g5 points to a per-cpu stack for saving alternate - * globals, %g6 points to the current thread's pcb, and %g7 points - * to the per-cpu data structure. - */ - wrpr(pstate, ps, PSTATE_AG | PSTATE_IE); - __asm __volatile("mov %0, %%g5" : : "r" - (&__pcpu.pc_alt_stack[ALT_STACK_SIZE - 1])); - __asm __volatile("mov %0, %%g6" : : "r" (thread0->td_pcb)); - __asm __volatile("mov %0, %%g7" : : "r" (&__pcpu)); - - /* - * Interrupt %g6 points to a per-cpu interrupt queue, %g7 points to - * the interrupt vector table. - */ - wrpr(pstate, ps, PSTATE_IG | PSTATE_IE); - __asm __volatile("mov %0, %%g6" : : "r" (&__pcpu.pc_iq)); - __asm __volatile("mov %0, %%g7" : : "r" (&intr_vectors)); - - /* - * MMU %g7 points to the user tsb. Initialize it to something sane - * here to catch invalid use. - */ - wrpr(pstate, ps, PSTATE_MG | PSTATE_IE); - __asm __volatile("mov %%g0, %%g7" : :); - - wrpr(pstate, ps, 0); + cpu_setregs(pc); /* * Map and initialize the message buffer (after setting trap table). @@ -345,13 +310,6 @@ sparc64_init(caddr_t mdp, ofw_vec_t *vec) pmap_kenter((vm_offset_t)msgbufp + off, msgbuf_phys + off); msgbufinit(msgbufp, MSGBUF_SIZE); - /* - * Initialize curthread so that mutexes work. - */ - pcpu_init(pcpup, 0, sizeof(struct pcpu)); - PCPU_SET(curthread, thread0); - PCPU_SET(curpcb, thread0->td_pcb); - /* * Initialize mutexes. */ diff --git a/sys/sparc64/sparc64/pmap.c b/sys/sparc64/sparc64/pmap.c index 55c1729e7e4e..1211b1882c70 100644 --- a/sys/sparc64/sparc64/pmap.c +++ b/sys/sparc64/sparc64/pmap.c @@ -308,23 +308,23 @@ pmap_bootstrap(vm_offset_t ekva) tsb_kernel_phys = pa; tsb_kernel = (struct tte *)virtual_avail; virtual_avail += KVA_PAGES * PAGE_SIZE_4M; - for (i = 0; i < KVA_PAGES; i++) { - va = (vm_offset_t)tsb_kernel + i * PAGE_SIZE_4M; - tte.tte_tag = TT_CTX(TLB_CTX_KERNEL) | TT_VA(va); - tte.tte_data = TD_V | TD_4M | TD_VA_LOW(va) | TD_PA(pa) | - TD_L | TD_CP | TD_CV | TD_P | TD_W; - tlb_store_slot(TLB_DTLB, va, TLB_CTX_KERNEL, tte, - TLB_SLOT_TSB_KERNEL_MIN + i); - } + pmap_map_tsb(); bzero(tsb_kernel, KVA_PAGES * PAGE_SIZE_4M); /* - * Load the tsb registers. + * Allocate a kernel stack with guard page for thread0 and map it into + * the kernel tsb. */ - stxa(AA_DMMU_TSB, ASI_DMMU, (vm_offset_t)tsb_kernel); - stxa(AA_IMMU_TSB, ASI_IMMU, (vm_offset_t)tsb_kernel); - membar(Sync); - flush(tsb_kernel); + pa = pmap_bootstrap_alloc(KSTACK_PAGES * PAGE_SIZE); + kstack0_phys = pa; + kstack0 = virtual_avail + (KSTACK_GUARD_PAGES * PAGE_SIZE); + virtual_avail += (KSTACK_PAGES + KSTACK_GUARD_PAGES) * PAGE_SIZE; + for (i = 0; i < KSTACK_PAGES; i++) { + pa = kstack0_phys + i * PAGE_SIZE; + va = kstack0 + i * PAGE_SIZE; + pmap_kenter(va, pa); + tlb_page_demap(TLB_DTLB, TLB_CTX_KERNEL, va); + } /* * Allocate the message buffer. @@ -399,6 +399,36 @@ pmap_bootstrap(vm_offset_t ekva) pm->pm_active = ~0; pm->pm_count = 1; TAILQ_INIT(&pm->pm_pvlist); +} + +void +pmap_map_tsb(void) +{ + struct tte tte; + vm_offset_t va; + vm_offset_t pa; + int i; + + /* + * Map the 4mb tsb pages. + */ + for (i = 0; i < KVA_PAGES; i++) { + va = (vm_offset_t)tsb_kernel + i * PAGE_SIZE_4M; + pa = tsb_kernel_phys + i * PAGE_SIZE_4M; + tte.tte_tag = TT_CTX(TLB_CTX_KERNEL) | TT_VA(va); + tte.tte_data = TD_V | TD_4M | TD_VA_LOW(va) | TD_PA(pa) | + TD_L | TD_CP | TD_CV | TD_P | TD_W; + tlb_store_slot(TLB_DTLB, va, TLB_CTX_KERNEL, tte, + TLB_SLOT_TSB_KERNEL_MIN + i); + } + + /* + * Load the tsb registers. + */ + stxa(AA_DMMU_TSB, ASI_DMMU, (vm_offset_t)tsb_kernel); + stxa(AA_IMMU_TSB, ASI_IMMU, (vm_offset_t)tsb_kernel); + membar(Sync); + flush(tsb_kernel); /* * Set the secondary context to be the kernel context (needed for