1*b793947bSmiod /* $OpenBSD: cpu.h,v 1.109 2024/11/06 12:06:15 miod Exp $ */ 2de24d0bcSjason /* $NetBSD: cpu.h,v 1.28 2001/06/14 22:56:58 thorpej Exp $ */ 3de24d0bcSjason 4de24d0bcSjason /* 5de24d0bcSjason * Copyright (c) 1992, 1993 6de24d0bcSjason * The Regents of the University of California. All rights reserved. 7de24d0bcSjason * 8de24d0bcSjason * This software was developed by the Computer Systems Engineering group 9de24d0bcSjason * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 10de24d0bcSjason * contributed to Berkeley. 11de24d0bcSjason * 12de24d0bcSjason * All advertising materials mentioning features or use of this software 13de24d0bcSjason * must display the following acknowledgement: 14de24d0bcSjason * This product includes software developed by the University of 15de24d0bcSjason * California, Lawrence Berkeley Laboratory. 16de24d0bcSjason * 17de24d0bcSjason * Redistribution and use in source and binary forms, with or without 18de24d0bcSjason * modification, are permitted provided that the following conditions 19de24d0bcSjason * are met: 20de24d0bcSjason * 1. Redistributions of source code must retain the above copyright 21de24d0bcSjason * notice, this list of conditions and the following disclaimer. 22de24d0bcSjason * 2. Redistributions in binary form must reproduce the above copyright 23de24d0bcSjason * notice, this list of conditions and the following disclaimer in the 24de24d0bcSjason * documentation and/or other materials provided with the distribution. 2529295d1cSmillert * 3. Neither the name of the University nor the names of its contributors 26de24d0bcSjason * may be used to endorse or promote products derived from this software 27de24d0bcSjason * without specific prior written permission. 28de24d0bcSjason * 29de24d0bcSjason * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 30de24d0bcSjason * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 31de24d0bcSjason * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 32de24d0bcSjason * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 33de24d0bcSjason * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 34de24d0bcSjason * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 35de24d0bcSjason * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 36de24d0bcSjason * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 37de24d0bcSjason * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 38de24d0bcSjason * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 39de24d0bcSjason * SUCH DAMAGE. 40de24d0bcSjason * 41de24d0bcSjason * @(#)cpu.h 8.4 (Berkeley) 1/5/94 42de24d0bcSjason */ 43de24d0bcSjason 442fa72412Spirofti #ifndef _MACHINE_CPU_H_ 452fa72412Spirofti #define _MACHINE_CPU_H_ 46de24d0bcSjason 47de24d0bcSjason /* 48de24d0bcSjason * CTL_MACHDEP definitions. 49de24d0bcSjason */ 50b2e0f490Snaddy /* 1 formerly: booted kernel name */ 518f4f8c11Sjason #define CPU_LED_BLINK 2 /* int: blink leds? */ 52424311dfSjason #define CPU_ALLOWAPERTURE 3 /* allow xf86 operations */ 539ec54805Sart #define CPU_CPUTYPE 4 /* cpu type */ 54e767e0e2Sjason #define CPU_CECCERRORS 5 /* Correctable ECC errors */ 55e767e0e2Sjason #define CPU_CECCLAST 6 /* Correctable ECC last fault addr */ 56b2e0f490Snaddy /* 7 formerly: soft reset via keyboard */ 575611998eSjason #define CPU_MAXID 8 /* number of valid machdep ids */ 58de24d0bcSjason 59de24d0bcSjason #define CTL_MACHDEP_NAMES { \ 60de24d0bcSjason { 0, 0 }, \ 61823e4330Smiod { 0, 0 }, \ 628f4f8c11Sjason { "led_blink", CTLTYPE_INT }, \ 63424311dfSjason { "allowaperture", CTLTYPE_INT }, \ 64305f13f4Sjason { "cputype", CTLTYPE_INT }, \ 65e767e0e2Sjason { "ceccerrs", CTLTYPE_INT }, \ 66e767e0e2Sjason { "cecclast", CTLTYPE_QUAD }, \ 67b2e0f490Snaddy { 0, 0 }, \ 68de24d0bcSjason } 69de24d0bcSjason 70de24d0bcSjason #ifdef _KERNEL 71de24d0bcSjason /* 72de24d0bcSjason * Exported definitions unique to SPARC cpu support. 73de24d0bcSjason */ 74de24d0bcSjason 752d084210Shenric #include <machine/ctlreg.h> 761c00236eSmiod #include <machine/frame.h> 77de24d0bcSjason #include <machine/intr.h> 78cfc56827Smiod #include <machine/psl.h> 79cfc56827Smiod #include <machine/reg.h> 80de24d0bcSjason 81573d576bScheloha #include <sys/clockintr.h> 82346b4f84Sart #include <sys/sched.h> 831a1181a9Sjsg #include <sys/srp.h> 84e9ae4e90Sclaudio #include <uvm/uvm_percpu.h> 85de24d0bcSjason 86de24d0bcSjason /* 87de24d0bcSjason * The cpu_info structure is part of a 64KB structure mapped both the kernel 88de24d0bcSjason * pmap and a single locked TTE a CPUINFO_VA for that particular processor. 89de24d0bcSjason * Each processor's cpu_info is accessible at CPUINFO_VA only for that 90de24d0bcSjason * processor. Other processors can access that through an additional mapping 91de24d0bcSjason * in the kernel pmap. 92de24d0bcSjason * 93de24d0bcSjason * The 64KB page contains: 94de24d0bcSjason * 95de24d0bcSjason * cpu_info 96de24d0bcSjason * interrupt stack (all remaining space) 97de24d0bcSjason * idle PCB 98de24d0bcSjason * idle stack (STACKSPACE - sizeof(PCB)) 99de24d0bcSjason * 32KB TSB 100de24d0bcSjason */ 101de24d0bcSjason 102de24d0bcSjason struct cpu_info { 1034b1c87d1Skettenis /* 1044b1c87d1Skettenis * SPARC cpu_info structures live at two VAs: one global 1054b1c87d1Skettenis * VA (so each CPU can access any other CPU's cpu_info) 1064b1c87d1Skettenis * and an alias VA CPUINFO_VA which is the same on each 1074b1c87d1Skettenis * CPU and maps to that CPU's cpu_info. Since the alias 1084b1c87d1Skettenis * CPUINFO_VA is how we locate our cpu_info, we have to 1094b1c87d1Skettenis * self-reference the global VA so that we can return it 1104b1c87d1Skettenis * in the curcpu() macro. 1114b1c87d1Skettenis */ 1124b1c87d1Skettenis struct cpu_info * volatile ci_self; 1134b1c87d1Skettenis 114de24d0bcSjason /* Most important fields first */ 115de24d0bcSjason struct proc *ci_curproc; 116de24d0bcSjason struct pcb *ci_cpcb; /* also initial stack */ 1178ad6162fSmiod paddr_t ci_cpcbpaddr; 118de24d0bcSjason struct cpu_info *ci_next; 119de24d0bcSjason 120de24d0bcSjason struct proc *ci_fpproc; 121ba177d4eSmpi int ci_cpuid; 122e1fc0c1eSkettenis int ci_flags; 123de24d0bcSjason int ci_upaid; 124023c9b86Skettenis #ifdef MULTIPROCESSOR 125023c9b86Skettenis int ci_itid; 12652776b7dSdlg struct srp_hazard ci_srp_hazards[SRP_HAZARD_NUM]; 127e9ae4e90Sclaudio #define __HAVE_UVM_PERCPU 128e9ae4e90Sclaudio struct uvm_pmr_cache ci_uvm; /* [o] page cache */ 129023c9b86Skettenis #endif 1304b1c87d1Skettenis int ci_node; 1316a46a94aSderaadt u_int32_t ci_randseed; 132de24d0bcSjason struct schedstate_percpu ci_schedstate; /* scheduler state */ 133de24d0bcSjason 1346fb6e3c7Skettenis int ci_want_resched; 135edf47abcSkettenis int ci_handled_intr_level; 136*b793947bSmiod int ci_idepth; 137*b793947bSmiod struct intrhand *ci_intrpending[16]; 138c737cf90Scheloha struct clockqueue ci_queue; 13940cab56cSkettenis struct intrhand ci_tickintr; 1406fb6e3c7Skettenis 141b0ad0500Skettenis volatile int ci_ddb_paused; 142b0ad0500Skettenis #define CI_DDB_RUNNING 0 143b0ad0500Skettenis #define CI_DDB_SHOULDSTOP 1 144b0ad0500Skettenis #define CI_DDB_STOPPED 2 145b0ad0500Skettenis #define CI_DDB_ENTERDDB 3 146b0ad0500Skettenis #define CI_DDB_INDDB 4 147b0ad0500Skettenis 148de24d0bcSjason /* Spinning up the CPU */ 149c4071fd1Smillert void (*ci_spinup)(void); /* spinup routine */ 150de24d0bcSjason void *ci_initstack; 151de24d0bcSjason paddr_t ci_paddr; /* Phys addr of this structure. */ 152b18bb33bSkettenis 153b18bb33bSkettenis #ifdef SUN4V 1541c00236eSmiod struct rwindow ci_rw; 155b18bb33bSkettenis u_int64_t ci_rwsp; 156b18bb33bSkettenis 157b18bb33bSkettenis paddr_t ci_mmfsa; 158b18bb33bSkettenis paddr_t ci_cpumq; 159b18bb33bSkettenis paddr_t ci_devmq; 160b18bb33bSkettenis 161b18bb33bSkettenis paddr_t ci_cpuset; 162b18bb33bSkettenis paddr_t ci_mondo; 163b18bb33bSkettenis #endif 164ac5996fcSmiod 1650a20b156Skettenis int ci_pci_probe; 1660a20b156Skettenis int ci_pci_fault; 1670a20b156Skettenis 168ac5996fcSmiod #ifdef DIAGNOSTIC 169ac5996fcSmiod int ci_mutex_level; 170ac5996fcSmiod #endif 1716377c2eaSmpi #ifdef GPROF 1726377c2eaSmpi struct gmonparam *ci_gmon; 1731d970828Scheloha struct clockintr ci_gmonclock; 1746377c2eaSmpi #endif 1751a4a9ab2Scheloha char ci_panicbuf[512]; 176de24d0bcSjason }; 177de24d0bcSjason 178e1fc0c1eSkettenis #define CPUF_RUNNING 0x0001 /* CPU is running */ 179e1fc0c1eSkettenis 180de24d0bcSjason extern struct cpu_info *cpus; 181de24d0bcSjason 1824b1c87d1Skettenis #ifdef MULTIPROCESSOR 1834b1c87d1Skettenis 1843a9c0e11Skettenis register struct cpu_info *__curcpu asm ("g7"); 18564958104Skettenis 186b69b316eSdlg #define curcpu() (__curcpu->ci_self) 187ba177d4eSmpi #define cpu_number() (__curcpu->ci_cpuid) 1884b1c87d1Skettenis 189ba177d4eSmpi #define CPU_IS_PRIMARY(ci) ((ci)->ci_cpuid == 0) 190d73de46fSkettenis #define CPU_IS_RUNNING(ci) 1 1914b1c87d1Skettenis #define CPU_INFO_ITERATOR int 1924b1c87d1Skettenis #define CPU_INFO_FOREACH(cii, ci) \ 1934b1c87d1Skettenis for (cii = 0, ci = cpus; ci != NULL; ci = ci->ci_next) 194ba177d4eSmpi #define CPU_INFO_UNIT(ci) ((ci)->ci_cpuid) 195e3444f33Sart #define MAXCPUS 256 1964b1c87d1Skettenis 1974b1c87d1Skettenis void cpu_boot_secondary_processors(void); 1984b1c87d1Skettenis 1994b1c87d1Skettenis void sparc64_send_ipi(int, void (*)(void), u_int64_t, u_int64_t); 2004b1c87d1Skettenis void sparc64_broadcast_ipi(void (*)(void), u_int64_t, u_int64_t); 2014b1c87d1Skettenis 2028978f211Sart void cpu_unidle(struct cpu_info *); 2031ad5eaaaSmiod 204b69b316eSdlg #else /* MULTIPROCESSOR */ 2054b1c87d1Skettenis 206b69b316eSdlg #define __curcpu ((struct cpu_info *)CPUINFO_VA) 207b69b316eSdlg #define curcpu() __curcpu 2084b1c87d1Skettenis #define cpu_number() 0 2094ced3000Skettenis 2104ced3000Skettenis #define CPU_IS_PRIMARY(ci) 1 211d73de46fSkettenis #define CPU_IS_RUNNING(ci) 1 2124ced3000Skettenis #define CPU_INFO_ITERATOR int 2134ced3000Skettenis #define CPU_INFO_FOREACH(cii, ci) \ 2144ced3000Skettenis for (cii = 0, ci = curcpu(); ci != NULL; ci = NULL) 2154bbbf93eSart #define CPU_INFO_UNIT(ci) 0 216e3444f33Sart #define MAXCPUS 1 2174ced3000Skettenis 2188978f211Sart #define cpu_unidle(ci) 2198978f211Sart 220b69b316eSdlg #endif /* MULTIPROCESSOR */ 221b69b316eSdlg 222b69b316eSdlg #define curpcb __curcpu->ci_cpcb 223b69b316eSdlg #define fpproc __curcpu->ci_fpproc 224de24d0bcSjason 2254f1155a8Snaddy static inline unsigned int 2264f1155a8Snaddy cpu_rnd_messybits(void) 2274f1155a8Snaddy { 2284f1155a8Snaddy u_int64_t tick; 2294f1155a8Snaddy 2304f1155a8Snaddy __asm volatile("rd %%tick, %0" : "=r" (tick) :); 2314f1155a8Snaddy 2324f1155a8Snaddy return ((tick >> 32) ^ tick); 2334f1155a8Snaddy } 23401802d2cSdlg 235275e6a2fSmpi /* 236275e6a2fSmpi * On processors with multiple threads we force a thread switch. 237275e6a2fSmpi * 238275e6a2fSmpi * On UltraSPARC T2 and its successors, the optimal way to do this 239275e6a2fSmpi * seems to be to do three nop reads of %ccr. This works on 240275e6a2fSmpi * UltraSPARC T1 as well, even though three nop casx operations seem 241275e6a2fSmpi * to be slightly more optimal. Since these instructions are 242275e6a2fSmpi * effectively nops, executing them on earlier non-CMT processors is 243275e6a2fSmpi * harmless, so we make this the default. 244275e6a2fSmpi * 245275e6a2fSmpi * On SPARC T4 and later, we can use the processor-specific pause 246275e6a2fSmpi * instruction. 247275e6a2fSmpi * 248275e6a2fSmpi * On SPARC64 VI and its successors we execute the processor-specific 249275e6a2fSmpi * sleep instruction. 250275e6a2fSmpi */ 251275e6a2fSmpi #define CPU_BUSY_CYCLE() \ 252275e6a2fSmpi do { \ 253275e6a2fSmpi __asm volatile( \ 254275e6a2fSmpi "999: rd %%ccr, %%g0 \n" \ 255275e6a2fSmpi " rd %%ccr, %%g0 \n" \ 256275e6a2fSmpi " rd %%ccr, %%g0 \n" \ 257275e6a2fSmpi " .section .sun4v_pause_patch, \"ax\" \n" \ 258275e6a2fSmpi " .word 999b \n" \ 259275e6a2fSmpi " .word 0xb7802080 ! pause 128 \n" \ 260275e6a2fSmpi " .word 999b + 4 \n" \ 261275e6a2fSmpi " nop \n" \ 262275e6a2fSmpi " .word 999b + 8 \n" \ 263275e6a2fSmpi " nop \n" \ 264275e6a2fSmpi " .previous \n" \ 265275e6a2fSmpi " .section .sun4u_mtp_patch, \"ax\" \n" \ 266275e6a2fSmpi " .word 999b \n" \ 267275e6a2fSmpi " .word 0x81b01060 ! sleep \n" \ 268275e6a2fSmpi " .word 999b + 4 \n" \ 269275e6a2fSmpi " nop \n" \ 270275e6a2fSmpi " .word 999b + 8 \n" \ 271275e6a2fSmpi " nop \n" \ 272275e6a2fSmpi " .previous \n" \ 273275e6a2fSmpi : : : "memory"); \ 274275e6a2fSmpi } while (0) 2759f35e288Ssebastia 276de24d0bcSjason /* 2775c9ee8d9Smiod * Arguments to clockintr_dispatch encapsulate the 2785c9ee8d9Smiod * previous machine state in an opaque clockframe. 279de24d0bcSjason */ 280de24d0bcSjason struct clockframe { 2811c00236eSmiod struct trapframe t; 28279a31abaSkettenis int saved_intr_level; 283de24d0bcSjason }; 284de24d0bcSjason 285de24d0bcSjason #define CLKF_USERMODE(framep) (((framep)->t.tf_tstate & TSTATE_PRIV) == 0) 286de24d0bcSjason #define CLKF_PC(framep) ((framep)->t.tf_pc) 28779a31abaSkettenis #define CLKF_INTR(framep) ((framep)->saved_intr_level != 0) 288de24d0bcSjason 289ebe39446Skettenis extern void (*cpu_start_clock)(void); 290ebe39446Skettenis 29163415629Skettenis #define aston(p) ((p)->p_md.md_astpending = 1) 292de24d0bcSjason 293de24d0bcSjason /* 294de24d0bcSjason * Preempt the current process if in interrupt from user mode, 295de24d0bcSjason * or after the current trap/syscall if in system mode. 296de24d0bcSjason */ 29763415629Skettenis extern void need_resched(struct cpu_info *); 2982c9d4ccbSart #define clear_resched(ci) (ci)->ci_want_resched = 0 299de24d0bcSjason 300de24d0bcSjason /* 3014516c5b4Smiod * This is used during profiling to integrate system time. 3024516c5b4Smiod */ 3034516c5b4Smiod #define PROC_PC(p) ((p)->p_md.md_tf->tf_pc) 3041eaa59e7Sguenther #define PROC_STACK(p) ((p)->p_md.md_tf->tf_out[6] + (2048-1)) /* BIAS */ 3054516c5b4Smiod 3064516c5b4Smiod /* 307de24d0bcSjason * Give a profiling tick to the current process when the user profiling 308de24d0bcSjason * buffer pages are invalid. On the sparc, request an ast to send us 309de24d0bcSjason * through trap(), marking the proc as needing a profiling tick. 310de24d0bcSjason */ 31163415629Skettenis #define need_proftick(p) aston(p) 312de24d0bcSjason 31363415629Skettenis void signotify(struct proc *); 314de24d0bcSjason 315023c9b86Skettenis /* cpu.c */ 316023c9b86Skettenis int cpu_myid(void); 317de24d0bcSjason /* machdep.c */ 318c4071fd1Smillert void dumpconf(void); 319c4071fd1Smillert caddr_t reserve_dumppages(caddr_t); 320de24d0bcSjason /* clock.c */ 321de24d0bcSjason struct timeval; 322c4071fd1Smillert int clockintr(void *);/* level 10 (clock) interrupt code */ 323de24d0bcSjason /* locore.s */ 3241c00236eSmiod struct fpstate; 3251c00236eSmiod void savefpstate(struct fpstate *); 3261c00236eSmiod void loadfpstate(struct fpstate *); 32740ff1d9fSkettenis void clearfpstate(void); 328c4071fd1Smillert u_int64_t probeget(paddr_t, int, int); 3292df76cc2Sguenther #define write_all_windows() __asm volatile("flushw" : : ) 3300187012aSkettenis void write_user_windows(void); 331c4071fd1Smillert void proc_trampoline(void); 332de24d0bcSjason struct pcb; 333c4071fd1Smillert void snapshot(struct pcb *); 334c4071fd1Smillert struct frame *getfp(void); 335c4071fd1Smillert void switchtoctx(int); 336de24d0bcSjason /* trap.c */ 3379e074385Smiod void pmap_unuse_final(struct proc *); 338c4071fd1Smillert int rwindow_save(struct proc *); 33940ff1d9fSkettenis /* vm_machdep.c */ 3402e2bde79Skettenis void fpusave_cpu(struct cpu_info *, int); 3412e2bde79Skettenis void fpusave_proc(struct proc *, int); 342de24d0bcSjason /* fb.c */ 343c4071fd1Smillert void fb_unblank(void); 3441c00236eSmiod /* ltc.c */ 3451c00236eSmiod void ltc_full_blast(void); 3468e7461c8Srobert /* tda.c */ 3478e7461c8Srobert void tda_full_blast(void); 348de24d0bcSjason /* emul.c */ 3491c00236eSmiod int emul_qf(int32_t, struct proc *, union sigval, struct trapframe *); 3501c00236eSmiod int emul_popc(int32_t, struct proc *, union sigval, struct trapframe *); 351de24d0bcSjason 352de24d0bcSjason /* 353de24d0bcSjason * 354de24d0bcSjason * The SPARC has a Trap Base Register (TBR) which holds the upper 20 bits 355de24d0bcSjason * of the trap vector table. The next eight bits are supplied by the 356de24d0bcSjason * hardware when the trap occurs, and the bottom four bits are always 357de24d0bcSjason * zero (so that we can shove up to 16 bytes of executable code---exactly 358de24d0bcSjason * four instructions---into each trap vector). 359de24d0bcSjason * 360de24d0bcSjason * The hardware allocates half the trap vectors to hardware and half to 361de24d0bcSjason * software. 362de24d0bcSjason * 363de24d0bcSjason * Traps have priorities assigned (lower number => higher priority). 364de24d0bcSjason */ 365de24d0bcSjason 366de24d0bcSjason struct trapvec { 367de24d0bcSjason int tv_instr[8]; /* the eight instructions */ 368de24d0bcSjason }; 36947e9681cSkettenis extern struct trapvec trapbase[]; /* the 256 vectors */ 370de24d0bcSjason 3719f31f4f7Sjason struct blink_led { 3729f31f4f7Sjason void (*bl_func)(void *, int); 3739f31f4f7Sjason void *bl_arg; 3749f31f4f7Sjason SLIST_ENTRY(blink_led) bl_next; 3759f31f4f7Sjason }; 3769f31f4f7Sjason 3779f31f4f7Sjason extern void blink_led_register(struct blink_led *); 3789f31f4f7Sjason 3794b1c87d1Skettenis #ifdef MULTIPROCESSOR 3804b1c87d1Skettenis #include <sys/mplock.h> 3814b1c87d1Skettenis #endif 3824b1c87d1Skettenis 383de24d0bcSjason #endif /* _KERNEL */ 3842fa72412Spirofti #endif /* _MACHINE_CPU_H_ */ 385