machdep.c revision 182768
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 182768 2008-09-04 19:58:52Z 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 136106555Stmmchar sparc64_model[32]; 137106555Stmm 138113166Sjakestatic int cpu_use_vis = 1; 139113166Sjake 140113166Sjakecpu_block_copy_t *cpu_block_copy; 141113166Sjakecpu_block_zero_t *cpu_block_zero; 142113166Sjake 14391616Sjakevoid sparc64_init(caddr_t mdp, u_long o1, u_long o2, u_long o3, 144181701Smarius ofw_vec_t *vec); 14586147Stmmvoid sparc64_shutdown_final(void *dummy, int howto); 14680709Sjake 14780709Sjakestatic void cpu_startup(void *); 14880709SjakeSYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL); 14980709Sjake 15091336SjakeCTASSERT((1 << INT_SHIFT) == sizeof(int)); 15191336SjakeCTASSERT((1 << PTR_SHIFT) == sizeof(char *)); 15291336Sjake 153105733SjakeCTASSERT(sizeof(struct reg) == 256); 154105733SjakeCTASSERT(sizeof(struct fpreg) == 272); 155105733SjakeCTASSERT(sizeof(struct __mcontext) == 512); 156105733Sjake 157113023SjakeCTASSERT((sizeof(struct pcb) & (64 - 1)) == 0); 158113023SjakeCTASSERT((offsetof(struct pcb, pcb_kfp) & (64 - 1)) == 0); 159113023SjakeCTASSERT((offsetof(struct pcb, pcb_ufp) & (64 - 1)) == 0); 160113023SjakeCTASSERT(sizeof(struct pcb) <= ((KSTACK_PAGES * PAGE_SIZE) / 8)); 161113023Sjake 16291360SjakeCTASSERT(sizeof(struct pcpu) <= ((PCPU_PAGES * PAGE_SIZE) / 2)); 16389038Sjake 16480709Sjakestatic void 16580709Sjakecpu_startup(void *arg) 16680709Sjake{ 167115971Sjake vm_paddr_t physsz; 168115971Sjake int i; 16980709Sjake 170115971Sjake physsz = 0; 171115971Sjake for (i = 0; i < sparc64_nmemreg; i++) 172115971Sjake physsz += sparc64_memreg[i].mr_size; 173115971Sjake printf("real memory = %lu (%lu MB)\n", physsz, 174115971Sjake physsz / (1024 * 1024)); 175155680Sjhb realmem = (long)physsz / PAGE_SIZE; 17680709Sjake 17782902Sjake vm_ksubmap_init(&kmi); 17880709Sjake 17980709Sjake bufinit(); 18080709Sjake vm_pager_bufferinit(); 18180709Sjake 18286147Stmm EVENTHANDLER_REGISTER(shutdown_final, sparc64_shutdown_final, NULL, 18386147Stmm SHUTDOWN_PRI_LAST); 184113338Sjake 185170170Sattilio printf("avail memory = %lu (%lu MB)\n", cnt.v_free_count * PAGE_SIZE, 186170170Sattilio cnt.v_free_count / ((1024 * 1024) / PAGE_SIZE)); 187113338Sjake 188113338Sjake if (bootverbose) 189113338Sjake printf("machine: %s\n", sparc64_model); 190113338Sjake 191182730Smarius cpu_identify(rdpr(ver), PCPU_GET(clock), curcpu); 19280709Sjake} 19380709Sjake 19487702Sjhbvoid 19587702Sjhbcpu_pcpu_init(struct pcpu *pcpu, int cpuid, size_t size) 19687702Sjhb{ 19797265Sjake struct intr_request *ir; 19897265Sjake int i; 19997265Sjake 20097265Sjake pcpu->pc_irtail = &pcpu->pc_irhead; 20197265Sjake for (i = 0; i < IR_FREE; i++) { 20297265Sjake ir = &pcpu->pc_irpool[i]; 20397265Sjake ir->ir_next = pcpu->pc_irfree; 20497265Sjake pcpu->pc_irfree = ir; 20597265Sjake } 20687702Sjhb} 20787702Sjhb 208144637Sjhbvoid 209144637Sjhbspinlock_enter(void) 210144637Sjhb{ 211144637Sjhb struct thread *td; 212145085Sjhb register_t pil; 213144637Sjhb 214144637Sjhb td = curthread; 215144637Sjhb if (td->td_md.md_spinlock_count == 0) { 216145085Sjhb pil = rdpr(pil); 217145151Smarius wrpr(pil, 0, PIL_TICK); 218145085Sjhb td->td_md.md_saved_pil = pil; 219144637Sjhb } 220144637Sjhb td->td_md.md_spinlock_count++; 221144637Sjhb critical_enter(); 222144637Sjhb} 223144637Sjhb 224144637Sjhbvoid 225144637Sjhbspinlock_exit(void) 226144637Sjhb{ 227144637Sjhb struct thread *td; 228144637Sjhb 229144637Sjhb td = curthread; 230144637Sjhb critical_exit(); 231144637Sjhb td->td_md.md_spinlock_count--; 232144637Sjhb if (td->td_md.md_spinlock_count == 0) 233144637Sjhb wrpr(pil, td->td_md.md_saved_pil, 0); 234144637Sjhb} 235144637Sjhb 23680708Sjakevoid 23791616Sjakesparc64_init(caddr_t mdp, u_long o1, u_long o2, u_long o3, ofw_vec_t *vec) 23880708Sjake{ 239181701Smarius char type[8]; 240181701Smarius char *env; 24189038Sjake struct pcpu *pc; 24286521Sjake vm_offset_t end; 24386521Sjake caddr_t kmdp; 244181701Smarius phandle_t child; 245181701Smarius phandle_t root; 246182689Smarius uint32_t portid; 24780709Sjake 24886521Sjake end = 0; 24986521Sjake kmdp = NULL; 25086521Sjake 25180709Sjake /* 252181701Smarius * Find out what kind of CPU we have first, for anything that changes 253112398Sjake * behaviour. 254112398Sjake */ 255112398Sjake cpu_impl = VER_IMPL(rdpr(ver)); 256112398Sjake 257112398Sjake /* 258182768Smarius * Do CPU-specific Initialization. 259182768Smarius */ 260182768Smarius if (cpu_impl >= CPU_IMPL_ULTRASPARCIII) 261182768Smarius cheetah_init(); 262182768Smarius 263182768Smarius /* 264182730Smarius * Clear (S)TICK timer (including NPT). 265182730Smarius */ 266182730Smarius tick_clear(); 267182730Smarius 268182730Smarius /* 269182730Smarius * UltraSparc II[e,i] based systems come up with the tick interrupt 270182730Smarius * enabled and a handler that resets the tick counter, causing DELAY() 271182730Smarius * to not work properly when used early in boot. 272182730Smarius * UltraSPARC III based systems come up with the system tick interrupt 273182730Smarius * enabled, causing an interrupt storm on startup since they are not 274182730Smarius * handled. 275182730Smarius */ 276182730Smarius tick_stop(); 277182730Smarius 278182730Smarius /* 279133862Smarius * Initialize Open Firmware (needed for console). 28080709Sjake */ 28180709Sjake OF_init(vec); 28280709Sjake 28380709Sjake /* 28486521Sjake * Parse metadata if present and fetch parameters. Must be before the 28586521Sjake * console is inited so cninit gets the right value of boothowto. 28686521Sjake */ 28786521Sjake if (mdp != NULL) { 28886521Sjake preload_metadata = mdp; 289114374Speter kmdp = preload_search_by_type("elf kernel"); 29086521Sjake if (kmdp != NULL) { 29186521Sjake boothowto = MD_FETCH(kmdp, MODINFOMD_HOWTO, int); 29286521Sjake kern_envp = MD_FETCH(kmdp, MODINFOMD_ENVP, char *); 29386521Sjake end = MD_FETCH(kmdp, MODINFOMD_KERNEND, vm_offset_t); 29491616Sjake kernel_tlb_slots = MD_FETCH(kmdp, MODINFOMD_DTLB_SLOTS, 29591616Sjake int); 29697445Sjake kernel_tlbs = (void *)preload_search_info(kmdp, 29791616Sjake MODINFO_METADATA | MODINFOMD_DTLB); 29886521Sjake } 29986521Sjake } 30086521Sjake 301122462Sjake init_param1(); 302122462Sjake 303182689Smarius /* 304182689Smarius * Prime our per-CPU data page for use. Note, we are using it for 305182689Smarius * our stack, so don't pass the real size (PAGE_SIZE) to pcpu_init 306182689Smarius * or it'll zero it out from under us. 307182689Smarius */ 308182689Smarius pc = (struct pcpu *)(pcpu0 + (PCPU_PAGES * PAGE_SIZE)) - 1; 309182689Smarius pcpu_init(pc, 0, sizeof(struct pcpu)); 310182689Smarius pc->pc_addr = (vm_offset_t)pcpu0; 311182689Smarius pc->pc_mid = UPA_CR_GET_MID(ldxa(0, ASI_UPA_CONFIG_REG)); 312182689Smarius pc->pc_tlb_ctx = TLB_CTX_USER_MIN; 313182689Smarius pc->pc_tlb_ctx_min = TLB_CTX_USER_MIN; 314182689Smarius pc->pc_tlb_ctx_max = TLB_CTX_USER_MAX; 315182689Smarius 316182689Smarius /* 317182730Smarius * Determine the OFW node and frequency of the BSP (and ensure the 318182689Smarius * BSP is in the device tree in the first place). 319182689Smarius */ 320182689Smarius pc->pc_node = 0; 321122462Sjake root = OF_peer(0); 322122462Sjake for (child = OF_child(root); child != 0; child = OF_peer(child)) { 323182689Smarius if (OF_getprop(child, "device_type", type, sizeof(type)) <= 0) 324182689Smarius continue; 325182689Smarius if (strcmp(type, "cpu") != 0) 326182689Smarius continue; 327182689Smarius if (OF_getprop(child, cpu_impl < CPU_IMPL_ULTRASPARCIII ? 328182689Smarius "upa-portid" : "portid", &portid, sizeof(portid)) <= 0) 329182689Smarius continue; 330182689Smarius if (portid == pc->pc_mid) { 331182689Smarius pc->pc_node = child; 332122462Sjake break; 333182689Smarius } 334122462Sjake } 335182689Smarius if (pc->pc_node == 0) 336182689Smarius OF_exit(); 337182730Smarius if (OF_getprop(child, "clock-frequency", &pc->pc_clock, 338182730Smarius sizeof(pc->pc_clock)) <= 0) 339182730Smarius OF_exit(); 340122462Sjake 341157227Smarius /* 342182730Smarius * Provide a DELAY() that works before PCPU_REG is set. We can't 343182730Smarius * set PCPU_REG without also taking over the trap table or the 344182730Smarius * firmware will overwrite it. Unfortunately, it's way to early 345182730Smarius * to also take over the trap table at this point. 346157227Smarius */ 347182730Smarius clock_boot = pc->pc_clock; 348182730Smarius delay_func = delay_boot; 349122462Sjake 35086521Sjake /* 35180709Sjake * Initialize the console before printing anything. 352182730Smarius * NB: the low-level console drivers require a working DELAY() at 353182730Smarius * this point. 35480709Sjake */ 35588639Sjake cninit(); 35680709Sjake 35780709Sjake /* 358157227Smarius * Panic if there is no metadata. Most likely the kernel was booted 35986521Sjake * directly, instead of through loader(8). 36080709Sjake */ 36186521Sjake if (mdp == NULL || kmdp == NULL) { 36286521Sjake printf("sparc64_init: no loader metadata.\n" 363181701Smarius "This probably means you are not using loader(8).\n"); 36486521Sjake panic("sparc64_init"); 36586521Sjake } 36680709Sjake 36781383Sjake /* 36886521Sjake * Sanity check the kernel end, which is important. 36986521Sjake */ 37086521Sjake if (end == 0) { 37186521Sjake printf("sparc64_init: warning, kernel end not specified.\n" 372181701Smarius "Attempting to continue anyway.\n"); 37386521Sjake end = (vm_offset_t)_end; 37486521Sjake } 37586521Sjake 376182689Smarius cache_init(pc); 377182689Smarius uma_set_align(pc->pc_cache.dc_linesize - 1); 378101898Sjake 379169178Smarius cpu_block_copy = bcopy; 380169178Smarius cpu_block_zero = bzero; 381113166Sjake getenv_int("machdep.use_vis", &cpu_use_vis); 382113166Sjake if (cpu_use_vis) { 383169178Smarius switch (cpu_impl) { 384169178Smarius case CPU_IMPL_SPARC64: 385169178Smarius case CPU_IMPL_ULTRASPARCI: 386169178Smarius case CPU_IMPL_ULTRASPARCII: 387169178Smarius case CPU_IMPL_ULTRASPARCIIi: 388169178Smarius case CPU_IMPL_ULTRASPARCIIe: 389169178Smarius cpu_block_copy = spitfire_block_copy; 390169178Smarius cpu_block_zero = spitfire_block_zero; 391169178Smarius break; 392169178Smarius } 393113166Sjake } 394113166Sjake 39591616Sjake#ifdef SMP 396170846Smarius mp_init(); 39791616Sjake#endif 39891616Sjake 39986521Sjake /* 40090625Stmm * Initialize virtual memory and calculate physmem. 40187546Sdillon */ 40290625Stmm pmap_bootstrap(end); 40387546Sdillon 40487546Sdillon /* 40581383Sjake * Initialize tunables. 40681383Sjake */ 40787546Sdillon init_param2(physmem); 408105569Smux env = getenv("kernelname"); 409105569Smux if (env != NULL) { 410105569Smux strlcpy(kernelname, env, sizeof(kernelname)); 411105569Smux freeenv(env); 412105569Smux } 41381085Sjake 41480709Sjake /* 41589038Sjake * Initialize the interrupt tables. 41689038Sjake */ 41790624Stmm intr_init1(); 41880709Sjake 41980709Sjake /* 420182689Smarius * Initialize proc0, set kstack0, frame0, curthread and curpcb. 42180709Sjake */ 422173361Skib proc_linkup0(&proc0, &thread0); 42395744Sjake proc0.p_md.md_sigtramp = NULL; 42488822Stmm proc0.p_md.md_utrap = NULL; 42590361Sjulian thread0.td_kstack = kstack0; 42690361Sjulian thread0.td_pcb = (struct pcb *) 42790361Sjulian (thread0.td_kstack + KSTACK_PAGES * PAGE_SIZE) - 1; 428105908Sjake frame0.tf_tstate = TSTATE_IE | TSTATE_PEF | TSTATE_PRIV; 42990361Sjulian thread0.td_frame = &frame0; 43090361Sjulian pc->pc_curthread = &thread0; 43191156Sjake pc->pc_curpcb = thread0.td_pcb; 43288639Sjake 43380709Sjake /* 434163973Sjb * Initialize global registers. 435163973Sjb */ 436163973Sjb cpu_setregs(pc); 437163973Sjb 438163973Sjb /* 439182730Smarius * It's now safe to use the real DELAY(). 440182730Smarius */ 441182730Smarius delay_func = delay_tick; 442182730Smarius 443182730Smarius /* 444108301Sjake * Initialize the message buffer (after setting trap table). 44588822Stmm */ 44688822Stmm msgbufinit(msgbufp, MSGBUF_SIZE); 44788822Stmm 44893702Sjhb mutex_init(); 44990624Stmm intr_init2(); 450105946Stmm 451133451Salc /* 452133451Salc * Finish pmap initialization now that we're ready for mutexes. 453133451Salc */ 454133451Salc PMAP_LOCK_INIT(kernel_pmap); 455133451Salc 456106555Stmm OF_getprop(root, "name", sparc64_model, sizeof(sparc64_model) - 1); 457122604Ssimokawa 458131950Smarcel kdb_init(); 459131950Smarcel 460131950Smarcel#ifdef KDB 461122604Ssimokawa if (boothowto & RB_KDB) 462174898Srwatson kdb_enter(KDB_WHY_BOOTFLAGS, "Boot flags requested debugger"); 463122604Ssimokawa#endif 46480708Sjake} 46580708Sjake 46680708Sjakevoid 46780709Sjakeset_openfirm_callback(ofw_vec_t *vec) 46880709Sjake{ 469181701Smarius 47080709Sjake ofw_tba = rdpr(tba); 47180709Sjake ofw_vec = (u_long)vec; 47280709Sjake} 47380709Sjake 47480709Sjakevoid 475151316Sdavidxusendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask) 47680708Sjake{ 47782902Sjake struct trapframe *tf; 47882902Sjake struct sigframe *sfp; 47982902Sjake struct sigacts *psp; 48082902Sjake struct sigframe sf; 48183366Sjulian struct thread *td; 48285242Sjake struct frame *fp; 48382902Sjake struct proc *p; 484181701Smarius u_long sp; 48585242Sjake int oonstack; 486151316Sdavidxu int sig; 48782902Sjake 48882902Sjake oonstack = 0; 48983366Sjulian td = curthread; 49083366Sjulian p = td->td_proc; 491114983Sjhb PROC_LOCK_ASSERT(p, MA_OWNED); 492151316Sdavidxu sig = ksi->ksi_signo; 49382902Sjake psp = p->p_sigacts; 494114983Sjhb mtx_assert(&psp->ps_mtx, MA_OWNED); 49583366Sjulian tf = td->td_frame; 49682902Sjake sp = tf->tf_sp + SPOFF; 49782902Sjake oonstack = sigonstack(sp); 49882902Sjake 49983366Sjulian CTR4(KTR_SIG, "sendsig: td=%p (%s) catcher=%p sig=%d", td, p->p_comm, 50082902Sjake catcher, sig); 50182902Sjake 502102554Sjake /* Make sure we have a signal trampoline to return to. */ 503102554Sjake if (p->p_md.md_sigtramp == NULL) { 504102554Sjake /* 505157445Smarius * No signal trampoline... kill the process. 506102554Sjake */ 507102554Sjake CTR0(KTR_SIG, "sendsig: no sigtramp"); 508102873Sjake printf("sendsig: %s is too old, rebuild it\n", p->p_comm); 509102554Sjake sigexit(td, sig); 510102554Sjake /* NOTREACHED */ 511102554Sjake } 512102554Sjake 51382902Sjake /* Save user context. */ 51482902Sjake bzero(&sf, sizeof(sf)); 515118708Sjake get_mcontext(td, &sf.sf_uc.uc_mcontext, 0); 51682902Sjake sf.sf_uc.uc_sigmask = *mask; 517124092Sdavidxu sf.sf_uc.uc_stack = td->td_sigstk; 518181701Smarius sf.sf_uc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK) ? 519181701Smarius ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE; 52082902Sjake 52182902Sjake /* Allocate and validate space for the signal handler context. */ 522124092Sdavidxu if ((td->td_pflags & TDP_ALTSTACK) != 0 && !oonstack && 52382902Sjake SIGISMEMBER(psp->ps_sigonstack, sig)) { 524124092Sdavidxu sfp = (struct sigframe *)(td->td_sigstk.ss_sp + 525124092Sdavidxu td->td_sigstk.ss_size - sizeof(struct sigframe)); 52682902Sjake } else 52782902Sjake sfp = (struct sigframe *)sp - 1; 528114983Sjhb mtx_unlock(&psp->ps_mtx); 52982902Sjake PROC_UNLOCK(p); 53082902Sjake 53185242Sjake fp = (struct frame *)sfp - 1; 53282902Sjake 53382902Sjake /* Translate the signal if appropriate. */ 53482902Sjake if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize) 53582902Sjake sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)]; 53682902Sjake 53782902Sjake /* Build the argument list for the signal handler. */ 53882902Sjake tf->tf_out[0] = sig; 53982902Sjake tf->tf_out[2] = (register_t)&sfp->sf_uc; 54082902Sjake tf->tf_out[4] = (register_t)catcher; 541157445Smarius if (SIGISMEMBER(psp->ps_siginfo, sig)) { 542157445Smarius /* Signal handler installed with SA_SIGINFO. */ 543157445Smarius tf->tf_out[1] = (register_t)&sfp->sf_si; 54482902Sjake 545157445Smarius /* Fill in POSIX parts. */ 546157445Smarius sf.sf_si = ksi->ksi_info; 547157445Smarius sf.sf_si.si_signo = sig; /* maybe a translated signal */ 548157445Smarius } else { 549157445Smarius /* Old FreeBSD-style arguments. */ 550157445Smarius tf->tf_out[1] = ksi->ksi_code; 551157445Smarius tf->tf_out[3] = (register_t)ksi->ksi_addr; 552157445Smarius } 553157445Smarius 55482902Sjake /* Copy the sigframe out to the user's stack. */ 55585242Sjake if (rwindow_save(td) != 0 || copyout(&sf, sfp, sizeof(*sfp)) != 0 || 55694254Sjake suword(&fp->fr_in[6], tf->tf_out[6]) != 0) { 55782902Sjake /* 55882902Sjake * Something is wrong with the stack pointer. 55982902Sjake * ...Kill the process. 56082902Sjake */ 56183366Sjulian CTR2(KTR_SIG, "sendsig: sigexit td=%p sfp=%p", td, sfp); 56282902Sjake PROC_LOCK(p); 56383366Sjulian sigexit(td, SIGILL); 56482902Sjake /* NOTREACHED */ 56582902Sjake } 56682902Sjake 567102554Sjake tf->tf_tpc = (u_long)p->p_md.md_sigtramp; 56882902Sjake tf->tf_tnpc = tf->tf_tpc + 4; 56985242Sjake tf->tf_sp = (u_long)fp - SPOFF; 57082902Sjake 57183366Sjulian CTR3(KTR_SIG, "sendsig: return td=%p pc=%#lx sp=%#lx", td, tf->tf_tpc, 57282902Sjake tf->tf_sp); 57384178Sjake 57484178Sjake PROC_LOCK(p); 575114983Sjhb mtx_lock(&psp->ps_mtx); 57680708Sjake} 57780708Sjake 57880708Sjake#ifndef _SYS_SYSPROTO_H_ 57983088Sobrienstruct sigreturn_args { 58080708Sjake ucontext_t *ucp; 58180708Sjake}; 58280708Sjake#endif 58380708Sjake 58494606Salc/* 58594606Salc * MPSAFE 58694606Salc */ 58780708Sjakeint 58883366Sjuliansigreturn(struct thread *td, struct sigreturn_args *uap) 58980708Sjake{ 59083366Sjulian struct proc *p; 591118768Sjake mcontext_t *mc; 59282902Sjake ucontext_t uc; 593118708Sjake int error; 59482902Sjake 59583366Sjulian p = td->td_proc; 59683366Sjulian if (rwindow_save(td)) { 59782902Sjake PROC_LOCK(p); 59883366Sjulian sigexit(td, SIGILL); 59982902Sjake } 60082902Sjake 60183366Sjulian CTR2(KTR_SIG, "sigreturn: td=%p ucp=%p", td, uap->sigcntxp); 60282902Sjake if (copyin(uap->sigcntxp, &uc, sizeof(uc)) != 0) { 60383366Sjulian CTR1(KTR_SIG, "sigreturn: efault td=%p", td); 60482902Sjake return (EFAULT); 60582902Sjake } 60682902Sjake 607118768Sjake mc = &uc.uc_mcontext; 608118768Sjake error = set_mcontext(td, mc); 609118708Sjake if (error != 0) 610118708Sjake return (error); 61182902Sjake 61282902Sjake PROC_LOCK(p); 613112888Sjeff td->td_sigmask = uc.uc_sigmask; 614112888Sjeff SIG_CANTMASK(td->td_sigmask); 615112888Sjeff signotify(td); 61682902Sjake PROC_UNLOCK(p); 617105733Sjake 61883366Sjulian CTR4(KTR_SIG, "sigreturn: return td=%p pc=%#lx sp=%#lx tstate=%#lx", 619118768Sjake td, mc->mc_tpc, mc->mc_sp, mc->mc_tstate); 62082902Sjake return (EJUSTRETURN); 62180708Sjake} 62280708Sjake 623105950Speter#ifdef COMPAT_FREEBSD4 624105950Speterint 625105950Speterfreebsd4_sigreturn(struct thread *td, struct freebsd4_sigreturn_args *uap) 626105950Speter{ 627105950Speter 628105950Speter return sigreturn(td, (struct sigreturn_args *)uap); 629105950Speter} 630105950Speter#endif 631105950Speter 632131905Smarcel/* 633131905Smarcel * Construct a PCB from a trapframe. This is called from kdb_trap() where 634131905Smarcel * we want to start a backtrace from the function that caused us to enter 635131905Smarcel * the debugger. We have the context in the trapframe, but base the trace 636131905Smarcel * on the PCB. The PCB doesn't have to be perfect, as long as it contains 637131905Smarcel * enough for a backtrace. 638131905Smarcel */ 639131905Smarcelvoid 640131905Smarcelmakectx(struct trapframe *tf, struct pcb *pcb) 641131905Smarcel{ 642131905Smarcel 643131905Smarcel pcb->pcb_pc = tf->tf_tpc; 644131905Smarcel pcb->pcb_sp = tf->tf_sp; 645131905Smarcel} 646131905Smarcel 647106977Sdeischenint 648122364Smarcelget_mcontext(struct thread *td, mcontext_t *mc, int flags) 649106977Sdeischen{ 650112924Sjake struct trapframe *tf; 651112924Sjake struct pcb *pcb; 652106977Sdeischen 653112924Sjake tf = td->td_frame; 654112924Sjake pcb = td->td_pcb; 655112924Sjake bcopy(tf, mc, sizeof(*tf)); 656122364Smarcel if (flags & GET_MC_CLEAR_RET) { 657113998Sdeischen mc->mc_out[0] = 0; 658113998Sdeischen mc->mc_out[1] = 0; 659113998Sdeischen } 660112961Sjake mc->mc_flags = _MC_VERSION; 661112924Sjake critical_enter(); 662112961Sjake if ((tf->tf_fprs & FPRS_FEF) != 0) { 663112961Sjake savefpctx(pcb->pcb_ufp); 664112961Sjake tf->tf_fprs &= ~FPRS_FEF; 665112961Sjake pcb->pcb_flags |= PCB_FEF; 666112961Sjake } 667112961Sjake if ((pcb->pcb_flags & PCB_FEF) != 0) { 668113018Sjake bcopy(pcb->pcb_ufp, mc->mc_fp, sizeof(mc->mc_fp)); 669112924Sjake mc->mc_fprs |= FPRS_FEF; 670112924Sjake } 671112924Sjake critical_exit(); 672112924Sjake return (0); 673106977Sdeischen} 674106977Sdeischen 675106977Sdeischenint 676112924Sjakeset_mcontext(struct thread *td, const mcontext_t *mc) 677106977Sdeischen{ 678112924Sjake struct trapframe *tf; 679112924Sjake struct pcb *pcb; 680112924Sjake uint64_t wstate; 681106977Sdeischen 682112961Sjake if (!TSTATE_SECURE(mc->mc_tstate) || 683112961Sjake (mc->mc_flags & ((1L << _MC_VERSION_BITS) - 1)) != _MC_VERSION) 684112924Sjake return (EINVAL); 685112924Sjake tf = td->td_frame; 686112924Sjake pcb = td->td_pcb; 687136325Skensmith /* Make sure the windows are spilled first. */ 688136325Skensmith flushw(); 689112924Sjake wstate = tf->tf_wstate; 690112924Sjake bcopy(mc, tf, sizeof(*tf)); 691112924Sjake tf->tf_wstate = wstate; 692112924Sjake if ((mc->mc_fprs & FPRS_FEF) != 0) { 693112924Sjake tf->tf_fprs = 0; 694113018Sjake bcopy(mc->mc_fp, pcb->pcb_ufp, sizeof(pcb->pcb_ufp)); 695112924Sjake pcb->pcb_flags |= PCB_FEF; 696112924Sjake } 697112924Sjake return (0); 698106977Sdeischen} 699106977Sdeischen 70086147Stmm/* 70192205Sjake * Exit the kernel and execute a firmware call that will not return, as 70292205Sjake * specified by the arguments. 70392205Sjake */ 70492205Sjakevoid 70592205Sjakecpu_shutdown(void *args) 70692205Sjake{ 70792205Sjake 70892205Sjake#ifdef SMP 70992205Sjake cpu_mp_shutdown(); 71092205Sjake#endif 71192205Sjake openfirmware_exit(args); 71292205Sjake} 71392205Sjake 714181701Smarius/* Get current clock frequency for the given CPU ID. */ 715141237Snjlint 716141237Snjlcpu_est_clockrate(int cpu_id, uint64_t *rate) 717141237Snjl{ 718182730Smarius struct pcpu *pc; 719141237Snjl 720182730Smarius pc = pcpu_find(cpu_id); 721182730Smarius if (pc == NULL || rate == NULL) 722182730Smarius return (EINVAL); 723182730Smarius *rate = pc->pc_clock; 724182730Smarius return (0); 725141237Snjl} 726141237Snjl 72792205Sjake/* 72886147Stmm * Duplicate OF_exit() with a different firmware call function that restores 72986147Stmm * the trap table, otherwise a RED state exception is triggered in at least 73086147Stmm * some firmware versions. 73186147Stmm */ 73280708Sjakevoid 73380708Sjakecpu_halt(void) 73480708Sjake{ 73586147Stmm static struct { 73686147Stmm cell_t name; 73786147Stmm cell_t nargs; 73886147Stmm cell_t nreturns; 73986147Stmm } args = { 74086147Stmm (cell_t)"exit", 74186147Stmm 0, 74286147Stmm 0 74386147Stmm }; 74484178Sjake 74592205Sjake cpu_shutdown(&args); 74680708Sjake} 74780708Sjake 74886147Stmmvoid 74986147Stmmsparc64_shutdown_final(void *dummy, int howto) 75086147Stmm{ 75186147Stmm static struct { 75286147Stmm cell_t name; 75386147Stmm cell_t nargs; 75486147Stmm cell_t nreturns; 75586147Stmm } args = { 75686147Stmm (cell_t)"SUNW,power-off", 75786147Stmm 0, 75886147Stmm 0 75986147Stmm }; 76086147Stmm 76186147Stmm /* Turn the power off? */ 76286147Stmm if ((howto & RB_POWEROFF) != 0) 76392205Sjake cpu_shutdown(&args); 76486147Stmm /* In case of halt, return to the firmware */ 76586147Stmm if ((howto & RB_HALT) != 0) 76686147Stmm cpu_halt(); 76786147Stmm} 76886147Stmm 769121237Spetervoid 770178471Sjeffcpu_idle(int busy) 771121237Speter{ 772181701Smarius 773181701Smarius /* Insert code to halt (until next interrupt) for the idle loop. */ 774121237Speter} 775121237Speter 77680708Sjakeint 777178471Sjeffcpu_idle_wakeup(int cpu) 778178471Sjeff{ 779178471Sjeff 780178471Sjeff return (0); 781178471Sjeff} 782178471Sjeff 783178471Sjeffint 78483366Sjulianptrace_set_pc(struct thread *td, u_long addr) 78580708Sjake{ 78682016Sjake 78783366Sjulian td->td_frame->tf_tpc = addr; 78883366Sjulian td->td_frame->tf_tnpc = addr + 4; 78980708Sjake return (0); 79080708Sjake} 79180708Sjake 79280708Sjakeint 79383366Sjulianptrace_single_step(struct thread *td) 79480708Sjake{ 795181701Smarius 796104271Sjake /* TODO; */ 79780708Sjake return (0); 79880708Sjake} 79980708Sjake 800132088Sdavidxuint 801132088Sdavidxuptrace_clear_single_step(struct thread *td) 802132088Sdavidxu{ 803181701Smarius 804132088Sdavidxu /* TODO; */ 805132088Sdavidxu return (0); 806132088Sdavidxu} 807132088Sdavidxu 80880708Sjakevoid 809102561Sjakeexec_setregs(struct thread *td, u_long entry, u_long stack, u_long ps_strings) 81080708Sjake{ 81188639Sjake struct trapframe *tf; 81281135Stmm struct pcb *pcb; 813102557Sjake struct proc *p; 81484178Sjake u_long sp; 81581135Stmm 81688782Sjake /* XXX no cpu_exec */ 817102557Sjake p = td->td_proc; 818102557Sjake p->p_md.md_sigtramp = NULL; 819140485Sjhb if (p->p_md.md_utrap != NULL) { 820140485Sjhb utrap_free(p->p_md.md_utrap); 821102557Sjake p->p_md.md_utrap = NULL; 82288782Sjake } 82388782Sjake 82483366Sjulian pcb = td->td_pcb; 825105908Sjake tf = td->td_frame; 82688639Sjake sp = rounddown(stack, 16); 82798032Sjake bzero(pcb, sizeof(*pcb)); 82898032Sjake bzero(tf, sizeof(*tf)); 82988639Sjake tf->tf_out[0] = stack; 830105908Sjake tf->tf_out[3] = p->p_sysent->sv_psstrings; 83188639Sjake tf->tf_out[6] = sp - SPOFF - sizeof(struct frame); 83288639Sjake tf->tf_tnpc = entry + 4; 83388639Sjake tf->tf_tpc = entry; 83488639Sjake tf->tf_tstate = TSTATE_IE | TSTATE_PEF | TSTATE_MM_TSO; 83588639Sjake 83688639Sjake td->td_retval[0] = tf->tf_out[0]; 83788639Sjake td->td_retval[1] = tf->tf_out[1]; 83880708Sjake} 83980708Sjake 84080708Sjakeint 84184178Sjakefill_regs(struct thread *td, struct reg *regs) 84280708Sjake{ 84380708Sjake 844105733Sjake bcopy(td->td_frame, regs, sizeof(*regs)); 84580708Sjake return (0); 84680708Sjake} 84780708Sjake 84880708Sjakeint 84984178Sjakeset_regs(struct thread *td, struct reg *regs) 85080708Sjake{ 851112922Sjake struct trapframe *tf; 85280708Sjake 85384178Sjake if (!TSTATE_SECURE(regs->r_tstate)) 85484178Sjake return (EINVAL); 855112922Sjake tf = td->td_frame; 856112922Sjake regs->r_wstate = tf->tf_wstate; 857112922Sjake bcopy(regs, tf, sizeof(*regs)); 85880708Sjake return (0); 85980708Sjake} 86080708Sjake 86180708Sjakeint 86285294Sdesfill_dbregs(struct thread *td, struct dbreg *dbregs) 86385294Sdes{ 86485294Sdes 86585294Sdes return (ENOSYS); 86685294Sdes} 86785294Sdes 86885294Sdesint 86985294Sdesset_dbregs(struct thread *td, struct dbreg *dbregs) 87085294Sdes{ 87185294Sdes 87285294Sdes return (ENOSYS); 87385294Sdes} 87485294Sdes 87585294Sdesint 87683366Sjulianfill_fpregs(struct thread *td, struct fpreg *fpregs) 87780708Sjake{ 87888639Sjake struct trapframe *tf; 87984178Sjake struct pcb *pcb; 88084178Sjake 88184178Sjake pcb = td->td_pcb; 88288639Sjake tf = td->td_frame; 883112920Sjake bcopy(pcb->pcb_ufp, fpregs->fr_regs, sizeof(fpregs->fr_regs)); 88488639Sjake fpregs->fr_fsr = tf->tf_fsr; 885105733Sjake fpregs->fr_gsr = tf->tf_gsr; 88680708Sjake return (0); 88780708Sjake} 88880708Sjake 88980708Sjakeint 89083366Sjulianset_fpregs(struct thread *td, struct fpreg *fpregs) 89180708Sjake{ 89288639Sjake struct trapframe *tf; 89384178Sjake struct pcb *pcb; 89484178Sjake 89584178Sjake pcb = td->td_pcb; 89688639Sjake tf = td->td_frame; 897112922Sjake tf->tf_fprs &= ~FPRS_FEF; 898112920Sjake bcopy(fpregs->fr_regs, pcb->pcb_ufp, sizeof(pcb->pcb_ufp)); 89988639Sjake tf->tf_fsr = fpregs->fr_fsr; 900105733Sjake tf->tf_gsr = fpregs->fr_gsr; 90180708Sjake return (0); 90280708Sjake} 903140485Sjhb 904140485Sjhbstruct md_utrap * 905140485Sjhbutrap_alloc(void) 906140485Sjhb{ 907140485Sjhb struct md_utrap *ut; 908140485Sjhb 909140485Sjhb ut = malloc(sizeof(struct md_utrap), M_SUBPROC, M_WAITOK | M_ZERO); 910140485Sjhb ut->ut_refcnt = 1; 911140485Sjhb return (ut); 912140485Sjhb} 913140485Sjhb 914140485Sjhbvoid 915140485Sjhbutrap_free(struct md_utrap *ut) 916140485Sjhb{ 917140485Sjhb int refcnt; 918140485Sjhb 919140485Sjhb if (ut == NULL) 920140485Sjhb return; 921140485Sjhb mtx_pool_lock(mtxpool_sleep, ut); 922140485Sjhb ut->ut_refcnt--; 923140485Sjhb refcnt = ut->ut_refcnt; 924140485Sjhb mtx_pool_unlock(mtxpool_sleep, ut); 925140485Sjhb if (refcnt == 0) 926140485Sjhb free(ut, M_SUBPROC); 927140485Sjhb} 928140485Sjhb 929140485Sjhbstruct md_utrap * 930140485Sjhbutrap_hold(struct md_utrap *ut) 931140485Sjhb{ 932140485Sjhb 933140485Sjhb if (ut == NULL) 934140485Sjhb return (NULL); 935140485Sjhb mtx_pool_lock(mtxpool_sleep, ut); 936140485Sjhb ut->ut_refcnt++; 937140485Sjhb mtx_pool_unlock(mtxpool_sleep, ut); 938140485Sjhb return (ut); 939140485Sjhb} 940