From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1K1Vsx-00032i-Ay for qemu-devel@nongnu.org; Wed, 28 May 2008 20:20:51 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1K1Vsv-00032S-R9 for qemu-devel@nongnu.org; Wed, 28 May 2008 20:20:49 -0400 Received: from [199.232.76.173] (port=37968 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1K1Vsv-00032P-Lx for qemu-devel@nongnu.org; Wed, 28 May 2008 20:20:49 -0400 Received: from savannah.gnu.org ([199.232.41.3]:33664 helo=sv.gnu.org) by monty-python.gnu.org with esmtps (TLS-1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.60) (envelope-from ) id 1K1Vsv-00068l-A3 for qemu-devel@nongnu.org; Wed, 28 May 2008 20:20:49 -0400 Received: from cvs.savannah.gnu.org ([199.232.41.69]) by sv.gnu.org with esmtp (Exim 4.63) (envelope-from ) id 1K1Vss-0004Qy-CN for qemu-devel@nongnu.org; Thu, 29 May 2008 00:20:46 +0000 Received: from pbrook by cvs.savannah.gnu.org with local (Exim 4.63) (envelope-from ) id 1K1Vsr-0004Qk-Oq for qemu-devel@nongnu.org; Thu, 29 May 2008 00:20:46 +0000 MIME-Version: 1.0 Errors-To: pbrook Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Paul Brook Message-Id: Date: Thu, 29 May 2008 00:20:45 +0000 Subject: [Qemu-devel] [4610] Implement ARM magic kernel page and TLS register. Reply-To: qemu-devel@nongnu.org List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org 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. */