@@ -240,7 +240,6 @@ struct kvm_arch {
unsigned long sdr1;
unsigned long host_sdr1;
int tlbie_lock;
- unsigned long lpcr;
unsigned long rmor;
struct kvm_rma_info *rma;
unsigned long vrma_slb_v;
@@ -261,6 +260,7 @@ struct kvm_arch {
struct mutex hpt_mutex;
#endif
#ifdef CONFIG_PPC_BOOK3S_64
+ unsigned long lpcr;
struct list_head spapr_tce_tables;
struct list_head rtas_tokens;
#endif
@@ -524,6 +524,7 @@ struct kvm_vcpu_arch {
#ifdef CONFIG_PPC_BOOK3S
ulong fault_dar;
u32 fault_dsisr;
+ unsigned long intr_msr;
#endif
#ifdef CONFIG_BOOKE
@@ -616,7 +617,6 @@ struct kvm_vcpu_arch {
spinlock_t tbacct_lock;
u64 busy_stolen;
u64 busy_preempt;
- unsigned long intr_msr;
#endif
};
@@ -473,7 +473,6 @@ int main(void)
#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
DEFINE(KVM_SDR1, offsetof(struct kvm, arch.sdr1));
DEFINE(KVM_HOST_LPID, offsetof(struct kvm, arch.host_lpid));
- DEFINE(KVM_HOST_LPCR, offsetof(struct kvm, arch.host_lpcr));
DEFINE(KVM_HOST_SDR1, offsetof(struct kvm, arch.host_sdr1));
DEFINE(KVM_TLBIE_LOCK, offsetof(struct kvm, arch.tlbie_lock));
DEFINE(KVM_NEED_FLUSH, offsetof(struct kvm, arch.need_tlb_flush.bits));
@@ -484,9 +483,9 @@ int main(void)
DEFINE(VCPU_DAR, offsetof(struct kvm_vcpu, arch.shregs.dar));
DEFINE(VCPU_VPA, offsetof(struct kvm_vcpu, arch.vpa.pinned_addr));
DEFINE(VCPU_VPA_DIRTY, offsetof(struct kvm_vcpu, arch.vpa.dirty));
- DEFINE(VCPU_INTR_MSR, offsetof(struct kvm_vcpu, arch.intr_msr));
#endif
#ifdef CONFIG_PPC_BOOK3S
+ DEFINE(KVM_HOST_LPCR, offsetof(struct kvm, arch.host_lpcr));
DEFINE(VCPU_VCPUID, offsetof(struct kvm_vcpu, vcpu_id));
DEFINE(VCPU_PURR, offsetof(struct kvm_vcpu, arch.purr));
DEFINE(VCPU_SPURR, offsetof(struct kvm_vcpu, arch.spurr));
@@ -510,6 +509,7 @@ int main(void)
DEFINE(VCPU_SLB_NR, offsetof(struct kvm_vcpu, arch.slb_nr));
DEFINE(VCPU_FAULT_DSISR, offsetof(struct kvm_vcpu, arch.fault_dsisr));
DEFINE(VCPU_FAULT_DAR, offsetof(struct kvm_vcpu, arch.fault_dar));
+ DEFINE(VCPU_INTR_MSR, offsetof(struct kvm_vcpu, arch.intr_msr));
DEFINE(VCPU_LAST_INST, offsetof(struct kvm_vcpu, arch.last_inst));
DEFINE(VCPU_TRAP, offsetof(struct kvm_vcpu, arch.trap));
DEFINE(VCPU_PTID, offsetof(struct kvm_vcpu, arch.ptid));
@@ -38,7 +38,7 @@
static void kvmppc_mmu_book3s_64_reset_msr(struct kvm_vcpu *vcpu)
{
- kvmppc_set_msr(vcpu, MSR_SF);
+ kvmppc_set_msr(vcpu, vcpu->arch.intr_msr);
}
static struct kvmppc_slb *kvmppc_mmu_book3s_64_find_slbe(
@@ -226,7 +226,7 @@ static void kvmppc_recalc_shadow_msr(struct kvm_vcpu *vcpu)
ulong smsr = vcpu->arch.shared->msr;
/* Guest MSR values */
- smsr &= MSR_FE0 | MSR_FE1 | MSR_SF | MSR_SE | MSR_BE;
+ smsr &= MSR_FE0 | MSR_FE1 | MSR_SF | MSR_SE | MSR_BE | MSR_LE;
/* Process MSR values */
smsr |= MSR_ME | MSR_RI | MSR_IR | MSR_DR | MSR_PR | MSR_EE;
/* External providers the guest reserved */
@@ -1207,6 +1207,7 @@ static struct kvm_vcpu *kvmppc_core_vcpu_create_pr(struct kvm *kvm,
vcpu->arch.pvr = 0x3C0301;
if (mmu_has_feature(MMU_FTR_1T_SEGMENT))
vcpu->arch.pvr = mfspr(SPRN_PVR);
+ vcpu->arch.intr_msr = MSR_SF;
#else
/* default to book3s_32 (750) */
vcpu->arch.pvr = 0x84202;
@@ -256,6 +256,61 @@ static int kvmppc_h_pr_xics_hcall(struct kvm_vcpu *vcpu, u32 cmd)
return EMULATE_DONE;
}
+static int kvmppc_h_set_mode_pr(struct kvm_vcpu *vcpu, unsigned long mflags,
+ unsigned long resource, unsigned long value1,
+ unsigned long value2)
+{
+ struct kvm *kvm = vcpu->kvm;
+ struct kvm_vcpu *v;
+ int n;
+
+ switch (resource) {
+ case H_SET_MODE_RESOURCE_LE:
+ if (value1)
+ return H_P3;
+ if (value2)
+ return H_P4;
+
+ switch (mflags) {
+ case 0:
+ mutex_lock(&kvm->lock);
+ kvmppc_update_lpcr(kvm, 0, LPCR_ILE);
+ kvm_for_each_vcpu(n, v, kvm)
+ v->arch.intr_msr &= ~MSR_LE;
+ mutex_unlock(&kvm->lock);
+ kick_all_cpus_sync();
+ return H_SUCCESS;
+
+ case 1:
+ mutex_lock(&kvm->lock);
+ kvmppc_update_lpcr(kvm, LPCR_ILE, LPCR_ILE);
+ kvm_for_each_vcpu(n, v, kvm)
+ v->arch.intr_msr |= MSR_LE;
+ mutex_unlock(&kvm->lock);
+ kick_all_cpus_sync();
+ return H_SUCCESS;
+
+ default:
+ return H_UNSUPPORTED_FLAG_START;
+ }
+ default:
+ return H_P2;
+ }
+}
+
+static int kvmppc_h_pr_set_mode(struct kvm_vcpu *vcpu)
+{
+ int ret;
+ unsigned long mflags = kvmppc_get_gpr(vcpu, 4);
+ unsigned long resource = kvmppc_get_gpr(vcpu, 5);
+ unsigned long value1 = kvmppc_get_gpr(vcpu, 6);
+ unsigned long value2 = kvmppc_get_gpr(vcpu, 7);
+
+ ret = kvmppc_h_set_mode_pr(vcpu, mflags, resource, value1, value2);
+ kvmppc_set_gpr(vcpu, 3, ret);
+ return EMULATE_DONE;
+}
+
int kvmppc_h_pr(struct kvm_vcpu *vcpu, unsigned long cmd)
{
switch (cmd) {
@@ -291,6 +346,8 @@ int kvmppc_h_pr(struct kvm_vcpu *vcpu, unsigned long cmd)
break;
kvmppc_set_gpr(vcpu, 3, 0);
return EMULATE_DONE;
+ case H_SET_MODE:
+ return kvmppc_h_pr_set_mode(vcpu);
}
return EMULATE_FAIL;