Skip to content

Commit 315775f

Browse files
Quentin PerretMarc Zyngier
authored andcommitted
KVM: arm64: Consolidate stage-2 initialisation into a single function
The initialisation of guest stage-2 page-tables is currently split across two functions: kvm_init_stage2_mmu() and kvm_arm_setup_stage2(). That is presumably for historical reasons as kvm_arm_setup_stage2() originates from the (now defunct) KVM port for 32-bit Arm. Simplify this code path by merging both functions into one, taking care to map the 'struct kvm' into the hypervisor stage-1 early on in order to simplify the failure path. Tested-by: Vincent Donnefort <[email protected]> Co-developed-by: Fuad Tabba <[email protected]> Signed-off-by: Fuad Tabba <[email protected]> Signed-off-by: Quentin Perret <[email protected]> Signed-off-by: Will Deacon <[email protected]> Signed-off-by: Marc Zyngier <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 717a7ee commit 315775f

File tree

6 files changed

+41
-48
lines changed

6 files changed

+41
-48
lines changed

arch/arm64/include/asm/kvm_arm.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@
135135
* 40 bits wide (T0SZ = 24). Systems with a PARange smaller than 40 bits are
136136
* not known to exist and will break with this configuration.
137137
*
138-
* The VTCR_EL2 is configured per VM and is initialised in kvm_arm_setup_stage2().
138+
* The VTCR_EL2 is configured per VM and is initialised in kvm_init_stage2_mmu.
139139
*
140140
* Note that when using 4K pages, we concatenate two first level page tables
141141
* together. With 16K pages, we concatenate 16 first level page tables.

arch/arm64/include/asm/kvm_host.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -990,8 +990,6 @@ int kvm_set_ipa_limit(void);
990990
#define __KVM_HAVE_ARCH_VM_ALLOC
991991
struct kvm *kvm_arch_alloc_vm(void);
992992

993-
int kvm_arm_setup_stage2(struct kvm *kvm, unsigned long type);
994-
995993
static inline bool kvm_vm_is_protected(struct kvm *kvm)
996994
{
997995
return false;

arch/arm64/include/asm/kvm_mmu.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ int create_hyp_exec_mappings(phys_addr_t phys_addr, size_t size,
166166
void free_hyp_pgds(void);
167167

168168
void stage2_unmap_vm(struct kvm *kvm);
169-
int kvm_init_stage2_mmu(struct kvm *kvm, struct kvm_s2_mmu *mmu);
169+
int kvm_init_stage2_mmu(struct kvm *kvm, struct kvm_s2_mmu *mmu, unsigned long type);
170170
void kvm_free_stage2_pgd(struct kvm_s2_mmu *mmu);
171171
int kvm_phys_addr_ioremap(struct kvm *kvm, phys_addr_t guest_ipa,
172172
phys_addr_t pa, unsigned long size, bool writable);

arch/arm64/kvm/arm.c

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -139,28 +139,24 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
139139
{
140140
int ret;
141141

142-
ret = kvm_arm_setup_stage2(kvm, type);
143-
if (ret)
144-
return ret;
145-
146-
ret = kvm_init_stage2_mmu(kvm, &kvm->arch.mmu);
147-
if (ret)
148-
return ret;
149-
150142
ret = kvm_share_hyp(kvm, kvm + 1);
151143
if (ret)
152-
goto out_free_stage2_pgd;
144+
return ret;
153145

154146
ret = pkvm_init_host_vm(kvm);
155147
if (ret)
156-
goto out_free_stage2_pgd;
148+
goto err_unshare_kvm;
157149

158150
if (!zalloc_cpumask_var(&kvm->arch.supported_cpus, GFP_KERNEL)) {
159151
ret = -ENOMEM;
160-
goto out_free_stage2_pgd;
152+
goto err_unshare_kvm;
161153
}
162154
cpumask_copy(kvm->arch.supported_cpus, cpu_possible_mask);
163155

156+
ret = kvm_init_stage2_mmu(kvm, &kvm->arch.mmu, type);
157+
if (ret)
158+
goto err_free_cpumask;
159+
164160
kvm_vgic_early_init(kvm);
165161

166162
/* The maximum number of VCPUs is limited by the host's GIC model */
@@ -169,9 +165,12 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
169165
set_default_spectre(kvm);
170166
kvm_arm_init_hypercalls(kvm);
171167

172-
return ret;
173-
out_free_stage2_pgd:
174-
kvm_free_stage2_pgd(&kvm->arch.mmu);
168+
return 0;
169+
170+
err_free_cpumask:
171+
free_cpumask_var(kvm->arch.supported_cpus);
172+
err_unshare_kvm:
173+
kvm_unshare_hyp(kvm, kvm + 1);
175174
return ret;
176175
}
177176

arch/arm64/kvm/mmu.c

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -675,15 +675,40 @@ static struct kvm_pgtable_mm_ops kvm_s2_mm_ops = {
675675
* kvm_init_stage2_mmu - Initialise a S2 MMU structure
676676
* @kvm: The pointer to the KVM structure
677677
* @mmu: The pointer to the s2 MMU structure
678+
* @type: The machine type of the virtual machine
678679
*
679680
* Allocates only the stage-2 HW PGD level table(s).
680681
* Note we don't need locking here as this is only called when the VM is
681682
* created, which can only be done once.
682683
*/
683-
int kvm_init_stage2_mmu(struct kvm *kvm, struct kvm_s2_mmu *mmu)
684+
int kvm_init_stage2_mmu(struct kvm *kvm, struct kvm_s2_mmu *mmu, unsigned long type)
684685
{
686+
u32 kvm_ipa_limit = get_kvm_ipa_limit();
685687
int cpu, err;
686688
struct kvm_pgtable *pgt;
689+
u64 mmfr0, mmfr1;
690+
u32 phys_shift;
691+
692+
if (type & ~KVM_VM_TYPE_ARM_IPA_SIZE_MASK)
693+
return -EINVAL;
694+
695+
phys_shift = KVM_VM_TYPE_ARM_IPA_SIZE(type);
696+
if (phys_shift) {
697+
if (phys_shift > kvm_ipa_limit ||
698+
phys_shift < ARM64_MIN_PARANGE_BITS)
699+
return -EINVAL;
700+
} else {
701+
phys_shift = KVM_PHYS_SHIFT;
702+
if (phys_shift > kvm_ipa_limit) {
703+
pr_warn_once("%s using unsupported default IPA limit, upgrade your VMM\n",
704+
current->comm);
705+
return -EINVAL;
706+
}
707+
}
708+
709+
mmfr0 = read_sanitised_ftr_reg(SYS_ID_AA64MMFR0_EL1);
710+
mmfr1 = read_sanitised_ftr_reg(SYS_ID_AA64MMFR1_EL1);
711+
kvm->arch.vtcr = kvm_get_vtcr(mmfr0, mmfr1, phys_shift);
687712

688713
if (mmu->pgt != NULL) {
689714
kvm_err("kvm_arch already initialized?\n");

arch/arm64/kvm/reset.c

Lines changed: 0 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -395,32 +395,3 @@ int kvm_set_ipa_limit(void)
395395

396396
return 0;
397397
}
398-
399-
int kvm_arm_setup_stage2(struct kvm *kvm, unsigned long type)
400-
{
401-
u64 mmfr0, mmfr1;
402-
u32 phys_shift;
403-
404-
if (type & ~KVM_VM_TYPE_ARM_IPA_SIZE_MASK)
405-
return -EINVAL;
406-
407-
phys_shift = KVM_VM_TYPE_ARM_IPA_SIZE(type);
408-
if (phys_shift) {
409-
if (phys_shift > kvm_ipa_limit ||
410-
phys_shift < ARM64_MIN_PARANGE_BITS)
411-
return -EINVAL;
412-
} else {
413-
phys_shift = KVM_PHYS_SHIFT;
414-
if (phys_shift > kvm_ipa_limit) {
415-
pr_warn_once("%s using unsupported default IPA limit, upgrade your VMM\n",
416-
current->comm);
417-
return -EINVAL;
418-
}
419-
}
420-
421-
mmfr0 = read_sanitised_ftr_reg(SYS_ID_AA64MMFR0_EL1);
422-
mmfr1 = read_sanitised_ftr_reg(SYS_ID_AA64MMFR1_EL1);
423-
kvm->arch.vtcr = kvm_get_vtcr(mmfr0, mmfr1, phys_shift);
424-
425-
return 0;
426-
}

0 commit comments

Comments
 (0)