opensbi: weekly rls 2024.07.20

-0aa741, support cv181x/cv180x suspend to ram.

Change-Id: I64dcb0ff942aa7238a88ef3bd1da2c67f5d089b4
This commit is contained in:
sophgo-forum-service
2024-07-20 21:40:47 +08:00
parent 3fd99912a6
commit ab9b8f8d10
21 changed files with 363 additions and 4 deletions

View File

@@ -22,6 +22,7 @@ libsbi-objs-y += sbi_ecall_hsm.o
libsbi-objs-y += sbi_ecall_legacy.o
libsbi-objs-y += sbi_ecall_replace.o
libsbi-objs-y += sbi_ecall_vendor.o
libsbi-objs-y += sbi_ecall_susp.o
libsbi-objs-y += sbi_emulate_csr.o
libsbi-objs-y += sbi_fifo.o
libsbi-objs-y += sbi_hart.o

View File

@@ -34,6 +34,7 @@ struct sbi_domain root = {
.possible_harts = &root_hmask,
.regions = root_memregs,
.system_reset_allowed = TRUE,
.system_suspend_allowed = TRUE,
};
bool sbi_domain_is_assigned_hart(const struct sbi_domain *dom, u32 hartid)
@@ -383,6 +384,8 @@ void sbi_domain_dump(const struct sbi_domain *dom, const char *suffix)
sbi_printf("Domain%d SysReset %s: %s\n",
dom->index, suffix, (dom->system_reset_allowed) ? "yes" : "no");
sbi_printf("Domain%d SysSuspend %s: %s\n",
dom->index, suffix, (dom->system_suspend_allowed) ? "yes" : "no");
}
void sbi_domain_dump_all(const char *suffix)

View File

@@ -168,6 +168,9 @@ int sbi_ecall_init(void)
if (ret)
return ret;
ret = sbi_ecall_register_extension(&ecall_vendor);
if (ret)
return ret;
ret = sbi_ecall_register_extension(&ecall_susp);
if (ret)
return ret;

60
lib/sbi/sbi_ecall_susp.c Normal file
View File

@@ -0,0 +1,60 @@
// SPDX-License-Identifier: BSD-2-Clause
#include <sbi/sbi_ecall.h>
#include <sbi/sbi_ecall_interface.h>
#include <sbi/sbi_error.h>
#include <sbi/sbi_trap.h>
#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)
{
int ret = SBI_ENOTSUPP;
if (funcid == SBI_EXT_SUSP_SUSPEND)
ret = sbi_system_suspend(regs->a0, regs->a1, regs->a2);
if (ret >= 0) {
*out_val = ret;
ret = 0;
}
return ret;
}
static bool susp_available(void)
{
u32 type;
/*
* At least one suspend type should be supported by the
* platform for the SBI SUSP extension to be usable.
*/
for (type = 0; type <= SBI_SUSP_SLEEP_TYPE_LAST; type++) {
if (sbi_system_suspend_supported(type))
return true;
}
return false;
}
struct sbi_ecall_extension ecall_susp;
static int sbi_ecall_susp_register_extensions(unsigned long extid, unsigned long *out_val)
{
if (!susp_available()) {
*out_val = 0;
return 0;
}
*out_val = 1;
return 0;
}
struct sbi_ecall_extension ecall_susp = {
.extid_start = SBI_EXT_SUSP,
.extid_end = SBI_EXT_SUSP,
.probe = sbi_ecall_susp_register_extensions,
.handle = sbi_ecall_susp_handler,
};

View File

@@ -36,8 +36,25 @@ struct sbi_hsm_data {
unsigned long saved_mie;
unsigned long saved_mip;
};
#define __sbi_hsm_hart_change_state(hdata, oldstate, newstate) \
({ \
long state = atomic_cmpxchg(&(hdata)->state, oldstate, newstate); \
if (state != (oldstate)) \
sbi_printf("%s: ERR: The hart is in invalid state [%lu]\n", \
__func__, state); \
state == (oldstate); \
})
static inline int __sbi_hsm_hart_get_state(u32 hartid)
int sbi_hsm_hart_change_state(struct sbi_scratch *scratch, long oldstate,
long newstate)
{
struct sbi_hsm_data *hdata = sbi_scratch_offset_ptr(scratch,
hart_data_offset);
return __sbi_hsm_hart_change_state(hdata, oldstate, newstate);
}
int __sbi_hsm_hart_get_state(u32 hartid)
{
struct sbi_hsm_data *hdata;
struct sbi_scratch *scratch;
@@ -322,7 +339,7 @@ static int __sbi_hsm_suspend_ret_default(struct sbi_scratch *scratch)
return 0;
}
static void __sbi_hsm_suspend_non_ret_save(struct sbi_scratch *scratch)
void __sbi_hsm_suspend_non_ret_save(struct sbi_scratch *scratch)
{
struct sbi_hsm_data *hdata = sbi_scratch_offset_ptr(scratch,
hart_data_offset);

View File

@@ -58,6 +58,7 @@ static void sbi_boot_print_general(struct sbi_scratch *scratch)
const struct sbi_timer_device *tdev;
const struct sbi_console_device *cdev;
const struct sbi_system_reset_device *srdev;
const struct sbi_system_suspend_device *susp_dev;
const struct sbi_platform *plat = sbi_platform_ptr(scratch);
if (scratch->options & SBI_SCRATCH_NO_BOOT_PRINTS)
@@ -85,6 +86,9 @@ static void sbi_boot_print_general(struct sbi_scratch *scratch)
srdev = sbi_system_reset_get_device();
sbi_printf("Platform SysReset Device : %s\n",
(srdev) ? srdev->name : "---");
susp_dev = sbi_system_suspend_get_device();
sbi_printf("Platform Suspend Device : %s\n",
(susp_dev) ? susp_dev->name : "---");
/* Firmware details */
sbi_printf("Firmware Base : 0x%lx\n", scratch->fw_start);

View File

@@ -72,3 +72,88 @@ void __noreturn sbi_system_reset(u32 reset_type, u32 reset_reason)
/* If platform specific reset did not work then do sbi_exit() */
sbi_exit(scratch);
}
static const struct sbi_system_suspend_device *suspend_dev;
const struct sbi_system_suspend_device *sbi_system_suspend_get_device(void)
{
return suspend_dev;
}
void sbi_system_suspend_set_device(struct sbi_system_suspend_device *dev)
{
if (!dev || suspend_dev)
return;
suspend_dev = dev;
}
bool sbi_system_suspend_supported(u32 sleep_type)
{
return suspend_dev && suspend_dev->system_suspend_check &&
suspend_dev->system_suspend_check(sleep_type) == 0;
}
int sbi_system_suspend(u32 sleep_type, ulong resume_addr, ulong opaque)
{
const 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();
unsigned long prev_mode;
//unsigned long i, j;
int ret;
if (!dom || !dom->system_suspend_allowed)
return SBI_EFAIL;
if (!suspend_dev || !suspend_dev->system_suspend ||
!suspend_dev->system_suspend_check)
return SBI_EFAIL;
ret = suspend_dev->system_suspend_check(sleep_type);
if (ret != SBI_OK)
return ret;
prev_mode = (csr_read(CSR_MSTATUS) & MSTATUS_MPP) >> MSTATUS_MPP_SHIFT;
if (prev_mode != PRV_S && prev_mode != PRV_U)
return SBI_EFAIL;
//FIX ME: hartindex to hart
//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)
// return SBI_ERR_DENIED;
//}
if (!sbi_domain_check_addr(dom, resume_addr, prev_mode,
SBI_DOMAIN_EXECUTE))
return SBI_EINVALID_ADDR;
if (!sbi_hsm_hart_change_state(scratch, SBI_HSM_STATE_STARTED,
SBI_HSM_STATE_SUSPENDED))
return SBI_EFAIL;
/* Prepare for resume */
scratch->next_mode = prev_mode;
scratch->next_addr = resume_addr;
scratch->next_arg1 = opaque;
__sbi_hsm_suspend_non_ret_save(scratch);
/* Suspend */
ret = suspend_dev->system_suspend(sleep_type, scratch->warmboot_addr);
if (ret != SBI_OK) {
if (!sbi_hsm_hart_change_state(scratch, SBI_HSM_STATE_SUSPENDED,
SBI_HSM_STATE_STARTED))
sbi_hart_hang();
return ret;
}
/* Resume */
jump_warmboot();
__builtin_unreachable();
}

View File

@@ -398,6 +398,13 @@ static int __fdt_parse_domain(void *fdt, int domain_offset, void *opaque)
else
dom->system_reset_allowed = FALSE;
/* Read "system-suspend-allowed" DT property */
if (fdt_get_property(fdt, domain_offset,
"system-suspend-allowed", NULL))
dom->system_suspend_allowed = TRUE;
else
dom->system_suspend_allowed = FALSE;
/* Find /cpus DT node */
cpus_offset = fdt_path_offset(fdt, "/cpus");
if (cpus_offset < 0)