1*0a6a1f1dSLionel Sambuc /* $NetBSD: cpu.h,v 1.66 2014/02/23 22:38:40 dsl Exp $ */ 27f2d47d8SEvgeniy Ivanov 37f2d47d8SEvgeniy Ivanov /*- 47f2d47d8SEvgeniy Ivanov * Copyright (c) 1990 The Regents of the University of California. 57f2d47d8SEvgeniy Ivanov * All rights reserved. 67f2d47d8SEvgeniy Ivanov * 77f2d47d8SEvgeniy Ivanov * This code is derived from software contributed to Berkeley by 87f2d47d8SEvgeniy Ivanov * William Jolitz. 97f2d47d8SEvgeniy Ivanov * 107f2d47d8SEvgeniy Ivanov * Redistribution and use in source and binary forms, with or without 117f2d47d8SEvgeniy Ivanov * modification, are permitted provided that the following conditions 127f2d47d8SEvgeniy Ivanov * are met: 137f2d47d8SEvgeniy Ivanov * 1. Redistributions of source code must retain the above copyright 147f2d47d8SEvgeniy Ivanov * notice, this list of conditions and the following disclaimer. 157f2d47d8SEvgeniy Ivanov * 2. Redistributions in binary form must reproduce the above copyright 167f2d47d8SEvgeniy Ivanov * notice, this list of conditions and the following disclaimer in the 177f2d47d8SEvgeniy Ivanov * documentation and/or other materials provided with the distribution. 187f2d47d8SEvgeniy Ivanov * 3. Neither the name of the University nor the names of its contributors 197f2d47d8SEvgeniy Ivanov * may be used to endorse or promote products derived from this software 207f2d47d8SEvgeniy Ivanov * without specific prior written permission. 217f2d47d8SEvgeniy Ivanov * 227f2d47d8SEvgeniy Ivanov * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 237f2d47d8SEvgeniy Ivanov * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 247f2d47d8SEvgeniy Ivanov * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 257f2d47d8SEvgeniy Ivanov * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 267f2d47d8SEvgeniy Ivanov * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 277f2d47d8SEvgeniy Ivanov * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 287f2d47d8SEvgeniy Ivanov * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 297f2d47d8SEvgeniy Ivanov * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 307f2d47d8SEvgeniy Ivanov * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 317f2d47d8SEvgeniy Ivanov * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 327f2d47d8SEvgeniy Ivanov * SUCH DAMAGE. 337f2d47d8SEvgeniy Ivanov * 347f2d47d8SEvgeniy Ivanov * @(#)cpu.h 5.4 (Berkeley) 5/9/91 357f2d47d8SEvgeniy Ivanov */ 367f2d47d8SEvgeniy Ivanov 377f2d47d8SEvgeniy Ivanov #ifndef _X86_CPU_H_ 387f2d47d8SEvgeniy Ivanov #define _X86_CPU_H_ 397f2d47d8SEvgeniy Ivanov 407f2d47d8SEvgeniy Ivanov #if defined(_KERNEL) || defined(_STANDALONE) 417f2d47d8SEvgeniy Ivanov #include <sys/types.h> 427f2d47d8SEvgeniy Ivanov #else 43*0a6a1f1dSLionel Sambuc #include <stdint.h> 447f2d47d8SEvgeniy Ivanov #include <stdbool.h> 457f2d47d8SEvgeniy Ivanov #endif /* _KERNEL || _STANDALONE */ 467f2d47d8SEvgeniy Ivanov 477f2d47d8SEvgeniy Ivanov #if defined(_KERNEL) || defined(_KMEMUSER) 487f2d47d8SEvgeniy Ivanov #if defined(_KERNEL_OPT) 497f2d47d8SEvgeniy Ivanov #include "opt_xen.h" 507f2d47d8SEvgeniy Ivanov #ifdef i386 517f2d47d8SEvgeniy Ivanov #include "opt_user_ldt.h" 527f2d47d8SEvgeniy Ivanov #include "opt_vm86.h" 537f2d47d8SEvgeniy Ivanov #endif 547f2d47d8SEvgeniy Ivanov #endif 557f2d47d8SEvgeniy Ivanov 567f2d47d8SEvgeniy Ivanov /* 577f2d47d8SEvgeniy Ivanov * Definitions unique to x86 cpu support. 587f2d47d8SEvgeniy Ivanov */ 597f2d47d8SEvgeniy Ivanov #include <machine/frame.h> 607f2d47d8SEvgeniy Ivanov #include <machine/pte.h> 617f2d47d8SEvgeniy Ivanov #include <machine/segments.h> 627f2d47d8SEvgeniy Ivanov #include <machine/tss.h> 637f2d47d8SEvgeniy Ivanov #include <machine/intrdefs.h> 647f2d47d8SEvgeniy Ivanov 657f2d47d8SEvgeniy Ivanov #include <x86/cacheinfo.h> 667f2d47d8SEvgeniy Ivanov 677f2d47d8SEvgeniy Ivanov #include <sys/cpu_data.h> 687f2d47d8SEvgeniy Ivanov #include <sys/evcnt.h> 697f2d47d8SEvgeniy Ivanov #include <sys/device_if.h> /* for device_t */ 707f2d47d8SEvgeniy Ivanov 717f2d47d8SEvgeniy Ivanov #ifdef XEN 727f2d47d8SEvgeniy Ivanov #include <xen/xen-public/xen.h> 737f2d47d8SEvgeniy Ivanov #include <xen/xen-public/event_channel.h> 741cd76c75SBen Gras #include <sys/mutex.h> 757f2d47d8SEvgeniy Ivanov #endif /* XEN */ 767f2d47d8SEvgeniy Ivanov 777f2d47d8SEvgeniy Ivanov struct intrsource; 787f2d47d8SEvgeniy Ivanov struct pmap; 797f2d47d8SEvgeniy Ivanov 807f2d47d8SEvgeniy Ivanov #ifdef __x86_64__ 817f2d47d8SEvgeniy Ivanov #define i386tss x86_64_tss 827f2d47d8SEvgeniy Ivanov #endif 837f2d47d8SEvgeniy Ivanov 847f2d47d8SEvgeniy Ivanov #define NIOPORTS 1024 /* # of ports we allow to be mapped */ 857f2d47d8SEvgeniy Ivanov #define IOMAPSIZE (NIOPORTS / 8) /* I/O bitmap size in bytes */ 867f2d47d8SEvgeniy Ivanov 877f2d47d8SEvgeniy Ivanov /* 887f2d47d8SEvgeniy Ivanov * a bunch of this belongs in cpuvar.h; move it later.. 897f2d47d8SEvgeniy Ivanov */ 907f2d47d8SEvgeniy Ivanov 917f2d47d8SEvgeniy Ivanov struct cpu_info { 927f2d47d8SEvgeniy Ivanov struct cpu_data ci_data; /* MI per-cpu data */ 937f2d47d8SEvgeniy Ivanov device_t ci_dev; /* pointer to our device */ 947f2d47d8SEvgeniy Ivanov struct cpu_info *ci_self; /* self-pointer */ 957f2d47d8SEvgeniy Ivanov volatile struct vcpu_info *ci_vcpu; /* for XEN */ 967f2d47d8SEvgeniy Ivanov void *ci_tlog_base; /* Trap log base */ 977f2d47d8SEvgeniy Ivanov int32_t ci_tlog_offset; /* Trap log current offset */ 987f2d47d8SEvgeniy Ivanov 997f2d47d8SEvgeniy Ivanov /* 1007f2d47d8SEvgeniy Ivanov * Will be accessed by other CPUs. 1017f2d47d8SEvgeniy Ivanov */ 1027f2d47d8SEvgeniy Ivanov struct cpu_info *ci_next; /* next cpu */ 1037f2d47d8SEvgeniy Ivanov struct lwp *ci_curlwp; /* current owner of the processor */ 1047f2d47d8SEvgeniy Ivanov struct lwp *ci_fpcurlwp; /* current owner of the FPU */ 105*0a6a1f1dSLionel Sambuc int _unused1[2]; 1067f2d47d8SEvgeniy Ivanov cpuid_t ci_cpuid; /* our CPU ID */ 1071cd76c75SBen Gras int _unused; 1087f2d47d8SEvgeniy Ivanov uint32_t ci_acpiid; /* our ACPI/MADT ID */ 1097f2d47d8SEvgeniy Ivanov uint32_t ci_initapicid; /* our intitial APIC ID */ 1107f2d47d8SEvgeniy Ivanov 1117f2d47d8SEvgeniy Ivanov /* 1127f2d47d8SEvgeniy Ivanov * Private members. 1137f2d47d8SEvgeniy Ivanov */ 1147f2d47d8SEvgeniy Ivanov struct evcnt ci_tlb_evcnt; /* tlb shootdown counter */ 1157f2d47d8SEvgeniy Ivanov struct pmap *ci_pmap; /* current pmap */ 1167f2d47d8SEvgeniy Ivanov int ci_need_tlbwait; /* need to wait for TLB invalidations */ 1177f2d47d8SEvgeniy Ivanov int ci_want_pmapload; /* pmap_load() is needed */ 1187f2d47d8SEvgeniy Ivanov volatile int ci_tlbstate; /* one of TLBSTATE_ states. see below */ 1197f2d47d8SEvgeniy Ivanov #define TLBSTATE_VALID 0 /* all user tlbs are valid */ 1207f2d47d8SEvgeniy Ivanov #define TLBSTATE_LAZY 1 /* tlbs are valid but won't be kept uptodate */ 1217f2d47d8SEvgeniy Ivanov #define TLBSTATE_STALE 2 /* we might have stale user tlbs */ 1227f2d47d8SEvgeniy Ivanov int ci_curldt; /* current LDT descriptor */ 1237f2d47d8SEvgeniy Ivanov int ci_nintrhand; /* number of H/W interrupt handlers */ 1247f2d47d8SEvgeniy Ivanov uint64_t ci_scratch; 1257f2d47d8SEvgeniy Ivanov uintptr_t ci_pmap_data[128 / sizeof(uintptr_t)]; 1267f2d47d8SEvgeniy Ivanov 1277f2d47d8SEvgeniy Ivanov #ifdef XEN 1287f2d47d8SEvgeniy Ivanov struct iplsource *ci_isources[NIPL]; 1297f2d47d8SEvgeniy Ivanov u_long ci_evtmask[NR_EVENT_CHANNELS]; /* events allowed on this CPU */ 1307f2d47d8SEvgeniy Ivanov #else 1317f2d47d8SEvgeniy Ivanov struct intrsource *ci_isources[MAX_INTR_SOURCES]; 1327f2d47d8SEvgeniy Ivanov #endif 1337f2d47d8SEvgeniy Ivanov volatile int ci_mtx_count; /* Negative count of spin mutexes */ 1347f2d47d8SEvgeniy Ivanov volatile int ci_mtx_oldspl; /* Old SPL at this ci_idepth */ 1357f2d47d8SEvgeniy Ivanov 1367f2d47d8SEvgeniy Ivanov /* The following must be aligned for cmpxchg8b. */ 1377f2d47d8SEvgeniy Ivanov struct { 1387f2d47d8SEvgeniy Ivanov uint32_t ipending; 1397f2d47d8SEvgeniy Ivanov int ilevel; 1407f2d47d8SEvgeniy Ivanov } ci_istate __aligned(8); 1417f2d47d8SEvgeniy Ivanov #define ci_ipending ci_istate.ipending 1427f2d47d8SEvgeniy Ivanov #define ci_ilevel ci_istate.ilevel 1437f2d47d8SEvgeniy Ivanov 1447f2d47d8SEvgeniy Ivanov int ci_idepth; 1457f2d47d8SEvgeniy Ivanov void * ci_intrstack; 1467f2d47d8SEvgeniy Ivanov uint32_t ci_imask[NIPL]; 1477f2d47d8SEvgeniy Ivanov uint32_t ci_iunmask[NIPL]; 1487f2d47d8SEvgeniy Ivanov 1497f2d47d8SEvgeniy Ivanov uint32_t ci_flags; /* flags; see below */ 1507f2d47d8SEvgeniy Ivanov uint32_t ci_ipis; /* interprocessor interrupts pending */ 1517f2d47d8SEvgeniy Ivanov uint32_t sc_apic_version; /* local APIC version */ 1527f2d47d8SEvgeniy Ivanov 153*0a6a1f1dSLionel Sambuc uint32_t ci_signature; /* X86 cpuid type (cpuid.1.%eax) */ 1547f2d47d8SEvgeniy Ivanov uint32_t ci_vendor[4]; /* vendor string */ 155*0a6a1f1dSLionel Sambuc uint32_t _unused2; 156*0a6a1f1dSLionel Sambuc uint32_t ci_max_cpuid; /* cpuid.0:%eax */ 157*0a6a1f1dSLionel Sambuc uint32_t ci_max_ext_cpuid; /* cpuid.80000000:%eax */ 1587f2d47d8SEvgeniy Ivanov volatile uint32_t ci_lapic_counter; 1597f2d47d8SEvgeniy Ivanov 160*0a6a1f1dSLionel Sambuc uint32_t ci_feat_val[5]; /* X86 CPUID feature bits */ 161*0a6a1f1dSLionel Sambuc /* [0] basic features cpuid.1:%edx 162*0a6a1f1dSLionel Sambuc * [1] basic features cpuid.1:%ecx (CPUID2_xxx bits) 163*0a6a1f1dSLionel Sambuc * [2] extended features cpuid:80000001:%edx 164*0a6a1f1dSLionel Sambuc * [3] extended features cpuid:80000001:%ecx 1657f2d47d8SEvgeniy Ivanov * [4] VIA padlock features 1667f2d47d8SEvgeniy Ivanov */ 1677f2d47d8SEvgeniy Ivanov 1687f2d47d8SEvgeniy Ivanov const struct cpu_functions *ci_func; /* start/stop functions */ 1697f2d47d8SEvgeniy Ivanov struct trapframe *ci_ddb_regs; 1707f2d47d8SEvgeniy Ivanov 1717f2d47d8SEvgeniy Ivanov u_int ci_cflush_lsize; /* CFLUSH insn line size */ 1727f2d47d8SEvgeniy Ivanov struct x86_cache_info ci_cinfo[CAI_COUNT]; 1737f2d47d8SEvgeniy Ivanov 1747f2d47d8SEvgeniy Ivanov union descriptor *ci_gdt; 1757f2d47d8SEvgeniy Ivanov 1767f2d47d8SEvgeniy Ivanov #ifdef i386 1777f2d47d8SEvgeniy Ivanov struct i386tss ci_doubleflt_tss; 1787f2d47d8SEvgeniy Ivanov struct i386tss ci_ddbipi_tss; 1797f2d47d8SEvgeniy Ivanov #endif 1807f2d47d8SEvgeniy Ivanov 1817f2d47d8SEvgeniy Ivanov #ifdef PAE 1827f2d47d8SEvgeniy Ivanov uint32_t ci_pae_l3_pdirpa; /* PA of L3 PD */ 1837f2d47d8SEvgeniy Ivanov pd_entry_t * ci_pae_l3_pdir; /* VA pointer to L3 PD */ 1847f2d47d8SEvgeniy Ivanov #endif 1857f2d47d8SEvgeniy Ivanov 1867f2d47d8SEvgeniy Ivanov #if defined(XEN) && (defined(PAE) || defined(__x86_64__)) 1877f2d47d8SEvgeniy Ivanov /* Currently active user PGD (can't use rcr3() with Xen) */ 1887f2d47d8SEvgeniy Ivanov pd_entry_t * ci_kpm_pdir; /* per-cpu PMD (va) */ 1897f2d47d8SEvgeniy Ivanov paddr_t ci_kpm_pdirpa; /* per-cpu PMD (pa) */ 1901cd76c75SBen Gras kmutex_t ci_kpm_mtx; 1917f2d47d8SEvgeniy Ivanov #if defined(__x86_64__) 1921cd76c75SBen Gras /* per-cpu version of normal_pdes */ 1931cd76c75SBen Gras pd_entry_t * ci_normal_pdes[3]; /* Ok to hardcode. only for x86_64 && XEN */ 1947f2d47d8SEvgeniy Ivanov paddr_t ci_xen_current_user_pgd; 1957f2d47d8SEvgeniy Ivanov #endif /* __x86_64__ */ 1967f2d47d8SEvgeniy Ivanov #endif /* XEN et.al */ 1977f2d47d8SEvgeniy Ivanov 1987f2d47d8SEvgeniy Ivanov char *ci_doubleflt_stack; 1997f2d47d8SEvgeniy Ivanov char *ci_ddbipi_stack; 2007f2d47d8SEvgeniy Ivanov 2017f2d47d8SEvgeniy Ivanov #ifndef XEN 2027f2d47d8SEvgeniy Ivanov struct evcnt ci_ipi_events[X86_NIPI]; 2037f2d47d8SEvgeniy Ivanov #else /* XEN */ 2047f2d47d8SEvgeniy Ivanov struct evcnt ci_ipi_events[XEN_NIPIS]; 2057f2d47d8SEvgeniy Ivanov evtchn_port_t ci_ipi_evtchn; 2067f2d47d8SEvgeniy Ivanov #endif /* XEN */ 2077f2d47d8SEvgeniy Ivanov 2087f2d47d8SEvgeniy Ivanov device_t ci_frequency; /* Frequency scaling technology */ 2097f2d47d8SEvgeniy Ivanov device_t ci_padlock; /* VIA PadLock private storage */ 2107f2d47d8SEvgeniy Ivanov device_t ci_temperature; /* Intel coretemp(4) or equivalent */ 2117f2d47d8SEvgeniy Ivanov device_t ci_vm; /* Virtual machine guest driver */ 2127f2d47d8SEvgeniy Ivanov 2137f2d47d8SEvgeniy Ivanov struct i386tss ci_tss; /* Per-cpu TSS; shared among LWPs */ 2147f2d47d8SEvgeniy Ivanov char ci_iomap[IOMAPSIZE]; /* I/O Bitmap */ 2157f2d47d8SEvgeniy Ivanov int ci_tss_sel; /* TSS selector of this cpu */ 2167f2d47d8SEvgeniy Ivanov 2177f2d47d8SEvgeniy Ivanov /* 2187f2d47d8SEvgeniy Ivanov * The following two are actually region_descriptors, 2197f2d47d8SEvgeniy Ivanov * but that would pollute the namespace. 2207f2d47d8SEvgeniy Ivanov */ 2217f2d47d8SEvgeniy Ivanov uintptr_t ci_suspend_gdt; 2227f2d47d8SEvgeniy Ivanov uint16_t ci_suspend_gdt_padding; 2237f2d47d8SEvgeniy Ivanov uintptr_t ci_suspend_idt; 2247f2d47d8SEvgeniy Ivanov uint16_t ci_suspend_idt_padding; 2257f2d47d8SEvgeniy Ivanov 2267f2d47d8SEvgeniy Ivanov uint16_t ci_suspend_tr; 2277f2d47d8SEvgeniy Ivanov uint16_t ci_suspend_ldt; 2287f2d47d8SEvgeniy Ivanov uintptr_t ci_suspend_fs; 2297f2d47d8SEvgeniy Ivanov uintptr_t ci_suspend_gs; 2307f2d47d8SEvgeniy Ivanov uintptr_t ci_suspend_kgs; 2317f2d47d8SEvgeniy Ivanov uintptr_t ci_suspend_efer; 2327f2d47d8SEvgeniy Ivanov uintptr_t ci_suspend_reg[12]; 2337f2d47d8SEvgeniy Ivanov uintptr_t ci_suspend_cr0; 2347f2d47d8SEvgeniy Ivanov uintptr_t ci_suspend_cr2; 2357f2d47d8SEvgeniy Ivanov uintptr_t ci_suspend_cr3; 2367f2d47d8SEvgeniy Ivanov uintptr_t ci_suspend_cr4; 2377f2d47d8SEvgeniy Ivanov uintptr_t ci_suspend_cr8; 2387f2d47d8SEvgeniy Ivanov 2397f2d47d8SEvgeniy Ivanov /* The following must be in a single cache line. */ 2407f2d47d8SEvgeniy Ivanov int ci_want_resched __aligned(64); 2417f2d47d8SEvgeniy Ivanov int ci_padout __aligned(64); 2427f2d47d8SEvgeniy Ivanov }; 2437f2d47d8SEvgeniy Ivanov 2447f2d47d8SEvgeniy Ivanov /* 2457f2d47d8SEvgeniy Ivanov * Macros to handle (some) trapframe registers for common x86 code. 2467f2d47d8SEvgeniy Ivanov */ 2477f2d47d8SEvgeniy Ivanov #ifdef __x86_64__ 2487f2d47d8SEvgeniy Ivanov #define X86_TF_RAX(tf) tf->tf_rax 2497f2d47d8SEvgeniy Ivanov #define X86_TF_RDX(tf) tf->tf_rdx 2507f2d47d8SEvgeniy Ivanov #define X86_TF_RSP(tf) tf->tf_rsp 2517f2d47d8SEvgeniy Ivanov #define X86_TF_RIP(tf) tf->tf_rip 2527f2d47d8SEvgeniy Ivanov #define X86_TF_RFLAGS(tf) tf->tf_rflags 2537f2d47d8SEvgeniy Ivanov #else 2547f2d47d8SEvgeniy Ivanov #define X86_TF_RAX(tf) tf->tf_eax 2557f2d47d8SEvgeniy Ivanov #define X86_TF_RDX(tf) tf->tf_edx 2567f2d47d8SEvgeniy Ivanov #define X86_TF_RSP(tf) tf->tf_esp 2577f2d47d8SEvgeniy Ivanov #define X86_TF_RIP(tf) tf->tf_eip 2587f2d47d8SEvgeniy Ivanov #define X86_TF_RFLAGS(tf) tf->tf_eflags 2597f2d47d8SEvgeniy Ivanov #endif 2607f2d47d8SEvgeniy Ivanov 2617f2d47d8SEvgeniy Ivanov /* 2627f2d47d8SEvgeniy Ivanov * Processor flag notes: The "primary" CPU has certain MI-defined 2637f2d47d8SEvgeniy Ivanov * roles (mostly relating to hardclock handling); we distinguish 2647f2d47d8SEvgeniy Ivanov * betwen the processor which booted us, and the processor currently 2657f2d47d8SEvgeniy Ivanov * holding the "primary" role just to give us the flexibility later to 2667f2d47d8SEvgeniy Ivanov * change primaries should we be sufficiently twisted. 2677f2d47d8SEvgeniy Ivanov */ 2687f2d47d8SEvgeniy Ivanov 2697f2d47d8SEvgeniy Ivanov #define CPUF_BSP 0x0001 /* CPU is the original BSP */ 2707f2d47d8SEvgeniy Ivanov #define CPUF_AP 0x0002 /* CPU is an AP */ 2717f2d47d8SEvgeniy Ivanov #define CPUF_SP 0x0004 /* CPU is only processor */ 2727f2d47d8SEvgeniy Ivanov #define CPUF_PRIMARY 0x0008 /* CPU is active primary processor */ 2737f2d47d8SEvgeniy Ivanov 2747f2d47d8SEvgeniy Ivanov #define CPUF_SYNCTSC 0x0800 /* Synchronize TSC */ 2757f2d47d8SEvgeniy Ivanov #define CPUF_PRESENT 0x1000 /* CPU is present */ 2767f2d47d8SEvgeniy Ivanov #define CPUF_RUNNING 0x2000 /* CPU is running */ 2777f2d47d8SEvgeniy Ivanov #define CPUF_PAUSE 0x4000 /* CPU is paused in DDB */ 2787f2d47d8SEvgeniy Ivanov #define CPUF_GO 0x8000 /* CPU should start running */ 2797f2d47d8SEvgeniy Ivanov 2807f2d47d8SEvgeniy Ivanov #endif /* _KERNEL || __KMEMUSER */ 2817f2d47d8SEvgeniy Ivanov 2827f2d47d8SEvgeniy Ivanov #ifdef _KERNEL 2837f2d47d8SEvgeniy Ivanov /* 2847f2d47d8SEvgeniy Ivanov * We statically allocate the CPU info for the primary CPU (or, 2857f2d47d8SEvgeniy Ivanov * the only CPU on uniprocessors), and the primary CPU is the 2867f2d47d8SEvgeniy Ivanov * first CPU on the CPU info list. 2877f2d47d8SEvgeniy Ivanov */ 2887f2d47d8SEvgeniy Ivanov extern struct cpu_info cpu_info_primary; 2897f2d47d8SEvgeniy Ivanov extern struct cpu_info *cpu_info_list; 2907f2d47d8SEvgeniy Ivanov 29184d9c625SLionel Sambuc #define CPU_INFO_ITERATOR int __unused 29284d9c625SLionel Sambuc #define CPU_INFO_FOREACH(cii, ci) ci = cpu_info_list; \ 2937f2d47d8SEvgeniy Ivanov ci != NULL; ci = ci->ci_next 2947f2d47d8SEvgeniy Ivanov 2957f2d47d8SEvgeniy Ivanov #define CPU_STARTUP(_ci, _target) ((_ci)->ci_func->start(_ci, _target)) 2967f2d47d8SEvgeniy Ivanov #define CPU_STOP(_ci) ((_ci)->ci_func->stop(_ci)) 2977f2d47d8SEvgeniy Ivanov #define CPU_START_CLEANUP(_ci) ((_ci)->ci_func->cleanup(_ci)) 2987f2d47d8SEvgeniy Ivanov 2997f2d47d8SEvgeniy Ivanov #if !defined(__GNUC__) || defined(_MODULE) 3007f2d47d8SEvgeniy Ivanov /* For non-GCC and modules */ 3017f2d47d8SEvgeniy Ivanov struct cpu_info *x86_curcpu(void); 3027f2d47d8SEvgeniy Ivanov void cpu_set_curpri(int); 3037f2d47d8SEvgeniy Ivanov # ifdef __GNUC__ 3047f2d47d8SEvgeniy Ivanov lwp_t *x86_curlwp(void) __attribute__ ((const)); 3057f2d47d8SEvgeniy Ivanov # else 3067f2d47d8SEvgeniy Ivanov lwp_t *x86_curlwp(void); 3077f2d47d8SEvgeniy Ivanov # endif 3087f2d47d8SEvgeniy Ivanov #endif 3097f2d47d8SEvgeniy Ivanov 3107f2d47d8SEvgeniy Ivanov #define cpu_number() (cpu_index(curcpu())) 3117f2d47d8SEvgeniy Ivanov 3127f2d47d8SEvgeniy Ivanov #define CPU_IS_PRIMARY(ci) ((ci)->ci_flags & CPUF_PRIMARY) 3137f2d47d8SEvgeniy Ivanov 3147f2d47d8SEvgeniy Ivanov #define X86_AST_GENERIC 0x01 3157f2d47d8SEvgeniy Ivanov #define X86_AST_PREEMPT 0x02 3167f2d47d8SEvgeniy Ivanov 3177f2d47d8SEvgeniy Ivanov #define aston(l, why) ((l)->l_md.md_astpending |= (why)) 3187f2d47d8SEvgeniy Ivanov #define cpu_did_resched(l) ((l)->l_md.md_astpending &= ~X86_AST_PREEMPT) 3197f2d47d8SEvgeniy Ivanov 3207f2d47d8SEvgeniy Ivanov void cpu_boot_secondary_processors(void); 3217f2d47d8SEvgeniy Ivanov void cpu_init_idle_lwps(void); 3227f2d47d8SEvgeniy Ivanov void cpu_init_msrs(struct cpu_info *, bool); 3231cd76c75SBen Gras void cpu_load_pmap(struct pmap *, struct pmap *); 3247f2d47d8SEvgeniy Ivanov void cpu_broadcast_halt(void); 3257f2d47d8SEvgeniy Ivanov void cpu_kick(struct cpu_info *); 3267f2d47d8SEvgeniy Ivanov 3277f2d47d8SEvgeniy Ivanov #define curcpu() x86_curcpu() 3287f2d47d8SEvgeniy Ivanov #define curlwp x86_curlwp() 3297f2d47d8SEvgeniy Ivanov #define curpcb ((struct pcb *)lwp_getpcb(curlwp)) 3307f2d47d8SEvgeniy Ivanov 3317f2d47d8SEvgeniy Ivanov /* 3327f2d47d8SEvgeniy Ivanov * Arguments to hardclock, softclock and statclock 3337f2d47d8SEvgeniy Ivanov * encapsulate the previous machine state in an opaque 3347f2d47d8SEvgeniy Ivanov * clockframe; for now, use generic intrframe. 3357f2d47d8SEvgeniy Ivanov */ 3367f2d47d8SEvgeniy Ivanov struct clockframe { 3377f2d47d8SEvgeniy Ivanov struct intrframe cf_if; 3387f2d47d8SEvgeniy Ivanov }; 3397f2d47d8SEvgeniy Ivanov 3407f2d47d8SEvgeniy Ivanov /* 3417f2d47d8SEvgeniy Ivanov * Give a profiling tick to the current process when the user profiling 3427f2d47d8SEvgeniy Ivanov * buffer pages are invalid. On the i386, request an ast to send us 3437f2d47d8SEvgeniy Ivanov * through trap(), marking the proc as needing a profiling tick. 3447f2d47d8SEvgeniy Ivanov */ 3457f2d47d8SEvgeniy Ivanov extern void cpu_need_proftick(struct lwp *l); 3467f2d47d8SEvgeniy Ivanov 3477f2d47d8SEvgeniy Ivanov /* 3487f2d47d8SEvgeniy Ivanov * Notify the LWP l that it has a signal pending, process as soon as 3497f2d47d8SEvgeniy Ivanov * possible. 3507f2d47d8SEvgeniy Ivanov */ 3517f2d47d8SEvgeniy Ivanov extern void cpu_signotify(struct lwp *); 3527f2d47d8SEvgeniy Ivanov 3537f2d47d8SEvgeniy Ivanov /* 3547f2d47d8SEvgeniy Ivanov * We need a machine-independent name for this. 3557f2d47d8SEvgeniy Ivanov */ 3567f2d47d8SEvgeniy Ivanov extern void (*delay_func)(unsigned int); 3577f2d47d8SEvgeniy Ivanov struct timeval; 3587f2d47d8SEvgeniy Ivanov 3597f2d47d8SEvgeniy Ivanov #define DELAY(x) (*delay_func)(x) 3607f2d47d8SEvgeniy Ivanov #define delay(x) (*delay_func)(x) 3617f2d47d8SEvgeniy Ivanov 3627f2d47d8SEvgeniy Ivanov extern int biosbasemem; 3637f2d47d8SEvgeniy Ivanov extern int biosextmem; 3641cd76c75SBen Gras extern int cputype; 3657f2d47d8SEvgeniy Ivanov extern int cpuid_level; 3667f2d47d8SEvgeniy Ivanov extern int cpu_class; 3677f2d47d8SEvgeniy Ivanov extern char cpu_brand_string[]; 3687f2d47d8SEvgeniy Ivanov extern int use_pae; 3697f2d47d8SEvgeniy Ivanov 370*0a6a1f1dSLionel Sambuc #ifdef __i386__ 371*0a6a1f1dSLionel Sambuc extern int i386_fpu_present; 372*0a6a1f1dSLionel Sambuc int npx586bug1(int, int); 373*0a6a1f1dSLionel Sambuc extern int i386_fpu_fdivbug; 3747f2d47d8SEvgeniy Ivanov extern int i386_use_fxsave; 3757f2d47d8SEvgeniy Ivanov extern int i386_has_sse; 3767f2d47d8SEvgeniy Ivanov extern int i386_has_sse2; 377*0a6a1f1dSLionel Sambuc #else 378*0a6a1f1dSLionel Sambuc #define i386_fpu_present 1 379*0a6a1f1dSLionel Sambuc #define i386_fpu_fdivbug 0 380*0a6a1f1dSLionel Sambuc #define i386_use_fxsave 1 381*0a6a1f1dSLionel Sambuc #define i386_has_sse 1 382*0a6a1f1dSLionel Sambuc #define i386_has_sse2 1 383*0a6a1f1dSLionel Sambuc #endif 384*0a6a1f1dSLionel Sambuc 385*0a6a1f1dSLionel Sambuc extern int x86_fpu_save; 386*0a6a1f1dSLionel Sambuc #define FPU_SAVE_FSAVE 0 387*0a6a1f1dSLionel Sambuc #define FPU_SAVE_FXSAVE 1 388*0a6a1f1dSLionel Sambuc #define FPU_SAVE_XSAVE 2 389*0a6a1f1dSLionel Sambuc #define FPU_SAVE_XSAVEOPT 3 390*0a6a1f1dSLionel Sambuc extern unsigned int x86_fpu_save_size; 391*0a6a1f1dSLionel Sambuc extern uint64_t x86_xsave_features; 3927f2d47d8SEvgeniy Ivanov 3937f2d47d8SEvgeniy Ivanov extern void (*x86_cpu_idle)(void); 3947f2d47d8SEvgeniy Ivanov #define cpu_idle() (*x86_cpu_idle)() 3957f2d47d8SEvgeniy Ivanov 3967f2d47d8SEvgeniy Ivanov /* machdep.c */ 3977f2d47d8SEvgeniy Ivanov void dumpconf(void); 3987f2d47d8SEvgeniy Ivanov void cpu_reset(void); 3997f2d47d8SEvgeniy Ivanov void i386_proc0_tss_ldt_init(void); 4007f2d47d8SEvgeniy Ivanov void dumpconf(void); 4017f2d47d8SEvgeniy Ivanov void cpu_reset(void); 4027f2d47d8SEvgeniy Ivanov void x86_64_proc0_tss_ldt_init(void); 4037f2d47d8SEvgeniy Ivanov void x86_64_init_pcb_tss_ldt(struct cpu_info *); 4047f2d47d8SEvgeniy Ivanov 4057f2d47d8SEvgeniy Ivanov /* longrun.c */ 4067f2d47d8SEvgeniy Ivanov u_int tmx86_get_longrun_mode(void); 4077f2d47d8SEvgeniy Ivanov void tmx86_get_longrun_status(u_int *, u_int *, u_int *); 4087f2d47d8SEvgeniy Ivanov void tmx86_init_longrun(void); 4097f2d47d8SEvgeniy Ivanov 4107f2d47d8SEvgeniy Ivanov /* identcpu.c */ 4117f2d47d8SEvgeniy Ivanov void cpu_probe(struct cpu_info *); 4127f2d47d8SEvgeniy Ivanov void cpu_identify(struct cpu_info *); 4137f2d47d8SEvgeniy Ivanov 4147f2d47d8SEvgeniy Ivanov /* cpu_topology.c */ 4157f2d47d8SEvgeniy Ivanov void x86_cpu_topology(struct cpu_info *); 4167f2d47d8SEvgeniy Ivanov 4177f2d47d8SEvgeniy Ivanov /* vm_machdep.c */ 4187f2d47d8SEvgeniy Ivanov void cpu_proc_fork(struct proc *, struct proc *); 4197f2d47d8SEvgeniy Ivanov 4207f2d47d8SEvgeniy Ivanov /* locore.s */ 4217f2d47d8SEvgeniy Ivanov struct region_descriptor; 4227f2d47d8SEvgeniy Ivanov void lgdt(struct region_descriptor *); 4237f2d47d8SEvgeniy Ivanov #ifdef XEN 4247f2d47d8SEvgeniy Ivanov void lgdt_finish(void); 4257f2d47d8SEvgeniy Ivanov #endif 4267f2d47d8SEvgeniy Ivanov 4277f2d47d8SEvgeniy Ivanov struct pcb; 4287f2d47d8SEvgeniy Ivanov void savectx(struct pcb *); 4297f2d47d8SEvgeniy Ivanov void lwp_trampoline(void); 4307f2d47d8SEvgeniy Ivanov #ifdef XEN 4317f2d47d8SEvgeniy Ivanov void startrtclock(void); 4327f2d47d8SEvgeniy Ivanov void xen_delay(unsigned int); 4337f2d47d8SEvgeniy Ivanov void xen_initclocks(void); 4341cd76c75SBen Gras void xen_suspendclocks(struct cpu_info *); 4351cd76c75SBen Gras void xen_resumeclocks(struct cpu_info *); 4367f2d47d8SEvgeniy Ivanov #else 4377f2d47d8SEvgeniy Ivanov /* clock.c */ 4387f2d47d8SEvgeniy Ivanov void initrtclock(u_long); 4397f2d47d8SEvgeniy Ivanov void startrtclock(void); 4407f2d47d8SEvgeniy Ivanov void i8254_delay(unsigned int); 4417f2d47d8SEvgeniy Ivanov void i8254_microtime(struct timeval *); 4427f2d47d8SEvgeniy Ivanov void i8254_initclocks(void); 4437f2d47d8SEvgeniy Ivanov #endif 4447f2d47d8SEvgeniy Ivanov 4457f2d47d8SEvgeniy Ivanov /* cpu.c */ 4467f2d47d8SEvgeniy Ivanov 4477f2d47d8SEvgeniy Ivanov void cpu_probe_features(struct cpu_info *); 4487f2d47d8SEvgeniy Ivanov 4497f2d47d8SEvgeniy Ivanov /* vm_machdep.c */ 4507f2d47d8SEvgeniy Ivanov paddr_t kvtop(void *); 4517f2d47d8SEvgeniy Ivanov 4527f2d47d8SEvgeniy Ivanov #ifdef USER_LDT 4537f2d47d8SEvgeniy Ivanov /* sys_machdep.h */ 4547f2d47d8SEvgeniy Ivanov int x86_get_ldt(struct lwp *, void *, register_t *); 4557f2d47d8SEvgeniy Ivanov int x86_set_ldt(struct lwp *, void *, register_t *); 4567f2d47d8SEvgeniy Ivanov #endif 4577f2d47d8SEvgeniy Ivanov 4587f2d47d8SEvgeniy Ivanov /* isa_machdep.c */ 4597f2d47d8SEvgeniy Ivanov void isa_defaultirq(void); 4607f2d47d8SEvgeniy Ivanov int isa_nmi(void); 4617f2d47d8SEvgeniy Ivanov 4627f2d47d8SEvgeniy Ivanov #ifdef VM86 4637f2d47d8SEvgeniy Ivanov /* vm86.c */ 4647f2d47d8SEvgeniy Ivanov void vm86_gpfault(struct lwp *, int); 4657f2d47d8SEvgeniy Ivanov #endif /* VM86 */ 4667f2d47d8SEvgeniy Ivanov 4677f2d47d8SEvgeniy Ivanov /* consinit.c */ 4687f2d47d8SEvgeniy Ivanov void kgdb_port_init(void); 4697f2d47d8SEvgeniy Ivanov 4707f2d47d8SEvgeniy Ivanov /* bus_machdep.c */ 4717f2d47d8SEvgeniy Ivanov void x86_bus_space_init(void); 4727f2d47d8SEvgeniy Ivanov void x86_bus_space_mallocok(void); 4737f2d47d8SEvgeniy Ivanov 4747f2d47d8SEvgeniy Ivanov #endif /* _KERNEL */ 4757f2d47d8SEvgeniy Ivanov 4767f2d47d8SEvgeniy Ivanov #if defined(_KERNEL) || defined(_KMEMUSER) 4777f2d47d8SEvgeniy Ivanov #include <machine/psl.h> /* Must be after struct cpu_info declaration */ 4787f2d47d8SEvgeniy Ivanov #endif /* _KERNEL || __KMEMUSER */ 4797f2d47d8SEvgeniy Ivanov 4807f2d47d8SEvgeniy Ivanov /* 4817f2d47d8SEvgeniy Ivanov * CTL_MACHDEP definitions. 4827f2d47d8SEvgeniy Ivanov */ 4837f2d47d8SEvgeniy Ivanov #define CPU_CONSDEV 1 /* dev_t: console terminal device */ 4847f2d47d8SEvgeniy Ivanov #define CPU_BIOSBASEMEM 2 /* int: bios-reported base mem (K) */ 4857f2d47d8SEvgeniy Ivanov #define CPU_BIOSEXTMEM 3 /* int: bios-reported ext. mem (K) */ 4867f2d47d8SEvgeniy Ivanov /* CPU_NKPDE 4 obsolete: int: number of kernel PDEs */ 4877f2d47d8SEvgeniy Ivanov #define CPU_BOOTED_KERNEL 5 /* string: booted kernel name */ 4887f2d47d8SEvgeniy Ivanov #define CPU_DISKINFO 6 /* struct disklist *: 4897f2d47d8SEvgeniy Ivanov * disk geometry information */ 4907f2d47d8SEvgeniy Ivanov #define CPU_FPU_PRESENT 7 /* int: FPU is present */ 4917f2d47d8SEvgeniy Ivanov #define CPU_OSFXSR 8 /* int: OS uses FXSAVE/FXRSTOR */ 4927f2d47d8SEvgeniy Ivanov #define CPU_SSE 9 /* int: OS/CPU supports SSE */ 4937f2d47d8SEvgeniy Ivanov #define CPU_SSE2 10 /* int: OS/CPU supports SSE2 */ 4947f2d47d8SEvgeniy Ivanov #define CPU_TMLR_MODE 11 /* int: longrun mode 4957f2d47d8SEvgeniy Ivanov * 0: minimum frequency 4967f2d47d8SEvgeniy Ivanov * 1: economy 4977f2d47d8SEvgeniy Ivanov * 2: performance 4987f2d47d8SEvgeniy Ivanov * 3: maximum frequency 4997f2d47d8SEvgeniy Ivanov */ 5007f2d47d8SEvgeniy Ivanov #define CPU_TMLR_FREQUENCY 12 /* int: current frequency */ 5017f2d47d8SEvgeniy Ivanov #define CPU_TMLR_VOLTAGE 13 /* int: curret voltage */ 5027f2d47d8SEvgeniy Ivanov #define CPU_TMLR_PERCENTAGE 14 /* int: current clock percentage */ 5037f2d47d8SEvgeniy Ivanov #define CPU_MAXID 15 /* number of valid machdep ids */ 5047f2d47d8SEvgeniy Ivanov 5057f2d47d8SEvgeniy Ivanov /* 5067f2d47d8SEvgeniy Ivanov * Structure for CPU_DISKINFO sysctl call. 5077f2d47d8SEvgeniy Ivanov * XXX this should be somewhere else. 5087f2d47d8SEvgeniy Ivanov */ 5097f2d47d8SEvgeniy Ivanov #define MAX_BIOSDISKS 16 5107f2d47d8SEvgeniy Ivanov 5117f2d47d8SEvgeniy Ivanov struct disklist { 5127f2d47d8SEvgeniy Ivanov int dl_nbiosdisks; /* number of bios disks */ 5137f2d47d8SEvgeniy Ivanov struct biosdisk_info { 5147f2d47d8SEvgeniy Ivanov int bi_dev; /* BIOS device # (0x80 ..) */ 5157f2d47d8SEvgeniy Ivanov int bi_cyl; /* cylinders on disk */ 5167f2d47d8SEvgeniy Ivanov int bi_head; /* heads per track */ 5177f2d47d8SEvgeniy Ivanov int bi_sec; /* sectors per track */ 5187f2d47d8SEvgeniy Ivanov uint64_t bi_lbasecs; /* total sec. (iff ext13) */ 5197f2d47d8SEvgeniy Ivanov #define BIFLAG_INVALID 0x01 5207f2d47d8SEvgeniy Ivanov #define BIFLAG_EXTINT13 0x02 5217f2d47d8SEvgeniy Ivanov int bi_flags; 5227f2d47d8SEvgeniy Ivanov } dl_biosdisks[MAX_BIOSDISKS]; 5237f2d47d8SEvgeniy Ivanov 5247f2d47d8SEvgeniy Ivanov int dl_nnativedisks; /* number of native disks */ 5257f2d47d8SEvgeniy Ivanov struct nativedisk_info { 5267f2d47d8SEvgeniy Ivanov char ni_devname[16]; /* native device name */ 5277f2d47d8SEvgeniy Ivanov int ni_nmatches; /* # of matches w/ BIOS */ 5287f2d47d8SEvgeniy Ivanov int ni_biosmatches[MAX_BIOSDISKS]; /* indices in dl_biosdisks */ 5297f2d47d8SEvgeniy Ivanov } dl_nativedisks[1]; /* actually longer */ 5307f2d47d8SEvgeniy Ivanov }; 5317f2d47d8SEvgeniy Ivanov #endif /* !_X86_CPU_H_ */ 532