From b2df751acfd2858f2370d896f91543593647b243 Mon Sep 17 00:00:00 2001 From: Atish Patra Date: Sat, 9 May 2020 16:47:28 -0700 Subject: [PATCH] platform: Move platform features to hart PMP & performance counters belong to a hart rather than a platform. In addition to that, these features enable reading/writing from a particular csr. Thus, they can be detected and set at runtime rather than compile time. Move PMP/MCOUNTEREN/SCOUNTEREN features to hart and detect them at runtime. Signed-off-by: Atish Patra Tested-by: Jonathan Balkind Reviewed-by: Anup Patel --- include/sbi/sbi_hart.h | 11 ++++++ include/sbi/sbi_platform.h | 22 ++---------- lib/sbi/sbi_hart.c | 68 +++++++++++++++++++++++++++++++++----- lib/utils/fdt/fdt_fixup.c | 4 +-- platform/fpga/ariane/platform.c | 2 -- platform/fpga/openpiton/platform.c | 2 -- platform/thead/c910/platform.h | 4 +-- 7 files changed, 77 insertions(+), 36 deletions(-) diff --git a/include/sbi/sbi_hart.h b/include/sbi/sbi_hart.h index e285bdf..f7870d9 100644 --- a/include/sbi/sbi_hart.h +++ b/include/sbi/sbi_hart.h @@ -12,6 +12,16 @@ #include +/** Possible feature flags of a hart */ +enum sbi_hart_features { + /** Hart has PMP support */ + SBI_HART_HAS_PMP = (1 << 0), + /** Hart has S-mode counter enable */ + SBI_HART_HAS_SCOUNTEREN = (1 << 1), + /** Hart has M-mode counter enable */ + SBI_HART_HAS_MCOUNTEREN = (1 << 2), +}; + struct sbi_scratch; int sbi_hart_init(struct sbi_scratch *scratch, u32 hartid, bool cold_boot); @@ -27,6 +37,7 @@ void sbi_hart_pmp_dump(struct sbi_scratch *scratch); int sbi_hart_pmp_check_addr(struct sbi_scratch *scratch, unsigned long daddr, unsigned long attr); bool sbi_hart_has_feature(u32 hartid, unsigned long feature); +unsigned long sbi_hart_get_features(u32 hartid); void __attribute__((noreturn)) sbi_hart_hang(void); diff --git a/include/sbi/sbi_platform.h b/include/sbi/sbi_platform.h index 9eaf82e..675d021 100644 --- a/include/sbi/sbi_platform.h +++ b/include/sbi/sbi_platform.h @@ -52,23 +52,15 @@ enum sbi_platform_features { SBI_PLATFORM_HAS_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), + SBI_PLATFORM_HAS_MFAULTS_DELEGATION = (1 << 2), /** Platform has custom secondary hart booting support */ - SBI_PLATFORM_HAS_HART_SECONDARY_BOOT = (1 << 6), + SBI_PLATFORM_HAS_HART_SECONDARY_BOOT = (1 << 3), }; /** Default feature set for a platform */ #define SBI_PLATFORM_DEFAULT_FEATURES \ - (SBI_PLATFORM_HAS_TIMER_VALUE | SBI_PLATFORM_HAS_PMP | \ - SBI_PLATFORM_HAS_SCOUNTEREN | SBI_PLATFORM_HAS_MCOUNTEREN | \ - SBI_PLATFORM_HAS_MFAULTS_DELEGATION) + (SBI_PLATFORM_HAS_TIMER_VALUE | SBI_PLATFORM_HAS_MFAULTS_DELEGATION) /** Platform functions */ struct sbi_platform_operations { @@ -224,14 +216,6 @@ struct sbi_platform { /** 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) diff --git a/lib/sbi/sbi_hart.c b/lib/sbi/sbi_hart.c index cf3e9fb..10972c8 100644 --- a/lib/sbi/sbi_hart.c +++ b/lib/sbi/sbi_hart.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -26,7 +27,6 @@ static unsigned long hart_features_offset; static void mstatus_init(struct sbi_scratch *scratch, u32 hartid) { - const struct sbi_platform *plat = sbi_platform_ptr(scratch); unsigned long mstatus_val = 0; /* Enable FPU */ @@ -40,9 +40,10 @@ static void mstatus_init(struct sbi_scratch *scratch, u32 hartid) csr_write(CSR_MSTATUS, mstatus_val); /* Enable user/supervisor use of perf counters */ - if (misa_extension('S') && sbi_platform_has_scounteren(plat)) + if (misa_extension('S') && + sbi_hart_has_feature(hartid, SBI_HART_HAS_SCOUNTEREN)) csr_write(CSR_SCOUNTEREN, -1); - if (sbi_platform_has_mcounteren(plat)) + if (!sbi_hart_has_feature(hartid, SBI_HART_HAS_MCOUNTEREN)) csr_write(CSR_MCOUNTEREN, -1); /* Disable all interrupts */ @@ -125,11 +126,10 @@ void sbi_hart_delegation_dump(struct sbi_scratch *scratch) void sbi_hart_pmp_dump(struct sbi_scratch *scratch) { - const struct sbi_platform *plat = sbi_platform_ptr(scratch); unsigned long prot, addr, size; unsigned int i; - if (!sbi_platform_has_pmp(plat)) + if (!sbi_hart_has_feature(current_hartid(), SBI_HART_HAS_PMP)) return; for (i = 0; i < PMP_COUNT; i++) { @@ -158,9 +158,8 @@ int sbi_hart_pmp_check_addr(struct sbi_scratch *scratch, unsigned long addr, unsigned long attr) { unsigned long prot, size, i, tempaddr; - const struct sbi_platform *plat = sbi_platform_ptr(scratch); - if (!sbi_platform_has_pmp(plat)) + if (!sbi_hart_has_feature(current_hartid(), SBI_HART_HAS_PMP)) return SBI_OK; for (i = 0; i < PMP_COUNT; i++) { @@ -182,7 +181,7 @@ static int pmp_init(struct sbi_scratch *scratch, u32 hartid) ulong prot, addr, log2size; const struct sbi_platform *plat = sbi_platform_ptr(scratch); - if (!sbi_platform_has_pmp(plat)) + if (!sbi_hart_has_feature(current_hartid(), SBI_HART_HAS_PMP)) return 0; /* Firmware PMP region to protect OpenSBI firmware */ @@ -224,6 +223,57 @@ bool sbi_hart_has_feature(u32 hartid, unsigned long feature) return false; } +static void sbi_hart_set_feature(u32 hartid, unsigned long feature) +{ + unsigned long *hart_features; + struct sbi_scratch *scratch; + + scratch = sbi_hartid_to_scratch(hartid); + hart_features = sbi_scratch_offset_ptr(scratch, hart_features_offset); + + *hart_features = *hart_features | feature; +} + +static void sbi_hart_detect_features(u32 hartid) +{ + struct sbi_trap_info trap = {0}; + unsigned long feature = 0; + unsigned long csr_val; + + if (hartid != current_hartid()) + sbi_hart_hang(); + + /* Detect if hart supports PMP feature */ + csr_val = csr_read_allowed(CSR_PMPCFG0, (unsigned long)&trap); + if (!trap.cause) { + csr_write_allowed(CSR_PMPCFG0, (unsigned long)&trap, csr_val); + if (!trap.cause) + feature |= SBI_HART_HAS_PMP; + } + + /* Detect if hart supports SCOUNTEREN feature */ + trap.cause = 0; + csr_val = csr_read_allowed(CSR_SCOUNTEREN, (unsigned long)&trap); + if (!trap.cause) { + csr_write_allowed(CSR_SCOUNTEREN, (unsigned long)&trap, + csr_val); + if (!trap.cause) + feature |= SBI_HART_HAS_SCOUNTEREN; + } + + /* Detect if hart supports MCOUNTEREN feature */ + trap.cause = 0; + csr_val = csr_read_allowed(CSR_MCOUNTEREN, (unsigned long)&trap); + if (!trap.cause) { + csr_write_allowed(CSR_MCOUNTEREN, (unsigned long)&trap, + csr_val); + if (!trap.cause) + feature |= SBI_HART_HAS_MCOUNTEREN; + } + + sbi_hart_set_feature(hartid, feature); +} + int sbi_hart_init(struct sbi_scratch *scratch, u32 hartid, bool cold_boot) { int rc; @@ -251,6 +301,8 @@ int sbi_hart_init(struct sbi_scratch *scratch, u32 hartid, bool cold_boot) if (rc) return rc; + sbi_hart_detect_features(hartid); + return pmp_init(scratch, hartid); } diff --git a/lib/utils/fdt/fdt_fixup.c b/lib/utils/fdt/fdt_fixup.c index e209cb6..e69ba1d 100644 --- a/lib/utils/fdt/fdt_fixup.c +++ b/lib/utils/fdt/fdt_fixup.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -143,7 +144,6 @@ static int fdt_resv_memory_update_node(void *fdt, unsigned long addr, int fdt_reserved_memory_fixup(void *fdt) { struct sbi_scratch *scratch = sbi_scratch_thishart_ptr(); - const struct sbi_platform *plat = sbi_platform_ptr(scratch); unsigned long prot, addr, size; int parent, i, j; int err; @@ -183,7 +183,7 @@ int fdt_reserved_memory_fixup(void *fdt) return err; } - if (!sbi_platform_has_pmp(plat)) { + if (!sbi_hart_has_feature(current_hartid(), SBI_HART_HAS_PMP)) { /* update the DT with firmware start & size even if PMP is not * supported. This makes sure that supervisor OS is always * aware of wheren OpenSBI resident memory area. diff --git a/platform/fpga/ariane/platform.c b/platform/fpga/ariane/platform.c index 7c76ff8..ad64c74 100644 --- a/platform/fpga/ariane/platform.c +++ b/platform/fpga/ariane/platform.c @@ -28,8 +28,6 @@ #define SBI_ARIANE_FEATURES \ (SBI_PLATFORM_HAS_TIMER_VALUE | \ - SBI_PLATFORM_HAS_SCOUNTEREN | \ - SBI_PLATFORM_HAS_MCOUNTEREN | \ SBI_PLATFORM_HAS_MFAULTS_DELEGATION) /* diff --git a/platform/fpga/openpiton/platform.c b/platform/fpga/openpiton/platform.c index c549a95..89512e1 100644 --- a/platform/fpga/openpiton/platform.c +++ b/platform/fpga/openpiton/platform.c @@ -28,8 +28,6 @@ #define SBI_OPENPITON_FEATURES \ (SBI_PLATFORM_HAS_TIMER_VALUE | \ - SBI_PLATFORM_HAS_SCOUNTEREN | \ - SBI_PLATFORM_HAS_MCOUNTEREN | \ SBI_PLATFORM_HAS_MFAULTS_DELEGATION) static struct platform_uart_data uart = { diff --git a/platform/thead/c910/platform.h b/platform/thead/c910/platform.h index 0faf2af..354404e 100644 --- a/platform/thead/c910/platform.h +++ b/platform/thead/c910/platform.h @@ -8,9 +8,7 @@ #define C910_HART_COUNT 16 #define SBI_THEAD_FEATURES \ - (SBI_PLATFORM_HAS_SCOUNTEREN | \ - SBI_PLATFORM_HAS_MCOUNTEREN | \ - SBI_PLATFORM_HAS_MFAULTS_DELEGATION | \ + (SBI_PLATFORM_HAS_MFAULTS_DELEGATION | \ SBI_PLATFORM_HAS_HART_SECONDARY_BOOT) #define CSR_MCOR 0x7c2 -- 2.7.4