diff mbox

[2/2] tcg/i386: Use segment for 32-bit guest base on linux

Message ID 1465026847-6744-3-git-send-email-rth@twiddle.net (mailing list archive)
State New, archived
Headers show

Commit Message

Richard Henderson June 4, 2016, 7:54 a.m. UTC
From: Richard Henderson <rth@smalltime.twiddle.net>

This saves 3 bytes per memory operation.

Signed-off-by: Richard Henderson <rth@smalltime.twiddle.net>
---
 tcg/i386/tcg-target.inc.c | 44 +++++++++++++++++++++++++++++++++++++-------
 1 file changed, 37 insertions(+), 7 deletions(-)
diff mbox

Patch

diff --git a/tcg/i386/tcg-target.inc.c b/tcg/i386/tcg-target.inc.c
index 11cbb3c..d8c2f6d 100644
--- a/tcg/i386/tcg-target.inc.c
+++ b/tcg/i386/tcg-target.inc.c
@@ -290,14 +290,13 @@  static inline int tcg_target_const_match(tcg_target_long val, TCGType type,
 # define P_REXW         0x1000          /* Set REX.W = 1 */
 # define P_REXB_R       0x2000          /* REG field as byte register */
 # define P_REXB_RM      0x4000          /* R/M field as byte register */
-# define P_GS           0x8000          /* gs segment override */
 #else
 # define P_ADDR32	0
 # define P_REXW		0
 # define P_REXB_R	0
 # define P_REXB_RM	0
-# define P_GS           0
 #endif
+#define P_SEG           0x8000          /* fs/gs segment override */
 #define P_SIMDF3        0x10000         /* 0xf3 opcode prefix */
 #define P_SIMDF2        0x20000         /* 0xf2 opcode prefix */
 
@@ -420,8 +419,8 @@  static void tcg_out_opc(TCGContext *s, int opc, int r, int rm, int x)
 {
     int rex;
 
-    if (opc & P_GS) {
-        tcg_out8(s, 0x65);
+    if (opc & P_SEG) {
+        tcg_out8(s, 0x65); /* %gs */
     }
     if (opc & P_DATA16) {
         /* We should never be asking for both 16 and 64-bit operation.  */
@@ -462,6 +461,9 @@  static void tcg_out_opc(TCGContext *s, int opc, int r, int rm, int x)
 #else
 static void tcg_out_opc(TCGContext *s, int opc)
 {
+    if (opc & P_SEG) {
+        tcg_out8(s, 0x64); /* %fs */
+    }
     if (opc & P_DATA16) {
         tcg_out8(s, 0x66);
     }
@@ -1461,7 +1463,7 @@  static void setup_guest_base(TCGContext *s)
     }
 # ifdef __linux__
     if (arch_prctl(ARCH_SET_GS, guest_base) == 0) {
-        guest_base_flags = (TARGET_LONG_BITS == 32 ? P_GS | P_ADDR32 : P_GS);
+        guest_base_flags = P_SEG + (TARGET_LONG_BITS == 32) * P_ADDR32;
         return;
     }
 # endif
@@ -1473,6 +1475,33 @@  static void setup_guest_base(TCGContext *s)
         tcg_out_movi(s, TCG_TYPE_PTR, guest_base_reg, guest_base);
     }
 }
+#elif defined(__linux__)
+# include <asm/ldt.h>
+# include <sys/syscall.h>
+
+static int32_t guest_base_ofs;
+static int guest_base_flags;
+#define guest_base_reg    -1
+static void setup_guest_base(TCGContext *s)
+{
+    if (guest_base != 0) {
+        struct user_desc desc = {
+            .entry_number = -1,
+            .base_addr = guest_base,
+            .limit = 0xfffff,
+            .seg_32bit = 1,
+            .limit_in_pages = 1,
+            .useable = 1,
+        };
+        if (syscall(SYS_set_thread_area, &desc) == 0) {
+	    int seg = desc.entry_number * 8 + 3;
+            asm volatile("movl %0,%%fs" : : "r"(seg));
+	    guest_base_flags = P_SEG;
+            return;
+	}
+    }
+    guest_base_ofs = guest_base;
+}
 #else
 # define guest_base_flags  0
 # define guest_base_reg    -1
@@ -2310,6 +2339,9 @@  static void tcg_target_qemu_prologue(TCGContext *s)
     tcg_out_ld(s, TCG_TYPE_PTR, TCG_AREG0, TCG_REG_ESP,
                (ARRAY_SIZE(tcg_target_callee_save_regs) + 1) * 4);
     tcg_out_addi(s, TCG_REG_ESP, -stack_addend);
+# if !defined(CONFIG_SOFTMMU)
+    setup_guest_base(s);
+# endif
     /* jmp *tb.  */
     tcg_out_modrm_offset(s, OPC_GRP5, EXT5_JMPN_Ev, TCG_REG_ESP,
 		         (ARRAY_SIZE(tcg_target_callee_save_regs) + 2) * 4
@@ -2317,11 +2349,9 @@  static void tcg_target_qemu_prologue(TCGContext *s)
 #else
     tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
     tcg_out_addi(s, TCG_REG_ESP, -stack_addend);
-
 # if !defined(CONFIG_SOFTMMU)
     setup_guest_base(s);
 # endif
-
     /* jmp *tb.  */
     tcg_out_modrm(s, OPC_GRP5, EXT5_JMPN_Ev, tcg_target_call_iarg_regs[1]);
 #endif