Skip to content

Commit 8c82a0b

Browse files
mmhaldwmw2
authored andcommitted
KVM: Store immutable gfn_to_pfn_cache properties
Move the assignment of immutable properties @kvm, @vcpu, and @Usage to the initializer. Make _activate() and _deactivate() use stored values. Note, @len is also effectively immutable for most cases, but not in the case of the Xen runstate cache, which may be split across two pages and the length of the first segment will depend on its address. Suggested-by: Sean Christopherson <[email protected]> Signed-off-by: Michal Luczaj <[email protected]> [sean: handle @len in a separate patch] Signed-off-by: Sean Christopherson <[email protected]> [dwmw2: acknowledge that @len can actually change for some use cases] Signed-off-by: David Woodhouse <[email protected]>
1 parent 214b0a8 commit 8c82a0b

File tree

5 files changed

+69
-70
lines changed

5 files changed

+69
-70
lines changed

arch/x86/kvm/x86.c

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2317,13 +2317,11 @@ static void kvm_write_system_time(struct kvm_vcpu *vcpu, gpa_t system_time,
23172317
kvm_make_request(KVM_REQ_GLOBAL_CLOCK_UPDATE, vcpu);
23182318

23192319
/* we verify if the enable bit is set... */
2320-
if (system_time & 1) {
2321-
kvm_gpc_activate(vcpu->kvm, &vcpu->arch.pv_time, vcpu,
2322-
KVM_HOST_USES_PFN, system_time & ~1ULL,
2320+
if (system_time & 1)
2321+
kvm_gpc_activate(&vcpu->arch.pv_time, system_time & ~1ULL,
23232322
sizeof(struct pvclock_vcpu_time_info));
2324-
} else {
2325-
kvm_gpc_deactivate(vcpu->kvm, &vcpu->arch.pv_time);
2326-
}
2323+
else
2324+
kvm_gpc_deactivate(&vcpu->arch.pv_time);
23272325

23282326
return;
23292327
}
@@ -3391,7 +3389,7 @@ static int kvm_pv_enable_async_pf_int(struct kvm_vcpu *vcpu, u64 data)
33913389

33923390
static void kvmclock_reset(struct kvm_vcpu *vcpu)
33933391
{
3394-
kvm_gpc_deactivate(vcpu->kvm, &vcpu->arch.pv_time);
3392+
kvm_gpc_deactivate(&vcpu->arch.pv_time);
33953393
vcpu->arch.time = 0;
33963394
}
33973395

@@ -11542,7 +11540,7 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)
1154211540
vcpu->arch.regs_avail = ~0;
1154311541
vcpu->arch.regs_dirty = ~0;
1154411542

11545-
kvm_gpc_init(&vcpu->arch.pv_time);
11543+
kvm_gpc_init(&vcpu->arch.pv_time, vcpu->kvm, vcpu, KVM_HOST_USES_PFN);
1154611544

1154711545
if (!irqchip_in_kernel(vcpu->kvm) || kvm_vcpu_is_reset_bsp(vcpu))
1154811546
vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE;

arch/x86/kvm/xen.c

Lines changed: 30 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,12 @@ static int kvm_xen_shared_info_init(struct kvm *kvm, gfn_t gfn)
4242
int idx = srcu_read_lock(&kvm->srcu);
4343

4444
if (gfn == GPA_INVALID) {
45-
kvm_gpc_deactivate(kvm, gpc);
45+
kvm_gpc_deactivate(gpc);
4646
goto out;
4747
}
4848

4949
do {
50-
ret = kvm_gpc_activate(kvm, gpc, NULL, KVM_HOST_USES_PFN, gpa,
51-
PAGE_SIZE);
50+
ret = kvm_gpc_activate(gpc, gpa, PAGE_SIZE);
5251
if (ret)
5352
goto out;
5453

@@ -323,8 +322,8 @@ static void kvm_xen_update_runstate_guest(struct kvm_vcpu *v, bool atomic)
323322
* to the second page now because the guest changed to
324323
* 64-bit mode, the second GPC won't have been set up.
325324
*/
326-
if (kvm_gpc_activate(v->kvm, gpc2, NULL, KVM_HOST_USES_PFN,
327-
gpc1->gpa + user_len1, user_len2))
325+
if (kvm_gpc_activate(gpc2, gpc1->gpa + user_len1,
326+
user_len2))
328327
return;
329328

330329
/*
@@ -711,31 +710,27 @@ int kvm_xen_vcpu_set_attr(struct kvm_vcpu *vcpu, struct kvm_xen_vcpu_attr *data)
711710
offsetof(struct compat_vcpu_info, time));
712711

713712
if (data->u.gpa == GPA_INVALID) {
714-
kvm_gpc_deactivate(vcpu->kvm, &vcpu->arch.xen.vcpu_info_cache);
713+
kvm_gpc_deactivate(&vcpu->arch.xen.vcpu_info_cache);
715714
r = 0;
716715
break;
717716
}
718717

719-
r = kvm_gpc_activate(vcpu->kvm,
720-
&vcpu->arch.xen.vcpu_info_cache, NULL,
721-
KVM_HOST_USES_PFN, data->u.gpa,
722-
sizeof(struct vcpu_info));
718+
r = kvm_gpc_activate(&vcpu->arch.xen.vcpu_info_cache,
719+
data->u.gpa, sizeof(struct vcpu_info));
723720
if (!r)
724721
kvm_make_request(KVM_REQ_CLOCK_UPDATE, vcpu);
725722

726723
break;
727724

728725
case KVM_XEN_VCPU_ATTR_TYPE_VCPU_TIME_INFO:
729726
if (data->u.gpa == GPA_INVALID) {
730-
kvm_gpc_deactivate(vcpu->kvm,
731-
&vcpu->arch.xen.vcpu_time_info_cache);
727+
kvm_gpc_deactivate(&vcpu->arch.xen.vcpu_time_info_cache);
732728
r = 0;
733729
break;
734730
}
735731

736-
r = kvm_gpc_activate(vcpu->kvm,
737-
&vcpu->arch.xen.vcpu_time_info_cache,
738-
NULL, KVM_HOST_USES_PFN, data->u.gpa,
732+
r = kvm_gpc_activate(&vcpu->arch.xen.vcpu_time_info_cache,
733+
data->u.gpa,
739734
sizeof(struct pvclock_vcpu_time_info));
740735
if (!r)
741736
kvm_make_request(KVM_REQ_CLOCK_UPDATE, vcpu);
@@ -751,10 +746,8 @@ int kvm_xen_vcpu_set_attr(struct kvm_vcpu *vcpu, struct kvm_xen_vcpu_attr *data)
751746
if (data->u.gpa == GPA_INVALID) {
752747
r = 0;
753748
deactivate_out:
754-
kvm_gpc_deactivate(vcpu->kvm,
755-
&vcpu->arch.xen.runstate_cache);
756-
kvm_gpc_deactivate(vcpu->kvm,
757-
&vcpu->arch.xen.runstate2_cache);
749+
kvm_gpc_deactivate(&vcpu->arch.xen.runstate_cache);
750+
kvm_gpc_deactivate(&vcpu->arch.xen.runstate2_cache);
758751
break;
759752
}
760753

@@ -770,20 +763,18 @@ int kvm_xen_vcpu_set_attr(struct kvm_vcpu *vcpu, struct kvm_xen_vcpu_attr *data)
770763

771764
/* How much fits in the (first) page? */
772765
sz1 = PAGE_SIZE - (data->u.gpa & ~PAGE_MASK);
773-
r = kvm_gpc_activate(vcpu->kvm, &vcpu->arch.xen.runstate_cache,
774-
NULL, KVM_HOST_USES_PFN, data->u.gpa, sz1);
766+
r = kvm_gpc_activate(&vcpu->arch.xen.runstate_cache,
767+
data->u.gpa, sz1);
775768
if (r)
776769
goto deactivate_out;
777770

778771
/* Either map the second page, or deactivate the second GPC */
779772
if (sz1 >= sz) {
780-
kvm_gpc_deactivate(vcpu->kvm,
781-
&vcpu->arch.xen.runstate2_cache);
773+
kvm_gpc_deactivate(&vcpu->arch.xen.runstate2_cache);
782774
} else {
783775
sz2 = sz - sz1;
784776
BUG_ON((data->u.gpa + sz1) & ~PAGE_MASK);
785-
r = kvm_gpc_activate(vcpu->kvm, &vcpu->arch.xen.runstate2_cache,
786-
NULL, KVM_HOST_USES_PFN,
777+
r = kvm_gpc_activate(&vcpu->arch.xen.runstate2_cache,
787778
data->u.gpa + sz1, sz2);
788779
if (r)
789780
goto deactivate_out;
@@ -2051,37 +2042,41 @@ void kvm_xen_init_vcpu(struct kvm_vcpu *vcpu)
20512042

20522043
timer_setup(&vcpu->arch.xen.poll_timer, cancel_evtchn_poll, 0);
20532044

2054-
kvm_gpc_init(&vcpu->arch.xen.runstate_cache);
2055-
kvm_gpc_init(&vcpu->arch.xen.runstate2_cache);
2056-
kvm_gpc_init(&vcpu->arch.xen.vcpu_info_cache);
2057-
kvm_gpc_init(&vcpu->arch.xen.vcpu_time_info_cache);
2045+
kvm_gpc_init(&vcpu->arch.xen.runstate_cache, vcpu->kvm, NULL,
2046+
KVM_HOST_USES_PFN);
2047+
kvm_gpc_init(&vcpu->arch.xen.runstate2_cache, vcpu->kvm, NULL,
2048+
KVM_HOST_USES_PFN);
2049+
kvm_gpc_init(&vcpu->arch.xen.vcpu_info_cache, vcpu->kvm, NULL,
2050+
KVM_HOST_USES_PFN);
2051+
kvm_gpc_init(&vcpu->arch.xen.vcpu_time_info_cache, vcpu->kvm, NULL,
2052+
KVM_HOST_USES_PFN);
20582053
}
20592054

20602055
void kvm_xen_destroy_vcpu(struct kvm_vcpu *vcpu)
20612056
{
20622057
if (kvm_xen_timer_enabled(vcpu))
20632058
kvm_xen_stop_timer(vcpu);
20642059

2065-
kvm_gpc_deactivate(vcpu->kvm, &vcpu->arch.xen.runstate_cache);
2066-
kvm_gpc_deactivate(vcpu->kvm, &vcpu->arch.xen.runstate2_cache);
2067-
kvm_gpc_deactivate(vcpu->kvm, &vcpu->arch.xen.vcpu_info_cache);
2068-
kvm_gpc_deactivate(vcpu->kvm, &vcpu->arch.xen.vcpu_time_info_cache);
2060+
kvm_gpc_deactivate(&vcpu->arch.xen.runstate_cache);
2061+
kvm_gpc_deactivate(&vcpu->arch.xen.runstate2_cache);
2062+
kvm_gpc_deactivate(&vcpu->arch.xen.vcpu_info_cache);
2063+
kvm_gpc_deactivate(&vcpu->arch.xen.vcpu_time_info_cache);
20692064

20702065
del_timer_sync(&vcpu->arch.xen.poll_timer);
20712066
}
20722067

20732068
void kvm_xen_init_vm(struct kvm *kvm)
20742069
{
20752070
idr_init(&kvm->arch.xen.evtchn_ports);
2076-
kvm_gpc_init(&kvm->arch.xen.shinfo_cache);
2071+
kvm_gpc_init(&kvm->arch.xen.shinfo_cache, kvm, NULL, KVM_HOST_USES_PFN);
20772072
}
20782073

20792074
void kvm_xen_destroy_vm(struct kvm *kvm)
20802075
{
20812076
struct evtchnfd *evtchnfd;
20822077
int i;
20832078

2084-
kvm_gpc_deactivate(kvm, &kvm->arch.xen.shinfo_cache);
2079+
kvm_gpc_deactivate(&kvm->arch.xen.shinfo_cache);
20852080

20862081
idr_for_each_entry(&kvm->arch.xen.evtchn_ports, evtchnfd, i) {
20872082
if (!evtchnfd->deliver.port.port)

include/linux/kvm_host.h

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1260,18 +1260,7 @@ void kvm_vcpu_mark_page_dirty(struct kvm_vcpu *vcpu, gfn_t gfn);
12601260
* kvm_gpc_init - initialize gfn_to_pfn_cache.
12611261
*
12621262
* @gpc: struct gfn_to_pfn_cache object.
1263-
*
1264-
* This sets up a gfn_to_pfn_cache by initializing locks. Note, the cache must
1265-
* be zero-allocated (or zeroed by the caller before init).
1266-
*/
1267-
void kvm_gpc_init(struct gfn_to_pfn_cache *gpc);
1268-
1269-
/**
1270-
* kvm_gpc_activate - prepare a cached kernel mapping and HPA for a given guest
1271-
* physical address.
1272-
*
12731263
* @kvm: pointer to kvm instance.
1274-
* @gpc: struct gfn_to_pfn_cache object.
12751264
* @vcpu: vCPU to be used for marking pages dirty and to be woken on
12761265
* invalidation.
12771266
* @usage: indicates if the resulting host physical PFN is used while
@@ -1280,20 +1269,31 @@ void kvm_gpc_init(struct gfn_to_pfn_cache *gpc);
12801269
* changes!---will also force @vcpu to exit the guest and
12811270
* refresh the cache); and/or if the PFN used directly
12821271
* by KVM (and thus needs a kernel virtual mapping).
1272+
*
1273+
* This sets up a gfn_to_pfn_cache by initializing locks and assigning the
1274+
* immutable attributes. Note, the cache must be zero-allocated (or zeroed by
1275+
* the caller before init).
1276+
*/
1277+
void kvm_gpc_init(struct gfn_to_pfn_cache *gpc, struct kvm *kvm,
1278+
struct kvm_vcpu *vcpu, enum pfn_cache_usage usage);
1279+
1280+
/**
1281+
* kvm_gpc_activate - prepare a cached kernel mapping and HPA for a given guest
1282+
* physical address.
1283+
*
1284+
* @gpc: struct gfn_to_pfn_cache object.
12831285
* @gpa: guest physical address to map.
12841286
* @len: sanity check; the range being access must fit a single page.
12851287
*
12861288
* @return: 0 for success.
12871289
* -EINVAL for a mapping which would cross a page boundary.
1288-
* -EFAULT for an untranslatable guest physical address.
1290+
* -EFAULT for an untranslatable guest physical address.
12891291
*
1290-
* This primes a gfn_to_pfn_cache and links it into the @kvm's list for
1292+
* This primes a gfn_to_pfn_cache and links it into the @gpc->kvm's list for
12911293
* invalidations to be processed. Callers are required to use kvm_gpc_check()
12921294
* to ensure that the cache is valid before accessing the target page.
12931295
*/
1294-
int kvm_gpc_activate(struct kvm *kvm, struct gfn_to_pfn_cache *gpc,
1295-
struct kvm_vcpu *vcpu, enum pfn_cache_usage usage,
1296-
gpa_t gpa, unsigned long len);
1296+
int kvm_gpc_activate(struct gfn_to_pfn_cache *gpc, gpa_t gpa, unsigned long len);
12971297

12981298
/**
12991299
* kvm_gpc_check - check validity of a gfn_to_pfn_cache.
@@ -1352,13 +1352,12 @@ void kvm_gpc_unmap(struct kvm *kvm, struct gfn_to_pfn_cache *gpc);
13521352
/**
13531353
* kvm_gpc_deactivate - deactivate and unlink a gfn_to_pfn_cache.
13541354
*
1355-
* @kvm: pointer to kvm instance.
13561355
* @gpc: struct gfn_to_pfn_cache object.
13571356
*
1358-
* This removes a cache from the @kvm's list to be processed on MMU notifier
1357+
* This removes a cache from the VM's list to be processed on MMU notifier
13591358
* invocation.
13601359
*/
1361-
void kvm_gpc_deactivate(struct kvm *kvm, struct gfn_to_pfn_cache *gpc);
1360+
void kvm_gpc_deactivate(struct gfn_to_pfn_cache *gpc);
13621361

13631362
void kvm_sigset_activate(struct kvm_vcpu *vcpu);
13641363
void kvm_sigset_deactivate(struct kvm_vcpu *vcpu);

include/linux/kvm_types.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ struct gfn_to_pfn_cache {
6767
gpa_t gpa;
6868
unsigned long uhva;
6969
struct kvm_memory_slot *memslot;
70+
struct kvm *kvm;
7071
struct kvm_vcpu *vcpu;
7172
struct list_head list;
7273
rwlock_t lock;

virt/kvm/pfncache.c

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -362,25 +362,29 @@ void kvm_gpc_unmap(struct kvm *kvm, struct gfn_to_pfn_cache *gpc)
362362
}
363363
EXPORT_SYMBOL_GPL(kvm_gpc_unmap);
364364

365-
void kvm_gpc_init(struct gfn_to_pfn_cache *gpc)
365+
void kvm_gpc_init(struct gfn_to_pfn_cache *gpc, struct kvm *kvm,
366+
struct kvm_vcpu *vcpu, enum pfn_cache_usage usage)
366367
{
368+
WARN_ON_ONCE(!usage || (usage & KVM_GUEST_AND_HOST_USE_PFN) != usage);
369+
WARN_ON_ONCE((usage & KVM_GUEST_USES_PFN) && !vcpu);
370+
367371
rwlock_init(&gpc->lock);
368372
mutex_init(&gpc->refresh_lock);
373+
374+
gpc->kvm = kvm;
375+
gpc->vcpu = vcpu;
376+
gpc->usage = usage;
369377
}
370378
EXPORT_SYMBOL_GPL(kvm_gpc_init);
371379

372-
int kvm_gpc_activate(struct kvm *kvm, struct gfn_to_pfn_cache *gpc,
373-
struct kvm_vcpu *vcpu, enum pfn_cache_usage usage,
374-
gpa_t gpa, unsigned long len)
380+
int kvm_gpc_activate(struct gfn_to_pfn_cache *gpc, gpa_t gpa, unsigned long len)
375381
{
376-
WARN_ON_ONCE(!usage || (usage & KVM_GUEST_AND_HOST_USE_PFN) != usage);
382+
struct kvm *kvm = gpc->kvm;
377383

378384
if (!gpc->active) {
379385
gpc->khva = NULL;
380386
gpc->pfn = KVM_PFN_ERR_FAULT;
381387
gpc->uhva = KVM_HVA_ERR_BAD;
382-
gpc->vcpu = vcpu;
383-
gpc->usage = usage;
384388
gpc->valid = false;
385389

386390
spin_lock(&kvm->gpc_lock);
@@ -400,8 +404,10 @@ int kvm_gpc_activate(struct kvm *kvm, struct gfn_to_pfn_cache *gpc,
400404
}
401405
EXPORT_SYMBOL_GPL(kvm_gpc_activate);
402406

403-
void kvm_gpc_deactivate(struct kvm *kvm, struct gfn_to_pfn_cache *gpc)
407+
void kvm_gpc_deactivate(struct gfn_to_pfn_cache *gpc)
404408
{
409+
struct kvm *kvm = gpc->kvm;
410+
405411
if (gpc->active) {
406412
/*
407413
* Deactivate the cache before removing it from the list, KVM

0 commit comments

Comments
 (0)