1 /* $NetBSD: cpu.h,v 1.92 2002/12/06 14:47:09 junyoung Exp $ */ 2 3 /*- 4 * Copyright (c) 1990 The Regents of the University of California. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * William Jolitz. 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 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the University of 21 * California, Berkeley and its contributors. 22 * 4. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 * 38 * @(#)cpu.h 5.4 (Berkeley) 5/9/91 39 */ 40 41 #ifndef _I386_CPU_H_ 42 #define _I386_CPU_H_ 43 44 #if defined(_KERNEL_OPT) 45 #include "opt_multiprocessor.h" 46 #endif 47 48 /* 49 * Definitions unique to i386 cpu support. 50 */ 51 #include <machine/frame.h> 52 #include <machine/segments.h> 53 #include <machine/tss.h> 54 #include <machine/intrdefs.h> 55 56 #include <sys/device.h> 57 #include <sys/lock.h> /* will also get LOCKDEBUG */ 58 #include <sys/sched.h> 59 60 struct i386_cache_info { 61 uint8_t cai_index; 62 uint8_t cai_desc; 63 uint8_t cai_associativity; 64 u_int cai_totalsize; /* #entries for TLB, bytes for cache */ 65 u_int cai_linesize; /* or page size for TLB */ 66 const char *cai_string; 67 }; 68 69 #define CAI_ITLB 0 /* Instruction TLB (4K pages) */ 70 #define CAI_ITLB2 1 /* Instruction TLB (2/4M pages) */ 71 #define CAI_DTLB 2 /* Data TLB (4K pages) */ 72 #define CAI_DTLB2 3 /* Data TLB (2/4M pages) */ 73 #define CAI_ICACHE 4 /* Instruction cache */ 74 #define CAI_DCACHE 5 /* Data cache */ 75 #define CAI_L2CACHE 6 /* Level 2 cache */ 76 77 #define CAI_COUNT 7 78 79 struct intrsource; 80 81 /* 82 * a bunch of this belongs in cpuvar.h; move it later.. 83 */ 84 85 struct cpu_info { 86 struct device *ci_dev; /* pointer to our device */ 87 struct cpu_info *ci_self; /* self-pointer */ 88 void *ci_tlog_base; /* Trap log base */ 89 int32_t ci_tlog_offset; /* Trap log current offset */ 90 struct schedstate_percpu ci_schedstate; /* scheduler state */ 91 struct cpu_info *ci_next; /* next cpu */ 92 93 /* 94 * Public members. 95 */ 96 struct proc *ci_curproc; /* current owner of the processor */ 97 struct simplelock ci_slock; /* lock on this data structure */ 98 cpuid_t ci_cpuid; /* our CPU ID */ 99 u_int ci_apicid; /* our APIC ID */ 100 u_long ci_spin_locks; /* # of spin locks held */ 101 u_long ci_simple_locks; /* # of simple locks held */ 102 103 /* 104 * Private members. 105 */ 106 struct proc *ci_fpcurproc; /* current owner of the FPU */ 107 int ci_fpsaving; /* save in progress */ 108 109 volatile u_int32_t ci_tlb_ipi_mask; 110 111 struct pcb *ci_curpcb; /* VA of current HW PCB */ 112 struct pcb *ci_idle_pcb; /* VA of current PCB */ 113 int ci_idle_tss_sel; /* TSS selector of idle PCB */ 114 115 struct intrsource *ci_isources[MAX_INTR_SOURCES]; 116 u_int32_t ci_ipending; 117 int ci_ilevel; 118 int ci_idepth; 119 u_int32_t ci_imask[NIPL]; 120 u_int32_t ci_iunmask[NIPL]; 121 122 paddr_t ci_idle_pcb_paddr; /* PA of idle PCB */ 123 u_int32_t ci_flags; /* flags; see below */ 124 u_int32_t ci_ipis; /* interprocessor interrupts pending */ 125 int sc_apic_version; /* local APIC version */ 126 127 int32_t ci_cpuid_level; 128 u_int32_t ci_signature; /* X86 cpuid type */ 129 u_int32_t ci_feature_flags;/* X86 CPUID feature bits */ 130 u_int32_t ci_cpu_class; /* CPU class */ 131 u_int32_t ci_brand_id; /* Intel brand id */ 132 u_int32_t ci_vendor[4]; /* vendor string */ 133 u_int32_t ci_cpu_serial[3]; /* PIII serial number */ 134 u_int64_t ci_tsc_freq; /* cpu cycles/second */ 135 136 struct cpu_functions *ci_func; /* start/stop functions */ 137 void (*cpu_setup) __P((struct cpu_info *)); 138 /* proc-dependant init */ 139 void (*ci_info) __P((struct cpu_info *)); 140 141 int ci_want_resched; 142 int ci_astpending; 143 struct trapframe *ci_ddb_regs; 144 145 u_int ci_cflush_lsize; /* CFLUSH insn line size */ 146 struct i386_cache_info ci_cinfo[CAI_COUNT]; 147 148 /* 149 * Variables used by tsc_microtime(). 150 */ 151 struct timeval ci_tsc_time; 152 int64_t ci_tsc_tsc; 153 int64_t ci_tsc_ms_delta; 154 int64_t ci_tsc_denom; 155 156 union descriptor *ci_gdt; 157 158 struct i386tss ci_doubleflt_tss; 159 struct i386tss ci_ddbipi_tss; 160 161 char *ci_doubleflt_stack; 162 char *ci_ddbipi_stack; 163 164 struct evcnt ci_ipi_events[I386_NIPI]; 165 }; 166 167 /* 168 * Processor flag notes: The "primary" CPU has certain MI-defined 169 * roles (mostly relating to hardclock handling); we distinguish 170 * betwen the processor which booted us, and the processor currently 171 * holding the "primary" role just to give us the flexibility later to 172 * change primaries should we be sufficiently twisted. 173 */ 174 175 #define CPUF_BSP 0x0001 /* CPU is the original BSP */ 176 #define CPUF_AP 0x0002 /* CPU is an AP */ 177 #define CPUF_SP 0x0004 /* CPU is only processor */ 178 #define CPUF_PRIMARY 0x0008 /* CPU is active primary processor */ 179 180 #define CPUF_APIC_CD 0x0010 /* CPU has apic configured */ 181 182 #define CPUF_PRESENT 0x1000 /* CPU is present */ 183 #define CPUF_RUNNING 0x2000 /* CPU is running */ 184 #define CPUF_PAUSE 0x4000 /* CPU is paused in DDB */ 185 #define CPUF_GO 0x8000 /* CPU should start running */ 186 187 /* 188 * We statically allocate the CPU info for the primary CPU (or, 189 * the only CPU on uniprocessors), and the primary CPU is the 190 * first CPU on the CPU info list. 191 */ 192 extern struct cpu_info cpu_info_primary; 193 extern struct cpu_info *cpu_info_list; 194 195 #define CPU_INFO_ITERATOR int 196 #define CPU_INFO_FOREACH(cii, ci) cii = 0, ci = cpu_info_list; \ 197 ci != NULL; ci = ci->ci_next 198 199 #if defined(MULTIPROCESSOR) 200 201 #define I386_MAXPROCS 32 /* because we use a bitmask */ 202 203 #define CPU_STARTUP(_ci) ((_ci)->ci_func->start(_ci)) 204 #define CPU_STOP(_ci) ((_ci)->ci_func->stop(_ci)) 205 #define CPU_START_CLEANUP(_ci) ((_ci)->ci_func->cleanup(_ci)) 206 207 #define curcpu() ({struct cpu_info *ci; \ 208 asm volatile("movl %%fs:4,%0" : "=r" (ci)); \ 209 ci;}) 210 #define cpu_number() (curcpu()->ci_cpuid) 211 212 #define CPU_IS_PRIMARY(ci) ((ci)->ci_flags & CPUF_PRIMARY) 213 214 #if 0 215 #define i386_ipisend(ci) (((ci) != curcpu()) ? i386_send_ipi((ci),0) : 0) 216 #else 217 #define i386_ipisend(ci) 0 218 #endif 219 220 #define aston(ci) ((ci)->ci_astpending = 1, i386_ipisend(ci)) 221 222 extern struct cpu_info *cpu_info[I386_MAXPROCS]; 223 224 void cpu_boot_secondary_processors __P((void)); 225 void cpu_init_idle_pcbs __P((void)); 226 227 /* 228 * Preempt the current process if in interrupt from user mode, 229 * or after the current trap/syscall if in system mode. 230 */ 231 extern void need_resched __P((struct cpu_info *)); 232 233 #else /* !MULTIPROCESSOR */ 234 235 #define I386_MAXPROCS 1 236 237 #ifdef _KERNEL 238 extern struct cpu_info cpu_info_primary; 239 240 #define curcpu() (&cpu_info_primary) 241 #endif 242 243 /* 244 * definitions of cpu-dependent requirements 245 * referenced in generic code 246 */ 247 #define cpu_number() 0 248 #define CPU_IS_PRIMARY(ci) 1 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 #define need_resched(ci) \ 255 do { \ 256 struct cpu_info *__ci = (ci); \ 257 __ci->ci_want_resched = 1; \ 258 aston(__ci); \ 259 } while (/*CONSTCOND*/0) 260 261 #define aston(ci) (curcpu()->ci_astpending = 1) 262 263 #endif 264 265 #define curpcb curcpu()->ci_curpcb 266 #define curproc curcpu()->ci_curproc 267 268 /* 269 * Arguments to hardclock, softclock and statclock 270 * encapsulate the previous machine state in an opaque 271 * clockframe; for now, use generic intrframe. 272 * 273 * Note: Since spllowersoftclock() does not actually unmask the currently 274 * running (hardclock) interrupt, CLKF_BASEPRI() *must* always be 0; otherwise 275 * we could stall hardclock ticks if another interrupt takes too long. 276 */ 277 #define clockframe intrframe 278 279 #define CLKF_USERMODE(frame) USERMODE((frame)->if_cs, (frame)->if_eflags) 280 #define CLKF_BASEPRI(frame) (0) 281 #define CLKF_PC(frame) ((frame)->if_eip) 282 #define CLKF_INTR(frame) (curcpu()->ci_idepth > 1) 283 284 /* 285 * This is used during profiling to integrate system time. It can safely 286 * assume that the process is resident. 287 */ 288 #define PROC_PC(p) ((p)->p_md.md_regs->tf_eip) 289 290 /* 291 * Give a profiling tick to the current process when the user profiling 292 * buffer pages are invalid. On the i386, request an ast to send us 293 * through trap(), marking the proc as needing a profiling tick. 294 */ 295 #define need_proftick(p) ((p)->p_flag |= P_OWEUPC, aston(p->p_cpu)) 296 297 /* 298 * Notify the current process (p) that it has a signal pending, 299 * process as soon as possible. 300 */ 301 #define signotify(p) aston(p->p_cpu) 302 303 /* 304 * We need a machine-independent name for this. 305 */ 306 extern void (*delay_func) __P((int)); 307 struct timeval; 308 extern void (*microtime_func) __P((struct timeval *)); 309 310 #define DELAY(x) (*delay_func)(x) 311 #define delay(x) (*delay_func)(x) 312 #define microtime(tv) (*microtime_func)(tv) 313 314 /* 315 * pull in #defines for kinds of processors 316 */ 317 #include <machine/cputypes.h> 318 319 struct cpu_nocpuid_nameclass { 320 int cpu_vendor; 321 const char *cpu_vendorname; 322 const char *cpu_name; 323 int cpu_class; 324 void (*cpu_setup) __P((struct cpu_info *)); 325 void (*cpu_cacheinfo) __P((struct cpu_info *)); 326 void (*cpu_info) __P((struct cpu_info *)); 327 }; 328 329 330 struct cpu_cpuid_nameclass { 331 const char *cpu_id; 332 int cpu_vendor; 333 const char *cpu_vendorname; 334 struct cpu_cpuid_family { 335 int cpu_class; 336 const char *cpu_models[CPU_MAXMODEL+2]; 337 void (*cpu_setup) __P((struct cpu_info *)); 338 void (*cpu_probe) __P((struct cpu_info *)); 339 void (*cpu_info) __P((struct cpu_info *)); 340 } cpu_family[CPU_MAXFAMILY - CPU_MINFAMILY + 1]; 341 }; 342 343 #ifdef _KERNEL 344 extern int biosbasemem; 345 extern int biosextmem; 346 extern int cpu_feature; 347 extern int cpu; 348 extern int cpu_class; 349 extern const struct cpu_nocpuid_nameclass i386_nocpuid_cpus[]; 350 extern const struct cpu_cpuid_nameclass i386_cpuid_cpus[]; 351 352 extern int i386_use_fxsave; 353 extern int i386_has_sse; 354 extern int i386_has_sse2; 355 356 /* machdep.c */ 357 void dumpconf __P((void)); 358 void cpu_reset __P((void)); 359 void i386_init_pcb_tss_ldt __P((struct cpu_info *)); 360 void i386_proc0_tss_ldt_init __P((void)); 361 void i386_bufinit __P((void)); 362 363 /* locore.s */ 364 struct region_descriptor; 365 void lgdt __P((struct region_descriptor *)); 366 void fillw __P((short, void *, size_t)); 367 368 struct pcb; 369 void savectx __P((struct pcb *)); 370 void switch_exit __P((struct proc *)); 371 void proc_trampoline __P((void)); 372 373 /* clock.c */ 374 void initrtclock __P((void)); 375 void startrtclock __P((void)); 376 void i8254_delay __P((int)); 377 void i8254_microtime __P((struct timeval *)); 378 void i8254_initclocks __P((void)); 379 380 /* tsc_microtime.c */ 381 382 void tsc_microtime __P((struct timeval *)); 383 void tsc_microset __P((struct cpu_info *)); 384 385 /* cpu.c */ 386 387 void cpu_probe_features __P((struct cpu_info *)); 388 389 /* npx.c */ 390 void npxsave_proc __P((struct proc *, int)); 391 void npxsave_cpu __P((struct cpu_info *, int)); 392 393 /* vm_machdep.c */ 394 int kvtop __P((caddr_t)); 395 396 #if !defined(_LKM) 397 #include "opt_math_emulate.h" 398 #endif 399 #ifdef MATH_EMULATE 400 /* math_emulate.c */ 401 int math_emulate __P((struct trapframe *)); 402 #endif 403 404 #if !defined(_LKM) 405 #include "opt_user_ldt.h" 406 #endif 407 #ifdef USER_LDT 408 /* sys_machdep.h */ 409 int i386_get_ldt __P((struct proc *, void *, register_t *)); 410 int i386_set_ldt __P((struct proc *, void *, register_t *)); 411 #endif 412 413 /* isa_machdep.c */ 414 void isa_defaultirq __P((void)); 415 int isa_nmi __P((void)); 416 417 #if !defined(_LKM) 418 #include "opt_vm86.h" 419 #endif 420 #ifdef VM86 421 /* vm86.c */ 422 void vm86_gpfault __P((struct proc *, int)); 423 #endif /* VM86 */ 424 425 /* consinit.c */ 426 void kgdb_port_init __P((void)); 427 428 /* bus_machdep.c */ 429 void i386_bus_space_init __P((void)); 430 void i386_bus_space_mallocok __P((void)); 431 432 #endif /* _KERNEL */ 433 434 #include <machine/psl.h> 435 436 /* 437 * CTL_MACHDEP definitions. 438 */ 439 #define CPU_CONSDEV 1 /* dev_t: console terminal device */ 440 #define CPU_BIOSBASEMEM 2 /* int: bios-reported base mem (K) */ 441 #define CPU_BIOSEXTMEM 3 /* int: bios-reported ext. mem (K) */ 442 #define CPU_NKPDE 4 /* int: number of kernel PDEs */ 443 #define CPU_BOOTED_KERNEL 5 /* string: booted kernel name */ 444 #define CPU_DISKINFO 6 /* struct disklist *: 445 * disk geometry information */ 446 #define CPU_FPU_PRESENT 7 /* int: FPU is present */ 447 #define CPU_OSFXSR 8 /* int: OS uses FXSAVE/FXRSTOR */ 448 #define CPU_SSE 9 /* int: OS/CPU supports SSE */ 449 #define CPU_SSE2 10 /* int: OS/CPU supports SSE2 */ 450 #define CPU_TMLR_MODE 11 /* int: longrun mode 451 * 0: minimum frequency 452 * 1: economy 453 * 2: performance 454 * 3: maximum frequency 455 */ 456 #define CPU_TMLR_FREQUENCY 12 /* int: current frequency */ 457 #define CPU_TMLR_VOLTAGE 13 /* int: curret voltage */ 458 #define CPU_TMLR_PERCENTAGE 14 /* int: current clock percentage */ 459 #define CPU_MAXID 15 /* number of valid machdep ids */ 460 461 #define CTL_MACHDEP_NAMES { \ 462 { 0, 0 }, \ 463 { "console_device", CTLTYPE_STRUCT }, \ 464 { "biosbasemem", CTLTYPE_INT }, \ 465 { "biosextmem", CTLTYPE_INT }, \ 466 { "nkpde", CTLTYPE_INT }, \ 467 { "booted_kernel", CTLTYPE_STRING }, \ 468 { "diskinfo", CTLTYPE_STRUCT }, \ 469 { "fpu_present", CTLTYPE_INT }, \ 470 { "osfxsr", CTLTYPE_INT }, \ 471 { "sse", CTLTYPE_INT }, \ 472 { "sse2", CTLTYPE_INT }, \ 473 { "tm_longrun_mode", CTLTYPE_INT }, \ 474 { "tm_longrun_frequency", CTLTYPE_INT }, \ 475 { "tm_longrun_voltage", CTLTYPE_INT }, \ 476 { "tm_longrun_percentage", CTLTYPE_INT }, \ 477 } 478 479 480 /* 481 * Structure for CPU_DISKINFO sysctl call. 482 * XXX this should be somewhere else. 483 */ 484 #define MAX_BIOSDISKS 16 485 486 struct disklist { 487 int dl_nbiosdisks; /* number of bios disks */ 488 struct biosdisk_info { 489 int bi_dev; /* BIOS device # (0x80 ..) */ 490 int bi_cyl; /* cylinders on disk */ 491 int bi_head; /* heads per track */ 492 int bi_sec; /* sectors per track */ 493 u_int64_t bi_lbasecs; /* total sec. (iff ext13) */ 494 #define BIFLAG_INVALID 0x01 495 #define BIFLAG_EXTINT13 0x02 496 int bi_flags; 497 } dl_biosdisks[MAX_BIOSDISKS]; 498 499 int dl_nnativedisks; /* number of native disks */ 500 struct nativedisk_info { 501 char ni_devname[16]; /* native device name */ 502 int ni_nmatches; /* # of matches w/ BIOS */ 503 int ni_biosmatches[MAX_BIOSDISKS]; /* indices in dl_biosdisks */ 504 } dl_nativedisks[1]; /* actually longer */ 505 }; 506 507 #endif /* !_I386_CPU_H_ */ 508