machdep.c revision 181701
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 * 4. Neither the name of the University nor the names of its contributors 1982902Sjake * may be used to endorse or promote products derived from this software 2082902Sjake * without specific prior written permission. 2180708Sjake * 2282902Sjake * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2380708Sjake * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2480708Sjake * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2582902Sjake * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2680708Sjake * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2780708Sjake * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2880708Sjake * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2980708Sjake * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3080708Sjake * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3180708Sjake * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3280708Sjake * SUCH DAMAGE. 3380708Sjake * 3482902Sjake * from: @(#)machdep.c 7.4 (Berkeley) 6/3/91 35181701Smarius * from: FreeBSD: src/sys/i386/i386/machdep.c,v 1.477 2001/08/27 3680708Sjake */ 3780708Sjake 38145151Smarius#include <sys/cdefs.h> 39145151Smarius__FBSDID("$FreeBSD: head/sys/sparc64/sparc64/machdep.c 181701 2008-08-13 20:30:28Z marius $"); 40145151Smarius 41105950Speter#include "opt_compat.h" 4280709Sjake#include "opt_ddb.h" 43118239Speter#include "opt_kstack_pages.h" 4485242Sjake#include "opt_msgbuf.h" 4580709Sjake 4680708Sjake#include <sys/param.h> 47141378Snjl#include <sys/malloc.h> 48141378Snjl#include <sys/proc.h> 4980708Sjake#include <sys/systm.h> 50141249Snjl#include <sys/bio.h> 51141249Snjl#include <sys/buf.h> 52141249Snjl#include <sys/bus.h> 53141249Snjl#include <sys/cpu.h> 5480709Sjake#include <sys/cons.h> 55141378Snjl#include <sys/eventhandler.h> 56141378Snjl#include <sys/exec.h> 57102561Sjake#include <sys/imgact.h> 58141378Snjl#include <sys/interrupt.h> 59131950Smarcel#include <sys/kdb.h> 6080709Sjake#include <sys/kernel.h> 6185262Sjake#include <sys/ktr.h> 6280709Sjake#include <sys/linker.h> 6380709Sjake#include <sys/lock.h> 6485242Sjake#include <sys/msgbuf.h> 6580708Sjake#include <sys/mutex.h> 6680709Sjake#include <sys/pcpu.h> 67141378Snjl#include <sys/ptrace.h> 6885242Sjake#include <sys/reboot.h> 6980708Sjake#include <sys/signalvar.h> 7091616Sjake#include <sys/smp.h> 7182902Sjake#include <sys/sysent.h> 7280708Sjake#include <sys/sysproto.h> 7380709Sjake#include <sys/timetc.h> 7491156Sjake#include <sys/ucontext.h> 7580708Sjake 7680708Sjake#include <dev/ofw/openfirm.h> 7780708Sjake 7880709Sjake#include <vm/vm.h> 79141378Snjl#include <vm/vm_extern.h> 8080709Sjake#include <vm/vm_kern.h> 8180709Sjake#include <vm/vm_page.h> 8280709Sjake#include <vm/vm_map.h> 83141378Snjl#include <vm/vm_object.h> 8480709Sjake#include <vm/vm_pager.h> 85141378Snjl#include <vm/vm_param.h> 8680709Sjake 8780709Sjake#include <ddb/ddb.h> 8880709Sjake 89119696Smarcel#include <machine/bus.h> 9086521Sjake#include <machine/cache.h> 9181383Sjake#include <machine/clock.h> 9282902Sjake#include <machine/cpu.h> 9383366Sjulian#include <machine/fp.h> 94112922Sjake#include <machine/fsr.h> 9581383Sjake#include <machine/intr_machdep.h> 9680708Sjake#include <machine/md_var.h> 9788436Sjake#include <machine/metadata.h> 9886147Stmm#include <machine/ofw_machdep.h> 99115971Sjake#include <machine/ofw_mem.h> 100138129Sdas#include <machine/pcb.h> 10180709Sjake#include <machine/pmap.h> 10280709Sjake#include <machine/pstate.h> 10380708Sjake#include <machine/reg.h> 10482902Sjake#include <machine/sigframe.h> 105141378Snjl#include <machine/smp.h> 10681383Sjake#include <machine/tick.h> 10791613Sjake#include <machine/tlb.h> 10882016Sjake#include <machine/tstate.h> 10991616Sjake#include <machine/upa.h> 11082902Sjake#include <machine/ver.h> 11180708Sjake 11280709Sjaketypedef int ofw_vec_t(void *); 11380708Sjake 114131950Smarcel#ifdef DDB 115131950Smarcelextern vm_offset_t ksym_start, ksym_end; 116131950Smarcel#endif 117131950Smarcel 11897445Sjakestruct tlb_entry *kernel_tlbs; 11991616Sjakeint kernel_tlb_slots; 12091616Sjake 12180708Sjakeint cold = 1; 122102600Speterlong Maxmem; 123142956Sweslong realmem; 12480708Sjake 12591360Sjakechar pcpu0[PCPU_PAGES * PAGE_SIZE]; 12689038Sjakestruct trapframe frame0; 12780708Sjake 12889038Sjakevm_offset_t kstack0; 129113238Sjakevm_paddr_t kstack0_phys; 13088781Sjake 13182902Sjakestruct kva_md_info kmi; 13280709Sjake 13380709Sjakeu_long ofw_vec; 13480709Sjakeu_long ofw_tba; 13580709Sjake 136135972Skensmith/* 137135972Skensmith * Note: timer quality for CPU's is set low to try and prevent them from 138135972Skensmith * being chosen as the primary timecounter. The CPU counters are not 139135972Skensmith * synchronized among the CPU's so in MP machines this causes problems 140135972Skensmith * when calculating the time. With this value the CPU's should only be 141135972Skensmith * chosen as the primary timecounter as a last resort. 142135972Skensmith */ 143135972Skensmith 144135972Skensmith#define UP_TICK_QUALITY 1000 145135972Skensmith#define MP_TICK_QUALITY -100 14680709Sjakestatic struct timecounter tick_tc; 14780709Sjake 148106555Stmmchar sparc64_model[32]; 149106555Stmm 150113166Sjakestatic int cpu_use_vis = 1; 151113166Sjake 152113166Sjakecpu_block_copy_t *cpu_block_copy; 153113166Sjakecpu_block_zero_t *cpu_block_zero; 154113166Sjake 15580709Sjakestatic timecounter_get_t tick_get_timecount; 15691616Sjakevoid sparc64_init(caddr_t mdp, u_long o1, u_long o2, u_long o3, 157181701Smarius ofw_vec_t *vec); 15886147Stmmvoid sparc64_shutdown_final(void *dummy, int howto); 15980709Sjake 16080709Sjakestatic void cpu_startup(void *); 16180709SjakeSYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL); 16280709Sjake 16391336SjakeCTASSERT((1 << INT_SHIFT) == sizeof(int)); 16491336SjakeCTASSERT((1 << PTR_SHIFT) == sizeof(char *)); 16591336Sjake 166105733SjakeCTASSERT(sizeof(struct reg) == 256); 167105733SjakeCTASSERT(sizeof(struct fpreg) == 272); 168105733SjakeCTASSERT(sizeof(struct __mcontext) == 512); 169105733Sjake 170113023SjakeCTASSERT((sizeof(struct pcb) & (64 - 1)) == 0); 171113023SjakeCTASSERT((offsetof(struct pcb, pcb_kfp) & (64 - 1)) == 0); 172113023SjakeCTASSERT((offsetof(struct pcb, pcb_ufp) & (64 - 1)) == 0); 173113023SjakeCTASSERT(sizeof(struct pcb) <= ((KSTACK_PAGES * PAGE_SIZE) / 8)); 174113023Sjake 17591360SjakeCTASSERT(sizeof(struct pcpu) <= ((PCPU_PAGES * PAGE_SIZE) / 2)); 17689038Sjake 17780709Sjakestatic void 17880709Sjakecpu_startup(void *arg) 17980709Sjake{ 180115971Sjake vm_paddr_t physsz; 181115971Sjake int i; 18280709Sjake 18380709Sjake tick_tc.tc_get_timecount = tick_get_timecount; 18480709Sjake tick_tc.tc_poll_pps = NULL; 18580709Sjake tick_tc.tc_counter_mask = ~0u; 186105946Stmm tick_tc.tc_frequency = tick_freq; 18780709Sjake tick_tc.tc_name = "tick"; 188135972Skensmith tick_tc.tc_quality = UP_TICK_QUALITY; 189135972Skensmith#ifdef SMP 190135972Skensmith /* 191135972Skensmith * We do not know if each CPU's tick counter is synchronized. 192135972Skensmith */ 193135972Skensmith if (cpu_mp_probe()) 194135972Skensmith tick_tc.tc_quality = MP_TICK_QUALITY; 195135972Skensmith#endif 196135972Skensmith 19780709Sjake tc_init(&tick_tc); 19880709Sjake 199115971Sjake physsz = 0; 200115971Sjake for (i = 0; i < sparc64_nmemreg; i++) 201115971Sjake physsz += sparc64_memreg[i].mr_size; 202115971Sjake printf("real memory = %lu (%lu MB)\n", physsz, 203115971Sjake physsz / (1024 * 1024)); 204155680Sjhb realmem = (long)physsz / PAGE_SIZE; 20580709Sjake 20682902Sjake vm_ksubmap_init(&kmi); 20780709Sjake 20880709Sjake bufinit(); 20980709Sjake vm_pager_bufferinit(); 21080709Sjake 21186147Stmm EVENTHANDLER_REGISTER(shutdown_final, sparc64_shutdown_final, NULL, 21286147Stmm SHUTDOWN_PRI_LAST); 213113338Sjake 214170170Sattilio printf("avail memory = %lu (%lu MB)\n", cnt.v_free_count * PAGE_SIZE, 215170170Sattilio cnt.v_free_count / ((1024 * 1024) / PAGE_SIZE)); 216113338Sjake 217113338Sjake if (bootverbose) 218113338Sjake printf("machine: %s\n", sparc64_model); 219113338Sjake 220113338Sjake cpu_identify(rdpr(ver), tick_freq, PCPU_GET(cpuid)); 22180709Sjake} 22280709Sjake 22387702Sjhbvoid 22487702Sjhbcpu_pcpu_init(struct pcpu *pcpu, int cpuid, size_t size) 22587702Sjhb{ 22697265Sjake struct intr_request *ir; 22797265Sjake int i; 22897265Sjake 22997265Sjake pcpu->pc_irtail = &pcpu->pc_irhead; 23097265Sjake for (i = 0; i < IR_FREE; i++) { 23197265Sjake ir = &pcpu->pc_irpool[i]; 23297265Sjake ir->ir_next = pcpu->pc_irfree; 23397265Sjake pcpu->pc_irfree = ir; 23497265Sjake } 23587702Sjhb} 23687702Sjhb 237144637Sjhbvoid 238144637Sjhbspinlock_enter(void) 239144637Sjhb{ 240144637Sjhb struct thread *td; 241145085Sjhb register_t pil; 242144637Sjhb 243144637Sjhb td = curthread; 244144637Sjhb if (td->td_md.md_spinlock_count == 0) { 245145085Sjhb pil = rdpr(pil); 246145151Smarius wrpr(pil, 0, PIL_TICK); 247145085Sjhb td->td_md.md_saved_pil = pil; 248144637Sjhb } 249144637Sjhb td->td_md.md_spinlock_count++; 250144637Sjhb critical_enter(); 251144637Sjhb} 252144637Sjhb 253144637Sjhbvoid 254144637Sjhbspinlock_exit(void) 255144637Sjhb{ 256144637Sjhb struct thread *td; 257144637Sjhb 258144637Sjhb td = curthread; 259144637Sjhb critical_exit(); 260144637Sjhb td->td_md.md_spinlock_count--; 261144637Sjhb if (td->td_md.md_spinlock_count == 0) 262144637Sjhb wrpr(pil, td->td_md.md_saved_pil, 0); 263144637Sjhb} 264144637Sjhb 26580709Sjakeunsigned 26680709Sjaketick_get_timecount(struct timecounter *tc) 26780709Sjake{ 26880709Sjake return ((unsigned)rd(tick)); 26980709Sjake} 27080709Sjake 27180708Sjakevoid 27291616Sjakesparc64_init(caddr_t mdp, u_long o1, u_long o2, u_long o3, ofw_vec_t *vec) 27380708Sjake{ 274181701Smarius char type[8]; 275181701Smarius char *env; 27689038Sjake struct pcpu *pc; 27786521Sjake vm_offset_t end; 27886521Sjake caddr_t kmdp; 279181701Smarius phandle_t child; 280181701Smarius phandle_t root; 281105946Stmm u_int clock; 28280709Sjake 28386521Sjake end = 0; 28486521Sjake kmdp = NULL; 28586521Sjake 28680709Sjake /* 287181701Smarius * Find out what kind of CPU we have first, for anything that changes 288112398Sjake * behaviour. 289112398Sjake */ 290112398Sjake cpu_impl = VER_IMPL(rdpr(ver)); 291112398Sjake 292112398Sjake /* 293133862Smarius * Initialize Open Firmware (needed for console). 29480709Sjake */ 29580709Sjake OF_init(vec); 29680709Sjake 29780709Sjake /* 29886521Sjake * Parse metadata if present and fetch parameters. Must be before the 29986521Sjake * console is inited so cninit gets the right value of boothowto. 30086521Sjake */ 30186521Sjake if (mdp != NULL) { 30286521Sjake preload_metadata = mdp; 303114374Speter kmdp = preload_search_by_type("elf kernel"); 30486521Sjake if (kmdp != NULL) { 30586521Sjake boothowto = MD_FETCH(kmdp, MODINFOMD_HOWTO, int); 30686521Sjake kern_envp = MD_FETCH(kmdp, MODINFOMD_ENVP, char *); 30786521Sjake end = MD_FETCH(kmdp, MODINFOMD_KERNEND, vm_offset_t); 30891616Sjake kernel_tlb_slots = MD_FETCH(kmdp, MODINFOMD_DTLB_SLOTS, 30991616Sjake int); 31097445Sjake kernel_tlbs = (void *)preload_search_info(kmdp, 31191616Sjake MODINFO_METADATA | MODINFOMD_DTLB); 31286521Sjake } 31386521Sjake } 31486521Sjake 315122462Sjake init_param1(); 316122462Sjake 317122462Sjake root = OF_peer(0); 318122462Sjake for (child = OF_child(root); child != 0; child = OF_peer(child)) { 319122462Sjake OF_getprop(child, "device_type", type, sizeof(type)); 320122462Sjake if (strcmp(type, "cpu") == 0) 321122462Sjake break; 322122462Sjake } 323122462Sjake 324157227Smarius /* 325157227Smarius * Initialize the tick counter. Must be before the console is inited 326157227Smarius * in order to provide the low-level console drivers with a working 327157227Smarius * DELAY(). 328157227Smarius */ 329122462Sjake OF_getprop(child, "clock-frequency", &clock, sizeof(clock)); 330122462Sjake tick_init(clock); 331122462Sjake 33286521Sjake /* 33380709Sjake * Initialize the console before printing anything. 33480709Sjake */ 33588639Sjake cninit(); 33680709Sjake 33780709Sjake /* 338157227Smarius * Panic if there is no metadata. Most likely the kernel was booted 33986521Sjake * directly, instead of through loader(8). 34080709Sjake */ 34186521Sjake if (mdp == NULL || kmdp == NULL) { 34286521Sjake printf("sparc64_init: no loader metadata.\n" 343181701Smarius "This probably means you are not using loader(8).\n"); 34486521Sjake panic("sparc64_init"); 34586521Sjake } 34680709Sjake 34781383Sjake /* 34886521Sjake * Sanity check the kernel end, which is important. 34986521Sjake */ 35086521Sjake if (end == 0) { 35186521Sjake printf("sparc64_init: warning, kernel end not specified.\n" 352181701Smarius "Attempting to continue anyway.\n"); 35386521Sjake end = (vm_offset_t)_end; 35486521Sjake } 35586521Sjake 356101898Sjake cache_init(child); 357166968Smarius uma_set_align(cache.dc_linesize - 1); 358101898Sjake 359169178Smarius cpu_block_copy = bcopy; 360169178Smarius cpu_block_zero = bzero; 361113166Sjake getenv_int("machdep.use_vis", &cpu_use_vis); 362113166Sjake if (cpu_use_vis) { 363169178Smarius switch (cpu_impl) { 364169178Smarius case CPU_IMPL_SPARC64: 365169178Smarius case CPU_IMPL_ULTRASPARCI: 366169178Smarius case CPU_IMPL_ULTRASPARCII: 367169178Smarius case CPU_IMPL_ULTRASPARCIIi: 368169178Smarius case CPU_IMPL_ULTRASPARCIIe: 369169178Smarius cpu_block_copy = spitfire_block_copy; 370169178Smarius cpu_block_zero = spitfire_block_zero; 371169178Smarius break; 372169178Smarius } 373113166Sjake } 374113166Sjake 37591616Sjake#ifdef SMP 376170846Smarius mp_init(); 37791616Sjake#endif 37891616Sjake 37986521Sjake /* 38090625Stmm * Initialize virtual memory and calculate physmem. 38187546Sdillon */ 38290625Stmm pmap_bootstrap(end); 38387546Sdillon 38487546Sdillon /* 38581383Sjake * Initialize tunables. 38681383Sjake */ 38787546Sdillon init_param2(physmem); 388105569Smux env = getenv("kernelname"); 389105569Smux if (env != NULL) { 390105569Smux strlcpy(kernelname, env, sizeof(kernelname)); 391105569Smux freeenv(env); 392105569Smux } 39381085Sjake 39480709Sjake /* 39589038Sjake * Initialize the interrupt tables. 39689038Sjake */ 39790624Stmm intr_init1(); 39880709Sjake 39980709Sjake /* 40080709Sjake * Initialize proc0 stuff (p_contested needs to be done early). 40180709Sjake */ 402173361Skib proc_linkup0(&proc0, &thread0); 40395744Sjake proc0.p_md.md_sigtramp = NULL; 40488822Stmm proc0.p_md.md_utrap = NULL; 40590361Sjulian thread0.td_kstack = kstack0; 40690361Sjulian thread0.td_pcb = (struct pcb *) 40790361Sjulian (thread0.td_kstack + KSTACK_PAGES * PAGE_SIZE) - 1; 408105908Sjake frame0.tf_tstate = TSTATE_IE | TSTATE_PEF | TSTATE_PRIV; 40990361Sjulian thread0.td_frame = &frame0; 41080709Sjake 41180709Sjake /* 41289038Sjake * Prime our per-cpu data page for use. Note, we are using it for our 41389038Sjake * stack, so don't pass the real size (PAGE_SIZE) to pcpu_init or 41489038Sjake * it'll zero it out from under us. 41580709Sjake */ 416163973Sjb pc = (struct pcpu *)(pcpu0 + (PCPU_PAGES * PAGE_SIZE)) - 1; 41789038Sjake pcpu_init(pc, 0, sizeof(struct pcpu)); 41890361Sjulian pc->pc_curthread = &thread0; 41991156Sjake pc->pc_curpcb = thread0.td_pcb; 42091616Sjake pc->pc_mid = UPA_CR_GET_MID(ldxa(0, ASI_UPA_CONFIG_REG)); 42191616Sjake pc->pc_addr = (vm_offset_t)pcpu0; 422101898Sjake pc->pc_node = child; 42391613Sjake pc->pc_tlb_ctx = TLB_CTX_USER_MIN; 42491613Sjake pc->pc_tlb_ctx_min = TLB_CTX_USER_MIN; 42591613Sjake pc->pc_tlb_ctx_max = TLB_CTX_USER_MAX; 42688639Sjake 42780709Sjake /* 428163973Sjb * Initialize global registers. 429163973Sjb */ 430163973Sjb cpu_setregs(pc); 431163973Sjb 432163973Sjb /* 433108301Sjake * Initialize the message buffer (after setting trap table). 43488822Stmm */ 43588822Stmm msgbufinit(msgbufp, MSGBUF_SIZE); 43688822Stmm 43793702Sjhb mutex_init(); 43890624Stmm intr_init2(); 439105946Stmm 440133451Salc /* 441133451Salc * Finish pmap initialization now that we're ready for mutexes. 442133451Salc */ 443133451Salc PMAP_LOCK_INIT(kernel_pmap); 444133451Salc 445106555Stmm OF_getprop(root, "name", sparc64_model, sizeof(sparc64_model) - 1); 446122604Ssimokawa 447131950Smarcel kdb_init(); 448131950Smarcel 449131950Smarcel#ifdef KDB 450122604Ssimokawa if (boothowto & RB_KDB) 451174898Srwatson kdb_enter(KDB_WHY_BOOTFLAGS, "Boot flags requested debugger"); 452122604Ssimokawa#endif 45380708Sjake} 45480708Sjake 45580708Sjakevoid 45680709Sjakeset_openfirm_callback(ofw_vec_t *vec) 45780709Sjake{ 458181701Smarius 45980709Sjake ofw_tba = rdpr(tba); 46080709Sjake ofw_vec = (u_long)vec; 46180709Sjake} 46280709Sjake 46380709Sjakevoid 464151316Sdavidxusendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask) 46580708Sjake{ 46682902Sjake struct trapframe *tf; 46782902Sjake struct sigframe *sfp; 46882902Sjake struct sigacts *psp; 46982902Sjake struct sigframe sf; 47083366Sjulian struct thread *td; 47185242Sjake struct frame *fp; 47282902Sjake struct proc *p; 473181701Smarius u_long sp; 47485242Sjake int oonstack; 475151316Sdavidxu int sig; 47682902Sjake 47782902Sjake oonstack = 0; 47883366Sjulian td = curthread; 47983366Sjulian p = td->td_proc; 480114983Sjhb PROC_LOCK_ASSERT(p, MA_OWNED); 481151316Sdavidxu sig = ksi->ksi_signo; 48282902Sjake psp = p->p_sigacts; 483114983Sjhb mtx_assert(&psp->ps_mtx, MA_OWNED); 48483366Sjulian tf = td->td_frame; 48582902Sjake sp = tf->tf_sp + SPOFF; 48682902Sjake oonstack = sigonstack(sp); 48782902Sjake 48883366Sjulian CTR4(KTR_SIG, "sendsig: td=%p (%s) catcher=%p sig=%d", td, p->p_comm, 48982902Sjake catcher, sig); 49082902Sjake 491102554Sjake /* Make sure we have a signal trampoline to return to. */ 492102554Sjake if (p->p_md.md_sigtramp == NULL) { 493102554Sjake /* 494157445Smarius * No signal trampoline... kill the process. 495102554Sjake */ 496102554Sjake CTR0(KTR_SIG, "sendsig: no sigtramp"); 497102873Sjake printf("sendsig: %s is too old, rebuild it\n", p->p_comm); 498102554Sjake sigexit(td, sig); 499102554Sjake /* NOTREACHED */ 500102554Sjake } 501102554Sjake 50282902Sjake /* Save user context. */ 50382902Sjake bzero(&sf, sizeof(sf)); 504118708Sjake get_mcontext(td, &sf.sf_uc.uc_mcontext, 0); 50582902Sjake sf.sf_uc.uc_sigmask = *mask; 506124092Sdavidxu sf.sf_uc.uc_stack = td->td_sigstk; 507181701Smarius sf.sf_uc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK) ? 508181701Smarius ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE; 50982902Sjake 51082902Sjake /* Allocate and validate space for the signal handler context. */ 511124092Sdavidxu if ((td->td_pflags & TDP_ALTSTACK) != 0 && !oonstack && 51282902Sjake SIGISMEMBER(psp->ps_sigonstack, sig)) { 513124092Sdavidxu sfp = (struct sigframe *)(td->td_sigstk.ss_sp + 514124092Sdavidxu td->td_sigstk.ss_size - sizeof(struct sigframe)); 51582902Sjake } else 51682902Sjake sfp = (struct sigframe *)sp - 1; 517114983Sjhb mtx_unlock(&psp->ps_mtx); 51882902Sjake PROC_UNLOCK(p); 51982902Sjake 52085242Sjake fp = (struct frame *)sfp - 1; 52182902Sjake 52282902Sjake /* Translate the signal if appropriate. */ 52382902Sjake if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize) 52482902Sjake sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)]; 52582902Sjake 52682902Sjake /* Build the argument list for the signal handler. */ 52782902Sjake tf->tf_out[0] = sig; 52882902Sjake tf->tf_out[2] = (register_t)&sfp->sf_uc; 52982902Sjake tf->tf_out[4] = (register_t)catcher; 530157445Smarius if (SIGISMEMBER(psp->ps_siginfo, sig)) { 531157445Smarius /* Signal handler installed with SA_SIGINFO. */ 532157445Smarius tf->tf_out[1] = (register_t)&sfp->sf_si; 53382902Sjake 534157445Smarius /* Fill in POSIX parts. */ 535157445Smarius sf.sf_si = ksi->ksi_info; 536157445Smarius sf.sf_si.si_signo = sig; /* maybe a translated signal */ 537157445Smarius } else { 538157445Smarius /* Old FreeBSD-style arguments. */ 539157445Smarius tf->tf_out[1] = ksi->ksi_code; 540157445Smarius tf->tf_out[3] = (register_t)ksi->ksi_addr; 541157445Smarius } 542157445Smarius 54382902Sjake /* Copy the sigframe out to the user's stack. */ 54485242Sjake if (rwindow_save(td) != 0 || copyout(&sf, sfp, sizeof(*sfp)) != 0 || 54594254Sjake suword(&fp->fr_in[6], tf->tf_out[6]) != 0) { 54682902Sjake /* 54782902Sjake * Something is wrong with the stack pointer. 54882902Sjake * ...Kill the process. 54982902Sjake */ 55083366Sjulian CTR2(KTR_SIG, "sendsig: sigexit td=%p sfp=%p", td, sfp); 55182902Sjake PROC_LOCK(p); 55283366Sjulian sigexit(td, SIGILL); 55382902Sjake /* NOTREACHED */ 55482902Sjake } 55582902Sjake 556102554Sjake tf->tf_tpc = (u_long)p->p_md.md_sigtramp; 55782902Sjake tf->tf_tnpc = tf->tf_tpc + 4; 55885242Sjake tf->tf_sp = (u_long)fp - SPOFF; 55982902Sjake 56083366Sjulian CTR3(KTR_SIG, "sendsig: return td=%p pc=%#lx sp=%#lx", td, tf->tf_tpc, 56182902Sjake tf->tf_sp); 56284178Sjake 56384178Sjake PROC_LOCK(p); 564114983Sjhb mtx_lock(&psp->ps_mtx); 56580708Sjake} 56680708Sjake 56780708Sjake#ifndef _SYS_SYSPROTO_H_ 56883088Sobrienstruct sigreturn_args { 56980708Sjake ucontext_t *ucp; 57080708Sjake}; 57180708Sjake#endif 57280708Sjake 57394606Salc/* 57494606Salc * MPSAFE 57594606Salc */ 57680708Sjakeint 57783366Sjuliansigreturn(struct thread *td, struct sigreturn_args *uap) 57880708Sjake{ 57983366Sjulian struct proc *p; 580118768Sjake mcontext_t *mc; 58182902Sjake ucontext_t uc; 582118708Sjake int error; 58382902Sjake 58483366Sjulian p = td->td_proc; 58583366Sjulian if (rwindow_save(td)) { 58682902Sjake PROC_LOCK(p); 58783366Sjulian sigexit(td, SIGILL); 58882902Sjake } 58982902Sjake 59083366Sjulian CTR2(KTR_SIG, "sigreturn: td=%p ucp=%p", td, uap->sigcntxp); 59182902Sjake if (copyin(uap->sigcntxp, &uc, sizeof(uc)) != 0) { 59283366Sjulian CTR1(KTR_SIG, "sigreturn: efault td=%p", td); 59382902Sjake return (EFAULT); 59482902Sjake } 59582902Sjake 596118768Sjake mc = &uc.uc_mcontext; 597118768Sjake error = set_mcontext(td, mc); 598118708Sjake if (error != 0) 599118708Sjake return (error); 60082902Sjake 60182902Sjake PROC_LOCK(p); 602112888Sjeff td->td_sigmask = uc.uc_sigmask; 603112888Sjeff SIG_CANTMASK(td->td_sigmask); 604112888Sjeff signotify(td); 60582902Sjake PROC_UNLOCK(p); 606105733Sjake 60783366Sjulian CTR4(KTR_SIG, "sigreturn: return td=%p pc=%#lx sp=%#lx tstate=%#lx", 608118768Sjake td, mc->mc_tpc, mc->mc_sp, mc->mc_tstate); 60982902Sjake return (EJUSTRETURN); 61080708Sjake} 61180708Sjake 612105950Speter#ifdef COMPAT_FREEBSD4 613105950Speterint 614105950Speterfreebsd4_sigreturn(struct thread *td, struct freebsd4_sigreturn_args *uap) 615105950Speter{ 616105950Speter 617105950Speter return sigreturn(td, (struct sigreturn_args *)uap); 618105950Speter} 619105950Speter#endif 620105950Speter 621131905Smarcel/* 622131905Smarcel * Construct a PCB from a trapframe. This is called from kdb_trap() where 623131905Smarcel * we want to start a backtrace from the function that caused us to enter 624131905Smarcel * the debugger. We have the context in the trapframe, but base the trace 625131905Smarcel * on the PCB. The PCB doesn't have to be perfect, as long as it contains 626131905Smarcel * enough for a backtrace. 627131905Smarcel */ 628131905Smarcelvoid 629131905Smarcelmakectx(struct trapframe *tf, struct pcb *pcb) 630131905Smarcel{ 631131905Smarcel 632131905Smarcel pcb->pcb_pc = tf->tf_tpc; 633131905Smarcel pcb->pcb_sp = tf->tf_sp; 634131905Smarcel} 635131905Smarcel 636106977Sdeischenint 637122364Smarcelget_mcontext(struct thread *td, mcontext_t *mc, int flags) 638106977Sdeischen{ 639112924Sjake struct trapframe *tf; 640112924Sjake struct pcb *pcb; 641106977Sdeischen 642112924Sjake tf = td->td_frame; 643112924Sjake pcb = td->td_pcb; 644112924Sjake bcopy(tf, mc, sizeof(*tf)); 645122364Smarcel if (flags & GET_MC_CLEAR_RET) { 646113998Sdeischen mc->mc_out[0] = 0; 647113998Sdeischen mc->mc_out[1] = 0; 648113998Sdeischen } 649112961Sjake mc->mc_flags = _MC_VERSION; 650112924Sjake critical_enter(); 651112961Sjake if ((tf->tf_fprs & FPRS_FEF) != 0) { 652112961Sjake savefpctx(pcb->pcb_ufp); 653112961Sjake tf->tf_fprs &= ~FPRS_FEF; 654112961Sjake pcb->pcb_flags |= PCB_FEF; 655112961Sjake } 656112961Sjake if ((pcb->pcb_flags & PCB_FEF) != 0) { 657113018Sjake bcopy(pcb->pcb_ufp, mc->mc_fp, sizeof(mc->mc_fp)); 658112924Sjake mc->mc_fprs |= FPRS_FEF; 659112924Sjake } 660112924Sjake critical_exit(); 661112924Sjake return (0); 662106977Sdeischen} 663106977Sdeischen 664106977Sdeischenint 665112924Sjakeset_mcontext(struct thread *td, const mcontext_t *mc) 666106977Sdeischen{ 667112924Sjake struct trapframe *tf; 668112924Sjake struct pcb *pcb; 669112924Sjake uint64_t wstate; 670106977Sdeischen 671112961Sjake if (!TSTATE_SECURE(mc->mc_tstate) || 672112961Sjake (mc->mc_flags & ((1L << _MC_VERSION_BITS) - 1)) != _MC_VERSION) 673112924Sjake return (EINVAL); 674112924Sjake tf = td->td_frame; 675112924Sjake pcb = td->td_pcb; 676136325Skensmith /* Make sure the windows are spilled first. */ 677136325Skensmith flushw(); 678112924Sjake wstate = tf->tf_wstate; 679112924Sjake bcopy(mc, tf, sizeof(*tf)); 680112924Sjake tf->tf_wstate = wstate; 681112924Sjake if ((mc->mc_fprs & FPRS_FEF) != 0) { 682112924Sjake tf->tf_fprs = 0; 683113018Sjake bcopy(mc->mc_fp, pcb->pcb_ufp, sizeof(pcb->pcb_ufp)); 684112924Sjake pcb->pcb_flags |= PCB_FEF; 685112924Sjake } 686112924Sjake return (0); 687106977Sdeischen} 688106977Sdeischen 68986147Stmm/* 69092205Sjake * Exit the kernel and execute a firmware call that will not return, as 69192205Sjake * specified by the arguments. 69292205Sjake */ 69392205Sjakevoid 69492205Sjakecpu_shutdown(void *args) 69592205Sjake{ 69692205Sjake 69792205Sjake#ifdef SMP 69892205Sjake cpu_mp_shutdown(); 69992205Sjake#endif 70092205Sjake openfirmware_exit(args); 70192205Sjake} 70292205Sjake 703181701Smarius/* Get current clock frequency for the given CPU ID. */ 704141237Snjlint 705141237Snjlcpu_est_clockrate(int cpu_id, uint64_t *rate) 706141237Snjl{ 707141237Snjl 708141237Snjl return (ENXIO); 709141237Snjl} 710141237Snjl 71192205Sjake/* 71286147Stmm * Duplicate OF_exit() with a different firmware call function that restores 71386147Stmm * the trap table, otherwise a RED state exception is triggered in at least 71486147Stmm * some firmware versions. 71586147Stmm */ 71680708Sjakevoid 71780708Sjakecpu_halt(void) 71880708Sjake{ 71986147Stmm static struct { 72086147Stmm cell_t name; 72186147Stmm cell_t nargs; 72286147Stmm cell_t nreturns; 72386147Stmm } args = { 72486147Stmm (cell_t)"exit", 72586147Stmm 0, 72686147Stmm 0 72786147Stmm }; 72884178Sjake 72992205Sjake cpu_shutdown(&args); 73080708Sjake} 73180708Sjake 73286147Stmmvoid 73386147Stmmsparc64_shutdown_final(void *dummy, int howto) 73486147Stmm{ 73586147Stmm static struct { 73686147Stmm cell_t name; 73786147Stmm cell_t nargs; 73886147Stmm cell_t nreturns; 73986147Stmm } args = { 74086147Stmm (cell_t)"SUNW,power-off", 74186147Stmm 0, 74286147Stmm 0 74386147Stmm }; 74486147Stmm 74586147Stmm /* Turn the power off? */ 74686147Stmm if ((howto & RB_POWEROFF) != 0) 74792205Sjake cpu_shutdown(&args); 74886147Stmm /* In case of halt, return to the firmware */ 74986147Stmm if ((howto & RB_HALT) != 0) 75086147Stmm cpu_halt(); 75186147Stmm} 75286147Stmm 753121237Spetervoid 754178471Sjeffcpu_idle(int busy) 755121237Speter{ 756181701Smarius 757181701Smarius /* Insert code to halt (until next interrupt) for the idle loop. */ 758121237Speter} 759121237Speter 76080708Sjakeint 761178471Sjeffcpu_idle_wakeup(int cpu) 762178471Sjeff{ 763178471Sjeff 764178471Sjeff return (0); 765178471Sjeff} 766178471Sjeff 767178471Sjeffint 76883366Sjulianptrace_set_pc(struct thread *td, u_long addr) 76980708Sjake{ 77082016Sjake 77183366Sjulian td->td_frame->tf_tpc = addr; 77283366Sjulian td->td_frame->tf_tnpc = addr + 4; 77380708Sjake return (0); 77480708Sjake} 77580708Sjake 77680708Sjakeint 77783366Sjulianptrace_single_step(struct thread *td) 77880708Sjake{ 779181701Smarius 780104271Sjake /* TODO; */ 78180708Sjake return (0); 78280708Sjake} 78380708Sjake 784132088Sdavidxuint 785132088Sdavidxuptrace_clear_single_step(struct thread *td) 786132088Sdavidxu{ 787181701Smarius 788132088Sdavidxu /* TODO; */ 789132088Sdavidxu return (0); 790132088Sdavidxu} 791132088Sdavidxu 79280708Sjakevoid 793102561Sjakeexec_setregs(struct thread *td, u_long entry, u_long stack, u_long ps_strings) 79480708Sjake{ 79588639Sjake struct trapframe *tf; 79681135Stmm struct pcb *pcb; 797102557Sjake struct proc *p; 79884178Sjake u_long sp; 79981135Stmm 80088782Sjake /* XXX no cpu_exec */ 801102557Sjake p = td->td_proc; 802102557Sjake p->p_md.md_sigtramp = NULL; 803140485Sjhb if (p->p_md.md_utrap != NULL) { 804140485Sjhb utrap_free(p->p_md.md_utrap); 805102557Sjake p->p_md.md_utrap = NULL; 80688782Sjake } 80788782Sjake 80883366Sjulian pcb = td->td_pcb; 809105908Sjake tf = td->td_frame; 81088639Sjake sp = rounddown(stack, 16); 81198032Sjake bzero(pcb, sizeof(*pcb)); 81298032Sjake bzero(tf, sizeof(*tf)); 81388639Sjake tf->tf_out[0] = stack; 814105908Sjake tf->tf_out[3] = p->p_sysent->sv_psstrings; 81588639Sjake tf->tf_out[6] = sp - SPOFF - sizeof(struct frame); 81688639Sjake tf->tf_tnpc = entry + 4; 81788639Sjake tf->tf_tpc = entry; 81888639Sjake tf->tf_tstate = TSTATE_IE | TSTATE_PEF | TSTATE_MM_TSO; 81988639Sjake 82088639Sjake td->td_retval[0] = tf->tf_out[0]; 82188639Sjake td->td_retval[1] = tf->tf_out[1]; 82280708Sjake} 82380708Sjake 82480708Sjakeint 82584178Sjakefill_regs(struct thread *td, struct reg *regs) 82680708Sjake{ 82780708Sjake 828105733Sjake bcopy(td->td_frame, regs, sizeof(*regs)); 82980708Sjake return (0); 83080708Sjake} 83180708Sjake 83280708Sjakeint 83384178Sjakeset_regs(struct thread *td, struct reg *regs) 83480708Sjake{ 835112922Sjake struct trapframe *tf; 83680708Sjake 83784178Sjake if (!TSTATE_SECURE(regs->r_tstate)) 83884178Sjake return (EINVAL); 839112922Sjake tf = td->td_frame; 840112922Sjake regs->r_wstate = tf->tf_wstate; 841112922Sjake bcopy(regs, tf, sizeof(*regs)); 84280708Sjake return (0); 84380708Sjake} 84480708Sjake 84580708Sjakeint 84685294Sdesfill_dbregs(struct thread *td, struct dbreg *dbregs) 84785294Sdes{ 84885294Sdes 84985294Sdes return (ENOSYS); 85085294Sdes} 85185294Sdes 85285294Sdesint 85385294Sdesset_dbregs(struct thread *td, struct dbreg *dbregs) 85485294Sdes{ 85585294Sdes 85685294Sdes return (ENOSYS); 85785294Sdes} 85885294Sdes 85985294Sdesint 86083366Sjulianfill_fpregs(struct thread *td, struct fpreg *fpregs) 86180708Sjake{ 86288639Sjake struct trapframe *tf; 86384178Sjake struct pcb *pcb; 86484178Sjake 86584178Sjake pcb = td->td_pcb; 86688639Sjake tf = td->td_frame; 867112920Sjake bcopy(pcb->pcb_ufp, fpregs->fr_regs, sizeof(fpregs->fr_regs)); 86888639Sjake fpregs->fr_fsr = tf->tf_fsr; 869105733Sjake fpregs->fr_gsr = tf->tf_gsr; 87080708Sjake return (0); 87180708Sjake} 87280708Sjake 87380708Sjakeint 87483366Sjulianset_fpregs(struct thread *td, struct fpreg *fpregs) 87580708Sjake{ 87688639Sjake struct trapframe *tf; 87784178Sjake struct pcb *pcb; 87884178Sjake 87984178Sjake pcb = td->td_pcb; 88088639Sjake tf = td->td_frame; 881112922Sjake tf->tf_fprs &= ~FPRS_FEF; 882112920Sjake bcopy(fpregs->fr_regs, pcb->pcb_ufp, sizeof(pcb->pcb_ufp)); 88388639Sjake tf->tf_fsr = fpregs->fr_fsr; 884105733Sjake tf->tf_gsr = fpregs->fr_gsr; 88580708Sjake return (0); 88680708Sjake} 887140485Sjhb 888140485Sjhbstruct md_utrap * 889140485Sjhbutrap_alloc(void) 890140485Sjhb{ 891140485Sjhb struct md_utrap *ut; 892140485Sjhb 893140485Sjhb ut = malloc(sizeof(struct md_utrap), M_SUBPROC, M_WAITOK | M_ZERO); 894140485Sjhb ut->ut_refcnt = 1; 895140485Sjhb return (ut); 896140485Sjhb} 897140485Sjhb 898140485Sjhbvoid 899140485Sjhbutrap_free(struct md_utrap *ut) 900140485Sjhb{ 901140485Sjhb int refcnt; 902140485Sjhb 903140485Sjhb if (ut == NULL) 904140485Sjhb return; 905140485Sjhb mtx_pool_lock(mtxpool_sleep, ut); 906140485Sjhb ut->ut_refcnt--; 907140485Sjhb refcnt = ut->ut_refcnt; 908140485Sjhb mtx_pool_unlock(mtxpool_sleep, ut); 909140485Sjhb if (refcnt == 0) 910140485Sjhb free(ut, M_SUBPROC); 911140485Sjhb} 912140485Sjhb 913140485Sjhbstruct md_utrap * 914140485Sjhbutrap_hold(struct md_utrap *ut) 915140485Sjhb{ 916140485Sjhb 917140485Sjhb if (ut == NULL) 918140485Sjhb return (NULL); 919140485Sjhb mtx_pool_lock(mtxpool_sleep, ut); 920140485Sjhb ut->ut_refcnt++; 921140485Sjhb mtx_pool_unlock(mtxpool_sleep, ut); 922140485Sjhb return (ut); 923140485Sjhb} 924