![Juergen Gross](/assets/img/avatar_default.png)
commit b4845bb6383821a9516ce30af3a27dc873e37fd4 upstream. Add generic hypercall functions usable for all normal (i.e. not iret) hypercalls. Depending on the guest type and the processor vendor different functions need to be used due to the to be used instruction for entering the hypervisor: - PV guests need to use syscall - HVM/PVH guests on Intel need to use vmcall - HVM/PVH guests on AMD and Hygon need to use vmmcall As PVH guests need to issue hypercalls very early during boot, there is a 4th hypercall function needed for HVM/PVH which can be used on Intel and AMD processors. It will check the vendor type and then set the Intel or AMD specific function to use via static_call(). This is part of XSA-466 / CVE-2024-53241. Reported-by: Andrew Cooper <andrew.cooper3@citrix.com> Signed-off-by: Juergen Gross <jgross@suse.com> Co-developed-by: Peter Zijlstra <peterz@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
196 lines
4.6 KiB
ArmAsm
Executable file
196 lines
4.6 KiB
ArmAsm
Executable file
/* SPDX-License-Identifier: GPL-2.0 */
|
|
/* Xen-specific pieces of head.S, intended to be included in the right
|
|
place in head.S */
|
|
|
|
#ifdef CONFIG_XEN
|
|
|
|
#include <linux/elfnote.h>
|
|
#include <linux/init.h>
|
|
#include <linux/instrumentation.h>
|
|
|
|
#include <asm/boot.h>
|
|
#include <asm/asm.h>
|
|
#include <asm/frame.h>
|
|
#include <asm/msr.h>
|
|
#include <asm/page_types.h>
|
|
#include <asm/percpu.h>
|
|
#include <asm/unwind_hints.h>
|
|
|
|
#include <xen/interface/elfnote.h>
|
|
#include <xen/interface/features.h>
|
|
#include <xen/interface/xen.h>
|
|
#include <xen/interface/xen-mca.h>
|
|
#include <asm/xen/interface.h>
|
|
|
|
#ifdef CONFIG_XEN_PV
|
|
__INIT
|
|
SYM_CODE_START(startup_xen)
|
|
UNWIND_HINT_EMPTY
|
|
cld
|
|
|
|
/* Clear .bss */
|
|
xor %eax,%eax
|
|
mov $__bss_start, %_ASM_DI
|
|
mov $__bss_stop, %_ASM_CX
|
|
sub %_ASM_DI, %_ASM_CX
|
|
shr $__ASM_SEL(2, 3), %_ASM_CX
|
|
rep __ASM_SIZE(stos)
|
|
|
|
mov %_ASM_SI, xen_start_info
|
|
mov initial_stack(%rip), %rsp
|
|
|
|
/* Set up %gs.
|
|
*
|
|
* The base of %gs always points to fixed_percpu_data. If the
|
|
* stack protector canary is enabled, it is located at %gs:40.
|
|
* Note that, on SMP, the boot cpu uses init data section until
|
|
* the per cpu areas are set up.
|
|
*/
|
|
movl $MSR_GS_BASE,%ecx
|
|
movq $INIT_PER_CPU_VAR(fixed_percpu_data),%rax
|
|
cdq
|
|
wrmsr
|
|
|
|
call xen_start_kernel
|
|
SYM_CODE_END(startup_xen)
|
|
__FINIT
|
|
|
|
#ifdef CONFIG_XEN_PV_SMP
|
|
.pushsection .text
|
|
SYM_CODE_START(asm_cpu_bringup_and_idle)
|
|
UNWIND_HINT_EMPTY
|
|
|
|
call cpu_bringup_and_idle
|
|
SYM_CODE_END(asm_cpu_bringup_and_idle)
|
|
.popsection
|
|
#endif
|
|
#endif
|
|
|
|
.pushsection .text
|
|
/*
|
|
* Xen hypercall interface to the hypervisor.
|
|
*
|
|
* Input:
|
|
* %eax: hypercall number
|
|
* 32-bit:
|
|
* %ebx, %ecx, %edx, %esi, %edi: args 1..5 for the hypercall
|
|
* 64-bit:
|
|
* %rdi, %rsi, %rdx, %r10, %r8: args 1..5 for the hypercall
|
|
* Output: %[er]ax
|
|
*/
|
|
SYM_FUNC_START(xen_hypercall_hvm)
|
|
FRAME_BEGIN
|
|
/* Save all relevant registers (caller save and arguments). */
|
|
#ifdef CONFIG_X86_32
|
|
push %eax
|
|
push %ebx
|
|
push %ecx
|
|
push %edx
|
|
push %esi
|
|
push %edi
|
|
#else
|
|
push %rax
|
|
push %rcx
|
|
push %rdx
|
|
push %rdi
|
|
push %rsi
|
|
push %r11
|
|
push %r10
|
|
push %r9
|
|
push %r8
|
|
#ifdef CONFIG_FRAME_POINTER
|
|
pushq $0 /* Dummy push for stack alignment. */
|
|
#endif
|
|
#endif
|
|
/* Set the vendor specific function. */
|
|
call __xen_hypercall_setfunc
|
|
/* Set ZF = 1 if AMD, Restore saved registers. */
|
|
#ifdef CONFIG_X86_32
|
|
lea xen_hypercall_amd, %ebx
|
|
cmp %eax, %ebx
|
|
pop %edi
|
|
pop %esi
|
|
pop %edx
|
|
pop %ecx
|
|
pop %ebx
|
|
pop %eax
|
|
#else
|
|
lea xen_hypercall_amd(%rip), %rbx
|
|
cmp %rax, %rbx
|
|
#ifdef CONFIG_FRAME_POINTER
|
|
pop %rax /* Dummy pop. */
|
|
#endif
|
|
pop %r8
|
|
pop %r9
|
|
pop %r10
|
|
pop %r11
|
|
pop %rsi
|
|
pop %rdi
|
|
pop %rdx
|
|
pop %rcx
|
|
pop %rax
|
|
#endif
|
|
/* Use correct hypercall function. */
|
|
jz xen_hypercall_amd
|
|
jmp xen_hypercall_intel
|
|
SYM_FUNC_END(xen_hypercall_hvm)
|
|
|
|
SYM_FUNC_START(xen_hypercall_amd)
|
|
vmmcall
|
|
RET
|
|
SYM_FUNC_END(xen_hypercall_amd)
|
|
|
|
SYM_FUNC_START(xen_hypercall_intel)
|
|
vmcall
|
|
RET
|
|
SYM_FUNC_END(xen_hypercall_intel)
|
|
.popsection
|
|
|
|
.pushsection .text
|
|
.balign PAGE_SIZE
|
|
SYM_CODE_START(hypercall_page)
|
|
.rept (PAGE_SIZE / 32)
|
|
UNWIND_HINT_FUNC
|
|
ANNOTATE_UNRET_SAFE
|
|
ret
|
|
.skip 31, 0xcc
|
|
.endr
|
|
|
|
#define HYPERCALL(n) \
|
|
.equ xen_hypercall_##n, hypercall_page + __HYPERVISOR_##n * 32; \
|
|
.type xen_hypercall_##n, @function; .size xen_hypercall_##n, 32
|
|
#include <asm/xen-hypercalls.h>
|
|
#undef HYPERCALL
|
|
SYM_CODE_END(hypercall_page)
|
|
.popsection
|
|
|
|
ELFNOTE(Xen, XEN_ELFNOTE_GUEST_OS, .asciz "linux")
|
|
ELFNOTE(Xen, XEN_ELFNOTE_GUEST_VERSION, .asciz "2.6")
|
|
ELFNOTE(Xen, XEN_ELFNOTE_XEN_VERSION, .asciz "xen-3.0")
|
|
#ifdef CONFIG_X86_32
|
|
ELFNOTE(Xen, XEN_ELFNOTE_VIRT_BASE, _ASM_PTR __PAGE_OFFSET)
|
|
#else
|
|
ELFNOTE(Xen, XEN_ELFNOTE_VIRT_BASE, _ASM_PTR __START_KERNEL_map)
|
|
/* Map the p2m table to a 512GB-aligned user address. */
|
|
ELFNOTE(Xen, XEN_ELFNOTE_INIT_P2M, .quad (PUD_SIZE * PTRS_PER_PUD))
|
|
#endif
|
|
#ifdef CONFIG_XEN_PV
|
|
ELFNOTE(Xen, XEN_ELFNOTE_ENTRY, _ASM_PTR startup_xen)
|
|
#endif
|
|
ELFNOTE(Xen, XEN_ELFNOTE_HYPERCALL_PAGE, _ASM_PTR hypercall_page)
|
|
ELFNOTE(Xen, XEN_ELFNOTE_FEATURES,
|
|
.ascii "!writable_page_tables|pae_pgdir_above_4gb")
|
|
ELFNOTE(Xen, XEN_ELFNOTE_SUPPORTED_FEATURES,
|
|
.long (1 << XENFEAT_writable_page_tables) | \
|
|
(1 << XENFEAT_dom0) | \
|
|
(1 << XENFEAT_linux_rsdp_unrestricted))
|
|
ELFNOTE(Xen, XEN_ELFNOTE_PAE_MODE, .asciz "yes")
|
|
ELFNOTE(Xen, XEN_ELFNOTE_LOADER, .asciz "generic")
|
|
ELFNOTE(Xen, XEN_ELFNOTE_L1_MFN_VALID,
|
|
.quad _PAGE_PRESENT; .quad _PAGE_PRESENT)
|
|
ELFNOTE(Xen, XEN_ELFNOTE_SUSPEND_CANCEL, .long 1)
|
|
ELFNOTE(Xen, XEN_ELFNOTE_MOD_START_PFN, .long 1)
|
|
ELFNOTE(Xen, XEN_ELFNOTE_HV_START_LOW, _ASM_PTR __HYPERVISOR_VIRT_START)
|
|
ELFNOTE(Xen, XEN_ELFNOTE_PADDR_OFFSET, _ASM_PTR 0)
|
|
|
|
#endif /*CONFIG_XEN */
|