120 lines
3.9 KiB
Diff
120 lines
3.9 KiB
Diff
From 65ae8d101f18e9d85b5e8d91f0d164117d811914 Mon Sep 17 00:00:00 2001
|
|
From: Arun Ajith S <aajith@arista.com>
|
|
Date: Tue, 6 Jun 2023 07:20:06 -0700
|
|
Subject: [PATCH] rpmrc: Fix how x86 models are derived
|
|
|
|
The code to autodetect x86 CPU model runs the cpuid instruction after
|
|
setting up 1 in eax. This gives the processor signature back in eax
|
|
which encodes the model number.
|
|
|
|
As per Intel Application Note 485 and AMD publication #25481, when
|
|
deriving model, we should look at both the base model in eax[7:4] and
|
|
the extended model in eax[19:16]. However current code is only looking
|
|
at base model and this causes some newer CPUs like Icelake(Model 0x6a)
|
|
to be detected wrongly as Pentium 3(Model 0x0a).
|
|
|
|
Note that this code is only exercised when rpm is built as 32-bit
|
|
binary because all of this is within a `#if defined(__i386__)`.
|
|
|
|
Because of this misdetection on Icelake, `setarch x86_64 rpm --showrc`
|
|
has `pentium3` as the `installed arch` instead of the expected `x86_64`.
|
|
It doesn't have `x86_64` as one of the `compatible archs` as expected.
|
|
Attempting to install a x86_64 rpm with `setarch x86_64 rpm -i` is
|
|
failing with `is intended for a different architecture` errors.
|
|
|
|
```
|
|
ARCHITECTURE AND OS:
|
|
build arch : i386
|
|
compatible build archs: pentium3 i686 i586 i486 i386 noarch fat
|
|
build os : Linux
|
|
compatible build os's : Linux
|
|
install arch : pentium3
|
|
install os : Linux
|
|
compatible archs : pentium3 i686 i586 i486 i386 noarch fat
|
|
compatible os's : Linux
|
|
```
|
|
|
|
Fix the code to also consider extended model and extended family when
|
|
applicable. The implementation is similar to the one in the linuxi
|
|
kernel.
|
|
|
|
References:
|
|
https://www.scss.tcd.ie/~jones/CS4021/processor-identification-cpuid-instruction-note.pdf
|
|
https://www.amd.com/system/files/TechDocs/25481.pdf
|
|
https://elixir.bootlin.com/linux/v6.3.6/source/arch/x86/lib/cpu.c#L19
|
|
|
|
Fixes: #2535
|
|
---
|
|
lib/rpmrc.c | 37 +++++++++++++++++++++++++++++++------
|
|
1 file changed, 31 insertions(+), 6 deletions(-)
|
|
|
|
diff --git a/lib/rpmrc.c b/lib/rpmrc.c
|
|
index e5ddeb0916..8e77ca5458 100644
|
|
--- a/lib/rpmrc.c
|
|
+++ b/lib/rpmrc.c
|
|
@@ -933,6 +933,31 @@ static int is_athlon(void)
|
|
return 1;
|
|
}
|
|
|
|
+static unsigned int x86_family(unsigned int processor_sig)
|
|
+{
|
|
+ unsigned int base_family = (processor_sig >> 8) & 0x0f;
|
|
+ unsigned int family;
|
|
+ if (base_family == 0x0f) {
|
|
+ unsigned int extended_family = (processor_sig >> 20) & 0x0ff;
|
|
+ family = base_family + extended_family;
|
|
+ } else
|
|
+ family = base_family;
|
|
+ return family;
|
|
+}
|
|
+
|
|
+static unsigned int x86_model(unsigned int processor_sig)
|
|
+{
|
|
+ unsigned int base_model = (processor_sig >> 4) & 0x0f;
|
|
+ unsigned int family = x86_family(processor_sig);
|
|
+ unsigned int model;
|
|
+ if (family >= 0x6) {
|
|
+ unsigned int extended_model = (processor_sig >> 16) & 0x0f;
|
|
+ model = (extended_model << 4) | base_model;
|
|
+ } else
|
|
+ model = base_model;
|
|
+ return model;
|
|
+}
|
|
+
|
|
static int is_pentium3(void)
|
|
{
|
|
unsigned int eax, ebx, ecx, edx, family, model;
|
|
@@ -945,8 +970,8 @@ static int is_pentium3(void)
|
|
if (!rstreqn(vendor, "GenuineIntel", 12))
|
|
return 0;
|
|
cpuid(1, &eax, &ebx, &ecx, &edx);
|
|
- family = (eax >> 8) & 0x0f;
|
|
- model = (eax >> 4) & 0x0f;
|
|
+ family = x86_family(eax);
|
|
+ model = x86_model(eax);
|
|
if (family == 6)
|
|
switch (model)
|
|
{
|
|
@@ -972,8 +997,8 @@ static int is_pentium4(void)
|
|
if (!rstreqn(vendor, "GenuineIntel", 12))
|
|
return 0;
|
|
cpuid(1, &eax, &ebx, &ecx, &edx);
|
|
- family = (eax >> 8) & 0x0f;
|
|
- model = (eax >> 4) & 0x0f;
|
|
+ family = x86_family(eax);
|
|
+ model = x86_model(eax);
|
|
if (family == 15)
|
|
switch (model)
|
|
{
|
|
@@ -1002,8 +1027,8 @@ static int is_geode(void)
|
|
if (!rstreqn(vendor, "AuthenticAMD", 12))
|
|
return 0;
|
|
cpuid(1, &eax, &ebx, &ecx, &edx);
|
|
- family = (eax >> 8) & 0x0f;
|
|
- model = (eax >> 4) & 0x0f;
|
|
+ family = x86_family(eax);
|
|
+ model = x86_model(eax);
|
|
if (family == 5)
|
|
switch (model)
|
|
{
|