machdep.c revision 209613
180708Sjake/*- 280708Sjake * Copyright (c) 2001 Jake Burkholder. 382902Sjake * Copyright (c) 1992 Terrence R. Lambert. 482902Sjake * Copyright (c) 1982, 1987, 1990 The Regents of the University of California. 580708Sjake * All rights reserved. 680708Sjake * 782902Sjake * This code is derived from software contributed to Berkeley by 882902Sjake * William Jolitz. 982902Sjake * 1080708Sjake * Redistribution and use in source and binary forms, with or without 1180708Sjake * modification, are permitted provided that the following conditions 1280708Sjake * are met: 1380708Sjake * 1. Redistributions of source code must retain the above copyright 1480708Sjake * notice, this list of conditions and the following disclaimer. 1580708Sjake * 2. Redistributions in binary form must reproduce the above copyright 1680708Sjake * notice, this list of conditions and the following disclaimer in the 1780708Sjake * documentation and/or other materials provided with the distribution. 1882902Sjake * 4. Neither the name of the University nor the names of its contributors 1982902Sjake * may be used to endorse or promote products derived from this software 2082902Sjake * without specific prior written permission. 2180708Sjake * 2282902Sjake * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2380708Sjake * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2480708Sjake * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2582902Sjake * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2680708Sjake * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2780708Sjake * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2880708Sjake * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2980708Sjake * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3080708Sjake * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3180708Sjake * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3280708Sjake * SUCH DAMAGE. 3380708Sjake * 3482902Sjake * from: @(#)machdep.c 7.4 (Berkeley) 6/3/91 35181701Smarius * from: FreeBSD: src/sys/i386/i386/machdep.c,v 1.477 2001/08/27 3680708Sjake */ 3780708Sjake 38145151Smarius#include <sys/cdefs.h> 39145151Smarius__FBSDID("$FreeBSD: head/sys/sparc64/sparc64/machdep.c 209613 2010-06-30 18:03:42Z jhb $"); 40145151Smarius 41105950Speter#include "opt_compat.h" 4280709Sjake#include "opt_ddb.h" 43118239Speter#include "opt_kstack_pages.h" 4485242Sjake#include "opt_msgbuf.h" 4580709Sjake 4680708Sjake#include <sys/param.h> 47141378Snjl#include <sys/malloc.h> 48141378Snjl#include <sys/proc.h> 4980708Sjake#include <sys/systm.h> 50141249Snjl#include <sys/bio.h> 51141249Snjl#include <sys/buf.h> 52141249Snjl#include <sys/bus.h> 53141249Snjl#include <sys/cpu.h> 5480709Sjake#include <sys/cons.h> 55141378Snjl#include <sys/eventhandler.h> 56141378Snjl#include <sys/exec.h> 57102561Sjake#include <sys/imgact.h> 58141378Snjl#include <sys/interrupt.h> 59131950Smarcel#include <sys/kdb.h> 6080709Sjake#include <sys/kernel.h> 6185262Sjake#include <sys/ktr.h> 6280709Sjake#include <sys/linker.h> 6380709Sjake#include <sys/lock.h> 6485242Sjake#include <sys/msgbuf.h> 6580708Sjake#include <sys/mutex.h> 6680709Sjake#include <sys/pcpu.h> 67141378Snjl#include <sys/ptrace.h> 6885242Sjake#include <sys/reboot.h> 6980708Sjake#include <sys/signalvar.h> 7091616Sjake#include <sys/smp.h> 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> 9281383Sjake#include <machine/clock.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 118131950Smarcel#ifdef DDB 119131950Smarcelextern vm_offset_t ksym_start, ksym_end; 120131950Smarcel#endif 121131950Smarcel 122186682Smariusint dtlb_slots; 123186682Smariusint itlb_slots; 12497445Sjakestruct tlb_entry *kernel_tlbs; 12591616Sjakeint kernel_tlb_slots; 12691616Sjake 12780708Sjakeint cold = 1; 128102600Speterlong Maxmem; 129142956Sweslong realmem; 13080708Sjake 131194784Sjeffvoid *dpcpu0; 13291360Sjakechar pcpu0[PCPU_PAGES * PAGE_SIZE]; 13389038Sjakestruct trapframe frame0; 13480708Sjake 13589038Sjakevm_offset_t kstack0; 136113238Sjakevm_paddr_t kstack0_phys; 13788781Sjake 13882902Sjakestruct kva_md_info kmi; 13980709Sjake 14080709Sjakeu_long ofw_vec; 14180709Sjakeu_long ofw_tba; 142205409Smariusu_int tba_taken_over; 14380709Sjake 144106555Stmmchar sparc64_model[32]; 145106555Stmm 146113166Sjakestatic int cpu_use_vis = 1; 147113166Sjake 148113166Sjakecpu_block_copy_t *cpu_block_copy; 149113166Sjakecpu_block_zero_t *cpu_block_zero; 150113166Sjake 151204152Smariusstatic phandle_t find_bsp(phandle_t node, uint32_t bspid, u_int cpu_impl); 15291616Sjakevoid sparc64_init(caddr_t mdp, u_long o1, u_long o2, u_long o3, 153181701Smarius ofw_vec_t *vec); 154203838Smariusstatic void sparc64_shutdown_final(void *dummy, int howto); 15580709Sjake 156203838Smariusstatic void cpu_startup(void *arg); 15780709SjakeSYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL); 15880709Sjake 15991336SjakeCTASSERT((1 << INT_SHIFT) == sizeof(int)); 16091336SjakeCTASSERT((1 << PTR_SHIFT) == sizeof(char *)); 16191336Sjake 162105733SjakeCTASSERT(sizeof(struct reg) == 256); 163105733SjakeCTASSERT(sizeof(struct fpreg) == 272); 164105733SjakeCTASSERT(sizeof(struct __mcontext) == 512); 165105733Sjake 166113023SjakeCTASSERT((sizeof(struct pcb) & (64 - 1)) == 0); 167113023SjakeCTASSERT((offsetof(struct pcb, pcb_kfp) & (64 - 1)) == 0); 168113023SjakeCTASSERT((offsetof(struct pcb, pcb_ufp) & (64 - 1)) == 0); 169113023SjakeCTASSERT(sizeof(struct pcb) <= ((KSTACK_PAGES * PAGE_SIZE) / 8)); 170113023Sjake 17191360SjakeCTASSERT(sizeof(struct pcpu) <= ((PCPU_PAGES * PAGE_SIZE) / 2)); 17289038Sjake 17380709Sjakestatic void 17480709Sjakecpu_startup(void *arg) 17580709Sjake{ 176115971Sjake vm_paddr_t physsz; 177115971Sjake int i; 17880709Sjake 179115971Sjake physsz = 0; 180115971Sjake for (i = 0; i < sparc64_nmemreg; i++) 181115971Sjake physsz += sparc64_memreg[i].mr_size; 182115971Sjake printf("real memory = %lu (%lu MB)\n", physsz, 183115971Sjake physsz / (1024 * 1024)); 184155680Sjhb realmem = (long)physsz / PAGE_SIZE; 18580709Sjake 18682902Sjake vm_ksubmap_init(&kmi); 18780709Sjake 18880709Sjake bufinit(); 18980709Sjake vm_pager_bufferinit(); 19080709Sjake 19186147Stmm EVENTHANDLER_REGISTER(shutdown_final, sparc64_shutdown_final, NULL, 19286147Stmm SHUTDOWN_PRI_LAST); 193113338Sjake 194170170Sattilio printf("avail memory = %lu (%lu MB)\n", cnt.v_free_count * PAGE_SIZE, 195170170Sattilio cnt.v_free_count / ((1024 * 1024) / PAGE_SIZE)); 196113338Sjake 197113338Sjake if (bootverbose) 198113338Sjake printf("machine: %s\n", sparc64_model); 199113338Sjake 200182730Smarius cpu_identify(rdpr(ver), PCPU_GET(clock), curcpu); 20180709Sjake} 20280709Sjake 20387702Sjhbvoid 20487702Sjhbcpu_pcpu_init(struct pcpu *pcpu, int cpuid, size_t size) 20587702Sjhb{ 20697265Sjake struct intr_request *ir; 20797265Sjake int i; 20897265Sjake 20997265Sjake pcpu->pc_irtail = &pcpu->pc_irhead; 21097265Sjake for (i = 0; i < IR_FREE; i++) { 21197265Sjake ir = &pcpu->pc_irpool[i]; 21297265Sjake ir->ir_next = pcpu->pc_irfree; 21397265Sjake pcpu->pc_irfree = ir; 21497265Sjake } 21587702Sjhb} 21687702Sjhb 217144637Sjhbvoid 218144637Sjhbspinlock_enter(void) 219144637Sjhb{ 220144637Sjhb struct thread *td; 221145085Sjhb register_t pil; 222144637Sjhb 223144637Sjhb td = curthread; 224144637Sjhb if (td->td_md.md_spinlock_count == 0) { 225145085Sjhb pil = rdpr(pil); 226145151Smarius wrpr(pil, 0, PIL_TICK); 227145085Sjhb td->td_md.md_saved_pil = pil; 228144637Sjhb } 229144637Sjhb td->td_md.md_spinlock_count++; 230144637Sjhb critical_enter(); 231144637Sjhb} 232144637Sjhb 233144637Sjhbvoid 234144637Sjhbspinlock_exit(void) 235144637Sjhb{ 236144637Sjhb struct thread *td; 237144637Sjhb 238144637Sjhb td = curthread; 239144637Sjhb critical_exit(); 240144637Sjhb td->td_md.md_spinlock_count--; 241144637Sjhb if (td->td_md.md_spinlock_count == 0) 242144637Sjhb wrpr(pil, td->td_md.md_saved_pil, 0); 243144637Sjhb} 244144637Sjhb 245203838Smariusstatic phandle_t 246204152Smariusfind_bsp(phandle_t node, uint32_t bspid, u_int cpu_impl) 247203838Smarius{ 248203838Smarius char type[sizeof("cpu")]; 249203838Smarius phandle_t child; 250203838Smarius uint32_t cpuid; 251203838Smarius 252203838Smarius for (; node != 0; node = OF_peer(node)) { 253203838Smarius child = OF_child(node); 254203838Smarius if (child > 0) { 255204152Smarius child = find_bsp(child, bspid, cpu_impl); 256203838Smarius if (child > 0) 257203838Smarius return (child); 258203838Smarius } else { 259203838Smarius if (OF_getprop(node, "device_type", type, 260203838Smarius sizeof(type)) <= 0) 261203838Smarius continue; 262203838Smarius if (strcmp(type, "cpu") != 0) 263203838Smarius continue; 264204152Smarius if (OF_getprop(node, cpu_cpuid_prop(cpu_impl), &cpuid, 265203838Smarius sizeof(cpuid)) <= 0) 266203838Smarius continue; 267203838Smarius if (cpuid == bspid) 268203838Smarius return (node); 269203838Smarius } 270203838Smarius } 271203838Smarius return (0); 272203838Smarius} 273203838Smarius 274203838Smariusconst char * 275204152Smariuscpu_cpuid_prop(u_int cpu_impl) 276203838Smarius{ 277203838Smarius 278203838Smarius switch (cpu_impl) { 279203838Smarius case CPU_IMPL_SPARC64: 280207537Smarius case CPU_IMPL_SPARC64V: 281203838Smarius case CPU_IMPL_ULTRASPARCI: 282203838Smarius case CPU_IMPL_ULTRASPARCII: 283203838Smarius case CPU_IMPL_ULTRASPARCIIi: 284203838Smarius case CPU_IMPL_ULTRASPARCIIe: 285203838Smarius return ("upa-portid"); 286203838Smarius case CPU_IMPL_ULTRASPARCIII: 287203838Smarius case CPU_IMPL_ULTRASPARCIIIp: 288203838Smarius case CPU_IMPL_ULTRASPARCIIIi: 289203838Smarius case CPU_IMPL_ULTRASPARCIIIip: 290203838Smarius return ("portid"); 291203838Smarius case CPU_IMPL_ULTRASPARCIV: 292203838Smarius case CPU_IMPL_ULTRASPARCIVp: 293203838Smarius return ("cpuid"); 294203838Smarius default: 295203838Smarius return (""); 296203838Smarius } 297203838Smarius} 298203838Smarius 299203838Smariusuint32_t 300204152Smariuscpu_get_mid(u_int cpu_impl) 301203838Smarius{ 302203838Smarius 303203838Smarius switch (cpu_impl) { 304203838Smarius case CPU_IMPL_SPARC64: 305207537Smarius case CPU_IMPL_SPARC64V: 306203838Smarius case CPU_IMPL_ULTRASPARCI: 307203838Smarius case CPU_IMPL_ULTRASPARCII: 308203838Smarius case CPU_IMPL_ULTRASPARCIIi: 309203838Smarius case CPU_IMPL_ULTRASPARCIIe: 310203838Smarius return (UPA_CR_GET_MID(ldxa(0, ASI_UPA_CONFIG_REG))); 311203838Smarius case CPU_IMPL_ULTRASPARCIII: 312203838Smarius case CPU_IMPL_ULTRASPARCIIIp: 313203838Smarius return (FIREPLANE_CR_GET_AID(ldxa(AA_FIREPLANE_CONFIG, 314203838Smarius ASI_FIREPLANE_CONFIG_REG))); 315203838Smarius case CPU_IMPL_ULTRASPARCIIIi: 316203838Smarius case CPU_IMPL_ULTRASPARCIIIip: 317203838Smarius return (JBUS_CR_GET_JID(ldxa(0, ASI_JBUS_CONFIG_REG))); 318203838Smarius case CPU_IMPL_ULTRASPARCIV: 319203838Smarius case CPU_IMPL_ULTRASPARCIVp: 320203838Smarius return (INTR_ID_GET_ID(ldxa(AA_INTR_ID, ASI_INTR_ID))); 321203838Smarius default: 322203838Smarius return (0); 323203838Smarius } 324203838Smarius} 325203838Smarius 32680708Sjakevoid 32791616Sjakesparc64_init(caddr_t mdp, u_long o1, u_long o2, u_long o3, ofw_vec_t *vec) 32880708Sjake{ 329181701Smarius char *env; 33089038Sjake struct pcpu *pc; 33186521Sjake vm_offset_t end; 332195149Smarius vm_offset_t va; 33386521Sjake caddr_t kmdp; 334181701Smarius phandle_t root; 335204152Smarius u_int cpu_impl; 33680709Sjake 33786521Sjake end = 0; 33886521Sjake kmdp = NULL; 33986521Sjake 34080709Sjake /* 341181701Smarius * Find out what kind of CPU we have first, for anything that changes 342112398Sjake * behaviour. 343112398Sjake */ 344112398Sjake cpu_impl = VER_IMPL(rdpr(ver)); 345112398Sjake 346112398Sjake /* 347207248Smarius * Do CPU-specific initialization. 348182768Smarius */ 349207537Smarius if (cpu_impl == CPU_IMPL_SPARC64V || 350207537Smarius cpu_impl >= CPU_IMPL_ULTRASPARCIII) 351204152Smarius cheetah_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 37686521Sjake * 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); 38386521Sjake kern_envp = MD_FETCH(kmdp, MODINFOMD_ENVP, char *); 38486521Sjake end = MD_FETCH(kmdp, MODINFOMD_KERNEND, vm_offset_t); 38591616Sjake kernel_tlb_slots = MD_FETCH(kmdp, MODINFOMD_DTLB_SLOTS, 38691616Sjake int); 38797445Sjake kernel_tlbs = (void *)preload_search_info(kmdp, 38891616Sjake MODINFO_METADATA | MODINFOMD_DTLB); 38986521Sjake } 39086521Sjake } 39186521Sjake 392122462Sjake init_param1(); 393122462Sjake 394182689Smarius /* 395186347Snwhitehorn * Initialize Open Firmware (needed for console). 396186347Snwhitehorn */ 397186347Snwhitehorn OF_install(OFW_STD_DIRECT, 0); 398186347Snwhitehorn OF_init(ofw_entry); 399186347Snwhitehorn 400186347Snwhitehorn /* 401182689Smarius * Prime our per-CPU data page for use. Note, we are using it for 402182689Smarius * our stack, so don't pass the real size (PAGE_SIZE) to pcpu_init 403182689Smarius * or it'll zero it out from under us. 404182689Smarius */ 405182689Smarius pc = (struct pcpu *)(pcpu0 + (PCPU_PAGES * PAGE_SIZE)) - 1; 406182689Smarius pcpu_init(pc, 0, sizeof(struct pcpu)); 407182689Smarius pc->pc_addr = (vm_offset_t)pcpu0; 408204152Smarius pc->pc_impl = cpu_impl; 409204152Smarius pc->pc_mid = cpu_get_mid(cpu_impl); 410182689Smarius pc->pc_tlb_ctx = TLB_CTX_USER_MIN; 411182689Smarius pc->pc_tlb_ctx_min = TLB_CTX_USER_MIN; 412182689Smarius pc->pc_tlb_ctx_max = TLB_CTX_USER_MAX; 413182689Smarius 414182689Smarius /* 415182730Smarius * Determine the OFW node and frequency of the BSP (and ensure the 416182689Smarius * BSP is in the device tree in the first place). 417182689Smarius */ 418122462Sjake root = OF_peer(0); 419204152Smarius pc->pc_node = find_bsp(root, pc->pc_mid, cpu_impl); 420182689Smarius if (pc->pc_node == 0) 421182689Smarius OF_exit(); 422203838Smarius if (OF_getprop(pc->pc_node, "clock-frequency", &pc->pc_clock, 423182730Smarius sizeof(pc->pc_clock)) <= 0) 424182730Smarius OF_exit(); 425122462Sjake 426157227Smarius /* 427182730Smarius * Provide a DELAY() that works before PCPU_REG is set. We can't 428182730Smarius * set PCPU_REG without also taking over the trap table or the 429182730Smarius * firmware will overwrite it. Unfortunately, it's way to early 430182730Smarius * to also take over the trap table at this point. 431157227Smarius */ 432182730Smarius clock_boot = pc->pc_clock; 433182730Smarius delay_func = delay_boot; 434122462Sjake 43586521Sjake /* 43680709Sjake * Initialize the console before printing anything. 437182730Smarius * NB: the low-level console drivers require a working DELAY() at 438182730Smarius * this point. 43980709Sjake */ 44088639Sjake cninit(); 44180709Sjake 44280709Sjake /* 443157227Smarius * Panic if there is no metadata. Most likely the kernel was booted 44486521Sjake * directly, instead of through loader(8). 44580709Sjake */ 446195149Smarius if (mdp == NULL || kmdp == NULL || end == 0 || 447195149Smarius kernel_tlb_slots == 0 || kernel_tlbs == NULL) { 448195149Smarius printf("sparc64_init: missing loader metadata.\n" 449181701Smarius "This probably means you are not using loader(8).\n"); 45086521Sjake panic("sparc64_init"); 45186521Sjake } 45280709Sjake 45381383Sjake /* 454195149Smarius * Work around the broken loader behavior of not demapping no 455195149Smarius * longer used kernel TLB slots when unloading the kernel or 456195149Smarius * modules. 45786521Sjake */ 458195149Smarius for (va = KERNBASE + (kernel_tlb_slots - 1) * PAGE_SIZE_4M; 459195149Smarius va >= roundup2(end, PAGE_SIZE_4M); va -= PAGE_SIZE_4M) { 460201396Smarius if (bootverbose) 461201396Smarius printf("demapping unused kernel TLB slot " 462201396Smarius "(va %#lx - %#lx)\n", va, va + PAGE_SIZE_4M - 1); 463195149Smarius stxa(TLB_DEMAP_VA(va) | TLB_DEMAP_PRIMARY | TLB_DEMAP_PAGE, 464195149Smarius ASI_DMMU_DEMAP, 0); 465195149Smarius stxa(TLB_DEMAP_VA(va) | TLB_DEMAP_PRIMARY | TLB_DEMAP_PAGE, 466195149Smarius ASI_IMMU_DEMAP, 0); 467195149Smarius flush(KERNBASE); 468195149Smarius kernel_tlb_slots--; 46986521Sjake } 47086521Sjake 471186682Smarius /* 472186682Smarius * Determine the TLB slot maxima, which are expected to be 473186682Smarius * equal across all CPUs. 474205409Smarius * NB: for cheetah-class CPUs, these properties only refer 475186682Smarius * to the t16s. 476186682Smarius */ 477186682Smarius if (OF_getprop(pc->pc_node, "#dtlb-entries", &dtlb_slots, 478186682Smarius sizeof(dtlb_slots)) == -1) 479186682Smarius panic("sparc64_init: cannot determine number of dTLB slots"); 480186682Smarius if (OF_getprop(pc->pc_node, "#itlb-entries", &itlb_slots, 481186682Smarius sizeof(itlb_slots)) == -1) 482186682Smarius panic("sparc64_init: cannot determine number of iTLB slots"); 483186682Smarius 484207248Smarius /* 485207248Smarius * Initialize and enable the caches. Note that his may include 486207248Smarius * applying workarounds. 487207248Smarius */ 488182689Smarius cache_init(pc); 489204152Smarius cache_enable(cpu_impl); 490182689Smarius uma_set_align(pc->pc_cache.dc_linesize - 1); 491101898Sjake 492169178Smarius cpu_block_copy = bcopy; 493169178Smarius cpu_block_zero = bzero; 494113166Sjake getenv_int("machdep.use_vis", &cpu_use_vis); 495113166Sjake if (cpu_use_vis) { 496169178Smarius switch (cpu_impl) { 497169178Smarius case CPU_IMPL_SPARC64: 498207537Smarius case CPU_IMPL_SPARC64V: 499169178Smarius case CPU_IMPL_ULTRASPARCI: 500169178Smarius case CPU_IMPL_ULTRASPARCII: 501169178Smarius case CPU_IMPL_ULTRASPARCIIi: 502169178Smarius case CPU_IMPL_ULTRASPARCIIe: 503185007Smarius case CPU_IMPL_ULTRASPARCIII: /* NB: we've disabled P$. */ 504185007Smarius case CPU_IMPL_ULTRASPARCIIIp: 505185007Smarius case CPU_IMPL_ULTRASPARCIIIi: 506185007Smarius case CPU_IMPL_ULTRASPARCIV: 507185007Smarius case CPU_IMPL_ULTRASPARCIVp: 508185007Smarius case CPU_IMPL_ULTRASPARCIIIip: 509169178Smarius cpu_block_copy = spitfire_block_copy; 510169178Smarius cpu_block_zero = spitfire_block_zero; 511169178Smarius break; 512169178Smarius } 513113166Sjake } 514113166Sjake 51591616Sjake#ifdef SMP 516204152Smarius mp_init(cpu_impl); 51791616Sjake#endif 51891616Sjake 51986521Sjake /* 52090625Stmm * Initialize virtual memory and calculate physmem. 52187546Sdillon */ 522204152Smarius pmap_bootstrap(cpu_impl); 52387546Sdillon 52487546Sdillon /* 52581383Sjake * Initialize tunables. 52681383Sjake */ 52787546Sdillon init_param2(physmem); 528105569Smux env = getenv("kernelname"); 529105569Smux if (env != NULL) { 530105569Smux strlcpy(kernelname, env, sizeof(kernelname)); 531105569Smux freeenv(env); 532105569Smux } 53381085Sjake 53480709Sjake /* 53589038Sjake * Initialize the interrupt tables. 53689038Sjake */ 53790624Stmm intr_init1(); 53880709Sjake 53980709Sjake /* 540182689Smarius * Initialize proc0, set kstack0, frame0, curthread and curpcb. 54180709Sjake */ 542173361Skib proc_linkup0(&proc0, &thread0); 54395744Sjake proc0.p_md.md_sigtramp = NULL; 54488822Stmm proc0.p_md.md_utrap = NULL; 54590361Sjulian thread0.td_kstack = kstack0; 54690361Sjulian thread0.td_pcb = (struct pcb *) 54790361Sjulian (thread0.td_kstack + KSTACK_PAGES * PAGE_SIZE) - 1; 548105908Sjake frame0.tf_tstate = TSTATE_IE | TSTATE_PEF | TSTATE_PRIV; 54990361Sjulian thread0.td_frame = &frame0; 55090361Sjulian pc->pc_curthread = &thread0; 55191156Sjake pc->pc_curpcb = thread0.td_pcb; 55288639Sjake 55380709Sjake /* 554163973Sjb * Initialize global registers. 555163973Sjb */ 556163973Sjb cpu_setregs(pc); 557163973Sjb 558163973Sjb /* 559182773Smarius * Take over the trap table via the PROM. Using the PROM for this 560182773Smarius * is necessary in order to set obp-control-relinquished to true 561182773Smarius * within the PROM so obtaining /virtual-memory/translations doesn't 562182773Smarius * trigger a fatal reset error or worse things further down the road. 563182773Smarius * XXX it should be possible to use this soley instead of writing 564182773Smarius * %tba in cpu_setregs(). Doing so causes a hang however. 565182773Smarius */ 566182773Smarius sun4u_set_traptable(tl0_base); 567182773Smarius 568182773Smarius /* 569182730Smarius * It's now safe to use the real DELAY(). 570182730Smarius */ 571182730Smarius delay_func = delay_tick; 572182730Smarius 573182730Smarius /* 574194784Sjeff * Initialize the dynamic per-CPU area for the BSP and the message 575194784Sjeff * buffer (after setting the trap table). 57688822Stmm */ 577194784Sjeff dpcpu_init(dpcpu0, 0); 57888822Stmm msgbufinit(msgbufp, MSGBUF_SIZE); 57988822Stmm 580207248Smarius /* 581207248Smarius * Initialize mutexes. 582207248Smarius */ 58393702Sjhb mutex_init(); 584207248Smarius 585207248Smarius /* 586207248Smarius * Finish the interrupt initialization now that mutexes work and 587207248Smarius * enable them. 588207248Smarius */ 58990624Stmm intr_init2(); 590207248Smarius wrpr(pil, 0, PIL_TICK); 591207248Smarius wrpr(pstate, 0, PSTATE_KERNEL); 592105946Stmm 593133451Salc /* 594133451Salc * Finish pmap initialization now that we're ready for mutexes. 595133451Salc */ 596133451Salc PMAP_LOCK_INIT(kernel_pmap); 597133451Salc 598106555Stmm OF_getprop(root, "name", sparc64_model, sizeof(sparc64_model) - 1); 599122604Ssimokawa 600131950Smarcel kdb_init(); 601131950Smarcel 602190161Smarius#ifdef KDB 603122604Ssimokawa if (boothowto & RB_KDB) 604174898Srwatson kdb_enter(KDB_WHY_BOOTFLAGS, "Boot flags requested debugger"); 605190161Smarius#endif 60680708Sjake} 60780708Sjake 60880708Sjakevoid 609151316Sdavidxusendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask) 61080708Sjake{ 61182902Sjake struct trapframe *tf; 61282902Sjake struct sigframe *sfp; 61382902Sjake struct sigacts *psp; 61482902Sjake struct sigframe sf; 61583366Sjulian struct thread *td; 61685242Sjake struct frame *fp; 61782902Sjake struct proc *p; 618181701Smarius u_long sp; 61985242Sjake int oonstack; 620151316Sdavidxu int sig; 62182902Sjake 62282902Sjake oonstack = 0; 62383366Sjulian td = curthread; 62483366Sjulian p = td->td_proc; 625114983Sjhb PROC_LOCK_ASSERT(p, MA_OWNED); 626151316Sdavidxu sig = ksi->ksi_signo; 62782902Sjake psp = p->p_sigacts; 628114983Sjhb mtx_assert(&psp->ps_mtx, MA_OWNED); 62983366Sjulian tf = td->td_frame; 63082902Sjake sp = tf->tf_sp + SPOFF; 63182902Sjake oonstack = sigonstack(sp); 63282902Sjake 63383366Sjulian CTR4(KTR_SIG, "sendsig: td=%p (%s) catcher=%p sig=%d", td, p->p_comm, 63482902Sjake catcher, sig); 63582902Sjake 636102554Sjake /* Make sure we have a signal trampoline to return to. */ 637102554Sjake if (p->p_md.md_sigtramp == NULL) { 638102554Sjake /* 639157445Smarius * No signal trampoline... kill the process. 640102554Sjake */ 641102554Sjake CTR0(KTR_SIG, "sendsig: no sigtramp"); 642102873Sjake printf("sendsig: %s is too old, rebuild it\n", p->p_comm); 643102554Sjake sigexit(td, sig); 644102554Sjake /* NOTREACHED */ 645102554Sjake } 646102554Sjake 64782902Sjake /* Save user context. */ 64882902Sjake bzero(&sf, sizeof(sf)); 649118708Sjake get_mcontext(td, &sf.sf_uc.uc_mcontext, 0); 65082902Sjake sf.sf_uc.uc_sigmask = *mask; 651124092Sdavidxu sf.sf_uc.uc_stack = td->td_sigstk; 652181701Smarius sf.sf_uc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK) ? 653181701Smarius ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE; 65482902Sjake 65582902Sjake /* Allocate and validate space for the signal handler context. */ 656124092Sdavidxu if ((td->td_pflags & TDP_ALTSTACK) != 0 && !oonstack && 65782902Sjake SIGISMEMBER(psp->ps_sigonstack, sig)) { 658124092Sdavidxu sfp = (struct sigframe *)(td->td_sigstk.ss_sp + 659124092Sdavidxu td->td_sigstk.ss_size - sizeof(struct sigframe)); 66082902Sjake } else 66182902Sjake sfp = (struct sigframe *)sp - 1; 662114983Sjhb mtx_unlock(&psp->ps_mtx); 66382902Sjake PROC_UNLOCK(p); 66482902Sjake 66585242Sjake fp = (struct frame *)sfp - 1; 66682902Sjake 66782902Sjake /* Translate the signal if appropriate. */ 66882902Sjake if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize) 66982902Sjake sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)]; 67082902Sjake 67182902Sjake /* Build the argument list for the signal handler. */ 67282902Sjake tf->tf_out[0] = sig; 67382902Sjake tf->tf_out[2] = (register_t)&sfp->sf_uc; 67482902Sjake tf->tf_out[4] = (register_t)catcher; 675157445Smarius if (SIGISMEMBER(psp->ps_siginfo, sig)) { 676157445Smarius /* Signal handler installed with SA_SIGINFO. */ 677157445Smarius tf->tf_out[1] = (register_t)&sfp->sf_si; 67882902Sjake 679157445Smarius /* Fill in POSIX parts. */ 680157445Smarius sf.sf_si = ksi->ksi_info; 681157445Smarius sf.sf_si.si_signo = sig; /* maybe a translated signal */ 682157445Smarius } else { 683157445Smarius /* Old FreeBSD-style arguments. */ 684157445Smarius tf->tf_out[1] = ksi->ksi_code; 685157445Smarius tf->tf_out[3] = (register_t)ksi->ksi_addr; 686157445Smarius } 687157445Smarius 68882902Sjake /* Copy the sigframe out to the user's stack. */ 68985242Sjake if (rwindow_save(td) != 0 || copyout(&sf, sfp, sizeof(*sfp)) != 0 || 69094254Sjake suword(&fp->fr_in[6], tf->tf_out[6]) != 0) { 69182902Sjake /* 69282902Sjake * Something is wrong with the stack pointer. 69382902Sjake * ...Kill the process. 69482902Sjake */ 69583366Sjulian CTR2(KTR_SIG, "sendsig: sigexit td=%p sfp=%p", td, sfp); 69682902Sjake PROC_LOCK(p); 69783366Sjulian sigexit(td, SIGILL); 69882902Sjake /* NOTREACHED */ 69982902Sjake } 70082902Sjake 701102554Sjake tf->tf_tpc = (u_long)p->p_md.md_sigtramp; 70282902Sjake tf->tf_tnpc = tf->tf_tpc + 4; 70385242Sjake tf->tf_sp = (u_long)fp - SPOFF; 70482902Sjake 70583366Sjulian CTR3(KTR_SIG, "sendsig: return td=%p pc=%#lx sp=%#lx", td, tf->tf_tpc, 70682902Sjake tf->tf_sp); 70784178Sjake 70884178Sjake PROC_LOCK(p); 709114983Sjhb mtx_lock(&psp->ps_mtx); 71080708Sjake} 71180708Sjake 71280708Sjake#ifndef _SYS_SYSPROTO_H_ 71383088Sobrienstruct sigreturn_args { 71480708Sjake ucontext_t *ucp; 71580708Sjake}; 71680708Sjake#endif 71780708Sjake 71894606Salc/* 71994606Salc * MPSAFE 72094606Salc */ 72180708Sjakeint 72283366Sjuliansigreturn(struct thread *td, struct sigreturn_args *uap) 72380708Sjake{ 72483366Sjulian struct proc *p; 725118768Sjake mcontext_t *mc; 72682902Sjake ucontext_t uc; 727118708Sjake int error; 72882902Sjake 72983366Sjulian p = td->td_proc; 73083366Sjulian if (rwindow_save(td)) { 73182902Sjake PROC_LOCK(p); 73283366Sjulian sigexit(td, SIGILL); 73382902Sjake } 73482902Sjake 73583366Sjulian CTR2(KTR_SIG, "sigreturn: td=%p ucp=%p", td, uap->sigcntxp); 73682902Sjake if (copyin(uap->sigcntxp, &uc, sizeof(uc)) != 0) { 73783366Sjulian CTR1(KTR_SIG, "sigreturn: efault td=%p", td); 73882902Sjake return (EFAULT); 73982902Sjake } 74082902Sjake 741118768Sjake mc = &uc.uc_mcontext; 742118768Sjake error = set_mcontext(td, mc); 743118708Sjake if (error != 0) 744118708Sjake return (error); 74582902Sjake 746198507Skib kern_sigprocmask(td, SIG_SETMASK, &uc.uc_sigmask, NULL, 0); 747105733Sjake 74883366Sjulian CTR4(KTR_SIG, "sigreturn: return td=%p pc=%#lx sp=%#lx tstate=%#lx", 749118768Sjake td, mc->mc_tpc, mc->mc_sp, mc->mc_tstate); 75082902Sjake return (EJUSTRETURN); 75180708Sjake} 75280708Sjake 753131905Smarcel/* 754131905Smarcel * Construct a PCB from a trapframe. This is called from kdb_trap() where 755131905Smarcel * we want to start a backtrace from the function that caused us to enter 756131905Smarcel * the debugger. We have the context in the trapframe, but base the trace 757131905Smarcel * on the PCB. The PCB doesn't have to be perfect, as long as it contains 758131905Smarcel * enough for a backtrace. 759131905Smarcel */ 760131905Smarcelvoid 761131905Smarcelmakectx(struct trapframe *tf, struct pcb *pcb) 762131905Smarcel{ 763131905Smarcel 764131905Smarcel pcb->pcb_pc = tf->tf_tpc; 765131905Smarcel pcb->pcb_sp = tf->tf_sp; 766131905Smarcel} 767131905Smarcel 768106977Sdeischenint 769122364Smarcelget_mcontext(struct thread *td, mcontext_t *mc, int flags) 770106977Sdeischen{ 771112924Sjake struct trapframe *tf; 772112924Sjake struct pcb *pcb; 773106977Sdeischen 774112924Sjake tf = td->td_frame; 775112924Sjake pcb = td->td_pcb; 776199442Smarius /* 777199442Smarius * Copy the registers which will be restored by tl0_ret() from the 778199442Smarius * trapframe. 779199442Smarius * Note that we skip %g7 which is used as the userland TLS register 780199442Smarius * and %wstate. 781199442Smarius */ 782199442Smarius mc->mc_flags = _MC_VERSION; 783199442Smarius mc->mc_global[1] = tf->tf_global[1]; 784199442Smarius mc->mc_global[2] = tf->tf_global[2]; 785199442Smarius mc->mc_global[3] = tf->tf_global[3]; 786199442Smarius mc->mc_global[4] = tf->tf_global[4]; 787199442Smarius mc->mc_global[5] = tf->tf_global[5]; 788199442Smarius mc->mc_global[6] = tf->tf_global[6]; 789122364Smarcel if (flags & GET_MC_CLEAR_RET) { 790113998Sdeischen mc->mc_out[0] = 0; 791113998Sdeischen mc->mc_out[1] = 0; 792199442Smarius } else { 793199442Smarius mc->mc_out[0] = tf->tf_out[0]; 794199442Smarius mc->mc_out[1] = tf->tf_out[1]; 795113998Sdeischen } 796199442Smarius mc->mc_out[2] = tf->tf_out[2]; 797199442Smarius mc->mc_out[3] = tf->tf_out[3]; 798199442Smarius mc->mc_out[4] = tf->tf_out[4]; 799199442Smarius mc->mc_out[5] = tf->tf_out[5]; 800199442Smarius mc->mc_out[6] = tf->tf_out[6]; 801199442Smarius mc->mc_out[7] = tf->tf_out[7]; 802199442Smarius mc->mc_fprs = tf->tf_fprs; 803199442Smarius mc->mc_fsr = tf->tf_fsr; 804199442Smarius mc->mc_gsr = tf->tf_gsr; 805199442Smarius mc->mc_tnpc = tf->tf_tnpc; 806199442Smarius mc->mc_tpc = tf->tf_tpc; 807199442Smarius mc->mc_tstate = tf->tf_tstate; 808199442Smarius mc->mc_y = tf->tf_y; 809112924Sjake critical_enter(); 810112961Sjake if ((tf->tf_fprs & FPRS_FEF) != 0) { 811112961Sjake savefpctx(pcb->pcb_ufp); 812112961Sjake tf->tf_fprs &= ~FPRS_FEF; 813112961Sjake pcb->pcb_flags |= PCB_FEF; 814112961Sjake } 815112961Sjake if ((pcb->pcb_flags & PCB_FEF) != 0) { 816113018Sjake bcopy(pcb->pcb_ufp, mc->mc_fp, sizeof(mc->mc_fp)); 817112924Sjake mc->mc_fprs |= FPRS_FEF; 818112924Sjake } 819112924Sjake critical_exit(); 820112924Sjake return (0); 821106977Sdeischen} 822106977Sdeischen 823106977Sdeischenint 824112924Sjakeset_mcontext(struct thread *td, const mcontext_t *mc) 825106977Sdeischen{ 826112924Sjake struct trapframe *tf; 827112924Sjake struct pcb *pcb; 828106977Sdeischen 829112961Sjake if (!TSTATE_SECURE(mc->mc_tstate) || 830112961Sjake (mc->mc_flags & ((1L << _MC_VERSION_BITS) - 1)) != _MC_VERSION) 831112924Sjake return (EINVAL); 832112924Sjake tf = td->td_frame; 833112924Sjake pcb = td->td_pcb; 834136325Skensmith /* Make sure the windows are spilled first. */ 835136325Skensmith flushw(); 836199442Smarius /* 837199442Smarius * Copy the registers which will be restored by tl0_ret() to the 838199442Smarius * trapframe. 839199442Smarius * Note that we skip %g7 which is used as the userland TLS register 840199442Smarius * and %wstate. 841199442Smarius */ 842199442Smarius tf->tf_global[1] = mc->mc_global[1]; 843199442Smarius tf->tf_global[2] = mc->mc_global[2]; 844199442Smarius tf->tf_global[3] = mc->mc_global[3]; 845199442Smarius tf->tf_global[4] = mc->mc_global[4]; 846199442Smarius tf->tf_global[5] = mc->mc_global[5]; 847199442Smarius tf->tf_global[6] = mc->mc_global[6]; 848199442Smarius tf->tf_out[0] = mc->mc_out[0]; 849199442Smarius tf->tf_out[1] = mc->mc_out[1]; 850199442Smarius tf->tf_out[2] = mc->mc_out[2]; 851199442Smarius tf->tf_out[3] = mc->mc_out[3]; 852199442Smarius tf->tf_out[4] = mc->mc_out[4]; 853199442Smarius tf->tf_out[5] = mc->mc_out[5]; 854199442Smarius tf->tf_out[6] = mc->mc_out[6]; 855199442Smarius tf->tf_out[7] = mc->mc_out[7]; 856199442Smarius tf->tf_fprs = mc->mc_fprs; 857199442Smarius tf->tf_fsr = mc->mc_fsr; 858199442Smarius tf->tf_gsr = mc->mc_gsr; 859199442Smarius tf->tf_tnpc = mc->mc_tnpc; 860199442Smarius tf->tf_tpc = mc->mc_tpc; 861199442Smarius tf->tf_tstate = mc->mc_tstate; 862199442Smarius tf->tf_y = mc->mc_y; 863112924Sjake if ((mc->mc_fprs & FPRS_FEF) != 0) { 864112924Sjake tf->tf_fprs = 0; 865113018Sjake bcopy(mc->mc_fp, pcb->pcb_ufp, sizeof(pcb->pcb_ufp)); 866112924Sjake pcb->pcb_flags |= PCB_FEF; 867112924Sjake } 868112924Sjake return (0); 869106977Sdeischen} 870106977Sdeischen 87186147Stmm/* 87292205Sjake * Exit the kernel and execute a firmware call that will not return, as 87392205Sjake * specified by the arguments. 87492205Sjake */ 87592205Sjakevoid 87692205Sjakecpu_shutdown(void *args) 87792205Sjake{ 87892205Sjake 87992205Sjake#ifdef SMP 88092205Sjake cpu_mp_shutdown(); 88192205Sjake#endif 882186347Snwhitehorn ofw_exit(args); 88392205Sjake} 88492205Sjake 885192323Smarcel/* 886192323Smarcel * Flush the D-cache for non-DMA I/O so that the I-cache can 887192323Smarcel * be made coherent later. 888192323Smarcel */ 889192323Smarcelvoid 890192323Smarcelcpu_flush_dcache(void *ptr, size_t len) 891192323Smarcel{ 892195149Smarius 893192323Smarcel /* TBD */ 894192323Smarcel} 895192323Smarcel 896181701Smarius/* Get current clock frequency for the given CPU ID. */ 897141237Snjlint 898141237Snjlcpu_est_clockrate(int cpu_id, uint64_t *rate) 899141237Snjl{ 900182730Smarius struct pcpu *pc; 901141237Snjl 902182730Smarius pc = pcpu_find(cpu_id); 903182730Smarius if (pc == NULL || rate == NULL) 904182730Smarius return (EINVAL); 905182730Smarius *rate = pc->pc_clock; 906182730Smarius return (0); 907141237Snjl} 908141237Snjl 90992205Sjake/* 91086147Stmm * Duplicate OF_exit() with a different firmware call function that restores 91186147Stmm * the trap table, otherwise a RED state exception is triggered in at least 91286147Stmm * some firmware versions. 91386147Stmm */ 91480708Sjakevoid 91580708Sjakecpu_halt(void) 91680708Sjake{ 91786147Stmm static struct { 91886147Stmm cell_t name; 91986147Stmm cell_t nargs; 92086147Stmm cell_t nreturns; 92186147Stmm } args = { 92286147Stmm (cell_t)"exit", 92386147Stmm 0, 92486147Stmm 0 92586147Stmm }; 92684178Sjake 92792205Sjake cpu_shutdown(&args); 92880708Sjake} 92980708Sjake 930203838Smariusstatic void 93186147Stmmsparc64_shutdown_final(void *dummy, int howto) 93286147Stmm{ 93386147Stmm static struct { 93486147Stmm cell_t name; 93586147Stmm cell_t nargs; 93686147Stmm cell_t nreturns; 93786147Stmm } args = { 93886147Stmm (cell_t)"SUNW,power-off", 93986147Stmm 0, 94086147Stmm 0 94186147Stmm }; 94286147Stmm 94386147Stmm /* Turn the power off? */ 94486147Stmm if ((howto & RB_POWEROFF) != 0) 94592205Sjake cpu_shutdown(&args); 946185007Smarius /* In case of halt, return to the firmware. */ 94786147Stmm if ((howto & RB_HALT) != 0) 94886147Stmm cpu_halt(); 94986147Stmm} 95086147Stmm 951121237Spetervoid 952178471Sjeffcpu_idle(int busy) 953121237Speter{ 954181701Smarius 955181701Smarius /* Insert code to halt (until next interrupt) for the idle loop. */ 956121237Speter} 957121237Speter 95880708Sjakeint 959178471Sjeffcpu_idle_wakeup(int cpu) 960178471Sjeff{ 961178471Sjeff 962178471Sjeff return (0); 963178471Sjeff} 964178471Sjeff 965178471Sjeffint 96683366Sjulianptrace_set_pc(struct thread *td, u_long addr) 96780708Sjake{ 96882016Sjake 96983366Sjulian td->td_frame->tf_tpc = addr; 97083366Sjulian td->td_frame->tf_tnpc = addr + 4; 97180708Sjake return (0); 97280708Sjake} 97380708Sjake 97480708Sjakeint 97583366Sjulianptrace_single_step(struct thread *td) 97680708Sjake{ 977181701Smarius 978104271Sjake /* TODO; */ 97980708Sjake return (0); 98080708Sjake} 98180708Sjake 982132088Sdavidxuint 983132088Sdavidxuptrace_clear_single_step(struct thread *td) 984132088Sdavidxu{ 985181701Smarius 986132088Sdavidxu /* TODO; */ 987132088Sdavidxu return (0); 988132088Sdavidxu} 989132088Sdavidxu 99080708Sjakevoid 991205642Snwhitehornexec_setregs(struct thread *td, struct image_params *imgp, u_long stack) 99280708Sjake{ 99388639Sjake struct trapframe *tf; 99481135Stmm struct pcb *pcb; 995102557Sjake struct proc *p; 99684178Sjake u_long sp; 99781135Stmm 99888782Sjake /* XXX no cpu_exec */ 999102557Sjake p = td->td_proc; 1000102557Sjake p->p_md.md_sigtramp = NULL; 1001140485Sjhb if (p->p_md.md_utrap != NULL) { 1002140485Sjhb utrap_free(p->p_md.md_utrap); 1003102557Sjake p->p_md.md_utrap = NULL; 100488782Sjake } 100588782Sjake 100683366Sjulian pcb = td->td_pcb; 1007105908Sjake tf = td->td_frame; 100888639Sjake sp = rounddown(stack, 16); 100998032Sjake bzero(pcb, sizeof(*pcb)); 101098032Sjake bzero(tf, sizeof(*tf)); 101188639Sjake tf->tf_out[0] = stack; 1012105908Sjake tf->tf_out[3] = p->p_sysent->sv_psstrings; 101388639Sjake tf->tf_out[6] = sp - SPOFF - sizeof(struct frame); 1014205642Snwhitehorn tf->tf_tnpc = imgp->entry_addr + 4; 1015205642Snwhitehorn tf->tf_tpc = imgp->entry_addr; 101688639Sjake tf->tf_tstate = TSTATE_IE | TSTATE_PEF | TSTATE_MM_TSO; 101788639Sjake 101888639Sjake td->td_retval[0] = tf->tf_out[0]; 101988639Sjake td->td_retval[1] = tf->tf_out[1]; 102080708Sjake} 102180708Sjake 102280708Sjakeint 102384178Sjakefill_regs(struct thread *td, struct reg *regs) 102480708Sjake{ 102580708Sjake 1026105733Sjake bcopy(td->td_frame, regs, sizeof(*regs)); 102780708Sjake return (0); 102880708Sjake} 102980708Sjake 103080708Sjakeint 103184178Sjakeset_regs(struct thread *td, struct reg *regs) 103280708Sjake{ 1033112922Sjake struct trapframe *tf; 103480708Sjake 103584178Sjake if (!TSTATE_SECURE(regs->r_tstate)) 103684178Sjake return (EINVAL); 1037112922Sjake tf = td->td_frame; 1038112922Sjake regs->r_wstate = tf->tf_wstate; 1039112922Sjake bcopy(regs, tf, sizeof(*regs)); 104080708Sjake return (0); 104180708Sjake} 104280708Sjake 104380708Sjakeint 104485294Sdesfill_dbregs(struct thread *td, struct dbreg *dbregs) 104585294Sdes{ 104685294Sdes 104785294Sdes return (ENOSYS); 104885294Sdes} 104985294Sdes 105085294Sdesint 105185294Sdesset_dbregs(struct thread *td, struct dbreg *dbregs) 105285294Sdes{ 105385294Sdes 105485294Sdes return (ENOSYS); 105585294Sdes} 105685294Sdes 105785294Sdesint 105883366Sjulianfill_fpregs(struct thread *td, struct fpreg *fpregs) 105980708Sjake{ 106088639Sjake struct trapframe *tf; 106184178Sjake struct pcb *pcb; 106284178Sjake 106384178Sjake pcb = td->td_pcb; 106488639Sjake tf = td->td_frame; 1065112920Sjake bcopy(pcb->pcb_ufp, fpregs->fr_regs, sizeof(fpregs->fr_regs)); 106688639Sjake fpregs->fr_fsr = tf->tf_fsr; 1067105733Sjake fpregs->fr_gsr = tf->tf_gsr; 106880708Sjake return (0); 106980708Sjake} 107080708Sjake 107180708Sjakeint 107283366Sjulianset_fpregs(struct thread *td, struct fpreg *fpregs) 107380708Sjake{ 107488639Sjake struct trapframe *tf; 107584178Sjake struct pcb *pcb; 107684178Sjake 107784178Sjake pcb = td->td_pcb; 107888639Sjake tf = td->td_frame; 1079112922Sjake tf->tf_fprs &= ~FPRS_FEF; 1080112920Sjake bcopy(fpregs->fr_regs, pcb->pcb_ufp, sizeof(pcb->pcb_ufp)); 108188639Sjake tf->tf_fsr = fpregs->fr_fsr; 1082105733Sjake tf->tf_gsr = fpregs->fr_gsr; 108380708Sjake return (0); 108480708Sjake} 1085140485Sjhb 1086140485Sjhbstruct md_utrap * 1087140485Sjhbutrap_alloc(void) 1088140485Sjhb{ 1089140485Sjhb struct md_utrap *ut; 1090140485Sjhb 1091140485Sjhb ut = malloc(sizeof(struct md_utrap), M_SUBPROC, M_WAITOK | M_ZERO); 1092140485Sjhb ut->ut_refcnt = 1; 1093140485Sjhb return (ut); 1094140485Sjhb} 1095140485Sjhb 1096140485Sjhbvoid 1097140485Sjhbutrap_free(struct md_utrap *ut) 1098140485Sjhb{ 1099140485Sjhb int refcnt; 1100140485Sjhb 1101140485Sjhb if (ut == NULL) 1102140485Sjhb return; 1103140485Sjhb mtx_pool_lock(mtxpool_sleep, ut); 1104140485Sjhb ut->ut_refcnt--; 1105140485Sjhb refcnt = ut->ut_refcnt; 1106140485Sjhb mtx_pool_unlock(mtxpool_sleep, ut); 1107140485Sjhb if (refcnt == 0) 1108140485Sjhb free(ut, M_SUBPROC); 1109140485Sjhb} 1110140485Sjhb 1111140485Sjhbstruct md_utrap * 1112140485Sjhbutrap_hold(struct md_utrap *ut) 1113140485Sjhb{ 1114140485Sjhb 1115140485Sjhb if (ut == NULL) 1116140485Sjhb return (NULL); 1117140485Sjhb mtx_pool_lock(mtxpool_sleep, ut); 1118140485Sjhb ut->ut_refcnt++; 1119140485Sjhb mtx_pool_unlock(mtxpool_sleep, ut); 1120140485Sjhb return (ut); 1121140485Sjhb} 1122