static bool has_msr_hv_hypercall;
static bool has_msr_hv_vapic;
static bool has_msr_hv_tsc;
+static bool has_msr_mtrr;
+static bool has_msr_xss;
static bool has_msr_architectural_pmu;
static uint32_t num_architectural_pmu_counters;
int r, size;
size = sizeof(*cpuid) + max * sizeof(*cpuid->entries);
- cpuid = (struct kvm_cpuid2 *)g_malloc0(size);
+ cpuid = g_malloc0(size);
cpuid->nent = max;
r = kvm_ioctl(s, KVM_GET_SUPPORTED_CPUID, cpuid);
if (r == 0 && cpuid->nent >= max) {
return;
}
}
- page = g_malloc(sizeof(HWPoisonPage));
+ page = g_new(HWPoisonPage, 1);
page->ram_addr = ram_addr;
QLIST_INSERT_HEAD(&hwpoison_page_list, page, list);
}
env->kvm_xsave_buf = qemu_memalign(4096, sizeof(struct kvm_xsave));
}
+ if (env->features[FEAT_1_EDX] & CPUID_MTRR) {
+ has_msr_mtrr = true;
+ }
+
return 0;
}
has_msr_bndcfgs = true;
continue;
}
+ if (kvm_msr_list->indices[i] == MSR_IA32_XSS) {
+ has_msr_xss = true;
+ continue;
+ }
}
}
fpu.ftwx |= (!env->fptags[i]) << i;
}
memcpy(fpu.fpr, env->fpregs, sizeof env->fpregs);
- memcpy(fpu.xmm, env->xmm_regs, sizeof env->xmm_regs);
+ for (i = 0; i < CPU_NB_REGS; i++) {
+ stq_p(&fpu.xmm[i][0], env->xmm_regs[i].XMM_Q(0));
+ stq_p(&fpu.xmm[i][8], env->xmm_regs[i].XMM_Q(1));
+ }
fpu.mxcsr = env->mxcsr;
return kvm_vcpu_ioctl(CPU(cpu), KVM_SET_FPU, &fpu);
#define XSAVE_YMMH_SPACE 144
#define XSAVE_BNDREGS 240
#define XSAVE_BNDCSR 256
+#define XSAVE_OPMASK 272
+#define XSAVE_ZMM_Hi256 288
+#define XSAVE_Hi16_ZMM 416
static int kvm_put_xsave(X86CPU *cpu)
{
CPUX86State *env = &cpu->env;
struct kvm_xsave* xsave = env->kvm_xsave_buf;
uint16_t cwd, swd, twd;
+ uint8_t *xmm, *ymmh, *zmmh;
int i, r;
if (!kvm_has_xsave()) {
memcpy(&xsave->region[XSAVE_CWD_RDP], &env->fpdp, sizeof(env->fpdp));
memcpy(&xsave->region[XSAVE_ST_SPACE], env->fpregs,
sizeof env->fpregs);
- memcpy(&xsave->region[XSAVE_XMM_SPACE], env->xmm_regs,
- sizeof env->xmm_regs);
xsave->region[XSAVE_MXCSR] = env->mxcsr;
*(uint64_t *)&xsave->region[XSAVE_XSTATE_BV] = env->xstate_bv;
- memcpy(&xsave->region[XSAVE_YMMH_SPACE], env->ymmh_regs,
- sizeof env->ymmh_regs);
memcpy(&xsave->region[XSAVE_BNDREGS], env->bnd_regs,
sizeof env->bnd_regs);
memcpy(&xsave->region[XSAVE_BNDCSR], &env->bndcs_regs,
sizeof(env->bndcs_regs));
+ memcpy(&xsave->region[XSAVE_OPMASK], env->opmask_regs,
+ sizeof env->opmask_regs);
+
+ xmm = (uint8_t *)&xsave->region[XSAVE_XMM_SPACE];
+ ymmh = (uint8_t *)&xsave->region[XSAVE_YMMH_SPACE];
+ zmmh = (uint8_t *)&xsave->region[XSAVE_ZMM_Hi256];
+ for (i = 0; i < CPU_NB_REGS; i++, xmm += 16, ymmh += 16, zmmh += 32) {
+ stq_p(xmm, env->xmm_regs[i].XMM_Q(0));
+ stq_p(xmm+8, env->xmm_regs[i].XMM_Q(1));
+ stq_p(ymmh, env->xmm_regs[i].XMM_Q(2));
+ stq_p(ymmh+8, env->xmm_regs[i].XMM_Q(3));
+ stq_p(zmmh, env->xmm_regs[i].XMM_Q(4));
+ stq_p(zmmh+8, env->xmm_regs[i].XMM_Q(5));
+ stq_p(zmmh+16, env->xmm_regs[i].XMM_Q(6));
+ stq_p(zmmh+24, env->xmm_regs[i].XMM_Q(7));
+ }
+
+#ifdef TARGET_X86_64
+ memcpy(&xsave->region[XSAVE_Hi16_ZMM], &env->xmm_regs[16],
+ 16 * sizeof env->xmm_regs[16]);
+#endif
r = kvm_vcpu_ioctl(CPU(cpu), KVM_SET_XSAVE, xsave);
return r;
}
static int kvm_put_xcrs(X86CPU *cpu)
{
CPUX86State *env = &cpu->env;
- struct kvm_xcrs xcrs;
+ struct kvm_xcrs xcrs = {};
if (!kvm_has_xcrs()) {
return 0;
uint32_t index, uint64_t value)
{
entry->index = index;
+ entry->reserved = 0;
entry->data = value;
}
kvm_msr_entry_set(&msrs[0], MSR_IA32_TSCDEADLINE, env->tsc_deadline);
- msr_data.info.nmsrs = 1;
+ msr_data.info = (struct kvm_msrs) {
+ .nmsrs = 1,
+ };
return kvm_vcpu_ioctl(CPU(cpu), KVM_SET_MSRS, &msr_data);
}
kvm_msr_entry_set(&msr_data.entry, MSR_IA32_FEATURE_CONTROL,
cpu->env.msr_ia32_feature_control);
- msr_data.info.nmsrs = 1;
+
+ msr_data.info = (struct kvm_msrs) {
+ .nmsrs = 1,
+ };
+
return kvm_vcpu_ioctl(CPU(cpu), KVM_SET_MSRS, &msr_data);
}
CPUX86State *env = &cpu->env;
struct {
struct kvm_msrs info;
- struct kvm_msr_entry entries[100];
+ struct kvm_msr_entry entries[150];
} msr_data;
struct kvm_msr_entry *msrs = msr_data.entries;
int n = 0, i;
if (has_msr_bndcfgs) {
kvm_msr_entry_set(&msrs[n++], MSR_IA32_BNDCFGS, env->msr_bndcfgs);
}
+ if (has_msr_xss) {
+ kvm_msr_entry_set(&msrs[n++], MSR_IA32_XSS, env->xss);
+ }
#ifdef TARGET_X86_64
if (lm_capable_kernel) {
kvm_msr_entry_set(&msrs[n++], MSR_CSTAR, env->cstar);
kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_REFERENCE_TSC,
env->msr_hv_tsc);
}
+ if (has_msr_mtrr) {
+ kvm_msr_entry_set(&msrs[n++], MSR_MTRRdefType, env->mtrr_deftype);
+ kvm_msr_entry_set(&msrs[n++],
+ MSR_MTRRfix64K_00000, env->mtrr_fixed[0]);
+ kvm_msr_entry_set(&msrs[n++],
+ MSR_MTRRfix16K_80000, env->mtrr_fixed[1]);
+ kvm_msr_entry_set(&msrs[n++],
+ MSR_MTRRfix16K_A0000, env->mtrr_fixed[2]);
+ kvm_msr_entry_set(&msrs[n++],
+ MSR_MTRRfix4K_C0000, env->mtrr_fixed[3]);
+ kvm_msr_entry_set(&msrs[n++],
+ MSR_MTRRfix4K_C8000, env->mtrr_fixed[4]);
+ kvm_msr_entry_set(&msrs[n++],
+ MSR_MTRRfix4K_D0000, env->mtrr_fixed[5]);
+ kvm_msr_entry_set(&msrs[n++],
+ MSR_MTRRfix4K_D8000, env->mtrr_fixed[6]);
+ kvm_msr_entry_set(&msrs[n++],
+ MSR_MTRRfix4K_E0000, env->mtrr_fixed[7]);
+ kvm_msr_entry_set(&msrs[n++],
+ MSR_MTRRfix4K_E8000, env->mtrr_fixed[8]);
+ kvm_msr_entry_set(&msrs[n++],
+ MSR_MTRRfix4K_F0000, env->mtrr_fixed[9]);
+ kvm_msr_entry_set(&msrs[n++],
+ MSR_MTRRfix4K_F8000, env->mtrr_fixed[10]);
+ for (i = 0; i < MSR_MTRRcap_VCNT; i++) {
+ kvm_msr_entry_set(&msrs[n++],
+ MSR_MTRRphysBase(i), env->mtrr_var[i].base);
+ kvm_msr_entry_set(&msrs[n++],
+ MSR_MTRRphysMask(i), env->mtrr_var[i].mask);
+ }
+ }
/* Note: MSR_IA32_FEATURE_CONTROL is written separately, see
* kvm_put_msr_feature_control. */
}
}
- msr_data.info.nmsrs = n;
+ msr_data.info = (struct kvm_msrs) {
+ .nmsrs = n,
+ };
return kvm_vcpu_ioctl(CPU(cpu), KVM_SET_MSRS, &msr_data);
env->fptags[i] = !((fpu.ftwx >> i) & 1);
}
memcpy(env->fpregs, fpu.fpr, sizeof env->fpregs);
- memcpy(env->xmm_regs, fpu.xmm, sizeof env->xmm_regs);
+ for (i = 0; i < CPU_NB_REGS; i++) {
+ env->xmm_regs[i].XMM_Q(0) = ldq_p(&fpu.xmm[i][0]);
+ env->xmm_regs[i].XMM_Q(1) = ldq_p(&fpu.xmm[i][8]);
+ }
env->mxcsr = fpu.mxcsr;
return 0;
CPUX86State *env = &cpu->env;
struct kvm_xsave* xsave = env->kvm_xsave_buf;
int ret, i;
+ const uint8_t *xmm, *ymmh, *zmmh;
uint16_t cwd, swd, twd;
if (!kvm_has_xsave()) {
env->mxcsr = xsave->region[XSAVE_MXCSR];
memcpy(env->fpregs, &xsave->region[XSAVE_ST_SPACE],
sizeof env->fpregs);
- memcpy(env->xmm_regs, &xsave->region[XSAVE_XMM_SPACE],
- sizeof env->xmm_regs);
env->xstate_bv = *(uint64_t *)&xsave->region[XSAVE_XSTATE_BV];
- memcpy(env->ymmh_regs, &xsave->region[XSAVE_YMMH_SPACE],
- sizeof env->ymmh_regs);
memcpy(env->bnd_regs, &xsave->region[XSAVE_BNDREGS],
sizeof env->bnd_regs);
memcpy(&env->bndcs_regs, &xsave->region[XSAVE_BNDCSR],
sizeof(env->bndcs_regs));
+ memcpy(env->opmask_regs, &xsave->region[XSAVE_OPMASK],
+ sizeof env->opmask_regs);
+
+ xmm = (const uint8_t *)&xsave->region[XSAVE_XMM_SPACE];
+ ymmh = (const uint8_t *)&xsave->region[XSAVE_YMMH_SPACE];
+ zmmh = (const uint8_t *)&xsave->region[XSAVE_ZMM_Hi256];
+ for (i = 0; i < CPU_NB_REGS; i++, xmm += 16, ymmh += 16, zmmh += 32) {
+ env->xmm_regs[i].XMM_Q(0) = ldq_p(xmm);
+ env->xmm_regs[i].XMM_Q(1) = ldq_p(xmm+8);
+ env->xmm_regs[i].XMM_Q(2) = ldq_p(ymmh);
+ env->xmm_regs[i].XMM_Q(3) = ldq_p(ymmh+8);
+ env->xmm_regs[i].XMM_Q(4) = ldq_p(zmmh);
+ env->xmm_regs[i].XMM_Q(5) = ldq_p(zmmh+8);
+ env->xmm_regs[i].XMM_Q(6) = ldq_p(zmmh+16);
+ env->xmm_regs[i].XMM_Q(7) = ldq_p(zmmh+24);
+ }
+
+#ifdef TARGET_X86_64
+ memcpy(&env->xmm_regs[16], &xsave->region[XSAVE_Hi16_ZMM],
+ 16 * sizeof env->xmm_regs[16]);
+#endif
return 0;
}
CPUX86State *env = &cpu->env;
struct {
struct kvm_msrs info;
- struct kvm_msr_entry entries[100];
+ struct kvm_msr_entry entries[150];
} msr_data;
struct kvm_msr_entry *msrs = msr_data.entries;
int ret, i, n;
if (has_msr_bndcfgs) {
msrs[n++].index = MSR_IA32_BNDCFGS;
}
+ if (has_msr_xss) {
+ msrs[n++].index = MSR_IA32_XSS;
+ }
+
if (!env->tsc_valid) {
msrs[n++].index = MSR_IA32_TSC;
if (has_msr_hv_tsc) {
msrs[n++].index = HV_X64_MSR_REFERENCE_TSC;
}
+ if (has_msr_mtrr) {
+ msrs[n++].index = MSR_MTRRdefType;
+ msrs[n++].index = MSR_MTRRfix64K_00000;
+ msrs[n++].index = MSR_MTRRfix16K_80000;
+ msrs[n++].index = MSR_MTRRfix16K_A0000;
+ msrs[n++].index = MSR_MTRRfix4K_C0000;
+ msrs[n++].index = MSR_MTRRfix4K_C8000;
+ msrs[n++].index = MSR_MTRRfix4K_D0000;
+ msrs[n++].index = MSR_MTRRfix4K_D8000;
+ msrs[n++].index = MSR_MTRRfix4K_E0000;
+ msrs[n++].index = MSR_MTRRfix4K_E8000;
+ msrs[n++].index = MSR_MTRRfix4K_F0000;
+ msrs[n++].index = MSR_MTRRfix4K_F8000;
+ for (i = 0; i < MSR_MTRRcap_VCNT; i++) {
+ msrs[n++].index = MSR_MTRRphysBase(i);
+ msrs[n++].index = MSR_MTRRphysMask(i);
+ }
+ }
+
+ msr_data.info = (struct kvm_msrs) {
+ .nmsrs = n,
+ };
- msr_data.info.nmsrs = n;
ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_MSRS, &msr_data);
if (ret < 0) {
return ret;
case MSR_IA32_BNDCFGS:
env->msr_bndcfgs = msrs[i].data;
break;
+ case MSR_IA32_XSS:
+ env->xss = msrs[i].data;
+ break;
default:
if (msrs[i].index >= MSR_MC0_CTL &&
msrs[i].index < MSR_MC0_CTL + (env->mcg_cap & 0xff) * 4) {
case HV_X64_MSR_REFERENCE_TSC:
env->msr_hv_tsc = msrs[i].data;
break;
+ case MSR_MTRRdefType:
+ env->mtrr_deftype = msrs[i].data;
+ break;
+ case MSR_MTRRfix64K_00000:
+ env->mtrr_fixed[0] = msrs[i].data;
+ break;
+ case MSR_MTRRfix16K_80000:
+ env->mtrr_fixed[1] = msrs[i].data;
+ break;
+ case MSR_MTRRfix16K_A0000:
+ env->mtrr_fixed[2] = msrs[i].data;
+ break;
+ case MSR_MTRRfix4K_C0000:
+ env->mtrr_fixed[3] = msrs[i].data;
+ break;
+ case MSR_MTRRfix4K_C8000:
+ env->mtrr_fixed[4] = msrs[i].data;
+ break;
+ case MSR_MTRRfix4K_D0000:
+ env->mtrr_fixed[5] = msrs[i].data;
+ break;
+ case MSR_MTRRfix4K_D8000:
+ env->mtrr_fixed[6] = msrs[i].data;
+ break;
+ case MSR_MTRRfix4K_E0000:
+ env->mtrr_fixed[7] = msrs[i].data;
+ break;
+ case MSR_MTRRfix4K_E8000:
+ env->mtrr_fixed[8] = msrs[i].data;
+ break;
+ case MSR_MTRRfix4K_F0000:
+ env->mtrr_fixed[9] = msrs[i].data;
+ break;
+ case MSR_MTRRfix4K_F8000:
+ env->mtrr_fixed[10] = msrs[i].data;
+ break;
+ case MSR_MTRRphysBase(0) ... MSR_MTRRphysMask(MSR_MTRRcap_VCNT - 1):
+ if (index & 1) {
+ env->mtrr_var[MSR_MTRRphysIndex(index)].mask = msrs[i].data;
+ } else {
+ env->mtrr_var[MSR_MTRRphysIndex(index)].base = msrs[i].data;
+ }
+ break;
}
}
static int kvm_put_vcpu_events(X86CPU *cpu, int level)
{
CPUX86State *env = &cpu->env;
- struct kvm_vcpu_events events;
+ struct kvm_vcpu_events events = {};
if (!kvm_has_vcpu_events()) {
return 0;
* irqchip, so we can use irqfds, and on x86 we know
* we can use msi via irqfd and GSI routing.
*/
- kvm_irqfds_allowed = true;
kvm_msi_via_irqfd_allowed = true;
kvm_gsi_routing_allowed = true;
}
return kvm_deassign_irq_internal(s, dev_id, KVM_DEV_IRQ_GUEST_MSIX |
KVM_DEV_IRQ_HOST_MSIX);
}
+
+int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route,
+ uint64_t address, uint32_t data)
+{
+ return 0;
+}