1*e8331b74Skettenis /* $OpenBSD: cpu.h,v 1.50 2024/07/24 21:24:18 kettenis Exp $ */ 2f24071e5Spatrick /* 3f24071e5Spatrick * Copyright (c) 2016 Dale Rahn <drahn@dalerahn.com> 4f24071e5Spatrick * 5f24071e5Spatrick * Permission to use, copy, modify, and distribute this software for any 6f24071e5Spatrick * purpose with or without fee is hereby granted, provided that the above 7f24071e5Spatrick * copyright notice and this permission notice appear in all copies. 8f24071e5Spatrick * 9f24071e5Spatrick * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10f24071e5Spatrick * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11f24071e5Spatrick * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12f24071e5Spatrick * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13f24071e5Spatrick * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14f24071e5Spatrick * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15f24071e5Spatrick * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16f24071e5Spatrick */ 17823a97b9Skettenis 18f24071e5Spatrick #ifndef _MACHINE_CPU_H_ 19f24071e5Spatrick #define _MACHINE_CPU_H_ 20f24071e5Spatrick 21f24071e5Spatrick /* 22f24071e5Spatrick * User-visible definitions 23f24071e5Spatrick */ 24f24071e5Spatrick 25943434f8Skettenis /* 26943434f8Skettenis * CTL_MACHDEP definitions. 27943434f8Skettenis */ 28f8c21047Skettenis #define CPU_COMPATIBLE 1 /* compatible property */ 29d335af93Skettenis #define CPU_ID_AA64ISAR0 2 30d335af93Skettenis #define CPU_ID_AA64ISAR1 3 31c7654cd6Skettenis #define CPU_ID_AA64ISAR2 4 32c7654cd6Skettenis #define CPU_ID_AA64MMFR0 5 33c7654cd6Skettenis #define CPU_ID_AA64MMFR1 6 34c7654cd6Skettenis #define CPU_ID_AA64MMFR2 7 35c7654cd6Skettenis #define CPU_ID_AA64PFR0 8 36c7654cd6Skettenis #define CPU_ID_AA64PFR1 9 37c7654cd6Skettenis #define CPU_ID_AA64SMFR0 10 38c7654cd6Skettenis #define CPU_ID_AA64ZFR0 11 39ec9fe3b7Stobhe #define CPU_LIDACTION 12 40ec9fe3b7Stobhe #define CPU_MAXID 13 /* number of valid machdep ids */ 41f24071e5Spatrick 42f24071e5Spatrick #define CTL_MACHDEP_NAMES { \ 43943434f8Skettenis { 0, 0 }, \ 44943434f8Skettenis { "compatible", CTLTYPE_STRING }, \ 45d335af93Skettenis { "id_aa64isar0", CTLTYPE_QUAD }, \ 46d335af93Skettenis { "id_aa64isar1", CTLTYPE_QUAD }, \ 47c7654cd6Skettenis { "id_aa64isar2", CTLTYPE_QUAD }, \ 48c7654cd6Skettenis { "id_aa64mmfr0", CTLTYPE_QUAD }, \ 49c7654cd6Skettenis { "id_aa64mmfr1", CTLTYPE_QUAD }, \ 50c7654cd6Skettenis { "id_aa64mmfr2", CTLTYPE_QUAD }, \ 51c7654cd6Skettenis { "id_aa64pfr0", CTLTYPE_QUAD }, \ 52c7654cd6Skettenis { "id_aa64pfr1", CTLTYPE_QUAD }, \ 53c7654cd6Skettenis { "id_aa64smfr0", CTLTYPE_QUAD }, \ 54c7654cd6Skettenis { "id_aa64zfr0", CTLTYPE_QUAD }, \ 556dd70ce4Spatrick { "lidaction", CTLTYPE_INT }, \ 56f24071e5Spatrick } 57f24071e5Spatrick 58f24071e5Spatrick #ifdef _KERNEL 59f24071e5Spatrick 60f24071e5Spatrick /* 61f24071e5Spatrick * Kernel-only definitions 62f24071e5Spatrick */ 63f24071e5Spatrick 644171e492Skettenis extern uint64_t cpu_id_aa64isar0; 654171e492Skettenis extern uint64_t cpu_id_aa64isar1; 66aeddddc8Skettenis extern uint64_t cpu_id_aa64isar2; 67*e8331b74Skettenis extern uint64_t cpu_id_aa64mmfr0; 68*e8331b74Skettenis extern uint64_t cpu_id_aa64mmfr1; 69*e8331b74Skettenis extern uint64_t cpu_id_aa64mmfr2; 704171e492Skettenis extern uint64_t cpu_id_aa64pfr0; 714171e492Skettenis extern uint64_t cpu_id_aa64pfr1; 724171e492Skettenis 73aeddddc8Skettenis void cpu_identify_cleanup(void); 74aeddddc8Skettenis 75f24071e5Spatrick #include <machine/intr.h> 76f24071e5Spatrick #include <machine/frame.h> 77f24071e5Spatrick #include <machine/armreg.h> 78f24071e5Spatrick 79f24071e5Spatrick /* All the CLKF_* macros take a struct clockframe * as an argument. */ 80f24071e5Spatrick 81f24071e5Spatrick #define clockframe trapframe 82f24071e5Spatrick /* 83f24071e5Spatrick * CLKF_USERMODE: Return TRUE/FALSE (1/0) depending on whether the 84f24071e5Spatrick * frame came from USR mode or not. 85f24071e5Spatrick */ 86f24071e5Spatrick #define CLKF_USERMODE(frame) ((frame->tf_elr & (1ul << 63)) == 0) 87f24071e5Spatrick 88f24071e5Spatrick /* 89f24071e5Spatrick * CLKF_INTR: True if we took the interrupt from inside another 90f24071e5Spatrick * interrupt handler. 91f24071e5Spatrick */ 92f24071e5Spatrick #define CLKF_INTR(frame) (curcpu()->ci_idepth > 1) 93f24071e5Spatrick 94f24071e5Spatrick /* 95f24071e5Spatrick * CLKF_PC: Extract the program counter from a clockframe 96f24071e5Spatrick */ 97f24071e5Spatrick #define CLKF_PC(frame) (frame->tf_elr) 98f24071e5Spatrick 99f24071e5Spatrick /* 100f24071e5Spatrick * PROC_PC: Find out the program counter for the given process. 101f24071e5Spatrick */ 102f24071e5Spatrick #define PROC_PC(p) ((p)->p_addr->u_pcb.pcb_tf->tf_elr) 103f24071e5Spatrick #define PROC_STACK(p) ((p)->p_addr->u_pcb.pcb_tf->tf_sp) 104f24071e5Spatrick 105f24071e5Spatrick /* 106f24071e5Spatrick * Per-CPU information. For now we assume one CPU. 107f24071e5Spatrick */ 108f24071e5Spatrick 109e3d8572aScheloha #include <sys/clockintr.h> 110f24071e5Spatrick #include <sys/device.h> 111f24071e5Spatrick #include <sys/sched.h> 1121a1181a9Sjsg #include <sys/srp.h> 11382673a18Smpi #include <uvm/uvm_percpu.h> 114823a97b9Skettenis 115f24071e5Spatrick struct cpu_info { 116f24071e5Spatrick struct device *ci_dev; /* Device corresponding to this CPU */ 117f24071e5Spatrick struct cpu_info *ci_next; 118f24071e5Spatrick struct schedstate_percpu ci_schedstate; /* scheduler state */ 119f24071e5Spatrick 12070943fa6Skettenis u_int32_t ci_cpuid; 12170943fa6Skettenis uint64_t ci_mpidr; 122a84df9b3Skettenis uint64_t ci_midr; 12319666448Skettenis u_int ci_acpi_proc_id; 12470943fa6Skettenis int ci_node; 12570943fa6Skettenis struct cpu_info *ci_self; 12670943fa6Skettenis 127f1f10f33Skettenis #define __HAVE_CPU_TOPOLOGY 128f1f10f33Skettenis u_int32_t ci_smt_id; 129f1f10f33Skettenis u_int32_t ci_core_id; 130f1f10f33Skettenis u_int32_t ci_pkg_id; 131f1f10f33Skettenis 132f24071e5Spatrick struct proc *ci_curproc; 1334002e08dSkettenis struct pcb *ci_curpcb; 134f24071e5Spatrick struct pmap *ci_curpm; 135f24071e5Spatrick u_int32_t ci_randseed; 136f24071e5Spatrick 137f24071e5Spatrick u_int32_t ci_ctrl; /* The CPU control register */ 138f24071e5Spatrick 13916569a75Spatrick u_int64_t ci_trampoline_vectors; 14016569a75Spatrick 141f24071e5Spatrick uint32_t ci_cpl; 142f24071e5Spatrick uint32_t ci_ipending; 143f24071e5Spatrick uint32_t ci_idepth; 144f24071e5Spatrick #ifdef DIAGNOSTIC 145f24071e5Spatrick int ci_mutex_level; 146f24071e5Spatrick #endif 147f24071e5Spatrick int ci_want_resched; 148f24071e5Spatrick 149d855ec95Skettenis void (*ci_flush_bp)(void); 1504ef70b62Skettenis void (*ci_serror)(void); 151d855ec95Skettenis 1524002e08dSkettenis uint64_t ci_ttbr1; 1534002e08dSkettenis vaddr_t ci_el1_stkend; 1544002e08dSkettenis 15507eca602Skettenis uint32_t ci_psci_idle_latency; 15607eca602Skettenis uint32_t ci_psci_idle_param; 1575f4ad52dSkettenis uint32_t ci_psci_suspend_param; 1585f4ad52dSkettenis 15927d9c428Skettenis struct opp_table *ci_opp_table; 16027d9c428Skettenis volatile int ci_opp_idx; 16103e57840Skettenis volatile int ci_opp_max; 16227d9c428Skettenis uint32_t ci_cpu_supply; 16327d9c428Skettenis 164c4936e80Skettenis u_long ci_prev_sleep; 165c4936e80Skettenis u_long ci_last_itime; 166c4936e80Skettenis 1677a7b3facSkettenis #ifdef MULTIPROCESSOR 1687a7b3facSkettenis struct srp_hazard ci_srp_hazards[SRP_HAZARD_NUM]; 16982673a18Smpi #define __HAVE_UVM_PERCPU 17082673a18Smpi struct uvm_pmr_cache ci_uvm; 17170943fa6Skettenis volatile int ci_flags; 172755135dbSkettenis 173755135dbSkettenis volatile int ci_ddb_paused; 174755135dbSkettenis #define CI_DDB_RUNNING 0 175755135dbSkettenis #define CI_DDB_SHOULDSTOP 1 176755135dbSkettenis #define CI_DDB_STOPPED 2 177755135dbSkettenis #define CI_DDB_ENTERDDB 3 178755135dbSkettenis #define CI_DDB_INDDB 4 179755135dbSkettenis 1807a7b3facSkettenis #endif 1817a7b3facSkettenis 182f24071e5Spatrick #ifdef GPROF 183f24071e5Spatrick struct gmonparam *ci_gmon; 1841d970828Scheloha struct clockintr ci_gmonclock; 185f24071e5Spatrick #endif 186c737cf90Scheloha struct clockqueue ci_queue; 1871a4a9ab2Scheloha char ci_panicbuf[512]; 188f24071e5Spatrick }; 189f24071e5Spatrick 19070943fa6Skettenis #define CPUF_PRIMARY (1<<0) 19170943fa6Skettenis #define CPUF_AP (1<<1) 19270943fa6Skettenis #define CPUF_IDENTIFY (1<<2) 19370943fa6Skettenis #define CPUF_IDENTIFIED (1<<3) 19470943fa6Skettenis #define CPUF_PRESENT (1<<4) 19570943fa6Skettenis #define CPUF_GO (1<<5) 19670943fa6Skettenis #define CPUF_RUNNING (1<<6) 19770943fa6Skettenis 198f24071e5Spatrick static inline struct cpu_info * 199f24071e5Spatrick curcpu(void) 200f24071e5Spatrick { 201f24071e5Spatrick struct cpu_info *__ci = NULL; 202dd81489dSjsg __asm volatile("mrs %0, tpidr_el1" : "=r" (__ci)); 203f24071e5Spatrick return (__ci); 204f24071e5Spatrick } 205f24071e5Spatrick 206f24071e5Spatrick extern struct cpu_info cpu_info_primary; 207f24071e5Spatrick extern struct cpu_info *cpu_info_list; 208f24071e5Spatrick 209f24071e5Spatrick #ifndef MULTIPROCESSOR 210f24071e5Spatrick #define cpu_number() 0 211f24071e5Spatrick #define CPU_IS_PRIMARY(ci) 1 212d73de46fSkettenis #define CPU_IS_RUNNING(ci) 1 213f24071e5Spatrick #define CPU_INFO_ITERATOR int 214f24071e5Spatrick #define CPU_INFO_FOREACH(cii, ci) \ 215f24071e5Spatrick for (cii = 0, ci = curcpu(); ci != NULL; ci = NULL) 216f24071e5Spatrick #define CPU_INFO_UNIT(ci) 0 217f24071e5Spatrick #define MAXCPUS 1 218f24071e5Spatrick #define cpu_unidle(ci) 219f24071e5Spatrick #else 220f24071e5Spatrick #define cpu_number() (curcpu()->ci_cpuid) 221f24071e5Spatrick #define CPU_IS_PRIMARY(ci) ((ci) == &cpu_info_primary) 222d73de46fSkettenis #define CPU_IS_RUNNING(ci) ((ci)->ci_flags & CPUF_RUNNING) 223f24071e5Spatrick #define CPU_INFO_ITERATOR int 224f24071e5Spatrick #define CPU_INFO_FOREACH(cii, ci) for (cii = 0, ci = cpu_info_list; \ 225f24071e5Spatrick ci != NULL; ci = ci->ci_next) 226f24071e5Spatrick #define CPU_INFO_UNIT(ci) ((ci)->ci_dev ? (ci)->ci_dev->dv_unit : 0) 227d8d35dc4Skettenis #define MAXCPUS 256 228f24071e5Spatrick 229f24071e5Spatrick extern struct cpu_info *cpu_info[MAXCPUS]; 230f24071e5Spatrick 231f24071e5Spatrick void cpu_boot_secondary_processors(void); 232f24071e5Spatrick #endif /* !MULTIPROCESSOR */ 233f24071e5Spatrick 234a6f94011Skettenis #define CPU_BUSY_CYCLE() __asm volatile("yield" : : : "memory") 235f24071e5Spatrick 236f24071e5Spatrick #define curpcb curcpu()->ci_curpcb 237f24071e5Spatrick 2388274f701Snaddy static inline unsigned int 2398274f701Snaddy cpu_rnd_messybits(void) 2408274f701Snaddy { 2418274f701Snaddy uint64_t val, rval; 2428274f701Snaddy 2438274f701Snaddy __asm volatile("mrs %0, CNTVCT_EL0; rbit %1, %0;" 2448274f701Snaddy : "=r" (val), "=r" (rval)); 2458274f701Snaddy 2468274f701Snaddy return (val ^ rval); 2478274f701Snaddy } 24801802d2cSdlg 249f24071e5Spatrick /* 250f24071e5Spatrick * Scheduling glue 251f24071e5Spatrick */ 252f24071e5Spatrick #define aston(p) ((p)->p_md.md_astpending = 1) 253f24071e5Spatrick #define setsoftast() aston(curcpu()->ci_curproc) 254f24071e5Spatrick 255f24071e5Spatrick /* 256f24071e5Spatrick * Notify the current process (p) that it has a signal pending, 257f24071e5Spatrick * process as soon as possible. 258f24071e5Spatrick */ 259f24071e5Spatrick 26070943fa6Skettenis #ifdef MULTIPROCESSOR 26170943fa6Skettenis void cpu_unidle(struct cpu_info *ci); 26270943fa6Skettenis #define signotify(p) (aston(p), cpu_unidle((p)->p_cpu)) 26370943fa6Skettenis void cpu_kick(struct cpu_info *); 26470943fa6Skettenis #else 26570943fa6Skettenis #define cpu_kick(ci) 26670943fa6Skettenis #define cpu_unidle(ci) 267f24071e5Spatrick #define signotify(p) setsoftast() 26870943fa6Skettenis #endif 269f24071e5Spatrick 270f24071e5Spatrick /* 271f24071e5Spatrick * Preempt the current process if in interrupt from user mode, 272f24071e5Spatrick * or after the current trap/syscall if in system mode. 273f24071e5Spatrick */ 274f24071e5Spatrick void need_resched(struct cpu_info *); 275f24071e5Spatrick #define clear_resched(ci) ((ci)->ci_want_resched = 0) 276f24071e5Spatrick 277f24071e5Spatrick /* 278f24071e5Spatrick * Give a profiling tick to the current process when the user profiling 279f24071e5Spatrick * buffer pages are invalid. On the i386, request an ast to send us 280f24071e5Spatrick * through trap(), marking the proc as needing a profiling tick. 281f24071e5Spatrick */ 282f24071e5Spatrick #define need_proftick(p) aston(p) 283f24071e5Spatrick 284f24071e5Spatrick // asm code to start new kernel contexts. 285f24071e5Spatrick void proc_trampoline(void); 286f24071e5Spatrick 287f24071e5Spatrick /* 288f24071e5Spatrick * Random cruft 289f24071e5Spatrick */ 290f24071e5Spatrick void dumpconf(void); 291f24071e5Spatrick 292f24071e5Spatrick // syscall.c 293f24071e5Spatrick void svc_handler (trapframe_t *); 294f24071e5Spatrick 295f24071e5Spatrick // functions to manipulate interrupt state 296f24071e5Spatrick static __inline void 297f24071e5Spatrick restore_daif(uint32_t daif) 298f24071e5Spatrick { 299f24071e5Spatrick __asm volatile ("msr daif, %x0":: "r"(daif)); 300f24071e5Spatrick } 301f24071e5Spatrick 302f24071e5Spatrick static __inline void 303adc7c282Skettenis enable_irq_daif(void) 304f24071e5Spatrick { 305adc7c282Skettenis __asm volatile ("msr daifclr, #3"); 306f24071e5Spatrick } 307f24071e5Spatrick 308f24071e5Spatrick static __inline void 309adc7c282Skettenis disable_irq_daif(void) 310f24071e5Spatrick { 311adc7c282Skettenis __asm volatile ("msr daifset, #3"); 312f24071e5Spatrick } 313f24071e5Spatrick 314f24071e5Spatrick static __inline uint32_t 315adc7c282Skettenis disable_irq_daif_ret(void) 316f24071e5Spatrick { 317f24071e5Spatrick uint32_t daif; 318f24071e5Spatrick __asm volatile ("mrs %x0, daif": "=r"(daif)); 319adc7c282Skettenis __asm volatile ("msr daifset, #3"); 320f24071e5Spatrick return daif; 321f24071e5Spatrick } 322f24071e5Spatrick 323b5e76318Skettenis static inline void 324b5e76318Skettenis intr_enable(void) 325b5e76318Skettenis { 326b5e76318Skettenis enable_irq_daif(); 327b5e76318Skettenis } 328b5e76318Skettenis 329a6f94011Skettenis static inline u_long 330a6f94011Skettenis intr_disable(void) 331a6f94011Skettenis { 332a6f94011Skettenis return disable_irq_daif_ret(); 333a6f94011Skettenis } 334a6f94011Skettenis 335a6f94011Skettenis static inline void 336a6f94011Skettenis intr_restore(u_long daif) 337a6f94011Skettenis { 338a6f94011Skettenis restore_daif(daif); 339a6f94011Skettenis } 340a6f94011Skettenis 3414002e08dSkettenis void cpu_halt(void); 3424002e08dSkettenis int cpu_suspend_primary(void); 3434002e08dSkettenis void cpu_resume_secondary(struct cpu_info *); 34470943fa6Skettenis 345c4936e80Skettenis extern void (*cpu_idle_cycle_fcn)(void); 346c4936e80Skettenis extern void (*cpu_suspend_cycle_fcn)(void); 347c4936e80Skettenis 348c4936e80Skettenis void cpu_wfi(void); 349c4936e80Skettenis 350f24071e5Spatrick void delay (unsigned); 351f24071e5Spatrick #define DELAY(x) delay(x) 352f24071e5Spatrick 353f24071e5Spatrick #endif /* _KERNEL */ 354f24071e5Spatrick 355f24071e5Spatrick #ifdef MULTIPROCESSOR 356f24071e5Spatrick #include <sys/mplock.h> 357f24071e5Spatrick #endif /* MULTIPROCESSOR */ 358f24071e5Spatrick 359f24071e5Spatrick #endif /* !_MACHINE_CPU_H_ */ 360