Re: [PATCH] x86/cpu/centaur: Disable X86_FEATURE_FSGSBASE on Zhaoxin C4600
From: Tony W Wang-oc
Date: Tue Mar 17 2026 - 03:41:55 EST
On 2026/3/12 23:52, Dave Hansen wrote:
On 3/11/26 19:14, Tony W Wang-oc wrote:Sorry, MSR 0x1232 is a Zhaoxin private MSR. Currently, this MSR is not documented in any public specification. It is used to store CPU manufacturing information.
So, I'm sorry but that's not really consistent how we're doing things
+ if (c->x86 == 6 && c->x86_model == 15 && c->x86_stepping >= 14) {
+ native_rdmsr(0x1232, dummy, chip_pf);
+ chip_pf = (chip_pf >> 15) & 0x7;
+ c->microcode = intel_get_microcode_revision();
+
+ if ((chip_pf == 0 && c->microcode < 0x20e) ||
+ (chip_pf == 1 && c->microcode < 0x208)) {
+ pr_warn_once("CPU has broken FSGSBASE support;
clear FSGSBASE feature\n");
+ setup_clear_cpu_cap(X86_FEATURE_FSGSBASE);
+ }
+ }
these days.
The model needs a symbolic name.
The MSR you're reading is completely undocumented and unnamed.
chip_pf retrieved from MSR 0x1232 represents the CPU product version.
"chip_pf" is nonsensical and unexplained.
Thank you for providing the example code.
Code is duplicated across the centaur and zhaoxin files.
Once you have all of that fixed, you should have a simple:
#define CENTAUR_MODEL_FOO VFM_MAKE(X86_VENDOR_CENTAUR, 6, 15)
#define ZHAOXIN_MODEL_BAR VFM_MAKE(X86_VENDOR_ZHAOXIN, 6, 25)
in a central header, plus:
struct x86_cpu_id *naughty_list[] = {
X86_MATCH_VFM_STEPS(CENTAUR_MODEL_FOO, 14, MAX_STEP, 0),
X86_MATCH_VFM_STEPS(ZHAOXIN_MODEL_BAR, MIN_STEP, 3, 0),
{}
};
void check_fsgsbase_bugs()
{
u32 fixed_ucode;
if (!cpu_feature_enabled(X86_FEATURE_FSGSBASE))
return;
c = x86_match_cpu(naughty_list);
if (!c)
return;
chip_pf = ...
if (chip_pf == 0)
fixed_ucode = 0x20e;
if (chip_pf == 1)
fixed_ucode = 0x208;
if (intel_get_microcode_revision() >= fixed_ucode)
return;
pr_warn_once("Broken FSGSBASE support, clearing feature\n");
setup_clear_cpu_cap(X86_FEATURE_FSGSBASE);
}
Then check_fsgsbase_bugs() can pretty much be called anywhere. It can
even be in generic code.
We are also getting some new matching fields in 'x86_cpu_id'. I suspect
'chip_pf' can be stored in there where Intel has the platform_id right
now. But you don't have to do that now.
Could you please go this route rather than copy-and-pasted chunks of
code sprinkled with a healthy dose of magic numbers?
Could you please take another look at the following patch to see if it's acceptable?
diff --git a/MAINTAINERS b/MAINTAINERS
index 364f0bec8748..42093a794056 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -29168,6 +29168,7 @@ ZHAOXIN PROCESSOR SUPPORT
M: Tony W Wang-oc <TonyWWang-oc@xxxxxxxxxxx>
L: linux-kernel@xxxxxxxxxxxxxxx
S: Maintained
+F: arch/x86/include/asm/zhaoxin.h
F: arch/x86/kernel/cpu/zhaoxin.c
ZONED BLOCK DEVICE (BLOCK LAYER)
diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
index be3e3cc963b2..dc71a4adc776 100644
--- a/arch/x86/include/asm/msr-index.h
+++ b/arch/x86/include/asm/msr-index.h
@@ -1306,5 +1306,7 @@
* disabling x2APIC will cause
* a #GP
*/
+/* ZHAOXIN defined MSRs*/
+#define MSR_ZHAOXIN_MFGID 0x00001232
#endif /* _ASM_X86_MSR_INDEX_H */
diff --git a/arch/x86/include/asm/zhaoxin.h b/arch/x86/include/asm/zhaoxin.h
new file mode 100644
index 000000000000..a3883bb149b4
--- /dev/null
+++ b/arch/x86/include/asm/zhaoxin.h
@@ -0,0 +1,48 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_X86_ZHAOXIN_H
+#define _ASM_X86_ZHAOXIN_H
+
+#include <asm/cpu_device_id.h>
+#include <asm/microcode.h>
+
+#define ZHAOXIN_MODEL_ZXC VFM_MAKE(X86_VENDOR_ZHAOXIN, 6, 25)
+#define CENTAUR_MODEL_ZXC VFM_MAKE(X86_VENDOR_CENTAUR, 6, 15)
+
+struct x86_cpu_id naughty_list[] = {
+ X86_MATCH_VFM_STEPS(ZHAOXIN_MODEL_ZXC, 0, 3, 0),
+ X86_MATCH_VFM_STEPS(CENTAUR_MODEL_ZXC, 14, 15, 0),
+ {}
+};
+
+void check_fsgsbase_bugs(void);
+
+void check_fsgsbase_bugs(void)
+{
+
+ u32 chip_pf, dummy, fixed_ucode;
+
+ if (!cpu_feature_enabled(X86_FEATURE_FSGSBASE))
+ return;
+
+ if (!x86_match_cpu(naughty_list))
+ return;
+
+ native_rdmsr(MSR_ZHAOXIN_MFGID, dummy, chip_pf);
+
+ /* chip_pf represents product version flag */
+ chip_pf = (chip_pf >> 15) & 0x7;
+
+ if (chip_pf == 0)
+ fixed_ucode = 0x20e;
+ if (chip_pf == 1)
+ fixed_ucode = 0x208;
+
+ if (intel_get_microcode_revision() >= fixed_ucode)
+ return;
+
+ pr_warn_once("Broken FSGSBASE support, clearing feature\n");
+ setup_clear_cpu_cap(X86_FEATURE_FSGSBASE);
+}
+
+#endif
+
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 1c3261cae40c..fe24830a47aa 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -73,6 +73,7 @@
#include <asm/tdx.h>
#include <asm/posted_intr.h>
#include <asm/runtime-const.h>
+#include <asm/zhaoxin.h>
#include "cpu.h"
@@ -2047,6 +2048,8 @@ static void identify_cpu(struct cpuinfo_x86 *c)
setup_umip(c);
setup_lass(c);
+ check_fsgsbase_bugs();
+
/* Enable FSGSBASE instructions if available. */
if (cpu_has(c, X86_FEATURE_FSGSBASE)) {
cr4_set_bits(X86_CR4_FSGSBASE);