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: stable/11/sys/sparc64/sparc64/machdep.c 341491 2018-12-04 19:07:10Z markj $"); 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> 76331017Skevans#include <sys/vmmeter.h> 7780708Sjake 7880708Sjake#include <dev/ofw/openfirm.h> 7980708Sjake 8080709Sjake#include <vm/vm.h> 81141378Snjl#include <vm/vm_extern.h> 8280709Sjake#include <vm/vm_kern.h> 8380709Sjake#include <vm/vm_page.h> 8480709Sjake#include <vm/vm_map.h> 85141378Snjl#include <vm/vm_object.h> 8680709Sjake#include <vm/vm_pager.h> 87141378Snjl#include <vm/vm_param.h> 8880709Sjake 8980709Sjake#include <ddb/ddb.h> 9080709Sjake 91119696Smarcel#include <machine/bus.h> 9286521Sjake#include <machine/cache.h> 93203838Smarius#include <machine/cmt.h> 9482902Sjake#include <machine/cpu.h> 95203838Smarius#include <machine/fireplane.h> 9683366Sjulian#include <machine/fp.h> 97112922Sjake#include <machine/fsr.h> 9881383Sjake#include <machine/intr_machdep.h> 99203838Smarius#include <machine/jbus.h> 10080708Sjake#include <machine/md_var.h> 10188436Sjake#include <machine/metadata.h> 10286147Stmm#include <machine/ofw_machdep.h> 103115971Sjake#include <machine/ofw_mem.h> 104138129Sdas#include <machine/pcb.h> 10580709Sjake#include <machine/pmap.h> 10680709Sjake#include <machine/pstate.h> 10780708Sjake#include <machine/reg.h> 10882902Sjake#include <machine/sigframe.h> 109141378Snjl#include <machine/smp.h> 11081383Sjake#include <machine/tick.h> 11191613Sjake#include <machine/tlb.h> 11282016Sjake#include <machine/tstate.h> 11391616Sjake#include <machine/upa.h> 11482902Sjake#include <machine/ver.h> 11580708Sjake 11680709Sjaketypedef int ofw_vec_t(void *); 11780708Sjake 118186682Smariusint dtlb_slots; 119186682Smariusint itlb_slots; 12097445Sjakestruct tlb_entry *kernel_tlbs; 12191616Sjakeint kernel_tlb_slots; 12291616Sjake 12380708Sjakeint cold = 1; 124102600Speterlong Maxmem; 125142956Sweslong realmem; 12680708Sjake 127194784Sjeffvoid *dpcpu0; 12891360Sjakechar pcpu0[PCPU_PAGES * PAGE_SIZE]; 12989038Sjakestruct trapframe frame0; 13080708Sjake 13189038Sjakevm_offset_t kstack0; 132113238Sjakevm_paddr_t kstack0_phys; 13388781Sjake 13482902Sjakestruct kva_md_info kmi; 13580709Sjake 13680709Sjakeu_long ofw_vec; 13780709Sjakeu_long ofw_tba; 138205409Smariusu_int tba_taken_over; 13980709Sjake 140106555Stmmchar sparc64_model[32]; 141106555Stmm 142113166Sjakestatic int cpu_use_vis = 1; 143113166Sjake 144113166Sjakecpu_block_copy_t *cpu_block_copy; 145113166Sjakecpu_block_zero_t *cpu_block_zero; 146113166Sjake 147204152Smariusstatic phandle_t find_bsp(phandle_t node, uint32_t bspid, u_int cpu_impl); 14891616Sjakevoid sparc64_init(caddr_t mdp, u_long o1, u_long o2, u_long o3, 149181701Smarius ofw_vec_t *vec); 150203838Smariusstatic void sparc64_shutdown_final(void *dummy, int howto); 15180709Sjake 152203838Smariusstatic void cpu_startup(void *arg); 15380709SjakeSYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL); 15480709Sjake 15591336SjakeCTASSERT((1 << INT_SHIFT) == sizeof(int)); 15691336SjakeCTASSERT((1 << PTR_SHIFT) == sizeof(char *)); 15791336Sjake 158105733SjakeCTASSERT(sizeof(struct reg) == 256); 159105733SjakeCTASSERT(sizeof(struct fpreg) == 272); 160105733SjakeCTASSERT(sizeof(struct __mcontext) == 512); 161105733Sjake 162113023SjakeCTASSERT((sizeof(struct pcb) & (64 - 1)) == 0); 163113023SjakeCTASSERT((offsetof(struct pcb, pcb_kfp) & (64 - 1)) == 0); 164113023SjakeCTASSERT((offsetof(struct pcb, pcb_ufp) & (64 - 1)) == 0); 165113023SjakeCTASSERT(sizeof(struct pcb) <= ((KSTACK_PAGES * PAGE_SIZE) / 8)); 166113023Sjake 16791360SjakeCTASSERT(sizeof(struct pcpu) <= ((PCPU_PAGES * PAGE_SIZE) / 2)); 16889038Sjake 16980709Sjakestatic void 17080709Sjakecpu_startup(void *arg) 17180709Sjake{ 172115971Sjake vm_paddr_t physsz; 173115971Sjake int i; 17480709Sjake 175115971Sjake physsz = 0; 176115971Sjake for (i = 0; i < sparc64_nmemreg; i++) 177115971Sjake physsz += sparc64_memreg[i].mr_size; 178115971Sjake printf("real memory = %lu (%lu MB)\n", physsz, 179115971Sjake physsz / (1024 * 1024)); 180155680Sjhb realmem = (long)physsz / PAGE_SIZE; 18180709Sjake 18282902Sjake vm_ksubmap_init(&kmi); 18380709Sjake 18480709Sjake bufinit(); 18580709Sjake vm_pager_bufferinit(); 18680709Sjake 18786147Stmm EVENTHANDLER_REGISTER(shutdown_final, sparc64_shutdown_final, NULL, 18886147Stmm SHUTDOWN_PRI_LAST); 189113338Sjake 190263620Sbdrewery printf("avail memory = %lu (%lu MB)\n", vm_cnt.v_free_count * PAGE_SIZE, 191263620Sbdrewery vm_cnt.v_free_count / ((1024 * 1024) / PAGE_SIZE)); 192113338Sjake 193113338Sjake if (bootverbose) 194113338Sjake printf("machine: %s\n", sparc64_model); 195113338Sjake 196182730Smarius cpu_identify(rdpr(ver), PCPU_GET(clock), curcpu); 19780709Sjake} 19880709Sjake 19987702Sjhbvoid 20087702Sjhbcpu_pcpu_init(struct pcpu *pcpu, int cpuid, size_t size) 20187702Sjhb{ 20297265Sjake struct intr_request *ir; 20397265Sjake int i; 20497265Sjake 20597265Sjake pcpu->pc_irtail = &pcpu->pc_irhead; 20697265Sjake for (i = 0; i < IR_FREE; i++) { 20797265Sjake ir = &pcpu->pc_irpool[i]; 20897265Sjake ir->ir_next = pcpu->pc_irfree; 20997265Sjake pcpu->pc_irfree = ir; 21097265Sjake } 21187702Sjhb} 21287702Sjhb 213144637Sjhbvoid 214144637Sjhbspinlock_enter(void) 215144637Sjhb{ 216144637Sjhb struct thread *td; 217145085Sjhb register_t pil; 218144637Sjhb 219144637Sjhb td = curthread; 220144637Sjhb if (td->td_md.md_spinlock_count == 0) { 221145085Sjhb pil = rdpr(pil); 222145151Smarius wrpr(pil, 0, PIL_TICK); 223214835Sjhb td->td_md.md_spinlock_count = 1; 224145085Sjhb td->td_md.md_saved_pil = pil; 225214835Sjhb } else 226214835Sjhb td->td_md.md_spinlock_count++; 227144637Sjhb critical_enter(); 228144637Sjhb} 229144637Sjhb 230144637Sjhbvoid 231144637Sjhbspinlock_exit(void) 232144637Sjhb{ 233144637Sjhb struct thread *td; 234214835Sjhb register_t pil; 235144637Sjhb 236144637Sjhb td = curthread; 237144637Sjhb critical_exit(); 238214835Sjhb pil = td->td_md.md_saved_pil; 239144637Sjhb td->td_md.md_spinlock_count--; 240144637Sjhb if (td->td_md.md_spinlock_count == 0) 241214835Sjhb wrpr(pil, pil, 0); 242144637Sjhb} 243144637Sjhb 244203838Smariusstatic phandle_t 245204152Smariusfind_bsp(phandle_t node, uint32_t bspid, u_int cpu_impl) 246203838Smarius{ 247203838Smarius char type[sizeof("cpu")]; 248203838Smarius phandle_t child; 249291121Smarius uint32_t portid; 250203838Smarius 251203838Smarius for (; node != 0; node = OF_peer(node)) { 252203838Smarius child = OF_child(node); 253203838Smarius if (child > 0) { 254204152Smarius child = find_bsp(child, bspid, cpu_impl); 255203838Smarius if (child > 0) 256203838Smarius return (child); 257203838Smarius } else { 258203838Smarius if (OF_getprop(node, "device_type", type, 259203838Smarius sizeof(type)) <= 0) 260203838Smarius continue; 261203838Smarius if (strcmp(type, "cpu") != 0) 262203838Smarius continue; 263291121Smarius if (OF_getprop(node, cpu_portid_prop(cpu_impl), 264291121Smarius &portid, sizeof(portid)) <= 0) 265203838Smarius continue; 266291121Smarius if (portid == bspid) 267203838Smarius return (node); 268203838Smarius } 269203838Smarius } 270203838Smarius return (0); 271203838Smarius} 272203838Smarius 273203838Smariusconst char * 274291121Smariuscpu_portid_prop(u_int cpu_impl) 275203838Smarius{ 276203838Smarius 277203838Smarius switch (cpu_impl) { 278203838Smarius case CPU_IMPL_SPARC64: 279207537Smarius case CPU_IMPL_SPARC64V: 280203838Smarius case CPU_IMPL_ULTRASPARCI: 281203838Smarius case CPU_IMPL_ULTRASPARCII: 282203838Smarius case CPU_IMPL_ULTRASPARCIIi: 283203838Smarius case CPU_IMPL_ULTRASPARCIIe: 284203838Smarius return ("upa-portid"); 285203838Smarius case CPU_IMPL_ULTRASPARCIII: 286203838Smarius case CPU_IMPL_ULTRASPARCIIIp: 287203838Smarius case CPU_IMPL_ULTRASPARCIIIi: 288203838Smarius case CPU_IMPL_ULTRASPARCIIIip: 289203838Smarius return ("portid"); 290203838Smarius case CPU_IMPL_ULTRASPARCIV: 291203838Smarius case CPU_IMPL_ULTRASPARCIVp: 292203838Smarius return ("cpuid"); 293203838Smarius default: 294203838Smarius return (""); 295203838Smarius } 296203838Smarius} 297203838Smarius 298203838Smariusuint32_t 299204152Smariuscpu_get_mid(u_int cpu_impl) 300203838Smarius{ 301203838Smarius 302203838Smarius switch (cpu_impl) { 303203838Smarius case CPU_IMPL_SPARC64: 304207537Smarius case CPU_IMPL_SPARC64V: 305203838Smarius case CPU_IMPL_ULTRASPARCI: 306203838Smarius case CPU_IMPL_ULTRASPARCII: 307203838Smarius case CPU_IMPL_ULTRASPARCIIi: 308203838Smarius case CPU_IMPL_ULTRASPARCIIe: 309203838Smarius return (UPA_CR_GET_MID(ldxa(0, ASI_UPA_CONFIG_REG))); 310203838Smarius case CPU_IMPL_ULTRASPARCIII: 311203838Smarius case CPU_IMPL_ULTRASPARCIIIp: 312203838Smarius return (FIREPLANE_CR_GET_AID(ldxa(AA_FIREPLANE_CONFIG, 313203838Smarius ASI_FIREPLANE_CONFIG_REG))); 314203838Smarius case CPU_IMPL_ULTRASPARCIIIi: 315203838Smarius case CPU_IMPL_ULTRASPARCIIIip: 316203838Smarius return (JBUS_CR_GET_JID(ldxa(0, ASI_JBUS_CONFIG_REG))); 317203838Smarius case CPU_IMPL_ULTRASPARCIV: 318203838Smarius case CPU_IMPL_ULTRASPARCIVp: 319203838Smarius return (INTR_ID_GET_ID(ldxa(AA_INTR_ID, ASI_INTR_ID))); 320203838Smarius default: 321203838Smarius return (0); 322203838Smarius } 323203838Smarius} 324203838Smarius 32580708Sjakevoid 32691616Sjakesparc64_init(caddr_t mdp, u_long o1, u_long o2, u_long o3, ofw_vec_t *vec) 32780708Sjake{ 328181701Smarius char *env; 32989038Sjake struct pcpu *pc; 33086521Sjake vm_offset_t end; 331195149Smarius vm_offset_t va; 33286521Sjake caddr_t kmdp; 333181701Smarius phandle_t root; 334204152Smarius u_int cpu_impl; 33580709Sjake 33686521Sjake end = 0; 33786521Sjake kmdp = NULL; 33886521Sjake 33980709Sjake /* 340181701Smarius * Find out what kind of CPU we have first, for anything that changes 341112398Sjake * behaviour. 342112398Sjake */ 343112398Sjake cpu_impl = VER_IMPL(rdpr(ver)); 344112398Sjake 345112398Sjake /* 346207248Smarius * Do CPU-specific initialization. 347182768Smarius */ 348223719Smarius if (cpu_impl >= CPU_IMPL_ULTRASPARCIII) 349204152Smarius cheetah_init(cpu_impl); 350223719Smarius else if (cpu_impl == CPU_IMPL_SPARC64V) 351223719Smarius zeus_init(cpu_impl); 352182768Smarius 353182768Smarius /* 354182730Smarius * Clear (S)TICK timer (including NPT). 355182730Smarius */ 356204152Smarius tick_clear(cpu_impl); 357182730Smarius 358182730Smarius /* 359182730Smarius * UltraSparc II[e,i] based systems come up with the tick interrupt 360182730Smarius * enabled and a handler that resets the tick counter, causing DELAY() 361182730Smarius * to not work properly when used early in boot. 362182730Smarius * UltraSPARC III based systems come up with the system tick interrupt 363182730Smarius * enabled, causing an interrupt storm on startup since they are not 364182730Smarius * handled. 365182730Smarius */ 366204152Smarius tick_stop(cpu_impl); 367182730Smarius 368182730Smarius /* 369186682Smarius * Set up Open Firmware entry points. 37080709Sjake */ 371186347Snwhitehorn ofw_tba = rdpr(tba); 372186347Snwhitehorn ofw_vec = (u_long)vec; 37380709Sjake 37480709Sjake /* 37586521Sjake * Parse metadata if present and fetch parameters. Must be before the 376230633Smarius * console is inited so cninit() gets the right value of boothowto. 37786521Sjake */ 37886521Sjake if (mdp != NULL) { 37986521Sjake preload_metadata = mdp; 380114374Speter kmdp = preload_search_by_type("elf kernel"); 38186521Sjake if (kmdp != NULL) { 38286521Sjake boothowto = MD_FETCH(kmdp, MODINFOMD_HOWTO, int); 383293045Sian init_static_kenv(MD_FETCH(kmdp, MODINFOMD_ENVP, char *), 384293045Sian 0); 38586521Sjake end = MD_FETCH(kmdp, MODINFOMD_KERNEND, vm_offset_t); 38691616Sjake kernel_tlb_slots = MD_FETCH(kmdp, MODINFOMD_DTLB_SLOTS, 38791616Sjake int); 38897445Sjake kernel_tlbs = (void *)preload_search_info(kmdp, 38991616Sjake MODINFO_METADATA | MODINFOMD_DTLB); 39086521Sjake } 39186521Sjake } 39286521Sjake 393122462Sjake init_param1(); 394122462Sjake 395182689Smarius /* 396186347Snwhitehorn * Initialize Open Firmware (needed for console). 397186347Snwhitehorn */ 398186347Snwhitehorn OF_install(OFW_STD_DIRECT, 0); 399186347Snwhitehorn OF_init(ofw_entry); 400186347Snwhitehorn 401186347Snwhitehorn /* 402182689Smarius * Prime our per-CPU data page for use. Note, we are using it for 403182689Smarius * our stack, so don't pass the real size (PAGE_SIZE) to pcpu_init 404182689Smarius * or it'll zero it out from under us. 405182689Smarius */ 406182689Smarius pc = (struct pcpu *)(pcpu0 + (PCPU_PAGES * PAGE_SIZE)) - 1; 407182689Smarius pcpu_init(pc, 0, sizeof(struct pcpu)); 408182689Smarius pc->pc_addr = (vm_offset_t)pcpu0; 409204152Smarius pc->pc_impl = cpu_impl; 410204152Smarius pc->pc_mid = cpu_get_mid(cpu_impl); 411182689Smarius pc->pc_tlb_ctx = TLB_CTX_USER_MIN; 412182689Smarius pc->pc_tlb_ctx_min = TLB_CTX_USER_MIN; 413182689Smarius pc->pc_tlb_ctx_max = TLB_CTX_USER_MAX; 414182689Smarius 415182689Smarius /* 416182730Smarius * Determine the OFW node and frequency of the BSP (and ensure the 417182689Smarius * BSP is in the device tree in the first place). 418182689Smarius */ 419122462Sjake root = OF_peer(0); 420204152Smarius pc->pc_node = find_bsp(root, pc->pc_mid, cpu_impl); 421182689Smarius if (pc->pc_node == 0) 422230633Smarius OF_panic("%s: cannot find boot CPU node", __func__); 423203838Smarius if (OF_getprop(pc->pc_node, "clock-frequency", &pc->pc_clock, 424182730Smarius sizeof(pc->pc_clock)) <= 0) 425230633Smarius OF_panic("%s: cannot determine boot CPU clock", __func__); 426122462Sjake 427157227Smarius /* 428157227Smarius * Panic if there is no metadata. Most likely the kernel was booted 42986521Sjake * directly, instead of through loader(8). 43080709Sjake */ 431195149Smarius if (mdp == NULL || kmdp == NULL || end == 0 || 432230633Smarius kernel_tlb_slots == 0 || kernel_tlbs == NULL) 433230633Smarius OF_panic("%s: missing loader metadata.\nThis probably means " 434230633Smarius "you are not using loader(8).", __func__); 43580709Sjake 43681383Sjake /* 437195149Smarius * Work around the broken loader behavior of not demapping no 438195149Smarius * longer used kernel TLB slots when unloading the kernel or 439195149Smarius * modules. 44086521Sjake */ 441195149Smarius for (va = KERNBASE + (kernel_tlb_slots - 1) * PAGE_SIZE_4M; 442195149Smarius va >= roundup2(end, PAGE_SIZE_4M); va -= PAGE_SIZE_4M) { 443201396Smarius if (bootverbose) 444230633Smarius OF_printf("demapping unused kernel TLB slot " 445201396Smarius "(va %#lx - %#lx)\n", va, va + PAGE_SIZE_4M - 1); 446195149Smarius stxa(TLB_DEMAP_VA(va) | TLB_DEMAP_PRIMARY | TLB_DEMAP_PAGE, 447195149Smarius ASI_DMMU_DEMAP, 0); 448195149Smarius stxa(TLB_DEMAP_VA(va) | TLB_DEMAP_PRIMARY | TLB_DEMAP_PAGE, 449195149Smarius ASI_IMMU_DEMAP, 0); 450195149Smarius flush(KERNBASE); 451195149Smarius kernel_tlb_slots--; 45286521Sjake } 45386521Sjake 454186682Smarius /* 455186682Smarius * Determine the TLB slot maxima, which are expected to be 456186682Smarius * equal across all CPUs. 457205409Smarius * NB: for cheetah-class CPUs, these properties only refer 458186682Smarius * to the t16s. 459186682Smarius */ 460186682Smarius if (OF_getprop(pc->pc_node, "#dtlb-entries", &dtlb_slots, 461186682Smarius sizeof(dtlb_slots)) == -1) 462230633Smarius OF_panic("%s: cannot determine number of dTLB slots", 463230633Smarius __func__); 464186682Smarius if (OF_getprop(pc->pc_node, "#itlb-entries", &itlb_slots, 465186682Smarius sizeof(itlb_slots)) == -1) 466230633Smarius OF_panic("%s: cannot determine number of iTLB slots", 467230633Smarius __func__); 468186682Smarius 469207248Smarius /* 470230633Smarius * Initialize and enable the caches. Note that this may include 471207248Smarius * applying workarounds. 472207248Smarius */ 473182689Smarius cache_init(pc); 474204152Smarius cache_enable(cpu_impl); 475182689Smarius uma_set_align(pc->pc_cache.dc_linesize - 1); 476101898Sjake 477169178Smarius cpu_block_copy = bcopy; 478169178Smarius cpu_block_zero = bzero; 479113166Sjake getenv_int("machdep.use_vis", &cpu_use_vis); 480113166Sjake if (cpu_use_vis) { 481169178Smarius switch (cpu_impl) { 482169178Smarius case CPU_IMPL_SPARC64: 483169178Smarius case CPU_IMPL_ULTRASPARCI: 484169178Smarius case CPU_IMPL_ULTRASPARCII: 485169178Smarius case CPU_IMPL_ULTRASPARCIIi: 486169178Smarius case CPU_IMPL_ULTRASPARCIIe: 487185007Smarius case CPU_IMPL_ULTRASPARCIII: /* NB: we've disabled P$. */ 488185007Smarius case CPU_IMPL_ULTRASPARCIIIp: 489185007Smarius case CPU_IMPL_ULTRASPARCIIIi: 490185007Smarius case CPU_IMPL_ULTRASPARCIV: 491185007Smarius case CPU_IMPL_ULTRASPARCIVp: 492185007Smarius case CPU_IMPL_ULTRASPARCIIIip: 493169178Smarius cpu_block_copy = spitfire_block_copy; 494169178Smarius cpu_block_zero = spitfire_block_zero; 495169178Smarius break; 496212709Smarius case CPU_IMPL_SPARC64V: 497212709Smarius cpu_block_copy = zeus_block_copy; 498212709Smarius cpu_block_zero = zeus_block_zero; 499212709Smarius break; 500169178Smarius } 501113166Sjake } 502113166Sjake 50391616Sjake#ifdef SMP 504285839Smarius mp_init(); 50591616Sjake#endif 50691616Sjake 50786521Sjake /* 50890625Stmm * Initialize virtual memory and calculate physmem. 50987546Sdillon */ 510204152Smarius pmap_bootstrap(cpu_impl); 51187546Sdillon 51287546Sdillon /* 51381383Sjake * Initialize tunables. 51481383Sjake */ 51587546Sdillon init_param2(physmem); 516273174Sdavide env = kern_getenv("kernelname"); 517105569Smux if (env != NULL) { 518219523Smdf strlcpy(kernelname, env, sizeof(kernelname)); 519105569Smux freeenv(env); 520105569Smux } 52181085Sjake 52280709Sjake /* 52389038Sjake * Initialize the interrupt tables. 52489038Sjake */ 52590624Stmm intr_init1(); 52680709Sjake 52780709Sjake /* 528182689Smarius * Initialize proc0, set kstack0, frame0, curthread and curpcb. 52980709Sjake */ 530173361Skib proc_linkup0(&proc0, &thread0); 53195744Sjake proc0.p_md.md_sigtramp = NULL; 53288822Stmm proc0.p_md.md_utrap = NULL; 53390361Sjulian thread0.td_kstack = kstack0; 534218468Smarius thread0.td_kstack_pages = KSTACK_PAGES; 53590361Sjulian thread0.td_pcb = (struct pcb *) 53690361Sjulian (thread0.td_kstack + KSTACK_PAGES * PAGE_SIZE) - 1; 537105908Sjake frame0.tf_tstate = TSTATE_IE | TSTATE_PEF | TSTATE_PRIV; 53890361Sjulian thread0.td_frame = &frame0; 53990361Sjulian pc->pc_curthread = &thread0; 54091156Sjake pc->pc_curpcb = thread0.td_pcb; 54188639Sjake 54280709Sjake /* 543163973Sjb * Initialize global registers. 544163973Sjb */ 545163973Sjb cpu_setregs(pc); 546163973Sjb 547163973Sjb /* 548182773Smarius * Take over the trap table via the PROM. Using the PROM for this 549182773Smarius * is necessary in order to set obp-control-relinquished to true 550182773Smarius * within the PROM so obtaining /virtual-memory/translations doesn't 551182773Smarius * trigger a fatal reset error or worse things further down the road. 552220939Smarius * XXX it should be possible to use this solely instead of writing 553182773Smarius * %tba in cpu_setregs(). Doing so causes a hang however. 554259102Smarius * 555259102Smarius * NB: the low-level console drivers require a working DELAY() and 556259102Smarius * some compiler optimizations may cause the curthread accesses of 557259102Smarius * mutex(9) to be factored out even if the latter aren't actually 558259102Smarius * called. Both of these require PCPU_REG to be set. However, we 559259102Smarius * can't set PCPU_REG without also taking over the trap table or the 560259102Smarius * firmware will overwrite it. 561182773Smarius */ 562182773Smarius sun4u_set_traptable(tl0_base); 563182773Smarius 564182773Smarius /* 565194784Sjeff * Initialize the dynamic per-CPU area for the BSP and the message 566194784Sjeff * buffer (after setting the trap table). 56788822Stmm */ 568194784Sjeff dpcpu_init(dpcpu0, 0); 569217688Spluknet msgbufinit(msgbufp, msgbufsize); 57088822Stmm 571207248Smarius /* 572207248Smarius * Initialize mutexes. 573207248Smarius */ 57493702Sjhb mutex_init(); 575207248Smarius 576207248Smarius /* 577259016Sray * Initialize console now that we have a reasonable set of system 578259016Sray * services. 579259016Sray */ 580259016Sray cninit(); 581259016Sray 582259016Sray /* 583207248Smarius * Finish the interrupt initialization now that mutexes work and 584207248Smarius * enable them. 585207248Smarius */ 58690624Stmm intr_init2(); 587213873Smarius wrpr(pil, 0, 0); 588207248Smarius wrpr(pstate, 0, PSTATE_KERNEL); 589105946Stmm 590106555Stmm OF_getprop(root, "name", sparc64_model, sizeof(sparc64_model) - 1); 591122604Ssimokawa 592131950Smarcel kdb_init(); 593131950Smarcel 594190161Smarius#ifdef KDB 595122604Ssimokawa if (boothowto & RB_KDB) 596174898Srwatson kdb_enter(KDB_WHY_BOOTFLAGS, "Boot flags requested debugger"); 597190161Smarius#endif 59880708Sjake} 59980708Sjake 60080708Sjakevoid 601151316Sdavidxusendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask) 60280708Sjake{ 60382902Sjake struct trapframe *tf; 60482902Sjake struct sigframe *sfp; 60582902Sjake struct sigacts *psp; 60682902Sjake struct sigframe sf; 60783366Sjulian struct thread *td; 60885242Sjake struct frame *fp; 60982902Sjake struct proc *p; 610181701Smarius u_long sp; 61185242Sjake int oonstack; 612151316Sdavidxu int sig; 61382902Sjake 61482902Sjake oonstack = 0; 61583366Sjulian td = curthread; 61683366Sjulian p = td->td_proc; 617114983Sjhb PROC_LOCK_ASSERT(p, MA_OWNED); 618151316Sdavidxu sig = ksi->ksi_signo; 61982902Sjake psp = p->p_sigacts; 620114983Sjhb mtx_assert(&psp->ps_mtx, MA_OWNED); 62183366Sjulian tf = td->td_frame; 62282902Sjake sp = tf->tf_sp + SPOFF; 62382902Sjake oonstack = sigonstack(sp); 62482902Sjake 62583366Sjulian CTR4(KTR_SIG, "sendsig: td=%p (%s) catcher=%p sig=%d", td, p->p_comm, 62682902Sjake catcher, sig); 62782902Sjake 628102554Sjake /* Make sure we have a signal trampoline to return to. */ 629102554Sjake if (p->p_md.md_sigtramp == NULL) { 630102554Sjake /* 631157445Smarius * No signal trampoline... kill the process. 632102554Sjake */ 633102554Sjake CTR0(KTR_SIG, "sendsig: no sigtramp"); 634102873Sjake printf("sendsig: %s is too old, rebuild it\n", p->p_comm); 635102554Sjake sigexit(td, sig); 636102554Sjake /* NOTREACHED */ 637102554Sjake } 638102554Sjake 63982902Sjake /* Save user context. */ 64082902Sjake bzero(&sf, sizeof(sf)); 641118708Sjake get_mcontext(td, &sf.sf_uc.uc_mcontext, 0); 64282902Sjake sf.sf_uc.uc_sigmask = *mask; 643124092Sdavidxu sf.sf_uc.uc_stack = td->td_sigstk; 644181701Smarius sf.sf_uc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK) ? 645181701Smarius ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE; 64682902Sjake 64782902Sjake /* Allocate and validate space for the signal handler context. */ 648124092Sdavidxu if ((td->td_pflags & TDP_ALTSTACK) != 0 && !oonstack && 64982902Sjake SIGISMEMBER(psp->ps_sigonstack, sig)) { 650294930Sjhb sfp = (struct sigframe *)((uintptr_t)td->td_sigstk.ss_sp + 651124092Sdavidxu td->td_sigstk.ss_size - sizeof(struct sigframe)); 65282902Sjake } else 65382902Sjake sfp = (struct sigframe *)sp - 1; 654114983Sjhb mtx_unlock(&psp->ps_mtx); 65582902Sjake PROC_UNLOCK(p); 65682902Sjake 65785242Sjake fp = (struct frame *)sfp - 1; 65882902Sjake 65982902Sjake /* Build the argument list for the signal handler. */ 66082902Sjake tf->tf_out[0] = sig; 66182902Sjake tf->tf_out[2] = (register_t)&sfp->sf_uc; 66282902Sjake tf->tf_out[4] = (register_t)catcher; 663157445Smarius if (SIGISMEMBER(psp->ps_siginfo, sig)) { 664157445Smarius /* Signal handler installed with SA_SIGINFO. */ 665157445Smarius tf->tf_out[1] = (register_t)&sfp->sf_si; 66682902Sjake 667157445Smarius /* Fill in POSIX parts. */ 668157445Smarius sf.sf_si = ksi->ksi_info; 669157445Smarius sf.sf_si.si_signo = sig; /* maybe a translated signal */ 670157445Smarius } else { 671157445Smarius /* Old FreeBSD-style arguments. */ 672157445Smarius tf->tf_out[1] = ksi->ksi_code; 673157445Smarius tf->tf_out[3] = (register_t)ksi->ksi_addr; 674157445Smarius } 675157445Smarius 67682902Sjake /* Copy the sigframe out to the user's stack. */ 67785242Sjake if (rwindow_save(td) != 0 || copyout(&sf, sfp, sizeof(*sfp)) != 0 || 67894254Sjake suword(&fp->fr_in[6], tf->tf_out[6]) != 0) { 67982902Sjake /* 68082902Sjake * Something is wrong with the stack pointer. 68182902Sjake * ...Kill the process. 68282902Sjake */ 68383366Sjulian CTR2(KTR_SIG, "sendsig: sigexit td=%p sfp=%p", td, sfp); 68482902Sjake PROC_LOCK(p); 68583366Sjulian sigexit(td, SIGILL); 68682902Sjake /* NOTREACHED */ 68782902Sjake } 68882902Sjake 689102554Sjake tf->tf_tpc = (u_long)p->p_md.md_sigtramp; 69082902Sjake tf->tf_tnpc = tf->tf_tpc + 4; 69185242Sjake tf->tf_sp = (u_long)fp - SPOFF; 69282902Sjake 69383366Sjulian CTR3(KTR_SIG, "sendsig: return td=%p pc=%#lx sp=%#lx", td, tf->tf_tpc, 69482902Sjake tf->tf_sp); 69584178Sjake 69684178Sjake PROC_LOCK(p); 697114983Sjhb mtx_lock(&psp->ps_mtx); 69880708Sjake} 69980708Sjake 70080708Sjake#ifndef _SYS_SYSPROTO_H_ 70183088Sobrienstruct sigreturn_args { 70280708Sjake ucontext_t *ucp; 70380708Sjake}; 70480708Sjake#endif 70580708Sjake 70694606Salc/* 70794606Salc * MPSAFE 70894606Salc */ 70980708Sjakeint 710225617Skmacysys_sigreturn(struct thread *td, struct sigreturn_args *uap) 71180708Sjake{ 71283366Sjulian struct proc *p; 713118768Sjake mcontext_t *mc; 71482902Sjake ucontext_t uc; 715118708Sjake int error; 71682902Sjake 71783366Sjulian p = td->td_proc; 71883366Sjulian if (rwindow_save(td)) { 71982902Sjake PROC_LOCK(p); 72083366Sjulian sigexit(td, SIGILL); 72182902Sjake } 72282902Sjake 72383366Sjulian CTR2(KTR_SIG, "sigreturn: td=%p ucp=%p", td, uap->sigcntxp); 72482902Sjake if (copyin(uap->sigcntxp, &uc, sizeof(uc)) != 0) { 72583366Sjulian CTR1(KTR_SIG, "sigreturn: efault td=%p", td); 72682902Sjake return (EFAULT); 72782902Sjake } 72882902Sjake 729118768Sjake mc = &uc.uc_mcontext; 730118768Sjake error = set_mcontext(td, mc); 731118708Sjake if (error != 0) 732118708Sjake return (error); 73382902Sjake 734198507Skib kern_sigprocmask(td, SIG_SETMASK, &uc.uc_sigmask, NULL, 0); 735105733Sjake 73683366Sjulian CTR4(KTR_SIG, "sigreturn: return td=%p pc=%#lx sp=%#lx tstate=%#lx", 737253266Smarius td, mc->_mc_tpc, mc->_mc_sp, mc->_mc_tstate); 73882902Sjake return (EJUSTRETURN); 73980708Sjake} 74080708Sjake 741131905Smarcel/* 742131905Smarcel * Construct a PCB from a trapframe. This is called from kdb_trap() where 743131905Smarcel * we want to start a backtrace from the function that caused us to enter 744131905Smarcel * the debugger. We have the context in the trapframe, but base the trace 745131905Smarcel * on the PCB. The PCB doesn't have to be perfect, as long as it contains 746131905Smarcel * enough for a backtrace. 747131905Smarcel */ 748131905Smarcelvoid 749131905Smarcelmakectx(struct trapframe *tf, struct pcb *pcb) 750131905Smarcel{ 751131905Smarcel 752131905Smarcel pcb->pcb_pc = tf->tf_tpc; 753131905Smarcel pcb->pcb_sp = tf->tf_sp; 754131905Smarcel} 755131905Smarcel 756106977Sdeischenint 757122364Smarcelget_mcontext(struct thread *td, mcontext_t *mc, int flags) 758106977Sdeischen{ 759112924Sjake struct trapframe *tf; 760112924Sjake struct pcb *pcb; 761106977Sdeischen 762112924Sjake tf = td->td_frame; 763112924Sjake pcb = td->td_pcb; 764199442Smarius /* 765199442Smarius * Copy the registers which will be restored by tl0_ret() from the 766199442Smarius * trapframe. 767199442Smarius * Note that we skip %g7 which is used as the userland TLS register 768199442Smarius * and %wstate. 769199442Smarius */ 770253266Smarius mc->_mc_flags = _MC_VERSION; 771199442Smarius mc->mc_global[1] = tf->tf_global[1]; 772199442Smarius mc->mc_global[2] = tf->tf_global[2]; 773199442Smarius mc->mc_global[3] = tf->tf_global[3]; 774199442Smarius mc->mc_global[4] = tf->tf_global[4]; 775199442Smarius mc->mc_global[5] = tf->tf_global[5]; 776199442Smarius mc->mc_global[6] = tf->tf_global[6]; 777122364Smarcel if (flags & GET_MC_CLEAR_RET) { 778113998Sdeischen mc->mc_out[0] = 0; 779113998Sdeischen mc->mc_out[1] = 0; 780199442Smarius } else { 781199442Smarius mc->mc_out[0] = tf->tf_out[0]; 782199442Smarius mc->mc_out[1] = tf->tf_out[1]; 783113998Sdeischen } 784199442Smarius mc->mc_out[2] = tf->tf_out[2]; 785199442Smarius mc->mc_out[3] = tf->tf_out[3]; 786199442Smarius mc->mc_out[4] = tf->tf_out[4]; 787199442Smarius mc->mc_out[5] = tf->tf_out[5]; 788199442Smarius mc->mc_out[6] = tf->tf_out[6]; 789199442Smarius mc->mc_out[7] = tf->tf_out[7]; 790253266Smarius mc->_mc_fprs = tf->tf_fprs; 791253266Smarius mc->_mc_fsr = tf->tf_fsr; 792253266Smarius mc->_mc_gsr = tf->tf_gsr; 793253266Smarius mc->_mc_tnpc = tf->tf_tnpc; 794253266Smarius mc->_mc_tpc = tf->tf_tpc; 795253266Smarius mc->_mc_tstate = tf->tf_tstate; 796253266Smarius mc->_mc_y = tf->tf_y; 797112924Sjake critical_enter(); 798112961Sjake if ((tf->tf_fprs & FPRS_FEF) != 0) { 799112961Sjake savefpctx(pcb->pcb_ufp); 800112961Sjake tf->tf_fprs &= ~FPRS_FEF; 801112961Sjake pcb->pcb_flags |= PCB_FEF; 802112961Sjake } 803112961Sjake if ((pcb->pcb_flags & PCB_FEF) != 0) { 804113018Sjake bcopy(pcb->pcb_ufp, mc->mc_fp, sizeof(mc->mc_fp)); 805253266Smarius mc->_mc_fprs |= FPRS_FEF; 806112924Sjake } 807112924Sjake critical_exit(); 808112924Sjake return (0); 809106977Sdeischen} 810106977Sdeischen 811106977Sdeischenint 812278001Skibset_mcontext(struct thread *td, mcontext_t *mc) 813106977Sdeischen{ 814112924Sjake struct trapframe *tf; 815112924Sjake struct pcb *pcb; 816106977Sdeischen 817253266Smarius if (!TSTATE_SECURE(mc->_mc_tstate) || 818253266Smarius (mc->_mc_flags & ((1L << _MC_VERSION_BITS) - 1)) != _MC_VERSION) 819112924Sjake return (EINVAL); 820112924Sjake tf = td->td_frame; 821112924Sjake pcb = td->td_pcb; 822136325Skensmith /* Make sure the windows are spilled first. */ 823136325Skensmith flushw(); 824199442Smarius /* 825199442Smarius * Copy the registers which will be restored by tl0_ret() to the 826199442Smarius * trapframe. 827199442Smarius * Note that we skip %g7 which is used as the userland TLS register 828199442Smarius * and %wstate. 829199442Smarius */ 830199442Smarius tf->tf_global[1] = mc->mc_global[1]; 831199442Smarius tf->tf_global[2] = mc->mc_global[2]; 832199442Smarius tf->tf_global[3] = mc->mc_global[3]; 833199442Smarius tf->tf_global[4] = mc->mc_global[4]; 834199442Smarius tf->tf_global[5] = mc->mc_global[5]; 835199442Smarius tf->tf_global[6] = mc->mc_global[6]; 836199442Smarius tf->tf_out[0] = mc->mc_out[0]; 837199442Smarius tf->tf_out[1] = mc->mc_out[1]; 838199442Smarius tf->tf_out[2] = mc->mc_out[2]; 839199442Smarius tf->tf_out[3] = mc->mc_out[3]; 840199442Smarius tf->tf_out[4] = mc->mc_out[4]; 841199442Smarius tf->tf_out[5] = mc->mc_out[5]; 842199442Smarius tf->tf_out[6] = mc->mc_out[6]; 843199442Smarius tf->tf_out[7] = mc->mc_out[7]; 844253266Smarius tf->tf_fprs = mc->_mc_fprs; 845253266Smarius tf->tf_fsr = mc->_mc_fsr; 846253266Smarius tf->tf_gsr = mc->_mc_gsr; 847253266Smarius tf->tf_tnpc = mc->_mc_tnpc; 848253266Smarius tf->tf_tpc = mc->_mc_tpc; 849253266Smarius tf->tf_tstate = mc->_mc_tstate; 850253266Smarius tf->tf_y = mc->_mc_y; 851253266Smarius if ((mc->_mc_fprs & FPRS_FEF) != 0) { 852112924Sjake tf->tf_fprs = 0; 853113018Sjake bcopy(mc->mc_fp, pcb->pcb_ufp, sizeof(pcb->pcb_ufp)); 854112924Sjake pcb->pcb_flags |= PCB_FEF; 855112924Sjake } 856112924Sjake return (0); 857106977Sdeischen} 858106977Sdeischen 85986147Stmm/* 86092205Sjake * Exit the kernel and execute a firmware call that will not return, as 86192205Sjake * specified by the arguments. 86292205Sjake */ 86392205Sjakevoid 86492205Sjakecpu_shutdown(void *args) 86592205Sjake{ 86692205Sjake 86792205Sjake#ifdef SMP 86892205Sjake cpu_mp_shutdown(); 86992205Sjake#endif 870186347Snwhitehorn ofw_exit(args); 87192205Sjake} 87292205Sjake 873192323Smarcel/* 874192323Smarcel * Flush the D-cache for non-DMA I/O so that the I-cache can 875192323Smarcel * be made coherent later. 876192323Smarcel */ 877192323Smarcelvoid 878192323Smarcelcpu_flush_dcache(void *ptr, size_t len) 879192323Smarcel{ 880195149Smarius 881192323Smarcel /* TBD */ 882192323Smarcel} 883192323Smarcel 884181701Smarius/* Get current clock frequency for the given CPU ID. */ 885141237Snjlint 886141237Snjlcpu_est_clockrate(int cpu_id, uint64_t *rate) 887141237Snjl{ 888182730Smarius struct pcpu *pc; 889141237Snjl 890182730Smarius pc = pcpu_find(cpu_id); 891182730Smarius if (pc == NULL || rate == NULL) 892182730Smarius return (EINVAL); 893182730Smarius *rate = pc->pc_clock; 894182730Smarius return (0); 895141237Snjl} 896141237Snjl 89792205Sjake/* 89886147Stmm * Duplicate OF_exit() with a different firmware call function that restores 89986147Stmm * the trap table, otherwise a RED state exception is triggered in at least 90086147Stmm * some firmware versions. 90186147Stmm */ 90280708Sjakevoid 90380708Sjakecpu_halt(void) 90480708Sjake{ 90586147Stmm static struct { 90686147Stmm cell_t name; 90786147Stmm cell_t nargs; 90886147Stmm cell_t nreturns; 90986147Stmm } args = { 91086147Stmm (cell_t)"exit", 91186147Stmm 0, 91286147Stmm 0 91386147Stmm }; 91484178Sjake 91592205Sjake cpu_shutdown(&args); 91680708Sjake} 91780708Sjake 918203838Smariusstatic void 91986147Stmmsparc64_shutdown_final(void *dummy, int howto) 92086147Stmm{ 92186147Stmm static struct { 92286147Stmm cell_t name; 92386147Stmm cell_t nargs; 92486147Stmm cell_t nreturns; 92586147Stmm } args = { 92686147Stmm (cell_t)"SUNW,power-off", 92786147Stmm 0, 92886147Stmm 0 92986147Stmm }; 93086147Stmm 93186147Stmm /* Turn the power off? */ 93286147Stmm if ((howto & RB_POWEROFF) != 0) 93392205Sjake cpu_shutdown(&args); 934185007Smarius /* In case of halt, return to the firmware. */ 93586147Stmm if ((howto & RB_HALT) != 0) 93686147Stmm cpu_halt(); 93786147Stmm} 93886147Stmm 939121237Spetervoid 940178471Sjeffcpu_idle(int busy) 941121237Speter{ 942181701Smarius 943181701Smarius /* Insert code to halt (until next interrupt) for the idle loop. */ 944121237Speter} 945121237Speter 94680708Sjakeint 947178471Sjeffcpu_idle_wakeup(int cpu) 948178471Sjeff{ 949178471Sjeff 950212456Smav return (1); 951178471Sjeff} 952178471Sjeff 953178471Sjeffint 95483366Sjulianptrace_set_pc(struct thread *td, u_long addr) 95580708Sjake{ 95682016Sjake 95783366Sjulian td->td_frame->tf_tpc = addr; 95883366Sjulian td->td_frame->tf_tnpc = addr + 4; 95980708Sjake return (0); 96080708Sjake} 96180708Sjake 96280708Sjakeint 96383366Sjulianptrace_single_step(struct thread *td) 96480708Sjake{ 965181701Smarius 966104271Sjake /* TODO; */ 96780708Sjake return (0); 96880708Sjake} 96980708Sjake 970132088Sdavidxuint 971132088Sdavidxuptrace_clear_single_step(struct thread *td) 972132088Sdavidxu{ 973181701Smarius 974132088Sdavidxu /* TODO; */ 975132088Sdavidxu return (0); 976132088Sdavidxu} 977132088Sdavidxu 97880708Sjakevoid 979205642Snwhitehornexec_setregs(struct thread *td, struct image_params *imgp, u_long stack) 98080708Sjake{ 98188639Sjake struct trapframe *tf; 98281135Stmm struct pcb *pcb; 983102557Sjake struct proc *p; 98484178Sjake u_long sp; 98581135Stmm 98688782Sjake /* XXX no cpu_exec */ 987102557Sjake p = td->td_proc; 988102557Sjake p->p_md.md_sigtramp = NULL; 989140485Sjhb if (p->p_md.md_utrap != NULL) { 990140485Sjhb utrap_free(p->p_md.md_utrap); 991102557Sjake p->p_md.md_utrap = NULL; 99288782Sjake } 99388782Sjake 99483366Sjulian pcb = td->td_pcb; 995105908Sjake tf = td->td_frame; 99688639Sjake sp = rounddown(stack, 16); 99798032Sjake bzero(pcb, sizeof(*pcb)); 99898032Sjake bzero(tf, sizeof(*tf)); 99988639Sjake tf->tf_out[0] = stack; 1000105908Sjake tf->tf_out[3] = p->p_sysent->sv_psstrings; 100188639Sjake tf->tf_out[6] = sp - SPOFF - sizeof(struct frame); 1002205642Snwhitehorn tf->tf_tnpc = imgp->entry_addr + 4; 1003205642Snwhitehorn tf->tf_tpc = imgp->entry_addr; 1004225888Smarius /* 1005225888Smarius * While we could adhere to the memory model indicated in the ELF 1006225888Smarius * header, it turns out that just always using TSO performs best. 1007225888Smarius */ 100888639Sjake tf->tf_tstate = TSTATE_IE | TSTATE_PEF | TSTATE_MM_TSO; 100988639Sjake 101088639Sjake td->td_retval[0] = tf->tf_out[0]; 101188639Sjake td->td_retval[1] = tf->tf_out[1]; 101280708Sjake} 101380708Sjake 101480708Sjakeint 101584178Sjakefill_regs(struct thread *td, struct reg *regs) 101680708Sjake{ 101780708Sjake 1018105733Sjake bcopy(td->td_frame, regs, sizeof(*regs)); 101980708Sjake return (0); 102080708Sjake} 102180708Sjake 102280708Sjakeint 102384178Sjakeset_regs(struct thread *td, struct reg *regs) 102480708Sjake{ 1025112922Sjake struct trapframe *tf; 102680708Sjake 102784178Sjake if (!TSTATE_SECURE(regs->r_tstate)) 102884178Sjake return (EINVAL); 1029112922Sjake tf = td->td_frame; 1030112922Sjake regs->r_wstate = tf->tf_wstate; 1031112922Sjake bcopy(regs, tf, sizeof(*regs)); 103280708Sjake return (0); 103380708Sjake} 103480708Sjake 103580708Sjakeint 103685294Sdesfill_dbregs(struct thread *td, struct dbreg *dbregs) 103785294Sdes{ 103885294Sdes 103985294Sdes return (ENOSYS); 104085294Sdes} 104185294Sdes 104285294Sdesint 104385294Sdesset_dbregs(struct thread *td, struct dbreg *dbregs) 104485294Sdes{ 104585294Sdes 104685294Sdes return (ENOSYS); 104785294Sdes} 104885294Sdes 104985294Sdesint 105083366Sjulianfill_fpregs(struct thread *td, struct fpreg *fpregs) 105180708Sjake{ 105288639Sjake struct trapframe *tf; 105384178Sjake struct pcb *pcb; 105484178Sjake 105584178Sjake pcb = td->td_pcb; 105688639Sjake tf = td->td_frame; 1057112920Sjake bcopy(pcb->pcb_ufp, fpregs->fr_regs, sizeof(fpregs->fr_regs)); 105888639Sjake fpregs->fr_fsr = tf->tf_fsr; 1059105733Sjake fpregs->fr_gsr = tf->tf_gsr; 1060341491Smarkj fpregs->fr_pad[0] = 0; 106180708Sjake return (0); 106280708Sjake} 106380708Sjake 106480708Sjakeint 106583366Sjulianset_fpregs(struct thread *td, struct fpreg *fpregs) 106680708Sjake{ 106788639Sjake struct trapframe *tf; 106884178Sjake struct pcb *pcb; 106984178Sjake 107084178Sjake pcb = td->td_pcb; 107188639Sjake tf = td->td_frame; 1072112922Sjake tf->tf_fprs &= ~FPRS_FEF; 1073112920Sjake bcopy(fpregs->fr_regs, pcb->pcb_ufp, sizeof(pcb->pcb_ufp)); 107488639Sjake tf->tf_fsr = fpregs->fr_fsr; 1075105733Sjake tf->tf_gsr = fpregs->fr_gsr; 107680708Sjake return (0); 107780708Sjake} 1078140485Sjhb 1079140485Sjhbstruct md_utrap * 1080140485Sjhbutrap_alloc(void) 1081140485Sjhb{ 1082140485Sjhb struct md_utrap *ut; 1083140485Sjhb 1084140485Sjhb ut = malloc(sizeof(struct md_utrap), M_SUBPROC, M_WAITOK | M_ZERO); 1085140485Sjhb ut->ut_refcnt = 1; 1086140485Sjhb return (ut); 1087140485Sjhb} 1088140485Sjhb 1089140485Sjhbvoid 1090140485Sjhbutrap_free(struct md_utrap *ut) 1091140485Sjhb{ 1092140485Sjhb int refcnt; 1093140485Sjhb 1094140485Sjhb if (ut == NULL) 1095140485Sjhb return; 1096140485Sjhb mtx_pool_lock(mtxpool_sleep, ut); 1097140485Sjhb ut->ut_refcnt--; 1098140485Sjhb refcnt = ut->ut_refcnt; 1099140485Sjhb mtx_pool_unlock(mtxpool_sleep, ut); 1100140485Sjhb if (refcnt == 0) 1101140485Sjhb free(ut, M_SUBPROC); 1102140485Sjhb} 1103140485Sjhb 1104140485Sjhbstruct md_utrap * 1105140485Sjhbutrap_hold(struct md_utrap *ut) 1106140485Sjhb{ 1107140485Sjhb 1108140485Sjhb if (ut == NULL) 1109140485Sjhb return (NULL); 1110140485Sjhb mtx_pool_lock(mtxpool_sleep, ut); 1111140485Sjhb ut->ut_refcnt++; 1112140485Sjhb mtx_pool_unlock(mtxpool_sleep, ut); 1113140485Sjhb return (ut); 1114140485Sjhb} 1115