qemu/user-exec.c
<<
>>
Prefs
   1/*
   2 *  User emulator execution
   3 *
   4 *  Copyright (c) 2003-2005 Fabrice Bellard
   5 *
   6 * This library is free software; you can redistribute it and/or
   7 * modify it under the terms of the GNU Lesser General Public
   8 * License as published by the Free Software Foundation; either
   9 * version 2 of the License, or (at your option) any later version.
  10 *
  11 * This library is distributed in the hope that it will be useful,
  12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14 * Lesser General Public License for more details.
  15 *
  16 * You should have received a copy of the GNU Lesser General Public
  17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  18 */
  19#include "config.h"
  20#include "exec.h"
  21#include "disas.h"
  22#include "tcg.h"
  23
  24#undef EAX
  25#undef ECX
  26#undef EDX
  27#undef EBX
  28#undef ESP
  29#undef EBP
  30#undef ESI
  31#undef EDI
  32#undef EIP
  33#include <signal.h>
  34#ifdef __linux__
  35#include <sys/ucontext.h>
  36#endif
  37
  38//#define DEBUG_SIGNAL
  39
  40static void exception_action(CPUState *env1)
  41{
  42#if defined(TARGET_I386)
  43    raise_exception_err(env1->exception_index, env1->error_code);
  44#else
  45    cpu_loop_exit(env1);
  46#endif
  47}
  48
  49/* exit the current TB from a signal handler. The host registers are
  50   restored in a state compatible with the CPU emulator
  51 */
  52void cpu_resume_from_signal(CPUState *env1, void *puc)
  53{
  54#ifdef __linux__
  55    struct ucontext *uc = puc;
  56#elif defined(__OpenBSD__)
  57    struct sigcontext *uc = puc;
  58#endif
  59
  60    env = env1;
  61
  62    /* XXX: restore cpu registers saved in host registers */
  63
  64    if (puc) {
  65        /* XXX: use siglongjmp ? */
  66#ifdef __linux__
  67#ifdef __ia64
  68        sigprocmask(SIG_SETMASK, (sigset_t *)&uc->uc_sigmask, NULL);
  69#else
  70        sigprocmask(SIG_SETMASK, &uc->uc_sigmask, NULL);
  71#endif
  72#elif defined(__OpenBSD__)
  73        sigprocmask(SIG_SETMASK, &uc->sc_mask, NULL);
  74#endif
  75    }
  76    env->exception_index = -1;
  77    longjmp(env->jmp_env, 1);
  78}
  79
  80/* 'pc' is the host PC at which the exception was raised. 'address' is
  81   the effective address of the memory exception. 'is_write' is 1 if a
  82   write caused the exception and otherwise 0'. 'old_set' is the
  83   signal set which should be restored */
  84static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
  85                                    int is_write, sigset_t *old_set,
  86                                    void *puc)
  87{
  88    TranslationBlock *tb;
  89    int ret;
  90
  91    if (cpu_single_env) {
  92        env = cpu_single_env; /* XXX: find a correct solution for multithread */
  93    }
  94#if defined(DEBUG_SIGNAL)
  95    qemu_printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
  96                pc, address, is_write, *(unsigned long *)old_set);
  97#endif
  98    /* XXX: locking issue */
  99    if (is_write && page_unprotect(h2g(address), pc, puc)) {
 100        return 1;
 101    }
 102
 103    /* see if it is an MMU fault */
 104    ret = cpu_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
 105    if (ret < 0) {
 106        return 0; /* not an MMU fault */
 107    }
 108    if (ret == 0) {
 109        return 1; /* the MMU fault was handled without causing real CPU fault */
 110    }
 111    /* now we have a real cpu fault */
 112    tb = tb_find_pc(pc);
 113    if (tb) {
 114        /* the PC is inside the translated code. It means that we have
 115           a virtual CPU fault */
 116        cpu_restore_state(tb, env, pc);
 117    }
 118
 119    /* we restore the process signal mask as the sigreturn should
 120       do it (XXX: use sigsetjmp) */
 121    sigprocmask(SIG_SETMASK, old_set, NULL);
 122    exception_action(env);
 123
 124    /* never comes here */
 125    return 1;
 126}
 127
 128#if defined(__i386__)
 129
 130#if defined(__APPLE__)
 131#include <sys/ucontext.h>
 132
 133#define EIP_sig(context)  (*((unsigned long *)&(context)->uc_mcontext->ss.eip))
 134#define TRAP_sig(context)    ((context)->uc_mcontext->es.trapno)
 135#define ERROR_sig(context)   ((context)->uc_mcontext->es.err)
 136#define MASK_sig(context)    ((context)->uc_sigmask)
 137#elif defined(__NetBSD__)
 138#include <ucontext.h>
 139
 140#define EIP_sig(context)     ((context)->uc_mcontext.__gregs[_REG_EIP])
 141#define TRAP_sig(context)    ((context)->uc_mcontext.__gregs[_REG_TRAPNO])
 142#define ERROR_sig(context)   ((context)->uc_mcontext.__gregs[_REG_ERR])
 143#define MASK_sig(context)    ((context)->uc_sigmask)
 144#elif defined(__FreeBSD__) || defined(__DragonFly__)
 145#include <ucontext.h>
 146
 147#define EIP_sig(context)  (*((unsigned long *)&(context)->uc_mcontext.mc_eip))
 148#define TRAP_sig(context)    ((context)->uc_mcontext.mc_trapno)
 149#define ERROR_sig(context)   ((context)->uc_mcontext.mc_err)
 150#define MASK_sig(context)    ((context)->uc_sigmask)
 151#elif defined(__OpenBSD__)
 152#define EIP_sig(context)     ((context)->sc_eip)
 153#define TRAP_sig(context)    ((context)->sc_trapno)
 154#define ERROR_sig(context)   ((context)->sc_err)
 155#define MASK_sig(context)    ((context)->sc_mask)
 156#else
 157#define EIP_sig(context)     ((context)->uc_mcontext.gregs[REG_EIP])
 158#define TRAP_sig(context)    ((context)->uc_mcontext.gregs[REG_TRAPNO])
 159#define ERROR_sig(context)   ((context)->uc_mcontext.gregs[REG_ERR])
 160#define MASK_sig(context)    ((context)->uc_sigmask)
 161#endif
 162
 163int cpu_signal_handler(int host_signum, void *pinfo,
 164                       void *puc)
 165{
 166    siginfo_t *info = pinfo;
 167#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__)
 168    ucontext_t *uc = puc;
 169#elif defined(__OpenBSD__)
 170    struct sigcontext *uc = puc;
 171#else
 172    struct ucontext *uc = puc;
 173#endif
 174    unsigned long pc;
 175    int trapno;
 176
 177#ifndef REG_EIP
 178/* for glibc 2.1 */
 179#define REG_EIP    EIP
 180#define REG_ERR    ERR
 181#define REG_TRAPNO TRAPNO
 182#endif
 183    pc = EIP_sig(uc);
 184    trapno = TRAP_sig(uc);
 185    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
 186                             trapno == 0xe ?
 187                             (ERROR_sig(uc) >> 1) & 1 : 0,
 188                             &MASK_sig(uc), puc);
 189}
 190
 191#elif defined(__x86_64__)
 192
 193#ifdef __NetBSD__
 194#define PC_sig(context)       _UC_MACHINE_PC(context)
 195#define TRAP_sig(context)     ((context)->uc_mcontext.__gregs[_REG_TRAPNO])
 196#define ERROR_sig(context)    ((context)->uc_mcontext.__gregs[_REG_ERR])
 197#define MASK_sig(context)     ((context)->uc_sigmask)
 198#elif defined(__OpenBSD__)
 199#define PC_sig(context)       ((context)->sc_rip)
 200#define TRAP_sig(context)     ((context)->sc_trapno)
 201#define ERROR_sig(context)    ((context)->sc_err)
 202#define MASK_sig(context)     ((context)->sc_mask)
 203#elif defined(__FreeBSD__) || defined(__DragonFly__)
 204#include <ucontext.h>
 205
 206#define PC_sig(context)  (*((unsigned long *)&(context)->uc_mcontext.mc_rip))
 207#define TRAP_sig(context)     ((context)->uc_mcontext.mc_trapno)
 208#define ERROR_sig(context)    ((context)->uc_mcontext.mc_err)
 209#define MASK_sig(context)     ((context)->uc_sigmask)
 210#else
 211#define PC_sig(context)       ((context)->uc_mcontext.gregs[REG_RIP])
 212#define TRAP_sig(context)     ((context)->uc_mcontext.gregs[REG_TRAPNO])
 213#define ERROR_sig(context)    ((context)->uc_mcontext.gregs[REG_ERR])
 214#define MASK_sig(context)     ((context)->uc_sigmask)
 215#endif
 216
 217int cpu_signal_handler(int host_signum, void *pinfo,
 218                       void *puc)
 219{
 220    siginfo_t *info = pinfo;
 221    unsigned long pc;
 222#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__)
 223    ucontext_t *uc = puc;
 224#elif defined(__OpenBSD__)
 225    struct sigcontext *uc = puc;
 226#else
 227    struct ucontext *uc = puc;
 228#endif
 229
 230    pc = PC_sig(uc);
 231    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
 232                             TRAP_sig(uc) == 0xe ?
 233                             (ERROR_sig(uc) >> 1) & 1 : 0,
 234                             &MASK_sig(uc), puc);
 235}
 236
 237#elif defined(_ARCH_PPC)
 238
 239/***********************************************************************
 240 * signal context platform-specific definitions
 241 * From Wine
 242 */
 243#ifdef linux
 244/* All Registers access - only for local access */
 245#define REG_sig(reg_name, context)              \
 246    ((context)->uc_mcontext.regs->reg_name)
 247/* Gpr Registers access  */
 248#define GPR_sig(reg_num, context)              REG_sig(gpr[reg_num], context)
 249/* Program counter */
 250#define IAR_sig(context)                       REG_sig(nip, context)
 251/* Machine State Register (Supervisor) */
 252#define MSR_sig(context)                       REG_sig(msr, context)
 253/* Count register */
 254#define CTR_sig(context)                       REG_sig(ctr, context)
 255/* User's integer exception register */
 256#define XER_sig(context)                       REG_sig(xer, context)
 257/* Link register */
 258#define LR_sig(context)                        REG_sig(link, context)
 259/* Condition register */
 260#define CR_sig(context)                        REG_sig(ccr, context)
 261
 262/* Float Registers access  */
 263#define FLOAT_sig(reg_num, context)                                     \
 264    (((double *)((char *)((context)->uc_mcontext.regs + 48 * 4)))[reg_num])
 265#define FPSCR_sig(context) \
 266    (*(int *)((char *)((context)->uc_mcontext.regs + (48 + 32 * 2) * 4)))
 267/* Exception Registers access */
 268#define DAR_sig(context)                       REG_sig(dar, context)
 269#define DSISR_sig(context)                     REG_sig(dsisr, context)
 270#define TRAP_sig(context)                      REG_sig(trap, context)
 271#endif /* linux */
 272
 273#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
 274#include <ucontext.h>
 275#define IAR_sig(context)               ((context)->uc_mcontext.mc_srr0)
 276#define MSR_sig(context)               ((context)->uc_mcontext.mc_srr1)
 277#define CTR_sig(context)               ((context)->uc_mcontext.mc_ctr)
 278#define XER_sig(context)               ((context)->uc_mcontext.mc_xer)
 279#define LR_sig(context)                ((context)->uc_mcontext.mc_lr)
 280#define CR_sig(context)                ((context)->uc_mcontext.mc_cr)
 281/* Exception Registers access */
 282#define DAR_sig(context)               ((context)->uc_mcontext.mc_dar)
 283#define DSISR_sig(context)             ((context)->uc_mcontext.mc_dsisr)
 284#define TRAP_sig(context)              ((context)->uc_mcontext.mc_exc)
 285#endif /* __FreeBSD__|| __FreeBSD_kernel__ */
 286
 287#ifdef __APPLE__
 288#include <sys/ucontext.h>
 289typedef struct ucontext SIGCONTEXT;
 290/* All Registers access - only for local access */
 291#define REG_sig(reg_name, context)              \
 292    ((context)->uc_mcontext->ss.reg_name)
 293#define FLOATREG_sig(reg_name, context)         \
 294    ((context)->uc_mcontext->fs.reg_name)
 295#define EXCEPREG_sig(reg_name, context)         \
 296    ((context)->uc_mcontext->es.reg_name)
 297#define VECREG_sig(reg_name, context)           \
 298    ((context)->uc_mcontext->vs.reg_name)
 299/* Gpr Registers access */
 300#define GPR_sig(reg_num, context)              REG_sig(r##reg_num, context)
 301/* Program counter */
 302#define IAR_sig(context)                       REG_sig(srr0, context)
 303/* Machine State Register (Supervisor) */
 304#define MSR_sig(context)                       REG_sig(srr1, context)
 305#define CTR_sig(context)                       REG_sig(ctr, context)
 306/* Link register */
 307#define XER_sig(context)                       REG_sig(xer, context)
 308/* User's integer exception register */
 309#define LR_sig(context)                        REG_sig(lr, context)
 310/* Condition register */
 311#define CR_sig(context)                        REG_sig(cr, context)
 312/* Float Registers access */
 313#define FLOAT_sig(reg_num, context)             \
 314    FLOATREG_sig(fpregs[reg_num], context)
 315#define FPSCR_sig(context)                      \
 316    ((double)FLOATREG_sig(fpscr, context))
 317/* Exception Registers access */
 318/* Fault registers for coredump */
 319#define DAR_sig(context)                       EXCEPREG_sig(dar, context)
 320#define DSISR_sig(context)                     EXCEPREG_sig(dsisr, context)
 321/* number of powerpc exception taken */
 322#define TRAP_sig(context)                      EXCEPREG_sig(exception, context)
 323#endif /* __APPLE__ */
 324
 325int cpu_signal_handler(int host_signum, void *pinfo,
 326                       void *puc)
 327{
 328    siginfo_t *info = pinfo;
 329#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
 330    ucontext_t *uc = puc;
 331#else
 332    struct ucontext *uc = puc;
 333#endif
 334    unsigned long pc;
 335    int is_write;
 336
 337    pc = IAR_sig(uc);
 338    is_write = 0;
 339#if 0
 340    /* ppc 4xx case */
 341    if (DSISR_sig(uc) & 0x00800000) {
 342        is_write = 1;
 343    }
 344#else
 345    if (TRAP_sig(uc) != 0x400 && (DSISR_sig(uc) & 0x02000000)) {
 346        is_write = 1;
 347    }
 348#endif
 349    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
 350                             is_write, &uc->uc_sigmask, puc);
 351}
 352
 353#elif defined(__alpha__)
 354
 355int cpu_signal_handler(int host_signum, void *pinfo,
 356                           void *puc)
 357{
 358    siginfo_t *info = pinfo;
 359    struct ucontext *uc = puc;
 360    uint32_t *pc = uc->uc_mcontext.sc_pc;
 361    uint32_t insn = *pc;
 362    int is_write = 0;
 363
 364    /* XXX: need kernel patch to get write flag faster */
 365    switch (insn >> 26) {
 366    case 0x0d: /* stw */
 367    case 0x0e: /* stb */
 368    case 0x0f: /* stq_u */
 369    case 0x24: /* stf */
 370    case 0x25: /* stg */
 371    case 0x26: /* sts */
 372    case 0x27: /* stt */
 373    case 0x2c: /* stl */
 374    case 0x2d: /* stq */
 375    case 0x2e: /* stl_c */
 376    case 0x2f: /* stq_c */
 377        is_write = 1;
 378    }
 379
 380    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
 381                             is_write, &uc->uc_sigmask, puc);
 382}
 383#elif defined(__sparc__)
 384
 385int cpu_signal_handler(int host_signum, void *pinfo,
 386                       void *puc)
 387{
 388    siginfo_t *info = pinfo;
 389    int is_write;
 390    uint32_t insn;
 391#if !defined(__arch64__) || defined(CONFIG_SOLARIS)
 392    uint32_t *regs = (uint32_t *)(info + 1);
 393    void *sigmask = (regs + 20);
 394    /* XXX: is there a standard glibc define ? */
 395    unsigned long pc = regs[1];
 396#else
 397#ifdef __linux__
 398    struct sigcontext *sc = puc;
 399    unsigned long pc = sc->sigc_regs.tpc;
 400    void *sigmask = (void *)sc->sigc_mask;
 401#elif defined(__OpenBSD__)
 402    struct sigcontext *uc = puc;
 403    unsigned long pc = uc->sc_pc;
 404    void *sigmask = (void *)(long)uc->sc_mask;
 405#endif
 406#endif
 407
 408    /* XXX: need kernel patch to get write flag faster */
 409    is_write = 0;
 410    insn = *(uint32_t *)pc;
 411    if ((insn >> 30) == 3) {
 412        switch ((insn >> 19) & 0x3f) {
 413        case 0x05: /* stb */
 414        case 0x15: /* stba */
 415        case 0x06: /* sth */
 416        case 0x16: /* stha */
 417        case 0x04: /* st */
 418        case 0x14: /* sta */
 419        case 0x07: /* std */
 420        case 0x17: /* stda */
 421        case 0x0e: /* stx */
 422        case 0x1e: /* stxa */
 423        case 0x24: /* stf */
 424        case 0x34: /* stfa */
 425        case 0x27: /* stdf */
 426        case 0x37: /* stdfa */
 427        case 0x26: /* stqf */
 428        case 0x36: /* stqfa */
 429        case 0x25: /* stfsr */
 430        case 0x3c: /* casa */
 431        case 0x3e: /* casxa */
 432            is_write = 1;
 433            break;
 434        }
 435    }
 436    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
 437                             is_write, sigmask, NULL);
 438}
 439
 440#elif defined(__arm__)
 441
 442int cpu_signal_handler(int host_signum, void *pinfo,
 443                       void *puc)
 444{
 445    siginfo_t *info = pinfo;
 446    struct ucontext *uc = puc;
 447    unsigned long pc;
 448    int is_write;
 449
 450#if (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3))
 451    pc = uc->uc_mcontext.gregs[R15];
 452#else
 453    pc = uc->uc_mcontext.arm_pc;
 454#endif
 455    /* XXX: compute is_write */
 456    is_write = 0;
 457    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
 458                             is_write,
 459                             &uc->uc_sigmask, puc);
 460}
 461
 462#elif defined(__mc68000)
 463
 464int cpu_signal_handler(int host_signum, void *pinfo,
 465                       void *puc)
 466{
 467    siginfo_t *info = pinfo;
 468    struct ucontext *uc = puc;
 469    unsigned long pc;
 470    int is_write;
 471
 472    pc = uc->uc_mcontext.gregs[16];
 473    /* XXX: compute is_write */
 474    is_write = 0;
 475    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
 476                             is_write,
 477                             &uc->uc_sigmask, puc);
 478}
 479
 480#elif defined(__ia64)
 481
 482#ifndef __ISR_VALID
 483  /* This ought to be in <bits/siginfo.h>... */
 484# define __ISR_VALID    1
 485#endif
 486
 487int cpu_signal_handler(int host_signum, void *pinfo, void *puc)
 488{
 489    siginfo_t *info = pinfo;
 490    struct ucontext *uc = puc;
 491    unsigned long ip;
 492    int is_write = 0;
 493
 494    ip = uc->uc_mcontext.sc_ip;
 495    switch (host_signum) {
 496    case SIGILL:
 497    case SIGFPE:
 498    case SIGSEGV:
 499    case SIGBUS:
 500    case SIGTRAP:
 501        if (info->si_code && (info->si_segvflags & __ISR_VALID)) {
 502            /* ISR.W (write-access) is bit 33:  */
 503            is_write = (info->si_isr >> 33) & 1;
 504        }
 505        break;
 506
 507    default:
 508        break;
 509    }
 510    return handle_cpu_signal(ip, (unsigned long)info->si_addr,
 511                             is_write,
 512                             (sigset_t *)&uc->uc_sigmask, puc);
 513}
 514
 515#elif defined(__s390__)
 516
 517int cpu_signal_handler(int host_signum, void *pinfo,
 518                       void *puc)
 519{
 520    siginfo_t *info = pinfo;
 521    struct ucontext *uc = puc;
 522    unsigned long pc;
 523    uint16_t *pinsn;
 524    int is_write = 0;
 525
 526    pc = uc->uc_mcontext.psw.addr;
 527
 528    /* ??? On linux, the non-rt signal handler has 4 (!) arguments instead
 529       of the normal 2 arguments.  The 3rd argument contains the "int_code"
 530       from the hardware which does in fact contain the is_write value.
 531       The rt signal handler, as far as I can tell, does not give this value
 532       at all.  Not that we could get to it from here even if it were.  */
 533    /* ??? This is not even close to complete, since it ignores all
 534       of the read-modify-write instructions.  */
 535    pinsn = (uint16_t *)pc;
 536    switch (pinsn[0] >> 8) {
 537    case 0x50: /* ST */
 538    case 0x42: /* STC */
 539    case 0x40: /* STH */
 540        is_write = 1;
 541        break;
 542    case 0xc4: /* RIL format insns */
 543        switch (pinsn[0] & 0xf) {
 544        case 0xf: /* STRL */
 545        case 0xb: /* STGRL */
 546        case 0x7: /* STHRL */
 547            is_write = 1;
 548        }
 549        break;
 550    case 0xe3: /* RXY format insns */
 551        switch (pinsn[2] & 0xff) {
 552        case 0x50: /* STY */
 553        case 0x24: /* STG */
 554        case 0x72: /* STCY */
 555        case 0x70: /* STHY */
 556        case 0x8e: /* STPQ */
 557        case 0x3f: /* STRVH */
 558        case 0x3e: /* STRV */
 559        case 0x2f: /* STRVG */
 560            is_write = 1;
 561        }
 562        break;
 563    }
 564    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
 565                             is_write, &uc->uc_sigmask, puc);
 566}
 567
 568#elif defined(__mips__)
 569
 570int cpu_signal_handler(int host_signum, void *pinfo,
 571                       void *puc)
 572{
 573    siginfo_t *info = pinfo;
 574    struct ucontext *uc = puc;
 575    greg_t pc = uc->uc_mcontext.pc;
 576    int is_write;
 577
 578    /* XXX: compute is_write */
 579    is_write = 0;
 580    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
 581                             is_write, &uc->uc_sigmask, puc);
 582}
 583
 584#elif defined(__hppa__)
 585
 586int cpu_signal_handler(int host_signum, void *pinfo,
 587                       void *puc)
 588{
 589    struct siginfo *info = pinfo;
 590    struct ucontext *uc = puc;
 591    unsigned long pc = uc->uc_mcontext.sc_iaoq[0];
 592    uint32_t insn = *(uint32_t *)pc;
 593    int is_write = 0;
 594
 595    /* XXX: need kernel patch to get write flag faster.  */
 596    switch (insn >> 26) {
 597    case 0x1a: /* STW */
 598    case 0x19: /* STH */
 599    case 0x18: /* STB */
 600    case 0x1b: /* STWM */
 601        is_write = 1;
 602        break;
 603
 604    case 0x09: /* CSTWX, FSTWX, FSTWS */
 605    case 0x0b: /* CSTDX, FSTDX, FSTDS */
 606        /* Distinguish from coprocessor load ... */
 607        is_write = (insn >> 9) & 1;
 608        break;
 609
 610    case 0x03:
 611        switch ((insn >> 6) & 15) {
 612        case 0xa: /* STWS */
 613        case 0x9: /* STHS */
 614        case 0x8: /* STBS */
 615        case 0xe: /* STWAS */
 616        case 0xc: /* STBYS */
 617            is_write = 1;
 618        }
 619        break;
 620    }
 621
 622    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
 623                             is_write, &uc->uc_sigmask, puc);
 624}
 625
 626#else
 627
 628#error host CPU specific signal handler needed
 629
 630#endif
 631
 632#if defined(TARGET_I386)
 633
 634void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector)
 635{
 636    CPUX86State *saved_env;
 637
 638    saved_env = env;
 639    env = s;
 640    if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK)) {
 641        selector &= 0xffff;
 642        cpu_x86_load_seg_cache(env, seg_reg, selector,
 643                               (selector << 4), 0xffff, 0);
 644    } else {
 645        helper_load_seg(seg_reg, selector);
 646    }
 647    env = saved_env;
 648}
 649
 650void cpu_x86_fsave(CPUX86State *s, target_ulong ptr, int data32)
 651{
 652    CPUX86State *saved_env;
 653
 654    saved_env = env;
 655    env = s;
 656
 657    helper_fsave(ptr, data32);
 658
 659    env = saved_env;
 660}
 661
 662void cpu_x86_frstor(CPUX86State *s, target_ulong ptr, int data32)
 663{
 664    CPUX86State *saved_env;
 665
 666    saved_env = env;
 667    env = s;
 668
 669    helper_frstor(ptr, data32);
 670
 671    env = saved_env;
 672}
 673
 674#endif /* TARGET_I386 */
 675