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

Commit dd9ebf1f authored by Liu Yu's avatar Liu Yu Committed by Avi Kivity
Browse files

KVM: PPC: e500: Add shadow PID support



Dynamically assign host PIDs to guest PIDs, splitting each guest PID into
multiple host (shadow) PIDs based on kernel/user and MSR[IS/DS].  Use
both PID0 and PID1 so that the shadow PIDs for the right mode can be
selected, that correspond both to guest TID = zero and guest TID = guest
PID.

This allows us to significantly reduce the frequency of needing to
invalidate the entire TLB.  When the guest mode or PID changes, we just
update the host PID0/PID1.  And since the allocation of shadow PIDs is
global, multiple guests can share the TLB without conflict.

Note that KVM does not yet support the guest setting PID1 or PID2 to
a value other than zero.  This will need to be fixed for nested KVM
to work.  Until then, we enforce the requirement for guest PID1/PID2
to stay zero by failing the emulation if the guest tries to set them
to something else.

Signed-off-by: default avatarLiu Yu <yu.liu@freescale.com>
Signed-off-by: default avatarScott Wood <scottwood@freescale.com>
Signed-off-by: default avatarAlexander Graf <agraf@suse.de>
parent 08b7fa92
Loading
Loading
Loading
Loading
+7 −1
Original line number Diff line number Diff line
/*
 * Copyright (C) 2008 Freescale Semiconductor, Inc. All rights reserved.
 * Copyright (C) 2008-2011 Freescale Semiconductor, Inc. All rights reserved.
 *
 * Author: Yu Liu, <yu.liu@freescale.com>
 *
@@ -37,6 +37,8 @@ struct tlbe_priv {
	unsigned int flags; /* E500_TLB_* */
};

struct vcpu_id_table;

struct kvmppc_vcpu_e500 {
	/* Unmodified copy of the guest's TLB. */
	struct tlbe *gtlb_arch[E500_TLB_NUM];
@@ -59,6 +61,10 @@ struct kvmppc_vcpu_e500 {
	u32 mas5;
	u32 mas6;
	u32 mas7;

	/* vcpu id table */
	struct vcpu_id_table *idt;

	u32 l1csr0;
	u32 l1csr1;
	u32 hid0;
+1 −0
Original line number Diff line number Diff line
@@ -255,6 +255,7 @@ struct kvm_vcpu_arch {
	u32 pvr;

	u32 shadow_pid;
	u32 shadow_pid1;
	u32 pid;
	u32 swap_pid;

+1 −0
Original line number Diff line number Diff line
@@ -402,6 +402,7 @@ int main(void)
	DEFINE(VCPU_SPRG6, offsetof(struct kvm_vcpu, arch.sprg6));
	DEFINE(VCPU_SPRG7, offsetof(struct kvm_vcpu, arch.sprg7));
	DEFINE(VCPU_SHADOW_PID, offsetof(struct kvm_vcpu, arch.shadow_pid));
	DEFINE(VCPU_SHADOW_PID1, offsetof(struct kvm_vcpu, arch.shadow_pid1));
	DEFINE(VCPU_SHARED, offsetof(struct kvm_vcpu, arch.shared));
	DEFINE(VCPU_SHARED_MSR, offsetof(struct kvm_vcpu_arch_shared, msr));
	DEFINE(VCPU_SHADOW_MSR, offsetof(struct kvm_vcpu, arch.shadow_msr));
+3 −1
Original line number Diff line number Diff line
@@ -387,8 +387,10 @@ static void kvmppc_44x_invalidate(struct kvm_vcpu *vcpu,
	}
}

void kvmppc_mmu_priv_switch(struct kvm_vcpu *vcpu, int usermode)
void kvmppc_mmu_msr_notify(struct kvm_vcpu *vcpu, u32 old_msr)
{
	int usermode = vcpu->arch.shared->msr & MSR_PR;

	vcpu->arch.shadow_pid = !usermode;
}

+7 −4
Original line number Diff line number Diff line
@@ -113,15 +113,18 @@ static void kvmppc_vcpu_sync_spe(struct kvm_vcpu *vcpu)
}
#endif

/* Helper function for "full" MSR writes. No need to call this if only EE is
 * changing. */
/*
 * Helper function for "full" MSR writes.  No need to call this if only
 * EE/CE/ME/DE/RI are changing.
 */
void kvmppc_set_msr(struct kvm_vcpu *vcpu, u32 new_msr)
{
	if ((new_msr & MSR_PR) != (vcpu->arch.shared->msr & MSR_PR))
		kvmppc_mmu_priv_switch(vcpu, new_msr & MSR_PR);
	u32 old_msr = vcpu->arch.shared->msr;

	vcpu->arch.shared->msr = new_msr;

	kvmppc_mmu_msr_notify(vcpu, old_msr);

	if (vcpu->arch.shared->msr & MSR_WE) {
		kvm_vcpu_block(vcpu);
		kvmppc_set_exit_type(vcpu, EMULATED_MTMSRWE_EXITS);
Loading