forked from ~ljy/RK356X_SDK_RELEASE

hc
2023-12-06 08f87f769b595151be1afeff53e144f543faa614
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 */
....@@ -66,10 +64,8 @@
6664 /*
6765 * On POWER7, see if we can handle a machine check that occurred inside
6866 * the guest in real mode, without switching to the host partition.
69
- *
70
- * Returns: 0 => exit guest, 1 => deliver machine check to guest
7167 */
72
-static long kvmppc_realmode_mc_power7(struct kvm_vcpu *vcpu)
68
+static void kvmppc_realmode_mc_power7(struct kvm_vcpu *vcpu)
7369 {
7470 unsigned long srr1 = vcpu->arch.shregs.msr;
7571 struct machine_check_event mce_evt;
....@@ -111,52 +107,24 @@
111107 }
112108
113109 /*
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.
110
+ * Now get the event and stash it in the vcpu struct so it can
111
+ * be handled by the primary thread in virtual mode. We can't
112
+ * call machine_check_queue_event() here if we are running on
113
+ * an offline secondary thread.
120114 */
121
- if (!get_mce_event(&mce_evt, MCE_EVENT_DONTRELEASE))
122
- goto out;
115
+ if (get_mce_event(&mce_evt, MCE_EVENT_RELEASE)) {
116
+ if (handled && mce_evt.version == MCE_V1)
117
+ mce_evt.disposition = MCE_DISPOSITION_RECOVERED;
118
+ } else {
119
+ memset(&mce_evt, 0, sizeof(mce_evt));
120
+ }
123121
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;
122
+ vcpu->arch.mce_evt = mce_evt;
155123 }
156124
157
-long kvmppc_realmode_machine_check(struct kvm_vcpu *vcpu)
125
+void kvmppc_realmode_machine_check(struct kvm_vcpu *vcpu)
158126 {
159
- return kvmppc_realmode_mc_power7(vcpu);
127
+ kvmppc_realmode_mc_power7(vcpu);
160128 }
161129
162130 /* Check if dynamic split is in force and return subcore size accordingly. */
....@@ -177,6 +145,7 @@
177145
178146 local_paca->sibling_subcore_state->in_guest[subcore_id] = 1;
179147 }
148
+EXPORT_SYMBOL_GPL(kvmppc_subcore_enter_guest);
180149
181150 void kvmppc_subcore_exit_guest(void)
182151 {
....@@ -187,6 +156,7 @@
187156
188157 local_paca->sibling_subcore_state->in_guest[subcore_id] = 0;
189158 }
159
+EXPORT_SYMBOL_GPL(kvmppc_subcore_exit_guest);
190160
191161 static bool kvmppc_tb_resync_required(void)
192162 {
....@@ -274,7 +244,7 @@
274244 {
275245 bool resync_req;
276246
277
- __this_cpu_inc(irq_stat.hmi_exceptions);
247
+ local_paca->hmi_irqs++;
278248
279249 if (hmi_handle_debugtrig(NULL) >= 0)
280250 return 1;
....@@ -331,5 +301,13 @@
331301 } else {
332302 wait_for_tb_resync();
333303 }
304
+
305
+ /*
306
+ * Reset tb_offset_applied so the guest exit code won't try
307
+ * to subtract the previous timebase offset from the timebase.
308
+ */
309
+ if (local_paca->kvm_hstate.kvm_vcore)
310
+ local_paca->kvm_hstate.kvm_vcore->tb_offset_applied = 0;
311
+
334312 return 0;
335313 }