1 /* $OpenBSD: cpu.h,v 1.148 2016/07/28 21:57:57 kettenis Exp $ */ 2 /* $NetBSD: cpu.h,v 1.35 1996/05/05 19:29:26 christos Exp $ */ 3 4 /*- 5 * Copyright (c) 1990 The Regents of the University of California. 6 * All rights reserved. 7 * 8 * This code is derived from software contributed to Berkeley by 9 * William Jolitz. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 * 35 * @(#)cpu.h 5.4 (Berkeley) 5/9/91 36 */ 37 38 #ifndef _MACHINE_CPU_H_ 39 #define _MACHINE_CPU_H_ 40 41 /* 42 * Definitions unique to i386 cpu support. 43 */ 44 #ifdef _KERNEL 45 #include <machine/frame.h> 46 #include <machine/psl.h> 47 #include <machine/segments.h> 48 #include <machine/intrdefs.h> 49 50 #ifdef MULTIPROCESSOR 51 #include <machine/i82489reg.h> 52 #include <machine/i82489var.h> 53 #endif 54 55 #endif /* _KERNEL */ 56 57 /* 58 * Arguments to hardclock, softclock and statclock 59 * encapsulate the previous machine state in an opaque 60 * clockframe; for now, use generic intrframe. 61 * 62 * XXX intrframe has a lot of gunk we don't need. 63 */ 64 #define clockframe intrframe 65 66 #include <sys/device.h> 67 #include <sys/sched.h> 68 #include <sys/sensors.h> 69 70 struct intrsource; 71 72 #ifdef _KERNEL 73 /* XXX stuff to move to cpuvar.h later */ 74 struct cpu_info { 75 struct device ci_dev; /* our device */ 76 struct cpu_info *ci_self; /* pointer to this structure */ 77 struct schedstate_percpu ci_schedstate; /* scheduler state */ 78 struct cpu_info *ci_next; /* next cpu */ 79 80 /* 81 * Public members. 82 */ 83 struct proc *ci_curproc; /* current owner of the processor */ 84 cpuid_t ci_cpuid; /* our CPU ID */ 85 u_int ci_apicid; /* our APIC ID */ 86 u_int ci_acpi_proc_id; 87 u_int32_t ci_randseed; 88 89 #if defined(MULTIPROCESSOR) 90 struct srp_hazard ci_srp_hazards[SRP_HAZARD_NUM]; 91 #endif 92 93 /* 94 * Private members. 95 */ 96 struct proc *ci_fpcurproc; /* current owner of the FPU */ 97 struct proc *ci_fpsaveproc; 98 int ci_fpsaving; /* save in progress */ 99 100 struct pcb *ci_curpcb; /* VA of current HW PCB */ 101 struct pcb *ci_idle_pcb; /* VA of current PCB */ 102 int ci_idle_tss_sel; /* TSS selector of idle PCB */ 103 struct pmap *ci_curpmap; 104 105 struct intrsource *ci_isources[MAX_INTR_SOURCES]; 106 u_int32_t ci_ipending; 107 int ci_ilevel; 108 int ci_idepth; 109 u_int32_t ci_imask[NIPL]; 110 u_int32_t ci_iunmask[NIPL]; 111 #ifdef DIAGNOSTIC 112 int ci_mutex_level; 113 #endif 114 115 paddr_t ci_idle_pcb_paddr; /* PA of idle PCB */ 116 volatile u_long ci_flags; /* flags; see below */ 117 u_int32_t ci_ipis; /* interprocessor interrupts pending */ 118 119 u_int32_t ci_level; 120 u_int32_t ci_vendor[4]; 121 u_int32_t ci_signature; /* X86 cpuid type */ 122 u_int32_t ci_family; /* extended cpuid family */ 123 u_int32_t ci_model; /* extended cpuid model */ 124 u_int32_t ci_feature_flags; /* X86 CPUID feature bits */ 125 u_int32_t ci_feature_sefflags_ebx;/* more CPUID feature bits */ 126 u_int32_t ci_feature_sefflags_ecx;/* more CPUID feature bits */ 127 u_int32_t ci_feature_tpmflags; /* thermal & power bits */ 128 u_int32_t cpu_class; /* CPU class */ 129 u_int32_t ci_cflushsz; /* clflush cache-line size */ 130 131 int ci_inatomic; 132 133 struct cpu_functions *ci_func; /* start/stop functions */ 134 void (*cpu_setup)(struct cpu_info *); /* proc-dependant init */ 135 136 struct device *ci_acpicpudev; 137 volatile u_int ci_mwait; 138 #define MWAIT_IN_IDLE 0x1 /* don't need IPI to wake */ 139 #define MWAIT_KEEP_IDLING 0x2 /* cleared by other cpus to wake me */ 140 #define MWAIT_ONLY 0x4 /* set if all idle states use mwait */ 141 #define MWAIT_IDLING (MWAIT_IN_IDLE | MWAIT_KEEP_IDLING) 142 143 int ci_want_resched; 144 145 union descriptor *ci_gdt; 146 147 volatile int ci_ddb_paused; /* paused due to other proc in ddb */ 148 #define CI_DDB_RUNNING 0 149 #define CI_DDB_SHOULDSTOP 1 150 #define CI_DDB_STOPPED 2 151 #define CI_DDB_ENTERDDB 3 152 #define CI_DDB_INDDB 4 153 154 struct ksensordev ci_sensordev; 155 struct ksensor ci_sensor; 156 #ifdef GPROF 157 struct gmonparam *ci_gmon; 158 #endif 159 }; 160 161 /* 162 * Processor flag notes: The "primary" CPU has certain MI-defined 163 * roles (mostly relating to hardclock handling); we distinguish 164 * betwen the processor which booted us, and the processor currently 165 * holding the "primary" role just to give us the flexibility later to 166 * change primaries should we be sufficiently twisted. 167 */ 168 169 #define CPUF_BSP 0x0001 /* CPU is the original BSP */ 170 #define CPUF_AP 0x0002 /* CPU is an AP */ 171 #define CPUF_SP 0x0004 /* CPU is only processor */ 172 #define CPUF_PRIMARY 0x0008 /* CPU is active primary processor */ 173 #define CPUF_APIC_CD 0x0010 /* CPU has apic configured */ 174 #define CPUF_CONST_TSC 0x0020 /* CPU has constant TSC */ 175 176 #define CPUF_PRESENT 0x1000 /* CPU is present */ 177 #define CPUF_RUNNING 0x2000 /* CPU is running */ 178 179 /* 180 * We statically allocate the CPU info for the primary CPU (or, 181 * the only CPU on uniprocessors), and the primary CPU is the 182 * first CPU on the CPU info list. 183 */ 184 extern struct cpu_info cpu_info_primary; 185 extern struct cpu_info *cpu_info_list; 186 187 #define CPU_INFO_ITERATOR int 188 #define CPU_INFO_FOREACH(cii, ci) for (cii = 0, ci = cpu_info_list; \ 189 ci != NULL; ci = ci->ci_next) 190 191 #define CPU_INFO_UNIT(ci) ((ci)->ci_dev.dv_unit) 192 193 #ifdef MULTIPROCESSOR 194 195 #define MAXCPUS 32 /* because we use a bitmask */ 196 197 #define CPU_STARTUP(_ci) ((_ci)->ci_func->start(_ci)) 198 #define CPU_STOP(_ci) ((_ci)->ci_func->stop(_ci)) 199 #define CPU_START_CLEANUP(_ci) ((_ci)->ci_func->cleanup(_ci)) 200 201 static struct cpu_info *curcpu(void); 202 203 __inline static struct cpu_info * 204 curcpu(void) 205 { 206 struct cpu_info *ci; 207 208 /* Can't include sys/param.h for offsetof() since it includes us */ 209 __asm volatile("movl %%fs:%1, %0" : 210 "=r" (ci) : "m" 211 (*(struct cpu_info * const *)&((struct cpu_info *)0)->ci_self)); 212 return ci; 213 } 214 #define cpu_number() (curcpu()->ci_cpuid) 215 216 #define CPU_IS_PRIMARY(ci) ((ci)->ci_flags & CPUF_PRIMARY) 217 218 extern struct cpu_info *cpu_info[MAXCPUS]; 219 220 extern void cpu_boot_secondary_processors(void); 221 extern void cpu_init_idle_pcbs(void); 222 223 void cpu_kick(struct cpu_info *); 224 void cpu_unidle(struct cpu_info *); 225 226 #define CPU_BUSY_CYCLE() __asm volatile("pause": : : "memory") 227 228 #else /* MULTIPROCESSOR */ 229 230 #define MAXCPUS 1 231 232 #define cpu_number() 0 233 #define curcpu() (&cpu_info_primary) 234 235 #define CPU_IS_PRIMARY(ci) 1 236 237 #define cpu_kick(ci) 238 #define cpu_unidle(ci) 239 240 #define CPU_BUSY_CYCLE() do {} while (0) 241 242 #endif 243 244 #define aston(p) ((p)->p_md.md_astpending = 1) 245 246 #define curpcb curcpu()->ci_curpcb 247 248 #define want_resched (curcpu()->ci_want_resched) 249 250 /* 251 * Preempt the current process if in interrupt from user mode, 252 * or after the current trap/syscall if in system mode. 253 */ 254 extern void need_resched(struct cpu_info *); 255 #define clear_resched(ci) (ci)->ci_want_resched = 0 256 257 #define CLKF_USERMODE(frame) USERMODE((frame)->if_cs, (frame)->if_eflags) 258 #define CLKF_PC(frame) ((frame)->if_eip) 259 #define CLKF_INTR(frame) (IDXSEL((frame)->if_cs) == GICODE_SEL) 260 261 /* 262 * This is used during profiling to integrate system time. 263 */ 264 #define PROC_PC(p) ((p)->p_md.md_regs->tf_eip) 265 #define PROC_STACK(p) ((p)->p_md.md_regs->tf_esp) 266 267 /* 268 * Give a profiling tick to the current process when the user profiling 269 * buffer pages are invalid. On the i386, request an ast to send us 270 * through trap(), marking the proc as needing a profiling tick. 271 */ 272 #define need_proftick(p) aston(p) 273 274 /* 275 * Notify the current process (p) that it has a signal pending, 276 * process as soon as possible. 277 */ 278 void signotify(struct proc *); 279 280 /* 281 * We need a machine-independent name for this. 282 */ 283 extern void (*delay_func)(int); 284 struct timeval; 285 286 #define DELAY(x) (*delay_func)(x) 287 #define delay(x) (*delay_func)(x) 288 289 /* 290 * High resolution clock support (Pentium only) 291 */ 292 void calibrate_cyclecounter(void); 293 294 /* 295 * pull in #defines for kinds of processors 296 */ 297 #include <machine/cputypes.h> 298 299 struct cpu_nocpuid_nameclass { 300 int cpu_vendor; 301 const char *cpu_vendorname; 302 const char *cpu_name; 303 int cpu_class; 304 void (*cpu_setup)(struct cpu_info *); 305 }; 306 307 struct cpu_cpuid_nameclass { 308 const char *cpu_id; 309 int cpu_vendor; 310 const char *cpu_vendorname; 311 struct cpu_cpuid_family { 312 int cpu_class; 313 const char *cpu_models[CPU_MAXMODEL+2]; 314 void (*cpu_setup)(struct cpu_info *); 315 } cpu_family[CPU_MAXFAMILY - CPU_MINFAMILY + 1]; 316 }; 317 318 struct cpu_cpuid_feature { 319 int feature_bit; 320 const char *feature_name; 321 }; 322 323 /* locore.s */ 324 extern int cpu; 325 extern int cpu_id; 326 extern char cpu_vendor[]; /* note: NOT nul-terminated */ 327 extern char cpu_brandstr[]; 328 extern int cpuid_level; 329 extern int cpu_miscinfo; 330 extern int cpu_feature; 331 extern int ecpu_feature; 332 extern int cpu_ecxfeature; 333 extern int ecpu_ecxfeature; 334 extern int cpu_cache_eax; 335 extern int cpu_cache_ebx; 336 extern int cpu_cache_ecx; 337 extern int cpu_cache_edx; 338 extern int cpu_perf_eax; 339 extern int cpu_perf_ebx; 340 extern int cpu_perf_edx; 341 extern int cpu_apmi_edx; 342 343 /* cpu.c */ 344 extern u_int cpu_mwait_size; 345 extern u_int cpu_mwait_states; 346 347 /* machdep.c */ 348 extern int cpu_apmhalt; 349 extern int cpu_class; 350 extern char cpu_model[]; 351 extern const struct cpu_nocpuid_nameclass i386_nocpuid_cpus[]; 352 extern const struct cpu_cpuid_nameclass i386_cpuid_cpus[]; 353 extern void (*cpu_idle_enter_fcn)(void); 354 extern void (*cpu_idle_cycle_fcn)(void); 355 extern void (*cpu_idle_leave_fcn)(void); 356 357 /* apm.c */ 358 extern int cpu_apmwarn; 359 360 extern int cpuspeed; 361 362 #if !defined(SMALL_KERNEL) 363 #define BUS66 6667 364 #define BUS100 10000 365 #define BUS133 13333 366 #define BUS166 16667 367 #define BUS200 20000 368 #define BUS266 26667 369 #define BUS333 33333 370 extern int bus_clock; 371 #endif 372 373 /* F00F bug fix stuff for pentium cpu */ 374 extern int cpu_f00f_bug; 375 void fix_f00f(void); 376 377 /* dkcsum.c */ 378 void dkcsumattach(void); 379 380 extern int i386_use_fxsave; 381 extern int i386_has_sse; 382 extern int i386_has_sse2; 383 384 extern void (*update_cpuspeed)(void); 385 386 /* machdep.c */ 387 void dumpconf(void); 388 void cpu_reset(void); 389 void i386_proc0_tss_init(void); 390 void i386_init_pcb_tss(struct cpu_info *); 391 void cpuid(u_int32_t, u_int32_t *); 392 393 /* locore.s */ 394 struct region_descriptor; 395 void lgdt(struct region_descriptor *); 396 397 struct pcb; 398 void savectx(struct pcb *); 399 void switch_exit(struct proc *); 400 void proc_trampoline(void); 401 402 /* clock.c */ 403 extern void (*initclock_func)(void); 404 void startclocks(void); 405 void rtcdrain(void *); 406 void rtcstart(void); 407 void rtcstop(void); 408 void i8254_delay(int); 409 void i8254_initclocks(void); 410 void i8254_startclock(void); 411 void i8254_inittimecounter(void); 412 void i8254_inittimecounter_simple(void); 413 414 #if !defined(SMALL_KERNEL) 415 /* est.c */ 416 void est_init(struct cpu_info *, int); 417 void est_setperf(int); 418 /* longrun.c */ 419 void longrun_init(void); 420 void longrun_setperf(int); 421 /* p4tcc.c */ 422 void p4tcc_init(int, int); 423 void p4tcc_setperf(int); 424 /* powernow.c */ 425 void k6_powernow_init(void); 426 void k6_powernow_setperf(int); 427 /* powernow-k7.c */ 428 void k7_powernow_init(void); 429 void k7_powernow_setperf(int); 430 /* powernow-k8.c */ 431 void k8_powernow_init(void); 432 void k8_powernow_setperf(int); 433 /* k1x-pstate.c */ 434 void k1x_init(struct cpu_info *); 435 void k1x_setperf(int); 436 #endif 437 438 /* npx.c */ 439 void npxdrop(struct proc *); 440 void npxsave_proc(struct proc *, int); 441 void npxsave_cpu(struct cpu_info *, int); 442 443 /* isa_machdep.c */ 444 void isa_defaultirq(void); 445 int isa_nmi(void); 446 447 /* pmap.c */ 448 void pmap_bootstrap(vaddr_t); 449 450 /* vm_machdep.c */ 451 int kvtop(caddr_t); 452 453 #ifdef MULTIPROCESSOR 454 /* mp_setperf.c */ 455 void mp_setperf_init(void); 456 #endif 457 458 #ifdef VM86 459 /* vm86.c */ 460 void vm86_gpfault(struct proc *, int); 461 #endif /* VM86 */ 462 463 int cpu_paenable(void *); 464 #endif /* _KERNEL */ 465 466 /* 467 * CTL_MACHDEP definitions. 468 */ 469 #define CPU_CONSDEV 1 /* dev_t: console terminal device */ 470 #define CPU_BIOS 2 /* BIOS variables */ 471 #define CPU_BLK2CHR 3 /* convert blk maj into chr one */ 472 #define CPU_CHR2BLK 4 /* convert chr maj into blk one */ 473 #define CPU_ALLOWAPERTURE 5 /* allow mmap of /dev/xf86 */ 474 #define CPU_CPUVENDOR 6 /* cpuid vendor string */ 475 #define CPU_CPUID 7 /* cpuid */ 476 #define CPU_CPUFEATURE 8 /* cpuid features */ 477 #define CPU_APMWARN 9 /* APM battery warning percentage */ 478 #define CPU_KBDRESET 10 /* keyboard reset under pcvt */ 479 #define CPU_APMHALT 11 /* halt -p hack */ 480 #define CPU_OSFXSR 13 /* uses FXSAVE/FXRSTOR */ 481 #define CPU_SSE 14 /* supports SSE */ 482 #define CPU_SSE2 15 /* supports SSE2 */ 483 #define CPU_XCRYPT 16 /* supports VIA xcrypt in userland */ 484 #define CPU_LIDSUSPEND 17 /* lid close causes a suspend */ 485 #define CPU_MAXID 18 /* number of valid machdep ids */ 486 487 #define CTL_MACHDEP_NAMES { \ 488 { 0, 0 }, \ 489 { "console_device", CTLTYPE_STRUCT }, \ 490 { "bios", CTLTYPE_INT }, \ 491 { "blk2chr", CTLTYPE_STRUCT }, \ 492 { "chr2blk", CTLTYPE_STRUCT }, \ 493 { "allowaperture", CTLTYPE_INT }, \ 494 { "cpuvendor", CTLTYPE_STRING }, \ 495 { "cpuid", CTLTYPE_INT }, \ 496 { "cpufeature", CTLTYPE_INT }, \ 497 { "apmwarn", CTLTYPE_INT }, \ 498 { "kbdreset", CTLTYPE_INT }, \ 499 { "apmhalt", CTLTYPE_INT }, \ 500 { 0, 0 }, \ 501 { "osfxsr", CTLTYPE_INT }, \ 502 { "sse", CTLTYPE_INT }, \ 503 { "sse2", CTLTYPE_INT }, \ 504 { "xcrypt", CTLTYPE_INT }, \ 505 { "lidsuspend", CTLTYPE_INT }, \ 506 } 507 508 /* 509 * This needs to be included late since it relies on definitions higher 510 * up in this file. 511 */ 512 #if defined(MULTIPROCESSOR) && defined(_KERNEL) 513 #include <sys/mplock.h> 514 #endif 515 516 #endif /* !_MACHINE_CPU_H_ */ 517