[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH v2] amd: disable C6 after 1000 days on Zen2


  • To: xen-devel@xxxxxxxxxxxxxxxxxxxx
  • From: Roger Pau Monne <roger.pau@xxxxxxxxxx>
  • Date: Fri, 30 Jun 2023 15:18:20 +0200
  • Arc-authentication-results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=citrix.com; dmarc=pass action=none header.from=citrix.com; dkim=pass header.d=citrix.com; arc=none
  • Arc-message-signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=v37ahnbQVAMnPOCwWe3H8Ii1Qz+FpCWeHJE9Rg7DH8U=; b=NxdN0ns/4e1y+2o3NSXP9chIcYcUSGxe866rckygXSk/7aRYhtVuWJCfkFN56/SQftF5p6nElpYnwHqv1TinRgYYGT6eZiCfDG00F8x3O0r8IhKiIE8y/n8lQYt/yhQmm/+ke/o/kXw8mVUlP7VCsdPWYaDiXdGzDopOqXiGgcaC72YvfFHqVEXPEOsQ6Oxh0yZgLhw8tCPQfaJzSaE4I+zx5qtAlTCIK7iFFdCxQtxkVPCV2qXC0tPIWZ1m5mwp+fBXGyFNMgDPH3teWmirQCOvOYomChJfIN0cUraTjxuOwY96gmT/3iPkCQAEh6dEDfkhpoFfb+ysKN8iuCVhOw==
  • Arc-seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=NGOXqlLTLFZi3Njg47GcNaPSgZJ3NHA8j81nNkyVadaj/27kjC3mSDsI0NyYawU3xeXawx9yrSVPwdNvfd/lh8P4PNFCb1EtQFEkEwHnskkM8qj+iQ5VppbXG8UjsDu3VPiRZ/SIOHkoQPnr+2JBJnp8Uqb6uhStjbbB4WNhzSrCiGdIXJaM85X43X05t3WDY6HC3nhLcATuGyqZXPLIyZQtiq3rx10ZQOCHeS/lufNddck5DtEpB43TcJ0fQs0fJdf/uUXk+mPa+6N7H7MzTMw1HErQ+NymTxCHGECGv3FugijyLLg3/uUl5FLaH11VSLfXh3CEcpPBO9bXcYqrcQ==
  • Authentication-results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=citrix.com;
  • Cc: Roger Pau Monne <roger.pau@xxxxxxxxxx>, Jan Beulich <jbeulich@xxxxxxxx>, Andrew Cooper <andrew.cooper3@xxxxxxxxxx>, Wei Liu <wl@xxxxxxx>, George Dunlap <george.dunlap@xxxxxxxxxx>, Julien Grall <julien@xxxxxxx>, Stefano Stabellini <sstabellini@xxxxxxxxxx>
  • Delivery-date: Fri, 30 Jun 2023 13:21:49 +0000
  • Ironport-data: A9a23:NEjxJa16Tv8SDpOFpvbD5R1wkn2cJEfYwER7XKvMYLTBsI5bp2EDn 2dJDDuCPfqNZWT0LdFxbo21pkwFvpSHyIQ3SwZopC1hF35El5HIVI+TRqvS04F+DeWYFR46s J9OAjXkBJppJpMJjk71atANlVEliefTAOK6ULWeUsxIbVcMYD87jh5+kPIOjIdtgNyoayuAo tq3qMDEULOf82cc3lk8teTb8XuDgNyo4GlD5gJlPagS1LPjvyJ94Kw3dPnZw0TQGuG4LsbiL 87fwbew+H/u/htFIrtJRZ6iLyXm6paLVeS/oiI+t5qK23CulQRrukoPD9IOaF8/ttm8t4sZJ OOhF3CHYVxB0qXkwIzxWvTDes10FfUuFLTveRBTvSEPpqFvnrSFL/hGVSkL0YMkFulfW2RW1 aUoCRc0TxWnptus6Y6lYM5NiZF2RCXrFNt3VnBI6xj8VK5jbbWdBqLA6JlfwSs6gd1IEbDGf c0FZDFzbRPGJRpSJlMQD5F4l+Ct7pX9W2QA9BTJ+uxqsy6KlFQZPLvFabI5fvSQQspYhACAr 3/u9GXlGBAKcteYzFJp91r137OQw3+iAdl6+LuQp9tYmwTM12svGDoMT3b8+sfo0HfuVIcKQ 6AT0m90xUQoz2S7Q9+4UxCmrXqsuh8HR8EWA+A88BuKyKff/0CeHGdsZjxLZcEitcQ2bSc3z VLPlNTsbRRwtJWFRHTb8a2bxRuwJCwUIGkqdSICCwwf7LHLu5ovhxjCStJiFq+djdDvHzz0h TeQo0ADa647iMcK0+C3+A7Bijf1/pzRFFdtvkPQQ36v6R5/aMi9fYu05FPH7PFGaoGEUl2Gu 3tCkM+bhAwTMayweOW2aL1lNNmUCzytalUwXXYH80EdygmQ
  • Ironport-hdrordr: A9a23:5zAUVaGP4VrldywQpLqE78eALOsnbusQ8zAXPiFKOHpom6mj/a 2TdZsgtCMc5AxwZJhYo7690cq7MBThHPxOkOws1N6ZNWGMhILPFvAA0WKL+VHd8kbFh4pgPM lbAspD4AKZNzdHZaGT2njAL+od
  • List-id: Xen developer discussion <xen-devel.lists.xenproject.org>

As specified on Errata 1474:

"A core will fail to exit CC6 after about 1044 days after the last
system reset. The time of failure may vary depending on the spread
spectrum and REFCLK frequency."

Detect when running on AMD Zen2 (family 17h models 30-3fh, 60-6fh or
70-7fh) and setup a timer to prevent entering C6 after 1000 days of
uptime.  Take into account the TSC value at boot in order to account
for any time elapsed before Xen has been booted.  Worst case we end
up disabling C6 before strictly necessary, but that would still be
safe, and it's better than not taking the TSC value into account and
hanging.

Disable C6 by updating the MSR listed in the revision guide, this
avoids applying workarounds in the CPU idle drivers, as the processor
won't be allowed to enter C6 by the hardware itself.

Print a message once C6 is disabled in order to let the user know.

Signed-off-by: Roger Pau Monné <roger.pau@xxxxxxxxxx>
---
The current Revision Guide for Fam17h model 60-6Fh (Lucienne and
Renoir) hasn't been updated to reflect the MSR workaround, but the PPR
for those models lists the MSR and the bits as having the expected
meaning, so I assume it's safe to apply the same workaround there.

For all accounts this seems to affect all Zen2 models, and hence the
workaround should be the same.  Might also affect Hygon, albeit I
think Hygon is strictly limited to Zen1.
---
Changes since v1:
 - Apply the workaround listed by AMD: toggle some MSR bits.
 - Do not apply the workaround if virtualized.
 - Check for STIBP feature instead of listing specific models.
 - Implement the DAYS macro based on SECONDS.
---
 xen/arch/x86/cpu/amd.c               | 70 ++++++++++++++++++++++++++++
 xen/arch/x86/include/asm/msr-index.h |  5 ++
 xen/include/xen/time.h               |  1 +
 3 files changed, 76 insertions(+)

diff --git a/xen/arch/x86/cpu/amd.c b/xen/arch/x86/cpu/amd.c
index 0eaef82e5145..bdf45f8387e8 100644
--- a/xen/arch/x86/cpu/amd.c
+++ b/xen/arch/x86/cpu/amd.c
@@ -51,6 +51,8 @@ bool __read_mostly amd_acpi_c1e_quirk;
 bool __ro_after_init amd_legacy_ssbd;
 bool __initdata amd_virt_spec_ctrl;
 
+static bool __read_mostly c6_disabled;
+
 static inline int rdmsr_amd_safe(unsigned int msr, unsigned int *lo,
                                 unsigned int *hi)
 {
@@ -905,6 +907,31 @@ void __init detect_zen2_null_seg_behaviour(void)
 
 }
 
+static void cf_check disable_c6(void *arg)
+{
+       uint64_t val;
+
+       if (!c6_disabled) {
+               printk(XENLOG_WARNING
+    "Disabling C6 after 1000 days apparent uptime due to AMD errata 1474\n");
+               c6_disabled = true;
+               smp_call_function(disable_c6, NULL, 0);
+       }
+
+       /* Update the MSR to disable C6, done on all threads. */
+       if (rdmsr_safe(MSR_AMD_CSTATE_CFG, val)) {
+error:
+               printk_once(XENLOG_ERR
+               "Unable to disable C6 on AMD system affected by errata 1474\n"
+               "Reboot recommended, otherwise system might hang\n");
+               return;
+       }
+       val &= ~(CSTATE_CFG_CCR0_CC6EN | CSTATE_CFG_CCR1_CC6EN |
+                CSTATE_CFG_CCR2_CC6EN);
+       if (wrmsr_safe(MSR_AMD_CSTATE_CFG, val))
+               goto error;
+}
+
 static void cf_check init_amd(struct cpuinfo_x86 *c)
 {
        u32 l, h;
@@ -1171,6 +1198,9 @@ static void cf_check init_amd(struct cpuinfo_x86 *c)
        if ((smp_processor_id() == 1) && !cpu_has(c, X86_FEATURE_ITSC))
                disable_c1_ramping();
 
+       if (c6_disabled)
+               disable_c6(NULL);
+
        check_syscfg_dram_mod_en();
 
        amd_log_freq(c);
@@ -1180,3 +1210,43 @@ const struct cpu_dev amd_cpu_dev = {
        .c_early_init   = early_init_amd,
        .c_init         = init_amd,
 };
+
+static int __init cf_check c6_errata_check(void)
+{
+       /*
+        * Errata #1474: A Core May Hang After About 1044 Days
+        * Set up a timer to disable C6 after 1000 days uptime.
+        */
+       s_time_t delta;
+
+       /*
+        * Apply to all Zen2 models.  According to AMD revision guides at least
+        * Rome, Castle Peak, Renoir, Lucienne and Matisse are affected.
+        */
+       if (cpu_has_hypervisor || !boot_cpu_has(X86_FEATURE_AMD_STIBP))
+               return 0;
+
+       /*
+        * Deduct current TSC value, this would be relevant if kexec'ed for
+        * example.  Might not be accurate, but worst case we end up disabling
+        * C6 before strictly required, which would still be safe.
+        *
+        * NB: all affected models (Zen2) have invariant TSC and TSC adjust
+        * MSR, so early_time_init() will have already cleared any TSC offset.
+        */
+       delta = DAYS(1000) - tsc_ticks2ns(rdtsc());
+       if (delta > 0) {
+               static struct timer errata_c6;
+
+               init_timer(&errata_c6, disable_c6, NULL, 0);
+               set_timer(&errata_c6, NOW() + delta);
+       } else
+               disable_c6(NULL);
+
+       return 0;
+}
+/*
+ * Must be executed after early_time_init() for tsc_ticks2ns() to have been
+ * calibrated.  That prevents us doing the check in init_amd().
+ */
+presmp_initcall(c6_errata_check);
diff --git a/xen/arch/x86/include/asm/msr-index.h 
b/xen/arch/x86/include/asm/msr-index.h
index 2749e433d2a7..5df090fba791 100644
--- a/xen/arch/x86/include/asm/msr-index.h
+++ b/xen/arch/x86/include/asm/msr-index.h
@@ -211,6 +211,11 @@
 
 #define MSR_VIRT_SPEC_CTRL                  0xc001011f /* Layout matches 
MSR_SPEC_CTRL */
 
+#define MSR_AMD_CSTATE_CFG                  0xc0010296
+#define  CSTATE_CFG_CCR0_CC6EN              (_AC(1, ULL) <<  6)
+#define  CSTATE_CFG_CCR1_CC6EN              (_AC(1, ULL) << 14)
+#define  CSTATE_CFG_CCR2_CC6EN              (_AC(1, ULL) << 22)
+
 /*
  * Legacy MSR constants in need of cleanup.  No new MSRs below this comment.
  */
diff --git a/xen/include/xen/time.h b/xen/include/xen/time.h
index b7427460dd13..9ceaec541f4d 100644
--- a/xen/include/xen/time.h
+++ b/xen/include/xen/time.h
@@ -53,6 +53,7 @@ struct tm wallclock_time(uint64_t *ns);
 
 #define SYSTEM_TIME_HZ  1000000000ULL
 #define NOW()           ((s_time_t)get_s_time())
+#define DAYS(_d)        SECONDS((_d) * 86400ULL)
 #define SECONDS(_s)     ((s_time_t)((_s)  * 1000000000ULL))
 #define MILLISECS(_ms)  ((s_time_t)((_ms) * 1000000ULL))
 #define MICROSECS(_us)  ((s_time_t)((_us) * 1000ULL))
-- 
2.41.0




 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.