machdep.c revision 105569
180708Sjake/*- 280708Sjake * Copyright (c) 2001 Jake Burkholder. 382902Sjake * Copyright (c) 1992 Terrence R. Lambert. 482902Sjake * Copyright (c) 1982, 1987, 1990 The Regents of the University of California. 580708Sjake * All rights reserved. 680708Sjake * 782902Sjake * This code is derived from software contributed to Berkeley by 882902Sjake * William Jolitz. 982902Sjake * 1080708Sjake * Redistribution and use in source and binary forms, with or without 1180708Sjake * modification, are permitted provided that the following conditions 1280708Sjake * are met: 1380708Sjake * 1. Redistributions of source code must retain the above copyright 1480708Sjake * notice, this list of conditions and the following disclaimer. 1580708Sjake * 2. Redistributions in binary form must reproduce the above copyright 1680708Sjake * notice, this list of conditions and the following disclaimer in the 1780708Sjake * documentation and/or other materials provided with the distribution. 1882902Sjake * 3. All advertising materials mentioning features or use of this software 1982902Sjake * must display the following acknowledgement: 2082902Sjake * This product includes software developed by the University of 2182902Sjake * California, Berkeley and its contributors. 2282902Sjake * 4. Neither the name of the University nor the names of its contributors 2382902Sjake * may be used to endorse or promote products derived from this software 2482902Sjake * without specific prior written permission. 2580708Sjake * 2682902Sjake * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2780708Sjake * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2880708Sjake * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2982902Sjake * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 3080708Sjake * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 3180708Sjake * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3280708Sjake * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3380708Sjake * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3480708Sjake * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3580708Sjake * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3680708Sjake * SUCH DAMAGE. 3780708Sjake * 3882902Sjake * from: @(#)machdep.c 7.4 (Berkeley) 6/3/91 3982902Sjake * from: FreeBSD: src/sys/i386/i386/machdep.c,v 1.477 2001/08/27 4080708Sjake * $FreeBSD: head/sys/sparc64/sparc64/machdep.c 105569 2002-10-20 21:55:35Z mux $ 4180708Sjake */ 4280708Sjake 4380709Sjake#include "opt_ddb.h" 4485242Sjake#include "opt_msgbuf.h" 4580709Sjake 4680708Sjake#include <sys/param.h> 4780708Sjake#include <sys/systm.h> 4880709Sjake#include <sys/cons.h> 49102561Sjake#include <sys/imgact.h> 5080709Sjake#include <sys/kernel.h> 5185262Sjake#include <sys/ktr.h> 5280709Sjake#include <sys/linker.h> 5380709Sjake#include <sys/lock.h> 5488782Sjake#include <sys/malloc.h> 5585242Sjake#include <sys/msgbuf.h> 5680708Sjake#include <sys/mutex.h> 5780709Sjake#include <sys/pcpu.h> 5880708Sjake#include <sys/proc.h> 5985242Sjake#include <sys/reboot.h> 6080709Sjake#include <sys/bio.h> 6180709Sjake#include <sys/buf.h> 6284849Stmm#include <sys/bus.h> 6386147Stmm#include <sys/eventhandler.h> 6484849Stmm#include <sys/interrupt.h> 6580708Sjake#include <sys/ptrace.h> 6680708Sjake#include <sys/signalvar.h> 6791616Sjake#include <sys/smp.h> 6882902Sjake#include <sys/sysent.h> 6980708Sjake#include <sys/sysproto.h> 7080709Sjake#include <sys/timetc.h> 7191783Sjake#include <sys/user.h> 7291156Sjake#include <sys/ucontext.h> 7380709Sjake#include <sys/user.h> 7491616Sjake#include <sys/ucontext.h> 7582902Sjake#include <sys/exec.h> 7680708Sjake 7780708Sjake#include <dev/ofw/openfirm.h> 7880708Sjake 7980709Sjake#include <vm/vm.h> 8080709Sjake#include <vm/vm_param.h> 8180709Sjake#include <vm/vm_kern.h> 8280709Sjake#include <vm/vm_object.h> 8380709Sjake#include <vm/vm_page.h> 8480709Sjake#include <vm/vm_map.h> 8580709Sjake#include <vm/vm_pager.h> 8680709Sjake#include <vm/vm_extern.h> 8780709Sjake 8880709Sjake#include <ddb/ddb.h> 8980709Sjake 9086521Sjake#include <machine/cache.h> 9181383Sjake#include <machine/clock.h> 9282902Sjake#include <machine/cpu.h> 9383366Sjulian#include <machine/fp.h> 9481383Sjake#include <machine/intr_machdep.h> 9580708Sjake#include <machine/md_var.h> 9688436Sjake#include <machine/metadata.h> 9786147Stmm#include <machine/ofw_machdep.h> 9891783Sjake#include <machine/smp.h> 9980709Sjake#include <machine/pmap.h> 10080709Sjake#include <machine/pstate.h> 10180708Sjake#include <machine/reg.h> 10282902Sjake#include <machine/sigframe.h> 10381383Sjake#include <machine/tick.h> 10491613Sjake#include <machine/tlb.h> 10582016Sjake#include <machine/tstate.h> 10691616Sjake#include <machine/upa.h> 10782902Sjake#include <machine/ver.h> 10880708Sjake 10980709Sjaketypedef int ofw_vec_t(void *); 11080708Sjake 11197445Sjakestruct tlb_entry *kernel_tlbs; 11291616Sjakeint kernel_tlb_slots; 11391616Sjake 114102600Speterlong physmem; 11580708Sjakeint cold = 1; 116102600Speterlong Maxmem; 11780708Sjake 11891360Sjakechar pcpu0[PCPU_PAGES * PAGE_SIZE]; 11989038Sjakechar uarea0[UAREA_PAGES * PAGE_SIZE]; 12089038Sjakestruct trapframe frame0; 12180708Sjake 12289038Sjakevm_offset_t kstack0; 12389038Sjakevm_offset_t kstack0_phys; 12488781Sjake 12582902Sjakestruct kva_md_info kmi; 12680709Sjake 12780709Sjakeu_long ofw_vec; 12880709Sjakeu_long ofw_tba; 12980709Sjake 13080709Sjakestatic struct timecounter tick_tc; 13180709Sjake 13280709Sjakestatic timecounter_get_t tick_get_timecount; 13391616Sjakevoid sparc64_init(caddr_t mdp, u_long o1, u_long o2, u_long o3, 13489038Sjake ofw_vec_t *vec); 13586147Stmmvoid sparc64_shutdown_final(void *dummy, int howto); 13680709Sjake 13780709Sjakestatic void cpu_startup(void *); 13880709SjakeSYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL); 13980709Sjake 14091336SjakeCTASSERT((1 << INT_SHIFT) == sizeof(int)); 14191336SjakeCTASSERT((1 << PTR_SHIFT) == sizeof(char *)); 14291336Sjake 14391360SjakeCTASSERT(sizeof(struct pcpu) <= ((PCPU_PAGES * PAGE_SIZE) / 2)); 14489038Sjake 14580709Sjakestatic void 14680709Sjakecpu_startup(void *arg) 14780709Sjake{ 14880709Sjake u_int clock; 14980709Sjake 150101898Sjake OF_getprop(PCPU_GET(node), "clock-frequency", &clock, sizeof(clock)); 15180709Sjake 15280709Sjake tick_tc.tc_get_timecount = tick_get_timecount; 15380709Sjake tick_tc.tc_poll_pps = NULL; 15480709Sjake tick_tc.tc_counter_mask = ~0u; 15580709Sjake tick_tc.tc_frequency = clock; 15680709Sjake tick_tc.tc_name = "tick"; 15780709Sjake tc_init(&tick_tc); 15880709Sjake 15991359Sjake cpu_identify(rdpr(ver), clock, PCPU_GET(cpuid)); 16080709Sjake 16182902Sjake vm_ksubmap_init(&kmi); 16280709Sjake 16380709Sjake bufinit(); 16480709Sjake vm_pager_bufferinit(); 16580709Sjake 16681383Sjake tick_start(clock, tick_hardclock); 16786147Stmm 16886147Stmm EVENTHANDLER_REGISTER(shutdown_final, sparc64_shutdown_final, NULL, 16986147Stmm SHUTDOWN_PRI_LAST); 17080709Sjake} 17180709Sjake 17287702Sjhbvoid 17387702Sjhbcpu_pcpu_init(struct pcpu *pcpu, int cpuid, size_t size) 17487702Sjhb{ 17597265Sjake struct intr_request *ir; 17697265Sjake int i; 17797265Sjake 17897265Sjake pcpu->pc_irtail = &pcpu->pc_irhead; 17997265Sjake for (i = 0; i < IR_FREE; i++) { 18097265Sjake ir = &pcpu->pc_irpool[i]; 18197265Sjake ir->ir_next = pcpu->pc_irfree; 18297265Sjake pcpu->pc_irfree = ir; 18397265Sjake } 18487702Sjhb} 18587702Sjhb 18680709Sjakeunsigned 18780709Sjaketick_get_timecount(struct timecounter *tc) 18880709Sjake{ 18980709Sjake return ((unsigned)rd(tick)); 19080709Sjake} 19180709Sjake 19280708Sjakevoid 19391616Sjakesparc64_init(caddr_t mdp, u_long o1, u_long o2, u_long o3, ofw_vec_t *vec) 19480708Sjake{ 195101898Sjake phandle_t child; 196101898Sjake phandle_t root; 19789038Sjake struct pcpu *pc; 19886521Sjake vm_offset_t end; 19997871Sjake vm_offset_t va; 20086521Sjake caddr_t kmdp; 201105569Smux char *env; 202101898Sjake char type[8]; 20380709Sjake 20486521Sjake end = 0; 20586521Sjake kmdp = NULL; 20686521Sjake 20780709Sjake /* 20880709Sjake * Initialize openfirmware (needed for console). 20980709Sjake */ 21080709Sjake OF_init(vec); 21180709Sjake 21280709Sjake /* 21386521Sjake * Parse metadata if present and fetch parameters. Must be before the 21486521Sjake * console is inited so cninit gets the right value of boothowto. 21586521Sjake */ 21686521Sjake if (mdp != NULL) { 21786521Sjake preload_metadata = mdp; 21886521Sjake kmdp = preload_search_by_type("elf kernel"); 21986521Sjake if (kmdp != NULL) { 22086521Sjake boothowto = MD_FETCH(kmdp, MODINFOMD_HOWTO, int); 22186521Sjake kern_envp = MD_FETCH(kmdp, MODINFOMD_ENVP, char *); 22286521Sjake end = MD_FETCH(kmdp, MODINFOMD_KERNEND, vm_offset_t); 22391616Sjake kernel_tlb_slots = MD_FETCH(kmdp, MODINFOMD_DTLB_SLOTS, 22491616Sjake int); 22597445Sjake kernel_tlbs = (void *)preload_search_info(kmdp, 22691616Sjake MODINFO_METADATA | MODINFOMD_DTLB); 22786521Sjake } 22886521Sjake } 22986521Sjake 23086521Sjake /* 23180709Sjake * Initialize the console before printing anything. 23280709Sjake */ 23388639Sjake cninit(); 23480709Sjake 23580709Sjake /* 23686521Sjake * Panic is there is no metadata. Most likely the kernel was booted 23786521Sjake * directly, instead of through loader(8). 23880709Sjake */ 23986521Sjake if (mdp == NULL || kmdp == NULL) { 24086521Sjake printf("sparc64_init: no loader metadata.\n" 24186521Sjake "This probably means you are not using loader(8).\n"); 24286521Sjake panic("sparc64_init"); 24386521Sjake } 24480709Sjake 24581383Sjake /* 24686521Sjake * Sanity check the kernel end, which is important. 24786521Sjake */ 24886521Sjake if (end == 0) { 24986521Sjake printf("sparc64_init: warning, kernel end not specified.\n" 25086521Sjake "Attempting to continue anyway.\n"); 25186521Sjake end = (vm_offset_t)_end; 25286521Sjake } 25386521Sjake 254101898Sjake root = OF_peer(0); 255101898Sjake for (child = OF_child(root); child != 0; child = OF_peer(child)) { 256101898Sjake OF_getprop(child, "device_type", type, sizeof(type)); 257101898Sjake if (strcmp(type, "cpu") == 0) 258101898Sjake break; 259101898Sjake } 260101898Sjake if (child == 0) 261101898Sjake panic("cpu_startup: no cpu\n"); 262101898Sjake OF_getprop(child, "#dtlb-entries", &tlb_dtlb_entries, 263101898Sjake sizeof(tlb_dtlb_entries)); 264101898Sjake OF_getprop(child, "#itlb-entries", &tlb_itlb_entries, 265101898Sjake sizeof(tlb_itlb_entries)); 266101898Sjake 267101898Sjake cache_init(child); 268101898Sjake 26990625Stmm#ifdef DDB 27090625Stmm kdb_init(); 27190625Stmm#endif 27290625Stmm 27391616Sjake#ifdef SMP 27491616Sjake mp_tramp = mp_tramp_alloc(); 27591616Sjake#endif 27691616Sjake 27786521Sjake /* 27890625Stmm * Initialize virtual memory and calculate physmem. 27987546Sdillon */ 28090625Stmm pmap_bootstrap(end); 28187546Sdillon 28287546Sdillon /* 28381383Sjake * Initialize tunables. 28481383Sjake */ 28587546Sdillon init_param1(); 28687546Sdillon init_param2(physmem); 287105569Smux env = getenv("kernelname"); 288105569Smux if (env != NULL) { 289105569Smux strlcpy(kernelname, env, sizeof(kernelname)); 290105569Smux freeenv(env); 291105569Smux } 29281085Sjake 29380709Sjake /* 29481383Sjake * Disable tick for now. 29580709Sjake */ 29681383Sjake tick_stop(); 29780709Sjake 29889038Sjake /* 29989038Sjake * Initialize the interrupt tables. 30089038Sjake */ 30190624Stmm intr_init1(); 30280709Sjake 30380709Sjake /* 30480709Sjake * Initialize proc0 stuff (p_contested needs to be done early). 30580709Sjake */ 306103367Sjulian proc_linkup(&proc0, &ksegrp0, &kse0, &thread0); 30795744Sjake proc0.p_md.md_sigtramp = NULL; 30888822Stmm proc0.p_md.md_utrap = NULL; 30989038Sjake proc0.p_uarea = (struct user *)uarea0; 31083366Sjulian proc0.p_stats = &proc0.p_uarea->u_stats; 31190361Sjulian thread0.td_kstack = kstack0; 31290361Sjulian thread0.td_pcb = (struct pcb *) 31390361Sjulian (thread0.td_kstack + KSTACK_PAGES * PAGE_SIZE) - 1; 31488639Sjake frame0.tf_tstate = TSTATE_IE | TSTATE_PEF; 31590361Sjulian thread0.td_frame = &frame0; 31680709Sjake 31780709Sjake /* 31889038Sjake * Prime our per-cpu data page for use. Note, we are using it for our 31989038Sjake * stack, so don't pass the real size (PAGE_SIZE) to pcpu_init or 32089038Sjake * it'll zero it out from under us. 32180709Sjake */ 32291360Sjake pc = (struct pcpu *)(pcpu0 + (PCPU_PAGES * PAGE_SIZE)) - 1; 32389038Sjake pcpu_init(pc, 0, sizeof(struct pcpu)); 32490361Sjulian pc->pc_curthread = &thread0; 32591156Sjake pc->pc_curpcb = thread0.td_pcb; 32691616Sjake pc->pc_mid = UPA_CR_GET_MID(ldxa(0, ASI_UPA_CONFIG_REG)); 32791616Sjake pc->pc_addr = (vm_offset_t)pcpu0; 328101898Sjake pc->pc_node = child; 32991613Sjake pc->pc_tlb_ctx = TLB_CTX_USER_MIN; 33091613Sjake pc->pc_tlb_ctx_min = TLB_CTX_USER_MIN; 33191613Sjake pc->pc_tlb_ctx_max = TLB_CTX_USER_MAX; 33288639Sjake 33380709Sjake /* 33489038Sjake * Initialize global registers. 33581383Sjake */ 33689038Sjake cpu_setregs(pc); 33788639Sjake 33888639Sjake /* 33988822Stmm * Map and initialize the message buffer (after setting trap table). 34088822Stmm */ 34197871Sjake va = (vm_offset_t)msgbufp; 34297871Sjake pmap_map(&va, msgbuf_phys, msgbuf_phys + MSGBUF_SIZE, 0); 34388822Stmm msgbufinit(msgbufp, MSGBUF_SIZE); 34488822Stmm 34593702Sjhb mutex_init(); 34690624Stmm intr_init2(); 34780708Sjake} 34880708Sjake 34980708Sjakevoid 35080709Sjakeset_openfirm_callback(ofw_vec_t *vec) 35180709Sjake{ 35280709Sjake ofw_tba = rdpr(tba); 35380709Sjake ofw_vec = (u_long)vec; 35480709Sjake} 35580709Sjake 35680709Sjakevoid 35780708Sjakesendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) 35880708Sjake{ 35982902Sjake struct trapframe *tf; 36082902Sjake struct sigframe *sfp; 36182902Sjake struct sigacts *psp; 36282902Sjake struct sigframe sf; 36383366Sjulian struct thread *td; 36485242Sjake struct frame *fp; 36582902Sjake struct proc *p; 36685242Sjake int oonstack; 36782902Sjake u_long sp; 36882902Sjake 36982902Sjake oonstack = 0; 37083366Sjulian td = curthread; 37183366Sjulian p = td->td_proc; 37282902Sjake psp = p->p_sigacts; 37383366Sjulian tf = td->td_frame; 37482902Sjake sp = tf->tf_sp + SPOFF; 37582902Sjake oonstack = sigonstack(sp); 37682902Sjake 37783366Sjulian CTR4(KTR_SIG, "sendsig: td=%p (%s) catcher=%p sig=%d", td, p->p_comm, 37882902Sjake catcher, sig); 37982902Sjake 380102554Sjake /* Make sure we have a signal trampoline to return to. */ 381102554Sjake if (p->p_md.md_sigtramp == NULL) { 382102554Sjake /* 383102554Sjake * No signal tramoline... kill the process. 384102554Sjake */ 385102554Sjake CTR0(KTR_SIG, "sendsig: no sigtramp"); 386102873Sjake printf("sendsig: %s is too old, rebuild it\n", p->p_comm); 387102554Sjake sigexit(td, sig); 388102554Sjake /* NOTREACHED */ 389102554Sjake } 390102554Sjake 39182902Sjake /* Save user context. */ 39282902Sjake bzero(&sf, sizeof(sf)); 39382902Sjake sf.sf_uc.uc_sigmask = *mask; 39482902Sjake sf.sf_uc.uc_stack = p->p_sigstk; 39582902Sjake sf.sf_uc.uc_stack.ss_flags = (p->p_flag & P_ALTSTACK) 39682902Sjake ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE; 39782902Sjake sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0; 39882902Sjake bcopy(tf->tf_global, sf.sf_uc.uc_mcontext.mc_global, 39982902Sjake sizeof (tf->tf_global)); 40082902Sjake bcopy(tf->tf_out, sf.sf_uc.uc_mcontext.mc_out, sizeof (tf->tf_out)); 40182902Sjake sf.sf_uc.uc_mcontext.mc_tpc = tf->tf_tpc; 40282902Sjake sf.sf_uc.uc_mcontext.mc_tnpc = tf->tf_tnpc; 40382902Sjake sf.sf_uc.uc_mcontext.mc_tstate = tf->tf_tstate; 40482902Sjake 40582902Sjake /* Allocate and validate space for the signal handler context. */ 40682902Sjake if ((p->p_flag & P_ALTSTACK) != 0 && !oonstack && 40782902Sjake SIGISMEMBER(psp->ps_sigonstack, sig)) { 40882902Sjake sfp = (struct sigframe *)(p->p_sigstk.ss_sp + 40982902Sjake p->p_sigstk.ss_size - sizeof(struct sigframe)); 41082902Sjake#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 41182902Sjake p->p_sigstk.ss_flags |= SS_ONSTACK; 41282902Sjake#endif 41382902Sjake } else 41482902Sjake sfp = (struct sigframe *)sp - 1; 41582902Sjake PROC_UNLOCK(p); 41682902Sjake 41785242Sjake fp = (struct frame *)sfp - 1; 41882902Sjake 41982902Sjake /* Translate the signal if appropriate. */ 42082902Sjake if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize) 42182902Sjake sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)]; 42282902Sjake 42382902Sjake /* Build the argument list for the signal handler. */ 42482902Sjake tf->tf_out[0] = sig; 42582902Sjake tf->tf_out[2] = (register_t)&sfp->sf_uc; 42682902Sjake tf->tf_out[3] = tf->tf_type; 42782902Sjake tf->tf_out[4] = (register_t)catcher; 42882902Sjake PROC_LOCK(p); 42982902Sjake if (SIGISMEMBER(p->p_sigacts->ps_siginfo, sig)) { 43082902Sjake /* Signal handler installed with SA_SIGINFO. */ 43182902Sjake tf->tf_out[1] = (register_t)&sfp->sf_si; 43282902Sjake 43382902Sjake /* Fill siginfo structure. */ 43482902Sjake sf.sf_si.si_signo = sig; 43582902Sjake sf.sf_si.si_code = code; 43688639Sjake sf.sf_si.si_addr = (void *)tf->tf_sfar; 437103081Sjmallett sf.sf_si.si_pid = p->p_pid; 438103081Sjmallett sf.sf_si.si_uid = p->p_ucred->cr_uid; 43982902Sjake } else { 44082902Sjake /* Old FreeBSD-style arguments. */ 44182902Sjake tf->tf_out[1] = code; 44282902Sjake } 44382902Sjake PROC_UNLOCK(p); 44482902Sjake 44582902Sjake /* Copy the sigframe out to the user's stack. */ 44685242Sjake if (rwindow_save(td) != 0 || copyout(&sf, sfp, sizeof(*sfp)) != 0 || 44794254Sjake suword(&fp->fr_in[6], tf->tf_out[6]) != 0) { 44882902Sjake /* 44982902Sjake * Something is wrong with the stack pointer. 45082902Sjake * ...Kill the process. 45182902Sjake */ 45283366Sjulian CTR2(KTR_SIG, "sendsig: sigexit td=%p sfp=%p", td, sfp); 45382902Sjake PROC_LOCK(p); 45483366Sjulian sigexit(td, SIGILL); 45582902Sjake /* NOTREACHED */ 45682902Sjake } 45782902Sjake 458102554Sjake tf->tf_tpc = (u_long)p->p_md.md_sigtramp; 45982902Sjake tf->tf_tnpc = tf->tf_tpc + 4; 46085242Sjake tf->tf_sp = (u_long)fp - SPOFF; 46182902Sjake 46283366Sjulian CTR3(KTR_SIG, "sendsig: return td=%p pc=%#lx sp=%#lx", td, tf->tf_tpc, 46382902Sjake tf->tf_sp); 46484178Sjake 46584178Sjake PROC_LOCK(p); 46680708Sjake} 46780708Sjake 46890065Sbde/* 46990065Sbde * Stub to satisfy the reference to osigreturn in the syscall table. This 47090065Sbde * is needed even for newer arches that don't support old signals because 47190065Sbde * the syscall table is machine-independent. 47294606Salc * 47394606Salc * MPSAFE 47490065Sbde */ 47590065Sbdeint 47690065Sbdeosigreturn(struct thread *td, struct osigreturn_args *uap) 47790065Sbde{ 47890065Sbde 47990065Sbde return (nosys(td, (struct nosys_args *)uap)); 48090065Sbde} 48190065Sbde 48280708Sjake#ifndef _SYS_SYSPROTO_H_ 48383088Sobrienstruct sigreturn_args { 48480708Sjake ucontext_t *ucp; 48580708Sjake}; 48680708Sjake#endif 48780708Sjake 48894606Salc/* 48994606Salc * MPSAFE 49094606Salc */ 49180708Sjakeint 49283366Sjuliansigreturn(struct thread *td, struct sigreturn_args *uap) 49380708Sjake{ 49482902Sjake struct trapframe *tf; 49583366Sjulian struct proc *p; 49682902Sjake ucontext_t uc; 49782902Sjake 49883366Sjulian p = td->td_proc; 49983366Sjulian if (rwindow_save(td)) { 50082902Sjake PROC_LOCK(p); 50183366Sjulian sigexit(td, SIGILL); 50282902Sjake } 50382902Sjake 50483366Sjulian CTR2(KTR_SIG, "sigreturn: td=%p ucp=%p", td, uap->sigcntxp); 50582902Sjake if (copyin(uap->sigcntxp, &uc, sizeof(uc)) != 0) { 50683366Sjulian CTR1(KTR_SIG, "sigreturn: efault td=%p", td); 50782902Sjake return (EFAULT); 50882902Sjake } 50982902Sjake 51082902Sjake if (((uc.uc_mcontext.mc_tpc | uc.uc_mcontext.mc_tnpc) & 3) != 0) 51182902Sjake return (EINVAL); 51284178Sjake if (!TSTATE_SECURE(uc.uc_mcontext.mc_tstate)) 51384178Sjake return (EINVAL); 51482902Sjake 51583366Sjulian tf = td->td_frame; 51682902Sjake bcopy(uc.uc_mcontext.mc_global, tf->tf_global, 51782902Sjake sizeof(tf->tf_global)); 51882902Sjake bcopy(uc.uc_mcontext.mc_out, tf->tf_out, sizeof(tf->tf_out)); 51982902Sjake tf->tf_tpc = uc.uc_mcontext.mc_tpc; 52082902Sjake tf->tf_tnpc = uc.uc_mcontext.mc_tnpc; 52182902Sjake tf->tf_tstate = uc.uc_mcontext.mc_tstate; 52282902Sjake PROC_LOCK(p); 52382902Sjake#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 52482902Sjake if (uc.uc_mcontext.mc_onstack & 1) 52582902Sjake p->p_sigstk.ss_flags |= SS_ONSTACK; 52682902Sjake else 52782902Sjake p->p_sigstk.ss_flags &= ~SS_ONSTACK; 52882902Sjake#endif 52982902Sjake 53082902Sjake p->p_sigmask = uc.uc_sigmask; 53182902Sjake SIG_CANTMASK(p->p_sigmask); 53293793Sbde signotify(p); 53382902Sjake PROC_UNLOCK(p); 53483366Sjulian CTR4(KTR_SIG, "sigreturn: return td=%p pc=%#lx sp=%#lx tstate=%#lx", 53583366Sjulian td, tf->tf_tpc, tf->tf_sp, tf->tf_tstate); 53682902Sjake return (EJUSTRETURN); 53780708Sjake} 53880708Sjake 53986147Stmm/* 54092205Sjake * Exit the kernel and execute a firmware call that will not return, as 54192205Sjake * specified by the arguments. 54292205Sjake */ 54392205Sjakevoid 54492205Sjakecpu_shutdown(void *args) 54592205Sjake{ 54692205Sjake 54792205Sjake#ifdef SMP 54892205Sjake cpu_mp_shutdown(); 54992205Sjake#endif 55092205Sjake openfirmware_exit(args); 55192205Sjake} 55292205Sjake 55392205Sjake/* 55486147Stmm * Duplicate OF_exit() with a different firmware call function that restores 55586147Stmm * the trap table, otherwise a RED state exception is triggered in at least 55686147Stmm * some firmware versions. 55786147Stmm */ 55880708Sjakevoid 55980708Sjakecpu_halt(void) 56080708Sjake{ 56186147Stmm static struct { 56286147Stmm cell_t name; 56386147Stmm cell_t nargs; 56486147Stmm cell_t nreturns; 56586147Stmm } args = { 56686147Stmm (cell_t)"exit", 56786147Stmm 0, 56886147Stmm 0 56986147Stmm }; 57084178Sjake 57192205Sjake cpu_shutdown(&args); 57280708Sjake} 57380708Sjake 57486147Stmmvoid 57586147Stmmsparc64_shutdown_final(void *dummy, int howto) 57686147Stmm{ 57786147Stmm static struct { 57886147Stmm cell_t name; 57986147Stmm cell_t nargs; 58086147Stmm cell_t nreturns; 58186147Stmm } args = { 58286147Stmm (cell_t)"SUNW,power-off", 58386147Stmm 0, 58486147Stmm 0 58586147Stmm }; 58686147Stmm 58786147Stmm /* Turn the power off? */ 58886147Stmm if ((howto & RB_POWEROFF) != 0) 58992205Sjake cpu_shutdown(&args); 59086147Stmm /* In case of halt, return to the firmware */ 59186147Stmm if ((howto & RB_HALT) != 0) 59286147Stmm cpu_halt(); 59386147Stmm} 59486147Stmm 59580708Sjakeint 59683366Sjulianptrace_set_pc(struct thread *td, u_long addr) 59780708Sjake{ 59882016Sjake 59983366Sjulian td->td_frame->tf_tpc = addr; 60083366Sjulian td->td_frame->tf_tnpc = addr + 4; 60180708Sjake return (0); 60280708Sjake} 60380708Sjake 60480708Sjakeint 60583366Sjulianptrace_single_step(struct thread *td) 60680708Sjake{ 607104271Sjake /* TODO; */ 60880708Sjake return (0); 60980708Sjake} 61080708Sjake 61180708Sjakevoid 612102561Sjakeexec_setregs(struct thread *td, u_long entry, u_long stack, u_long ps_strings) 61380708Sjake{ 61488639Sjake struct trapframe *tf; 61588782Sjake struct md_utrap *ut; 61681135Stmm struct pcb *pcb; 617102557Sjake struct proc *p; 61884178Sjake u_long sp; 61981135Stmm 62088782Sjake /* XXX no cpu_exec */ 621102557Sjake p = td->td_proc; 622102557Sjake p->p_md.md_sigtramp = NULL; 623102557Sjake if ((ut = p->p_md.md_utrap) != NULL) { 62488782Sjake ut->ut_refcnt--; 62588782Sjake if (ut->ut_refcnt == 0) 62688782Sjake free(ut, M_SUBPROC); 627102557Sjake p->p_md.md_utrap = NULL; 62888782Sjake } 62988782Sjake 63083366Sjulian pcb = td->td_pcb; 63188639Sjake sp = rounddown(stack, 16); 63288639Sjake tf = td->td_frame; 63398032Sjake bzero(pcb, sizeof(*pcb)); 63498032Sjake bzero(tf, sizeof(*tf)); 63588639Sjake tf->tf_out[0] = stack; 63688639Sjake tf->tf_out[3] = PS_STRINGS; 63788639Sjake tf->tf_out[6] = sp - SPOFF - sizeof(struct frame); 63888639Sjake tf->tf_tnpc = entry + 4; 63988639Sjake tf->tf_tpc = entry; 64088639Sjake tf->tf_tstate = TSTATE_IE | TSTATE_PEF | TSTATE_MM_TSO; 64188639Sjake 64288639Sjake td->td_retval[0] = tf->tf_out[0]; 64388639Sjake td->td_retval[1] = tf->tf_out[1]; 64480708Sjake} 64580708Sjake 64680708Sjakevoid 64780708SjakeDebugger(const char *msg) 64880708Sjake{ 64980709Sjake 65080709Sjake printf("Debugger(\"%s\")\n", msg); 65188436Sjake critical_enter(); 65280709Sjake breakpoint(); 65388436Sjake critical_exit(); 65480708Sjake} 65580708Sjake 65680708Sjakeint 65784178Sjakefill_regs(struct thread *td, struct reg *regs) 65880708Sjake{ 65984178Sjake struct trapframe *tf; 66080708Sjake 66184178Sjake tf = td->td_frame; 66294254Sjake regs->r_tstate = tf->tf_tstate; 66394254Sjake regs->r_pc = tf->tf_tpc; 66494254Sjake regs->r_npc = tf->tf_tnpc; 66594254Sjake regs->r_y = tf->tf_y; 66684178Sjake bcopy(tf->tf_global, regs->r_global, sizeof(tf->tf_global)); 66784178Sjake bcopy(tf->tf_out, regs->r_out, sizeof(tf->tf_out)); 66894254Sjake /* XXX - these are a pain to get at */ 66994254Sjake bzero(regs->r_in, sizeof(regs->r_in)); 67094254Sjake bzero(regs->r_local, sizeof(regs->r_local)); 67180708Sjake return (0); 67280708Sjake} 67380708Sjake 67480708Sjakeint 67584178Sjakeset_regs(struct thread *td, struct reg *regs) 67680708Sjake{ 67784178Sjake struct trapframe *tf; 67880708Sjake 67984178Sjake tf = td->td_frame; 68084178Sjake if (((regs->r_pc | regs->r_npc) & 3) != 0) 68184178Sjake return (EINVAL); 68284178Sjake if (!TSTATE_SECURE(regs->r_tstate)) 68384178Sjake return (EINVAL); 68494254Sjake tf->tf_tstate = regs->r_tstate; 68594254Sjake tf->tf_tpc = regs->r_pc; 68694254Sjake tf->tf_tnpc = regs->r_npc; 68794254Sjake tf->tf_y = regs->r_y; 68884178Sjake bcopy(regs->r_global, tf->tf_global, sizeof(regs->r_global)); 68984178Sjake bcopy(regs->r_out, tf->tf_out, sizeof(regs->r_out)); 69080708Sjake return (0); 69180708Sjake} 69280708Sjake 69380708Sjakeint 69485294Sdesfill_dbregs(struct thread *td, struct dbreg *dbregs) 69585294Sdes{ 69685294Sdes 69785294Sdes return (ENOSYS); 69885294Sdes} 69985294Sdes 70085294Sdesint 70185294Sdesset_dbregs(struct thread *td, struct dbreg *dbregs) 70285294Sdes{ 70385294Sdes 70485294Sdes return (ENOSYS); 70585294Sdes} 70685294Sdes 70785294Sdesint 70883366Sjulianfill_fpregs(struct thread *td, struct fpreg *fpregs) 70980708Sjake{ 71088639Sjake struct trapframe *tf; 71184178Sjake struct pcb *pcb; 71284178Sjake 71384178Sjake pcb = td->td_pcb; 71488639Sjake tf = td->td_frame; 71584178Sjake bcopy(pcb->pcb_fpstate.fp_fb, fpregs->fr_regs, 71684178Sjake sizeof(pcb->pcb_fpstate.fp_fb)); 71788639Sjake fpregs->fr_fprs = tf->tf_fprs; 71888639Sjake fpregs->fr_fsr = tf->tf_fsr; 71980708Sjake return (0); 72080708Sjake} 72180708Sjake 72280708Sjakeint 72383366Sjulianset_fpregs(struct thread *td, struct fpreg *fpregs) 72480708Sjake{ 72588639Sjake struct trapframe *tf; 72684178Sjake struct pcb *pcb; 72784178Sjake 72884178Sjake pcb = td->td_pcb; 72988639Sjake tf = td->td_frame; 73084178Sjake bcopy(fpregs->fr_regs, pcb->pcb_fpstate.fp_fb, 73184178Sjake sizeof(fpregs->fr_regs)); 73288639Sjake tf->tf_fprs = fpregs->fr_fprs; 73388639Sjake tf->tf_fsr = fpregs->fr_fsr; 73480708Sjake return (0); 73580708Sjake} 736