17bddac94SSimon Glass /* 27bddac94SSimon Glass * Copyright (c) 2014 The Chromium OS Authors. 37bddac94SSimon Glass * 452f952bfSBin Meng * Part of this file is adapted from coreboot 552f952bfSBin Meng * src/arch/x86/include/arch/cpu.h and 652f952bfSBin Meng * src/arch/x86/lib/cpu.c 752f952bfSBin Meng * 87bddac94SSimon Glass * SPDX-License-Identifier: GPL-2.0+ 97bddac94SSimon Glass */ 107bddac94SSimon Glass 1152f952bfSBin Meng #ifndef _ASM_CPU_H 1252f952bfSBin Meng #define _ASM_CPU_H 1352f952bfSBin Meng 1452f952bfSBin Meng enum { 1552f952bfSBin Meng X86_VENDOR_INVALID = 0, 1652f952bfSBin Meng X86_VENDOR_INTEL, 1752f952bfSBin Meng X86_VENDOR_CYRIX, 1852f952bfSBin Meng X86_VENDOR_AMD, 1952f952bfSBin Meng X86_VENDOR_UMC, 2052f952bfSBin Meng X86_VENDOR_NEXGEN, 2152f952bfSBin Meng X86_VENDOR_CENTAUR, 2252f952bfSBin Meng X86_VENDOR_RISE, 2352f952bfSBin Meng X86_VENDOR_TRANSMETA, 2452f952bfSBin Meng X86_VENDOR_NSC, 2552f952bfSBin Meng X86_VENDOR_SIS, 2652f952bfSBin Meng X86_VENDOR_ANY = 0xfe, 2752f952bfSBin Meng X86_VENDOR_UNKNOWN = 0xff 2852f952bfSBin Meng }; 2952f952bfSBin Meng 3052f952bfSBin Meng struct cpuid_result { 3152f952bfSBin Meng uint32_t eax; 3252f952bfSBin Meng uint32_t ebx; 3352f952bfSBin Meng uint32_t ecx; 3452f952bfSBin Meng uint32_t edx; 3552f952bfSBin Meng }; 3652f952bfSBin Meng 3752f952bfSBin Meng /* 3852f952bfSBin Meng * Generic CPUID function 3952f952bfSBin Meng */ 4052f952bfSBin Meng static inline struct cpuid_result cpuid(int op) 4152f952bfSBin Meng { 4252f952bfSBin Meng struct cpuid_result result; 4352f952bfSBin Meng asm volatile( 4452f952bfSBin Meng "mov %%ebx, %%edi;" 4552f952bfSBin Meng "cpuid;" 4652f952bfSBin Meng "mov %%ebx, %%esi;" 4752f952bfSBin Meng "mov %%edi, %%ebx;" 4852f952bfSBin Meng : "=a" (result.eax), 4952f952bfSBin Meng "=S" (result.ebx), 5052f952bfSBin Meng "=c" (result.ecx), 5152f952bfSBin Meng "=d" (result.edx) 5252f952bfSBin Meng : "0" (op) 5352f952bfSBin Meng : "edi"); 5452f952bfSBin Meng return result; 5552f952bfSBin Meng } 5652f952bfSBin Meng 5752f952bfSBin Meng /* 5852f952bfSBin Meng * Generic Extended CPUID function 5952f952bfSBin Meng */ 6052f952bfSBin Meng static inline struct cpuid_result cpuid_ext(int op, unsigned ecx) 6152f952bfSBin Meng { 6252f952bfSBin Meng struct cpuid_result result; 6352f952bfSBin Meng asm volatile( 6452f952bfSBin Meng "mov %%ebx, %%edi;" 6552f952bfSBin Meng "cpuid;" 6652f952bfSBin Meng "mov %%ebx, %%esi;" 6752f952bfSBin Meng "mov %%edi, %%ebx;" 6852f952bfSBin Meng : "=a" (result.eax), 6952f952bfSBin Meng "=S" (result.ebx), 7052f952bfSBin Meng "=c" (result.ecx), 7152f952bfSBin Meng "=d" (result.edx) 7252f952bfSBin Meng : "0" (op), "2" (ecx) 7352f952bfSBin Meng : "edi"); 7452f952bfSBin Meng return result; 7552f952bfSBin Meng } 7652f952bfSBin Meng 7752f952bfSBin Meng /* 7852f952bfSBin Meng * CPUID functions returning a single datum 7952f952bfSBin Meng */ 8052f952bfSBin Meng static inline unsigned int cpuid_eax(unsigned int op) 8152f952bfSBin Meng { 8252f952bfSBin Meng unsigned int eax; 8352f952bfSBin Meng 8452f952bfSBin Meng __asm__("mov %%ebx, %%edi;" 8552f952bfSBin Meng "cpuid;" 8652f952bfSBin Meng "mov %%edi, %%ebx;" 8752f952bfSBin Meng : "=a" (eax) 8852f952bfSBin Meng : "0" (op) 8952f952bfSBin Meng : "ecx", "edx", "edi"); 9052f952bfSBin Meng return eax; 9152f952bfSBin Meng } 9252f952bfSBin Meng 9352f952bfSBin Meng static inline unsigned int cpuid_ebx(unsigned int op) 9452f952bfSBin Meng { 9552f952bfSBin Meng unsigned int eax, ebx; 9652f952bfSBin Meng 9752f952bfSBin Meng __asm__("mov %%ebx, %%edi;" 9852f952bfSBin Meng "cpuid;" 9952f952bfSBin Meng "mov %%ebx, %%esi;" 10052f952bfSBin Meng "mov %%edi, %%ebx;" 10152f952bfSBin Meng : "=a" (eax), "=S" (ebx) 10252f952bfSBin Meng : "0" (op) 10352f952bfSBin Meng : "ecx", "edx", "edi"); 10452f952bfSBin Meng return ebx; 10552f952bfSBin Meng } 10652f952bfSBin Meng 10752f952bfSBin Meng static inline unsigned int cpuid_ecx(unsigned int op) 10852f952bfSBin Meng { 10952f952bfSBin Meng unsigned int eax, ecx; 11052f952bfSBin Meng 11152f952bfSBin Meng __asm__("mov %%ebx, %%edi;" 11252f952bfSBin Meng "cpuid;" 11352f952bfSBin Meng "mov %%edi, %%ebx;" 11452f952bfSBin Meng : "=a" (eax), "=c" (ecx) 11552f952bfSBin Meng : "0" (op) 11652f952bfSBin Meng : "edx", "edi"); 11752f952bfSBin Meng return ecx; 11852f952bfSBin Meng } 11952f952bfSBin Meng 12052f952bfSBin Meng static inline unsigned int cpuid_edx(unsigned int op) 12152f952bfSBin Meng { 12252f952bfSBin Meng unsigned int eax, edx; 12352f952bfSBin Meng 12452f952bfSBin Meng __asm__("mov %%ebx, %%edi;" 12552f952bfSBin Meng "cpuid;" 12652f952bfSBin Meng "mov %%edi, %%ebx;" 12752f952bfSBin Meng : "=a" (eax), "=d" (edx) 12852f952bfSBin Meng : "0" (op) 12952f952bfSBin Meng : "ecx", "edi"); 13052f952bfSBin Meng return edx; 13152f952bfSBin Meng } 13252f952bfSBin Meng 13352f952bfSBin Meng /* Standard macro to see if a specific flag is changeable */ 13452f952bfSBin Meng static inline int flag_is_changeable_p(uint32_t flag) 13552f952bfSBin Meng { 13652f952bfSBin Meng uint32_t f1, f2; 13752f952bfSBin Meng 13852f952bfSBin Meng asm( 13952f952bfSBin Meng "pushfl\n\t" 14052f952bfSBin Meng "pushfl\n\t" 14152f952bfSBin Meng "popl %0\n\t" 14252f952bfSBin Meng "movl %0,%1\n\t" 14352f952bfSBin Meng "xorl %2,%0\n\t" 14452f952bfSBin Meng "pushl %0\n\t" 14552f952bfSBin Meng "popfl\n\t" 14652f952bfSBin Meng "pushfl\n\t" 14752f952bfSBin Meng "popl %0\n\t" 14852f952bfSBin Meng "popfl\n\t" 14952f952bfSBin Meng : "=&r" (f1), "=&r" (f2) 15052f952bfSBin Meng : "ir" (flag)); 15152f952bfSBin Meng return ((f1^f2) & flag) != 0; 15252f952bfSBin Meng } 1537bddac94SSimon Glass 154*837a136fSSimon Glass static inline void mfence(void) 155*837a136fSSimon Glass { 156*837a136fSSimon Glass __asm__ __volatile__("mfence" : : : "memory"); 157*837a136fSSimon Glass } 158*837a136fSSimon Glass 1597bddac94SSimon Glass /** 1607bddac94SSimon Glass * cpu_enable_paging_pae() - Enable PAE-paging 1617bddac94SSimon Glass * 16252f952bfSBin Meng * @cr3: Value to set in cr3 (PDPT or PML4T) 1637bddac94SSimon Glass */ 1647bddac94SSimon Glass void cpu_enable_paging_pae(ulong cr3); 1657bddac94SSimon Glass 1667bddac94SSimon Glass /** 1677bddac94SSimon Glass * cpu_disable_paging_pae() - Disable paging and PAE 1687bddac94SSimon Glass */ 1697bddac94SSimon Glass void cpu_disable_paging_pae(void); 1707bddac94SSimon Glass 17192cc94a1SSimon Glass /** 17292cc94a1SSimon Glass * cpu_has_64bit() - Check if the CPU has 64-bit support 17392cc94a1SSimon Glass * 17492cc94a1SSimon Glass * @return 1 if this CPU supports long mode (64-bit), 0 if not 17592cc94a1SSimon Glass */ 17692cc94a1SSimon Glass int cpu_has_64bit(void); 17792cc94a1SSimon Glass 178200182a7SSimon Glass /** 17952f952bfSBin Meng * cpu_vendor_name() - Get CPU vendor name 18052f952bfSBin Meng * 18152f952bfSBin Meng * @vendor: CPU vendor enumeration number 18252f952bfSBin Meng * 18352f952bfSBin Meng * @return: Address to hold the CPU vendor name string 18452f952bfSBin Meng */ 18552f952bfSBin Meng const char *cpu_vendor_name(int vendor); 18652f952bfSBin Meng 187727c1a98SSimon Glass #define CPU_MAX_NAME_LEN 49 188727c1a98SSimon Glass 18952f952bfSBin Meng /** 190727c1a98SSimon Glass * cpu_get_name() - Get the name of the current cpu 19152f952bfSBin Meng * 192727c1a98SSimon Glass * @name: Place to put name, which must be CPU_MAX_NAME_LEN bytes including 193727c1a98SSimon Glass * @return pointer to name, which will likely be a few bytes after the start 194727c1a98SSimon Glass * of @name 195727c1a98SSimon Glass * \0 terminator 19652f952bfSBin Meng */ 197727c1a98SSimon Glass char *cpu_get_name(char *name); 19852f952bfSBin Meng 19952f952bfSBin Meng /** 200200182a7SSimon Glass * cpu_call64() - Jump to a 64-bit Linux kernel (internal function) 201200182a7SSimon Glass * 202200182a7SSimon Glass * The kernel is uncompressed and the 64-bit entry point is expected to be 203200182a7SSimon Glass * at @target. 204200182a7SSimon Glass * 205200182a7SSimon Glass * This function is used internally - see cpu_jump_to_64bit() for a more 206200182a7SSimon Glass * useful function. 207200182a7SSimon Glass * 208200182a7SSimon Glass * @pgtable: Address of 24KB area containing the page table 209200182a7SSimon Glass * @setup_base: Pointer to the setup.bin information for the kernel 210200182a7SSimon Glass * @target: Pointer to the start of the kernel image 211200182a7SSimon Glass */ 212200182a7SSimon Glass void cpu_call64(ulong pgtable, ulong setup_base, ulong target); 213200182a7SSimon Glass 214200182a7SSimon Glass /** 215200182a7SSimon Glass * cpu_jump_to_64bit() - Jump to a 64-bit Linux kernel 216200182a7SSimon Glass * 217200182a7SSimon Glass * The kernel is uncompressed and the 64-bit entry point is expected to be 218200182a7SSimon Glass * at @target. 219200182a7SSimon Glass * 220200182a7SSimon Glass * @setup_base: Pointer to the setup.bin information for the kernel 221200182a7SSimon Glass * @target: Pointer to the start of the kernel image 222200182a7SSimon Glass */ 223200182a7SSimon Glass int cpu_jump_to_64bit(ulong setup_base, ulong target); 224200182a7SSimon Glass 2257bddac94SSimon Glass #endif 226