Skip to content

Commit

Permalink
Merge tag 'mips-fixes_6.15_1' of git://git.kernel.org/pub/scm/linux/k…
Browse files Browse the repository at this point in the history
…ernel/git/mips/linux

Pull MIPS fixes from Thomas Bogendoerfer:

 - Fix delayed timers

 - Fix NULL pointer deref

 - Fix wrong range check

* tag 'mips-fixes_6.15_1' of git://git.kernel.org/pub/scm/linux/kernel/git/mips/linux:
  MIPS: Fix MAX_REG_OFFSET
  MIPS: CPS: Fix potential NULL pointer dereferences in cps_prepare_cpus()
  MIPS: rename rollback_handler with skipover_handler
  MIPS: Move r4k_wait() to .cpuidle.text section
  MIPS: Fix idle VS timer enqueue
  • Loading branch information
Linus Torvalds committed May 11, 2025
2 parents b9e62a2 + c44572e commit ecb9194
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 46 deletions.
5 changes: 2 additions & 3 deletions arch/mips/include/asm/idle.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,10 @@
#include <linux/linkage.h>

extern void (*cpu_wait)(void);
extern void r4k_wait(void);
extern asmlinkage void __r4k_wait(void);
extern asmlinkage void r4k_wait(void);
extern void r4k_wait_irqoff(void);

static inline int using_rollback_handler(void)
static inline int using_skipover_handler(void)
{
return cpu_wait == r4k_wait;
}
Expand Down
3 changes: 2 additions & 1 deletion arch/mips/include/asm/ptrace.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,8 @@ static inline void instruction_pointer_set(struct pt_regs *regs,

/* Query offset/name of register from its name/offset */
extern int regs_query_register_offset(const char *name);
#define MAX_REG_OFFSET (offsetof(struct pt_regs, __last))
#define MAX_REG_OFFSET \
(offsetof(struct pt_regs, __last) - sizeof(unsigned long))

/**
* regs_get_register() - get register value from its offset
Expand Down
71 changes: 41 additions & 30 deletions arch/mips/kernel/genex.S
Original file line number Diff line number Diff line change
Expand Up @@ -104,48 +104,59 @@ handle_vcei:

__FINIT

.align 5 /* 32 byte rollback region */
LEAF(__r4k_wait)
.set push
.set noreorder
/* start of rollback region */
LONG_L t0, TI_FLAGS($28)
nop
andi t0, _TIF_NEED_RESCHED
bnez t0, 1f
nop
nop
nop
#ifdef CONFIG_CPU_MICROMIPS
nop
nop
nop
nop
#endif
.section .cpuidle.text,"ax"
/* Align to 32 bytes for the maximum idle interrupt region size. */
.align 5
LEAF(r4k_wait)
/* Keep the ISA bit clear for calculations on local labels here. */
0: .fill 0
/* Start of idle interrupt region. */
local_irq_enable
/*
* If an interrupt lands here, before going idle on the next
* instruction, we must *NOT* go idle since the interrupt could
* have set TIF_NEED_RESCHED or caused a timer to need resched.
* Fall through -- see skipover_handler below -- and have the
* idle loop take care of things.
*/
1: .fill 0
/* The R2 EI/EHB sequence takes 8 bytes, otherwise pad up. */
.if 1b - 0b > 32
.error "overlong idle interrupt region"
.elseif 1b - 0b > 8
.align 4
.endif
2: .fill 0
.equ r4k_wait_idle_size, 2b - 0b
/* End of idle interrupt region; size has to be a power of 2. */
.set MIPS_ISA_ARCH_LEVEL_RAW
r4k_wait_insn:
wait
/* end of rollback region (the region size must be power of two) */
1:
r4k_wait_exit:
.set mips0
local_irq_disable
jr ra
nop
.set pop
END(__r4k_wait)
END(r4k_wait)
.previous

.macro BUILD_ROLLBACK_PROLOGUE handler
FEXPORT(rollback_\handler)
.macro BUILD_SKIPOVER_PROLOGUE handler
FEXPORT(skipover_\handler)
.set push
.set noat
MFC0 k0, CP0_EPC
PTR_LA k1, __r4k_wait
ori k0, 0x1f /* 32 byte rollback region */
xori k0, 0x1f
/* Subtract/add 2 to let the ISA bit propagate through the mask. */
PTR_LA k1, r4k_wait_insn - 2
ori k0, r4k_wait_idle_size - 2
.set noreorder
bne k0, k1, \handler
PTR_ADDIU k0, r4k_wait_exit - r4k_wait_insn + 2
.set reorder
MTC0 k0, CP0_EPC
.set pop
.endm

.align 5
BUILD_ROLLBACK_PROLOGUE handle_int
BUILD_SKIPOVER_PROLOGUE handle_int
NESTED(handle_int, PT_SIZE, sp)
.cfi_signal_frame
#ifdef CONFIG_TRACE_IRQFLAGS
Expand Down Expand Up @@ -265,7 +276,7 @@ NESTED(except_vec_ejtag_debug, 0, sp)
* This prototype is copied to ebase + n*IntCtl.VS and patched
* to invoke the handler
*/
BUILD_ROLLBACK_PROLOGUE except_vec_vi
BUILD_SKIPOVER_PROLOGUE except_vec_vi
NESTED(except_vec_vi, 0, sp)
SAVE_SOME docfi=1
SAVE_AT docfi=1
Expand Down
7 changes: 0 additions & 7 deletions arch/mips/kernel/idle.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,6 @@ static void __cpuidle r3081_wait(void)
write_c0_conf(cfg | R30XX_CONF_HALT);
}

void __cpuidle r4k_wait(void)
{
raw_local_irq_enable();
__r4k_wait();
raw_local_irq_disable();
}

/*
* This variant is preferable as it allows testing need_resched and going to
* sleep depending on the outcome atomically. Unfortunately the "It is
Expand Down
4 changes: 4 additions & 0 deletions arch/mips/kernel/smp-cps.c
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,8 @@ static void __init cps_prepare_cpus(unsigned int max_cpus)
mips_cps_cluster_bootcfg = kcalloc(nclusters,
sizeof(*mips_cps_cluster_bootcfg),
GFP_KERNEL);
if (!mips_cps_cluster_bootcfg)
goto err_out;

if (nclusters > 1)
mips_cm_update_property();
Expand All @@ -348,6 +350,8 @@ static void __init cps_prepare_cpus(unsigned int max_cpus)
mips_cps_cluster_bootcfg[cl].core_power =
kcalloc(BITS_TO_LONGS(ncores), sizeof(unsigned long),
GFP_KERNEL);
if (!mips_cps_cluster_bootcfg[cl].core_power)
goto err_out;

/* Allocate VPE boot configuration structs */
for (c = 0; c < ncores; c++) {
Expand Down
10 changes: 5 additions & 5 deletions arch/mips/kernel/traps.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@
#include "access-helper.h"

extern void check_wait(void);
extern asmlinkage void rollback_handle_int(void);
extern asmlinkage void skipover_handle_int(void);
extern asmlinkage void handle_int(void);
extern asmlinkage void handle_adel(void);
extern asmlinkage void handle_ades(void);
Expand Down Expand Up @@ -2066,7 +2066,7 @@ void *set_vi_handler(int n, vi_handler_t addr)
{
extern const u8 except_vec_vi[];
extern const u8 except_vec_vi_ori[], except_vec_vi_end[];
extern const u8 rollback_except_vec_vi[];
extern const u8 skipover_except_vec_vi[];
unsigned long handler;
unsigned long old_handler = vi_handlers[n];
int srssets = current_cpu_data.srsets;
Expand Down Expand Up @@ -2095,7 +2095,7 @@ void *set_vi_handler(int n, vi_handler_t addr)
change_c0_srsmap(0xf << n*4, 0 << n*4);
}

vec_start = using_rollback_handler() ? rollback_except_vec_vi :
vec_start = using_skipover_handler() ? skipover_except_vec_vi :
except_vec_vi;
#if defined(CONFIG_CPU_MICROMIPS) || defined(CONFIG_CPU_BIG_ENDIAN)
ori_offset = except_vec_vi_ori - vec_start + 2;
Expand Down Expand Up @@ -2426,8 +2426,8 @@ void __init trap_init(void)
if (board_be_init)
board_be_init();

set_except_vector(EXCCODE_INT, using_rollback_handler() ?
rollback_handle_int : handle_int);
set_except_vector(EXCCODE_INT, using_skipover_handler() ?
skipover_handle_int : handle_int);
set_except_vector(EXCCODE_MOD, handle_tlbm);
set_except_vector(EXCCODE_TLBL, handle_tlbl);
set_except_vector(EXCCODE_TLBS, handle_tlbs);
Expand Down

0 comments on commit ecb9194

Please sign in to comment.