lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Fri, 10 Feb 2023 17:09:17 +0800
From:   Huacai Chen <chenhuacai@...nel.org>
To:     Youling Tang <tangyouling@...ngson.cn>
Cc:     Xi Ruoyao <xry111@...111.site>, Jinyang He <hejinyang@...ngson.cn>,
        Xuerui Wang <kernel@...0n.name>, loongarch@...ts.linux.dev,
        linux-kernel@...r.kernel.org
Subject: Re: [PATCH v4 2/5] LoongArch: Use la.pcrel instead of la.abs for
 exception handlers

Hi, Youling and Ruoyao,

Thank you very much for implementing the per-node exceptions. But I
want to know if the per-node solution is really worthy for a PIE
kernel. So, could you please test the performance? Maybe we can reduce
the complexity if we give up the per-node solution.

Huacai

On Fri, Feb 10, 2023 at 4:47 PM Youling Tang <tangyouling@...ngson.cn> wrote:
>
> From: Xi Ruoyao <xry111@...111.site>
>
> It's needed to build the kernel as a PIE, or the linker will complain.
>
> For the consideration about performance, we copy the exception handlers
> to a dedicated 64 KB area for each CPU.  So, the PC-relative offset
> calculated at link time will be incorrect and we need to relocate the
> exception handlers after copying them.
>
> For the simplicity, we don't use the ELF R_LARCH_* relocations, but code
> an relocation entry as simply (offset_in_the_handler, symbol_addr).  For
> each exception handler, we also code the number of relocation entries.
> Then we can use the relocation information to fix up the handlers after
> copying them.
>
> Signed-off-by: Xi Ruoyao <xry111@...111.site>
> ---
>  arch/loongarch/include/asm/inst.h       |   1 +
>  arch/loongarch/include/asm/setup.h      |   6 +-
>  arch/loongarch/include/asm/stackframe.h |   3 +-
>  arch/loongarch/kernel/genex.S           |  40 +++++-
>  arch/loongarch/kernel/traps.c           | 158 ++++++++++++++++++++----
>  arch/loongarch/mm/tlb.c                 |  23 ++--
>  arch/loongarch/mm/tlbex.S               |  69 +++++++++--
>  7 files changed, 255 insertions(+), 45 deletions(-)
>
> diff --git a/arch/loongarch/include/asm/inst.h b/arch/loongarch/include/asm/inst.h
> index 7eedd83fd0d7..426054518a3d 100644
> --- a/arch/loongarch/include/asm/inst.h
> +++ b/arch/loongarch/include/asm/inst.h
> @@ -32,6 +32,7 @@ enum reg1i20_op {
>         lu12iw_op       = 0x0a,
>         lu32id_op       = 0x0b,
>         pcaddi_op       = 0x0c,
> +       pcalau12i_op    = 0x0d,
>         pcaddu12i_op    = 0x0e,
>         pcaddu18i_op    = 0x0f,
>  };
> diff --git a/arch/loongarch/include/asm/setup.h b/arch/loongarch/include/asm/setup.h
> index 72ead58039f3..f0a2b34365f1 100644
> --- a/arch/loongarch/include/asm/setup.h
> +++ b/arch/loongarch/include/asm/setup.h
> @@ -11,6 +11,9 @@
>
>  #define VECSIZE 0x200
>
> +struct handler_reloc;
> +
> +extern struct handler_reloc *eentry_reloc[];
>  extern unsigned long eentry;
>  extern unsigned long tlbrentry;
>  extern char init_command_line[COMMAND_LINE_SIZE];
> @@ -18,7 +21,8 @@ extern void tlb_init(int cpu);
>  extern void cpu_cache_init(void);
>  extern void cache_error_setup(void);
>  extern void per_cpu_trap_init(int cpu);
> -extern void set_handler(unsigned long offset, void *addr, unsigned long len);
> +extern void set_handler(unsigned long exccode, void *addr);
>  extern void set_merr_handler(unsigned long offset, void *addr, unsigned long len);
> +extern void reloc_handler(unsigned long handler, struct handler_reloc *rel);
>
>  #endif /* __SETUP_H */
> diff --git a/arch/loongarch/include/asm/stackframe.h b/arch/loongarch/include/asm/stackframe.h
> index 7deb043ce387..bbec1e56b61b 100644
> --- a/arch/loongarch/include/asm/stackframe.h
> +++ b/arch/loongarch/include/asm/stackframe.h
> @@ -77,7 +77,8 @@
>   * new value in sp.
>   */
>         .macro  get_saved_sp docfi=0
> -       la.abs    t1, kernelsp
> +       /* The label is used for generating reloc tables for handlers */
> +514:   la.pcrel  t1, t0, kernelsp
>  #ifdef CONFIG_SMP
>         csrrd     t0, PERCPU_BASE_KS
>         LONG_ADD  t1, t1, t0
> diff --git a/arch/loongarch/kernel/genex.S b/arch/loongarch/kernel/genex.S
> index 7e5c293ed89f..005a10fe5a50 100644
> --- a/arch/loongarch/kernel/genex.S
> +++ b/arch/loongarch/kernel/genex.S
> @@ -34,7 +34,7 @@ SYM_FUNC_END(__arch_cpu_idle)
>  SYM_FUNC_START(handle_vint)
>         BACKUP_T0T1
>         SAVE_ALL
> -       la.abs  t1, __arch_cpu_idle
> +0:     la.pcrel t1, t2, __arch_cpu_idle
>         LONG_L  t0, sp, PT_ERA
>         /* 32 byte rollback region */
>         ori     t0, t0, 0x1f
> @@ -43,11 +43,25 @@ SYM_FUNC_START(handle_vint)
>         LONG_S  t0, sp, PT_ERA
>  1:     move    a0, sp
>         move    a1, sp
> -       la.abs  t0, do_vint
> +2:     la.pcrel t0, t2, do_vint
>         jirl    ra, t0, 0
>         RESTORE_ALL_AND_RET
>  SYM_FUNC_END(handle_vint)
>
> +SYM_DATA_START(rel_handle_vint)
> +LONG   3
> +
> +LONG   514b - handle_vint
> +LONG   kernelsp
> +
> +LONG   0b - handle_vint
> +LONG   __arch_cpu_idle
> +
> +LONG   2b - handle_vint
> +LONG   do_vint
> +
> +SYM_DATA_END(rel_handle_vint)
> +
>  SYM_FUNC_START(except_vec_cex)
>         b       cache_parity_error
>  SYM_FUNC_END(except_vec_cex)
> @@ -72,12 +86,24 @@ SYM_FUNC_END(except_vec_cex)
>         SAVE_ALL
>         build_prep_\prep
>         move    a0, sp
> -       la.abs  t0, do_\handler
> +       667:
> +       la.pcrel t0, t1, do_\handler
>         jirl    ra, t0, 0
>         668:
>         RESTORE_ALL_AND_RET
>         SYM_FUNC_END(handle_\exception)
>         SYM_DATA(unwind_hint_\exception, .word 668b - 666b)
> +
> +       SYM_DATA_START(rel_handle_\exception)
> +       LONG    2
> +
> +       LONG    514b - 666b
> +       LONG    kernelsp
> +
> +       LONG    667b - 666b
> +       LONG    do_\handler
> +
> +       SYM_DATA_END(rel_handle_\exception)
>         .endm
>
>         BUILD_HANDLER ade ade badv
> @@ -93,6 +119,12 @@ SYM_FUNC_END(except_vec_cex)
>         BUILD_HANDLER reserved reserved none    /* others */
>
>  SYM_FUNC_START(handle_sys)
> -       la.abs  t0, handle_syscall
> +       la.pcrel t0, t1, handle_syscall
>         jr      t0
>  SYM_FUNC_END(handle_sys)
> +
> +SYM_DATA_START(rel_handle_sys)
> +LONG   1
> +LONG   0
> +LONG   handle_syscall
> +SYM_DATA_END(rel_handle_sys)
> diff --git a/arch/loongarch/kernel/traps.c b/arch/loongarch/kernel/traps.c
> index c38a146a973b..7e073854f493 100644
> --- a/arch/loongarch/kernel/traps.c
> +++ b/arch/loongarch/kernel/traps.c
> @@ -62,6 +62,127 @@ extern asmlinkage void handle_reserved(void);
>  extern asmlinkage void handle_watch(void);
>  extern asmlinkage void handle_vint(void);
>
> +struct handler_reloc_entry {
> +       unsigned long offset;
> +       unsigned long sym;
> +};
> +
> +struct handler_reloc {
> +       unsigned long cnt;
> +       struct handler_reloc_entry entries[];
> +};
> +
> +extern struct handler_reloc rel_handle_tlb_load;
> +extern struct handler_reloc rel_handle_tlb_store;
> +extern struct handler_reloc rel_handle_tlb_modify;
> +extern struct handler_reloc rel_handle_tlb_protect;
> +extern struct handler_reloc rel_handle_ade;
> +extern struct handler_reloc rel_handle_ale;
> +extern struct handler_reloc rel_handle_sys;
> +extern struct handler_reloc rel_handle_bp;
> +extern struct handler_reloc rel_handle_ri;
> +extern struct handler_reloc rel_handle_fpu;
> +extern struct handler_reloc rel_handle_lsx;
> +extern struct handler_reloc rel_handle_lasx;
> +extern struct handler_reloc rel_handle_fpe;
> +extern struct handler_reloc rel_handle_lbt;
> +extern struct handler_reloc rel_handle_watch;
> +extern struct handler_reloc rel_handle_reserved;
> +extern struct handler_reloc rel_handle_vint;
> +
> +struct handler_reloc *eentry_reloc[128] = {
> +       [0] = NULL, /* merr handler */
> +       [EXCCODE_TLBL] = &rel_handle_tlb_load,
> +       [EXCCODE_TLBS] = &rel_handle_tlb_store,
> +       [EXCCODE_TLBI] = &rel_handle_tlb_load,
> +       [EXCCODE_TLBM] = &rel_handle_tlb_modify,
> +       [EXCCODE_TLBNR] = &rel_handle_tlb_protect,
> +       [EXCCODE_TLBNX] = &rel_handle_tlb_protect,
> +       [EXCCODE_TLBPE] = &rel_handle_tlb_protect,
> +       [EXCCODE_ADE] = &rel_handle_ade,
> +       [EXCCODE_ALE] = &rel_handle_ale,
> +       [EXCCODE_SYS] = &rel_handle_sys,
> +       [EXCCODE_BP] = &rel_handle_bp,
> +       [EXCCODE_INE] = &rel_handle_ri,
> +       [EXCCODE_IPE] = &rel_handle_ri,
> +       [EXCCODE_FPDIS] = &rel_handle_fpu,
> +       [EXCCODE_LSXDIS] = &rel_handle_lsx,
> +       [EXCCODE_LASXDIS] = &rel_handle_lasx,
> +       [EXCCODE_FPE] = &rel_handle_fpe,
> +       [EXCCODE_BTDIS] = &rel_handle_lbt,
> +       [EXCCODE_WATCH] = &rel_handle_watch,
> +       [(EXCCODE_WATCH + 1) ... (EXCCODE_INT_START - 1)] = &rel_handle_reserved,
> +       [EXCCODE_INT_START ... (EXCCODE_INT_END - 1)] = &rel_handle_vint,
> +};
> +
> +void reloc_handler(unsigned long handler, struct handler_reloc *rel)
> +{
> +       if (!rel)
> +               return;
> +
> +       for (unsigned long i = 0; i < rel->cnt; i++) {
> +               unsigned long pc = handler + rel->entries[i].offset;
> +               union loongarch_instruction *insn =
> +                       (union loongarch_instruction *)pc;
> +               u32 imm[4];
> +               unsigned long v = rel->entries[i].sym;
> +
> +               /* GNU as >= 2.40 uses pcalau12i for la.pcrel, but GNU ld <= 2.39
> +                * uses pcaddu12i.
> +                */
> +               if (insn->reg1i20_format.opcode == pcalau12i_op) {
> +                       /* Use s32 deliberately for sign extension. */
> +                       s32 offset_hi20 = ((v + 0x800) & ~0xfff) -
> +                                         (pc & ~0xfff);
> +                       unsigned long anchor = (pc & ~0xfff) + offset_hi20;
> +                       unsigned long offset_rem = v - anchor;
> +
> +                       imm[0] = (offset_hi20 >> 12) & 0xfffff;
> +                       imm[1] = v & 0xfff;
> +                       imm[2] = (offset_rem >> 32) & 0xfffff;
> +                       imm[3] = offset_rem >> 52;
> +               } else if (insn->reg1i20_format.opcode == pcaddu12i_op) {
> +                       /* Use s32 deliberately for sign extension. */
> +                       s32 offset_lo = v - pc;
> +                       unsigned long offset_hi = v - pc - offset_lo;
> +
> +                       imm[0] = (offset_lo >> 12) & 0xfffff;
> +                       imm[1] = offset_lo & 0xfff;
> +                       imm[2] = (offset_hi >> 32) & 0xfffff;
> +                       imm[3] = offset_hi >> 52;
> +               } else
> +                       panic("Cannot fixup la.pcrel for exception handler at %lu: unexpected instruction %d!",
> +                             pc, insn->word);
> +
> +               insn[0].reg1i20_format.immediate = imm[0];
> +               insn[1].reg2i12_format.immediate = imm[1];
> +               insn[2].reg1i20_format.immediate = imm[2];
> +               insn[3].reg2i12_format.immediate = imm[3];
> +       }
> +}
> +
> +/* Install CPU exception handler */
> +static void do_set_handler(unsigned long exccode, void *addr,
> +                          struct handler_reloc *rel)
> +{
> +       unsigned long dest_addr = eentry + exccode * VECSIZE;
> +
> +       memcpy((void *)dest_addr, addr, VECSIZE);
> +       reloc_handler(dest_addr, rel);
> +       local_flush_icache_range(dest_addr, dest_addr + VECSIZE);
> +}
> +
> +/* Install CPU exception handler, with the reloc table from eentry_reloc */
> +void set_handler(unsigned long exccode, void *addr)
> +{
> +       do_set_handler(exccode, addr, eentry_reloc[exccode]);
> +}
> +
> +static void set_handler_reserved(unsigned long exccode)
> +{
> +       do_set_handler(exccode, handle_reserved, &rel_handle_reserved);
> +}
> +
>  static void show_backtrace(struct task_struct *task, const struct pt_regs *regs,
>                            const char *loglvl, bool user)
>  {
> @@ -704,19 +825,12 @@ void per_cpu_trap_init(int cpu)
>         /* Initialise exception handlers */
>         if (cpu == 0)
>                 for (i = 0; i < 64; i++)
> -                       set_handler(i * VECSIZE, handle_reserved, VECSIZE);
> +                       set_handler_reserved(i);
>
>         tlb_init(cpu);
>         cpu_cache_init();
>  }
>
> -/* Install CPU exception handler */
> -void set_handler(unsigned long offset, void *addr, unsigned long size)
> -{
> -       memcpy((void *)(eentry + offset), addr, size);
> -       local_flush_icache_range(eentry + offset, eentry + offset + size);
> -}
> -
>  static const char panic_null_cerr[] =
>         "Trying to set NULL cache error exception handler\n";
>
> @@ -741,20 +855,20 @@ void __init trap_init(void)
>
>         /* Set interrupt vector handler */
>         for (i = EXCCODE_INT_START; i < EXCCODE_INT_END; i++)
> -               set_handler(i * VECSIZE, handle_vint, VECSIZE);
> -
> -       set_handler(EXCCODE_ADE * VECSIZE, handle_ade, VECSIZE);
> -       set_handler(EXCCODE_ALE * VECSIZE, handle_ale, VECSIZE);
> -       set_handler(EXCCODE_SYS * VECSIZE, handle_sys, VECSIZE);
> -       set_handler(EXCCODE_BP * VECSIZE, handle_bp, VECSIZE);
> -       set_handler(EXCCODE_INE * VECSIZE, handle_ri, VECSIZE);
> -       set_handler(EXCCODE_IPE * VECSIZE, handle_ri, VECSIZE);
> -       set_handler(EXCCODE_FPDIS * VECSIZE, handle_fpu, VECSIZE);
> -       set_handler(EXCCODE_LSXDIS * VECSIZE, handle_lsx, VECSIZE);
> -       set_handler(EXCCODE_LASXDIS * VECSIZE, handle_lasx, VECSIZE);
> -       set_handler(EXCCODE_FPE * VECSIZE, handle_fpe, VECSIZE);
> -       set_handler(EXCCODE_BTDIS * VECSIZE, handle_lbt, VECSIZE);
> -       set_handler(EXCCODE_WATCH * VECSIZE, handle_watch, VECSIZE);
> +               set_handler(i, handle_vint);
> +
> +       set_handler(EXCCODE_ADE, handle_ade);
> +       set_handler(EXCCODE_ALE, handle_ale);
> +       set_handler(EXCCODE_SYS, handle_sys);
> +       set_handler(EXCCODE_BP, handle_bp);
> +       set_handler(EXCCODE_INE, handle_ri);
> +       set_handler(EXCCODE_IPE, handle_ri);
> +       set_handler(EXCCODE_FPDIS, handle_fpu);
> +       set_handler(EXCCODE_LSXDIS, handle_lsx);
> +       set_handler(EXCCODE_LASXDIS, handle_lasx);
> +       set_handler(EXCCODE_FPE, handle_fpe);
> +       set_handler(EXCCODE_BTDIS, handle_lbt);
> +       set_handler(EXCCODE_WATCH, handle_watch);
>
>         cache_error_setup();
>
> diff --git a/arch/loongarch/mm/tlb.c b/arch/loongarch/mm/tlb.c
> index 8bad6b0cff59..6f70aab7202a 100644
> --- a/arch/loongarch/mm/tlb.c
> +++ b/arch/loongarch/mm/tlb.c
> @@ -253,7 +253,6 @@ static void output_pgtable_bits_defines(void)
>  #ifdef CONFIG_NUMA
>  unsigned long pcpu_handlers[NR_CPUS];
>  #endif
> -extern long exception_handlers[VECSIZE * 128 / sizeof(long)];
>
>  void setup_tlb_handler(int cpu)
>  {
> @@ -264,19 +263,20 @@ void setup_tlb_handler(int cpu)
>         if (cpu == 0) {
>                 memcpy((void *)tlbrentry, handle_tlb_refill, 0x80);
>                 local_flush_icache_range(tlbrentry, tlbrentry + 0x80);
> -               set_handler(EXCCODE_TLBI * VECSIZE, handle_tlb_load, VECSIZE);
> -               set_handler(EXCCODE_TLBL * VECSIZE, handle_tlb_load, VECSIZE);
> -               set_handler(EXCCODE_TLBS * VECSIZE, handle_tlb_store, VECSIZE);
> -               set_handler(EXCCODE_TLBM * VECSIZE, handle_tlb_modify, VECSIZE);
> -               set_handler(EXCCODE_TLBNR * VECSIZE, handle_tlb_protect, VECSIZE);
> -               set_handler(EXCCODE_TLBNX * VECSIZE, handle_tlb_protect, VECSIZE);
> -               set_handler(EXCCODE_TLBPE * VECSIZE, handle_tlb_protect, VECSIZE);
> +               set_handler(EXCCODE_TLBI, handle_tlb_load);
> +               set_handler(EXCCODE_TLBL, handle_tlb_load);
> +               set_handler(EXCCODE_TLBS, handle_tlb_store);
> +               set_handler(EXCCODE_TLBM, handle_tlb_modify);
> +               set_handler(EXCCODE_TLBNR, handle_tlb_protect);
> +               set_handler(EXCCODE_TLBNX, handle_tlb_protect);
> +               set_handler(EXCCODE_TLBPE, handle_tlb_protect);
>         }
>  #ifdef CONFIG_NUMA
>         else {
>                 void *addr;
> +               unsigned long addr_ul;
>                 struct page *page;
> -               const int vec_sz = sizeof(exception_handlers);
> +               const int vec_sz = VECSIZE * 128;
>
>                 if (pcpu_handlers[cpu])
>                         return;
> @@ -286,8 +286,11 @@ void setup_tlb_handler(int cpu)
>                         return;
>
>                 addr = page_address(page);
> +               addr_ul = (unsigned long)addr;
>                 pcpu_handlers[cpu] = (unsigned long)addr;
> -               memcpy((void *)addr, (void *)eentry, vec_sz);
> +               memcpy(addr, (void *)eentry, vec_sz);
> +               for (unsigned long i = 0; i < 128; i++)
> +                       reloc_handler(addr_ul + i * VECSIZE, eentry_reloc[i]);
>                 local_flush_icache_range((unsigned long)addr, (unsigned long)addr + vec_sz);
>                 csr_write64(pcpu_handlers[cpu], LOONGARCH_CSR_EENTRY);
>                 csr_write64(pcpu_handlers[cpu], LOONGARCH_CSR_MERRENTRY);
> diff --git a/arch/loongarch/mm/tlbex.S b/arch/loongarch/mm/tlbex.S
> index 3dd2a9615cd9..044c2190771a 100644
> --- a/arch/loongarch/mm/tlbex.S
> +++ b/arch/loongarch/mm/tlbex.S
> @@ -39,11 +39,21 @@ SYM_FUNC_START(handle_tlb_protect)
>         move            a1, zero
>         csrrd           a2, LOONGARCH_CSR_BADV
>         REG_S           a2, sp, PT_BVADDR
> -       la.abs          t0, do_page_fault
> +1:     la.pcrel        t0, t1, do_page_fault
>         jirl            ra, t0, 0
>         RESTORE_ALL_AND_RET
>  SYM_FUNC_END(handle_tlb_protect)
>
> +SYM_DATA_START(rel_handle_tlb_protect)
> +       LONG    2
> +
> +       LONG    514b - handle_tlb_protect
> +       LONG    kernelsp
> +
> +       LONG    1b - handle_tlb_protect
> +       LONG    do_page_fault
> +SYM_DATA_END(rel_handle_tlb_protect)
> +
>  SYM_FUNC_START(handle_tlb_load)
>         csrwr           t0, EXCEPTION_KS0
>         csrwr           t1, EXCEPTION_KS1
> @@ -115,7 +125,8 @@ smp_pgtable_change_load:
>
>  #ifdef CONFIG_64BIT
>  vmalloc_load:
> -       la.abs          t1, swapper_pg_dir
> +       /* The first insn of vmalloc_done_load overwrites ra */
> +1:     la.pcrel        t1, ra, swapper_pg_dir
>         b               vmalloc_done_load
>  #endif
>
> @@ -186,10 +197,24 @@ tlb_huge_update_load:
>  nopage_tlb_load:
>         dbar            0
>         csrrd           ra, EXCEPTION_KS2
> -       la.abs          t0, tlb_do_page_fault_0
> +2:     la.pcrel        t0, t1, tlb_do_page_fault_0
>         jr              t0
>  SYM_FUNC_END(handle_tlb_load)
>
> +SYM_DATA_START(rel_handle_tlb_load)
> +#ifdef CONFIG_64BIT
> +       LONG    2
> +
> +       LONG    1b - handle_tlb_load
> +       LONG    swapper_pg_dir
> +#else
> +       LONG    1
> +#endif
> +
> +       LONG    2b - handle_tlb_load
> +       LONG    tlb_do_page_fault_0
> +SYM_DATA_END(rel_handle_tlb_load)
> +
>  SYM_FUNC_START(handle_tlb_store)
>         csrwr           t0, EXCEPTION_KS0
>         csrwr           t1, EXCEPTION_KS1
> @@ -262,7 +287,8 @@ smp_pgtable_change_store:
>
>  #ifdef CONFIG_64BIT
>  vmalloc_store:
> -       la.abs          t1, swapper_pg_dir
> +       /* The first insn of vmalloc_done_store overwrites ra */
> +1:     la.pcrel        t1, ra, swapper_pg_dir
>         b               vmalloc_done_store
>  #endif
>
> @@ -335,10 +361,24 @@ tlb_huge_update_store:
>  nopage_tlb_store:
>         dbar            0
>         csrrd           ra, EXCEPTION_KS2
> -       la.abs          t0, tlb_do_page_fault_1
> +2:     la.pcrel        t0, t1, tlb_do_page_fault_1
>         jr              t0
>  SYM_FUNC_END(handle_tlb_store)
>
> +SYM_DATA_START(rel_handle_tlb_store)
> +#ifdef CONFIG_64BIT
> +       LONG    2
> +
> +       LONG    1b - handle_tlb_store
> +       LONG    swapper_pg_dir
> +#else
> +       LONG    1
> +#endif
> +
> +       LONG    2b - handle_tlb_store
> +       LONG    tlb_do_page_fault_1
> +SYM_DATA_END(rel_handle_tlb_store)
> +
>  SYM_FUNC_START(handle_tlb_modify)
>         csrwr           t0, EXCEPTION_KS0
>         csrwr           t1, EXCEPTION_KS1
> @@ -410,7 +450,8 @@ smp_pgtable_change_modify:
>
>  #ifdef CONFIG_64BIT
>  vmalloc_modify:
> -       la.abs          t1, swapper_pg_dir
> +       /* The first insn of vmalloc_done_modify overwrites ra */
> +1:     la.pcrel        t1, ra, swapper_pg_dir
>         b               vmalloc_done_modify
>  #endif
>
> @@ -482,10 +523,24 @@ tlb_huge_update_modify:
>  nopage_tlb_modify:
>         dbar            0
>         csrrd           ra, EXCEPTION_KS2
> -       la.abs          t0, tlb_do_page_fault_1
> +2:     la.pcrel        t0, t1, tlb_do_page_fault_1
>         jr              t0
>  SYM_FUNC_END(handle_tlb_modify)
>
> +SYM_DATA_START(rel_handle_tlb_modify)
> +#ifdef CONFIG_64BIT
> +       LONG    2
> +
> +       LONG    1b - handle_tlb_modify
> +       LONG    swapper_pg_dir
> +#else
> +       LONG    1
> +#endif
> +
> +       LONG    2b - handle_tlb_modify
> +       LONG    tlb_do_page_fault_1
> +SYM_DATA_END(rel_handle_tlb_modify)
> +
>  SYM_FUNC_START(handle_tlb_refill)
>         csrwr           t0, LOONGARCH_CSR_TLBRSAVE
>         csrrd           t0, LOONGARCH_CSR_PGD
> --
> 2.37.3
>

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ