When calling FXSAVE, XSAVE, FXRSTOR, ... on amd64 use the "64"-suffixed
variant in order to prefix the operand with REX.W=1.  This causes them
to use the FXSAVE64 variant of x87 area that includes complete FIP/FDP
registers.

The difference between the two variants is that the FXSAVE64 (new)
variant represents FIP/FDP as 64-bit fields (union fp_addr.fa_64),
while the legacy FXSAVE variant uses split fields: 32-bit offset,
16-bit segment and 16-bit reserved field (union fp_addr.fa_32).
The latter implies that the actual addresses are truncated to 32 bits
which is insufficient in modern programs.

This is a potentially breaking change.  However, I don't think it likely
to actually break anything because the data provided by the old variant
were not meaningful (because of the truncated pointer).
---
 sys/arch/x86/include/cpufunc.h | 16 +++++++++++-----
 1 file changed, 11 insertions(+), 5 deletions(-)

diff --git a/sys/arch/x86/include/cpufunc.h b/sys/arch/x86/include/cpufunc.h
index 38534c305544..e0ea1e3210b8 100644
--- a/sys/arch/x86/include/cpufunc.h
+++ b/sys/arch/x86/include/cpufunc.h
@@ -411,13 +411,19 @@ frstor(const void *addr)
        );
 }
 
+#ifdef __x86_64__
+#define XSAVE_SUFFIX "64"
+#else
+#define XSAVE_SUFFIX
+#endif
+
 static inline void
 fxsave(void *addr)
 {
        uint8_t *area = addr;
 
        __asm volatile (
-               "fxsave %[area]"
+               "fxsave" XSAVE_SUFFIX " %[area]"
                : [area] "=m" (*area)
                :
                : "memory"
@@ -430,7 +436,7 @@ fxrstor(const void *addr)
        const uint8_t *area = addr;
 
        __asm volatile (
-               "fxrstor %[area]"
+               "fxrstor" XSAVE_SUFFIX " %[area]"
                :
                : [area] "m" (*area)
                : "memory"
@@ -446,7 +452,7 @@ xsave(void *addr, uint64_t mask)
        low = mask;
        high = mask >> 32;
        __asm volatile (
-               "xsave  %[area]"
+               "xsave" XSAVE_SUFFIX "  %[area]"
                : [area] "=m" (*area)
                : "a" (low), "d" (high)
                : "memory"
@@ -462,7 +468,7 @@ xsaveopt(void *addr, uint64_t mask)
        low = mask;
        high = mask >> 32;
        __asm volatile (
-               "xsaveopt %[area]"
+               "xsaveopt" XSAVE_SUFFIX " %[area]"
                : [area] "=m" (*area)
                : "a" (low), "d" (high)
                : "memory"
@@ -478,7 +484,7 @@ xrstor(const void *addr, uint64_t mask)
        low = mask;
        high = mask >> 32;
        __asm volatile (
-               "xrstor %[area]"
+               "xrstor" XSAVE_SUFFIX " %[area]"
                :
                : [area] "m" (*area), "a" (low), "d" (high)
                : "memory"
-- 
2.28.0

Reply via email to