machdep.c revision 262861
1323124Sdes/*- 2180750Sdes * Copyright (c) 2001 Jake Burkholder. 3180750Sdes * Copyright (c) 1992 Terrence R. Lambert. 4180750Sdes * Copyright (c) 1982, 1987, 1990 The Regents of the University of California. 5180750Sdes * All rights reserved. 6180750Sdes * 7180750Sdes * This code is derived from software contributed to Berkeley by 8180750Sdes * William Jolitz. 9180750Sdes * 10180750Sdes * Redistribution and use in source and binary forms, with or without 11180750Sdes * modification, are permitted provided that the following conditions 12180750Sdes * are met: 13180750Sdes * 1. Redistributions of source code must retain the above copyright 14180750Sdes * notice, this list of conditions and the following disclaimer. 15180750Sdes * 2. Redistributions in binary form must reproduce the above copyright 16180750Sdes * notice, this list of conditions and the following disclaimer in the 17180750Sdes * documentation and/or other materials provided with the distribution. 18180750Sdes * 4. Neither the name of the University nor the names of its contributors 19180750Sdes * may be used to endorse or promote products derived from this software 20180750Sdes * without specific prior written permission. 21180750Sdes * 22204917Sdes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23180750Sdes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24204917Sdes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25204917Sdes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26204917Sdes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27204917Sdes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28204917Sdes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29204917Sdes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30204917Sdes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31180750Sdes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32180750Sdes * SUCH DAMAGE. 33204917Sdes * 34294666Sdes * from: @(#)machdep.c 7.4 (Berkeley) 6/3/91 35204917Sdes * from: FreeBSD: src/sys/i386/i386/machdep.c,v 1.477 2001/08/27 36180750Sdes */ 37180750Sdes 38180750Sdes#include <sys/cdefs.h> 39180750Sdes__FBSDID("$FreeBSD: stable/10/sys/sparc64/sparc64/machdep.c 262861 2014-03-06 18:30:56Z jhb $"); 40180750Sdes 41180750Sdes#include "opt_compat.h" 42180750Sdes#include "opt_ddb.h" 43180750Sdes#include "opt_kstack_pages.h" 44180750Sdes 45180750Sdes#include <sys/param.h> 46180750Sdes#include <sys/malloc.h> 47180750Sdes#include <sys/proc.h> 48180750Sdes#include <sys/systm.h> 49180750Sdes#include <sys/bio.h> 50180750Sdes#include <sys/buf.h> 51180750Sdes#include <sys/bus.h> 52180750Sdes#include <sys/cpu.h> 53180750Sdes#include <sys/cons.h> 54204917Sdes#include <sys/eventhandler.h> 55204917Sdes#include <sys/exec.h> 56204917Sdes#include <sys/imgact.h> 57204917Sdes#include <sys/interrupt.h> 58204917Sdes#include <sys/kdb.h> 59204917Sdes#include <sys/kernel.h> 60204917Sdes#include <sys/ktr.h> 61204917Sdes#include <sys/linker.h> 62180750Sdes#include <sys/lock.h> 63180750Sdes#include <sys/msgbuf.h> 64180750Sdes#include <sys/mutex.h> 65180750Sdes#include <sys/pcpu.h> 66180750Sdes#include <sys/ptrace.h> 67180750Sdes#include <sys/reboot.h> 68180750Sdes#include <sys/rwlock.h> 69180750Sdes#include <sys/signalvar.h> 70215116Sdes#include <sys/smp.h> 71180750Sdes#include <sys/syscallsubr.h> 72180750Sdes#include <sys/sysent.h> 73180750Sdes#include <sys/sysproto.h> 74180750Sdes#include <sys/timetc.h> 75180750Sdes#include <sys/ucontext.h> 76180750Sdes 77180750Sdes#include <dev/ofw/openfirm.h> 78180750Sdes 79180750Sdes#include <vm/vm.h> 80180750Sdes#include <vm/vm_extern.h> 81180750Sdes#include <vm/vm_kern.h> 82180750Sdes#include <vm/vm_page.h> 83180750Sdes#include <vm/vm_map.h> 84180750Sdes#include <vm/vm_object.h> 85180750Sdes#include <vm/vm_pager.h> 86180750Sdes#include <vm/vm_param.h> 87180750Sdes 88180750Sdes#include <ddb/ddb.h> 89204917Sdes 90180750Sdes#include <machine/bus.h> 91204917Sdes#include <machine/cache.h> 92180750Sdes#include <machine/cmt.h> 93180750Sdes#include <machine/cpu.h> 94180750Sdes#include <machine/fireplane.h> 95204917Sdes#include <machine/fp.h> 96204917Sdes#include <machine/fsr.h> 97204917Sdes#include <machine/intr_machdep.h> 98204917Sdes#include <machine/jbus.h> 99180750Sdes#include <machine/md_var.h> 100180750Sdes#include <machine/metadata.h> 101180750Sdes#include <machine/ofw_machdep.h> 102180750Sdes#include <machine/ofw_mem.h> 103215116Sdes#include <machine/pcb.h> 104180750Sdes#include <machine/pmap.h> 105180750Sdes#include <machine/pstate.h> 106295367Sdes#include <machine/reg.h> 107295367Sdes#include <machine/sigframe.h> 108295367Sdes#include <machine/smp.h> 109295367Sdes#include <machine/tick.h> 110295367Sdes#include <machine/tlb.h> 111215116Sdes#include <machine/tstate.h> 112215116Sdes#include <machine/upa.h> 113215116Sdes#include <machine/ver.h> 114215116Sdes 115215116Sdestypedef int ofw_vec_t(void *); 116215116Sdes 117215116Sdes#ifdef DDB 118180750Sdesextern vm_offset_t ksym_start, ksym_end; 119180750Sdes#endif 120180750Sdes 121204917Sdesint dtlb_slots; 122204917Sdesint itlb_slots; 123204917Sdesstruct tlb_entry *kernel_tlbs; 124180750Sdesint kernel_tlb_slots; 125180750Sdes 126180750Sdesint cold = 1; 127180750Sdeslong Maxmem; 128180750Sdeslong realmem; 129180750Sdes 130180750Sdesvoid *dpcpu0; 131180750Sdeschar pcpu0[PCPU_PAGES * PAGE_SIZE]; 132180750Sdesstruct trapframe frame0; 133204917Sdes 134180750Sdesvm_offset_t kstack0; 135204917Sdesvm_paddr_t kstack0_phys; 136204917Sdes 137204917Sdesstruct kva_md_info kmi; 138180750Sdes 139204917Sdesu_long ofw_vec; 140204917Sdesu_long ofw_tba; 141204917Sdesu_int tba_taken_over; 142204917Sdes 143204917Sdeschar sparc64_model[32]; 144204917Sdes 145204917Sdesstatic int cpu_use_vis = 1; 146204917Sdes 147226046Sdescpu_block_copy_t *cpu_block_copy; 148204917Sdescpu_block_zero_t *cpu_block_zero; 149204917Sdes 150204917Sdesstatic phandle_t find_bsp(phandle_t node, uint32_t bspid, u_int cpu_impl); 151204917Sdesvoid sparc64_init(caddr_t mdp, u_long o1, u_long o2, u_long o3, 152204917Sdes ofw_vec_t *vec); 153204917Sdesstatic void sparc64_shutdown_final(void *dummy, int howto); 154215116Sdes 155226046Sdesstatic void cpu_startup(void *arg); 156204917SdesSYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL); 157204917Sdes 158204917SdesCTASSERT((1 << INT_SHIFT) == sizeof(int)); 159204917SdesCTASSERT((1 << PTR_SHIFT) == sizeof(char *)); 160204917Sdes 161204917SdesCTASSERT(sizeof(struct reg) == 256); 162215116SdesCTASSERT(sizeof(struct fpreg) == 272); 163295367SdesCTASSERT(sizeof(struct __mcontext) == 512); 164204917Sdes 165204917SdesCTASSERT((sizeof(struct pcb) & (64 - 1)) == 0); 166204917SdesCTASSERT((offsetof(struct pcb, pcb_kfp) & (64 - 1)) == 0); 167204917SdesCTASSERT((offsetof(struct pcb, pcb_ufp) & (64 - 1)) == 0); 168204917SdesCTASSERT(sizeof(struct pcb) <= ((KSTACK_PAGES * PAGE_SIZE) / 8)); 169204917Sdes 170204917SdesCTASSERT(sizeof(struct pcpu) <= ((PCPU_PAGES * PAGE_SIZE) / 2)); 171204917Sdes 172226046Sdesstatic void 173204917Sdescpu_startup(void *arg) 174204917Sdes{ 175204917Sdes vm_paddr_t physsz; 176204917Sdes int i; 177204917Sdes 178204917Sdes physsz = 0; 179204917Sdes for (i = 0; i < sparc64_nmemreg; i++) 180204917Sdes physsz += sparc64_memreg[i].mr_size; 181204917Sdes printf("real memory = %lu (%lu MB)\n", physsz, 182204917Sdes physsz / (1024 * 1024)); 183204917Sdes realmem = (long)physsz / PAGE_SIZE; 184204917Sdes 185226046Sdes vm_ksubmap_init(&kmi); 186204917Sdes 187204917Sdes bufinit(); 188204917Sdes vm_pager_bufferinit(); 189204917Sdes 190204917Sdes EVENTHANDLER_REGISTER(shutdown_final, sparc64_shutdown_final, NULL, 191255767Sdes SHUTDOWN_PRI_LAST); 192204917Sdes 193204917Sdes printf("avail memory = %lu (%lu MB)\n", cnt.v_free_count * PAGE_SIZE, 194204917Sdes cnt.v_free_count / ((1024 * 1024) / PAGE_SIZE)); 195204917Sdes 196204917Sdes if (bootverbose) 197204917Sdes printf("machine: %s\n", sparc64_model); 198204917Sdes 199204917Sdes cpu_identify(rdpr(ver), PCPU_GET(clock), curcpu); 200204917Sdes} 201204917Sdes 202204917Sdesvoid 203204917Sdescpu_pcpu_init(struct pcpu *pcpu, int cpuid, size_t size) 204204917Sdes{ 205204917Sdes struct intr_request *ir; 206204917Sdes int i; 207204917Sdes 208204917Sdes pcpu->pc_irtail = &pcpu->pc_irhead; 209204917Sdes for (i = 0; i < IR_FREE; i++) { 210204917Sdes ir = &pcpu->pc_irpool[i]; 211204917Sdes ir->ir_next = pcpu->pc_irfree; 212204917Sdes pcpu->pc_irfree = ir; 213204917Sdes } 214204917Sdes} 215204917Sdes 216204917Sdesvoid 217204917Sdesspinlock_enter(void) 218204917Sdes{ 219204917Sdes struct thread *td; 220204917Sdes register_t pil; 221204917Sdes 222215116Sdes td = curthread; 223204917Sdes if (td->td_md.md_spinlock_count == 0) { 224204917Sdes pil = rdpr(pil); 225204917Sdes wrpr(pil, 0, PIL_TICK); 226255767Sdes td->td_md.md_spinlock_count = 1; 227255767Sdes td->td_md.md_saved_pil = pil; 228204917Sdes } else 229204917Sdes td->td_md.md_spinlock_count++; 230204917Sdes critical_enter(); 231204917Sdes} 232204917Sdes 233204917Sdesvoid 234204917Sdesspinlock_exit(void) 235204917Sdes{ 236204917Sdes struct thread *td; 237204917Sdes register_t pil; 238204917Sdes 239204917Sdes td = curthread; 240204917Sdes critical_exit(); 241204917Sdes pil = td->td_md.md_saved_pil; 242204917Sdes td->td_md.md_spinlock_count--; 243204917Sdes if (td->td_md.md_spinlock_count == 0) 244204917Sdes wrpr(pil, pil, 0); 245204917Sdes} 246204917Sdes 247204917Sdesstatic phandle_t 248204917Sdesfind_bsp(phandle_t node, uint32_t bspid, u_int cpu_impl) 249204917Sdes{ 250204917Sdes char type[sizeof("cpu")]; 251204917Sdes phandle_t child; 252204917Sdes uint32_t cpuid; 253204917Sdes 254204917Sdes for (; node != 0; node = OF_peer(node)) { 255204917Sdes child = OF_child(node); 256204917Sdes if (child > 0) { 257204917Sdes child = find_bsp(child, bspid, cpu_impl); 258204917Sdes if (child > 0) 259204917Sdes return (child); 260204917Sdes } else { 261204917Sdes if (OF_getprop(node, "device_type", type, 262204917Sdes sizeof(type)) <= 0) 263204917Sdes continue; 264204917Sdes if (strcmp(type, "cpu") != 0) 265204917Sdes continue; 266204917Sdes if (OF_getprop(node, cpu_cpuid_prop(cpu_impl), &cpuid, 267204917Sdes sizeof(cpuid)) <= 0) 268204917Sdes continue; 269204917Sdes if (cpuid == bspid) 270204917Sdes return (node); 271204917Sdes } 272204917Sdes } 273204917Sdes return (0); 274204917Sdes} 275204917Sdes 276204917Sdesconst char * 277204917Sdescpu_cpuid_prop(u_int cpu_impl) 278204917Sdes{ 279204917Sdes 280204917Sdes switch (cpu_impl) { 281204917Sdes case CPU_IMPL_SPARC64: 282204917Sdes case CPU_IMPL_SPARC64V: 283204917Sdes case CPU_IMPL_ULTRASPARCI: 284204917Sdes case CPU_IMPL_ULTRASPARCII: 285204917Sdes case CPU_IMPL_ULTRASPARCIIi: 286204917Sdes case CPU_IMPL_ULTRASPARCIIe: 287204917Sdes return ("upa-portid"); 288204917Sdes case CPU_IMPL_ULTRASPARCIII: 289204917Sdes case CPU_IMPL_ULTRASPARCIIIp: 290204917Sdes case CPU_IMPL_ULTRASPARCIIIi: 291204917Sdes case CPU_IMPL_ULTRASPARCIIIip: 292204917Sdes return ("portid"); 293204917Sdes case CPU_IMPL_ULTRASPARCIV: 294255767Sdes case CPU_IMPL_ULTRASPARCIVp: 295255767Sdes return ("cpuid"); 296204917Sdes default: 297204917Sdes return (""); 298204917Sdes } 299255767Sdes} 300255767Sdes 301204917Sdesuint32_t 302204917Sdescpu_get_mid(u_int cpu_impl) 303204917Sdes{ 304204917Sdes 305204917Sdes switch (cpu_impl) { 306204917Sdes case CPU_IMPL_SPARC64: 307204917Sdes case CPU_IMPL_SPARC64V: 308204917Sdes case CPU_IMPL_ULTRASPARCI: 309204917Sdes case CPU_IMPL_ULTRASPARCII: 310204917Sdes case CPU_IMPL_ULTRASPARCIIi: 311204917Sdes case CPU_IMPL_ULTRASPARCIIe: 312204917Sdes return (UPA_CR_GET_MID(ldxa(0, ASI_UPA_CONFIG_REG))); 313204917Sdes case CPU_IMPL_ULTRASPARCIII: 314204917Sdes case CPU_IMPL_ULTRASPARCIIIp: 315204917Sdes return (FIREPLANE_CR_GET_AID(ldxa(AA_FIREPLANE_CONFIG, 316204917Sdes ASI_FIREPLANE_CONFIG_REG))); 317204917Sdes case CPU_IMPL_ULTRASPARCIIIi: 318215116Sdes case CPU_IMPL_ULTRASPARCIIIip: 319204917Sdes return (JBUS_CR_GET_JID(ldxa(0, ASI_JBUS_CONFIG_REG))); 320240075Sdes case CPU_IMPL_ULTRASPARCIV: 321240075Sdes case CPU_IMPL_ULTRASPARCIVp: 322204917Sdes return (INTR_ID_GET_ID(ldxa(AA_INTR_ID, ASI_INTR_ID))); 323204917Sdes default: 324204917Sdes return (0); 325204917Sdes } 326204917Sdes} 327204917Sdes 328204917Sdesvoid 329204917Sdessparc64_init(caddr_t mdp, u_long o1, u_long o2, u_long o3, ofw_vec_t *vec) 330204917Sdes{ 331255767Sdes char *env; 332255767Sdes struct pcpu *pc; 333240075Sdes vm_offset_t end; 334255767Sdes vm_offset_t va; 335255767Sdes caddr_t kmdp; 336255767Sdes phandle_t root; 337255767Sdes u_int cpu_impl; 338204917Sdes 339204917Sdes end = 0; 340204917Sdes kmdp = NULL; 341255767Sdes 342204917Sdes /* 343204917Sdes * Find out what kind of CPU we have first, for anything that changes 344204917Sdes * behaviour. 345204917Sdes */ 346240075Sdes cpu_impl = VER_IMPL(rdpr(ver)); 347204917Sdes 348204917Sdes /* 349255767Sdes * Do CPU-specific initialization. 350204917Sdes */ 351204917Sdes if (cpu_impl >= CPU_IMPL_ULTRASPARCIII) 352295367Sdes cheetah_init(cpu_impl); 353204917Sdes else if (cpu_impl == CPU_IMPL_SPARC64V) 354204917Sdes zeus_init(cpu_impl); 355204917Sdes 356204917Sdes /* 357204917Sdes * Clear (S)TICK timer (including NPT). 358204917Sdes */ 359204917Sdes tick_clear(cpu_impl); 360204917Sdes 361204917Sdes /* 362204917Sdes * UltraSparc II[e,i] based systems come up with the tick interrupt 363204917Sdes * enabled and a handler that resets the tick counter, causing DELAY() 364204917Sdes * to not work properly when used early in boot. 365204917Sdes * UltraSPARC III based systems come up with the system tick interrupt 366204917Sdes * enabled, causing an interrupt storm on startup since they are not 367204917Sdes * handled. 368204917Sdes */ 369204917Sdes tick_stop(cpu_impl); 370255767Sdes 371204917Sdes /* 372204917Sdes * Set up Open Firmware entry points. 373204917Sdes */ 374204917Sdes ofw_tba = rdpr(tba); 375204917Sdes ofw_vec = (u_long)vec; 376204917Sdes 377204917Sdes /* 378204917Sdes * Parse metadata if present and fetch parameters. Must be before the 379204917Sdes * console is inited so cninit() gets the right value of boothowto. 380204917Sdes */ 381255767Sdes if (mdp != NULL) { 382255767Sdes preload_metadata = mdp; 383255767Sdes kmdp = preload_search_by_type("elf kernel"); 384204917Sdes if (kmdp != NULL) { 385255767Sdes boothowto = MD_FETCH(kmdp, MODINFOMD_HOWTO, int); 386204917Sdes kern_envp = MD_FETCH(kmdp, MODINFOMD_ENVP, char *); 387204917Sdes end = MD_FETCH(kmdp, MODINFOMD_KERNEND, vm_offset_t); 388204917Sdes kernel_tlb_slots = MD_FETCH(kmdp, MODINFOMD_DTLB_SLOTS, 389204917Sdes int); 390204917Sdes kernel_tlbs = (void *)preload_search_info(kmdp, 391204917Sdes MODINFO_METADATA | MODINFOMD_DTLB); 392204917Sdes } 393204917Sdes } 394204917Sdes 395204917Sdes init_param1(); 396204917Sdes 397204917Sdes /* 398204917Sdes * Initialize Open Firmware (needed for console). 399204917Sdes */ 400204917Sdes OF_install(OFW_STD_DIRECT, 0); 401204917Sdes OF_init(ofw_entry); 402204917Sdes 403204917Sdes /* 404204917Sdes * Prime our per-CPU data page for use. Note, we are using it for 405204917Sdes * our stack, so don't pass the real size (PAGE_SIZE) to pcpu_init 406204917Sdes * or it'll zero it out from under us. 407204917Sdes */ 408204917Sdes pc = (struct pcpu *)(pcpu0 + (PCPU_PAGES * PAGE_SIZE)) - 1; 409204917Sdes pcpu_init(pc, 0, sizeof(struct pcpu)); 410255767Sdes pc->pc_addr = (vm_offset_t)pcpu0; 411204917Sdes pc->pc_impl = cpu_impl; 412204917Sdes pc->pc_mid = cpu_get_mid(cpu_impl); 413255767Sdes pc->pc_tlb_ctx = TLB_CTX_USER_MIN; 414255767Sdes pc->pc_tlb_ctx_min = TLB_CTX_USER_MIN; 415204917Sdes pc->pc_tlb_ctx_max = TLB_CTX_USER_MAX; 416204917Sdes 417255767Sdes /* 418204917Sdes * Determine the OFW node and frequency of the BSP (and ensure the 419204917Sdes * BSP is in the device tree in the first place). 420204917Sdes */ 421204917Sdes root = OF_peer(0); 422204917Sdes pc->pc_node = find_bsp(root, pc->pc_mid, cpu_impl); 423204917Sdes if (pc->pc_node == 0) 424204917Sdes OF_panic("%s: cannot find boot CPU node", __func__); 425204917Sdes if (OF_getprop(pc->pc_node, "clock-frequency", &pc->pc_clock, 426204917Sdes sizeof(pc->pc_clock)) <= 0) 427204917Sdes OF_panic("%s: cannot determine boot CPU clock", __func__); 428204917Sdes 429204917Sdes /* 430204917Sdes * Panic if there is no metadata. Most likely the kernel was booted 431204917Sdes * directly, instead of through loader(8). 432204917Sdes */ 433204917Sdes if (mdp == NULL || kmdp == NULL || end == 0 || 434204917Sdes kernel_tlb_slots == 0 || kernel_tlbs == NULL) 435204917Sdes OF_panic("%s: missing loader metadata.\nThis probably means " 436204917Sdes "you are not using loader(8).", __func__); 437204917Sdes 438204917Sdes /* 439204917Sdes * Work around the broken loader behavior of not demapping no 440204917Sdes * longer used kernel TLB slots when unloading the kernel or 441204917Sdes * modules. 442204917Sdes */ 443204917Sdes for (va = KERNBASE + (kernel_tlb_slots - 1) * PAGE_SIZE_4M; 444204917Sdes va >= roundup2(end, PAGE_SIZE_4M); va -= PAGE_SIZE_4M) { 445204917Sdes if (bootverbose) 446204917Sdes OF_printf("demapping unused kernel TLB slot " 447204917Sdes "(va %#lx - %#lx)\n", va, va + PAGE_SIZE_4M - 1); 448204917Sdes stxa(TLB_DEMAP_VA(va) | TLB_DEMAP_PRIMARY | TLB_DEMAP_PAGE, 449204917Sdes ASI_DMMU_DEMAP, 0); 450204917Sdes stxa(TLB_DEMAP_VA(va) | TLB_DEMAP_PRIMARY | TLB_DEMAP_PAGE, 451204917Sdes ASI_IMMU_DEMAP, 0); 452204917Sdes flush(KERNBASE); 453204917Sdes kernel_tlb_slots--; 454204917Sdes } 455204917Sdes 456204917Sdes /* 457204917Sdes * Determine the TLB slot maxima, which are expected to be 458204917Sdes * equal across all CPUs. 459204917Sdes * NB: for cheetah-class CPUs, these properties only refer 460204917Sdes * to the t16s. 461204917Sdes */ 462204917Sdes if (OF_getprop(pc->pc_node, "#dtlb-entries", &dtlb_slots, 463204917Sdes sizeof(dtlb_slots)) == -1) 464204917Sdes OF_panic("%s: cannot determine number of dTLB slots", 465204917Sdes __func__); 466204917Sdes if (OF_getprop(pc->pc_node, "#itlb-entries", &itlb_slots, 467204917Sdes sizeof(itlb_slots)) == -1) 468204917Sdes OF_panic("%s: cannot determine number of iTLB slots", 469204917Sdes __func__); 470204917Sdes 471215116Sdes /* 472215116Sdes * Initialize and enable the caches. Note that this may include 473204917Sdes * applying workarounds. 474215116Sdes */ 475204917Sdes cache_init(pc); 476204917Sdes cache_enable(cpu_impl); 477204917Sdes uma_set_align(pc->pc_cache.dc_linesize - 1); 478204917Sdes 479204917Sdes cpu_block_copy = bcopy; 480204917Sdes cpu_block_zero = bzero; 481204917Sdes getenv_int("machdep.use_vis", &cpu_use_vis); 482204917Sdes if (cpu_use_vis) { 483204917Sdes switch (cpu_impl) { 484204917Sdes case CPU_IMPL_SPARC64: 485204917Sdes case CPU_IMPL_ULTRASPARCI: 486204917Sdes case CPU_IMPL_ULTRASPARCII: 487204917Sdes case CPU_IMPL_ULTRASPARCIIi: 488204917Sdes case CPU_IMPL_ULTRASPARCIIe: 489204917Sdes case CPU_IMPL_ULTRASPARCIII: /* NB: we've disabled P$. */ 490204917Sdes case CPU_IMPL_ULTRASPARCIIIp: 491204917Sdes case CPU_IMPL_ULTRASPARCIIIi: 492204917Sdes case CPU_IMPL_ULTRASPARCIV: 493204917Sdes case CPU_IMPL_ULTRASPARCIVp: 494204917Sdes case CPU_IMPL_ULTRASPARCIIIip: 495204917Sdes cpu_block_copy = spitfire_block_copy; 496204917Sdes cpu_block_zero = spitfire_block_zero; 497204917Sdes break; 498204917Sdes case CPU_IMPL_SPARC64V: 499204917Sdes cpu_block_copy = zeus_block_copy; 500204917Sdes cpu_block_zero = zeus_block_zero; 501204917Sdes break; 502204917Sdes } 503204917Sdes } 504204917Sdes 505204917Sdes#ifdef SMP 506204917Sdes mp_init(cpu_impl); 507204917Sdes#endif 508204917Sdes 509204917Sdes /* 510204917Sdes * Initialize virtual memory and calculate physmem. 511204917Sdes */ 512204917Sdes pmap_bootstrap(cpu_impl); 513204917Sdes 514204917Sdes /* 515204917Sdes * Initialize tunables. 516295367Sdes */ 517204917Sdes init_param2(physmem); 518204917Sdes env = getenv("kernelname"); 519204917Sdes if (env != NULL) { 520204917Sdes strlcpy(kernelname, env, sizeof(kernelname)); 521204917Sdes freeenv(env); 522204917Sdes } 523295367Sdes 524204917Sdes /* 525295367Sdes * Initialize the interrupt tables. 526204917Sdes */ 527295367Sdes intr_init1(); 528204917Sdes 529204917Sdes /* 530204917Sdes * Initialize proc0, set kstack0, frame0, curthread and curpcb. 531204917Sdes */ 532204917Sdes proc_linkup0(&proc0, &thread0); 533295367Sdes proc0.p_md.md_sigtramp = NULL; 534204917Sdes proc0.p_md.md_utrap = NULL; 535204917Sdes thread0.td_kstack = kstack0; 536204917Sdes thread0.td_kstack_pages = KSTACK_PAGES; 537204917Sdes thread0.td_pcb = (struct pcb *) 538295367Sdes (thread0.td_kstack + KSTACK_PAGES * PAGE_SIZE) - 1; 539204917Sdes frame0.tf_tstate = TSTATE_IE | TSTATE_PEF | TSTATE_PRIV; 540204917Sdes thread0.td_frame = &frame0; 541204917Sdes pc->pc_curthread = &thread0; 542295367Sdes pc->pc_curpcb = thread0.td_pcb; 543204917Sdes 544204917Sdes /* 545204917Sdes * Initialize global registers. 546204917Sdes */ 547204917Sdes cpu_setregs(pc); 548204917Sdes 549204917Sdes /* 550204917Sdes * Take over the trap table via the PROM. Using the PROM for this 551204917Sdes * is necessary in order to set obp-control-relinquished to true 552204917Sdes * within the PROM so obtaining /virtual-memory/translations doesn't 553204917Sdes * trigger a fatal reset error or worse things further down the road. 554204917Sdes * XXX it should be possible to use this solely instead of writing 555204917Sdes * %tba in cpu_setregs(). Doing so causes a hang however. 556204917Sdes * 557204917Sdes * NB: the low-level console drivers require a working DELAY() and 558204917Sdes * some compiler optimizations may cause the curthread accesses of 559204917Sdes * mutex(9) to be factored out even if the latter aren't actually 560204917Sdes * called. Both of these require PCPU_REG to be set. However, we 561204917Sdes * can't set PCPU_REG without also taking over the trap table or the 562295367Sdes * firmware will overwrite it. 563204917Sdes */ 564204917Sdes sun4u_set_traptable(tl0_base); 565204917Sdes 566295367Sdes /* 567295367Sdes * Initialize the dynamic per-CPU area for the BSP and the message 568204917Sdes * buffer (after setting the trap table). 569204917Sdes */ 570204917Sdes dpcpu_init(dpcpu0, 0); 571204917Sdes msgbufinit(msgbufp, msgbufsize); 572295367Sdes 573295367Sdes /* 574204917Sdes * Initialize mutexes. 575204917Sdes */ 576204917Sdes mutex_init(); 577204917Sdes 578204917Sdes /* 579204917Sdes * Initialize console now that we have a reasonable set of system 580215116Sdes * services. 581215116Sdes */ 582215116Sdes cninit(); 583215116Sdes 584215116Sdes /* 585295367Sdes * Finish the interrupt initialization now that mutexes work and 586215116Sdes * enable them. 587215116Sdes */ 588215116Sdes intr_init2(); 589215116Sdes wrpr(pil, 0, 0); 590215116Sdes wrpr(pstate, 0, PSTATE_KERNEL); 591215116Sdes 592215116Sdes OF_getprop(root, "name", sparc64_model, sizeof(sparc64_model) - 1); 593215116Sdes 594215116Sdes kdb_init(); 595295367Sdes 596295367Sdes#ifdef KDB 597295367Sdes if (boothowto & RB_KDB) 598215116Sdes kdb_enter(KDB_WHY_BOOTFLAGS, "Boot flags requested debugger"); 599215116Sdes#endif 600215116Sdes} 601215116Sdes 602215116Sdesvoid 603215116Sdessendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask) 604295367Sdes{ 605295367Sdes struct trapframe *tf; 606215116Sdes struct sigframe *sfp; 607215116Sdes struct sigacts *psp; 608215116Sdes struct sigframe sf; 609295367Sdes struct thread *td; 610215116Sdes struct frame *fp; 611215116Sdes struct proc *p; 612215116Sdes u_long sp; 613215116Sdes int oonstack; 614215116Sdes int sig; 615240075Sdes 616240075Sdes oonstack = 0; 617215116Sdes td = curthread; 618215116Sdes p = td->td_proc; 619215116Sdes PROC_LOCK_ASSERT(p, MA_OWNED); 620215116Sdes sig = ksi->ksi_signo; 621215116Sdes psp = p->p_sigacts; 622215116Sdes mtx_assert(&psp->ps_mtx, MA_OWNED); 623240075Sdes tf = td->td_frame; 624240075Sdes sp = tf->tf_sp + SPOFF; 625295367Sdes oonstack = sigonstack(sp); 626295367Sdes 627295367Sdes CTR4(KTR_SIG, "sendsig: td=%p (%s) catcher=%p sig=%d", td, p->p_comm, 628295367Sdes catcher, sig); 629295367Sdes 630295367Sdes /* Make sure we have a signal trampoline to return to. */ 631295367Sdes if (p->p_md.md_sigtramp == NULL) { 632295367Sdes /* 633295367Sdes * No signal trampoline... kill the process. 634295367Sdes */ 635295367Sdes CTR0(KTR_SIG, "sendsig: no sigtramp"); 636295367Sdes printf("sendsig: %s is too old, rebuild it\n", p->p_comm); 637295367Sdes sigexit(td, sig); 638295367Sdes /* NOTREACHED */ 639295367Sdes } 640295367Sdes 641295367Sdes /* Save user context. */ 642215116Sdes bzero(&sf, sizeof(sf)); 643215116Sdes get_mcontext(td, &sf.sf_uc.uc_mcontext, 0); 644215116Sdes sf.sf_uc.uc_sigmask = *mask; 645215116Sdes sf.sf_uc.uc_stack = td->td_sigstk; 646215116Sdes sf.sf_uc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK) ? 647215116Sdes ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE; 648255767Sdes 649215116Sdes /* Allocate and validate space for the signal handler context. */ 650215116Sdes if ((td->td_pflags & TDP_ALTSTACK) != 0 && !oonstack && 651215116Sdes SIGISMEMBER(psp->ps_sigonstack, sig)) { 652215116Sdes sfp = (struct sigframe *)(td->td_sigstk.ss_sp + 653215116Sdes td->td_sigstk.ss_size - sizeof(struct sigframe)); 654215116Sdes } else 655215116Sdes sfp = (struct sigframe *)sp - 1; 656215116Sdes mtx_unlock(&psp->ps_mtx); 657204917Sdes PROC_UNLOCK(p); 658204917Sdes 659204917Sdes fp = (struct frame *)sfp - 1; 660295367Sdes 661204917Sdes /* Translate the signal if appropriate. */ 662295367Sdes if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize) 663204917Sdes sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)]; 664255767Sdes 665204917Sdes /* Build the argument list for the signal handler. */ 666204917Sdes tf->tf_out[0] = sig; 667287144Sdelphij tf->tf_out[2] = (register_t)&sfp->sf_uc; 668287144Sdelphij tf->tf_out[4] = (register_t)catcher; 669295367Sdes if (SIGISMEMBER(psp->ps_siginfo, sig)) { 670204917Sdes /* Signal handler installed with SA_SIGINFO. */ 671295367Sdes tf->tf_out[1] = (register_t)&sfp->sf_si; 672255767Sdes 673295367Sdes /* Fill in POSIX parts. */ 674255767Sdes sf.sf_si = ksi->ksi_info; 675295367Sdes sf.sf_si.si_signo = sig; /* maybe a translated signal */ 676295367Sdes } else { 677204917Sdes /* Old FreeBSD-style arguments. */ 678204917Sdes tf->tf_out[1] = ksi->ksi_code; 679204917Sdes tf->tf_out[3] = (register_t)ksi->ksi_addr; 680204917Sdes } 681295367Sdes 682295367Sdes /* Copy the sigframe out to the user's stack. */ 683295367Sdes if (rwindow_save(td) != 0 || copyout(&sf, sfp, sizeof(*sfp)) != 0 || 684204917Sdes suword(&fp->fr_in[6], tf->tf_out[6]) != 0) { 685295367Sdes /* 686295367Sdes * Something is wrong with the stack pointer. 687295367Sdes * ...Kill the process. 688204917Sdes */ 689204917Sdes CTR2(KTR_SIG, "sendsig: sigexit td=%p sfp=%p", td, sfp); 690295367Sdes PROC_LOCK(p); 691295367Sdes sigexit(td, SIGILL); 692295367Sdes /* NOTREACHED */ 693295367Sdes } 694295367Sdes 695295367Sdes tf->tf_tpc = (u_long)p->p_md.md_sigtramp; 696295367Sdes tf->tf_tnpc = tf->tf_tpc + 4; 697295367Sdes tf->tf_sp = (u_long)fp - SPOFF; 698295367Sdes 699295367Sdes CTR3(KTR_SIG, "sendsig: return td=%p pc=%#lx sp=%#lx", td, tf->tf_tpc, 700295367Sdes tf->tf_sp); 701295367Sdes 702204917Sdes PROC_LOCK(p); 703204917Sdes mtx_lock(&psp->ps_mtx); 704204917Sdes} 705204917Sdes 706204917Sdes#ifndef _SYS_SYSPROTO_H_ 707204917Sdesstruct sigreturn_args { 708204917Sdes ucontext_t *ucp; 709295367Sdes}; 710295367Sdes#endif 711204917Sdes 712204917Sdes/* 713204917Sdes * MPSAFE 714204917Sdes */ 715204917Sdesint 716295367Sdessys_sigreturn(struct thread *td, struct sigreturn_args *uap) 717295367Sdes{ 718295367Sdes struct proc *p; 719295367Sdes mcontext_t *mc; 720295367Sdes ucontext_t uc; 721295367Sdes int error; 722204917Sdes 723204917Sdes p = td->td_proc; 724204917Sdes if (rwindow_save(td)) { 725204917Sdes PROC_LOCK(p); 726295367Sdes sigexit(td, SIGILL); 727295367Sdes } 728204917Sdes 729204917Sdes CTR2(KTR_SIG, "sigreturn: td=%p ucp=%p", td, uap->sigcntxp); 730204917Sdes if (copyin(uap->sigcntxp, &uc, sizeof(uc)) != 0) { 731204917Sdes CTR1(KTR_SIG, "sigreturn: efault td=%p", td); 732295367Sdes return (EFAULT); 733204917Sdes } 734204917Sdes 735204917Sdes mc = &uc.uc_mcontext; 736204917Sdes error = set_mcontext(td, mc); 737204917Sdes if (error != 0) 738204917Sdes return (error); 739204917Sdes 740204917Sdes kern_sigprocmask(td, SIG_SETMASK, &uc.uc_sigmask, NULL, 0); 741204917Sdes 742204917Sdes CTR4(KTR_SIG, "sigreturn: return td=%p pc=%#lx sp=%#lx tstate=%#lx", 743204917Sdes td, mc->_mc_tpc, mc->_mc_sp, mc->_mc_tstate); 744204917Sdes return (EJUSTRETURN); 745204917Sdes} 746204917Sdes 747204917Sdes/* 748204917Sdes * Construct a PCB from a trapframe. This is called from kdb_trap() where 749204917Sdes * we want to start a backtrace from the function that caused us to enter 750204917Sdes * the debugger. We have the context in the trapframe, but base the trace 751204917Sdes * on the PCB. The PCB doesn't have to be perfect, as long as it contains 752204917Sdes * enough for a backtrace. 753204917Sdes */ 754204917Sdesvoid 755204917Sdesmakectx(struct trapframe *tf, struct pcb *pcb) 756215116Sdes{ 757215116Sdes 758215116Sdes pcb->pcb_pc = tf->tf_tpc; 759215116Sdes pcb->pcb_sp = tf->tf_sp; 760215116Sdes} 761215116Sdes 762215116Sdesint 763215116Sdesget_mcontext(struct thread *td, mcontext_t *mc, int flags) 764215116Sdes{ 765215116Sdes struct trapframe *tf; 766215116Sdes struct pcb *pcb; 767204917Sdes 768204917Sdes tf = td->td_frame; 769204917Sdes pcb = td->td_pcb; 770204917Sdes /* 771204917Sdes * Copy the registers which will be restored by tl0_ret() from the 772204917Sdes * trapframe. 773204917Sdes * Note that we skip %g7 which is used as the userland TLS register 774204917Sdes * and %wstate. 775204917Sdes */ 776204917Sdes mc->_mc_flags = _MC_VERSION; 777204917Sdes mc->mc_global[1] = tf->tf_global[1]; 778204917Sdes mc->mc_global[2] = tf->tf_global[2]; 779204917Sdes mc->mc_global[3] = tf->tf_global[3]; 780204917Sdes mc->mc_global[4] = tf->tf_global[4]; 781204917Sdes mc->mc_global[5] = tf->tf_global[5]; 782204917Sdes mc->mc_global[6] = tf->tf_global[6]; 783295367Sdes if (flags & GET_MC_CLEAR_RET) { 784295367Sdes mc->mc_out[0] = 0; 785204917Sdes mc->mc_out[1] = 0; 786204917Sdes } else { 787204917Sdes mc->mc_out[0] = tf->tf_out[0]; 788204917Sdes mc->mc_out[1] = tf->tf_out[1]; 789204917Sdes } 790204917Sdes mc->mc_out[2] = tf->tf_out[2]; 791204917Sdes mc->mc_out[3] = tf->tf_out[3]; 792204917Sdes mc->mc_out[4] = tf->tf_out[4]; 793204917Sdes mc->mc_out[5] = tf->tf_out[5]; 794204917Sdes mc->mc_out[6] = tf->tf_out[6]; 795215116Sdes mc->mc_out[7] = tf->tf_out[7]; 796215116Sdes mc->_mc_fprs = tf->tf_fprs; 797295367Sdes mc->_mc_fsr = tf->tf_fsr; 798240075Sdes mc->_mc_gsr = tf->tf_gsr; 799204917Sdes mc->_mc_tnpc = tf->tf_tnpc; 800204917Sdes mc->_mc_tpc = tf->tf_tpc; 801215116Sdes mc->_mc_tstate = tf->tf_tstate; 802215116Sdes mc->_mc_y = tf->tf_y; 803215116Sdes critical_enter(); 804215116Sdes if ((tf->tf_fprs & FPRS_FEF) != 0) { 805215116Sdes savefpctx(pcb->pcb_ufp); 806215116Sdes tf->tf_fprs &= ~FPRS_FEF; 807204917Sdes pcb->pcb_flags |= PCB_FEF; 808215116Sdes } 809215116Sdes if ((pcb->pcb_flags & PCB_FEF) != 0) { 810215116Sdes bcopy(pcb->pcb_ufp, mc->mc_fp, sizeof(mc->mc_fp)); 811204917Sdes mc->_mc_fprs |= FPRS_FEF; 812204917Sdes } 813204917Sdes critical_exit(); 814204917Sdes return (0); 815255767Sdes} 816204917Sdes 817255767Sdesint 818295367Sdesset_mcontext(struct thread *td, const mcontext_t *mc) 819255767Sdes{ 820295367Sdes struct trapframe *tf; 821204917Sdes struct pcb *pcb; 822204917Sdes 823204917Sdes if (!TSTATE_SECURE(mc->_mc_tstate) || 824204917Sdes (mc->_mc_flags & ((1L << _MC_VERSION_BITS) - 1)) != _MC_VERSION) 825204917Sdes return (EINVAL); 826204917Sdes tf = td->td_frame; 827204917Sdes pcb = td->td_pcb; 828295367Sdes /* Make sure the windows are spilled first. */ 829204917Sdes flushw(); 830240075Sdes /* 831295367Sdes * Copy the registers which will be restored by tl0_ret() to the 832204917Sdes * trapframe. 833295367Sdes * Note that we skip %g7 which is used as the userland TLS register 834255767Sdes * and %wstate. 835204917Sdes */ 836287144Sdelphij tf->tf_global[1] = mc->mc_global[1]; 837287144Sdelphij tf->tf_global[2] = mc->mc_global[2]; 838204917Sdes tf->tf_global[3] = mc->mc_global[3]; 839295367Sdes tf->tf_global[4] = mc->mc_global[4]; 840255767Sdes tf->tf_global[5] = mc->mc_global[5]; 841295367Sdes tf->tf_global[6] = mc->mc_global[6]; 842255767Sdes tf->tf_out[0] = mc->mc_out[0]; 843295367Sdes tf->tf_out[1] = mc->mc_out[1]; 844295367Sdes tf->tf_out[2] = mc->mc_out[2]; 845204917Sdes tf->tf_out[3] = mc->mc_out[3]; 846204917Sdes tf->tf_out[4] = mc->mc_out[4]; 847204917Sdes tf->tf_out[5] = mc->mc_out[5]; 848204917Sdes tf->tf_out[6] = mc->mc_out[6]; 849204917Sdes tf->tf_out[7] = mc->mc_out[7]; 850295367Sdes tf->tf_fprs = mc->_mc_fprs; 851295367Sdes tf->tf_fsr = mc->_mc_fsr; 852295367Sdes tf->tf_gsr = mc->_mc_gsr; 853204917Sdes tf->tf_tnpc = mc->_mc_tnpc; 854295367Sdes tf->tf_tpc = mc->_mc_tpc; 855295367Sdes tf->tf_tstate = mc->_mc_tstate; 856295367Sdes tf->tf_y = mc->_mc_y; 857204917Sdes if ((mc->_mc_fprs & FPRS_FEF) != 0) { 858204917Sdes tf->tf_fprs = 0; 859295367Sdes bcopy(mc->mc_fp, pcb->pcb_ufp, sizeof(pcb->pcb_ufp)); 860295367Sdes pcb->pcb_flags |= PCB_FEF; 861295367Sdes } 862295367Sdes return (0); 863295367Sdes} 864295367Sdes 865295367Sdes/* 866295367Sdes * Exit the kernel and execute a firmware call that will not return, as 867295367Sdes * specified by the arguments. 868295367Sdes */ 869295367Sdesvoid 870295367Sdescpu_shutdown(void *args) 871240075Sdes{ 872204917Sdes 873204917Sdes#ifdef SMP 874240075Sdes cpu_mp_shutdown(); 875240075Sdes#endif 876240075Sdes ofw_exit(args); 877240075Sdes} 878240075Sdes 879240075Sdes/* 880240075Sdes * Flush the D-cache for non-DMA I/O so that the I-cache can 881240075Sdes * be made coherent later. 882240075Sdes */ 883240075Sdesvoid 884240075Sdescpu_flush_dcache(void *ptr, size_t len) 885240075Sdes{ 886240075Sdes 887240075Sdes /* TBD */ 888240075Sdes} 889240075Sdes 890240075Sdes/* Get current clock frequency for the given CPU ID. */ 891240075Sdesint 892240075Sdescpu_est_clockrate(int cpu_id, uint64_t *rate) 893240075Sdes{ 894240075Sdes struct pcpu *pc; 895240075Sdes 896240075Sdes pc = pcpu_find(cpu_id); 897204917Sdes if (pc == NULL || rate == NULL) 898240075Sdes return (EINVAL); 899240075Sdes *rate = pc->pc_clock; 900240075Sdes return (0); 901240075Sdes} 902240075Sdes 903240075Sdes/* 904240075Sdes * Duplicate OF_exit() with a different firmware call function that restores 905295367Sdes * the trap table, otherwise a RED state exception is triggered in at least 906240075Sdes * some firmware versions. 907295367Sdes */ 908240075Sdesvoid 909240075Sdescpu_halt(void) 910240075Sdes{ 911295367Sdes static struct { 912295367Sdes cell_t name; 913240075Sdes cell_t nargs; 914240075Sdes cell_t nreturns; 915240075Sdes } args = { 916240075Sdes (cell_t)"exit", 917240075Sdes 0, 918240075Sdes 0 919240075Sdes }; 920255767Sdes 921295367Sdes cpu_shutdown(&args); 922255767Sdes} 923295367Sdes 924240075Sdesstatic void 925295367Sdessparc64_shutdown_final(void *dummy, int howto) 926240075Sdes{ 927240075Sdes static struct { 928240075Sdes cell_t name; 929240075Sdes cell_t nargs; 930240075Sdes cell_t nreturns; 931240075Sdes } args = { 932204917Sdes (cell_t)"SUNW,power-off", 933255767Sdes 0, 934295367Sdes 0 935295367Sdes }; 936204917Sdes 937204917Sdes /* Turn the power off? */ 938204917Sdes if ((howto & RB_POWEROFF) != 0) 939204917Sdes cpu_shutdown(&args); 940204917Sdes /* In case of halt, return to the firmware. */ 941204917Sdes if ((howto & RB_HALT) != 0) 942204917Sdes cpu_halt(); 943204917Sdes} 944204917Sdes 945204917Sdesvoid 946204917Sdescpu_idle(int busy) 947295367Sdes{ 948204917Sdes 949204917Sdes /* Insert code to halt (until next interrupt) for the idle loop. */ 950204917Sdes} 951204917Sdes 952204917Sdesint 953255767Sdescpu_idle_wakeup(int cpu) 954255767Sdes{ 955204917Sdes 956204917Sdes return (1); 957204917Sdes} 958255767Sdes 959204917Sdesint 960204917Sdesptrace_set_pc(struct thread *td, u_long addr) 961204917Sdes{ 962204917Sdes 963204917Sdes td->td_frame->tf_tpc = addr; 964204917Sdes td->td_frame->tf_tnpc = addr + 4; 965204917Sdes return (0); 966204917Sdes} 967204917Sdes 968204917Sdesint 969204917Sdesptrace_single_step(struct thread *td) 970255767Sdes{ 971204917Sdes 972204917Sdes /* TODO; */ 973204917Sdes return (0); 974204917Sdes} 975204917Sdes 976204917Sdesint 977204917Sdesptrace_clear_single_step(struct thread *td) 978204917Sdes{ 979204917Sdes 980204917Sdes /* TODO; */ 981204917Sdes return (0); 982204917Sdes} 983204917Sdes 984204917Sdesvoid 985204917Sdesexec_setregs(struct thread *td, struct image_params *imgp, u_long stack) 986204917Sdes{ 987204917Sdes struct trapframe *tf; 988204917Sdes struct pcb *pcb; 989204917Sdes struct proc *p; 990204917Sdes u_long sp; 991204917Sdes 992204917Sdes /* XXX no cpu_exec */ 993204917Sdes p = td->td_proc; 994255767Sdes p->p_md.md_sigtramp = NULL; 995204917Sdes if (p->p_md.md_utrap != NULL) { 996204917Sdes utrap_free(p->p_md.md_utrap); 997204917Sdes p->p_md.md_utrap = NULL; 998204917Sdes } 999204917Sdes 1000221420Sdes pcb = td->td_pcb; 1001204917Sdes tf = td->td_frame; 1002204917Sdes sp = rounddown(stack, 16); 1003204917Sdes bzero(pcb, sizeof(*pcb)); 1004204917Sdes bzero(tf, sizeof(*tf)); 1005204917Sdes tf->tf_out[0] = stack; 1006204917Sdes tf->tf_out[3] = p->p_sysent->sv_psstrings; 1007204917Sdes tf->tf_out[6] = sp - SPOFF - sizeof(struct frame); 1008204917Sdes tf->tf_tnpc = imgp->entry_addr + 4; 1009204917Sdes tf->tf_tpc = imgp->entry_addr; 1010204917Sdes /* 1011204917Sdes * While we could adhere to the memory model indicated in the ELF 1012204917Sdes * header, it turns out that just always using TSO performs best. 1013204917Sdes */ 1014204917Sdes tf->tf_tstate = TSTATE_IE | TSTATE_PEF | TSTATE_MM_TSO; 1015204917Sdes 1016204917Sdes td->td_retval[0] = tf->tf_out[0]; 1017204917Sdes td->td_retval[1] = tf->tf_out[1]; 1018204917Sdes} 1019204917Sdes 1020204917Sdesint 1021204917Sdesfill_regs(struct thread *td, struct reg *regs) 1022204917Sdes{ 1023204917Sdes 1024204917Sdes bcopy(td->td_frame, regs, sizeof(*regs)); 1025215116Sdes return (0); 1026204917Sdes} 1027295367Sdes 1028295367Sdesint 1029295367Sdesset_regs(struct thread *td, struct reg *regs) 1030295367Sdes{ 1031204917Sdes struct trapframe *tf; 1032295367Sdes 1033204917Sdes if (!TSTATE_SECURE(regs->r_tstate)) 1034204917Sdes return (EINVAL); 1035204917Sdes tf = td->td_frame; 1036295367Sdes regs->r_wstate = tf->tf_wstate; 1037295367Sdes bcopy(regs, tf, sizeof(*regs)); 1038295367Sdes return (0); 1039295367Sdes} 1040295367Sdes 1041295367Sdesint 1042295367Sdesfill_dbregs(struct thread *td, struct dbreg *dbregs) 1043295367Sdes{ 1044295367Sdes 1045295367Sdes return (ENOSYS); 1046295367Sdes} 1047295367Sdes 1048295367Sdesint 1049295367Sdesset_dbregs(struct thread *td, struct dbreg *dbregs) 1050295367Sdes{ 1051295367Sdes 1052295367Sdes return (ENOSYS); 1053295367Sdes} 1054295367Sdes 1055295367Sdesint 1056295367Sdesfill_fpregs(struct thread *td, struct fpreg *fpregs) 1057295367Sdes{ 1058295367Sdes struct trapframe *tf; 1059295367Sdes struct pcb *pcb; 1060295367Sdes 1061295367Sdes pcb = td->td_pcb; 1062295367Sdes tf = td->td_frame; 1063295367Sdes bcopy(pcb->pcb_ufp, fpregs->fr_regs, sizeof(fpregs->fr_regs)); 1064295367Sdes fpregs->fr_fsr = tf->tf_fsr; 1065295367Sdes fpregs->fr_gsr = tf->tf_gsr; 1066295367Sdes return (0); 1067295367Sdes} 1068295367Sdes 1069295367Sdesint 1070295367Sdesset_fpregs(struct thread *td, struct fpreg *fpregs) 1071295367Sdes{ 1072295367Sdes struct trapframe *tf; 1073295367Sdes struct pcb *pcb; 1074295367Sdes 1075295367Sdes pcb = td->td_pcb; 1076295367Sdes tf = td->td_frame; 1077295367Sdes tf->tf_fprs &= ~FPRS_FEF; 1078295367Sdes bcopy(fpregs->fr_regs, pcb->pcb_ufp, sizeof(pcb->pcb_ufp)); 1079295367Sdes tf->tf_fsr = fpregs->fr_fsr; 1080295367Sdes tf->tf_gsr = fpregs->fr_gsr; 1081226046Sdes return (0); 1082226046Sdes} 1083226046Sdes 1084226046Sdesstruct md_utrap * 1085226046Sdesutrap_alloc(void) 1086226046Sdes{ 1087226046Sdes struct md_utrap *ut; 1088226046Sdes 1089226046Sdes ut = malloc(sizeof(struct md_utrap), M_SUBPROC, M_WAITOK | M_ZERO); 1090226046Sdes ut->ut_refcnt = 1; 1091226046Sdes return (ut); 1092226046Sdes} 1093226046Sdes 1094226046Sdesvoid 1095226046Sdesutrap_free(struct md_utrap *ut) 1096226046Sdes{ 1097226046Sdes int refcnt; 1098226046Sdes 1099226046Sdes if (ut == NULL) 1100226046Sdes return; 1101255767Sdes mtx_pool_lock(mtxpool_sleep, ut); 1102226046Sdes ut->ut_refcnt--; 1103226046Sdes refcnt = ut->ut_refcnt; 1104226046Sdes mtx_pool_unlock(mtxpool_sleep, ut); 1105226046Sdes if (refcnt == 0) 1106226046Sdes free(ut, M_SUBPROC); 1107226046Sdes} 1108226046Sdes 1109226046Sdesstruct md_utrap * 1110226046Sdesutrap_hold(struct md_utrap *ut) 1111226046Sdes{ 1112226046Sdes 1113226046Sdes if (ut == NULL) 1114204917Sdes return (NULL); 1115204917Sdes mtx_pool_lock(mtxpool_sleep, ut); 1116204917Sdes ut->ut_refcnt++; 1117204917Sdes mtx_pool_unlock(mtxpool_sleep, ut); 1118204917Sdes return (ut); 1119204917Sdes} 1120295367Sdes