diff options
author | Anup Patel <apatel@ventanamicro.com> | 2022-01-06 09:16:55 +0530 |
---|---|---|
committer | Anup Patel <anup@brainfault.org> | 2022-01-11 18:17:49 +0530 |
commit | 6dde43584f185f71a8dd713deb438d7c724a9ad5 (patch) | |
tree | 46a01fc502ec87a7210f81bf8a000e08f73e67a8 | |
parent | 5b9960379fae14b554c953b0d4139f4b1a57cd5e (diff) | |
download | opensbi-6dde43584f185f71a8dd713deb438d7c724a9ad5.zip opensbi-6dde43584f185f71a8dd713deb438d7c724a9ad5.tar.gz opensbi-6dde43584f185f71a8dd713deb438d7c724a9ad5.tar.bz2 |
lib: utils/sys: Extend HTIF library to allow custom base address
Some of RISC-V emulators provide HTIF at fixed base address so for
such emulators users have to hard-code HTIF base address in the
linker script.
To address this problem, we let users optionally provide fixed HTIF
base address via platform support (or device tree).
Signed-off-by: Anup Patel <apatel@ventanamicro.com>
Reviewed-by: Dong Du <Dd_nirvana@sjtu.edu.cn>
Reviewed-by: Atish Patra <atishp@rivosinc.com>
-rw-r--r-- | include/sbi_utils/sys/htif.h | 8 | ||||
-rw-r--r-- | lib/utils/reset/fdt_reset_htif.c | 12 | ||||
-rw-r--r-- | lib/utils/serial/fdt_serial_htif.c | 12 | ||||
-rw-r--r-- | lib/utils/sys/htif.c | 85 |
4 files changed, 103 insertions, 14 deletions
diff --git a/include/sbi_utils/sys/htif.h b/include/sbi_utils/sys/htif.h index 9cc9634..78784cf 100644 --- a/include/sbi_utils/sys/htif.h +++ b/include/sbi_utils/sys/htif.h @@ -10,8 +10,12 @@ #include <sbi/sbi_types.h> -int htif_serial_init(void); +int htif_serial_init(bool custom_addr, + unsigned long custom_fromhost_addr, + unsigned long custom_tohost_addr); -int htif_system_reset_init(void); +int htif_system_reset_init(bool custom_addr, + unsigned long custom_fromhost_addr, + unsigned long custom_tohost_addr); #endif diff --git a/lib/utils/reset/fdt_reset_htif.c b/lib/utils/reset/fdt_reset_htif.c index dd08660..2cc52dd 100644 --- a/lib/utils/reset/fdt_reset_htif.c +++ b/lib/utils/reset/fdt_reset_htif.c @@ -14,7 +14,17 @@ static int htif_reset_init(void *fdt, int nodeoff, const struct fdt_match *match) { - return htif_system_reset_init(); + bool custom = false; + uint64_t fromhost_addr = 0, tohost_addr = 0; + + if (!fdt_get_node_addr_size(fdt, nodeoff, 0, &fromhost_addr, NULL)) { + custom = true; + tohost_addr = fromhost_addr + sizeof(uint64_t); + } + + fdt_get_node_addr_size(fdt, nodeoff, 1, &tohost_addr, NULL); + + return htif_system_reset_init(custom, fromhost_addr, tohost_addr); } static const struct fdt_match htif_reset_match[] = { diff --git a/lib/utils/serial/fdt_serial_htif.c b/lib/utils/serial/fdt_serial_htif.c index fae55b8..61f66d6 100644 --- a/lib/utils/serial/fdt_serial_htif.c +++ b/lib/utils/serial/fdt_serial_htif.c @@ -19,7 +19,17 @@ static const struct fdt_match serial_htif_match[] = { static int serial_htif_init(void *fdt, int nodeoff, const struct fdt_match *match) { - return htif_serial_init(); + bool custom = false; + uint64_t fromhost_addr = 0, tohost_addr = 0; + + if (!fdt_get_node_addr_size(fdt, nodeoff, 0, &fromhost_addr, NULL)) { + custom = true; + tohost_addr = fromhost_addr + sizeof(uint64_t); + } + + fdt_get_node_addr_size(fdt, nodeoff, 1, &tohost_addr, NULL); + + return htif_serial_init(custom, fromhost_addr, tohost_addr); } struct fdt_serial fdt_serial_htif = { diff --git a/lib/utils/sys/htif.c b/lib/utils/sys/htif.c index 7c69c7f..d7cbeaf 100644 --- a/lib/utils/sys/htif.c +++ b/lib/utils/sys/htif.c @@ -7,6 +7,7 @@ #include <sbi/riscv_locks.h> #include <sbi/sbi_console.h> +#include <sbi/sbi_error.h> #include <sbi/sbi_system.h> #include <sbi_utils/sys/htif.h> @@ -47,15 +48,46 @@ volatile uint64_t tohost __attribute__((section(".htif"))); volatile uint64_t fromhost __attribute__((section(".htif"))); + +static uint64_t *htif_fromhost = NULL; +static uint64_t *htif_tohost = NULL; +static bool htif_custom = false; + static int htif_console_buf; static spinlock_t htif_lock = SPIN_LOCK_INITIALIZER; +static inline uint64_t __read_tohost(void) +{ + return (htif_custom) ? *htif_tohost : tohost; +} + +static inline void __write_tohost(uint64_t val) +{ + if (htif_custom) + *htif_tohost = val; + else + tohost = val; +} + +static inline uint64_t __read_fromhost(void) +{ + return (htif_custom) ? *htif_fromhost : fromhost; +} + +static inline void __write_fromhost(uint64_t val) +{ + if (htif_custom) + *htif_fromhost = val; + else + fromhost = val; +} + static void __check_fromhost() { - uint64_t fh = fromhost; + uint64_t fh = __read_fromhost(); if (!fh) return; - fromhost = 0; + __write_fromhost(0); /* this should be from the console */ if (FROMHOST_DEV(fh) != HTIF_DEV_CONSOLE) @@ -73,9 +105,26 @@ static void __check_fromhost() static void __set_tohost(uint64_t dev, uint64_t cmd, uint64_t data) { - while (tohost) + while (__read_tohost()) __check_fromhost(); - tohost = TOHOST_CMD(dev, cmd, data); + __write_tohost(TOHOST_CMD(dev, cmd, data)); +} + +static int set_custom_addr(bool custom_addr, + unsigned long custom_fromhost_addr, + unsigned long custom_tohost_addr) +{ + if (custom_addr) { + if (htif_custom && + ((custom_fromhost_addr != (unsigned long)htif_fromhost) || + (custom_tohost_addr != (unsigned long)htif_tohost))) + return SBI_EINVAL; + htif_fromhost = (uint64_t *)custom_fromhost_addr; + htif_tohost = (uint64_t *)custom_tohost_addr; + htif_custom = true; + } + + return 0; } #if __riscv_xlen == 32 @@ -148,10 +197,18 @@ static struct sbi_console_device htif_console = { .console_getc = htif_getc }; -int htif_serial_init(void) +int htif_serial_init(bool custom_addr, + unsigned long custom_fromhost_addr, + unsigned long custom_tohost_addr) { - sbi_console_set_device(&htif_console); + int rc; + + rc = set_custom_addr(custom_addr, custom_fromhost_addr, + custom_tohost_addr); + if (rc) + return rc; + sbi_console_set_device(&htif_console); return 0; } @@ -163,8 +220,8 @@ static int htif_system_reset_check(u32 type, u32 reason) static void htif_system_reset(u32 type, u32 reason) { while (1) { - fromhost = 0; - tohost = 1; + __write_fromhost(0); + __write_tohost(1); } } @@ -174,9 +231,17 @@ static struct sbi_system_reset_device htif_reset = { .system_reset = htif_system_reset }; -int htif_system_reset_init(void) +int htif_system_reset_init(bool custom_addr, + unsigned long custom_fromhost_addr, + unsigned long custom_tohost_addr) { - sbi_system_reset_add_device(&htif_reset); + int rc; + + rc = set_custom_addr(custom_addr, custom_fromhost_addr, + custom_tohost_addr); + if (rc) + return rc; + sbi_system_reset_add_device(&htif_reset); return 0; } |