diff mbox series

[for-4.0,v2,36/37] tcg/i386: Require segment syscalls to succeed

Message ID 20181123144558.5048-37-richard.henderson@linaro.org
State New
Headers show
Series tcg: Assorted cleanups | expand

Commit Message

Richard Henderson Nov. 23, 2018, 2:45 p.m. UTC
There ought be no reason they should ever fail.  If we don't know
how to set a segment base register for user-only (NetBSD, OpenBSD?),
then error out if we cannot proceed.

This is one more step toward the removal of all scratch registers
during user-only guest memory operations.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

---
 tcg/i386/tcg-target.inc.c | 54 +++++++++++++++++----------------------
 1 file changed, 23 insertions(+), 31 deletions(-)

-- 
2.17.2
diff mbox series

Patch

diff --git a/tcg/i386/tcg-target.inc.c b/tcg/i386/tcg-target.inc.c
index 55c5a8516c..19a0fa8a03 100644
--- a/tcg/i386/tcg-target.inc.c
+++ b/tcg/i386/tcg-target.inc.c
@@ -1814,9 +1814,12 @@  int arch_prctl(int code, unsigned long addr);
 static int guest_base_flags;
 static inline void setup_guest_base_seg(void)
 {
-    if (arch_prctl(ARCH_SET_GS, guest_base) == 0) {
-        guest_base_flags = P_GS;
+    /* There is no reason this syscall should fail.  */
+    if (arch_prctl(ARCH_SET_GS, guest_base) < 0) {
+        perror("arch_prctl(ARCH_SET_GS)");
+        exit(1);
     }
+    guest_base_flags = P_GS;
 }
 #elif defined (__FreeBSD__) || defined (__FreeBSD_kernel__)
 # include <machine/sysarch.h>
@@ -1824,13 +1827,28 @@  static inline void setup_guest_base_seg(void)
 static int guest_base_flags;
 static inline void setup_guest_base_seg(void)
 {
-    if (sysarch(AMD64_SET_GSBASE, &guest_base) == 0) {
-        guest_base_flags = P_GS;
+    /* There is no reason this syscall should fail.  */
+    if (sysarch(AMD64_SET_GSBASE, &guest_base) < 0) {
+        perror("sysarch(AMD64_SET_GSBASE)");
+        exit(1);
     }
+    guest_base_flags = P_GS;
 }
 #else
 # define guest_base_flags 0
-static inline void setup_guest_base_seg(void) { }
+static inline void setup_guest_base_seg(void)
+{
+    /*
+     * Verify we can proceed without scratch registers.
+     * If guest_base > INT32_MAX, then it would need to be loaded.
+     * If 32-bit guest, the address would need to be zero-extended.
+     */
+    if (TCG_TARGET_REG_BITS == 64
+        && (TARGET_LONG_BITS == 32 || guest_base > INT32_MAX)) {
+        error_report("Segment base register not supported on this OS");
+        exit(1);
+    }
+}
 #endif /* SOFTMMU */
 
 static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg datalo, TCGReg datahi,
@@ -2013,16 +2031,6 @@  static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, bool is64)
             if (TCG_TARGET_REG_BITS > TARGET_LONG_BITS) {
                 seg |= P_ADDR32;
             }
-        } else if (TCG_TARGET_REG_BITS == 64) {
-            if (TARGET_LONG_BITS == 32) {
-                tcg_out_ext32u(s, TCG_REG_L0, base);
-                base = TCG_REG_L0;
-            }
-            if (offset != guest_base) {
-                tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_L1, guest_base);
-                index = TCG_REG_L1;
-                offset = 0;
-            }
         }
 
         tcg_out_qemu_ld_direct(s, datalo, datahi,
@@ -2156,22 +2164,6 @@  static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, bool is64)
             if (TCG_TARGET_REG_BITS > TARGET_LONG_BITS) {
                 seg |= P_ADDR32;
             }
-        } else if (TCG_TARGET_REG_BITS == 64) {
-            /* ??? Note that we can't use the same SIB addressing scheme
-               as for loads, since we require L0 free for bswap.  */
-            if (offset != guest_base) {
-                if (TARGET_LONG_BITS == 32) {
-                    tcg_out_ext32u(s, TCG_REG_L0, base);
-                    base = TCG_REG_L0;
-                }
-                tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_L1, guest_base);
-                tgen_arithr(s, ARITH_ADD + P_REXW, TCG_REG_L1, base);
-                base = TCG_REG_L1;
-                offset = 0;
-            } else if (TARGET_LONG_BITS == 32) {
-                tcg_out_ext32u(s, TCG_REG_L1, base);
-                base = TCG_REG_L1;
-            }
         }
 
         tcg_out_qemu_st_direct(s, datalo, datahi, base, offset, seg, opc);