5 Commits

Author SHA1 Message Date
Carlos López
43cace6c36 lib: sbi: check result of pmp_get() in is_pmp_entry_mapped()
pmp_get() may return an error if the given entry, given by the caller
of is_pmp_entry_mapped(), is invalid. This results in the output
parameters for pmp_get() being uninitialized. To avoid using garbage
values, check the result and return early if necessary.

This issue is not being hit because at the moment
is_pmp_entry_mapped() is only being called from a single site with a
valid hardcoded value.

Signed-off-by: Carlos López <carlos.lopezr4096@gmail.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-08-02 08:53:22 +05:30
Carlos López
cb0f4757fc lib: sbi: fwft: fix incorrect size passed to sbi_zalloc()
The fwt_hart_state struct inciludes a flexible array member, so its
allocation size will be that of the struct itself, plus that of each
of the members in the array. When calculating this size, instead of
taking the size of the struct, the size of a pointer to it was taken,
which is incorrect. Luckily, this happenned to not produce memory
corruption because the size of the non-flexible members of the struct
is the same as the size of a pointer.

Signed-off-by: Carlos López <carlos.lopezr4096@gmail.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-08-02 08:53:20 +05:30
Carlos López
baf6a75e3f lib: sbi: dbtr: fix potential NULL pointer dereferences
In several dbtr functions, we first check that the dbtr trigger is not
NULL and that its state is what we expect. However, it only makes
sense to perform the second check if the dbtr trigger is not NULL.
Othwerwise we will dereference a NULL pointer. Thus, change the
condition so that it shortcuts to the first check if necessary.

Signed-off-by: Carlos López <carlos.lopezr4096@gmail.com>
Reviewed-By: Anup Patel <anup@brainfault.org>
2024-08-02 08:53:19 +05:30
Eric Lin
778949eeb8 include: Adjust Sscofpmf mhpmevent mask for upper 8 bits
Currently, OpenSBI reserves the upper 16 bits in mhpmevent for
the Sscofpmf extension.

However, according to the Sscofpmf extension specification[1],
it only defines the upper 8 bits in mhpmevent for privilege mode
inhibit and counter overflow disable. Other bits are defined by
the platform for event selection.

Since vendors might define raw event encoding exceeding 48 bits in
mhpmevent, we should adjust the MHPMEVENT_SSCOF_MASK to support it.

Link: https://github.com/riscvarchive/riscv-count-overflow [1]
Signed-off-by: Eric Lin <eric.lin@sifive.com>
Reviewed-by: Xiang W <wxjstz@126.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-08-02 08:53:17 +05:30
Samuel Holland
65a3938fad lib: sbi_hsm: Save/restore menvcfg only when it exists
Attempting to access the menvcfg CSR raises an illegal instruction
exception on hardware which implements Sm1p11 or older.

Fixes: e9ee9678ba ("lib: sbi: fwft: add support for SBI_FWFT_PTE_AD_HW_UPDATING")
Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-07-29 11:34:18 +05:30
5 changed files with 15 additions and 10 deletions

View File

@@ -207,7 +207,7 @@
#endif
#define MHPMEVENT_SSCOF_MASK _ULL(0xFFFF000000000000)
#define MHPMEVENT_SSCOF_MASK _ULL(0xFF00000000000000)
#define ENVCFG_STCE (_ULL(1) << 63)
#define ENVCFG_PBMTE (_ULL(1) << 62)

View File

@@ -291,7 +291,8 @@ int is_pmp_entry_mapped(unsigned long entry)
unsigned long addr;
unsigned long log2len;
pmp_get(entry, &prot, &addr, &log2len);
if (pmp_get(entry, &prot, &addr, &log2len) != 0)
return false;
/* If address matching bits are non-zero, the entry is enable */
if (prot & PMP_A)

View File

@@ -357,7 +357,7 @@ static void dbtr_trigger_enable(struct sbi_dbtr_trigger *trig)
unsigned long state;
unsigned long tdata1;
if (!trig && !(trig->state & RV_DBTR_BIT_MASK(TS, MAPPED)))
if (!trig || !(trig->state & RV_DBTR_BIT_MASK(TS, MAPPED)))
return;
state = trig->state;
@@ -403,7 +403,7 @@ static void dbtr_trigger_disable(struct sbi_dbtr_trigger *trig)
{
unsigned long tdata1;
if (!trig && !(trig->state & RV_DBTR_BIT_MASK(TS, MAPPED)))
if (!trig || !(trig->state & RV_DBTR_BIT_MASK(TS, MAPPED)))
return;
tdata1 = trig->tdata1;
@@ -429,7 +429,7 @@ static void dbtr_trigger_disable(struct sbi_dbtr_trigger *trig)
static void dbtr_trigger_clear(struct sbi_dbtr_trigger *trig)
{
if (!trig && !(trig->state & RV_DBTR_BIT_MASK(TS, MAPPED)))
if (!trig || !(trig->state & RV_DBTR_BIT_MASK(TS, MAPPED)))
return;
csr_write(CSR_TSELECT, trig->index);

View File

@@ -251,7 +251,7 @@ int sbi_fwft_init(struct sbi_scratch *scratch, bool cold_boot)
fhs = fwft_get_hart_state_ptr(scratch);
if (!fhs) {
fhs = sbi_zalloc(sizeof(fhs) + array_size(features) * sizeof(struct fwft_config));
fhs = sbi_zalloc(sizeof(*fhs) + array_size(features) * sizeof(struct fwft_config));
if (!fhs)
return SBI_ENOMEM;

View File

@@ -423,21 +423,25 @@ void __sbi_hsm_suspend_non_ret_save(struct sbi_scratch *scratch)
hdata->saved_mie = csr_read(CSR_MIE);
hdata->saved_mip = csr_read(CSR_MIP) & (MIP_SSIP | MIP_STIP);
hdata->saved_medeleg = csr_read(CSR_MEDELEG);
if (sbi_hart_priv_version(scratch) >= SBI_HART_PRIV_VER_1_12) {
#if __riscv_xlen == 32
hdata->saved_menvcfgh = csr_read(CSR_MENVCFGH);
#endif
hdata->saved_menvcfg = csr_read(CSR_MENVCFG);
}
}
static void __sbi_hsm_suspend_non_ret_restore(struct sbi_scratch *scratch)
{
struct sbi_hsm_data *hdata = sbi_scratch_offset_ptr(scratch,
hart_data_offset);
if (sbi_hart_priv_version(scratch) >= SBI_HART_PRIV_VER_1_12) {
csr_write(CSR_MENVCFG, hdata->saved_menvcfg);
#if __riscv_xlen == 32
csr_write(CSR_MENVCFGH, hdata->saved_menvcfgh);
#endif
}
csr_write(CSR_MEDELEG, hdata->saved_medeleg);
csr_write(CSR_MIE, hdata->saved_mie);
csr_set(CSR_MIP, (hdata->saved_mip & (MIP_SSIP | MIP_STIP)));