qemu/target/i386/tcg/misc_helper.c
<<
>>
Prefs
   1/*
   2 *  x86 misc helpers
   3 *
   4 *  Copyright (c) 2003 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.1 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
  20#include "qemu/osdep.h"
  21#include "qemu/main-loop.h"
  22#include "cpu.h"
  23#include "exec/helper-proto.h"
  24#include "exec/exec-all.h"
  25#include "exec/cpu_ldst.h"
  26#include "exec/address-spaces.h"
  27#include "helper-tcg.h"
  28
  29/*
  30 * NOTE: the translator must set DisasContext.cc_op to CC_OP_EFLAGS
  31 * after generating a call to a helper that uses this.
  32 */
  33void cpu_load_eflags(CPUX86State *env, int eflags, int update_mask)
  34{
  35    CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
  36    CC_OP = CC_OP_EFLAGS;
  37    env->df = 1 - (2 * ((eflags >> 10) & 1));
  38    env->eflags = (env->eflags & ~update_mask) |
  39        (eflags & update_mask) | 0x2;
  40}
  41
  42void helper_outb(CPUX86State *env, uint32_t port, uint32_t data)
  43{
  44#ifdef CONFIG_USER_ONLY
  45    fprintf(stderr, "outb: port=0x%04x, data=%02x\n", port, data);
  46#else
  47    address_space_stb(&address_space_io, port, data,
  48                      cpu_get_mem_attrs(env), NULL);
  49#endif
  50}
  51
  52target_ulong helper_inb(CPUX86State *env, uint32_t port)
  53{
  54#ifdef CONFIG_USER_ONLY
  55    fprintf(stderr, "inb: port=0x%04x\n", port);
  56    return 0;
  57#else
  58    return address_space_ldub(&address_space_io, port,
  59                              cpu_get_mem_attrs(env), NULL);
  60#endif
  61}
  62
  63void helper_outw(CPUX86State *env, uint32_t port, uint32_t data)
  64{
  65#ifdef CONFIG_USER_ONLY
  66    fprintf(stderr, "outw: port=0x%04x, data=%04x\n", port, data);
  67#else
  68    address_space_stw(&address_space_io, port, data,
  69                      cpu_get_mem_attrs(env), NULL);
  70#endif
  71}
  72
  73target_ulong helper_inw(CPUX86State *env, uint32_t port)
  74{
  75#ifdef CONFIG_USER_ONLY
  76    fprintf(stderr, "inw: port=0x%04x\n", port);
  77    return 0;
  78#else
  79    return address_space_lduw(&address_space_io, port,
  80                              cpu_get_mem_attrs(env), NULL);
  81#endif
  82}
  83
  84void helper_outl(CPUX86State *env, uint32_t port, uint32_t data)
  85{
  86#ifdef CONFIG_USER_ONLY
  87    fprintf(stderr, "outl: port=0x%04x, data=%08x\n", port, data);
  88#else
  89    address_space_stl(&address_space_io, port, data,
  90                      cpu_get_mem_attrs(env), NULL);
  91#endif
  92}
  93
  94target_ulong helper_inl(CPUX86State *env, uint32_t port)
  95{
  96#ifdef CONFIG_USER_ONLY
  97    fprintf(stderr, "inl: port=0x%04x\n", port);
  98    return 0;
  99#else
 100    return address_space_ldl(&address_space_io, port,
 101                             cpu_get_mem_attrs(env), NULL);
 102#endif
 103}
 104
 105void helper_into(CPUX86State *env, int next_eip_addend)
 106{
 107    int eflags;
 108
 109    eflags = cpu_cc_compute_all(env, CC_OP);
 110    if (eflags & CC_O) {
 111        raise_interrupt(env, EXCP04_INTO, 1, 0, next_eip_addend);
 112    }
 113}
 114
 115void helper_cpuid(CPUX86State *env)
 116{
 117    uint32_t eax, ebx, ecx, edx;
 118
 119    cpu_svm_check_intercept_param(env, SVM_EXIT_CPUID, 0, GETPC());
 120
 121    cpu_x86_cpuid(env, (uint32_t)env->regs[R_EAX], (uint32_t)env->regs[R_ECX],
 122                  &eax, &ebx, &ecx, &edx);
 123    env->regs[R_EAX] = eax;
 124    env->regs[R_EBX] = ebx;
 125    env->regs[R_ECX] = ecx;
 126    env->regs[R_EDX] = edx;
 127}
 128
 129#if defined(CONFIG_USER_ONLY)
 130target_ulong helper_read_crN(CPUX86State *env, int reg)
 131{
 132    return 0;
 133}
 134
 135void helper_write_crN(CPUX86State *env, int reg, target_ulong t0)
 136{
 137}
 138#else
 139target_ulong helper_read_crN(CPUX86State *env, int reg)
 140{
 141    target_ulong val;
 142
 143    cpu_svm_check_intercept_param(env, SVM_EXIT_READ_CR0 + reg, 0, GETPC());
 144    switch (reg) {
 145    default:
 146        val = env->cr[reg];
 147        break;
 148    case 8:
 149        if (!(env->hflags2 & HF2_VINTR_MASK)) {
 150            val = cpu_get_apic_tpr(env_archcpu(env)->apic_state);
 151        } else {
 152            val = env->v_tpr;
 153        }
 154        break;
 155    }
 156    return val;
 157}
 158
 159void helper_write_crN(CPUX86State *env, int reg, target_ulong t0)
 160{
 161    cpu_svm_check_intercept_param(env, SVM_EXIT_WRITE_CR0 + reg, 0, GETPC());
 162    switch (reg) {
 163    case 0:
 164        cpu_x86_update_cr0(env, t0);
 165        break;
 166    case 3:
 167        cpu_x86_update_cr3(env, t0);
 168        break;
 169    case 4:
 170        if (((t0 ^ env->cr[4]) & CR4_LA57_MASK) &&
 171            (env->hflags & HF_CS64_MASK)) {
 172             raise_exception_ra(env, EXCP0D_GPF, GETPC());
 173        }
 174        cpu_x86_update_cr4(env, t0);
 175        break;
 176    case 8:
 177        if (!(env->hflags2 & HF2_VINTR_MASK)) {
 178            qemu_mutex_lock_iothread();
 179            cpu_set_apic_tpr(env_archcpu(env)->apic_state, t0);
 180            qemu_mutex_unlock_iothread();
 181        }
 182        env->v_tpr = t0 & 0x0f;
 183        break;
 184    default:
 185        env->cr[reg] = t0;
 186        break;
 187    }
 188}
 189#endif
 190
 191void helper_lmsw(CPUX86State *env, target_ulong t0)
 192{
 193    /* only 4 lower bits of CR0 are modified. PE cannot be set to zero
 194       if already set to one. */
 195    t0 = (env->cr[0] & ~0xe) | (t0 & 0xf);
 196    helper_write_crN(env, 0, t0);
 197}
 198
 199void helper_invlpg(CPUX86State *env, target_ulong addr)
 200{
 201    X86CPU *cpu = env_archcpu(env);
 202
 203    cpu_svm_check_intercept_param(env, SVM_EXIT_INVLPG, 0, GETPC());
 204    tlb_flush_page(CPU(cpu), addr);
 205}
 206
 207void helper_rdtsc(CPUX86State *env)
 208{
 209    uint64_t val;
 210
 211    if ((env->cr[4] & CR4_TSD_MASK) && ((env->hflags & HF_CPL_MASK) != 0)) {
 212        raise_exception_ra(env, EXCP0D_GPF, GETPC());
 213    }
 214    cpu_svm_check_intercept_param(env, SVM_EXIT_RDTSC, 0, GETPC());
 215
 216    val = cpu_get_tsc(env) + env->tsc_offset;
 217    env->regs[R_EAX] = (uint32_t)(val);
 218    env->regs[R_EDX] = (uint32_t)(val >> 32);
 219}
 220
 221void helper_rdtscp(CPUX86State *env)
 222{
 223    helper_rdtsc(env);
 224    env->regs[R_ECX] = (uint32_t)(env->tsc_aux);
 225}
 226
 227void helper_rdpmc(CPUX86State *env)
 228{
 229    if (((env->cr[4] & CR4_PCE_MASK) == 0 ) &&
 230        ((env->hflags & HF_CPL_MASK) != 0)) {
 231        raise_exception_ra(env, EXCP0D_GPF, GETPC());
 232    }
 233    cpu_svm_check_intercept_param(env, SVM_EXIT_RDPMC, 0, GETPC());
 234
 235    /* currently unimplemented */
 236    qemu_log_mask(LOG_UNIMP, "x86: unimplemented rdpmc\n");
 237    raise_exception_err(env, EXCP06_ILLOP, 0);
 238}
 239
 240#if defined(CONFIG_USER_ONLY)
 241void helper_wrmsr(CPUX86State *env)
 242{
 243}
 244
 245void helper_rdmsr(CPUX86State *env)
 246{
 247}
 248#else
 249void helper_wrmsr(CPUX86State *env)
 250{
 251    uint64_t val;
 252    CPUState *cs = env_cpu(env);
 253
 254    cpu_svm_check_intercept_param(env, SVM_EXIT_MSR, 1, GETPC());
 255
 256    val = ((uint32_t)env->regs[R_EAX]) |
 257        ((uint64_t)((uint32_t)env->regs[R_EDX]) << 32);
 258
 259    switch ((uint32_t)env->regs[R_ECX]) {
 260    case MSR_IA32_SYSENTER_CS:
 261        env->sysenter_cs = val & 0xffff;
 262        break;
 263    case MSR_IA32_SYSENTER_ESP:
 264        env->sysenter_esp = val;
 265        break;
 266    case MSR_IA32_SYSENTER_EIP:
 267        env->sysenter_eip = val;
 268        break;
 269    case MSR_IA32_APICBASE:
 270        cpu_set_apic_base(env_archcpu(env)->apic_state, val);
 271        break;
 272    case MSR_EFER:
 273        {
 274            uint64_t update_mask;
 275
 276            update_mask = 0;
 277            if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_SYSCALL) {
 278                update_mask |= MSR_EFER_SCE;
 279            }
 280            if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM) {
 281                update_mask |= MSR_EFER_LME;
 282            }
 283            if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_FFXSR) {
 284                update_mask |= MSR_EFER_FFXSR;
 285            }
 286            if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_NX) {
 287                update_mask |= MSR_EFER_NXE;
 288            }
 289            if (env->features[FEAT_8000_0001_ECX] & CPUID_EXT3_SVM) {
 290                update_mask |= MSR_EFER_SVME;
 291            }
 292            if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_FFXSR) {
 293                update_mask |= MSR_EFER_FFXSR;
 294            }
 295            cpu_load_efer(env, (env->efer & ~update_mask) |
 296                          (val & update_mask));
 297        }
 298        break;
 299    case MSR_STAR:
 300        env->star = val;
 301        break;
 302    case MSR_PAT:
 303        env->pat = val;
 304        break;
 305    case MSR_IA32_PKRS:
 306        if (val & 0xFFFFFFFF00000000ull) {
 307            goto error;
 308        }
 309        env->pkrs = val;
 310        tlb_flush(cs);
 311        break;
 312    case MSR_VM_HSAVE_PA:
 313        env->vm_hsave = val;
 314        break;
 315#ifdef TARGET_X86_64
 316    case MSR_LSTAR:
 317        env->lstar = val;
 318        break;
 319    case MSR_CSTAR:
 320        env->cstar = val;
 321        break;
 322    case MSR_FMASK:
 323        env->fmask = val;
 324        break;
 325    case MSR_FSBASE:
 326        env->segs[R_FS].base = val;
 327        break;
 328    case MSR_GSBASE:
 329        env->segs[R_GS].base = val;
 330        break;
 331    case MSR_KERNELGSBASE:
 332        env->kernelgsbase = val;
 333        break;
 334#endif
 335    case MSR_MTRRphysBase(0):
 336    case MSR_MTRRphysBase(1):
 337    case MSR_MTRRphysBase(2):
 338    case MSR_MTRRphysBase(3):
 339    case MSR_MTRRphysBase(4):
 340    case MSR_MTRRphysBase(5):
 341    case MSR_MTRRphysBase(6):
 342    case MSR_MTRRphysBase(7):
 343        env->mtrr_var[((uint32_t)env->regs[R_ECX] -
 344                       MSR_MTRRphysBase(0)) / 2].base = val;
 345        break;
 346    case MSR_MTRRphysMask(0):
 347    case MSR_MTRRphysMask(1):
 348    case MSR_MTRRphysMask(2):
 349    case MSR_MTRRphysMask(3):
 350    case MSR_MTRRphysMask(4):
 351    case MSR_MTRRphysMask(5):
 352    case MSR_MTRRphysMask(6):
 353    case MSR_MTRRphysMask(7):
 354        env->mtrr_var[((uint32_t)env->regs[R_ECX] -
 355                       MSR_MTRRphysMask(0)) / 2].mask = val;
 356        break;
 357    case MSR_MTRRfix64K_00000:
 358        env->mtrr_fixed[(uint32_t)env->regs[R_ECX] -
 359                        MSR_MTRRfix64K_00000] = val;
 360        break;
 361    case MSR_MTRRfix16K_80000:
 362    case MSR_MTRRfix16K_A0000:
 363        env->mtrr_fixed[(uint32_t)env->regs[R_ECX] -
 364                        MSR_MTRRfix16K_80000 + 1] = val;
 365        break;
 366    case MSR_MTRRfix4K_C0000:
 367    case MSR_MTRRfix4K_C8000:
 368    case MSR_MTRRfix4K_D0000:
 369    case MSR_MTRRfix4K_D8000:
 370    case MSR_MTRRfix4K_E0000:
 371    case MSR_MTRRfix4K_E8000:
 372    case MSR_MTRRfix4K_F0000:
 373    case MSR_MTRRfix4K_F8000:
 374        env->mtrr_fixed[(uint32_t)env->regs[R_ECX] -
 375                        MSR_MTRRfix4K_C0000 + 3] = val;
 376        break;
 377    case MSR_MTRRdefType:
 378        env->mtrr_deftype = val;
 379        break;
 380    case MSR_MCG_STATUS:
 381        env->mcg_status = val;
 382        break;
 383    case MSR_MCG_CTL:
 384        if ((env->mcg_cap & MCG_CTL_P)
 385            && (val == 0 || val == ~(uint64_t)0)) {
 386            env->mcg_ctl = val;
 387        }
 388        break;
 389    case MSR_TSC_AUX:
 390        env->tsc_aux = val;
 391        break;
 392    case MSR_IA32_MISC_ENABLE:
 393        env->msr_ia32_misc_enable = val;
 394        break;
 395    case MSR_IA32_BNDCFGS:
 396        /* FIXME: #GP if reserved bits are set.  */
 397        /* FIXME: Extend highest implemented bit of linear address.  */
 398        env->msr_bndcfgs = val;
 399        cpu_sync_bndcs_hflags(env);
 400        break;
 401    default:
 402        if ((uint32_t)env->regs[R_ECX] >= MSR_MC0_CTL
 403            && (uint32_t)env->regs[R_ECX] < MSR_MC0_CTL +
 404            (4 * env->mcg_cap & 0xff)) {
 405            uint32_t offset = (uint32_t)env->regs[R_ECX] - MSR_MC0_CTL;
 406            if ((offset & 0x3) != 0
 407                || (val == 0 || val == ~(uint64_t)0)) {
 408                env->mce_banks[offset] = val;
 409            }
 410            break;
 411        }
 412        /* XXX: exception? */
 413        break;
 414    }
 415    return;
 416error:
 417    raise_exception_err_ra(env, EXCP0D_GPF, 0, GETPC());
 418}
 419
 420void helper_rdmsr(CPUX86State *env)
 421{
 422    X86CPU *x86_cpu = env_archcpu(env);
 423    uint64_t val;
 424
 425    cpu_svm_check_intercept_param(env, SVM_EXIT_MSR, 0, GETPC());
 426
 427    switch ((uint32_t)env->regs[R_ECX]) {
 428    case MSR_IA32_SYSENTER_CS:
 429        val = env->sysenter_cs;
 430        break;
 431    case MSR_IA32_SYSENTER_ESP:
 432        val = env->sysenter_esp;
 433        break;
 434    case MSR_IA32_SYSENTER_EIP:
 435        val = env->sysenter_eip;
 436        break;
 437    case MSR_IA32_APICBASE:
 438        val = cpu_get_apic_base(env_archcpu(env)->apic_state);
 439        break;
 440    case MSR_EFER:
 441        val = env->efer;
 442        break;
 443    case MSR_STAR:
 444        val = env->star;
 445        break;
 446    case MSR_PAT:
 447        val = env->pat;
 448        break;
 449    case MSR_IA32_PKRS:
 450        val = env->pkrs;
 451        break;
 452    case MSR_VM_HSAVE_PA:
 453        val = env->vm_hsave;
 454        break;
 455    case MSR_IA32_PERF_STATUS:
 456        /* tsc_increment_by_tick */
 457        val = 1000ULL;
 458        /* CPU multiplier */
 459        val |= (((uint64_t)4ULL) << 40);
 460        break;
 461#ifdef TARGET_X86_64
 462    case MSR_LSTAR:
 463        val = env->lstar;
 464        break;
 465    case MSR_CSTAR:
 466        val = env->cstar;
 467        break;
 468    case MSR_FMASK:
 469        val = env->fmask;
 470        break;
 471    case MSR_FSBASE:
 472        val = env->segs[R_FS].base;
 473        break;
 474    case MSR_GSBASE:
 475        val = env->segs[R_GS].base;
 476        break;
 477    case MSR_KERNELGSBASE:
 478        val = env->kernelgsbase;
 479        break;
 480    case MSR_TSC_AUX:
 481        val = env->tsc_aux;
 482        break;
 483#endif
 484    case MSR_SMI_COUNT:
 485        val = env->msr_smi_count;
 486        break;
 487    case MSR_MTRRphysBase(0):
 488    case MSR_MTRRphysBase(1):
 489    case MSR_MTRRphysBase(2):
 490    case MSR_MTRRphysBase(3):
 491    case MSR_MTRRphysBase(4):
 492    case MSR_MTRRphysBase(5):
 493    case MSR_MTRRphysBase(6):
 494    case MSR_MTRRphysBase(7):
 495        val = env->mtrr_var[((uint32_t)env->regs[R_ECX] -
 496                             MSR_MTRRphysBase(0)) / 2].base;
 497        break;
 498    case MSR_MTRRphysMask(0):
 499    case MSR_MTRRphysMask(1):
 500    case MSR_MTRRphysMask(2):
 501    case MSR_MTRRphysMask(3):
 502    case MSR_MTRRphysMask(4):
 503    case MSR_MTRRphysMask(5):
 504    case MSR_MTRRphysMask(6):
 505    case MSR_MTRRphysMask(7):
 506        val = env->mtrr_var[((uint32_t)env->regs[R_ECX] -
 507                             MSR_MTRRphysMask(0)) / 2].mask;
 508        break;
 509    case MSR_MTRRfix64K_00000:
 510        val = env->mtrr_fixed[0];
 511        break;
 512    case MSR_MTRRfix16K_80000:
 513    case MSR_MTRRfix16K_A0000:
 514        val = env->mtrr_fixed[(uint32_t)env->regs[R_ECX] -
 515                              MSR_MTRRfix16K_80000 + 1];
 516        break;
 517    case MSR_MTRRfix4K_C0000:
 518    case MSR_MTRRfix4K_C8000:
 519    case MSR_MTRRfix4K_D0000:
 520    case MSR_MTRRfix4K_D8000:
 521    case MSR_MTRRfix4K_E0000:
 522    case MSR_MTRRfix4K_E8000:
 523    case MSR_MTRRfix4K_F0000:
 524    case MSR_MTRRfix4K_F8000:
 525        val = env->mtrr_fixed[(uint32_t)env->regs[R_ECX] -
 526                              MSR_MTRRfix4K_C0000 + 3];
 527        break;
 528    case MSR_MTRRdefType:
 529        val = env->mtrr_deftype;
 530        break;
 531    case MSR_MTRRcap:
 532        if (env->features[FEAT_1_EDX] & CPUID_MTRR) {
 533            val = MSR_MTRRcap_VCNT | MSR_MTRRcap_FIXRANGE_SUPPORT |
 534                MSR_MTRRcap_WC_SUPPORTED;
 535        } else {
 536            /* XXX: exception? */
 537            val = 0;
 538        }
 539        break;
 540    case MSR_MCG_CAP:
 541        val = env->mcg_cap;
 542        break;
 543    case MSR_MCG_CTL:
 544        if (env->mcg_cap & MCG_CTL_P) {
 545            val = env->mcg_ctl;
 546        } else {
 547            val = 0;
 548        }
 549        break;
 550    case MSR_MCG_STATUS:
 551        val = env->mcg_status;
 552        break;
 553    case MSR_IA32_MISC_ENABLE:
 554        val = env->msr_ia32_misc_enable;
 555        break;
 556    case MSR_IA32_BNDCFGS:
 557        val = env->msr_bndcfgs;
 558        break;
 559     case MSR_IA32_UCODE_REV:
 560        val = x86_cpu->ucode_rev;
 561        break;
 562    default:
 563        if ((uint32_t)env->regs[R_ECX] >= MSR_MC0_CTL
 564            && (uint32_t)env->regs[R_ECX] < MSR_MC0_CTL +
 565            (4 * env->mcg_cap & 0xff)) {
 566            uint32_t offset = (uint32_t)env->regs[R_ECX] - MSR_MC0_CTL;
 567            val = env->mce_banks[offset];
 568            break;
 569        }
 570        /* XXX: exception? */
 571        val = 0;
 572        break;
 573    }
 574    env->regs[R_EAX] = (uint32_t)(val);
 575    env->regs[R_EDX] = (uint32_t)(val >> 32);
 576}
 577#endif
 578
 579static void do_pause(X86CPU *cpu)
 580{
 581    CPUState *cs = CPU(cpu);
 582
 583    /* Just let another CPU run.  */
 584    cs->exception_index = EXCP_INTERRUPT;
 585    cpu_loop_exit(cs);
 586}
 587
 588static void do_hlt(X86CPU *cpu)
 589{
 590    CPUState *cs = CPU(cpu);
 591    CPUX86State *env = &cpu->env;
 592
 593    env->hflags &= ~HF_INHIBIT_IRQ_MASK; /* needed if sti is just before */
 594    cs->halted = 1;
 595    cs->exception_index = EXCP_HLT;
 596    cpu_loop_exit(cs);
 597}
 598
 599void helper_hlt(CPUX86State *env, int next_eip_addend)
 600{
 601    X86CPU *cpu = env_archcpu(env);
 602
 603    cpu_svm_check_intercept_param(env, SVM_EXIT_HLT, 0, GETPC());
 604    env->eip += next_eip_addend;
 605
 606    do_hlt(cpu);
 607}
 608
 609void helper_monitor(CPUX86State *env, target_ulong ptr)
 610{
 611    if ((uint32_t)env->regs[R_ECX] != 0) {
 612        raise_exception_ra(env, EXCP0D_GPF, GETPC());
 613    }
 614    /* XXX: store address? */
 615    cpu_svm_check_intercept_param(env, SVM_EXIT_MONITOR, 0, GETPC());
 616}
 617
 618void helper_mwait(CPUX86State *env, int next_eip_addend)
 619{
 620    CPUState *cs = env_cpu(env);
 621    X86CPU *cpu = env_archcpu(env);
 622
 623    if ((uint32_t)env->regs[R_ECX] != 0) {
 624        raise_exception_ra(env, EXCP0D_GPF, GETPC());
 625    }
 626    cpu_svm_check_intercept_param(env, SVM_EXIT_MWAIT, 0, GETPC());
 627    env->eip += next_eip_addend;
 628
 629    /* XXX: not complete but not completely erroneous */
 630    if (cs->cpu_index != 0 || CPU_NEXT(cs) != NULL) {
 631        do_pause(cpu);
 632    } else {
 633        do_hlt(cpu);
 634    }
 635}
 636
 637void helper_pause(CPUX86State *env, int next_eip_addend)
 638{
 639    X86CPU *cpu = env_archcpu(env);
 640
 641    cpu_svm_check_intercept_param(env, SVM_EXIT_PAUSE, 0, GETPC());
 642    env->eip += next_eip_addend;
 643
 644    do_pause(cpu);
 645}
 646
 647void helper_debug(CPUX86State *env)
 648{
 649    CPUState *cs = env_cpu(env);
 650
 651    cs->exception_index = EXCP_DEBUG;
 652    cpu_loop_exit(cs);
 653}
 654
 655uint64_t helper_rdpkru(CPUX86State *env, uint32_t ecx)
 656{
 657    if ((env->cr[4] & CR4_PKE_MASK) == 0) {
 658        raise_exception_err_ra(env, EXCP06_ILLOP, 0, GETPC());
 659    }
 660    if (ecx != 0) {
 661        raise_exception_err_ra(env, EXCP0D_GPF, 0, GETPC());
 662    }
 663
 664    return env->pkru;
 665}
 666
 667void helper_wrpkru(CPUX86State *env, uint32_t ecx, uint64_t val)
 668{
 669    CPUState *cs = env_cpu(env);
 670
 671    if ((env->cr[4] & CR4_PKE_MASK) == 0) {
 672        raise_exception_err_ra(env, EXCP06_ILLOP, 0, GETPC());
 673    }
 674    if (ecx != 0 || (val & 0xFFFFFFFF00000000ull)) {
 675        raise_exception_err_ra(env, EXCP0D_GPF, 0, GETPC());
 676    }
 677
 678    env->pkru = val;
 679    tlb_flush(cs);
 680}
 681