Commit fbb4a2e371f2fa7d3bbe479795d8c79a795f7cd3

Authored by pbrook
1 parent ce5232c5

Implement ARM magic kernel page and TLS register.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4610 c046a42c-6fe2-441c-8c8c-71466251a162
linux-user/arm/syscall.h
... ... @@ -28,7 +28,9 @@ struct target_pt_regs {
28 28 #define ARM_SYSCALL_BASE 0x900000
29 29 #define ARM_THUMB_SYSCALL 0
30 30  
31   -#define ARM_NR_cacheflush (ARM_SYSCALL_BASE + 0xf0000 + 2)
  31 +#define ARM_NR_BASE 0xf0000
  32 +#define ARM_NR_cacheflush (ARM_NR_BASE + 2)
  33 +#define ARM_NR_set_tls (ARM_NR_BASE + 5)
32 34  
33 35 #define ARM_NR_semihosting 0x123456
34 36 #define ARM_NR_thumb_semihosting 0xAB
... ...
linux-user/main.c
... ... @@ -365,6 +365,55 @@ static void arm_cache_flush(abi_ulong start, abi_ulong last)
365 365 }
366 366 }
367 367  
  368 +/* Handle a jump to the kernel code page. */
  369 +static int
  370 +do_kernel_trap(CPUARMState *env)
  371 +{
  372 + uint32_t addr;
  373 + uint32_t cpsr;
  374 + uint32_t val;
  375 +
  376 + switch (env->regs[15]) {
  377 + case 0xffff0fa0: /* __kernel_memory_barrier */
  378 + /* ??? No-op. Will need to do better for SMP. */
  379 + break;
  380 + case 0xffff0fc0: /* __kernel_cmpxchg */
  381 + /* ??? This is not really atomic. However we don't support
  382 + threads anyway, so it doesn't realy matter. */
  383 + cpsr = cpsr_read(env);
  384 + addr = env->regs[2];
  385 + /* FIXME: This should SEGV if the access fails. */
  386 + if (get_user_u32(val, addr))
  387 + val = ~env->regs[0];
  388 + if (val == env->regs[0]) {
  389 + val = env->regs[1];
  390 + /* FIXME: Check for segfaults. */
  391 + put_user_u32(val, addr);
  392 + env->regs[0] = 0;
  393 + cpsr |= CPSR_C;
  394 + } else {
  395 + env->regs[0] = -1;
  396 + cpsr &= ~CPSR_C;
  397 + }
  398 + cpsr_write(env, cpsr, CPSR_C);
  399 + break;
  400 + case 0xffff0fe0: /* __kernel_get_tls */
  401 + env->regs[0] = env->cp15.c13_tls2;
  402 + break;
  403 + default:
  404 + return 1;
  405 + }
  406 + /* Jump back to the caller. */
  407 + addr = env->regs[14];
  408 + if (addr & 1) {
  409 + env->thumb = 1;
  410 + addr &= ~1;
  411 + }
  412 + env->regs[15] = addr;
  413 +
  414 + return 0;
  415 +}
  416 +
368 417 void cpu_loop(CPUARMState *env)
369 418 {
370 419 int trapnr;
... ... @@ -489,14 +538,31 @@ void cpu_loop(CPUARMState *env)
489 538 n -= ARM_SYSCALL_BASE;
490 539 env->eabi = 0;
491 540 }
492   - env->regs[0] = do_syscall(env,
493   - n,
494   - env->regs[0],
495   - env->regs[1],
496   - env->regs[2],
497   - env->regs[3],
498   - env->regs[4],
499   - env->regs[5]);
  541 + if ( n > ARM_NR_BASE) {
  542 + switch (n) {
  543 + case ARM_NR_cacheflush:
  544 + arm_cache_flush(env->regs[0], env->regs[1]);
  545 + break;
  546 + case ARM_NR_set_tls:
  547 + cpu_set_tls(env, env->regs[0]);
  548 + env->regs[0] = 0;
  549 + break;
  550 + default:
  551 + gemu_log("qemu: Unsupported ARM syscall: 0x%x\n",
  552 + n);
  553 + env->regs[0] = -TARGET_ENOSYS;
  554 + break;
  555 + }
  556 + } else {
  557 + env->regs[0] = do_syscall(env,
  558 + n,
  559 + env->regs[0],
  560 + env->regs[1],
  561 + env->regs[2],
  562 + env->regs[3],
  563 + env->regs[4],
  564 + env->regs[5]);
  565 + }
500 566 } else {
501 567 goto error;
502 568 }
... ... @@ -535,6 +601,10 @@ void cpu_loop(CPUARMState *env)
535 601 }
536 602 }
537 603 break;
  604 + case EXCP_KERNEL_TRAP:
  605 + if (do_kernel_trap(env))
  606 + goto error;
  607 + break;
538 608 default:
539 609 error:
540 610 fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
... ...
target-arm/cpu.h
... ... @@ -38,6 +38,7 @@
38 38 #define EXCP_FIQ 6
39 39 #define EXCP_BKPT 7
40 40 #define EXCP_EXCEPTION_EXIT 8 /* Return from v7M exception. */
  41 +#define EXCP_KERNEL_TRAP 9 /* Jumped to kernel code page. */
41 42  
42 43 #define ARMV7M_EXCP_RESET 1
43 44 #define ARMV7M_EXCP_NMI 2
... ... @@ -216,6 +217,10 @@ int cpu_arm_signal_handler(int host_signum, void *pinfo,
216 217  
217 218 void cpu_lock(void);
218 219 void cpu_unlock(void);
  220 +static inline void cpu_set_tls(CPUARMState *env, target_ulong newtls)
  221 +{
  222 + env->cp15.c13_tls2 = newtls;
  223 +}
219 224  
220 225 #define CPSR_M (0x1f)
221 226 #define CPSR_T (1 << 5)
... ...
target-arm/translate.c
... ... @@ -8583,7 +8583,16 @@ static inline int gen_intermediate_code_internal(CPUState *env,
8583 8583 store_cpu_field(tmp, condexec_bits);
8584 8584 }
8585 8585 do {
8586   -#ifndef CONFIG_USER_ONLY
  8586 +#ifdef CONFIG_USER_ONLY
  8587 + /* Intercept jump to the magic kernel page. */
  8588 + if (dc->pc >= 0xffff0000) {
  8589 + /* We always get here via a jump, so know we are not in a
  8590 + conditional execution block. */
  8591 + gen_exception(EXCP_KERNEL_TRAP);
  8592 + dc->is_jmp = DISAS_UPDATE;
  8593 + break;
  8594 + }
  8595 +#else
8587 8596 if (dc->pc >= 0xfffffff0 && IS_M(env)) {
8588 8597 /* We always get here via a jump, so know we are not in a
8589 8598 conditional execution block. */
... ...