xref: /linux/arch/x86/hyperv/mshv_vtl_asm.S (revision d30c1683aaecb93d2ab95685dc4300a33d3cea7a)
1/* SPDX-License-Identifier: GPL-2.0
2 *
3 * Assembly level code for mshv_vtl VTL transition
4 *
5 * Copyright (c) 2025, Microsoft Corporation.
6 *
7 * Author:
8 *   Naman Jain <namjain@microsoft.com>
9 */
10
11#include <linux/linkage.h>
12#include <linux/static_call_types.h>
13#include <asm/asm.h>
14#include <asm/asm-offsets.h>
15#include <asm/frame.h>
16#include "mshv-asm-offsets.h"
17
18	.text
19	.section .noinstr.text, "ax"
20/*
21 * void __mshv_vtl_return_call(struct mshv_vtl_cpu_context *vtl0)
22 *
23 * This function is used to context switch between different Virtual Trust Levels.
24 * It is marked as 'noinstr' to prevent against instrumentation and debugging facilities.
25 * NMIs aren't a problem because the NMI handler saves/restores CR2 specifically to guard
26 * against #PFs in NMI context clobbering the guest state.
27 */
28SYM_FUNC_START(__mshv_vtl_return_call)
29	/* Push callee save registers */
30	pushq %rbp
31	mov %rsp, %rbp
32	pushq %r12
33	pushq %r13
34	pushq %r14
35	pushq %r15
36	pushq %rbx
37
38	/* register switch to VTL0 clobbers all registers except rax/rcx */
39	mov %_ASM_ARG1, %rax
40
41	/* grab rbx/rbp/rsi/rdi/r8-r15 */
42	mov MSHV_VTL_CPU_CONTEXT_rbx(%rax), %rbx
43	mov MSHV_VTL_CPU_CONTEXT_rbp(%rax), %rbp
44	mov MSHV_VTL_CPU_CONTEXT_rsi(%rax), %rsi
45	mov MSHV_VTL_CPU_CONTEXT_rdi(%rax), %rdi
46	mov MSHV_VTL_CPU_CONTEXT_r8(%rax), %r8
47	mov MSHV_VTL_CPU_CONTEXT_r9(%rax), %r9
48	mov MSHV_VTL_CPU_CONTEXT_r10(%rax), %r10
49	mov MSHV_VTL_CPU_CONTEXT_r11(%rax), %r11
50	mov MSHV_VTL_CPU_CONTEXT_r12(%rax), %r12
51	mov MSHV_VTL_CPU_CONTEXT_r13(%rax), %r13
52	mov MSHV_VTL_CPU_CONTEXT_r14(%rax), %r14
53	mov MSHV_VTL_CPU_CONTEXT_r15(%rax), %r15
54
55	mov MSHV_VTL_CPU_CONTEXT_cr2(%rax), %rdx
56	mov %rdx, %cr2
57	mov MSHV_VTL_CPU_CONTEXT_rdx(%rax), %rdx
58
59	/* stash host registers on stack */
60	pushq %rax
61	pushq %rcx
62
63	xor %ecx, %ecx
64
65	/* make a hypercall to switch VTL */
66	call STATIC_CALL_TRAMP_STR(__mshv_vtl_return_hypercall)
67
68	/* stash guest registers on stack, restore saved host copies */
69	pushq %rax
70	pushq %rcx
71	mov 16(%rsp), %rcx
72	mov 24(%rsp), %rax
73
74	mov %rdx, MSHV_VTL_CPU_CONTEXT_rdx(%rax)
75	mov %cr2, %rdx
76	mov %rdx, MSHV_VTL_CPU_CONTEXT_cr2(%rax)
77	pop MSHV_VTL_CPU_CONTEXT_rcx(%rax)
78	pop MSHV_VTL_CPU_CONTEXT_rax(%rax)
79	add $16, %rsp
80
81	/* save rbx/rbp/rsi/rdi/r8-r15 */
82	mov %rbx, MSHV_VTL_CPU_CONTEXT_rbx(%rax)
83	mov %rbp, MSHV_VTL_CPU_CONTEXT_rbp(%rax)
84	mov %rsi, MSHV_VTL_CPU_CONTEXT_rsi(%rax)
85	mov %rdi, MSHV_VTL_CPU_CONTEXT_rdi(%rax)
86	mov %r8,  MSHV_VTL_CPU_CONTEXT_r8(%rax)
87	mov %r9,  MSHV_VTL_CPU_CONTEXT_r9(%rax)
88	mov %r10, MSHV_VTL_CPU_CONTEXT_r10(%rax)
89	mov %r11, MSHV_VTL_CPU_CONTEXT_r11(%rax)
90	mov %r12, MSHV_VTL_CPU_CONTEXT_r12(%rax)
91	mov %r13, MSHV_VTL_CPU_CONTEXT_r13(%rax)
92	mov %r14, MSHV_VTL_CPU_CONTEXT_r14(%rax)
93	mov %r15, MSHV_VTL_CPU_CONTEXT_r15(%rax)
94
95	/* pop callee-save registers r12-r15, rbx */
96	pop %rbx
97	pop %r15
98	pop %r14
99	pop %r13
100	pop %r12
101
102	pop %rbp
103	RET
104SYM_FUNC_END(__mshv_vtl_return_call)
105/*
106 * Make sure that static_call_key symbol: __SCK____mshv_vtl_return_hypercall is accessible here.
107 * Below code is inspired from __ADDRESSABLE(sym) macro. Symbol name is kept simple, to avoid
108 * naming it something like "__UNIQUE_ID_addressable___SCK____mshv_vtl_return_hypercall_662.0"
109 * which would otherwise have been generated by the macro.
110 */
111	.section	.discard.addressable,"aw"
112	.align 8
113	.type	mshv_vtl_return_sym, @object
114	.size	mshv_vtl_return_sym, 8
115mshv_vtl_return_sym:
116	.quad	__SCK____mshv_vtl_return_hypercall
117