Skip to content

Commit 8e8eb10

Browse files
pekangasMarc Zyngier
authored andcommitted
KVM: arm64: Calculate hyp VA size only once
Calculate the hypervisor's VA size only once to maintain consistency between the memory layout and MMU initialization logic. Previously the two would be inconsistent when the kernel is configured for less than IDMAP_VA_BITS of VA space. Signed-off-by: Petteri Kangaslampi <pekangas@google.com> Tested-by: Vincent Donnefort <vdonnefort@google.com> Link: https://patch.msgid.link/20260113194409.2970324-2-pekangas@google.com Signed-off-by: Marc Zyngier <maz@kernel.org>
1 parent b1a9a9b commit 8e8eb10

4 files changed

Lines changed: 36 additions & 32 deletions

File tree

arch/arm64/include/asm/kvm_mmu.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ alternative_cb_end
103103
void kvm_update_va_mask(struct alt_instr *alt,
104104
__le32 *origptr, __le32 *updptr, int nr_inst);
105105
void kvm_compute_layout(void);
106+
u32 kvm_hyp_va_bits(void);
106107
void kvm_apply_hyp_relocations(void);
107108

108109
#define __hyp_pa(x) (((phys_addr_t)(x)) + hyp_physvirt_offset)
@@ -185,7 +186,7 @@ int kvm_handle_guest_abort(struct kvm_vcpu *vcpu);
185186

186187
phys_addr_t kvm_mmu_get_httbr(void);
187188
phys_addr_t kvm_get_idmap_vector(void);
188-
int __init kvm_mmu_init(u32 *hyp_va_bits);
189+
int __init kvm_mmu_init(u32 hyp_va_bits);
189190

190191
static inline void *__kvm_vector_slot2addr(void *base,
191192
enum arm64_hyp_spectre_vector slot)

arch/arm64/kvm/arm.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2568,7 +2568,7 @@ static void pkvm_hyp_init_ptrauth(void)
25682568
/* Inits Hyp-mode on all online CPUs */
25692569
static int __init init_hyp_mode(void)
25702570
{
2571-
u32 hyp_va_bits;
2571+
u32 hyp_va_bits = kvm_hyp_va_bits();
25722572
int cpu;
25732573
int err = -ENOMEM;
25742574

@@ -2582,7 +2582,7 @@ static int __init init_hyp_mode(void)
25822582
/*
25832583
* Allocate Hyp PGD and setup Hyp identity mapping
25842584
*/
2585-
err = kvm_mmu_init(&hyp_va_bits);
2585+
err = kvm_mmu_init(hyp_va_bits);
25862586
if (err)
25872587
goto out_err;
25882588

arch/arm64/kvm/mmu.c

Lines changed: 4 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2284,11 +2284,9 @@ static struct kvm_pgtable_mm_ops kvm_hyp_mm_ops = {
22842284
.virt_to_phys = kvm_host_pa,
22852285
};
22862286

2287-
int __init kvm_mmu_init(u32 *hyp_va_bits)
2287+
int __init kvm_mmu_init(u32 hyp_va_bits)
22882288
{
22892289
int err;
2290-
u32 idmap_bits;
2291-
u32 kernel_bits;
22922290

22932291
hyp_idmap_start = __pa_symbol(__hyp_idmap_text_start);
22942292
hyp_idmap_start = ALIGN_DOWN(hyp_idmap_start, PAGE_SIZE);
@@ -2302,25 +2300,7 @@ int __init kvm_mmu_init(u32 *hyp_va_bits)
23022300
*/
23032301
BUG_ON((hyp_idmap_start ^ (hyp_idmap_end - 1)) & PAGE_MASK);
23042302

2305-
/*
2306-
* The ID map is always configured for 48 bits of translation, which
2307-
* may be fewer than the number of VA bits used by the regular kernel
2308-
* stage 1, when VA_BITS=52.
2309-
*
2310-
* At EL2, there is only one TTBR register, and we can't switch between
2311-
* translation tables *and* update TCR_EL2.T0SZ at the same time. Bottom
2312-
* line: we need to use the extended range with *both* our translation
2313-
* tables.
2314-
*
2315-
* So use the maximum of the idmap VA bits and the regular kernel stage
2316-
* 1 VA bits to assure that the hypervisor can both ID map its code page
2317-
* and map any kernel memory.
2318-
*/
2319-
idmap_bits = IDMAP_VA_BITS;
2320-
kernel_bits = vabits_actual;
2321-
*hyp_va_bits = max(idmap_bits, kernel_bits);
2322-
2323-
kvm_debug("Using %u-bit virtual addresses at EL2\n", *hyp_va_bits);
2303+
kvm_debug("Using %u-bit virtual addresses at EL2\n", hyp_va_bits);
23242304
kvm_debug("IDMAP page: %lx\n", hyp_idmap_start);
23252305
kvm_debug("HYP VA range: %lx:%lx\n",
23262306
kern_hyp_va(PAGE_OFFSET),
@@ -2345,7 +2325,7 @@ int __init kvm_mmu_init(u32 *hyp_va_bits)
23452325
goto out;
23462326
}
23472327

2348-
err = kvm_pgtable_hyp_init(hyp_pgtable, *hyp_va_bits, &kvm_hyp_mm_ops);
2328+
err = kvm_pgtable_hyp_init(hyp_pgtable, hyp_va_bits, &kvm_hyp_mm_ops);
23492329
if (err)
23502330
goto out_free_pgtable;
23512331

@@ -2354,7 +2334,7 @@ int __init kvm_mmu_init(u32 *hyp_va_bits)
23542334
goto out_destroy_pgtable;
23552335

23562336
io_map_base = hyp_idmap_start;
2357-
__hyp_va_bits = *hyp_va_bits;
2337+
__hyp_va_bits = hyp_va_bits;
23582338
return 0;
23592339

23602340
out_destroy_pgtable:

arch/arm64/kvm/va_layout.c

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,31 @@ static void init_hyp_physvirt_offset(void)
4646
hyp_physvirt_offset = (s64)__pa(kern_va) - (s64)hyp_va;
4747
}
4848

49+
/*
50+
* Calculate the actual VA size used by the hypervisor
51+
*/
52+
__init u32 kvm_hyp_va_bits(void)
53+
{
54+
/*
55+
* The ID map is always configured for 48 bits of translation, which may
56+
* be different from the number of VA bits used by the regular kernel
57+
* stage 1.
58+
*
59+
* At EL2, there is only one TTBR register, and we can't switch between
60+
* translation tables *and* update TCR_EL2.T0SZ at the same time. Bottom
61+
* line: we need to use the extended range with *both* our translation
62+
* tables.
63+
*
64+
* So use the maximum of the idmap VA bits and the regular kernel stage
65+
* 1 VA bits as the hypervisor VA size to assure that the hypervisor can
66+
* both ID map its code page and map any kernel memory.
67+
*/
68+
return max(IDMAP_VA_BITS, vabits_actual);
69+
}
70+
4971
/*
5072
* We want to generate a hyp VA with the following format (with V ==
51-
* vabits_actual):
73+
* hypervisor VA bits):
5274
*
5375
* 63 ... V | V-1 | V-2 .. tag_lsb | tag_lsb - 1 .. 0
5476
* ---------------------------------------------------------
@@ -61,20 +83,21 @@ __init void kvm_compute_layout(void)
6183
{
6284
phys_addr_t idmap_addr = __pa_symbol(__hyp_idmap_text_start);
6385
u64 hyp_va_msb;
86+
u32 hyp_va_bits = kvm_hyp_va_bits();
6487

6588
/* Where is my RAM region? */
66-
hyp_va_msb = idmap_addr & BIT(vabits_actual - 1);
67-
hyp_va_msb ^= BIT(vabits_actual - 1);
89+
hyp_va_msb = idmap_addr & BIT(hyp_va_bits - 1);
90+
hyp_va_msb ^= BIT(hyp_va_bits - 1);
6891

6992
tag_lsb = fls64((u64)phys_to_virt(memblock_start_of_DRAM()) ^
7093
(u64)(high_memory - 1));
7194

7295
va_mask = GENMASK_ULL(tag_lsb - 1, 0);
7396
tag_val = hyp_va_msb;
7497

75-
if (IS_ENABLED(CONFIG_RANDOMIZE_BASE) && tag_lsb != (vabits_actual - 1)) {
98+
if (IS_ENABLED(CONFIG_RANDOMIZE_BASE) && tag_lsb != (hyp_va_bits - 1)) {
7699
/* We have some free bits to insert a random tag. */
77-
tag_val |= get_random_long() & GENMASK_ULL(vabits_actual - 2, tag_lsb);
100+
tag_val |= get_random_long() & GENMASK_ULL(hyp_va_bits - 2, tag_lsb);
78101
}
79102
tag_val >>= tag_lsb;
80103

0 commit comments

Comments
 (0)