powerpc/pseries,powernv: Enable clang context analysis
Ritesh Harjani (IBM)
reviewercover powerpc/pseries,powernv: Enable clang context analysis
Enable Clang context analysis checking for PowerPC pseries & powernv platforms.
Lock acquire and release checking used to be done with Sparse. That support was removed [1] and replaced with Clang context analysis [2].
Note that enabling this caught few real locking races in arch/powerpc/mm. However, the fixes for those and enablement for the rest of the subsystems will be done in a follow up patch series. Also the more invasive checkers to check what each lock protects is again deferred for later enablement.
The series was build tested with Clang 23.x
[1] 5b63d0ae94cc ("compiler-context-analysis: Remove Sparse support")
[2] 3269701cb256 ("compiler-context-analysis: Add infrastructure for Context Analysis with Clang")
Ritesh Harjani (IBM) (12):
powerpc/pseries: Drop inline from hugepage invalidate powerpc/pseries: Rework hugepage invalidate to remove conditional locking powerpc/pseries: Rework hash flush to remove conditional locking powerpc/pseries: Add context annotations for the DTL worker lock powerpc/pseries: Annotate the VPD sequence lock context powerpc/pseries: Annotate the RTAS indices sequence lock context powerpc/pseries: Annotate the RTAS physical-attestation sequence lock context powerpc/pseries: Annotate the DTL debugfs read lock context powerpc/pseries: Disable context analysis for the CMM hotplug notifier powerpc/pseries: Enable context analysis
powerpc/powernv: Rework OPAL console write to remove conditional locking powerpc/powernv: Enable context analysis
arch/powerpc/platforms/powernv/Makefile | 2 + arch/powerpc/platforms/powernv/opal.c | 30 ++++++---- arch/powerpc/platforms/pseries/Makefile | 3 + arch/powerpc/platforms/pseries/cmm.c | 1 + arch/powerpc/platforms/pseries/dtl.c | 8 +++ arch/powerpc/platforms/pseries/lpar.c | 59 ++++++++++++------- arch/powerpc/platforms/pseries/papr-indices.c | 3 + .../platforms/pseries/papr-phy-attest.c | 4 ++ arch/powerpc/platforms/pseries/papr-vpd.c | 3 + 9 files changed, 81 insertions(+), 32 deletions(-)
--
2.39.5
Ritesh Harjani (IBM)
reviewerRFC 1/12 powerpc/pseries: Drop inline from hugepage invalidate
Leave __pSeries_lpar_hugepage_invalidate() static and let the compiler decide whether to inline it.
--- arch/powerpc/platforms/pseries/lpar.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/powerpc/platforms/pseries/lpar.c +1 -1
@@ -1225,7 +1225,7 @@ static void hugepage_bulk_invalidate(unsigned long *slot, unsigned long *vpn, } } -static inline void __pSeries_lpar_hugepage_invalidate (unsigned long *slot, +static void __pSeries_lpar_hugepage_invalidate (unsigned long *slot,unsigned long *vpn,int count,int psize,int ssize)
Signature · 1 line
2.39.5
Ritesh Harjani (IBM)
reviewerRFC 2/12 powerpc/pseries: Rework hugepage invalidate to remove conditional locking
In reply to Ritesh Harjani (IBM)Clang's compiler based static context analysis does not work with locks that are conditionally taken like in __pSeries_lpar_hugepage_invalidate().
lpar.c:1240:6: error: spinlock 'pSeries_lpar_tlbie_lock' is not held on every path through here [-Werror,-Wthread-safety-analysis]
But this also simplifies the function definition in my opinion - so this is also a win.
No functional change intended.
--- arch/powerpc/platforms/pseries/lpar.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-)
arch/powerpc/platforms/pseries/lpar.c +16 -9
@@ -1224,26 +1224,33 @@ static void hugepage_bulk_invalidate(unsigned long *slot, unsigned long *vpn,BUG_ON (rc !=H_SUCCESS ); } } - -static void __pSeries_lpar_hugepage_invalidate (unsigned long *slot, +static void __pSeries_lpar_hugepage_invalidate_unlocked (unsigned long *slot,unsigned long *vpn,int count,int psize,int ssize) { -unsigned long flags =0 ; -int lock_tlbie = !mmu_has_feature (MMU_FTR_LOCKLESS_TLBIE ); - -if (lock_tlbie) -spin_lock_irqsave (&pSeries_lpar_tlbie_lock, flags); -/* Assuming THP size is 16M */ if (is_supported_hlbkrm (psize,MMU_PAGE_16M ))hugepage_block_invalidate (slot, vpn, count, psize, ssize);else hugepage_bulk_invalidate (slot, vpn, count, psize, ssize); +} -if (lock_tlbie) +static void __pSeries_lpar_hugepage_invalidate (unsigned long *slot, +unsigned long *vpn, +int count,int psize, +int ssize) +{ +unsigned long flags =0 ; + +if (!mmu_has_feature (MMU_FTR_LOCKLESS_TLBIE )) { +spin_lock_irqsave (&pSeries_lpar_tlbie_lock, flags); +__pSeries_lpar_hugepage_invalidate_unlocked (slot, vpn, count, psize, ssize);spin_unlock_irqrestore (&pSeries_lpar_tlbie_lock, flags); +return ; + } + +__pSeries_lpar_hugepage_invalidate_unlocked (slot, vpn, count, psize, ssize); } static void pSeries_lpar_hugepage_invalidate(unsigned long vsid,
Signature · 1 line
2.39.5
Ritesh Harjani (IBM)
reviewerRFC 3/12 powerpc/pseries: Rework hash flush to remove conditional locking
In reply to Ritesh Harjani (IBM)Clang's compiler based static context analysis does not work with locks that are conditionally taken like in pSeries_lpar_flush_hash_range().
This also simplifies the function definition in my opinion - so this is also a win.
No functional change intended.
--- arch/powerpc/platforms/pseries/lpar.c | 31 ++++++++++++++++----------- 1 file changed, 18 insertions(+), 13 deletions(-)
arch/powerpc/platforms/pseries/lpar.c +18 -13
@@ -1526,28 +1526,19 @@ void __init pseries_lpar_read_hblkrm_characteristics(void) bpsize, idx, hblkrm_size[bpsize][idx]); } -/* -* Take a spinlock around flushes to avoid bouncing the hypervisor tlbie -* lock. -*/ -static void pSeries_lpar_flush_hash_range (unsigned long number,int local) +static void pSeries_lpar_flush_hash_range_unlocked (unsigned long number,int local) {unsigned long vpn;unsigned long i, pix, rc; -unsigned long flags =0 ;struct ppc64_tlb_batch *batch =this_cpu_ptr (&ppc64_tlb_batch); -int lock_tlbie = !mmu_has_feature (MMU_FTR_LOCKLESS_TLBIE );unsigned long param[PLPAR_HCALL9_BUFSIZE ];unsigned long index, shift, slot;real_pte_t pte;int psize, ssize; -if (lock_tlbie) -spin_lock_irqsave (&pSeries_lpar_tlbie_lock, flags); -if (is_supported_hlbkrm (batch->psize, batch->psize)) {do_block_remove (number, batch, param); - goto out; +return ; } psize = batch->psize;
@@ -1587,10 +1578,24 @@ static void pSeries_lpar_flush_hash_range(unsigned long number, int local) param[6], param[7]);BUG_ON (rc !=H_SUCCESS ); } +} -out: -if (lock_tlbie) +/* +* Take a spinlock around flushes to avoid bouncing the hypervisor tlbie +* lock. Firmware with MMU_FTR_LOCKLESS_TLBIE does not need it. +*/ +static void pSeries_lpar_flush_hash_range (unsigned long number,int local) +{ +unsigned long flags; + +if (!mmu_has_feature (MMU_FTR_LOCKLESS_TLBIE )) { +spin_lock_irqsave (&pSeries_lpar_tlbie_lock, flags); +pSeries_lpar_flush_hash_range_unlocked (number, local);spin_unlock_irqrestore (&pSeries_lpar_tlbie_lock, flags); +return ; + } + +pSeries_lpar_flush_hash_range_unlocked (number, local); }static int __init disable_bulk_remove (char *str)
Signature · 1 line
2.39.5
Ritesh Harjani (IBM)
reviewerRFC 4/12 powerpc/pseries: Add context annotations for the DTL worker lock
In reply to Ritesh Harjani (IBM)dtl_worker_{enable,disable}() needs annotations since they acquire and release locks. So this adds conditional annotation based on return value.
Let's also disable context analysis for vcpudispatch_stats_write(), since based on received input, it can leave the lock held until a later write of 0 unlocks it. So we need to mark it with __context_unsafe().
Otherwise we get following error on enabling CONTEXT_ANALYSIS on this
file:
lpar.c:490:9: error: rw_semaphore 'dtl_access_lock' is not held on every path through here [-Werror,-Wthread-safety-analysis] lpar.c:498:2: error: releasing rw_semaphore 'dtl_access_lock' that was not held [-Werror,-Wthread-safety-analysis]
--- arch/powerpc/platforms/pseries/lpar.c | 3 +++ 1 file changed, 3 insertions(+)
arch/powerpc/platforms/pseries/lpar.c +3 -0
@@ -461,6 +461,7 @@ static void reset_global_dtl_mask(void) }static int dtl_worker_enable (unsigned long *time_limit) + __cond_acquires(0, &dtl_access_lock) {int rc =0 , state;
@@ -491,6 +492,7 @@ static int dtl_worker_enable(unsigned long *time_limit) }static void dtl_worker_disable (unsigned long *time_limit) + __releases(&dtl_access_lock) {cpuhp_remove_state (dtl_worker_state);free_dtl_buffers (time_limit);
@@ -500,6 +502,7 @@ static void dtl_worker_disable(unsigned long *time_limit)static ssize_t vcpudispatch_stats_write (struct file *file,const char __user *p,size_t count,loff_t *ppos) +__context_unsafe (/* dtl_access_lock is held from enable write until disable write */ ) {unsigned long time_limit = jiffies +HZ ;struct vcpu_dispatch_data *disp;
Signature · 1 line
2.39.5
Ritesh Harjani (IBM)
reviewerRFC 5/12 powerpc/pseries: Annotate the VPD sequence lock context
In reply to Ritesh Harjani (IBM)Clang's context analysis reports:
papr-vpd.c:151:1: error: mutex 'rtas_ibm_get_vpd_lock' is still held at the end of function [-Werror,-Wthread-safety-analysis] papr-vpd.c:165:2: error: releasing mutex 'rtas_ibm_get_vpd_lock' that was not held [-Werror,-Wthread-safety-analysis]
Add the necessary annotations to in vpd_sequence_{begin|end}(), to fix these errors for enabling Clang context analysis.
--- arch/powerpc/platforms/pseries/papr-vpd.c | 3 +++ 1 file changed, 3 insertions(+)
arch/powerpc/platforms/pseries/papr-vpd.c +3 -0
@@ -123,8 +123,10 @@ static int rtas_ibm_get_vpd(struct rtas_ibm_get_vpd_params *params)* @seq: vpd call parameters from sequence struct * * Context: May sleep. +* Returns with rtas_ibm_get_vpd_lock held. vpd_sequence_end() releases it. */ static void vpd_sequence_begin (struct papr_rtas_sequence *seq) + __acquires(&rtas_ibm_get_vpd_lock) {struct rtas_ibm_get_vpd_params *vpd_params;/*
@@ -157,6 +159,7 @@ static void vpd_sequence_begin(struct papr_rtas_sequence *seq)* Releases resources obtained by vpd_sequence_begin(). */ static void vpd_sequence_end (struct papr_rtas_sequence *seq) + __releases(&rtas_ibm_get_vpd_lock) {struct rtas_ibm_get_vpd_params *vpd_params;
Signature · 1 line
2.39.5
Ritesh Harjani (IBM)
reviewerRFC 6/12 powerpc/pseries: Annotate the RTAS indices sequence lock context
In reply to Ritesh Harjani (IBM)Clang's context analysis reports:
papr-indices.c:145:1: error: mutex 'rtas_ibm_get_indices_lock' is still held at the end of function [-Werror,-Wthread-safety-analysis] papr-indices.c:158:2: error: releasing mutex 'rtas_ibm_get_indices_lock' that was not held [-Werror,-Wthread-safety-analysis]
Add the necessary annotations to indices_sequence_{begin|end}(), to fix these errors for enabling Clang context analysis.
--- arch/powerpc/platforms/pseries/papr-indices.c | 3 +++ 1 file changed, 3 insertions(+)
arch/powerpc/platforms/pseries/papr-indices.c +3 -0
@@ -126,8 +126,10 @@ static int rtas_ibm_get_indices(struct rtas_get_indices_params *params)* indices_sequence_begin() - Begin a indices retrieval sequence. * * Context: May sleep. +* Returns with rtas_ibm_get_indices_lock held. indices_sequence_end() releases it. */ static void indices_sequence_begin (struct papr_rtas_sequence *seq) + __acquires(&rtas_ibm_get_indices_lock) {struct rtas_get_indices_params *param;
@@ -150,6 +152,7 @@ static void indices_sequence_begin(struct papr_rtas_sequence *seq)* Releases resources obtained by indices_sequence_begin(). */ static void indices_sequence_end (struct papr_rtas_sequence *seq) + __releases(&rtas_ibm_get_indices_lock) {struct rtas_get_indices_params *param;
Signature · 1 line
2.39.5
Ritesh Harjani (IBM)
reviewerRFC 7/12 powerpc/pseries: Annotate the RTAS physical-attestation sequence lock context
In reply to Ritesh Harjani (IBM)Clang's context analysis reports:
papr-phy-attest.c:154:1: error: mutex 'rtas_ibm_physical_attestation_lock' is still held at the end of function [-Werror,-Wthread-safety-analysis] papr-phy-attest.c:169:2: error: releasing mutex 'rtas_ibm_physical_attestation_lock' that was not held [-Werror,-Wthread-safety-analysis]
Add the necessary annotations to phy_attest_sequence_{begin|end}(), to fix these errors for enabling Clang context analysis.
--- arch/powerpc/platforms/pseries/papr-phy-attest.c | 4 ++++ 1 file changed, 4 insertions(+)
arch/powerpc/platforms/pseries/papr-phy-attest.c +4 -0
@@ -133,8 +133,11 @@ static int rtas_physical_attestation(struct rtas_phy_attest_params *params)* @seq: user specified parameters for RTAS call from seq struct. * * Context: May sleep. +* Returns with rtas_ibm_physical_attestation_lock held. +* phy_attest_sequence_end() releases it. */ static void phy_attest_sequence_begin (struct papr_rtas_sequence *seq) + __acquires(&rtas_ibm_physical_attestation_lock) {struct rtas_phy_attest_params *param;
@@ -161,6 +164,7 @@ static void phy_attest_sequence_begin(struct papr_rtas_sequence *seq)* Releases resources obtained by phy_attest_sequence_begin(). */ static void phy_attest_sequence_end (struct papr_rtas_sequence *seq) + __releases(&rtas_ibm_physical_attestation_lock) {struct rtas_phy_attest_params *param;
Signature · 1 line
2.39.5
Ritesh Harjani (IBM)
reviewerRFC 8/12 powerpc/pseries: Annotate the DTL debugfs read lock context
In reply to Ritesh Harjani (IBM)Clang's context analysis reports:
dtl.c: error: rw_semaphore 'dtl_access_lock' is still held at the end of function [-Werror,-Wthread-safety-analysis] dtl.c: error: releasing rw_semaphore 'dtl_access_lock' that was not held [-Werror,-Wthread-safety-analysis]
Add the necessary annotations to phy_attest_sequence_{begin|end}(), to fix these errors for enabling Clang context analysis.
--- arch/powerpc/platforms/pseries/dtl.c | 8 ++++++++ 1 file changed, 8 insertions(+)
arch/powerpc/platforms/pseries/dtl.c +8 -0
@@ -177,7 +177,12 @@ static u64 dtl_current_index(struct dtl *dtl) }#endif /* CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */ +/* +* On success the read lock stays held until dtl_disable(). That covers +* the whole time the debugfs file is open. +*/ static int dtl_enable (struct dtl *dtl) + __cond_acquires_shared(0, &dtl_access_lock) {long int n_entries;long int rc;
@@ -225,6 +230,7 @@ static int dtl_enable(struct dtl *dtl) }static void dtl_disable (struct dtl *dtl) + __releases_shared(&dtl_access_lock) {spin_lock (&dtl->lock);dtl_stop (dtl);
@@ -238,6 +244,7 @@ static void dtl_disable(struct dtl *dtl)/* file interface */ static int dtl_file_open (struct inode *inode,struct file *filp) + __cond_acquires_shared(0, &dtl_access_lock) {struct dtl *dtl = inode->i_private;int rc;
@@ -251,6 +258,7 @@ static int dtl_file_open(struct inode *inode, struct file *filp) }static int dtl_file_release (struct inode *inode,struct file *filp) + __releases_shared(&dtl_access_lock) {struct dtl *dtl = inode->i_private;dtl_disable (dtl);
Signature · 1 line
2.39.5
Ritesh Harjani (IBM)
reviewerRe: [RFC 08/12] powerpc/pseries: Annotate the DTL debugfs read lock context
Quoted 6 lines · Ritesh Harjani (IBM)
Clang's context analysis reports:
dtl.c: error:rw_semaphore'dtl_access_lock' is still held at the end of function [-Werror,-Wthread-safety-analysis]dtl.c: error: releasingrw_semaphore'dtl_access_lock' that was not held [-Werror,-Wthread-safety-analysis]Add the necessary annotations to phy_attest_sequence_{begin|end}(), to fix these errors for enabling Clang context analysis.
Sashiko pointed out:
"Does this commit message reference the wrong functions here?"
So here is the corrected version:
Add the necessary annotations to dtl_{enable|disable}(), dtl_file{open|release}(), to fix these errors for enabling Clang context analysis.
I will wait for any review comments before revising v2.
-ritesh
Ritesh Harjani (IBM)
reviewerRFC 9/12 powerpc/pseries: Disable context analysis for the CMM hotplug notifier
In reply to Ritesh Harjani (IBM)Clang's context analysis reports:
cmm.c: error: mutex 'hotplug_mutex' is still held at the end of function [-Werror,-Wthread-safety-analysis] cmm.c: error: releasing mutex 'hotplug_mutex' that was not held [-Werror,-Wthread-safety-analysis]
cmm_memory_cb() takes hotplug_mutex on MEM_GOING_OFFLINE and drops it on a later MEM_OFFLINE or MEM_CANCEL_OFFLINE call.
Add __context_unsafe() annotation for cmm_memory_cb() callback to avoid the reported build error in order to enable Clang context analysis.
--- arch/powerpc/platforms/pseries/cmm.c | 1 + 1 file changed, 1 insertion(+)
arch/powerpc/platforms/pseries/cmm.c +1 -0
@@ -470,6 +470,7 @@ static struct notifier_block cmm_reboot_nb = {**/ static int cmm_memory_cb (struct notifier_block *self,unsigned long action,void *arg) +__context_unsafe (/* Conditional locking */ ) {switch (action) {case MEM_GOING_OFFLINE :
Signature · 1 line
2.39.5
Ritesh Harjani (IBM)
reviewerRFC 10/12 powerpc/pseries: Enable context analysis
In reply to Ritesh Harjani (IBM)pseries objects now build with Clang context analysis enabled. Turn it on for the directory.
This checks that each lock taken in this code is dropped on every path.
--- arch/powerpc/platforms/pseries/Makefile | 3 +++ 1 file changed, 3 insertions(+)
arch/powerpc/platforms/pseries/Makefile +3 -0
@@ -1,4 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 + +CONTEXT_ANALYSIS := y + ccflags-$(CONFIG_PPC_PSERIES_DEBUG) += -DDEBUG obj-y := lpar.o hvCall.o nvram.o reconfig.o \
Signature · 1 line
2.39.5
Ritesh Harjani (IBM)
reviewerRFC 11/12 powerpc/powernv: Rework OPAL console write to remove conditional locking
In reply to Ritesh Harjani (IBM)Clang's context analysis reports:
opal.c:454:7: error: spinlock 'opal_write_lock' is not held on every path through here [-Werror,-Wthread-safety-analysis] opal.c:493:3: error: releasing spinlock 'opal_write_lock' that was not held [-Werror,-Wthread-safety-analysis]
This patch rework the OPAL console write function to remove this conditional locking to fix the reported build errors while enabling Clang context analysis. We could have marked __context_unsafe(), but this anyways simplifies the locking a bit.
--- arch/powerpc/platforms/powernv/opal.c | 30 ++++++++++++++++++--------- 1 file changed, 20 insertions(+), 10 deletions(-)
arch/powerpc/platforms/powernv/opal.c +20 -10
@@ -438,19 +438,13 @@ ssize_t opal_get_chars(uint32_t vtermno, u8 *buf, size_t count)return 0 ; } -static ssize_t __opal_put_chars (uint32_t vtermno,const u8 *data, -size_t total_len,bool atomic) +static ssize_t __opal_put_chars_unlocked (uint32_t vtermno,const u8 *data, +size_t total_len,bool atomic) { -unsigned long flags =0 /* shut up gcc */ ;ssize_t written;__be64 olen;s64 rc; -if (!opal.entry) -return -ENODEV ; - -if (atomic) -spin_lock_irqsave (&opal_write_lock, flags); rc =opal_console_write_buffer_space (vtermno, &olen);if (rc ||be64_to_cpu (olen) < total_len) {/* Closed -> drop characters */
@@ -489,10 +483,26 @@ static ssize_t __opal_put_chars(uint32_t vtermno, const u8 *data, } out: -if (atomic) +return written; +} + +static ssize_t __opal_put_chars (uint32_t vtermno,const u8 *data, +size_t total_len,bool atomic) +{ +unsigned long flags =0 ; +ssize_t written; + +if (!opal.entry) +return -ENODEV ; + +if (atomic) { +spin_lock_irqsave (&opal_write_lock, flags); + written =__opal_put_chars_unlocked (vtermno, data, total_len, true);spin_unlock_irqrestore (&opal_write_lock, flags); +return written; + } -return written; +return __opal_put_chars_unlocked (vtermno, data, total_len, false); }ssize_t opal_put_chars (uint32_t vtermno,const u8 *data,size_t total_len)
Signature · 1 line
2.39.5
Ritesh Harjani (IBM)
reviewerRFC 12/12 powerpc/powernv: Enable context analysis
In reply to Ritesh Harjani (IBM)powernv objects now build with Clang context analysis enabled. Turn it on for the directory.
This checks that each lock taken in this code is dropped on every path.
--- arch/powerpc/platforms/powernv/Makefile | 2 ++ 1 file changed, 2 insertions(+)
arch/powerpc/platforms/powernv/Makefile +2 -0
@@ -1,5 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 +CONTEXT_ANALYSIS := y + # nothing that deals with real mode is safe to KASAN # in particular, idle code runs a bunch of things in real mode KASAN_SANITIZE_idle.o := n
Signature · 1 line
2.39.5