xref: /linux/arch/x86/xen/xen-head.S (revision 59dbb9d81adfe07a6f8483269146b407cf9d44d7)
1/* SPDX-License-Identifier: GPL-2.0 */
2/* Xen-specific pieces of head.S, intended to be included in the right
3	place in head.S */
4
5#ifdef CONFIG_XEN
6
7#include <linux/elfnote.h>
8#include <linux/init.h>
9#include <linux/instrumentation.h>
10
11#include <asm/boot.h>
12#include <asm/asm.h>
13#include <asm/frame.h>
14#include <asm/msr.h>
15#include <asm/page_types.h>
16#include <asm/percpu.h>
17#include <asm/unwind_hints.h>
18
19#include <xen/interface/elfnote.h>
20#include <xen/interface/features.h>
21#include <xen/interface/xen.h>
22#include <xen/interface/xen-mca.h>
23#include <asm/xen/interface.h>
24
25#ifdef CONFIG_XEN_PV
26	__INIT
27SYM_CODE_START(startup_xen)
28	UNWIND_HINT_END_OF_STACK
29	ANNOTATE_NOENDBR
30	cld
31
32	leaq	__top_init_kernel_stack(%rip), %rsp
33
34	/* Set up %gs.
35	 *
36	 * The base of %gs always points to fixed_percpu_data.  If the
37	 * stack protector canary is enabled, it is located at %gs:40.
38	 * Note that, on SMP, the boot cpu uses init data section until
39	 * the per cpu areas are set up.
40	 */
41	movl	$MSR_GS_BASE,%ecx
42	movq	$INIT_PER_CPU_VAR(fixed_percpu_data),%rax
43	cdq
44	wrmsr
45
46	mov	%rsi, %rdi
47	call xen_start_kernel
48SYM_CODE_END(startup_xen)
49	__FINIT
50
51#ifdef CONFIG_XEN_PV_SMP
52.pushsection .text
53SYM_CODE_START(asm_cpu_bringup_and_idle)
54	UNWIND_HINT_END_OF_STACK
55	ENDBR
56
57	call cpu_bringup_and_idle
58SYM_CODE_END(asm_cpu_bringup_and_idle)
59
60SYM_CODE_START(xen_cpu_bringup_again)
61	UNWIND_HINT_FUNC
62	mov	%rdi, %rsp
63	UNWIND_HINT_REGS
64	call	cpu_bringup_and_idle
65SYM_CODE_END(xen_cpu_bringup_again)
66.popsection
67#endif
68#endif
69
70	.pushsection .noinstr.text, "ax"
71/*
72 * Xen hypercall interface to the hypervisor.
73 *
74 * Input:
75 *     %eax: hypercall number
76 *   32-bit:
77 *     %ebx, %ecx, %edx, %esi, %edi: args 1..5 for the hypercall
78 *   64-bit:
79 *     %rdi, %rsi, %rdx, %r10, %r8: args 1..5 for the hypercall
80 * Output: %[er]ax
81 */
82SYM_FUNC_START(xen_hypercall_hvm)
83	ENDBR
84	FRAME_BEGIN
85	/* Save all relevant registers (caller save and arguments). */
86#ifdef CONFIG_X86_32
87	push %eax
88	push %ebx
89	push %ecx
90	push %edx
91	push %esi
92	push %edi
93#else
94	push %rax
95	push %rcx
96	push %rdx
97	push %rdi
98	push %rsi
99	push %r11
100	push %r10
101	push %r9
102	push %r8
103#ifdef CONFIG_FRAME_POINTER
104	pushq $0	/* Dummy push for stack alignment. */
105#endif
106#endif
107	/* Set the vendor specific function. */
108	call __xen_hypercall_setfunc
109	/* Set ZF = 1 if AMD, Restore saved registers. */
110#ifdef CONFIG_X86_32
111	lea xen_hypercall_amd, %ebx
112	cmp %eax, %ebx
113	pop %edi
114	pop %esi
115	pop %edx
116	pop %ecx
117	pop %ebx
118	pop %eax
119#else
120	lea xen_hypercall_amd(%rip), %rbx
121	cmp %rax, %rbx
122#ifdef CONFIG_FRAME_POINTER
123	pop %rax	/* Dummy pop. */
124#endif
125	pop %r8
126	pop %r9
127	pop %r10
128	pop %r11
129	pop %rsi
130	pop %rdi
131	pop %rdx
132	pop %rcx
133	pop %rax
134#endif
135	/* Use correct hypercall function. */
136	jz xen_hypercall_amd
137	jmp xen_hypercall_intel
138SYM_FUNC_END(xen_hypercall_hvm)
139
140SYM_FUNC_START(xen_hypercall_amd)
141	vmmcall
142	RET
143SYM_FUNC_END(xen_hypercall_amd)
144
145SYM_FUNC_START(xen_hypercall_intel)
146	vmcall
147	RET
148SYM_FUNC_END(xen_hypercall_intel)
149	.popsection
150
151	ELFNOTE(Xen, XEN_ELFNOTE_GUEST_OS,       .asciz "linux")
152	ELFNOTE(Xen, XEN_ELFNOTE_GUEST_VERSION,  .asciz "2.6")
153	ELFNOTE(Xen, XEN_ELFNOTE_XEN_VERSION,    .asciz "xen-3.0")
154#ifdef CONFIG_XEN_PV
155	ELFNOTE(Xen, XEN_ELFNOTE_VIRT_BASE,      _ASM_PTR __START_KERNEL_map)
156	/* Map the p2m table to a 512GB-aligned user address. */
157	ELFNOTE(Xen, XEN_ELFNOTE_INIT_P2M,       .quad (PUD_SIZE * PTRS_PER_PUD))
158	ELFNOTE(Xen, XEN_ELFNOTE_ENTRY,          .globl xen_elfnote_entry;
159		xen_elfnote_entry: _ASM_PTR xen_elfnote_entry_value - .)
160	ELFNOTE(Xen, XEN_ELFNOTE_FEATURES,       .ascii "!writable_page_tables")
161	ELFNOTE(Xen, XEN_ELFNOTE_PAE_MODE,       .asciz "yes")
162	ELFNOTE(Xen, XEN_ELFNOTE_L1_MFN_VALID,
163		.quad _PAGE_PRESENT; .quad _PAGE_PRESENT)
164	ELFNOTE(Xen, XEN_ELFNOTE_MOD_START_PFN,  .long 1)
165	ELFNOTE(Xen, XEN_ELFNOTE_PADDR_OFFSET,   _ASM_PTR 0)
166# define FEATURES_PV (1 << XENFEAT_writable_page_tables)
167#else
168# define FEATURES_PV 0
169#endif
170#ifdef CONFIG_XEN_PVH
171# define FEATURES_PVH (1 << XENFEAT_linux_rsdp_unrestricted)
172#else
173# define FEATURES_PVH 0
174#endif
175#ifdef CONFIG_XEN_DOM0
176# define FEATURES_DOM0 (1 << XENFEAT_dom0)
177#else
178# define FEATURES_DOM0 0
179#endif
180	ELFNOTE(Xen, XEN_ELFNOTE_SUPPORTED_FEATURES,
181		.long FEATURES_PV | FEATURES_PVH | FEATURES_DOM0)
182	ELFNOTE(Xen, XEN_ELFNOTE_LOADER,         .asciz "generic")
183	ELFNOTE(Xen, XEN_ELFNOTE_SUSPEND_CANCEL, .long 1)
184
185#endif /*CONFIG_XEN */
186