mirror of
https://github.com/ipxe/ipxe
synced 2025-12-13 07:20:47 +03:00
The existence of MMX and SSE is required by the System V x86_64 ABI and so is assumed by gcc, but these registers are not preserved by our own interrupt handlers and are unlikely to be preserved by other context switch handlers in a boot firmware environment. Explicitly prevent gcc from using MMX or SSE registers to avoid potential problems due to silent register corruption. We must remove the %xmm0-%xmm5 clobbers from the x86_64 version of hv_call() since otherwise gcc will complain about unknown register names. Theoretically, we should probably add code to explicitly preserve the %xmm0-%xmm5 registers across a hypercall, in order to guarantee to external code that these registers remain unchanged. In practice this is difficult since SSE registers are disabled by default: for background information see commits71560d1("[librm] Preserve FPU, MMX and SSE state across calls to virt_call()") anddd9a14d("[librm] Conditionalize the workaround for the Tivoli VMM's SSE garbling"). Signed-off-by: Michael Brown <mcb30@ipxe.org>
52 lines
1.1 KiB
C
52 lines
1.1 KiB
C
#ifndef _BITS_HYPERV_H
|
|
#define _BITS_HYPERV_H
|
|
|
|
/** @file
|
|
*
|
|
* Hyper-V interface
|
|
*
|
|
*/
|
|
|
|
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
|
|
|
#include <stddef.h>
|
|
#include <stdint.h>
|
|
#include <ipxe/io.h>
|
|
|
|
/**
|
|
* Issue hypercall
|
|
*
|
|
* @v hv Hyper-V hypervisor
|
|
* @v code Call code
|
|
* @v in Input parameters
|
|
* @v out Output parameters
|
|
* @ret status Status code
|
|
*/
|
|
static inline __attribute__ (( always_inline )) int
|
|
hv_call ( struct hv_hypervisor *hv, unsigned int code, const void *in,
|
|
void *out ) {
|
|
void *hypercall = hv->hypercall;
|
|
register uint64_t rcx asm ( "rcx" );
|
|
register uint64_t rdx asm ( "rdx" );
|
|
register uint64_t r8 asm ( "r8" );
|
|
uint64_t in_phys;
|
|
uint64_t out_phys;
|
|
uint16_t result;
|
|
|
|
in_phys = ( ( __builtin_constant_p ( in ) && ( in == NULL ) )
|
|
? 0 : virt_to_phys ( in ) );
|
|
out_phys = ( ( __builtin_constant_p ( out ) && ( out == NULL ) )
|
|
? 0 : virt_to_phys ( out ) );
|
|
rcx = code;
|
|
rdx = in_phys;
|
|
r8 = out_phys;
|
|
__asm__ __volatile__ ( "call *%4"
|
|
: "=a" ( result ), "+r" ( rcx ), "+r" ( rdx ),
|
|
"+r" ( r8 )
|
|
: "m" ( hypercall )
|
|
: "r9", "r10", "r11" );
|
|
return result;
|
|
}
|
|
|
|
#endif /* _BITS_HYPERV_H */
|