github.com/jlmucb/cloudproxy@v0.0.0-20170830161738-b5aa0b619bc4/cpvmm/vmm/include/hw/hw_utils.h (about) 1 /* 2 * Copyright (c) 2013 Intel Corporation 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * Unless required by applicable law or agreed to in writing, software 9 * distributed under the License is distributed on an "AS IS" BASIS, 10 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 * See the License for the specific language governing permissions and 12 * limitations under the License. 13 */ 14 15 #ifndef _HW_UTILS_H_ 16 #define _HW_UTILS_H_ 17 18 #include "vmm_defs.h" 19 #include "gdt.h" 20 21 BOOLEAN hw_rdmsr_safe(UINT32 msr_id, UINT64 *value, VECTOR_ID *fault_vector, UINT32 *error_code); 22 BOOLEAN hw_wrmsr_safe(UINT32 msr_id, UINT64 value, VECTOR_ID *fault_vector, UINT32 *error_code); 23 24 #ifdef __GNUC__ 25 26 UINT8 hw_read_port_8( UINT16 port ); 27 UINT16 hw_read_port_16( UINT16 port ); 28 UINT32 hw_read_port_32( UINT16 port ); 29 void hw_write_port_8( UINT16 port, UINT8 val8 ); 30 void hw_write_port_16( UINT16 port, UINT16 val16 ); 31 void hw_write_port_32( UINT16 port, UINT32 val32 ); 32 33 void hw_lidt(void *Source); 34 void hw_sidt(void *Destination); 35 void hw_write_msr( UINT32 msr_id, UINT64 Value ); 36 UINT64 hw_read_msr( UINT32 msr_id ); 37 38 // find first bit set 39 // forward: LSB->MSB 40 // backward: MSB->LSB 41 // Return 0 if no bits set 42 // Fills "bit_number" with the set bit position zero based 43 // BOOLEAN hw_scan_bit_forward( UINT32& bit_number, UINT32 bitset ); 44 // BOOLEAN hw_scan_bit_backward( UINT32& bit_number, UINT32 bitset ); 45 // BOOLEAN hw_scan_bit_forward64( UINT32& bit_number, UINT64 bitset ); 46 // BOOLEAN hw_scan_bit_backward64( UINT32& bit_number, UINT64 bitset ); 47 48 BOOLEAN hw_scan_bit_forward( UINT32 *bit_number_ptr, UINT32 bitset ); 49 BOOLEAN hw_scan_bit_backward( UINT32 *bit_number_ptr, UINT32 bitset ); 50 BOOLEAN hw_scan_bit_forward64( UINT32 *bit_number_ptr, UINT64 bitset ); 51 BOOLEAN hw_scan_bit_backward64( UINT32 *bit_number_ptr, UINT64 bitset ); 52 53 UINT64 hw_rdtsc(void); 54 UINT64 hw_read_cr0(void); 55 UINT64 hw_read_cr2(void); 56 UINT64 hw_read_cr3(void); 57 UINT64 hw_read_cr4(void); 58 UINT64 hw_read_cr8(void); 59 void hw_write_cr0(UINT64 Data); 60 void hw_write_cr3(UINT64 Data); 61 void hw_write_cr4(UINT64 Data); 62 void hw_write_cr8(UINT64 Data); 63 64 UINT64 hw_read_dr0(void); 65 UINT64 hw_read_dr1(void); 66 UINT64 hw_read_dr2(void); 67 UINT64 hw_read_dr3(void); 68 UINT64 hw_read_dr4(void); 69 UINT64 hw_read_dr5(void); 70 UINT64 hw_read_dr6(void); 71 UINT64 hw_read_dr7(void); 72 73 void hw_write_dr0(UINT64 value); 74 void hw_write_dr1(UINT64 value); 75 void hw_write_dr2(UINT64 value); 76 void hw_write_dr3(UINT64 value); 77 void hw_write_dr4(UINT64 value); 78 void hw_write_dr5(UINT64 value); 79 void hw_write_dr6(UINT64 value); 80 void hw_write_dr7(UINT64 value); 81 #define hw_read_dr(__dbg_reg) hw_read_dr##__dbg_reg() 82 #define hw_write_dr(__dbg_reg, __value) hw_write_dr##__dbg_reg(__value) 83 84 void hw_invlpg(void *address); 85 void hw_wbinvd(void); 86 void hw_halt( void ); 87 88 #else 89 90 extern unsigned char __inbyte( unsigned short Port ); 91 extern unsigned short _inpw( unsigned short port ); 92 extern unsigned long _inpd( unsigned short port ); 93 extern void __outbyte( unsigned short Port, unsigned char Data ); 94 extern unsigned short _outpw( unsigned short port, unsigned short dataword ); 95 extern unsigned long _outpd( unsigned short port, unsigned long dataword ); 96 extern void __lidt(void *Source); 97 extern void __sidt(void *Destination); 98 extern void __writemsr( unsigned long Register, unsigned __int64 Value ); 99 extern unsigned __int64 __readmsr( int msr_id ); 100 extern unsigned char _BitScanForward( unsigned long * Index, unsigned long Mask ); 101 extern unsigned char _BitScanReverse( unsigned long * Index, unsigned long Mask ); 102 extern unsigned char _BitScanForward64( unsigned long * Index, unsigned __int64 Mask ); 103 extern unsigned char _BitScanReverse64( unsigned long * Index, unsigned __int64 Mask ); 104 extern unsigned __int64 __rdtsc(void); 105 extern unsigned __int64 __readcr0(void); 106 extern unsigned __int64 __readcr2(void); 107 extern unsigned __int64 __readcr3(void); 108 extern unsigned __int64 __readcr4(void); 109 extern unsigned __int64 __readcr8(void); 110 extern void __writecr0(unsigned __int64 Data); 111 extern void __writecr3(unsigned __int64 Data); 112 extern void __writecr4(unsigned __int64 Data); 113 extern void __writecr8(unsigned __int64 Data); 114 extern unsigned __int64 __readdr(unsigned int DebugRegister); 115 extern void __writedr(unsigned DebugRegister, unsigned __int64 DebugValue); 116 extern void __invlpg(void* Address); 117 extern void __wbinvd(void); 118 extern void __halt( void ); 119 120 #define hw_read_port_8( port ) (UINT8)__inbyte( (unsigned short)(port)) 121 #define hw_read_port_16( port ) (UINT16)_inpw( (unsigned short)(port)) 122 #define hw_read_port_32( port ) (UINT32)_inpd( (unsigned short)(port)) 123 #define hw_write_port_8( port, data ) __outbyte( (unsigned short)(port), \ 124 (unsigned char)(data)) 125 #define hw_write_port_16( port, data ) _outpw( (unsigned short)(port), \ 126 (unsigned short)(data)) 127 #define hw_write_port_32( port, data ) _outpd( (unsigned short)(port),\ 128 (unsigned long)(data)) 129 130 #define hw_lidt( _idtr ) __lidt( _idtr ) 131 #define hw_sidt( _idtr ) __sidt( _idtr ) 132 133 #define hw_read_msr( _register ) __readmsr( _register ) 134 #define hw_write_msr( _register, _value ) __writemsr( _register, _value ) 135 136 #define hw_scan_bit_forward( _bit_number_ptr, _bitset ) \ 137 (UINT8)_BitScanForward( (unsigned long *) _bit_number_ptr, _bitset ) 138 #define hw_scan_bit_backward( _bit_number_ptr, _bitset ) \ 139 (UINT8)_BitScanReverse( (unsigned long *) _bit_number_ptr, _bitset ) 140 141 #define hw_scan_bit_forward64( _bit_number_ptr, _bitset ) \ 142 (UINT8)_BitScanForward64( (unsigned long *) _bit_number_ptr, _bitset ) 143 #define hw_scan_bit_backward64( _bit_number_ptr, _bitset ) \ 144 (UINT8)_BitScanReverse64( (unsigned long *) _bit_number_ptr, _bitset ) 145 146 #define hw_rdtsc() __rdtsc() 147 #define hw_read_cr0() __readcr0() 148 #define hw_write_cr0( _value ) __writecr0( _value ) 149 #define hw_read_cr2() __readcr2() 150 #define hw_read_cr3() __readcr3() 151 #define hw_write_cr3( _value ) __writecr3( _value ) 152 #define hw_read_cr4() __readcr4() 153 #define hw_write_cr4( _value ) __writecr4( _value ) 154 #define hw_read_cr8() __readcr8() 155 #define hw_write_cr8( _value ) __writecr8( _value ) 156 #define hw_read_dr( _index ) __readdr( _index ) 157 #define hw_write_dr( _index, _value ) __writedr( _index, _value ) 158 #define hw_invlpg(addr) __invlpg((void*)addr) 159 #define hw_wbinvd() __wbinvd() 160 #define hw_halt() __halt() 161 162 #endif // ! __GNUC__ 163 164 165 typedef struct { 166 UINT64 m_rax; 167 UINT64 m_rbx; 168 UINT64 m_rcx; 169 UINT64 m_rdx; 170 } PACKED CPUID_PARAMS; 171 172 void hw_cpuid(CPUID_PARAMS *); 173 174 typedef struct _CPUID_INFO_STRUCT { 175 int data[4]; 176 } CPUID_INFO_STRUCT; 177 178 179 // CPUID leaf and ext leaf definitions 180 #define CPUID_LEAF_1H 0x1 181 #define CPUID_LEAF_3H 0x3 182 #define CPUID_LEAF_7H 0x7 183 184 #define CPUID_SUB_LEAF_0H 0x0 //sub leaf input ECX = 0 185 186 #define CPUID_EXT_LEAF_1H 0x80000001 187 #define CPUID_EXT_LEAF_2H 0x80000002 188 189 190 // CPUID bit support for h/w features 191 #define CPUID_LEAF_1H_ECX_VMX_SUPPORT 5 // ecx bit 5 for VMX 192 #define CPUID_LEAF_1H_ECX_SMX_SUPPORT 6 // ecx bit 6 for SMX 193 #define CPUID_LEAF_1H_ECX_PCID_SUPPORT 17 // ecx bit 17 for PCID (CR4.PCIDE) 194 195 #define CPUID_EXT_LEAF_1H_EDX_SYSCALL_SYSRET 11 // edx bit 11 for syscall/ret 196 #define CPUID_EXT_LEAF_1H_EDX_RDTSCP_BIT 27 // edx bit 27 for rdtscp 197 198 // ebx bit 10 for INVPCID (INPUT leaf EAX=07H, ECX=0H) 199 #define CPUID_LEAF_7H_0H_EBX_INVPCID_BIT 10 200 201 // ebx bit 0 for supporting RDFSBASE/RDGSBASE/WRFSBASE/WRGSBASE 202 #define CPUID_LEAF_7H_0H_EBX_FSGSBASE_BIT 0 203 204 #define CPUID_VALUE_EAX( cpuid_info ) ((UINT32)((cpuid_info).data[0])) 205 #define CPUID_VALUE_EBX( cpuid_info ) ((UINT32)((cpuid_info).data[1])) 206 #define CPUID_VALUE_ECX( cpuid_info ) ((UINT32)((cpuid_info).data[2])) 207 #define CPUID_VALUE_EDX( cpuid_info ) ((UINT32)((cpuid_info).data[3])) 208 209 #define cpuid( p_cpuid_info, type ) \ 210 { \ 211 CPUID_PARAMS __cpuid_params; \ 212 __cpuid_params.m_rax = type; \ 213 hw_cpuid(&__cpuid_params); \ 214 \ 215 (p_cpuid_info)->data[0] = (UINT32)__cpuid_params.m_rax; \ 216 (p_cpuid_info)->data[1] = (UINT32)__cpuid_params.m_rbx; \ 217 (p_cpuid_info)->data[2] = (UINT32)__cpuid_params.m_rcx; \ 218 (p_cpuid_info)->data[3] = (UINT32)__cpuid_params.m_rdx; \ 219 } 220 221 INLINE UINT32 hw_read_address_size(void) 222 { 223 CPUID_INFO_STRUCT cpu_info; 224 cpuid(&cpu_info, 0x80000008); 225 return CPUID_VALUE_EAX(cpu_info); 226 } 227 228 INLINE BOOLEAN is_rdtscp_supported(void) 229 { 230 CPUID_PARAMS cpuid_params = {0,0,0,0}; 231 cpuid_params.m_rax = CPUID_EXT_LEAF_1H; 232 hw_cpuid(&cpuid_params); 233 return BIT_GET64( cpuid_params.m_rdx, CPUID_EXT_LEAF_1H_EDX_RDTSCP_BIT)? TRUE:FALSE; 234 } 235 236 237 INLINE BOOLEAN is_invpcid_supported(void) 238 { 239 CPUID_PARAMS cpuid_params = {0,0,0,0}; 240 cpuid_params.m_rax = CPUID_LEAF_7H; 241 cpuid_params.m_rcx = CPUID_SUB_LEAF_0H; 242 hw_cpuid(&cpuid_params); 243 return BIT_GET64(cpuid_params.m_rbx, CPUID_LEAF_7H_0H_EBX_INVPCID_BIT)? 244 TRUE:FALSE; 245 } 246 247 INLINE BOOLEAN is_fsgsbase_supported(void) 248 { 249 CPUID_PARAMS cpuid_params = {0,0,0,0}; 250 cpuid_params.m_rax = CPUID_LEAF_7H; 251 cpuid_params.m_rcx = CPUID_SUB_LEAF_0H; 252 hw_cpuid(&cpuid_params); 253 return BIT_GET64(cpuid_params.m_rbx, CPUID_LEAF_7H_0H_EBX_FSGSBASE_BIT)? 254 TRUE:FALSE; 255 } 256 257 258 INLINE BOOLEAN is_pcid_supported(void) 259 { 260 CPUID_PARAMS cpuid_params = {0,0,0,0}; 261 cpuid_params.m_rax = CPUID_LEAF_1H; 262 hw_cpuid(&cpuid_params); 263 return BIT_GET64( cpuid_params.m_rcx, CPUID_LEAF_1H_ECX_PCID_SUPPORT)? TRUE:FALSE; 264 } 265 266 void hw_perform_asm_iret(void); 267 void hw_lgdt(void * gdtr); 268 void hw_sgdt(void * gdtr); 269 UINT16 hw_read_cs(void); 270 void hw_write_cs(UINT16); 271 UINT16 hw_read_ds(void); 272 void hw_write_ds(UINT16); 273 UINT16 hw_read_es(void); 274 void hw_write_es(UINT16); 275 UINT16 hw_read_ss(void); 276 void hw_write_ss(UINT16); 277 UINT16 hw_read_fs(void); 278 void hw_write_fs(UINT16); 279 UINT16 hw_read_gs(void); 280 void hw_write_gs(UINT16); 281 UINT16 hw_read_tr(void); 282 void hw_write_tr(UINT16); 283 UINT16 hw_read_ldtr(void); 284 void hw_write_ldtr(UINT16); 285 286 typedef void (*main_continue_fn)(void* params); 287 void hw_set_stack_pointer(HVA new_stack_pointer, 288 main_continue_fn func, void* params); 289 UINT64 hw_read_rsp(void); 290 void hw_cpuid(CPUID_PARAMS *); 291 void hw_write_cr2( UINT64 value ); 292 293 294 #define hw_flash_tlb() hw_write_cr3(hw_read_cr3()) 295 296 void hw_reset_platform(void); 297 void hw_stall(UINT32 stall_usec); 298 void hw_calibrate_tsc_ticks_per_second(void); 299 UINT64 hw_get_tsc_ticks_per_second(void); 300 void hw_stall_using_tsc(UINT32 stall_usec); 301 302 303 // Test for ready-to-be-accepted fixed interrupts. 304 BOOLEAN hw_is_ready_interrupt_exist(void); 305 306 void hw_write_to_smi_port( 307 UINT64 * p_rax, // rcx 308 UINT64 * p_rbx, // rdx 309 UINT64 * p_rcx, // r8 310 UINT64 * p_rdx, // r9 311 UINT64 * p_rsi, // on the stack 312 UINT64 * p_rdi, // on the stack 313 UINT64 * p_rflags); // on the stack 314 void hw_enable_interrupts(void); 315 void hw_disable_interrupts(void); 316 void hw_fxsave( void* buffer ); 317 void hw_fxrestore( void* buffer ); 318 319 INLINE UINT32 hw_read_memory_mapped_register(ADDRESS base, ADDRESS offset) 320 { 321 return *((volatile UINT32 *) (base + offset)); 322 } 323 324 INLINE UINT32 hw_write_memory_mapped_register(ADDRESS base, ADDRESS offset, UINT32 value) 325 { 326 return *((volatile UINT32 *) (base + offset)) = value; 327 } 328 329 INLINE UINT64 hw_read_memory_mapped_register64(ADDRESS base, ADDRESS offset) 330 { 331 return *((volatile UINT64 *) (base + offset)); 332 } 333 334 INLINE UINT64 hw_write_memory_mapped_register64(ADDRESS base, ADDRESS offset, UINT64 value) 335 { 336 return *((volatile UINT64 *) (base + offset)) = value; 337 } 338 339 #endif // _HW_UTILS_H_ 340