소스 검색

KVM: PPC: e500: Add support for EPTCFG register

EPTCFG register defined by E.PT is accessed unconditionally by Linux guests
in the presence of MAV 2.0. Emulate it now.

Signed-off-by: Mihai Caraman <mihai.caraman@freescale.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
Mihai Caraman 12 년 전
부모
커밋
9a6061d7fd
5개의 변경된 파일24개의 추가작업 그리고 0개의 파일을 삭제
  1. 1 0
      Documentation/virtual/kvm/api.txt
  2. 1 0
      arch/powerpc/include/asm/kvm_host.h
  3. 1 0
      arch/powerpc/include/uapi/asm/kvm.h
  4. 9 0
      arch/powerpc/kvm/e500_emulate.c
  5. 12 0
      arch/powerpc/kvm/e500_mmu.c

+ 1 - 0
Documentation/virtual/kvm/api.txt

@@ -1807,6 +1807,7 @@ registers, find a list below:
   PPC   | KVM_REG_PPC_TLB1PS	| 32
   PPC   | KVM_REG_PPC_TLB1PS	| 32
   PPC   | KVM_REG_PPC_TLB2PS	| 32
   PPC   | KVM_REG_PPC_TLB2PS	| 32
   PPC   | KVM_REG_PPC_TLB3PS	| 32
   PPC   | KVM_REG_PPC_TLB3PS	| 32
+  PPC   | KVM_REG_PPC_EPTCFG	| 32
 
 
 ARM registers are mapped using the lower 32 bits.  The upper 16 of that
 ARM registers are mapped using the lower 32 bits.  The upper 16 of that
 is the register group type, or coprocessor number:
 is the register group type, or coprocessor number:

+ 1 - 0
arch/powerpc/include/asm/kvm_host.h

@@ -504,6 +504,7 @@ struct kvm_vcpu_arch {
 	u32 tlbcfg[4];
 	u32 tlbcfg[4];
 	u32 tlbps[4];
 	u32 tlbps[4];
 	u32 mmucfg;
 	u32 mmucfg;
+	u32 eptcfg;
 	u32 epr;
 	u32 epr;
 	u32 crit_save;
 	u32 crit_save;
 	struct kvmppc_booke_debug_reg dbg_reg;
 	struct kvmppc_booke_debug_reg dbg_reg;

+ 1 - 0
arch/powerpc/include/uapi/asm/kvm.h

@@ -469,5 +469,6 @@ struct kvm_get_htab_header {
 #define KVM_REG_PPC_TLB1PS	(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x98)
 #define KVM_REG_PPC_TLB1PS	(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x98)
 #define KVM_REG_PPC_TLB2PS	(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x99)
 #define KVM_REG_PPC_TLB2PS	(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x99)
 #define KVM_REG_PPC_TLB3PS	(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x9a)
 #define KVM_REG_PPC_TLB3PS	(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x9a)
+#define KVM_REG_PPC_EPTCFG	(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x9b)
 
 
 #endif /* __LINUX_KVM_POWERPC_H */
 #endif /* __LINUX_KVM_POWERPC_H */

+ 9 - 0
arch/powerpc/kvm/e500_emulate.c

@@ -317,6 +317,15 @@ int kvmppc_core_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, ulong *spr_val)
 	case SPRN_MMUCFG:
 	case SPRN_MMUCFG:
 		*spr_val = vcpu->arch.mmucfg;
 		*spr_val = vcpu->arch.mmucfg;
 		break;
 		break;
+	case SPRN_EPTCFG:
+		if (!has_feature(vcpu, VCPU_FTR_MMU_V2))
+			return EMULATE_FAIL;
+		/*
+		 * Legacy Linux guests access EPTCFG register even if the E.PT
+		 * category is disabled in the VM. Give them a chance to live.
+		 */
+		*spr_val = vcpu->arch.eptcfg;
+		break;
 
 
 	/* extra exceptions */
 	/* extra exceptions */
 	case SPRN_IVOR32:
 	case SPRN_IVOR32:

+ 12 - 0
arch/powerpc/kvm/e500_mmu.c

@@ -624,6 +624,9 @@ int kvmppc_get_one_reg_e500_tlb(struct kvm_vcpu *vcpu, u64 id,
 	case KVM_REG_PPC_MMUCFG:
 	case KVM_REG_PPC_MMUCFG:
 		*val = get_reg_val(id, vcpu->arch.mmucfg);
 		*val = get_reg_val(id, vcpu->arch.mmucfg);
 		break;
 		break;
+	case KVM_REG_PPC_EPTCFG:
+		*val = get_reg_val(id, vcpu->arch.eptcfg);
+		break;
 	case KVM_REG_PPC_TLB0CFG:
 	case KVM_REG_PPC_TLB0CFG:
 	case KVM_REG_PPC_TLB1CFG:
 	case KVM_REG_PPC_TLB1CFG:
 	case KVM_REG_PPC_TLB2CFG:
 	case KVM_REG_PPC_TLB2CFG:
@@ -678,6 +681,12 @@ int kvmppc_set_one_reg_e500_tlb(struct kvm_vcpu *vcpu, u64 id,
 			r = -EINVAL;
 			r = -EINVAL;
 		break;
 		break;
 	}
 	}
+	case KVM_REG_PPC_EPTCFG: {
+		u32 reg = set_reg_val(id, *val);
+		if (reg != vcpu->arch.eptcfg)
+			r = -EINVAL;
+		break;
+	}
 	case KVM_REG_PPC_TLB0CFG:
 	case KVM_REG_PPC_TLB0CFG:
 	case KVM_REG_PPC_TLB1CFG:
 	case KVM_REG_PPC_TLB1CFG:
 	case KVM_REG_PPC_TLB2CFG:
 	case KVM_REG_PPC_TLB2CFG:
@@ -875,6 +884,9 @@ static int vcpu_mmu_init(struct kvm_vcpu *vcpu,
 	if (has_feature(vcpu, VCPU_FTR_MMU_V2)) {
 	if (has_feature(vcpu, VCPU_FTR_MMU_V2)) {
 		vcpu->arch.tlbps[0] = mfspr(SPRN_TLB0PS);
 		vcpu->arch.tlbps[0] = mfspr(SPRN_TLB0PS);
 		vcpu->arch.tlbps[1] = mfspr(SPRN_TLB1PS);
 		vcpu->arch.tlbps[1] = mfspr(SPRN_TLB1PS);
+
+		/* Guest mmu emulation currently doesn't handle E.PT */
+		vcpu->arch.eptcfg = 0;
 	}
 	}
 
 
 	return 0;
 	return 0;