mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-15 08:26:40 +07:00
kvm: nVMX: Shadow "high" parts of shadowed 64-bit VMCS fields
Inconsistencies result from shadowing only accesses to the full 64-bits of a 64-bit VMCS field, but not shadowing accesses to the high 32-bits of the field. The "high" part of a 64-bit field should be shadowed whenever the full 64-bit field is shadowed. Signed-off-by: Jim Mattson <jmattson@google.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
5fa99cbe7b
commit
85fd514e24
@ -3764,6 +3764,25 @@ static void free_kvm_area(void)
|
||||
}
|
||||
}
|
||||
|
||||
enum vmcs_field_type {
|
||||
VMCS_FIELD_TYPE_U16 = 0,
|
||||
VMCS_FIELD_TYPE_U64 = 1,
|
||||
VMCS_FIELD_TYPE_U32 = 2,
|
||||
VMCS_FIELD_TYPE_NATURAL_WIDTH = 3
|
||||
};
|
||||
|
||||
static inline int vmcs_field_type(unsigned long field)
|
||||
{
|
||||
if (0x1 & field) /* the *_HIGH fields are all 32 bit */
|
||||
return VMCS_FIELD_TYPE_U32;
|
||||
return (field >> 13) & 0x3 ;
|
||||
}
|
||||
|
||||
static inline int vmcs_field_readonly(unsigned long field)
|
||||
{
|
||||
return (((field >> 10) & 0x3) == 1);
|
||||
}
|
||||
|
||||
static void init_vmcs_shadow_fields(void)
|
||||
{
|
||||
int i, j;
|
||||
@ -3789,14 +3808,22 @@ static void init_vmcs_shadow_fields(void)
|
||||
|
||||
/* shadowed fields guest access without vmexit */
|
||||
for (i = 0; i < max_shadow_read_write_fields; i++) {
|
||||
clear_bit(shadow_read_write_fields[i],
|
||||
vmx_vmwrite_bitmap);
|
||||
clear_bit(shadow_read_write_fields[i],
|
||||
vmx_vmread_bitmap);
|
||||
unsigned long field = shadow_read_write_fields[i];
|
||||
|
||||
clear_bit(field, vmx_vmwrite_bitmap);
|
||||
clear_bit(field, vmx_vmread_bitmap);
|
||||
if (vmcs_field_type(field) == VMCS_FIELD_TYPE_U64) {
|
||||
clear_bit(field + 1, vmx_vmwrite_bitmap);
|
||||
clear_bit(field + 1, vmx_vmread_bitmap);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < max_shadow_read_only_fields; i++) {
|
||||
unsigned long field = shadow_read_only_fields[i];
|
||||
|
||||
clear_bit(field, vmx_vmread_bitmap);
|
||||
if (vmcs_field_type(field) == VMCS_FIELD_TYPE_U64)
|
||||
clear_bit(field + 1, vmx_vmread_bitmap);
|
||||
}
|
||||
for (i = 0; i < max_shadow_read_only_fields; i++)
|
||||
clear_bit(shadow_read_only_fields[i],
|
||||
vmx_vmread_bitmap);
|
||||
}
|
||||
|
||||
static __init int alloc_kvm_area(void)
|
||||
@ -7219,25 +7246,6 @@ static int handle_vmresume(struct kvm_vcpu *vcpu)
|
||||
return nested_vmx_run(vcpu, false);
|
||||
}
|
||||
|
||||
enum vmcs_field_type {
|
||||
VMCS_FIELD_TYPE_U16 = 0,
|
||||
VMCS_FIELD_TYPE_U64 = 1,
|
||||
VMCS_FIELD_TYPE_U32 = 2,
|
||||
VMCS_FIELD_TYPE_NATURAL_WIDTH = 3
|
||||
};
|
||||
|
||||
static inline int vmcs_field_type(unsigned long field)
|
||||
{
|
||||
if (0x1 & field) /* the *_HIGH fields are all 32 bit */
|
||||
return VMCS_FIELD_TYPE_U32;
|
||||
return (field >> 13) & 0x3 ;
|
||||
}
|
||||
|
||||
static inline int vmcs_field_readonly(unsigned long field)
|
||||
{
|
||||
return (((field >> 10) & 0x3) == 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Read a vmcs12 field. Since these can have varying lengths and we return
|
||||
* one type, we chose the biggest type (u64) and zero-extend the return value
|
||||
|
Loading…
Reference in New Issue
Block a user