machdep.c revision 113023
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 113023 2003-04-03 18:28:03Z jake $ 4180708Sjake */ 4280708Sjake 43105950Speter#include "opt_compat.h" 4480709Sjake#include "opt_ddb.h" 4585242Sjake#include "opt_msgbuf.h" 4680709Sjake 4780708Sjake#include <sys/param.h> 4880708Sjake#include <sys/systm.h> 4980709Sjake#include <sys/cons.h> 50102561Sjake#include <sys/imgact.h> 5180709Sjake#include <sys/kernel.h> 5285262Sjake#include <sys/ktr.h> 5380709Sjake#include <sys/linker.h> 5480709Sjake#include <sys/lock.h> 5588782Sjake#include <sys/malloc.h> 5685242Sjake#include <sys/msgbuf.h> 5780708Sjake#include <sys/mutex.h> 5880709Sjake#include <sys/pcpu.h> 5980708Sjake#include <sys/proc.h> 6085242Sjake#include <sys/reboot.h> 6180709Sjake#include <sys/bio.h> 6280709Sjake#include <sys/buf.h> 6384849Stmm#include <sys/bus.h> 6486147Stmm#include <sys/eventhandler.h> 6584849Stmm#include <sys/interrupt.h> 6680708Sjake#include <sys/ptrace.h> 6780708Sjake#include <sys/signalvar.h> 6891616Sjake#include <sys/smp.h> 6982902Sjake#include <sys/sysent.h> 7080708Sjake#include <sys/sysproto.h> 7180709Sjake#include <sys/timetc.h> 7291783Sjake#include <sys/user.h> 7391156Sjake#include <sys/ucontext.h> 7480709Sjake#include <sys/user.h> 7591616Sjake#include <sys/ucontext.h> 7682902Sjake#include <sys/exec.h> 7780708Sjake 7880708Sjake#include <dev/ofw/openfirm.h> 7980708Sjake 8080709Sjake#include <vm/vm.h> 8180709Sjake#include <vm/vm_param.h> 8280709Sjake#include <vm/vm_kern.h> 8380709Sjake#include <vm/vm_object.h> 8480709Sjake#include <vm/vm_page.h> 8580709Sjake#include <vm/vm_map.h> 8680709Sjake#include <vm/vm_pager.h> 8780709Sjake#include <vm/vm_extern.h> 8880709Sjake 8980709Sjake#include <ddb/ddb.h> 9080709Sjake 9186521Sjake#include <machine/cache.h> 9281383Sjake#include <machine/clock.h> 9382902Sjake#include <machine/cpu.h> 9483366Sjulian#include <machine/fp.h> 95112922Sjake#include <machine/fsr.h> 9681383Sjake#include <machine/intr_machdep.h> 9780708Sjake#include <machine/md_var.h> 9888436Sjake#include <machine/metadata.h> 9986147Stmm#include <machine/ofw_machdep.h> 10091783Sjake#include <machine/smp.h> 10180709Sjake#include <machine/pmap.h> 10280709Sjake#include <machine/pstate.h> 10380708Sjake#include <machine/reg.h> 10482902Sjake#include <machine/sigframe.h> 10581383Sjake#include <machine/tick.h> 10691613Sjake#include <machine/tlb.h> 10782016Sjake#include <machine/tstate.h> 10891616Sjake#include <machine/upa.h> 10982902Sjake#include <machine/ver.h> 11080708Sjake 11180709Sjaketypedef int ofw_vec_t(void *); 11280708Sjake 11397445Sjakestruct tlb_entry *kernel_tlbs; 11491616Sjakeint kernel_tlb_slots; 11591616Sjake 11680708Sjakeint cold = 1; 117102600Speterlong Maxmem; 11880708Sjake 11991360Sjakechar pcpu0[PCPU_PAGES * PAGE_SIZE]; 12089038Sjakechar uarea0[UAREA_PAGES * PAGE_SIZE]; 12189038Sjakestruct trapframe frame0; 12280708Sjake 12389038Sjakevm_offset_t kstack0; 12489038Sjakevm_offset_t kstack0_phys; 12588781Sjake 12682902Sjakestruct kva_md_info kmi; 12780709Sjake 12880709Sjakeu_long ofw_vec; 12980709Sjakeu_long ofw_tba; 13080709Sjake 13180709Sjakestatic struct timecounter tick_tc; 13280709Sjake 133106555Stmmchar sparc64_model[32]; 134106555Stmm 13580709Sjakestatic timecounter_get_t tick_get_timecount; 13691616Sjakevoid sparc64_init(caddr_t mdp, u_long o1, u_long o2, u_long o3, 13789038Sjake ofw_vec_t *vec); 13886147Stmmvoid sparc64_shutdown_final(void *dummy, int howto); 13980709Sjake 14080709Sjakestatic void cpu_startup(void *); 14180709SjakeSYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL); 14280709Sjake 14391336SjakeCTASSERT((1 << INT_SHIFT) == sizeof(int)); 14491336SjakeCTASSERT((1 << PTR_SHIFT) == sizeof(char *)); 14591336Sjake 146105733SjakeCTASSERT(sizeof(struct reg) == 256); 147105733SjakeCTASSERT(sizeof(struct fpreg) == 272); 148105733SjakeCTASSERT(sizeof(struct __mcontext) == 512); 149105733Sjake 150113023SjakeCTASSERT((sizeof(struct pcb) & (64 - 1)) == 0); 151113023SjakeCTASSERT((offsetof(struct pcb, pcb_kfp) & (64 - 1)) == 0); 152113023SjakeCTASSERT((offsetof(struct pcb, pcb_ufp) & (64 - 1)) == 0); 153113023SjakeCTASSERT(sizeof(struct pcb) <= ((KSTACK_PAGES * PAGE_SIZE) / 8)); 154113023Sjake 15591360SjakeCTASSERT(sizeof(struct pcpu) <= ((PCPU_PAGES * PAGE_SIZE) / 2)); 15689038Sjake 15780709Sjakestatic void 15880709Sjakecpu_startup(void *arg) 15980709Sjake{ 16080709Sjake 16180709Sjake tick_tc.tc_get_timecount = tick_get_timecount; 16280709Sjake tick_tc.tc_poll_pps = NULL; 16380709Sjake tick_tc.tc_counter_mask = ~0u; 164105946Stmm tick_tc.tc_frequency = tick_freq; 16580709Sjake tick_tc.tc_name = "tick"; 16680709Sjake tc_init(&tick_tc); 16780709Sjake 168105946Stmm cpu_identify(rdpr(ver), tick_freq, PCPU_GET(cpuid)); 169106555Stmm printf("Model: %s\n", sparc64_model); 17080709Sjake 17182902Sjake vm_ksubmap_init(&kmi); 17280709Sjake 17380709Sjake bufinit(); 17480709Sjake vm_pager_bufferinit(); 17580709Sjake 17686147Stmm EVENTHANDLER_REGISTER(shutdown_final, sparc64_shutdown_final, NULL, 17786147Stmm SHUTDOWN_PRI_LAST); 17880709Sjake} 17980709Sjake 18087702Sjhbvoid 18187702Sjhbcpu_pcpu_init(struct pcpu *pcpu, int cpuid, size_t size) 18287702Sjhb{ 18397265Sjake struct intr_request *ir; 18497265Sjake int i; 18597265Sjake 18697265Sjake pcpu->pc_irtail = &pcpu->pc_irhead; 18797265Sjake for (i = 0; i < IR_FREE; i++) { 18897265Sjake ir = &pcpu->pc_irpool[i]; 18997265Sjake ir->ir_next = pcpu->pc_irfree; 19097265Sjake pcpu->pc_irfree = ir; 19197265Sjake } 19287702Sjhb} 19387702Sjhb 19480709Sjakeunsigned 19580709Sjaketick_get_timecount(struct timecounter *tc) 19680709Sjake{ 19780709Sjake return ((unsigned)rd(tick)); 19880709Sjake} 19980709Sjake 20080708Sjakevoid 20191616Sjakesparc64_init(caddr_t mdp, u_long o1, u_long o2, u_long o3, ofw_vec_t *vec) 20280708Sjake{ 203101898Sjake phandle_t child; 204101898Sjake phandle_t root; 20589038Sjake struct pcpu *pc; 20686521Sjake vm_offset_t end; 20786521Sjake caddr_t kmdp; 208105946Stmm u_int clock; 209105569Smux char *env; 210101898Sjake char type[8]; 21180709Sjake 21286521Sjake end = 0; 21386521Sjake kmdp = NULL; 21486521Sjake 21580709Sjake /* 216112398Sjake * Find out what kind of cpu we have first, for anything that changes 217112398Sjake * behaviour. 218112398Sjake */ 219112398Sjake cpu_impl = VER_IMPL(rdpr(ver)); 220112398Sjake 221112398Sjake /* 22280709Sjake * Initialize openfirmware (needed for console). 22380709Sjake */ 22480709Sjake OF_init(vec); 22580709Sjake 22680709Sjake /* 22786521Sjake * Parse metadata if present and fetch parameters. Must be before the 22886521Sjake * console is inited so cninit gets the right value of boothowto. 22986521Sjake */ 23086521Sjake if (mdp != NULL) { 23186521Sjake preload_metadata = mdp; 23286521Sjake kmdp = preload_search_by_type("elf kernel"); 23386521Sjake if (kmdp != NULL) { 23486521Sjake boothowto = MD_FETCH(kmdp, MODINFOMD_HOWTO, int); 23586521Sjake kern_envp = MD_FETCH(kmdp, MODINFOMD_ENVP, char *); 23686521Sjake end = MD_FETCH(kmdp, MODINFOMD_KERNEND, vm_offset_t); 23791616Sjake kernel_tlb_slots = MD_FETCH(kmdp, MODINFOMD_DTLB_SLOTS, 23891616Sjake int); 23997445Sjake kernel_tlbs = (void *)preload_search_info(kmdp, 24091616Sjake MODINFO_METADATA | MODINFOMD_DTLB); 24186521Sjake } 24286521Sjake } 24386521Sjake 24486521Sjake /* 24580709Sjake * Initialize the console before printing anything. 24680709Sjake */ 24788639Sjake cninit(); 24880709Sjake 24980709Sjake /* 25086521Sjake * Panic is there is no metadata. Most likely the kernel was booted 25186521Sjake * directly, instead of through loader(8). 25280709Sjake */ 25386521Sjake if (mdp == NULL || kmdp == NULL) { 25486521Sjake printf("sparc64_init: no loader metadata.\n" 25586521Sjake "This probably means you are not using loader(8).\n"); 25686521Sjake panic("sparc64_init"); 25786521Sjake } 25880709Sjake 25981383Sjake /* 26086521Sjake * Sanity check the kernel end, which is important. 26186521Sjake */ 26286521Sjake if (end == 0) { 26386521Sjake printf("sparc64_init: warning, kernel end not specified.\n" 26486521Sjake "Attempting to continue anyway.\n"); 26586521Sjake end = (vm_offset_t)_end; 26686521Sjake } 26786521Sjake 268101898Sjake root = OF_peer(0); 269101898Sjake for (child = OF_child(root); child != 0; child = OF_peer(child)) { 270101898Sjake OF_getprop(child, "device_type", type, sizeof(type)); 271101898Sjake if (strcmp(type, "cpu") == 0) 272101898Sjake break; 273101898Sjake } 274101898Sjake if (child == 0) 275101898Sjake panic("cpu_startup: no cpu\n"); 276101898Sjake OF_getprop(child, "#dtlb-entries", &tlb_dtlb_entries, 277101898Sjake sizeof(tlb_dtlb_entries)); 278101898Sjake OF_getprop(child, "#itlb-entries", &tlb_itlb_entries, 279101898Sjake sizeof(tlb_itlb_entries)); 280101898Sjake 281101898Sjake cache_init(child); 282101898Sjake 28390625Stmm#ifdef DDB 28490625Stmm kdb_init(); 28590625Stmm#endif 28690625Stmm 28791616Sjake#ifdef SMP 28891616Sjake mp_tramp = mp_tramp_alloc(); 28991616Sjake#endif 29091616Sjake 29186521Sjake /* 29290625Stmm * Initialize virtual memory and calculate physmem. 29387546Sdillon */ 29490625Stmm pmap_bootstrap(end); 29587546Sdillon 29687546Sdillon /* 29781383Sjake * Initialize tunables. 29881383Sjake */ 29987546Sdillon init_param1(); 30087546Sdillon init_param2(physmem); 301105569Smux env = getenv("kernelname"); 302105569Smux if (env != NULL) { 303105569Smux strlcpy(kernelname, env, sizeof(kernelname)); 304105569Smux freeenv(env); 305105569Smux } 30681085Sjake 30780709Sjake /* 30881383Sjake * Disable tick for now. 30980709Sjake */ 31081383Sjake tick_stop(); 31180709Sjake 31289038Sjake /* 31389038Sjake * Initialize the interrupt tables. 31489038Sjake */ 31590624Stmm intr_init1(); 31680709Sjake 31780709Sjake /* 31880709Sjake * Initialize proc0 stuff (p_contested needs to be done early). 31980709Sjake */ 320103367Sjulian proc_linkup(&proc0, &ksegrp0, &kse0, &thread0); 32195744Sjake proc0.p_md.md_sigtramp = NULL; 32288822Stmm proc0.p_md.md_utrap = NULL; 32389038Sjake proc0.p_uarea = (struct user *)uarea0; 32483366Sjulian proc0.p_stats = &proc0.p_uarea->u_stats; 32590361Sjulian thread0.td_kstack = kstack0; 32690361Sjulian thread0.td_pcb = (struct pcb *) 32790361Sjulian (thread0.td_kstack + KSTACK_PAGES * PAGE_SIZE) - 1; 328105908Sjake frame0.tf_tstate = TSTATE_IE | TSTATE_PEF | TSTATE_PRIV; 32990361Sjulian thread0.td_frame = &frame0; 33080709Sjake 33180709Sjake /* 33289038Sjake * Prime our per-cpu data page for use. Note, we are using it for our 33389038Sjake * stack, so don't pass the real size (PAGE_SIZE) to pcpu_init or 33489038Sjake * it'll zero it out from under us. 33580709Sjake */ 33691360Sjake pc = (struct pcpu *)(pcpu0 + (PCPU_PAGES * PAGE_SIZE)) - 1; 33789038Sjake pcpu_init(pc, 0, sizeof(struct pcpu)); 33890361Sjulian pc->pc_curthread = &thread0; 33991156Sjake pc->pc_curpcb = thread0.td_pcb; 34091616Sjake pc->pc_mid = UPA_CR_GET_MID(ldxa(0, ASI_UPA_CONFIG_REG)); 34191616Sjake pc->pc_addr = (vm_offset_t)pcpu0; 342101898Sjake pc->pc_node = child; 34391613Sjake pc->pc_tlb_ctx = TLB_CTX_USER_MIN; 34491613Sjake pc->pc_tlb_ctx_min = TLB_CTX_USER_MIN; 34591613Sjake pc->pc_tlb_ctx_max = TLB_CTX_USER_MAX; 34688639Sjake 34780709Sjake /* 34889038Sjake * Initialize global registers. 34981383Sjake */ 35089038Sjake cpu_setregs(pc); 35188639Sjake 35288639Sjake /* 353108301Sjake * Initialize the message buffer (after setting trap table). 35488822Stmm */ 35588822Stmm msgbufinit(msgbufp, MSGBUF_SIZE); 35688822Stmm 35793702Sjhb mutex_init(); 35890624Stmm intr_init2(); 359105946Stmm 360105946Stmm OF_getprop(PCPU_GET(node), "clock-frequency", &clock, sizeof(clock)); 361105946Stmm tick_init(clock); 362106555Stmm 363106555Stmm OF_getprop(root, "name", sparc64_model, sizeof(sparc64_model) - 1); 36480708Sjake} 36580708Sjake 36680708Sjakevoid 36780709Sjakeset_openfirm_callback(ofw_vec_t *vec) 36880709Sjake{ 36980709Sjake ofw_tba = rdpr(tba); 37080709Sjake ofw_vec = (u_long)vec; 37180709Sjake} 37280709Sjake 37380709Sjakevoid 37480708Sjakesendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) 37580708Sjake{ 37682902Sjake struct trapframe *tf; 37782902Sjake struct sigframe *sfp; 37882902Sjake struct sigacts *psp; 37982902Sjake struct sigframe sf; 38083366Sjulian struct thread *td; 38185242Sjake struct frame *fp; 38282902Sjake struct proc *p; 38385242Sjake int oonstack; 38482902Sjake u_long sp; 38582902Sjake 38682902Sjake oonstack = 0; 38783366Sjulian td = curthread; 38883366Sjulian p = td->td_proc; 38982902Sjake psp = p->p_sigacts; 39083366Sjulian tf = td->td_frame; 39182902Sjake sp = tf->tf_sp + SPOFF; 39282902Sjake oonstack = sigonstack(sp); 39382902Sjake 39483366Sjulian CTR4(KTR_SIG, "sendsig: td=%p (%s) catcher=%p sig=%d", td, p->p_comm, 39582902Sjake catcher, sig); 39682902Sjake 397102554Sjake /* Make sure we have a signal trampoline to return to. */ 398102554Sjake if (p->p_md.md_sigtramp == NULL) { 399102554Sjake /* 400102554Sjake * No signal tramoline... kill the process. 401102554Sjake */ 402102554Sjake CTR0(KTR_SIG, "sendsig: no sigtramp"); 403102873Sjake printf("sendsig: %s is too old, rebuild it\n", p->p_comm); 404102554Sjake sigexit(td, sig); 405102554Sjake /* NOTREACHED */ 406102554Sjake } 407102554Sjake 40882902Sjake /* Save user context. */ 40982902Sjake bzero(&sf, sizeof(sf)); 41082902Sjake sf.sf_uc.uc_sigmask = *mask; 41182902Sjake sf.sf_uc.uc_stack = p->p_sigstk; 41282902Sjake sf.sf_uc.uc_stack.ss_flags = (p->p_flag & P_ALTSTACK) 41382902Sjake ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE; 414105733Sjake bcopy(tf, &sf.sf_uc.uc_mcontext, sizeof(*tf)); 41582902Sjake 41682902Sjake /* Allocate and validate space for the signal handler context. */ 41782902Sjake if ((p->p_flag & P_ALTSTACK) != 0 && !oonstack && 41882902Sjake SIGISMEMBER(psp->ps_sigonstack, sig)) { 41982902Sjake sfp = (struct sigframe *)(p->p_sigstk.ss_sp + 42082902Sjake p->p_sigstk.ss_size - sizeof(struct sigframe)); 42182902Sjake } else 42282902Sjake sfp = (struct sigframe *)sp - 1; 42382902Sjake PROC_UNLOCK(p); 42482902Sjake 42585242Sjake fp = (struct frame *)sfp - 1; 42682902Sjake 42782902Sjake /* Translate the signal if appropriate. */ 42882902Sjake if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize) 42982902Sjake sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)]; 43082902Sjake 43182902Sjake /* Build the argument list for the signal handler. */ 43282902Sjake tf->tf_out[0] = sig; 433105733Sjake tf->tf_out[1] = (register_t)&sfp->sf_si; 43482902Sjake tf->tf_out[2] = (register_t)&sfp->sf_uc; 43582902Sjake tf->tf_out[4] = (register_t)catcher; 436105733Sjake /* Fill siginfo structure. */ 437105733Sjake sf.sf_si.si_signo = sig; 438105733Sjake sf.sf_si.si_code = code; 439105733Sjake sf.sf_si.si_addr = (void *)tf->tf_sfar; 44082902Sjake 44182902Sjake /* Copy the sigframe out to the user's stack. */ 44285242Sjake if (rwindow_save(td) != 0 || copyout(&sf, sfp, sizeof(*sfp)) != 0 || 44394254Sjake suword(&fp->fr_in[6], tf->tf_out[6]) != 0) { 44482902Sjake /* 44582902Sjake * Something is wrong with the stack pointer. 44682902Sjake * ...Kill the process. 44782902Sjake */ 44883366Sjulian CTR2(KTR_SIG, "sendsig: sigexit td=%p sfp=%p", td, sfp); 44982902Sjake PROC_LOCK(p); 45083366Sjulian sigexit(td, SIGILL); 45182902Sjake /* NOTREACHED */ 45282902Sjake } 45382902Sjake 454102554Sjake tf->tf_tpc = (u_long)p->p_md.md_sigtramp; 45582902Sjake tf->tf_tnpc = tf->tf_tpc + 4; 45685242Sjake tf->tf_sp = (u_long)fp - SPOFF; 45782902Sjake 45883366Sjulian CTR3(KTR_SIG, "sendsig: return td=%p pc=%#lx sp=%#lx", td, tf->tf_tpc, 45982902Sjake tf->tf_sp); 46084178Sjake 46184178Sjake PROC_LOCK(p); 46280708Sjake} 46380708Sjake 46480708Sjake#ifndef _SYS_SYSPROTO_H_ 46583088Sobrienstruct sigreturn_args { 46680708Sjake ucontext_t *ucp; 46780708Sjake}; 46880708Sjake#endif 46980708Sjake 47094606Salc/* 47194606Salc * MPSAFE 47294606Salc */ 47380708Sjakeint 47483366Sjuliansigreturn(struct thread *td, struct sigreturn_args *uap) 47580708Sjake{ 476109036Sjake struct trapframe *tf; 47783366Sjulian struct proc *p; 478109036Sjake mcontext_t *mc; 47982902Sjake ucontext_t uc; 48082902Sjake 48183366Sjulian p = td->td_proc; 48283366Sjulian if (rwindow_save(td)) { 48382902Sjake PROC_LOCK(p); 48483366Sjulian sigexit(td, SIGILL); 48582902Sjake } 48682902Sjake 48783366Sjulian CTR2(KTR_SIG, "sigreturn: td=%p ucp=%p", td, uap->sigcntxp); 48882902Sjake if (copyin(uap->sigcntxp, &uc, sizeof(uc)) != 0) { 48983366Sjulian CTR1(KTR_SIG, "sigreturn: efault td=%p", td); 49082902Sjake return (EFAULT); 49182902Sjake } 49282902Sjake 493109036Sjake mc = &uc.uc_mcontext; 494109036Sjake tf = td->td_frame; 495109036Sjake if (!TSTATE_SECURE(mc->mc_tstate)) 49684178Sjake return (EINVAL); 497109036Sjake mc->mc_wstate = tf->tf_wstate; 498109036Sjake bcopy(mc, tf, sizeof(*tf)); 49982902Sjake 50082902Sjake PROC_LOCK(p); 501112888Sjeff td->td_sigmask = uc.uc_sigmask; 502112888Sjeff SIG_CANTMASK(td->td_sigmask); 503112888Sjeff signotify(td); 50482902Sjake PROC_UNLOCK(p); 505105733Sjake 50683366Sjulian CTR4(KTR_SIG, "sigreturn: return td=%p pc=%#lx sp=%#lx tstate=%#lx", 507109036Sjake td, tf->tf_tpc, tf->tf_sp, tf->tf_tstate); 50882902Sjake return (EJUSTRETURN); 50980708Sjake} 51080708Sjake 511105950Speter#ifdef COMPAT_FREEBSD4 512105950Speterint 513105950Speterfreebsd4_sigreturn(struct thread *td, struct freebsd4_sigreturn_args *uap) 514105950Speter{ 515105950Speter 516105950Speter return sigreturn(td, (struct sigreturn_args *)uap); 517105950Speter} 518105950Speter#endif 519105950Speter 520106977Sdeischenint 521112924Sjakeget_mcontext(struct thread *td, mcontext_t *mc) 522106977Sdeischen{ 523112924Sjake struct trapframe *tf; 524112924Sjake struct pcb *pcb; 525106977Sdeischen 526112924Sjake tf = td->td_frame; 527112924Sjake pcb = td->td_pcb; 528112924Sjake bcopy(tf, mc, sizeof(*tf)); 529112961Sjake mc->mc_flags = _MC_VERSION; 530112924Sjake critical_enter(); 531112961Sjake if ((tf->tf_fprs & FPRS_FEF) != 0) { 532112961Sjake savefpctx(pcb->pcb_ufp); 533112961Sjake tf->tf_fprs &= ~FPRS_FEF; 534112961Sjake pcb->pcb_flags |= PCB_FEF; 535112961Sjake } 536112961Sjake if ((pcb->pcb_flags & PCB_FEF) != 0) { 537113018Sjake bcopy(pcb->pcb_ufp, mc->mc_fp, sizeof(mc->mc_fp)); 538112924Sjake mc->mc_fprs |= FPRS_FEF; 539112924Sjake } 540112924Sjake critical_exit(); 541112924Sjake return (0); 542106977Sdeischen} 543106977Sdeischen 544106977Sdeischenint 545112924Sjakeset_mcontext(struct thread *td, const mcontext_t *mc) 546106977Sdeischen{ 547112924Sjake struct trapframe *tf; 548112924Sjake struct pcb *pcb; 549112924Sjake uint64_t wstate; 550106977Sdeischen 551112961Sjake if (!TSTATE_SECURE(mc->mc_tstate) || 552112961Sjake (mc->mc_flags & ((1L << _MC_VERSION_BITS) - 1)) != _MC_VERSION) 553112924Sjake return (EINVAL); 554112924Sjake tf = td->td_frame; 555112924Sjake pcb = td->td_pcb; 556112924Sjake wstate = tf->tf_wstate; 557112924Sjake bcopy(mc, tf, sizeof(*tf)); 558112924Sjake tf->tf_wstate = wstate; 559112924Sjake if ((mc->mc_fprs & FPRS_FEF) != 0) { 560112924Sjake tf->tf_fprs = 0; 561113018Sjake bcopy(mc->mc_fp, pcb->pcb_ufp, sizeof(pcb->pcb_ufp)); 562112924Sjake pcb->pcb_flags |= PCB_FEF; 563112924Sjake } 564112924Sjake return (0); 565106977Sdeischen} 566106977Sdeischen 56786147Stmm/* 56892205Sjake * Exit the kernel and execute a firmware call that will not return, as 56992205Sjake * specified by the arguments. 57092205Sjake */ 57192205Sjakevoid 57292205Sjakecpu_shutdown(void *args) 57392205Sjake{ 57492205Sjake 57592205Sjake#ifdef SMP 57692205Sjake cpu_mp_shutdown(); 57792205Sjake#endif 57892205Sjake openfirmware_exit(args); 57992205Sjake} 58092205Sjake 58192205Sjake/* 58286147Stmm * Duplicate OF_exit() with a different firmware call function that restores 58386147Stmm * the trap table, otherwise a RED state exception is triggered in at least 58486147Stmm * some firmware versions. 58586147Stmm */ 58680708Sjakevoid 58780708Sjakecpu_halt(void) 58880708Sjake{ 58986147Stmm static struct { 59086147Stmm cell_t name; 59186147Stmm cell_t nargs; 59286147Stmm cell_t nreturns; 59386147Stmm } args = { 59486147Stmm (cell_t)"exit", 59586147Stmm 0, 59686147Stmm 0 59786147Stmm }; 59884178Sjake 59992205Sjake cpu_shutdown(&args); 60080708Sjake} 60180708Sjake 60286147Stmmvoid 60386147Stmmsparc64_shutdown_final(void *dummy, int howto) 60486147Stmm{ 60586147Stmm static struct { 60686147Stmm cell_t name; 60786147Stmm cell_t nargs; 60886147Stmm cell_t nreturns; 60986147Stmm } args = { 61086147Stmm (cell_t)"SUNW,power-off", 61186147Stmm 0, 61286147Stmm 0 61386147Stmm }; 61486147Stmm 61586147Stmm /* Turn the power off? */ 61686147Stmm if ((howto & RB_POWEROFF) != 0) 61792205Sjake cpu_shutdown(&args); 61886147Stmm /* In case of halt, return to the firmware */ 61986147Stmm if ((howto & RB_HALT) != 0) 62086147Stmm cpu_halt(); 62186147Stmm} 62286147Stmm 62380708Sjakeint 62483366Sjulianptrace_set_pc(struct thread *td, u_long addr) 62580708Sjake{ 62682016Sjake 62783366Sjulian td->td_frame->tf_tpc = addr; 62883366Sjulian td->td_frame->tf_tnpc = addr + 4; 62980708Sjake return (0); 63080708Sjake} 63180708Sjake 63280708Sjakeint 63383366Sjulianptrace_single_step(struct thread *td) 63480708Sjake{ 635104271Sjake /* TODO; */ 63680708Sjake return (0); 63780708Sjake} 63880708Sjake 63980708Sjakevoid 640102561Sjakeexec_setregs(struct thread *td, u_long entry, u_long stack, u_long ps_strings) 64180708Sjake{ 64288639Sjake struct trapframe *tf; 64388782Sjake struct md_utrap *ut; 64481135Stmm struct pcb *pcb; 645102557Sjake struct proc *p; 64684178Sjake u_long sp; 64781135Stmm 64888782Sjake /* XXX no cpu_exec */ 649102557Sjake p = td->td_proc; 650102557Sjake p->p_md.md_sigtramp = NULL; 651102557Sjake if ((ut = p->p_md.md_utrap) != NULL) { 65288782Sjake ut->ut_refcnt--; 65388782Sjake if (ut->ut_refcnt == 0) 65488782Sjake free(ut, M_SUBPROC); 655102557Sjake p->p_md.md_utrap = NULL; 65688782Sjake } 65788782Sjake 65883366Sjulian pcb = td->td_pcb; 659105908Sjake tf = td->td_frame; 66088639Sjake sp = rounddown(stack, 16); 66198032Sjake bzero(pcb, sizeof(*pcb)); 66298032Sjake bzero(tf, sizeof(*tf)); 66388639Sjake tf->tf_out[0] = stack; 664105908Sjake tf->tf_out[3] = p->p_sysent->sv_psstrings; 66588639Sjake tf->tf_out[6] = sp - SPOFF - sizeof(struct frame); 66688639Sjake tf->tf_tnpc = entry + 4; 66788639Sjake tf->tf_tpc = entry; 66888639Sjake tf->tf_tstate = TSTATE_IE | TSTATE_PEF | TSTATE_MM_TSO; 66988639Sjake 67088639Sjake td->td_retval[0] = tf->tf_out[0]; 67188639Sjake td->td_retval[1] = tf->tf_out[1]; 67280708Sjake} 67380708Sjake 67480708Sjakevoid 67580708SjakeDebugger(const char *msg) 67680708Sjake{ 67780709Sjake 67880709Sjake printf("Debugger(\"%s\")\n", msg); 67988436Sjake critical_enter(); 68080709Sjake breakpoint(); 68188436Sjake critical_exit(); 68280708Sjake} 68380708Sjake 68480708Sjakeint 68584178Sjakefill_regs(struct thread *td, struct reg *regs) 68680708Sjake{ 68780708Sjake 688105733Sjake bcopy(td->td_frame, regs, sizeof(*regs)); 68980708Sjake return (0); 69080708Sjake} 69180708Sjake 69280708Sjakeint 69384178Sjakeset_regs(struct thread *td, struct reg *regs) 69480708Sjake{ 695112922Sjake struct trapframe *tf; 69680708Sjake 69784178Sjake if (!TSTATE_SECURE(regs->r_tstate)) 69884178Sjake return (EINVAL); 699112922Sjake tf = td->td_frame; 700112922Sjake regs->r_wstate = tf->tf_wstate; 701112922Sjake bcopy(regs, tf, sizeof(*regs)); 70280708Sjake return (0); 70380708Sjake} 70480708Sjake 70580708Sjakeint 70685294Sdesfill_dbregs(struct thread *td, struct dbreg *dbregs) 70785294Sdes{ 70885294Sdes 70985294Sdes return (ENOSYS); 71085294Sdes} 71185294Sdes 71285294Sdesint 71385294Sdesset_dbregs(struct thread *td, struct dbreg *dbregs) 71485294Sdes{ 71585294Sdes 71685294Sdes return (ENOSYS); 71785294Sdes} 71885294Sdes 71985294Sdesint 72083366Sjulianfill_fpregs(struct thread *td, struct fpreg *fpregs) 72180708Sjake{ 72288639Sjake struct trapframe *tf; 72384178Sjake struct pcb *pcb; 72484178Sjake 72584178Sjake pcb = td->td_pcb; 72688639Sjake tf = td->td_frame; 727112920Sjake bcopy(pcb->pcb_ufp, fpregs->fr_regs, sizeof(fpregs->fr_regs)); 72888639Sjake fpregs->fr_fsr = tf->tf_fsr; 729105733Sjake fpregs->fr_gsr = tf->tf_gsr; 73080708Sjake return (0); 73180708Sjake} 73280708Sjake 73380708Sjakeint 73483366Sjulianset_fpregs(struct thread *td, struct fpreg *fpregs) 73580708Sjake{ 73688639Sjake struct trapframe *tf; 73784178Sjake struct pcb *pcb; 73884178Sjake 73984178Sjake pcb = td->td_pcb; 74088639Sjake tf = td->td_frame; 741112922Sjake tf->tf_fprs &= ~FPRS_FEF; 742112920Sjake bcopy(fpregs->fr_regs, pcb->pcb_ufp, sizeof(pcb->pcb_ufp)); 74388639Sjake tf->tf_fsr = fpregs->fr_fsr; 744105733Sjake tf->tf_gsr = fpregs->fr_gsr; 74580708Sjake return (0); 74680708Sjake} 747