Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e329fb75 authored by Christoffer Dall's avatar Christoffer Dall Committed by Marc Zyngier
Browse files

KVM: arm/arm64: Factor out VMID into struct kvm_vmid



In preparation for nested virtualization where we are going to have more
than a single VMID per VM, let's factor out the VMID data into a
separate VMID data structure and change the VMID allocator to operate on
this new structure instead of using a struct kvm.

This also means that udate_vttbr now becomes update_vmid, and that the
vttbr itself is generated on the fly based on the stage 2 page table
base address and the vmid.

We cache the physical address of the pgd when allocating the pgd to
avoid doing the calculation on every entry to the guest and to avoid
calling into potentially non-hyp-mapped code from hyp/EL2.

If we wanted to merge the VMID allocator with the arm64 ASID allocator
at some point in the future, it should actually become easier to do that
after this patch.

Note that to avoid mapping the kvm_vmid_bits variable into hyp, we
simply forego the masking of the vmid value in kvm_get_vttbr and rely on
update_vmid to always assign a valid vmid value (within the supported
range).

Reviewed-by: default avatarMarc Zyngier <marc.zyngier@arm.com>
[maz: minor cleanups]
Reviewed-by: default avatarJulien Thierry <julien.thierry@arm.com>
Signed-off-by: default avatarChristoffer Dall <christoffer.dall@arm.com>
Signed-off-by: default avatarMarc Zyngier <marc.zyngier@arm.com>
parent 32f13955
Loading
Loading
Loading
Loading
+8 −5
Original line number Diff line number Diff line
@@ -57,10 +57,13 @@ int __attribute_const__ kvm_target_cpu(void);
int kvm_reset_vcpu(struct kvm_vcpu *vcpu);
void kvm_reset_coprocs(struct kvm_vcpu *vcpu);

struct kvm_arch {
	/* VTTBR value associated with below pgd and vmid */
	u64    vttbr;
struct kvm_vmid {
	/* The VMID generation used for the virt. memory system */
	u64    vmid_gen;
	u32    vmid;
};

struct kvm_arch {
	/* The last vcpu id that ran on each physical CPU */
	int __percpu *last_vcpu_ran;

@@ -70,11 +73,11 @@ struct kvm_arch {
	 */

	/* The VMID generation used for the virt. memory system */
	u64    vmid_gen;
	u32    vmid;
	struct kvm_vmid vmid;

	/* Stage-2 page table */
	pgd_t *pgd;
	phys_addr_t pgd_phys;

	/* Interrupt controller */
	struct vgic_dist	vgic;
+7 −2
Original line number Diff line number Diff line
@@ -421,9 +421,14 @@ static inline int hyp_map_aux_data(void)

static inline void kvm_set_ipa_limit(void) {}

static inline bool kvm_cpu_has_cnp(void)
static __always_inline u64 kvm_get_vttbr(struct kvm *kvm)
{
	return false;
	struct kvm_vmid *vmid = &kvm->arch.vmid;
	u64 vmid_field, baddr;

	baddr = kvm->arch.pgd_phys;
	vmid_field = (u64)vmid->vmid << VTTBR_VMID_SHIFT;
	return kvm_phys_to_vttbr(baddr) | vmid_field;
}

#endif	/* !__ASSEMBLY__ */
+1 −1
Original line number Diff line number Diff line
@@ -77,7 +77,7 @@ static void __hyp_text __deactivate_traps(struct kvm_vcpu *vcpu)
static void __hyp_text __activate_vm(struct kvm_vcpu *vcpu)
{
	struct kvm *kvm = kern_hyp_va(vcpu->kvm);
	write_sysreg(kvm->arch.vttbr, VTTBR);
	write_sysreg(kvm_get_vttbr(kvm), VTTBR);
	write_sysreg(vcpu->arch.midr, VPIDR);
}

+2 −2
Original line number Diff line number Diff line
@@ -41,7 +41,7 @@ void __hyp_text __kvm_tlb_flush_vmid(struct kvm *kvm)

	/* Switch to requested VMID */
	kvm = kern_hyp_va(kvm);
	write_sysreg(kvm->arch.vttbr, VTTBR);
	write_sysreg(kvm_get_vttbr(kvm), VTTBR);
	isb();

	write_sysreg(0, TLBIALLIS);
@@ -61,7 +61,7 @@ void __hyp_text __kvm_tlb_flush_local_vmid(struct kvm_vcpu *vcpu)
	struct kvm *kvm = kern_hyp_va(kern_hyp_va(vcpu)->kvm);

	/* Switch to requested VMID */
	write_sysreg(kvm->arch.vttbr, VTTBR);
	write_sysreg(kvm_get_vttbr(kvm), VTTBR);
	isb();

	write_sysreg(0, TLBIALL);
+6 −3
Original line number Diff line number Diff line
@@ -57,16 +57,19 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu);
int kvm_arch_vm_ioctl_check_extension(struct kvm *kvm, long ext);
void __extended_idmap_trampoline(phys_addr_t boot_pgd, phys_addr_t idmap_start);

struct kvm_arch {
struct kvm_vmid {
	/* The VMID generation used for the virt. memory system */
	u64    vmid_gen;
	u32    vmid;
};

struct kvm_arch {
	struct kvm_vmid vmid;

	/* stage2 entry level table */
	pgd_t *pgd;
	phys_addr_t pgd_phys;

	/* VTTBR value associated with above pgd and vmid */
	u64    vttbr;
	/* VTCR_EL2 value for this VM */
	u64    vtcr;

Loading