sh: trapped io support V2
PATCH 1/1 sh: trapped io support V2
The idea is that we want to get rid of the in/out/readb/writeb callbacks from the machvec and replace that with simple inline read and write operations to memory. Fast and simple for most hardware devices (think pci).
Some devices require special treatment though - like 16-bit only CF devices - so we need to have some method to hook in callbacks.
This patch makes it possible to add a per-device trap generating filter. This way we can get maximum performance of sane hardware - which doesn't need this filter - and crappy hardware works but gets punished by a performance hit.
V2 changes things around a bit and replaces io access callbacks with a simple minimum_bus_width value. In the future we can add stride as well.
---
arch/sh/Kconfig | 3 arch/sh/kernel/Makefile_32 | 1 arch/sh/kernel/Makefile_64 | 1 arch/sh/kernel/io.c | 8 + arch/sh/kernel/io_generic.c | 24 +-- arch/sh/kernel/io_trapped.c | 269 +++++++++++++++++++++++++++++++++++++++++++ arch/sh/kernel/traps_32.c | 59 +++++---- arch/sh/mm/fault_32.c | 3 include/asm-sh/io.h | 10 + include/asm-sh/io_trapped.h | 58 +++++++++ include/asm-sh/system.h | 5 include/asm-sh/system_32.h | 3 12 files changed, 406 insertions(+), 38 deletions(-)
arch/sh/Kconfig +3 -0
@@ -89,6 +89,9 @@ config ARCH_HAS_ILOG2_U64 config ARCH_NO_VIRT_TO_BUS def_bool y +config IO_TRAPPED + bool + source "init/Kconfig" menu "System type"
arch/sh/kernel/Makefile_32 +1 -0
@@ -22,5 +22,6 @@ obj-$(CONFIG_CRASH_DUMP) += crash_dump.o obj-$(CONFIG_PM) += pm.o obj-$(CONFIG_STACKTRACE) += stacktrace.o obj-$(CONFIG_BINFMT_ELF) += dump_task.o +obj-$(CONFIG_IO_TRAPPED) += io_trapped.o EXTRA_CFLAGS += -Werror
arch/sh/kernel/Makefile_64 +1 -0
@@ -18,5 +18,6 @@ obj-$(CONFIG_CRASH_DUMP) += crash_dump.o obj-$(CONFIG_PM) += pm.o obj-$(CONFIG_STACKTRACE) += stacktrace.o obj-$(CONFIG_BINFMT_ELF) += dump_task.o +obj-$(CONFIG_IO_TRAPPED) += io_trapped.o EXTRA_CFLAGS += -Werror
arch/sh/kernel/io.c +7 -1
@@ -63,7 +63,13 @@ EXPORT_SYMBOL(memset_io);void __iomem *ioport_map (unsigned long port,unsigned int nr) { -return sh_mv.mv_ioport_map (port, nr); +void __iomem *ret; + + ret =__ioport_map_trapped (port, nr); +if (ret) +return ret; + +return __ioport_map (port, nr); }EXPORT_SYMBOL (ioport_map);
arch/sh/kernel/io_generic.c +12 -12
@@ -33,17 +33,17 @@ static inline void delay(void)u8 generic_inb (unsigned long port) { -return ctrl_inb ((unsigned long __force )ioport_map (port,1 )); +return ctrl_inb ((unsigned long __force )__ioport_map (port,1 )); }u16 generic_inw (unsigned long port) { -return ctrl_inw ((unsigned long __force )ioport_map (port,2 )); +return ctrl_inw ((unsigned long __force )__ioport_map (port,2 )); }u32 generic_inl (unsigned long port) { -return ctrl_inl ((unsigned long __force )ioport_map (port,4 )); +return ctrl_inl ((unsigned long __force )__ioport_map (port,4 )); }u8 generic_inb_p (unsigned long port)
@@ -81,7 +81,7 @@ void generic_insb(unsigned long port, vovolatile u8 *port_addr;u8 *buf = dst; - port_addr = (volatile u8 *)ioport_map (port,1 ); + port_addr = (volatile u8 *)__ioport_map (port,1 );while (count--) *buf++ = *port_addr; }
@@ -91,7 +91,7 @@ void generic_insw(unsigned long port, vovolatile u16 *port_addr;u16 *buf = dst; - port_addr = (volatile u16 *)ioport_map (port,2 ); + port_addr = (volatile u16 *)__ioport_map (port,2 );while (count--) *buf++ = *port_addr;
@@ -103,7 +103,7 @@ void generic_insl(unsigned long port, vovolatile u32 *port_addr;u32 *buf = dst; - port_addr = (volatile u32 *)ioport_map (port,4 ); + port_addr = (volatile u32 *)__ioport_map (port,4 );while (count--) *buf++ = *port_addr;
@@ -112,17 +112,17 @@ void generic_insl(unsigned long port, vovoid generic_outb (u8 b,unsigned long port) { -ctrl_outb (b, (unsigned long __force )ioport_map (port,1 )); +ctrl_outb (b, (unsigned long __force )__ioport_map (port,1 )); }void generic_outw (u16 b,unsigned long port) { -ctrl_outw (b, (unsigned long __force )ioport_map (port,2 )); +ctrl_outw (b, (unsigned long __force )__ioport_map (port,2 )); }void generic_outl (u32 b,unsigned long port) { -ctrl_outl (b, (unsigned long __force )ioport_map (port,4 )); +ctrl_outl (b, (unsigned long __force )__ioport_map (port,4 )); }void generic_outb_p (u8 b,unsigned long port)
@@ -153,7 +153,7 @@ void generic_outsb(unsigned long port, cvolatile u8 *port_addr;const u8 *buf = src; - port_addr = (volatile u8 __force *)ioport_map (port,1 ); + port_addr = (volatile u8 __force *)__ioport_map (port,1 );while (count--) *port_addr = *buf++;
@@ -164,7 +164,7 @@ void generic_outsw(unsigned long port, cvolatile u16 *port_addr;const u16 *buf = src; - port_addr = (volatile u16 __force *)ioport_map (port,2 ); + port_addr = (volatile u16 __force *)__ioport_map (port,2 );while (count--) *port_addr = *buf++;
@@ -177,7 +177,7 @@ void generic_outsl(unsigned long port, cvolatile u32 *port_addr;const u32 *buf = src; - port_addr = (volatile u32 __force *)ioport_map (port,4 ); + port_addr = (volatile u32 __force *)__ioport_map (port,4 );while (count--) *port_addr = *buf++;
arch/sh/kernel/io_trapped.c new file +269 -0
269 lines not on this page · raw message
arch/sh/kernel/traps_32.c +34 -25
205 lines not on this page · raw message
arch/sh/mm/fault_32.c +3 -0
@@ -15,6 +15,7 @@#include <linux/mm.h> #include <linux/hardirq.h> #include <linux/kprobes.h> +#include <asm/io_trapped.h> #include <asm/system.h> #include <asm/mmu_context.h> #include <asm/tlbflush.h>
@@ -163,6 +164,8 @@ no_context:if (fixup_exception (regs))return ; +if (handle_trapped_io (regs, address)) +return ;/* * Oops. The kernel tried to access some bad page. We'll have to * terminate things with extreme prejudice.
include/asm-sh/io.h +10 -0
@@ -38,6 +38,7 @@*/ #define __IO_PREFIX generic#include <asm/io_generic.h> +#include <asm/io_trapped.h> #define maybebadio (port) \ printk(KERN_ERR "bad PC-like io %s:%u for port 0x%lx at 0x%08x\n", \
@@ -207,6 +208,8 @@ static inline void __set_io_port_base(un generic_io_base = pbase; } +#define __ioport_map (p, n) sh_mv.mv_ioport_map((p), (n)) +/* We really want to try and get these to memcpy etc */ extern void memcpy_fromio (void *,volatile void __iomem *,unsigned long );extern void memcpy_toio (volatile void __iomem *,const void *,unsigned long );
@@ -309,7 +312,14 @@ __ioremap_mode(unsigned long offset, uns {#ifdef CONFIG_SUPERH32 unsigned long last_addr = offset + size -1 ; +#endif +void __iomem *ret; + ret =__ioremap_trapped (offset, size); +if (ret) +return ret; + +#ifdef CONFIG_SUPERH32 /* * For P1 and P2 space this is trivial, as everything is already * mapped. Uncached access for P1 addresses are done through P2.
include/asm-sh/io_trapped.h new file +58 -0
58 lines not on this page · raw message
include/asm-sh/system.h +5 -0
@@ -182,6 +182,11 @@ BUILD_TRAP_HANDLER(fpu_state_restore);#define arch_align_stack (x) (x) +struct mem_access { +unsigned long (*from)(void *dst,const void *src,unsigned long cnt); +unsigned long (*to)(void *dst,const void *src,unsigned long cnt); +}; +#ifdef CONFIG_SUPERH32 # include "system_32.h" #else
include/asm-sh/system_32.h +3 -0
@@ -96,4 +96,7 @@ do { \ : "=&r" (__dummy)); \ } while (0) +int handle_unaligned_access(opcode_t instruction, struct pt_regs *regs, + struct mem_access *ma); +#endif /* __ASM_SH_SYSTEM_32_H */