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$"); 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. 556182773Smarius */ 557182773Smarius sun4u_set_traptable(tl0_base); 558182773Smarius 559182773Smarius /* 560230633Smarius * Initialize the console. 561230633Smarius * NB: the low-level console drivers require a working DELAY() and 562230633Smarius * some compiler optimizations may cause the curthread accesses of 563230633Smarius * mutex(9) to be factored out even if the latter aren't actually 564230633Smarius * called, both requiring PCPU_REG to be set. 565182730Smarius */ 566230633Smarius cninit(); 567182730Smarius 568182730Smarius /* 569194784Sjeff * Initialize the dynamic per-CPU area for the BSP and the message 570194784Sjeff * buffer (after setting the trap table). 57188822Stmm */ 572194784Sjeff dpcpu_init(dpcpu0, 0); 573217688Spluknet msgbufinit(msgbufp, msgbufsize); 57488822Stmm 575207248Smarius /* 576207248Smarius * Initialize mutexes. 577207248Smarius */ 57893702Sjhb mutex_init(); 579207248Smarius 580207248Smarius /* 581207248Smarius * Finish the interrupt initialization now that mutexes work and 582207248Smarius * enable them. 583207248Smarius */ 58490624Stmm intr_init2(); 585213873Smarius wrpr(pil, 0, 0); 586207248Smarius wrpr(pstate, 0, PSTATE_KERNEL); 587105946Stmm 588106555Stmm OF_getprop(root, "name", sparc64_model, sizeof(sparc64_model) - 1); 589122604Ssimokawa 590131950Smarcel kdb_init(); 591131950Smarcel 592190161Smarius#ifdef KDB 593122604Ssimokawa if (boothowto & RB_KDB) 594174898Srwatson kdb_enter(KDB_WHY_BOOTFLAGS, "Boot flags requested debugger"); 595190161Smarius#endif 59680708Sjake} 59780708Sjake 59880708Sjakevoid 599151316Sdavidxusendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask) 60080708Sjake{ 60182902Sjake struct trapframe *tf; 60282902Sjake struct sigframe *sfp; 60382902Sjake struct sigacts *psp; 60482902Sjake struct sigframe sf; 60583366Sjulian struct thread *td; 60685242Sjake struct frame *fp; 60782902Sjake struct proc *p; 608181701Smarius u_long sp; 60985242Sjake int oonstack; 610151316Sdavidxu int sig; 61182902Sjake 61282902Sjake oonstack = 0; 61383366Sjulian td = curthread; 61483366Sjulian p = td->td_proc; 615114983Sjhb PROC_LOCK_ASSERT(p, MA_OWNED); 616151316Sdavidxu sig = ksi->ksi_signo; 61782902Sjake psp = p->p_sigacts; 618114983Sjhb mtx_assert(&psp->ps_mtx, MA_OWNED); 61983366Sjulian tf = td->td_frame; 62082902Sjake sp = tf->tf_sp + SPOFF; 62182902Sjake oonstack = sigonstack(sp); 62282902Sjake 62383366Sjulian CTR4(KTR_SIG, "sendsig: td=%p (%s) catcher=%p sig=%d", td, p->p_comm, 62482902Sjake catcher, sig); 62582902Sjake 626102554Sjake /* Make sure we have a signal trampoline to return to. */ 627102554Sjake if (p->p_md.md_sigtramp == NULL) { 628102554Sjake /* 629157445Smarius * No signal trampoline... kill the process. 630102554Sjake */ 631102554Sjake CTR0(KTR_SIG, "sendsig: no sigtramp"); 632102873Sjake printf("sendsig: %s is too old, rebuild it\n", p->p_comm); 633102554Sjake sigexit(td, sig); 634102554Sjake /* NOTREACHED */ 635102554Sjake } 636102554Sjake 63782902Sjake /* Save user context. */ 63882902Sjake bzero(&sf, sizeof(sf)); 639118708Sjake get_mcontext(td, &sf.sf_uc.uc_mcontext, 0); 64082902Sjake sf.sf_uc.uc_sigmask = *mask; 641124092Sdavidxu sf.sf_uc.uc_stack = td->td_sigstk; 642181701Smarius sf.sf_uc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK) ? 643181701Smarius ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE; 64482902Sjake 64582902Sjake /* Allocate and validate space for the signal handler context. */ 646124092Sdavidxu if ((td->td_pflags & TDP_ALTSTACK) != 0 && !oonstack && 64782902Sjake SIGISMEMBER(psp->ps_sigonstack, sig)) { 648124092Sdavidxu sfp = (struct sigframe *)(td->td_sigstk.ss_sp + 649124092Sdavidxu td->td_sigstk.ss_size - sizeof(struct sigframe)); 65082902Sjake } else 65182902Sjake sfp = (struct sigframe *)sp - 1; 652114983Sjhb mtx_unlock(&psp->ps_mtx); 65382902Sjake PROC_UNLOCK(p); 65482902Sjake 65585242Sjake fp = (struct frame *)sfp - 1; 65682902Sjake 65782902Sjake /* Translate the signal if appropriate. */ 65882902Sjake if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize) 65982902Sjake sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)]; 66082902Sjake 66182902Sjake /* Build the argument list for the signal handler. */ 66282902Sjake tf->tf_out[0] = sig; 66382902Sjake tf->tf_out[2] = (register_t)&sfp->sf_uc; 66482902Sjake tf->tf_out[4] = (register_t)catcher; 665157445Smarius if (SIGISMEMBER(psp->ps_siginfo, sig)) { 666157445Smarius /* Signal handler installed with SA_SIGINFO. */ 667157445Smarius tf->tf_out[1] = (register_t)&sfp->sf_si; 66882902Sjake 669157445Smarius /* Fill in POSIX parts. */ 670157445Smarius sf.sf_si = ksi->ksi_info; 671157445Smarius sf.sf_si.si_signo = sig; /* maybe a translated signal */ 672157445Smarius } else { 673157445Smarius /* Old FreeBSD-style arguments. */ 674157445Smarius tf->tf_out[1] = ksi->ksi_code; 675157445Smarius tf->tf_out[3] = (register_t)ksi->ksi_addr; 676157445Smarius } 677157445Smarius 67882902Sjake /* Copy the sigframe out to the user's stack. */ 67985242Sjake if (rwindow_save(td) != 0 || copyout(&sf, sfp, sizeof(*sfp)) != 0 || 68094254Sjake suword(&fp->fr_in[6], tf->tf_out[6]) != 0) { 68182902Sjake /* 68282902Sjake * Something is wrong with the stack pointer. 68382902Sjake * ...Kill the process. 68482902Sjake */ 68583366Sjulian CTR2(KTR_SIG, "sendsig: sigexit td=%p sfp=%p", td, sfp); 68682902Sjake PROC_LOCK(p); 68783366Sjulian sigexit(td, SIGILL); 68882902Sjake /* NOTREACHED */ 68982902Sjake } 69082902Sjake 691102554Sjake tf->tf_tpc = (u_long)p->p_md.md_sigtramp; 69282902Sjake tf->tf_tnpc = tf->tf_tpc + 4; 69385242Sjake tf->tf_sp = (u_long)fp - SPOFF; 69482902Sjake 69583366Sjulian CTR3(KTR_SIG, "sendsig: return td=%p pc=%#lx sp=%#lx", td, tf->tf_tpc, 69682902Sjake tf->tf_sp); 69784178Sjake 69884178Sjake PROC_LOCK(p); 699114983Sjhb mtx_lock(&psp->ps_mtx); 70080708Sjake} 70180708Sjake 70280708Sjake#ifndef _SYS_SYSPROTO_H_ 70383088Sobrienstruct sigreturn_args { 70480708Sjake ucontext_t *ucp; 70580708Sjake}; 70680708Sjake#endif 70780708Sjake 70894606Salc/* 70994606Salc * MPSAFE 71094606Salc */ 71180708Sjakeint 712225617Skmacysys_sigreturn(struct thread *td, struct sigreturn_args *uap) 71380708Sjake{ 71483366Sjulian struct proc *p; 715118768Sjake mcontext_t *mc; 71682902Sjake ucontext_t uc; 717118708Sjake int error; 71882902Sjake 71983366Sjulian p = td->td_proc; 72083366Sjulian if (rwindow_save(td)) { 72182902Sjake PROC_LOCK(p); 72283366Sjulian sigexit(td, SIGILL); 72382902Sjake } 72482902Sjake 72583366Sjulian CTR2(KTR_SIG, "sigreturn: td=%p ucp=%p", td, uap->sigcntxp); 72682902Sjake if (copyin(uap->sigcntxp, &uc, sizeof(uc)) != 0) { 72783366Sjulian CTR1(KTR_SIG, "sigreturn: efault td=%p", td); 72882902Sjake return (EFAULT); 72982902Sjake } 73082902Sjake 731118768Sjake mc = &uc.uc_mcontext; 732118768Sjake error = set_mcontext(td, mc); 733118708Sjake if (error != 0) 734118708Sjake return (error); 73582902Sjake 736198507Skib kern_sigprocmask(td, SIG_SETMASK, &uc.uc_sigmask, NULL, 0); 737105733Sjake 73883366Sjulian CTR4(KTR_SIG, "sigreturn: return td=%p pc=%#lx sp=%#lx tstate=%#lx", 739253266Smarius td, mc->_mc_tpc, mc->_mc_sp, mc->_mc_tstate); 74082902Sjake return (EJUSTRETURN); 74180708Sjake} 74280708Sjake 743131905Smarcel/* 744131905Smarcel * Construct a PCB from a trapframe. This is called from kdb_trap() where 745131905Smarcel * we want to start a backtrace from the function that caused us to enter 746131905Smarcel * the debugger. We have the context in the trapframe, but base the trace 747131905Smarcel * on the PCB. The PCB doesn't have to be perfect, as long as it contains 748131905Smarcel * enough for a backtrace. 749131905Smarcel */ 750131905Smarcelvoid 751131905Smarcelmakectx(struct trapframe *tf, struct pcb *pcb) 752131905Smarcel{ 753131905Smarcel 754131905Smarcel pcb->pcb_pc = tf->tf_tpc; 755131905Smarcel pcb->pcb_sp = tf->tf_sp; 756131905Smarcel} 757131905Smarcel 758106977Sdeischenint 759122364Smarcelget_mcontext(struct thread *td, mcontext_t *mc, int flags) 760106977Sdeischen{ 761112924Sjake struct trapframe *tf; 762112924Sjake struct pcb *pcb; 763106977Sdeischen 764112924Sjake tf = td->td_frame; 765112924Sjake pcb = td->td_pcb; 766199442Smarius /* 767199442Smarius * Copy the registers which will be restored by tl0_ret() from the 768199442Smarius * trapframe. 769199442Smarius * Note that we skip %g7 which is used as the userland TLS register 770199442Smarius * and %wstate. 771199442Smarius */ 772253266Smarius mc->_mc_flags = _MC_VERSION; 773199442Smarius mc->mc_global[1] = tf->tf_global[1]; 774199442Smarius mc->mc_global[2] = tf->tf_global[2]; 775199442Smarius mc->mc_global[3] = tf->tf_global[3]; 776199442Smarius mc->mc_global[4] = tf->tf_global[4]; 777199442Smarius mc->mc_global[5] = tf->tf_global[5]; 778199442Smarius mc->mc_global[6] = tf->tf_global[6]; 779122364Smarcel if (flags & GET_MC_CLEAR_RET) { 780113998Sdeischen mc->mc_out[0] = 0; 781113998Sdeischen mc->mc_out[1] = 0; 782199442Smarius } else { 783199442Smarius mc->mc_out[0] = tf->tf_out[0]; 784199442Smarius mc->mc_out[1] = tf->tf_out[1]; 785113998Sdeischen } 786199442Smarius mc->mc_out[2] = tf->tf_out[2]; 787199442Smarius mc->mc_out[3] = tf->tf_out[3]; 788199442Smarius mc->mc_out[4] = tf->tf_out[4]; 789199442Smarius mc->mc_out[5] = tf->tf_out[5]; 790199442Smarius mc->mc_out[6] = tf->tf_out[6]; 791199442Smarius mc->mc_out[7] = tf->tf_out[7]; 792253266Smarius mc->_mc_fprs = tf->tf_fprs; 793253266Smarius mc->_mc_fsr = tf->tf_fsr; 794253266Smarius mc->_mc_gsr = tf->tf_gsr; 795253266Smarius mc->_mc_tnpc = tf->tf_tnpc; 796253266Smarius mc->_mc_tpc = tf->tf_tpc; 797253266Smarius mc->_mc_tstate = tf->tf_tstate; 798253266Smarius mc->_mc_y = tf->tf_y; 799112924Sjake critical_enter(); 800112961Sjake if ((tf->tf_fprs & FPRS_FEF) != 0) { 801112961Sjake savefpctx(pcb->pcb_ufp); 802112961Sjake tf->tf_fprs &= ~FPRS_FEF; 803112961Sjake pcb->pcb_flags |= PCB_FEF; 804112961Sjake } 805112961Sjake if ((pcb->pcb_flags & PCB_FEF) != 0) { 806113018Sjake bcopy(pcb->pcb_ufp, mc->mc_fp, sizeof(mc->mc_fp)); 807253266Smarius mc->_mc_fprs |= FPRS_FEF; 808112924Sjake } 809112924Sjake critical_exit(); 810112924Sjake return (0); 811106977Sdeischen} 812106977Sdeischen 813106977Sdeischenint 814112924Sjakeset_mcontext(struct thread *td, const mcontext_t *mc) 815106977Sdeischen{ 816112924Sjake struct trapframe *tf; 817112924Sjake struct pcb *pcb; 818106977Sdeischen 819253266Smarius if (!TSTATE_SECURE(mc->_mc_tstate) || 820253266Smarius (mc->_mc_flags & ((1L << _MC_VERSION_BITS) - 1)) != _MC_VERSION) 821112924Sjake return (EINVAL); 822112924Sjake tf = td->td_frame; 823112924Sjake pcb = td->td_pcb; 824136325Skensmith /* Make sure the windows are spilled first. */ 825136325Skensmith flushw(); 826199442Smarius /* 827199442Smarius * Copy the registers which will be restored by tl0_ret() to the 828199442Smarius * trapframe. 829199442Smarius * Note that we skip %g7 which is used as the userland TLS register 830199442Smarius * and %wstate. 831199442Smarius */ 832199442Smarius tf->tf_global[1] = mc->mc_global[1]; 833199442Smarius tf->tf_global[2] = mc->mc_global[2]; 834199442Smarius tf->tf_global[3] = mc->mc_global[3]; 835199442Smarius tf->tf_global[4] = mc->mc_global[4]; 836199442Smarius tf->tf_global[5] = mc->mc_global[5]; 837199442Smarius tf->tf_global[6] = mc->mc_global[6]; 838199442Smarius tf->tf_out[0] = mc->mc_out[0]; 839199442Smarius tf->tf_out[1] = mc->mc_out[1]; 840199442Smarius tf->tf_out[2] = mc->mc_out[2]; 841199442Smarius tf->tf_out[3] = mc->mc_out[3]; 842199442Smarius tf->tf_out[4] = mc->mc_out[4]; 843199442Smarius tf->tf_out[5] = mc->mc_out[5]; 844199442Smarius tf->tf_out[6] = mc->mc_out[6]; 845199442Smarius tf->tf_out[7] = mc->mc_out[7]; 846253266Smarius tf->tf_fprs = mc->_mc_fprs; 847253266Smarius tf->tf_fsr = mc->_mc_fsr; 848253266Smarius tf->tf_gsr = mc->_mc_gsr; 849253266Smarius tf->tf_tnpc = mc->_mc_tnpc; 850253266Smarius tf->tf_tpc = mc->_mc_tpc; 851253266Smarius tf->tf_tstate = mc->_mc_tstate; 852253266Smarius tf->tf_y = mc->_mc_y; 853253266Smarius if ((mc->_mc_fprs & FPRS_FEF) != 0) { 854112924Sjake tf->tf_fprs = 0; 855113018Sjake bcopy(mc->mc_fp, pcb->pcb_ufp, sizeof(pcb->pcb_ufp)); 856112924Sjake pcb->pcb_flags |= PCB_FEF; 857112924Sjake } 858112924Sjake return (0); 859106977Sdeischen} 860106977Sdeischen 86186147Stmm/* 86292205Sjake * Exit the kernel and execute a firmware call that will not return, as 86392205Sjake * specified by the arguments. 86492205Sjake */ 86592205Sjakevoid 86692205Sjakecpu_shutdown(void *args) 86792205Sjake{ 86892205Sjake 86992205Sjake#ifdef SMP 87092205Sjake cpu_mp_shutdown(); 87192205Sjake#endif 872186347Snwhitehorn ofw_exit(args); 87392205Sjake} 87492205Sjake 875192323Smarcel/* 876192323Smarcel * Flush the D-cache for non-DMA I/O so that the I-cache can 877192323Smarcel * be made coherent later. 878192323Smarcel */ 879192323Smarcelvoid 880192323Smarcelcpu_flush_dcache(void *ptr, size_t len) 881192323Smarcel{ 882195149Smarius 883192323Smarcel /* TBD */ 884192323Smarcel} 885192323Smarcel 886181701Smarius/* Get current clock frequency for the given CPU ID. */ 887141237Snjlint 888141237Snjlcpu_est_clockrate(int cpu_id, uint64_t *rate) 889141237Snjl{ 890182730Smarius struct pcpu *pc; 891141237Snjl 892182730Smarius pc = pcpu_find(cpu_id); 893182730Smarius if (pc == NULL || rate == NULL) 894182730Smarius return (EINVAL); 895182730Smarius *rate = pc->pc_clock; 896182730Smarius return (0); 897141237Snjl} 898141237Snjl 89992205Sjake/* 90086147Stmm * Duplicate OF_exit() with a different firmware call function that restores 90186147Stmm * the trap table, otherwise a RED state exception is triggered in at least 90286147Stmm * some firmware versions. 90386147Stmm */ 90480708Sjakevoid 90580708Sjakecpu_halt(void) 90680708Sjake{ 90786147Stmm static struct { 90886147Stmm cell_t name; 90986147Stmm cell_t nargs; 91086147Stmm cell_t nreturns; 91186147Stmm } args = { 91286147Stmm (cell_t)"exit", 91386147Stmm 0, 91486147Stmm 0 91586147Stmm }; 91684178Sjake 91792205Sjake cpu_shutdown(&args); 91880708Sjake} 91980708Sjake 920203838Smariusstatic void 92186147Stmmsparc64_shutdown_final(void *dummy, int howto) 92286147Stmm{ 92386147Stmm static struct { 92486147Stmm cell_t name; 92586147Stmm cell_t nargs; 92686147Stmm cell_t nreturns; 92786147Stmm } args = { 92886147Stmm (cell_t)"SUNW,power-off", 92986147Stmm 0, 93086147Stmm 0 93186147Stmm }; 93286147Stmm 93386147Stmm /* Turn the power off? */ 93486147Stmm if ((howto & RB_POWEROFF) != 0) 93592205Sjake cpu_shutdown(&args); 936185007Smarius /* In case of halt, return to the firmware. */ 93786147Stmm if ((howto & RB_HALT) != 0) 93886147Stmm cpu_halt(); 93986147Stmm} 94086147Stmm 941121237Spetervoid 942178471Sjeffcpu_idle(int busy) 943121237Speter{ 944181701Smarius 945181701Smarius /* Insert code to halt (until next interrupt) for the idle loop. */ 946121237Speter} 947121237Speter 94880708Sjakeint 949178471Sjeffcpu_idle_wakeup(int cpu) 950178471Sjeff{ 951178471Sjeff 952212456Smav return (1); 953178471Sjeff} 954178471Sjeff 955178471Sjeffint 95683366Sjulianptrace_set_pc(struct thread *td, u_long addr) 95780708Sjake{ 95882016Sjake 95983366Sjulian td->td_frame->tf_tpc = addr; 96083366Sjulian td->td_frame->tf_tnpc = addr + 4; 96180708Sjake return (0); 96280708Sjake} 96380708Sjake 96480708Sjakeint 96583366Sjulianptrace_single_step(struct thread *td) 96680708Sjake{ 967181701Smarius 968104271Sjake /* TODO; */ 96980708Sjake return (0); 97080708Sjake} 97180708Sjake 972132088Sdavidxuint 973132088Sdavidxuptrace_clear_single_step(struct thread *td) 974132088Sdavidxu{ 975181701Smarius 976132088Sdavidxu /* TODO; */ 977132088Sdavidxu return (0); 978132088Sdavidxu} 979132088Sdavidxu 98080708Sjakevoid 981205642Snwhitehornexec_setregs(struct thread *td, struct image_params *imgp, u_long stack) 98280708Sjake{ 98388639Sjake struct trapframe *tf; 98481135Stmm struct pcb *pcb; 985102557Sjake struct proc *p; 98684178Sjake u_long sp; 98781135Stmm 98888782Sjake /* XXX no cpu_exec */ 989102557Sjake p = td->td_proc; 990102557Sjake p->p_md.md_sigtramp = NULL; 991140485Sjhb if (p->p_md.md_utrap != NULL) { 992140485Sjhb utrap_free(p->p_md.md_utrap); 993102557Sjake p->p_md.md_utrap = NULL; 99488782Sjake } 99588782Sjake 99683366Sjulian pcb = td->td_pcb; 997105908Sjake tf = td->td_frame; 99888639Sjake sp = rounddown(stack, 16); 99998032Sjake bzero(pcb, sizeof(*pcb)); 100098032Sjake bzero(tf, sizeof(*tf)); 100188639Sjake tf->tf_out[0] = stack; 1002105908Sjake tf->tf_out[3] = p->p_sysent->sv_psstrings; 100388639Sjake tf->tf_out[6] = sp - SPOFF - sizeof(struct frame); 1004205642Snwhitehorn tf->tf_tnpc = imgp->entry_addr + 4; 1005205642Snwhitehorn tf->tf_tpc = imgp->entry_addr; 1006225888Smarius /* 1007225888Smarius * While we could adhere to the memory model indicated in the ELF 1008225888Smarius * header, it turns out that just always using TSO performs best. 1009225888Smarius */ 101088639Sjake tf->tf_tstate = TSTATE_IE | TSTATE_PEF | TSTATE_MM_TSO; 101188639Sjake 101288639Sjake td->td_retval[0] = tf->tf_out[0]; 101388639Sjake td->td_retval[1] = tf->tf_out[1]; 101480708Sjake} 101580708Sjake 101680708Sjakeint 101784178Sjakefill_regs(struct thread *td, struct reg *regs) 101880708Sjake{ 101980708Sjake 1020105733Sjake bcopy(td->td_frame, regs, sizeof(*regs)); 102180708Sjake return (0); 102280708Sjake} 102380708Sjake 102480708Sjakeint 102584178Sjakeset_regs(struct thread *td, struct reg *regs) 102680708Sjake{ 1027112922Sjake struct trapframe *tf; 102880708Sjake 102984178Sjake if (!TSTATE_SECURE(regs->r_tstate)) 103084178Sjake return (EINVAL); 1031112922Sjake tf = td->td_frame; 1032112922Sjake regs->r_wstate = tf->tf_wstate; 1033112922Sjake bcopy(regs, tf, sizeof(*regs)); 103480708Sjake return (0); 103580708Sjake} 103680708Sjake 103780708Sjakeint 103885294Sdesfill_dbregs(struct thread *td, struct dbreg *dbregs) 103985294Sdes{ 104085294Sdes 104185294Sdes return (ENOSYS); 104285294Sdes} 104385294Sdes 104485294Sdesint 104585294Sdesset_dbregs(struct thread *td, struct dbreg *dbregs) 104685294Sdes{ 104785294Sdes 104885294Sdes return (ENOSYS); 104985294Sdes} 105085294Sdes 105185294Sdesint 105283366Sjulianfill_fpregs(struct thread *td, struct fpreg *fpregs) 105380708Sjake{ 105488639Sjake struct trapframe *tf; 105584178Sjake struct pcb *pcb; 105684178Sjake 105784178Sjake pcb = td->td_pcb; 105888639Sjake tf = td->td_frame; 1059112920Sjake bcopy(pcb->pcb_ufp, fpregs->fr_regs, sizeof(fpregs->fr_regs)); 106088639Sjake fpregs->fr_fsr = tf->tf_fsr; 1061105733Sjake fpregs->fr_gsr = tf->tf_gsr; 106280708Sjake return (0); 106380708Sjake} 106480708Sjake 106580708Sjakeint 106683366Sjulianset_fpregs(struct thread *td, struct fpreg *fpregs) 106780708Sjake{ 106888639Sjake struct trapframe *tf; 106984178Sjake struct pcb *pcb; 107084178Sjake 107184178Sjake pcb = td->td_pcb; 107288639Sjake tf = td->td_frame; 1073112922Sjake tf->tf_fprs &= ~FPRS_FEF; 1074112920Sjake bcopy(fpregs->fr_regs, pcb->pcb_ufp, sizeof(pcb->pcb_ufp)); 107588639Sjake tf->tf_fsr = fpregs->fr_fsr; 1076105733Sjake tf->tf_gsr = fpregs->fr_gsr; 107780708Sjake return (0); 107880708Sjake} 1079140485Sjhb 1080140485Sjhbstruct md_utrap * 1081140485Sjhbutrap_alloc(void) 1082140485Sjhb{ 1083140485Sjhb struct md_utrap *ut; 1084140485Sjhb 1085140485Sjhb ut = malloc(sizeof(struct md_utrap), M_SUBPROC, M_WAITOK | M_ZERO); 1086140485Sjhb ut->ut_refcnt = 1; 1087140485Sjhb return (ut); 1088140485Sjhb} 1089140485Sjhb 1090140485Sjhbvoid 1091140485Sjhbutrap_free(struct md_utrap *ut) 1092140485Sjhb{ 1093140485Sjhb int refcnt; 1094140485Sjhb 1095140485Sjhb if (ut == NULL) 1096140485Sjhb return; 1097140485Sjhb mtx_pool_lock(mtxpool_sleep, ut); 1098140485Sjhb ut->ut_refcnt--; 1099140485Sjhb refcnt = ut->ut_refcnt; 1100140485Sjhb mtx_pool_unlock(mtxpool_sleep, ut); 1101140485Sjhb if (refcnt == 0) 1102140485Sjhb free(ut, M_SUBPROC); 1103140485Sjhb} 1104140485Sjhb 1105140485Sjhbstruct md_utrap * 1106140485Sjhbutrap_hold(struct md_utrap *ut) 1107140485Sjhb{ 1108140485Sjhb 1109140485Sjhb if (ut == NULL) 1110140485Sjhb return (NULL); 1111140485Sjhb mtx_pool_lock(mtxpool_sleep, ut); 1112140485Sjhb ut->ut_refcnt++; 1113140485Sjhb mtx_pool_unlock(mtxpool_sleep, ut); 1114140485Sjhb return (ut); 1115140485Sjhb} 1116