• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/* SPDX-License-Identifier: GPL-2.0-only */
2/*
3 * Copyright (C) 2016 - ARM Ltd
4 * Author: Marc Zyngier <marc.zyngier@arm.com>
5*/
6
7#include <linux/linkage.h>
8#include <asm/asm-offsets.h>
9#include <asm/kvm_arm.h>
10#include <asm/kvm_asm.h>
11
12	.arch_extension     virt
13
14	.text
15	.pushsection	.hyp.text, "ax"
16
17#define USR_REGS_OFFSET		(CPU_CTXT_GP_REGS + GP_REGS_USR)
18
19/* int __guest_enter(struct kvm_vcpu *vcpu, struct kvm_cpu_context *host) */
20ENTRY(__guest_enter)
21	@ Save host registers
22	add	r1, r1, #(USR_REGS_OFFSET + S_R4)
23	stm	r1!, {r4-r12}
24	str	lr, [r1, #4]	@ Skip SP_usr (already saved)
25
26	@ Restore guest registers
27	add	r0, r0,  #(VCPU_GUEST_CTXT + USR_REGS_OFFSET + S_R0)
28	ldr	lr, [r0, #S_LR]
29	ldm	r0, {r0-r12}
30
31	clrex
32	eret
33ENDPROC(__guest_enter)
34
35ENTRY(__guest_exit)
36	/*
37	 * return convention:
38	 * guest r0, r1, r2 saved on the stack
39	 * r0: vcpu pointer
40	 * r1: exception code
41	 */
42
43	add	r2, r0, #(VCPU_GUEST_CTXT + USR_REGS_OFFSET + S_R3)
44	stm	r2!, {r3-r12}
45	str	lr, [r2, #4]
46	add	r2, r0, #(VCPU_GUEST_CTXT + USR_REGS_OFFSET + S_R0)
47	pop	{r3, r4, r5}		@ r0, r1, r2
48	stm	r2, {r3-r5}
49
50	ldr	r0, [r0, #VCPU_HOST_CTXT]
51	add	r0, r0, #(USR_REGS_OFFSET + S_R4)
52	ldm	r0!, {r4-r12}
53	ldr	lr, [r0, #4]
54
55	mov	r0, r1
56	mrs	r1, SPSR
57	mrs	r2, ELR_hyp
58	mrc	p15, 4, r3, c5, c2, 0	@ HSR
59
60	/*
61	 * Force loads and stores to complete before unmasking aborts
62	 * and forcing the delivery of the exception. This gives us a
63	 * single instruction window, which the handler will try to
64	 * match.
65	 */
66	dsb	sy
67	cpsie	a
68
69	.global	abort_guest_exit_start
70abort_guest_exit_start:
71
72	isb
73
74	.global	abort_guest_exit_end
75abort_guest_exit_end:
76
77	/*
78	 * If we took an abort, r0[31] will be set, and cmp will set
79	 * the N bit in PSTATE.
80	 */
81	cmp	r0, #0
82	msrmi	SPSR_cxsf, r1
83	msrmi	ELR_hyp, r2
84	mcrmi	p15, 4, r3, c5, c2, 0	@ HSR
85
86	bx	lr
87ENDPROC(__guest_exit)
88
89/*
90 * If VFPv3 support is not available, then we will not switch the VFP
91 * registers; however cp10 and cp11 accesses will still trap and fallback
92 * to the regular coprocessor emulation code, which currently will
93 * inject an undefined exception to the guest.
94 */
95#ifdef CONFIG_VFPv3
96ENTRY(__vfp_guest_restore)
97	push	{r3, r4, lr}
98
99	@ NEON/VFP used.  Turn on VFP access.
100	mrc	p15, 4, r1, c1, c1, 2		@ HCPTR
101	bic	r1, r1, #(HCPTR_TCP(10) | HCPTR_TCP(11))
102	mcr	p15, 4, r1, c1, c1, 2		@ HCPTR
103	isb
104
105	@ Switch VFP/NEON hardware state to the guest's
106	mov	r4, r0
107	ldr	r0, [r0, #VCPU_HOST_CTXT]
108	add	r0, r0, #CPU_CTXT_VFP
109	bl	__vfp_save_state
110	add	r0, r4, #(VCPU_GUEST_CTXT + CPU_CTXT_VFP)
111	bl	__vfp_restore_state
112
113	pop	{r3, r4, lr}
114	pop	{r0, r1, r2}
115	clrex
116	eret
117ENDPROC(__vfp_guest_restore)
118#endif
119
120	.popsection
121
122