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
cpu_rnd_messybits(void)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