Skip to content

Commit 3e1efe2

Browse files
committed
KVM: Wrap kvm_{gfn,hva}_range.pte in a per-action union
Wrap kvm_{gfn,hva}_range.pte in a union so that future notifier events can pass event specific information up and down the stack without needing to constantly expand and churn the APIs. Lockless aging of SPTEs will pass around a bitmap, and support for memory attributes will pass around the new attributes for the range. Add a "KVM_NO_ARG" placeholder to simplify handling events without an argument (creating a dummy union variable is midly annoying). Opportunstically drop explicit zero-initialization of the "pte" field, as omitting the field (now a union) has the same effect. Cc: Yu Zhao <yuzhao@google.com> Link: https://lore.kernel.org/all/CAOUHufagkd2Jk3_HrVoFFptRXM=hX2CV8f+M-dka-hJU4bP8kw@mail.gmail.com Reviewed-by: Oliver Upton <oliver.upton@linux.dev> Acked-by: Yu Zhao <yuzhao@google.com> Link: https://lore.kernel.org/r/20230729004144.1054885-1-seanjc@google.com Signed-off-by: Sean Christopherson <seanjc@google.com>
1 parent fdf0eaf commit 3e1efe2

File tree

7 files changed

+22
-17
lines changed

7 files changed

+22
-17
lines changed

arch/arm64/kvm/mmu.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1721,7 +1721,7 @@ bool kvm_unmap_gfn_range(struct kvm *kvm, struct kvm_gfn_range *range)
17211721

17221722
bool kvm_set_spte_gfn(struct kvm *kvm, struct kvm_gfn_range *range)
17231723
{
1724-
kvm_pfn_t pfn = pte_pfn(range->pte);
1724+
kvm_pfn_t pfn = pte_pfn(range->arg.pte);
17251725

17261726
if (!kvm->arch.mmu.pgt)
17271727
return false;

arch/mips/kvm/mmu.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -447,7 +447,7 @@ bool kvm_unmap_gfn_range(struct kvm *kvm, struct kvm_gfn_range *range)
447447
bool kvm_set_spte_gfn(struct kvm *kvm, struct kvm_gfn_range *range)
448448
{
449449
gpa_t gpa = range->start << PAGE_SHIFT;
450-
pte_t hva_pte = range->pte;
450+
pte_t hva_pte = range->arg.pte;
451451
pte_t *gpa_pte = kvm_mips_pte_for_gpa(kvm, NULL, gpa);
452452
pte_t old_pte;
453453

arch/riscv/kvm/mmu.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -559,7 +559,7 @@ bool kvm_unmap_gfn_range(struct kvm *kvm, struct kvm_gfn_range *range)
559559
bool kvm_set_spte_gfn(struct kvm *kvm, struct kvm_gfn_range *range)
560560
{
561561
int ret;
562-
kvm_pfn_t pfn = pte_pfn(range->pte);
562+
kvm_pfn_t pfn = pte_pfn(range->arg.pte);
563563

564564
if (!kvm->arch.pgd)
565565
return false;

arch/x86/kvm/mmu/mmu.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1588,7 +1588,7 @@ static __always_inline bool kvm_handle_gfn_range(struct kvm *kvm,
15881588
for_each_slot_rmap_range(range->slot, PG_LEVEL_4K, KVM_MAX_HUGEPAGE_LEVEL,
15891589
range->start, range->end - 1, &iterator)
15901590
ret |= handler(kvm, iterator.rmap, range->slot, iterator.gfn,
1591-
iterator.level, range->pte);
1591+
iterator.level, range->arg.pte);
15921592

15931593
return ret;
15941594
}

arch/x86/kvm/mmu/tdp_mmu.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1241,7 +1241,7 @@ static bool set_spte_gfn(struct kvm *kvm, struct tdp_iter *iter,
12411241
u64 new_spte;
12421242

12431243
/* Huge pages aren't expected to be modified without first being zapped. */
1244-
WARN_ON(pte_huge(range->pte) || range->start + 1 != range->end);
1244+
WARN_ON(pte_huge(range->arg.pte) || range->start + 1 != range->end);
12451245

12461246
if (iter->level != PG_LEVEL_4K ||
12471247
!is_shadow_present_pte(iter->old_spte))
@@ -1255,9 +1255,9 @@ static bool set_spte_gfn(struct kvm *kvm, struct tdp_iter *iter,
12551255
*/
12561256
tdp_mmu_iter_set_spte(kvm, iter, 0);
12571257

1258-
if (!pte_write(range->pte)) {
1258+
if (!pte_write(range->arg.pte)) {
12591259
new_spte = kvm_mmu_changed_pte_notifier_make_spte(iter->old_spte,
1260-
pte_pfn(range->pte));
1260+
pte_pfn(range->arg.pte));
12611261

12621262
tdp_mmu_iter_set_spte(kvm, iter, new_spte);
12631263
}

include/linux/kvm_host.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -256,11 +256,15 @@ int kvm_async_pf_wakeup_all(struct kvm_vcpu *vcpu);
256256
#endif
257257

258258
#ifdef KVM_ARCH_WANT_MMU_NOTIFIER
259+
union kvm_mmu_notifier_arg {
260+
pte_t pte;
261+
};
262+
259263
struct kvm_gfn_range {
260264
struct kvm_memory_slot *slot;
261265
gfn_t start;
262266
gfn_t end;
263-
pte_t pte;
267+
union kvm_mmu_notifier_arg arg;
264268
bool may_block;
265269
};
266270
bool kvm_unmap_gfn_range(struct kvm *kvm, struct kvm_gfn_range *range);

virt/kvm/kvm_main.c

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -526,7 +526,7 @@ typedef void (*on_unlock_fn_t)(struct kvm *kvm);
526526
struct kvm_hva_range {
527527
unsigned long start;
528528
unsigned long end;
529-
pte_t pte;
529+
union kvm_mmu_notifier_arg arg;
530530
hva_handler_t handler;
531531
on_lock_fn_t on_lock;
532532
on_unlock_fn_t on_unlock;
@@ -547,6 +547,8 @@ static void kvm_null_fn(void)
547547
}
548548
#define IS_KVM_NULL_FN(fn) ((fn) == (void *)kvm_null_fn)
549549

550+
static const union kvm_mmu_notifier_arg KVM_MMU_NOTIFIER_NO_ARG;
551+
550552
/* Iterate over each memslot intersecting [start, last] (inclusive) range */
551553
#define kvm_for_each_memslot_in_hva_range(node, slots, start, last) \
552554
for (node = interval_tree_iter_first(&slots->hva_tree, start, last); \
@@ -591,7 +593,7 @@ static __always_inline int __kvm_handle_hva_range(struct kvm *kvm,
591593
* bother making these conditional (to avoid writes on
592594
* the second or later invocation of the handler).
593595
*/
594-
gfn_range.pte = range->pte;
596+
gfn_range.arg = range->arg;
595597
gfn_range.may_block = range->may_block;
596598

597599
/*
@@ -632,14 +634,14 @@ static __always_inline int __kvm_handle_hva_range(struct kvm *kvm,
632634
static __always_inline int kvm_handle_hva_range(struct mmu_notifier *mn,
633635
unsigned long start,
634636
unsigned long end,
635-
pte_t pte,
637+
union kvm_mmu_notifier_arg arg,
636638
hva_handler_t handler)
637639
{
638640
struct kvm *kvm = mmu_notifier_to_kvm(mn);
639641
const struct kvm_hva_range range = {
640642
.start = start,
641643
.end = end,
642-
.pte = pte,
644+
.arg = arg,
643645
.handler = handler,
644646
.on_lock = (void *)kvm_null_fn,
645647
.on_unlock = (void *)kvm_null_fn,
@@ -659,7 +661,6 @@ static __always_inline int kvm_handle_hva_range_no_flush(struct mmu_notifier *mn
659661
const struct kvm_hva_range range = {
660662
.start = start,
661663
.end = end,
662-
.pte = __pte(0),
663664
.handler = handler,
664665
.on_lock = (void *)kvm_null_fn,
665666
.on_unlock = (void *)kvm_null_fn,
@@ -693,6 +694,7 @@ static void kvm_mmu_notifier_change_pte(struct mmu_notifier *mn,
693694
pte_t pte)
694695
{
695696
struct kvm *kvm = mmu_notifier_to_kvm(mn);
697+
const union kvm_mmu_notifier_arg arg = { .pte = pte };
696698

697699
trace_kvm_set_spte_hva(address);
698700

@@ -708,7 +710,7 @@ static void kvm_mmu_notifier_change_pte(struct mmu_notifier *mn,
708710
if (!READ_ONCE(kvm->mmu_invalidate_in_progress))
709711
return;
710712

711-
kvm_handle_hva_range(mn, address, address + 1, pte, kvm_change_spte_gfn);
713+
kvm_handle_hva_range(mn, address, address + 1, arg, kvm_change_spte_gfn);
712714
}
713715

714716
void kvm_mmu_invalidate_begin(struct kvm *kvm, unsigned long start,
@@ -747,7 +749,6 @@ static int kvm_mmu_notifier_invalidate_range_start(struct mmu_notifier *mn,
747749
const struct kvm_hva_range hva_range = {
748750
.start = range->start,
749751
.end = range->end,
750-
.pte = __pte(0),
751752
.handler = kvm_unmap_gfn_range,
752753
.on_lock = kvm_mmu_invalidate_begin,
753754
.on_unlock = kvm_arch_guest_memory_reclaimed,
@@ -812,7 +813,6 @@ static void kvm_mmu_notifier_invalidate_range_end(struct mmu_notifier *mn,
812813
const struct kvm_hva_range hva_range = {
813814
.start = range->start,
814815
.end = range->end,
815-
.pte = __pte(0),
816816
.handler = (void *)kvm_null_fn,
817817
.on_lock = kvm_mmu_invalidate_end,
818818
.on_unlock = (void *)kvm_null_fn,
@@ -845,7 +845,8 @@ static int kvm_mmu_notifier_clear_flush_young(struct mmu_notifier *mn,
845845
{
846846
trace_kvm_age_hva(start, end);
847847

848-
return kvm_handle_hva_range(mn, start, end, __pte(0), kvm_age_gfn);
848+
return kvm_handle_hva_range(mn, start, end, KVM_MMU_NOTIFIER_NO_ARG,
849+
kvm_age_gfn);
849850
}
850851

851852
static int kvm_mmu_notifier_clear_young(struct mmu_notifier *mn,

0 commit comments

Comments
 (0)