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
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/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));
> }
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 ]
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 ]