1 /* $NetBSD: cpu.h,v 1.16 2024/08/04 08:16:25 skrll Exp $ */ 2 3 /*- 4 * Copyright (c) 2014 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Matt Thomas of 3am Software Foundry. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #ifndef _RISCV_CPU_H_ 33 #define _RISCV_CPU_H_ 34 35 #if defined(_KERNEL) || defined(_KMEMUSER) 36 37 struct clockframe { 38 vaddr_t cf_epc; 39 register_t cf_status; 40 int cf_intr_depth; 41 }; 42 43 #define CLKF_USERMODE(cf) (((cf)->cf_status & SR_SPP) == 0) 44 #define CLKF_PC(cf) ((cf)->cf_epc) 45 #define CLKF_INTR(cf) ((cf)->cf_intr_depth > 1) 46 47 #include <sys/cpu_data.h> 48 #include <sys/device_if.h> 49 #include <sys/evcnt.h> 50 #include <sys/intr.h> 51 52 struct cpu_info { 53 struct cpu_data ci_data; 54 device_t ci_dev; 55 cpuid_t ci_cpuid; 56 struct lwp *ci_curlwp; 57 struct lwp *ci_onproc; /* current user LWP / kthread */ 58 struct lwp *ci_softlwps[SOFTINT_COUNT]; 59 struct trapframe *ci_ddb_regs; 60 61 uint64_t ci_lastintr; 62 uint64_t ci_lastintr_scheduled; 63 struct evcnt ci_ev_timer; 64 struct evcnt ci_ev_timer_missed; 65 66 u_long ci_cpu_freq; /* CPU frequency */ 67 int ci_mtx_oldspl; 68 int ci_mtx_count; 69 int ci_cpl; 70 volatile u_int ci_intr_depth; 71 72 int ci_want_resched __aligned(COHERENCY_UNIT); 73 u_int ci_softints; 74 75 tlb_asid_t ci_pmap_asid_cur; 76 77 union pmap_segtab *ci_pmap_user_segtab; 78 #ifdef _LP64 79 union pmap_segtab *ci_pmap_user_seg0tab; 80 #endif 81 82 struct evcnt ci_ev_fpu_saves; 83 struct evcnt ci_ev_fpu_loads; 84 struct evcnt ci_ev_fpu_reenables; 85 86 struct pmap_tlb_info *ci_tlb_info; 87 88 #ifdef MULTIPROCESSOR 89 volatile u_long ci_flags; 90 #define CPUF_PRIMARY __BIT(0) /* CPU is primary CPU */ 91 #define CPUF_PRESENT __BIT(1) /* CPU is present */ 92 #define CPUF_RUNNING __BIT(2) /* CPU is running */ 93 #define CPUF_PAUSED __BIT(3) /* CPU is paused */ 94 95 void *ci_intcsoftc; 96 volatile u_long ci_request_ipis; 97 /* bitmask of IPIs requested */ 98 u_long ci_active_ipis; /* bitmask of IPIs being serviced */ 99 100 struct evcnt ci_evcnt_all_ipis; /* aggregated IPI counter */ 101 struct evcnt ci_evcnt_per_ipi[NIPIS]; /* individual IPI counters */ 102 struct evcnt ci_evcnt_synci_onproc_rqst; 103 struct evcnt ci_evcnt_synci_deferred_rqst; 104 struct evcnt ci_evcnt_synci_ipi_rqst; 105 106 kcpuset_t *ci_shootdowncpus; 107 kcpuset_t *ci_multicastcpus; 108 kcpuset_t *ci_watchcpus; 109 kcpuset_t *ci_ddbcpus; 110 #endif 111 112 #if defined(GPROF) && defined(MULTIPROCESSOR) 113 struct gmonparam *ci_gmon; /* MI per-cpu GPROF */ 114 #endif 115 }; 116 117 #endif /* _KERNEL || _KMEMUSER */ 118 119 #ifdef _KERNEL 120 121 extern struct cpu_info cpu_info_store[]; 122 extern cpuid_t cpu_bphartid; 123 extern u_int cpu_hartindex[]; 124 125 #ifdef MULTIPROCESSOR 126 127 void cpu_hatch(struct cpu_info *, unsigned long); 128 129 void cpu_init_secondary_processor(u_int); 130 void cpu_boot_secondary_processors(void); 131 void cpu_mpstart(void); 132 bool cpu_hatched_p(u_int); 133 134 void cpu_clr_mbox(u_int); 135 void cpu_set_hatched(u_int); 136 137 138 void cpu_halt(void); 139 void cpu_halt_others(void); 140 bool cpu_is_paused(cpuid_t); 141 void cpu_pause(void); 142 void cpu_pause_others(void); 143 void cpu_resume(cpuid_t); 144 void cpu_resume_others(void); 145 void cpu_debug_dump(void); 146 147 extern kcpuset_t *cpus_running; 148 extern kcpuset_t *cpus_hatched; 149 extern kcpuset_t *cpus_paused; 150 extern kcpuset_t *cpus_resumed; 151 extern kcpuset_t *cpus_halted; 152 153 /* 154 * definitions of cpu-dependent requirements 155 * referenced in generic code 156 */ 157 158 /* 159 * Send an inter-processor interrupt to each other CPU (excludes curcpu()) 160 */ 161 void cpu_broadcast_ipi(int); 162 163 /* 164 * Send an inter-processor interrupt to CPUs in kcpuset (excludes curcpu()) 165 */ 166 void cpu_multicast_ipi(const kcpuset_t *, int); 167 168 /* 169 * Send an inter-processor interrupt to another CPU. 170 */ 171 int cpu_send_ipi(struct cpu_info *, int); 172 173 #endif 174 175 struct lwp; 176 static inline struct cpu_info *lwp_getcpu(struct lwp *); 177 178 register struct lwp *riscv_curlwp __asm("tp"); 179 #define curlwp riscv_curlwp 180 #define curcpu() lwp_getcpu(curlwp) 181 #define curpcb ((struct pcb *)lwp_getpcb(curlwp)) 182 183 static inline cpuid_t 184 cpu_number(void) 185 { 186 #ifdef MULTIPROCESSOR 187 return curcpu()->ci_cpuid; 188 #else 189 return 0; 190 #endif 191 } 192 193 void cpu_proc_fork(struct proc *, struct proc *); 194 void cpu_signotify(struct lwp *); 195 void cpu_need_proftick(struct lwp *l); 196 void cpu_boot_secondary_processors(void); 197 198 #define CPU_INFO_ITERATOR cpuid_t 199 #ifdef MULTIPROCESSOR 200 #define CPU_IS_PRIMARY(ci) ((ci)->ci_flags & CPUF_PRIMARY) 201 #define CPU_INFO_FOREACH(cii, ci) \ 202 cii = 0, ci = &cpu_info_store[0]; \ 203 ci != NULL; \ 204 cii++, ncpu ? (ci = cpu_infos[cii]) \ 205 : (ci = NULL) 206 #else 207 #define CPU_IS_PRIMARY(ci) true 208 #define CPU_INFO_FOREACH(cii, ci) \ 209 (cii) = 0, (ci) = curcpu(); (cii) == 0; (cii)++ 210 #endif 211 212 #define CPU_INFO_CURPMAP(ci) (curlwp->l_proc->p_vmspace->vm_map.pmap) 213 214 static inline void 215 cpu_dosoftints(void) 216 { 217 extern void dosoftints(void); 218 struct cpu_info * const ci = curcpu(); 219 if (ci->ci_intr_depth == 0 220 && (ci->ci_data.cpu_softints >> ci->ci_cpl) > 0) 221 dosoftints(); 222 } 223 224 static inline bool 225 cpu_intr_p(void) 226 { 227 return curcpu()->ci_intr_depth > 0; 228 } 229 230 #define LWP_PC(l) cpu_lwp_pc(l) 231 232 vaddr_t cpu_lwp_pc(struct lwp *); 233 234 static inline void 235 cpu_idle(void) 236 { 237 asm volatile("wfi" ::: "memory"); 238 } 239 240 #endif /* _KERNEL */ 241 242 #endif /* _RISCV_CPU_H_ */ 243