diff options
| author | Anup Patel <[email protected]> | 2023-12-11 20:59:14 +0530 |
|---|---|---|
| committer | Anup Patel <[email protected]> | 2023-12-19 15:56:37 +0530 |
| commit | 3284bea83368de2ced244d5b2b0eaeaae812a08d (patch) | |
| tree | 13dd7291e406519a06b421d0d06e948055d5e959 /lib | |
| parent | cdebae2cc9539e2e0553b9c68eab22997c734cbb (diff) | |
lib: sbi: Allow ecall handlers to directly update register state
Some of the upcoming SBI extensions (such as SSE) will directly
update register state so improve the prototype of ecall handler
to accommodate this. Further, this flexibility allows us to
push the trap redirection from sbi_ecall_handler() to the
sbi_ecall_legacy_handler().
Signed-off-by: Anup Patel <[email protected]>
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/sbi/sbi_ecall.c | 13 | ||||
| -rw-r--r-- | lib/sbi/sbi_ecall_base.c | 27 | ||||
| -rw-r--r-- | lib/sbi/sbi_ecall_cppc.c | 13 | ||||
| -rw-r--r-- | lib/sbi/sbi_ecall_dbcn.c | 9 | ||||
| -rw-r--r-- | lib/sbi/sbi_ecall_hsm.c | 7 | ||||
| -rw-r--r-- | lib/sbi/sbi_ecall_ipi.c | 5 | ||||
| -rw-r--r-- | lib/sbi/sbi_ecall_legacy.c | 37 | ||||
| -rw-r--r-- | lib/sbi/sbi_ecall_pmu.c | 17 | ||||
| -rw-r--r-- | lib/sbi/sbi_ecall_rfence.c | 5 | ||||
| -rw-r--r-- | lib/sbi/sbi_ecall_srst.c | 5 | ||||
| -rw-r--r-- | lib/sbi/sbi_ecall_susp.c | 7 | ||||
| -rw-r--r-- | lib/sbi/sbi_ecall_time.c | 5 | ||||
| -rw-r--r-- | lib/sbi/sbi_ecall_vendor.c | 8 |
13 files changed, 81 insertions, 77 deletions
diff --git a/lib/sbi/sbi_ecall.c b/lib/sbi/sbi_ecall.c index 3eb4f0ad..631c5dd1 100644 --- a/lib/sbi/sbi_ecall.c +++ b/lib/sbi/sbi_ecall.c @@ -101,14 +101,12 @@ int sbi_ecall_handler(struct sbi_trap_regs *regs) struct sbi_ecall_extension *ext; unsigned long extension_id = regs->a7; unsigned long func_id = regs->a6; - struct sbi_trap_info trap = {0}; - unsigned long out_val = 0; + struct sbi_ecall_return out = {0}; bool is_0_1_spec = 0; ext = sbi_ecall_find_extension(extension_id); if (ext && ext->handle) { - ret = ext->handle(extension_id, func_id, - regs, &out_val, &trap); + ret = ext->handle(extension_id, func_id, regs, &out); if (extension_id >= SBI_EXT_0_1_SET_TIMER && extension_id <= SBI_EXT_0_1_SHUTDOWN) is_0_1_spec = 1; @@ -116,10 +114,7 @@ int sbi_ecall_handler(struct sbi_trap_regs *regs) ret = SBI_ENOTSUPP; } - if (ret == SBI_ETRAP) { - trap.epc = regs->mepc; - sbi_trap_redirect(regs, &trap); - } else { + if (!out.skip_regs_update) { if (ret < SBI_LAST_ERR || (extension_id != SBI_EXT_0_1_CONSOLE_GETCHAR && SBI_SUCCESS < ret)) { @@ -140,7 +135,7 @@ int sbi_ecall_handler(struct sbi_trap_regs *regs) regs->mepc += 4; regs->a0 = ret; if (!is_0_1_spec) - regs->a1 = out_val; + regs->a1 = out.value; } return 0; diff --git a/lib/sbi/sbi_ecall_base.c b/lib/sbi/sbi_ecall_base.c index 74f05eb2..b7178ea8 100644 --- a/lib/sbi/sbi_ecall_base.c +++ b/lib/sbi/sbi_ecall_base.c @@ -33,37 +33,36 @@ static int sbi_ecall_base_probe(unsigned long extid, unsigned long *out_val) } static int sbi_ecall_base_handler(unsigned long extid, unsigned long funcid, - const struct sbi_trap_regs *regs, - unsigned long *out_val, - struct sbi_trap_info *out_trap) + struct sbi_trap_regs *regs, + struct sbi_ecall_return *out) { int ret = 0; switch (funcid) { case SBI_EXT_BASE_GET_SPEC_VERSION: - *out_val = (SBI_ECALL_VERSION_MAJOR << - SBI_SPEC_VERSION_MAJOR_OFFSET) & - (SBI_SPEC_VERSION_MAJOR_MASK << - SBI_SPEC_VERSION_MAJOR_OFFSET); - *out_val = *out_val | SBI_ECALL_VERSION_MINOR; + out->value = (SBI_ECALL_VERSION_MAJOR << + SBI_SPEC_VERSION_MAJOR_OFFSET) & + (SBI_SPEC_VERSION_MAJOR_MASK << + SBI_SPEC_VERSION_MAJOR_OFFSET); + out->value = out->value | SBI_ECALL_VERSION_MINOR; break; case SBI_EXT_BASE_GET_IMP_ID: - *out_val = sbi_ecall_get_impid(); + out->value = sbi_ecall_get_impid(); break; case SBI_EXT_BASE_GET_IMP_VERSION: - *out_val = OPENSBI_VERSION; + out->value = OPENSBI_VERSION; break; case SBI_EXT_BASE_GET_MVENDORID: - *out_val = csr_read(CSR_MVENDORID); + out->value = csr_read(CSR_MVENDORID); break; case SBI_EXT_BASE_GET_MARCHID: - *out_val = csr_read(CSR_MARCHID); + out->value = csr_read(CSR_MARCHID); break; case SBI_EXT_BASE_GET_MIMPID: - *out_val = csr_read(CSR_MIMPID); + out->value = csr_read(CSR_MIMPID); break; case SBI_EXT_BASE_PROBE_EXT: - ret = sbi_ecall_base_probe(regs->a0, out_val); + ret = sbi_ecall_base_probe(regs->a0, &out->value); break; default: ret = SBI_ENOTSUPP; diff --git a/lib/sbi/sbi_ecall_cppc.c b/lib/sbi/sbi_ecall_cppc.c index b54d54ec..c26bb401 100644 --- a/lib/sbi/sbi_ecall_cppc.c +++ b/lib/sbi/sbi_ecall_cppc.c @@ -12,9 +12,8 @@ #include <sbi/sbi_cppc.h> static int sbi_ecall_cppc_handler(unsigned long extid, unsigned long funcid, - const struct sbi_trap_regs *regs, - unsigned long *out_val, - struct sbi_trap_info *out_trap) + struct sbi_trap_regs *regs, + struct sbi_ecall_return *out) { int ret = 0; uint64_t temp; @@ -22,14 +21,14 @@ static int sbi_ecall_cppc_handler(unsigned long extid, unsigned long funcid, switch (funcid) { case SBI_EXT_CPPC_READ: ret = sbi_cppc_read(regs->a0, &temp); - *out_val = temp; + out->value = temp; break; case SBI_EXT_CPPC_READ_HI: #if __riscv_xlen == 32 ret = sbi_cppc_read(regs->a0, &temp); - *out_val = temp >> 32; + out->value = temp >> 32; #else - *out_val = 0; + out->value = 0; #endif break; case SBI_EXT_CPPC_WRITE: @@ -38,7 +37,7 @@ static int sbi_ecall_cppc_handler(unsigned long extid, unsigned long funcid, case SBI_EXT_CPPC_PROBE: ret = sbi_cppc_probe(regs->a0); if (ret >= 0) { - *out_val = ret; + out->value = ret; ret = 0; } break; diff --git a/lib/sbi/sbi_ecall_dbcn.c b/lib/sbi/sbi_ecall_dbcn.c index 18cd6c8b..49a7713f 100644 --- a/lib/sbi/sbi_ecall_dbcn.c +++ b/lib/sbi/sbi_ecall_dbcn.c @@ -17,9 +17,8 @@ #include <sbi/sbi_hart.h> static int sbi_ecall_dbcn_handler(unsigned long extid, unsigned long funcid, - const struct sbi_trap_regs *regs, - unsigned long *out_val, - struct sbi_trap_info *out_trap) + struct sbi_trap_regs *regs, + struct sbi_ecall_return *out) { ulong smode = (csr_read(CSR_MSTATUS) & MSTATUS_MPP) >> MSTATUS_MPP_SHIFT; @@ -49,9 +48,9 @@ static int sbi_ecall_dbcn_handler(unsigned long extid, unsigned long funcid, return SBI_ERR_INVALID_PARAM; sbi_hart_map_saddr(regs->a1, regs->a0); if (funcid == SBI_EXT_DBCN_CONSOLE_WRITE) - *out_val = sbi_nputs((const char *)regs->a1, regs->a0); + out->value = sbi_nputs((const char *)regs->a1, regs->a0); else - *out_val = sbi_ngets((char *)regs->a1, regs->a0); + out->value = sbi_ngets((char *)regs->a1, regs->a0); sbi_hart_unmap_saddr(); return 0; case SBI_EXT_DBCN_CONSOLE_WRITE_BYTE: diff --git a/lib/sbi/sbi_ecall_hsm.c b/lib/sbi/sbi_ecall_hsm.c index 20705c39..93170b09 100644 --- a/lib/sbi/sbi_ecall_hsm.c +++ b/lib/sbi/sbi_ecall_hsm.c @@ -17,9 +17,8 @@ #include <sbi/riscv_asm.h> static int sbi_ecall_hsm_handler(unsigned long extid, unsigned long funcid, - const struct sbi_trap_regs *regs, - unsigned long *out_val, - struct sbi_trap_info *out_trap) + struct sbi_trap_regs *regs, + struct sbi_ecall_return *out) { int ret = 0; struct sbi_scratch *scratch = sbi_scratch_thishart_ptr(); @@ -47,7 +46,7 @@ static int sbi_ecall_hsm_handler(unsigned long extid, unsigned long funcid, } if (ret >= 0) { - *out_val = ret; + out->value = ret; ret = 0; } diff --git a/lib/sbi/sbi_ecall_ipi.c b/lib/sbi/sbi_ecall_ipi.c index a40d6b8c..50ef41dc 100644 --- a/lib/sbi/sbi_ecall_ipi.c +++ b/lib/sbi/sbi_ecall_ipi.c @@ -15,9 +15,8 @@ #include <sbi/sbi_ipi.h> static int sbi_ecall_ipi_handler(unsigned long extid, unsigned long funcid, - const struct sbi_trap_regs *regs, - unsigned long *out_val, - struct sbi_trap_info *out_trap) + struct sbi_trap_regs *regs, + struct sbi_ecall_return *out) { int ret = 0; diff --git a/lib/sbi/sbi_ecall_legacy.c b/lib/sbi/sbi_ecall_legacy.c index 556f629b..48bd2274 100644 --- a/lib/sbi/sbi_ecall_legacy.c +++ b/lib/sbi/sbi_ecall_legacy.c @@ -43,13 +43,13 @@ static int sbi_load_hart_mask_unpriv(ulong *pmask, ulong *hmask, } static int sbi_ecall_legacy_handler(unsigned long extid, unsigned long funcid, - const struct sbi_trap_regs *regs, - unsigned long *out_val, - struct sbi_trap_info *out_trap) + struct sbi_trap_regs *regs, + struct sbi_ecall_return *out) { int ret = 0; struct sbi_tlb_info tlb_info; u32 source_hart = current_hartid(); + struct sbi_trap_info trap = {0}; ulong hmask = 0; switch (extid) { @@ -71,37 +71,58 @@ static int sbi_ecall_legacy_handler(unsigned long extid, unsigned long funcid, break; case SBI_EXT_0_1_SEND_IPI: ret = sbi_load_hart_mask_unpriv((ulong *)regs->a0, - &hmask, out_trap); - if (ret != SBI_ETRAP) + &hmask, &trap); + if (ret != SBI_ETRAP) { ret = sbi_ipi_send_smode(hmask, 0); + } else { + ret = 0; + trap.epc = regs->mepc; + sbi_trap_redirect(regs, &trap); + out->skip_regs_update = true; + } break; case SBI_EXT_0_1_REMOTE_FENCE_I: ret = sbi_load_hart_mask_unpriv((ulong *)regs->a0, - &hmask, out_trap); + &hmask, &trap); if (ret != SBI_ETRAP) { SBI_TLB_INFO_INIT(&tlb_info, 0, 0, 0, 0, SBI_TLB_FENCE_I, source_hart); ret = sbi_tlb_request(hmask, 0, &tlb_info); + } else { + ret = 0; + trap.epc = regs->mepc; + sbi_trap_redirect(regs, &trap); + out->skip_regs_update = true; } break; case SBI_EXT_0_1_REMOTE_SFENCE_VMA: ret = sbi_load_hart_mask_unpriv((ulong *)regs->a0, - &hmask, out_trap); + &hmask, &trap); if (ret != SBI_ETRAP) { SBI_TLB_INFO_INIT(&tlb_info, regs->a1, regs->a2, 0, 0, SBI_TLB_SFENCE_VMA, source_hart); ret = sbi_tlb_request(hmask, 0, &tlb_info); + } else { + ret = 0; + trap.epc = regs->mepc; + sbi_trap_redirect(regs, &trap); + out->skip_regs_update = true; } break; case SBI_EXT_0_1_REMOTE_SFENCE_VMA_ASID: ret = sbi_load_hart_mask_unpriv((ulong *)regs->a0, - &hmask, out_trap); + &hmask, &trap); if (ret != SBI_ETRAP) { SBI_TLB_INFO_INIT(&tlb_info, regs->a1, regs->a2, regs->a3, 0, SBI_TLB_SFENCE_VMA_ASID, source_hart); ret = sbi_tlb_request(hmask, 0, &tlb_info); + } else { + ret = 0; + trap.epc = regs->mepc; + sbi_trap_redirect(regs, &trap); + out->skip_regs_update = true; } break; case SBI_EXT_0_1_SHUTDOWN: diff --git a/lib/sbi/sbi_ecall_pmu.c b/lib/sbi/sbi_ecall_pmu.c index c5859110..40a63a62 100644 --- a/lib/sbi/sbi_ecall_pmu.c +++ b/lib/sbi/sbi_ecall_pmu.c @@ -18,9 +18,8 @@ #include <sbi/riscv_asm.h> static int sbi_ecall_pmu_handler(unsigned long extid, unsigned long funcid, - const struct sbi_trap_regs *regs, - unsigned long *out_val, - struct sbi_trap_info *out_trap) + struct sbi_trap_regs *regs, + struct sbi_ecall_return *out) { int ret = 0; uint64_t temp; @@ -29,12 +28,12 @@ static int sbi_ecall_pmu_handler(unsigned long extid, unsigned long funcid, case SBI_EXT_PMU_NUM_COUNTERS: ret = sbi_pmu_num_ctr(); if (ret >= 0) { - *out_val = ret; + out->value = ret; ret = 0; } break; case SBI_EXT_PMU_COUNTER_GET_INFO: - ret = sbi_pmu_ctr_get_info(regs->a0, out_val); + ret = sbi_pmu_ctr_get_info(regs->a0, &out->value); break; case SBI_EXT_PMU_COUNTER_CFG_MATCH: #if __riscv_xlen == 32 @@ -45,21 +44,21 @@ static int sbi_ecall_pmu_handler(unsigned long extid, unsigned long funcid, ret = sbi_pmu_ctr_cfg_match(regs->a0, regs->a1, regs->a2, regs->a3, temp); if (ret >= 0) { - *out_val = ret; + out->value = ret; ret = 0; } break; case SBI_EXT_PMU_COUNTER_FW_READ: ret = sbi_pmu_ctr_fw_read(regs->a0, &temp); - *out_val = temp; + out->value = temp; break; case SBI_EXT_PMU_COUNTER_FW_READ_HI: #if __riscv_xlen == 32 ret = sbi_pmu_ctr_fw_read(regs->a0, &temp); - *out_val = temp >> 32; + out->value = temp >> 32; #else - *out_val = 0; + out->value = 0; #endif break; case SBI_EXT_PMU_COUNTER_START: diff --git a/lib/sbi/sbi_ecall_rfence.c b/lib/sbi/sbi_ecall_rfence.c index 4b74d412..ded16c26 100644 --- a/lib/sbi/sbi_ecall_rfence.c +++ b/lib/sbi/sbi_ecall_rfence.c @@ -16,9 +16,8 @@ #include <sbi/sbi_tlb.h> static int sbi_ecall_rfence_handler(unsigned long extid, unsigned long funcid, - const struct sbi_trap_regs *regs, - unsigned long *out_val, - struct sbi_trap_info *out_trap) + struct sbi_trap_regs *regs, + struct sbi_ecall_return *out) { int ret = 0; unsigned long vmid; diff --git a/lib/sbi/sbi_ecall_srst.c b/lib/sbi/sbi_ecall_srst.c index dcd560d2..46cfaca4 100644 --- a/lib/sbi/sbi_ecall_srst.c +++ b/lib/sbi/sbi_ecall_srst.c @@ -15,9 +15,8 @@ #include <sbi/sbi_system.h> static int sbi_ecall_srst_handler(unsigned long extid, unsigned long funcid, - const struct sbi_trap_regs *regs, - unsigned long *out_val, - struct sbi_trap_info *out_trap) + struct sbi_trap_regs *regs, + struct sbi_ecall_return *out) { if (funcid == SBI_EXT_SRST_RESET) { if ((((u32)-1U) <= ((u64)regs->a0)) || diff --git a/lib/sbi/sbi_ecall_susp.c b/lib/sbi/sbi_ecall_susp.c index 2bfd99ae..7b66bfcd 100644 --- a/lib/sbi/sbi_ecall_susp.c +++ b/lib/sbi/sbi_ecall_susp.c @@ -6,9 +6,8 @@ #include <sbi/sbi_system.h> static int sbi_ecall_susp_handler(unsigned long extid, unsigned long funcid, - const struct sbi_trap_regs *regs, - unsigned long *out_val, - struct sbi_trap_info *out_trap) + struct sbi_trap_regs *regs, + struct sbi_ecall_return *out) { int ret = SBI_ENOTSUPP; @@ -16,7 +15,7 @@ static int sbi_ecall_susp_handler(unsigned long extid, unsigned long funcid, ret = sbi_system_suspend(regs->a0, regs->a1, regs->a2); if (ret >= 0) { - *out_val = ret; + out->value = ret; ret = 0; } diff --git a/lib/sbi/sbi_ecall_time.c b/lib/sbi/sbi_ecall_time.c index e79196f7..5a2316eb 100644 --- a/lib/sbi/sbi_ecall_time.c +++ b/lib/sbi/sbi_ecall_time.c @@ -15,9 +15,8 @@ #include <sbi/sbi_timer.h> static int sbi_ecall_time_handler(unsigned long extid, unsigned long funcid, - const struct sbi_trap_regs *regs, - unsigned long *out_val, - struct sbi_trap_info *out_trap) + struct sbi_trap_regs *regs, + struct sbi_ecall_return *out) { int ret = 0; diff --git a/lib/sbi/sbi_ecall_vendor.c b/lib/sbi/sbi_ecall_vendor.c index 700f475f..ebebc586 100644 --- a/lib/sbi/sbi_ecall_vendor.c +++ b/lib/sbi/sbi_ecall_vendor.c @@ -23,13 +23,11 @@ static inline unsigned long sbi_ecall_vendor_id(void) } static int sbi_ecall_vendor_handler(unsigned long extid, unsigned long funcid, - const struct sbi_trap_regs *regs, - unsigned long *out_val, - struct sbi_trap_info *out_trap) + struct sbi_trap_regs *regs, + struct sbi_ecall_return *out) { return sbi_platform_vendor_ext_provider(sbi_platform_thishart_ptr(), - funcid, regs, - out_val, out_trap); + funcid, regs, out); } struct sbi_ecall_extension ecall_vendor; |
