void helper_rdmsr(void)

{

    uint64_t val;



    helper_svm_check_intercept_param(SVM_EXIT_MSR, 0);



    switch((uint32_t)ECX) {

    case MSR_IA32_SYSENTER_CS:

        val = env->sysenter_cs;

        break;

    case MSR_IA32_SYSENTER_ESP:

        val = env->sysenter_esp;

        break;

    case MSR_IA32_SYSENTER_EIP:

        val = env->sysenter_eip;

        break;

    case MSR_IA32_APICBASE:

        val = cpu_get_apic_base(env);

        break;

    case MSR_EFER:

        val = env->efer;

        break;

    case MSR_STAR:

        val = env->star;

        break;

    case MSR_PAT:

        val = env->pat;

        break;

    case MSR_VM_HSAVE_PA:

        val = env->vm_hsave;

        break;

    case MSR_IA32_PERF_STATUS:

        /* tsc_increment_by_tick */

        val = 1000ULL;

        /* CPU multiplier */

        val |= (((uint64_t)4ULL) << 40);

        break;

#ifdef TARGET_X86_64

    case MSR_LSTAR:

        val = env->lstar;

        break;

    case MSR_CSTAR:

        val = env->cstar;

        break;

    case MSR_FMASK:

        val = env->fmask;

        break;

    case MSR_FSBASE:

        val = env->segs[R_FS].base;

        break;

    case MSR_GSBASE:

        val = env->segs[R_GS].base;

        break;

    case MSR_KERNELGSBASE:

        val = env->kernelgsbase;

        break;

#endif

#ifdef CONFIG_KQEMU

    case MSR_QPI_COMMBASE:

        if (env->kqemu_enabled) {

            val = kqemu_comm_base;

        } else {

            val = 0;

        }

        break;

#endif

    case MSR_MTRRphysBase(0):

    case MSR_MTRRphysBase(1):

    case MSR_MTRRphysBase(2):

    case MSR_MTRRphysBase(3):

    case MSR_MTRRphysBase(4):

    case MSR_MTRRphysBase(5):

    case MSR_MTRRphysBase(6):

    case MSR_MTRRphysBase(7):

        val = env->mtrr_var[((uint32_t)ECX - MSR_MTRRphysBase(0)) / 2].base;

        break;

    case MSR_MTRRphysMask(0):

    case MSR_MTRRphysMask(1):

    case MSR_MTRRphysMask(2):

    case MSR_MTRRphysMask(3):

    case MSR_MTRRphysMask(4):

    case MSR_MTRRphysMask(5):

    case MSR_MTRRphysMask(6):

    case MSR_MTRRphysMask(7):

        val = env->mtrr_var[((uint32_t)ECX - MSR_MTRRphysMask(0)) / 2].mask;

        break;

    case MSR_MTRRfix64K_00000:

        val = env->mtrr_fixed[0];

        break;

    case MSR_MTRRfix16K_80000:

    case MSR_MTRRfix16K_A0000:

        val = env->mtrr_fixed[(uint32_t)ECX - MSR_MTRRfix16K_80000 + 1];

        break;

    case MSR_MTRRfix4K_C0000:

    case MSR_MTRRfix4K_C8000:

    case MSR_MTRRfix4K_D0000:

    case MSR_MTRRfix4K_D8000:

    case MSR_MTRRfix4K_E0000:

    case MSR_MTRRfix4K_E8000:

    case MSR_MTRRfix4K_F0000:

    case MSR_MTRRfix4K_F8000:

        val = env->mtrr_fixed[(uint32_t)ECX - MSR_MTRRfix4K_C0000 + 3];

        break;

    case MSR_MTRRdefType:

        val = env->mtrr_deftype;

        break;

    case MSR_MTRRcap:

        if (env->cpuid_features & CPUID_MTRR)

            val = MSR_MTRRcap_VCNT | MSR_MTRRcap_FIXRANGE_SUPPORT | MSR_MTRRcap_WC_SUPPORTED;

        else

            /* XXX: exception ? */

            val = 0;

        break;

    case MSR_MCG_CAP:

        val = env->mcg_cap;

        break;

    case MSR_MCG_CTL:

        if (env->mcg_cap & MCG_CTL_P)

            val = env->mcg_ctl;

        else

            val = 0;

        break;

    case MSR_MCG_STATUS:

        val = env->mcg_status;

        break;

    default:

        if ((uint32_t)ECX >= MSR_MC0_CTL

            && (uint32_t)ECX < MSR_MC0_CTL + (4 * env->mcg_cap & 0xff)) {

            uint32_t offset = (uint32_t)ECX - MSR_MC0_CTL;

            val = env->mce_banks[offset];

            break;

        }

        /* XXX: exception ? */

        val = 0;

        break;

    }

    EAX = (uint32_t)(val);

    EDX = (uint32_t)(val >> 32);

}
