1*305d28e7Sbluhm /* $OpenBSD: cpufunc.h,v 1.43 2024/11/08 12:08:22 bluhm Exp $ */ 2f5df1827Smickey /* $NetBSD: cpufunc.h,v 1.3 2003/05/08 10:27:43 fvdl Exp $ */ 3f5df1827Smickey 4f5df1827Smickey /*- 5f5df1827Smickey * Copyright (c) 1998 The NetBSD Foundation, Inc. 6f5df1827Smickey * All rights reserved. 7f5df1827Smickey * 8f5df1827Smickey * This code is derived from software contributed to The NetBSD Foundation 9f5df1827Smickey * by Charles M. Hannum. 10f5df1827Smickey * 11f5df1827Smickey * Redistribution and use in source and binary forms, with or without 12f5df1827Smickey * modification, are permitted provided that the following conditions 13f5df1827Smickey * are met: 14f5df1827Smickey * 1. Redistributions of source code must retain the above copyright 15f5df1827Smickey * notice, this list of conditions and the following disclaimer. 16f5df1827Smickey * 2. Redistributions in binary form must reproduce the above copyright 17f5df1827Smickey * notice, this list of conditions and the following disclaimer in the 18f5df1827Smickey * documentation and/or other materials provided with the distribution. 19f5df1827Smickey * 20f5df1827Smickey * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21f5df1827Smickey * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22f5df1827Smickey * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23f5df1827Smickey * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24f5df1827Smickey * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25f5df1827Smickey * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26f5df1827Smickey * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27f5df1827Smickey * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28f5df1827Smickey * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29f5df1827Smickey * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30f5df1827Smickey * POSSIBILITY OF SUCH DAMAGE. 31f5df1827Smickey */ 32f5df1827Smickey 332fa72412Spirofti #ifndef _MACHINE_CPUFUNC_H_ 342fa72412Spirofti #define _MACHINE_CPUFUNC_H_ 35f5df1827Smickey 36f5df1827Smickey /* 37f5df1827Smickey * Functions to provide access to i386-specific instructions. 38f5df1827Smickey */ 39f5df1827Smickey 40f5df1827Smickey #include <sys/types.h> 41f5df1827Smickey 42f5df1827Smickey #include <machine/specialreg.h> 43f5df1827Smickey 44f9b85086Sderaadt #if defined(_KERNEL) && !defined (_STANDALONE) 45f5df1827Smickey 46f5df1827Smickey static __inline void 47f5df1827Smickey invlpg(u_int64_t addr) 48f5df1827Smickey { 492df76cc2Sguenther __asm volatile("invlpg (%0)" : : "r" (addr) : "memory"); 50f5df1827Smickey } 51f5df1827Smickey 52f5df1827Smickey static __inline void 535845e8e5Smlarkin sidt(void *p) 545845e8e5Smlarkin { 555845e8e5Smlarkin __asm volatile("sidt (%0)" : : "r" (p) : "memory"); 565845e8e5Smlarkin } 575845e8e5Smlarkin 585845e8e5Smlarkin static __inline void 59f5df1827Smickey lidt(void *p) 60f5df1827Smickey { 612df76cc2Sguenther __asm volatile("lidt (%0)" : : "r" (p) : "memory"); 62f5df1827Smickey } 63f5df1827Smickey 64f5df1827Smickey static __inline void 655845e8e5Smlarkin sgdt(void *p) 665845e8e5Smlarkin { 675845e8e5Smlarkin __asm volatile("sgdt (%0)" : : "r" (p) : "memory"); 685845e8e5Smlarkin } 695845e8e5Smlarkin 705845e8e5Smlarkin static __inline void 715845e8e5Smlarkin bare_lgdt(struct region_descriptor *p) 725845e8e5Smlarkin { 735845e8e5Smlarkin __asm volatile("lgdt (%0)" : : "r" (p) : "memory"); 745845e8e5Smlarkin } 755845e8e5Smlarkin 765845e8e5Smlarkin static __inline void 775845e8e5Smlarkin sldt(u_short *sel) 785845e8e5Smlarkin { 795845e8e5Smlarkin __asm volatile("sldt (%0)" : : "r" (sel) : "memory"); 805845e8e5Smlarkin } 815845e8e5Smlarkin 825845e8e5Smlarkin static __inline void 83f5df1827Smickey lldt(u_short sel) 84f5df1827Smickey { 852df76cc2Sguenther __asm volatile("lldt %0" : : "r" (sel)); 86f5df1827Smickey } 87f5df1827Smickey 88f5df1827Smickey static __inline void 89f5df1827Smickey ltr(u_short sel) 90f5df1827Smickey { 912df76cc2Sguenther __asm volatile("ltr %0" : : "r" (sel)); 92f5df1827Smickey } 93f5df1827Smickey 94f5df1827Smickey static __inline void 95f5df1827Smickey lcr8(u_int val) 96f5df1827Smickey { 97f5df1827Smickey u_int64_t val64 = val; 982df76cc2Sguenther __asm volatile("movq %0,%%cr8" : : "r" (val64)); 99f5df1827Smickey } 100f5df1827Smickey 101f5df1827Smickey /* 102f5df1827Smickey * Upper 32 bits are reserved anyway, so just keep this 32bits. 103f5df1827Smickey */ 104f5df1827Smickey static __inline void 105f5df1827Smickey lcr0(u_int val) 106f5df1827Smickey { 107f5df1827Smickey u_int64_t val64 = val; 1082df76cc2Sguenther __asm volatile("movq %0,%%cr0" : : "r" (val64)); 109f5df1827Smickey } 110f5df1827Smickey 111f5df1827Smickey static __inline u_int 112f5df1827Smickey rcr0(void) 113f5df1827Smickey { 114f5df1827Smickey u_int64_t val64; 115f5df1827Smickey u_int val; 1162df76cc2Sguenther __asm volatile("movq %%cr0,%0" : "=r" (val64)); 117f5df1827Smickey val = val64; 118f5df1827Smickey return val; 119f5df1827Smickey } 120f5df1827Smickey 121f5df1827Smickey static __inline u_int64_t 122f5df1827Smickey rcr2(void) 123f5df1827Smickey { 124f5df1827Smickey u_int64_t val; 1252df76cc2Sguenther __asm volatile("movq %%cr2,%0" : "=r" (val)); 126f5df1827Smickey return val; 127f5df1827Smickey } 128f5df1827Smickey 129f5df1827Smickey static __inline void 130f5df1827Smickey lcr3(u_int64_t val) 131f5df1827Smickey { 1322df76cc2Sguenther __asm volatile("movq %0,%%cr3" : : "r" (val)); 133f5df1827Smickey } 134f5df1827Smickey 135f5df1827Smickey static __inline u_int64_t 136f5df1827Smickey rcr3(void) 137f5df1827Smickey { 138f5df1827Smickey u_int64_t val; 1392df76cc2Sguenther __asm volatile("movq %%cr3,%0" : "=r" (val)); 140f5df1827Smickey return val; 141f5df1827Smickey } 142f5df1827Smickey 143f5df1827Smickey /* 144f5df1827Smickey * Same as for cr0. Don't touch upper 32 bits. 145f5df1827Smickey */ 146f5df1827Smickey static __inline void 147f5df1827Smickey lcr4(u_int val) 148f5df1827Smickey { 149f5df1827Smickey u_int64_t val64 = val; 150f5df1827Smickey 1512df76cc2Sguenther __asm volatile("movq %0,%%cr4" : : "r" (val64)); 152f5df1827Smickey } 153f5df1827Smickey 154f5df1827Smickey static __inline u_int 155f5df1827Smickey rcr4(void) 156f5df1827Smickey { 157f5df1827Smickey u_int64_t val64; 1582df76cc2Sguenther __asm volatile("movq %%cr4,%0" : "=r" (val64)); 159c61a50a0Sderaadt return (u_int) val64; 160f5df1827Smickey } 161f5df1827Smickey 162f5df1827Smickey static __inline void 163f5df1827Smickey tlbflush(void) 164f5df1827Smickey { 165f5df1827Smickey u_int64_t val; 1662df76cc2Sguenther __asm volatile("movq %%cr3,%0" : "=r" (val)); 1672df76cc2Sguenther __asm volatile("movq %0,%%cr3" : : "r" (val)); 168f5df1827Smickey } 169f5df1827Smickey 170f95e373fSguenther static inline void 171f95e373fSguenther invpcid(uint64_t type, paddr_t pcid, paddr_t addr) 172f95e373fSguenther { 173f95e373fSguenther uint64_t desc[2] = { pcid, addr }; 174f95e373fSguenther asm volatile("invpcid %0,%1" : : "m"(desc[0]), "r"(type)); 175f95e373fSguenther } 176f95e373fSguenther #define INVPCID_ADDR 0 177f95e373fSguenther #define INVPCID_PCID 1 178f95e373fSguenther #define INVPCID_ALL 2 179f95e373fSguenther #define INVPCID_NON_GLOBAL 3 180f95e373fSguenther 181f5df1827Smickey #ifdef notyet 182f5df1827Smickey void setidt(int idx, /*XXX*/caddr_t func, int typ, int dpl); 183f5df1827Smickey #endif 184f5df1827Smickey 185f5df1827Smickey 186f5df1827Smickey /* XXXX ought to be in psl.h with spl() functions */ 187f5df1827Smickey 188f5df1827Smickey static __inline u_long 189f5df1827Smickey read_rflags(void) 190f5df1827Smickey { 191f5df1827Smickey u_long ef; 192f5df1827Smickey 1932df76cc2Sguenther __asm volatile("pushfq; popq %0" : "=r" (ef)); 194f5df1827Smickey return (ef); 195f5df1827Smickey } 196f5df1827Smickey 197f5df1827Smickey static __inline void 198f5df1827Smickey write_rflags(u_long ef) 199f5df1827Smickey { 2002df76cc2Sguenther __asm volatile("pushq %0; popfq" : : "r" (ef)); 201f5df1827Smickey } 202f5df1827Smickey 20382ffe153Skettenis static __inline void 20482ffe153Skettenis intr_enable(void) 20582ffe153Skettenis { 2060db9c031Skettenis __asm volatile("sti"); 20782ffe153Skettenis } 20882ffe153Skettenis 2096950c8e2Smpi static __inline u_long 2106950c8e2Smpi intr_disable(void) 2116950c8e2Smpi { 2126950c8e2Smpi u_long ef; 2136950c8e2Smpi 2146950c8e2Smpi ef = read_rflags(); 2150db9c031Skettenis __asm volatile("cli"); 2166950c8e2Smpi return (ef); 2176950c8e2Smpi } 2186950c8e2Smpi 2196950c8e2Smpi static __inline void 2206950c8e2Smpi intr_restore(u_long ef) 2216950c8e2Smpi { 2226950c8e2Smpi write_rflags(ef); 2236950c8e2Smpi } 2246950c8e2Smpi 225f5df1827Smickey static __inline u_int64_t 226f5df1827Smickey rdmsr(u_int msr) 227f5df1827Smickey { 228f5df1827Smickey uint32_t hi, lo; 2292df76cc2Sguenther __asm volatile("rdmsr" : "=d" (hi), "=a" (lo) : "c" (msr)); 230f5df1827Smickey return (((uint64_t)hi << 32) | (uint64_t) lo); 231f5df1827Smickey } 232f5df1827Smickey 233e9e0c464Sderaadt static __inline int 234e9e0c464Sderaadt rdpkru(u_int ecx) 235e9e0c464Sderaadt { 236e9e0c464Sderaadt uint32_t edx, pkru; 237e9e0c464Sderaadt asm volatile("rdpkru " : "=a" (pkru), "=d" (edx) : "c" (ecx)); 238e9e0c464Sderaadt return pkru; 239e9e0c464Sderaadt } 240e9e0c464Sderaadt 241f5df1827Smickey static __inline void 2427d13b9d9Sguenther wrpkru(u_int ecx, uint32_t pkru) 24389e94d10Sdv { 2447d13b9d9Sguenther uint32_t edx = 0; 2457d13b9d9Sguenther asm volatile("wrpkru" : : "a" (pkru), "c" (ecx), "d" (edx)); 24689e94d10Sdv } 24789e94d10Sdv 24889e94d10Sdv static __inline void 249f5df1827Smickey wrmsr(u_int msr, u_int64_t newval) 250f5df1827Smickey { 2512df76cc2Sguenther __asm volatile("wrmsr" : 252f5df1827Smickey : "a" (newval & 0xffffffff), "d" (newval >> 32), "c" (msr)); 253f5df1827Smickey } 254f5df1827Smickey 255d279ab14Stom /* 256d279ab14Stom * Some of the undocumented AMD64 MSRs need a 'passcode' to access. 257d279ab14Stom * 258d279ab14Stom * See LinuxBIOSv2: src/cpu/amd/model_fxx/model_fxx_init.c 259d279ab14Stom */ 260d279ab14Stom 261d279ab14Stom #define OPTERON_MSR_PASSCODE 0x9c5a203a 262d279ab14Stom 263d279ab14Stom static __inline u_int64_t 264d279ab14Stom rdmsr_locked(u_int msr, u_int code) 265d279ab14Stom { 266e4dc6a9fSderaadt uint32_t hi, lo; 2672df76cc2Sguenther __asm volatile("rdmsr" 268e4dc6a9fSderaadt : "=d" (hi), "=a" (lo) 269d279ab14Stom : "c" (msr), "D" (code)); 270e4dc6a9fSderaadt return (((uint64_t)hi << 32) | (uint64_t) lo); 271d279ab14Stom } 272d279ab14Stom 273d279ab14Stom static __inline void 274d279ab14Stom wrmsr_locked(u_int msr, u_int code, u_int64_t newval) 275d279ab14Stom { 2762df76cc2Sguenther __asm volatile("wrmsr" : 277e4dc6a9fSderaadt : "a" (newval & 0xffffffff), "d" (newval >> 32), "c" (msr), "D" (code)); 278d279ab14Stom } 279d279ab14Stom 280f5df1827Smickey static __inline void 281f5df1827Smickey wbinvd(void) 282f5df1827Smickey { 283728dd5ccSbluhm __asm volatile("wbinvd" : : : "memory"); 284f5df1827Smickey } 285f5df1827Smickey 2863fb0e55cSjsg #ifdef MULTIPROCESSOR 2873fb0e55cSjsg int wbinvd_on_all_cpus(void); 288daa3eda4Sbluhm void wbinvd_on_all_cpus_acked(void); 2893fb0e55cSjsg #else 2903fb0e55cSjsg static inline int 2913fb0e55cSjsg wbinvd_on_all_cpus(void) 2923fb0e55cSjsg { 2933fb0e55cSjsg wbinvd(); 2943fb0e55cSjsg return 0; 2953fb0e55cSjsg } 296*305d28e7Sbluhm 297*305d28e7Sbluhm static inline int 298*305d28e7Sbluhm wbinvd_on_all_cpus_acked(void) 299*305d28e7Sbluhm { 300*305d28e7Sbluhm wbinvd(); 301*305d28e7Sbluhm return 0; 302*305d28e7Sbluhm } 303*305d28e7Sbluhm #endif /* MULTIPROCESSOR */ 3043fb0e55cSjsg 305432a1d93Soga static __inline void 306432a1d93Soga clflush(u_int64_t addr) 307432a1d93Soga { 3082df76cc2Sguenther __asm volatile("clflush %0" : "+m" (*(volatile char *)addr)); 309432a1d93Soga } 310432a1d93Soga 311432a1d93Soga static __inline void 312432a1d93Soga mfence(void) 313432a1d93Soga { 3142df76cc2Sguenther __asm volatile("mfence" : : : "memory"); 315432a1d93Soga } 316432a1d93Soga 317f5df1827Smickey static __inline u_int64_t 318f5df1827Smickey rdtsc(void) 319f5df1827Smickey { 320f5df1827Smickey uint32_t hi, lo; 321f5df1827Smickey 3222df76cc2Sguenther __asm volatile("rdtsc" : "=d" (hi), "=a" (lo)); 323f5df1827Smickey return (((uint64_t)hi << 32) | (uint64_t) lo); 324f5df1827Smickey } 325f5df1827Smickey 326f5df1827Smickey static __inline u_int64_t 327d55ef580Srobert rdtscp(void) 328d55ef580Srobert { 329d55ef580Srobert uint32_t hi, lo; 330d55ef580Srobert 331d55ef580Srobert __asm volatile("rdtscp" : "=d" (hi), "=a" (lo) : : "ecx"); 332d55ef580Srobert return (((uint64_t)hi << 32) | (uint64_t) lo); 333d55ef580Srobert } 334d55ef580Srobert 335d55ef580Srobert static __inline u_int64_t 3366112a61fSkettenis rdtsc_lfence(void) 3376112a61fSkettenis { 3386112a61fSkettenis uint32_t hi, lo; 3396112a61fSkettenis 3406112a61fSkettenis __asm volatile("lfence; rdtsc" : "=d" (hi), "=a" (lo)); 3416112a61fSkettenis return (((uint64_t)hi << 32) | (uint64_t) lo); 3426112a61fSkettenis } 3436112a61fSkettenis 3446112a61fSkettenis static __inline u_int64_t 345f5df1827Smickey rdpmc(u_int pmc) 346f5df1827Smickey { 347f5df1827Smickey uint32_t hi, lo; 348f5df1827Smickey 3492df76cc2Sguenther __asm volatile("rdpmc" : "=d" (hi), "=a" (lo) : "c" (pmc)); 350f5df1827Smickey return (((uint64_t)hi << 32) | (uint64_t) lo); 351f5df1827Smickey } 352f5df1827Smickey 3536e1e92d4Sguenther static __inline void 3546e1e92d4Sguenther monitor(const volatile void *addr, u_long extensions, u_int hints) 3556e1e92d4Sguenther { 3566e1e92d4Sguenther 3572df76cc2Sguenther __asm volatile("monitor" 3586e1e92d4Sguenther : : "a" (addr), "c" (extensions), "d" (hints)); 3596e1e92d4Sguenther } 3606e1e92d4Sguenther 3616e1e92d4Sguenther static __inline void 3626e1e92d4Sguenther mwait(u_long extensions, u_int hints) 3636e1e92d4Sguenther { 3646e1e92d4Sguenther 365a4858df8Sguenther __asm volatile( 366a4858df8Sguenther " mwait ;" 367a4858df8Sguenther " mov $8,%%rcx ;" 368a4858df8Sguenther " .align 16,0x90 ;" 369a4858df8Sguenther "3: call 5f ;" 370a4858df8Sguenther "4: pause ;" 371a1fa3538Sguenther " lfence ;" 372a4858df8Sguenther " call 4b ;" 373a4858df8Sguenther " .align 16,0xcc ;" 374a4858df8Sguenther "5: call 7f ;" 375a4858df8Sguenther "6: pause ;" 376a1fa3538Sguenther " lfence ;" 377a4858df8Sguenther " call 6b ;" 378a4858df8Sguenther " .align 16,0xcc ;" 379a4858df8Sguenther "7: loop 3b ;" 380a4858df8Sguenther " add $(16*8),%%rsp" 3819d94673fSguenther : "+c" (extensions) : "a" (hints)); 3826e1e92d4Sguenther } 3836e1e92d4Sguenther 384b03cf8e0Skettenis static __inline void 385b03cf8e0Skettenis xsetbv(uint32_t reg, uint64_t mask) 386b03cf8e0Skettenis { 387b03cf8e0Skettenis uint32_t lo, hi; 388b03cf8e0Skettenis 389b03cf8e0Skettenis lo = mask; 390b03cf8e0Skettenis hi = mask >> 32; 391b03cf8e0Skettenis __asm volatile("xsetbv" :: "c" (reg), "a" (lo), "d" (hi) : "memory"); 392b03cf8e0Skettenis } 393b03cf8e0Skettenis 394c86bb406Smlarkin static __inline uint64_t 395c86bb406Smlarkin xgetbv(uint32_t reg) 396c86bb406Smlarkin { 397c86bb406Smlarkin uint32_t lo, hi; 398c86bb406Smlarkin 399c86bb406Smlarkin __asm volatile("xgetbv" : "=a" (lo), "=d" (hi) : "c" (reg)); 400c86bb406Smlarkin 401c86bb406Smlarkin return (((uint64_t)hi << 32) | (uint64_t)lo); 402c86bb406Smlarkin } 403c86bb406Smlarkin 404368e368bSmlarkin static __inline void 405368e368bSmlarkin stgi(void) 406368e368bSmlarkin { 407368e368bSmlarkin __asm volatile("stgi"); 408368e368bSmlarkin } 409368e368bSmlarkin 410368e368bSmlarkin static __inline void 411368e368bSmlarkin clgi(void) 412368e368bSmlarkin { 413368e368bSmlarkin __asm volatile("clgi"); 414368e368bSmlarkin } 415368e368bSmlarkin 416f4c36297Smpi /* Break into DDB. */ 417f5df1827Smickey static __inline void 418f5df1827Smickey breakpoint(void) 419f5df1827Smickey { 4202df76cc2Sguenther __asm volatile("int $3"); 421f5df1827Smickey } 422f5df1827Smickey 423d279ab14Stom void amd64_errata(struct cpu_info *); 424b4ccf14aSpatrick void cpu_ucode_setup(void); 425448c3487Spatrick void cpu_ucode_apply(struct cpu_info *); 426d279ab14Stom 427b767b017Sguenther struct cpu_info_full; 428b767b017Sguenther void cpu_enter_pages(struct cpu_info_full *); 429b767b017Sguenther 4306f4c4614Smlarkin int rdmsr_safe(u_int msr, uint64_t *); 4316f4c4614Smlarkin 432f5df1827Smickey #endif /* _KERNEL */ 433f5df1827Smickey 4342fa72412Spirofti #endif /* !_MACHINE_CPUFUNC_H_ */ 435