Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

authored by

Petteri Kangaslampi and committed by
Marc Zyngier
8e8eb10c b1a9a9b9

+36 -32
+2 -1
arch/arm64/include/asm/kvm_mmu.h
··· 103 103 void kvm_update_va_mask(struct alt_instr *alt, 104 104 __le32 *origptr, __le32 *updptr, int nr_inst); 105 105 void kvm_compute_layout(void); 106 + u32 kvm_hyp_va_bits(void); 106 107 void kvm_apply_hyp_relocations(void); 107 108 108 109 #define __hyp_pa(x) (((phys_addr_t)(x)) + hyp_physvirt_offset) ··· 186 185 187 186 phys_addr_t kvm_mmu_get_httbr(void); 188 187 phys_addr_t kvm_get_idmap_vector(void); 189 - int __init kvm_mmu_init(u32 *hyp_va_bits); 188 + int __init kvm_mmu_init(u32 hyp_va_bits); 190 189 191 190 static inline void *__kvm_vector_slot2addr(void *base, 192 191 enum arm64_hyp_spectre_vector slot)
+2 -2
arch/arm64/kvm/arm.c
··· 2568 2568 /* Inits Hyp-mode on all online CPUs */ 2569 2569 static int __init init_hyp_mode(void) 2570 2570 { 2571 - u32 hyp_va_bits; 2571 + u32 hyp_va_bits = kvm_hyp_va_bits(); 2572 2572 int cpu; 2573 2573 int err = -ENOMEM; 2574 2574 ··· 2582 2582 /* 2583 2583 * Allocate Hyp PGD and setup Hyp identity mapping 2584 2584 */ 2585 - err = kvm_mmu_init(&hyp_va_bits); 2585 + err = kvm_mmu_init(hyp_va_bits); 2586 2586 if (err) 2587 2587 goto out_err; 2588 2588
+4 -24
arch/arm64/kvm/mmu.c
··· 2284 2284 .virt_to_phys = kvm_host_pa, 2285 2285 }; 2286 2286 2287 - int __init kvm_mmu_init(u32 *hyp_va_bits) 2287 + int __init kvm_mmu_init(u32 hyp_va_bits) 2288 2288 { 2289 2289 int err; 2290 - u32 idmap_bits; 2291 - u32 kernel_bits; 2292 2290 2293 2291 hyp_idmap_start = __pa_symbol(__hyp_idmap_text_start); 2294 2292 hyp_idmap_start = ALIGN_DOWN(hyp_idmap_start, PAGE_SIZE); ··· 2300 2302 */ 2301 2303 BUG_ON((hyp_idmap_start ^ (hyp_idmap_end - 1)) & PAGE_MASK); 2302 2304 2303 - /* 2304 - * The ID map is always configured for 48 bits of translation, which 2305 - * may be fewer than the number of VA bits used by the regular kernel 2306 - * stage 1, when VA_BITS=52. 2307 - * 2308 - * At EL2, there is only one TTBR register, and we can't switch between 2309 - * translation tables *and* update TCR_EL2.T0SZ at the same time. Bottom 2310 - * line: we need to use the extended range with *both* our translation 2311 - * tables. 2312 - * 2313 - * So use the maximum of the idmap VA bits and the regular kernel stage 2314 - * 1 VA bits to assure that the hypervisor can both ID map its code page 2315 - * and map any kernel memory. 2316 - */ 2317 - idmap_bits = IDMAP_VA_BITS; 2318 - kernel_bits = vabits_actual; 2319 - *hyp_va_bits = max(idmap_bits, kernel_bits); 2320 - 2321 - kvm_debug("Using %u-bit virtual addresses at EL2\n", *hyp_va_bits); 2305 + kvm_debug("Using %u-bit virtual addresses at EL2\n", hyp_va_bits); 2322 2306 kvm_debug("IDMAP page: %lx\n", hyp_idmap_start); 2323 2307 kvm_debug("HYP VA range: %lx:%lx\n", 2324 2308 kern_hyp_va(PAGE_OFFSET), ··· 2325 2345 goto out; 2326 2346 } 2327 2347 2328 - err = kvm_pgtable_hyp_init(hyp_pgtable, *hyp_va_bits, &kvm_hyp_mm_ops); 2348 + err = kvm_pgtable_hyp_init(hyp_pgtable, hyp_va_bits, &kvm_hyp_mm_ops); 2329 2349 if (err) 2330 2350 goto out_free_pgtable; 2331 2351 ··· 2334 2354 goto out_destroy_pgtable; 2335 2355 2336 2356 io_map_base = hyp_idmap_start; 2337 - __hyp_va_bits = *hyp_va_bits; 2357 + __hyp_va_bits = hyp_va_bits; 2338 2358 return 0; 2339 2359 2340 2360 out_destroy_pgtable:
+28 -5
arch/arm64/kvm/va_layout.c
··· 47 47 } 48 48 49 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 + 71 + /* 50 72 * We want to generate a hyp VA with the following format (with V == 51 - * vabits_actual): 73 + * hypervisor VA bits): 52 74 * 53 75 * 63 ... V | V-1 | V-2 .. tag_lsb | tag_lsb - 1 .. 0 54 76 * --------------------------------------------------------- ··· 83 61 { 84 62 phys_addr_t idmap_addr = __pa_symbol(__hyp_idmap_text_start); 85 63 u64 hyp_va_msb; 64 + u32 hyp_va_bits = kvm_hyp_va_bits(); 86 65 87 66 /* Where is my RAM region? */ 88 - hyp_va_msb = idmap_addr & BIT(vabits_actual - 1); 89 - hyp_va_msb ^= BIT(vabits_actual - 1); 67 + hyp_va_msb = idmap_addr & BIT(hyp_va_bits - 1); 68 + hyp_va_msb ^= BIT(hyp_va_bits - 1); 90 69 91 70 tag_lsb = fls64((u64)phys_to_virt(memblock_start_of_DRAM()) ^ 92 71 (u64)(high_memory - 1)); ··· 95 72 va_mask = GENMASK_ULL(tag_lsb - 1, 0); 96 73 tag_val = hyp_va_msb; 97 74 98 - if (IS_ENABLED(CONFIG_RANDOMIZE_BASE) && tag_lsb != (vabits_actual - 1)) { 75 + if (IS_ENABLED(CONFIG_RANDOMIZE_BASE) && tag_lsb != (hyp_va_bits - 1)) { 99 76 /* We have some free bits to insert a random tag. */ 100 - tag_val |= get_random_long() & GENMASK_ULL(vabits_actual - 2, tag_lsb); 77 + tag_val |= get_random_long() & GENMASK_ULL(hyp_va_bits - 2, tag_lsb); 101 78 } 102 79 tag_val >>= tag_lsb; 103 80