diff options
author | Thomas Bogendoerfer <tsbogend@alpha.franken.de> | 2023-12-21 13:54:03 +0100 |
---|---|---|
committer | Thomas Bogendoerfer <tsbogend@alpha.franken.de> | 2023-12-30 15:36:01 +0100 |
commit | 682fb5be353117b7321f1dfb65b7bb98cbfe59ab (patch) | |
tree | 719f69c640afc0020af40fa672dccffeb18f9983 /arch/mips | |
parent | efe8ee1a8b9a89835dcbbec8cebc9d5a27428914 (diff) |
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 <tsbogend@alpha.franken.de>
Reviewed-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
Diffstat (limited to 'arch/mips')
-rw-r--r-- | arch/mips/kernel/genex.S | 8 | ||||
-rw-r--r-- | 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)); } |