1/*	$NetBSD: nvmm_x86_svmfunc.S,v 1.6 2020/09/05 07:22:26 maxv Exp $	*/
2
3/*
4 * Copyright (c) 2018-2020 Maxime Villard, m00nbsd.net
5 * All rights reserved.
6 *
7 * This code is part of the NVMM hypervisor.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in the
16 *    documentation and/or other materials provided with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
23 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
25 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 */
30
31#define LOCORE
32#include <machine/asmacros.h>
33#include <machine/segments.h>
34#include "assym.s"
35
36#define ASM_NVMM
37#include <dev/virtual/nvmm/x86/nvmm_x86.h>
38
39	.text
40
41#define HOST_SAVE_GPRS		\
42	pushq	%rbx		;\
43	pushq	%rbp		;\
44	pushq	%r12		;\
45	pushq	%r13		;\
46	pushq	%r14		;\
47	pushq	%r15
48
49#define HOST_RESTORE_GPRS	\
50	popq	%r15		;\
51	popq	%r14		;\
52	popq	%r13		;\
53	popq	%r12		;\
54	popq	%rbp		;\
55	popq	%rbx
56
57#define HOST_SAVE_MSR(msr)	\
58	movq	$msr,%rcx	;\
59	rdmsr			;\
60	pushq	%rdx		;\
61	pushq	%rax
62
63#define HOST_RESTORE_MSR(msr)	\
64	popq	%rax		;\
65	popq	%rdx		;\
66	movq	$msr,%rcx	;\
67	wrmsr
68
69#define HOST_SAVE_TR		\
70	strw	%ax		;\
71	pushq	%rax
72
73/* In DragonFly, PCPU(tss_gdt) points directly to the gdt[] entry for the
74 * current CPU's TSS descriptor; while NetBSD's CPUVAR(GDT) points to the
75 * gdtstore[] table. */
76#define HOST_RESTORE_TR				\
77	popq	%rax				;\
78	movzwq	%ax,%rdx			;\
79	movq	PCPU(tss_gdt),%rax		;\
80	/* Clear the busy bit for reloading. */	\
81	andq	$~0x0200,4(%rax)		;\
82	ltrw	%dx
83
84#define HOST_SAVE_LDT		\
85	sldtw	%ax		;\
86	pushq	%rax
87
88#define HOST_RESTORE_LDT	\
89	popq	%rax		;\
90	lldtw	%ax
91
92/*
93 * All GPRs except RAX and RSP, which are taken care of in VMCB.
94 */
95
96#define GUEST_SAVE_GPRS(reg)				\
97	movq	%rcx,(NVMM_X64_GPR_RCX * 8)(reg)	;\
98	movq	%rdx,(NVMM_X64_GPR_RDX * 8)(reg)	;\
99	movq	%rbx,(NVMM_X64_GPR_RBX * 8)(reg)	;\
100	movq	%rbp,(NVMM_X64_GPR_RBP * 8)(reg)	;\
101	movq	%rsi,(NVMM_X64_GPR_RSI * 8)(reg)	;\
102	movq	%rdi,(NVMM_X64_GPR_RDI * 8)(reg)	;\
103	movq	%r8,(NVMM_X64_GPR_R8 * 8)(reg)		;\
104	movq	%r9,(NVMM_X64_GPR_R9 * 8)(reg)		;\
105	movq	%r10,(NVMM_X64_GPR_R10 * 8)(reg)	;\
106	movq	%r11,(NVMM_X64_GPR_R11 * 8)(reg)	;\
107	movq	%r12,(NVMM_X64_GPR_R12 * 8)(reg)	;\
108	movq	%r13,(NVMM_X64_GPR_R13 * 8)(reg)	;\
109	movq	%r14,(NVMM_X64_GPR_R14 * 8)(reg)	;\
110	movq	%r15,(NVMM_X64_GPR_R15 * 8)(reg)
111
112#define GUEST_RESTORE_GPRS(reg)				\
113	movq	(NVMM_X64_GPR_RCX * 8)(reg),%rcx	;\
114	movq	(NVMM_X64_GPR_RDX * 8)(reg),%rdx	;\
115	movq	(NVMM_X64_GPR_RBX * 8)(reg),%rbx	;\
116	movq	(NVMM_X64_GPR_RBP * 8)(reg),%rbp	;\
117	movq	(NVMM_X64_GPR_RSI * 8)(reg),%rsi	;\
118	movq	(NVMM_X64_GPR_RDI * 8)(reg),%rdi	;\
119	movq	(NVMM_X64_GPR_R8 * 8)(reg),%r8		;\
120	movq	(NVMM_X64_GPR_R9 * 8)(reg),%r9		;\
121	movq	(NVMM_X64_GPR_R10 * 8)(reg),%r10	;\
122	movq	(NVMM_X64_GPR_R11 * 8)(reg),%r11	;\
123	movq	(NVMM_X64_GPR_R12 * 8)(reg),%r12	;\
124	movq	(NVMM_X64_GPR_R13 * 8)(reg),%r13	;\
125	movq	(NVMM_X64_GPR_R14 * 8)(reg),%r14	;\
126	movq	(NVMM_X64_GPR_R15 * 8)(reg),%r15
127
128/*
129 * %rdi = PA of VMCB
130 * %rsi = VA of guest GPR state
131 */
132ENTRY(svm_vmrun)
133	/* Save the Host GPRs. */
134	HOST_SAVE_GPRS
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	/* Restore the Host GPRs. */
187	HOST_RESTORE_GPRS
188
189	retq
190END(svm_vmrun)
191