| 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 | 
|---|
| 27 | SYM_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 | /* | 
|---|
| 35 | * Set up GSBASE. | 
|---|
| 36 | * Note that, on SMP, the boot cpu uses init data section until | 
|---|
| 37 | * the per cpu areas are set up. | 
|---|
| 38 | */ | 
|---|
| 39 | movl	$MSR_GS_BASE,%ecx | 
|---|
| 40 | xorl	%eax, %eax | 
|---|
| 41 | xorl	%edx, %edx | 
|---|
| 42 | wrmsr | 
|---|
| 43 |  | 
|---|
| 44 | mov	%rsi, %rdi | 
|---|
| 45 | call xen_start_kernel | 
|---|
| 46 | SYM_CODE_END(startup_xen) | 
|---|
| 47 | __FINIT | 
|---|
| 48 |  | 
|---|
| 49 | #ifdef CONFIG_XEN_PV_SMP | 
|---|
| 50 | .pushsection .text | 
|---|
| 51 | SYM_CODE_START(asm_cpu_bringup_and_idle) | 
|---|
| 52 | UNWIND_HINT_END_OF_STACK | 
|---|
| 53 | ENDBR | 
|---|
| 54 |  | 
|---|
| 55 | call cpu_bringup_and_idle | 
|---|
| 56 | SYM_CODE_END(asm_cpu_bringup_and_idle) | 
|---|
| 57 |  | 
|---|
| 58 | SYM_CODE_START(xen_cpu_bringup_again) | 
|---|
| 59 | UNWIND_HINT_FUNC | 
|---|
| 60 | mov	%rdi, %rsp | 
|---|
| 61 | UNWIND_HINT_REGS | 
|---|
| 62 | call	cpu_bringup_and_idle | 
|---|
| 63 | SYM_CODE_END(xen_cpu_bringup_again) | 
|---|
| 64 | .popsection | 
|---|
| 65 | #endif | 
|---|
| 66 | #endif | 
|---|
| 67 |  | 
|---|
| 68 | .pushsection .noinstr.text, "ax" | 
|---|
| 69 | /* | 
|---|
| 70 | * Xen hypercall interface to the hypervisor. | 
|---|
| 71 | * | 
|---|
| 72 | * Input: | 
|---|
| 73 | *     %eax: hypercall number | 
|---|
| 74 | *   32-bit: | 
|---|
| 75 | *     %ebx, %ecx, %edx, %esi, %edi: args 1..5 for the hypercall | 
|---|
| 76 | *   64-bit: | 
|---|
| 77 | *     %rdi, %rsi, %rdx, %r10, %r8: args 1..5 for the hypercall | 
|---|
| 78 | * Output: %[er]ax | 
|---|
| 79 | */ | 
|---|
| 80 | SYM_FUNC_START(xen_hypercall_hvm) | 
|---|
| 81 | ENDBR | 
|---|
| 82 | FRAME_BEGIN | 
|---|
| 83 | /* Save all relevant registers (caller save and arguments). */ | 
|---|
| 84 | #ifdef CONFIG_X86_32 | 
|---|
| 85 | push %eax | 
|---|
| 86 | push %ebx | 
|---|
| 87 | push %ecx | 
|---|
| 88 | push %edx | 
|---|
| 89 | push %esi | 
|---|
| 90 | push %edi | 
|---|
| 91 | #else | 
|---|
| 92 | push %rax | 
|---|
| 93 | push %rcx | 
|---|
| 94 | push %rdx | 
|---|
| 95 | push %rdi | 
|---|
| 96 | push %rsi | 
|---|
| 97 | push %r11 | 
|---|
| 98 | push %r10 | 
|---|
| 99 | push %r9 | 
|---|
| 100 | push %r8 | 
|---|
| 101 | #endif | 
|---|
| 102 | /* Set the vendor specific function. */ | 
|---|
| 103 | call __xen_hypercall_setfunc | 
|---|
| 104 | /* Set ZF = 1 if AMD, Restore saved registers. */ | 
|---|
| 105 | #ifdef CONFIG_X86_32 | 
|---|
| 106 | lea xen_hypercall_amd, %ebx | 
|---|
| 107 | cmp %eax, %ebx | 
|---|
| 108 | pop %edi | 
|---|
| 109 | pop %esi | 
|---|
| 110 | pop %edx | 
|---|
| 111 | pop %ecx | 
|---|
| 112 | pop %ebx | 
|---|
| 113 | pop %eax | 
|---|
| 114 | #else | 
|---|
| 115 | lea xen_hypercall_amd(%rip), %rcx | 
|---|
| 116 | cmp %rax, %rcx | 
|---|
| 117 | pop %r8 | 
|---|
| 118 | pop %r9 | 
|---|
| 119 | pop %r10 | 
|---|
| 120 | pop %r11 | 
|---|
| 121 | pop %rsi | 
|---|
| 122 | pop %rdi | 
|---|
| 123 | pop %rdx | 
|---|
| 124 | pop %rcx | 
|---|
| 125 | pop %rax | 
|---|
| 126 | #endif | 
|---|
| 127 | FRAME_END | 
|---|
| 128 | /* Use correct hypercall function. */ | 
|---|
| 129 | jz xen_hypercall_amd | 
|---|
| 130 | jmp xen_hypercall_intel | 
|---|
| 131 | SYM_FUNC_END(xen_hypercall_hvm) | 
|---|
| 132 |  | 
|---|
| 133 | SYM_FUNC_START(xen_hypercall_amd) | 
|---|
| 134 | ANNOTATE_NOENDBR | 
|---|
| 135 | vmmcall | 
|---|
| 136 | RET | 
|---|
| 137 | SYM_FUNC_END(xen_hypercall_amd) | 
|---|
| 138 |  | 
|---|
| 139 | SYM_FUNC_START(xen_hypercall_intel) | 
|---|
| 140 | ANNOTATE_NOENDBR | 
|---|
| 141 | vmcall | 
|---|
| 142 | RET | 
|---|
| 143 | SYM_FUNC_END(xen_hypercall_intel) | 
|---|
| 144 | .popsection | 
|---|
| 145 |  | 
|---|
| 146 | ELFNOTE(Xen, XEN_ELFNOTE_GUEST_OS,       .asciz "linux") | 
|---|
| 147 | ELFNOTE(Xen, XEN_ELFNOTE_GUEST_VERSION,  .asciz "2.6") | 
|---|
| 148 | ELFNOTE(Xen, XEN_ELFNOTE_XEN_VERSION,    .asciz "xen-3.0") | 
|---|
| 149 | #ifdef CONFIG_XEN_PV | 
|---|
| 150 | ELFNOTE(Xen, XEN_ELFNOTE_VIRT_BASE,      _ASM_PTR __START_KERNEL_map) | 
|---|
| 151 | /* Map the p2m table to a 512GB-aligned user address. */ | 
|---|
| 152 | ELFNOTE(Xen, XEN_ELFNOTE_INIT_P2M,       .quad (PUD_SIZE * PTRS_PER_PUD)) | 
|---|
| 153 | ELFNOTE(Xen, XEN_ELFNOTE_ENTRY,          .globl xen_elfnote_entry; | 
|---|
| 154 | xen_elfnote_entry: _ASM_PTR xen_elfnote_entry_value - .) | 
|---|
| 155 | ELFNOTE(Xen, XEN_ELFNOTE_FEATURES,       .ascii "!writable_page_tables") | 
|---|
| 156 | ELFNOTE(Xen, XEN_ELFNOTE_PAE_MODE,       .asciz "yes") | 
|---|
| 157 | ELFNOTE(Xen, XEN_ELFNOTE_L1_MFN_VALID, | 
|---|
| 158 | .quad _PAGE_PRESENT; .quad _PAGE_PRESENT) | 
|---|
| 159 | ELFNOTE(Xen, XEN_ELFNOTE_MOD_START_PFN,  .long 1) | 
|---|
| 160 | ELFNOTE(Xen, XEN_ELFNOTE_PADDR_OFFSET,   _ASM_PTR 0) | 
|---|
| 161 | # define FEATURES_PV (1 << XENFEAT_writable_page_tables) | 
|---|
| 162 | #else | 
|---|
| 163 | # define FEATURES_PV 0 | 
|---|
| 164 | #endif | 
|---|
| 165 | #ifdef CONFIG_XEN_PVH | 
|---|
| 166 | # define FEATURES_PVH (1 << XENFEAT_linux_rsdp_unrestricted) | 
|---|
| 167 | #else | 
|---|
| 168 | # define FEATURES_PVH 0 | 
|---|
| 169 | #endif | 
|---|
| 170 | #ifdef CONFIG_XEN_DOM0 | 
|---|
| 171 | # define FEATURES_DOM0 (1 << XENFEAT_dom0) | 
|---|
| 172 | #else | 
|---|
| 173 | # define FEATURES_DOM0 0 | 
|---|
| 174 | #endif | 
|---|
| 175 | ELFNOTE(Xen, XEN_ELFNOTE_SUPPORTED_FEATURES, | 
|---|
| 176 | .long FEATURES_PV | FEATURES_PVH | FEATURES_DOM0) | 
|---|
| 177 | ELFNOTE(Xen, XEN_ELFNOTE_LOADER,         .asciz "generic") | 
|---|
| 178 | ELFNOTE(Xen, XEN_ELFNOTE_SUSPEND_CANCEL, .long 1) | 
|---|
| 179 |  | 
|---|
| 180 | #endif /*CONFIG_XEN */ | 
|---|
| 181 |  | 
|---|