x86 queue, 2018-03-12

* Intel Processor Trace support
 * KVM_HINTS_DEDICATED
 -----BEGIN PGP SIGNATURE-----
 
 iQIcBAABCAAGBQJaptvvAAoJECgHk2+YTcWmiZUP/3crzf9eiRyrXG2Pw8xY95ia
 62a/xdZH5UnIvhczVDiIsbDgnGGKwSce690ypHVCle0Pr5jv0Seym5Pb5DUGKwWa
 O/LI9UjjzthK96a2uMjf0DuAlwbBGtUnryO1y1PJqrlZa4N2nMPKeZLatUY5qybS
 sM0OmmQvdl2PESx0DrtY2wTap+Mx4/FTefx8FoICpFj+tjkDTNyEM3znG5cejuCo
 vD7098Y0XW9pnVdEEfsugV52HNX8cHtaT5E+uL2RRPJyuZW2/10mczTGd2SZEgoj
 DZlKLr7gqXYAOOvO/J9pSYqwIhCiED2VG7ceI0ulfEPrLMJeXsq/D8G0fkszvURr
 TgDblNKR37Iogth64teZBS1YXvNF6cIaTLuEJ3xtLDPZuNpC4x4fNJZDrj06YAAy
 l8ReOec/KCuD9Oi+XhWj/Teb/MxCI+C8MR7S1qS+Wb405jIJwUS27f1hjcOu0AdA
 9a54HIRxByiDYUhzVauHushfMyxfB6Erc+c6XGHWnfsQBbH9So8rHCbCKrHsFi4q
 QGPmPMvR6Im6v2ExtU91w6mZp+J54Jzx0lZMOKqf/V6eBndyn/OF91cfOBu/vZtv
 5WYfJrkbXDfR0+Xnd464FvrwhhlqQJ/xtpgjeeil9PD/HhLeIc7qAyWHfWhRpijS
 diiKJNui+QKTDOoRrxtL
 =uEnF
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/ehabkost/tags/x86-next-pull-request' into staging

x86 queue, 2018-03-12

* Intel Processor Trace support
* KVM_HINTS_DEDICATED

# gpg: Signature made Mon 12 Mar 2018 19:58:39 GMT
# gpg:                using RSA key 2807936F984DC5A6
# gpg: Good signature from "Eduardo Habkost <ehabkost@redhat.com>"
# Primary key fingerprint: 5A32 2FD5 ABC4 D3DB ACCF  D1AA 2807 936F 984D C5A6

* remotes/ehabkost/tags/x86-next-pull-request:
  i386: Add support to get/set/migrate Intel Processor Trace feature
  i386: Add Intel Processor Trace feature support
  target-i386: add KVM_HINTS_DEDICATED performance hint

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2018-03-13 14:02:47 +00:00
commit 59667bb167
4 changed files with 232 additions and 2 deletions

View File

@ -173,7 +173,32 @@
#define L2_ITLB_4K_ASSOC 4
#define L2_ITLB_4K_ENTRIES 512
/* CPUID Leaf 0x14 constants: */
#define INTEL_PT_MAX_SUBLEAF 0x1
/*
* bit[00]: IA32_RTIT_CTL.CR3 filter can be set to 1 and IA32_RTIT_CR3_MATCH
* MSR can be accessed;
* bit[01]: Support Configurable PSB and Cycle-Accurate Mode;
* bit[02]: Support IP Filtering, TraceStop filtering, and preservation
* of Intel PT MSRs across warm reset;
* bit[03]: Support MTC timing packet and suppression of COFI-based packets;
*/
#define INTEL_PT_MINIMAL_EBX 0xf
/*
* bit[00]: Tracing can be enabled with IA32_RTIT_CTL.ToPA = 1 and
* IA32_RTIT_OUTPUT_BASE and IA32_RTIT_OUTPUT_MASK_PTRS MSRs can be
* accessed;
* bit[01]: ToPA tables can hold any number of output entries, up to the
* maximum allowed by the MaskOrTableOffset field of
* IA32_RTIT_OUTPUT_MASK_PTRS;
* bit[02]: Support Single-Range Output scheme;
*/
#define INTEL_PT_MINIMAL_ECX 0x7
#define INTEL_PT_ADDR_RANGES_NUM 0x2 /* Number of configurable address ranges */
#define INTEL_PT_ADDR_RANGES_NUM_MASK 0x3
#define INTEL_PT_MTC_BITMAP (0x0249 << 16) /* Support ART(0,3,6,9) */
#define INTEL_PT_CYCLE_BITMAP 0x1fff /* Support 0,2^(0~11) */
#define INTEL_PT_PSB_BITMAP (0x003f << 16) /* Support 2K,4K,8K,16K,32K,64K */
static void x86_cpu_vendor_words2str(char *dst, uint32_t vendor1,
uint32_t vendor2, uint32_t vendor3)
@ -359,6 +384,20 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
.cpuid_eax = KVM_CPUID_FEATURES, .cpuid_reg = R_EAX,
.tcg_features = TCG_KVM_FEATURES,
},
[FEAT_KVM_HINTS] = {
.feat_names = {
"kvm-hint-dedicated", NULL, NULL, NULL,
NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL,
},
.cpuid_eax = KVM_CPUID_FEATURES, .cpuid_reg = R_EDX,
.tcg_features = TCG_KVM_FEATURES,
},
[FEAT_HYPERV_EAX] = {
.feat_names = {
NULL /* hv_msr_vp_runtime_access */, NULL /* hv_msr_time_refcount_access */,
@ -428,7 +467,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
NULL, NULL, "mpx", NULL,
"avx512f", "avx512dq", "rdseed", "adx",
"smap", "avx512ifma", "pcommit", "clflushopt",
"clwb", NULL, "avx512pf", "avx512er",
"clwb", "intel-pt", "avx512pf", "avx512er",
"avx512cd", "sha-ni", "avx512bw", "avx512vl",
},
.cpuid_eax = 7,
@ -3453,6 +3492,27 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
}
break;
}
case 0x14: {
/* Intel Processor Trace Enumeration */
*eax = 0;
*ebx = 0;
*ecx = 0;
*edx = 0;
if (!(env->features[FEAT_7_0_EBX] & CPUID_7_0_EBX_INTEL_PT) ||
!kvm_enabled()) {
break;
}
if (count == 0) {
*eax = INTEL_PT_MAX_SUBLEAF;
*ebx = INTEL_PT_MINIMAL_EBX;
*ecx = INTEL_PT_MINIMAL_ECX;
} else if (count == 1) {
*eax = INTEL_PT_MTC_BITMAP | INTEL_PT_ADDR_RANGES_NUM;
*ebx = INTEL_PT_PSB_BITMAP | INTEL_PT_CYCLE_BITMAP;
}
break;
}
case 0x40000000:
/*
* CPUID code in kvm_arch_init_vcpu() ignores stuff
@ -4083,6 +4143,34 @@ static int x86_cpu_filter_features(X86CPU *cpu)
}
}
if ((env->features[FEAT_7_0_EBX] & CPUID_7_0_EBX_INTEL_PT) &&
kvm_enabled()) {
KVMState *s = CPU(cpu)->kvm_state;
uint32_t eax_0 = kvm_arch_get_supported_cpuid(s, 0x14, 0, R_EAX);
uint32_t ebx_0 = kvm_arch_get_supported_cpuid(s, 0x14, 0, R_EBX);
uint32_t ecx_0 = kvm_arch_get_supported_cpuid(s, 0x14, 0, R_ECX);
uint32_t eax_1 = kvm_arch_get_supported_cpuid(s, 0x14, 1, R_EAX);
uint32_t ebx_1 = kvm_arch_get_supported_cpuid(s, 0x14, 1, R_EBX);
if (!eax_0 ||
((ebx_0 & INTEL_PT_MINIMAL_EBX) != INTEL_PT_MINIMAL_EBX) ||
((ecx_0 & INTEL_PT_MINIMAL_ECX) != INTEL_PT_MINIMAL_ECX) ||
((eax_1 & INTEL_PT_MTC_BITMAP) != INTEL_PT_MTC_BITMAP) ||
((eax_1 & INTEL_PT_ADDR_RANGES_NUM_MASK) <
INTEL_PT_ADDR_RANGES_NUM) ||
((ebx_1 & (INTEL_PT_PSB_BITMAP | INTEL_PT_CYCLE_BITMAP)) !=
(INTEL_PT_PSB_BITMAP | INTEL_PT_CYCLE_BITMAP))) {
/*
* Processor Trace capabilities aren't configurable, so if the
* host can't emulate the capabilities we report on
* cpu_x86_cpuid(), intel-pt can't be enabled on the current host.
*/
env->features[FEAT_7_0_EBX] &= ~CPUID_7_0_EBX_INTEL_PT;
cpu->filtered_features[FEAT_7_0_EBX] |= CPUID_7_0_EBX_INTEL_PT;
rv = 1;
}
}
return rv;
}

View File

@ -415,6 +415,21 @@ typedef enum X86Seg {
#define MSR_MC0_ADDR 0x402
#define MSR_MC0_MISC 0x403
#define MSR_IA32_RTIT_OUTPUT_BASE 0x560
#define MSR_IA32_RTIT_OUTPUT_MASK 0x561
#define MSR_IA32_RTIT_CTL 0x570
#define MSR_IA32_RTIT_STATUS 0x571
#define MSR_IA32_RTIT_CR3_MATCH 0x572
#define MSR_IA32_RTIT_ADDR0_A 0x580
#define MSR_IA32_RTIT_ADDR0_B 0x581
#define MSR_IA32_RTIT_ADDR1_A 0x582
#define MSR_IA32_RTIT_ADDR1_B 0x583
#define MSR_IA32_RTIT_ADDR2_A 0x584
#define MSR_IA32_RTIT_ADDR2_B 0x585
#define MSR_IA32_RTIT_ADDR3_A 0x586
#define MSR_IA32_RTIT_ADDR3_B 0x587
#define MAX_RTIT_ADDRS 8
#define MSR_EFER 0xc0000080
#define MSR_EFER_SCE (1 << 0)
@ -471,6 +486,7 @@ typedef enum FeatureWord {
FEAT_8000_0008_EBX, /* CPUID[8000_0008].EBX */
FEAT_C000_0001_EDX, /* CPUID[C000_0001].EDX */
FEAT_KVM, /* CPUID[4000_0001].EAX (KVM_CPUID_FEATURES) */
FEAT_KVM_HINTS, /* CPUID[4000_0001].EDX */
FEAT_HYPERV_EAX, /* CPUID[4000_0003].EAX */
FEAT_HYPERV_EBX, /* CPUID[4000_0003].EBX */
FEAT_HYPERV_EDX, /* CPUID[4000_0003].EDX */
@ -640,6 +656,7 @@ typedef uint32_t FeatureWordArray[FEATURE_WORDS];
#define CPUID_7_0_EBX_PCOMMIT (1U << 22) /* Persistent Commit */
#define CPUID_7_0_EBX_CLFLUSHOPT (1U << 23) /* Flush a Cache Line Optimized */
#define CPUID_7_0_EBX_CLWB (1U << 24) /* Cache Line Write Back */
#define CPUID_7_0_EBX_INTEL_PT (1U << 25) /* Intel Processor Trace */
#define CPUID_7_0_EBX_AVX512PF (1U << 26) /* AVX-512 Prefetch */
#define CPUID_7_0_EBX_AVX512ER (1U << 27) /* AVX-512 Exponential and Reciprocal */
#define CPUID_7_0_EBX_AVX512CD (1U << 28) /* AVX-512 Conflict Detection */
@ -666,6 +683,8 @@ typedef uint32_t FeatureWordArray[FEATURE_WORDS];
#define CPUID_7_0_EDX_AVX512_4FMAPS (1U << 3) /* AVX512 Multiply Accumulation Single Precision */
#define CPUID_7_0_EDX_SPEC_CTRL (1U << 26) /* Speculation Control */
#define KVM_HINTS_DEDICATED (1U << 0)
#define CPUID_8000_0008_EBX_IBPB (1U << 12) /* Indirect Branch Prediction Barrier */
#define CPUID_XSAVE_XSAVEOPT (1U << 0)
@ -1153,6 +1172,13 @@ typedef struct CPUX86State {
uint64_t msr_hv_stimer_config[HV_STIMER_COUNT];
uint64_t msr_hv_stimer_count[HV_STIMER_COUNT];
uint64_t msr_rtit_ctrl;
uint64_t msr_rtit_status;
uint64_t msr_rtit_output_base;
uint64_t msr_rtit_output_mask;
uint64_t msr_rtit_cr3_match;
uint64_t msr_rtit_addrs[MAX_RTIT_ADDRS];
/* exception/interrupt handling */
int error_code;
int exception_is_int;

View File

@ -383,6 +383,9 @@ uint32_t kvm_arch_get_supported_cpuid(KVMState *s, uint32_t function,
if (!kvm_irqchip_in_kernel()) {
ret &= ~(1U << KVM_FEATURE_PV_UNHALT);
}
} else if (function == KVM_CPUID_FEATURES && reg == R_EDX) {
ret |= KVM_HINTS_DEDICATED;
found = 1;
}
/* fallback for older kernels */
@ -801,6 +804,7 @@ int kvm_arch_init_vcpu(CPUState *cs)
c = &cpuid_data.entries[cpuid_i++];
c->function = KVM_CPUID_FEATURES | kvm_base;
c->eax = env->features[FEAT_KVM];
c->edx = env->features[FEAT_KVM_HINTS];
}
cpu_x86_cpuid(env, 0, 0, &limit, &unused, &unused, &unused);
@ -865,6 +869,29 @@ int kvm_arch_init_vcpu(CPUState *cs)
c = &cpuid_data.entries[cpuid_i++];
}
break;
case 0x14: {
uint32_t times;
c->function = i;
c->index = 0;
c->flags = KVM_CPUID_FLAG_SIGNIFCANT_INDEX;
cpu_x86_cpuid(env, i, 0, &c->eax, &c->ebx, &c->ecx, &c->edx);
times = c->eax;
for (j = 1; j <= times; ++j) {
if (cpuid_i == KVM_MAX_CPUID_ENTRIES) {
fprintf(stderr, "cpuid_data is full, no space for "
"cpuid(eax:0x14,ecx:0x%x)\n", j);
abort();
}
c = &cpuid_data.entries[cpuid_i++];
c->function = i;
c->index = j;
c->flags = KVM_CPUID_FLAG_SIGNIFCANT_INDEX;
cpu_x86_cpuid(env, i, j, &c->eax, &c->ebx, &c->ecx, &c->edx);
}
break;
}
default:
c->function = i;
c->flags = 0;
@ -1788,6 +1815,25 @@ static int kvm_put_msrs(X86CPU *cpu, int level)
kvm_msr_entry_add(cpu, MSR_MTRRphysMask(i), mask);
}
}
if (env->features[FEAT_7_0_EBX] & CPUID_7_0_EBX_INTEL_PT) {
int addr_num = kvm_arch_get_supported_cpuid(kvm_state,
0x14, 1, R_EAX) & 0x7;
kvm_msr_entry_add(cpu, MSR_IA32_RTIT_CTL,
env->msr_rtit_ctrl);
kvm_msr_entry_add(cpu, MSR_IA32_RTIT_STATUS,
env->msr_rtit_status);
kvm_msr_entry_add(cpu, MSR_IA32_RTIT_OUTPUT_BASE,
env->msr_rtit_output_base);
kvm_msr_entry_add(cpu, MSR_IA32_RTIT_OUTPUT_MASK,
env->msr_rtit_output_mask);
kvm_msr_entry_add(cpu, MSR_IA32_RTIT_CR3_MATCH,
env->msr_rtit_cr3_match);
for (i = 0; i < addr_num; i++) {
kvm_msr_entry_add(cpu, MSR_IA32_RTIT_ADDR0_A + i,
env->msr_rtit_addrs[i]);
}
}
/* Note: MSR_IA32_FEATURE_CONTROL is written separately, see
* kvm_put_msr_feature_control. */
@ -2101,6 +2147,20 @@ static int kvm_get_msrs(X86CPU *cpu)
}
}
if (env->features[FEAT_7_0_EBX] & CPUID_7_0_EBX_INTEL_PT) {
int addr_num =
kvm_arch_get_supported_cpuid(kvm_state, 0x14, 1, R_EAX) & 0x7;
kvm_msr_entry_add(cpu, MSR_IA32_RTIT_CTL, 0);
kvm_msr_entry_add(cpu, MSR_IA32_RTIT_STATUS, 0);
kvm_msr_entry_add(cpu, MSR_IA32_RTIT_OUTPUT_BASE, 0);
kvm_msr_entry_add(cpu, MSR_IA32_RTIT_OUTPUT_MASK, 0);
kvm_msr_entry_add(cpu, MSR_IA32_RTIT_CR3_MATCH, 0);
for (i = 0; i < addr_num; i++) {
kvm_msr_entry_add(cpu, MSR_IA32_RTIT_ADDR0_A + i, 0);
}
}
ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_MSRS, cpu->kvm_msr_buf);
if (ret < 0) {
return ret;
@ -2341,6 +2401,24 @@ static int kvm_get_msrs(X86CPU *cpu)
case MSR_IA32_SPEC_CTRL:
env->spec_ctrl = msrs[i].data;
break;
case MSR_IA32_RTIT_CTL:
env->msr_rtit_ctrl = msrs[i].data;
break;
case MSR_IA32_RTIT_STATUS:
env->msr_rtit_status = msrs[i].data;
break;
case MSR_IA32_RTIT_OUTPUT_BASE:
env->msr_rtit_output_base = msrs[i].data;
break;
case MSR_IA32_RTIT_OUTPUT_MASK:
env->msr_rtit_output_mask = msrs[i].data;
break;
case MSR_IA32_RTIT_CR3_MATCH:
env->msr_rtit_cr3_match = msrs[i].data;
break;
case MSR_IA32_RTIT_ADDR0_A ... MSR_IA32_RTIT_ADDR3_B:
env->msr_rtit_addrs[index - MSR_IA32_RTIT_ADDR0_A] = msrs[i].data;
break;
}
}

View File

@ -837,6 +837,43 @@ static const VMStateDescription vmstate_spec_ctrl = {
}
};
static bool intel_pt_enable_needed(void *opaque)
{
X86CPU *cpu = opaque;
CPUX86State *env = &cpu->env;
int i;
if (env->msr_rtit_ctrl || env->msr_rtit_status ||
env->msr_rtit_output_base || env->msr_rtit_output_mask ||
env->msr_rtit_cr3_match) {
return true;
}
for (i = 0; i < MAX_RTIT_ADDRS; i++) {
if (env->msr_rtit_addrs[i]) {
return true;
}
}
return false;
}
static const VMStateDescription vmstate_msr_intel_pt = {
.name = "cpu/intel_pt",
.version_id = 1,
.minimum_version_id = 1,
.needed = intel_pt_enable_needed,
.fields = (VMStateField[]) {
VMSTATE_UINT64(env.msr_rtit_ctrl, X86CPU),
VMSTATE_UINT64(env.msr_rtit_status, X86CPU),
VMSTATE_UINT64(env.msr_rtit_output_base, X86CPU),
VMSTATE_UINT64(env.msr_rtit_output_mask, X86CPU),
VMSTATE_UINT64(env.msr_rtit_cr3_match, X86CPU),
VMSTATE_UINT64_ARRAY(env.msr_rtit_addrs, X86CPU, MAX_RTIT_ADDRS),
VMSTATE_END_OF_LIST()
}
};
VMStateDescription vmstate_x86_cpu = {
.name = "cpu",
.version_id = 12,
@ -957,6 +994,7 @@ VMStateDescription vmstate_x86_cpu = {
#endif
&vmstate_spec_ctrl,
&vmstate_mcg_ext_ctl,
&vmstate_msr_intel_pt,
NULL
}
};