aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAtish Patra <atish.patra@wdc.com>2019-09-10 03:40:38 -0700
committerAnup Patel <anup@brainfault.org>2019-09-10 17:44:10 +0530
commit98ee15ca3adcf7bc22695897cd63a3ce8c5c53ff (patch)
treefad1689c391ba8660674e2b80cab3c9df5900aba
parentf2e82c3d797d9f64ec8f33365c35a2b5f7ea2bbb (diff)
lib: provide a platform specific tlb range flush threshold
Currently, the tlb range flush threshold is fixed and set to 4k for all platforms. However, it should be platform specific as it completely depends upon how platform actually implements sfence instruction. Define a platform feature that allows every individual platform to set different values. If a platform doesn't define it, just use a page size as the threshold. Signed-off-by: Atish Patra <atish.patra@wdc.com> Reviewed-by: Bin Meng <bmeng.cn@gmail.com> Reviewed-by: Anup Patel <anup.patel@wdc.com>
-rw-r--r--include/sbi/sbi_platform.h26
-rw-r--r--include/sbi/sbi_tlb.h1
-rw-r--r--lib/sbi/sbi_tlb.c5
-rw-r--r--platform/template/platform.c1
4 files changed, 29 insertions, 4 deletions
diff --git a/include/sbi/sbi_platform.h b/include/sbi/sbi_platform.h
index 97195c4..7f5dd29 100644
--- a/include/sbi/sbi_platform.h
+++ b/include/sbi/sbi_platform.h
@@ -30,10 +30,14 @@
#define SBI_PLATFORM_HART_STACK_SIZE_OFFSET (0x54)
/** Offset of disabled_hart_mask in struct sbi_platform */
#define SBI_PLATFORM_DISABLED_HART_OFFSET (0x58)
+/** Offset of tlb_range_flush_limit in struct sbi_platform */
+#define SBI_PLATFORM_TLB_RANGE_FLUSH_LIMIT_OFFSET (0x60)
/** Offset of platform_ops_addr in struct sbi_platform */
-#define SBI_PLATFORM_OPS_OFFSET (0x60)
+#define SBI_PLATFORM_OPS_OFFSET (0x68)
/** Offset of firmware_context in struct sbi_platform */
-#define SBI_PLATFORM_FIRMWARE_CONTEXT_OFFSET (0x60 + __SIZEOF_POINTER__)
+#define SBI_PLATFORM_FIRMWARE_CONTEXT_OFFSET (0x68 + __SIZEOF_POINTER__)
+
+#define SBI_PLATFORM_TLB_RANGE_FLUSH_LIMIT_DEFAULT (1UL << 12)
#ifndef __ASSEMBLY__
@@ -134,6 +138,8 @@ struct sbi_platform {
u32 hart_stack_size;
/** Mask representing the set of disabled HARTs */
u64 disabled_hart_mask;
+ /* Maximum value of tlb flush range request*/
+ u64 tlb_range_flush_limit;
/** Pointer to sbi platform operations */
unsigned long platform_ops_addr;
/** Pointer to system firmware specific context */
@@ -199,6 +205,22 @@ static inline bool sbi_platform_hart_disabled(const struct sbi_platform *plat,
}
/**
+ * Get platform specific tlb range flush maximum value. Any request with size
+ * higher than this is upgraded to a full flush.
+ *
+ * @param plat pointer to struct sbi_platform
+ *
+ * @return tlb range flush limit value. Returns a default (page size) if not
+ * defined by platform.
+ */
+static inline u64 sbi_platform_tlbr_flush_limit(const struct sbi_platform *plat)
+{
+ if (plat)
+ return plat->tlb_range_flush_limit;
+ return SBI_PLATFORM_TLB_RANGE_FLUSH_LIMIT_DEFAULT;
+}
+
+/**
* Get total number of HARTs supported by the platform
*
* @param plat pointer to struct sbi_platform
diff --git a/include/sbi/sbi_tlb.h b/include/sbi/sbi_tlb.h
index cd52c12..d1d6f22 100644
--- a/include/sbi/sbi_tlb.h
+++ b/include/sbi/sbi_tlb.h
@@ -16,7 +16,6 @@
/* clang-format off */
#define SBI_TLB_FLUSH_ALL ((unsigned long)-1)
-#define SBI_TLB_FLUSH_MAX_SIZE (1UL << 12)
/* clang-format on */
diff --git a/lib/sbi/sbi_tlb.c b/lib/sbi/sbi_tlb.c
index c4e5f48..5c4c596 100644
--- a/lib/sbi/sbi_tlb.c
+++ b/lib/sbi/sbi_tlb.c
@@ -23,6 +23,7 @@
static unsigned long tlb_sync_off;
static unsigned long tlb_fifo_off;
static unsigned long tlb_fifo_mem_off;
+static unsigned long tlb_range_flush_limit;
static void sbi_tlb_flush_all(void)
{
@@ -232,7 +233,7 @@ int sbi_tlb_fifo_update(struct sbi_scratch *rscratch, u32 hartid, void *data)
* upgrade it to flush all because we can only flush
* 4KB at a time.
*/
- if (tinfo->size > SBI_TLB_FLUSH_MAX_SIZE) {
+ if (tinfo->size > tlb_range_flush_limit) {
tinfo->start = 0;
tinfo->size = SBI_TLB_FLUSH_ALL;
}
@@ -276,6 +277,7 @@ int sbi_tlb_fifo_init(struct sbi_scratch *scratch, bool cold_boot)
void *tlb_mem;
unsigned long *tlb_sync;
struct sbi_fifo *tlb_q;
+ const struct sbi_platform *plat = sbi_platform_ptr(scratch);
if (cold_boot) {
tlb_sync_off = sbi_scratch_alloc_offset(sizeof(*tlb_sync),
@@ -296,6 +298,7 @@ int sbi_tlb_fifo_init(struct sbi_scratch *scratch, bool cold_boot)
sbi_scratch_free_offset(tlb_sync_off);
return SBI_ENOMEM;
}
+ tlb_range_flush_limit = sbi_platform_tlbr_flush_limit(plat);
} else {
if (!tlb_sync_off ||
!tlb_fifo_off ||
diff --git a/platform/template/platform.c b/platform/template/platform.c
index e123f3a..d36af48 100644
--- a/platform/template/platform.c
+++ b/platform/template/platform.c
@@ -224,5 +224,6 @@ const struct sbi_platform platform = {
.hart_count = 1,
.hart_stack_size = 4096,
.disabled_hart_mask = 0,
+ .tlb_range_flush_limit = 0,
.platform_ops_addr = (unsigned long)&platform_ops
};