Commit ecb9194d authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
parents b9e62a2b c44572e0
Loading
Loading
Loading
Loading
+2 −3
Original line number Diff line number Diff line
@@ -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;
}
+2 −1
Original line number Diff line number Diff line
@@ -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
+41 −30
Original line number Diff line number Diff line
@@ -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
@@ -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
+0 −7
Original line number Diff line number Diff line
@@ -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
+4 −0
Original line number Diff line number Diff line
@@ -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();
@@ -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++) {
Loading