diff --git a/firmware/fw_base.S b/firmware/fw_base.S index 63bb4473b20..4317935da73 100644 --- a/firmware/fw_base.S +++ b/firmware/fw_base.S @@ -110,21 +110,7 @@ _bss_zero: /* Trying to initialize the stack guard via the Zkr extension */ lla t0, __stack_chk_guard_done csrw CSR_MTVEC, t0 - li t0, 0 - li t3, SEED_OPTS_ES16 - li t4, SEED_ENTROPY_MASK - li t5, __SIZEOF_POINTER__ -__stack_chk_guard_loop: - csrrw t1, CSR_SEED, x0 - li t2, SEED_OPTS_MASK - and t2, t2, t1 - bgtu t2, t3, __stack_chk_guard_done - bltu t2, t3, __stack_chk_guard_loop - and t1, t1, t4 - slli t0, t0, 16 - or t0, t0, t1 - addi t5, t5, -2 - bgtz t5, __stack_chk_guard_loop + li t0, 0xdeadbeefdeadbeef lla t1, __stack_chk_guard REG_S t0, 0(t1) j __stack_chk_guard_done diff --git a/platform/ikr/Kconfig b/platform/ikr/Kconfig new file mode 100644 index 00000000000..d73825da99f --- /dev/null +++ b/platform/ikr/Kconfig @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: BSD-2-Clause + +# +# All mandatory drivers or libraries for this platform should +# be directly selected by the PLATFORM_xyz kconfig symbol. +# +# All optional drivers or libraries for this platform should +# be enabled via configs/defconfig of this platform. +# +config PLATFORM_TEMPLATE + bool + select IPI_MSWI + select IRQCHIP_PLIC + select SERIAL_UART8250 + select TIMER_MTIMER + default y diff --git a/platform/ikr/configs/defconfig b/platform/ikr/configs/defconfig new file mode 100644 index 00000000000..e69de29bb2d diff --git a/platform/ikr/objects.mk b/platform/ikr/objects.mk new file mode 100644 index 00000000000..1386bc9e126 --- /dev/null +++ b/platform/ikr/objects.mk @@ -0,0 +1,105 @@ +# +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2019 Western Digital Corporation or its affiliates. +# + +# IKR config: cyclone 10GX starting address +FW_TEXT_START=0x40000000 + +# Compiler pre-processor flags +platform-cppflags-y = + +# C Compiler and assembler flags. +platform-cflags-y = +platform-asflags-y = + +# Linker flags: additional libraries and object files that the platform +# code needs can be added here +platform-ldflags-y = + +# +# Command for platform specific "make run" +# Useful for development and debugging on plaftform simulator (such as QEMU) +# +# platform-runcmd = your_platform_run.sh + +# +# Platform RISC-V XLEN, ABI, ISA and Code Model configuration. +# These are optional parameters but platforms can optionaly provide it. +# Some of these are guessed based on GCC compiler capabilities +# +# PLATFORM_RISCV_XLEN = 64 +# PLATFORM_RISCV_ABI = lp64 +PLATFORM_RISCV_ISA = rv64ima_zicsr_zifencei +# PLATFORM_RISCV_CODE_MODEL = medany + +# Space separated list of object file names to be compiled for the platform +platform-objs-y += platform.o + +# +# If the platform support requires a builtin device tree file, the name of +# the device tree compiled file should be specified here. The device tree +# source file be in the form
.dts +# +# platform-objs-y +=
.o + +# Optional parameter for path to external FDT +# FW_FDT_PATH="path to platform flattened device tree file" +# FW_PAYLOAD_PATH=/home/elkomy/rp-workspace/linux/arch/riscv/boot/Image +# FW_PAYLOAD_PATH=/home/elkomy/rp-workspace/u-boot/u-boot.bin +# FW_FDT_PATH=/home/elkomy/rp-workspace/output/ikr.dtb + +# +# Dynamic firmware configuration. +# Optional parameters are commented out. Uncomment and define these parameters +# as needed. +# +FW_DYNAMIC=n + +# +# Jump firmware configuration. +# Optional parameters are commented out. Uncomment and define these parameters +# as needed. +# +FW_JUMP=n +# This needs to be 4MB aligned for 32-bit support +# This needs to be 2MB aligned for 64-bit support +# ifeq ($(PLATFORM_RISCV_XLEN), 32) +# FW_JUMP_OFFSET=0x400000 +# else +# FW_JUMP_OFFSET=0x200000 +# endif +# FW_JUMP_FDT_OFFSET=0x2200000 +# +# You can use fixed address for jump firmware as an alternative option. +# SBI will prefer "_ADDR" if both "_ADDR" and "_OFFSET" are +# defined +# ifeq ($(PLATFORM_RISCV_XLEN), 32) +# FW_JUMP_ADDR=0x80400000 +# else +# FW_JUMP_ADDR=0x80200000 +# endif +# FW_JUMP_FDT_ADDR=0x82200000 + +# +# Firmware with payload configuration. +# Optional parameters are commented out. Uncomment and define these parameters +# as needed. +# +FW_PAYLOAD=y +# This needs to be 4MB aligned for 32-bit support +# This needs to be 2MB aligned for 64-bit support +ifeq ($(PLATFORM_RISCV_XLEN), 32) +FW_PAYLOAD_OFFSET=0x400000 +else +FW_PAYLOAD_OFFSET=0x200000 +endif +# FW_PAYLOAD_ALIGN=0x1000 +# FW_PAYLOAD_PATH="path to next boot stage binary image file" +FW_PAYLOAD_FDT_OFFSET=0x2200000 +# +# You can use fixed address for payload firmware as an alternative option. +# SBI will prefer "FW_PAYLOAD_FDT_ADDR" if both "FW_PAYLOAD_FDT_OFFSET" +# and "FW_PAYLOAD_FDT_ADDR" are defined. +# FW_PAYLOAD_FDT_ADDR=0x82200000 diff --git a/platform/ikr/platform.c b/platform/ikr/platform.c new file mode 100644 index 00000000000..17df9aa059e --- /dev/null +++ b/platform/ikr/platform.c @@ -0,0 +1,215 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2019 Western Digital Corporation or its affiliates. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PLATFORM_PLIC_ADDR 0x00200100 +#define PLATFORM_PLIC_SIZE (0x200000 + (2 * PLATFORM_HART_COUNT * 0x1000)) +#define PLATFORM_PLIC_NUM_SOURCES 128 +#define PLATFORM_HART_COUNT 1 + +#define PLATFORM_ACLINT_MTIMER_FREQ 10000000 +#define PLATFORM_ACLINT_MSWI_ADDR 0x00000096 +#define PLATFORM_ACLINT_MTIMER_ADDR 0x00000080 + +#define PLATFORM_UART_ADDR 0x01 +#define PLATFORM_UART_INPUT_FREQ 10000000 +#define PLATFORM_UART_RXSTS_OFFSET 1 +#define PLATFORM_UART_TXSTS_OFFSET 2 +#define PLATFORM_UART_DATA_OFFSET 0x00 +#define PLATFORM_UART_IER_OFFSET 0x01 +#define PLATFORM_UART_FCR_OFFSET 0x02 +#define PLATFORM_UART_LCR_OFFSET 0x03 +#define PLATFORM_UART_MCR_OFFSET 0x04 +#define PLATFORM_UART_LSR_OFFSET 0x05 +#define PLATFORM_UART_RX_AVAIL 0x01 // DR bit in LSR +/* Bit masks for the LSR (Offset 5) */ +#define PLATFORM_UART_LSR_RX_READY 0x01 // Bit 0: Data Ready +#define PLATFORM_UART_LSR_TX_EMPTY 0x20 // Bit 5: Transmit Holding Register Empty + +// #define USE_UART_QEMU 1 // Set to 1 to use the QEMU-specific UART implementation + +// For Qemu +#ifdef USE_UART_QEMU +static void ikr_uart_putc(char ch) +{ + // Wait until THR is empty (Bit 5 of LSR becomes 1) + while ((readb((volatile void *)(PLATFORM_UART_ADDR + + PLATFORM_UART_LSR_OFFSET)) & + PLATFORM_UART_LSR_TX_EMPTY) == 0) + ; + + writeb((u8)ch, (volatile void *)(PLATFORM_UART_ADDR + + PLATFORM_UART_DATA_OFFSET)); +} + +static int ikr_uart_getc(void) +{ + // Check LSR Bit 0 (Data Ready) + u8 status = readb((volatile void *)(PLATFORM_UART_ADDR + + PLATFORM_UART_LSR_OFFSET)); + // + if (status & PLATFORM_UART_LSR_RX_READY) { + // Read the data; this hardware-clears the Ready bit + return (int)readb((volatile void *)(PLATFORM_UART_ADDR + + PLATFORM_UART_DATA_OFFSET)); + } + return -1; +} +#else + +static void ikr_uart_putc(char ch) +{ + while (readb((volatile void *)(PLATFORM_UART_ADDR + + PLATFORM_UART_TXSTS_OFFSET)) != 0) + ; + + writeb((u8)ch, (volatile void *)(PLATFORM_UART_ADDR + + PLATFORM_UART_DATA_OFFSET)); +} + +static int ikr_uart_getc(void) +{ + /* + * Check RX_STATE bit 0 (data available). Reading UART_DATA + * automatically clears the RX_AVAIL bit in hardware, so no + * explicit status-register write is needed here. Writing 0 + * to RXSTS after the DATA read would race with rvemu's input + * thread (which sets RX_AVAIL for the next queued character + * between the DATA read and such a write), silently dropping + * characters when multiple bytes arrive before a poll cycle. + */ + if (readb((volatile void *)(PLATFORM_UART_ADDR + + PLATFORM_UART_RXSTS_OFFSET)) & + PLATFORM_UART_RX_AVAIL) { + return (int)(u8)readb( + (volatile void *)(PLATFORM_UART_ADDR + + PLATFORM_UART_DATA_OFFSET)); + } + return -1; +} + +#endif + +static void ikr_uart_puts(const char *s) +{ + while (*s) { + if (*s == '\n') + ikr_uart_putc('\r'); + ikr_uart_putc(*s++); + } +} + +static struct sbi_console_device ikr_uart_console = { + .name = "ikr-uart", + .console_putc = ikr_uart_putc, + .console_getc = ikr_uart_getc, +}; + +static struct plic_data plic = { + .unique_id = 0, + .addr = PLATFORM_PLIC_ADDR, + .size = PLATFORM_PLIC_SIZE, + .num_src = PLATFORM_PLIC_NUM_SOURCES, + .context_map = { + [0] = { 0, 1 }, + }, +}; + +static struct aclint_mtimer_data mtimer = { + .mtime_freq = PLATFORM_ACLINT_MTIMER_FREQ, + .mtime_addr = PLATFORM_ACLINT_MTIMER_ADDR, + .mtime_size = 0x8, + .mtimecmp_addr = PLATFORM_ACLINT_MTIMER_ADDR + 0x8, + .mtimecmp_size = 0x8, + .first_hartid = 0, + .hart_count = PLATFORM_HART_COUNT, + .has_64bit_mmio = true, +}; + +/* + * Platform early initialization. + */ +static int platform_early_init(bool cold_boot) +{ + + if (!cold_boot) + return 0; + + /* Raw UART banner before console registration. */ + ikr_uart_puts("Loading OpenSBI now...\n"); + + sbi_console_set_device(&ikr_uart_console); + + /* UART and other low MMIO lives in the first page in rvemu. */ + sbi_domain_root_add_memrange(0x0, PAGE_SIZE, PAGE_SIZE, + (SBI_DOMAIN_MEMREGION_MMIO | + SBI_DOMAIN_MEMREGION_SHARED_SURW_MRW)); + /* Allow access to the IKR UART MMIO region (0x11000). */ + /* Keep access to the PLIC/Timer area (assuming they are near 0x0c000000 or 0x02000000) */ + sbi_domain_root_add_memrange(PLATFORM_PLIC_ADDR, 0x400000, PAGE_SIZE, + (SBI_DOMAIN_MEMREGION_MMIO | + SBI_DOMAIN_MEMREGION_SHARED_SURW_MRW)); + + /* rvemu does not provide a page-aligned MSWI window; with one hart we can + * skip MSWI initialization and still boot OpenSBI. + */ + return 0; +} + +/* + * Platform final initialization. + */ +static int platform_final_init(bool cold_boot) +{ + return 0; +} + +/* + * Initialize the platform interrupt controller during cold boot. + */ +static int platform_irqchip_init(void) +{ + /* Example if the generic PLIC driver is used */ + return plic_cold_irqchip_init(&plic); +} + +/* + * Initialize platform timer during cold boot. + */ +static int platform_timer_init(void) +{ + /* Example if the generic ACLINT driver is used */ + return aclint_mtimer_cold_init(&mtimer, NULL); +} + +/* + * Platform descriptor. + */ +const struct sbi_platform_operations platform_ops = { + .early_init = platform_early_init, + .final_init = platform_final_init, + .irqchip_init = platform_irqchip_init, + .timer_init = platform_timer_init +}; +const struct sbi_platform platform = { + .opensbi_version = OPENSBI_VERSION, + .platform_version = SBI_PLATFORM_VERSION(0x0, 0x00), + .name = "ikr-linux", + .features = SBI_PLATFORM_DEFAULT_FEATURES, + .hart_count = PLATFORM_HART_COUNT, + .hart_stack_size = SBI_PLATFORM_DEFAULT_HART_STACK_SIZE, + .heap_size = SBI_PLATFORM_DEFAULT_HEAP_SIZE(1), + .platform_ops_addr = (unsigned long)&platform_ops +};