forked from luck/tmp_suning_uos_patched
KVM: x86: cache maxphyaddr CPUID leaf in struct kvm_vcpu
cpuid_maxphyaddr(), which performs lot of memory accesses is called extensively across KVM, especially in nVMX code. This patch adds a cached value of maxphyaddr to vcpu.arch to reduce the pressure onto CPU cache and simplify the code of cpuid_maxphyaddr() callers. The cached value is initialized in kvm_arch_vcpu_init() and reloaded every time CPUID is updated by usermode. It is obvious that these reloads occur infrequently. Signed-off-by: Eugene Korenevsky <ekorenevsky@gmail.com> Message-Id: <20150329205612.GA1223@gnote> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
80f0e95d1b
commit
5a4f55cde8
@ -426,6 +426,9 @@ struct kvm_vcpu_arch {
|
||||
|
||||
int cpuid_nent;
|
||||
struct kvm_cpuid_entry2 cpuid_entries[KVM_MAX_CPUID_ENTRIES];
|
||||
|
||||
int maxphyaddr;
|
||||
|
||||
/* emulate context */
|
||||
|
||||
struct x86_emulate_ctxt emulate_ctxt;
|
||||
@ -1124,7 +1127,6 @@ int kvm_unmap_hva_range(struct kvm *kvm, unsigned long start, unsigned long end)
|
||||
int kvm_age_hva(struct kvm *kvm, unsigned long start, unsigned long end);
|
||||
int kvm_test_age_hva(struct kvm *kvm, unsigned long hva);
|
||||
void kvm_set_spte_hva(struct kvm *kvm, unsigned long hva, pte_t pte);
|
||||
int cpuid_maxphyaddr(struct kvm_vcpu *vcpu);
|
||||
int kvm_cpu_has_injectable_intr(struct kvm_vcpu *v);
|
||||
int kvm_cpu_has_interrupt(struct kvm_vcpu *vcpu);
|
||||
int kvm_arch_interrupt_allowed(struct kvm_vcpu *vcpu);
|
||||
|
@ -104,6 +104,9 @@ int kvm_update_cpuid(struct kvm_vcpu *vcpu)
|
||||
((best->eax & 0xff00) >> 8) != 0)
|
||||
return -EINVAL;
|
||||
|
||||
/* Update physical-address width */
|
||||
vcpu->arch.maxphyaddr = cpuid_query_maxphyaddr(vcpu);
|
||||
|
||||
kvm_pmu_cpuid_update(vcpu);
|
||||
return 0;
|
||||
}
|
||||
@ -135,6 +138,21 @@ static void cpuid_fix_nx_cap(struct kvm_vcpu *vcpu)
|
||||
}
|
||||
}
|
||||
|
||||
int cpuid_query_maxphyaddr(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
struct kvm_cpuid_entry2 *best;
|
||||
|
||||
best = kvm_find_cpuid_entry(vcpu, 0x80000000, 0);
|
||||
if (!best || best->eax < 0x80000008)
|
||||
goto not_found;
|
||||
best = kvm_find_cpuid_entry(vcpu, 0x80000008, 0);
|
||||
if (best)
|
||||
return best->eax & 0xff;
|
||||
not_found:
|
||||
return 36;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cpuid_query_maxphyaddr);
|
||||
|
||||
/* when an old userspace process fills a new kernel module */
|
||||
int kvm_vcpu_ioctl_set_cpuid(struct kvm_vcpu *vcpu,
|
||||
struct kvm_cpuid *cpuid,
|
||||
@ -757,21 +775,6 @@ struct kvm_cpuid_entry2 *kvm_find_cpuid_entry(struct kvm_vcpu *vcpu,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(kvm_find_cpuid_entry);
|
||||
|
||||
int cpuid_maxphyaddr(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
struct kvm_cpuid_entry2 *best;
|
||||
|
||||
best = kvm_find_cpuid_entry(vcpu, 0x80000000, 0);
|
||||
if (!best || best->eax < 0x80000008)
|
||||
goto not_found;
|
||||
best = kvm_find_cpuid_entry(vcpu, 0x80000008, 0);
|
||||
if (best)
|
||||
return best->eax & 0xff;
|
||||
not_found:
|
||||
return 36;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cpuid_maxphyaddr);
|
||||
|
||||
/*
|
||||
* If no match is found, check whether we exceed the vCPU's limit
|
||||
* and return the content of the highest valid _standard_ leaf instead.
|
||||
|
@ -20,6 +20,12 @@ int kvm_vcpu_ioctl_get_cpuid2(struct kvm_vcpu *vcpu,
|
||||
struct kvm_cpuid_entry2 __user *entries);
|
||||
void kvm_cpuid(struct kvm_vcpu *vcpu, u32 *eax, u32 *ebx, u32 *ecx, u32 *edx);
|
||||
|
||||
int cpuid_query_maxphyaddr(struct kvm_vcpu *vcpu);
|
||||
|
||||
static inline int cpuid_maxphyaddr(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
return vcpu->arch.maxphyaddr;
|
||||
}
|
||||
|
||||
static inline bool guest_cpuid_has_xsave(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
|
@ -7317,6 +7317,8 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
|
||||
vcpu->arch.guest_supported_xcr0 = 0;
|
||||
vcpu->arch.guest_xstate_size = XSAVE_HDR_SIZE + XSAVE_HDR_OFFSET;
|
||||
|
||||
vcpu->arch.maxphyaddr = cpuid_query_maxphyaddr(vcpu);
|
||||
|
||||
kvm_async_pf_hash_reset(vcpu);
|
||||
kvm_pmu_init(vcpu);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user