From 4c87a1868835d05f1cadae7b8ad6a7c95d9d9c0e Mon Sep 17 00:00:00 2001 From: Ross Philipson Date: Tue, 14 Mar 2017 15:40:33 -0400 Subject: Initial commit of EFI TBOOT work from internal project. Signed-off-by: Ross Philipson --- tboot/include/processor.h | 340 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 340 insertions(+) create mode 100644 tboot/include/processor.h (limited to 'tboot/include/processor.h') diff --git a/tboot/include/processor.h b/tboot/include/processor.h new file mode 100644 index 0000000..83b9fe4 --- /dev/null +++ b/tboot/include/processor.h @@ -0,0 +1,340 @@ +/* Copyright (c) 1991 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +/* + * Portions copyright (c) 2010, Intel Corporation + */ + +#ifndef __PROCESSOR_H__ +#define __PROCESSOR_H__ + +/* from: @(#)specialreg.h 7.1 (Berkeley) 5/9/91 + * $FreeBSD: stable/8/sys/i386/include/specialreg.h 198989 2009-11-06 15:24:48Z attilio $ + */ + +/* + * EFLAGS bits + */ +#define X86_EFLAGS_CF 0x00000001 /* Carry Flag */ +#define X86_EFLAGS_PF 0x00000004 /* Parity Flag */ +#define X86_EFLAGS_AF 0x00000010 /* Auxillary carry Flag */ +#define X86_EFLAGS_ZF 0x00000040 /* Zero Flag */ +#define X86_EFLAGS_SF 0x00000080 /* Sign Flag */ +#define X86_EFLAGS_TF 0x00000100 /* Trap Flag */ +#define X86_EFLAGS_IF 0x00000200 /* Interrupt Flag */ +#define X86_EFLAGS_DF 0x00000400 /* Direction Flag */ +#define X86_EFLAGS_OF 0x00000800 /* Overflow Flag */ +#define X86_EFLAGS_IOPL 0x00003000 /* IOPL mask */ +#define X86_EFLAGS_NT 0x00004000 /* Nested Task */ +#define X86_EFLAGS_RF 0x00010000 /* Resume Flag */ +#define X86_EFLAGS_VM 0x00020000 /* Virtual Mode */ +#define X86_EFLAGS_AC 0x00040000 /* Alignment Check */ +#define X86_EFLAGS_VIF 0x00080000 /* Virtual Interrupt Flag */ +#define X86_EFLAGS_VIP 0x00100000 /* Virtual Interrupt Pending */ +#define X86_EFLAGS_ID 0x00200000 /* CPUID detection flag */ + +/* + * Bits in 386 special registers: + */ +#define CR0_PE 0x00000001 /* Protected mode Enable */ +#define CR0_MP 0x00000002 /* "Math" (fpu) Present */ +#define CR0_EM 0x00000004 /* EMulate FPU instructions. (trap ESC only) */ +#define CR0_TS 0x00000008 /* Task Switched (if MP, trap ESC and WAIT) */ +#define CR0_ET 0x00000010 /* Extension type */ +#define CR0_PG 0x80000000 /* PaGing enable */ + +/* + * Bits in 486 special registers: + */ +#define CR0_NE 0x00000020 /* Numeric Error enable (EX16 vs IRQ13) */ +#define CR0_WP 0x00010000 /* Write Protect (honor page protect in all modes) */ +#define CR0_AM 0x00040000 /* Alignment Mask (set to enable AC flag) */ +#define CR0_NW 0x20000000 /* Not Write-through */ +#define CR0_CD 0x40000000 /* Cache Disable */ + +/* + * Bits in PPro special registers + */ +#define CR4_VME 0x00000001 /* Virtual 8086 mode extensions */ +#define CR4_PVI 0x00000002 /* Protected-mode virtual interrupts */ +#define CR4_TSD 0x00000004 /* Time stamp disable */ +#define CR4_DE 0x00000008 /* Debugging extensions */ +#define CR4_PSE 0x00000010 /* Page size extensions */ +#define CR4_PAE 0x00000020 /* Physical address extension */ +#define CR4_MCE 0x00000040 /* Machine check enable */ +#define CR4_PGE 0x00000080 /* Page global enable */ +#define CR4_PCE 0x00000100 /* Performance monitoring counter enable */ +#define CR4_FXSR 0x00000200/* Fast FPU save/restore used by OS */ +#define CR4_XMM 0x00000400 /* enable SIMD/MMX2 to use except 16 */ +#define CR4_VMXE 0x00002000/* enable VMX */ +#define CR4_SMXE 0x00004000/* enable SMX */ +#define CR4_PCIDE 0x00020000/* enable PCID */ + +#ifndef __ASSEMBLY__ + +/* from: + * $FreeBSD: src/sys/i386/include/cpufunc.h,v 1.158 2010/01/01 20:55:11 obrien Exp $ + */ + +static inline void do_cpuid(unsigned int ax, uint32_t *p) +{ + __asm__ __volatile__ ("cpuid" + : "=a" (p[0]), "=b" (p[1]), "=c" (p[2]), "=d" (p[3]) + : "0" (ax)); +} + +static inline void do_cpuid1(unsigned int ax, unsigned int cx, uint32_t *p) +{ + __asm__ __volatile__ ("cpuid" + : "=a" (p[0]), "=b" (p[1]), "=c" (p[2]), "=d" (p[3]) + : "0" (ax), "c" (cx)); +} + +static always_inline uint32_t cpuid_eax(unsigned int op) +{ + /* eax: regs[0], ebx: regs[1], ecx: regs[2], edx: regs[3] */ + uint32_t regs[4]; + + do_cpuid(op, regs); + + return regs[0]; +} + +static always_inline uint32_t cpuid_ebx(unsigned int op) +{ + /* eax: regs[0], ebx: regs[1], ecx: regs[2], edx: regs[3] */ + uint32_t regs[4]; + + do_cpuid(op, regs); + + return regs[1]; +} + +static always_inline uint32_t cpuid_ebx1(unsigned int op1, unsigned int op2) +{ + /* eax: regs[0], ebx: regs[1], ecx: regs[2], edx: regs[3] */ + uint32_t regs[4]; + + do_cpuid1(op1, op2, regs); + + return regs[1]; +} +static always_inline uint32_t cpuid_ecx(unsigned int op) +{ + /* eax: regs[0], ebx: regs[1], ecx: regs[2], edx: regs[3] */ + uint32_t regs[4]; + + do_cpuid(op, regs); + + return regs[2]; +} + +#define CPUID_X86_FEATURE_XMM3 (1<<0) +#define CPUID_X86_FEATURE_VMX (1<<5) +#define CPUID_X86_FEATURE_SMX (1<<6) + +/* Note, removed read/write ecx, not used */ + +static inline unsigned long long read_cr0(void) +{ + unsigned long long data; + /* 64: movl -> movq */ + __asm__ __volatile__ ("movq %%cr0,%0" : "=r" (data)); + return (data); +} + +static inline void write_cr0(unsigned long long data) +{ + /* 64: movl -> movq */ + __asm__ __volatile__("movq %0,%%cr0" : : "r" (data)); +} + +static inline unsigned long long read_cr4(void) +{ + unsigned long long data; + /* 64: movl -> movq */ + __asm__ __volatile__ ("movq %%cr4,%0" : "=r" (data)); + return (data); +} + +static inline void write_cr4(unsigned long long data) +{ + /* 64: movl -> movq */ + __asm__ __volatile__ ("movq %0,%%cr4" : : "r" (data)); +} + +static inline unsigned long long read_cr3(void) +{ + unsigned long long data; + /* 64: movl -> movq */ + __asm__ __volatile__ ("movq %%cr3,%0" : "=r" (data)); + return (data); +} + +static inline void write_cr3(unsigned long long data) +{ + /* 64: movl -> movq */ + __asm__ __volatile__("movq %0,%%cr3" : : "r" (data) : "memory"); +} + +static inline uint64_t read_rflags(void) +{ + uint64_t rf; + /* 32: EFLAGS stuff __asm__ __volatile__ ("pushfl; popl %0" : "=r" (ef));*/ + __asm__ __volatile__ ("pushfq; popq %0" : "=r" (rf)); + return (rf); +} + +static inline void write_rflags(uint64_t rf) +{ + /* 32: EFLAGS stuff __asm__ __volatile__ ("pushl %0; popfl" : : "r" (ef));*/ + __asm__ __volatile__ ("pushq %0; popfq" : : "r" (rf)); +} + +static inline void disable_intr(void) +{ + __asm__ __volatile__ ("cli" : : : "memory"); +} + +static inline void enable_intr(void) +{ + __asm__ __volatile__ ("sti"); +} + +/* was ia32_pause() */ +static inline void cpu_relax(void) +{ + __asm__ __volatile__ ("pause"); +} + +static inline void halt(void) +{ + __asm__ __volatile__ ("hlt"); +} + +static inline unsigned int get_apicid(void) +{ + return cpuid_ebx(1) >> 24; +} + +static inline void wbinvd(void) +{ + __asm__ __volatile__ ("wbinvd"); +} + +static inline uint32_t bsrl(uint32_t mask) +{ + uint32_t result; + + /* 64: Ok to shift 32b mask */ + __asm__ __volatile__ ("bsrl %1,%0" : "=r" (result) : "rm" (mask) : "cc"); + return (result); +} + +static inline int fls(int mask) +{ + return (mask == 0 ? mask : (int)bsrl((u_int)mask) + 1); +} + +static always_inline void mb(void) +{ + /* 32: __asm__ __volatile__ ("lock;addl $0,0(%%esp)" : : : "memory"); */ + __asm__ __volatile__ ("lock;addq $0,0(%%rsp)" : : : "memory"); +} + +static inline void cpu_monitor(const void *addr, int extensions, int hints) +{ + /* 64: a=rax, c=rcx, d=rdx ints are 32b into ecx, edx */ + __asm __volatile__ ("monitor;" : :"a" (addr), "c" (extensions), "d"(hints)); +} + +static inline void cpu_mwait(int extensions, int hints) +{ + /* 64: a=rax, c=rcx ints are 32b into eax, ecx */ + __asm __volatile__ ("mwait;" : :"a" (hints), "c" (extensions)); +} + +static inline void flush_tlb(void) +{ + __asm__ __volatile__ ( + "movq %%cr3, %%rax\n" + "movq %%rax, %%cr3\n" + : : : "rax"); +} + +typedef struct __packed lmode_desc { + uint16_t limit; + uint64_t base; +} lmode_desc_t; + +static inline void store_gdt(lmode_desc_t *gdt) +{ + __asm__ __volatile__("sgdt %0\n\t" + : "=m" (*gdt) : : "memory"); +} + +static inline void store_idt(lmode_desc_t *idt) +{ + __asm__ __volatile__("sidt %0\n\t" + : "=m" (*idt): : "memory"); +} + +#define lea_reference(i, o) __asm__ __volatile__ \ + ("lea "#i"(%%rip), %%rax\n\t" : "=a" (o)) + +#define mov_sel(r, o) __asm__ __volatile__ \ + ("movw %%"#r"s, %0\n\t" : "=m" (o) : : "memory"); + +/* In inline asm, these 3 use the A constraint to specify the EDX:EAX register + * pair. The inline assembler was getting the code badly wrong so the + * implementation of these moved to the assembly module (and renamed). + */ +uint64_t read_msr(uint32_t msr); +void write_msr(uint32_t msr, uint64_t newval); +uint64_t read_tsc(void); + +uint64_t get_rip(void); +uint64_t bsp_stack_ref(void); + +#define rdmsr read_msr +#define wrmsr write_msr +#define rdtsc read_tsc + +#endif /* __ASSEMBLY__ */ + +#endif /* __PROCESSOR_H__ */ + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ -- cgit v1.2.3