* [PATCH v6 0/3] asm-generic/io.h: Silence -Wnull-pointer-arithmetic warning on PCI_IOBASE @ 2021-05-10 14:52 ` Niklas Schnelle 0 siblings, 0 replies; 8+ messages in thread From: Niklas Schnelle @ 2021-05-10 14:52 UTC (permalink / raw) To: Arnd Bergmann, Vineet Gupta, David S. Miller Cc: Nathan Chancellor, Nick Desaulniers, clang-built-linux, linux-arch, linux-kernel, linux-s390, linux-snps-arc, sparclinux Hi, This is version 6 of my attempt to get rid of a clang -Wnull-pointer-arithmetic warning for the use of PCI_IOBASE in asm-generic/io.h and fix the NULL pointer access it points out. This was originally found on s390 but should apply to all platforms leaving PCI_IOBASE undefined while making use of the inb() and friends helpers from asm-generic/io.h. This applies cleanly and was compile tested on top of v5.12 for the previously broken ARC, nds32, h8300 and risc-v architecture. It also applies cleanly on v5.13-rc1 for which I boot tested it on s390. I did boot test this only on x86_64 and s390x the former implements inb() et al itself while the latter would emit a WARN_ONCE() but no drivers use inb(). Thanks, Niklas Changes sinve v5: - memset() the buffer in insb()/insw()/insl() in the WARN_ONCE() case to prevent use of uninitialized data (Arnd) Changes since v4: - Added Link to patch 4 (Arnd) - Improved comment on RISC-V patch mentioning current brokeness (Arnd) Changes since v3: - Changed the subject of the last patch to better reflect the actual change i.e. the addition of WARN_ONCE() to the helpers not the silencing of the clang warning - Added asm/bug.h to asm-generic/io.h so it doesn't have to be included previously by all arches to be available for the WARN_ONCE() - Added patch for risc-v which defines PCI_IOBASE except when compiled for nommu Changes since v2: - Improved comment for SPARC PCI_IOBASE definition as suggested by David Laight - Added a patch for ARC which is missing the asm/bug.h include for WARN_ONCE() (kernel test robot) - Added ifdefs to ioport_map() and __pci_ioport_map() since apparently at least test configs enable CONFIG_HAS_IOPORT_MAP even on architectures which leave PCI_IOBASE unset (kernel test robot for nds32 and ARC). Changes since v1: - Added patch to explicitly set PCI_IOBASE to 0 on sparc as suggested by Arnd Bergmann - Instead of working around the warning with a uintptr_t PCI_IOBASE make inb() and friends explicitly WARN_ONCE() and return 0xff... (Arnd Bergmann) Niklas Schnelle (3): sparc: explicitly set PCI_IOBASE to 0 risc-v: Use generic io.h helpers for nommu asm-generic/io.h: warn in inb() and friends with undefined PCI_IOBASE arch/riscv/include/asm/io.h | 5 +-- arch/sparc/include/asm/io.h | 8 +++++ include/asm-generic/io.h | 68 ++++++++++++++++++++++++++++++++++--- 3 files changed, 75 insertions(+), 6 deletions(-) -- 2.25.1 ^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v6 0/3] asm-generic/io.h: Silence -Wnull-pointer-arithmetic warning on PCI_IOBASE @ 2021-05-10 14:52 ` Niklas Schnelle 0 siblings, 0 replies; 8+ messages in thread From: Niklas Schnelle @ 2021-05-10 14:52 UTC (permalink / raw) To: Arnd Bergmann, Vineet Gupta, David S. Miller Cc: Nathan Chancellor, Nick Desaulniers, clang-built-linux, linux-arch, linux-kernel, linux-s390, linux-snps-arc, sparclinux Hi, This is version 6 of my attempt to get rid of a clang -Wnull-pointer-arithmetic warning for the use of PCI_IOBASE in asm-generic/io.h and fix the NULL pointer access it points out. This was originally found on s390 but should apply to all platforms leaving PCI_IOBASE undefined while making use of the inb() and friends helpers from asm-generic/io.h. This applies cleanly and was compile tested on top of v5.12 for the previously broken ARC, nds32, h8300 and risc-v architecture. It also applies cleanly on v5.13-rc1 for which I boot tested it on s390. I did boot test this only on x86_64 and s390x the former implements inb() et al itself while the latter would emit a WARN_ONCE() but no drivers use inb(). Thanks, Niklas Changes sinve v5: - memset() the buffer in insb()/insw()/insl() in the WARN_ONCE() case to prevent use of uninitialized data (Arnd) Changes since v4: - Added Link to patch 4 (Arnd) - Improved comment on RISC-V patch mentioning current brokeness (Arnd) Changes since v3: - Changed the subject of the last patch to better reflect the actual change i.e. the addition of WARN_ONCE() to the helpers not the silencing of the clang warning - Added asm/bug.h to asm-generic/io.h so it doesn't have to be included previously by all arches to be available for the WARN_ONCE() - Added patch for risc-v which defines PCI_IOBASE except when compiled for nommu Changes since v2: - Improved comment for SPARC PCI_IOBASE definition as suggested by David Laight - Added a patch for ARC which is missing the asm/bug.h include for WARN_ONCE() (kernel test robot) - Added ifdefs to ioport_map() and __pci_ioport_map() since apparently at least test configs enable CONFIG_HAS_IOPORT_MAP even on architectures which leave PCI_IOBASE unset (kernel test robot for nds32 and ARC). Changes since v1: - Added patch to explicitly set PCI_IOBASE to 0 on sparc as suggested by Arnd Bergmann - Instead of working around the warning with a uintptr_t PCI_IOBASE make inb() and friends explicitly WARN_ONCE() and return 0xff... (Arnd Bergmann) Niklas Schnelle (3): sparc: explicitly set PCI_IOBASE to 0 risc-v: Use generic io.h helpers for nommu asm-generic/io.h: warn in inb() and friends with undefined PCI_IOBASE arch/riscv/include/asm/io.h | 5 +-- arch/sparc/include/asm/io.h | 8 +++++ include/asm-generic/io.h | 68 ++++++++++++++++++++++++++++++++++--- 3 files changed, 75 insertions(+), 6 deletions(-) -- 2.25.1 _______________________________________________ linux-snps-arc mailing list linux-snps-arc@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-snps-arc ^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v6 1/3] sparc: explicitly set PCI_IOBASE to 0 2021-05-10 14:52 ` Niklas Schnelle @ 2021-05-10 14:52 ` Niklas Schnelle -1 siblings, 0 replies; 8+ messages in thread From: Niklas Schnelle @ 2021-05-10 14:52 UTC (permalink / raw) To: Arnd Bergmann, Vineet Gupta, David S. Miller Cc: Nathan Chancellor, Nick Desaulniers, clang-built-linux, linux-arch, linux-kernel, linux-s390, linux-snps-arc, sparclinux Instead of relying on the fallback in asm-generic/io.h which sets PCI_IOBASE 0 if it is not defined set it explicitly. Link: https://lore.kernel.org/lkml/CAK8P3a3PK9zyeP4ymELtc2ZYnymECoACiigw9Za+pvSJpCk5=g@mail.gmail.com/ Signed-off-by: Niklas Schnelle <schnelle@linux.ibm.com> --- arch/sparc/include/asm/io.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/sparc/include/asm/io.h b/arch/sparc/include/asm/io.h index 2eefa526b38f..c019e50702c1 100644 --- a/arch/sparc/include/asm/io.h +++ b/arch/sparc/include/asm/io.h @@ -1,6 +1,14 @@ /* SPDX-License-Identifier: GPL-2.0 */ #ifndef ___ASM_SPARC_IO_H #define ___ASM_SPARC_IO_H + +/* + * On LEON PCI addresses below 64k are converted to IO accesses. + * io_remap_xxx() returns a kernel virtual address in the PCI window so + * inb() doesn't need to add an offset. + */ +#define PCI_IOBASE ((void __iomem *)0) + #if defined(__sparc__) && defined(__arch64__) #include <asm/io_64.h> #else -- 2.25.1 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v6 1/3] sparc: explicitly set PCI_IOBASE to 0 @ 2021-05-10 14:52 ` Niklas Schnelle 0 siblings, 0 replies; 8+ messages in thread From: Niklas Schnelle @ 2021-05-10 14:52 UTC (permalink / raw) To: Arnd Bergmann, Vineet Gupta, David S. Miller Cc: Nathan Chancellor, Nick Desaulniers, clang-built-linux, linux-arch, linux-kernel, linux-s390, linux-snps-arc, sparclinux Instead of relying on the fallback in asm-generic/io.h which sets PCI_IOBASE 0 if it is not defined set it explicitly. Link: https://lore.kernel.org/lkml/CAK8P3a3PK9zyeP4ymELtc2ZYnymECoACiigw9Za+pvSJpCk5=g@mail.gmail.com/ Signed-off-by: Niklas Schnelle <schnelle@linux.ibm.com> --- arch/sparc/include/asm/io.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/sparc/include/asm/io.h b/arch/sparc/include/asm/io.h index 2eefa526b38f..c019e50702c1 100644 --- a/arch/sparc/include/asm/io.h +++ b/arch/sparc/include/asm/io.h @@ -1,6 +1,14 @@ /* SPDX-License-Identifier: GPL-2.0 */ #ifndef ___ASM_SPARC_IO_H #define ___ASM_SPARC_IO_H + +/* + * On LEON PCI addresses below 64k are converted to IO accesses. + * io_remap_xxx() returns a kernel virtual address in the PCI window so + * inb() doesn't need to add an offset. + */ +#define PCI_IOBASE ((void __iomem *)0) + #if defined(__sparc__) && defined(__arch64__) #include <asm/io_64.h> #else -- 2.25.1 _______________________________________________ linux-snps-arc mailing list linux-snps-arc@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-snps-arc ^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v6 2/3] risc-v: Use generic io.h helpers for nommu 2021-05-10 14:52 ` Niklas Schnelle @ 2021-05-10 14:52 ` Niklas Schnelle -1 siblings, 0 replies; 8+ messages in thread From: Niklas Schnelle @ 2021-05-10 14:52 UTC (permalink / raw) To: Arnd Bergmann, Vineet Gupta, David S. Miller Cc: Nathan Chancellor, Nick Desaulniers, clang-built-linux, linux-arch, linux-kernel, linux-s390, linux-snps-arc, sparclinux From: Niklas Schnelle <niklas@komani.de> Without MMU support PCI_IOBASE is left undefined because PCI_IO_END is VMEMMAP_START. Nevertheless the in*()/out*() helper macros are left defined with uses of PCI_IOBASE. At the moment this only compiles because asm-generic/io.h defines PCI_IOBASE as 0 if it is undefined and so at macro expansion PCI_IOBASE is defined. This leads to compilation errors when asm-generic/io.h is changed to leave PCI_IOBASE undefined. More importantly it is currently broken at runtime, as accessing a fixed I/O port number of an ISA device on NOMMU RISC-V would turn into a NULL pointer dereference. Instead only define the in*()/out*() helper macros with MMU support and fall back to the asm-generic/io.h helper stubs otherwise. Signed-off-by: Niklas Schnelle <niklas@komani.de> --- arch/riscv/include/asm/io.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/riscv/include/asm/io.h b/arch/riscv/include/asm/io.h index c025a746a148..31a8b98c0f13 100644 --- a/arch/riscv/include/asm/io.h +++ b/arch/riscv/include/asm/io.h @@ -23,12 +23,12 @@ #include <asm/mmio.h> /* - * I/O port access constants. + * I/O port access constants. Without MMU support leave PCI_IOBASE undefined + * and fall back to generic stubs for I/O access routines. */ #ifdef CONFIG_MMU #define IO_SPACE_LIMIT (PCI_IO_SIZE - 1) #define PCI_IOBASE ((void __iomem *)PCI_IO_START) -#endif /* CONFIG_MMU */ /* * Emulation routines for the port-mapped IO space used by some PCI drivers. @@ -145,6 +145,7 @@ __io_writes_outs(writes, u64, q, __io_bw(), __io_aw()) __io_writes_outs(outs, u64, q, __io_pbr(), __io_paw()) #define outsq(addr, buffer, count) __outsq((void __iomem *)addr, buffer, count) #endif +#endif /* CONFIG_MMU */ #include <asm-generic/io.h> -- 2.25.1 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v6 2/3] risc-v: Use generic io.h helpers for nommu @ 2021-05-10 14:52 ` Niklas Schnelle 0 siblings, 0 replies; 8+ messages in thread From: Niklas Schnelle @ 2021-05-10 14:52 UTC (permalink / raw) To: Arnd Bergmann, Vineet Gupta, David S. Miller Cc: Nathan Chancellor, Nick Desaulniers, clang-built-linux, linux-arch, linux-kernel, linux-s390, linux-snps-arc, sparclinux From: Niklas Schnelle <niklas@komani.de> Without MMU support PCI_IOBASE is left undefined because PCI_IO_END is VMEMMAP_START. Nevertheless the in*()/out*() helper macros are left defined with uses of PCI_IOBASE. At the moment this only compiles because asm-generic/io.h defines PCI_IOBASE as 0 if it is undefined and so at macro expansion PCI_IOBASE is defined. This leads to compilation errors when asm-generic/io.h is changed to leave PCI_IOBASE undefined. More importantly it is currently broken at runtime, as accessing a fixed I/O port number of an ISA device on NOMMU RISC-V would turn into a NULL pointer dereference. Instead only define the in*()/out*() helper macros with MMU support and fall back to the asm-generic/io.h helper stubs otherwise. Signed-off-by: Niklas Schnelle <niklas@komani.de> --- arch/riscv/include/asm/io.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/riscv/include/asm/io.h b/arch/riscv/include/asm/io.h index c025a746a148..31a8b98c0f13 100644 --- a/arch/riscv/include/asm/io.h +++ b/arch/riscv/include/asm/io.h @@ -23,12 +23,12 @@ #include <asm/mmio.h> /* - * I/O port access constants. + * I/O port access constants. Without MMU support leave PCI_IOBASE undefined + * and fall back to generic stubs for I/O access routines. */ #ifdef CONFIG_MMU #define IO_SPACE_LIMIT (PCI_IO_SIZE - 1) #define PCI_IOBASE ((void __iomem *)PCI_IO_START) -#endif /* CONFIG_MMU */ /* * Emulation routines for the port-mapped IO space used by some PCI drivers. @@ -145,6 +145,7 @@ __io_writes_outs(writes, u64, q, __io_bw(), __io_aw()) __io_writes_outs(outs, u64, q, __io_pbr(), __io_paw()) #define outsq(addr, buffer, count) __outsq((void __iomem *)addr, buffer, count) #endif +#endif /* CONFIG_MMU */ #include <asm-generic/io.h> -- 2.25.1 _______________________________________________ linux-snps-arc mailing list linux-snps-arc@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-snps-arc ^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v6 3/3] asm-generic/io.h: warn in inb() and friends with undefined PCI_IOBASE 2021-05-10 14:52 ` Niklas Schnelle @ 2021-05-10 14:52 ` Niklas Schnelle -1 siblings, 0 replies; 8+ messages in thread From: Niklas Schnelle @ 2021-05-10 14:52 UTC (permalink / raw) To: Arnd Bergmann, Vineet Gupta, David S. Miller Cc: Nathan Chancellor, Nick Desaulniers, clang-built-linux, linux-arch, linux-kernel, linux-s390, linux-snps-arc, sparclinux When PCI_IOBASE is not defined, it is set to 0 such that it is ignored in calls to the readX/writeX primitives. This triggers clang's -Wnull-pointer-arithmetic warning and will result in illegal accesses on platforms that do not support I/O ports. Make things explicit and silence the warning by letting inb() and friends fail with WARN_ONCE() and a 0xff... return in case PCI_IOBASE is not defined. Link: https://lore.kernel.org/lkml/20210421111759.2059976-1-schnelle@linux.ibm.com/ Signed-off-by: Niklas Schnelle <schnelle@linux.ibm.com> --- v5 -> v6: - Added memset to insb()/insw()/insl() in WARN_ONCE() case to prevent access to uninitalized memory v4 -> v5: - Added Link to commit message (Arnd) v3 -> v4: - Changed the subject to better reflect the actual change - Added asm/bug.h so WARN_ONCE() is always available v2 -> v3: - Added ifdefs to ioport_map() and __pci_ioport_map() since apparently at least test configs enable CONFIG_HAS_IOPORT_MAP even on architectures which leave PCI_IOBASE unset (kernel test robot for nds32 and ARC). v1 -> v2: - Instead of working around the warning with a uintptr_t PCI_IOBASE make inb() and friends explicitly WARN_ONCE() and return 0xff... (Arnd) include/asm-generic/io.h | 68 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 64 insertions(+), 4 deletions(-) diff --git a/include/asm-generic/io.h b/include/asm-generic/io.h index e93375c710b9..4a3af97a832d 100644 --- a/include/asm-generic/io.h +++ b/include/asm-generic/io.h @@ -8,6 +8,7 @@ #define __ASM_GENERIC_IO_H #include <asm/page.h> /* I/O is all done through memory accesses */ +#include <linux/bug.h> #include <linux/string.h> /* for memset() and memcpy() */ #include <linux/types.h> @@ -440,10 +441,6 @@ static inline void writesq(volatile void __iomem *addr, const void *buffer, #endif #endif /* CONFIG_64BIT */ -#ifndef PCI_IOBASE -#define PCI_IOBASE ((void __iomem *)0) -#endif - #ifndef IO_SPACE_LIMIT #define IO_SPACE_LIMIT 0xffff #endif @@ -458,12 +455,17 @@ static inline void writesq(volatile void __iomem *addr, const void *buffer, #define _inb _inb static inline u8 _inb(unsigned long addr) { +#ifdef PCI_IOBASE u8 val; __io_pbr(); val = __raw_readb(PCI_IOBASE + addr); __io_par(val); return val; +#else + WARN_ONCE(1, "No I/O port support\n"); + return ~0; +#endif } #endif @@ -471,12 +473,17 @@ static inline u8 _inb(unsigned long addr) #define _inw _inw static inline u16 _inw(unsigned long addr) { +#ifdef PCI_IOBASE u16 val; __io_pbr(); val = __le16_to_cpu((__le16 __force)__raw_readw(PCI_IOBASE + addr)); __io_par(val); return val; +#else + WARN_ONCE(1, "No I/O port support\n"); + return ~0; +#endif } #endif @@ -484,12 +491,17 @@ static inline u16 _inw(unsigned long addr) #define _inl _inl static inline u32 _inl(unsigned long addr) { +#ifdef PCI_IOBASE u32 val; __io_pbr(); val = __le32_to_cpu((__le32 __force)__raw_readl(PCI_IOBASE + addr)); __io_par(val); return val; +#else + WARN_ONCE(1, "No I/O port support\n"); + return ~0; +#endif } #endif @@ -497,9 +509,13 @@ static inline u32 _inl(unsigned long addr) #define _outb _outb static inline void _outb(u8 value, unsigned long addr) { +#ifdef PCI_IOBASE __io_pbw(); __raw_writeb(value, PCI_IOBASE + addr); __io_paw(); +#else + WARN_ONCE(1, "No I/O port support\n"); +#endif } #endif @@ -507,9 +523,13 @@ static inline void _outb(u8 value, unsigned long addr) #define _outw _outw static inline void _outw(u16 value, unsigned long addr) { +#ifdef PCI_IOBASE __io_pbw(); __raw_writew((u16 __force)cpu_to_le16(value), PCI_IOBASE + addr); __io_paw(); +#else + WARN_ONCE(1, "No I/O port support\n"); +#endif } #endif @@ -517,9 +537,13 @@ static inline void _outw(u16 value, unsigned long addr) #define _outl _outl static inline void _outl(u32 value, unsigned long addr) { +#ifdef PCI_IOBASE __io_pbw(); __raw_writel((u32 __force)cpu_to_le32(value), PCI_IOBASE + addr); __io_paw(); +#else + WARN_ONCE(1, "No I/O port support\n"); +#endif } #endif @@ -606,7 +630,12 @@ static inline void outl_p(u32 value, unsigned long addr) #define insb insb static inline void insb(unsigned long addr, void *buffer, unsigned int count) { +#ifdef PCI_IOBASE readsb(PCI_IOBASE + addr, buffer, count); +#else + memset(buffer, 0xff, count); + WARN_ONCE(1, "No I/O port support\n"); +#endif } #endif @@ -614,7 +643,12 @@ static inline void insb(unsigned long addr, void *buffer, unsigned int count) #define insw insw static inline void insw(unsigned long addr, void *buffer, unsigned int count) { +#ifdef PCI_IOBASE readsw(PCI_IOBASE + addr, buffer, count); +#else + memset(buffer, 0xff, count); + WARN_ONCE(1, "No I/O port support\n"); +#endif } #endif @@ -622,7 +656,12 @@ static inline void insw(unsigned long addr, void *buffer, unsigned int count) #define insl insl static inline void insl(unsigned long addr, void *buffer, unsigned int count) { +#ifdef PCI_IOBASE readsl(PCI_IOBASE + addr, buffer, count); +#else + memset(buffer, 0xff, count); + WARN_ONCE(1, "No I/O port support\n"); +#endif } #endif @@ -631,7 +670,11 @@ static inline void insl(unsigned long addr, void *buffer, unsigned int count) static inline void outsb(unsigned long addr, const void *buffer, unsigned int count) { +#ifdef PCI_IOBASE writesb(PCI_IOBASE + addr, buffer, count); +#else + WARN_ONCE(1, "No I/O port support\n"); +#endif } #endif @@ -640,7 +683,11 @@ static inline void outsb(unsigned long addr, const void *buffer, static inline void outsw(unsigned long addr, const void *buffer, unsigned int count) { +#ifdef PCI_IOBASE writesw(PCI_IOBASE + addr, buffer, count); +#else + WARN_ONCE(1, "No I/O port support\n"); +#endif } #endif @@ -649,7 +696,11 @@ static inline void outsw(unsigned long addr, const void *buffer, static inline void outsl(unsigned long addr, const void *buffer, unsigned int count) { +#ifdef PCI_IOBASE writesl(PCI_IOBASE + addr, buffer, count); +#else + WARN_ONCE(1, "No I/O port support\n"); +#endif } #endif @@ -1020,18 +1071,27 @@ static inline void __iomem *ioremap_np(phys_addr_t offset, size_t size) #define ioport_map ioport_map static inline void __iomem *ioport_map(unsigned long port, unsigned int nr) { +#ifdef PCI_IOBASE port &= IO_SPACE_LIMIT; return (port > MMIO_UPPER_LIMIT) ? NULL : PCI_IOBASE + port; +#else + WARN_ONCE(1, "No I/O port support\n"); + return NULL; +#endif } #define __pci_ioport_unmap __pci_ioport_unmap static inline void __pci_ioport_unmap(void __iomem *p) { +#ifdef PCI_IOBASE uintptr_t start = (uintptr_t) PCI_IOBASE; uintptr_t addr = (uintptr_t) p; if (addr >= start && addr < start + IO_SPACE_LIMIT) return; iounmap(p); +#else + WARN_ONCE(1, "No I/O port support\n"); +#endif } #endif -- 2.25.1 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v6 3/3] asm-generic/io.h: warn in inb() and friends with undefined PCI_IOBASE @ 2021-05-10 14:52 ` Niklas Schnelle 0 siblings, 0 replies; 8+ messages in thread From: Niklas Schnelle @ 2021-05-10 14:52 UTC (permalink / raw) To: Arnd Bergmann, Vineet Gupta, David S. Miller Cc: Nathan Chancellor, Nick Desaulniers, clang-built-linux, linux-arch, linux-kernel, linux-s390, linux-snps-arc, sparclinux When PCI_IOBASE is not defined, it is set to 0 such that it is ignored in calls to the readX/writeX primitives. This triggers clang's -Wnull-pointer-arithmetic warning and will result in illegal accesses on platforms that do not support I/O ports. Make things explicit and silence the warning by letting inb() and friends fail with WARN_ONCE() and a 0xff... return in case PCI_IOBASE is not defined. Link: https://lore.kernel.org/lkml/20210421111759.2059976-1-schnelle@linux.ibm.com/ Signed-off-by: Niklas Schnelle <schnelle@linux.ibm.com> --- v5 -> v6: - Added memset to insb()/insw()/insl() in WARN_ONCE() case to prevent access to uninitalized memory v4 -> v5: - Added Link to commit message (Arnd) v3 -> v4: - Changed the subject to better reflect the actual change - Added asm/bug.h so WARN_ONCE() is always available v2 -> v3: - Added ifdefs to ioport_map() and __pci_ioport_map() since apparently at least test configs enable CONFIG_HAS_IOPORT_MAP even on architectures which leave PCI_IOBASE unset (kernel test robot for nds32 and ARC). v1 -> v2: - Instead of working around the warning with a uintptr_t PCI_IOBASE make inb() and friends explicitly WARN_ONCE() and return 0xff... (Arnd) include/asm-generic/io.h | 68 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 64 insertions(+), 4 deletions(-) diff --git a/include/asm-generic/io.h b/include/asm-generic/io.h index e93375c710b9..4a3af97a832d 100644 --- a/include/asm-generic/io.h +++ b/include/asm-generic/io.h @@ -8,6 +8,7 @@ #define __ASM_GENERIC_IO_H #include <asm/page.h> /* I/O is all done through memory accesses */ +#include <linux/bug.h> #include <linux/string.h> /* for memset() and memcpy() */ #include <linux/types.h> @@ -440,10 +441,6 @@ static inline void writesq(volatile void __iomem *addr, const void *buffer, #endif #endif /* CONFIG_64BIT */ -#ifndef PCI_IOBASE -#define PCI_IOBASE ((void __iomem *)0) -#endif - #ifndef IO_SPACE_LIMIT #define IO_SPACE_LIMIT 0xffff #endif @@ -458,12 +455,17 @@ static inline void writesq(volatile void __iomem *addr, const void *buffer, #define _inb _inb static inline u8 _inb(unsigned long addr) { +#ifdef PCI_IOBASE u8 val; __io_pbr(); val = __raw_readb(PCI_IOBASE + addr); __io_par(val); return val; +#else + WARN_ONCE(1, "No I/O port support\n"); + return ~0; +#endif } #endif @@ -471,12 +473,17 @@ static inline u8 _inb(unsigned long addr) #define _inw _inw static inline u16 _inw(unsigned long addr) { +#ifdef PCI_IOBASE u16 val; __io_pbr(); val = __le16_to_cpu((__le16 __force)__raw_readw(PCI_IOBASE + addr)); __io_par(val); return val; +#else + WARN_ONCE(1, "No I/O port support\n"); + return ~0; +#endif } #endif @@ -484,12 +491,17 @@ static inline u16 _inw(unsigned long addr) #define _inl _inl static inline u32 _inl(unsigned long addr) { +#ifdef PCI_IOBASE u32 val; __io_pbr(); val = __le32_to_cpu((__le32 __force)__raw_readl(PCI_IOBASE + addr)); __io_par(val); return val; +#else + WARN_ONCE(1, "No I/O port support\n"); + return ~0; +#endif } #endif @@ -497,9 +509,13 @@ static inline u32 _inl(unsigned long addr) #define _outb _outb static inline void _outb(u8 value, unsigned long addr) { +#ifdef PCI_IOBASE __io_pbw(); __raw_writeb(value, PCI_IOBASE + addr); __io_paw(); +#else + WARN_ONCE(1, "No I/O port support\n"); +#endif } #endif @@ -507,9 +523,13 @@ static inline void _outb(u8 value, unsigned long addr) #define _outw _outw static inline void _outw(u16 value, unsigned long addr) { +#ifdef PCI_IOBASE __io_pbw(); __raw_writew((u16 __force)cpu_to_le16(value), PCI_IOBASE + addr); __io_paw(); +#else + WARN_ONCE(1, "No I/O port support\n"); +#endif } #endif @@ -517,9 +537,13 @@ static inline void _outw(u16 value, unsigned long addr) #define _outl _outl static inline void _outl(u32 value, unsigned long addr) { +#ifdef PCI_IOBASE __io_pbw(); __raw_writel((u32 __force)cpu_to_le32(value), PCI_IOBASE + addr); __io_paw(); +#else + WARN_ONCE(1, "No I/O port support\n"); +#endif } #endif @@ -606,7 +630,12 @@ static inline void outl_p(u32 value, unsigned long addr) #define insb insb static inline void insb(unsigned long addr, void *buffer, unsigned int count) { +#ifdef PCI_IOBASE readsb(PCI_IOBASE + addr, buffer, count); +#else + memset(buffer, 0xff, count); + WARN_ONCE(1, "No I/O port support\n"); +#endif } #endif @@ -614,7 +643,12 @@ static inline void insb(unsigned long addr, void *buffer, unsigned int count) #define insw insw static inline void insw(unsigned long addr, void *buffer, unsigned int count) { +#ifdef PCI_IOBASE readsw(PCI_IOBASE + addr, buffer, count); +#else + memset(buffer, 0xff, count); + WARN_ONCE(1, "No I/O port support\n"); +#endif } #endif @@ -622,7 +656,12 @@ static inline void insw(unsigned long addr, void *buffer, unsigned int count) #define insl insl static inline void insl(unsigned long addr, void *buffer, unsigned int count) { +#ifdef PCI_IOBASE readsl(PCI_IOBASE + addr, buffer, count); +#else + memset(buffer, 0xff, count); + WARN_ONCE(1, "No I/O port support\n"); +#endif } #endif @@ -631,7 +670,11 @@ static inline void insl(unsigned long addr, void *buffer, unsigned int count) static inline void outsb(unsigned long addr, const void *buffer, unsigned int count) { +#ifdef PCI_IOBASE writesb(PCI_IOBASE + addr, buffer, count); +#else + WARN_ONCE(1, "No I/O port support\n"); +#endif } #endif @@ -640,7 +683,11 @@ static inline void outsb(unsigned long addr, const void *buffer, static inline void outsw(unsigned long addr, const void *buffer, unsigned int count) { +#ifdef PCI_IOBASE writesw(PCI_IOBASE + addr, buffer, count); +#else + WARN_ONCE(1, "No I/O port support\n"); +#endif } #endif @@ -649,7 +696,11 @@ static inline void outsw(unsigned long addr, const void *buffer, static inline void outsl(unsigned long addr, const void *buffer, unsigned int count) { +#ifdef PCI_IOBASE writesl(PCI_IOBASE + addr, buffer, count); +#else + WARN_ONCE(1, "No I/O port support\n"); +#endif } #endif @@ -1020,18 +1071,27 @@ static inline void __iomem *ioremap_np(phys_addr_t offset, size_t size) #define ioport_map ioport_map static inline void __iomem *ioport_map(unsigned long port, unsigned int nr) { +#ifdef PCI_IOBASE port &= IO_SPACE_LIMIT; return (port > MMIO_UPPER_LIMIT) ? NULL : PCI_IOBASE + port; +#else + WARN_ONCE(1, "No I/O port support\n"); + return NULL; +#endif } #define __pci_ioport_unmap __pci_ioport_unmap static inline void __pci_ioport_unmap(void __iomem *p) { +#ifdef PCI_IOBASE uintptr_t start = (uintptr_t) PCI_IOBASE; uintptr_t addr = (uintptr_t) p; if (addr >= start && addr < start + IO_SPACE_LIMIT) return; iounmap(p); +#else + WARN_ONCE(1, "No I/O port support\n"); +#endif } #endif -- 2.25.1 _______________________________________________ linux-snps-arc mailing list linux-snps-arc@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-snps-arc ^ permalink raw reply related [flat|nested] 8+ messages in thread
end of thread, other threads:[~2021-05-10 14:55 UTC | newest] Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2021-05-10 14:52 [PATCH v6 0/3] asm-generic/io.h: Silence -Wnull-pointer-arithmetic warning on PCI_IOBASE Niklas Schnelle 2021-05-10 14:52 ` Niklas Schnelle 2021-05-10 14:52 ` [PATCH v6 1/3] sparc: explicitly set PCI_IOBASE to 0 Niklas Schnelle 2021-05-10 14:52 ` Niklas Schnelle 2021-05-10 14:52 ` [PATCH v6 2/3] risc-v: Use generic io.h helpers for nommu Niklas Schnelle 2021-05-10 14:52 ` Niklas Schnelle 2021-05-10 14:52 ` [PATCH v6 3/3] asm-generic/io.h: warn in inb() and friends with undefined PCI_IOBASE Niklas Schnelle 2021-05-10 14:52 ` Niklas Schnelle
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.