mirror of
				https://github.com/riscv-software-src/opensbi
				synced 2025-11-04 05:50:22 +00:00 
			
		
		
		
	commit 6dde43584f18 ("lib: utils/sys: Extend HTIF library to allow custom base address")
forgot to update do_tohost_fromhost() codes for RV32, which still
accesses the HTIF registers using the ELF symbol address directly.
Fixes: 6dde43584f18 ("lib: utils/sys: Extend HTIF library to allow custom base address")
Signed-off-by: Bin Meng <bmeng@tinylab.org>
Tested-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
		
	
			
		
			
				
	
	
		
			248 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			248 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 * SPDX-License-Identifier: BSD-3-Clause
 | 
						|
 *
 | 
						|
 * Copyright (c) 2010-2020, The Regents of the University of California
 | 
						|
 * (Regents).  All Rights Reserved.
 | 
						|
 */
 | 
						|
 | 
						|
#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>
 | 
						|
 | 
						|
#define HTIF_DATA_BITS		48
 | 
						|
#define HTIF_DATA_MASK		((1ULL << HTIF_DATA_BITS) - 1)
 | 
						|
#define HTIF_DATA_SHIFT		0
 | 
						|
#define HTIF_CMD_BITS		8
 | 
						|
#define HTIF_CMD_MASK		((1ULL << HTIF_CMD_BITS) - 1)
 | 
						|
#define HTIF_CMD_SHIFT		48
 | 
						|
#define HTIF_DEV_BITS		8
 | 
						|
#define HTIF_DEV_MASK		((1ULL << HTIF_DEV_BITS) - 1)
 | 
						|
#define HTIF_DEV_SHIFT		56
 | 
						|
 | 
						|
#define HTIF_DEV_SYSTEM		0
 | 
						|
#define HTIF_DEV_CONSOLE	1
 | 
						|
 | 
						|
#define HTIF_CONSOLE_CMD_GETC	0
 | 
						|
#define HTIF_CONSOLE_CMD_PUTC	1
 | 
						|
 | 
						|
#if __riscv_xlen == 64
 | 
						|
# define TOHOST_CMD(dev, cmd, payload) \
 | 
						|
	(((uint64_t)(dev) << HTIF_DEV_SHIFT) | \
 | 
						|
	 ((uint64_t)(cmd) << HTIF_CMD_SHIFT) | \
 | 
						|
	 (uint64_t)(payload))
 | 
						|
#else
 | 
						|
# define TOHOST_CMD(dev, cmd, payload) ({ \
 | 
						|
  if ((dev) || (cmd)) __builtin_trap(); \
 | 
						|
  (payload); })
 | 
						|
#endif
 | 
						|
#define FROMHOST_DEV(fromhost_value) \
 | 
						|
	((uint64_t)((fromhost_value) >> HTIF_DEV_SHIFT) & HTIF_DEV_MASK)
 | 
						|
#define FROMHOST_CMD(fromhost_value) \
 | 
						|
	((uint64_t)((fromhost_value) >> HTIF_CMD_SHIFT) & HTIF_CMD_MASK)
 | 
						|
#define FROMHOST_DATA(fromhost_value) \
 | 
						|
	((uint64_t)((fromhost_value) >> HTIF_DATA_SHIFT) & HTIF_DATA_MASK)
 | 
						|
 | 
						|
#define PK_SYS_write 64
 | 
						|
 | 
						|
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 = __read_fromhost();
 | 
						|
	if (!fh)
 | 
						|
		return;
 | 
						|
	__write_fromhost(0);
 | 
						|
 | 
						|
	/* this should be from the console */
 | 
						|
	if (FROMHOST_DEV(fh) != HTIF_DEV_CONSOLE)
 | 
						|
		__builtin_trap();
 | 
						|
	switch (FROMHOST_CMD(fh)) {
 | 
						|
		case HTIF_CONSOLE_CMD_GETC:
 | 
						|
			htif_console_buf = 1 + (uint8_t)FROMHOST_DATA(fh);
 | 
						|
			break;
 | 
						|
		case HTIF_CONSOLE_CMD_PUTC:
 | 
						|
			break;
 | 
						|
		default:
 | 
						|
			__builtin_trap();
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
static void __set_tohost(uint64_t dev, uint64_t cmd, uint64_t data)
 | 
						|
{
 | 
						|
	while (__read_tohost())
 | 
						|
		__check_fromhost();
 | 
						|
	__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
 | 
						|
static void do_tohost_fromhost(uint64_t dev, uint64_t cmd, uint64_t data)
 | 
						|
{
 | 
						|
	spin_lock(&htif_lock);
 | 
						|
 | 
						|
	__set_tohost(HTIF_DEV_SYSTEM, cmd, data);
 | 
						|
 | 
						|
	while (1) {
 | 
						|
		uint64_t fh = __read_fromhost();
 | 
						|
		if (fh) {
 | 
						|
			if (FROMHOST_DEV(fh) == HTIF_DEV_SYSTEM &&
 | 
						|
			    FROMHOST_CMD(fh) == cmd) {
 | 
						|
				__write_fromhost(0);
 | 
						|
				break;
 | 
						|
			}
 | 
						|
			__check_fromhost();
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	spin_unlock(&htif_lock);
 | 
						|
}
 | 
						|
 | 
						|
static void htif_putc(char ch)
 | 
						|
{
 | 
						|
	/* HTIF devices are not supported on RV32, so do a proxy write call */
 | 
						|
	volatile uint64_t magic_mem[8];
 | 
						|
	magic_mem[0] = PK_SYS_write;
 | 
						|
	magic_mem[1] = HTIF_DEV_CONSOLE;
 | 
						|
	magic_mem[2] = (uint64_t)(uintptr_t)&ch;
 | 
						|
	magic_mem[3] = HTIF_CONSOLE_CMD_PUTC;
 | 
						|
	do_tohost_fromhost(HTIF_DEV_SYSTEM, 0, (uint64_t)(uintptr_t)magic_mem);
 | 
						|
}
 | 
						|
#else
 | 
						|
static void htif_putc(char ch)
 | 
						|
{
 | 
						|
	spin_lock(&htif_lock);
 | 
						|
	__set_tohost(HTIF_DEV_CONSOLE, HTIF_CONSOLE_CMD_PUTC, ch);
 | 
						|
	spin_unlock(&htif_lock);
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
static int htif_getc(void)
 | 
						|
{
 | 
						|
	int ch;
 | 
						|
 | 
						|
#if __riscv_xlen == 32
 | 
						|
	/* HTIF devices are not supported on RV32 */
 | 
						|
	return -1;
 | 
						|
#endif
 | 
						|
 | 
						|
	spin_lock(&htif_lock);
 | 
						|
 | 
						|
	__check_fromhost();
 | 
						|
	ch = htif_console_buf;
 | 
						|
	if (ch >= 0) {
 | 
						|
		htif_console_buf = -1;
 | 
						|
		__set_tohost(HTIF_DEV_CONSOLE, HTIF_CONSOLE_CMD_GETC, 0);
 | 
						|
	}
 | 
						|
 | 
						|
	spin_unlock(&htif_lock);
 | 
						|
 | 
						|
	return ch - 1;
 | 
						|
}
 | 
						|
 | 
						|
static struct sbi_console_device htif_console = {
 | 
						|
	.name = "htif",
 | 
						|
	.console_putc = htif_putc,
 | 
						|
	.console_getc = htif_getc
 | 
						|
};
 | 
						|
 | 
						|
int htif_serial_init(bool custom_addr,
 | 
						|
		     unsigned long custom_fromhost_addr,
 | 
						|
		     unsigned long custom_tohost_addr)
 | 
						|
{
 | 
						|
	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;
 | 
						|
}
 | 
						|
 | 
						|
static int htif_system_reset_check(u32 type, u32 reason)
 | 
						|
{
 | 
						|
	return 1;
 | 
						|
}
 | 
						|
 | 
						|
static void htif_system_reset(u32 type, u32 reason)
 | 
						|
{
 | 
						|
	while (1) {
 | 
						|
		__write_fromhost(0);
 | 
						|
		__write_tohost(1);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
static struct sbi_system_reset_device htif_reset = {
 | 
						|
	.name = "htif",
 | 
						|
	.system_reset_check = htif_system_reset_check,
 | 
						|
	.system_reset = htif_system_reset
 | 
						|
};
 | 
						|
 | 
						|
int htif_system_reset_init(bool custom_addr,
 | 
						|
			   unsigned long custom_fromhost_addr,
 | 
						|
			   unsigned long custom_tohost_addr)
 | 
						|
{
 | 
						|
	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;
 | 
						|
}
 |