961c6a4326
The mtrr_value[] array is a static variable which is used only in a few configurations. Consuming 6kB is ridiculous for this case, especially as the array doesn't need to be that large and it can easily be allocated dynamically. Signed-off-by: Juergen Gross <jgross@suse.com> Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de> Tested-by: Michael Kelley <mikelley@microsoft.com> Link: https://lore.kernel.org/r/20230502120931.20719-10-jgross@suse.com Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
91 lines
1.9 KiB
C
91 lines
1.9 KiB
C
// SPDX-License-Identifier: GPL-2.0-only
|
|
|
|
#include <linux/types.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/syscore_ops.h>
|
|
#include <asm/cpufeature.h>
|
|
#include <asm/mtrr.h>
|
|
#include <asm/processor.h>
|
|
#include "mtrr.h"
|
|
|
|
void mtrr_set_if(void)
|
|
{
|
|
switch (boot_cpu_data.x86_vendor) {
|
|
case X86_VENDOR_AMD:
|
|
/* Pre-Athlon (K6) AMD CPU MTRRs */
|
|
if (cpu_feature_enabled(X86_FEATURE_K6_MTRR))
|
|
mtrr_if = &amd_mtrr_ops;
|
|
break;
|
|
case X86_VENDOR_CENTAUR:
|
|
if (cpu_feature_enabled(X86_FEATURE_CENTAUR_MCR))
|
|
mtrr_if = ¢aur_mtrr_ops;
|
|
break;
|
|
case X86_VENDOR_CYRIX:
|
|
if (cpu_feature_enabled(X86_FEATURE_CYRIX_ARR))
|
|
mtrr_if = &cyrix_mtrr_ops;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* The suspend/resume methods are only for CPUs without MTRR. CPUs using generic
|
|
* MTRR driver don't require this.
|
|
*/
|
|
struct mtrr_value {
|
|
mtrr_type ltype;
|
|
unsigned long lbase;
|
|
unsigned long lsize;
|
|
};
|
|
|
|
static struct mtrr_value *mtrr_value;
|
|
|
|
static int mtrr_save(void)
|
|
{
|
|
int i;
|
|
|
|
if (!mtrr_value)
|
|
return -ENOMEM;
|
|
|
|
for (i = 0; i < num_var_ranges; i++) {
|
|
mtrr_if->get(i, &mtrr_value[i].lbase,
|
|
&mtrr_value[i].lsize,
|
|
&mtrr_value[i].ltype);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static void mtrr_restore(void)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < num_var_ranges; i++) {
|
|
if (mtrr_value[i].lsize) {
|
|
mtrr_if->set(i, mtrr_value[i].lbase,
|
|
mtrr_value[i].lsize,
|
|
mtrr_value[i].ltype);
|
|
}
|
|
}
|
|
}
|
|
|
|
static struct syscore_ops mtrr_syscore_ops = {
|
|
.suspend = mtrr_save,
|
|
.resume = mtrr_restore,
|
|
};
|
|
|
|
void mtrr_register_syscore(void)
|
|
{
|
|
mtrr_value = kcalloc(num_var_ranges, sizeof(*mtrr_value), GFP_KERNEL);
|
|
|
|
/*
|
|
* The CPU has no MTRR and seems to not support SMP. They have
|
|
* specific drivers, we use a tricky method to support
|
|
* suspend/resume for them.
|
|
*
|
|
* TBD: is there any system with such CPU which supports
|
|
* suspend/resume? If no, we should remove the code.
|
|
*/
|
|
register_syscore_ops(&mtrr_syscore_ops);
|
|
}
|