machdep.c revision 259102
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 259102 2013-12-08 15:25:19Z marius $"); 40145151Smarius 41105950Speter#include "opt_compat.h" 4280709Sjake#include "opt_ddb.h" 43118239Speter#include "opt_kstack_pages.h" 4480709Sjake 4580708Sjake#include <sys/param.h> 46141378Snjl#include <sys/malloc.h> 47141378Snjl#include <sys/proc.h> 4880708Sjake#include <sys/systm.h> 49141249Snjl#include <sys/bio.h> 50141249Snjl#include <sys/buf.h> 51141249Snjl#include <sys/bus.h> 52141249Snjl#include <sys/cpu.h> 5380709Sjake#include <sys/cons.h> 54141378Snjl#include <sys/eventhandler.h> 55141378Snjl#include <sys/exec.h> 56102561Sjake#include <sys/imgact.h> 57141378Snjl#include <sys/interrupt.h> 58131950Smarcel#include <sys/kdb.h> 5980709Sjake#include <sys/kernel.h> 6085262Sjake#include <sys/ktr.h> 6180709Sjake#include <sys/linker.h> 6280709Sjake#include <sys/lock.h> 6385242Sjake#include <sys/msgbuf.h> 6480708Sjake#include <sys/mutex.h> 6580709Sjake#include <sys/pcpu.h> 66141378Snjl#include <sys/ptrace.h> 6785242Sjake#include <sys/reboot.h> 68248084Sattilio#include <sys/rwlock.h> 6980708Sjake#include <sys/signalvar.h> 7091616Sjake#include <sys/smp.h> 71209613Sjhb#include <sys/syscallsubr.h> 7282902Sjake#include <sys/sysent.h> 7380708Sjake#include <sys/sysproto.h> 7480709Sjake#include <sys/timetc.h> 7591156Sjake#include <sys/ucontext.h> 7680708Sjake 7780708Sjake#include <dev/ofw/openfirm.h> 7880708Sjake 7980709Sjake#include <vm/vm.h> 80141378Snjl#include <vm/vm_extern.h> 8180709Sjake#include <vm/vm_kern.h> 8280709Sjake#include <vm/vm_page.h> 8380709Sjake#include <vm/vm_map.h> 84141378Snjl#include <vm/vm_object.h> 8580709Sjake#include <vm/vm_pager.h> 86141378Snjl#include <vm/vm_param.h> 8780709Sjake 8880709Sjake#include <ddb/ddb.h> 8980709Sjake 90119696Smarcel#include <machine/bus.h> 9186521Sjake#include <machine/cache.h> 92203838Smarius#include <machine/cmt.h> 9382902Sjake#include <machine/cpu.h> 94203838Smarius#include <machine/fireplane.h> 9583366Sjulian#include <machine/fp.h> 96112922Sjake#include <machine/fsr.h> 9781383Sjake#include <machine/intr_machdep.h> 98203838Smarius#include <machine/jbus.h> 9980708Sjake#include <machine/md_var.h> 10088436Sjake#include <machine/metadata.h> 10186147Stmm#include <machine/ofw_machdep.h> 102115971Sjake#include <machine/ofw_mem.h> 103138129Sdas#include <machine/pcb.h> 10480709Sjake#include <machine/pmap.h> 10580709Sjake#include <machine/pstate.h> 10680708Sjake#include <machine/reg.h> 10782902Sjake#include <machine/sigframe.h> 108141378Snjl#include <machine/smp.h> 10981383Sjake#include <machine/tick.h> 11091613Sjake#include <machine/tlb.h> 11182016Sjake#include <machine/tstate.h> 11291616Sjake#include <machine/upa.h> 11382902Sjake#include <machine/ver.h> 11480708Sjake 11580709Sjaketypedef int ofw_vec_t(void *); 11680708Sjake 117131950Smarcel#ifdef DDB 118131950Smarcelextern vm_offset_t ksym_start, ksym_end; 119131950Smarcel#endif 120131950Smarcel 121186682Smariusint dtlb_slots; 122186682Smariusint itlb_slots; 12397445Sjakestruct tlb_entry *kernel_tlbs; 12491616Sjakeint kernel_tlb_slots; 12591616Sjake 12680708Sjakeint cold = 1; 127102600Speterlong Maxmem; 128142956Sweslong realmem; 12980708Sjake 130194784Sjeffvoid *dpcpu0; 13191360Sjakechar pcpu0[PCPU_PAGES * PAGE_SIZE]; 13289038Sjakestruct trapframe frame0; 13380708Sjake 13489038Sjakevm_offset_t kstack0; 135113238Sjakevm_paddr_t kstack0_phys; 13688781Sjake 13782902Sjakestruct kva_md_info kmi; 13880709Sjake 13980709Sjakeu_long ofw_vec; 14080709Sjakeu_long ofw_tba; 141205409Smariusu_int tba_taken_over; 14280709Sjake 143106555Stmmchar sparc64_model[32]; 144106555Stmm 145113166Sjakestatic int cpu_use_vis = 1; 146113166Sjake 147113166Sjakecpu_block_copy_t *cpu_block_copy; 148113166Sjakecpu_block_zero_t *cpu_block_zero; 149113166Sjake 150204152Smariusstatic phandle_t find_bsp(phandle_t node, uint32_t bspid, u_int cpu_impl); 15191616Sjakevoid sparc64_init(caddr_t mdp, u_long o1, u_long o2, u_long o3, 152181701Smarius ofw_vec_t *vec); 153203838Smariusstatic void sparc64_shutdown_final(void *dummy, int howto); 15480709Sjake 155203838Smariusstatic void cpu_startup(void *arg); 15680709SjakeSYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL); 15780709Sjake 15891336SjakeCTASSERT((1 << INT_SHIFT) == sizeof(int)); 15991336SjakeCTASSERT((1 << PTR_SHIFT) == sizeof(char *)); 16091336Sjake 161105733SjakeCTASSERT(sizeof(struct reg) == 256); 162105733SjakeCTASSERT(sizeof(struct fpreg) == 272); 163105733SjakeCTASSERT(sizeof(struct __mcontext) == 512); 164105733Sjake 165113023SjakeCTASSERT((sizeof(struct pcb) & (64 - 1)) == 0); 166113023SjakeCTASSERT((offsetof(struct pcb, pcb_kfp) & (64 - 1)) == 0); 167113023SjakeCTASSERT((offsetof(struct pcb, pcb_ufp) & (64 - 1)) == 0); 168113023SjakeCTASSERT(sizeof(struct pcb) <= ((KSTACK_PAGES * PAGE_SIZE) / 8)); 169113023Sjake 17091360SjakeCTASSERT(sizeof(struct pcpu) <= ((PCPU_PAGES * PAGE_SIZE) / 2)); 17189038Sjake 17280709Sjakestatic void 17380709Sjakecpu_startup(void *arg) 17480709Sjake{ 175115971Sjake vm_paddr_t physsz; 176115971Sjake int i; 17780709Sjake 178115971Sjake physsz = 0; 179115971Sjake for (i = 0; i < sparc64_nmemreg; i++) 180115971Sjake physsz += sparc64_memreg[i].mr_size; 181115971Sjake printf("real memory = %lu (%lu MB)\n", physsz, 182115971Sjake physsz / (1024 * 1024)); 183155680Sjhb realmem = (long)physsz / PAGE_SIZE; 18480709Sjake 18582902Sjake vm_ksubmap_init(&kmi); 18680709Sjake 18780709Sjake bufinit(); 18880709Sjake vm_pager_bufferinit(); 18980709Sjake 19086147Stmm EVENTHANDLER_REGISTER(shutdown_final, sparc64_shutdown_final, NULL, 19186147Stmm SHUTDOWN_PRI_LAST); 192113338Sjake 193170170Sattilio printf("avail memory = %lu (%lu MB)\n", cnt.v_free_count * PAGE_SIZE, 194170170Sattilio cnt.v_free_count / ((1024 * 1024) / PAGE_SIZE)); 195113338Sjake 196113338Sjake if (bootverbose) 197113338Sjake printf("machine: %s\n", sparc64_model); 198113338Sjake 199182730Smarius cpu_identify(rdpr(ver), PCPU_GET(clock), curcpu); 20080709Sjake} 20180709Sjake 20287702Sjhbvoid 20387702Sjhbcpu_pcpu_init(struct pcpu *pcpu, int cpuid, size_t size) 20487702Sjhb{ 20597265Sjake struct intr_request *ir; 20697265Sjake int i; 20797265Sjake 20897265Sjake pcpu->pc_irtail = &pcpu->pc_irhead; 20997265Sjake for (i = 0; i < IR_FREE; i++) { 21097265Sjake ir = &pcpu->pc_irpool[i]; 21197265Sjake ir->ir_next = pcpu->pc_irfree; 21297265Sjake pcpu->pc_irfree = ir; 21397265Sjake } 21487702Sjhb} 21587702Sjhb 216144637Sjhbvoid 217144637Sjhbspinlock_enter(void) 218144637Sjhb{ 219144637Sjhb struct thread *td; 220145085Sjhb register_t pil; 221144637Sjhb 222144637Sjhb td = curthread; 223144637Sjhb if (td->td_md.md_spinlock_count == 0) { 224145085Sjhb pil = rdpr(pil); 225145151Smarius wrpr(pil, 0, PIL_TICK); 226214835Sjhb td->td_md.md_spinlock_count = 1; 227145085Sjhb td->td_md.md_saved_pil = pil; 228214835Sjhb } else 229214835Sjhb td->td_md.md_spinlock_count++; 230144637Sjhb critical_enter(); 231144637Sjhb} 232144637Sjhb 233144637Sjhbvoid 234144637Sjhbspinlock_exit(void) 235144637Sjhb{ 236144637Sjhb struct thread *td; 237214835Sjhb register_t pil; 238144637Sjhb 239144637Sjhb td = curthread; 240144637Sjhb critical_exit(); 241214835Sjhb pil = td->td_md.md_saved_pil; 242144637Sjhb td->td_md.md_spinlock_count--; 243144637Sjhb if (td->td_md.md_spinlock_count == 0) 244214835Sjhb wrpr(pil, pil, 0); 245144637Sjhb} 246144637Sjhb 247203838Smariusstatic phandle_t 248204152Smariusfind_bsp(phandle_t node, uint32_t bspid, u_int cpu_impl) 249203838Smarius{ 250203838Smarius char type[sizeof("cpu")]; 251203838Smarius phandle_t child; 252203838Smarius uint32_t cpuid; 253203838Smarius 254203838Smarius for (; node != 0; node = OF_peer(node)) { 255203838Smarius child = OF_child(node); 256203838Smarius if (child > 0) { 257204152Smarius child = find_bsp(child, bspid, cpu_impl); 258203838Smarius if (child > 0) 259203838Smarius return (child); 260203838Smarius } else { 261203838Smarius if (OF_getprop(node, "device_type", type, 262203838Smarius sizeof(type)) <= 0) 263203838Smarius continue; 264203838Smarius if (strcmp(type, "cpu") != 0) 265203838Smarius continue; 266204152Smarius if (OF_getprop(node, cpu_cpuid_prop(cpu_impl), &cpuid, 267203838Smarius sizeof(cpuid)) <= 0) 268203838Smarius continue; 269203838Smarius if (cpuid == bspid) 270203838Smarius return (node); 271203838Smarius } 272203838Smarius } 273203838Smarius return (0); 274203838Smarius} 275203838Smarius 276203838Smariusconst char * 277204152Smariuscpu_cpuid_prop(u_int cpu_impl) 278203838Smarius{ 279203838Smarius 280203838Smarius switch (cpu_impl) { 281203838Smarius case CPU_IMPL_SPARC64: 282207537Smarius case CPU_IMPL_SPARC64V: 283203838Smarius case CPU_IMPL_ULTRASPARCI: 284203838Smarius case CPU_IMPL_ULTRASPARCII: 285203838Smarius case CPU_IMPL_ULTRASPARCIIi: 286203838Smarius case CPU_IMPL_ULTRASPARCIIe: 287203838Smarius return ("upa-portid"); 288203838Smarius case CPU_IMPL_ULTRASPARCIII: 289203838Smarius case CPU_IMPL_ULTRASPARCIIIp: 290203838Smarius case CPU_IMPL_ULTRASPARCIIIi: 291203838Smarius case CPU_IMPL_ULTRASPARCIIIip: 292203838Smarius return ("portid"); 293203838Smarius case CPU_IMPL_ULTRASPARCIV: 294203838Smarius case CPU_IMPL_ULTRASPARCIVp: 295203838Smarius return ("cpuid"); 296203838Smarius default: 297203838Smarius return (""); 298203838Smarius } 299203838Smarius} 300203838Smarius 301203838Smariusuint32_t 302204152Smariuscpu_get_mid(u_int cpu_impl) 303203838Smarius{ 304203838Smarius 305203838Smarius switch (cpu_impl) { 306203838Smarius case CPU_IMPL_SPARC64: 307207537Smarius case CPU_IMPL_SPARC64V: 308203838Smarius case CPU_IMPL_ULTRASPARCI: 309203838Smarius case CPU_IMPL_ULTRASPARCII: 310203838Smarius case CPU_IMPL_ULTRASPARCIIi: 311203838Smarius case CPU_IMPL_ULTRASPARCIIe: 312203838Smarius return (UPA_CR_GET_MID(ldxa(0, ASI_UPA_CONFIG_REG))); 313203838Smarius case CPU_IMPL_ULTRASPARCIII: 314203838Smarius case CPU_IMPL_ULTRASPARCIIIp: 315203838Smarius return (FIREPLANE_CR_GET_AID(ldxa(AA_FIREPLANE_CONFIG, 316203838Smarius ASI_FIREPLANE_CONFIG_REG))); 317203838Smarius case CPU_IMPL_ULTRASPARCIIIi: 318203838Smarius case CPU_IMPL_ULTRASPARCIIIip: 319203838Smarius return (JBUS_CR_GET_JID(ldxa(0, ASI_JBUS_CONFIG_REG))); 320203838Smarius case CPU_IMPL_ULTRASPARCIV: 321203838Smarius case CPU_IMPL_ULTRASPARCIVp: 322203838Smarius return (INTR_ID_GET_ID(ldxa(AA_INTR_ID, ASI_INTR_ID))); 323203838Smarius default: 324203838Smarius return (0); 325203838Smarius } 326203838Smarius} 327203838Smarius 32880708Sjakevoid 32991616Sjakesparc64_init(caddr_t mdp, u_long o1, u_long o2, u_long o3, ofw_vec_t *vec) 33080708Sjake{ 331181701Smarius char *env; 33289038Sjake struct pcpu *pc; 33386521Sjake vm_offset_t end; 334195149Smarius vm_offset_t va; 33586521Sjake caddr_t kmdp; 336181701Smarius phandle_t root; 337204152Smarius u_int cpu_impl; 33880709Sjake 33986521Sjake end = 0; 34086521Sjake kmdp = NULL; 34186521Sjake 34280709Sjake /* 343181701Smarius * Find out what kind of CPU we have first, for anything that changes 344112398Sjake * behaviour. 345112398Sjake */ 346112398Sjake cpu_impl = VER_IMPL(rdpr(ver)); 347112398Sjake 348112398Sjake /* 349207248Smarius * Do CPU-specific initialization. 350182768Smarius */ 351223719Smarius if (cpu_impl >= CPU_IMPL_ULTRASPARCIII) 352204152Smarius cheetah_init(cpu_impl); 353223719Smarius else if (cpu_impl == CPU_IMPL_SPARC64V) 354223719Smarius zeus_init(cpu_impl); 355182768Smarius 356182768Smarius /* 357182730Smarius * Clear (S)TICK timer (including NPT). 358182730Smarius */ 359204152Smarius tick_clear(cpu_impl); 360182730Smarius 361182730Smarius /* 362182730Smarius * UltraSparc II[e,i] based systems come up with the tick interrupt 363182730Smarius * enabled and a handler that resets the tick counter, causing DELAY() 364182730Smarius * to not work properly when used early in boot. 365182730Smarius * UltraSPARC III based systems come up with the system tick interrupt 366182730Smarius * enabled, causing an interrupt storm on startup since they are not 367182730Smarius * handled. 368182730Smarius */ 369204152Smarius tick_stop(cpu_impl); 370182730Smarius 371182730Smarius /* 372186682Smarius * Set up Open Firmware entry points. 37380709Sjake */ 374186347Snwhitehorn ofw_tba = rdpr(tba); 375186347Snwhitehorn ofw_vec = (u_long)vec; 37680709Sjake 37780709Sjake /* 37886521Sjake * Parse metadata if present and fetch parameters. Must be before the 379230633Smarius * console is inited so cninit() gets the right value of boothowto. 38086521Sjake */ 38186521Sjake if (mdp != NULL) { 38286521Sjake preload_metadata = mdp; 383114374Speter kmdp = preload_search_by_type("elf kernel"); 38486521Sjake if (kmdp != NULL) { 38586521Sjake boothowto = MD_FETCH(kmdp, MODINFOMD_HOWTO, int); 38686521Sjake kern_envp = MD_FETCH(kmdp, MODINFOMD_ENVP, char *); 38786521Sjake end = MD_FETCH(kmdp, MODINFOMD_KERNEND, vm_offset_t); 38891616Sjake kernel_tlb_slots = MD_FETCH(kmdp, MODINFOMD_DTLB_SLOTS, 38991616Sjake int); 39097445Sjake kernel_tlbs = (void *)preload_search_info(kmdp, 39191616Sjake MODINFO_METADATA | MODINFOMD_DTLB); 39286521Sjake } 39386521Sjake } 39486521Sjake 395122462Sjake init_param1(); 396122462Sjake 397182689Smarius /* 398186347Snwhitehorn * Initialize Open Firmware (needed for console). 399186347Snwhitehorn */ 400186347Snwhitehorn OF_install(OFW_STD_DIRECT, 0); 401186347Snwhitehorn OF_init(ofw_entry); 402186347Snwhitehorn 403186347Snwhitehorn /* 404182689Smarius * Prime our per-CPU data page for use. Note, we are using it for 405182689Smarius * our stack, so don't pass the real size (PAGE_SIZE) to pcpu_init 406182689Smarius * or it'll zero it out from under us. 407182689Smarius */ 408182689Smarius pc = (struct pcpu *)(pcpu0 + (PCPU_PAGES * PAGE_SIZE)) - 1; 409182689Smarius pcpu_init(pc, 0, sizeof(struct pcpu)); 410182689Smarius pc->pc_addr = (vm_offset_t)pcpu0; 411204152Smarius pc->pc_impl = cpu_impl; 412204152Smarius pc->pc_mid = cpu_get_mid(cpu_impl); 413182689Smarius pc->pc_tlb_ctx = TLB_CTX_USER_MIN; 414182689Smarius pc->pc_tlb_ctx_min = TLB_CTX_USER_MIN; 415182689Smarius pc->pc_tlb_ctx_max = TLB_CTX_USER_MAX; 416182689Smarius 417182689Smarius /* 418182730Smarius * Determine the OFW node and frequency of the BSP (and ensure the 419182689Smarius * BSP is in the device tree in the first place). 420182689Smarius */ 421122462Sjake root = OF_peer(0); 422204152Smarius pc->pc_node = find_bsp(root, pc->pc_mid, cpu_impl); 423182689Smarius if (pc->pc_node == 0) 424230633Smarius OF_panic("%s: cannot find boot CPU node", __func__); 425203838Smarius if (OF_getprop(pc->pc_node, "clock-frequency", &pc->pc_clock, 426182730Smarius sizeof(pc->pc_clock)) <= 0) 427230633Smarius OF_panic("%s: cannot determine boot CPU clock", __func__); 428122462Sjake 429157227Smarius /* 430157227Smarius * Panic if there is no metadata. Most likely the kernel was booted 43186521Sjake * directly, instead of through loader(8). 43280709Sjake */ 433195149Smarius if (mdp == NULL || kmdp == NULL || end == 0 || 434230633Smarius kernel_tlb_slots == 0 || kernel_tlbs == NULL) 435230633Smarius OF_panic("%s: missing loader metadata.\nThis probably means " 436230633Smarius "you are not using loader(8).", __func__); 43780709Sjake 43881383Sjake /* 439195149Smarius * Work around the broken loader behavior of not demapping no 440195149Smarius * longer used kernel TLB slots when unloading the kernel or 441195149Smarius * modules. 44286521Sjake */ 443195149Smarius for (va = KERNBASE + (kernel_tlb_slots - 1) * PAGE_SIZE_4M; 444195149Smarius va >= roundup2(end, PAGE_SIZE_4M); va -= PAGE_SIZE_4M) { 445201396Smarius if (bootverbose) 446230633Smarius OF_printf("demapping unused kernel TLB slot " 447201396Smarius "(va %#lx - %#lx)\n", va, va + PAGE_SIZE_4M - 1); 448195149Smarius stxa(TLB_DEMAP_VA(va) | TLB_DEMAP_PRIMARY | TLB_DEMAP_PAGE, 449195149Smarius ASI_DMMU_DEMAP, 0); 450195149Smarius stxa(TLB_DEMAP_VA(va) | TLB_DEMAP_PRIMARY | TLB_DEMAP_PAGE, 451195149Smarius ASI_IMMU_DEMAP, 0); 452195149Smarius flush(KERNBASE); 453195149Smarius kernel_tlb_slots--; 45486521Sjake } 45586521Sjake 456186682Smarius /* 457186682Smarius * Determine the TLB slot maxima, which are expected to be 458186682Smarius * equal across all CPUs. 459205409Smarius * NB: for cheetah-class CPUs, these properties only refer 460186682Smarius * to the t16s. 461186682Smarius */ 462186682Smarius if (OF_getprop(pc->pc_node, "#dtlb-entries", &dtlb_slots, 463186682Smarius sizeof(dtlb_slots)) == -1) 464230633Smarius OF_panic("%s: cannot determine number of dTLB slots", 465230633Smarius __func__); 466186682Smarius if (OF_getprop(pc->pc_node, "#itlb-entries", &itlb_slots, 467186682Smarius sizeof(itlb_slots)) == -1) 468230633Smarius OF_panic("%s: cannot determine number of iTLB slots", 469230633Smarius __func__); 470186682Smarius 471207248Smarius /* 472230633Smarius * Initialize and enable the caches. Note that this may include 473207248Smarius * applying workarounds. 474207248Smarius */ 475182689Smarius cache_init(pc); 476204152Smarius cache_enable(cpu_impl); 477182689Smarius uma_set_align(pc->pc_cache.dc_linesize - 1); 478101898Sjake 479169178Smarius cpu_block_copy = bcopy; 480169178Smarius cpu_block_zero = bzero; 481113166Sjake getenv_int("machdep.use_vis", &cpu_use_vis); 482113166Sjake if (cpu_use_vis) { 483169178Smarius switch (cpu_impl) { 484169178Smarius case CPU_IMPL_SPARC64: 485169178Smarius case CPU_IMPL_ULTRASPARCI: 486169178Smarius case CPU_IMPL_ULTRASPARCII: 487169178Smarius case CPU_IMPL_ULTRASPARCIIi: 488169178Smarius case CPU_IMPL_ULTRASPARCIIe: 489185007Smarius case CPU_IMPL_ULTRASPARCIII: /* NB: we've disabled P$. */ 490185007Smarius case CPU_IMPL_ULTRASPARCIIIp: 491185007Smarius case CPU_IMPL_ULTRASPARCIIIi: 492185007Smarius case CPU_IMPL_ULTRASPARCIV: 493185007Smarius case CPU_IMPL_ULTRASPARCIVp: 494185007Smarius case CPU_IMPL_ULTRASPARCIIIip: 495169178Smarius cpu_block_copy = spitfire_block_copy; 496169178Smarius cpu_block_zero = spitfire_block_zero; 497169178Smarius break; 498212709Smarius case CPU_IMPL_SPARC64V: 499212709Smarius cpu_block_copy = zeus_block_copy; 500212709Smarius cpu_block_zero = zeus_block_zero; 501212709Smarius break; 502169178Smarius } 503113166Sjake } 504113166Sjake 50591616Sjake#ifdef SMP 506204152Smarius mp_init(cpu_impl); 50791616Sjake#endif 50891616Sjake 50986521Sjake /* 51090625Stmm * Initialize virtual memory and calculate physmem. 51187546Sdillon */ 512204152Smarius pmap_bootstrap(cpu_impl); 51387546Sdillon 51487546Sdillon /* 51581383Sjake * Initialize tunables. 51681383Sjake */ 51787546Sdillon init_param2(physmem); 518105569Smux env = getenv("kernelname"); 519105569Smux if (env != NULL) { 520219523Smdf strlcpy(kernelname, env, sizeof(kernelname)); 521105569Smux freeenv(env); 522105569Smux } 52381085Sjake 52480709Sjake /* 52589038Sjake * Initialize the interrupt tables. 52689038Sjake */ 52790624Stmm intr_init1(); 52880709Sjake 52980709Sjake /* 530182689Smarius * Initialize proc0, set kstack0, frame0, curthread and curpcb. 53180709Sjake */ 532173361Skib proc_linkup0(&proc0, &thread0); 53395744Sjake proc0.p_md.md_sigtramp = NULL; 53488822Stmm proc0.p_md.md_utrap = NULL; 53590361Sjulian thread0.td_kstack = kstack0; 536218468Smarius thread0.td_kstack_pages = KSTACK_PAGES; 53790361Sjulian thread0.td_pcb = (struct pcb *) 53890361Sjulian (thread0.td_kstack + KSTACK_PAGES * PAGE_SIZE) - 1; 539105908Sjake frame0.tf_tstate = TSTATE_IE | TSTATE_PEF | TSTATE_PRIV; 54090361Sjulian thread0.td_frame = &frame0; 54190361Sjulian pc->pc_curthread = &thread0; 54291156Sjake pc->pc_curpcb = thread0.td_pcb; 54388639Sjake 54480709Sjake /* 545163973Sjb * Initialize global registers. 546163973Sjb */ 547163973Sjb cpu_setregs(pc); 548163973Sjb 549163973Sjb /* 550182773Smarius * Take over the trap table via the PROM. Using the PROM for this 551182773Smarius * is necessary in order to set obp-control-relinquished to true 552182773Smarius * within the PROM so obtaining /virtual-memory/translations doesn't 553182773Smarius * trigger a fatal reset error or worse things further down the road. 554220939Smarius * XXX it should be possible to use this solely instead of writing 555182773Smarius * %tba in cpu_setregs(). Doing so causes a hang however. 556259102Smarius * 557259102Smarius * NB: the low-level console drivers require a working DELAY() and 558259102Smarius * some compiler optimizations may cause the curthread accesses of 559259102Smarius * mutex(9) to be factored out even if the latter aren't actually 560259102Smarius * called. Both of these require PCPU_REG to be set. However, we 561259102Smarius * can't set PCPU_REG without also taking over the trap table or the 562259102Smarius * firmware will overwrite it. 563182773Smarius */ 564182773Smarius sun4u_set_traptable(tl0_base); 565182773Smarius 566182773Smarius /* 567194784Sjeff * Initialize the dynamic per-CPU area for the BSP and the message 568194784Sjeff * buffer (after setting the trap table). 56988822Stmm */ 570194784Sjeff dpcpu_init(dpcpu0, 0); 571217688Spluknet msgbufinit(msgbufp, msgbufsize); 57288822Stmm 573207248Smarius /* 574207248Smarius * Initialize mutexes. 575207248Smarius */ 57693702Sjhb mutex_init(); 577207248Smarius 578207248Smarius /* 579259016Sray * Initialize console now that we have a reasonable set of system 580259016Sray * services. 581259016Sray */ 582259016Sray cninit(); 583259016Sray 584259016Sray /* 585207248Smarius * Finish the interrupt initialization now that mutexes work and 586207248Smarius * enable them. 587207248Smarius */ 58890624Stmm intr_init2(); 589213873Smarius wrpr(pil, 0, 0); 590207248Smarius wrpr(pstate, 0, PSTATE_KERNEL); 591105946Stmm 592106555Stmm OF_getprop(root, "name", sparc64_model, sizeof(sparc64_model) - 1); 593122604Ssimokawa 594131950Smarcel kdb_init(); 595131950Smarcel 596190161Smarius#ifdef KDB 597122604Ssimokawa if (boothowto & RB_KDB) 598174898Srwatson kdb_enter(KDB_WHY_BOOTFLAGS, "Boot flags requested debugger"); 599190161Smarius#endif 60080708Sjake} 60180708Sjake 60280708Sjakevoid 603151316Sdavidxusendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask) 60480708Sjake{ 60582902Sjake struct trapframe *tf; 60682902Sjake struct sigframe *sfp; 60782902Sjake struct sigacts *psp; 60882902Sjake struct sigframe sf; 60983366Sjulian struct thread *td; 61085242Sjake struct frame *fp; 61182902Sjake struct proc *p; 612181701Smarius u_long sp; 61385242Sjake int oonstack; 614151316Sdavidxu int sig; 61582902Sjake 61682902Sjake oonstack = 0; 61783366Sjulian td = curthread; 61883366Sjulian p = td->td_proc; 619114983Sjhb PROC_LOCK_ASSERT(p, MA_OWNED); 620151316Sdavidxu sig = ksi->ksi_signo; 62182902Sjake psp = p->p_sigacts; 622114983Sjhb mtx_assert(&psp->ps_mtx, MA_OWNED); 62383366Sjulian tf = td->td_frame; 62482902Sjake sp = tf->tf_sp + SPOFF; 62582902Sjake oonstack = sigonstack(sp); 62682902Sjake 62783366Sjulian CTR4(KTR_SIG, "sendsig: td=%p (%s) catcher=%p sig=%d", td, p->p_comm, 62882902Sjake catcher, sig); 62982902Sjake 630102554Sjake /* Make sure we have a signal trampoline to return to. */ 631102554Sjake if (p->p_md.md_sigtramp == NULL) { 632102554Sjake /* 633157445Smarius * No signal trampoline... kill the process. 634102554Sjake */ 635102554Sjake CTR0(KTR_SIG, "sendsig: no sigtramp"); 636102873Sjake printf("sendsig: %s is too old, rebuild it\n", p->p_comm); 637102554Sjake sigexit(td, sig); 638102554Sjake /* NOTREACHED */ 639102554Sjake } 640102554Sjake 64182902Sjake /* Save user context. */ 64282902Sjake bzero(&sf, sizeof(sf)); 643118708Sjake get_mcontext(td, &sf.sf_uc.uc_mcontext, 0); 64482902Sjake sf.sf_uc.uc_sigmask = *mask; 645124092Sdavidxu sf.sf_uc.uc_stack = td->td_sigstk; 646181701Smarius sf.sf_uc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK) ? 647181701Smarius ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE; 64882902Sjake 64982902Sjake /* Allocate and validate space for the signal handler context. */ 650124092Sdavidxu if ((td->td_pflags & TDP_ALTSTACK) != 0 && !oonstack && 65182902Sjake SIGISMEMBER(psp->ps_sigonstack, sig)) { 652124092Sdavidxu sfp = (struct sigframe *)(td->td_sigstk.ss_sp + 653124092Sdavidxu td->td_sigstk.ss_size - sizeof(struct sigframe)); 65482902Sjake } else 65582902Sjake sfp = (struct sigframe *)sp - 1; 656114983Sjhb mtx_unlock(&psp->ps_mtx); 65782902Sjake PROC_UNLOCK(p); 65882902Sjake 65985242Sjake fp = (struct frame *)sfp - 1; 66082902Sjake 66182902Sjake /* Translate the signal if appropriate. */ 66282902Sjake if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize) 66382902Sjake sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)]; 66482902Sjake 66582902Sjake /* Build the argument list for the signal handler. */ 66682902Sjake tf->tf_out[0] = sig; 66782902Sjake tf->tf_out[2] = (register_t)&sfp->sf_uc; 66882902Sjake tf->tf_out[4] = (register_t)catcher; 669157445Smarius if (SIGISMEMBER(psp->ps_siginfo, sig)) { 670157445Smarius /* Signal handler installed with SA_SIGINFO. */ 671157445Smarius tf->tf_out[1] = (register_t)&sfp->sf_si; 67282902Sjake 673157445Smarius /* Fill in POSIX parts. */ 674157445Smarius sf.sf_si = ksi->ksi_info; 675157445Smarius sf.sf_si.si_signo = sig; /* maybe a translated signal */ 676157445Smarius } else { 677157445Smarius /* Old FreeBSD-style arguments. */ 678157445Smarius tf->tf_out[1] = ksi->ksi_code; 679157445Smarius tf->tf_out[3] = (register_t)ksi->ksi_addr; 680157445Smarius } 681157445Smarius 68282902Sjake /* Copy the sigframe out to the user's stack. */ 68385242Sjake if (rwindow_save(td) != 0 || copyout(&sf, sfp, sizeof(*sfp)) != 0 || 68494254Sjake suword(&fp->fr_in[6], tf->tf_out[6]) != 0) { 68582902Sjake /* 68682902Sjake * Something is wrong with the stack pointer. 68782902Sjake * ...Kill the process. 68882902Sjake */ 68983366Sjulian CTR2(KTR_SIG, "sendsig: sigexit td=%p sfp=%p", td, sfp); 69082902Sjake PROC_LOCK(p); 69183366Sjulian sigexit(td, SIGILL); 69282902Sjake /* NOTREACHED */ 69382902Sjake } 69482902Sjake 695102554Sjake tf->tf_tpc = (u_long)p->p_md.md_sigtramp; 69682902Sjake tf->tf_tnpc = tf->tf_tpc + 4; 69785242Sjake tf->tf_sp = (u_long)fp - SPOFF; 69882902Sjake 69983366Sjulian CTR3(KTR_SIG, "sendsig: return td=%p pc=%#lx sp=%#lx", td, tf->tf_tpc, 70082902Sjake tf->tf_sp); 70184178Sjake 70284178Sjake PROC_LOCK(p); 703114983Sjhb mtx_lock(&psp->ps_mtx); 70480708Sjake} 70580708Sjake 70680708Sjake#ifndef _SYS_SYSPROTO_H_ 70783088Sobrienstruct sigreturn_args { 70880708Sjake ucontext_t *ucp; 70980708Sjake}; 71080708Sjake#endif 71180708Sjake 71294606Salc/* 71394606Salc * MPSAFE 71494606Salc */ 71580708Sjakeint 716225617Skmacysys_sigreturn(struct thread *td, struct sigreturn_args *uap) 71780708Sjake{ 71883366Sjulian struct proc *p; 719118768Sjake mcontext_t *mc; 72082902Sjake ucontext_t uc; 721118708Sjake int error; 72282902Sjake 72383366Sjulian p = td->td_proc; 72483366Sjulian if (rwindow_save(td)) { 72582902Sjake PROC_LOCK(p); 72683366Sjulian sigexit(td, SIGILL); 72782902Sjake } 72882902Sjake 72983366Sjulian CTR2(KTR_SIG, "sigreturn: td=%p ucp=%p", td, uap->sigcntxp); 73082902Sjake if (copyin(uap->sigcntxp, &uc, sizeof(uc)) != 0) { 73183366Sjulian CTR1(KTR_SIG, "sigreturn: efault td=%p", td); 73282902Sjake return (EFAULT); 73382902Sjake } 73482902Sjake 735118768Sjake mc = &uc.uc_mcontext; 736118768Sjake error = set_mcontext(td, mc); 737118708Sjake if (error != 0) 738118708Sjake return (error); 73982902Sjake 740198507Skib kern_sigprocmask(td, SIG_SETMASK, &uc.uc_sigmask, NULL, 0); 741105733Sjake 74283366Sjulian CTR4(KTR_SIG, "sigreturn: return td=%p pc=%#lx sp=%#lx tstate=%#lx", 743253266Smarius td, mc->_mc_tpc, mc->_mc_sp, mc->_mc_tstate); 74482902Sjake return (EJUSTRETURN); 74580708Sjake} 74680708Sjake 747131905Smarcel/* 748131905Smarcel * Construct a PCB from a trapframe. This is called from kdb_trap() where 749131905Smarcel * we want to start a backtrace from the function that caused us to enter 750131905Smarcel * the debugger. We have the context in the trapframe, but base the trace 751131905Smarcel * on the PCB. The PCB doesn't have to be perfect, as long as it contains 752131905Smarcel * enough for a backtrace. 753131905Smarcel */ 754131905Smarcelvoid 755131905Smarcelmakectx(struct trapframe *tf, struct pcb *pcb) 756131905Smarcel{ 757131905Smarcel 758131905Smarcel pcb->pcb_pc = tf->tf_tpc; 759131905Smarcel pcb->pcb_sp = tf->tf_sp; 760131905Smarcel} 761131905Smarcel 762106977Sdeischenint 763122364Smarcelget_mcontext(struct thread *td, mcontext_t *mc, int flags) 764106977Sdeischen{ 765112924Sjake struct trapframe *tf; 766112924Sjake struct pcb *pcb; 767106977Sdeischen 768112924Sjake tf = td->td_frame; 769112924Sjake pcb = td->td_pcb; 770199442Smarius /* 771199442Smarius * Copy the registers which will be restored by tl0_ret() from the 772199442Smarius * trapframe. 773199442Smarius * Note that we skip %g7 which is used as the userland TLS register 774199442Smarius * and %wstate. 775199442Smarius */ 776253266Smarius mc->_mc_flags = _MC_VERSION; 777199442Smarius mc->mc_global[1] = tf->tf_global[1]; 778199442Smarius mc->mc_global[2] = tf->tf_global[2]; 779199442Smarius mc->mc_global[3] = tf->tf_global[3]; 780199442Smarius mc->mc_global[4] = tf->tf_global[4]; 781199442Smarius mc->mc_global[5] = tf->tf_global[5]; 782199442Smarius mc->mc_global[6] = tf->tf_global[6]; 783122364Smarcel if (flags & GET_MC_CLEAR_RET) { 784113998Sdeischen mc->mc_out[0] = 0; 785113998Sdeischen mc->mc_out[1] = 0; 786199442Smarius } else { 787199442Smarius mc->mc_out[0] = tf->tf_out[0]; 788199442Smarius mc->mc_out[1] = tf->tf_out[1]; 789113998Sdeischen } 790199442Smarius mc->mc_out[2] = tf->tf_out[2]; 791199442Smarius mc->mc_out[3] = tf->tf_out[3]; 792199442Smarius mc->mc_out[4] = tf->tf_out[4]; 793199442Smarius mc->mc_out[5] = tf->tf_out[5]; 794199442Smarius mc->mc_out[6] = tf->tf_out[6]; 795199442Smarius mc->mc_out[7] = tf->tf_out[7]; 796253266Smarius mc->_mc_fprs = tf->tf_fprs; 797253266Smarius mc->_mc_fsr = tf->tf_fsr; 798253266Smarius mc->_mc_gsr = tf->tf_gsr; 799253266Smarius mc->_mc_tnpc = tf->tf_tnpc; 800253266Smarius mc->_mc_tpc = tf->tf_tpc; 801253266Smarius mc->_mc_tstate = tf->tf_tstate; 802253266Smarius mc->_mc_y = tf->tf_y; 803112924Sjake critical_enter(); 804112961Sjake if ((tf->tf_fprs & FPRS_FEF) != 0) { 805112961Sjake savefpctx(pcb->pcb_ufp); 806112961Sjake tf->tf_fprs &= ~FPRS_FEF; 807112961Sjake pcb->pcb_flags |= PCB_FEF; 808112961Sjake } 809112961Sjake if ((pcb->pcb_flags & PCB_FEF) != 0) { 810113018Sjake bcopy(pcb->pcb_ufp, mc->mc_fp, sizeof(mc->mc_fp)); 811253266Smarius mc->_mc_fprs |= FPRS_FEF; 812112924Sjake } 813112924Sjake critical_exit(); 814112924Sjake return (0); 815106977Sdeischen} 816106977Sdeischen 817106977Sdeischenint 818112924Sjakeset_mcontext(struct thread *td, const mcontext_t *mc) 819106977Sdeischen{ 820112924Sjake struct trapframe *tf; 821112924Sjake struct pcb *pcb; 822106977Sdeischen 823253266Smarius if (!TSTATE_SECURE(mc->_mc_tstate) || 824253266Smarius (mc->_mc_flags & ((1L << _MC_VERSION_BITS) - 1)) != _MC_VERSION) 825112924Sjake return (EINVAL); 826112924Sjake tf = td->td_frame; 827112924Sjake pcb = td->td_pcb; 828136325Skensmith /* Make sure the windows are spilled first. */ 829136325Skensmith flushw(); 830199442Smarius /* 831199442Smarius * Copy the registers which will be restored by tl0_ret() to the 832199442Smarius * trapframe. 833199442Smarius * Note that we skip %g7 which is used as the userland TLS register 834199442Smarius * and %wstate. 835199442Smarius */ 836199442Smarius tf->tf_global[1] = mc->mc_global[1]; 837199442Smarius tf->tf_global[2] = mc->mc_global[2]; 838199442Smarius tf->tf_global[3] = mc->mc_global[3]; 839199442Smarius tf->tf_global[4] = mc->mc_global[4]; 840199442Smarius tf->tf_global[5] = mc->mc_global[5]; 841199442Smarius tf->tf_global[6] = mc->mc_global[6]; 842199442Smarius tf->tf_out[0] = mc->mc_out[0]; 843199442Smarius tf->tf_out[1] = mc->mc_out[1]; 844199442Smarius tf->tf_out[2] = mc->mc_out[2]; 845199442Smarius tf->tf_out[3] = mc->mc_out[3]; 846199442Smarius tf->tf_out[4] = mc->mc_out[4]; 847199442Smarius tf->tf_out[5] = mc->mc_out[5]; 848199442Smarius tf->tf_out[6] = mc->mc_out[6]; 849199442Smarius tf->tf_out[7] = mc->mc_out[7]; 850253266Smarius tf->tf_fprs = mc->_mc_fprs; 851253266Smarius tf->tf_fsr = mc->_mc_fsr; 852253266Smarius tf->tf_gsr = mc->_mc_gsr; 853253266Smarius tf->tf_tnpc = mc->_mc_tnpc; 854253266Smarius tf->tf_tpc = mc->_mc_tpc; 855253266Smarius tf->tf_tstate = mc->_mc_tstate; 856253266Smarius tf->tf_y = mc->_mc_y; 857253266Smarius if ((mc->_mc_fprs & FPRS_FEF) != 0) { 858112924Sjake tf->tf_fprs = 0; 859113018Sjake bcopy(mc->mc_fp, pcb->pcb_ufp, sizeof(pcb->pcb_ufp)); 860112924Sjake pcb->pcb_flags |= PCB_FEF; 861112924Sjake } 862112924Sjake return (0); 863106977Sdeischen} 864106977Sdeischen 86586147Stmm/* 86692205Sjake * Exit the kernel and execute a firmware call that will not return, as 86792205Sjake * specified by the arguments. 86892205Sjake */ 86992205Sjakevoid 87092205Sjakecpu_shutdown(void *args) 87192205Sjake{ 87292205Sjake 87392205Sjake#ifdef SMP 87492205Sjake cpu_mp_shutdown(); 87592205Sjake#endif 876186347Snwhitehorn ofw_exit(args); 87792205Sjake} 87892205Sjake 879192323Smarcel/* 880192323Smarcel * Flush the D-cache for non-DMA I/O so that the I-cache can 881192323Smarcel * be made coherent later. 882192323Smarcel */ 883192323Smarcelvoid 884192323Smarcelcpu_flush_dcache(void *ptr, size_t len) 885192323Smarcel{ 886195149Smarius 887192323Smarcel /* TBD */ 888192323Smarcel} 889192323Smarcel 890181701Smarius/* Get current clock frequency for the given CPU ID. */ 891141237Snjlint 892141237Snjlcpu_est_clockrate(int cpu_id, uint64_t *rate) 893141237Snjl{ 894182730Smarius struct pcpu *pc; 895141237Snjl 896182730Smarius pc = pcpu_find(cpu_id); 897182730Smarius if (pc == NULL || rate == NULL) 898182730Smarius return (EINVAL); 899182730Smarius *rate = pc->pc_clock; 900182730Smarius return (0); 901141237Snjl} 902141237Snjl 90392205Sjake/* 90486147Stmm * Duplicate OF_exit() with a different firmware call function that restores 90586147Stmm * the trap table, otherwise a RED state exception is triggered in at least 90686147Stmm * some firmware versions. 90786147Stmm */ 90880708Sjakevoid 90980708Sjakecpu_halt(void) 91080708Sjake{ 91186147Stmm static struct { 91286147Stmm cell_t name; 91386147Stmm cell_t nargs; 91486147Stmm cell_t nreturns; 91586147Stmm } args = { 91686147Stmm (cell_t)"exit", 91786147Stmm 0, 91886147Stmm 0 91986147Stmm }; 92084178Sjake 92192205Sjake cpu_shutdown(&args); 92280708Sjake} 92380708Sjake 924203838Smariusstatic void 92586147Stmmsparc64_shutdown_final(void *dummy, int howto) 92686147Stmm{ 92786147Stmm static struct { 92886147Stmm cell_t name; 92986147Stmm cell_t nargs; 93086147Stmm cell_t nreturns; 93186147Stmm } args = { 93286147Stmm (cell_t)"SUNW,power-off", 93386147Stmm 0, 93486147Stmm 0 93586147Stmm }; 93686147Stmm 93786147Stmm /* Turn the power off? */ 93886147Stmm if ((howto & RB_POWEROFF) != 0) 93992205Sjake cpu_shutdown(&args); 940185007Smarius /* In case of halt, return to the firmware. */ 94186147Stmm if ((howto & RB_HALT) != 0) 94286147Stmm cpu_halt(); 94386147Stmm} 94486147Stmm 945121237Spetervoid 946178471Sjeffcpu_idle(int busy) 947121237Speter{ 948181701Smarius 949181701Smarius /* Insert code to halt (until next interrupt) for the idle loop. */ 950121237Speter} 951121237Speter 95280708Sjakeint 953178471Sjeffcpu_idle_wakeup(int cpu) 954178471Sjeff{ 955178471Sjeff 956212456Smav return (1); 957178471Sjeff} 958178471Sjeff 959178471Sjeffint 96083366Sjulianptrace_set_pc(struct thread *td, u_long addr) 96180708Sjake{ 96282016Sjake 96383366Sjulian td->td_frame->tf_tpc = addr; 96483366Sjulian td->td_frame->tf_tnpc = addr + 4; 96580708Sjake return (0); 96680708Sjake} 96780708Sjake 96880708Sjakeint 96983366Sjulianptrace_single_step(struct thread *td) 97080708Sjake{ 971181701Smarius 972104271Sjake /* TODO; */ 97380708Sjake return (0); 97480708Sjake} 97580708Sjake 976132088Sdavidxuint 977132088Sdavidxuptrace_clear_single_step(struct thread *td) 978132088Sdavidxu{ 979181701Smarius 980132088Sdavidxu /* TODO; */ 981132088Sdavidxu return (0); 982132088Sdavidxu} 983132088Sdavidxu 98480708Sjakevoid 985205642Snwhitehornexec_setregs(struct thread *td, struct image_params *imgp, u_long stack) 98680708Sjake{ 98788639Sjake struct trapframe *tf; 98881135Stmm struct pcb *pcb; 989102557Sjake struct proc *p; 99084178Sjake u_long sp; 99181135Stmm 99288782Sjake /* XXX no cpu_exec */ 993102557Sjake p = td->td_proc; 994102557Sjake p->p_md.md_sigtramp = NULL; 995140485Sjhb if (p->p_md.md_utrap != NULL) { 996140485Sjhb utrap_free(p->p_md.md_utrap); 997102557Sjake p->p_md.md_utrap = NULL; 99888782Sjake } 99988782Sjake 100083366Sjulian pcb = td->td_pcb; 1001105908Sjake tf = td->td_frame; 100288639Sjake sp = rounddown(stack, 16); 100398032Sjake bzero(pcb, sizeof(*pcb)); 100498032Sjake bzero(tf, sizeof(*tf)); 100588639Sjake tf->tf_out[0] = stack; 1006105908Sjake tf->tf_out[3] = p->p_sysent->sv_psstrings; 100788639Sjake tf->tf_out[6] = sp - SPOFF - sizeof(struct frame); 1008205642Snwhitehorn tf->tf_tnpc = imgp->entry_addr + 4; 1009205642Snwhitehorn tf->tf_tpc = imgp->entry_addr; 1010225888Smarius /* 1011225888Smarius * While we could adhere to the memory model indicated in the ELF 1012225888Smarius * header, it turns out that just always using TSO performs best. 1013225888Smarius */ 101488639Sjake tf->tf_tstate = TSTATE_IE | TSTATE_PEF | TSTATE_MM_TSO; 101588639Sjake 101688639Sjake td->td_retval[0] = tf->tf_out[0]; 101788639Sjake td->td_retval[1] = tf->tf_out[1]; 101880708Sjake} 101980708Sjake 102080708Sjakeint 102184178Sjakefill_regs(struct thread *td, struct reg *regs) 102280708Sjake{ 102380708Sjake 1024105733Sjake bcopy(td->td_frame, regs, sizeof(*regs)); 102580708Sjake return (0); 102680708Sjake} 102780708Sjake 102880708Sjakeint 102984178Sjakeset_regs(struct thread *td, struct reg *regs) 103080708Sjake{ 1031112922Sjake struct trapframe *tf; 103280708Sjake 103384178Sjake if (!TSTATE_SECURE(regs->r_tstate)) 103484178Sjake return (EINVAL); 1035112922Sjake tf = td->td_frame; 1036112922Sjake regs->r_wstate = tf->tf_wstate; 1037112922Sjake bcopy(regs, tf, sizeof(*regs)); 103880708Sjake return (0); 103980708Sjake} 104080708Sjake 104180708Sjakeint 104285294Sdesfill_dbregs(struct thread *td, struct dbreg *dbregs) 104385294Sdes{ 104485294Sdes 104585294Sdes return (ENOSYS); 104685294Sdes} 104785294Sdes 104885294Sdesint 104985294Sdesset_dbregs(struct thread *td, struct dbreg *dbregs) 105085294Sdes{ 105185294Sdes 105285294Sdes return (ENOSYS); 105385294Sdes} 105485294Sdes 105585294Sdesint 105683366Sjulianfill_fpregs(struct thread *td, struct fpreg *fpregs) 105780708Sjake{ 105888639Sjake struct trapframe *tf; 105984178Sjake struct pcb *pcb; 106084178Sjake 106184178Sjake pcb = td->td_pcb; 106288639Sjake tf = td->td_frame; 1063112920Sjake bcopy(pcb->pcb_ufp, fpregs->fr_regs, sizeof(fpregs->fr_regs)); 106488639Sjake fpregs->fr_fsr = tf->tf_fsr; 1065105733Sjake fpregs->fr_gsr = tf->tf_gsr; 106680708Sjake return (0); 106780708Sjake} 106880708Sjake 106980708Sjakeint 107083366Sjulianset_fpregs(struct thread *td, struct fpreg *fpregs) 107180708Sjake{ 107288639Sjake struct trapframe *tf; 107384178Sjake struct pcb *pcb; 107484178Sjake 107584178Sjake pcb = td->td_pcb; 107688639Sjake tf = td->td_frame; 1077112922Sjake tf->tf_fprs &= ~FPRS_FEF; 1078112920Sjake bcopy(fpregs->fr_regs, pcb->pcb_ufp, sizeof(pcb->pcb_ufp)); 107988639Sjake tf->tf_fsr = fpregs->fr_fsr; 1080105733Sjake tf->tf_gsr = fpregs->fr_gsr; 108180708Sjake return (0); 108280708Sjake} 1083140485Sjhb 1084140485Sjhbstruct md_utrap * 1085140485Sjhbutrap_alloc(void) 1086140485Sjhb{ 1087140485Sjhb struct md_utrap *ut; 1088140485Sjhb 1089140485Sjhb ut = malloc(sizeof(struct md_utrap), M_SUBPROC, M_WAITOK | M_ZERO); 1090140485Sjhb ut->ut_refcnt = 1; 1091140485Sjhb return (ut); 1092140485Sjhb} 1093140485Sjhb 1094140485Sjhbvoid 1095140485Sjhbutrap_free(struct md_utrap *ut) 1096140485Sjhb{ 1097140485Sjhb int refcnt; 1098140485Sjhb 1099140485Sjhb if (ut == NULL) 1100140485Sjhb return; 1101140485Sjhb mtx_pool_lock(mtxpool_sleep, ut); 1102140485Sjhb ut->ut_refcnt--; 1103140485Sjhb refcnt = ut->ut_refcnt; 1104140485Sjhb mtx_pool_unlock(mtxpool_sleep, ut); 1105140485Sjhb if (refcnt == 0) 1106140485Sjhb free(ut, M_SUBPROC); 1107140485Sjhb} 1108140485Sjhb 1109140485Sjhbstruct md_utrap * 1110140485Sjhbutrap_hold(struct md_utrap *ut) 1111140485Sjhb{ 1112140485Sjhb 1113140485Sjhb if (ut == NULL) 1114140485Sjhb return (NULL); 1115140485Sjhb mtx_pool_lock(mtxpool_sleep, ut); 1116140485Sjhb ut->ut_refcnt++; 1117140485Sjhb mtx_pool_unlock(mtxpool_sleep, ut); 1118140485Sjhb return (ut); 1119140485Sjhb} 1120