diff --git a/include/sbi/sbi_platform.h b/include/sbi/sbi_platform.h index 43fb4ea..2a26346 100644 --- a/include/sbi/sbi_platform.h +++ b/include/sbi/sbi_platform.h @@ -10,24 +10,36 @@ #ifndef __SBI_PLATFORM_H__ #define __SBI_PLATFORM_H__ +/** Offset of name in struct sbi_platform */ #define SBI_PLATFORM_NAME_OFFSET (0x0) +/** Offset of features in struct sbi_platform */ #define SBI_PLATFORM_FEATURES_OFFSET (0x40) +/** Offset of hart_count in struct sbi_platform */ #define SBI_PLATFORM_HART_COUNT_OFFSET (0x48) +/** Offset of hart_stack_size in struct sbi_platform */ #define SBI_PLATFORM_HART_STACK_SIZE_OFFSET (0x4c) #ifndef __ASSEMBLY__ #include +/** Possible feature flags of a platform */ enum sbi_platform_features { + /** Platform has MMIO based timer */ SBI_PLATFORM_HAS_MMIO_TIMER_VALUE = (1 << 0), + /** Platform has HART hotplug support */ SBI_PLATFORM_HAS_HART_HOTPLUG = (1 << 1), + /** Platform has PMP support */ SBI_PLATFORM_HAS_PMP = (1 << 2), + /** Platform has S-mode counter enable */ SBI_PLATFORM_HAS_SCOUNTEREN = (1 << 3), + /** Platform has M-mode counter enable */ SBI_PLATFORM_HAS_MCOUNTEREN = (1 << 4), + /** Platform has fault delegation support */ SBI_PLATFORM_HAS_MFAULTS_DELEGATION = (1 << 5), }; +/** Default feature set for a platform */ #define SBI_PLATFORM_DEFAULT_FEATURES \ (SBI_PLATFORM_HAS_MMIO_TIMER_VALUE | \ SBI_PLATFORM_HAS_PMP | \ @@ -35,50 +47,99 @@ enum sbi_platform_features { SBI_PLATFORM_HAS_MCOUNTEREN | \ SBI_PLATFORM_HAS_MFAULTS_DELEGATION) +/** Representation of a platform */ struct sbi_platform { + /** Name of the platform */ char name[64]; + /** Supported features */ u64 features; + /** Total number of HARTs */ u32 hart_count; + /** Per-HART stack size for exception/interrupt handling */ u32 hart_stack_size; + /** Mask representing the set of disabled HARTs */ u64 disabled_hart_mask; + + /** Platform early initialization */ int (*early_init)(u32 hartid, bool cold_boot); + /** Platform final initialization */ int (*final_init)(u32 hartid, bool cold_boot); + + /** Get number of PMP regions for given HART */ u32 (*pmp_region_count)(u32 hartid); + /** + * Get PMP regions details (namely: protection, base address, + * and size) for given HART + */ int (*pmp_region_info)(u32 hartid, u32 index, ulong *prot, ulong *addr, ulong *log2size); - void (*console_putc)(char ch); - char (*console_getc)(void); - int (*console_init)(void); - int (*irqchip_init)(u32 hartid, bool cold_boot); - void (*ipi_inject)(u32 target_hart, u32 source_hart); - void (*ipi_sync)(u32 target_hart, u32 source_hart); - void (*ipi_clear)(u32 target_hart); - int (*ipi_init)(u32 hartid, bool cold_boot); - u64 (*timer_value)(void); - void (*timer_event_stop)(u32 target_hart); - void (*timer_event_start)(u32 target_hart, u64 next_event); - int (*timer_init)(u32 hartid, bool cold_boot); - int (*system_reboot)(u32 type); - int (*system_shutdown)(u32 type); -} __attribute__((packed)); + /** Write a character to the platform console output */ + void (*console_putc)(char ch); + /** Read a character from the platform console input */ + char (*console_getc)(void); + /** Initialize the platform console */ + int (*console_init)(void); + + /** Initialize the platform interrupt controller */ + int (*irqchip_init)(u32 hartid, bool cold_boot); + + /** Inject IPI to a target HART */ + void (*ipi_inject)(u32 target_hart, u32 source_hart); + /** Wait for target HART to acknowledge IPI */ + void (*ipi_sync)(u32 target_hart, u32 source_hart); + /** Clear IPI for a target HART */ + void (*ipi_clear)(u32 target_hart); + /** Initialize IPI for given HART */ + int (*ipi_init)(u32 hartid, bool cold_boot); + + /** Get MMIO timer value */ + u64 (*timer_value)(void); + /** Start MMIO timer event for a target HART */ + void (*timer_event_start)(u32 target_hart, u64 next_event); + /** Stop MMIO timer event for a target HART */ + void (*timer_event_stop)(u32 target_hart); + /** Initialize MMIO timer for given HART */ + int (*timer_init)(u32 hartid, bool cold_boot); + + /** Reboot the platform */ + int (*system_reboot)(u32 type); + /** Shutdown or poweroff the platform */ + int (*system_shutdown)(u32 type); +} __packed; + +/** Get pointer to sbi_platform for sbi_scratch pointer */ #define sbi_platform_ptr(__s) \ ((struct sbi_platform *)((__s)->platform_addr)) +/** Get pointer to sbi_platform for current HART */ #define sbi_platform_thishart_ptr() \ ((struct sbi_platform *)(sbi_scratch_thishart_ptr()->platform_addr)) +/** Check whether the platform supports MMIO timer */ #define sbi_platform_has_mmio_timer_value(__p) \ ((__p)->features & SBI_PLATFORM_HAS_MMIO_TIMER_VALUE) +/** Check whether the platform supports HART hotplug */ #define sbi_platform_has_hart_hotplug(__p) \ ((__p)->features & SBI_PLATFORM_HAS_HART_HOTPLUG) +/** Check whether the platform has PMP support */ #define sbi_platform_has_pmp(__p) \ ((__p)->features & SBI_PLATFORM_HAS_PMP) +/** Check whether the platform supports scounteren CSR */ #define sbi_platform_has_scounteren(__p) \ ((__p)->features & SBI_PLATFORM_HAS_SCOUNTEREN) +/** Check whether the platform supports mcounteren CSR */ #define sbi_platform_has_mcounteren(__p) \ ((__p)->features & SBI_PLATFORM_HAS_MCOUNTEREN) +/** Check whether the platform supports fault delegation */ #define sbi_platform_has_mfaults_delegation(__p) \ ((__p)->features & SBI_PLATFORM_HAS_MFAULTS_DELEGATION) +/** + * Get name of the platform + * + * @param plat pointer to struct sbi_platform + * + * @return pointer to platform name on success and NULL on failure + */ static inline const char *sbi_platform_name(struct sbi_platform *plat) { if (plat) @@ -86,6 +147,14 @@ static inline const char *sbi_platform_name(struct sbi_platform *plat) return NULL; } +/** + * Check whether the given HART is disabled + * + * @param plat pointer to struct sbi_platform + * @param hartid HART ID + * + * @return TRUE if HART is disabled and FALSE otherwise + */ static inline bool sbi_platform_hart_disabled(struct sbi_platform *plat, u32 hartid) { if (plat && (plat->disabled_hart_mask & (1 << hartid))) @@ -93,6 +162,14 @@ static inline bool sbi_platform_hart_disabled(struct sbi_platform *plat, u32 har else return 0; } + +/** + * Get total number of HARTs supported by the platform + * + * @param plat pointer to struct sbi_platform + * + * @return total number of HARTs + */ static inline u32 sbi_platform_hart_count(struct sbi_platform *plat) { if (plat) @@ -100,6 +177,13 @@ static inline u32 sbi_platform_hart_count(struct sbi_platform *plat) return 0; } +/** + * Get per-HART stack size for exception/interrupt handling + * + * @param plat pointer to struct sbi_platform + * + * @return stack size in bytes + */ static inline u32 sbi_platform_hart_stack_size(struct sbi_platform *plat) { if (plat) @@ -107,6 +191,15 @@ static inline u32 sbi_platform_hart_stack_size(struct sbi_platform *plat) return 0; } +/** + * Early initialization of a given HART + * + * @param plat pointer to struct sbi_platform + * @param hartid HART ID + * @param cold_boot whether cold boot (TRUE) or warm_boot (FALSE) + * + * @return 0 on success and negative error code on failure + */ static inline int sbi_platform_early_init(struct sbi_platform *plat, u32 hartid, bool cold_boot) { @@ -115,6 +208,15 @@ static inline int sbi_platform_early_init(struct sbi_platform *plat, return 0; } +/** + * Final initialization of a HART + * + * @param plat pointer to struct sbi_platform + * @param hartid HART ID + * @param cold_boot whether cold boot (TRUE) or warm_boot (FALSE) + * + * @return 0 on success and negative error code on failure + */ static inline int sbi_platform_final_init(struct sbi_platform *plat, u32 hartid, bool cold_boot) { @@ -123,6 +225,14 @@ static inline int sbi_platform_final_init(struct sbi_platform *plat, return 0; } +/** + * Get the number of PMP regions of a HART + * + * @param plat pointer to struct sbi_platform + * @param hartid HART ID + * + * @return number of PMP regions + */ static inline u32 sbi_platform_pmp_region_count(struct sbi_platform *plat, u32 hartid) { @@ -131,6 +241,19 @@ static inline u32 sbi_platform_pmp_region_count(struct sbi_platform *plat, return 0; } +/** + * Get PMP regions details (namely: protection, base address, + * and size) of a HART + * + * @param plat pointer to struct sbi_platform + * @param hartid HART ID + * @param index index of PMP region for which we want details + * @param prot output pointer for PMP region protection + * @param addr output pointer for PMP region base address + * @param log2size output pointer for log-of-2 PMP region size + * + * @return 0 on success and negative error code on failure + */ static inline int sbi_platform_pmp_region_info(struct sbi_platform *plat, u32 hartid, u32 index, ulong *prot, ulong *addr, @@ -142,6 +265,12 @@ static inline int sbi_platform_pmp_region_info(struct sbi_platform *plat, return 0; } +/** + * Write a character to the platform console output + * + * @param plat pointer to struct sbi_platform + * @param ch character to write + */ static inline void sbi_platform_console_putc(struct sbi_platform *plat, char ch) { @@ -149,6 +278,13 @@ static inline void sbi_platform_console_putc(struct sbi_platform *plat, plat->console_putc(ch); } +/** + * Read a character from the platform console input + * + * @param plat pointer to struct sbi_platform + * + * @return character read from console input + */ static inline char sbi_platform_console_getc(struct sbi_platform *plat) { if (plat && plat->console_getc) @@ -156,6 +292,13 @@ static inline char sbi_platform_console_getc(struct sbi_platform *plat) return 0; } +/** + * Initialize the platform console + * + * @param plat pointer to struct sbi_platform + * + * @return 0 on success and negative error code on failure + */ static inline int sbi_platform_console_init(struct sbi_platform *plat) { if (plat && plat->console_init) @@ -163,6 +306,15 @@ static inline int sbi_platform_console_init(struct sbi_platform *plat) return 0; } +/** + * Initialize the platform interrupt controller for given HART + * + * @param plat pointer to struct sbi_platform + * @param hartid HART ID + * @param cold_boot whether cold boot (TRUE) or warm_boot (FALSE) + * + * @return 0 on success and negative error code on failure + */ static inline int sbi_platform_irqchip_init(struct sbi_platform *plat, u32 hartid, bool cold_boot) { @@ -171,6 +323,12 @@ static inline int sbi_platform_irqchip_init(struct sbi_platform *plat, return 0; } +/** + * Inject IPI to a target HART + * + * @param plat pointer to struct sbi_platform + * @param target_hart HART ID of IPI target + */ static inline void sbi_platform_ipi_inject(struct sbi_platform *plat, u32 target_hart, u32 source_hart) { @@ -178,6 +336,13 @@ static inline void sbi_platform_ipi_inject(struct sbi_platform *plat, plat->ipi_inject(target_hart, source_hart); } +/** + * Wait for target HART to acknowledge IPI + * + * @param plat pointer to struct sbi_platform + * @param target_hart HART ID of IPI target + * @param source_hart HART ID of IPI source + */ static inline void sbi_platform_ipi_sync(struct sbi_platform *plat, u32 target_hart, u32 source_hart) { @@ -185,6 +350,12 @@ static inline void sbi_platform_ipi_sync(struct sbi_platform *plat, plat->ipi_sync(target_hart, source_hart); } +/** + * Clear IPI for a target HART + * + * @param plat pointer to struct sbi_platform + * @param target_hart HART ID of IPI target + */ static inline void sbi_platform_ipi_clear(struct sbi_platform *plat, u32 target_hart) { @@ -192,6 +363,15 @@ static inline void sbi_platform_ipi_clear(struct sbi_platform *plat, plat->ipi_clear(target_hart); } +/** + * Initialize the platform IPI support for given HART + * + * @param plat pointer to struct sbi_platform + * @param hartid HART ID + * @param cold_boot whether cold boot (TRUE) or warm_boot (FALSE) + * + * @return 0 on success and negative error code on failure + */ static inline int sbi_platform_ipi_init(struct sbi_platform *plat, u32 hartid, bool cold_boot) { @@ -200,6 +380,13 @@ static inline int sbi_platform_ipi_init(struct sbi_platform *plat, return 0; } +/** + * Get MMIO timer value + * + * @param plat pointer to struct sbi_platform + * + * @return 64bit timer value + */ static inline u64 sbi_platform_timer_value(struct sbi_platform *plat) { if (plat && plat->timer_value) @@ -207,13 +394,13 @@ static inline u64 sbi_platform_timer_value(struct sbi_platform *plat) return 0; } -static inline void sbi_platform_timer_event_stop(struct sbi_platform *plat, - u32 target_hart) -{ - if (plat && plat->timer_event_stop) - plat->timer_event_stop(target_hart); -} - +/** + * Start MMIO timer event for a target HART + * + * @param plat pointer to struct struct sbi_platform + * @param target_hart HART ID of timer event target + * @param next_event timer value when timer event will happen + */ static inline void sbi_platform_timer_event_start(struct sbi_platform *plat, u32 target_hart, u64 next_event) @@ -222,6 +409,28 @@ static inline void sbi_platform_timer_event_start(struct sbi_platform *plat, plat->timer_event_start(target_hart, next_event); } +/** + * Stop MMIO timer event for a target HART + * + * @param plat pointer to struct sbi_platform + * @param target_hart HART ID of timer event target + */ +static inline void sbi_platform_timer_event_stop(struct sbi_platform *plat, + u32 target_hart) +{ + if (plat && plat->timer_event_stop) + plat->timer_event_stop(target_hart); +} + +/** + * Initialize the platform MMIO timer for given HART + * + * @param plat pointer to struct sbi_platform + * @param hartid HART ID + * @param cold_boot whether cold boot (TRUE) or warm_boot (FALSE) + * + * @return 0 on success and negative error code on failure + */ static inline int sbi_platform_timer_init(struct sbi_platform *plat, u32 hartid, bool cold_boot) { @@ -230,6 +439,14 @@ static inline int sbi_platform_timer_init(struct sbi_platform *plat, return 0; } +/** + * Reboot the platform + * + * @param plat pointer to struct sbi_platform + * @param type type of reboot + * + * @return 0 on success and negative error code on failure + */ static inline int sbi_platform_system_reboot(struct sbi_platform *plat, u32 type) { @@ -238,6 +455,14 @@ static inline int sbi_platform_system_reboot(struct sbi_platform *plat, return 0; } +/** + * Shutdown or poweroff the platform + * + * @param plat pointer to struct sbi_platform + * @param type type of shutdown or poweroff + * + * @return 0 on success and negative error code on failure + */ static inline int sbi_platform_system_shutdown(struct sbi_platform *plat, u32 type) { diff --git a/lib/sbi_trap.c b/lib/sbi_trap.c index 9f212c1..3c01660 100644 --- a/lib/sbi_trap.c +++ b/lib/sbi_trap.c @@ -75,7 +75,7 @@ static void __noreturn sbi_trap_error(const char *msg, * @param cause exception cause for lower privledge mode * @param tval trap value for lower privledge mode * - * Returns 0 on success and error code (< 0) on failure + * @return 0 on success and negative error code on failure */ int sbi_trap_redirect(struct sbi_trap_regs *regs, struct sbi_scratch *scratch,