Skip to content
This repository was archived by the owner on Jan 28, 2023. It is now read-only.

Commit 4247f6c

Browse files
committed
Added VMCS-cache macros
Signed-off-by: Alexandro Sanchez Bach <asanchez@kryptoslogic.com>
1 parent 7562d10 commit 4247f6c

File tree

3 files changed

+284
-0
lines changed

3 files changed

+284
-0
lines changed

core/include/vmx.h

Lines changed: 266 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/*
22
* Copyright (c) 2009 Intel Corporation
3+
* Copyright (c) 2018 Kryptos Logic
34
*
45
* Redistribution and use in source and binary forms, with or without
56
* modification, are permitted provided that the following conditions are met:
@@ -257,6 +258,208 @@ enum component_index_t {
257258

258259
typedef enum component_index_t component_index_t;
259260

261+
// VMCS component types
262+
#define COMP_TYPE_W_16 uint16_t
263+
#define COMP_TYPE_W_32 uint32_t
264+
#define COMP_TYPE_W_64 uint64_t
265+
#ifdef HAX_ARCH_X86_64
266+
#define COMP_TYPE_W_UL uint64_t
267+
#else
268+
#define COMP_TYPE_W_UL uint32_t
269+
#endif
270+
271+
/**
272+
* VMCS Cache
273+
* ==========
274+
* Stores all VMCS components declared through the macro
275+
* COMP(cache_r, cache_w, width, value), with the arguments:
276+
* - cache_r: Boolean value to toggle read-cache:
277+
* - 0 Reading cache disabled
278+
* - 1 Reading cache enabled
279+
* - cache_w: Boolean value to toggle write-cache:
280+
* - 0 Writing cache disabled
281+
* - 1 Writing cache enabled
282+
* - width: Component width.
283+
* - W_16 (0): 16-bit unsigned integer.
284+
* - W_64 (1): 64-bit unsigned integer.
285+
* - W_32 (2): 32-bit unsigned integer.
286+
* - W_UL (3): Natural-width unsigned integer.
287+
* - name: Component name, defined as encoding value.
288+
*
289+
* For optimal memory packing, components should be declared
290+
* in the following order: W_64, W_UL, W_32, W_16.
291+
*/
292+
#define VMCS_COMPS \
293+
/* 64-bit components */ \
294+
COMP(1, 1, W_64, VMX_IO_BITMAP_A) \
295+
COMP(0, 0, W_64, VMX_IO_BITMAP_B) \
296+
COMP(0, 0, W_64, VMX_MSR_BITMAP) \
297+
COMP(0, 0, W_64, VMX_EXIT_MSR_STORE_ADDRESS) \
298+
COMP(0, 0, W_64, VMX_EXIT_MSR_LOAD_ADDRESS) \
299+
COMP(0, 0, W_64, VMX_ENTRY_MSR_LOAD_ADDRESS) \
300+
COMP(0, 0, W_64, VMX_TSC_OFFSET) \
301+
COMP(0, 0, W_64, VMX_VAPIC_PAGE) \
302+
COMP(0, 0, W_64, VMX_APIC_ACCESS_PAGE) \
303+
COMP(0, 0, W_64, VMX_EPTP) \
304+
COMP(0, 0, W_64, VM_EXIT_INFO_GUEST_PHYSICAL_ADDRESS) \
305+
COMP(0, 0, W_64, HOST_PAT) \
306+
COMP(0, 0, W_64, HOST_EFER) \
307+
COMP(0, 0, W_64, HOST_PERF_GLOBAL_CTRL) \
308+
COMP(0, 0, W_64, GUEST_VMCS_LINK_PTR) \
309+
COMP(0, 0, W_64, GUEST_DEBUGCTL) \
310+
COMP(0, 0, W_64, GUEST_PAT) \
311+
COMP(0, 0, W_64, GUEST_EFER) \
312+
COMP(0, 0, W_64, GUEST_PERF_GLOBAL_CTRL) \
313+
COMP(0, 0, W_64, GUEST_PDPTE0) \
314+
COMP(0, 0, W_64, GUEST_PDPTE1) \
315+
COMP(0, 0, W_64, GUEST_PDPTE2) \
316+
COMP(0, 0, W_64, GUEST_PDPTE3) \
317+
/* Natural-width components */ \
318+
COMP(0, 0, W_UL, VMX_CR0_MASK) \
319+
COMP(0, 0, W_UL, VMX_CR4_MASK) \
320+
COMP(0, 0, W_UL, VMX_CR0_READ_SHADOW) \
321+
COMP(0, 0, W_UL, VMX_CR4_READ_SHADOW) \
322+
COMP(0, 0, W_UL, VMX_CR3_TARGET_VAL_BASE) \
323+
COMP(0, 0, W_UL, VM_EXIT_INFO_QUALIFICATION) \
324+
COMP(0, 0, W_UL, VM_EXIT_INFO_IO_ECX) \
325+
COMP(0, 0, W_UL, VM_EXIT_INFO_IO_ESI) \
326+
COMP(0, 0, W_UL, VM_EXIT_INFO_IO_EDI) \
327+
COMP(0, 0, W_UL, VM_EXIT_INFO_IO_EIP) \
328+
COMP(0, 0, W_UL, VM_EXIT_INFO_GUEST_LINEAR_ADDRESS) \
329+
COMP(0, 0, W_UL, HOST_RIP) \
330+
COMP(0, 0, W_UL, HOST_RSP) \
331+
COMP(0, 0, W_UL, HOST_CR0) \
332+
COMP(0, 0, W_UL, HOST_CR3) \
333+
COMP(0, 0, W_UL, HOST_CR4) \
334+
COMP(0, 0, W_UL, HOST_FS_BASE) \
335+
COMP(0, 0, W_UL, HOST_GS_BASE) \
336+
COMP(0, 0, W_UL, HOST_TR_BASE) \
337+
COMP(0, 0, W_UL, HOST_GDTR_BASE) \
338+
COMP(0, 0, W_UL, HOST_IDTR_BASE) \
339+
COMP(0, 0, W_UL, HOST_SYSENTER_ESP) \
340+
COMP(0, 0, W_UL, HOST_SYSENTER_EIP) \
341+
COMP(0, 0, W_UL, GUEST_RIP) \
342+
COMP(0, 0, W_UL, GUEST_RFLAGS) \
343+
COMP(0, 0, W_UL, GUEST_RSP) \
344+
COMP(0, 0, W_UL, GUEST_CR0) \
345+
COMP(0, 0, W_UL, GUEST_CR3) \
346+
COMP(0, 0, W_UL, GUEST_CR4) \
347+
COMP(0, 0, W_UL, GUEST_ES_BASE) \
348+
COMP(0, 0, W_UL, GUEST_CS_BASE) \
349+
COMP(0, 0, W_UL, GUEST_SS_BASE) \
350+
COMP(0, 0, W_UL, GUEST_DS_BASE) \
351+
COMP(0, 0, W_UL, GUEST_FS_BASE) \
352+
COMP(0, 0, W_UL, GUEST_GS_BASE) \
353+
COMP(0, 0, W_UL, GUEST_LDTR_BASE) \
354+
COMP(0, 0, W_UL, GUEST_TR_BASE) \
355+
COMP(0, 0, W_UL, GUEST_GDTR_BASE) \
356+
COMP(0, 0, W_UL, GUEST_IDTR_BASE) \
357+
COMP(0, 0, W_UL, GUEST_DR7) \
358+
COMP(0, 0, W_UL, GUEST_PENDING_DBE) \
359+
COMP(0, 0, W_UL, GUEST_SYSENTER_ESP) \
360+
COMP(0, 0, W_UL, GUEST_SYSENTER_EIP) \
361+
/* 32-bit components */ \
362+
COMP(0, 0, W_32, VMX_PIN_CONTROLS) \
363+
COMP(0, 0, W_32, VMX_PRIMARY_PROCESSOR_CONTROLS) \
364+
COMP(0, 0, W_32, VMX_SECONDARY_PROCESSOR_CONTROLS) \
365+
COMP(0, 0, W_32, VMX_EXCEPTION_BITMAP) \
366+
COMP(0, 0, W_32, VMX_PAGE_FAULT_ERROR_CODE_MASK) \
367+
COMP(0, 0, W_32, VMX_PAGE_FAULT_ERROR_CODE_MATCH) \
368+
COMP(0, 0, W_32, VMX_EXIT_CONTROLS) \
369+
COMP(0, 0, W_32, VMX_EXIT_MSR_STORE_COUNT) \
370+
COMP(0, 0, W_32, VMX_EXIT_MSR_LOAD_COUNT) \
371+
COMP(0, 0, W_32, VMX_ENTRY_CONTROLS) \
372+
COMP(0, 0, W_32, VMX_ENTRY_MSR_LOAD_COUNT) \
373+
COMP(0, 0, W_32, VMX_ENTRY_INTERRUPT_INFO) \
374+
COMP(0, 0, W_32, VMX_ENTRY_EXCEPTION_ERROR_CODE) \
375+
COMP(0, 0, W_32, VMX_ENTRY_INSTRUCTION_LENGTH) \
376+
COMP(0, 0, W_32, VMX_TPR_THRESHOLD) \
377+
COMP(0, 0, W_32, VMX_CR3_TARGET_COUNT) \
378+
COMP(0, 0, W_32, VMX_PREEMPTION_TIMER) \
379+
COMP(0, 0, W_32, VMX_INSTRUCTION_ERROR_CODE) \
380+
COMP(0, 0, W_32, VM_EXIT_INFO_REASON) \
381+
COMP(0, 0, W_32, VM_EXIT_INFO_INTERRUPT_INFO) \
382+
COMP(0, 0, W_32, VM_EXIT_INFO_EXCEPTION_ERROR_CODE) \
383+
COMP(0, 0, W_32, VM_EXIT_INFO_IDT_VECTORING) \
384+
COMP(0, 0, W_32, VM_EXIT_INFO_IDT_VECTORING_ERROR_CODE) \
385+
COMP(0, 0, W_32, VM_EXIT_INFO_INSTRUCTION_LENGTH) \
386+
COMP(0, 0, W_32, VM_EXIT_INFO_INSTRUCTION_INFO) \
387+
COMP(0, 0, W_32, HOST_SYSENTER_CS) \
388+
COMP(0, 0, W_32, GUEST_ES_AR) \
389+
COMP(0, 0, W_32, GUEST_CS_AR) \
390+
COMP(0, 0, W_32, GUEST_SS_AR) \
391+
COMP(0, 0, W_32, GUEST_DS_AR) \
392+
COMP(0, 0, W_32, GUEST_FS_AR) \
393+
COMP(0, 0, W_32, GUEST_GS_AR) \
394+
COMP(0, 0, W_32, GUEST_LDTR_AR) \
395+
COMP(0, 0, W_32, GUEST_TR_AR) \
396+
COMP(0, 0, W_32, GUEST_ES_LIMIT) \
397+
COMP(0, 0, W_32, GUEST_CS_LIMIT) \
398+
COMP(0, 0, W_32, GUEST_SS_LIMIT) \
399+
COMP(0, 0, W_32, GUEST_DS_LIMIT) \
400+
COMP(0, 0, W_32, GUEST_FS_LIMIT) \
401+
COMP(0, 0, W_32, GUEST_GS_LIMIT) \
402+
COMP(0, 0, W_32, GUEST_LDTR_LIMIT) \
403+
COMP(0, 0, W_32, GUEST_TR_LIMIT) \
404+
COMP(0, 0, W_32, GUEST_GDTR_LIMIT) \
405+
COMP(0, 0, W_32, GUEST_IDTR_LIMIT) \
406+
COMP(0, 0, W_32, GUEST_SYSENTER_CS) \
407+
COMP(0, 0, W_32, GUEST_SMBASE) \
408+
COMP(0, 0, W_32, GUEST_INTERRUPTIBILITY) \
409+
COMP(0, 0, W_32, GUEST_ACTIVITY_STATE) \
410+
/* 16-bit components */ \
411+
COMP(0, 0, W_16, VMX_VPID) \
412+
COMP(0, 0, W_16, HOST_CS_SELECTOR) \
413+
COMP(0, 0, W_16, HOST_DS_SELECTOR) \
414+
COMP(0, 0, W_16, HOST_ES_SELECTOR) \
415+
COMP(0, 0, W_16, HOST_FS_SELECTOR) \
416+
COMP(0, 0, W_16, HOST_GS_SELECTOR) \
417+
COMP(0, 0, W_16, HOST_SS_SELECTOR) \
418+
COMP(0, 0, W_16, HOST_TR_SELECTOR) \
419+
COMP(0, 0, W_16, GUEST_ES_SELECTOR) \
420+
COMP(0, 0, W_16, GUEST_CS_SELECTOR) \
421+
COMP(0, 0, W_16, GUEST_SS_SELECTOR) \
422+
COMP(0, 0, W_16, GUEST_DS_SELECTOR) \
423+
COMP(0, 0, W_16, GUEST_FS_SELECTOR) \
424+
COMP(0, 0, W_16, GUEST_GS_SELECTOR) \
425+
COMP(0, 0, W_16, GUEST_LDTR_SELECTOR) \
426+
COMP(0, 0, W_16, GUEST_TR_SELECTOR)
427+
428+
// Macros for declaring cache and R/W-flags declarations
429+
#define COMP_CACHE_R_0(name)
430+
#define COMP_CACHE_R_1(name) \
431+
bool name##_cache : 1;
432+
#define COMP_CACHE_W_0(name)
433+
#define COMP_CACHE_W_1(name) \
434+
bool name##_dirty : 1;
435+
436+
#define COMP_CACHE_R(cache_r, cache_w, width, name) \
437+
COMP_CACHE_R_##cache_r(name)
438+
#define COMP_CACHE_W(cache_r, cache_w, width, name) \
439+
COMP_CACHE_W_##cache_w(name)
440+
#define COMP_DECLARE(cache_r, cache_w, width, name) \
441+
COMP_TYPE_##width name##_value;
442+
443+
// Structures
444+
struct vmx_vmcs_t {
445+
#define COMP COMP_DECLARE
446+
VMCS_COMPS
447+
#undef COMP
448+
};
449+
450+
struct vmx_vmcs_cache_r_t {
451+
#define COMP COMP_CACHE_R
452+
VMCS_COMPS
453+
#undef COMP
454+
};
455+
456+
struct vmx_vmcs_cache_w_t {
457+
bool dirty : 1;
458+
#define COMP COMP_CACHE_W
459+
VMCS_COMPS
460+
#undef COMP
461+
};
462+
260463
// PIN-BASED CONTROLS
261464
#define EXT_INTERRUPT_EXITING 0x00000001
262465
#define NMI_EXITING 0x00000008
@@ -653,6 +856,11 @@ struct vcpu_state_t;
653856
struct vcpu_t;
654857

655858
struct vcpu_vmx_data {
859+
struct vcpu_t *parent;
860+
struct vmx_vmcs_t vmcs;
861+
struct vmx_vmcs_cache_r_t vmcs_cache_r;
862+
struct vmx_vmcs_cache_w_t vmcs_cache_w;
863+
656864
uint32_t pin_ctls_base;
657865
uint32_t pcpu_ctls_base;
658866
uint32_t scpu_ctls_base;
@@ -706,6 +914,64 @@ void vmx_vmwrite(struct vcpu_t *vcpu, const char *name,
706914

707915
#define vmwrite(vcpu, x, y) vmx_vmwrite(vcpu, #x, x, y)
708916

917+
/**
918+
* vmcs_read_<name>
919+
* Reads the VMCS-component <name> from the specified VCPU (cached if enabled).
920+
*/
921+
#define COMP_R_0(width, name) \
922+
static inline COMP_TYPE_##width \
923+
vmcs_read_##name(struct vcpu_vmx_data* vcpu_vmx) { \
924+
return vmread(vcpu_vmx->parent, name); \
925+
}
926+
#define COMP_R_1(width, name) \
927+
static inline COMP_TYPE_##width \
928+
vmcs_read_##name(struct vcpu_vmx_data* vcpu_vmx) { \
929+
if (vcpu_vmx->vmcs_cache_r.name##_cache) \
930+
return vcpu_vmx->vmcs.name##_value; \
931+
vcpu_vmx->vmcs.name##_value = vmread(vcpu_vmx->parent, name); \
932+
vcpu_vmx->vmcs_cache_r.name##_cache = 1; \
933+
return vcpu_vmx->vmcs.name##_value; \
934+
}
935+
936+
/**
937+
* vmcs_write_<name>
938+
* Writes the VMCS-component <name> to the specified VCPU (cached if enabled).
939+
*/
940+
#define COMP_W_0(width, name) \
941+
static inline void vmcs_write_##name(struct vcpu_vmx_data* vcpu_vmx, \
942+
COMP_TYPE_##width value) { \
943+
vmwrite(vcpu_vmx->parent, name, value); \
944+
}
945+
#define COMP_W_1(width, name) \
946+
static inline void vmcs_write_##name(struct vcpu_vmx_data* vcpu_vmx, \
947+
COMP_TYPE_##width value) { \
948+
vcpu_vmx->vmcs.name##_value = value; \
949+
vcpu_vmx->vmcs_cache_r.name##_cache = 1; \
950+
vcpu_vmx->vmcs_cache_w.name##_dirty = 1; \
951+
}
952+
953+
// Declarations
954+
#define COMP_R(cache_r, cache_w, width, name) \
955+
COMP_R_##cache_r(width, name);
956+
#define COMP_W(cache_r, cache_w, width, name) \
957+
COMP_W_##cache_w(width, name);
958+
959+
// Helper functions
960+
#define COMP COMP_R
961+
VMCS_COMPS
962+
#undef COMP
963+
964+
#define COMP COMP_W
965+
VMCS_COMPS
966+
#undef COMP
967+
968+
#define vmcs_read(vcpu, name) \
969+
vmcs_read_##name(&vcpu->vmx)
970+
#define vmcs_write(vcpu, name, value) \
971+
vmcs_write_##name(&vcpu->vmx, value)
972+
973+
void vmcs_write_pending(struct vcpu_t *vcpu);
974+
709975
#define VMREAD_SEG(vcpu, seg, val) \
710976
((val).selector = vmread(vcpu, GUEST_##seg##_SELECTOR), \
711977
(val).base = vmread(vcpu, GUEST_##seg##_BASE), \

core/vcpu.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -562,6 +562,7 @@ static void vcpu_init(struct vcpu_t *vcpu)
562562
vmx(vcpu, cr0_shadow) = 0;
563563
vmx(vcpu, cr4_mask) = 0;
564564
vmx(vcpu, cr4_shadow) = 0;
565+
vmx(vcpu, parent) = vcpu;
565566

566567
vcpu->ref_count = 1;
567568

core/vmx.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,3 +296,20 @@ void get_interruption_info_t(interruption_info_t *info, uint8_t v, uint8_t t)
296296
info->reserved = 0;
297297
info->valid = 1;
298298
}
299+
300+
#define COMP_PENDING_0(name)
301+
#define COMP_PENDING_1(name) \
302+
if (vcpu->vmx.vmcs_cache_w.name##_dirty) \
303+
vmwrite(vcpu, name, vcpu->vmx.vmcs.name##_value);
304+
#define COMP_PENDING(cache_r, cache_w, width, name) \
305+
COMP_PENDING_##cache_w(name)
306+
307+
void vmcs_write_pending(struct vcpu_t* vcpu)
308+
{
309+
if (!vcpu || !vcpu->vmx.vmcs_cache_w.dirty)
310+
return;
311+
312+
#define COMP COMP_PENDING
313+
VMCS_COMPS
314+
#undef COMP
315+
}

0 commit comments

Comments
 (0)