Skip to content

Commit 02c6bea

Browse files
committed
KVM: x86/mmu: Dynamically allocate shadow MMU's hashed page list
Dynamically allocate the (massive) array of hashed lists used to track shadow pages, as the array itself is 32KiB, i.e. is an order-3 allocation all on its own, and is *exactly* an order-3 allocation. Dynamically allocating the array will allow allocating "struct kvm" using kvmalloc(), and will also allow deferring allocation of the array until it's actually needed, i.e. until the first shadow root is allocated. Opportunistically use kvmalloc() for the hashed lists, as an order-3 allocation is (stating the obvious) less likely to fail than an order-4 allocation, and the overhead of vmalloc() is undesirable given that the size of the allocation is fixed. Cc: Vipin Sharma <vipinsh@google.com> Reviewed-by: Xiaoyao Li <xiaoyao.li@intel.com> Link: https://lore.kernel.org/r/20250523001138.3182794-3-seanjc@google.com Signed-off-by: Sean Christopherson <seanjc@google.com>
1 parent 1f287a4 commit 02c6bea

File tree

3 files changed

+28
-4
lines changed

3 files changed

+28
-4
lines changed

arch/x86/include/asm/kvm_host.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1344,7 +1344,7 @@ struct kvm_arch {
13441344
bool has_private_mem;
13451345
bool has_protected_state;
13461346
bool pre_fault_allowed;
1347-
struct hlist_head mmu_page_hash[KVM_NUM_MMU_PAGES];
1347+
struct hlist_head *mmu_page_hash;
13481348
struct list_head active_mmu_pages;
13491349
/*
13501350
* A list of kvm_mmu_page structs that, if zapped, could possibly be
@@ -2007,7 +2007,7 @@ void kvm_mmu_vendor_module_exit(void);
20072007

20082008
void kvm_mmu_destroy(struct kvm_vcpu *vcpu);
20092009
int kvm_mmu_create(struct kvm_vcpu *vcpu);
2010-
void kvm_mmu_init_vm(struct kvm *kvm);
2010+
int kvm_mmu_init_vm(struct kvm *kvm);
20112011
void kvm_mmu_uninit_vm(struct kvm *kvm);
20122012

20132013
void kvm_mmu_init_memslot_memory_attributes(struct kvm *kvm,

arch/x86/kvm/mmu/mmu.c

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3882,6 +3882,18 @@ static int mmu_alloc_direct_roots(struct kvm_vcpu *vcpu)
38823882
return r;
38833883
}
38843884

3885+
static int kvm_mmu_alloc_page_hash(struct kvm *kvm)
3886+
{
3887+
typeof(kvm->arch.mmu_page_hash) h;
3888+
3889+
h = kvcalloc(KVM_NUM_MMU_PAGES, sizeof(*h), GFP_KERNEL_ACCOUNT);
3890+
if (!h)
3891+
return -ENOMEM;
3892+
3893+
kvm->arch.mmu_page_hash = h;
3894+
return 0;
3895+
}
3896+
38853897
static int mmu_first_shadow_root_alloc(struct kvm *kvm)
38863898
{
38873899
struct kvm_memslots *slots;
@@ -6682,13 +6694,19 @@ static void kvm_mmu_zap_all_fast(struct kvm *kvm)
66826694
kvm_tdp_mmu_zap_invalidated_roots(kvm, true);
66836695
}
66846696

6685-
void kvm_mmu_init_vm(struct kvm *kvm)
6697+
int kvm_mmu_init_vm(struct kvm *kvm)
66866698
{
6699+
int r;
6700+
66876701
kvm->arch.shadow_mmio_value = shadow_mmio_value;
66886702
INIT_LIST_HEAD(&kvm->arch.active_mmu_pages);
66896703
INIT_LIST_HEAD(&kvm->arch.possible_nx_huge_pages);
66906704
spin_lock_init(&kvm->arch.mmu_unsync_pages_lock);
66916705

6706+
r = kvm_mmu_alloc_page_hash(kvm);
6707+
if (r)
6708+
return r;
6709+
66926710
if (tdp_mmu_enabled)
66936711
kvm_mmu_init_tdp_mmu(kvm);
66946712

@@ -6699,6 +6717,7 @@ void kvm_mmu_init_vm(struct kvm *kvm)
66996717

67006718
kvm->arch.split_desc_cache.kmem_cache = pte_list_desc_cache;
67016719
kvm->arch.split_desc_cache.gfp_zero = __GFP_ZERO;
6720+
return 0;
67026721
}
67036722

67046723
static void mmu_free_vm_memory_caches(struct kvm *kvm)
@@ -6710,6 +6729,8 @@ static void mmu_free_vm_memory_caches(struct kvm *kvm)
67106729

67116730
void kvm_mmu_uninit_vm(struct kvm *kvm)
67126731
{
6732+
kvfree(kvm->arch.mmu_page_hash);
6733+
67136734
if (tdp_mmu_enabled)
67146735
kvm_mmu_uninit_tdp_mmu(kvm);
67156736

arch/x86/kvm/x86.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12789,7 +12789,9 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
1278912789
if (ret)
1279012790
goto out;
1279112791

12792-
kvm_mmu_init_vm(kvm);
12792+
ret = kvm_mmu_init_vm(kvm);
12793+
if (ret)
12794+
goto out_cleanup_page_track;
1279312795

1279412796
ret = kvm_x86_call(vm_init)(kvm);
1279512797
if (ret)
@@ -12842,6 +12844,7 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
1284212844

1284312845
out_uninit_mmu:
1284412846
kvm_mmu_uninit_vm(kvm);
12847+
out_cleanup_page_track:
1284512848
kvm_page_track_cleanup(kvm);
1284612849
out:
1284712850
return ret;

0 commit comments

Comments
 (0)