2023-12-21 12:59:33

by Thomas Bogendoerfer

[permalink] [raw]
Subject: [PATCH 1/2] MIPS: Allow vectored interrupt handler to reside everywhere for 64bit

Setting up vector interrupts worked only with handlers, which resided
in CKSEG0 space. This limits the kernel placement for 64bit platforms.
By patching in the offset into vi_handlers[] instead of the full
handler address, the vectored exception handler can load the
address by itself and jump to it.

Signed-off-by: Thomas Bogendoerfer <[email protected]>
---
arch/mips/kernel/genex.S | 8 ++++----
arch/mips/kernel/traps.c | 9 +++------
2 files changed, 7 insertions(+), 10 deletions(-)

diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S
index b6de8e88c1bd..a572ce36a24f 100644
--- a/arch/mips/kernel/genex.S
+++ b/arch/mips/kernel/genex.S
@@ -272,18 +272,17 @@ NESTED(except_vec_vi, 0, sp)
.set push
.set noreorder
PTR_LA v1, except_vec_vi_handler
-FEXPORT(except_vec_vi_lui)
- lui v0, 0 /* Patched */
jr v1
FEXPORT(except_vec_vi_ori)
- ori v0, 0 /* Patched */
+ ori v0, zero, 0 /* Offset in vi_handlers[] */
.set pop
END(except_vec_vi)
EXPORT(except_vec_vi_end)

/*
* Common Vectored Interrupt code
- * Complete the register saves and invoke the handler which is passed in $v0
+ * Complete the register saves and invoke the handler, $v0 holds
+ * offset into vi_handlers[]
*/
NESTED(except_vec_vi_handler, 0, sp)
SAVE_TEMP
@@ -331,6 +330,7 @@ NESTED(except_vec_vi_handler, 0, sp)
/* Save task's sp on IRQ stack so that unwinding can follow it */
LONG_S s1, 0(sp)
2:
+ PTR_L v0, vi_handlers(v0)
jalr v0

/* Restore sp */
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 246c6a6b0261..d90b18908692 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -2091,16 +2091,14 @@ static void *set_vi_srs_handler(int n, vi_handler_t addr, int srs)
* If no shadow set is selected then use the default handler
* that does normal register saving and standard interrupt exit
*/
- extern const u8 except_vec_vi[], except_vec_vi_lui[];
+ extern const u8 except_vec_vi[];
extern const u8 except_vec_vi_ori[], except_vec_vi_end[];
extern const u8 rollback_except_vec_vi[];
const u8 *vec_start = using_rollback_handler() ?
rollback_except_vec_vi : except_vec_vi;
#if defined(CONFIG_CPU_MICROMIPS) || defined(CONFIG_CPU_BIG_ENDIAN)
- const int lui_offset = except_vec_vi_lui - vec_start + 2;
const int ori_offset = except_vec_vi_ori - vec_start + 2;
#else
- const int lui_offset = except_vec_vi_lui - vec_start;
const int ori_offset = except_vec_vi_ori - vec_start;
#endif
const int handler_len = except_vec_vi_end - vec_start;
@@ -2119,10 +2117,9 @@ static void *set_vi_srs_handler(int n, vi_handler_t addr, int srs)
#else
handler_len);
#endif
- h = (u16 *)(b + lui_offset);
- *h = (handler >> 16) & 0xffff;
+ /* insert offset into vi_handlers[] */
h = (u16 *)(b + ori_offset);
- *h = (handler & 0xffff);
+ *h = n * sizeof(handler);
local_flush_icache_range((unsigned long)b,
(unsigned long)(b+handler_len));
}
--
2.35.3



2023-12-21 12:59:51

by Thomas Bogendoerfer

[permalink] [raw]
Subject: [PATCH 2/2] MIPS: Remove unused shadow GPR support from vector irq setup

Using shadow GPRs for vectored interrupts has never been used,
time to remove it.

Signed-off-by: Thomas Bogendoerfer <[email protected]>
---
arch/mips/kernel/traps.c | 94 +++++++++++++---------------------------
1 file changed, 30 insertions(+), 64 deletions(-)

diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index d90b18908692..c1b2b18b0505 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -2055,105 +2055,71 @@ static void do_default_vi(void)
panic("Caught unexpected vectored interrupt.");
}

-static void *set_vi_srs_handler(int n, vi_handler_t addr, int srs)
+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[];
unsigned long handler;
unsigned long old_handler = vi_handlers[n];
int srssets = current_cpu_data.srsets;
u16 *h;
unsigned char *b;
+ const u8 *vec_start;
+ int ori_offset;
+ int handler_len;

BUG_ON(!cpu_has_veic && !cpu_has_vint);

if (addr == NULL) {
handler = (unsigned long) do_default_vi;
- srs = 0;
} else
handler = (unsigned long) addr;
vi_handlers[n] = handler;

b = (unsigned char *)(ebase + 0x200 + n*VECTORSPACING);

- if (srs >= srssets)
- panic("Shadow register set %d not supported", srs);
-
if (cpu_has_veic) {
if (board_bind_eic_interrupt)
- board_bind_eic_interrupt(n, srs);
+ board_bind_eic_interrupt(n, 0);
} else if (cpu_has_vint) {
/* SRSMap is only defined if shadow sets are implemented */
if (srssets > 1)
- change_c0_srsmap(0xf << n*4, srs << n*4);
+ change_c0_srsmap(0xf << n*4, 0 << n*4);
}

- if (srs == 0) {
- /*
- * If no shadow set is selected then use the default handler
- * that does normal register saving and standard interrupt exit
- */
- extern const u8 except_vec_vi[];
- extern const u8 except_vec_vi_ori[], except_vec_vi_end[];
- extern const u8 rollback_except_vec_vi[];
- const u8 *vec_start = using_rollback_handler() ?
- rollback_except_vec_vi : except_vec_vi;
+ vec_start = using_rollback_handler() ? rollback_except_vec_vi :
+ except_vec_vi;
#if defined(CONFIG_CPU_MICROMIPS) || defined(CONFIG_CPU_BIG_ENDIAN)
- const int ori_offset = except_vec_vi_ori - vec_start + 2;
+ ori_offset = except_vec_vi_ori - vec_start + 2;
#else
- const int ori_offset = except_vec_vi_ori - vec_start;
+ ori_offset = except_vec_vi_ori - vec_start;
#endif
- const int handler_len = except_vec_vi_end - vec_start;
+ handler_len = except_vec_vi_end - vec_start;

- if (handler_len > VECTORSPACING) {
- /*
- * Sigh... panicing won't help as the console
- * is probably not configured :(
- */
- panic("VECTORSPACING too small");
- }
-
- set_handler(((unsigned long)b - ebase), vec_start,
-#ifdef CONFIG_CPU_MICROMIPS
- (handler_len - 1));
-#else
- handler_len);
-#endif
- /* insert offset into vi_handlers[] */
- h = (u16 *)(b + ori_offset);
- *h = n * sizeof(handler);
- local_flush_icache_range((unsigned long)b,
- (unsigned long)(b+handler_len));
- }
- else {
+ if (handler_len > VECTORSPACING) {
/*
- * In other cases jump directly to the interrupt handler. It
- * is the handler's responsibility to save registers if required
- * (eg hi/lo) and return from the exception using "eret".
+ * Sigh... panicing won't help as the console
+ * is probably not configured :(
*/
- u32 insn;
-
- h = (u16 *)b;
- /* j handler */
-#ifdef CONFIG_CPU_MICROMIPS
- insn = 0xd4000000 | (((u32)handler & 0x07ffffff) >> 1);
-#else
- insn = 0x08000000 | (((u32)handler & 0x0fffffff) >> 2);
-#endif
- h[0] = (insn >> 16) & 0xffff;
- h[1] = insn & 0xffff;
- h[2] = 0;
- h[3] = 0;
- local_flush_icache_range((unsigned long)b,
- (unsigned long)(b+8));
+ panic("VECTORSPACING too small");
}

+ set_handler(((unsigned long)b - ebase), vec_start,
+#ifdef CONFIG_CPU_MICROMIPS
+ (handler_len - 1));
+#else
+ handler_len);
+#endif
+ /* insert offset into vi_handlers[] */
+ h = (u16 *)(b + ori_offset);
+ *h = n * sizeof(handler);
+ local_flush_icache_range((unsigned long)b,
+ (unsigned long)(b+handler_len));
+
return (void *)old_handler;
}

-void *set_vi_handler(int n, vi_handler_t addr)
-{
- return set_vi_srs_handler(n, addr, 0);
-}
-
extern void tlb_init(void);

/*
--
2.35.3


2023-12-22 12:59:09

by Jiaxun Yang

[permalink] [raw]
Subject: Re: [PATCH 1/2] MIPS: Allow vectored interrupt handler to reside everywhere for 64bit



在 2023/12/21 12:54, Thomas Bogendoerfer 写道:
> Setting up vector interrupts worked only with handlers, which resided
> in CKSEG0 space. This limits the kernel placement for 64bit platforms.
> By patching in the offset into vi_handlers[] instead of the full
> handler address, the vectored exception handler can load the
> address by itself and jump to it.
>
> Signed-off-by: Thomas Bogendoerfer <[email protected]>

Reviewed-by: Jiaxun Yang <[email protected]>

Could you please keep me in Cc if you are going to propose a better
solution :-)

Thanks
- Jiaxun

> ---
> arch/mips/kernel/genex.S | 8 ++++----
> arch/mips/kernel/traps.c | 9 +++------
> 2 files changed, 7 insertions(+), 10 deletions(-)
>
> diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S
> index b6de8e88c1bd..a572ce36a24f 100644
> --- a/arch/mips/kernel/genex.S
> +++ b/arch/mips/kernel/genex.S
> @@ -272,18 +272,17 @@ NESTED(except_vec_vi, 0, sp)
> .set push
> .set noreorder
> PTR_LA v1, except_vec_vi_handler
> -FEXPORT(except_vec_vi_lui)
> - lui v0, 0 /* Patched */
> jr v1
> FEXPORT(except_vec_vi_ori)
> - ori v0, 0 /* Patched */
> + ori v0, zero, 0 /* Offset in vi_handlers[] */
> .set pop
> END(except_vec_vi)
> EXPORT(except_vec_vi_end)
>
> /*
> * Common Vectored Interrupt code
> - * Complete the register saves and invoke the handler which is passed in $v0
> + * Complete the register saves and invoke the handler, $v0 holds
> + * offset into vi_handlers[]
> */
> NESTED(except_vec_vi_handler, 0, sp)
> SAVE_TEMP
> @@ -331,6 +330,7 @@ NESTED(except_vec_vi_handler, 0, sp)
> /* Save task's sp on IRQ stack so that unwinding can follow it */
> LONG_S s1, 0(sp)
> 2:
> + PTR_L v0, vi_handlers(v0)
> jalr v0
>
> /* Restore sp */
> diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
> index 246c6a6b0261..d90b18908692 100644
> --- a/arch/mips/kernel/traps.c
> +++ b/arch/mips/kernel/traps.c
> @@ -2091,16 +2091,14 @@ static void *set_vi_srs_handler(int n, vi_handler_t addr, int srs)
> * If no shadow set is selected then use the default handler
> * that does normal register saving and standard interrupt exit
> */
> - extern const u8 except_vec_vi[], except_vec_vi_lui[];
> + extern const u8 except_vec_vi[];
> extern const u8 except_vec_vi_ori[], except_vec_vi_end[];
> extern const u8 rollback_except_vec_vi[];
> const u8 *vec_start = using_rollback_handler() ?
> rollback_except_vec_vi : except_vec_vi;
> #if defined(CONFIG_CPU_MICROMIPS) || defined(CONFIG_CPU_BIG_ENDIAN)
> - const int lui_offset = except_vec_vi_lui - vec_start + 2;
> const int ori_offset = except_vec_vi_ori - vec_start + 2;
> #else
> - const int lui_offset = except_vec_vi_lui - vec_start;
> const int ori_offset = except_vec_vi_ori - vec_start;
> #endif
> const int handler_len = except_vec_vi_end - vec_start;
> @@ -2119,10 +2117,9 @@ static void *set_vi_srs_handler(int n, vi_handler_t addr, int srs)
> #else
> handler_len);
> #endif
> - h = (u16 *)(b + lui_offset);
> - *h = (handler >> 16) & 0xffff;
> + /* insert offset into vi_handlers[] */
> h = (u16 *)(b + ori_offset);
> - *h = (handler & 0xffff);
> + *h = n * sizeof(handler);
> local_flush_icache_range((unsigned long)b,
> (unsigned long)(b+handler_len));
> }


2023-12-30 15:39:30

by Thomas Bogendoerfer

[permalink] [raw]
Subject: Re: [PATCH 2/2] MIPS: Remove unused shadow GPR support from vector irq setup

On Thu, Dec 21, 2023 at 01:54:04PM +0100, Thomas Bogendoerfer wrote:
> Using shadow GPRs for vectored interrupts has never been used,
> time to remove it.
>
> Signed-off-by: Thomas Bogendoerfer <[email protected]>
> ---
> arch/mips/kernel/traps.c | 94 +++++++++++++---------------------------
> 1 file changed, 30 insertions(+), 64 deletions(-)

applied to mips-next.

Thomas.

--
Crap can work. Given enough thrust pigs will fly, but it's not necessarily a
good idea. [ RFC1925, 2.3 ]

2023-12-30 15:40:01

by Thomas Bogendoerfer

[permalink] [raw]
Subject: Re: [PATCH 1/2] MIPS: Allow vectored interrupt handler to reside everywhere for 64bit

On Thu, Dec 21, 2023 at 01:54:03PM +0100, Thomas Bogendoerfer wrote:
> Setting up vector interrupts worked only with handlers, which resided
> in CKSEG0 space. This limits the kernel placement for 64bit platforms.
> By patching in the offset into vi_handlers[] instead of the full
> handler address, the vectored exception handler can load the
> address by itself and jump to it.
>
> Signed-off-by: Thomas Bogendoerfer <[email protected]>
> ---
> arch/mips/kernel/genex.S | 8 ++++----
> arch/mips/kernel/traps.c | 9 +++------
> 2 files changed, 7 insertions(+), 10 deletions(-)

applied to mips-next.

Thomas.

--
Crap can work. Given enough thrust pigs will fly, but it's not necessarily a
good idea. [ RFC1925, 2.3 ]