Revision fbb4a2e3 linux-user/main.c

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",

Also available in: Unified diff