forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-05-10 cde9070d9970eef1f7ec2360586c802a16230ad8
kernel/arch/powerpc/kvm/book3s_hv_ras.c
....@@ -1,7 +1,5 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
2
- * This program is free software; you can redistribute it and/or modify
3
- * it under the terms of the GNU General Public License, version 2, as
4
- * published by the Free Software Foundation.
53 *
64 * Copyright 2012 Paul Mackerras, IBM Corp. <paulus@au1.ibm.com>
75 */
....@@ -11,6 +9,7 @@
119 #include <linux/kvm.h>
1210 #include <linux/kvm_host.h>
1311 #include <linux/kernel.h>
12
+#include <asm/lppaca.h>
1413 #include <asm/opal.h>
1514 #include <asm/mce.h>
1615 #include <asm/machdep.h>
....@@ -66,10 +65,8 @@
6665 /*
6766 * On POWER7, see if we can handle a machine check that occurred inside
6867 * the guest in real mode, without switching to the host partition.
69
- *
70
- * Returns: 0 => exit guest, 1 => deliver machine check to guest
7168 */
72
-static long kvmppc_realmode_mc_power7(struct kvm_vcpu *vcpu)
69
+static void kvmppc_realmode_mc_power7(struct kvm_vcpu *vcpu)
7370 {
7471 unsigned long srr1 = vcpu->arch.shregs.msr;
7572 struct machine_check_event mce_evt;
....@@ -111,52 +108,24 @@
111108 }
112109
113110 /*
114
- * See if we have already handled the condition in the linux host.
115
- * We assume that if the condition is recovered then linux host
116
- * will have generated an error log event that we will pick
117
- * up and log later.
118
- * Don't release mce event now. We will queue up the event so that
119
- * we can log the MCE event info on host console.
111
+ * Now get the event and stash it in the vcpu struct so it can
112
+ * be handled by the primary thread in virtual mode. We can't
113
+ * call machine_check_queue_event() here if we are running on
114
+ * an offline secondary thread.
120115 */
121
- if (!get_mce_event(&mce_evt, MCE_EVENT_DONTRELEASE))
122
- goto out;
116
+ if (get_mce_event(&mce_evt, MCE_EVENT_RELEASE)) {
117
+ if (handled && mce_evt.version == MCE_V1)
118
+ mce_evt.disposition = MCE_DISPOSITION_RECOVERED;
119
+ } else {
120
+ memset(&mce_evt, 0, sizeof(mce_evt));
121
+ }
123122
124
- if (mce_evt.version == MCE_V1 &&
125
- (mce_evt.severity == MCE_SEV_NO_ERROR ||
126
- mce_evt.disposition == MCE_DISPOSITION_RECOVERED))
127
- handled = 1;
128
-
129
-out:
130
- /*
131
- * For guest that supports FWNMI capability, hook the MCE event into
132
- * vcpu structure. We are going to exit the guest with KVM_EXIT_NMI
133
- * exit reason. On our way to exit we will pull this event from vcpu
134
- * structure and print it from thread 0 of the core/subcore.
135
- *
136
- * For guest that does not support FWNMI capability (old QEMU):
137
- * We are now going enter guest either through machine check
138
- * interrupt (for unhandled errors) or will continue from
139
- * current HSRR0 (for handled errors) in guest. Hence
140
- * queue up the event so that we can log it from host console later.
141
- */
142
- if (vcpu->kvm->arch.fwnmi_enabled) {
143
- /*
144
- * Hook up the mce event on to vcpu structure.
145
- * First clear the old event.
146
- */
147
- memset(&vcpu->arch.mce_evt, 0, sizeof(vcpu->arch.mce_evt));
148
- if (get_mce_event(&mce_evt, MCE_EVENT_RELEASE)) {
149
- vcpu->arch.mce_evt = mce_evt;
150
- }
151
- } else
152
- machine_check_queue_event();
153
-
154
- return handled;
123
+ vcpu->arch.mce_evt = mce_evt;
155124 }
156125
157
-long kvmppc_realmode_machine_check(struct kvm_vcpu *vcpu)
126
+void kvmppc_realmode_machine_check(struct kvm_vcpu *vcpu)
158127 {
159
- return kvmppc_realmode_mc_power7(vcpu);
128
+ kvmppc_realmode_mc_power7(vcpu);
160129 }
161130
162131 /* Check if dynamic split is in force and return subcore size accordingly. */
....@@ -177,6 +146,7 @@
177146
178147 local_paca->sibling_subcore_state->in_guest[subcore_id] = 1;
179148 }
149
+EXPORT_SYMBOL_GPL(kvmppc_subcore_enter_guest);
180150
181151 void kvmppc_subcore_exit_guest(void)
182152 {
....@@ -187,6 +157,7 @@
187157
188158 local_paca->sibling_subcore_state->in_guest[subcore_id] = 0;
189159 }
160
+EXPORT_SYMBOL_GPL(kvmppc_subcore_exit_guest);
190161
191162 static bool kvmppc_tb_resync_required(void)
192163 {
....@@ -274,7 +245,7 @@
274245 {
275246 bool resync_req;
276247
277
- __this_cpu_inc(irq_stat.hmi_exceptions);
248
+ local_paca->hmi_irqs++;
278249
279250 if (hmi_handle_debugtrig(NULL) >= 0)
280251 return 1;
....@@ -331,5 +302,13 @@
331302 } else {
332303 wait_for_tb_resync();
333304 }
305
+
306
+ /*
307
+ * Reset tb_offset_applied so the guest exit code won't try
308
+ * to subtract the previous timebase offset from the timebase.
309
+ */
310
+ if (local_paca->kvm_hstate.kvm_vcore)
311
+ local_paca->kvm_hstate.kvm_vcore->tb_offset_applied = 0;
312
+
334313 return 0;
335314 }