Skip to content

Commit 73412df

Browse files
committed
KVM: SVM: do not allocate struct svm_cpu_data dynamically
The svm_data percpu variable is a pointer, but it is allocated via svm_hardware_setup() when KVM is loaded. Unlike hardware_enable() this means that it is never NULL for the whole lifetime of KVM, and static allocation does not waste any memory compared to the status quo. It is also more efficient and more easily handled from assembly code, so do it and don't look back. Reviewed-by: Sean Christopherson <seanjc@google.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
1 parent 181d0fb commit 73412df

3 files changed

Lines changed: 18 additions & 29 deletions

File tree

arch/x86/kvm/svm/sev.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ static void sev_asid_free(struct kvm_sev_info *sev)
196196
__set_bit(sev->asid, sev_reclaim_asid_bitmap);
197197

198198
for_each_possible_cpu(cpu) {
199-
sd = per_cpu(svm_data, cpu);
199+
sd = per_cpu_ptr(&svm_data, cpu);
200200
sd->sev_vmcbs[sev->asid] = NULL;
201201
}
202202

@@ -2600,7 +2600,7 @@ void sev_es_unmap_ghcb(struct vcpu_svm *svm)
26002600

26012601
void pre_sev_run(struct vcpu_svm *svm, int cpu)
26022602
{
2603-
struct svm_cpu_data *sd = per_cpu(svm_data, cpu);
2603+
struct svm_cpu_data *sd = per_cpu_ptr(&svm_data, cpu);
26042604
int asid = sev_get_asid(svm->vcpu.kvm);
26052605

26062606
/* Assign the asid allocated with this SEV guest */

arch/x86/kvm/svm/svm.c

Lines changed: 15 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,7 @@ struct kvm_ldttss_desc {
245245
u32 zero1;
246246
} __attribute__((packed));
247247

248-
DEFINE_PER_CPU(struct svm_cpu_data *, svm_data);
248+
DEFINE_PER_CPU(struct svm_cpu_data, svm_data);
249249

250250
/*
251251
* Only MSR_TSC_AUX is switched via the user return hook. EFER is switched via
@@ -581,12 +581,7 @@ static int svm_hardware_enable(void)
581581
pr_err("%s: err EOPNOTSUPP on %d\n", __func__, me);
582582
return -EINVAL;
583583
}
584-
sd = per_cpu(svm_data, me);
585-
if (!sd) {
586-
pr_err("%s: svm_data is NULL on %d\n", __func__, me);
587-
return -EINVAL;
588-
}
589-
584+
sd = per_cpu_ptr(&svm_data, me);
590585
sd->asid_generation = 1;
591586
sd->max_asid = cpuid_ebx(SVM_CPUID_FUNC) - 1;
592587
sd->next_asid = sd->max_asid + 1;
@@ -646,41 +641,35 @@ static int svm_hardware_enable(void)
646641

647642
static void svm_cpu_uninit(int cpu)
648643
{
649-
struct svm_cpu_data *sd = per_cpu(svm_data, cpu);
644+
struct svm_cpu_data *sd = per_cpu_ptr(&svm_data, cpu);
650645

651-
if (!sd)
646+
if (!sd->save_area)
652647
return;
653648

654-
per_cpu(svm_data, cpu) = NULL;
655649
kfree(sd->sev_vmcbs);
656650
__free_page(sd->save_area);
657-
kfree(sd);
651+
sd->save_area = NULL;
658652
}
659653

660654
static int svm_cpu_init(int cpu)
661655
{
662-
struct svm_cpu_data *sd;
656+
struct svm_cpu_data *sd = per_cpu_ptr(&svm_data, cpu);
663657
int ret = -ENOMEM;
664658

665-
sd = kzalloc(sizeof(struct svm_cpu_data), GFP_KERNEL);
666-
if (!sd)
667-
return ret;
659+
memset(sd, 0, sizeof(struct svm_cpu_data));
668660
sd->save_area = alloc_page(GFP_KERNEL | __GFP_ZERO);
669661
if (!sd->save_area)
670-
goto free_cpu_data;
662+
return ret;
671663

672664
ret = sev_cpu_init(sd);
673665
if (ret)
674666
goto free_save_area;
675667

676-
per_cpu(svm_data, cpu) = sd;
677-
678668
return 0;
679669

680670
free_save_area:
681671
__free_page(sd->save_area);
682-
free_cpu_data:
683-
kfree(sd);
672+
sd->save_area = NULL;
684673
return ret;
685674

686675
}
@@ -1424,7 +1413,7 @@ static void svm_clear_current_vmcb(struct vmcb *vmcb)
14241413
int i;
14251414

14261415
for_each_online_cpu(i)
1427-
cmpxchg(&per_cpu(svm_data, i)->current_vmcb, vmcb, NULL);
1416+
cmpxchg(per_cpu_ptr(&svm_data.current_vmcb, i), vmcb, NULL);
14281417
}
14291418

14301419
static void svm_vcpu_free(struct kvm_vcpu *vcpu)
@@ -1449,7 +1438,7 @@ static void svm_vcpu_free(struct kvm_vcpu *vcpu)
14491438
static void svm_prepare_switch_to_guest(struct kvm_vcpu *vcpu)
14501439
{
14511440
struct vcpu_svm *svm = to_svm(vcpu);
1452-
struct svm_cpu_data *sd = per_cpu(svm_data, vcpu->cpu);
1441+
struct svm_cpu_data *sd = per_cpu_ptr(&svm_data, vcpu->cpu);
14531442

14541443
if (sev_es_guest(vcpu->kvm))
14551444
sev_es_unmap_ghcb(svm);
@@ -1486,7 +1475,7 @@ static void svm_prepare_host_switch(struct kvm_vcpu *vcpu)
14861475
static void svm_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
14871476
{
14881477
struct vcpu_svm *svm = to_svm(vcpu);
1489-
struct svm_cpu_data *sd = per_cpu(svm_data, cpu);
1478+
struct svm_cpu_data *sd = per_cpu_ptr(&svm_data, cpu);
14901479

14911480
if (sd->current_vmcb != svm->vmcb) {
14921481
sd->current_vmcb = svm->vmcb;
@@ -3442,15 +3431,15 @@ static int svm_handle_exit(struct kvm_vcpu *vcpu, fastpath_t exit_fastpath)
34423431

34433432
static void reload_tss(struct kvm_vcpu *vcpu)
34443433
{
3445-
struct svm_cpu_data *sd = per_cpu(svm_data, vcpu->cpu);
3434+
struct svm_cpu_data *sd = per_cpu_ptr(&svm_data, vcpu->cpu);
34463435

34473436
sd->tss_desc->type = 9; /* available 32/64-bit TSS */
34483437
load_TR_desc();
34493438
}
34503439

34513440
static void pre_svm_run(struct kvm_vcpu *vcpu)
34523441
{
3453-
struct svm_cpu_data *sd = per_cpu(svm_data, vcpu->cpu);
3442+
struct svm_cpu_data *sd = per_cpu_ptr(&svm_data, vcpu->cpu);
34543443
struct vcpu_svm *svm = to_svm(vcpu);
34553444

34563445
/*
@@ -3919,7 +3908,7 @@ static noinstr void svm_vcpu_enter_exit(struct kvm_vcpu *vcpu)
39193908
if (sev_es_guest(vcpu->kvm)) {
39203909
__svm_sev_es_vcpu_run(svm);
39213910
} else {
3922-
struct svm_cpu_data *sd = per_cpu(svm_data, vcpu->cpu);
3911+
struct svm_cpu_data *sd = per_cpu_ptr(&svm_data, vcpu->cpu);
39233912

39243913
/*
39253914
* Use a single vmcb (vmcb01 because it's always valid) for

arch/x86/kvm/svm/svm.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,7 @@ struct svm_cpu_data {
293293
struct vmcb **sev_vmcbs;
294294
};
295295

296-
DECLARE_PER_CPU(struct svm_cpu_data *, svm_data);
296+
DECLARE_PER_CPU(struct svm_cpu_data, svm_data);
297297

298298
void recalc_intercepts(struct vcpu_svm *svm);
299299

0 commit comments

Comments
 (0)