qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [4610] Implement ARM magic kernel page and TLS register.


From: Paul Brook
Subject: [Qemu-devel] [4610] Implement ARM magic kernel page and TLS register.
Date: Thu, 29 May 2008 00:20:45 +0000

Revision: 4610
          http://svn.sv.gnu.org/viewvc/?view=rev&root=qemu&revision=4610
Author:   pbrook
Date:     2008-05-29 00:20:44 +0000 (Thu, 29 May 2008)

Log Message:
-----------
Implement ARM magic kernel page and TLS register.

Modified Paths:
--------------
    trunk/linux-user/arm/syscall.h
    trunk/linux-user/main.c
    trunk/target-arm/cpu.h
    trunk/target-arm/translate.c

Modified: trunk/linux-user/arm/syscall.h
===================================================================
--- trunk/linux-user/arm/syscall.h      2008-05-28 17:14:10 UTC (rev 4609)
+++ trunk/linux-user/arm/syscall.h      2008-05-29 00:20:44 UTC (rev 4610)
@@ -28,7 +28,9 @@
 #define ARM_SYSCALL_BASE       0x900000
 #define ARM_THUMB_SYSCALL      0
 
-#define ARM_NR_cacheflush (ARM_SYSCALL_BASE + 0xf0000 + 2)
+#define ARM_NR_BASE      0xf0000
+#define ARM_NR_cacheflush (ARM_NR_BASE + 2)
+#define ARM_NR_set_tls   (ARM_NR_BASE + 5)
 
 #define ARM_NR_semihosting       0x123456
 #define ARM_NR_thumb_semihosting  0xAB

Modified: trunk/linux-user/main.c
===================================================================
--- trunk/linux-user/main.c     2008-05-28 17:14:10 UTC (rev 4609)
+++ trunk/linux-user/main.c     2008-05-29 00:20:44 UTC (rev 4610)
@@ -365,6 +365,55 @@
     }
 }
 
+/* Handle a jump to the kernel code page.  */
+static int
+do_kernel_trap(CPUARMState *env)
+{
+    uint32_t addr;
+    uint32_t cpsr;
+    uint32_t val;
+
+    switch (env->regs[15]) {
+    case 0xffff0fa0: /* __kernel_memory_barrier */
+        /* ??? No-op. Will need to do better for SMP.  */
+        break;
+    case 0xffff0fc0: /* __kernel_cmpxchg */
+        /* ??? This is not really atomic.  However we don't support
+           threads anyway, so it doesn't realy matter.  */
+        cpsr = cpsr_read(env);
+        addr = env->regs[2];
+        /* FIXME: This should SEGV if the access fails.  */
+        if (get_user_u32(val, addr))
+            val = ~env->regs[0];
+        if (val == env->regs[0]) {
+            val = env->regs[1];
+            /* FIXME: Check for segfaults.  */
+            put_user_u32(val, addr);
+            env->regs[0] = 0;
+            cpsr |= CPSR_C;
+        } else {
+            env->regs[0] = -1;
+            cpsr &= ~CPSR_C;
+        }
+        cpsr_write(env, cpsr, CPSR_C);
+        break;
+    case 0xffff0fe0: /* __kernel_get_tls */
+        env->regs[0] = env->cp15.c13_tls2;
+        break;
+    default:
+        return 1;
+    }
+    /* Jump back to the caller.  */
+    addr = env->regs[14];
+    if (addr & 1) {
+        env->thumb = 1;
+        addr &= ~1;
+    }
+    env->regs[15] = addr;
+
+    return 0;
+}
+
 void cpu_loop(CPUARMState *env)
 {
     int trapnr;
@@ -489,14 +538,31 @@
                         n -= ARM_SYSCALL_BASE;
                         env->eabi = 0;
                     }
-                    env->regs[0] = do_syscall(env,
-                                              n,
-                                              env->regs[0],
-                                              env->regs[1],
-                                              env->regs[2],
-                                              env->regs[3],
-                                              env->regs[4],
-                                              env->regs[5]);
+                    if ( n > ARM_NR_BASE) {
+                        switch (n) {
+                        case ARM_NR_cacheflush:
+                            arm_cache_flush(env->regs[0], env->regs[1]);
+                            break;
+                        case ARM_NR_set_tls:
+                            cpu_set_tls(env, env->regs[0]);
+                            env->regs[0] = 0;
+                            break;
+                        default:
+                            gemu_log("qemu: Unsupported ARM syscall: 0x%x\n",
+                                     n);
+                            env->regs[0] = -TARGET_ENOSYS;
+                            break;
+                        }
+                    } else {
+                        env->regs[0] = do_syscall(env,
+                                                  n,
+                                                  env->regs[0],
+                                                  env->regs[1],
+                                                  env->regs[2],
+                                                  env->regs[3],
+                                                  env->regs[4],
+                                                  env->regs[5]);
+                    }
                 } else {
                     goto error;
                 }
@@ -535,6 +601,10 @@
                   }
             }
             break;
+        case EXCP_KERNEL_TRAP:
+            if (do_kernel_trap(env))
+              goto error;
+            break;
         default:
         error:
             fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",

Modified: trunk/target-arm/cpu.h
===================================================================
--- trunk/target-arm/cpu.h      2008-05-28 17:14:10 UTC (rev 4609)
+++ trunk/target-arm/cpu.h      2008-05-29 00:20:44 UTC (rev 4610)
@@ -38,6 +38,7 @@
 #define EXCP_FIQ             6
 #define EXCP_BKPT            7
 #define EXCP_EXCEPTION_EXIT  8   /* Return from v7M exception.  */
+#define EXCP_KERNEL_TRAP     9   /* Jumped to kernel code page.  */
 
 #define ARMV7M_EXCP_RESET   1
 #define ARMV7M_EXCP_NMI     2
@@ -216,6 +217,10 @@
 
 void cpu_lock(void);
 void cpu_unlock(void);
+static inline void cpu_set_tls(CPUARMState *env, target_ulong newtls)
+{
+  env->cp15.c13_tls2 = newtls;
+}
 
 #define CPSR_M (0x1f)
 #define CPSR_T (1 << 5)

Modified: trunk/target-arm/translate.c
===================================================================
--- trunk/target-arm/translate.c        2008-05-28 17:14:10 UTC (rev 4609)
+++ trunk/target-arm/translate.c        2008-05-29 00:20:44 UTC (rev 4610)
@@ -8583,7 +8583,16 @@
         store_cpu_field(tmp, condexec_bits);
       }
     do {
-#ifndef CONFIG_USER_ONLY
+#ifdef CONFIG_USER_ONLY
+        /* Intercept jump to the magic kernel page.  */
+        if (dc->pc >= 0xffff0000) {
+            /* We always get here via a jump, so know we are not in a
+               conditional execution block.  */
+            gen_exception(EXCP_KERNEL_TRAP);
+            dc->is_jmp = DISAS_UPDATE;
+            break;
+        }
+#else
         if (dc->pc >= 0xfffffff0 && IS_M(env)) {
             /* We always get here via a jump, so know we are not in a
                conditional execution block.  */






reply via email to

[Prev in Thread] Current Thread [Next in Thread]