aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kvm
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kvm')
-rw-r--r--arch/powerpc/kvm/book3s_hv_ras.c50
-rw-r--r--arch/powerpc/kvm/bookehv_interrupts.S2
2 files changed, 26 insertions, 26 deletions
diff --git a/arch/powerpc/kvm/book3s_hv_ras.c b/arch/powerpc/kvm/book3s_hv_ras.c
index a353c485808c..768a9f977c00 100644
--- a/arch/powerpc/kvm/book3s_hv_ras.c
+++ b/arch/powerpc/kvm/book3s_hv_ras.c
@@ -12,6 +12,7 @@
12#include <linux/kvm_host.h> 12#include <linux/kvm_host.h>
13#include <linux/kernel.h> 13#include <linux/kernel.h>
14#include <asm/opal.h> 14#include <asm/opal.h>
15#include <asm/mce.h>
15 16
16/* SRR1 bits for machine check on POWER7 */ 17/* SRR1 bits for machine check on POWER7 */
17#define SRR1_MC_LDSTERR (1ul << (63-42)) 18#define SRR1_MC_LDSTERR (1ul << (63-42))
@@ -58,18 +59,6 @@ static void reload_slb(struct kvm_vcpu *vcpu)
58 } 59 }
59} 60}
60 61
61/* POWER7 TLB flush */
62static void flush_tlb_power7(struct kvm_vcpu *vcpu)
63{
64 unsigned long i, rb;
65
66 rb = TLBIEL_INVAL_SET_LPID;
67 for (i = 0; i < POWER7_TLB_SETS; ++i) {
68 asm volatile("tlbiel %0" : : "r" (rb));
69 rb += 1 << TLBIEL_INVAL_SET_SHIFT;
70 }
71}
72
73/* 62/*
74 * On POWER7, see if we can handle a machine check that occurred inside 63 * On POWER7, see if we can handle a machine check that occurred inside
75 * the guest in real mode, without switching to the host partition. 64 * the guest in real mode, without switching to the host partition.
@@ -79,9 +68,7 @@ static void flush_tlb_power7(struct kvm_vcpu *vcpu)
79static long kvmppc_realmode_mc_power7(struct kvm_vcpu *vcpu) 68static long kvmppc_realmode_mc_power7(struct kvm_vcpu *vcpu)
80{ 69{
81 unsigned long srr1 = vcpu->arch.shregs.msr; 70 unsigned long srr1 = vcpu->arch.shregs.msr;
82#ifdef CONFIG_PPC_POWERNV 71 struct machine_check_event mce_evt;
83 struct opal_machine_check_event *opal_evt;
84#endif
85 long handled = 1; 72 long handled = 1;
86 73
87 if (srr1 & SRR1_MC_LDSTERR) { 74 if (srr1 & SRR1_MC_LDSTERR) {
@@ -96,7 +83,8 @@ static long kvmppc_realmode_mc_power7(struct kvm_vcpu *vcpu)
96 DSISR_MC_SLB_PARITY | DSISR_MC_DERAT_MULTI); 83 DSISR_MC_SLB_PARITY | DSISR_MC_DERAT_MULTI);
97 } 84 }
98 if (dsisr & DSISR_MC_TLB_MULTI) { 85 if (dsisr & DSISR_MC_TLB_MULTI) {
99 flush_tlb_power7(vcpu); 86 if (cur_cpu_spec && cur_cpu_spec->flush_tlb)
87 cur_cpu_spec->flush_tlb(TLBIEL_INVAL_SET_LPID);
100 dsisr &= ~DSISR_MC_TLB_MULTI; 88 dsisr &= ~DSISR_MC_TLB_MULTI;
101 } 89 }
102 /* Any other errors we don't understand? */ 90 /* Any other errors we don't understand? */
@@ -113,28 +101,38 @@ static long kvmppc_realmode_mc_power7(struct kvm_vcpu *vcpu)
113 reload_slb(vcpu); 101 reload_slb(vcpu);
114 break; 102 break;
115 case SRR1_MC_IFETCH_TLBMULTI: 103 case SRR1_MC_IFETCH_TLBMULTI:
116 flush_tlb_power7(vcpu); 104 if (cur_cpu_spec && cur_cpu_spec->flush_tlb)
105 cur_cpu_spec->flush_tlb(TLBIEL_INVAL_SET_LPID);
117 break; 106 break;
118 default: 107 default:
119 handled = 0; 108 handled = 0;
120 } 109 }
121 110
122#ifdef CONFIG_PPC_POWERNV
123 /* 111 /*
124 * See if OPAL has already handled the condition. 112 * See if we have already handled the condition in the linux host.
125 * We assume that if the condition is recovered then OPAL 113 * We assume that if the condition is recovered then linux host
126 * will have generated an error log event that we will pick 114 * will have generated an error log event that we will pick
127 * up and log later. 115 * up and log later.
116 * Don't release mce event now. In case if condition is not
117 * recovered we do guest exit and go back to linux host machine
118 * check handler. Hence we need make sure that current mce event
119 * is available for linux host to consume.
128 */ 120 */
129 opal_evt = local_paca->opal_mc_evt; 121 if (!get_mce_event(&mce_evt, MCE_EVENT_DONTRELEASE))
130 if (opal_evt->version == OpalMCE_V1 && 122 goto out;
131 (opal_evt->severity == OpalMCE_SEV_NO_ERROR || 123
132 opal_evt->disposition == OpalMCE_DISPOSITION_RECOVERED)) 124 if (mce_evt.version == MCE_V1 &&
125 (mce_evt.severity == MCE_SEV_NO_ERROR ||
126 mce_evt.disposition == MCE_DISPOSITION_RECOVERED))
133 handled = 1; 127 handled = 1;
134 128
129out:
130 /*
131 * If we have handled the error, then release the mce event because
132 * we will be delivering machine check to guest.
133 */
135 if (handled) 134 if (handled)
136 opal_evt->in_use = 0; 135 release_mce_event();
137#endif
138 136
139 return handled; 137 return handled;
140} 138}
diff --git a/arch/powerpc/kvm/bookehv_interrupts.S b/arch/powerpc/kvm/bookehv_interrupts.S
index be3de1dd7bb3..e4185f6b3309 100644
--- a/arch/powerpc/kvm/bookehv_interrupts.S
+++ b/arch/powerpc/kvm/bookehv_interrupts.S
@@ -321,6 +321,8 @@ kvm_handler BOOKE_INTERRUPT_DEBUG, EX_PARAMS(DBG), \
321 SPRN_DSRR0, SPRN_DSRR1, 0 321 SPRN_DSRR0, SPRN_DSRR1, 0
322kvm_handler BOOKE_INTERRUPT_DEBUG, EX_PARAMS(CRIT), \ 322kvm_handler BOOKE_INTERRUPT_DEBUG, EX_PARAMS(CRIT), \
323 SPRN_CSRR0, SPRN_CSRR1, 0 323 SPRN_CSRR0, SPRN_CSRR1, 0
324kvm_handler BOOKE_INTERRUPT_LRAT_ERROR, EX_PARAMS(GEN), \
325 SPRN_SRR0, SPRN_SRR1, (NEED_EMU | NEED_DEAR | NEED_ESR)
324#else 326#else
325/* 327/*
326 * For input register values, see arch/powerpc/include/asm/kvm_booke_hv_asm.h 328 * For input register values, see arch/powerpc/include/asm/kvm_booke_hv_asm.h