Revision fbb4a2e3

b/linux-user/arm/syscall.h
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
b/linux-user/main.c
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 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 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",
b/target-arm/cpu.h
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 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)
b/target-arm/translate.c
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.  */

Also available in: Unified diff