1 /* $NetBSD: cpu.h,v 1.13 2023/07/29 06:59:47 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 #define CPUF_USERPMAP __BIT(4) /* CPU has a user pmap activated */ 95 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[]; 122 extern struct cpu_info cpu_info_store[]; 123 124 125 #ifdef MULTIPROCESSOR 126 extern u_int riscv_cpu_max; 127 extern cpuid_t cpu_hartid[]; 128 129 void cpu_hatch(struct cpu_info *); 130 131 void cpu_init_secondary_processor(int); 132 void cpu_boot_secondary_processors(void); 133 void cpu_mpstart(void); 134 bool cpu_hatched_p(u_int); 135 136 void cpu_clr_mbox(int); 137 void cpu_set_hatched(int); 138 139 140 void cpu_halt(void); 141 void cpu_halt_others(void); 142 bool cpu_is_paused(cpuid_t); 143 void cpu_pause(void); 144 void cpu_pause_others(void); 145 void cpu_resume(cpuid_t); 146 void cpu_resume_others(void); 147 void cpu_debug_dump(void); 148 149 extern kcpuset_t *cpus_running; 150 extern kcpuset_t *cpus_hatched; 151 extern kcpuset_t *cpus_paused; 152 extern kcpuset_t *cpus_resumed; 153 extern kcpuset_t *cpus_halted; 154 155 /* 156 * definitions of cpu-dependent requirements 157 * referenced in generic code 158 */ 159 160 /* 161 * Send an inter-processor interrupt to each other CPU (excludes curcpu()) 162 */ 163 void cpu_broadcast_ipi(int); 164 165 /* 166 * Send an inter-processor interrupt to CPUs in kcpuset (excludes curcpu()) 167 */ 168 void cpu_multicast_ipi(const kcpuset_t *, int); 169 170 /* 171 * Send an inter-processor interrupt to another CPU. 172 */ 173 int cpu_send_ipi(struct cpu_info *, int); 174 175 #endif 176 177 struct lwp; 178 static inline struct cpu_info *lwp_getcpu(struct lwp *); 179 180 register struct lwp *riscv_curlwp __asm("tp"); 181 #define curlwp riscv_curlwp 182 #define curcpu() lwp_getcpu(curlwp) 183 #define curpcb ((struct pcb *)lwp_getpcb(curlwp)) 184 185 static inline cpuid_t 186 cpu_number(void) 187 { 188 #ifdef MULTIPROCESSOR 189 return curcpu()->ci_cpuid; 190 #else 191 return 0; 192 #endif 193 } 194 195 void cpu_proc_fork(struct proc *, struct proc *); 196 void cpu_signotify(struct lwp *); 197 void cpu_need_proftick(struct lwp *l); 198 void cpu_boot_secondary_processors(void); 199 200 #define CPU_INFO_ITERATOR cpuid_t 201 #ifdef MULTIPROCESSOR 202 #define CPU_IS_PRIMARY(ci) ((ci)->ci_flags & CPUF_PRIMARY) 203 #define CPU_INFO_FOREACH(cii, ci) \ 204 cii = 0, ci = &cpu_info_store[0]; \ 205 ci != NULL; \ 206 cii++, ncpu ? (ci = cpu_infos[cii]) \ 207 : (ci = NULL) 208 #else 209 #define CPU_IS_PRIMARY(ci) true 210 #define CPU_INFO_FOREACH(cii, ci) \ 211 (cii) = 0, (ci) = curcpu(); (cii) == 0; (cii)++ 212 #endif 213 214 #define CPU_INFO_CURPMAP(ci) (curlwp->l_proc->p_vmspace->vm_map.pmap) 215 216 static inline void 217 cpu_dosoftints(void) 218 { 219 extern void dosoftints(void); 220 struct cpu_info * const ci = curcpu(); 221 if (ci->ci_intr_depth == 0 222 && (ci->ci_data.cpu_softints >> ci->ci_cpl) > 0) 223 dosoftints(); 224 } 225 226 static inline bool 227 cpu_intr_p(void) 228 { 229 return curcpu()->ci_intr_depth > 0; 230 } 231 232 #define LWP_PC(l) cpu_lwp_pc(l) 233 234 vaddr_t cpu_lwp_pc(struct lwp *); 235 236 static inline void 237 cpu_idle(void) 238 { 239 asm volatile("wfi" ::: "memory"); 240 } 241 242 #endif /* _KERNEL */ 243 244 #endif /* _RISCV_CPU_H_ */ 245