Skip to content

Commit

Permalink
powerpc: drop port I/O helpers for CONFIG_HAS_IOPORT=n
Browse files Browse the repository at this point in the history
Calling inb()/outb() on powerpc when CONFIG_PCI is disabled causes
a NULL pointer dereference, which is bad for a number of reasons.

After my patch to turn on -Werror in linux-next, this caused a
compiler-time warning with clang:

In file included from arch/powerpc/include/asm/io.h:672:
arch/powerpc/include/asm/io-defs.h:43:1: error: performing pointer
arithmetic on a null pointer has undefined behavior
[-Werror,-Wnull-pointer-arithmetic]
   43 | DEF_PCI_AC_NORET(insb, (unsigned long p, void *b, unsigned long c),
      | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   44 |                  (p, b, c), pio, p)
      |                  ~~~~~~~~~~~~~~~~~~

In this configuration, CONFIG_HAS_IOPORT is already disabled, and all
drivers that use inb()/outb() should now depend on that (some patches are
still in the process of getting marged).

Hide all references to inb()/outb() in the powerpc code and the definitions
when HAS_IOPORT is disabled to remove the possible NULL pointer access.
The same should happin in asm-generic in the near future, but for now
the empty inb() macros are still defined to ensure the generic version
does not get pulled in.

Signed-off-by: Arnd Bergmann <[email protected]>
Reported-by: Naresh Kamboju <[email protected]>
Closes: https://lore.kernel.org/all/CA+G9fYtEh8zmq8k8wE-8RZwW-Qr927RLTn+KqGnq1F=ptaaNsA@mail.gmail.com
Signed-off-by: Michael Ellerman <[email protected]>
Link: https://msgid.link/[email protected]
  • Loading branch information
arndb authored and mpe committed Apr 18, 2024
1 parent 1edb154 commit 3cfdbc2
Show file tree
Hide file tree
Showing 5 changed files with 32 additions and 9 deletions.
12 changes: 8 additions & 4 deletions arch/powerpc/include/asm/dma.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@
#define _ASM_POWERPC_DMA_H
#ifdef __KERNEL__

/* The maximum address that we can perform a DMA transfer to on this platform */
/* Doesn't really apply... */
#define MAX_DMA_ADDRESS (~0UL)

#ifdef CONFIG_HAS_IOPORT

/*
* Defines for using and allocating dma channels.
* Written by Hennus Bergman, 1992.
Expand All @@ -26,10 +32,6 @@
#define MAX_DMA_CHANNELS 8
#endif

/* The maximum address that we can perform a DMA transfer to on this platform */
/* Doesn't really apply... */
#define MAX_DMA_ADDRESS (~0UL)

#ifdef HAVE_REALLY_SLOW_DMA_CONTROLLER
#define dma_outb outb_p
#else
Expand Down Expand Up @@ -340,5 +342,7 @@ extern int request_dma(unsigned int dmanr, const char *device_id);
/* release it again */
extern void free_dma(unsigned int dmanr);

#endif

#endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_DMA_H */
4 changes: 4 additions & 0 deletions arch/powerpc/include/asm/io-defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,14 @@ DEF_PCI_AC_NORET(writeq, (u64 val, PCI_IO_ADDR addr), (val, addr), mem, addr)
DEF_PCI_AC_NORET(writeq_be, (u64 val, PCI_IO_ADDR addr), (val, addr), mem, addr)
#endif /* __powerpc64__ */

#ifdef CONFIG_HAS_IOPORT
DEF_PCI_AC_RET(inb, u8, (unsigned long port), (port), pio, port)
DEF_PCI_AC_RET(inw, u16, (unsigned long port), (port), pio, port)
DEF_PCI_AC_RET(inl, u32, (unsigned long port), (port), pio, port)
DEF_PCI_AC_NORET(outb, (u8 val, unsigned long port), (val, port), pio, port)
DEF_PCI_AC_NORET(outw, (u16 val, unsigned long port), (val, port), pio, port)
DEF_PCI_AC_NORET(outl, (u32 val, unsigned long port), (val, port), pio, port)
#endif

DEF_PCI_AC_NORET(readsb, (const PCI_IO_ADDR a, void *b, unsigned long c),
(a, b, c), mem, a)
Expand All @@ -40,6 +42,7 @@ DEF_PCI_AC_NORET(writesw, (PCI_IO_ADDR a, const void *b, unsigned long c),
DEF_PCI_AC_NORET(writesl, (PCI_IO_ADDR a, const void *b, unsigned long c),
(a, b, c), mem, a)

#ifdef CONFIG_HAS_IOPORT
DEF_PCI_AC_NORET(insb, (unsigned long p, void *b, unsigned long c),
(p, b, c), pio, p)
DEF_PCI_AC_NORET(insw, (unsigned long p, void *b, unsigned long c),
Expand All @@ -52,6 +55,7 @@ DEF_PCI_AC_NORET(outsw, (unsigned long p, const void *b, unsigned long c),
(p, b, c), pio, p)
DEF_PCI_AC_NORET(outsl, (unsigned long p, const void *b, unsigned long c),
(p, b, c), pio, p)
#endif

DEF_PCI_AC_NORET(memset_io, (PCI_IO_ADDR a, int c, unsigned long n),
(a, c, n), mem, a)
Expand Down
19 changes: 15 additions & 4 deletions arch/powerpc/include/asm/io.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ extern struct pci_dev *isa_bridge_pcidev;
* define properly based on the platform
*/
#ifndef CONFIG_PCI
#define _IO_BASE 0
#define _ISA_MEM_BASE 0
#define PCI_DRAM_OFFSET 0
#elif defined(CONFIG_PPC32)
Expand Down Expand Up @@ -486,8 +485,7 @@ static inline u64 __raw_rm_readq(volatile void __iomem *paddr)
* to port it over
*/

#ifdef CONFIG_PPC32

#if defined(CONFIG_PPC32) && defined(CONFIG_HAS_IOPORT)
#define __do_in_asm(name, op) \
static inline unsigned int name(unsigned int port) \
{ \
Expand Down Expand Up @@ -534,7 +532,7 @@ __do_out_asm(_rec_outb, "stbx")
__do_out_asm(_rec_outw, "sthbrx")
__do_out_asm(_rec_outl, "stwbrx")

#endif /* CONFIG_PPC32 */
#endif /* CONFIG_PPC32 && CONFIG_HAS_IOPORT */

/* The "__do_*" operations below provide the actual "base" implementation
* for each of the defined accessors. Some of them use the out_* functions
Expand Down Expand Up @@ -577,6 +575,7 @@ __do_out_asm(_rec_outl, "stwbrx")
#define __do_readq_be(addr) in_be64(PCI_FIX_ADDR(addr))
#endif /* !defined(CONFIG_EEH) */

#ifdef CONFIG_HAS_IOPORT
#ifdef CONFIG_PPC32
#define __do_outb(val, port) _rec_outb(val, port)
#define __do_outw(val, port) _rec_outw(val, port)
Expand All @@ -592,6 +591,7 @@ __do_out_asm(_rec_outl, "stwbrx")
#define __do_inw(port) readw((PCI_IO_ADDR)_IO_BASE + port);
#define __do_inl(port) readl((PCI_IO_ADDR)_IO_BASE + port);
#endif /* !CONFIG_PPC32 */
#endif

#ifdef CONFIG_EEH
#define __do_readsb(a, b, n) eeh_readsb(PCI_FIX_ADDR(a), (b), (n))
Expand All @@ -606,12 +606,14 @@ __do_out_asm(_rec_outl, "stwbrx")
#define __do_writesw(a, b, n) _outsw(PCI_FIX_ADDR(a),(b),(n))
#define __do_writesl(a, b, n) _outsl(PCI_FIX_ADDR(a),(b),(n))

#ifdef CONFIG_HAS_IOPORT
#define __do_insb(p, b, n) readsb((PCI_IO_ADDR)_IO_BASE+(p), (b), (n))
#define __do_insw(p, b, n) readsw((PCI_IO_ADDR)_IO_BASE+(p), (b), (n))
#define __do_insl(p, b, n) readsl((PCI_IO_ADDR)_IO_BASE+(p), (b), (n))
#define __do_outsb(p, b, n) writesb((PCI_IO_ADDR)_IO_BASE+(p),(b),(n))
#define __do_outsw(p, b, n) writesw((PCI_IO_ADDR)_IO_BASE+(p),(b),(n))
#define __do_outsl(p, b, n) writesl((PCI_IO_ADDR)_IO_BASE+(p),(b),(n))
#endif

#define __do_memset_io(addr, c, n) \
_memset_io(PCI_FIX_ADDR(addr), c, n)
Expand Down Expand Up @@ -689,6 +691,7 @@ static inline void name at \
#define writesb writesb
#define writesw writesw
#define writesl writesl

#define inb inb
#define inw inw
#define inl inl
Expand Down Expand Up @@ -848,8 +851,16 @@ static inline void iosync(void)
#define inl_p(port) inl(port)
#define outl_p(val, port) (udelay(1), outl((val), (port)))

#define insb_p insb
#define insw_p insw
#define insl_p insl
#define outsb_p outsb
#define outsw_p outsw
#define outsl_p outsl

#ifdef CONFIG_HAS_IOPORT
#define IO_SPACE_LIMIT ~(0UL)
#endif

/**
* ioremap - map bus memory into CPU space
Expand Down
4 changes: 4 additions & 0 deletions arch/powerpc/kernel/iomap.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,11 @@

void __iomem *ioport_map(unsigned long port, unsigned int len)
{
#ifdef CONFIG_HAS_IOPORT
return (void __iomem *) (port + _IO_BASE);
#else
return NULL;
#endif
}
EXPORT_SYMBOL(ioport_map);

Expand Down
2 changes: 1 addition & 1 deletion arch/powerpc/kernel/traps.c
Original file line number Diff line number Diff line change
Expand Up @@ -531,7 +531,7 @@ DEFINE_INTERRUPT_HANDLER_NMI(system_reset_exception)
*/
static inline int check_io_access(struct pt_regs *regs)
{
#ifdef CONFIG_PPC32
#if defined(CONFIG_PPC32) && defined(CONFIG_HAS_IOPORT)
unsigned long msr = regs->msr;
const struct exception_table_entry *entry;
unsigned int *nip = (unsigned int *)regs->nip;
Expand Down

0 comments on commit 3cfdbc2

Please sign in to comment.