Commit 92cff2f9 authored by Muralidhara M K's avatar Muralidhara M K Committed by Pu Wen
Browse files

x86/MCE/AMD: Use an u64 for bank_map

stable inclusion
from stable-v5.10.180
commit 4c1cdec3
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I7DX6V
CVE: NA

Reference: https://git.kernel.org/torvalds/c/4c1cdec319b9aadb65737c3eb1f5cb74bd6aa156



---------------------------

commit 4c1cdec3 upstream.

Thee maximum number of MCA banks is 64 (MAX_NR_BANKS), see

  a0bc32b3 ("x86/mce: Increase maximum number of banks to 64").

However, the bank_map which contains a bitfield of which banks to
initialize is of type unsigned int and that overflows when those bit
numbers are >= 32, leading to UBSAN complaining correctly:

  UBSAN: shift-out-of-bounds in arch/x86/kernel/cpu/mce/amd.c:1365:38
  shift exponent 32 is too large for 32-bit type 'int'

Change the bank_map to a u64 and use the proper BIT_ULL() macro when
modifying bits in there.

  [ bp: Rewrite commit message. ]

Fixes: a0bc32b3 ("x86/mce: Increase maximum number of banks to 64")
Signed-off-by: default avatarMuralidhara M K <muralimk@amd.com>
Signed-off-by: default avatarBorislav Petkov (AMD) <bp@alien8.de>
Link: https://lore.kernel.org/r/20230127151601.1068324-1-muralimk@amd.com


Signed-off-by: default avatarPu Wen <puwen@hygon.cn>
parent 2b1b5c1d
Loading
Loading
Loading
Loading
+7 −7
Original line number Original line Diff line number Diff line
@@ -235,10 +235,10 @@ static DEFINE_PER_CPU(struct threshold_bank **, threshold_banks);
 * A list of the banks enabled on each logical CPU. Controls which respective
 * A list of the banks enabled on each logical CPU. Controls which respective
 * descriptors to initialize later in mce_threshold_create_device().
 * descriptors to initialize later in mce_threshold_create_device().
 */
 */
static DEFINE_PER_CPU(unsigned int, bank_map);
static DEFINE_PER_CPU(u64, bank_map);


/* Map of banks that have more than MCA_MISC0 available. */
/* Map of banks that have more than MCA_MISC0 available. */
static DEFINE_PER_CPU(u32, smca_misc_banks_map);
static DEFINE_PER_CPU(u64, smca_misc_banks_map);


static void amd_threshold_interrupt(void);
static void amd_threshold_interrupt(void);
static void amd_deferred_error_interrupt(void);
static void amd_deferred_error_interrupt(void);
@@ -267,7 +267,7 @@ static void smca_set_misc_banks_map(unsigned int bank, unsigned int cpu)
		return;
		return;


	if (low & MASK_BLKPTR_LO)
	if (low & MASK_BLKPTR_LO)
		per_cpu(smca_misc_banks_map, cpu) |= BIT(bank);
		per_cpu(smca_misc_banks_map, cpu) |= BIT_ULL(bank);


}
}


@@ -528,7 +528,7 @@ static u32 smca_get_block_address(unsigned int bank, unsigned int block,
	if (!block)
	if (!block)
		return MSR_AMD64_SMCA_MCx_MISC(bank);
		return MSR_AMD64_SMCA_MCx_MISC(bank);


	if (!(per_cpu(smca_misc_banks_map, cpu) & BIT(bank)))
	if (!(per_cpu(smca_misc_banks_map, cpu) & BIT_ULL(bank)))
		return 0;
		return 0;


	return MSR_AMD64_SMCA_MCx_MISCy(bank, block - 1);
	return MSR_AMD64_SMCA_MCx_MISCy(bank, block - 1);
@@ -572,7 +572,7 @@ prepare_threshold_block(unsigned int bank, unsigned int block, u32 addr,
	int new;
	int new;


	if (!block)
	if (!block)
		per_cpu(bank_map, cpu) |= (1 << bank);
		per_cpu(bank_map, cpu) |= BIT_ULL(bank);


	memset(&b, 0, sizeof(b));
	memset(&b, 0, sizeof(b));
	b.cpu			= cpu;
	b.cpu			= cpu;
@@ -884,7 +884,7 @@ static void amd_threshold_interrupt(void)
		return;
		return;


	for (bank = 0; bank < this_cpu_read(mce_num_banks); ++bank) {
	for (bank = 0; bank < this_cpu_read(mce_num_banks); ++bank) {
		if (!(per_cpu(bank_map, cpu) & (1 << bank)))
		if (!(per_cpu(bank_map, cpu) & BIT_ULL(bank)))
			continue;
			continue;


		first_block = bp[bank]->blocks;
		first_block = bp[bank]->blocks;
@@ -1361,7 +1361,7 @@ int mce_threshold_create_device(unsigned int cpu)
		return -ENOMEM;
		return -ENOMEM;


	for (bank = 0; bank < numbanks; ++bank) {
	for (bank = 0; bank < numbanks; ++bank) {
		if (!(this_cpu_read(bank_map) & (1 << bank)))
		if (!(this_cpu_read(bank_map) & BIT_ULL(bank)))
			continue;
			continue;
		err = threshold_create_bank(bp, cpu, bank);
		err = threshold_create_bank(bp, cpu, bank);
		if (err) {
		if (err) {