162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Author: Huacai Chen <chenhuacai@loongson.cn> 462306a36Sopenharmony_ci * Copyright (C) 2020-2022 Loongson Technology Corporation Limited 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * Derived from MIPS: 762306a36Sopenharmony_ci * Copyright (C) 1994 - 1999, 2000 by Ralf Baechle and others. 862306a36Sopenharmony_ci * Copyright (C) 2005, 2006 by Ralf Baechle (ralf@linux-mips.org) 962306a36Sopenharmony_ci * Copyright (C) 1999, 2000 Silicon Graphics, Inc. 1062306a36Sopenharmony_ci * Copyright (C) 2004 Thiemo Seufer 1162306a36Sopenharmony_ci * Copyright (C) 2013 Imagination Technologies Ltd. 1262306a36Sopenharmony_ci */ 1362306a36Sopenharmony_ci#include <linux/cpu.h> 1462306a36Sopenharmony_ci#include <linux/init.h> 1562306a36Sopenharmony_ci#include <linux/kernel.h> 1662306a36Sopenharmony_ci#include <linux/errno.h> 1762306a36Sopenharmony_ci#include <linux/sched.h> 1862306a36Sopenharmony_ci#include <linux/sched/debug.h> 1962306a36Sopenharmony_ci#include <linux/sched/task.h> 2062306a36Sopenharmony_ci#include <linux/sched/task_stack.h> 2162306a36Sopenharmony_ci#include <linux/hw_breakpoint.h> 2262306a36Sopenharmony_ci#include <linux/mm.h> 2362306a36Sopenharmony_ci#include <linux/stddef.h> 2462306a36Sopenharmony_ci#include <linux/unistd.h> 2562306a36Sopenharmony_ci#include <linux/export.h> 2662306a36Sopenharmony_ci#include <linux/ptrace.h> 2762306a36Sopenharmony_ci#include <linux/mman.h> 2862306a36Sopenharmony_ci#include <linux/personality.h> 2962306a36Sopenharmony_ci#include <linux/sys.h> 3062306a36Sopenharmony_ci#include <linux/completion.h> 3162306a36Sopenharmony_ci#include <linux/kallsyms.h> 3262306a36Sopenharmony_ci#include <linux/random.h> 3362306a36Sopenharmony_ci#include <linux/prctl.h> 3462306a36Sopenharmony_ci#include <linux/nmi.h> 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci#include <asm/asm.h> 3762306a36Sopenharmony_ci#include <asm/bootinfo.h> 3862306a36Sopenharmony_ci#include <asm/cpu.h> 3962306a36Sopenharmony_ci#include <asm/elf.h> 4062306a36Sopenharmony_ci#include <asm/exec.h> 4162306a36Sopenharmony_ci#include <asm/fpu.h> 4262306a36Sopenharmony_ci#include <asm/lbt.h> 4362306a36Sopenharmony_ci#include <asm/io.h> 4462306a36Sopenharmony_ci#include <asm/irq.h> 4562306a36Sopenharmony_ci#include <asm/irq_regs.h> 4662306a36Sopenharmony_ci#include <asm/loongarch.h> 4762306a36Sopenharmony_ci#include <asm/pgtable.h> 4862306a36Sopenharmony_ci#include <asm/processor.h> 4962306a36Sopenharmony_ci#include <asm/reg.h> 5062306a36Sopenharmony_ci#include <asm/unwind.h> 5162306a36Sopenharmony_ci#include <asm/vdso.h> 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci#ifdef CONFIG_STACKPROTECTOR 5462306a36Sopenharmony_ci#include <linux/stackprotector.h> 5562306a36Sopenharmony_ciunsigned long __stack_chk_guard __read_mostly; 5662306a36Sopenharmony_ciEXPORT_SYMBOL(__stack_chk_guard); 5762306a36Sopenharmony_ci#endif 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci/* 6062306a36Sopenharmony_ci * Idle related variables and functions 6162306a36Sopenharmony_ci */ 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ciunsigned long boot_option_idle_override = IDLE_NO_OVERRIDE; 6462306a36Sopenharmony_ciEXPORT_SYMBOL(boot_option_idle_override); 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ciasmlinkage void ret_from_fork(void); 6762306a36Sopenharmony_ciasmlinkage void ret_from_kernel_thread(void); 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_civoid start_thread(struct pt_regs *regs, unsigned long pc, unsigned long sp) 7062306a36Sopenharmony_ci{ 7162306a36Sopenharmony_ci unsigned long crmd; 7262306a36Sopenharmony_ci unsigned long prmd; 7362306a36Sopenharmony_ci unsigned long euen; 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci /* New thread loses kernel privileges. */ 7662306a36Sopenharmony_ci crmd = regs->csr_crmd & ~(PLV_MASK); 7762306a36Sopenharmony_ci crmd |= PLV_USER; 7862306a36Sopenharmony_ci regs->csr_crmd = crmd; 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci prmd = regs->csr_prmd & ~(PLV_MASK); 8162306a36Sopenharmony_ci prmd |= PLV_USER; 8262306a36Sopenharmony_ci regs->csr_prmd = prmd; 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci euen = regs->csr_euen & ~(CSR_EUEN_FPEN); 8562306a36Sopenharmony_ci regs->csr_euen = euen; 8662306a36Sopenharmony_ci lose_fpu(0); 8762306a36Sopenharmony_ci lose_lbt(0); 8862306a36Sopenharmony_ci current->thread.fpu.fcsr = boot_cpu_data.fpu_csr0; 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci clear_thread_flag(TIF_LSX_CTX_LIVE); 9162306a36Sopenharmony_ci clear_thread_flag(TIF_LASX_CTX_LIVE); 9262306a36Sopenharmony_ci clear_thread_flag(TIF_LBT_CTX_LIVE); 9362306a36Sopenharmony_ci clear_used_math(); 9462306a36Sopenharmony_ci regs->csr_era = pc; 9562306a36Sopenharmony_ci regs->regs[3] = sp; 9662306a36Sopenharmony_ci} 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_civoid flush_thread(void) 9962306a36Sopenharmony_ci{ 10062306a36Sopenharmony_ci flush_ptrace_hw_breakpoint(current); 10162306a36Sopenharmony_ci} 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_civoid exit_thread(struct task_struct *tsk) 10462306a36Sopenharmony_ci{ 10562306a36Sopenharmony_ci} 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ciint arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) 10862306a36Sopenharmony_ci{ 10962306a36Sopenharmony_ci /* 11062306a36Sopenharmony_ci * Save any process state which is live in hardware registers to the 11162306a36Sopenharmony_ci * parent context prior to duplication. This prevents the new child 11262306a36Sopenharmony_ci * state becoming stale if the parent is preempted before copy_thread() 11362306a36Sopenharmony_ci * gets a chance to save the parent's live hardware registers to the 11462306a36Sopenharmony_ci * child context. 11562306a36Sopenharmony_ci */ 11662306a36Sopenharmony_ci preempt_disable(); 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci if (is_fpu_owner()) { 11962306a36Sopenharmony_ci if (is_lasx_enabled()) 12062306a36Sopenharmony_ci save_lasx(current); 12162306a36Sopenharmony_ci else if (is_lsx_enabled()) 12262306a36Sopenharmony_ci save_lsx(current); 12362306a36Sopenharmony_ci else 12462306a36Sopenharmony_ci save_fp(current); 12562306a36Sopenharmony_ci } 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ci preempt_enable(); 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci if (!used_math()) 13062306a36Sopenharmony_ci memcpy(dst, src, offsetof(struct task_struct, thread.fpu.fpr)); 13162306a36Sopenharmony_ci else 13262306a36Sopenharmony_ci memcpy(dst, src, offsetof(struct task_struct, thread.lbt.scr0)); 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci#ifdef CONFIG_CPU_HAS_LBT 13562306a36Sopenharmony_ci memcpy(&dst->thread.lbt, &src->thread.lbt, sizeof(struct loongarch_lbt)); 13662306a36Sopenharmony_ci#endif 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci return 0; 13962306a36Sopenharmony_ci} 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci/* 14262306a36Sopenharmony_ci * Copy architecture-specific thread state 14362306a36Sopenharmony_ci */ 14462306a36Sopenharmony_ciint copy_thread(struct task_struct *p, const struct kernel_clone_args *args) 14562306a36Sopenharmony_ci{ 14662306a36Sopenharmony_ci unsigned long childksp; 14762306a36Sopenharmony_ci unsigned long tls = args->tls; 14862306a36Sopenharmony_ci unsigned long usp = args->stack; 14962306a36Sopenharmony_ci unsigned long clone_flags = args->flags; 15062306a36Sopenharmony_ci struct pt_regs *childregs, *regs = current_pt_regs(); 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ci childksp = (unsigned long)task_stack_page(p) + THREAD_SIZE; 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ci /* set up new TSS. */ 15562306a36Sopenharmony_ci childregs = (struct pt_regs *) childksp - 1; 15662306a36Sopenharmony_ci /* Put the stack after the struct pt_regs. */ 15762306a36Sopenharmony_ci childksp = (unsigned long) childregs; 15862306a36Sopenharmony_ci p->thread.sched_cfa = 0; 15962306a36Sopenharmony_ci p->thread.csr_euen = 0; 16062306a36Sopenharmony_ci p->thread.csr_crmd = csr_read32(LOONGARCH_CSR_CRMD); 16162306a36Sopenharmony_ci p->thread.csr_prmd = csr_read32(LOONGARCH_CSR_PRMD); 16262306a36Sopenharmony_ci p->thread.csr_ecfg = csr_read32(LOONGARCH_CSR_ECFG); 16362306a36Sopenharmony_ci if (unlikely(args->fn)) { 16462306a36Sopenharmony_ci /* kernel thread */ 16562306a36Sopenharmony_ci p->thread.reg03 = childksp; 16662306a36Sopenharmony_ci p->thread.reg23 = (unsigned long)args->fn; 16762306a36Sopenharmony_ci p->thread.reg24 = (unsigned long)args->fn_arg; 16862306a36Sopenharmony_ci p->thread.reg01 = (unsigned long)ret_from_kernel_thread; 16962306a36Sopenharmony_ci p->thread.sched_ra = (unsigned long)ret_from_kernel_thread; 17062306a36Sopenharmony_ci memset(childregs, 0, sizeof(struct pt_regs)); 17162306a36Sopenharmony_ci childregs->csr_euen = p->thread.csr_euen; 17262306a36Sopenharmony_ci childregs->csr_crmd = p->thread.csr_crmd; 17362306a36Sopenharmony_ci childregs->csr_prmd = p->thread.csr_prmd; 17462306a36Sopenharmony_ci childregs->csr_ecfg = p->thread.csr_ecfg; 17562306a36Sopenharmony_ci goto out; 17662306a36Sopenharmony_ci } 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ci /* user thread */ 17962306a36Sopenharmony_ci *childregs = *regs; 18062306a36Sopenharmony_ci childregs->regs[4] = 0; /* Child gets zero as return value */ 18162306a36Sopenharmony_ci if (usp) 18262306a36Sopenharmony_ci childregs->regs[3] = usp; 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_ci p->thread.reg03 = (unsigned long) childregs; 18562306a36Sopenharmony_ci p->thread.reg01 = (unsigned long) ret_from_fork; 18662306a36Sopenharmony_ci p->thread.sched_ra = (unsigned long) ret_from_fork; 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_ci /* 18962306a36Sopenharmony_ci * New tasks lose permission to use the fpu. This accelerates context 19062306a36Sopenharmony_ci * switching for most programs since they don't use the fpu. 19162306a36Sopenharmony_ci */ 19262306a36Sopenharmony_ci childregs->csr_euen = 0; 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_ci if (clone_flags & CLONE_SETTLS) 19562306a36Sopenharmony_ci childregs->regs[2] = tls; 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ciout: 19862306a36Sopenharmony_ci ptrace_hw_copy_thread(p); 19962306a36Sopenharmony_ci clear_tsk_thread_flag(p, TIF_USEDFPU); 20062306a36Sopenharmony_ci clear_tsk_thread_flag(p, TIF_USEDSIMD); 20162306a36Sopenharmony_ci clear_tsk_thread_flag(p, TIF_USEDLBT); 20262306a36Sopenharmony_ci clear_tsk_thread_flag(p, TIF_LSX_CTX_LIVE); 20362306a36Sopenharmony_ci clear_tsk_thread_flag(p, TIF_LASX_CTX_LIVE); 20462306a36Sopenharmony_ci clear_tsk_thread_flag(p, TIF_LBT_CTX_LIVE); 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_ci return 0; 20762306a36Sopenharmony_ci} 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_ciunsigned long __get_wchan(struct task_struct *task) 21062306a36Sopenharmony_ci{ 21162306a36Sopenharmony_ci unsigned long pc = 0; 21262306a36Sopenharmony_ci struct unwind_state state; 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ci if (!try_get_task_stack(task)) 21562306a36Sopenharmony_ci return 0; 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci for (unwind_start(&state, task, NULL); 21862306a36Sopenharmony_ci !unwind_done(&state); unwind_next_frame(&state)) { 21962306a36Sopenharmony_ci pc = unwind_get_return_address(&state); 22062306a36Sopenharmony_ci if (!pc) 22162306a36Sopenharmony_ci break; 22262306a36Sopenharmony_ci if (in_sched_functions(pc)) 22362306a36Sopenharmony_ci continue; 22462306a36Sopenharmony_ci break; 22562306a36Sopenharmony_ci } 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_ci put_task_stack(task); 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_ci return pc; 23062306a36Sopenharmony_ci} 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_cibool in_irq_stack(unsigned long stack, struct stack_info *info) 23362306a36Sopenharmony_ci{ 23462306a36Sopenharmony_ci unsigned long nextsp; 23562306a36Sopenharmony_ci unsigned long begin = (unsigned long)this_cpu_read(irq_stack); 23662306a36Sopenharmony_ci unsigned long end = begin + IRQ_STACK_START; 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_ci if (stack < begin || stack >= end) 23962306a36Sopenharmony_ci return false; 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_ci nextsp = *(unsigned long *)end; 24262306a36Sopenharmony_ci if (nextsp & (SZREG - 1)) 24362306a36Sopenharmony_ci return false; 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_ci info->begin = begin; 24662306a36Sopenharmony_ci info->end = end; 24762306a36Sopenharmony_ci info->next_sp = nextsp; 24862306a36Sopenharmony_ci info->type = STACK_TYPE_IRQ; 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_ci return true; 25162306a36Sopenharmony_ci} 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_cibool in_task_stack(unsigned long stack, struct task_struct *task, 25462306a36Sopenharmony_ci struct stack_info *info) 25562306a36Sopenharmony_ci{ 25662306a36Sopenharmony_ci unsigned long begin = (unsigned long)task_stack_page(task); 25762306a36Sopenharmony_ci unsigned long end = begin + THREAD_SIZE; 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_ci if (stack < begin || stack >= end) 26062306a36Sopenharmony_ci return false; 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_ci info->begin = begin; 26362306a36Sopenharmony_ci info->end = end; 26462306a36Sopenharmony_ci info->next_sp = 0; 26562306a36Sopenharmony_ci info->type = STACK_TYPE_TASK; 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ci return true; 26862306a36Sopenharmony_ci} 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_ciint get_stack_info(unsigned long stack, struct task_struct *task, 27162306a36Sopenharmony_ci struct stack_info *info) 27262306a36Sopenharmony_ci{ 27362306a36Sopenharmony_ci task = task ? : current; 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci if (!stack || stack & (SZREG - 1)) 27662306a36Sopenharmony_ci goto unknown; 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ci if (in_task_stack(stack, task, info)) 27962306a36Sopenharmony_ci return 0; 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci if (task != current) 28262306a36Sopenharmony_ci goto unknown; 28362306a36Sopenharmony_ci 28462306a36Sopenharmony_ci if (in_irq_stack(stack, info)) 28562306a36Sopenharmony_ci return 0; 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_ciunknown: 28862306a36Sopenharmony_ci info->type = STACK_TYPE_UNKNOWN; 28962306a36Sopenharmony_ci return -EINVAL; 29062306a36Sopenharmony_ci} 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_ciunsigned long stack_top(void) 29362306a36Sopenharmony_ci{ 29462306a36Sopenharmony_ci unsigned long top = TASK_SIZE & PAGE_MASK; 29562306a36Sopenharmony_ci 29662306a36Sopenharmony_ci /* Space for the VDSO & data page */ 29762306a36Sopenharmony_ci top -= PAGE_ALIGN(current->thread.vdso->size); 29862306a36Sopenharmony_ci top -= VVAR_SIZE; 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_ci /* Space to randomize the VDSO base */ 30162306a36Sopenharmony_ci if (current->flags & PF_RANDOMIZE) 30262306a36Sopenharmony_ci top -= VDSO_RANDOMIZE_SIZE; 30362306a36Sopenharmony_ci 30462306a36Sopenharmony_ci return top; 30562306a36Sopenharmony_ci} 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_ci/* 30862306a36Sopenharmony_ci * Don't forget that the stack pointer must be aligned on a 8 bytes 30962306a36Sopenharmony_ci * boundary for 32-bits ABI and 16 bytes for 64-bits ABI. 31062306a36Sopenharmony_ci */ 31162306a36Sopenharmony_ciunsigned long arch_align_stack(unsigned long sp) 31262306a36Sopenharmony_ci{ 31362306a36Sopenharmony_ci if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space) 31462306a36Sopenharmony_ci sp -= get_random_u32_below(PAGE_SIZE); 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ci return sp & STACK_ALIGN; 31762306a36Sopenharmony_ci} 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_cistatic DEFINE_PER_CPU(call_single_data_t, backtrace_csd); 32062306a36Sopenharmony_cistatic struct cpumask backtrace_csd_busy; 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_cistatic void handle_backtrace(void *info) 32362306a36Sopenharmony_ci{ 32462306a36Sopenharmony_ci nmi_cpu_backtrace(get_irq_regs()); 32562306a36Sopenharmony_ci cpumask_clear_cpu(smp_processor_id(), &backtrace_csd_busy); 32662306a36Sopenharmony_ci} 32762306a36Sopenharmony_ci 32862306a36Sopenharmony_cistatic void raise_backtrace(cpumask_t *mask) 32962306a36Sopenharmony_ci{ 33062306a36Sopenharmony_ci call_single_data_t *csd; 33162306a36Sopenharmony_ci int cpu; 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_ci for_each_cpu(cpu, mask) { 33462306a36Sopenharmony_ci /* 33562306a36Sopenharmony_ci * If we previously sent an IPI to the target CPU & it hasn't 33662306a36Sopenharmony_ci * cleared its bit in the busy cpumask then it didn't handle 33762306a36Sopenharmony_ci * our previous IPI & it's not safe for us to reuse the 33862306a36Sopenharmony_ci * call_single_data_t. 33962306a36Sopenharmony_ci */ 34062306a36Sopenharmony_ci if (cpumask_test_and_set_cpu(cpu, &backtrace_csd_busy)) { 34162306a36Sopenharmony_ci pr_warn("Unable to send backtrace IPI to CPU%u - perhaps it hung?\n", 34262306a36Sopenharmony_ci cpu); 34362306a36Sopenharmony_ci continue; 34462306a36Sopenharmony_ci } 34562306a36Sopenharmony_ci 34662306a36Sopenharmony_ci csd = &per_cpu(backtrace_csd, cpu); 34762306a36Sopenharmony_ci csd->func = handle_backtrace; 34862306a36Sopenharmony_ci smp_call_function_single_async(cpu, csd); 34962306a36Sopenharmony_ci } 35062306a36Sopenharmony_ci} 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_civoid arch_trigger_cpumask_backtrace(const cpumask_t *mask, int exclude_cpu) 35362306a36Sopenharmony_ci{ 35462306a36Sopenharmony_ci nmi_trigger_cpumask_backtrace(mask, exclude_cpu, raise_backtrace); 35562306a36Sopenharmony_ci} 35662306a36Sopenharmony_ci 35762306a36Sopenharmony_ci#ifdef CONFIG_64BIT 35862306a36Sopenharmony_civoid loongarch_dump_regs64(u64 *uregs, const struct pt_regs *regs) 35962306a36Sopenharmony_ci{ 36062306a36Sopenharmony_ci unsigned int i; 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_ci for (i = LOONGARCH_EF_R1; i <= LOONGARCH_EF_R31; i++) { 36362306a36Sopenharmony_ci uregs[i] = regs->regs[i - LOONGARCH_EF_R0]; 36462306a36Sopenharmony_ci } 36562306a36Sopenharmony_ci 36662306a36Sopenharmony_ci uregs[LOONGARCH_EF_ORIG_A0] = regs->orig_a0; 36762306a36Sopenharmony_ci uregs[LOONGARCH_EF_CSR_ERA] = regs->csr_era; 36862306a36Sopenharmony_ci uregs[LOONGARCH_EF_CSR_BADV] = regs->csr_badvaddr; 36962306a36Sopenharmony_ci uregs[LOONGARCH_EF_CSR_CRMD] = regs->csr_crmd; 37062306a36Sopenharmony_ci uregs[LOONGARCH_EF_CSR_PRMD] = regs->csr_prmd; 37162306a36Sopenharmony_ci uregs[LOONGARCH_EF_CSR_EUEN] = regs->csr_euen; 37262306a36Sopenharmony_ci uregs[LOONGARCH_EF_CSR_ECFG] = regs->csr_ecfg; 37362306a36Sopenharmony_ci uregs[LOONGARCH_EF_CSR_ESTAT] = regs->csr_estat; 37462306a36Sopenharmony_ci} 37562306a36Sopenharmony_ci#endif /* CONFIG_64BIT */ 376