Commit 2e1e9212 authored by Linus Torvalds's avatar Linus Torvalds

Merge git://git.kernel.org/pub/scm/linux/kernel/git/lethal/sh-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/lethal/sh-2.6: (29 commits)
  sh: enable maple_keyb in dreamcast_defconfig.
  SH2(A) cache update
  nommu: Provide vmalloc_exec().
  add addrespace definition for sh2a.
  sh: Kill off ARCH_SUPPORTS_AOUT and remnants of a.out support.
  sh: define GENERIC_HARDIRQS_NO__DO_IRQ.
  sh: define GENERIC_LOCKBREAK.
  sh: Save NUMA node data in vmcore for crash dumps.
  sh: module_alloc() should be using vmalloc_exec().
  sh: Fix up __bug_table handling in module loader.
  sh: Add documentation and integrate into docbook build.
  sh: Fix up broken kerneldoc comments.
  maple: Kill useless private_data pointer.
  maple: Clean up maple_driver_register/unregister routines.
  input: Clean up maple keyboard driver
  maple: allow removal and reinsertion of keyboard driver module
  sh: /proc/asids depends on MMU.
  arch/sh/boards/mach-se/7343/irq.c: removed duplicated #include
  arch/sh/boards/board-ap325rxa.c: removed duplicated #include
  sh/boards/Makefile typo fix
  ...
parents 2acb802b f5663f5b
......@@ -12,7 +12,7 @@ DOCBOOKS := wanbook.xml z8530book.xml mcabook.xml videobook.xml \
kernel-api.xml filesystems.xml lsm.xml usb.xml kgdb.xml \
gadget.xml libata.xml mtdnand.xml librs.xml rapidio.xml \
genericirq.xml s390-drivers.xml uio-howto.xml scsi.xml \
mac80211.xml debugobjects.xml
mac80211.xml debugobjects.xml sh.xml
###
# The build process is as follows (targets):
......
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
<book id="sh-drivers">
<bookinfo>
<title>SuperH Interfaces Guide</title>
<authorgroup>
<author>
<firstname>Paul</firstname>
<surname>Mundt</surname>
<affiliation>
<address>
<email>lethal@linux-sh.org</email>
</address>
</affiliation>
</author>
</authorgroup>
<copyright>
<year>2008</year>
<holder>Paul Mundt</holder>
</copyright>
<copyright>
<year>2008</year>
<holder>Renesas Technology Corp.</holder>
</copyright>
<legalnotice>
<para>
This documentation is free software; you can redistribute
it and/or modify it under the terms of the GNU General Public
License version 2 as published by the Free Software Foundation.
</para>
<para>
This program is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
</para>
<para>
You should have received a copy of the GNU General Public
License along with this program; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
MA 02111-1307 USA
</para>
<para>
For more details see the file COPYING in the source
distribution of Linux.
</para>
</legalnotice>
</bookinfo>
<toc></toc>
<chapter id="mm">
<title>Memory Management</title>
<sect1 id="sh4">
<title>SH-4</title>
<sect2 id="sq">
<title>Store Queue API</title>
!Earch/sh/kernel/cpu/sh4/sq.c
</sect2>
</sect1>
<sect1 id="sh5">
<title>SH-5</title>
<sect2 id="tlb">
<title>TLB Interfaces</title>
!Iarch/sh/mm/tlb-sh5.c
!Iarch/sh/include/asm/tlb_64.h
</sect2>
</sect1>
</chapter>
<chapter id="clk">
<title>Clock Framework Extensions</title>
!Iarch/sh/include/asm/clock.h
</chapter>
<chapter id="mach">
<title>Machine Specific Interfaces</title>
<sect1 id="dreamcast">
<title>mach-dreamcast</title>
!Iarch/sh/boards/mach-dreamcast/rtc.c
</sect1>
<sect1 id="x3proto">
<title>mach-x3proto</title>
!Earch/sh/boards/mach-x3proto/ilsel.c
</sect1>
</chapter>
<chapter id="busses">
<title>Busses</title>
<sect1 id="superhyway">
<title>SuperHyway</title>
!Edrivers/sh/superhyway/superhyway.c
</sect1>
<sect1 id="maple">
<title>Maple</title>
!Edrivers/sh/maple/maple.c
</sect1>
</chapter>
</book>
......@@ -48,6 +48,9 @@ config GENERIC_HWEIGHT
config GENERIC_HARDIRQS
def_bool y
config GENERIC_HARDIRQS_NO__DO_IRQ
def_bool y
config GENERIC_IRQ_PROBE
def_bool y
......@@ -63,6 +66,10 @@ config GENERIC_TIME
config GENERIC_CLOCKEVENTS
def_bool n
config GENERIC_LOCKBREAK
def_bool y
depends on SMP && PREEMPT
config SYS_SUPPORTS_PM
bool
......@@ -94,9 +101,6 @@ config ARCH_HAS_ILOG2_U64
config ARCH_NO_VIRT_TO_BUS
def_bool y
config ARCH_SUPPORTS_AOUT
def_bool y
config IO_TRAPPED
bool
......@@ -483,6 +487,23 @@ config CRASH_DUMP
For more details see Documentation/kdump/kdump.txt
config SECCOMP
bool "Enable seccomp to safely compute untrusted bytecode"
depends on PROC_FS
default y
help
This kernel feature is useful for number crunching applications
that may need to compute untrusted bytecode during their
execution. By using pipes or other transports made available to
the process as file descriptors supporting the read/write
syscalls, it's possible to isolate those applications in
their own address space using seccomp. Once seccomp is
enabled via prctl, it cannot be disabled and the task is only
allowed to execute a few safe syscalls defined by each seccomp
mode.
If unsure, say N.
config SMP
bool "Symmetric multi-processing support"
depends on SYS_SUPPORTS_SMP
......
......@@ -182,7 +182,7 @@ if SUPERH64
config SH64_PROC_ASIDS
bool "Debug: report ASIDs through /proc/asids"
depends on PROC_FS
depends on PROC_FS && MMU
config SH64_SR_WATCH
bool "Debug: set SR.WATCH to enable hardware watchpoints and trace"
......
......@@ -95,8 +95,6 @@ head-y := arch/sh/kernel/init_task.o
head-$(CONFIG_SUPERH32) += arch/sh/kernel/head_32.o
head-$(CONFIG_SUPERH64) += arch/sh/kernel/head_64.o
LIBGCC := $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name)
core-y += arch/sh/kernel/ arch/sh/mm/ arch/sh/boards/
core-$(CONFIG_SH_FPU_EMU) += arch/sh/math-emu/
......@@ -145,10 +143,6 @@ cpuincdir-$(CONFIG_CPU_SH4) += cpu-sh4
cpuincdir-$(CONFIG_CPU_SH5) += cpu-sh5
cpuincdir-y += cpu-common # Must be last
libs-$(CONFIG_SUPERH32) := arch/sh/lib/ $(libs-y)
libs-$(CONFIG_SUPERH64) := arch/sh/lib64/ $(libs-y)
libs-y += $(LIBGCC)
drivers-y += arch/sh/drivers/
drivers-$(CONFIG_OPROFILE) += arch/sh/oprofile/
......@@ -161,10 +155,16 @@ KBUILD_CFLAGS += -pipe $(cflags-y)
KBUILD_CPPFLAGS += $(cflags-y)
KBUILD_AFLAGS += $(cflags-y)
LIBGCC := $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name)
libs-$(CONFIG_SUPERH32) := arch/sh/lib/ $(libs-y)
libs-$(CONFIG_SUPERH64) := arch/sh/lib64/ $(libs-y)
libs-y += $(LIBGCC)
PHONY += maketools FORCE
maketools: include/linux/version.h FORCE
$(Q)$(MAKE) $(build)=arch/sh/tools arch/sh/include/asm/machtypes.h
$(Q)$(MAKE) $(build)=arch/sh/tools include/asm-sh/machtypes.h
all: $(KBUILD_IMAGE)
......@@ -215,4 +215,4 @@ arch/sh/lib64/syscalltab.h: arch/sh/kernel/syscalls_64.S
$(call filechk,gen-syscalltab)
CLEAN_FILES += arch/sh/lib64/syscalltab.h \
arch/sh/include/asm/machtypes.h
include/asm-sh/machtypes.h
......@@ -5,4 +5,4 @@ obj-$(CONFIG_SH_AP325RXA) += board-ap325rxa.o
obj-$(CONFIG_SH_MAGIC_PANEL_R2) += board-magicpanelr2.o
obj-$(CONFIG_SH_RSK7203) += board-rsk7203.o
obj-$(CONFIG_SH_SH7785LCR) += board-sh7785lcr.o
obj-$(CONFIG_SH_SHMIN) += board-shmin..o
obj-$(CONFIG_SH_SHMIN) += board-shmin.o
......@@ -17,7 +17,6 @@
#include <linux/mtd/physmap.h>
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/delay.h>
#include <linux/smc911x.h>
#include <media/soc_camera_platform.h>
#include <media/sh_mobile_ceu.h>
......
......@@ -13,7 +13,6 @@
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/io.h>
#include <mach-se/mach/se7343.h>
......
#
# Automatically generated make config: don't edit
# Linux kernel version: 2.6.26
# Wed Jul 30 01:34:24 2008
# Linux kernel version: 2.6.27-rc1
# Mon Aug 4 16:49:13 2008
#
CONFIG_SUPERH=y
CONFIG_SUPERH32=y
......@@ -11,6 +11,7 @@ CONFIG_GENERIC_BUG=y
CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
CONFIG_GENERIC_IRQ_PROBE=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_GENERIC_TIME=y
......@@ -21,7 +22,6 @@ CONFIG_LOCKDEP_SUPPORT=y
# CONFIG_ARCH_HAS_ILOG2_U32 is not set
# CONFIG_ARCH_HAS_ILOG2_U64 is not set
CONFIG_ARCH_NO_VIRT_TO_BUS=y
CONFIG_ARCH_SUPPORTS_AOUT=y
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
#
......@@ -87,6 +87,7 @@ CONFIG_HAVE_OPROFILE=y
# CONFIG_USE_GENERIC_SMP_HELPERS is not set
CONFIG_HAVE_CLK=y
CONFIG_PROC_PAGE_MONITOR=y
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
......@@ -284,6 +285,7 @@ CONFIG_HZ=250
# CONFIG_SCHED_HRTICK is not set
# CONFIG_KEXEC is not set
# CONFIG_CRASH_DUMP is not set
CONFIG_SECCOMP=y
# CONFIG_PREEMPT_NONE is not set
# CONFIG_PREEMPT_VOLUNTARY is not set
CONFIG_PREEMPT=y
......@@ -317,10 +319,6 @@ CONFIG_PCI_LEGACY=y
#
CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set
#
# Networking
#
CONFIG_NET=y
#
......@@ -555,7 +553,7 @@ CONFIG_INPUT_KEYBOARD=y
# CONFIG_KEYBOARD_XTKBD is not set
# CONFIG_KEYBOARD_NEWTON is not set
# CONFIG_KEYBOARD_STOWAWAY is not set
# CONFIG_KEYBOARD_MAPLE is not set
CONFIG_KEYBOARD_MAPLE=y
# CONFIG_KEYBOARD_SH_KEYSC is not set
CONFIG_INPUT_MOUSE=y
# CONFIG_MOUSE_PS2 is not set
......
#ifndef __ASM_SH_A_OUT_H
#define __ASM_SH_A_OUT_H
struct exec
{
unsigned long a_info; /* Use macros N_MAGIC, etc for access */
unsigned a_text; /* length of text, in bytes */
unsigned a_data; /* length of data, in bytes */
unsigned a_bss; /* length of uninitialized data area for file, in bytes */
unsigned a_syms; /* length of symbol table data in file, in bytes */
unsigned a_entry; /* start address */
unsigned a_trsize; /* length of relocation info for text, in bytes */
unsigned a_drsize; /* length of relocation info for data, in bytes */
};
#define N_TRSIZE(a) ((a).a_trsize)
#define N_DRSIZE(a) ((a).a_drsize)
#define N_SYMSIZE(a) ((a).a_syms)
#endif /* __ASM_SH_A_OUT_H */
......@@ -104,6 +104,15 @@ struct pt_dspregs {
extern void show_regs(struct pt_regs *);
/*
* These are defined as per linux/ptrace.h.
*/
struct task_struct;
#define arch_has_single_step() (1)
extern void user_enable_single_step(struct task_struct *);
extern void user_disable_single_step(struct task_struct *);
#ifdef CONFIG_SH_DSP
#define task_pt_regs(task) \
((struct pt_regs *) (task_stack_page(task) + THREAD_SIZE \
......
#ifndef __ASM_SECCOMP_H
#include <linux/unistd.h>
#define __NR_seccomp_read __NR_read
#define __NR_seccomp_write __NR_write
#define __NR_seccomp_exit __NR_exit
#define __NR_seccomp_sigreturn __NR_rt_sigreturn
#endif /* __ASM_SECCOMP_H */
......@@ -117,24 +117,45 @@ static inline struct thread_info *current_thread_info(void)
#define TIF_NEED_RESCHED 2 /* rescheduling necessary */
#define TIF_RESTORE_SIGMASK 3 /* restore signal mask in do_signal() */
#define TIF_SINGLESTEP 4 /* singlestepping active */
#define TIF_SYSCALL_AUDIT 5
#define TIF_SYSCALL_AUDIT 5 /* syscall auditing active */
#define TIF_SECCOMP 6 /* secure computing */
#define TIF_NOTIFY_RESUME 7 /* callback before returning to user */
#define TIF_USEDFPU 16 /* FPU was used by this task this quantum (SMP) */
#define TIF_POLLING_NRFLAG 17 /* true if poll_idle() is polling TIF_NEED_RESCHED */
#define TIF_MEMDIE 18
#define TIF_FREEZE 19
#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
#define _TIF_SIGPENDING (1<<TIF_SIGPENDING)
#define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED)
#define _TIF_RESTORE_SIGMASK (1<<TIF_RESTORE_SIGMASK)
#define _TIF_SINGLESTEP (1<<TIF_SINGLESTEP)
#define _TIF_SYSCALL_AUDIT (1<<TIF_SYSCALL_AUDIT)
#define _TIF_USEDFPU (1<<TIF_USEDFPU)
#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG)
#define _TIF_FREEZE (1<<TIF_FREEZE)
#define _TIF_WORK_MASK 0x000000FE /* work to do on interrupt/exception return */
#define _TIF_ALLWORK_MASK 0x000000FF /* work to do on any return to u-space */
#define TIF_FREEZE 19 /* Freezing for suspend */
#define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE)
#define _TIF_SIGPENDING (1 << TIF_SIGPENDING)
#define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
#define _TIF_RESTORE_SIGMASK (1 << TIF_RESTORE_SIGMASK)
#define _TIF_SINGLESTEP (1 << TIF_SINGLESTEP)
#define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT)
#define _TIF_SECCOMP (1 << TIF_SECCOMP)
#define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME)
#define _TIF_USEDFPU (1 << TIF_USEDFPU)
#define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG)
#define _TIF_FREEZE (1 << TIF_FREEZE)
/*
* _TIF_ALLWORK_MASK and _TIF_WORK_MASK need to fit within a byte, or we
* blow the tst immediate size constraints and need to fix up
* arch/sh/kernel/entry-common.S.
*/
/* work to do in syscall trace */
#define _TIF_WORK_SYSCALL_MASK (_TIF_SYSCALL_TRACE | _TIF_SINGLESTEP | \
_TIF_SYSCALL_AUDIT | _TIF_SECCOMP)
/* work to do on any return to u-space */
#define _TIF_ALLWORK_MASK (_TIF_SYSCALL_TRACE | _TIF_SIGPENDING | \
_TIF_NEED_RESCHED | _TIF_SYSCALL_AUDIT | \
_TIF_SINGLESTEP | _TIF_RESTORE_SIGMASK | \
_TIF_NOTIFY_RESUME)
/* work to do on interrupt/exception return */
#define _TIF_WORK_MASK (_TIF_ALLWORK_MASK & ~(_TIF_SYSCALL_TRACE | \
_TIF_SYSCALL_AUDIT | _TIF_SINGLESTEP))
#endif /* __KERNEL__ */
......
......@@ -21,11 +21,9 @@
#ifndef __ASSEMBLY__
/**
* for_each_dtlb_entry
* for_each_dtlb_entry - Iterate over free (non-wired) DTLB entries
*
* @tlb: TLB entry
*
* Iterate over free (non-wired) DTLB entries
*/
#define for_each_dtlb_entry(tlb) \
for (tlb = cpu_data->dtlb.first; \
......@@ -33,11 +31,9 @@
tlb += cpu_data->dtlb.step)
/**
* for_each_itlb_entry
* for_each_itlb_entry - Iterate over free (non-wired) ITLB entries
*
* @tlb: TLB entry
*
* Iterate over free (non-wired) ITLB entries
*/
#define for_each_itlb_entry(tlb) \
for (tlb = cpu_data->itlb.first; \
......@@ -45,11 +41,9 @@
tlb += cpu_data->itlb.step)
/**
* __flush_tlb_slot
* __flush_tlb_slot - Flushes TLB slot @slot.
*
* @slot: Address of TLB slot.
*
* Flushes TLB slot @slot.
*/
static inline void __flush_tlb_slot(unsigned long long slot)
{
......
......@@ -21,11 +21,11 @@
#define CCR 0xffffffec
#define CCR_CACHE_CE 0x01 /* Cache enable */
#define CCR_CACHE_WT 0x06 /* CCR[bit1=1,bit2=1] */
#define CCR_CACHE_WT 0x02 /* CCR[bit1=1,bit2=1] */
/* 0x00000000-0x7fffffff: Write-through */
/* 0x80000000-0x9fffffff: Write-back */
/* 0xc0000000-0xdfffffff: Write-through */
#define CCR_CACHE_CB 0x00 /* CCR[bit1=0,bit2=0] */
#define CCR_CACHE_CB 0x04 /* CCR[bit1=0,bit2=0] */
/* 0x00000000-0x7fffffff: Write-back */
/* 0x80000000-0x9fffffff: Write-through */
/* 0xc0000000-0xdfffffff: Write-back */
......@@ -36,6 +36,8 @@
#define CCR_CACHE_ENABLE CCR_CACHE_CE
#define CCR_CACHE_INVALIDATE CCR_CACHE_CF
#define CACHE_PHYSADDR_MASK 0x1ffffc00
#endif
#endif /* __ASM_CPU_SH2_CACHE_H */
#ifndef __ASM_SH_CPU_SH2A_ADDRSPACE_H
#define __ASM_SH_CPU_SH2A_ADDRSPACE_H
#define P0SEG 0x00000000
#define P1SEG 0x00000000
#define P2SEG 0x20000000
#define P3SEG 0x40000000
#define P4SEG 0x60000000
#endif /* __ASM_SH_CPU_SH2A_ADDRSPACE_H */
......@@ -36,5 +36,8 @@
#define CCR_CACHE_ENABLE (CCR_CACHE_OCE | CCR_CACHE_ICE)
#define CCR_CACHE_INVALIDATE (CCR_CACHE_OCI | CCR_CACHE_ICI)
#define CCR_ICACHE_INVALIDATE CCR_CACHE_ICI
#define CCR_OCACHE_INVALIDATE CCR_CACHE_OCI
#define CACHE_PHYSADDR_MASK 0x1ffffc00
#endif /* __ASM_CPU_SH2A_CACHE_H */
#ifndef __ASM_CPU_SH2A_CACHEFLUSH_H
#define __ASM_CPU_SH2A_CACHEFLUSH_H
/*
* Cache flushing:
*
* - flush_cache_all() flushes entire cache
* - flush_cache_mm(mm) flushes the specified mm context's cache lines
* - flush_cache_dup mm(mm) handles cache flushing when forking
* - flush_cache_page(mm, vmaddr, pfn) flushes a single page
* - flush_cache_range(vma, start, end) flushes a range of pages
*
* - flush_dcache_page(pg) flushes(wback&invalidates) a page for dcache
* - flush_icache_range(start, end) flushes(invalidates) a range for icache
* - flush_icache_page(vma, pg) flushes(invalidates) a page for icache
*
* Caches are indexed (effectively) by physical address on SH-2, so
* we don't need them.
*/
#define flush_cache_all() do { } while (0)
#define flush_cache_mm(mm) do { } while (0)
#define flush_cache_dup_mm(mm) do { } while (0)
#define flush_cache_range(vma, start, end) do { } while (0)
#define flush_cache_page(vma, vmaddr, pfn) do { } while (0)
#define flush_dcache_page(page) do { } while (0)
#define flush_dcache_mmap_lock(mapping) do { } while (0)
#define flush_dcache_mmap_unlock(mapping) do { } while (0)
void flush_icache_range(unsigned long start, unsigned long end);
#define flush_icache_page(vma,pg) do { } while (0)
#define flush_icache_user_range(vma,pg,adr,len) do { } while (0)
#define flush_cache_sigtramp(vaddr) do { } while (0)
#define p3_cache_init() do { } while (0)
#endif /* __ASM_CPU_SH2A_CACHEFLUSH_H */
......@@ -199,7 +199,7 @@ EXPORT_SYMBOL(sq_remap);
/**
* sq_unmap - Unmap a Store Queue allocation
* @map: Pre-allocated Store Queue mapping.
* @vaddr: Pre-allocated Store Queue mapping.
*
* Unmaps the store queue allocation @map that was previously created by
* sq_remap(). Also frees up the pte that was previously inserted into
......
......@@ -987,11 +987,11 @@ work_resched:
work_notifysig:
gettr tr1, LINK
movi do_signal, r6
movi do_notify_resume, r6
ptabs r6, tr0
or SP, ZERO, r2
or ZERO, ZERO, r3
blink tr0, LINK /* Call do_signal(regs, 0), return here */
or r7, ZERO, r3
blink tr0, LINK /* Call do_notify_resume(regs, current_thread_info->flags), return here */
restore_all:
/* Do prefetches */
......@@ -1300,18 +1300,20 @@ syscall_allowed:
getcon KCR0, r2
ld.l r2, TI_FLAGS, r4
movi (_TIF_SYSCALL_TRACE | _TIF_SINGLESTEP | _TIF_SYSCALL_AUDIT), r6
movi _TIF_WORK_SYSCALL_MASK, r6
and r6, r4, r6
beq/l r6, ZERO, tr0
/* Trace it by calling syscall_trace before and after */
movi syscall_trace, r4
movi do_syscall_trace_enter, r4
or SP, ZERO, r2
or ZERO, ZERO, r3
ptabs r4, tr0
blink tr0, LINK
/* Reload syscall number as r5 is trashed by syscall_trace */
/* Save the retval */
st.q SP, FRAME_R(2), r2
/* Reload syscall number as r5 is trashed by do_syscall_trace_enter */
ld.q SP, FRAME_S(FSYSCALL_ID), r5
andi r5, 0x1ff, r5
......@@ -1343,9 +1345,8 @@ syscall_ret_trace:
/* We get back here only if under trace */
st.q SP, FRAME_R(9), r2 /* Save return value */
movi syscall_trace, LINK
movi do_syscall_trace_leave, LINK
or SP, ZERO, r2
movi 1, r3
ptabs LINK, tr0
blink tr0, LINK
......
......@@ -202,7 +202,7 @@ work_resched:
syscall_exit_work:
! r0: current_thread_info->flags
! r8: current_thread_info
tst #_TIF_SYSCALL_TRACE | _TIF_SINGLESTEP | _TIF_SYSCALL_AUDIT, r0
tst #_TIF_WORK_SYSCALL_MASK, r0
bt/s work_pending
tst #_TIF_NEED_RESCHED, r0
#ifdef CONFIG_TRACE_IRQFLAGS
......@@ -211,10 +211,8 @@ syscall_exit_work:
nop
#endif
sti
! XXX setup arguments...
mov r15, r4
mov #1, r5
mov.l 4f, r0 ! do_syscall_trace
mov.l 8f, r0 ! do_syscall_trace_leave
jsr @r0
nop
bra resume_userspace
......@@ -223,12 +221,11 @@ syscall_exit_work:
.align 2
syscall_trace_entry:
! Yes it is traced.
! XXX setup arguments...
mov r15, r4
mov #0, r5
mov.l 4f, r11 ! Call do_syscall_trace which notifies
mov.l 7f, r11 ! Call do_syscall_trace_enter which notifies
jsr @r11 ! superior (will chomp R[0-7])
nop
mov.l r0, @(OFF_R0,r15) ! Save return value
! Reload R0-R4 from kernel stack, where the
! parent may have modified them using
! ptrace(POKEUSR). (Note that R0-R2 are
......@@ -351,7 +348,7 @@ ENTRY(system_call)
!
get_current_thread_info r8, r10
mov.l @(TI_FLAGS,r8), r8
mov #(_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT), r10
mov #_TIF_WORK_SYSCALL_MASK, r10
tst r10, r8
bf syscall_trace_entry
!
......@@ -389,8 +386,9 @@ syscall_exit:
#endif
2: .long NR_syscalls
3: .long sys_call_table
4: .long do_syscall_trace
#ifdef CONFIG_TRACE_IRQFLAGS
5: .long trace_hardirqs_on
6: .long trace_hardirqs_off
#endif
7: .long do_syscall_trace_enter
8: .long do_syscall_trace_leave
......@@ -13,6 +13,7 @@
#include <linux/kexec.h>
#include <linux/delay.h>
#include <linux/reboot.h>
#include <linux/numa.h>
#include <asm/pgtable.h>
#include <asm/pgalloc.h>
#include <asm/mmu_context.h>
......@@ -104,3 +105,10 @@ void machine_kexec(struct kimage *image)
(*rnk)(page_list, reboot_code_buffer, image->start, vbr_reg);
}
void arch_crash_save_vmcoreinfo(void)
{
#ifdef CONFIG_NUMA
VMCOREINFO_SYMBOL(node_data);
VMCOREINFO_LENGTH(node_data, MAX_NUMNODES);
#endif
}
......@@ -27,6 +27,7 @@
#include <linux/moduleloader.h>
#include <linux/elf.h>
#include <linux/vmalloc.h>
#include <linux/bug.h>
#include <linux/fs.h>
#include <linux/string.h>
#include <linux/kernel.h>
......@@ -36,7 +37,8 @@ void *module_alloc(unsigned long size)
{
if (size == 0)
return NULL;
return vmalloc(size);
return vmalloc_exec(size);
}
......@@ -145,9 +147,10 @@ int module_finalize(const Elf_Ehdr *hdr,
const Elf_Shdr *sechdrs,
struct module *me)
{
return 0;
return module_bug_finalize(hdr, sechdrs, me);
}
void module_arch_cleanup(struct module *mod)
{
module_bug_cleanup(mod);
}
......@@ -20,6 +20,8 @@
#include <linux/signal.h>
#include <linux/io.h>
#include <linux/audit.h>
#include <linux/seccomp.h>
#include <linux/tracehook.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
#include <asm/system.h>
......@@ -57,7 +59,23 @@ static inline int put_stack_long(struct task_struct *task, int offset,
return 0;
}
static void ptrace_disable_singlestep(struct task_struct *child)
void user_enable_single_step(struct task_struct *child)
{
struct pt_regs *regs = task_pt_regs(child);
long pc;
pc = get_stack_long(child, (long)&regs->pc);
/* Next scheduling will set up UBC */
if (child->thread.ubc_pc == 0)
ubc_usercnt += 1;
child->thread.ubc_pc = pc;
set_tsk_thread_flag(child, TIF_SINGLESTEP);
}
void user_disable_single_step(struct task_struct *child)
{
clear_tsk_thread_flag(child, TIF_SINGLESTEP);
......@@ -81,7 +99,7 @@ static void ptrace_disable_singlestep(struct task_struct *child)
*/
void ptrace_disable(struct task_struct *child)
{
ptrace_disable_singlestep(child);
user_disable_single_step(child);
}
long arch_ptrace(struct task_struct *child, long request, long addr, long data)
......@@ -90,12 +108,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
int ret;
switch (request) {
/* when I and D space are separate, these will need to be fixed. */
case PTRACE_PEEKTEXT: /* read word at location addr. */
case PTRACE_PEEKDATA:
ret = generic_ptrace_peekdata(child, addr, data);
break;
/* read the word at location addr in the USER area. */
case PTRACE_PEEKUSR: {
unsigned long tmp;
......@@ -125,12 +137,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
break;
}
/* when I and D space are separate, this will have to be fixed. */
case PTRACE_POKETEXT: /* write the word at location addr. */
case PTRACE_POKEDATA:
ret = generic_ptrace_pokedata(child, addr, data);
break;
case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
ret = -EIO;
if ((addr & 3) || addr < 0 ||
......@@ -151,67 +157,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
}
break;
case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
case PTRACE_CONT: { /* restart after signal. */
ret = -EIO;
if (!valid_signal(data))
break;
if (request == PTRACE_SYSCALL)
set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
else
clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
ptrace_disable_singlestep(child);
child->exit_code = data;
wake_up_process(child);
ret = 0;
break;
}
/*
* make the child exit. Best I can do is send it a sigkill.
* perhaps it should be put in the status that it wants to
* exit.
*/
case PTRACE_KILL: {
ret = 0;
if (child->exit_state == EXIT_ZOMBIE) /* already dead */
break;
ptrace_disable_singlestep(child);
child->exit_code = SIGKILL;
wake_up_process(child);
break;
}
case PTRACE_SINGLESTEP: { /* set the trap flag. */
long pc;
struct pt_regs *regs = NULL;
ret = -EIO;
if (!valid_signal(data))
break;
clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
if ((child->ptrace & PT_DTRACE) == 0) {
/* Spurious delayed TF traps may occur */
child->ptrace |= PT_DTRACE;
}
pc = get_stack_long(child, (long)&regs->pc);
/* Next scheduling will set up UBC */
if (child->thread.ubc_pc == 0)
ubc_usercnt += 1;
child->thread.ubc_pc = pc;
set_tsk_thread_flag(child, TIF_SINGLESTEP);
child->exit_code = data;
/* give it a chance to run. */
wake_up_process(child);
ret = 0;
break;
}
#ifdef CONFIG_SH_DSP
case PTRACE_GETDSPREGS: {
unsigned long dp;
......@@ -272,39 +217,49 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
return ret;
}
asmlinkage void do_syscall_trace(struct pt_regs *regs, int entryexit)
static inline int audit_arch(void)
{
struct task_struct *tsk = current;
int arch = EM_SH;
if (unlikely(current->audit_context) && entryexit)
audit_syscall_exit(AUDITSC_RESULT(regs->regs[0]),
regs->regs[0]);
#ifdef CONFIG_CPU_LITTLE_ENDIAN
arch |= __AUDIT_ARCH_LE;
#endif
if (!test_thread_flag(TIF_SYSCALL_TRACE) &&
!test_thread_flag(TIF_SINGLESTEP))
goto out;
if (!(tsk->ptrace & PT_PTRACED))
goto out;
return arch;
}
/* the 0x80 provides a way for the tracing parent to distinguish
between a syscall stop and SIGTRAP delivery */
ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) &&
!test_thread_flag(TIF_SINGLESTEP) ? 0x80 : 0));
asmlinkage long do_syscall_trace_enter(struct pt_regs *regs)
{
long ret = 0;
/*
* this isn't the same as continuing with a signal, but it will do
* for normal use. strace only continues with a signal if the
* stopping signal is not SIGTRAP. -brl
*/
if (tsk->exit_code) {
send_sig(tsk->exit_code, tsk, 1);
tsk->exit_code = 0;
}
secure_computing(regs->regs[0]);
if (test_thread_flag(TIF_SYSCALL_TRACE) &&
tracehook_report_syscall_entry(regs))
/*
* Tracing decided this syscall should not happen.
* We'll return a bogus call number to get an ENOSYS
* error, but leave the original number in regs->regs[0].
*/
ret = -1L;
out:
if (unlikely(current->audit_context) && !entryexit)
audit_syscall_entry(AUDIT_ARCH_SH, regs->regs[3],
if (unlikely(current->audit_context))
audit_syscall_entry(audit_arch(), regs->regs[3],
regs->regs[4], regs->regs[5],
regs->regs[6], regs->regs[7]);
return ret ?: regs->regs[0];
}
asmlinkage void do_syscall_trace_leave(struct pt_regs *regs)
{
int step;
if (unlikely(current->audit_context))
audit_syscall_exit(AUDITSC_RESULT(regs->regs[0]),
regs->regs[0]);
step = test_thread_flag(TIF_SINGLESTEP);
if (step || test_thread_flag(TIF_SYSCALL_TRACE))
tracehook_report_syscall_exit(regs, step);
}
......@@ -27,6 +27,8 @@
#include <linux/signal.h>
#include <linux/syscalls.h>
#include <linux/audit.h>
#include <linux/seccomp.h>
#include <linux/tracehook.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
......@@ -120,18 +122,23 @@ put_fpu_long(struct task_struct *task, unsigned long addr, unsigned long data)
return 0;
}
void user_enable_single_step(struct task_struct *child)
{
struct pt_regs *regs = child->thread.uregs;
regs->sr |= SR_SSTEP; /* auto-resetting upon exception */
}
void user_disable_single_step(struct task_struct *child)
{
regs->sr &= ~SR_SSTEP;
}
long arch_ptrace(struct task_struct *child, long request, long addr, long data)
{
int ret;
switch (request) {
/* when I and D space are separate, these will need to be fixed. */
case PTRACE_PEEKTEXT: /* read word at location addr. */
case PTRACE_PEEKDATA:
ret = generic_ptrace_peekdata(child, addr, data);
break;
/* read the word at location addr in the USER area. */
case PTRACE_PEEKUSR: {
unsigned long tmp;
......@@ -154,12 +161,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
break;
}
/* when I and D space are separate, this will have to be fixed. */
case PTRACE_POKETEXT: /* write the word at location addr. */
case PTRACE_POKEDATA:
ret = generic_ptrace_pokedata(child, addr, data);
break;
case PTRACE_POKEUSR:
/* write the word at location addr in the USER area. We must
disallow any changes to certain SR bits or u_fpvalid, since
......@@ -191,58 +192,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
}
break;
case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
case PTRACE_CONT: { /* restart after signal. */
ret = -EIO;
if (!valid_signal(data))
break;
if (request == PTRACE_SYSCALL)
set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
else
clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
child->exit_code = data;
wake_up_process(child);
ret = 0;
break;
}
/*
* make the child exit. Best I can do is send it a sigkill.
* perhaps it should be put in the status that it wants to
* exit.
*/
case PTRACE_KILL: {
ret = 0;
if (child->exit_state == EXIT_ZOMBIE) /* already dead */
break;
child->exit_code = SIGKILL;
wake_up_process(child);
break;
}
case PTRACE_SINGLESTEP: { /* set the trap flag. */
struct pt_regs *regs;
ret = -EIO;
if (!valid_signal(data))
break;
clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
if ((child->ptrace & PT_DTRACE) == 0) {
/* Spurious delayed TF traps may occur */
child->ptrace |= PT_DTRACE;
}
regs = child->thread.uregs;
regs->sr |= SR_SSTEP; /* auto-resetting upon exception */
child->exit_code = data;
/* give it a chance to run. */
wake_up_process(child);
ret = 0;
break;
}
default:
ret = ptrace_request(child, request, addr, data);
break;
......@@ -273,38 +222,51 @@ asmlinkage int sh64_ptrace(long request, long pid, long addr, long data)
return sys_ptrace(request, pid, addr, data);
}
asmlinkage void syscall_trace(struct pt_regs *regs, int entryexit)
static inline int audit_arch(void)
{
struct task_struct *tsk = current;
int arch = EM_SH;
if (unlikely(current->audit_context) && entryexit)
audit_syscall_exit(AUDITSC_RESULT(regs->regs[9]),
regs->regs[9]);
#ifdef CONFIG_64BIT
arch |= __AUDIT_ARCH_64BIT;
#endif
#ifdef CONFIG_CPU_LITTLE_ENDIAN
arch |= __AUDIT_ARCH_LE;
#endif
if (!test_thread_flag(TIF_SYSCALL_TRACE) &&
!test_thread_flag(TIF_SINGLESTEP))
goto out;
if (!(tsk->ptrace & PT_PTRACED))
goto out;
ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) &&
!test_thread_flag(TIF_SINGLESTEP) ? 0x80 : 0));
/*
* this isn't the same as continuing with a signal, but it will do
* for normal use. strace only continues with a signal if the
* stopping signal is not SIGTRAP. -brl
*/
if (tsk->exit_code) {
send_sig(tsk->exit_code, tsk, 1);
tsk->exit_code = 0;
}
return arch;
}
out:
if (unlikely(current->audit_context) && !entryexit)
audit_syscall_entry(AUDIT_ARCH_SH, regs->regs[1],
asmlinkage long long do_syscall_trace_enter(struct pt_regs *regs)
{
long long ret = 0;
secure_computing(regs->regs[9]);
if (test_thread_flag(TIF_SYSCALL_TRACE) &&
tracehook_report_syscall_entry(regs))
/*
* Tracing decided this syscall should not happen.
* We'll return a bogus call number to get an ENOSYS
* error, but leave the original number in regs->regs[0].
*/
ret = -1LL;
if (unlikely(current->audit_context))
audit_syscall_entry(audit_arch(), regs->regs[1],
regs->regs[2], regs->regs[3],
regs->regs[4], regs->regs[5]);
return ret ?: regs->regs[9];
}
asmlinkage void do_syscall_trace_leave(struct pt_regs *regs)
{
if (unlikely(current->audit_context))
audit_syscall_exit(AUDITSC_RESULT(regs->regs[9]),
regs->regs[9]);
if (test_thread_flag(TIF_SYSCALL_TRACE))
tracehook_report_syscall_exit(regs, 0);
}
/* Called with interrupts disabled */
......@@ -338,5 +300,5 @@ asmlinkage void do_software_break_point(unsigned long long vec,
*/
void ptrace_disable(struct task_struct *child)
{
/* nothing to do.. */
user_disable_single_step(child);
}
......@@ -25,6 +25,7 @@
#include <linux/smp.h>
#include <linux/err.h>
#include <linux/debugfs.h>
#include <linux/crash_dump.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <asm/page.h>
......@@ -286,6 +287,25 @@ static void __init setup_memory(void)
extern void __init setup_memory(void);
#endif
/*
* Note: elfcorehdr_addr is not just limited to vmcore. It is also used by
* is_kdump_kernel() to determine if we are booting after a panic. Hence
* ifdef it under CONFIG_CRASH_DUMP and not CONFIG_PROC_VMCORE.
*/
#ifdef CONFIG_CRASH_DUMP
/* elfcorehdr= specifies the location of elf core header
* stored by the crashed kernel.
*/
static int __init parse_elfcorehdr(char *arg)
{
if (!arg)
return -EINVAL;
elfcorehdr_addr = memparse(arg, &arg);
return 0;
}
early_param("elfcorehdr", parse_elfcorehdr);
#endif
void __init setup_arch(char **cmdline_p)
{
enable_mmu();
......
......@@ -24,6 +24,7 @@
#include <linux/binfmts.h>
#include <linux/freezer.h>
#include <linux/io.h>
#include <linux/tracehook.h>
#include <asm/system.h>
#include <asm/ucontext.h>
#include <asm/uaccess.h>
......@@ -507,14 +508,13 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
switch (regs->regs[0]) {
case -ERESTART_RESTARTBLOCK:
case -ERESTARTNOHAND:
no_system_call_restart:
regs->regs[0] = -EINTR;
break;
case -ERESTARTSYS:
if (!(ka->sa.sa_flags & SA_RESTART)) {
regs->regs[0] = -EINTR;
break;
}
if (!(ka->sa.sa_flags & SA_RESTART))
goto no_system_call_restart;
/* fallthrough */
case -ERESTARTNOINTR:
regs->regs[0] = save_r0;
......@@ -589,12 +589,15 @@ static void do_signal(struct pt_regs *regs, unsigned int save_r0)
* clear the TIF_RESTORE_SIGMASK flag */
if (test_thread_flag(TIF_RESTORE_SIGMASK))
clear_thread_flag(TIF_RESTORE_SIGMASK);
tracehook_signal_handler(signr, &info, &ka, regs,
test_thread_flag(TIF_SINGLESTEP));
}
return;
}
no_signal:
no_signal:
/* Did we come from a system call? */
if (regs->tra >= 0) {
/* Restart the system call - no handlers present */
......@@ -618,9 +621,14 @@ static void do_signal(struct pt_regs *regs, unsigned int save_r0)
}
asmlinkage void do_notify_resume(struct pt_regs *regs, unsigned int save_r0,
__u32 thread_info_flags)
unsigned long thread_info_flags)
{
/* deal with pending signal delivery */
if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
if (thread_info_flags & _TIF_SIGPENDING)
do_signal(regs, save_r0);
if (thread_info_flags & _TIF_NOTIFY_RESUME) {
clear_thread_flag(TIF_NOTIFY_RESUME);
tracehook_notify_resume(regs);
}
}
......@@ -22,6 +22,7 @@
#include <linux/ptrace.h>
#include <linux/unistd.h>
#include <linux/stddef.h>
#include <linux/tracehook.h>
#include <asm/ucontext.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
......@@ -42,7 +43,84 @@
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset);
/*
* Note that 'init' is a special process: it doesn't get signals it doesn't
* want to handle. Thus you cannot kill init even with a SIGKILL even by
* mistake.
*
* Note that we go through the signals twice: once to check the signals that
* the kernel can handle, and then we build all the user-level signal handling
* stack-frames in one go after that.
*/
static int do_signal(struct pt_regs *regs, sigset_t *oldset)
{
siginfo_t info;
int signr;
struct k_sigaction ka;
/*
* We want the common case to go fast, which
* is why we may in certain cases get here from
* kernel mode. Just return without doing anything
* if so.
*/
if (!user_mode(regs))
return 1;
if (try_to_freeze())
goto no_signal;
if (test_thread_flag(TIF_RESTORE_SIGMASK))
oldset = &current->saved_sigmask;
else if (!oldset)
oldset = &current->blocked;
signr = get_signal_to_deliver(&info, &ka, regs, 0);
if (signr > 0) {
/* Whee! Actually deliver the signal. */
handle_signal(signr, &info, &ka, oldset, regs);
/*
* If a signal was successfully delivered, the saved sigmask
* is in its frame, and we can clear the TIF_RESTORE_SIGMASK
* flag.
*/
if (test_thread_flag(TIF_RESTORE_SIGMASK))
clear_thread_flag(TIF_RESTORE_SIGMASK);
tracehook_signal_handler(signr, &info, &ka, regs, 0);
return 1;
}
no_signal:
/* Did we come from a system call? */
if (regs->syscall_nr >= 0) {
/* Restart the system call - no handlers present */
switch (regs->regs[REG_RET]) {
case -ERESTARTNOHAND:
case -ERESTARTSYS:
case -ERESTARTNOINTR:
/* Decode Syscall # */
regs->regs[REG_RET] = regs->syscall_nr;
regs->pc -= 4;
break;
case -ERESTART_RESTARTBLOCK:
regs->regs[REG_RET] = __NR_restart_syscall;
regs->pc -= 4;
break;
}
}
/* No signal to deliver -- put the saved sigmask back */
if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
clear_thread_flag(TIF_RESTORE_SIGMASK);
sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
}
return 0;
}
/*
* Atomically swap in the new signal mask, and wait for a signal.
......@@ -643,14 +721,13 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
switch (regs->regs[REG_RET]) {
case -ERESTART_RESTARTBLOCK:
case -ERESTARTNOHAND:
no_system_call_restart:
regs->regs[REG_RET] = -EINTR;
break;
case -ERESTARTSYS:
if (!(ka->sa.sa_flags & SA_RESTART)) {
regs->regs[REG_RET] = -EINTR;
break;
}
if (!(ka->sa.sa_flags & SA_RESTART))
goto no_system_call_restart;
/* fallthrough */
case -ERESTARTNOINTR:
/* Decode syscall # */
......@@ -673,80 +750,13 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
spin_unlock_irq(&current->sighand->siglock);
}
/*
* Note that 'init' is a special process: it doesn't get signals it doesn't
* want to handle. Thus you cannot kill init even with a SIGKILL even by
* mistake.
*
* Note that we go through the signals twice: once to check the signals that
* the kernel can handle, and then we build all the user-level signal handling
* stack-frames in one go after that.
*/
int do_signal(struct pt_regs *regs, sigset_t *oldset)
asmlinkage void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags)
{
siginfo_t info;
int signr;
struct k_sigaction ka;
/*
* We want the common case to go fast, which
* is why we may in certain cases get here from
* kernel mode. Just return without doing anything
* if so.
*/
if (!user_mode(regs))
return 1;
if (try_to_freeze())
goto no_signal;
if (test_thread_flag(TIF_RESTORE_SIGMASK))
oldset = &current->saved_sigmask;
else if (!oldset)
oldset = &current->blocked;
signr = get_signal_to_deliver(&info, &ka, regs, 0);
if (signr > 0) {
/* Whee! Actually deliver the signal. */
handle_signal(signr, &info, &ka, oldset, regs);
if (thread_info_flags & _TIF_SIGPENDING)
do_signal(regs, 0);
/*
* If a signal was successfully delivered, the saved sigmask
* is in its frame, and we can clear the TIF_RESTORE_SIGMASK
* flag.
*/
if (test_thread_flag(TIF_RESTORE_SIGMASK))
clear_thread_flag(TIF_RESTORE_SIGMASK);
return 1;
if (thread_info_flags & _TIF_NOTIFY_RESUME) {
clear_thread_flag(TIF_NOTIFY_RESUME);
tracehook_notify_resume(regs);
}
no_signal:
/* Did we come from a system call? */
if (regs->syscall_nr >= 0) {
/* Restart the system call - no handlers present */
switch (regs->regs[REG_RET]) {
case -ERESTARTNOHAND:
case -ERESTARTSYS:
case -ERESTARTNOINTR:
/* Decode Syscall # */
regs->regs[REG_RET] = regs->syscall_nr;
regs->pc -= 4;
break;
case -ERESTART_RESTARTBLOCK:
regs->regs[REG_RET] = __NR_restart_syscall;
regs->pc -= 4;
break;
}
}
/* No signal to deliver -- put the saved sigmask back */
if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
clear_thread_flag(TIF_RESTORE_SIGMASK);
sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
}
return 0;
}
......@@ -237,7 +237,6 @@ choice
config CACHE_WRITEBACK
bool "Write-back"
depends on CPU_SH2A || CPU_SH3 || CPU_SH4 || CPU_SH5
config CACHE_WRITETHROUGH
bool "Write-through"
......
......@@ -5,12 +5,15 @@
obj-y := init.o extable_32.o consistent.o
ifndef CONFIG_CACHE_OFF
obj-$(CONFIG_CPU_SH2) += cache-sh2.o
obj-$(CONFIG_CPU_SH3) += cache-sh3.o
obj-$(CONFIG_CPU_SH4) += cache-sh4.o
obj-$(CONFIG_SH7705_CACHE_32KB) += cache-sh7705.o
cache-$(CONFIG_CPU_SH2) := cache-sh2.o
cache-$(CONFIG_CPU_SH2A) := cache-sh2a.o
cache-$(CONFIG_CPU_SH3) := cache-sh3.o
cache-$(CONFIG_CPU_SH4) := cache-sh4.o
cache-$(CONFIG_SH7705_CACHE_32KB) += cache-sh7705.o
endif
obj-y += $(cache-y)
mmu-y := tlb-nommu.o pg-nommu.o
mmu-$(CONFIG_MMU) := fault_32.o tlbflush_32.o ioremap_32.o
......
......@@ -2,6 +2,7 @@
* arch/sh/mm/cache-sh2.c
*
* Copyright (C) 2002 Paul Mundt
* Copyright (C) 2008 Yoshinori Sato
*
* Released under the terms of the GNU GPL v2.0.
*/
......@@ -24,8 +25,15 @@ void __flush_wback_region(void *start, int size)
end = ((unsigned long)start + size + L1_CACHE_BYTES-1)
& ~(L1_CACHE_BYTES-1);
for (v = begin; v < end; v+=L1_CACHE_BYTES) {
/* FIXME cache purge */
ctrl_outl((v & 0x1ffffc00), (v & 0x00000ff0) | 0x00000008);
unsigned long addr = CACHE_OC_ADDRESS_ARRAY | (v & 0x00000ff0);
int way;
for (way = 0; way < 4; way++) {
unsigned long data = ctrl_inl(addr | (way << 12));
if ((data & CACHE_PHYSADDR_MASK) == (v & CACHE_PHYSADDR_MASK)) {
data &= ~SH_CACHE_UPDATED;
ctrl_outl(data, addr | (way << 12));
}
}
}
}
......@@ -37,21 +45,40 @@ void __flush_purge_region(void *start, int size)
begin = (unsigned long)start & ~(L1_CACHE_BYTES-1);
end = ((unsigned long)start + size + L1_CACHE_BYTES-1)
& ~(L1_CACHE_BYTES-1);
for (v = begin; v < end; v+=L1_CACHE_BYTES) {
ctrl_outl((v & 0x1ffffc00), (v & 0x00000ff0) | 0x00000008);
}
for (v = begin; v < end; v+=L1_CACHE_BYTES)
ctrl_outl((v & CACHE_PHYSADDR_MASK),
CACHE_OC_ADDRESS_ARRAY | (v & 0x00000ff0) | 0x00000008);
}
void __flush_invalidate_region(void *start, int size)
{
#ifdef CONFIG_CACHE_WRITEBACK
/*
* SH-2 does not support individual line invalidation, only a
* global invalidate.
*/
unsigned long ccr;
unsigned long flags;
local_irq_save(flags);
jump_to_uncached();
ccr = ctrl_inl(CCR);
ccr |= CCR_CACHE_INVALIDATE;
ctrl_outl(ccr, CCR);
back_to_cached();
local_irq_restore(flags);
#else
unsigned long v;
unsigned long begin, end;
begin = (unsigned long)start & ~(L1_CACHE_BYTES-1);
end = ((unsigned long)start + size + L1_CACHE_BYTES-1)
& ~(L1_CACHE_BYTES-1);
for (v = begin; v < end; v+=L1_CACHE_BYTES) {
ctrl_outl((v & 0x1ffffc00), (v & 0x00000ff0) | 0x00000008);
}
}
for (v = begin; v < end; v+=L1_CACHE_BYTES)
ctrl_outl((v & CACHE_PHYSADDR_MASK),
CACHE_OC_ADDRESS_ARRAY | (v & 0x00000ff0) | 0x00000008);
#endif
}
/*
* arch/sh/mm/cache-sh2a.c
*
* Copyright (C) 2008 Yoshinori Sato
*
* Released under the terms of the GNU GPL v2.0.
*/
#include <linux/init.h>
#include <linux/mm.h>
#include <asm/cache.h>
#include <asm/addrspace.h>
#include <asm/processor.h>
#include <asm/cacheflush.h>
#include <asm/io.h>
void __flush_wback_region(void *start, int size)
{
unsigned long v;
unsigned long begin, end;
unsigned long flags;
begin = (unsigned long)start & ~(L1_CACHE_BYTES-1);
end = ((unsigned long)start + size + L1_CACHE_BYTES-1)
& ~(L1_CACHE_BYTES-1);
local_irq_save(flags);
jump_to_uncached();
for (v = begin; v < end; v+=L1_CACHE_BYTES) {
unsigned long addr = CACHE_OC_ADDRESS_ARRAY | (v & 0x000007f0);
int way;
for (way = 0; way < 4; way++) {
unsigned long data = ctrl_inl(addr | (way << 11));
if ((data & CACHE_PHYSADDR_MASK) == (v & CACHE_PHYSADDR_MASK)) {
data &= ~SH_CACHE_UPDATED;
ctrl_outl(data, addr | (way << 11));
}
}
}
back_to_cached();
local_irq_restore(flags);
}
void __flush_purge_region(void *start, int size)
{
unsigned long v;
unsigned long begin, end;
unsigned long flags;
begin = (unsigned long)start & ~(L1_CACHE_BYTES-1);
end = ((unsigned long)start + size + L1_CACHE_BYTES-1)
& ~(L1_CACHE_BYTES-1);
local_irq_save(flags);
jump_to_uncached();
for (v = begin; v < end; v+=L1_CACHE_BYTES) {
ctrl_outl((v & CACHE_PHYSADDR_MASK),
CACHE_OC_ADDRESS_ARRAY | (v & 0x000003f0) | 0x00000008);
}
back_to_cached();
local_irq_restore(flags);
}
void __flush_invalidate_region(void *start, int size)
{
unsigned long v;
unsigned long begin, end;
unsigned long flags;
begin = (unsigned long)start & ~(L1_CACHE_BYTES-1);
end = ((unsigned long)start + size + L1_CACHE_BYTES-1)
& ~(L1_CACHE_BYTES-1);
local_irq_save(flags);
jump_to_uncached();
#ifdef CONFIG_CACHE_WRITEBACK
ctrl_outl(ctrl_inl(CCR) | CCR_OCACHE_INVALIDATE, CCR);
/* I-cache invalidate */
for (v = begin; v < end; v+=L1_CACHE_BYTES) {
ctrl_outl((v & CACHE_PHYSADDR_MASK),
CACHE_IC_ADDRESS_ARRAY | (v & 0x000003f0) | 0x00000008);
}
#else
for (v = begin; v < end; v+=L1_CACHE_BYTES) {
ctrl_outl((v & CACHE_PHYSADDR_MASK),
CACHE_IC_ADDRESS_ARRAY | (v & 0x000003f0) | 0x00000008);
ctrl_outl((v & CACHE_PHYSADDR_MASK),
CACHE_OC_ADDRESS_ARRAY | (v & 0x000003f0) | 0x00000008);
}
#endif
back_to_cached();
local_irq_restore(flags);
}
/* WBack O-Cache and flush I-Cache */
void flush_icache_range(unsigned long start, unsigned long end)
{
unsigned long v;
unsigned long flags;
start = start & ~(L1_CACHE_BYTES-1);
end = (end + L1_CACHE_BYTES-1) & ~(L1_CACHE_BYTES-1);
local_irq_save(flags);
jump_to_uncached();
for (v = start; v < end; v+=L1_CACHE_BYTES) {
unsigned long addr = (v & 0x000007f0);
int way;
/* O-Cache writeback */
for (way = 0; way < 4; way++) {
unsigned long data = ctrl_inl(CACHE_OC_ADDRESS_ARRAY | addr | (way << 11));
if ((data & CACHE_PHYSADDR_MASK) == (v & CACHE_PHYSADDR_MASK)) {
data &= ~SH_CACHE_UPDATED;
ctrl_outl(data, CACHE_OC_ADDRESS_ARRAY | addr | (way << 11));
}
}
/* I-Cache invalidate */
ctrl_outl(addr,
CACHE_IC_ADDRESS_ARRAY | addr | 0x00000008);
}
back_to_cached();
local_irq_restore(flags);
}
......@@ -15,9 +15,7 @@
#include <asm/mmu_context.h>
/**
* sh64_tlb_init
*
* Perform initial setup for the DTLB and ITLB.
* sh64_tlb_init - Perform initial setup for the DTLB and ITLB.
*/
int __init sh64_tlb_init(void)
{
......@@ -46,9 +44,7 @@ int __init sh64_tlb_init(void)
}
/**
* sh64_next_free_dtlb_entry
*
* Find the next available DTLB entry
* sh64_next_free_dtlb_entry - Find the next available DTLB entry
*/
unsigned long long sh64_next_free_dtlb_entry(void)
{
......@@ -56,9 +52,7 @@ unsigned long long sh64_next_free_dtlb_entry(void)
}
/**
* sh64_get_wired_dtlb_entry
*
* Allocate a wired (locked-in) entry in the DTLB
* sh64_get_wired_dtlb_entry - Allocate a wired (locked-in) entry in the DTLB
*/
unsigned long long sh64_get_wired_dtlb_entry(void)
{
......@@ -71,12 +65,10 @@ unsigned long long sh64_get_wired_dtlb_entry(void)
}
/**
* sh64_put_wired_dtlb_entry
* sh64_put_wired_dtlb_entry - Free a wired (locked-in) entry in the DTLB.
*
* @entry: Address of TLB slot.
*
* Free a wired (locked-in) entry in the DTLB.
*
* Works like a stack, last one to allocate must be first one to free.
*/
int sh64_put_wired_dtlb_entry(unsigned long long entry)
......@@ -115,7 +107,7 @@ int sh64_put_wired_dtlb_entry(unsigned long long entry)
}
/**
* sh64_setup_tlb_slot
* sh64_setup_tlb_slot - Load up a translation in a wired slot.
*
* @config_addr: Address of TLB slot.
* @eaddr: Virtual address.
......@@ -154,7 +146,7 @@ inline void sh64_setup_tlb_slot(unsigned long long config_addr,
}
/**
* sh64_teardown_tlb_slot
* sh64_teardown_tlb_slot - Teardown a translation.
*
* @config_addr: Address of TLB slot.
*
......
......@@ -10,7 +10,7 @@
# Shamelessly cloned from ARM.
#
arch/sh/include/asm/machtypes.h: $(src)/gen-mach-types $(src)/mach-types
include/asm-sh/machtypes.h: $(src)/gen-mach-types $(src)/mach-types
@echo ' Generating $@'
$(Q)if [ ! -d arch/sh/include/asm ]; then mkdir -p arch/sh/include/asm; fi
$(Q)if [ ! -d include/asm-sh ]; then mkdir -p include/asm-sh; fi
$(Q)$(AWK) -f $^ > $@ || { rm -f $@; /bin/false; }
......@@ -2,7 +2,7 @@
* SEGA Dreamcast keyboard driver
* Based on drivers/usb/usbkbd.c
* Copyright YAEGASHI Takeshi, 2001
* Porting to 2.6 Copyright Adrian McMenamin, 2007
* Porting to 2.6 Copyright Adrian McMenamin, 2007, 2008
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
......@@ -45,39 +45,51 @@ struct dc_kbd {
};
static const unsigned short dc_kbd_keycode[NR_SCANCODES] = {
KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_A, KEY_B, KEY_C, KEY_D,
KEY_E, KEY_F, KEY_G, KEY_H, KEY_I, KEY_J, KEY_K, KEY_L,
KEY_M, KEY_N, KEY_O, KEY_P, KEY_Q, KEY_R, KEY_S, KEY_T,
KEY_U, KEY_V, KEY_W, KEY_X, KEY_Y, KEY_Z, KEY_1, KEY_2,
KEY_3, KEY_4, KEY_5, KEY_6, KEY_7, KEY_8, KEY_9, KEY_0,
KEY_ENTER, KEY_ESC, KEY_BACKSPACE, KEY_TAB, KEY_SPACE, KEY_MINUS, KEY_EQUAL, KEY_LEFTBRACE,
KEY_RIGHTBRACE, KEY_BACKSLASH, KEY_BACKSLASH, KEY_SEMICOLON, KEY_APOSTROPHE, KEY_GRAVE, KEY_COMMA,
KEY_DOT, KEY_SLASH, KEY_CAPSLOCK, KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, KEY_F6,
KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_A, KEY_B,
KEY_C, KEY_D, KEY_E, KEY_F, KEY_G, KEY_H, KEY_I, KEY_J, KEY_K, KEY_L,
KEY_M, KEY_N, KEY_O, KEY_P, KEY_Q, KEY_R, KEY_S, KEY_T, KEY_U, KEY_V,
KEY_W, KEY_X, KEY_Y, KEY_Z, KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6,
KEY_7, KEY_8, KEY_9, KEY_0, KEY_ENTER, KEY_ESC, KEY_BACKSPACE,
KEY_TAB, KEY_SPACE, KEY_MINUS, KEY_EQUAL, KEY_LEFTBRACE,
KEY_RIGHTBRACE, KEY_BACKSLASH, KEY_BACKSLASH, KEY_SEMICOLON,
KEY_APOSTROPHE, KEY_GRAVE, KEY_COMMA, KEY_DOT, KEY_SLASH,
KEY_CAPSLOCK, KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, KEY_F6,
KEY_F7, KEY_F8, KEY_F9, KEY_F10, KEY_F11, KEY_F12, KEY_SYSRQ,
KEY_SCROLLLOCK, KEY_PAUSE, KEY_INSERT, KEY_HOME, KEY_PAGEUP, KEY_DELETE,
KEY_END, KEY_PAGEDOWN, KEY_RIGHT, KEY_LEFT, KEY_DOWN, KEY_UP,
KEY_NUMLOCK, KEY_KPSLASH, KEY_KPASTERISK, KEY_KPMINUS, KEY_KPPLUS, KEY_KPENTER, KEY_KP1, KEY_KP2,
KEY_KP3, KEY_KP4, KEY_KP5, KEY_KP6, KEY_KP7, KEY_KP8, KEY_KP9, KEY_KP0, KEY_KPDOT,
KEY_102ND, KEY_COMPOSE, KEY_POWER, KEY_KPEQUAL, KEY_F13, KEY_F14, KEY_F15,
KEY_F16, KEY_F17, KEY_F18, KEY_F19, KEY_F20,
KEY_F21, KEY_F22, KEY_F23, KEY_F24, KEY_OPEN, KEY_HELP, KEY_PROPS, KEY_FRONT,
KEY_STOP, KEY_AGAIN, KEY_UNDO, KEY_CUT, KEY_COPY, KEY_PASTE, KEY_FIND, KEY_MUTE,
KEY_VOLUMEUP, KEY_VOLUMEDOWN, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_KPCOMMA, KEY_RESERVED, KEY_RO, KEY_KATAKANAHIRAGANA , KEY_YEN,
KEY_HENKAN, KEY_MUHENKAN, KEY_KPJPCOMMA, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
KEY_HANGEUL, KEY_HANJA, KEY_KATAKANA, KEY_HIRAGANA, KEY_ZENKAKUHANKAKU, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
KEY_LEFTCTRL, KEY_LEFTSHIFT, KEY_LEFTALT, KEY_LEFTMETA, KEY_RIGHTCTRL, KEY_RIGHTSHIFT, KEY_RIGHTALT, KEY_RIGHTMETA,
KEY_PLAYPAUSE, KEY_STOPCD, KEY_PREVIOUSSONG, KEY_NEXTSONG, KEY_EJECTCD, KEY_VOLUMEUP, KEY_VOLUMEDOWN, KEY_MUTE,
KEY_WWW, KEY_BACK, KEY_FORWARD, KEY_STOP, KEY_FIND, KEY_SCROLLUP, KEY_SCROLLDOWN, KEY_EDIT, KEY_SLEEP,
KEY_SCREENLOCK, KEY_REFRESH, KEY_CALC, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED
KEY_SCROLLLOCK, KEY_PAUSE, KEY_INSERT, KEY_HOME, KEY_PAGEUP,
KEY_DELETE, KEY_END, KEY_PAGEDOWN, KEY_RIGHT, KEY_LEFT, KEY_DOWN,
KEY_UP, KEY_NUMLOCK, KEY_KPSLASH, KEY_KPASTERISK, KEY_KPMINUS,
KEY_KPPLUS, KEY_KPENTER, KEY_KP1, KEY_KP2, KEY_KP3, KEY_KP4, KEY_KP5,
KEY_KP6, KEY_KP7, KEY_KP8, KEY_KP9, KEY_KP0, KEY_KPDOT, KEY_102ND,
KEY_COMPOSE, KEY_POWER, KEY_KPEQUAL, KEY_F13, KEY_F14, KEY_F15,
KEY_F16, KEY_F17, KEY_F18, KEY_F19, KEY_F20, KEY_F21, KEY_F22,
KEY_F23, KEY_F24, KEY_OPEN, KEY_HELP, KEY_PROPS, KEY_FRONT, KEY_STOP,
KEY_AGAIN, KEY_UNDO, KEY_CUT, KEY_COPY, KEY_PASTE, KEY_FIND, KEY_MUTE,
KEY_VOLUMEUP, KEY_VOLUMEDOWN, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
KEY_KPCOMMA, KEY_RESERVED, KEY_RO, KEY_KATAKANAHIRAGANA , KEY_YEN,
KEY_HENKAN, KEY_MUHENKAN, KEY_KPJPCOMMA, KEY_RESERVED, KEY_RESERVED,
KEY_RESERVED, KEY_HANGEUL, KEY_HANJA, KEY_KATAKANA, KEY_HIRAGANA,
KEY_ZENKAKUHANKAKU, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
KEY_RESERVED, KEY_RESERVED, KEY_LEFTCTRL, KEY_LEFTSHIFT, KEY_LEFTALT,
KEY_LEFTMETA, KEY_RIGHTCTRL, KEY_RIGHTSHIFT, KEY_RIGHTALT,
KEY_RIGHTMETA, KEY_PLAYPAUSE, KEY_STOPCD, KEY_PREVIOUSSONG,
KEY_NEXTSONG, KEY_EJECTCD, KEY_VOLUMEUP, KEY_VOLUMEDOWN, KEY_MUTE,
KEY_WWW, KEY_BACK, KEY_FORWARD, KEY_STOP, KEY_FIND, KEY_SCROLLUP,
KEY_SCROLLDOWN, KEY_EDIT, KEY_SLEEP, KEY_SCREENLOCK, KEY_REFRESH,
KEY_CALC, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED
};
static void dc_scan_kbd(struct dc_kbd *kbd)
......@@ -127,12 +139,12 @@ static void dc_scan_kbd(struct dc_kbd *kbd)
static void dc_kbd_callback(struct mapleq *mq)
{
struct maple_device *mapledev = mq->dev;
struct dc_kbd *kbd = mapledev->private_data;
struct dc_kbd *kbd = maple_get_drvdata(mapledev);
unsigned long *buf = mq->recvbuf;
/*
* We should always be getting the lock because the only
* time it may be locked if driver is in cleanup phase.
* We should always get the lock because the only
* time it may be locked is if the driver is in the cleanup phase.
*/
if (likely(mutex_trylock(&maple_keyb_mutex))) {
......@@ -145,106 +157,96 @@ static void dc_kbd_callback(struct mapleq *mq)
}
}
static int dc_kbd_connect(struct maple_device *mdev)
static int probe_maple_kbd(struct device *dev)
{
struct maple_device *mdev = to_maple_dev(dev);
struct maple_driver *mdrv = to_maple_driver(dev->driver);
int i, error;
struct dc_kbd *kbd;
struct input_dev *dev;
struct input_dev *idev;
if (!(mdev->function & MAPLE_FUNC_KEYBOARD))
return -EINVAL;
kbd = kzalloc(sizeof(struct dc_kbd), GFP_KERNEL);
dev = input_allocate_device();
if (!kbd || !dev) {
idev = input_allocate_device();
if (!kbd || !idev) {
error = -ENOMEM;
goto fail;
}
mdev->private_data = kbd;
kbd->dev = dev;
kbd->dev = idev;
memcpy(kbd->keycode, dc_kbd_keycode, sizeof(kbd->keycode));
dev->name = mdev->product_name;
dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
dev->keycode = kbd->keycode;
dev->keycodesize = sizeof (unsigned short);
dev->keycodemax = ARRAY_SIZE(kbd->keycode);
dev->id.bustype = BUS_HOST;
dev->dev.parent = &mdev->dev;
idev->name = mdev->product_name;
idev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
idev->keycode = kbd->keycode;
idev->keycodesize = sizeof(unsigned short);
idev->keycodemax = ARRAY_SIZE(kbd->keycode);
idev->id.bustype = BUS_HOST;
idev->dev.parent = &mdev->dev;
for (i = 0; i < NR_SCANCODES; i++)
__set_bit(dc_kbd_keycode[i], dev->keybit);
__clear_bit(KEY_RESERVED, dev->keybit);
__set_bit(dc_kbd_keycode[i], idev->keybit);
__clear_bit(KEY_RESERVED, idev->keybit);
input_set_capability(dev, EV_MSC, MSC_SCAN);
input_set_drvdata(dev, kbd);
input_set_capability(idev, EV_MSC, MSC_SCAN);
input_set_drvdata(idev, kbd);
error = input_register_device(dev);
error = input_register_device(idev);
if (error)
goto fail;
/* Maple polling is locked to VBLANK - which may be just 50/s */
maple_getcond_callback(mdev, dc_kbd_callback, HZ/50, MAPLE_FUNC_KEYBOARD);
return 0;
maple_getcond_callback(mdev, dc_kbd_callback, HZ/50,
MAPLE_FUNC_KEYBOARD);
fail:
input_free_device(dev);
mdev->driver = mdrv;
maple_set_drvdata(mdev, kbd);
return error;
fail:
input_free_device(idev);
kfree(kbd);
mdev->private_data = NULL;
maple_set_drvdata(mdev, NULL);
return error;
}
static void dc_kbd_disconnect(struct maple_device *mdev)
static int remove_maple_kbd(struct device *dev)
{
struct dc_kbd *kbd;
struct maple_device *mdev = to_maple_dev(dev);
struct dc_kbd *kbd = maple_get_drvdata(mdev);
mutex_lock(&maple_keyb_mutex);
kbd = mdev->private_data;
mdev->private_data = NULL;
input_unregister_device(kbd->dev);
kfree(kbd);
mutex_unlock(&maple_keyb_mutex);
}
/* allow the keyboard to be used */
static int probe_maple_kbd(struct device *dev)
{
struct maple_device *mdev = to_maple_dev(dev);
struct maple_driver *mdrv = to_maple_driver(dev->driver);
int error;
error = dc_kbd_connect(mdev);
if (error)
return error;
mdev->driver = mdrv;
mdev->registered = 1;
maple_set_drvdata(mdev, NULL);
mutex_unlock(&maple_keyb_mutex);
return 0;
}
static struct maple_driver dc_kbd_driver = {
.function = MAPLE_FUNC_KEYBOARD,
.connect = dc_kbd_connect,
.disconnect = dc_kbd_disconnect,
.drv = {
.name = "Dreamcast_keyboard",
.probe = probe_maple_kbd,
},
.remove = remove_maple_kbd,
},
};
static int __init dc_kbd_init(void)
{
return maple_driver_register(&dc_kbd_driver.drv);
return maple_driver_register(&dc_kbd_driver);
}
static void __exit dc_kbd_exit(void)
{
driver_unregister(&dc_kbd_driver.drv);
maple_driver_unregister(&dc_kbd_driver);
}
module_init(dc_kbd_init);
......
......@@ -19,7 +19,7 @@
#include <asm/system.h>
#include <asm/io.h>
#include <asm/se.h>
#include <mach-se/mach/se.h>
#include <asm/machvec.h>
#ifdef CONFIG_SH_STANDARD_BIOS
#include <asm/sh_bios.h>
......
......@@ -2,6 +2,7 @@
* Core maple bus functionality
*
* Copyright (C) 2007, 2008 Adrian McMenamin
* Copyright (C) 2001 - 2008 Paul Mundt
*
* Based on 2.4 code by:
*
......@@ -31,7 +32,7 @@
#include <mach/dma.h>
#include <mach/sysasic.h>
MODULE_AUTHOR("Yaegshi Takeshi, Paul Mundt, M.R. Brown, Adrian McMenamin");
MODULE_AUTHOR("Yaegashi Takeshi, Paul Mundt, M. R. Brown, Adrian McMenamin");
MODULE_DESCRIPTION("Maple bus driver for Dreamcast");
MODULE_LICENSE("GPL v2");
MODULE_SUPPORTED_DEVICE("{{SEGA, Dreamcast/Maple}}");
......@@ -65,19 +66,36 @@ static bool checked[4];
static struct maple_device *baseunits[4];
/**
* maple_driver_register - register a device driver
* automatically makes the driver bus a maple bus
* @drv: the driver to be registered
* maple_driver_register - register a maple driver
* @drv: maple driver to be registered.
*
* Registers the passed in @drv, while updating the bus type.
* Devices with matching function IDs will be automatically probed.
*/
int maple_driver_register(struct device_driver *drv)
int maple_driver_register(struct maple_driver *drv)
{
if (!drv)
return -EINVAL;
drv->bus = &maple_bus_type;
return driver_register(drv);
drv->drv.bus = &maple_bus_type;
return driver_register(&drv->drv);
}
EXPORT_SYMBOL_GPL(maple_driver_register);
/**
* maple_driver_unregister - unregister a maple driver.
* @drv: maple driver to unregister.
*
* Cleans up after maple_driver_register(). To be invoked in the exit
* path of any module drivers.
*/
void maple_driver_unregister(struct maple_driver *drv)
{
driver_unregister(&drv->drv);
}
EXPORT_SYMBOL_GPL(maple_driver_unregister);
/* set hardware registers to enable next round of dma */
static void maplebus_dma_reset(void)
{
......@@ -129,13 +147,13 @@ static void maple_release_device(struct device *dev)
kfree(mdev);
}
/*
/**
* maple_add_packet - add a single instruction to the queue
* @mdev - maple device
* @function - function on device being queried
* @command - maple command to add
* @length - length of command string (in 32 bit words)
* @data - remainder of command string
* @mdev: maple device
* @function: function on device being queried
* @command: maple command to add
* @length: length of command string (in 32 bit words)
* @data: remainder of command string
*/
int maple_add_packet(struct maple_device *mdev, u32 function, u32 command,
size_t length, void *data)
......@@ -176,14 +194,15 @@ int maple_add_packet(struct maple_device *mdev, u32 function, u32 command,
}
EXPORT_SYMBOL_GPL(maple_add_packet);
/*
/**
* maple_add_packet_sleeps - add a single instruction to the queue
* - waits for lock to be free
* @mdev - maple device
* @function - function on device being queried
* @command - maple command to add
* @length - length of command string (in 32 bit words)
* @data - remainder of command string
* @mdev: maple device
* @function: function on device being queried
* @command: maple command to add
* @length: length of command string (in 32 bit words)
* @data: remainder of command string
*
* Same as maple_add_packet(), but waits for the lock to become free.
*/
int maple_add_packet_sleeps(struct maple_device *mdev, u32 function,
u32 command, size_t length, void *data)
......@@ -724,11 +743,9 @@ static int maple_get_dma_buffer(void)
static int match_maple_bus_driver(struct device *devptr,
struct device_driver *drvptr)
{
struct maple_driver *maple_drv;
struct maple_device *maple_dev;
struct maple_driver *maple_drv = to_maple_driver(drvptr);
struct maple_device *maple_dev = to_maple_dev(devptr);
maple_drv = container_of(drvptr, struct maple_driver, drv);
maple_dev = container_of(devptr, struct maple_device, dev);
/* Trap empty port case */
if (maple_dev->devinfo.function == 0xFFFFFFFF)
return 0;
......
......@@ -51,7 +51,6 @@ struct maple_devinfo {
struct maple_device {
struct maple_driver *driver;
struct mapleq *mq;
void *private_data;
void (*callback) (struct mapleq * mq);
unsigned long when, interval, function;
struct maple_devinfo devinfo;
......@@ -70,7 +69,9 @@ void maple_getcond_callback(struct maple_device *dev,
void (*callback) (struct mapleq * mq),
unsigned long interval,
unsigned long function);
int maple_driver_register(struct device_driver *drv);
int maple_driver_register(struct maple_driver *);
void maple_driver_unregister(struct maple_driver *);
int maple_add_packet_sleeps(struct maple_device *mdev, u32 function,
u32 command, u32 length, void *data);
void maple_clear_dev(struct maple_device *mdev);
......@@ -78,4 +79,7 @@ void maple_clear_dev(struct maple_device *mdev);
#define to_maple_dev(n) container_of(n, struct maple_device, dev)
#define to_maple_driver(n) container_of(n, struct maple_driver, drv)
#define maple_get_drvdata(d) dev_get_drvdata(&(d)->dev)
#define maple_set_drvdata(d,p) dev_set_drvdata(&(d)->dev, (p))
#endif /* __LINUX_MAPLE_H */
......@@ -266,6 +266,27 @@ void *vmalloc_node(unsigned long size, int node)
}
EXPORT_SYMBOL(vmalloc_node);
#ifndef PAGE_KERNEL_EXEC
# define PAGE_KERNEL_EXEC PAGE_KERNEL
#endif
/**
* vmalloc_exec - allocate virtually contiguous, executable memory
* @size: allocation size
*
* Kernel-internal function to allocate enough pages to cover @size
* the page level allocator and map them into contiguous and
* executable kernel virtual space.
*
* For tight control over page level allocator and protection flags
* use __vmalloc() instead.
*/
void *vmalloc_exec(unsigned long size)
{
return __vmalloc(size, GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL_EXEC);
}
/**
* vmalloc_32 - allocate virtually contiguous memory (32bit addressable)
* @size: allocation size
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment