1386561f8SAndrew Jones // SPDX-License-Identifier: GPL-2.0-only 2386561f8SAndrew Jones /* 3386561f8SAndrew Jones * Copyright (C) 2023, Ventana Micro Systems Inc., Andrew Jones <ajones@ventanamicro.com> 4386561f8SAndrew Jones */ 5386561f8SAndrew Jones #include <libcflat.h> 6*94ca1aafSAndrew Jones #include <limits.h> 7386561f8SAndrew Jones #include <asm/csr.h> 8db0ae91cSAndrew Jones #include <asm/isa.h> 9386561f8SAndrew Jones #include <asm/processor.h> 10386561f8SAndrew Jones #include <asm/setup.h> 11*94ca1aafSAndrew Jones #include <asm/smp.h> 12386561f8SAndrew Jones 13e442bc9cSAndrew Jones extern unsigned long ImageBase; 14386561f8SAndrew Jones 15386561f8SAndrew Jones void show_regs(struct pt_regs *regs) 16386561f8SAndrew Jones { 179c92b28eSAndrew Jones struct thread_info *info = current_thread_info(); 18e442bc9cSAndrew Jones uintptr_t loadaddr = (uintptr_t)&ImageBase; 19386561f8SAndrew Jones unsigned int w = __riscv_xlen / 4; 20386561f8SAndrew Jones 21e442bc9cSAndrew Jones printf("Load address: %" PRIxPTR "\n", loadaddr); 229c92b28eSAndrew Jones printf("CPU%3d : hartid=%lx\n", info->cpu, info->hartid); 23386561f8SAndrew Jones printf("status : %.*lx\n", w, regs->status); 24386561f8SAndrew Jones printf("cause : %.*lx\n", w, regs->cause); 25386561f8SAndrew Jones printf("badaddr: %.*lx\n", w, regs->badaddr); 26e442bc9cSAndrew Jones printf("pc: %.*lx (%lx) ra: %.*lx (%lx)\n", w, regs->epc, regs->epc - loadaddr, w, regs->ra, regs->ra - loadaddr); 27386561f8SAndrew Jones printf("sp: %.*lx gp: %.*lx tp : %.*lx\n", w, regs->sp, w, regs->gp, w, regs->tp); 28386561f8SAndrew Jones printf("a0: %.*lx a1: %.*lx a2 : %.*lx a3 : %.*lx\n", w, regs->a0, w, regs->a1, w, regs->a2, w, regs->a3); 29386561f8SAndrew Jones printf("a4: %.*lx a5: %.*lx a6 : %.*lx a7 : %.*lx\n", w, regs->a4, w, regs->a5, w, regs->a6, w, regs->a7); 30386561f8SAndrew Jones printf("t0: %.*lx t1: %.*lx t2 : %.*lx t3 : %.*lx\n", w, regs->t0, w, regs->t1, w, regs->t2, w, regs->t3); 31386561f8SAndrew Jones printf("t4: %.*lx t5: %.*lx t6 : %.*lx\n", w, regs->t4, w, regs->t5, w, regs->t6); 32386561f8SAndrew Jones printf("s0: %.*lx s1: %.*lx s2 : %.*lx s3 : %.*lx\n", w, regs->s0, w, regs->s1, w, regs->s2, w, regs->s3); 33386561f8SAndrew Jones printf("s4: %.*lx s5: %.*lx s6 : %.*lx s7 : %.*lx\n", w, regs->s4, w, regs->s5, w, regs->s6, w, regs->s7); 34386561f8SAndrew Jones printf("s8: %.*lx s9: %.*lx s10: %.*lx s11: %.*lx\n", w, regs->s8, w, regs->s9, w, regs->s10, w, regs->s11); 35386561f8SAndrew Jones } 36386561f8SAndrew Jones 37386561f8SAndrew Jones void do_handle_exception(struct pt_regs *regs) 38386561f8SAndrew Jones { 39386561f8SAndrew Jones struct thread_info *info = current_thread_info(); 40386561f8SAndrew Jones 41a3c0b550SAndrew Jones if (regs->cause & CAUSE_IRQ_FLAG) { 42a3c0b550SAndrew Jones unsigned long irq_cause = regs->cause & ~CAUSE_IRQ_FLAG; 43a3c0b550SAndrew Jones 44a3c0b550SAndrew Jones assert(irq_cause < INTERRUPT_CAUSE_MAX); 45a3c0b550SAndrew Jones if (info->interrupt_handlers[irq_cause]) { 46a3c0b550SAndrew Jones info->interrupt_handlers[irq_cause](regs); 47a3c0b550SAndrew Jones return; 48a3c0b550SAndrew Jones } 49a3c0b550SAndrew Jones } else { 50386561f8SAndrew Jones assert(regs->cause < EXCEPTION_CAUSE_MAX); 51a3c0b550SAndrew Jones 52386561f8SAndrew Jones if (info->exception_handlers[regs->cause]) { 53386561f8SAndrew Jones info->exception_handlers[regs->cause](regs); 54386561f8SAndrew Jones return; 55386561f8SAndrew Jones } 56a3c0b550SAndrew Jones } 57386561f8SAndrew Jones 58386561f8SAndrew Jones show_regs(regs); 596c2108dbSAndrew Jones dump_frame_stack((void *)regs->epc, (void *)regs->s0); 606c2108dbSAndrew Jones abort(); 61386561f8SAndrew Jones } 62386561f8SAndrew Jones 63a3c0b550SAndrew Jones void install_irq_handler(unsigned long cause, void (*handler)(struct pt_regs *)) 64a3c0b550SAndrew Jones { 65a3c0b550SAndrew Jones struct thread_info *info = current_thread_info(); 66a3c0b550SAndrew Jones 67a3c0b550SAndrew Jones assert(cause < INTERRUPT_CAUSE_MAX); 68a3c0b550SAndrew Jones info->interrupt_handlers[cause] = handler; 69a3c0b550SAndrew Jones } 70a3c0b550SAndrew Jones 71386561f8SAndrew Jones void install_exception_handler(unsigned long cause, void (*handler)(struct pt_regs *)) 72386561f8SAndrew Jones { 73386561f8SAndrew Jones struct thread_info *info = current_thread_info(); 74386561f8SAndrew Jones 75386561f8SAndrew Jones assert(cause < EXCEPTION_CAUSE_MAX); 76386561f8SAndrew Jones info->exception_handlers[cause] = handler; 77386561f8SAndrew Jones } 78386561f8SAndrew Jones 79386561f8SAndrew Jones void thread_info_init(void) 80386561f8SAndrew Jones { 81386561f8SAndrew Jones unsigned long hartid = csr_read(CSR_SSCRATCH); 82386561f8SAndrew Jones int cpu = hartid_to_cpu(hartid); 83386561f8SAndrew Jones 84db0ae91cSAndrew Jones isa_init(&cpus[cpu]); 85386561f8SAndrew Jones csr_write(CSR_SSCRATCH, &cpus[cpu]); 86386561f8SAndrew Jones } 87*94ca1aafSAndrew Jones 88*94ca1aafSAndrew Jones void local_hart_init(void) 89*94ca1aafSAndrew Jones { 90*94ca1aafSAndrew Jones if (cpu_has_extension(smp_processor_id(), ISA_SSTC)) { 91*94ca1aafSAndrew Jones csr_write(CSR_STIMECMP, ULONG_MAX); 92*94ca1aafSAndrew Jones if (__riscv_xlen == 32) 93*94ca1aafSAndrew Jones csr_write(CSR_STIMECMPH, ULONG_MAX); 94*94ca1aafSAndrew Jones } 95*94ca1aafSAndrew Jones } 96