From 623972ceae091b31331ae4a1dc94fe5cbb891937 Mon Sep 17 00:00:00 2001 From: Babu Moger Date: Tue, 9 Feb 2021 15:04:05 -0600 Subject: [PATCH 1/3] i386: Add the support for AMD EPYC 3rd generation processors Adds the support for AMD 3rd generation processors. The model display for the new processor will be EPYC-Milan. Adds the following new feature bits on top of the feature bits from the first and second generation EPYC models. pcid : Process context identifiers support ibrs : Indirect Branch Restricted Speculation ssbd : Speculative Store Bypass Disable erms : Enhanced REP MOVSB/STOSB support fsrm : Fast Short REP MOVSB support invpcid : Invalidate processor context ID pku : Protection keys support svme-addr-chk : SVM instructions address check for #GP handling Depends on the following kernel commits: 14c2bf81fcd2 ("KVM: SVM: Fix #GP handling for doubly-nested virtualization") 3b9c723ed7cf ("KVM: SVM: Add support for SVM instruction address check change") 4aa2691dcbd3 ("8ce1c461188799d863398dd2865d KVM: x86: Factor out x86 instruction emulation with decoding") 4407a797e941 ("KVM: SVM: Enable INVPCID feature on AMD") 9715092f8d7e ("KVM: X86: Move handling of INVPCID types to x86") 3f3393b3ce38 ("KVM: X86: Rename and move the function vmx_handle_memory_failure to x86.c") 830bd71f2c06 ("KVM: SVM: Remove set_cr_intercept, clr_cr_intercept and is_cr_intercept") 4c44e8d6c193 ("KVM: SVM: Add new intercept word in vmcb_control_area") c62e2e94b9d4 ("KVM: SVM: Modify 64 bit intercept field to two 32 bit vectors") 9780d51dc2af ("KVM: SVM: Modify intercept_exceptions to generic intercepts") 30abaa88382c ("KVM: SVM: Change intercept_dr to generic intercepts") 03bfeeb988a9 ("KVM: SVM: Change intercept_cr to generic intercepts") c45ad7229d13 ("KVM: SVM: Introduce vmcb_(set_intercept/clr_intercept/_is_intercept)") a90c1ed9f11d ("(pcid) KVM: nSVM: Remove unused field") fa44b82eb831 ("KVM: x86: Move MPK feature detection to common code") 38f3e775e9c2 ("x86/Kconfig: Update config and kernel doc for MPK feature on AMD") 37486135d3a7 ("KVM: x86: Fix pkru save/restore when guest CR4.PKE=0, move it to x86.c") Signed-off-by: Babu Moger Message-Id: <161290460478.11352.8933244555799318236.stgit@bmoger-ubuntu> Signed-off-by: Eduardo Habkost --- target/i386/cpu.c | 107 +++++++++++++++++++++++++++++++++++++++++++++- target/i386/cpu.h | 4 ++ 2 files changed, 110 insertions(+), 1 deletion(-) diff --git a/target/i386/cpu.c b/target/i386/cpu.c index 20c3a5af3f..6a53446e6a 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -1033,7 +1033,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { "clzero", NULL, "xsaveerptr", NULL, NULL, NULL, NULL, NULL, NULL, "wbnoinvd", NULL, NULL, - "ibpb", NULL, NULL, "amd-stibp", + "ibpb", NULL, "ibrs", "amd-stibp", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "amd-ssbd", "virt-ssbd", "amd-no-ssb", NULL, @@ -1798,6 +1798,56 @@ static CPUCaches epyc_rome_cache_info = { }, }; +static CPUCaches epyc_milan_cache_info = { + .l1d_cache = &(CPUCacheInfo) { + .type = DATA_CACHE, + .level = 1, + .size = 32 * KiB, + .line_size = 64, + .associativity = 8, + .partitions = 1, + .sets = 64, + .lines_per_tag = 1, + .self_init = 1, + .no_invd_sharing = true, + }, + .l1i_cache = &(CPUCacheInfo) { + .type = INSTRUCTION_CACHE, + .level = 1, + .size = 32 * KiB, + .line_size = 64, + .associativity = 8, + .partitions = 1, + .sets = 64, + .lines_per_tag = 1, + .self_init = 1, + .no_invd_sharing = true, + }, + .l2_cache = &(CPUCacheInfo) { + .type = UNIFIED_CACHE, + .level = 2, + .size = 512 * KiB, + .line_size = 64, + .associativity = 8, + .partitions = 1, + .sets = 1024, + .lines_per_tag = 1, + }, + .l3_cache = &(CPUCacheInfo) { + .type = UNIFIED_CACHE, + .level = 3, + .size = 32 * MiB, + .line_size = 64, + .associativity = 16, + .partitions = 1, + .sets = 32768, + .lines_per_tag = 1, + .self_init = true, + .inclusive = true, + .complex_indexing = true, + }, +}; + /* The following VMX features are not supported by KVM and are left out in the * CPU definitions: * @@ -4130,6 +4180,61 @@ static X86CPUDefinition builtin_x86_defs[] = { .model_id = "AMD EPYC-Rome Processor", .cache_info = &epyc_rome_cache_info, }, + { + .name = "EPYC-Milan", + .level = 0xd, + .vendor = CPUID_VENDOR_AMD, + .family = 25, + .model = 1, + .stepping = 1, + .features[FEAT_1_EDX] = + CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | CPUID_CLFLUSH | + CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA | CPUID_PGE | + CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 | CPUID_MCE | + CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE | CPUID_DE | + CPUID_VME | CPUID_FP87, + .features[FEAT_1_ECX] = + CPUID_EXT_RDRAND | CPUID_EXT_F16C | CPUID_EXT_AVX | + CPUID_EXT_XSAVE | CPUID_EXT_AES | CPUID_EXT_POPCNT | + CPUID_EXT_MOVBE | CPUID_EXT_SSE42 | CPUID_EXT_SSE41 | + CPUID_EXT_CX16 | CPUID_EXT_FMA | CPUID_EXT_SSSE3 | + CPUID_EXT_MONITOR | CPUID_EXT_PCLMULQDQ | CPUID_EXT_SSE3 | + CPUID_EXT_PCID, + .features[FEAT_8000_0001_EDX] = + CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_PDPE1GB | + CPUID_EXT2_FFXSR | CPUID_EXT2_MMXEXT | CPUID_EXT2_NX | + CPUID_EXT2_SYSCALL, + .features[FEAT_8000_0001_ECX] = + CPUID_EXT3_OSVW | CPUID_EXT3_3DNOWPREFETCH | + CPUID_EXT3_MISALIGNSSE | CPUID_EXT3_SSE4A | CPUID_EXT3_ABM | + CPUID_EXT3_CR8LEG | CPUID_EXT3_SVM | CPUID_EXT3_LAHF_LM | + CPUID_EXT3_TOPOEXT | CPUID_EXT3_PERFCORE, + .features[FEAT_8000_0008_EBX] = + CPUID_8000_0008_EBX_CLZERO | CPUID_8000_0008_EBX_XSAVEERPTR | + CPUID_8000_0008_EBX_WBNOINVD | CPUID_8000_0008_EBX_IBPB | + CPUID_8000_0008_EBX_IBRS | CPUID_8000_0008_EBX_STIBP | + CPUID_8000_0008_EBX_AMD_SSBD, + .features[FEAT_7_0_EBX] = + CPUID_7_0_EBX_FSGSBASE | CPUID_7_0_EBX_BMI1 | CPUID_7_0_EBX_AVX2 | + CPUID_7_0_EBX_SMEP | CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_RDSEED | + CPUID_7_0_EBX_ADX | CPUID_7_0_EBX_SMAP | CPUID_7_0_EBX_CLFLUSHOPT | + CPUID_7_0_EBX_SHA_NI | CPUID_7_0_EBX_CLWB | CPUID_7_0_EBX_ERMS | + CPUID_7_0_EBX_INVPCID, + .features[FEAT_7_0_ECX] = + CPUID_7_0_ECX_UMIP | CPUID_7_0_ECX_RDPID | CPUID_7_0_ECX_PKU, + .features[FEAT_7_0_EDX] = + CPUID_7_0_EDX_FSRM, + .features[FEAT_XSAVE] = + CPUID_XSAVE_XSAVEOPT | CPUID_XSAVE_XSAVEC | + CPUID_XSAVE_XGETBV1 | CPUID_XSAVE_XSAVES, + .features[FEAT_6_EAX] = + CPUID_6_EAX_ARAT, + .features[FEAT_SVM] = + CPUID_SVM_NPT | CPUID_SVM_NRIPSAVE | CPUID_SVM_SVME_ADDR_CHK, + .xlevel = 0x8000001E, + .model_id = "AMD EPYC-Milan Processor", + .cache_info = &epyc_milan_cache_info, + }, }; /* KVM-specific features that are automatically added/removed diff --git a/target/i386/cpu.h b/target/i386/cpu.h index 82c1ac00ef..8be39cfb62 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -817,8 +817,12 @@ typedef uint64_t FeatureWordArray[FEATURE_WORDS]; #define CPUID_8000_0008_EBX_WBNOINVD (1U << 9) /* Indirect Branch Prediction Barrier */ #define CPUID_8000_0008_EBX_IBPB (1U << 12) +/* Indirect Branch Restricted Speculation */ +#define CPUID_8000_0008_EBX_IBRS (1U << 14) /* Single Thread Indirect Branch Predictors */ #define CPUID_8000_0008_EBX_STIBP (1U << 15) +/* Speculative Store Bypass Disable */ +#define CPUID_8000_0008_EBX_AMD_SSBD (1U << 24) #define CPUID_XSAVE_XSAVEOPT (1U << 0) #define CPUID_XSAVE_XSAVEC (1U << 1) From 1a14d4e16af96d6b390da30a9ac707a84b70cbfc Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Tue, 2 Feb 2021 14:12:07 -0500 Subject: [PATCH 2/3] device-crash-test: Remove problematic language Replace "whitelist" in the device-crash-test script with "rule list". I'm using "rule list" instead of "allow list" or "pass list" because the list is not used only for expected/allowed errors. It also contain rules specifying which errors shouldn't be ignored and/or should be fatal. Signed-off-by: Eduardo Habkost Reviewed-by: John Snow Acked-by: Thomas Huth Message-Id: <20210202191207.4103973-1-ehabkost@redhat.com> Signed-off-by: Eduardo Habkost --- scripts/device-crash-test | 96 +++++++++++++++++++-------------------- 1 file changed, 48 insertions(+), 48 deletions(-) diff --git a/scripts/device-crash-test b/scripts/device-crash-test index 04118669ba..ef1412ca59 100755 --- a/scripts/device-crash-test +++ b/scripts/device-crash-test @@ -41,18 +41,18 @@ logger = logging.getLogger('device-crash-test') dbg = logger.debug -# Purposes of the following whitelist: +# Purposes of the following rule list: # * Avoiding verbose log messages when we find known non-fatal # (exitcode=1) errors # * Avoiding fatal errors when we find known crashes # * Skipping machines/devices that are known not to work out of # the box, when running in --quick mode # -# Keeping the whitelist updated is desirable, but not required, +# Keeping the rule list updated is desirable, but not required, # because unexpected cases where QEMU exits with exitcode=1 will # just trigger a INFO message. -# Valid whitelist entry keys: +# Valid error rule keys: # * accel: regexp, full match only # * machine: regexp, full match only # * device: regexp, full match only @@ -62,7 +62,7 @@ dbg = logger.debug # * expected: if True, QEMU is expected to always fail every time # when testing the corresponding test case # * loglevel: log level of log output when there's a match. -ERROR_WHITELIST = [ +ERROR_RULE_LIST = [ # Machines that won't work out of the box: # MACHINE | ERROR MESSAGE {'machine':'niagara', 'expected':True}, # Unable to load a firmware for -M niagara @@ -186,65 +186,65 @@ ERROR_WHITELIST = [ ] -def whitelistTestCaseMatch(wl, t): - """Check if a test case specification can match a whitelist entry +def errorRuleTestCaseMatch(rule, t): + """Check if a test case specification can match a error rule - This only checks if a whitelist entry is a candidate match + This only checks if a error rule is a candidate match for a given test case, it won't check if the test case - results/output match the entry. See whitelistResultMatch(). + results/output match the rule. See ruleListResultMatch(). """ - return (('machine' not in wl or + return (('machine' not in rule or 'machine' not in t or - re.match(wl['machine'] + '$', t['machine'])) and - ('accel' not in wl or + re.match(rule['machine'] + '$', t['machine'])) and + ('accel' not in rule or 'accel' not in t or - re.match(wl['accel'] + '$', t['accel'])) and - ('device' not in wl or + re.match(rule['accel'] + '$', t['accel'])) and + ('device' not in rule or 'device' not in t or - re.match(wl['device'] + '$', t['device']))) + re.match(rule['device'] + '$', t['device']))) -def whitelistCandidates(t): +def ruleListCandidates(t): """Generate the list of candidates that can match a test case""" - for i, wl in enumerate(ERROR_WHITELIST): - if whitelistTestCaseMatch(wl, t): - yield (i, wl) + for i, rule in enumerate(ERROR_RULE_LIST): + if errorRuleTestCaseMatch(rule, t): + yield (i, rule) def findExpectedResult(t): - """Check if there's an expected=True whitelist entry for a test case + """Check if there's an expected=True error rule for a test case - Returns (i, wl) tuple, where i is the index in - ERROR_WHITELIST and wl is the whitelist entry itself. + Returns (i, rule) tuple, where i is the index in + ERROR_RULE_LIST and rule is the error rule itself. """ - for i, wl in whitelistCandidates(t): - if wl.get('expected'): - return (i, wl) + for i, rule in ruleListCandidates(t): + if rule.get('expected'): + return (i, rule) -def whitelistResultMatch(wl, r): - """Check if test case results/output match a whitelist entry +def ruleListResultMatch(rule, r): + """Check if test case results/output match a error rule It is valid to call this function only if - whitelistTestCaseMatch() is True for the entry (e.g. on - entries returned by whitelistCandidates()) + errorRuleTestCaseMatch() is True for the rule (e.g. on + rules returned by ruleListCandidates()) """ - assert whitelistTestCaseMatch(wl, r['testcase']) - return ((wl.get('exitcode', 1) is None or - r['exitcode'] == wl.get('exitcode', 1)) and - ('log' not in wl or - re.search(wl['log'], r['log'], re.MULTILINE))) + assert errorRuleTestCaseMatch(rule, r['testcase']) + return ((rule.get('exitcode', 1) is None or + r['exitcode'] == rule.get('exitcode', 1)) and + ('log' not in rule or + re.search(rule['log'], r['log'], re.MULTILINE))) -def checkResultWhitelist(r): - """Look up whitelist entry for a given test case result +def checkResultRuleList(r): + """Look up error rule for a given test case result - Returns (i, wl) tuple, where i is the index in - ERROR_WHITELIST and wl is the whitelist entry itself. + Returns (i, rule) tuple, where i is the index in + ERROR_RULE_LIST and rule is the error rule itself. """ - for i, wl in whitelistCandidates(r['testcase']): - if whitelistResultMatch(wl, r): - return i, wl + for i, rule in ruleListCandidates(r['testcase']): + if ruleListResultMatch(rule, r): + return i, rule raise Exception("this should never happen") @@ -543,12 +543,12 @@ def main(): break if f: - i, wl = checkResultWhitelist(f) - dbg("testcase: %r, whitelist match: %r", t, wl) + i, rule = checkResultRuleList(f) + dbg("testcase: %r, rule list match: %r", t, rule) wl_stats.setdefault(i, []).append(f) - level = wl.get('loglevel', logging.DEBUG) + level = rule.get('loglevel', logging.DEBUG) logFailure(f, level) - if wl.get('fatal') or (args.strict and level >= logging.WARN): + if rule.get('fatal') or (args.strict and level >= logging.WARN): fatal_failures.append(f) else: dbg("success: %s", formatTestCase(t)) @@ -560,10 +560,10 @@ def main(): logger.info("Skipped %d test cases", skipped) if args.debug: - stats = sorted([(len(wl_stats.get(i, [])), wl) for i, wl in - enumerate(ERROR_WHITELIST)], key=lambda x: x[0]) - for count, wl in stats: - dbg("whitelist entry stats: %d: %r", count, wl) + stats = sorted([(len(wl_stats.get(i, [])), rule) for i, rule in + enumerate(ERROR_RULE_LIST)], key=lambda x: x[0]) + for count, rule in stats: + dbg("error rule stats: %d: %r", count, rule) if fatal_failures: for f in fatal_failures: From def835f0da0d153b397071e6bb8f2b46f51f96b4 Mon Sep 17 00:00:00 2001 From: Michal Privoznik Date: Tue, 26 Jan 2021 08:48:25 +0100 Subject: [PATCH 3/3] hostmem: Don't report pmem attribute if unsupported When management applications (like Libvirt) want to check whether memory-backend-file.pmem is supported they can list object properties using 'qom-list-properties'. However, 'pmem' is declared always (and thus reported always) and only at runtime QEMU errors out if it was built without libpmem (and thus can not guarantee write persistence). This is suboptimal since we have ability to declare attributes at compile time. Signed-off-by: Michal Privoznik Tested-by: Daniel Henrique Barboza Reviewed-by: Daniel Henrique Barboza Reviewed-by: Igor Mammedov Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1915216 Message-Id: Signed-off-by: Eduardo Habkost --- backends/hostmem-file.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/backends/hostmem-file.c b/backends/hostmem-file.c index 733408e076..b683da9daf 100644 --- a/backends/hostmem-file.c +++ b/backends/hostmem-file.c @@ -124,6 +124,7 @@ static void file_memory_backend_set_align(Object *o, Visitor *v, fb->align = val; } +#ifdef CONFIG_LIBPMEM static bool file_memory_backend_get_pmem(Object *o, Error **errp) { return MEMORY_BACKEND_FILE(o)->is_pmem; @@ -140,17 +141,9 @@ static void file_memory_backend_set_pmem(Object *o, bool value, Error **errp) return; } -#ifndef CONFIG_LIBPMEM - if (value) { - error_setg(errp, "Lack of libpmem support while setting the 'pmem=on'" - " of %s. We can't ensure data persistence.", - object_get_typename(o)); - return; - } -#endif - fb->is_pmem = value; } +#endif /* CONFIG_LIBPMEM */ static bool file_memory_backend_get_readonly(Object *obj, Error **errp) { @@ -203,8 +196,10 @@ file_backend_class_init(ObjectClass *oc, void *data) file_memory_backend_get_align, file_memory_backend_set_align, NULL, NULL); +#ifdef CONFIG_LIBPMEM object_class_property_add_bool(oc, "pmem", file_memory_backend_get_pmem, file_memory_backend_set_pmem); +#endif object_class_property_add_bool(oc, "readonly", file_memory_backend_get_readonly, file_memory_backend_set_readonly);