Linux Audio

Check our new training course

Loading...
v4.17
 
  1/*
  2 * Copyright (C) 2012,2013 - ARM Ltd
  3 * Author: Marc Zyngier <marc.zyngier@arm.com>
  4 *
  5 * Derived from arch/arm/kvm/handle_exit.c:
  6 * Copyright (C) 2012 - Virtual Open Systems and Columbia University
  7 * Author: Christoffer Dall <c.dall@virtualopensystems.com>
  8 *
  9 * This program is free software; you can redistribute it and/or modify
 10 * it under the terms of the GNU General Public License version 2 as
 11 * published by the Free Software Foundation.
 12 *
 13 * This program is distributed in the hope that it will be useful,
 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 16 * GNU General Public License for more details.
 17 *
 18 * You should have received a copy of the GNU General Public License
 19 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 20 */
 21
 22#include <linux/kvm.h>
 23#include <linux/kvm_host.h>
 24
 25#include <kvm/arm_psci.h>
 26
 27#include <asm/esr.h>
 28#include <asm/exception.h>
 29#include <asm/kvm_asm.h>
 30#include <asm/kvm_coproc.h>
 31#include <asm/kvm_emulate.h>
 32#include <asm/kvm_mmu.h>
 33#include <asm/debug-monitors.h>
 34#include <asm/traps.h>
 35
 36#define CREATE_TRACE_POINTS
 37#include "trace.h"
 38
 39typedef int (*exit_handle_fn)(struct kvm_vcpu *, struct kvm_run *);
 40
 41static void kvm_handle_guest_serror(struct kvm_vcpu *vcpu, u32 esr)
 42{
 43	if (!arm64_is_ras_serror(esr) || arm64_is_fatal_ras_serror(NULL, esr))
 44		kvm_inject_vabt(vcpu);
 45}
 46
 47static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run *run)
 48{
 49	int ret;
 50
 51	trace_kvm_hvc_arm64(*vcpu_pc(vcpu), vcpu_get_reg(vcpu, 0),
 52			    kvm_vcpu_hvc_get_imm(vcpu));
 53	vcpu->stat.hvc_exit_stat++;
 54
 55	ret = kvm_hvc_call_handler(vcpu);
 56	if (ret < 0) {
 57		vcpu_set_reg(vcpu, 0, ~0UL);
 58		return 1;
 59	}
 60
 61	return ret;
 62}
 63
 64static int handle_smc(struct kvm_vcpu *vcpu, struct kvm_run *run)
 65{
 66	/*
 67	 * "If an SMC instruction executed at Non-secure EL1 is
 68	 * trapped to EL2 because HCR_EL2.TSC is 1, the exception is a
 69	 * Trap exception, not a Secure Monitor Call exception [...]"
 70	 *
 71	 * We need to advance the PC after the trap, as it would
 72	 * otherwise return to the same address...
 73	 */
 74	vcpu_set_reg(vcpu, 0, ~0UL);
 75	kvm_skip_instr(vcpu, kvm_vcpu_trap_il_is32bit(vcpu));
 76	return 1;
 77}
 78
 79/*
 80 * Guest access to FP/ASIMD registers are routed to this handler only
 81 * when the system doesn't support FP/ASIMD.
 82 */
 83static int handle_no_fpsimd(struct kvm_vcpu *vcpu, struct kvm_run *run)
 84{
 85	kvm_inject_undefined(vcpu);
 86	return 1;
 87}
 88
 89/**
 90 * kvm_handle_wfx - handle a wait-for-interrupts or wait-for-event
 91 *		    instruction executed by a guest
 92 *
 93 * @vcpu:	the vcpu pointer
 94 *
 95 * WFE: Yield the CPU and come back to this vcpu when the scheduler
 96 * decides to.
 97 * WFI: Simply call kvm_vcpu_block(), which will halt execution of
 98 * world-switches and schedule other host processes until there is an
 99 * incoming IRQ or FIQ to the VM.
100 */
101static int kvm_handle_wfx(struct kvm_vcpu *vcpu, struct kvm_run *run)
102{
103	if (kvm_vcpu_get_hsr(vcpu) & ESR_ELx_WFx_ISS_WFE) {
104		trace_kvm_wfx_arm64(*vcpu_pc(vcpu), true);
105		vcpu->stat.wfe_exit_stat++;
106		kvm_vcpu_on_spin(vcpu, vcpu_mode_priv(vcpu));
107	} else {
108		trace_kvm_wfx_arm64(*vcpu_pc(vcpu), false);
109		vcpu->stat.wfi_exit_stat++;
110		kvm_vcpu_block(vcpu);
111		kvm_clear_request(KVM_REQ_UNHALT, vcpu);
112	}
113
114	kvm_skip_instr(vcpu, kvm_vcpu_trap_il_is32bit(vcpu));
115
116	return 1;
117}
118
119/**
120 * kvm_handle_guest_debug - handle a debug exception instruction
121 *
122 * @vcpu:	the vcpu pointer
123 * @run:	access to the kvm_run structure for results
124 *
125 * We route all debug exceptions through the same handler. If both the
126 * guest and host are using the same debug facilities it will be up to
127 * userspace to re-inject the correct exception for guest delivery.
128 *
129 * @return: 0 (while setting run->exit_reason), -1 for error
130 */
131static int kvm_handle_guest_debug(struct kvm_vcpu *vcpu, struct kvm_run *run)
132{
133	u32 hsr = kvm_vcpu_get_hsr(vcpu);
134	int ret = 0;
135
136	run->exit_reason = KVM_EXIT_DEBUG;
137	run->debug.arch.hsr = hsr;
138
139	switch (ESR_ELx_EC(hsr)) {
140	case ESR_ELx_EC_WATCHPT_LOW:
141		run->debug.arch.far = vcpu->arch.fault.far_el2;
142		/* fall through */
143	case ESR_ELx_EC_SOFTSTP_LOW:
144	case ESR_ELx_EC_BREAKPT_LOW:
145	case ESR_ELx_EC_BKPT32:
146	case ESR_ELx_EC_BRK64:
147		break;
148	default:
149		kvm_err("%s: un-handled case hsr: %#08x\n",
150			__func__, (unsigned int) hsr);
151		ret = -1;
152		break;
153	}
154
155	return ret;
156}
157
158static int kvm_handle_unknown_ec(struct kvm_vcpu *vcpu, struct kvm_run *run)
159{
160	u32 hsr = kvm_vcpu_get_hsr(vcpu);
161
162	kvm_pr_unimpl("Unknown exception class: hsr: %#08x -- %s\n",
163		      hsr, esr_get_class_string(hsr));
164
165	kvm_inject_undefined(vcpu);
166	return 1;
167}
168
169static int handle_sve(struct kvm_vcpu *vcpu, struct kvm_run *run)
170{
171	/* Until SVE is supported for guests: */
172	kvm_inject_undefined(vcpu);
173	return 1;
174}
175
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
176static exit_handle_fn arm_exit_handlers[] = {
177	[0 ... ESR_ELx_EC_MAX]	= kvm_handle_unknown_ec,
178	[ESR_ELx_EC_WFx]	= kvm_handle_wfx,
179	[ESR_ELx_EC_CP15_32]	= kvm_handle_cp15_32,
180	[ESR_ELx_EC_CP15_64]	= kvm_handle_cp15_64,
181	[ESR_ELx_EC_CP14_MR]	= kvm_handle_cp14_32,
182	[ESR_ELx_EC_CP14_LS]	= kvm_handle_cp14_load_store,
183	[ESR_ELx_EC_CP14_64]	= kvm_handle_cp14_64,
184	[ESR_ELx_EC_HVC32]	= handle_hvc,
185	[ESR_ELx_EC_SMC32]	= handle_smc,
186	[ESR_ELx_EC_HVC64]	= handle_hvc,
187	[ESR_ELx_EC_SMC64]	= handle_smc,
188	[ESR_ELx_EC_SYS64]	= kvm_handle_sys_reg,
189	[ESR_ELx_EC_SVE]	= handle_sve,
190	[ESR_ELx_EC_IABT_LOW]	= kvm_handle_guest_abort,
191	[ESR_ELx_EC_DABT_LOW]	= kvm_handle_guest_abort,
192	[ESR_ELx_EC_SOFTSTP_LOW]= kvm_handle_guest_debug,
193	[ESR_ELx_EC_WATCHPT_LOW]= kvm_handle_guest_debug,
194	[ESR_ELx_EC_BREAKPT_LOW]= kvm_handle_guest_debug,
195	[ESR_ELx_EC_BKPT32]	= kvm_handle_guest_debug,
196	[ESR_ELx_EC_BRK64]	= kvm_handle_guest_debug,
197	[ESR_ELx_EC_FP_ASIMD]	= handle_no_fpsimd,
 
198};
199
200static exit_handle_fn kvm_get_exit_handler(struct kvm_vcpu *vcpu)
201{
202	u32 hsr = kvm_vcpu_get_hsr(vcpu);
203	u8 hsr_ec = ESR_ELx_EC(hsr);
204
205	return arm_exit_handlers[hsr_ec];
206}
207
208/*
209 * We may be single-stepping an emulated instruction. If the emulation
210 * has been completed in the kernel, we can return to userspace with a
211 * KVM_EXIT_DEBUG, otherwise userspace needs to complete its
212 * emulation first.
213 */
214static int handle_trap_exceptions(struct kvm_vcpu *vcpu, struct kvm_run *run)
215{
216	int handled;
217
218	/*
219	 * See ARM ARM B1.14.1: "Hyp traps on instructions
220	 * that fail their condition code check"
221	 */
222	if (!kvm_condition_valid(vcpu)) {
223		kvm_skip_instr(vcpu, kvm_vcpu_trap_il_is32bit(vcpu));
224		handled = 1;
225	} else {
226		exit_handle_fn exit_handler;
227
228		exit_handler = kvm_get_exit_handler(vcpu);
229		handled = exit_handler(vcpu, run);
230	}
231
232	/*
233	 * kvm_arm_handle_step_debug() sets the exit_reason on the kvm_run
234	 * structure if we need to return to userspace.
235	 */
236	if (handled > 0 && kvm_arm_handle_step_debug(vcpu, run))
237		handled = 0;
238
239	return handled;
240}
241
242/*
243 * Return > 0 to return to guest, < 0 on error, 0 (and set exit_reason) on
244 * proper exit to userspace.
245 */
246int handle_exit(struct kvm_vcpu *vcpu, struct kvm_run *run,
247		       int exception_index)
248{
249	if (ARM_SERROR_PENDING(exception_index)) {
250		u8 hsr_ec = ESR_ELx_EC(kvm_vcpu_get_hsr(vcpu));
251
252		/*
253		 * HVC/SMC already have an adjusted PC, which we need
254		 * to correct in order to return to after having
255		 * injected the SError.
256		 */
257		if (hsr_ec == ESR_ELx_EC_HVC32 || hsr_ec == ESR_ELx_EC_HVC64 ||
258		    hsr_ec == ESR_ELx_EC_SMC32 || hsr_ec == ESR_ELx_EC_SMC64) {
259			u32 adj =  kvm_vcpu_trap_il_is32bit(vcpu) ? 4 : 2;
260			*vcpu_pc(vcpu) -= adj;
261		}
262
263		return 1;
264	}
265
266	exception_index = ARM_EXCEPTION_CODE(exception_index);
267
268	switch (exception_index) {
269	case ARM_EXCEPTION_IRQ:
270		return 1;
271	case ARM_EXCEPTION_EL1_SERROR:
272		/* We may still need to return for single-step */
273		if (!(*vcpu_cpsr(vcpu) & DBG_SPSR_SS)
274			&& kvm_arm_handle_step_debug(vcpu, run))
275			return 0;
276		else
277			return 1;
278	case ARM_EXCEPTION_TRAP:
279		return handle_trap_exceptions(vcpu, run);
280	case ARM_EXCEPTION_HYP_GONE:
281		/*
282		 * EL2 has been reset to the hyp-stub. This happens when a guest
283		 * is pre-empted by kvm_reboot()'s shutdown call.
284		 */
285		run->exit_reason = KVM_EXIT_FAIL_ENTRY;
286		return 0;
 
 
 
 
 
 
 
287	default:
288		kvm_pr_unimpl("Unsupported exception type: %d",
289			      exception_index);
290		run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
291		return 0;
292	}
293}
294
295/* For exit types that need handling before we can be preempted */
296void handle_exit_early(struct kvm_vcpu *vcpu, struct kvm_run *run,
297		       int exception_index)
298{
299	if (ARM_SERROR_PENDING(exception_index)) {
300		if (this_cpu_has_cap(ARM64_HAS_RAS_EXTN)) {
301			u64 disr = kvm_vcpu_get_disr(vcpu);
302
303			kvm_handle_guest_serror(vcpu, disr_to_esr(disr));
304		} else {
305			kvm_inject_vabt(vcpu);
306		}
307
308		return;
309	}
310
311	exception_index = ARM_EXCEPTION_CODE(exception_index);
312
313	if (exception_index == ARM_EXCEPTION_EL1_SERROR)
314		kvm_handle_guest_serror(vcpu, kvm_vcpu_get_hsr(vcpu));
315}
v5.4
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * Copyright (C) 2012,2013 - ARM Ltd
  4 * Author: Marc Zyngier <marc.zyngier@arm.com>
  5 *
  6 * Derived from arch/arm/kvm/handle_exit.c:
  7 * Copyright (C) 2012 - Virtual Open Systems and Columbia University
  8 * Author: Christoffer Dall <c.dall@virtualopensystems.com>
 
 
 
 
 
 
 
 
 
 
 
 
  9 */
 10
 11#include <linux/kvm.h>
 12#include <linux/kvm_host.h>
 13
 14#include <kvm/arm_psci.h>
 15
 16#include <asm/esr.h>
 17#include <asm/exception.h>
 18#include <asm/kvm_asm.h>
 19#include <asm/kvm_coproc.h>
 20#include <asm/kvm_emulate.h>
 21#include <asm/kvm_mmu.h>
 22#include <asm/debug-monitors.h>
 23#include <asm/traps.h>
 24
 25#define CREATE_TRACE_POINTS
 26#include "trace.h"
 27
 28typedef int (*exit_handle_fn)(struct kvm_vcpu *, struct kvm_run *);
 29
 30static void kvm_handle_guest_serror(struct kvm_vcpu *vcpu, u32 esr)
 31{
 32	if (!arm64_is_ras_serror(esr) || arm64_is_fatal_ras_serror(NULL, esr))
 33		kvm_inject_vabt(vcpu);
 34}
 35
 36static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run *run)
 37{
 38	int ret;
 39
 40	trace_kvm_hvc_arm64(*vcpu_pc(vcpu), vcpu_get_reg(vcpu, 0),
 41			    kvm_vcpu_hvc_get_imm(vcpu));
 42	vcpu->stat.hvc_exit_stat++;
 43
 44	ret = kvm_hvc_call_handler(vcpu);
 45	if (ret < 0) {
 46		vcpu_set_reg(vcpu, 0, ~0UL);
 47		return 1;
 48	}
 49
 50	return ret;
 51}
 52
 53static int handle_smc(struct kvm_vcpu *vcpu, struct kvm_run *run)
 54{
 55	/*
 56	 * "If an SMC instruction executed at Non-secure EL1 is
 57	 * trapped to EL2 because HCR_EL2.TSC is 1, the exception is a
 58	 * Trap exception, not a Secure Monitor Call exception [...]"
 59	 *
 60	 * We need to advance the PC after the trap, as it would
 61	 * otherwise return to the same address...
 62	 */
 63	vcpu_set_reg(vcpu, 0, ~0UL);
 64	kvm_skip_instr(vcpu, kvm_vcpu_trap_il_is32bit(vcpu));
 65	return 1;
 66}
 67
 68/*
 69 * Guest access to FP/ASIMD registers are routed to this handler only
 70 * when the system doesn't support FP/ASIMD.
 71 */
 72static int handle_no_fpsimd(struct kvm_vcpu *vcpu, struct kvm_run *run)
 73{
 74	kvm_inject_undefined(vcpu);
 75	return 1;
 76}
 77
 78/**
 79 * kvm_handle_wfx - handle a wait-for-interrupts or wait-for-event
 80 *		    instruction executed by a guest
 81 *
 82 * @vcpu:	the vcpu pointer
 83 *
 84 * WFE: Yield the CPU and come back to this vcpu when the scheduler
 85 * decides to.
 86 * WFI: Simply call kvm_vcpu_block(), which will halt execution of
 87 * world-switches and schedule other host processes until there is an
 88 * incoming IRQ or FIQ to the VM.
 89 */
 90static int kvm_handle_wfx(struct kvm_vcpu *vcpu, struct kvm_run *run)
 91{
 92	if (kvm_vcpu_get_hsr(vcpu) & ESR_ELx_WFx_ISS_WFE) {
 93		trace_kvm_wfx_arm64(*vcpu_pc(vcpu), true);
 94		vcpu->stat.wfe_exit_stat++;
 95		kvm_vcpu_on_spin(vcpu, vcpu_mode_priv(vcpu));
 96	} else {
 97		trace_kvm_wfx_arm64(*vcpu_pc(vcpu), false);
 98		vcpu->stat.wfi_exit_stat++;
 99		kvm_vcpu_block(vcpu);
100		kvm_clear_request(KVM_REQ_UNHALT, vcpu);
101	}
102
103	kvm_skip_instr(vcpu, kvm_vcpu_trap_il_is32bit(vcpu));
104
105	return 1;
106}
107
108/**
109 * kvm_handle_guest_debug - handle a debug exception instruction
110 *
111 * @vcpu:	the vcpu pointer
112 * @run:	access to the kvm_run structure for results
113 *
114 * We route all debug exceptions through the same handler. If both the
115 * guest and host are using the same debug facilities it will be up to
116 * userspace to re-inject the correct exception for guest delivery.
117 *
118 * @return: 0 (while setting run->exit_reason), -1 for error
119 */
120static int kvm_handle_guest_debug(struct kvm_vcpu *vcpu, struct kvm_run *run)
121{
122	u32 hsr = kvm_vcpu_get_hsr(vcpu);
123	int ret = 0;
124
125	run->exit_reason = KVM_EXIT_DEBUG;
126	run->debug.arch.hsr = hsr;
127
128	switch (ESR_ELx_EC(hsr)) {
129	case ESR_ELx_EC_WATCHPT_LOW:
130		run->debug.arch.far = vcpu->arch.fault.far_el2;
131		/* fall through */
132	case ESR_ELx_EC_SOFTSTP_LOW:
133	case ESR_ELx_EC_BREAKPT_LOW:
134	case ESR_ELx_EC_BKPT32:
135	case ESR_ELx_EC_BRK64:
136		break;
137	default:
138		kvm_err("%s: un-handled case hsr: %#08x\n",
139			__func__, (unsigned int) hsr);
140		ret = -1;
141		break;
142	}
143
144	return ret;
145}
146
147static int kvm_handle_unknown_ec(struct kvm_vcpu *vcpu, struct kvm_run *run)
148{
149	u32 hsr = kvm_vcpu_get_hsr(vcpu);
150
151	kvm_pr_unimpl("Unknown exception class: hsr: %#08x -- %s\n",
152		      hsr, esr_get_class_string(hsr));
153
154	kvm_inject_undefined(vcpu);
155	return 1;
156}
157
158static int handle_sve(struct kvm_vcpu *vcpu, struct kvm_run *run)
159{
160	/* Until SVE is supported for guests: */
161	kvm_inject_undefined(vcpu);
162	return 1;
163}
164
165#define __ptrauth_save_key(regs, key)						\
166({										\
167	regs[key ## KEYLO_EL1] = read_sysreg_s(SYS_ ## key ## KEYLO_EL1);	\
168	regs[key ## KEYHI_EL1] = read_sysreg_s(SYS_ ## key ## KEYHI_EL1);	\
169})
170
171/*
172 * Handle the guest trying to use a ptrauth instruction, or trying to access a
173 * ptrauth register.
174 */
175void kvm_arm_vcpu_ptrauth_trap(struct kvm_vcpu *vcpu)
176{
177	struct kvm_cpu_context *ctxt;
178
179	if (vcpu_has_ptrauth(vcpu)) {
180		vcpu_ptrauth_enable(vcpu);
181		ctxt = vcpu->arch.host_cpu_context;
182		__ptrauth_save_key(ctxt->sys_regs, APIA);
183		__ptrauth_save_key(ctxt->sys_regs, APIB);
184		__ptrauth_save_key(ctxt->sys_regs, APDA);
185		__ptrauth_save_key(ctxt->sys_regs, APDB);
186		__ptrauth_save_key(ctxt->sys_regs, APGA);
187	} else {
188		kvm_inject_undefined(vcpu);
189	}
190}
191
192/*
193 * Guest usage of a ptrauth instruction (which the guest EL1 did not turn into
194 * a NOP).
195 */
196static int kvm_handle_ptrauth(struct kvm_vcpu *vcpu, struct kvm_run *run)
197{
198	kvm_arm_vcpu_ptrauth_trap(vcpu);
199	return 1;
200}
201
202static exit_handle_fn arm_exit_handlers[] = {
203	[0 ... ESR_ELx_EC_MAX]	= kvm_handle_unknown_ec,
204	[ESR_ELx_EC_WFx]	= kvm_handle_wfx,
205	[ESR_ELx_EC_CP15_32]	= kvm_handle_cp15_32,
206	[ESR_ELx_EC_CP15_64]	= kvm_handle_cp15_64,
207	[ESR_ELx_EC_CP14_MR]	= kvm_handle_cp14_32,
208	[ESR_ELx_EC_CP14_LS]	= kvm_handle_cp14_load_store,
209	[ESR_ELx_EC_CP14_64]	= kvm_handle_cp14_64,
210	[ESR_ELx_EC_HVC32]	= handle_hvc,
211	[ESR_ELx_EC_SMC32]	= handle_smc,
212	[ESR_ELx_EC_HVC64]	= handle_hvc,
213	[ESR_ELx_EC_SMC64]	= handle_smc,
214	[ESR_ELx_EC_SYS64]	= kvm_handle_sys_reg,
215	[ESR_ELx_EC_SVE]	= handle_sve,
216	[ESR_ELx_EC_IABT_LOW]	= kvm_handle_guest_abort,
217	[ESR_ELx_EC_DABT_LOW]	= kvm_handle_guest_abort,
218	[ESR_ELx_EC_SOFTSTP_LOW]= kvm_handle_guest_debug,
219	[ESR_ELx_EC_WATCHPT_LOW]= kvm_handle_guest_debug,
220	[ESR_ELx_EC_BREAKPT_LOW]= kvm_handle_guest_debug,
221	[ESR_ELx_EC_BKPT32]	= kvm_handle_guest_debug,
222	[ESR_ELx_EC_BRK64]	= kvm_handle_guest_debug,
223	[ESR_ELx_EC_FP_ASIMD]	= handle_no_fpsimd,
224	[ESR_ELx_EC_PAC]	= kvm_handle_ptrauth,
225};
226
227static exit_handle_fn kvm_get_exit_handler(struct kvm_vcpu *vcpu)
228{
229	u32 hsr = kvm_vcpu_get_hsr(vcpu);
230	u8 hsr_ec = ESR_ELx_EC(hsr);
231
232	return arm_exit_handlers[hsr_ec];
233}
234
235/*
236 * We may be single-stepping an emulated instruction. If the emulation
237 * has been completed in the kernel, we can return to userspace with a
238 * KVM_EXIT_DEBUG, otherwise userspace needs to complete its
239 * emulation first.
240 */
241static int handle_trap_exceptions(struct kvm_vcpu *vcpu, struct kvm_run *run)
242{
243	int handled;
244
245	/*
246	 * See ARM ARM B1.14.1: "Hyp traps on instructions
247	 * that fail their condition code check"
248	 */
249	if (!kvm_condition_valid(vcpu)) {
250		kvm_skip_instr(vcpu, kvm_vcpu_trap_il_is32bit(vcpu));
251		handled = 1;
252	} else {
253		exit_handle_fn exit_handler;
254
255		exit_handler = kvm_get_exit_handler(vcpu);
256		handled = exit_handler(vcpu, run);
257	}
258
 
 
 
 
 
 
 
259	return handled;
260}
261
262/*
263 * Return > 0 to return to guest, < 0 on error, 0 (and set exit_reason) on
264 * proper exit to userspace.
265 */
266int handle_exit(struct kvm_vcpu *vcpu, struct kvm_run *run,
267		       int exception_index)
268{
269	if (ARM_SERROR_PENDING(exception_index)) {
270		u8 hsr_ec = ESR_ELx_EC(kvm_vcpu_get_hsr(vcpu));
271
272		/*
273		 * HVC/SMC already have an adjusted PC, which we need
274		 * to correct in order to return to after having
275		 * injected the SError.
276		 */
277		if (hsr_ec == ESR_ELx_EC_HVC32 || hsr_ec == ESR_ELx_EC_HVC64 ||
278		    hsr_ec == ESR_ELx_EC_SMC32 || hsr_ec == ESR_ELx_EC_SMC64) {
279			u32 adj =  kvm_vcpu_trap_il_is32bit(vcpu) ? 4 : 2;
280			*vcpu_pc(vcpu) -= adj;
281		}
282
283		return 1;
284	}
285
286	exception_index = ARM_EXCEPTION_CODE(exception_index);
287
288	switch (exception_index) {
289	case ARM_EXCEPTION_IRQ:
290		return 1;
291	case ARM_EXCEPTION_EL1_SERROR:
292		return 1;
 
 
 
 
 
293	case ARM_EXCEPTION_TRAP:
294		return handle_trap_exceptions(vcpu, run);
295	case ARM_EXCEPTION_HYP_GONE:
296		/*
297		 * EL2 has been reset to the hyp-stub. This happens when a guest
298		 * is pre-empted by kvm_reboot()'s shutdown call.
299		 */
300		run->exit_reason = KVM_EXIT_FAIL_ENTRY;
301		return 0;
302	case ARM_EXCEPTION_IL:
303		/*
304		 * We attempted an illegal exception return.  Guest state must
305		 * have been corrupted somehow.  Give up.
306		 */
307		run->exit_reason = KVM_EXIT_FAIL_ENTRY;
308		return -EINVAL;
309	default:
310		kvm_pr_unimpl("Unsupported exception type: %d",
311			      exception_index);
312		run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
313		return 0;
314	}
315}
316
317/* For exit types that need handling before we can be preempted */
318void handle_exit_early(struct kvm_vcpu *vcpu, struct kvm_run *run,
319		       int exception_index)
320{
321	if (ARM_SERROR_PENDING(exception_index)) {
322		if (this_cpu_has_cap(ARM64_HAS_RAS_EXTN)) {
323			u64 disr = kvm_vcpu_get_disr(vcpu);
324
325			kvm_handle_guest_serror(vcpu, disr_to_esr(disr));
326		} else {
327			kvm_inject_vabt(vcpu);
328		}
329
330		return;
331	}
332
333	exception_index = ARM_EXCEPTION_CODE(exception_index);
334
335	if (exception_index == ARM_EXCEPTION_EL1_SERROR)
336		kvm_handle_guest_serror(vcpu, kvm_vcpu_get_hsr(vcpu));
337}