Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(arch/riscv): add SBI hart suspend #187

Merged
merged 1 commit into from
Oct 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion src/arch/riscv/cpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,10 @@ void cpu_arch_init(cpuid_t cpuid, paddr_t load_addr)

void cpu_arch_idle(void)
{
__asm__ volatile("wfi\n\t" ::: "memory");
struct sbiret ret = sbi_hart_suspend(SBI_HSM_SUSPEND_RET_DEFAULT, 0, 0);
if (ret.error < 0) {
ERROR("failed to suspend hart %d", cpu()->id);
}
__asm__ volatile("mv sp, %0\n\r"
"j cpu_idle_wakeup\n\r" ::"r"(&cpu()->stack[STACK_SIZE]));
ERROR("returned from idle wake up");
Expand Down
18 changes: 11 additions & 7 deletions src/arch/riscv/inc/arch/sbi.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,16 @@
* From https://github.com/riscv/riscv-sbi-doc
*/

#define SBI_SUCCESS (0)
#define SBI_ERR_FAILURE (-1)
#define SBI_ERR_NOT_SUPPORTED (-2)
#define SBI_ERR_INVALID_PARAM (-3)
#define SBI_ERR_DENIED (-4)
#define SBI_ERR_INVALID_ADDRESS (-5)
#define SBI_ERR_ALREADY_AVAILABLE (-6)
#define SBI_SUCCESS (0)
#define SBI_ERR_FAILURE (-1)
#define SBI_ERR_NOT_SUPPORTED (-2)
#define SBI_ERR_INVALID_PARAM (-3)
#define SBI_ERR_DENIED (-4)
#define SBI_ERR_INVALID_ADDRESS (-5)
#define SBI_ERR_ALREADY_AVAILABLE (-6)

#define SBI_HSM_SUSPEND_RET_DEFAULT (0x00000000)
#define SBI_HSM_SUSP_NON_RET_BIT (0x80000000)

struct sbiret {
long error;
Expand Down Expand Up @@ -73,5 +76,6 @@ struct sbiret sbi_remote_hfence_vvma(const unsigned long hart_mask, unsigned lon
struct sbiret sbi_hart_start(unsigned long hartid, unsigned long start_addr, unsigned long priv);
struct sbiret sbi_hart_stop(void);
struct sbiret sbi_hart_status(unsigned long hartid);
struct sbiret sbi_hart_suspend(uint32_t suspend_type, unsigned long resume_addr, unsigned long priv);

#endif /* __SBI_H__ */
34 changes: 34 additions & 0 deletions src/arch/riscv/sbi.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#define SBI_HART_START_FID (0)
#define SBI_HART_STOP_FID (1)
#define SBI_HART_STATUS_FID (2)
#define SBI_HART_SUSPEND_FID (3)

#define SBI_EXTID_RFNC (0x52464E43)
#define SBI_REMOTE_FENCE_I_FID (0)
Expand Down Expand Up @@ -170,6 +171,12 @@ struct sbiret sbi_hart_status(unsigned long hartid)
return sbi_ecall(SBI_EXTID_HSM, SBI_HART_STATUS_FID, hartid, 0, 0, 0, 0, 0);
}

struct sbiret sbi_hart_suspend(uint32_t suspend_type, unsigned long resume_addr, unsigned long priv)
{
return sbi_ecall(SBI_EXTID_HSM, SBI_HART_SUSPEND_FID, (unsigned long)suspend_type, resume_addr,
priv, 0, 0, 0);
}

static unsigned long ext_table[] = { SBI_EXTID_BASE, SBI_EXTID_TIME, SBI_EXTID_IPI, SBI_EXTID_RFNC,
SBI_EXTID_HSM };

Expand Down Expand Up @@ -382,6 +389,30 @@ static struct sbiret sbi_hsm_status_handler(void)
return ret;
}

static struct sbiret sbi_hsm_suspend_handler(void)
{
struct sbiret ret;
uint32_t suspend_type = (uint32_t)vcpu_readreg(cpu()->vcpu, REG_A0);

spin_lock(&cpu()->vcpu->arch.sbi_ctx.lock);
if (cpu()->vcpu->arch.sbi_ctx.state != STARTED) {
ret.error = SBI_ERR_FAILURE;
} else {
if (suspend_type & SBI_HSM_SUSP_NON_RET_BIT) {
/*
* TODO: We only need to implement this when we get a real physical platform
* with real non-retentive suspend implementation.
* To support this we will need to save and restore the hart registers and CSRs.
*/
ret.error = SBI_ERR_NOT_SUPPORTED;
} else {
ret = sbi_hart_suspend(suspend_type, 0, 0);
}
}

return ret;
}

static struct sbiret sbi_hsm_handler(unsigned long fid)
{
struct sbiret ret;
Expand All @@ -393,6 +424,9 @@ static struct sbiret sbi_hsm_handler(unsigned long fid)
case SBI_HART_STATUS_FID:
ret = sbi_hsm_status_handler();
break;
case SBI_HART_SUSPEND_FID:
ret = sbi_hsm_suspend_handler();
break;
default:
ret.error = SBI_ERR_NOT_SUPPORTED;
}
Expand Down