17bddac94SSimon Glass /* 27bddac94SSimon Glass * Copyright (c) 2014 The Chromium OS Authors. 37bddac94SSimon Glass * 4*52f952bfSBin Meng * Part of this file is adapted from coreboot 5*52f952bfSBin Meng * src/arch/x86/include/arch/cpu.h and 6*52f952bfSBin Meng * src/arch/x86/lib/cpu.c 7*52f952bfSBin Meng * 87bddac94SSimon Glass * SPDX-License-Identifier: GPL-2.0+ 97bddac94SSimon Glass */ 107bddac94SSimon Glass 11*52f952bfSBin Meng #ifndef _ASM_CPU_H 12*52f952bfSBin Meng #define _ASM_CPU_H 13*52f952bfSBin Meng 14*52f952bfSBin Meng enum { 15*52f952bfSBin Meng X86_VENDOR_INVALID = 0, 16*52f952bfSBin Meng X86_VENDOR_INTEL, 17*52f952bfSBin Meng X86_VENDOR_CYRIX, 18*52f952bfSBin Meng X86_VENDOR_AMD, 19*52f952bfSBin Meng X86_VENDOR_UMC, 20*52f952bfSBin Meng X86_VENDOR_NEXGEN, 21*52f952bfSBin Meng X86_VENDOR_CENTAUR, 22*52f952bfSBin Meng X86_VENDOR_RISE, 23*52f952bfSBin Meng X86_VENDOR_TRANSMETA, 24*52f952bfSBin Meng X86_VENDOR_NSC, 25*52f952bfSBin Meng X86_VENDOR_SIS, 26*52f952bfSBin Meng X86_VENDOR_ANY = 0xfe, 27*52f952bfSBin Meng X86_VENDOR_UNKNOWN = 0xff 28*52f952bfSBin Meng }; 29*52f952bfSBin Meng 30*52f952bfSBin Meng struct cpuid_result { 31*52f952bfSBin Meng uint32_t eax; 32*52f952bfSBin Meng uint32_t ebx; 33*52f952bfSBin Meng uint32_t ecx; 34*52f952bfSBin Meng uint32_t edx; 35*52f952bfSBin Meng }; 36*52f952bfSBin Meng 37*52f952bfSBin Meng /* 38*52f952bfSBin Meng * Generic CPUID function 39*52f952bfSBin Meng */ 40*52f952bfSBin Meng static inline struct cpuid_result cpuid(int op) 41*52f952bfSBin Meng { 42*52f952bfSBin Meng struct cpuid_result result; 43*52f952bfSBin Meng asm volatile( 44*52f952bfSBin Meng "mov %%ebx, %%edi;" 45*52f952bfSBin Meng "cpuid;" 46*52f952bfSBin Meng "mov %%ebx, %%esi;" 47*52f952bfSBin Meng "mov %%edi, %%ebx;" 48*52f952bfSBin Meng : "=a" (result.eax), 49*52f952bfSBin Meng "=S" (result.ebx), 50*52f952bfSBin Meng "=c" (result.ecx), 51*52f952bfSBin Meng "=d" (result.edx) 52*52f952bfSBin Meng : "0" (op) 53*52f952bfSBin Meng : "edi"); 54*52f952bfSBin Meng return result; 55*52f952bfSBin Meng } 56*52f952bfSBin Meng 57*52f952bfSBin Meng /* 58*52f952bfSBin Meng * Generic Extended CPUID function 59*52f952bfSBin Meng */ 60*52f952bfSBin Meng static inline struct cpuid_result cpuid_ext(int op, unsigned ecx) 61*52f952bfSBin Meng { 62*52f952bfSBin Meng struct cpuid_result result; 63*52f952bfSBin Meng asm volatile( 64*52f952bfSBin Meng "mov %%ebx, %%edi;" 65*52f952bfSBin Meng "cpuid;" 66*52f952bfSBin Meng "mov %%ebx, %%esi;" 67*52f952bfSBin Meng "mov %%edi, %%ebx;" 68*52f952bfSBin Meng : "=a" (result.eax), 69*52f952bfSBin Meng "=S" (result.ebx), 70*52f952bfSBin Meng "=c" (result.ecx), 71*52f952bfSBin Meng "=d" (result.edx) 72*52f952bfSBin Meng : "0" (op), "2" (ecx) 73*52f952bfSBin Meng : "edi"); 74*52f952bfSBin Meng return result; 75*52f952bfSBin Meng } 76*52f952bfSBin Meng 77*52f952bfSBin Meng /* 78*52f952bfSBin Meng * CPUID functions returning a single datum 79*52f952bfSBin Meng */ 80*52f952bfSBin Meng static inline unsigned int cpuid_eax(unsigned int op) 81*52f952bfSBin Meng { 82*52f952bfSBin Meng unsigned int eax; 83*52f952bfSBin Meng 84*52f952bfSBin Meng __asm__("mov %%ebx, %%edi;" 85*52f952bfSBin Meng "cpuid;" 86*52f952bfSBin Meng "mov %%edi, %%ebx;" 87*52f952bfSBin Meng : "=a" (eax) 88*52f952bfSBin Meng : "0" (op) 89*52f952bfSBin Meng : "ecx", "edx", "edi"); 90*52f952bfSBin Meng return eax; 91*52f952bfSBin Meng } 92*52f952bfSBin Meng 93*52f952bfSBin Meng static inline unsigned int cpuid_ebx(unsigned int op) 94*52f952bfSBin Meng { 95*52f952bfSBin Meng unsigned int eax, ebx; 96*52f952bfSBin Meng 97*52f952bfSBin Meng __asm__("mov %%ebx, %%edi;" 98*52f952bfSBin Meng "cpuid;" 99*52f952bfSBin Meng "mov %%ebx, %%esi;" 100*52f952bfSBin Meng "mov %%edi, %%ebx;" 101*52f952bfSBin Meng : "=a" (eax), "=S" (ebx) 102*52f952bfSBin Meng : "0" (op) 103*52f952bfSBin Meng : "ecx", "edx", "edi"); 104*52f952bfSBin Meng return ebx; 105*52f952bfSBin Meng } 106*52f952bfSBin Meng 107*52f952bfSBin Meng static inline unsigned int cpuid_ecx(unsigned int op) 108*52f952bfSBin Meng { 109*52f952bfSBin Meng unsigned int eax, ecx; 110*52f952bfSBin Meng 111*52f952bfSBin Meng __asm__("mov %%ebx, %%edi;" 112*52f952bfSBin Meng "cpuid;" 113*52f952bfSBin Meng "mov %%edi, %%ebx;" 114*52f952bfSBin Meng : "=a" (eax), "=c" (ecx) 115*52f952bfSBin Meng : "0" (op) 116*52f952bfSBin Meng : "edx", "edi"); 117*52f952bfSBin Meng return ecx; 118*52f952bfSBin Meng } 119*52f952bfSBin Meng 120*52f952bfSBin Meng static inline unsigned int cpuid_edx(unsigned int op) 121*52f952bfSBin Meng { 122*52f952bfSBin Meng unsigned int eax, edx; 123*52f952bfSBin Meng 124*52f952bfSBin Meng __asm__("mov %%ebx, %%edi;" 125*52f952bfSBin Meng "cpuid;" 126*52f952bfSBin Meng "mov %%edi, %%ebx;" 127*52f952bfSBin Meng : "=a" (eax), "=d" (edx) 128*52f952bfSBin Meng : "0" (op) 129*52f952bfSBin Meng : "ecx", "edi"); 130*52f952bfSBin Meng return edx; 131*52f952bfSBin Meng } 132*52f952bfSBin Meng 133*52f952bfSBin Meng /* Standard macro to see if a specific flag is changeable */ 134*52f952bfSBin Meng static inline int flag_is_changeable_p(uint32_t flag) 135*52f952bfSBin Meng { 136*52f952bfSBin Meng uint32_t f1, f2; 137*52f952bfSBin Meng 138*52f952bfSBin Meng asm( 139*52f952bfSBin Meng "pushfl\n\t" 140*52f952bfSBin Meng "pushfl\n\t" 141*52f952bfSBin Meng "popl %0\n\t" 142*52f952bfSBin Meng "movl %0,%1\n\t" 143*52f952bfSBin Meng "xorl %2,%0\n\t" 144*52f952bfSBin Meng "pushl %0\n\t" 145*52f952bfSBin Meng "popfl\n\t" 146*52f952bfSBin Meng "pushfl\n\t" 147*52f952bfSBin Meng "popl %0\n\t" 148*52f952bfSBin Meng "popfl\n\t" 149*52f952bfSBin Meng : "=&r" (f1), "=&r" (f2) 150*52f952bfSBin Meng : "ir" (flag)); 151*52f952bfSBin Meng return ((f1^f2) & flag) != 0; 152*52f952bfSBin Meng } 1537bddac94SSimon Glass 1547bddac94SSimon Glass /** 1557bddac94SSimon Glass * cpu_enable_paging_pae() - Enable PAE-paging 1567bddac94SSimon Glass * 157*52f952bfSBin Meng * @cr3: Value to set in cr3 (PDPT or PML4T) 1587bddac94SSimon Glass */ 1597bddac94SSimon Glass void cpu_enable_paging_pae(ulong cr3); 1607bddac94SSimon Glass 1617bddac94SSimon Glass /** 1627bddac94SSimon Glass * cpu_disable_paging_pae() - Disable paging and PAE 1637bddac94SSimon Glass */ 1647bddac94SSimon Glass void cpu_disable_paging_pae(void); 1657bddac94SSimon Glass 16692cc94a1SSimon Glass /** 16792cc94a1SSimon Glass * cpu_has_64bit() - Check if the CPU has 64-bit support 16892cc94a1SSimon Glass * 16992cc94a1SSimon Glass * @return 1 if this CPU supports long mode (64-bit), 0 if not 17092cc94a1SSimon Glass */ 17192cc94a1SSimon Glass int cpu_has_64bit(void); 17292cc94a1SSimon Glass 173200182a7SSimon Glass /** 174*52f952bfSBin Meng * cpu_vendor_name() - Get CPU vendor name 175*52f952bfSBin Meng * 176*52f952bfSBin Meng * @vendor: CPU vendor enumeration number 177*52f952bfSBin Meng * 178*52f952bfSBin Meng * @return: Address to hold the CPU vendor name string 179*52f952bfSBin Meng */ 180*52f952bfSBin Meng const char *cpu_vendor_name(int vendor); 181*52f952bfSBin Meng 182*52f952bfSBin Meng /** 183*52f952bfSBin Meng * fill_processor_name() - Get processor name 184*52f952bfSBin Meng * 185*52f952bfSBin Meng * @processor_name: Address to hold the processor name string 186*52f952bfSBin Meng */ 187*52f952bfSBin Meng void fill_processor_name(char *processor_name); 188*52f952bfSBin Meng 189*52f952bfSBin Meng /** 190200182a7SSimon Glass * cpu_call64() - Jump to a 64-bit Linux kernel (internal function) 191200182a7SSimon Glass * 192200182a7SSimon Glass * The kernel is uncompressed and the 64-bit entry point is expected to be 193200182a7SSimon Glass * at @target. 194200182a7SSimon Glass * 195200182a7SSimon Glass * This function is used internally - see cpu_jump_to_64bit() for a more 196200182a7SSimon Glass * useful function. 197200182a7SSimon Glass * 198200182a7SSimon Glass * @pgtable: Address of 24KB area containing the page table 199200182a7SSimon Glass * @setup_base: Pointer to the setup.bin information for the kernel 200200182a7SSimon Glass * @target: Pointer to the start of the kernel image 201200182a7SSimon Glass */ 202200182a7SSimon Glass void cpu_call64(ulong pgtable, ulong setup_base, ulong target); 203200182a7SSimon Glass 204200182a7SSimon Glass /** 205200182a7SSimon Glass * cpu_jump_to_64bit() - Jump to a 64-bit Linux kernel 206200182a7SSimon Glass * 207200182a7SSimon Glass * The kernel is uncompressed and the 64-bit entry point is expected to be 208200182a7SSimon Glass * at @target. 209200182a7SSimon Glass * 210200182a7SSimon Glass * @setup_base: Pointer to the setup.bin information for the kernel 211200182a7SSimon Glass * @target: Pointer to the start of the kernel image 212200182a7SSimon Glass */ 213200182a7SSimon Glass int cpu_jump_to_64bit(ulong setup_base, ulong target); 214200182a7SSimon Glass 2157bddac94SSimon Glass #endif 216