Skip to content

Commit 26baab4

Browse files
committed
KVM: SVM: Track AVIC tables as natively sized pointers, not "struct pages"
Allocate and track AVIC's logical and physical tables as u32 and u64 pointers respectively, as managing the pages as "struct page" pointers adds an almost absurd amount of boilerplate and complexity. E.g. with page_address() out of the way, svm->avic_physical_id_cache becomes completely superfluous, and will be removed in a future cleanup. No functional change intended. Tested-by: Sairaj Kodilkar <sarunkod@amd.com> Acked-by: Naveen N Rao (AMD) <naveen@kernel.org> Link: https://lore.kernel.org/r/20250611224604.313496-16-seanjc@google.com Signed-off-by: Sean Christopherson <seanjc@google.com>
1 parent c24ed20 commit 26baab4

File tree

2 files changed

+18
-35
lines changed

2 files changed

+18
-35
lines changed

arch/x86/kvm/svm/avic.c

Lines changed: 16 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -173,10 +173,8 @@ void avic_vm_destroy(struct kvm *kvm)
173173
if (!enable_apicv)
174174
return;
175175

176-
if (kvm_svm->avic_logical_id_table_page)
177-
__free_page(kvm_svm->avic_logical_id_table_page);
178-
if (kvm_svm->avic_physical_id_table_page)
179-
__free_page(kvm_svm->avic_physical_id_table_page);
176+
free_page((unsigned long)kvm_svm->avic_logical_id_table);
177+
free_page((unsigned long)kvm_svm->avic_physical_id_table);
180178

181179
spin_lock_irqsave(&svm_vm_data_hash_lock, flags);
182180
hash_del(&kvm_svm->hnode);
@@ -189,27 +187,19 @@ int avic_vm_init(struct kvm *kvm)
189187
int err = -ENOMEM;
190188
struct kvm_svm *kvm_svm = to_kvm_svm(kvm);
191189
struct kvm_svm *k2;
192-
struct page *p_page;
193-
struct page *l_page;
194190
u32 vm_id;
195191

196192
if (!enable_apicv)
197193
return 0;
198194

199-
/* Allocating physical APIC ID table (4KB) */
200-
p_page = alloc_page(GFP_KERNEL_ACCOUNT | __GFP_ZERO);
201-
if (!p_page)
195+
kvm_svm->avic_physical_id_table = (void *)get_zeroed_page(GFP_KERNEL_ACCOUNT);
196+
if (!kvm_svm->avic_physical_id_table)
202197
goto free_avic;
203198

204-
kvm_svm->avic_physical_id_table_page = p_page;
205-
206-
/* Allocating logical APIC ID table (4KB) */
207-
l_page = alloc_page(GFP_KERNEL_ACCOUNT | __GFP_ZERO);
208-
if (!l_page)
199+
kvm_svm->avic_logical_id_table = (void *)get_zeroed_page(GFP_KERNEL_ACCOUNT);
200+
if (!kvm_svm->avic_logical_id_table)
209201
goto free_avic;
210202

211-
kvm_svm->avic_logical_id_table_page = l_page;
212-
213203
spin_lock_irqsave(&svm_vm_data_hash_lock, flags);
214204
again:
215205
vm_id = next_vm_id = (next_vm_id + 1) & AVIC_VM_ID_MASK;
@@ -243,12 +233,10 @@ static phys_addr_t avic_get_backing_page_address(struct vcpu_svm *svm)
243233
void avic_init_vmcb(struct vcpu_svm *svm, struct vmcb *vmcb)
244234
{
245235
struct kvm_svm *kvm_svm = to_kvm_svm(svm->vcpu.kvm);
246-
phys_addr_t lpa = __sme_set(page_to_phys(kvm_svm->avic_logical_id_table_page));
247-
phys_addr_t ppa = __sme_set(page_to_phys(kvm_svm->avic_physical_id_table_page));
248236

249237
vmcb->control.avic_backing_page = avic_get_backing_page_address(svm);
250-
vmcb->control.avic_logical_id = lpa;
251-
vmcb->control.avic_physical_id = ppa;
238+
vmcb->control.avic_logical_id = __sme_set(__pa(kvm_svm->avic_logical_id_table));
239+
vmcb->control.avic_physical_id = __sme_set(__pa(kvm_svm->avic_physical_id_table));
252240
vmcb->control.avic_vapic_bar = APIC_DEFAULT_PHYS_BASE;
253241

254242
if (kvm_apicv_activated(svm->vcpu.kvm))
@@ -262,7 +250,7 @@ static int avic_init_backing_page(struct kvm_vcpu *vcpu)
262250
struct kvm_svm *kvm_svm = to_kvm_svm(vcpu->kvm);
263251
struct vcpu_svm *svm = to_svm(vcpu);
264252
u32 id = vcpu->vcpu_id;
265-
u64 *table, new_entry;
253+
u64 new_entry;
266254

267255
/*
268256
* Inhibit AVIC if the vCPU ID is bigger than what is supported by AVIC
@@ -278,8 +266,8 @@ static int avic_init_backing_page(struct kvm_vcpu *vcpu)
278266
return 0;
279267
}
280268

281-
BUILD_BUG_ON((AVIC_MAX_PHYSICAL_ID + 1) * sizeof(*table) > PAGE_SIZE ||
282-
(X2AVIC_MAX_PHYSICAL_ID + 1) * sizeof(*table) > PAGE_SIZE);
269+
BUILD_BUG_ON((AVIC_MAX_PHYSICAL_ID + 1) * sizeof(new_entry) > PAGE_SIZE ||
270+
(X2AVIC_MAX_PHYSICAL_ID + 1) * sizeof(new_entry) > PAGE_SIZE);
283271

284272
if (WARN_ON_ONCE(!vcpu->arch.apic->regs))
285273
return -EINVAL;
@@ -298,18 +286,16 @@ static int avic_init_backing_page(struct kvm_vcpu *vcpu)
298286
return ret;
299287
}
300288

301-
/* Setting AVIC backing page address in the phy APIC ID table */
302-
table = page_address(kvm_svm->avic_physical_id_table_page);
303-
304289
/* Note, fls64() returns the bit position, +1. */
305290
BUILD_BUG_ON(__PHYSICAL_MASK_SHIFT >
306291
fls64(AVIC_PHYSICAL_ID_ENTRY_BACKING_PAGE_MASK));
307292

293+
/* Setting AVIC backing page address in the phy APIC ID table */
308294
new_entry = avic_get_backing_page_address(svm) |
309295
AVIC_PHYSICAL_ID_ENTRY_VALID_MASK;
310-
WRITE_ONCE(table[id], new_entry);
296+
WRITE_ONCE(kvm_svm->avic_physical_id_table[id], new_entry);
311297

312-
svm->avic_physical_id_cache = &table[id];
298+
svm->avic_physical_id_cache = &kvm_svm->avic_physical_id_table[id];
313299

314300
return 0;
315301
}
@@ -443,7 +429,7 @@ static int avic_kick_target_vcpus_fast(struct kvm *kvm, struct kvm_lapic *source
443429
if (apic_x2apic_mode(source))
444430
avic_logical_id_table = NULL;
445431
else
446-
avic_logical_id_table = page_address(kvm_svm->avic_logical_id_table_page);
432+
avic_logical_id_table = kvm_svm->avic_logical_id_table;
447433

448434
/*
449435
* AVIC is inhibited if vCPUs aren't mapped 1:1 with logical
@@ -545,7 +531,6 @@ unsigned long avic_vcpu_get_apicv_inhibit_reasons(struct kvm_vcpu *vcpu)
545531
static u32 *avic_get_logical_id_entry(struct kvm_vcpu *vcpu, u32 ldr, bool flat)
546532
{
547533
struct kvm_svm *kvm_svm = to_kvm_svm(vcpu->kvm);
548-
u32 *logical_apic_id_table;
549534
u32 cluster, index;
550535

551536
ldr = GET_APIC_LOGICAL_ID(ldr);
@@ -566,9 +551,7 @@ static u32 *avic_get_logical_id_entry(struct kvm_vcpu *vcpu, u32 ldr, bool flat)
566551
return NULL;
567552
index += (cluster << 2);
568553

569-
logical_apic_id_table = (u32 *) page_address(kvm_svm->avic_logical_id_table_page);
570-
571-
return &logical_apic_id_table[index];
554+
return &kvm_svm->avic_logical_id_table[index];
572555
}
573556

574557
static void avic_ldr_write(struct kvm_vcpu *vcpu, u8 g_physical_id, u32 ldr)

arch/x86/kvm/svm/svm.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,8 +123,8 @@ struct kvm_svm {
123123

124124
/* Struct members for AVIC */
125125
u32 avic_vm_id;
126-
struct page *avic_logical_id_table_page;
127-
struct page *avic_physical_id_table_page;
126+
u32 *avic_logical_id_table;
127+
u64 *avic_physical_id_table;
128128
struct hlist_node hnode;
129129

130130
struct kvm_sev_info sev_info;

0 commit comments

Comments
 (0)