[PATCH v2 4/9] powerpc/pseries: Introduce helpers to gatekeep DTLB usage
From: Naveen N. Rao <hidden>
Date: 2019-06-14 15:54:01
Subsystem:
linux for powerpc (32-bit and 64-bit), the rest · Maintainers:
Madhavan Srinivasan, Linus Torvalds
Since we would be introducing a new user of the DTL buffer in a subsequent patch, add helpers to gatekeep use of the DTL buffer. The current usage of the DTL buffer from debugfs is at a per-cpu level (corresponding to the cpu debugfs file that is opened). Subsequently, we will have users enabling/accessing DTLB for all online cpus. These helpers allow any number of per-cpu users, or a single global user exclusively. Signed-off-by: Naveen N. Rao <redacted> --- arch/powerpc/include/asm/plpar_wrappers.h | 2 ++ arch/powerpc/platforms/pseries/dtl.c | 10 +++++- arch/powerpc/platforms/pseries/lpar.c | 38 +++++++++++++++++++++++ 3 files changed, 49 insertions(+), 1 deletion(-)
diff --git a/arch/powerpc/include/asm/plpar_wrappers.h b/arch/powerpc/include/asm/plpar_wrappers.h
index d08feb1bc2bd..ab7dd454b6eb 100644
--- a/arch/powerpc/include/asm/plpar_wrappers.h
+++ b/arch/powerpc/include/asm/plpar_wrappers.h@@ -88,6 +88,8 @@ static inline long register_dtl(unsigned long cpu, unsigned long vpa) return vpa_call(H_VPA_REG_DTL, cpu, vpa); } +extern bool register_dtl_buffer_access(bool global); +extern void unregister_dtl_buffer_access(bool global); extern void register_dtl_buffer(int cpu); extern void alloc_dtl_buffers(void); extern void vpa_init(int cpu);
diff --git a/arch/powerpc/platforms/pseries/dtl.c b/arch/powerpc/platforms/pseries/dtl.c
index a88176afba32..de531311cd9a 100644
--- a/arch/powerpc/platforms/pseries/dtl.c
+++ b/arch/powerpc/platforms/pseries/dtl.c@@ -180,11 +180,15 @@ static int dtl_enable(struct dtl *dtl) if (dtl->buf) return -EBUSY; + if (register_dtl_buffer_access(false)) + return -EBUSY; + n_entries = dtl_buf_entries; buf = kmem_cache_alloc_node(dtl_cache, GFP_KERNEL, cpu_to_node(dtl->cpu)); if (!buf) { printk(KERN_WARNING "%s: buffer alloc failed for cpu %d\n", __func__, dtl->cpu); + unregister_dtl_buffer_access(false); return -ENOMEM; }
@@ -201,8 +205,11 @@ static int dtl_enable(struct dtl *dtl) } spin_unlock(&dtl->lock); - if (rc) + if (rc) { + unregister_dtl_buffer_access(false); kmem_cache_free(dtl_cache, buf); + } + return rc; }
@@ -214,6 +221,7 @@ static void dtl_disable(struct dtl *dtl) dtl->buf = NULL; dtl->buf_entries = 0; spin_unlock(&dtl->lock); + unregister_dtl_buffer_access(false); } /* file interface */
diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c
index 8c5377fe9985..53e005c84078 100644
--- a/arch/powerpc/platforms/pseries/lpar.c
+++ b/arch/powerpc/platforms/pseries/lpar.c@@ -99,6 +99,44 @@ void register_dtl_buffer(int cpu) } } +#ifdef CONFIG_PPC_SPLPAR +static DEFINE_SPINLOCK(dtl_buffer_refctr_lock); +static unsigned int dtl_buffer_global_refctr, dtl_buffer_percpu_refctr; + +bool register_dtl_buffer_access(bool global) +{ + int rc = 0; + + spin_lock(&dtl_buffer_refctr_lock); + + if ((global && (dtl_buffer_global_refctr || dtl_buffer_percpu_refctr)) + || (!global && dtl_buffer_global_refctr)) { + rc = -1; + } else { + if (global) + dtl_buffer_global_refctr++; + else + dtl_buffer_percpu_refctr++; + } + + spin_unlock(&dtl_buffer_refctr_lock); + + return rc; +} + +void unregister_dtl_buffer_access(bool global) +{ + spin_lock(&dtl_buffer_refctr_lock); + + if (global) + dtl_buffer_global_refctr--; + else + dtl_buffer_percpu_refctr--; + + spin_unlock(&dtl_buffer_refctr_lock); +} +#endif /* CONFIG_PPC_SPLPAR */ + void vpa_init(int cpu) { int hwcpu = get_hard_smp_processor_id(cpu);
--
2.21.0