1/*	$NetBSD: nvmm_x86_svmfunc.S,v 1.3.4.1 2020/08/29 17:00:28 martin Exp $	*/
2
3/*
4 * Copyright (c) 2018 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Maxime Villard.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32#define LOCORE
33#include <machine/asmacros.h>
34#include <machine/segments.h>
35#include "assym.s"
36
37#define ASM_NVMM
38#include <dev/virtual/nvmm/x86/nvmm_x86.h>
39
40	.text
41
42#define HOST_SAVE_GPRS		\
43	pushq	%rbx		;\
44	pushq	%rbp		;\
45	pushq	%r12		;\
46	pushq	%r13		;\
47	pushq	%r14		;\
48	pushq	%r15
49
50#define HOST_RESTORE_GPRS	\
51	popq	%r15		;\
52	popq	%r14		;\
53	popq	%r13		;\
54	popq	%r12		;\
55	popq	%rbp		;\
56	popq	%rbx
57
58#define HOST_SAVE_MSR(msr)	\
59	movq	$msr,%rcx	;\
60	rdmsr			;\
61	pushq	%rdx		;\
62	pushq	%rax
63
64#define HOST_RESTORE_MSR(msr)	\
65	popq	%rax		;\
66	popq	%rdx		;\
67	movq	$msr,%rcx	;\
68	wrmsr
69
70#define HOST_SAVE_TR		\
71	strw	%ax		;\
72	pushq	%rax
73
74#define HOST_RESTORE_TR				\
75	popq	%rax				;\
76	movzwq	%ax,%rdx			;\
77	movq	PCPU(tss_gdt),%rax		;\
78	andq	$~0x0200,4(%rax,%rdx, 1)	;\
79	ltrw	%dx
80
81#define HOST_SAVE_LDT		\
82	sldtw	%ax		;\
83	pushq	%rax
84
85#define HOST_RESTORE_LDT	\
86	popq	%rax		;\
87	lldtw	%ax
88
89/*
90 * All GPRs except RAX and RSP, which are taken care of in VMCB.
91 */
92
93#define GUEST_SAVE_GPRS(reg)				\
94	movq	%rcx,(NVMM_X64_GPR_RCX * 8)(reg)	;\
95	movq	%rdx,(NVMM_X64_GPR_RDX * 8)(reg)	;\
96	movq	%rbx,(NVMM_X64_GPR_RBX * 8)(reg)	;\
97	movq	%rbp,(NVMM_X64_GPR_RBP * 8)(reg)	;\
98	movq	%rsi,(NVMM_X64_GPR_RSI * 8)(reg)	;\
99	movq	%rdi,(NVMM_X64_GPR_RDI * 8)(reg)	;\
100	movq	%r8,(NVMM_X64_GPR_R8 * 8)(reg)		;\
101	movq	%r9,(NVMM_X64_GPR_R9 * 8)(reg)		;\
102	movq	%r10,(NVMM_X64_GPR_R10 * 8)(reg)	;\
103	movq	%r11,(NVMM_X64_GPR_R11 * 8)(reg)	;\
104	movq	%r12,(NVMM_X64_GPR_R12 * 8)(reg)	;\
105	movq	%r13,(NVMM_X64_GPR_R13 * 8)(reg)	;\
106	movq	%r14,(NVMM_X64_GPR_R14 * 8)(reg)	;\
107	movq	%r15,(NVMM_X64_GPR_R15 * 8)(reg)
108
109#define GUEST_RESTORE_GPRS(reg)				\
110	movq	(NVMM_X64_GPR_RCX * 8)(reg),%rcx	;\
111	movq	(NVMM_X64_GPR_RDX * 8)(reg),%rdx	;\
112	movq	(NVMM_X64_GPR_RBX * 8)(reg),%rbx	;\
113	movq	(NVMM_X64_GPR_RBP * 8)(reg),%rbp	;\
114	movq	(NVMM_X64_GPR_RSI * 8)(reg),%rsi	;\
115	movq	(NVMM_X64_GPR_RDI * 8)(reg),%rdi	;\
116	movq	(NVMM_X64_GPR_R8 * 8)(reg),%r8		;\
117	movq	(NVMM_X64_GPR_R9 * 8)(reg),%r9		;\
118	movq	(NVMM_X64_GPR_R10 * 8)(reg),%r10	;\
119	movq	(NVMM_X64_GPR_R11 * 8)(reg),%r11	;\
120	movq	(NVMM_X64_GPR_R12 * 8)(reg),%r12	;\
121	movq	(NVMM_X64_GPR_R13 * 8)(reg),%r13	;\
122	movq	(NVMM_X64_GPR_R14 * 8)(reg),%r14	;\
123	movq	(NVMM_X64_GPR_R15 * 8)(reg),%r15
124
125/*
126 * %rdi = PA of VMCB
127 * %rsi = VA of guest GPR state
128 */
129ENTRY(svm_vmrun)
130	/* Save the Host GPRs. */
131	HOST_SAVE_GPRS
132
133	/* Disable Host interrupts. */
134	clgi
135
136	/* Save the Host TR. */
137	HOST_SAVE_TR
138
139	/* Save the Host GSBASE. */
140	HOST_SAVE_MSR(MSR_GSBASE)
141
142	/* Reset DS and ES. */
143	movq	$GSEL(GUDATA_SEL, SEL_UPL),%rax
144	movw	%ax,%ds
145	movw	%ax,%es
146
147	/* Save the Host LDT. */
148	HOST_SAVE_LDT
149
150	/* Prepare RAX. */
151	pushq	%rsi
152	pushq	%rdi
153
154	/* Restore the Guest GPRs. */
155	movq	%rsi,%rax
156	GUEST_RESTORE_GPRS(%rax)
157
158	/* Set RAX. */
159	popq	%rax
160
161	/* Run the VM. */
162	vmload	%rax
163	vmrun	%rax
164	vmsave	%rax
165
166	/* Get RAX. */
167	popq	%rax
168
169	/* Save the Guest GPRs. */
170	GUEST_SAVE_GPRS(%rax)
171
172	/* Restore the Host LDT. */
173	HOST_RESTORE_LDT
174
175	/* Reset FS and GS. */
176	xorq	%rax,%rax
177	movw	%ax,%fs
178	movw	%ax,%gs
179
180	/* Restore the Host GSBASE. */
181	HOST_RESTORE_MSR(MSR_GSBASE)
182
183	/* Restore the Host TR. */
184	HOST_RESTORE_TR
185
186	/* Enable Host interrupts. */
187	stgi
188
189	/* Restore the Host GPRs. */
190	HOST_RESTORE_GPRS
191
192	xorq	%rax,%rax
193	retq
194END(svm_vmrun)
195