There are several issues with 64bit builds. Correct the types/constraints to
prohibit encoding 32bit registers, and immediates which can't be represented
as a 32bit signed extended number.
Introduce asm_checks() in selftest as a build-time check for constraint corner
cases, to be extended as needed.
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
return ss;
}
-static inline void write_cs(unsigned int cs)
+static inline void write_cs(unsigned long cs)
{
asm volatile ("push %0;"
"push $1f;"
"rex64 "
#endif
"lret; 1:"
- :: "qI" (cs));
+ :: "rme" (cs));
}
static inline void write_ds(unsigned int ds)
asm volatile ("mov %0, %%ss" :: "rm" (ss));
}
-static inline unsigned int read_flags(void)
+static inline unsigned long read_flags(void)
{
- unsigned int flags;
+ unsigned long flags;
asm volatile ("pushf; pop %0" : "=rm" (flags));
return flags;
}
-static inline void write_flags(unsigned int flags)
+static inline void write_flags(unsigned long flags)
{
- asm volatile ("push %0; popf" :: "irm" (flags));
+ asm volatile ("push %0; popf" :: "rme" (flags));
}
static inline unsigned long read_cr0(void)
xtf_success(NULL);
}
+/*
+ * Inline assembly checks.
+ *
+ * Needs to be written out into an object file to cause build failures.
+ * Nothing executes the resulting code.
+ *
+ * - push/pop %reg need to use unsigned long types to avoid trying to allocate
+ * 32bit registers, which aren't encodable in 64bit.
+ * - push $imm can't encode 64bit integers (only 32bit sign extended)
+ */
+static void __used asm_checks(void)
+{
+ read_flags();
+
+#ifdef __x86_64__
+ unsigned long tmp = 0xdead0000c0deULL;
+
+ write_flags(tmp);
+ write_cs(tmp);
+#endif
+}
+
/*
* Local variables:
* mode: C