#ifndef __SBI_DOMAIN_H__
#define __SBI_DOMAIN_H__
+#include <sbi/riscv_locks.h>
#include <sbi/sbi_types.h>
#include <sbi/sbi_hartmask.h>
#include <sbi/sbi_domain_context.h>
* in the coldboot path
*/
struct sbi_hartmask assigned_harts;
+ /** Spinlock for accessing assigned_harts */
+ spinlock_t assigned_harts_lock;
/** Name of this domain */
char name[64];
/** Possible HARTs in this domain */
bool sbi_domain_is_assigned_hart(const struct sbi_domain *dom, u32 hartid)
{
- if (dom)
- return sbi_hartmask_test_hartid(hartid, &dom->assigned_harts);
+ bool ret;
+ struct sbi_domain *tdom = (struct sbi_domain *)dom;
- return false;
+ if (!dom)
+ return false;
+
+ spin_lock(&tdom->assigned_harts_lock);
+ ret = sbi_hartmask_test_hartid(hartid, &tdom->assigned_harts);
+ spin_unlock(&tdom->assigned_harts_lock);
+
+ return ret;
}
ulong sbi_domain_get_assigned_hartmask(const struct sbi_domain *dom,
ulong hbase)
{
ulong ret = 0;
+ struct sbi_domain *tdom = (struct sbi_domain *)dom;
+
+ if (!dom)
+ return 0;
+
+ spin_lock(&tdom->assigned_harts_lock);
for (int i = 0; i < 8 * sizeof(ret); i++) {
- if (sbi_domain_is_assigned_hart(dom, hbase + i))
+ if (sbi_hartmask_test_hartid(hbase + i, &tdom->assigned_harts))
ret |= 1UL << i;
}
+ spin_unlock(&tdom->assigned_harts_lock);
return ret;
}
dom->index = domain_count++;
domidx_to_domain_table[dom->index] = dom;
+ /* Initialize spinlock for dom->assigned_harts */
+ SPIN_LOCK_INIT(dom->assigned_harts_lock);
+
/* Clear assigned HARTs of domain */
sbi_hartmask_clear_all(&dom->assigned_harts);
continue;
/* Ignore if boot HART assigned different domain */
- if (sbi_hartindex_to_domain(dhart) != dom ||
- !sbi_hartmask_test_hartindex(dhart, &dom->assigned_harts))
+ if (sbi_hartindex_to_domain(dhart) != dom)
+ continue;
+
+ /* Ignore if boot HART is not part of the assigned HARTs */
+ spin_lock(&dom->assigned_harts_lock);
+ rc = sbi_hartmask_test_hartindex(dhart, &dom->assigned_harts);
+ spin_unlock(&dom->assigned_harts_lock);
+ if (!rc)
continue;
/* Startup boot HART of domain */
static void switch_to_next_domain_context(struct sbi_context *ctx,
struct sbi_context *dom_ctx)
{
- u32 hartindex;
+ u32 hartindex = sbi_hartid_to_hartindex(current_hartid());
struct sbi_trap_regs *trap_regs;
- struct sbi_domain *dom = dom_ctx->dom;
+ struct sbi_domain *current_dom = ctx->dom;
+ struct sbi_domain *target_dom = dom_ctx->dom;
struct sbi_scratch *scratch = sbi_scratch_thishart_ptr();
unsigned int pmp_count = sbi_hart_pmp_count(scratch);
/* Assign current hart to target domain */
- hartindex = sbi_hartid_to_hartindex(current_hartid());
- sbi_hartmask_clear_hartindex(
- hartindex, &sbi_domain_thishart_ptr()->assigned_harts);
- sbi_update_hartindex_to_domain(hartindex, dom);
- sbi_hartmask_set_hartindex(hartindex, &dom->assigned_harts);
+ spin_lock(¤t_dom->assigned_harts_lock);
+ sbi_hartmask_clear_hartindex(hartindex, ¤t_dom->assigned_harts);
+ spin_unlock(¤t_dom->assigned_harts_lock);
+
+ sbi_update_hartindex_to_domain(hartindex, target_dom);
+
+ spin_lock(&target_dom->assigned_harts_lock);
+ sbi_hartmask_set_hartindex(hartindex, &target_dom->assigned_harts);
+ spin_unlock(&target_dom->assigned_harts_lock);
/* Reconfigure PMP settings for the new domain */
for (int i = 0; i < pmp_count; i++) {
/* If target domain context is not initialized or runnable */
if (!dom_ctx->initialized) {
/* Startup boot HART of target domain */
- if (current_hartid() == dom->boot_hartid)
- sbi_hart_switch_mode(dom->boot_hartid, dom->next_arg1,
- dom->next_addr, dom->next_mode,
+ if (current_hartid() == target_dom->boot_hartid)
+ sbi_hart_switch_mode(target_dom->boot_hartid,
+ target_dom->next_arg1,
+ target_dom->next_addr,
+ target_dom->next_mode,
false);
else
sbi_hsm_hart_stop(scratch, true);
int sbi_system_suspend(u32 sleep_type, ulong resume_addr, ulong opaque)
{
- const struct sbi_domain *dom = sbi_domain_thishart_ptr();
+ struct sbi_domain *dom = sbi_domain_thishart_ptr();
struct sbi_scratch *scratch = sbi_scratch_thishart_ptr();
void (*jump_warmboot)(void) = (void (*)(void))scratch->warmboot_addr;
unsigned int hartid = current_hartid();
if (prev_mode != PRV_S && prev_mode != PRV_U)
return SBI_EFAIL;
+ spin_lock(&dom->assigned_harts_lock);
sbi_hartmask_for_each_hartindex(j, &dom->assigned_harts) {
i = sbi_hartindex_to_hartid(j);
if (i == hartid)
continue;
- if (__sbi_hsm_hart_get_state(i) != SBI_HSM_STATE_STOPPED)
+ if (__sbi_hsm_hart_get_state(i) != SBI_HSM_STATE_STOPPED) {
+ spin_unlock(&dom->assigned_harts_lock);
return SBI_ERR_DENIED;
+ }
}
+ spin_unlock(&dom->assigned_harts_lock);
if (!sbi_domain_check_addr(dom, resume_addr, prev_mode,
SBI_DOMAIN_EXECUTE))