mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 18:50:05 +01:00
x86/vmx: Internal cleanup for MSR load/save infrastructure
* Use an arch_vmx_struct local variable to reduce later code volume.
* Use start/total instead of msr_area/msr_count. This is in preparation for
more finegrained handling with later changes.
* Use ent/end pointers (again for preparation), and to make the vmx_add_msr()
logic easier to follow.
* Make the memory allocation block of vmx_add_msr() unlikely, and calculate
virt_to_maddr() just once.
No practical change to functionality.
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Acked-by: Kevin Tian <kevin.tian@intel.com>
(cherry picked from commit 94fda356fc)
This commit is contained in:
1 parent
d96893fe44
commit
df5bbf7a4a
1 file changed
+42
-34
+42
-34
@@ -1315,33 +1315,33 @@ static int construct_vmcs(struct vcpu *v)
|
||||
struct vmx_msr_entry *vmx_find_msr(uint32_t msr, enum vmx_msr_list_type type)
|
||||
{
|
||||
struct vcpu *curr = current;
|
||||
unsigned int msr_count;
|
||||
struct vmx_msr_entry *msr_area = NULL;
|
||||
unsigned int i;
|
||||
struct arch_vmx_struct *vmx = &curr->arch.hvm_vmx;
|
||||
struct vmx_msr_entry *start = NULL;
|
||||
unsigned int i, total;
|
||||
|
||||
switch ( type )
|
||||
{
|
||||
case VMX_MSR_HOST:
|
||||
msr_count = curr->arch.hvm_vmx.host_msr_count;
|
||||
msr_area = curr->arch.hvm_vmx.host_msr_area;
|
||||
start = vmx->host_msr_area;
|
||||
total = vmx->host_msr_count;
|
||||
break;
|
||||
|
||||
case VMX_MSR_GUEST:
|
||||
msr_count = curr->arch.hvm_vmx.msr_count;
|
||||
msr_area = curr->arch.hvm_vmx.msr_area;
|
||||
start = vmx->msr_area;
|
||||
total = vmx->msr_count;
|
||||
break;
|
||||
|
||||
default:
|
||||
ASSERT_UNREACHABLE();
|
||||
}
|
||||
|
||||
if ( msr_area == NULL )
|
||||
if ( !start )
|
||||
return NULL;
|
||||
|
||||
for ( i = 0; i < msr_count; i++ )
|
||||
for ( i = 0; i < total; i++ )
|
||||
{
|
||||
if ( msr_area[i].index == msr )
|
||||
return &msr_area[i];
|
||||
if ( start[i].index == msr )
|
||||
return &start[i];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
@@ -1350,19 +1350,20 @@ struct vmx_msr_entry *vmx_find_msr(uint32_t msr, enum vmx_msr_list_type type)
|
||||
int vmx_add_msr(uint32_t msr, enum vmx_msr_list_type type)
|
||||
{
|
||||
struct vcpu *curr = current;
|
||||
unsigned int idx, *msr_count;
|
||||
struct vmx_msr_entry **msr_area, *msr_area_elem;
|
||||
struct arch_vmx_struct *vmx = &curr->arch.hvm_vmx;
|
||||
struct vmx_msr_entry **ptr, *start = NULL, *ent, *end;
|
||||
unsigned int total;
|
||||
|
||||
switch ( type )
|
||||
{
|
||||
case VMX_MSR_HOST:
|
||||
msr_count = &curr->arch.hvm_vmx.host_msr_count;
|
||||
msr_area = &curr->arch.hvm_vmx.host_msr_area;
|
||||
ptr = &vmx->host_msr_area;
|
||||
total = vmx->host_msr_count;
|
||||
break;
|
||||
|
||||
case VMX_MSR_GUEST:
|
||||
msr_count = &curr->arch.hvm_vmx.msr_count;
|
||||
msr_area = &curr->arch.hvm_vmx.msr_area;
|
||||
ptr = &vmx->msr_area;
|
||||
total = vmx->msr_count;
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -1370,48 +1371,55 @@ int vmx_add_msr(uint32_t msr, enum vmx_msr_list_type type)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ( *msr_area == NULL )
|
||||
/* Allocate memory on first use. */
|
||||
if ( unlikely(!*ptr) )
|
||||
{
|
||||
if ( (*msr_area = alloc_xenheap_page()) == NULL )
|
||||
paddr_t addr;
|
||||
|
||||
if ( (*ptr = alloc_xenheap_page()) == NULL )
|
||||
return -ENOMEM;
|
||||
|
||||
addr = virt_to_maddr(*ptr);
|
||||
|
||||
switch ( type )
|
||||
{
|
||||
case VMX_MSR_HOST:
|
||||
__vmwrite(VM_EXIT_MSR_LOAD_ADDR, virt_to_maddr(*msr_area));
|
||||
__vmwrite(VM_EXIT_MSR_LOAD_ADDR, addr);
|
||||
break;
|
||||
|
||||
case VMX_MSR_GUEST:
|
||||
__vmwrite(VM_EXIT_MSR_STORE_ADDR, virt_to_maddr(*msr_area));
|
||||
__vmwrite(VM_ENTRY_MSR_LOAD_ADDR, virt_to_maddr(*msr_area));
|
||||
__vmwrite(VM_EXIT_MSR_STORE_ADDR, addr);
|
||||
__vmwrite(VM_ENTRY_MSR_LOAD_ADDR, addr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for ( idx = 0; idx < *msr_count; idx++ )
|
||||
if ( (*msr_area)[idx].index == msr )
|
||||
start = *ptr;
|
||||
end = start + total;
|
||||
|
||||
for ( ent = start; ent < end && ent->index <= msr; ++ent )
|
||||
if ( ent->index == msr )
|
||||
return 0;
|
||||
|
||||
if ( *msr_count == (PAGE_SIZE / sizeof(struct vmx_msr_entry)) )
|
||||
if ( total == (PAGE_SIZE / sizeof(*ent)) )
|
||||
return -ENOSPC;
|
||||
|
||||
msr_area_elem = *msr_area + *msr_count;
|
||||
msr_area_elem->index = msr;
|
||||
msr_area_elem->mbz = 0;
|
||||
memmove(ent + 1, ent, sizeof(*ent) * (end - ent));
|
||||
|
||||
++*msr_count;
|
||||
ent->index = msr;
|
||||
ent->mbz = 0;
|
||||
|
||||
switch ( type )
|
||||
{
|
||||
case VMX_MSR_HOST:
|
||||
rdmsrl(msr, msr_area_elem->data);
|
||||
__vmwrite(VM_EXIT_MSR_LOAD_COUNT, *msr_count);
|
||||
rdmsrl(msr, ent->data);
|
||||
__vmwrite(VM_EXIT_MSR_LOAD_COUNT, ++vmx->host_msr_count);
|
||||
break;
|
||||
|
||||
case VMX_MSR_GUEST:
|
||||
msr_area_elem->data = 0;
|
||||
__vmwrite(VM_EXIT_MSR_STORE_COUNT, *msr_count);
|
||||
__vmwrite(VM_ENTRY_MSR_LOAD_COUNT, *msr_count);
|
||||
ent->data = 0;
|
||||
__vmwrite(VM_EXIT_MSR_STORE_COUNT, ++vmx->msr_count);
|
||||
__vmwrite(VM_ENTRY_MSR_LOAD_COUNT, vmx->msr_count);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||