Skip to content

Commit 0c3566b

Browse files
committed
KVM: VMX: Extract checks on entry/exit control pairs to a helper macro
Extract the checking of entry/exit pairs to a helper macro so that the code can be reused to process the upcoming "secondary" exit controls (the primary exit controls field is out of bits). Use a macro instead of a function to support different sized variables (all secondary exit controls will be optional and so the MSR doesn't have the fixed-0/fixed-1 split). Taking the largest size as input is trivial, but handling the modification of KVM's to-be-used controls is much trickier, e.g. would require bitmap games to clear bits from a 32-bit bitmap vs. a 64-bit bitmap. Opportunistically add sanity checks to ensure the size of the controls match (yay, macro!), e.g. to detect bugs where KVM passes in the pairs for primary exit controls, but its variable for the secondary exit controls. To help users triage mismatches, print the control bits that are checked, not just the actual value. For the foreseeable future, that provides enough information for a user to determine which fields mismatched. E.g. until secondary entry controls comes along, all entry bits and thus all error messages are guaranteed to be unique. To avoid returning from a macro, which can get quite dangerous, simply process all pairs even if error_on_inconsistent_vmcs_config is set. The speed at which KVM rejects module load is not at all interesting. Keep the error message a "once" printk, even though it would be nice to print out all mismatching pairs. In practice, the most likely scenario is that a single pair will mismatch on all CPUs. Printing all mismatches generates redundant messages in that situation, and can be extremely noisy on systems with large numbers of CPUs. If a CPU has multiple mismatches, not printing every bad pair is the least of the user's concerns. Cc: Xin Li (Intel) <xin@zytor.com> Link: https://lore.kernel.org/r/20250227005353.3216123-1-seanjc@google.com Signed-off-by: Sean Christopherson <seanjc@google.com>
1 parent 64c947a commit 0c3566b

File tree

1 file changed

+31
-17
lines changed

1 file changed

+31
-17
lines changed

arch/x86/kvm/vmx/vmx.c

Lines changed: 31 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2582,6 +2582,34 @@ static u64 adjust_vmx_controls64(u64 ctl_opt, u32 msr)
25822582
return ctl_opt & allowed;
25832583
}
25842584

2585+
#define vmx_check_entry_exit_pairs(pairs, entry_controls, exit_controls) \
2586+
({ \
2587+
int i, r = 0; \
2588+
\
2589+
BUILD_BUG_ON(sizeof(pairs[0].entry_control) != sizeof(entry_controls)); \
2590+
BUILD_BUG_ON(sizeof(pairs[0].exit_control) != sizeof(exit_controls)); \
2591+
\
2592+
for (i = 0; i < ARRAY_SIZE(pairs); i++) { \
2593+
typeof(entry_controls) n_ctrl = pairs[i].entry_control; \
2594+
typeof(exit_controls) x_ctrl = pairs[i].exit_control; \
2595+
\
2596+
if (!(entry_controls & n_ctrl) == !(exit_controls & x_ctrl)) \
2597+
continue; \
2598+
\
2599+
pr_warn_once("Inconsistent VM-Entry/VM-Exit pair, " \
2600+
"entry = %llx (%llx), exit = %llx (%llx)\n", \
2601+
(u64)(entry_controls & n_ctrl), (u64)n_ctrl, \
2602+
(u64)(exit_controls & x_ctrl), (u64)x_ctrl); \
2603+
\
2604+
if (error_on_inconsistent_vmcs_config) \
2605+
r = -EIO; \
2606+
\
2607+
entry_controls &= ~n_ctrl; \
2608+
exit_controls &= ~x_ctrl; \
2609+
} \
2610+
r; \
2611+
})
2612+
25852613
static int setup_vmcs_config(struct vmcs_config *vmcs_conf,
25862614
struct vmx_capability *vmx_cap)
25872615
{
@@ -2593,7 +2621,6 @@ static int setup_vmcs_config(struct vmcs_config *vmcs_conf,
25932621
u32 _vmentry_control = 0;
25942622
u64 basic_msr;
25952623
u64 misc_msr;
2596-
int i;
25972624

25982625
/*
25992626
* LOAD/SAVE_DEBUG_CONTROLS are absent because both are mandatory.
@@ -2697,22 +2724,9 @@ static int setup_vmcs_config(struct vmcs_config *vmcs_conf,
26972724
&_vmentry_control))
26982725
return -EIO;
26992726

2700-
for (i = 0; i < ARRAY_SIZE(vmcs_entry_exit_pairs); i++) {
2701-
u32 n_ctrl = vmcs_entry_exit_pairs[i].entry_control;
2702-
u32 x_ctrl = vmcs_entry_exit_pairs[i].exit_control;
2703-
2704-
if (!(_vmentry_control & n_ctrl) == !(_vmexit_control & x_ctrl))
2705-
continue;
2706-
2707-
pr_warn_once("Inconsistent VM-Entry/VM-Exit pair, entry = %x, exit = %x\n",
2708-
_vmentry_control & n_ctrl, _vmexit_control & x_ctrl);
2709-
2710-
if (error_on_inconsistent_vmcs_config)
2711-
return -EIO;
2712-
2713-
_vmentry_control &= ~n_ctrl;
2714-
_vmexit_control &= ~x_ctrl;
2715-
}
2727+
if (vmx_check_entry_exit_pairs(vmcs_entry_exit_pairs,
2728+
_vmentry_control, _vmexit_control))
2729+
return -EIO;
27162730

27172731
/*
27182732
* Some cpus support VM_{ENTRY,EXIT}_IA32_PERF_GLOBAL_CTRL but they

0 commit comments

Comments
 (0)