machdep.c revision 103081
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 103081 2002-09-07 19:12:53Z jmallett $ 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; 201101898Sjake char type[8]; 20280709Sjake 20386521Sjake end = 0; 20486521Sjake kmdp = NULL; 20586521Sjake 20680709Sjake /* 20780709Sjake * Initialize openfirmware (needed for console). 20880709Sjake */ 20980709Sjake OF_init(vec); 21080709Sjake 21180709Sjake /* 21286521Sjake * Parse metadata if present and fetch parameters. Must be before the 21386521Sjake * console is inited so cninit gets the right value of boothowto. 21486521Sjake */ 21586521Sjake if (mdp != NULL) { 21686521Sjake preload_metadata = mdp; 21786521Sjake kmdp = preload_search_by_type("elf kernel"); 21886521Sjake if (kmdp != NULL) { 21986521Sjake boothowto = MD_FETCH(kmdp, MODINFOMD_HOWTO, int); 22086521Sjake kern_envp = MD_FETCH(kmdp, MODINFOMD_ENVP, char *); 22186521Sjake end = MD_FETCH(kmdp, MODINFOMD_KERNEND, vm_offset_t); 22291616Sjake kernel_tlb_slots = MD_FETCH(kmdp, MODINFOMD_DTLB_SLOTS, 22391616Sjake int); 22497445Sjake kernel_tlbs = (void *)preload_search_info(kmdp, 22591616Sjake MODINFO_METADATA | MODINFOMD_DTLB); 22686521Sjake } 22786521Sjake } 22886521Sjake 22986521Sjake /* 23080709Sjake * Initialize the console before printing anything. 23180709Sjake */ 23288639Sjake cninit(); 23380709Sjake 23480709Sjake /* 23586521Sjake * Panic is there is no metadata. Most likely the kernel was booted 23686521Sjake * directly, instead of through loader(8). 23780709Sjake */ 23886521Sjake if (mdp == NULL || kmdp == NULL) { 23986521Sjake printf("sparc64_init: no loader metadata.\n" 24086521Sjake "This probably means you are not using loader(8).\n"); 24186521Sjake panic("sparc64_init"); 24286521Sjake } 24380709Sjake 24481383Sjake /* 24586521Sjake * Sanity check the kernel end, which is important. 24686521Sjake */ 24786521Sjake if (end == 0) { 24886521Sjake printf("sparc64_init: warning, kernel end not specified.\n" 24986521Sjake "Attempting to continue anyway.\n"); 25086521Sjake end = (vm_offset_t)_end; 25186521Sjake } 25286521Sjake 253101898Sjake root = OF_peer(0); 254101898Sjake for (child = OF_child(root); child != 0; child = OF_peer(child)) { 255101898Sjake OF_getprop(child, "device_type", type, sizeof(type)); 256101898Sjake if (strcmp(type, "cpu") == 0) 257101898Sjake break; 258101898Sjake } 259101898Sjake if (child == 0) 260101898Sjake panic("cpu_startup: no cpu\n"); 261101898Sjake OF_getprop(child, "#dtlb-entries", &tlb_dtlb_entries, 262101898Sjake sizeof(tlb_dtlb_entries)); 263101898Sjake OF_getprop(child, "#itlb-entries", &tlb_itlb_entries, 264101898Sjake sizeof(tlb_itlb_entries)); 265101898Sjake 266101898Sjake cache_init(child); 267101898Sjake 26890625Stmm#ifdef DDB 26990625Stmm kdb_init(); 27090625Stmm#endif 27190625Stmm 27291616Sjake#ifdef SMP 27391616Sjake mp_tramp = mp_tramp_alloc(); 27491616Sjake#endif 27591616Sjake 27686521Sjake /* 27790625Stmm * Initialize virtual memory and calculate physmem. 27887546Sdillon */ 27990625Stmm pmap_bootstrap(end); 28087546Sdillon 28187546Sdillon /* 28281383Sjake * Initialize tunables. 28381383Sjake */ 28487546Sdillon init_param1(); 28587546Sdillon init_param2(physmem); 28681085Sjake 28780709Sjake /* 28881383Sjake * Disable tick for now. 28980709Sjake */ 29081383Sjake tick_stop(); 29180709Sjake 29289038Sjake /* 29389038Sjake * Initialize the interrupt tables. 29489038Sjake */ 29590624Stmm intr_init1(); 29680709Sjake 29780709Sjake /* 29880709Sjake * Initialize proc0 stuff (p_contested needs to be done early). 29980709Sjake */ 30090361Sjulian proc_linkup(&proc0, &proc0.p_ksegrp, &proc0.p_kse, &thread0); 30195744Sjake proc0.p_md.md_sigtramp = NULL; 30288822Stmm proc0.p_md.md_utrap = NULL; 30389038Sjake proc0.p_uarea = (struct user *)uarea0; 30483366Sjulian proc0.p_stats = &proc0.p_uarea->u_stats; 30590361Sjulian thread0.td_kstack = kstack0; 30690361Sjulian thread0.td_pcb = (struct pcb *) 30790361Sjulian (thread0.td_kstack + KSTACK_PAGES * PAGE_SIZE) - 1; 30888639Sjake frame0.tf_tstate = TSTATE_IE | TSTATE_PEF; 30990361Sjulian thread0.td_frame = &frame0; 31080709Sjake 31180709Sjake /* 31289038Sjake * Prime our per-cpu data page for use. Note, we are using it for our 31389038Sjake * stack, so don't pass the real size (PAGE_SIZE) to pcpu_init or 31489038Sjake * it'll zero it out from under us. 31580709Sjake */ 31691360Sjake pc = (struct pcpu *)(pcpu0 + (PCPU_PAGES * PAGE_SIZE)) - 1; 31789038Sjake pcpu_init(pc, 0, sizeof(struct pcpu)); 31890361Sjulian pc->pc_curthread = &thread0; 31991156Sjake pc->pc_curpcb = thread0.td_pcb; 32091616Sjake pc->pc_mid = UPA_CR_GET_MID(ldxa(0, ASI_UPA_CONFIG_REG)); 32191616Sjake pc->pc_addr = (vm_offset_t)pcpu0; 322101898Sjake pc->pc_node = child; 32391613Sjake pc->pc_tlb_ctx = TLB_CTX_USER_MIN; 32491613Sjake pc->pc_tlb_ctx_min = TLB_CTX_USER_MIN; 32591613Sjake pc->pc_tlb_ctx_max = TLB_CTX_USER_MAX; 32688639Sjake 32780709Sjake /* 32889038Sjake * Initialize global registers. 32981383Sjake */ 33089038Sjake cpu_setregs(pc); 33188639Sjake 33288639Sjake /* 33388822Stmm * Map and initialize the message buffer (after setting trap table). 33488822Stmm */ 33597871Sjake va = (vm_offset_t)msgbufp; 33697871Sjake pmap_map(&va, msgbuf_phys, msgbuf_phys + MSGBUF_SIZE, 0); 33788822Stmm msgbufinit(msgbufp, MSGBUF_SIZE); 33888822Stmm 33993702Sjhb mutex_init(); 34090624Stmm intr_init2(); 34180708Sjake} 34280708Sjake 34380708Sjakevoid 34480709Sjakeset_openfirm_callback(ofw_vec_t *vec) 34580709Sjake{ 34680709Sjake ofw_tba = rdpr(tba); 34780709Sjake ofw_vec = (u_long)vec; 34880709Sjake} 34980709Sjake 35080709Sjakevoid 35180708Sjakesendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) 35280708Sjake{ 35382902Sjake struct trapframe *tf; 35482902Sjake struct sigframe *sfp; 35582902Sjake struct sigacts *psp; 35682902Sjake struct sigframe sf; 35783366Sjulian struct thread *td; 35885242Sjake struct frame *fp; 35982902Sjake struct proc *p; 36085242Sjake int oonstack; 36182902Sjake u_long sp; 36282902Sjake 36382902Sjake oonstack = 0; 36483366Sjulian td = curthread; 36583366Sjulian p = td->td_proc; 36682902Sjake psp = p->p_sigacts; 36783366Sjulian tf = td->td_frame; 36882902Sjake sp = tf->tf_sp + SPOFF; 36982902Sjake oonstack = sigonstack(sp); 37082902Sjake 37183366Sjulian CTR4(KTR_SIG, "sendsig: td=%p (%s) catcher=%p sig=%d", td, p->p_comm, 37282902Sjake catcher, sig); 37382902Sjake 374102554Sjake /* Make sure we have a signal trampoline to return to. */ 375102554Sjake if (p->p_md.md_sigtramp == NULL) { 376102554Sjake /* 377102554Sjake * No signal tramoline... kill the process. 378102554Sjake */ 379102554Sjake CTR0(KTR_SIG, "sendsig: no sigtramp"); 380102873Sjake printf("sendsig: %s is too old, rebuild it\n", p->p_comm); 381102554Sjake sigexit(td, sig); 382102554Sjake /* NOTREACHED */ 383102554Sjake } 384102554Sjake 38582902Sjake /* Save user context. */ 38682902Sjake bzero(&sf, sizeof(sf)); 38782902Sjake sf.sf_uc.uc_sigmask = *mask; 38882902Sjake sf.sf_uc.uc_stack = p->p_sigstk; 38982902Sjake sf.sf_uc.uc_stack.ss_flags = (p->p_flag & P_ALTSTACK) 39082902Sjake ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE; 39182902Sjake sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0; 39282902Sjake bcopy(tf->tf_global, sf.sf_uc.uc_mcontext.mc_global, 39382902Sjake sizeof (tf->tf_global)); 39482902Sjake bcopy(tf->tf_out, sf.sf_uc.uc_mcontext.mc_out, sizeof (tf->tf_out)); 39582902Sjake sf.sf_uc.uc_mcontext.mc_tpc = tf->tf_tpc; 39682902Sjake sf.sf_uc.uc_mcontext.mc_tnpc = tf->tf_tnpc; 39782902Sjake sf.sf_uc.uc_mcontext.mc_tstate = tf->tf_tstate; 39882902Sjake 39982902Sjake /* Allocate and validate space for the signal handler context. */ 40082902Sjake if ((p->p_flag & P_ALTSTACK) != 0 && !oonstack && 40182902Sjake SIGISMEMBER(psp->ps_sigonstack, sig)) { 40282902Sjake sfp = (struct sigframe *)(p->p_sigstk.ss_sp + 40382902Sjake p->p_sigstk.ss_size - sizeof(struct sigframe)); 40482902Sjake#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 40582902Sjake p->p_sigstk.ss_flags |= SS_ONSTACK; 40682902Sjake#endif 40782902Sjake } else 40882902Sjake sfp = (struct sigframe *)sp - 1; 40982902Sjake PROC_UNLOCK(p); 41082902Sjake 41185242Sjake fp = (struct frame *)sfp - 1; 41282902Sjake 41382902Sjake /* Translate the signal if appropriate. */ 41482902Sjake if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize) 41582902Sjake sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)]; 41682902Sjake 41782902Sjake /* Build the argument list for the signal handler. */ 41882902Sjake tf->tf_out[0] = sig; 41982902Sjake tf->tf_out[2] = (register_t)&sfp->sf_uc; 42082902Sjake tf->tf_out[3] = tf->tf_type; 42182902Sjake tf->tf_out[4] = (register_t)catcher; 42282902Sjake PROC_LOCK(p); 42382902Sjake if (SIGISMEMBER(p->p_sigacts->ps_siginfo, sig)) { 42482902Sjake /* Signal handler installed with SA_SIGINFO. */ 42582902Sjake tf->tf_out[1] = (register_t)&sfp->sf_si; 42682902Sjake 42782902Sjake /* Fill siginfo structure. */ 42882902Sjake sf.sf_si.si_signo = sig; 42982902Sjake sf.sf_si.si_code = code; 43088639Sjake sf.sf_si.si_addr = (void *)tf->tf_sfar; 431103081Sjmallett sf.sf_si.si_pid = p->p_pid; 432103081Sjmallett sf.sf_si.si_uid = p->p_ucred->cr_uid; 43382902Sjake } else { 43482902Sjake /* Old FreeBSD-style arguments. */ 43582902Sjake tf->tf_out[1] = code; 43682902Sjake } 43782902Sjake PROC_UNLOCK(p); 43882902Sjake 43982902Sjake /* Copy the sigframe out to the user's stack. */ 44085242Sjake if (rwindow_save(td) != 0 || copyout(&sf, sfp, sizeof(*sfp)) != 0 || 44194254Sjake suword(&fp->fr_in[6], tf->tf_out[6]) != 0) { 44282902Sjake /* 44382902Sjake * Something is wrong with the stack pointer. 44482902Sjake * ...Kill the process. 44582902Sjake */ 44683366Sjulian CTR2(KTR_SIG, "sendsig: sigexit td=%p sfp=%p", td, sfp); 44782902Sjake PROC_LOCK(p); 44883366Sjulian sigexit(td, SIGILL); 44982902Sjake /* NOTREACHED */ 45082902Sjake } 45182902Sjake 452102554Sjake tf->tf_tpc = (u_long)p->p_md.md_sigtramp; 45382902Sjake tf->tf_tnpc = tf->tf_tpc + 4; 45485242Sjake tf->tf_sp = (u_long)fp - SPOFF; 45582902Sjake 45683366Sjulian CTR3(KTR_SIG, "sendsig: return td=%p pc=%#lx sp=%#lx", td, tf->tf_tpc, 45782902Sjake tf->tf_sp); 45884178Sjake 45984178Sjake PROC_LOCK(p); 46080708Sjake} 46180708Sjake 46290065Sbde/* 46390065Sbde * Stub to satisfy the reference to osigreturn in the syscall table. This 46490065Sbde * is needed even for newer arches that don't support old signals because 46590065Sbde * the syscall table is machine-independent. 46694606Salc * 46794606Salc * MPSAFE 46890065Sbde */ 46990065Sbdeint 47090065Sbdeosigreturn(struct thread *td, struct osigreturn_args *uap) 47190065Sbde{ 47290065Sbde 47390065Sbde return (nosys(td, (struct nosys_args *)uap)); 47490065Sbde} 47590065Sbde 47680708Sjake#ifndef _SYS_SYSPROTO_H_ 47783088Sobrienstruct sigreturn_args { 47880708Sjake ucontext_t *ucp; 47980708Sjake}; 48080708Sjake#endif 48180708Sjake 48294606Salc/* 48394606Salc * MPSAFE 48494606Salc */ 48580708Sjakeint 48683366Sjuliansigreturn(struct thread *td, struct sigreturn_args *uap) 48780708Sjake{ 48882902Sjake struct trapframe *tf; 48983366Sjulian struct proc *p; 49082902Sjake ucontext_t uc; 49182902Sjake 49283366Sjulian p = td->td_proc; 49383366Sjulian if (rwindow_save(td)) { 49482902Sjake PROC_LOCK(p); 49583366Sjulian sigexit(td, SIGILL); 49682902Sjake } 49782902Sjake 49883366Sjulian CTR2(KTR_SIG, "sigreturn: td=%p ucp=%p", td, uap->sigcntxp); 49982902Sjake if (copyin(uap->sigcntxp, &uc, sizeof(uc)) != 0) { 50083366Sjulian CTR1(KTR_SIG, "sigreturn: efault td=%p", td); 50182902Sjake return (EFAULT); 50282902Sjake } 50382902Sjake 50482902Sjake if (((uc.uc_mcontext.mc_tpc | uc.uc_mcontext.mc_tnpc) & 3) != 0) 50582902Sjake return (EINVAL); 50684178Sjake if (!TSTATE_SECURE(uc.uc_mcontext.mc_tstate)) 50784178Sjake return (EINVAL); 50882902Sjake 50983366Sjulian tf = td->td_frame; 51082902Sjake bcopy(uc.uc_mcontext.mc_global, tf->tf_global, 51182902Sjake sizeof(tf->tf_global)); 51282902Sjake bcopy(uc.uc_mcontext.mc_out, tf->tf_out, sizeof(tf->tf_out)); 51382902Sjake tf->tf_tpc = uc.uc_mcontext.mc_tpc; 51482902Sjake tf->tf_tnpc = uc.uc_mcontext.mc_tnpc; 51582902Sjake tf->tf_tstate = uc.uc_mcontext.mc_tstate; 51682902Sjake PROC_LOCK(p); 51782902Sjake#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 51882902Sjake if (uc.uc_mcontext.mc_onstack & 1) 51982902Sjake p->p_sigstk.ss_flags |= SS_ONSTACK; 52082902Sjake else 52182902Sjake p->p_sigstk.ss_flags &= ~SS_ONSTACK; 52282902Sjake#endif 52382902Sjake 52482902Sjake p->p_sigmask = uc.uc_sigmask; 52582902Sjake SIG_CANTMASK(p->p_sigmask); 52693793Sbde signotify(p); 52782902Sjake PROC_UNLOCK(p); 52883366Sjulian CTR4(KTR_SIG, "sigreturn: return td=%p pc=%#lx sp=%#lx tstate=%#lx", 52983366Sjulian td, tf->tf_tpc, tf->tf_sp, tf->tf_tstate); 53082902Sjake return (EJUSTRETURN); 53180708Sjake} 53280708Sjake 53386147Stmm/* 53492205Sjake * Exit the kernel and execute a firmware call that will not return, as 53592205Sjake * specified by the arguments. 53692205Sjake */ 53792205Sjakevoid 53892205Sjakecpu_shutdown(void *args) 53992205Sjake{ 54092205Sjake 54192205Sjake#ifdef SMP 54292205Sjake cpu_mp_shutdown(); 54392205Sjake#endif 54492205Sjake openfirmware_exit(args); 54592205Sjake} 54692205Sjake 54792205Sjake/* 54886147Stmm * Duplicate OF_exit() with a different firmware call function that restores 54986147Stmm * the trap table, otherwise a RED state exception is triggered in at least 55086147Stmm * some firmware versions. 55186147Stmm */ 55280708Sjakevoid 55380708Sjakecpu_halt(void) 55480708Sjake{ 55586147Stmm static struct { 55686147Stmm cell_t name; 55786147Stmm cell_t nargs; 55886147Stmm cell_t nreturns; 55986147Stmm } args = { 56086147Stmm (cell_t)"exit", 56186147Stmm 0, 56286147Stmm 0 56386147Stmm }; 56484178Sjake 56592205Sjake cpu_shutdown(&args); 56680708Sjake} 56780708Sjake 56886147Stmmvoid 56986147Stmmsparc64_shutdown_final(void *dummy, int howto) 57086147Stmm{ 57186147Stmm static struct { 57286147Stmm cell_t name; 57386147Stmm cell_t nargs; 57486147Stmm cell_t nreturns; 57586147Stmm } args = { 57686147Stmm (cell_t)"SUNW,power-off", 57786147Stmm 0, 57886147Stmm 0 57986147Stmm }; 58086147Stmm 58186147Stmm /* Turn the power off? */ 58286147Stmm if ((howto & RB_POWEROFF) != 0) 58392205Sjake cpu_shutdown(&args); 58486147Stmm /* In case of halt, return to the firmware */ 58586147Stmm if ((howto & RB_HALT) != 0) 58686147Stmm cpu_halt(); 58786147Stmm} 58886147Stmm 58980708Sjakeint 59083366Sjulianptrace_set_pc(struct thread *td, u_long addr) 59180708Sjake{ 59282016Sjake 59383366Sjulian td->td_frame->tf_tpc = addr; 59483366Sjulian td->td_frame->tf_tnpc = addr + 4; 59580708Sjake return (0); 59680708Sjake} 59780708Sjake 59880708Sjakeint 59983366Sjulianptrace_single_step(struct thread *td) 60080708Sjake{ 60180708Sjake TODO; 60280708Sjake return (0); 60380708Sjake} 60480708Sjake 60580708Sjakevoid 606102561Sjakeexec_setregs(struct thread *td, u_long entry, u_long stack, u_long ps_strings) 60780708Sjake{ 60888639Sjake struct trapframe *tf; 60988782Sjake struct md_utrap *ut; 61081135Stmm struct pcb *pcb; 611102557Sjake struct proc *p; 61284178Sjake u_long sp; 61381135Stmm 61488782Sjake /* XXX no cpu_exec */ 615102557Sjake p = td->td_proc; 616102557Sjake p->p_md.md_sigtramp = NULL; 617102557Sjake if ((ut = p->p_md.md_utrap) != NULL) { 61888782Sjake ut->ut_refcnt--; 61988782Sjake if (ut->ut_refcnt == 0) 62088782Sjake free(ut, M_SUBPROC); 621102557Sjake p->p_md.md_utrap = NULL; 62288782Sjake } 62388782Sjake 62483366Sjulian pcb = td->td_pcb; 62588639Sjake sp = rounddown(stack, 16); 62688639Sjake tf = td->td_frame; 62798032Sjake bzero(pcb, sizeof(*pcb)); 62898032Sjake bzero(tf, sizeof(*tf)); 62988639Sjake tf->tf_out[0] = stack; 63088639Sjake tf->tf_out[3] = PS_STRINGS; 63188639Sjake tf->tf_out[6] = sp - SPOFF - sizeof(struct frame); 63288639Sjake tf->tf_tnpc = entry + 4; 63388639Sjake tf->tf_tpc = entry; 63488639Sjake tf->tf_tstate = TSTATE_IE | TSTATE_PEF | TSTATE_MM_TSO; 63588639Sjake 63688639Sjake td->td_retval[0] = tf->tf_out[0]; 63788639Sjake td->td_retval[1] = tf->tf_out[1]; 63880708Sjake} 63980708Sjake 64080708Sjakevoid 64180708SjakeDebugger(const char *msg) 64280708Sjake{ 64380709Sjake 64480709Sjake printf("Debugger(\"%s\")\n", msg); 64588436Sjake critical_enter(); 64680709Sjake breakpoint(); 64788436Sjake critical_exit(); 64880708Sjake} 64980708Sjake 65080708Sjakeint 65184178Sjakefill_regs(struct thread *td, struct reg *regs) 65280708Sjake{ 65384178Sjake struct trapframe *tf; 65480708Sjake 65584178Sjake tf = td->td_frame; 65694254Sjake regs->r_tstate = tf->tf_tstate; 65794254Sjake regs->r_pc = tf->tf_tpc; 65894254Sjake regs->r_npc = tf->tf_tnpc; 65994254Sjake regs->r_y = tf->tf_y; 66084178Sjake bcopy(tf->tf_global, regs->r_global, sizeof(tf->tf_global)); 66184178Sjake bcopy(tf->tf_out, regs->r_out, sizeof(tf->tf_out)); 66294254Sjake /* XXX - these are a pain to get at */ 66394254Sjake bzero(regs->r_in, sizeof(regs->r_in)); 66494254Sjake bzero(regs->r_local, sizeof(regs->r_local)); 66580708Sjake return (0); 66680708Sjake} 66780708Sjake 66880708Sjakeint 66984178Sjakeset_regs(struct thread *td, struct reg *regs) 67080708Sjake{ 67184178Sjake struct trapframe *tf; 67280708Sjake 67384178Sjake tf = td->td_frame; 67484178Sjake if (((regs->r_pc | regs->r_npc) & 3) != 0) 67584178Sjake return (EINVAL); 67684178Sjake if (!TSTATE_SECURE(regs->r_tstate)) 67784178Sjake return (EINVAL); 67894254Sjake tf->tf_tstate = regs->r_tstate; 67994254Sjake tf->tf_tpc = regs->r_pc; 68094254Sjake tf->tf_tnpc = regs->r_npc; 68194254Sjake tf->tf_y = regs->r_y; 68284178Sjake bcopy(regs->r_global, tf->tf_global, sizeof(regs->r_global)); 68384178Sjake bcopy(regs->r_out, tf->tf_out, sizeof(regs->r_out)); 68480708Sjake return (0); 68580708Sjake} 68680708Sjake 68780708Sjakeint 68885294Sdesfill_dbregs(struct thread *td, struct dbreg *dbregs) 68985294Sdes{ 69085294Sdes 69185294Sdes return (ENOSYS); 69285294Sdes} 69385294Sdes 69485294Sdesint 69585294Sdesset_dbregs(struct thread *td, struct dbreg *dbregs) 69685294Sdes{ 69785294Sdes 69885294Sdes return (ENOSYS); 69985294Sdes} 70085294Sdes 70185294Sdesint 70283366Sjulianfill_fpregs(struct thread *td, struct fpreg *fpregs) 70380708Sjake{ 70488639Sjake struct trapframe *tf; 70584178Sjake struct pcb *pcb; 70684178Sjake 70784178Sjake pcb = td->td_pcb; 70888639Sjake tf = td->td_frame; 70984178Sjake bcopy(pcb->pcb_fpstate.fp_fb, fpregs->fr_regs, 71084178Sjake sizeof(pcb->pcb_fpstate.fp_fb)); 71188639Sjake fpregs->fr_fprs = tf->tf_fprs; 71288639Sjake fpregs->fr_fsr = tf->tf_fsr; 71380708Sjake return (0); 71480708Sjake} 71580708Sjake 71680708Sjakeint 71783366Sjulianset_fpregs(struct thread *td, struct fpreg *fpregs) 71880708Sjake{ 71988639Sjake struct trapframe *tf; 72084178Sjake struct pcb *pcb; 72184178Sjake 72284178Sjake pcb = td->td_pcb; 72388639Sjake tf = td->td_frame; 72484178Sjake bcopy(fpregs->fr_regs, pcb->pcb_fpstate.fp_fb, 72584178Sjake sizeof(fpregs->fr_regs)); 72688639Sjake tf->tf_fprs = fpregs->fr_fprs; 72788639Sjake tf->tf_fsr = fpregs->fr_fsr; 72880708Sjake return (0); 72980708Sjake} 730