lib: sbi: Use sbi_hartmask in sbi_hsm_hart_interruptible_mask()

This removes several hartid/hartindex conversions, as well as two loops
through the mask for broadcast IPIs.

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
This commit is contained in:
Samuel Holland
2024-08-30 08:49:13 -07:00
committed by Anup Patel
parent ebe0f31446
commit fe153c5516
6 changed files with 52 additions and 56 deletions

View File

@@ -226,14 +226,13 @@ extern struct sbi_dlist domain_list;
bool sbi_domain_is_assigned_hart(const struct sbi_domain *dom, u32 hartid); bool sbi_domain_is_assigned_hart(const struct sbi_domain *dom, u32 hartid);
/** /**
* Get ulong assigned HART mask for given domain and HART base ID * Get the assigned HART mask for given domain
* @param dom pointer to domain * @param dom pointer to domain
* @param hbase the HART base ID * @param mask the output hartmask to fill
* @return ulong possible HART mask * @return 0 on success and SBI_Exxx (< 0) on failure
* Note: the return ulong mask will be set to zero on failure.
*/ */
ulong sbi_domain_get_assigned_hartmask(const struct sbi_domain *dom, int sbi_domain_get_assigned_hartmask(const struct sbi_domain *dom,
ulong hbase); struct sbi_hartmask *mask);
/** /**
* Initialize a domain memory region based on it's physical * Initialize a domain memory region based on it's physical

View File

@@ -127,6 +127,18 @@ static inline void sbi_hartmask_clear_all(struct sbi_hartmask *dstp)
bitmap_zero(sbi_hartmask_bits(dstp), SBI_HARTMASK_MAX_BITS); bitmap_zero(sbi_hartmask_bits(dstp), SBI_HARTMASK_MAX_BITS);
} }
/**
* *dstp = *srcp
* @param dstp the hartmask destination
* @param srcp the hartmask source
*/
static inline void sbi_hartmask_copy(struct sbi_hartmask *dstp,
const struct sbi_hartmask *srcp)
{
bitmap_copy(sbi_hartmask_bits(dstp), sbi_hartmask_bits(srcp),
SBI_HARTMASK_MAX_BITS);
}
/** /**
* *dstp = *src1p & *src2p * *dstp = *src1p & *src2p
* @param dstp the hartmask result * @param dstp the hartmask result

View File

@@ -10,6 +10,7 @@
#ifndef __SBI_HSM_H__ #ifndef __SBI_HSM_H__
#define __SBI_HSM_H__ #define __SBI_HSM_H__
#include <sbi/sbi_hartmask.h>
#include <sbi/sbi_types.h> #include <sbi/sbi_types.h>
/** Hart state managment device */ /** Hart state managment device */
@@ -75,7 +76,7 @@ bool sbi_hsm_hart_change_state(struct sbi_scratch *scratch, long oldstate,
int __sbi_hsm_hart_get_state(u32 hartindex); int __sbi_hsm_hart_get_state(u32 hartindex);
int sbi_hsm_hart_get_state(const struct sbi_domain *dom, u32 hartid); int sbi_hsm_hart_get_state(const struct sbi_domain *dom, u32 hartid);
int sbi_hsm_hart_interruptible_mask(const struct sbi_domain *dom, int sbi_hsm_hart_interruptible_mask(const struct sbi_domain *dom,
ulong hbase, ulong *out_hmask); struct sbi_hartmask *mask);
void __sbi_hsm_suspend_non_ret_save(struct sbi_scratch *scratch); void __sbi_hsm_suspend_non_ret_save(struct sbi_scratch *scratch);
void __noreturn sbi_hsm_hart_start_finish(struct sbi_scratch *scratch, void __noreturn sbi_hsm_hart_start_finish(struct sbi_scratch *scratch,
u32 hartid); u32 hartid);

View File

@@ -75,20 +75,19 @@ bool sbi_domain_is_assigned_hart(const struct sbi_domain *dom, u32 hartid)
return ret; return ret;
} }
ulong sbi_domain_get_assigned_hartmask(const struct sbi_domain *dom, int sbi_domain_get_assigned_hartmask(const struct sbi_domain *dom,
ulong hbase) struct sbi_hartmask *mask)
{ {
ulong ret = 0; ulong ret = 0;
struct sbi_domain *tdom = (struct sbi_domain *)dom; struct sbi_domain *tdom = (struct sbi_domain *)dom;
if (!dom) if (!dom) {
sbi_hartmask_clear_all(mask);
return 0; return 0;
}
spin_lock(&tdom->assigned_harts_lock); spin_lock(&tdom->assigned_harts_lock);
for (int i = 0; i < 8 * sizeof(ret); i++) { sbi_hartmask_copy(mask, &tdom->assigned_harts);
if (sbi_hartmask_test_hartid(hbase + i, &tdom->assigned_harts))
ret |= 1UL << i;
}
spin_unlock(&tdom->assigned_harts_lock); spin_unlock(&tdom->assigned_harts_lock);
return ret; return ret;

View File

@@ -110,36 +110,27 @@ static void hsm_start_ticket_release(struct sbi_hsm_data *hdata)
} }
/** /**
* Get ulong HART mask for given HART base ID * Get the mask of harts which are valid IPI targets
* @param dom the domain to be used for output HART mask * @param dom the domain to be used for output HART mask
* @param hbase the HART base ID * @param mask the output hartmask to fill
* @param out_hmask the output ulong HART mask
* @return 0 on success and SBI_Exxx (< 0) on failure * @return 0 on success and SBI_Exxx (< 0) on failure
* Note: the output HART mask will be set to zero on failure as well.
*/ */
int sbi_hsm_hart_interruptible_mask(const struct sbi_domain *dom, int sbi_hsm_hart_interruptible_mask(const struct sbi_domain *dom,
ulong hbase, ulong *out_hmask) struct sbi_hartmask *mask)
{ {
int hstate; int hstate, ret;
ulong i, hmask, dmask; u32 i;
u32 hartindex;
*out_hmask = 0; ret = sbi_domain_get_assigned_hartmask(dom, mask);
if (!sbi_hartid_valid(hbase)) if (ret)
return SBI_EINVAL; return ret;
dmask = sbi_domain_get_assigned_hartmask(dom, hbase); sbi_hartmask_for_each_hartindex(i, mask) {
for (i = 0; i < BITS_PER_LONG; i++) { hstate = __sbi_hsm_hart_get_state(i);
hmask = 1UL << i; if (hstate != SBI_HSM_STATE_STARTED &&
if (!(dmask & hmask)) hstate != SBI_HSM_STATE_SUSPENDED &&
continue; hstate != SBI_HSM_STATE_RESUME_PENDING)
sbi_hartmask_clear_hartindex(i, mask);
hartindex = sbi_hartid_to_hartindex(hbase + i);
hstate = __sbi_hsm_hart_get_state(hartindex);
if (hstate == SBI_HSM_STATE_STARTED ||
hstate == SBI_HSM_STATE_SUSPENDED ||
hstate == SBI_HSM_STATE_RESUME_PENDING)
*out_hmask |= hmask;
} }
return 0; return 0;

View File

@@ -111,31 +111,25 @@ int sbi_ipi_send_many(ulong hmask, ulong hbase, u32 event, void *data)
{ {
int rc = 0; int rc = 0;
bool retry_needed; bool retry_needed;
ulong i, m; ulong i;
struct sbi_hartmask target_mask = {0}; struct sbi_hartmask target_mask;
struct sbi_domain *dom = sbi_domain_thishart_ptr(); struct sbi_domain *dom = sbi_domain_thishart_ptr();
struct sbi_scratch *scratch = sbi_scratch_thishart_ptr(); struct sbi_scratch *scratch = sbi_scratch_thishart_ptr();
/* Find the target harts */ /* Find the target harts */
if (hbase != -1UL) { rc = sbi_hsm_hart_interruptible_mask(dom, &target_mask);
rc = sbi_hsm_hart_interruptible_mask(dom, hbase, &m); if (rc)
if (rc) return rc;
return rc;
m &= hmask;
for (i = hbase; m; i++, m >>= 1) { if (hbase != -1UL) {
if (m & 1UL) struct sbi_hartmask tmp_mask = { 0 };
sbi_hartmask_set_hartid(i, &target_mask);
} for (i = hbase; hmask; i++, hmask >>= 1) {
} else { if (hmask & 1UL)
hbase = 0; sbi_hartmask_set_hartid(i, &tmp_mask);
while (!sbi_hsm_hart_interruptible_mask(dom, hbase, &m)) {
for (i = hbase; m; i++, m >>= 1) {
if (m & 1UL)
sbi_hartmask_set_hartid(i, &target_mask);
}
hbase += BITS_PER_LONG;
} }
sbi_hartmask_and(&target_mask, &target_mask, &tmp_mask);
} }
/* Send IPIs */ /* Send IPIs */