You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-2.6-mn10300
* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-2.6-mn10300: MN10300: gcc 4.6 vs am33 inline assembly MN10300: Deprecate gdbstub MN10300: Allow KGDB to use the MN10300 serial ports MN10300: Emulate single stepping in KGDB on MN10300 MN10300: Generalise kernel debugger kernel halt, reboot or power off hook KGDB: Notify GDB of machine halt, reboot or power off MN10300: Use KGDB MN10300: Create generic kernel debugger hooks MN10300: Create general kernel debugger cache flushing MN10300: Introduce a general config option for kernel debugger hooks MN10300: The icache invalidate functions should disable the icache first MN10300: gdbstub: Restrict single-stepping to non-preemptable non-SMP configs
This commit is contained in:
@@ -3,6 +3,8 @@ config MN10300
|
|||||||
select HAVE_OPROFILE
|
select HAVE_OPROFILE
|
||||||
select HAVE_GENERIC_HARDIRQS
|
select HAVE_GENERIC_HARDIRQS
|
||||||
select GENERIC_HARDIRQS_NO_DEPRECATED
|
select GENERIC_HARDIRQS_NO_DEPRECATED
|
||||||
|
select HAVE_ARCH_TRACEHOOK
|
||||||
|
select HAVE_ARCH_KGDB
|
||||||
|
|
||||||
config AM33_2
|
config AM33_2
|
||||||
def_bool n
|
def_bool n
|
||||||
@@ -401,9 +403,9 @@ comment "[!] NOTE: A lower number/level indicates a higher priority (0 is highes
|
|||||||
comment "____Non-maskable interrupt levels____"
|
comment "____Non-maskable interrupt levels____"
|
||||||
comment "The following must be set to a higher priority than local_irq_disable() and on-chip serial"
|
comment "The following must be set to a higher priority than local_irq_disable() and on-chip serial"
|
||||||
|
|
||||||
config GDBSTUB_IRQ_LEVEL
|
config DEBUGGER_IRQ_LEVEL
|
||||||
int "GDBSTUB interrupt priority"
|
int "DEBUGGER interrupt priority"
|
||||||
depends on GDBSTUB
|
depends on KERNEL_DEBUGGER
|
||||||
range 0 1 if LINUX_CLI_LEVEL = 2
|
range 0 1 if LINUX_CLI_LEVEL = 2
|
||||||
range 0 2 if LINUX_CLI_LEVEL = 3
|
range 0 2 if LINUX_CLI_LEVEL = 3
|
||||||
range 0 3 if LINUX_CLI_LEVEL = 4
|
range 0 3 if LINUX_CLI_LEVEL = 4
|
||||||
@@ -437,7 +439,7 @@ config LINUX_CLI_LEVEL
|
|||||||
EPSW.IM from 7. Any interrupt is permitted for which the level is
|
EPSW.IM from 7. Any interrupt is permitted for which the level is
|
||||||
lower than EPSW.IM.
|
lower than EPSW.IM.
|
||||||
|
|
||||||
Certain interrupts, such as GDBSTUB and virtual MN10300 on-chip
|
Certain interrupts, such as DEBUGGER and virtual MN10300 on-chip
|
||||||
serial DMA interrupts are allowed to interrupt normal disabled
|
serial DMA interrupts are allowed to interrupt normal disabled
|
||||||
sections.
|
sections.
|
||||||
|
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ config KPROBES
|
|||||||
|
|
||||||
config GDBSTUB
|
config GDBSTUB
|
||||||
bool "Remote GDB kernel debugging"
|
bool "Remote GDB kernel debugging"
|
||||||
depends on DEBUG_KERNEL
|
depends on DEBUG_KERNEL && DEPRECATED
|
||||||
select DEBUG_INFO
|
select DEBUG_INFO
|
||||||
select FRAME_POINTER
|
select FRAME_POINTER
|
||||||
help
|
help
|
||||||
@@ -46,6 +46,9 @@ config GDBSTUB
|
|||||||
RAM to avoid excessive linking time. This is only useful for kernel
|
RAM to avoid excessive linking time. This is only useful for kernel
|
||||||
hackers. If unsure, say N.
|
hackers. If unsure, say N.
|
||||||
|
|
||||||
|
This is deprecated in favour of KGDB and will be removed in a later
|
||||||
|
version.
|
||||||
|
|
||||||
config GDBSTUB_IMMEDIATE
|
config GDBSTUB_IMMEDIATE
|
||||||
bool "Break into GDB stub immediately"
|
bool "Break into GDB stub immediately"
|
||||||
depends on GDBSTUB
|
depends on GDBSTUB
|
||||||
@@ -54,6 +57,14 @@ config GDBSTUB_IMMEDIATE
|
|||||||
possible, leaving the program counter at the beginning of
|
possible, leaving the program counter at the beginning of
|
||||||
start_kernel() in init/main.c.
|
start_kernel() in init/main.c.
|
||||||
|
|
||||||
|
config GDBSTUB_ALLOW_SINGLE_STEP
|
||||||
|
bool "Allow software single-stepping in GDB stub"
|
||||||
|
depends on GDBSTUB && !SMP && !PREEMPT
|
||||||
|
help
|
||||||
|
Allow GDB stub to perform software single-stepping through the
|
||||||
|
kernel. This doesn't work very well on SMP or preemptible kernels as
|
||||||
|
it uses temporary breakpoints to emulate single-stepping.
|
||||||
|
|
||||||
config GDB_CONSOLE
|
config GDB_CONSOLE
|
||||||
bool "Console output to GDB"
|
bool "Console output to GDB"
|
||||||
depends on GDBSTUB
|
depends on GDBSTUB
|
||||||
@@ -142,3 +153,7 @@ config GDBSTUB_ON_TTYSx
|
|||||||
default y
|
default y
|
||||||
|
|
||||||
endmenu
|
endmenu
|
||||||
|
|
||||||
|
config KERNEL_DEBUGGER
|
||||||
|
def_bool y
|
||||||
|
depends on GDBSTUB || KGDB
|
||||||
|
|||||||
@@ -0,0 +1,43 @@
|
|||||||
|
/* Kernel debugger for MN10300
|
||||||
|
*
|
||||||
|
* Copyright (C) 2011 Red Hat, Inc. All Rights Reserved.
|
||||||
|
* Written by David Howells (dhowells@redhat.com)
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public Licence
|
||||||
|
* as published by the Free Software Foundation; either version
|
||||||
|
* 2 of the Licence, or (at your option) any later version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _ASM_DEBUGGER_H
|
||||||
|
#define _ASM_DEBUGGER_H
|
||||||
|
|
||||||
|
#if defined(CONFIG_KERNEL_DEBUGGER)
|
||||||
|
|
||||||
|
extern int debugger_intercept(enum exception_code, int, int, struct pt_regs *);
|
||||||
|
extern int at_debugger_breakpoint(struct pt_regs *);
|
||||||
|
|
||||||
|
#ifndef CONFIG_MN10300_DEBUGGER_CACHE_NO_FLUSH
|
||||||
|
extern void debugger_local_cache_flushinv(void);
|
||||||
|
extern void debugger_local_cache_flushinv_one(u8 *);
|
||||||
|
#else
|
||||||
|
static inline void debugger_local_cache_flushinv(void) {}
|
||||||
|
static inline void debugger_local_cache_flushinv_one(u8 *addr) {}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#else /* CONFIG_KERNEL_DEBUGGER */
|
||||||
|
|
||||||
|
static inline int debugger_intercept(enum exception_code excep,
|
||||||
|
int signo, int si_code,
|
||||||
|
struct pt_regs *regs)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int at_debugger_breakpoint(struct pt_regs *regs)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* CONFIG_KERNEL_DEBUGGER */
|
||||||
|
#endif /* _ASM_DEBUGGER_H */
|
||||||
@@ -15,6 +15,19 @@
|
|||||||
|
|
||||||
extern void ____unhandled_size_in_do_div___(void);
|
extern void ____unhandled_size_in_do_div___(void);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Beginning with gcc 4.6, the MDR register is represented explicitly. We
|
||||||
|
* must, therefore, at least explicitly clobber the register when we make
|
||||||
|
* changes to it. The following assembly fragments *could* be rearranged in
|
||||||
|
* order to leave the moves to/from the MDR register to the compiler, but the
|
||||||
|
* gains would be minimal at best.
|
||||||
|
*/
|
||||||
|
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
|
||||||
|
# define CLOBBER_MDR_CC "mdr", "cc"
|
||||||
|
#else
|
||||||
|
# define CLOBBER_MDR_CC "cc"
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* divide n by base, leaving the result in n and returning the remainder
|
* divide n by base, leaving the result in n and returning the remainder
|
||||||
* - we can do this quite efficiently on the MN10300 by cascading the divides
|
* - we can do this quite efficiently on the MN10300 by cascading the divides
|
||||||
@@ -29,7 +42,7 @@ extern void ____unhandled_size_in_do_div___(void);
|
|||||||
"mov mdr,%1 \n" \
|
"mov mdr,%1 \n" \
|
||||||
: "+r"(n), "=d"(__rem) \
|
: "+r"(n), "=d"(__rem) \
|
||||||
: "r"(base), "1"(__rem) \
|
: "r"(base), "1"(__rem) \
|
||||||
: "cc" \
|
: CLOBBER_MDR_CC \
|
||||||
); \
|
); \
|
||||||
} else if (sizeof(n) <= 8) { \
|
} else if (sizeof(n) <= 8) { \
|
||||||
union { \
|
union { \
|
||||||
@@ -48,7 +61,7 @@ extern void ____unhandled_size_in_do_div___(void);
|
|||||||
: "=d"(__rem), "=r"(__quot.w[1]), "=r"(__quot.w[0]) \
|
: "=d"(__rem), "=r"(__quot.w[1]), "=r"(__quot.w[0]) \
|
||||||
: "r"(base), "0"(__rem), "1"(__quot.w[1]), \
|
: "r"(base), "0"(__rem), "1"(__quot.w[1]), \
|
||||||
"2"(__quot.w[0]) \
|
"2"(__quot.w[0]) \
|
||||||
: "cc" \
|
: CLOBBER_MDR_CC \
|
||||||
); \
|
); \
|
||||||
n = __quot.l; \
|
n = __quot.l; \
|
||||||
} else { \
|
} else { \
|
||||||
@@ -72,7 +85,7 @@ unsigned __muldiv64u(unsigned val, unsigned mult, unsigned div)
|
|||||||
* MDR = MDR:val%div */
|
* MDR = MDR:val%div */
|
||||||
: "=r"(result)
|
: "=r"(result)
|
||||||
: "0"(val), "ir"(mult), "r"(div)
|
: "0"(val), "ir"(mult), "r"(div)
|
||||||
: "cc"
|
: CLOBBER_MDR_CC
|
||||||
);
|
);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@@ -93,7 +106,7 @@ signed __muldiv64s(signed val, signed mult, signed div)
|
|||||||
* MDR = MDR:val%div */
|
* MDR = MDR:val%div */
|
||||||
: "=r"(result)
|
: "=r"(result)
|
||||||
: "0"(val), "ir"(mult), "r"(div)
|
: "0"(val), "ir"(mult), "r"(div)
|
||||||
: "cc"
|
: CLOBBER_MDR_CC
|
||||||
);
|
);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
@@ -55,7 +55,6 @@ static inline void clear_using_fpu(struct task_struct *tsk)
|
|||||||
|
|
||||||
extern asmlinkage void fpu_kill_state(struct task_struct *);
|
extern asmlinkage void fpu_kill_state(struct task_struct *);
|
||||||
extern asmlinkage void fpu_exception(struct pt_regs *, enum exception_code);
|
extern asmlinkage void fpu_exception(struct pt_regs *, enum exception_code);
|
||||||
extern asmlinkage void fpu_invalid_op(struct pt_regs *, enum exception_code);
|
|
||||||
extern asmlinkage void fpu_init_state(void);
|
extern asmlinkage void fpu_init_state(void);
|
||||||
extern asmlinkage void fpu_save(struct fpu_state_struct *);
|
extern asmlinkage void fpu_save(struct fpu_state_struct *);
|
||||||
extern int fpu_setup_sigcontext(struct fpucontext *buf);
|
extern int fpu_setup_sigcontext(struct fpucontext *buf);
|
||||||
@@ -113,7 +112,6 @@ static inline void flush_fpu(void)
|
|||||||
|
|
||||||
extern asmlinkage
|
extern asmlinkage
|
||||||
void unexpected_fpu_exception(struct pt_regs *, enum exception_code);
|
void unexpected_fpu_exception(struct pt_regs *, enum exception_code);
|
||||||
#define fpu_invalid_op unexpected_fpu_exception
|
|
||||||
#define fpu_exception unexpected_fpu_exception
|
#define fpu_exception unexpected_fpu_exception
|
||||||
|
|
||||||
struct task_struct;
|
struct task_struct;
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
/*
|
/*
|
||||||
* interrupt control
|
* interrupt control
|
||||||
* - "disabled": run in IM1/2
|
* - "disabled": run in IM1/2
|
||||||
* - level 0 - GDB stub
|
* - level 0 - kernel debugger
|
||||||
* - level 1 - virtual serial DMA (if present)
|
* - level 1 - virtual serial DMA (if present)
|
||||||
* - level 5 - normal interrupt priority
|
* - level 5 - normal interrupt priority
|
||||||
* - level 6 - timer interrupt
|
* - level 6 - timer interrupt
|
||||||
|
|||||||
@@ -0,0 +1,81 @@
|
|||||||
|
/* Kernel debugger for MN10300
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 Red Hat, Inc. All Rights Reserved.
|
||||||
|
* Written by David Howells (dhowells@redhat.com)
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public Licence
|
||||||
|
* as published by the Free Software Foundation; either version
|
||||||
|
* 2 of the Licence, or (at your option) any later version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _ASM_KGDB_H
|
||||||
|
#define _ASM_KGDB_H
|
||||||
|
|
||||||
|
/*
|
||||||
|
* BUFMAX defines the maximum number of characters in inbound/outbound
|
||||||
|
* buffers at least NUMREGBYTES*2 are needed for register packets
|
||||||
|
* Longer buffer is needed to list all threads
|
||||||
|
*/
|
||||||
|
#define BUFMAX 1024
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Note that this register image is in a different order than the register
|
||||||
|
* image that Linux produces at interrupt time.
|
||||||
|
*/
|
||||||
|
enum regnames {
|
||||||
|
GDB_FR_D0 = 0,
|
||||||
|
GDB_FR_D1 = 1,
|
||||||
|
GDB_FR_D2 = 2,
|
||||||
|
GDB_FR_D3 = 3,
|
||||||
|
GDB_FR_A0 = 4,
|
||||||
|
GDB_FR_A1 = 5,
|
||||||
|
GDB_FR_A2 = 6,
|
||||||
|
GDB_FR_A3 = 7,
|
||||||
|
|
||||||
|
GDB_FR_SP = 8,
|
||||||
|
GDB_FR_PC = 9,
|
||||||
|
GDB_FR_MDR = 10,
|
||||||
|
GDB_FR_EPSW = 11,
|
||||||
|
GDB_FR_LIR = 12,
|
||||||
|
GDB_FR_LAR = 13,
|
||||||
|
GDB_FR_MDRQ = 14,
|
||||||
|
|
||||||
|
GDB_FR_E0 = 15,
|
||||||
|
GDB_FR_E1 = 16,
|
||||||
|
GDB_FR_E2 = 17,
|
||||||
|
GDB_FR_E3 = 18,
|
||||||
|
GDB_FR_E4 = 19,
|
||||||
|
GDB_FR_E5 = 20,
|
||||||
|
GDB_FR_E6 = 21,
|
||||||
|
GDB_FR_E7 = 22,
|
||||||
|
|
||||||
|
GDB_FR_SSP = 23,
|
||||||
|
GDB_FR_MSP = 24,
|
||||||
|
GDB_FR_USP = 25,
|
||||||
|
GDB_FR_MCRH = 26,
|
||||||
|
GDB_FR_MCRL = 27,
|
||||||
|
GDB_FR_MCVF = 28,
|
||||||
|
|
||||||
|
GDB_FR_FPCR = 29,
|
||||||
|
GDB_FR_DUMMY0 = 30,
|
||||||
|
GDB_FR_DUMMY1 = 31,
|
||||||
|
|
||||||
|
GDB_FR_FS0 = 32,
|
||||||
|
|
||||||
|
GDB_FR_SIZE = 64,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define GDB_ORIG_D0 41
|
||||||
|
#define NUMREGBYTES (GDB_FR_SIZE*4)
|
||||||
|
|
||||||
|
static inline void arch_kgdb_breakpoint(void)
|
||||||
|
{
|
||||||
|
asm(".globl __arch_kgdb_breakpoint; __arch_kgdb_breakpoint: break");
|
||||||
|
}
|
||||||
|
extern u8 __arch_kgdb_breakpoint;
|
||||||
|
|
||||||
|
#define BREAK_INSTR_SIZE 1
|
||||||
|
#define CACHE_FLUSH_IS_SAFE 1
|
||||||
|
|
||||||
|
#endif /* _ASM_KGDB_H */
|
||||||
@@ -34,7 +34,7 @@
|
|||||||
#define LOCAL_TIMER_IPI 193
|
#define LOCAL_TIMER_IPI 193
|
||||||
#define FLUSH_CACHE_IPI 194
|
#define FLUSH_CACHE_IPI 194
|
||||||
#define CALL_FUNCTION_NMI_IPI 195
|
#define CALL_FUNCTION_NMI_IPI 195
|
||||||
#define GDB_NMI_IPI 196
|
#define DEBUGGER_NMI_IPI 196
|
||||||
|
|
||||||
#define SMP_BOOT_IRQ 195
|
#define SMP_BOOT_IRQ 195
|
||||||
|
|
||||||
@@ -43,6 +43,7 @@
|
|||||||
#define LOCAL_TIMER_GxICR_LV GxICR_LEVEL_4
|
#define LOCAL_TIMER_GxICR_LV GxICR_LEVEL_4
|
||||||
#define FLUSH_CACHE_GxICR_LV GxICR_LEVEL_0
|
#define FLUSH_CACHE_GxICR_LV GxICR_LEVEL_0
|
||||||
#define SMP_BOOT_GxICR_LV GxICR_LEVEL_0
|
#define SMP_BOOT_GxICR_LV GxICR_LEVEL_0
|
||||||
|
#define DEBUGGER_GxICR_LV CONFIG_DEBUGGER_IRQ_LEVEL
|
||||||
|
|
||||||
#define TIME_OUT_COUNT_BOOT_IPI 100
|
#define TIME_OUT_COUNT_BOOT_IPI 100
|
||||||
#define DELAY_TIME_BOOT_IPI 75000
|
#define DELAY_TIME_BOOT_IPI 75000
|
||||||
@@ -61,8 +62,9 @@
|
|||||||
* An alternate way of dealing with this could be to use the EPSW.S bits to
|
* An alternate way of dealing with this could be to use the EPSW.S bits to
|
||||||
* cache this information for systems with up to four CPUs.
|
* cache this information for systems with up to four CPUs.
|
||||||
*/
|
*/
|
||||||
|
#define arch_smp_processor_id() (CPUID)
|
||||||
#if 0
|
#if 0
|
||||||
#define raw_smp_processor_id() (CPUID)
|
#define raw_smp_processor_id() (arch_smp_processor_id())
|
||||||
#else
|
#else
|
||||||
#define raw_smp_processor_id() (current_thread_info()->cpu)
|
#define raw_smp_processor_id() (current_thread_info()->cpu)
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -131,7 +131,11 @@ static inline unsigned long current_stack_pointer(void)
|
|||||||
kmalloc_node(THREAD_SIZE, GFP_KERNEL, node)
|
kmalloc_node(THREAD_SIZE, GFP_KERNEL, node)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef CONFIG_KGDB
|
||||||
#define free_thread_info(ti) kfree((ti))
|
#define free_thread_info(ti) kfree((ti))
|
||||||
|
#else
|
||||||
|
extern void free_thread_info(struct thread_info *);
|
||||||
|
#endif
|
||||||
#define get_thread_info(ti) get_task_struct((ti)->task)
|
#define get_thread_info(ti) get_task_struct((ti)->task)
|
||||||
#define put_thread_info(ti) put_task_struct((ti)->task)
|
#define put_thread_info(ti) put_task_struct((ti)->task)
|
||||||
|
|
||||||
|
|||||||
@@ -21,11 +21,8 @@ obj-$(CONFIG_GDBSTUB) += gdb-stub.o gdb-low.o
|
|||||||
obj-$(CONFIG_GDBSTUB_ON_TTYSx) += gdb-io-serial.o gdb-io-serial-low.o
|
obj-$(CONFIG_GDBSTUB_ON_TTYSx) += gdb-io-serial.o gdb-io-serial-low.o
|
||||||
obj-$(CONFIG_GDBSTUB_ON_TTYSMx) += gdb-io-ttysm.o gdb-io-ttysm-low.o
|
obj-$(CONFIG_GDBSTUB_ON_TTYSMx) += gdb-io-ttysm.o gdb-io-ttysm-low.o
|
||||||
|
|
||||||
ifeq ($(CONFIG_MN10300_CACHE_ENABLED),y)
|
|
||||||
obj-$(CONFIG_GDBSTUB) += gdb-cache.o
|
|
||||||
endif
|
|
||||||
|
|
||||||
obj-$(CONFIG_MN10300_RTC) += rtc.o
|
obj-$(CONFIG_MN10300_RTC) += rtc.o
|
||||||
obj-$(CONFIG_PROFILE) += profile.o profile-low.o
|
obj-$(CONFIG_PROFILE) += profile.o profile-low.o
|
||||||
obj-$(CONFIG_MODULES) += module.o
|
obj-$(CONFIG_MODULES) += module.o
|
||||||
obj-$(CONFIG_KPROBES) += kprobes.o
|
obj-$(CONFIG_KPROBES) += kprobes.o
|
||||||
|
obj-$(CONFIG_KGDB) += kgdb.o
|
||||||
|
|||||||
+24
-41
@@ -266,7 +266,11 @@ ENTRY(raw_bus_error)
|
|||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
#
|
#
|
||||||
# Miscellaneous exception entry points
|
# NMI exception entry points
|
||||||
|
#
|
||||||
|
# This is used by ordinary interrupt channels that have the GxICR_NMI bit set
|
||||||
|
# in addition to the main NMI and Watchdog channels. SMP NMI IPIs use this
|
||||||
|
# facility.
|
||||||
#
|
#
|
||||||
###############################################################################
|
###############################################################################
|
||||||
ENTRY(nmi_handler)
|
ENTRY(nmi_handler)
|
||||||
@@ -281,7 +285,7 @@ ENTRY(nmi_handler)
|
|||||||
and NMIAGR_GN,d0
|
and NMIAGR_GN,d0
|
||||||
lsr 0x2,d0
|
lsr 0x2,d0
|
||||||
cmp CALL_FUNCTION_NMI_IPI,d0
|
cmp CALL_FUNCTION_NMI_IPI,d0
|
||||||
bne 5f # if not call function, jump
|
bne nmi_not_smp_callfunc # if not call function, jump
|
||||||
|
|
||||||
# function call nmi ipi
|
# function call nmi ipi
|
||||||
add 4,sp # no need to store TBR
|
add 4,sp # no need to store TBR
|
||||||
@@ -295,59 +299,38 @@ ENTRY(nmi_handler)
|
|||||||
call smp_nmi_call_function_interrupt[],0
|
call smp_nmi_call_function_interrupt[],0
|
||||||
RESTORE_ALL
|
RESTORE_ALL
|
||||||
|
|
||||||
5:
|
nmi_not_smp_callfunc:
|
||||||
#ifdef CONFIG_GDBSTUB
|
#ifdef CONFIG_KERNEL_DEBUGGER
|
||||||
cmp GDB_NMI_IPI,d0
|
cmp DEBUGGER_NMI_IPI,d0
|
||||||
bne 3f # if not gdb nmi ipi, jump
|
bne nmi_not_debugger # if not kernel debugger NMI IPI, jump
|
||||||
|
|
||||||
# gdb nmi ipi
|
# kernel debugger NMI IPI
|
||||||
add 4,sp # no need to store TBR
|
add 4,sp # no need to store TBR
|
||||||
mov GxICR_DETECT,d0 # clear NMI
|
mov GxICR_DETECT,d0 # clear NMI
|
||||||
movbu d0,(GxICR(GDB_NMI_IPI))
|
movbu d0,(GxICR(DEBUGGER_NMI_IPI))
|
||||||
movhu (GxICR(GDB_NMI_IPI)),d0
|
movhu (GxICR(DEBUGGER_NMI_IPI)),d0
|
||||||
and ~EPSW_NMID,epsw # enable NMI
|
and ~EPSW_NMID,epsw # enable NMI
|
||||||
#ifdef CONFIG_MN10300_CACHE_ENABLED
|
|
||||||
mov (gdbstub_nmi_opr_type),d0
|
|
||||||
cmp GDBSTUB_NMI_CACHE_PURGE,d0
|
|
||||||
bne 4f # if not gdb cache purge, jump
|
|
||||||
|
|
||||||
# gdb cache purge nmi ipi
|
|
||||||
add -20,sp
|
|
||||||
mov d1,(4,sp)
|
|
||||||
mov a0,(8,sp)
|
|
||||||
mov a1,(12,sp)
|
|
||||||
mov mdr,d0
|
|
||||||
mov d0,(16,sp)
|
|
||||||
call gdbstub_local_purge_cache[],0
|
|
||||||
mov 0x1,d0
|
|
||||||
mov (CPUID),d1
|
|
||||||
asl d1,d0
|
|
||||||
mov gdbstub_nmi_cpumask,a0
|
|
||||||
bclr d0,(a0)
|
|
||||||
mov (4,sp),d1
|
|
||||||
mov (8,sp),a0
|
|
||||||
mov (12,sp),a1
|
|
||||||
mov (16,sp),d0
|
|
||||||
mov d0,mdr
|
|
||||||
add 20,sp
|
|
||||||
mov (sp),d0
|
|
||||||
add 4,sp
|
|
||||||
rti
|
|
||||||
4:
|
|
||||||
#endif /* CONFIG_MN10300_CACHE_ENABLED */
|
|
||||||
# gdb wait nmi ipi
|
|
||||||
mov (sp),d0
|
mov (sp),d0
|
||||||
SAVE_ALL
|
SAVE_ALL
|
||||||
call gdbstub_nmi_wait[],0
|
mov fp,d0 # arg 0: stacked register file
|
||||||
|
mov a2,d1 # arg 1: exception number
|
||||||
|
call debugger_nmi_interrupt[],0
|
||||||
RESTORE_ALL
|
RESTORE_ALL
|
||||||
3:
|
|
||||||
#endif /* CONFIG_GDBSTUB */
|
nmi_not_debugger:
|
||||||
|
#endif /* CONFIG_KERNEL_DEBUGGER */
|
||||||
mov (sp),d0 # restore TBR to d0
|
mov (sp),d0 # restore TBR to d0
|
||||||
add 4,sp
|
add 4,sp
|
||||||
#endif /* CONFIG_SMP */
|
#endif /* CONFIG_SMP */
|
||||||
|
|
||||||
bra __common_exception_nonmi
|
bra __common_exception_nonmi
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
#
|
||||||
|
# General exception entry point
|
||||||
|
#
|
||||||
|
###############################################################################
|
||||||
ENTRY(__common_exception)
|
ENTRY(__common_exception)
|
||||||
add -4,sp
|
add -4,sp
|
||||||
mov d0,(sp)
|
mov d0,(sp)
|
||||||
|
|||||||
@@ -69,24 +69,6 @@ asmlinkage void fpu_exception(struct pt_regs *regs, enum exception_code code)
|
|||||||
force_sig_info(SIGFPE, &info, tsk);
|
force_sig_info(SIGFPE, &info, tsk);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* handle an FPU invalid_op exception
|
|
||||||
* - Derived from DO_EINFO() macro in arch/mn10300/kernel/traps.c
|
|
||||||
*/
|
|
||||||
asmlinkage void fpu_invalid_op(struct pt_regs *regs, enum exception_code code)
|
|
||||||
{
|
|
||||||
siginfo_t info;
|
|
||||||
|
|
||||||
if (!user_mode(regs))
|
|
||||||
die_if_no_fixup("FPU invalid opcode", regs, code);
|
|
||||||
|
|
||||||
info.si_signo = SIGILL;
|
|
||||||
info.si_errno = 0;
|
|
||||||
info.si_code = ILL_COPROC;
|
|
||||||
info.si_addr = (void *) regs->pc;
|
|
||||||
force_sig_info(info.si_signo, &info, current);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* save the FPU state to a signal context
|
* save the FPU state to a signal context
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,105 +0,0 @@
|
|||||||
###############################################################################
|
|
||||||
#
|
|
||||||
# MN10300 Low-level cache purging routines for gdbstub
|
|
||||||
#
|
|
||||||
# Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
|
|
||||||
# Written by David Howells (dhowells@redhat.com)
|
|
||||||
#
|
|
||||||
# This program is free software; you can redistribute it and/or
|
|
||||||
# modify it under the terms of the GNU General Public Licence
|
|
||||||
# as published by the Free Software Foundation; either version
|
|
||||||
# 2 of the Licence, or (at your option) any later version.
|
|
||||||
#
|
|
||||||
###############################################################################
|
|
||||||
#include <linux/sys.h>
|
|
||||||
#include <linux/linkage.h>
|
|
||||||
#include <asm/smp.h>
|
|
||||||
#include <asm/cache.h>
|
|
||||||
#include <asm/cpu-regs.h>
|
|
||||||
#include <asm/exceptions.h>
|
|
||||||
#include <asm/frame.inc>
|
|
||||||
#include <asm/serial-regs.h>
|
|
||||||
|
|
||||||
.text
|
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
#
|
|
||||||
# GDB stub cache purge
|
|
||||||
#
|
|
||||||
###############################################################################
|
|
||||||
.type gdbstub_purge_cache,@function
|
|
||||||
ENTRY(gdbstub_purge_cache)
|
|
||||||
#######################################################################
|
|
||||||
# read the addresses tagged in the cache's tag RAM and attempt to flush
|
|
||||||
# those addresses specifically
|
|
||||||
# - we rely on the hardware to filter out invalid tag entry addresses
|
|
||||||
mov DCACHE_TAG(0,0),a0 # dcache tag RAM access address
|
|
||||||
mov DCACHE_PURGE(0,0),a1 # dcache purge request address
|
|
||||||
mov L1_CACHE_NWAYS*L1_CACHE_NENTRIES,d1 # total number of entries
|
|
||||||
|
|
||||||
mn10300_dcache_flush_loop:
|
|
||||||
mov (a0),d0
|
|
||||||
and L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d0
|
|
||||||
or L1_CACHE_TAG_VALID,d0 # retain valid entries in the
|
|
||||||
# cache
|
|
||||||
mov d0,(a1) # conditional purge
|
|
||||||
|
|
||||||
mn10300_dcache_flush_skip:
|
|
||||||
add L1_CACHE_BYTES,a0
|
|
||||||
add L1_CACHE_BYTES,a1
|
|
||||||
add -1,d1
|
|
||||||
bne mn10300_dcache_flush_loop
|
|
||||||
|
|
||||||
;; # unconditionally flush and invalidate the dcache
|
|
||||||
;; mov DCACHE_PURGE(0,0),a1 # dcache purge request address
|
|
||||||
;; mov L1_CACHE_NWAYS*L1_CACHE_NENTRIES,d1 # total number of
|
|
||||||
;; # entries
|
|
||||||
;;
|
|
||||||
;; gdbstub_purge_cache__dcache_loop:
|
|
||||||
;; mov (a1),d0 # unconditional purge
|
|
||||||
;;
|
|
||||||
;; add L1_CACHE_BYTES,a1
|
|
||||||
;; add -1,d1
|
|
||||||
;; bne gdbstub_purge_cache__dcache_loop
|
|
||||||
|
|
||||||
#######################################################################
|
|
||||||
# now invalidate the icache
|
|
||||||
mov CHCTR,a0
|
|
||||||
movhu (a0),a1
|
|
||||||
|
|
||||||
mov epsw,d1
|
|
||||||
and ~EPSW_IE,epsw
|
|
||||||
nop
|
|
||||||
nop
|
|
||||||
|
|
||||||
# disable the icache
|
|
||||||
and ~CHCTR_ICEN,d0
|
|
||||||
movhu d0,(a0)
|
|
||||||
|
|
||||||
# and wait for it to calm down
|
|
||||||
setlb
|
|
||||||
movhu (a0),d0
|
|
||||||
btst CHCTR_ICBUSY,d0
|
|
||||||
lne
|
|
||||||
|
|
||||||
# invalidate
|
|
||||||
or CHCTR_ICINV,d0
|
|
||||||
movhu d0,(a0)
|
|
||||||
|
|
||||||
# wait for the cache to finish
|
|
||||||
mov CHCTR,a0
|
|
||||||
setlb
|
|
||||||
movhu (a0),d0
|
|
||||||
btst CHCTR_ICBUSY,d0
|
|
||||||
lne
|
|
||||||
|
|
||||||
# and reenable it
|
|
||||||
movhu a1,(a0)
|
|
||||||
movhu (a0),d0 # read back to flush
|
|
||||||
# (SIGILLs all over without this)
|
|
||||||
|
|
||||||
mov d1,epsw
|
|
||||||
|
|
||||||
ret [],0
|
|
||||||
|
|
||||||
.size gdbstub_purge_cache,.-gdbstub_purge_cache
|
|
||||||
@@ -59,10 +59,10 @@ void __init gdbstub_io_init(void)
|
|||||||
|
|
||||||
/* we want to get serial receive interrupts */
|
/* we want to get serial receive interrupts */
|
||||||
set_intr_level(gdbstub_port->rx_irq,
|
set_intr_level(gdbstub_port->rx_irq,
|
||||||
NUM2GxICR_LEVEL(CONFIG_GDBSTUB_IRQ_LEVEL));
|
NUM2GxICR_LEVEL(CONFIG_DEBUGGER_IRQ_LEVEL));
|
||||||
set_intr_level(gdbstub_port->tx_irq,
|
set_intr_level(gdbstub_port->tx_irq,
|
||||||
NUM2GxICR_LEVEL(CONFIG_GDBSTUB_IRQ_LEVEL));
|
NUM2GxICR_LEVEL(CONFIG_DEBUGGER_IRQ_LEVEL));
|
||||||
set_intr_stub(NUM2EXCEP_IRQ_LEVEL(CONFIG_GDBSTUB_IRQ_LEVEL),
|
set_intr_stub(NUM2EXCEP_IRQ_LEVEL(CONFIG_DEBUGGER_IRQ_LEVEL),
|
||||||
gdbstub_io_rx_handler);
|
gdbstub_io_rx_handler);
|
||||||
|
|
||||||
*gdbstub_port->rx_icr |= GxICR_ENABLE;
|
*gdbstub_port->rx_icr |= GxICR_ENABLE;
|
||||||
@@ -88,7 +88,7 @@ void __init gdbstub_io_init(void)
|
|||||||
|
|
||||||
/* permit level 0 IRQs only */
|
/* permit level 0 IRQs only */
|
||||||
arch_local_change_intr_mask_level(
|
arch_local_change_intr_mask_level(
|
||||||
NUM2EPSW_IM(CONFIG_GDBSTUB_IRQ_LEVEL + 1));
|
NUM2EPSW_IM(CONFIG_DEBUGGER_IRQ_LEVEL + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -133,7 +133,7 @@
|
|||||||
#include <asm/system.h>
|
#include <asm/system.h>
|
||||||
#include <asm/gdb-stub.h>
|
#include <asm/gdb-stub.h>
|
||||||
#include <asm/exceptions.h>
|
#include <asm/exceptions.h>
|
||||||
#include <asm/cacheflush.h>
|
#include <asm/debugger.h>
|
||||||
#include <asm/serial-regs.h>
|
#include <asm/serial-regs.h>
|
||||||
#include <asm/busctl-regs.h>
|
#include <asm/busctl-regs.h>
|
||||||
#include <unit/leds.h>
|
#include <unit/leds.h>
|
||||||
@@ -405,6 +405,7 @@ static int hexToInt(char **ptr, int *intValue)
|
|||||||
return (numChars);
|
return (numChars);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_GDBSTUB_ALLOW_SINGLE_STEP
|
||||||
/*
|
/*
|
||||||
* We single-step by setting breakpoints. When an exception
|
* We single-step by setting breakpoints. When an exception
|
||||||
* is handled, we need to restore the instructions hoisted
|
* is handled, we need to restore the instructions hoisted
|
||||||
@@ -729,6 +730,7 @@ static int gdbstub_single_step(struct pt_regs *regs)
|
|||||||
__gdbstub_restore_bp();
|
__gdbstub_restore_bp();
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
|
#endif /* CONFIG_GDBSTUB_ALLOW_SINGLE_STEP */
|
||||||
|
|
||||||
#ifdef CONFIG_GDBSTUB_CONSOLE
|
#ifdef CONFIG_GDBSTUB_CONSOLE
|
||||||
|
|
||||||
@@ -1171,7 +1173,7 @@ int gdbstub_clear_breakpoint(u8 *addr, int len)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* This function does all command processing for interfacing to gdb
|
* This function does all command processing for interfacing to gdb
|
||||||
* - returns 1 if the exception should be skipped, 0 otherwise.
|
* - returns 0 if the exception should be skipped, -ERROR otherwise.
|
||||||
*/
|
*/
|
||||||
static int gdbstub(struct pt_regs *regs, enum exception_code excep)
|
static int gdbstub(struct pt_regs *regs, enum exception_code excep)
|
||||||
{
|
{
|
||||||
@@ -1186,7 +1188,7 @@ static int gdbstub(struct pt_regs *regs, enum exception_code excep)
|
|||||||
int loop;
|
int loop;
|
||||||
|
|
||||||
if (excep == EXCEP_FPU_DISABLED)
|
if (excep == EXCEP_FPU_DISABLED)
|
||||||
return 0;
|
return -ENOTSUPP;
|
||||||
|
|
||||||
gdbstub_flush_caches = 0;
|
gdbstub_flush_caches = 0;
|
||||||
|
|
||||||
@@ -1195,7 +1197,7 @@ static int gdbstub(struct pt_regs *regs, enum exception_code excep)
|
|||||||
asm volatile("mov mdr,%0" : "=d"(mdr));
|
asm volatile("mov mdr,%0" : "=d"(mdr));
|
||||||
local_save_flags(epsw);
|
local_save_flags(epsw);
|
||||||
arch_local_change_intr_mask_level(
|
arch_local_change_intr_mask_level(
|
||||||
NUM2EPSW_IM(CONFIG_GDBSTUB_IRQ_LEVEL + 1));
|
NUM2EPSW_IM(CONFIG_DEBUGGER_IRQ_LEVEL + 1));
|
||||||
|
|
||||||
gdbstub_store_fpu();
|
gdbstub_store_fpu();
|
||||||
|
|
||||||
@@ -1208,11 +1210,13 @@ static int gdbstub(struct pt_regs *regs, enum exception_code excep)
|
|||||||
/* if we were single stepping, restore the opcodes hoisted for the
|
/* if we were single stepping, restore the opcodes hoisted for the
|
||||||
* breakpoint[s] */
|
* breakpoint[s] */
|
||||||
broke = 0;
|
broke = 0;
|
||||||
|
#ifdef CONFIG_GDBSTUB_ALLOW_SINGLE_STEP
|
||||||
if ((step_bp[0].addr && step_bp[0].addr == (u8 *) regs->pc) ||
|
if ((step_bp[0].addr && step_bp[0].addr == (u8 *) regs->pc) ||
|
||||||
(step_bp[1].addr && step_bp[1].addr == (u8 *) regs->pc))
|
(step_bp[1].addr && step_bp[1].addr == (u8 *) regs->pc))
|
||||||
broke = 1;
|
broke = 1;
|
||||||
|
|
||||||
__gdbstub_restore_bp();
|
__gdbstub_restore_bp();
|
||||||
|
#endif
|
||||||
|
|
||||||
if (gdbstub_rx_unget) {
|
if (gdbstub_rx_unget) {
|
||||||
sigval = SIGINT;
|
sigval = SIGINT;
|
||||||
@@ -1548,17 +1552,21 @@ packet_waiting:
|
|||||||
* Step to next instruction
|
* Step to next instruction
|
||||||
*/
|
*/
|
||||||
case 's':
|
case 's':
|
||||||
/*
|
/* Using the T flag doesn't seem to perform single
|
||||||
* using the T flag doesn't seem to perform single
|
|
||||||
* stepping (it seems to wind up being caught by the
|
* stepping (it seems to wind up being caught by the
|
||||||
* JTAG unit), so we have to use breakpoints and
|
* JTAG unit), so we have to use breakpoints and
|
||||||
* continue instead.
|
* continue instead.
|
||||||
*/
|
*/
|
||||||
|
#ifdef CONFIG_GDBSTUB_ALLOW_SINGLE_STEP
|
||||||
if (gdbstub_single_step(regs) < 0)
|
if (gdbstub_single_step(regs) < 0)
|
||||||
/* ignore any fault error for now */
|
/* ignore any fault error for now */
|
||||||
gdbstub_printk("unable to set single-step"
|
gdbstub_printk("unable to set single-step"
|
||||||
" bp\n");
|
" bp\n");
|
||||||
goto done;
|
goto done;
|
||||||
|
#else
|
||||||
|
gdbstub_strcpy(output_buffer, "E01");
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set baud rate (bBB)
|
* Set baud rate (bBB)
|
||||||
@@ -1657,7 +1665,7 @@ done:
|
|||||||
* NB: We flush both caches, just to be sure...
|
* NB: We flush both caches, just to be sure...
|
||||||
*/
|
*/
|
||||||
if (gdbstub_flush_caches)
|
if (gdbstub_flush_caches)
|
||||||
gdbstub_purge_cache();
|
debugger_local_cache_flushinv();
|
||||||
|
|
||||||
gdbstub_load_fpu();
|
gdbstub_load_fpu();
|
||||||
mn10300_set_gdbleds(0);
|
mn10300_set_gdbleds(0);
|
||||||
@@ -1667,14 +1675,23 @@ done:
|
|||||||
touch_softlockup_watchdog();
|
touch_softlockup_watchdog();
|
||||||
|
|
||||||
local_irq_restore(epsw);
|
local_irq_restore(epsw);
|
||||||
return 1;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Determine if we hit a debugger special breakpoint that needs skipping over
|
||||||
|
* automatically.
|
||||||
|
*/
|
||||||
|
int at_debugger_breakpoint(struct pt_regs *regs)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* handle event interception
|
* handle event interception
|
||||||
*/
|
*/
|
||||||
asmlinkage int gdbstub_intercept(struct pt_regs *regs,
|
asmlinkage int debugger_intercept(enum exception_code excep,
|
||||||
enum exception_code excep)
|
int signo, int si_code, struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
static u8 notfirst = 1;
|
static u8 notfirst = 1;
|
||||||
int ret;
|
int ret;
|
||||||
@@ -1688,7 +1705,7 @@ asmlinkage int gdbstub_intercept(struct pt_regs *regs,
|
|||||||
asm("mov mdr,%0" : "=d"(mdr));
|
asm("mov mdr,%0" : "=d"(mdr));
|
||||||
|
|
||||||
gdbstub_entry(
|
gdbstub_entry(
|
||||||
"--> gdbstub_intercept(%p,%04x) [MDR=%lx PC=%lx]\n",
|
"--> debugger_intercept(%p,%04x) [MDR=%lx PC=%lx]\n",
|
||||||
regs, excep, mdr, regs->pc);
|
regs, excep, mdr, regs->pc);
|
||||||
|
|
||||||
gdbstub_entry(
|
gdbstub_entry(
|
||||||
@@ -1722,7 +1739,7 @@ asmlinkage int gdbstub_intercept(struct pt_regs *regs,
|
|||||||
|
|
||||||
ret = gdbstub(regs, excep);
|
ret = gdbstub(regs, excep);
|
||||||
|
|
||||||
gdbstub_entry("<-- gdbstub_intercept()\n");
|
gdbstub_entry("<-- debugger_intercept()\n");
|
||||||
gdbstub_busy = 0;
|
gdbstub_busy = 0;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,13 @@ extern void ret_from_fork(struct task_struct *) __attribute__((noreturn));
|
|||||||
extern void mn10300_low_ipi_handler(void);
|
extern void mn10300_low_ipi_handler(void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* smp.c
|
||||||
|
*/
|
||||||
|
#ifdef CONFIG_SMP
|
||||||
|
extern void smp_jump_to_debugger(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* time.c
|
* time.c
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -153,7 +153,7 @@ mn10300_cpupic_setaffinity(struct irq_data *d, const struct cpumask *mask,
|
|||||||
case LOCAL_TIMER_IPI:
|
case LOCAL_TIMER_IPI:
|
||||||
case FLUSH_CACHE_IPI:
|
case FLUSH_CACHE_IPI:
|
||||||
case CALL_FUNCTION_NMI_IPI:
|
case CALL_FUNCTION_NMI_IPI:
|
||||||
case GDB_NMI_IPI:
|
case DEBUGGER_NMI_IPI:
|
||||||
#ifdef CONFIG_MN10300_TTYSM0
|
#ifdef CONFIG_MN10300_TTYSM0
|
||||||
case SC0RXIRQ:
|
case SC0RXIRQ:
|
||||||
case SC0TXIRQ:
|
case SC0TXIRQ:
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -119,6 +119,10 @@ static int mn10300_serial_request_port(struct uart_port *);
|
|||||||
static void mn10300_serial_config_port(struct uart_port *, int);
|
static void mn10300_serial_config_port(struct uart_port *, int);
|
||||||
static int mn10300_serial_verify_port(struct uart_port *,
|
static int mn10300_serial_verify_port(struct uart_port *,
|
||||||
struct serial_struct *);
|
struct serial_struct *);
|
||||||
|
#ifdef CONFIG_CONSOLE_POLL
|
||||||
|
static void mn10300_serial_poll_put_char(struct uart_port *, unsigned char);
|
||||||
|
static int mn10300_serial_poll_get_char(struct uart_port *);
|
||||||
|
#endif
|
||||||
|
|
||||||
static const struct uart_ops mn10300_serial_ops = {
|
static const struct uart_ops mn10300_serial_ops = {
|
||||||
.tx_empty = mn10300_serial_tx_empty,
|
.tx_empty = mn10300_serial_tx_empty,
|
||||||
@@ -138,6 +142,10 @@ static const struct uart_ops mn10300_serial_ops = {
|
|||||||
.request_port = mn10300_serial_request_port,
|
.request_port = mn10300_serial_request_port,
|
||||||
.config_port = mn10300_serial_config_port,
|
.config_port = mn10300_serial_config_port,
|
||||||
.verify_port = mn10300_serial_verify_port,
|
.verify_port = mn10300_serial_verify_port,
|
||||||
|
#ifdef CONFIG_CONSOLE_POLL
|
||||||
|
.poll_put_char = mn10300_serial_poll_put_char,
|
||||||
|
.poll_get_char = mn10300_serial_poll_get_char,
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
static irqreturn_t mn10300_serial_interrupt(int irq, void *dev_id);
|
static irqreturn_t mn10300_serial_interrupt(int irq, void *dev_id);
|
||||||
@@ -1634,3 +1642,70 @@ static int __init mn10300_serial_console_init(void)
|
|||||||
|
|
||||||
console_initcall(mn10300_serial_console_init);
|
console_initcall(mn10300_serial_console_init);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_CONSOLE_POLL
|
||||||
|
/*
|
||||||
|
* Polled character reception for the kernel debugger
|
||||||
|
*/
|
||||||
|
static int mn10300_serial_poll_get_char(struct uart_port *_port)
|
||||||
|
{
|
||||||
|
struct mn10300_serial_port *port =
|
||||||
|
container_of(_port, struct mn10300_serial_port, uart);
|
||||||
|
unsigned ix;
|
||||||
|
u8 st, ch;
|
||||||
|
|
||||||
|
_enter("%s", port->name);
|
||||||
|
|
||||||
|
do {
|
||||||
|
/* pull chars out of the hat */
|
||||||
|
ix = port->rx_outp;
|
||||||
|
if (ix == port->rx_inp)
|
||||||
|
return NO_POLL_CHAR;
|
||||||
|
|
||||||
|
ch = port->rx_buffer[ix++];
|
||||||
|
st = port->rx_buffer[ix++];
|
||||||
|
smp_rmb();
|
||||||
|
port->rx_outp = ix & (MNSC_BUFFER_SIZE - 1);
|
||||||
|
|
||||||
|
} while (st & (SC01STR_FEF | SC01STR_PEF | SC01STR_OEF));
|
||||||
|
|
||||||
|
return ch;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Polled character transmission for the kernel debugger
|
||||||
|
*/
|
||||||
|
static void mn10300_serial_poll_put_char(struct uart_port *_port,
|
||||||
|
unsigned char ch)
|
||||||
|
{
|
||||||
|
struct mn10300_serial_port *port =
|
||||||
|
container_of(_port, struct mn10300_serial_port, uart);
|
||||||
|
u8 intr, tmp;
|
||||||
|
|
||||||
|
/* wait for the transmitter to finish anything it might be doing (and
|
||||||
|
* this includes the virtual DMA handler, so it might take a while) */
|
||||||
|
while (*port->_status & (SC01STR_TBF | SC01STR_TXF))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* disable the Tx ready interrupt */
|
||||||
|
intr = *port->_intr;
|
||||||
|
*port->_intr = intr & ~SC01ICR_TI;
|
||||||
|
tmp = *port->_intr;
|
||||||
|
|
||||||
|
if (ch == 0x0a) {
|
||||||
|
*(u8 *) port->_txb = 0x0d;
|
||||||
|
while (*port->_status & SC01STR_TBF)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
*(u8 *) port->_txb = ch;
|
||||||
|
while (*port->_status & SC01STR_TBF)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* restore the Tx interrupt flag */
|
||||||
|
*port->_intr = intr;
|
||||||
|
tmp = *port->_intr;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* CONFIG_CONSOLE_POLL */
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ void release_segments(struct mm_struct *mm)
|
|||||||
|
|
||||||
void machine_restart(char *cmd)
|
void machine_restart(char *cmd)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_GDBSTUB
|
#ifdef CONFIG_KERNEL_DEBUGGER
|
||||||
gdbstub_exit(0);
|
gdbstub_exit(0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -148,14 +148,14 @@ void machine_restart(char *cmd)
|
|||||||
|
|
||||||
void machine_halt(void)
|
void machine_halt(void)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_GDBSTUB
|
#ifdef CONFIG_KERNEL_DEBUGGER
|
||||||
gdbstub_exit(0);
|
gdbstub_exit(0);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void machine_power_off(void)
|
void machine_power_off(void)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_GDBSTUB
|
#ifdef CONFIG_KERNEL_DEBUGGER
|
||||||
gdbstub_exit(0);
|
gdbstub_exit(0);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user