mirror of
https://github.com/riscv-software-src/opensbi.git
synced 2025-08-25 07:41:42 +01:00
Compare commits
15 Commits
Author | SHA1 | Date | |
---|---|---|---|
e64a712de9 | |||
![]() |
84044ee83c | ||
![]() |
cc546e1a06 | ||
![]() |
079bf6f0f9 | ||
![]() |
ffd3ed976d | ||
![]() |
0b7c2e0d60 | ||
![]() |
e10a45752f | ||
![]() |
4825a3f87f | ||
![]() |
3876f8cd1e | ||
![]() |
5b305e30a5 | ||
![]() |
663b05a5f7 | ||
![]() |
edfbc1285d | ||
![]() |
ea5abd1f5e | ||
![]() |
61083eb504 | ||
![]() |
b8f370aa37 |
@@ -1 +1,28 @@
|
|||||||
# SPDX-License-Identifier: BSD-2-Clause
|
# SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
|
||||||
|
menu "Stack Protector Support"
|
||||||
|
|
||||||
|
config STACK_PROTECTOR
|
||||||
|
bool "Stack Protector buffer overflow detection"
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
This option turns on the "stack-protector" compiler feature.
|
||||||
|
|
||||||
|
config STACK_PROTECTOR_STRONG
|
||||||
|
bool "Strong Stack Protector"
|
||||||
|
depends on STACK_PROTECTOR
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
Turn on the "stack-protector" with "-fstack-protector-strong" option.
|
||||||
|
Like -fstack-protector but includes additional functions to be
|
||||||
|
protected.
|
||||||
|
|
||||||
|
config STACK_PROTECTOR_ALL
|
||||||
|
bool "Almighty Stack Protector"
|
||||||
|
depends on STACK_PROTECTOR
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
Turn on the "stack-protector" with "-fstack-protector-all" option.
|
||||||
|
Like -fstack-protector except that all functions are protected.
|
||||||
|
|
||||||
|
endmenu
|
||||||
|
@@ -76,21 +76,21 @@ _sc_fail:
|
|||||||
li t0, FW_TEXT_START /* link start */
|
li t0, FW_TEXT_START /* link start */
|
||||||
lla t1, _fw_start /* load start */
|
lla t1, _fw_start /* load start */
|
||||||
sub t2, t1, t0 /* load offset */
|
sub t2, t1, t0 /* load offset */
|
||||||
lla t0, __rel_dyn_start
|
lla t0, __rela_dyn_start
|
||||||
lla t1, __rel_dyn_end
|
lla t1, __rela_dyn_end
|
||||||
beq t0, t1, _relocate_done
|
beq t0, t1, _relocate_done
|
||||||
2:
|
2:
|
||||||
REG_L t5, REGBYTES(t0) /* t5 <-- relocation info:type */
|
REG_L t5, __SIZEOF_LONG__(t0) /* t5 <-- relocation info:type */
|
||||||
li t3, R_RISCV_RELATIVE /* reloc type R_RISCV_RELATIVE */
|
li t3, R_RISCV_RELATIVE /* reloc type R_RISCV_RELATIVE */
|
||||||
bne t5, t3, 3f
|
bne t5, t3, 3f
|
||||||
REG_L t3, 0(t0)
|
REG_L t3, 0(t0)
|
||||||
REG_L t5, (REGBYTES * 2)(t0) /* t5 <-- addend */
|
REG_L t5, (__SIZEOF_LONG__ * 2)(t0) /* t5 <-- addend */
|
||||||
add t5, t5, t2
|
add t5, t5, t2
|
||||||
add t3, t3, t2
|
add t3, t3, t2
|
||||||
REG_S t5, 0(t3) /* store runtime address to the GOT entry */
|
REG_S t5, 0(t3) /* store runtime address to the GOT entry */
|
||||||
|
|
||||||
3:
|
3:
|
||||||
addi t0, t0, (REGBYTES * 3)
|
addi t0, t0, (__SIZEOF_LONG__ * 3)
|
||||||
blt t0, t1, 2b
|
blt t0, t1, 2b
|
||||||
_relocate_done:
|
_relocate_done:
|
||||||
/* At this point we are running from link address */
|
/* At this point we are running from link address */
|
||||||
@@ -736,6 +736,27 @@ _reset_regs:
|
|||||||
|
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
.section .rodata
|
||||||
|
.Lstack_corrupt_msg:
|
||||||
|
.string "stack smashing detected\n"
|
||||||
|
|
||||||
|
/* This will be called when the stack corruption is detected */
|
||||||
|
.section .text
|
||||||
|
.align 3
|
||||||
|
.globl __stack_chk_fail
|
||||||
|
.type __stack_chk_fail, %function
|
||||||
|
__stack_chk_fail:
|
||||||
|
la a0, .Lstack_corrupt_msg
|
||||||
|
call sbi_panic
|
||||||
|
|
||||||
|
/* Initial value of the stack guard variable */
|
||||||
|
.section .data
|
||||||
|
.align 3
|
||||||
|
.globl __stack_chk_guard
|
||||||
|
.type __stack_chk_guard, %object
|
||||||
|
__stack_chk_guard:
|
||||||
|
RISCV_PTR 0x95B5FF5A
|
||||||
|
|
||||||
#ifdef FW_FDT_PATH
|
#ifdef FW_FDT_PATH
|
||||||
.section .rodata
|
.section .rodata
|
||||||
.align 4
|
.align 4
|
||||||
|
@@ -47,9 +47,9 @@
|
|||||||
. = ALIGN(0x1000); /* Ensure next section is page aligned */
|
. = ALIGN(0x1000); /* Ensure next section is page aligned */
|
||||||
|
|
||||||
.rela.dyn : {
|
.rela.dyn : {
|
||||||
PROVIDE(__rel_dyn_start = .);
|
PROVIDE(__rela_dyn_start = .);
|
||||||
*(.rela*)
|
*(.rela*)
|
||||||
PROVIDE(__rel_dyn_end = .);
|
PROVIDE(__rela_dyn_end = .);
|
||||||
}
|
}
|
||||||
|
|
||||||
PROVIDE(_rodata_end = .);
|
PROVIDE(_rodata_end = .);
|
||||||
|
@@ -66,3 +66,12 @@ endif
|
|||||||
ifdef FW_OPTIONS
|
ifdef FW_OPTIONS
|
||||||
firmware-genflags-y += -DFW_OPTIONS=$(FW_OPTIONS)
|
firmware-genflags-y += -DFW_OPTIONS=$(FW_OPTIONS)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq ($(CONFIG_STACK_PROTECTOR),y)
|
||||||
|
stack-protector-cflags-$(CONFIG_STACK_PROTECTOR) := -fstack-protector
|
||||||
|
stack-protector-cflags-$(CONFIG_STACK_PROTECTOR_STRONG) := -fstack-protector-strong
|
||||||
|
stack-protector-cflags-$(CONFIG_STACK_PROTECTOR_ALL) := -fstack-protector-all
|
||||||
|
else
|
||||||
|
stack-protector-cflags-y := -fno-stack-protector
|
||||||
|
endif
|
||||||
|
firmware-cflags-y += $(stack-protector-cflags-y)
|
||||||
|
@@ -97,3 +97,18 @@ _boot_a0:
|
|||||||
RISCV_PTR 0
|
RISCV_PTR 0
|
||||||
_boot_a1:
|
_boot_a1:
|
||||||
RISCV_PTR 0
|
RISCV_PTR 0
|
||||||
|
|
||||||
|
/* This will be called when the stack corruption is detected */
|
||||||
|
.section .text
|
||||||
|
.align 3
|
||||||
|
.globl __stack_chk_fail
|
||||||
|
.type __stack_chk_fail, %function
|
||||||
|
.equ __stack_chk_fail, _start_hang
|
||||||
|
|
||||||
|
/* Initial value of the stack guard variable */
|
||||||
|
.section .data
|
||||||
|
.align 3
|
||||||
|
.globl __stack_chk_guard
|
||||||
|
.type __stack_chk_guard, %object
|
||||||
|
__stack_chk_guard:
|
||||||
|
RISCV_PTR 0x95B5FF5A
|
||||||
|
@@ -46,6 +46,13 @@ static inline void sbi_ecall_console_puts(const char *str)
|
|||||||
sbi_strlen(str), (unsigned long)str, 0, 0, 0, 0);
|
sbi_strlen(str), (unsigned long)str, 0, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void sbi_ecall_shutdown(void)
|
||||||
|
{
|
||||||
|
sbi_ecall(SBI_EXT_SRST, SBI_EXT_SRST_RESET,
|
||||||
|
SBI_SRST_RESET_TYPE_SHUTDOWN, SBI_SRST_RESET_REASON_NONE,
|
||||||
|
0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
#define wfi() \
|
#define wfi() \
|
||||||
do { \
|
do { \
|
||||||
__asm__ __volatile__("wfi" ::: "memory"); \
|
__asm__ __volatile__("wfi" ::: "memory"); \
|
||||||
@@ -54,7 +61,6 @@ static inline void sbi_ecall_console_puts(const char *str)
|
|||||||
void test_main(unsigned long a0, unsigned long a1)
|
void test_main(unsigned long a0, unsigned long a1)
|
||||||
{
|
{
|
||||||
sbi_ecall_console_puts("\nTest payload running\n");
|
sbi_ecall_console_puts("\nTest payload running\n");
|
||||||
|
sbi_ecall_shutdown();
|
||||||
while (1)
|
sbi_ecall_console_puts("sbi_ecall_shutdown failed to execute.\n");
|
||||||
wfi();
|
|
||||||
}
|
}
|
||||||
|
@@ -1291,6 +1291,8 @@
|
|||||||
#define SHIFT_FUNCT3 12
|
#define SHIFT_FUNCT3 12
|
||||||
|
|
||||||
#define MASK_RS1 0xf8000
|
#define MASK_RS1 0xf8000
|
||||||
|
#define MASK_RS2 0x1f00000
|
||||||
|
#define MASK_RD 0xf80
|
||||||
|
|
||||||
#define MASK_CSR 0xfff00000
|
#define MASK_CSR 0xfff00000
|
||||||
#define SHIFT_CSR 20
|
#define SHIFT_CSR 20
|
||||||
@@ -1315,13 +1317,6 @@
|
|||||||
|
|
||||||
#define INSN_LEN(insn) (INSN_IS_16BIT(insn) ? 2 : 4)
|
#define INSN_LEN(insn) (INSN_IS_16BIT(insn) ? 2 : 4)
|
||||||
|
|
||||||
#if __riscv_xlen == 64
|
|
||||||
#define LOG_REGBYTES 3
|
|
||||||
#else
|
|
||||||
#define LOG_REGBYTES 2
|
|
||||||
#endif
|
|
||||||
#define REGBYTES (1 << LOG_REGBYTES)
|
|
||||||
|
|
||||||
#define SH_VSEW 3
|
#define SH_VSEW 3
|
||||||
#define SH_VIEW 12
|
#define SH_VIEW 12
|
||||||
#define SH_VD 7
|
#define SH_VD 7
|
||||||
@@ -1356,28 +1351,17 @@
|
|||||||
#define SHIFT_RIGHT(x, y) \
|
#define SHIFT_RIGHT(x, y) \
|
||||||
((y) < 0 ? ((x) << -(y)) : ((x) >> (y)))
|
((y) < 0 ? ((x) << -(y)) : ((x) >> (y)))
|
||||||
|
|
||||||
#define REG_MASK \
|
|
||||||
((1 << (5 + LOG_REGBYTES)) - (1 << LOG_REGBYTES))
|
|
||||||
|
|
||||||
#define REG_OFFSET(insn, pos) \
|
|
||||||
(SHIFT_RIGHT((insn), (pos) - LOG_REGBYTES) & REG_MASK)
|
|
||||||
|
|
||||||
#define REG_PTR(insn, pos, regs) \
|
|
||||||
(ulong *)((ulong)(regs) + REG_OFFSET(insn, pos))
|
|
||||||
|
|
||||||
#define GET_FUNC3(insn) ((insn & MASK_FUNCT3) >> SHIFT_FUNCT3)
|
#define GET_FUNC3(insn) ((insn & MASK_FUNCT3) >> SHIFT_FUNCT3)
|
||||||
#define GET_RM(insn) GET_FUNC3(insn)
|
#define GET_RM(insn) GET_FUNC3(insn)
|
||||||
#define GET_RS1_NUM(insn) ((insn & MASK_RS1) >> 15)
|
#define GET_RS1_NUM(insn) ((insn & MASK_RS1) >> SH_RS1)
|
||||||
|
#define GET_RS2_NUM(insn) ((insn & MASK_RS2) >> SH_RS2)
|
||||||
|
#define GET_RS1S_NUM(insn) RVC_RS1S(insn)
|
||||||
|
#define GET_RS2S_NUM(insn) RVC_RS2S(insn)
|
||||||
|
#define GET_RS2C_NUM(insn) RVC_RS2(insn)
|
||||||
|
#define GET_RD_NUM(insn) ((insn & MASK_RD) >> SH_RD)
|
||||||
#define GET_CSR_NUM(insn) ((insn & MASK_CSR) >> SHIFT_CSR)
|
#define GET_CSR_NUM(insn) ((insn & MASK_CSR) >> SHIFT_CSR)
|
||||||
#define GET_AQRL(insn) ((insn & MASK_AQRL) >> SHIFT_AQRL)
|
#define GET_AQRL(insn) ((insn & MASK_AQRL) >> SHIFT_AQRL)
|
||||||
|
|
||||||
#define GET_RS1(insn, regs) (*REG_PTR(insn, SH_RS1, regs))
|
|
||||||
#define GET_RS2(insn, regs) (*REG_PTR(insn, SH_RS2, regs))
|
|
||||||
#define GET_RS1S(insn, regs) (*REG_PTR(RVC_RS1S(insn), 0, regs))
|
|
||||||
#define GET_RS2S(insn, regs) (*REG_PTR(RVC_RS2S(insn), 0, regs))
|
|
||||||
#define GET_RS2C(insn, regs) (*REG_PTR(insn, SH_RS2C, regs))
|
|
||||||
#define GET_SP(regs) (*REG_PTR(2, 0, regs))
|
|
||||||
#define SET_RD(insn, regs, val) (*REG_PTR(insn, SH_RD, regs) = (val))
|
|
||||||
#define IMM_I(insn) ((s32)(insn) >> 20)
|
#define IMM_I(insn) ((s32)(insn) >> 20)
|
||||||
#define IMM_S(insn) (((s32)(insn) >> 25 << 5) | \
|
#define IMM_S(insn) (((s32)(insn) >> 25 << 5) | \
|
||||||
(s32)(((insn) >> 7) & 0x1f))
|
(s32)(((insn) >> 7) & 0x1f))
|
||||||
|
@@ -14,13 +14,13 @@
|
|||||||
# define _conv_cast(type, val) ((type)(val))
|
# define _conv_cast(type, val) ((type)(val))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define BSWAP16(x) ((((x) & 0x00ff) << 8) | \
|
#define __BSWAP16(x) ((((x) & 0x00ff) << 8) | \
|
||||||
(((x) & 0xff00) >> 8))
|
(((x) & 0xff00) >> 8))
|
||||||
#define BSWAP32(x) ((((x) & 0x000000ff) << 24) | \
|
#define __BSWAP32(x) ((((x) & 0x000000ff) << 24) | \
|
||||||
(((x) & 0x0000ff00) << 8) | \
|
(((x) & 0x0000ff00) << 8) | \
|
||||||
(((x) & 0x00ff0000) >> 8) | \
|
(((x) & 0x00ff0000) >> 8) | \
|
||||||
(((x) & 0xff000000) >> 24))
|
(((x) & 0xff000000) >> 24))
|
||||||
#define BSWAP64(x) ((((x) & 0x00000000000000ffULL) << 56) | \
|
#define __BSWAP64(x) ((((x) & 0x00000000000000ffULL) << 56) | \
|
||||||
(((x) & 0x000000000000ff00ULL) << 40) | \
|
(((x) & 0x000000000000ff00ULL) << 40) | \
|
||||||
(((x) & 0x0000000000ff0000ULL) << 24) | \
|
(((x) & 0x0000000000ff0000ULL) << 24) | \
|
||||||
(((x) & 0x00000000ff000000ULL) << 8) | \
|
(((x) & 0x00000000ff000000ULL) << 8) | \
|
||||||
@@ -29,6 +29,10 @@
|
|||||||
(((x) & 0x00ff000000000000ULL) >> 40) | \
|
(((x) & 0x00ff000000000000ULL) >> 40) | \
|
||||||
(((x) & 0xff00000000000000ULL) >> 56))
|
(((x) & 0xff00000000000000ULL) >> 56))
|
||||||
|
|
||||||
|
#define BSWAP64(x) ({ uint64_t _sv = (x); __BSWAP64(_sv); })
|
||||||
|
#define BSWAP32(x) ({ uint32_t _sv = (x); __BSWAP32(_sv); })
|
||||||
|
#define BSWAP16(x) ({ uint16_t _sv = (x); __BSWAP16(_sv); })
|
||||||
|
|
||||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ /* CPU(little-endian) */
|
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ /* CPU(little-endian) */
|
||||||
#define cpu_to_be16(x) _conv_cast(uint16_t, BSWAP16(x))
|
#define cpu_to_be16(x) _conv_cast(uint16_t, BSWAP16(x))
|
||||||
#define cpu_to_be32(x) _conv_cast(uint32_t, BSWAP32(x))
|
#define cpu_to_be32(x) _conv_cast(uint32_t, BSWAP32(x))
|
||||||
|
@@ -18,7 +18,7 @@
|
|||||||
({ \
|
({ \
|
||||||
register ulong tinfo asm("a3") = (ulong)trap; \
|
register ulong tinfo asm("a3") = (ulong)trap; \
|
||||||
register ulong ttmp asm("a4"); \
|
register ulong ttmp asm("a4"); \
|
||||||
register ulong mtvec = sbi_hart_expected_trap_addr(); \
|
register ulong mtvec = (ulong)sbi_hart_expected_trap; \
|
||||||
register ulong ret = 0; \
|
register ulong ret = 0; \
|
||||||
((struct sbi_trap_info *)(trap))->cause = 0; \
|
((struct sbi_trap_info *)(trap))->cause = 0; \
|
||||||
asm volatile( \
|
asm volatile( \
|
||||||
@@ -37,7 +37,7 @@
|
|||||||
({ \
|
({ \
|
||||||
register ulong tinfo asm("a3") = (ulong)trap; \
|
register ulong tinfo asm("a3") = (ulong)trap; \
|
||||||
register ulong ttmp asm("a4"); \
|
register ulong ttmp asm("a4"); \
|
||||||
register ulong mtvec = sbi_hart_expected_trap_addr(); \
|
register ulong mtvec = (ulong)sbi_hart_expected_trap; \
|
||||||
((struct sbi_trap_info *)(trap))->cause = 0; \
|
((struct sbi_trap_info *)(trap))->cause = 0; \
|
||||||
asm volatile( \
|
asm volatile( \
|
||||||
"add %[ttmp], %[tinfo], zero\n" \
|
"add %[ttmp], %[tinfo], zero\n" \
|
||||||
|
@@ -134,10 +134,6 @@ int sbi_hart_reinit(struct sbi_scratch *scratch);
|
|||||||
int sbi_hart_init(struct sbi_scratch *scratch, bool cold_boot);
|
int sbi_hart_init(struct sbi_scratch *scratch, bool cold_boot);
|
||||||
|
|
||||||
extern void (*sbi_hart_expected_trap)(void);
|
extern void (*sbi_hart_expected_trap)(void);
|
||||||
static inline ulong sbi_hart_expected_trap_addr(void)
|
|
||||||
{
|
|
||||||
return (ulong)sbi_hart_expected_trap;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int sbi_hart_mhpm_mask(struct sbi_scratch *scratch);
|
unsigned int sbi_hart_mhpm_mask(struct sbi_scratch *scratch);
|
||||||
void sbi_hart_delegation_dump(struct sbi_scratch *scratch,
|
void sbi_hart_delegation_dump(struct sbi_scratch *scratch,
|
||||||
|
@@ -160,4 +160,17 @@ static inline void sbi_list_del_init(struct sbi_dlist *entry)
|
|||||||
&pos->member != (head); \
|
&pos->member != (head); \
|
||||||
pos = sbi_list_entry(pos->member.next, typeof(*pos), member))
|
pos = sbi_list_entry(pos->member.next, typeof(*pos), member))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Iterate over list of given type safe against removal of list entry
|
||||||
|
* @param pos the type * to use as a loop cursor.
|
||||||
|
* @param n another type * to use as temporary storage.
|
||||||
|
* @param head the head for your list.
|
||||||
|
* @param member the name of the list_struct within the struct.
|
||||||
|
*/
|
||||||
|
#define sbi_list_for_each_entry_safe(pos, n, head, member) \
|
||||||
|
for (pos = sbi_list_entry((head)->next, typeof(*pos), member), \
|
||||||
|
n = sbi_list_entry(pos->member.next, typeof(*pos), member); \
|
||||||
|
&pos->member != (head); \
|
||||||
|
pos = n, n = sbi_list_entry(pos->member.next, typeof(*pos), member))
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -127,6 +127,9 @@
|
|||||||
|
|
||||||
/** Representation of register state at time of trap/interrupt */
|
/** Representation of register state at time of trap/interrupt */
|
||||||
struct sbi_trap_regs {
|
struct sbi_trap_regs {
|
||||||
|
union {
|
||||||
|
unsigned long gprs[32];
|
||||||
|
struct {
|
||||||
/** zero register state */
|
/** zero register state */
|
||||||
unsigned long zero;
|
unsigned long zero;
|
||||||
/** ra register state */
|
/** ra register state */
|
||||||
@@ -191,6 +194,8 @@ struct sbi_trap_regs {
|
|||||||
unsigned long t5;
|
unsigned long t5;
|
||||||
/** t6 register state */
|
/** t6 register state */
|
||||||
unsigned long t6;
|
unsigned long t6;
|
||||||
|
};
|
||||||
|
};
|
||||||
/** mepc register state */
|
/** mepc register state */
|
||||||
unsigned long mepc;
|
unsigned long mepc;
|
||||||
/** mstatus register state */
|
/** mstatus register state */
|
||||||
@@ -199,6 +204,21 @@ struct sbi_trap_regs {
|
|||||||
unsigned long mstatusH;
|
unsigned long mstatusH;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
_Static_assert(
|
||||||
|
sizeof(((struct sbi_trap_regs *)0)->gprs) ==
|
||||||
|
offsetof(struct sbi_trap_regs, t6) +
|
||||||
|
sizeof(((struct sbi_trap_regs *)0)->t6),
|
||||||
|
"struct sbi_trap_regs's layout differs between gprs and named members");
|
||||||
|
|
||||||
|
#define REG_VAL(idx, regs) ((regs)->gprs[(idx)])
|
||||||
|
|
||||||
|
#define GET_RS1(insn, regs) REG_VAL(GET_RS1_NUM(insn), regs)
|
||||||
|
#define GET_RS2(insn, regs) REG_VAL(GET_RS2_NUM(insn), regs)
|
||||||
|
#define GET_RS1S(insn, regs) REG_VAL(GET_RS1S_NUM(insn), regs)
|
||||||
|
#define GET_RS2S(insn, regs) REG_VAL(GET_RS2S_NUM(insn), regs)
|
||||||
|
#define GET_RS2C(insn, regs) REG_VAL(GET_RS2C_NUM(insn), regs)
|
||||||
|
#define SET_RD(insn, regs, val) (REG_VAL(GET_RD_NUM(insn), regs) = (val))
|
||||||
|
|
||||||
/** Representation of trap details */
|
/** Representation of trap details */
|
||||||
struct sbi_trap_info {
|
struct sbi_trap_info {
|
||||||
/** cause Trap exception cause */
|
/** cause Trap exception cause */
|
||||||
|
@@ -7,10 +7,12 @@
|
|||||||
#ifndef __SBI_VISIBILITY_H__
|
#ifndef __SBI_VISIBILITY_H__
|
||||||
#define __SBI_VISIBILITY_H__
|
#define __SBI_VISIBILITY_H__
|
||||||
|
|
||||||
|
#ifndef __DTS__
|
||||||
/*
|
/*
|
||||||
* Declare all global objects with hidden visibility so access is PC-relative
|
* Declare all global objects with hidden visibility so access is PC-relative
|
||||||
* instead of going through the GOT.
|
* instead of going through the GOT.
|
||||||
*/
|
*/
|
||||||
#pragma GCC visibility push(hidden)
|
#pragma GCC visibility push(hidden)
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -49,10 +49,10 @@ static void mstatus_init(struct sbi_scratch *scratch)
|
|||||||
|
|
||||||
csr_write(CSR_MSTATUS, mstatus_val);
|
csr_write(CSR_MSTATUS, mstatus_val);
|
||||||
|
|
||||||
/* Disable user mode usage of all perf counters except default ones (CY, TM, IR) */
|
/* Disable user mode usage of all perf counters except TM */
|
||||||
if (misa_extension('S') &&
|
if (misa_extension('S') &&
|
||||||
sbi_hart_priv_version(scratch) >= SBI_HART_PRIV_VER_1_10)
|
sbi_hart_priv_version(scratch) >= SBI_HART_PRIV_VER_1_10)
|
||||||
csr_write(CSR_SCOUNTEREN, 7);
|
csr_write(CSR_SCOUNTEREN, 0x02);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* OpenSBI doesn't use any PMU counters in M-mode.
|
* OpenSBI doesn't use any PMU counters in M-mode.
|
||||||
|
@@ -30,7 +30,7 @@ int sbi_illegal_atomic(ulong insn, struct sbi_trap_regs *regs)
|
|||||||
{ \
|
{ \
|
||||||
register ulong tinfo asm("a3"); \
|
register ulong tinfo asm("a3"); \
|
||||||
register ulong mstatus = 0; \
|
register ulong mstatus = 0; \
|
||||||
register ulong mtvec = sbi_hart_expected_trap_addr(); \
|
register ulong mtvec = (ulong)sbi_hart_expected_trap; \
|
||||||
type ret = 0; \
|
type ret = 0; \
|
||||||
trap->cause = 0; \
|
trap->cause = 0; \
|
||||||
asm volatile( \
|
asm volatile( \
|
||||||
@@ -57,7 +57,7 @@ int sbi_illegal_atomic(ulong insn, struct sbi_trap_regs *regs)
|
|||||||
{ \
|
{ \
|
||||||
register ulong tinfo asm("a3"); \
|
register ulong tinfo asm("a3"); \
|
||||||
register ulong mstatus = 0; \
|
register ulong mstatus = 0; \
|
||||||
register ulong mtvec = sbi_hart_expected_trap_addr(); \
|
register ulong mtvec = (ulong)sbi_hart_expected_trap; \
|
||||||
type ret = 0; \
|
type ret = 0; \
|
||||||
trap->cause = 0; \
|
trap->cause = 0; \
|
||||||
asm volatile( \
|
asm volatile( \
|
||||||
|
@@ -24,7 +24,7 @@
|
|||||||
{ \
|
{ \
|
||||||
register ulong tinfo asm("a3"); \
|
register ulong tinfo asm("a3"); \
|
||||||
register ulong mstatus = 0; \
|
register ulong mstatus = 0; \
|
||||||
register ulong mtvec = sbi_hart_expected_trap_addr(); \
|
register ulong mtvec = (ulong)sbi_hart_expected_trap; \
|
||||||
type ret = 0; \
|
type ret = 0; \
|
||||||
trap->cause = 0; \
|
trap->cause = 0; \
|
||||||
asm volatile( \
|
asm volatile( \
|
||||||
@@ -51,7 +51,7 @@
|
|||||||
{ \
|
{ \
|
||||||
register ulong tinfo asm("a3") = (ulong)trap; \
|
register ulong tinfo asm("a3") = (ulong)trap; \
|
||||||
register ulong mstatus = 0; \
|
register ulong mstatus = 0; \
|
||||||
register ulong mtvec = sbi_hart_expected_trap_addr(); \
|
register ulong mtvec = (ulong)sbi_hart_expected_trap; \
|
||||||
trap->cause = 0; \
|
trap->cause = 0; \
|
||||||
asm volatile( \
|
asm volatile( \
|
||||||
"add %[tinfo], %[taddr], zero\n" \
|
"add %[tinfo], %[taddr], zero\n" \
|
||||||
@@ -121,7 +121,7 @@ ulong sbi_get_insn(ulong mepc, struct sbi_trap_info *trap)
|
|||||||
register ulong tinfo asm("a3");
|
register ulong tinfo asm("a3");
|
||||||
register ulong ttmp asm("a4");
|
register ulong ttmp asm("a4");
|
||||||
register ulong mstatus = 0;
|
register ulong mstatus = 0;
|
||||||
register ulong mtvec = sbi_hart_expected_trap_addr();
|
register ulong mtvec = (ulong)sbi_hart_expected_trap;
|
||||||
ulong insn = 0;
|
ulong insn = 0;
|
||||||
|
|
||||||
trap->cause = 0;
|
trap->cause = 0;
|
||||||
|
@@ -84,23 +84,27 @@ static int fdt_translate_address(const void *fdt, uint64_t reg, int parent,
|
|||||||
uint64_t *addr)
|
uint64_t *addr)
|
||||||
{
|
{
|
||||||
int i, rlen;
|
int i, rlen;
|
||||||
int cell_addr, cell_size;
|
int cell_parent_addr, cell_child_addr, cell_size;
|
||||||
const fdt32_t *ranges;
|
const fdt32_t *ranges;
|
||||||
uint64_t offset, caddr = 0, paddr = 0, rsize = 0;
|
uint64_t offset, caddr = 0, paddr = 0, rsize = 0;
|
||||||
|
|
||||||
cell_addr = fdt_address_cells(fdt, parent);
|
ranges = fdt_getprop(fdt, parent, "ranges", &rlen);
|
||||||
if (cell_addr < 1)
|
if (ranges && rlen > 0) {
|
||||||
|
cell_child_addr = fdt_address_cells(fdt, parent);
|
||||||
|
if (cell_child_addr < 1)
|
||||||
|
return SBI_ENODEV;
|
||||||
|
|
||||||
|
cell_parent_addr = fdt_address_cells(fdt, fdt_parent_offset(fdt, parent));
|
||||||
|
if (cell_parent_addr < 1)
|
||||||
return SBI_ENODEV;
|
return SBI_ENODEV;
|
||||||
|
|
||||||
cell_size = fdt_size_cells(fdt, parent);
|
cell_size = fdt_size_cells(fdt, parent);
|
||||||
if (cell_size < 0)
|
if (cell_size < 0)
|
||||||
return SBI_ENODEV;
|
return SBI_ENODEV;
|
||||||
|
|
||||||
ranges = fdt_getprop(fdt, parent, "ranges", &rlen);
|
for (i = 0; i < cell_child_addr; i++)
|
||||||
if (ranges && rlen > 0) {
|
|
||||||
for (i = 0; i < cell_addr; i++)
|
|
||||||
caddr = (caddr << 32) | fdt32_to_cpu(*ranges++);
|
caddr = (caddr << 32) | fdt32_to_cpu(*ranges++);
|
||||||
for (i = 0; i < cell_addr; i++)
|
for (i = 0; i < cell_parent_addr; i++)
|
||||||
paddr = (paddr << 32) | fdt32_to_cpu(*ranges++);
|
paddr = (paddr << 32) | fdt32_to_cpu(*ranges++);
|
||||||
for (i = 0; i < cell_size; i++)
|
for (i = 0; i < cell_size; i++)
|
||||||
rsize = (rsize << 32) | fdt32_to_cpu(*ranges++);
|
rsize = (rsize << 32) | fdt32_to_cpu(*ranges++);
|
||||||
|
@@ -133,9 +133,8 @@ int uart8250_init(unsigned long base, u32 in_freq, u32 baudrate, u32 reg_shift,
|
|||||||
set_reg(UART_FCR_OFFSET, 0x01);
|
set_reg(UART_FCR_OFFSET, 0x01);
|
||||||
/* No modem control DTR RTS */
|
/* No modem control DTR RTS */
|
||||||
set_reg(UART_MCR_OFFSET, 0x00);
|
set_reg(UART_MCR_OFFSET, 0x00);
|
||||||
/* Clear line status */
|
/* Clear line status and read receive buffer */
|
||||||
get_reg(UART_LSR_OFFSET);
|
if (get_reg(UART_LSR_OFFSET) & UART_LSR_DR)
|
||||||
/* Read receive buffer */
|
|
||||||
get_reg(UART_RBR_OFFSET);
|
get_reg(UART_RBR_OFFSET);
|
||||||
/* Set scratchpad */
|
/* Set scratchpad */
|
||||||
set_reg(UART_SCR_OFFSET, 0x00);
|
set_reg(UART_SCR_OFFSET, 0x00);
|
||||||
|
@@ -79,7 +79,7 @@ static int openpiton_early_init(bool cold_boot)
|
|||||||
{
|
{
|
||||||
const void *fdt;
|
const void *fdt;
|
||||||
struct platform_uart_data uart_data = { 0 };
|
struct platform_uart_data uart_data = { 0 };
|
||||||
struct plic_data plic_data;
|
struct plic_data plic_data = plic;
|
||||||
unsigned long aclint_freq;
|
unsigned long aclint_freq;
|
||||||
uint64_t clint_addr;
|
uint64_t clint_addr;
|
||||||
int rc;
|
int rc;
|
||||||
|
16
platform/riscv_vp/Kconfig
Normal file
16
platform/riscv_vp/Kconfig
Normal file
@@ -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 n
|
0
platform/riscv_vp/configs/defconfig
Normal file
0
platform/riscv_vp/configs/defconfig
Normal file
99
platform/riscv_vp/objects.mk
Normal file
99
platform/riscv_vp/objects.mk
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
#
|
||||||
|
# SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
#
|
||||||
|
# Copyright (c) 2019 Western Digital Corporation or its affiliates.
|
||||||
|
#
|
||||||
|
|
||||||
|
# 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 = lp64d
|
||||||
|
PLATFORM_RISCV_ISA = rv64imafdc_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 <dt file name>.dts
|
||||||
|
#
|
||||||
|
# platform-objs-y += <dt file name>.o
|
||||||
|
|
||||||
|
# Optional parameter for path to external FDT
|
||||||
|
# FW_FDT_PATH="path to platform flattened device tree file"
|
||||||
|
|
||||||
|
#
|
||||||
|
# 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 "<X>_ADDR" if both "<X>_ADDR" and "<X>_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
|
178
platform/riscv_vp/platform.c
Normal file
178
platform/riscv_vp/platform.c
Normal file
@@ -0,0 +1,178 @@
|
|||||||
|
#include <sbi/riscv_asm.h>
|
||||||
|
#include <sbi/riscv_encoding.h>
|
||||||
|
#include <sbi/sbi_const.h>
|
||||||
|
#include <sbi/sbi_platform.h>
|
||||||
|
#include <sbi/sbi_console.h>
|
||||||
|
#include <sbi/sbi_types.h>
|
||||||
|
#include <sbi/sbi_ecall_interface.h>
|
||||||
|
#include <sbi/sbi_ecall.h>
|
||||||
|
#include <sbi/sbi_system.h>
|
||||||
|
#include <sbi/riscv_asm.h>
|
||||||
|
#include <sbi/sbi_timer.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
volatile uint32_t RX_TX_REG;
|
||||||
|
volatile uint32_t INT_CTRL_REG;
|
||||||
|
volatile uint32_t CLK_DIVIDER_REG;
|
||||||
|
volatile uint32_t FRAME_CONFIG_REG;
|
||||||
|
volatile uint32_t STATUS_REG;
|
||||||
|
} uart_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
volatile uint32_t MSIP0;
|
||||||
|
uint8_t fill0[16380];
|
||||||
|
volatile uint32_t MTIMECMP0LO;
|
||||||
|
volatile uint32_t MTIMECMP0HI;
|
||||||
|
uint8_t fill1[32752];
|
||||||
|
volatile uint32_t MTIME_LO;
|
||||||
|
volatile uint32_t MTIME_HI;
|
||||||
|
} aclint_t;
|
||||||
|
|
||||||
|
#define PERIPH(TYPE, ADDR) ((volatile TYPE *)(ADDR))
|
||||||
|
#define uart PERIPH(uart_t, 0x10000000 + 0x01000)
|
||||||
|
#define aclint PERIPH(aclint_t, 0x10000000 + 0x30000)
|
||||||
|
static inline void set_aclint_mtimecmp0lo(volatile aclint_t* reg, uint32_t value) {
|
||||||
|
reg->MTIMECMP0LO = (reg->MTIMECMP0LO & ~(0xffffffffU << 0)) | (value << 0);
|
||||||
|
}
|
||||||
|
static inline void set_aclint_mtimecmp0hi(volatile aclint_t* reg, uint32_t value) {
|
||||||
|
reg->MTIMECMP0HI = (reg->MTIMECMP0HI & ~(0xffffffffU << 0)) | (value << 0);
|
||||||
|
}
|
||||||
|
static inline uint32_t get_aclint_mtime_lo(volatile aclint_t* reg) { return (reg->MTIME_LO >> 0) & 0xffffffff; }
|
||||||
|
static inline uint32_t get_aclint_mtime_hi(volatile aclint_t* reg) { return (reg->MTIME_HI >> 0) & 0xffffffff; }
|
||||||
|
|
||||||
|
static inline uint32_t get_uart_rx_tx_reg_tx_free(volatile uart_t* reg) { return (reg->RX_TX_REG >> 15) & 0x1; }
|
||||||
|
static inline void set_uart_rx_tx_reg_data(volatile uart_t* reg, uint8_t value) {
|
||||||
|
reg->RX_TX_REG = (reg->RX_TX_REG & ~(0xffU << 0)) | (value << 0);
|
||||||
|
}
|
||||||
|
static inline uint32_t get_uart_rx_tx_reg_rx_avail(volatile uart_t* reg) { return (reg->RX_TX_REG >> 14) & 0x1; }
|
||||||
|
static inline uint32_t get_uart_rx_tx_reg_data(volatile uart_t* reg) { return (reg->RX_TX_REG >> 0) & 0xff; }
|
||||||
|
|
||||||
|
static void riscv_vp_putc(char c){
|
||||||
|
while(get_uart_rx_tx_reg_tx_free(uart) == 0)
|
||||||
|
;
|
||||||
|
set_uart_rx_tx_reg_data(uart, c);
|
||||||
|
}
|
||||||
|
static int riscv_vp_getc(){
|
||||||
|
if (get_uart_rx_tx_reg_rx_avail(uart))
|
||||||
|
return get_uart_rx_tx_reg_data(uart);
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
const struct sbi_console_device minres_console = {
|
||||||
|
.name = "riscv_vp-uart",
|
||||||
|
.console_putc = riscv_vp_putc,
|
||||||
|
.console_getc = riscv_vp_getc,
|
||||||
|
};
|
||||||
|
|
||||||
|
void riscv_vp_reset(u32 reset_type, u32 reset_reason){
|
||||||
|
switch (reset_type) {
|
||||||
|
case SBI_SRST_RESET_TYPE_SHUTDOWN:
|
||||||
|
sbi_printf("Shutting down system...\n");
|
||||||
|
break;
|
||||||
|
case SBI_SRST_RESET_TYPE_COLD_REBOOT:
|
||||||
|
sbi_printf("Performing cold reboot...\n");
|
||||||
|
break;
|
||||||
|
case SBI_SRST_RESET_TYPE_WARM_REBOOT:
|
||||||
|
sbi_printf("Performing warm reboot...\n");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
sbi_printf("Unknown system reset type: %u\n", reset_type);
|
||||||
|
}
|
||||||
|
while (1)
|
||||||
|
wfi();
|
||||||
|
};
|
||||||
|
int riscv_vp_reset_check(u32 reset_type, u32 reset_reason){
|
||||||
|
switch (reset_type) {
|
||||||
|
case SBI_SRST_RESET_TYPE_SHUTDOWN:
|
||||||
|
return 1;
|
||||||
|
case SBI_SRST_RESET_TYPE_COLD_REBOOT:
|
||||||
|
case SBI_SRST_RESET_TYPE_WARM_REBOOT:
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}};
|
||||||
|
|
||||||
|
|
||||||
|
static struct sbi_system_reset_device reset_device = {
|
||||||
|
.name = "riscv_vp-reset",
|
||||||
|
.system_reset_check = riscv_vp_reset_check,
|
||||||
|
.system_reset = riscv_vp_reset
|
||||||
|
};
|
||||||
|
|
||||||
|
static u64 riscv_vp_timer_value(void){
|
||||||
|
uint32_t hi, lo;
|
||||||
|
do {
|
||||||
|
hi = get_aclint_mtime_hi(aclint);
|
||||||
|
lo = get_aclint_mtime_lo(aclint);
|
||||||
|
} while (hi != get_aclint_mtime_hi(aclint));
|
||||||
|
return ((u64)hi << 32) | lo;
|
||||||
|
}
|
||||||
|
static void riscv_vp_timer_event_start(u64 next_event){
|
||||||
|
// sbi_printf("OpenSBI: setting timer at %#lx\n", next_event);
|
||||||
|
set_aclint_mtimecmp0lo(aclint, (uint32_t)0xFFFFFFFF);
|
||||||
|
set_aclint_mtimecmp0hi(aclint, (uint32_t)(next_event >> 32));
|
||||||
|
set_aclint_mtimecmp0lo(aclint, (uint32_t)(next_event & 0xFFFFFFFF));
|
||||||
|
}
|
||||||
|
static void riscv_vp_timer_event_stop(void){
|
||||||
|
// sbi_printf("OpenSBI: Cancelling pending event\n");
|
||||||
|
set_aclint_mtimecmp0lo(aclint, (uint32_t)0xFFFFFFFF);
|
||||||
|
set_aclint_mtimecmp0hi(aclint, (uint32_t)0xFFFFFFFF);
|
||||||
|
}
|
||||||
|
static int riscv_vp_timer_warm_init(void){
|
||||||
|
riscv_vp_timer_event_stop();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
static struct sbi_timer_device timer_device = {
|
||||||
|
.name = "riscv_vp_timer",
|
||||||
|
.timer_freq = 32768,
|
||||||
|
.timer_value = riscv_vp_timer_value,
|
||||||
|
.timer_event_start = riscv_vp_timer_event_start,
|
||||||
|
.timer_event_stop = riscv_vp_timer_event_stop,
|
||||||
|
.warm_init = riscv_vp_timer_warm_init
|
||||||
|
};
|
||||||
|
|
||||||
|
static int platform_early_init(bool cold_boot){
|
||||||
|
if (cold_boot){
|
||||||
|
sbi_console_set_device(&minres_console);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
static int platform_final_init(bool cold_boot){
|
||||||
|
if (cold_boot){
|
||||||
|
sbi_system_reset_add_device(&reset_device);
|
||||||
|
sbi_timer_set_device(&timer_device);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int platform_irqchip_init(void){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int platform_ipi_init(void){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int platform_timer_init(void){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const struct sbi_platform_operations platform_ops = {
|
||||||
|
.early_init = platform_early_init,
|
||||||
|
.final_init = platform_final_init,
|
||||||
|
.irqchip_init = platform_irqchip_init,
|
||||||
|
.ipi_init = platform_ipi_init,
|
||||||
|
.timer_init = platform_timer_init
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const struct sbi_platform platform = {
|
||||||
|
.opensbi_version = OPENSBI_VERSION,
|
||||||
|
.platform_version = SBI_PLATFORM_VERSION(0x1, 0x07),
|
||||||
|
.name = "riscv_vp",
|
||||||
|
.features = SBI_PLATFORM_DEFAULT_FEATURES,
|
||||||
|
.hart_count = 1,
|
||||||
|
.hart_stack_size = SBI_PLATFORM_DEFAULT_HART_STACK_SIZE,
|
||||||
|
.heap_size = SBI_PLATFORM_DEFAULT_HEAP_SIZE(1),
|
||||||
|
.platform_ops_addr = (unsigned long)&platform_ops
|
||||||
|
};
|
Reference in New Issue
Block a user