rpm/SOURCES/2536.patch

120 lines
3.9 KiB
Diff
Raw Normal View History

2024-11-22 09:43:36 +00:00
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)
{