1/* 2 * Copyright 2014, General Dynamics C4 Systems 3 * 4 * This software may be distributed and modified according to the terms of 5 * the GNU General Public License version 2. Note that NO WARRANTY is provided. 6 * See "LICENSE_GPLv2.txt" for details. 7 * 8 * @TAG(GD_GPL) 9 */ 10 11#ifndef __MODE_MACHINE_H 12#define __MODE_MACHINE_H 13 14#include <model/statedata.h> 15#include <arch/machine/cpu_registers.h> 16#include <arch/model/smp.h> 17 18/* Address space control */ 19static inline paddr_t getCurrentPD(void) 20{ 21 return MODE_NODE_STATE(ia32KSCurrentPD); 22} 23 24static inline void setCurrentPD(paddr_t addr) 25{ 26 MODE_NODE_STATE(ia32KSCurrentPD) = addr; 27 write_cr3(addr); 28} 29 30static inline void setCurrentVSpaceRoot(paddr_t addr, word_t pcid) 31{ 32 /* pcid is not supported on ia32 and so we should always be passed zero */ 33 assert(pcid == 0); 34 setCurrentPD(addr); 35} 36 37static inline cr3_t getCurrentCR3(void) 38{ 39 /* on ia32 the PD is the full value of CR3, so we can just return that */ 40 return cr3_new(getCurrentPD()); 41} 42 43static inline void invalidateLocalTLBEntry(vptr_t vptr) 44{ 45 asm volatile("invlpg (%[vptr])" :: [vptr] "r"(vptr)); 46} 47 48/* Invalidates page structures cache */ 49static inline void invalidateLocalPageStructureCache(void) 50{ 51 /* invalidate an arbitrary line to invalidate the page structure cache */ 52 invalidateLocalTLBEntry(0); 53} 54 55static inline void invalidateLocalPageStructureCacheASID(paddr_t root, asid_t asid) 56{ 57 /* ignore asid */ 58 invalidateLocalPageStructureCache(); 59} 60 61static inline void invalidateLocalTLB(void) 62{ 63 /* rewrite the current page directory */ 64 write_cr3(MODE_NODE_STATE(ia32KSCurrentPD)); 65} 66 67static inline void invalidateLocalTranslationSingle(vptr_t vptr) 68{ 69 /* Just invalidate a single entry in the TLB */ 70 invalidateLocalTLBEntry(vptr); 71} 72 73static inline void invalidateLocalTranslationSingleASID(vptr_t vptr, asid_t asid) 74{ 75 /* no asid support in 32-bit, just invalidate TLB */ 76 invalidateLocalTLBEntry(vptr); 77} 78 79static inline void invalidateLocalTranslationAll(void) 80{ 81 invalidateLocalTLB(); 82 invalidateLocalPageStructureCache(); 83} 84 85static inline rdmsr_safe_result_t x86_rdmsr_safe(const uint32_t reg) 86{ 87 uint32_t low; 88 uint32_t high; 89 word_t returnto; 90 rdmsr_safe_result_t result; 91 asm volatile( 92 "movl $1f, (%[returnto_addr]) \n\ 93 rdmsr \n\ 94 1: \n\ 95 movl (%[returnto_addr]), %[returnto] \n\ 96 movl $0, (%[returnto_addr])" 97 : [returnto] "=&r" (returnto), 98 [high] "=&d" (high), 99 [low] "=&a" (low) 100 : [returnto_addr] "r" (&ARCH_NODE_STATE(x86KSGPExceptReturnTo)), 101 [reg] "c" (reg) 102 : "memory" 103 ); 104 result.success = returnto != 0; 105 result.value = ((uint64_t)high << 32) | (uint64_t)low; 106 return result; 107} 108 109/* GDT installation */ 110void ia32_install_gdt(gdt_idt_ptr_t* gdt_idt_ptr); 111 112/* IDT installation */ 113void ia32_install_idt(gdt_idt_ptr_t* gdt_idt_ptr); 114 115/* LDT installation */ 116void ia32_install_ldt(uint32_t ldt_sel); 117 118/* TSS installation */ 119void ia32_install_tss(uint32_t tss_sel); 120 121#if defined(CONFIG_FSGSBASE_GDT) || !defined(CONFIG_FSGSBASE_MSR) 122 123static inline void FORCE_INLINE x86_write_fs_base_impl(word_t base) 124{ 125 gdt_entry_gdt_data_ptr_set_base_low(x86KSGlobalState[CURRENT_CPU_INDEX()].x86KSgdt + GDT_IPCBUF, base); 126 gdt_entry_gdt_data_ptr_set_base_mid(x86KSGlobalState[CURRENT_CPU_INDEX()].x86KSgdt + GDT_IPCBUF, (base >> 16) & 0xFF); 127 gdt_entry_gdt_data_ptr_set_base_high(x86KSGlobalState[CURRENT_CPU_INDEX()].x86KSgdt + GDT_IPCBUF, (base >> 24) & 0xFF); 128} 129 130static inline void FORCE_INLINE x86_write_gs_base_impl(word_t base) 131{ 132 gdt_entry_gdt_data_ptr_set_base_low(x86KSGlobalState[CURRENT_CPU_INDEX()].x86KSgdt + GDT_TLS, base); 133 gdt_entry_gdt_data_ptr_set_base_mid(x86KSGlobalState[CURRENT_CPU_INDEX()].x86KSgdt + GDT_TLS, (base >> 16) & 0xFF); 134 gdt_entry_gdt_data_ptr_set_base_high(x86KSGlobalState[CURRENT_CPU_INDEX()].x86KSgdt + GDT_TLS, (base >> 24) & 0xFF); 135} 136 137#endif 138 139void ia32_load_fs(word_t selector); 140void ia32_load_gs(word_t selector); 141 142static inline void init_syscall_msrs(void) 143{ 144 fail("syscall not supported on ia32"); 145} 146 147#endif 148