diff --git a/include/sbi/sbi_trap.h b/include/sbi/sbi_trap.h index 281366e7..04c420a0 100644 --- a/include/sbi/sbi_trap.h +++ b/include/sbi/sbi_trap.h @@ -350,6 +350,8 @@ struct sbi_trap_context *sbi_trap_handler(struct sbi_trap_context *tcntx); struct sbi_trap_context *sbi_trap_rnmi_handler(struct sbi_trap_context *tcntx); +int sbi_trap_init(struct sbi_scratch *scratch, bool cold_boot); + #endif #endif diff --git a/lib/sbi/sbi_hart.c b/lib/sbi/sbi_hart.c index 21713816..bee88557 100644 --- a/lib/sbi/sbi_hart.c +++ b/lib/sbi/sbi_hart.c @@ -211,48 +211,6 @@ static int fp_init(struct sbi_scratch *scratch) return 0; } -static int delegate_traps(struct sbi_scratch *scratch) -{ - const struct sbi_platform *plat = sbi_platform_ptr(scratch); - unsigned long interrupts, exceptions; - - if (!misa_extension('S')) - /* No delegation possible as mideleg does not exist */ - return 0; - - /* Send M-mode interrupts and most exceptions to S-mode */ - interrupts = MIP_SSIP | MIP_STIP | MIP_SEIP; - interrupts |= sbi_pmu_irq_mask(); - - exceptions = (1U << CAUSE_MISALIGNED_FETCH) | (1U << CAUSE_BREAKPOINT) | - (1U << CAUSE_USER_ECALL); - if (sbi_platform_has_mfaults_delegation(plat)) - exceptions |= (1U << CAUSE_FETCH_PAGE_FAULT) | - (1U << CAUSE_LOAD_PAGE_FAULT) | - (1U << CAUSE_STORE_PAGE_FAULT) | - (1U << CAUSE_SW_CHECK_EXCP); - - /* - * If hypervisor extension available then we only handle hypervisor - * calls (i.e. ecalls from HS-mode) in M-mode. - * - * The HS-mode will additionally handle supervisor calls (i.e. ecalls - * from VS-mode), Guest page faults and Virtual interrupts. - */ - if (misa_extension('H')) { - exceptions |= (1U << CAUSE_VIRTUAL_SUPERVISOR_ECALL); - exceptions |= (1U << CAUSE_FETCH_GUEST_PAGE_FAULT); - exceptions |= (1U << CAUSE_LOAD_GUEST_PAGE_FAULT); - exceptions |= (1U << CAUSE_VIRTUAL_INST_FAULT); - exceptions |= (1U << CAUSE_STORE_GUEST_PAGE_FAULT); - } - - csr_write(CSR_MIDELEG, interrupts); - csr_write(CSR_MEDELEG, exceptions); - - return 0; -} - void sbi_hart_delegation_dump(struct sbi_scratch *scratch, const char *prefix, const char *suffix) { @@ -773,10 +731,6 @@ int sbi_hart_init(struct sbi_scratch *scratch, bool cold_boot) return rc; } - rc = delegate_traps(scratch); - if (rc) - return rc; - return sbi_hart_reinit(scratch); } diff --git a/lib/sbi/sbi_init.c b/lib/sbi/sbi_init.c index 658fe37f..9bb1a37e 100644 --- a/lib/sbi/sbi_init.c +++ b/lib/sbi/sbi_init.c @@ -309,6 +309,10 @@ static void __noreturn init_coldboot(struct sbi_scratch *scratch, u32 hartid) __stack_chk_guard = guard_val; } + rc = sbi_trap_init(scratch, true); + if (rc) + sbi_hart_hang(); + rc = sbi_timer_init(scratch, true); if (rc) sbi_hart_hang(); @@ -466,6 +470,10 @@ static void __noreturn init_warm_startup(struct sbi_scratch *scratch, if (rc) sbi_hart_hang(); + rc = sbi_trap_init(scratch, false); + if (rc) + sbi_hart_hang(); + rc = sbi_timer_init(scratch, false); if (rc) sbi_hart_hang(); diff --git a/lib/sbi/sbi_trap.c b/lib/sbi/sbi_trap.c index 1e55b885..16774fd2 100644 --- a/lib/sbi/sbi_trap.c +++ b/lib/sbi/sbi_trap.c @@ -414,3 +414,50 @@ struct sbi_trap_context *sbi_trap_rnmi_handler(struct sbi_trap_context *tcntx) /* Never returns */ return tcntx; } + +static int delegate_traps(struct sbi_scratch *scratch) +{ + const struct sbi_platform *plat = sbi_platform_ptr(scratch); + unsigned long interrupts, exceptions; + + if (!misa_extension('S')) + /* No delegation possible as mideleg does not exist */ + return 0; + + /* Send M-mode interrupts and most exceptions to S-mode */ + interrupts = MIP_SSIP | MIP_STIP | MIP_SEIP; + interrupts |= sbi_pmu_irq_mask(); + + exceptions = (1U << CAUSE_MISALIGNED_FETCH) | (1U << CAUSE_BREAKPOINT) | + (1U << CAUSE_USER_ECALL); + if (sbi_platform_has_mfaults_delegation(plat)) + exceptions |= (1U << CAUSE_FETCH_PAGE_FAULT) | + (1U << CAUSE_LOAD_PAGE_FAULT) | + (1U << CAUSE_STORE_PAGE_FAULT) | + (1U << CAUSE_SW_CHECK_EXCP); + + /* + * If hypervisor extension available then we only handle hypervisor + * calls (i.e. ecalls from HS-mode) in M-mode. + * + * The HS-mode will additionally handle supervisor calls (i.e. ecalls + * from VS-mode), Guest page faults and Virtual interrupts. + */ + if (misa_extension('H')) { + exceptions |= (1U << CAUSE_VIRTUAL_SUPERVISOR_ECALL); + exceptions |= (1U << CAUSE_FETCH_GUEST_PAGE_FAULT); + exceptions |= (1U << CAUSE_LOAD_GUEST_PAGE_FAULT); + exceptions |= (1U << CAUSE_VIRTUAL_INST_FAULT); + exceptions |= (1U << CAUSE_STORE_GUEST_PAGE_FAULT); + } + + csr_write(CSR_MIDELEG, interrupts); + csr_write(CSR_MEDELEG, exceptions); + + return 0; +} + +int sbi_trap_init(struct sbi_scratch *scratch, bool cold_boot) +{ + return delegate_traps(scratch); +}