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:
Andrew Cooper committed 2018-08-14 17:27:26 +01:00
1 parent d96893fe44
commit df5bbf7a4a
1 file changed
+42 -34
+42 -34
View File
@@ -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;
}
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.