[PATCH 4/20] FRV: Fujitsu FR-V CPU arch implementation part 2

dhowells_at_redhat.com
Date: 11/08/04

  • Next message: dhowells_at_redhat.com: "[PATCH 17/20] FRV: Better mmap support in uClinux"
    Date:	Mon, 8 Nov 2004 14:34:17 GMT
    To: torvalds@osdl.org, akpm@osdl.org, davidm@snapgear.com
    
    

    The attached patches provides part 2 of an architecture implementation
    for the Fujitsu FR-V CPU series, configurably as Linux or uClinux.

    Signed-Off-By: dhowells@redhat.com

    ---
    diffstat frv-arch_2-2610rc1mm3.diff
     break.S       |  713 +++++++++++++++++++++++++++++
     cmode.S       |  190 +++++++
     debug-stub.c  |  259 ++++++++++
     dma.c         |  464 ++++++++++++++++++
     entry-table.S |  277 +++++++++++
     entry.S       | 1420 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
     6 files changed, 3323 insertions(+)
    diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/break.S linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/break.S
    --- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/break.S	1970-01-01 01:00:00.000000000 +0100
    +++ linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/break.S	2004-11-05 14:44:36.000000000 +0000
    @@ -0,0 +1,713 @@
    +/* break.S: Break interrupt handling (kept separate from entry.S)
    + *
    + * Copyright (C) 2003 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 License
    + * as published by the Free Software Foundation; either version
    + * 2 of the License, or (at your option) any later version.
    + */
    +
    +#include <linux/sys.h>
    +#include <linux/config.h>
    +#include <linux/linkage.h>
    +#include <asm/setup.h>
    +#include <asm/segment.h>
    +#include <asm/ptrace.h>
    +#include <asm/spr-regs.h>
    +
    +#include <asm/errno.h>
    +
    +#
    +# the break handler has its own stack
    +#
    +	.section	.bss.stack
    +	.globl		__break_user_context
    +	.balign		8192
    +__break_stack:
    +	.space		(8192 - (USER_CONTEXT_SIZE + REG__DEBUG_XTRA)) & ~7
    +__break_stack_tos:
    +	.space		REG__DEBUG_XTRA
    +__break_user_context:
    +	.space		USER_CONTEXT_SIZE
    +
    +#
    +# miscellaneous variables
    +#
    +	.section	.bss
    +#ifdef CONFIG_MMU
    +	.globl		__break_tlb_miss_real_return_info
    +__break_tlb_miss_real_return_info:
    +	.balign		8
    +	.space		2*4			/* saved PCSR, PSR for TLB-miss handler fixup */
    +#endif
    +
    +__break_trace_through_exceptions:
    +	.space		4
    +
    +#define CS2_ECS1	0xe1200000
    +#define CS2_USERLED	0x4
    +
    +.macro LEDS val,reg
    +#	sethi.p		%hi(CS2_ECS1+CS2_USERLED),gr30
    +#	setlo		%lo(CS2_ECS1+CS2_USERLED),gr30
    +#	setlos		#~\val,\reg
    +#	st		\reg,@(gr30,gr0)
    +#	setlos		#0x5555,\reg
    +#	sethi.p		%hi(0xffc00100),gr30
    +#	setlo		%lo(0xffc00100),gr30
    +#	sth		\reg,@(gr30,gr0)
    +#	membar
    +.endm
    +
    +###############################################################################
    +#
    +# entry point for Break Exceptions/Interrupts
    +#
    +###############################################################################
    +	.text
    +	.balign		4
    +	.globl		__entry_break
    +__entry_break:
    +#ifdef CONFIG_MMU
    +	movgs		gr31,scr3
    +#endif
    +	LEDS		0x1001,gr31
    +
    +	sethi.p		%hi(__break_user_context),gr31
    +	setlo		%lo(__break_user_context),gr31
    +
    +	stdi		gr2,@(gr31,#REG_GR(2))
    +	movsg		ccr,gr3
    +	sti		gr3,@(gr31,#REG_CCR)
    +
    +	# catch the return from a TLB-miss handler that had single-step disabled
    +	# traps will be enabled, so we have to do this now
    +#ifdef CONFIG_MMU
    +	movsg		bpcsr,gr3
    +	sethi.p		%hi(__break_tlb_miss_return_breaks_here),gr2
    +	setlo		%lo(__break_tlb_miss_return_breaks_here),gr2
    +	subcc		gr2,gr3,gr0,icc0
    +	beq		icc0,#2,__break_return_singlestep_tlbmiss
    +#endif
    +
    +	# determine whether we have stepped through into an exception
    +	# - we need to take special action to suspend h/w single stepping if we've done
    +	#   that, so that the gdbstub doesn't get bogged down endlessly stepping through
    +	#   external interrupt handling
    +	movsg		bpsr,gr3
    +	andicc		gr3,#BPSR_BET,gr0,icc0
    +	bne		icc0,#2,__break_maybe_userspace	/* jump if PSR.ET was 1 */
    +
    +	LEDS		0x1003,gr2
    +
    +	movsg		brr,gr3
    +	andicc		gr3,#BRR_ST,gr0,icc0
    +	andicc.p	gr3,#BRR_SB,gr0,icc1
    +	bne		icc0,#2,__break_step		/* jump if single-step caused break */
    +	beq		icc1,#2,__break_continue	/* jump if BREAK didn't cause break */
    +
    +	LEDS		0x1007,gr2
    +
    +	# handle special breaks
    +	movsg		bpcsr,gr3
    +
    +	sethi.p		%hi(__entry_return_singlestep_breaks_here),gr2
    +	setlo		%lo(__entry_return_singlestep_breaks_here),gr2
    +	subcc		gr2,gr3,gr0,icc0
    +	beq		icc0,#2,__break_return_singlestep
    +
    +	bra		__break_continue
    +
    +
    +###############################################################################
    +#
    +# handle BREAK instruction in kernel-mode exception epilogue
    +#
    +###############################################################################
    +__break_return_singlestep:
    +	LEDS		0x100f,gr2
    +
    +	# special break insn requests single-stepping to be turned back on
    +	#		HERE		RETT
    +	# PSR.ET	0		0
    +	# PSR.PS	old PSR.S	?
    +	# PSR.S		1		1
    +	# BPSR.ET	0		1 (can't have caused orig excep otherwise)
    +	# BPSR.BS	1		old PSR.S
    +	movsg		dcr,gr2
    +	sethi.p		%hi(DCR_SE),gr3
    +	setlo		%lo(DCR_SE),gr3
    +	or		gr2,gr3,gr2
    +	movgs		gr2,dcr
    +
    +	movsg		psr,gr2
    +	andi		gr2,#PSR_PS,gr2
    +	slli		gr2,#11,gr2			/* PSR.PS -> BPSR.BS */
    +	ori		gr2,#BPSR_BET,gr2		/* 1 -> BPSR.BET */
    +	movgs		gr2,bpsr
    +
    +	# return to the invoker of the original kernel exception
    +	movsg		pcsr,gr2
    +	movgs		gr2,bpcsr
    +
    +	LEDS		0x101f,gr2
    +
    +	ldi		@(gr31,#REG_CCR),gr3
    +	movgs		gr3,ccr
    +	lddi.p		@(gr31,#REG_GR(2)),gr2
    +	xor		gr31,gr31,gr31
    +	movgs		gr0,brr
    +#ifdef CONFIG_MMU
    +	movsg		scr3,gr31
    +#endif
    +	rett		#1
    +
    +###############################################################################
    +#
    +# handle BREAK instruction in TLB-miss handler return path
    +#
    +###############################################################################
    +#ifdef CONFIG_MMU
    +__break_return_singlestep_tlbmiss:
    +	LEDS		0x1100,gr2
    +	
    +	sethi.p		%hi(__break_tlb_miss_real_return_info),gr3
    +	setlo		%lo(__break_tlb_miss_real_return_info),gr3
    +	lddi		@(gr3,#0),gr2
    +	movgs		gr2,pcsr
    +	movgs		gr3,psr
    +
    +	bra		__break_return_singlestep
    +#endif
    +
    +
    +###############################################################################
    +#
    +# handle single stepping into an exception prologue from kernel mode
    +# - we try and catch it whilst it is still in the main vector table
    +# - if we catch it there, we have to jump to the fixup handler
    +#   - there is a fixup table that has a pointer for every 16b slot in the trap
    +#     table
    +#
    +###############################################################################
    +__break_step:
    +	LEDS		0x2003,gr2
    +
    +	# external interrupts seem to escape from the trap table before single
    +	# step catches up with them
    +	movsg		bpcsr,gr2
    +	sethi.p		%hi(__entry_kernel_external_interrupt),gr3
    +	setlo		%lo(__entry_kernel_external_interrupt),gr3
    +	subcc		gr2,gr3,gr0,icc0
    +	beq		icc0,#2,__break_step_kernel_external_interrupt
    +
    +	LEDS		0x2007,gr2
    +
    +	# the two main vector tables are adjacent on one 8Kb slab
    +	movsg		bpcsr,gr2
    +	setlos		#0xffffe000,gr3
    +	and		gr2,gr3,gr2
    +	sethi.p		%hi(__trap_tables),gr3
    +	setlo		%lo(__trap_tables),gr3
    +	subcc		gr2,gr3,gr0,icc0
    +	bne		icc0,#2,__break_continue
    +
    +	LEDS		0x200f,gr2
    +
    +	# skip workaround if so requested by GDB
    +	sethi.p		%hi(__break_trace_through_exceptions),gr3
    +	setlo		%lo(__break_trace_through_exceptions),gr3
    +	ld		@(gr3,gr0),gr3
    +	subcc		gr3,gr0,gr0,icc0
    +	bne		icc0,#0,__break_continue
    +
    +	LEDS		0x201f,gr2
    +
    +	# access the fixup table - there's a 1:1 mapping between the slots in the trap tables and
    +	# the slots in the trap fixup tables allowing us to simply divide the offset into the
    +	# former by 4 to access the latter
    +	sethi.p		%hi(__trap_tables),gr3
    +	setlo		%lo(__trap_tables),gr3
    +	movsg		bpcsr,gr2
    +	sub		gr2,gr3,gr2
    +	srli.p		gr2,#2,gr2
    +
    +	sethi		%hi(__trap_fixup_tables),gr3
    +	setlo.p		%lo(__trap_fixup_tables),gr3
    +	andi		gr2,#~3,gr2
    +	ld		@(gr2,gr3),gr2
    +	jmpil		@(gr2,#0)
    +
    +# step through an internal exception from kernel mode
    +	.globl		__break_step_kernel_softprog_interrupt
    +__break_step_kernel_softprog_interrupt:
    +	sethi.p		%hi(__entry_kernel_softprog_interrupt_reentry),gr3
    +	setlo		%lo(__entry_kernel_softprog_interrupt_reentry),gr3
    +	bra		__break_return_as_kernel_prologue
    +
    +# step through an external interrupt from kernel mode
    +	.globl		__break_step_kernel_external_interrupt
    +__break_step_kernel_external_interrupt:
    +	sethi.p		%hi(__entry_kernel_external_interrupt_reentry),gr3
    +	setlo		%lo(__entry_kernel_external_interrupt_reentry),gr3
    +
    +__break_return_as_kernel_prologue:
    +	LEDS		0x203f,gr2
    +
    +	movgs		gr3,bpcsr
    +
    +	# do the bit we had to skip
    +#ifdef CONFIG_MMU
    +	movsg		ear0,gr2		/* EAR0 can get clobbered by gdb-stub (ICI/ICEI) */
    +	movgs		gr2,scr2
    +#endif
    +
    +	or.p		sp,gr0,gr2		/* set up the stack pointer */
    +	subi		sp,#REG__END,sp
    +	sti.p		gr2,@(sp,#REG_SP)
    +
    +	setlos		#REG__STATUS_STEP,gr2
    +	sti		gr2,@(sp,#REG__STATUS)		/* record single step status */
    +
    +	# cancel single-stepping mode
    +	movsg		dcr,gr2
    +	sethi.p		%hi(~DCR_SE),gr3
    +	setlo		%lo(~DCR_SE),gr3
    +	and		gr2,gr3,gr2
    +	movgs		gr2,dcr
    +
    +	LEDS		0x207f,gr2
    +
    +	ldi		@(gr31,#REG_CCR),gr3
    +	movgs		gr3,ccr
    +	lddi.p		@(gr31,#REG_GR(2)),gr2
    +	xor		gr31,gr31,gr31
    +	movgs		gr0,brr
    +#ifdef CONFIG_MMU
    +	movsg		scr3,gr31
    +#endif
    +	rett		#1
    +
    +# step through an internal exception from uspace mode
    +	.globl		__break_step_uspace_softprog_interrupt
    +__break_step_uspace_softprog_interrupt:
    +	sethi.p		%hi(__entry_uspace_softprog_interrupt_reentry),gr3
    +	setlo		%lo(__entry_uspace_softprog_interrupt_reentry),gr3
    +	bra		__break_return_as_uspace_prologue
    +
    +# step through an external interrupt from kernel mode
    +	.globl		__break_step_uspace_external_interrupt
    +__break_step_uspace_external_interrupt:
    +	sethi.p		%hi(__entry_uspace_external_interrupt_reentry),gr3
    +	setlo		%lo(__entry_uspace_external_interrupt_reentry),gr3
    +
    +__break_return_as_uspace_prologue:
    +	LEDS		0x20ff,gr2
    +
    +	movgs		gr3,bpcsr
    +
    +	# do the bit we had to skip
    +	sethi.p		%hi(__kernel_frame0_ptr),gr28
    +	setlo		%lo(__kernel_frame0_ptr),gr28
    +	ldi.p		@(gr28,#0),gr28
    +
    +	setlos		#REG__STATUS_STEP,gr2
    +	sti		gr2,@(gr28,#REG__STATUS)	/* record single step status */
    +
    +	# cancel single-stepping mode
    +	movsg		dcr,gr2
    +	sethi.p		%hi(~DCR_SE),gr3
    +	setlo		%lo(~DCR_SE),gr3
    +	and		gr2,gr3,gr2
    +	movgs		gr2,dcr
    +
    +	LEDS		0x20fe,gr2
    +
    +	ldi		@(gr31,#REG_CCR),gr3
    +	movgs		gr3,ccr
    +	lddi.p		@(gr31,#REG_GR(2)),gr2
    +	xor		gr31,gr31,gr31
    +	movgs		gr0,brr
    +#ifdef CONFIG_MMU
    +	movsg		scr3,gr31
    +#endif
    +	rett		#1
    +
    +#ifdef CONFIG_MMU
    +# step through an ITLB-miss handler from user mode
    +	.globl		__break_user_insn_tlb_miss
    +__break_user_insn_tlb_miss:
    +	# we'll want to try the trap stub again
    +	sethi.p		%hi(__trap_user_insn_tlb_miss),gr2
    +	setlo		%lo(__trap_user_insn_tlb_miss),gr2
    +	movgs		gr2,bpcsr
    +
    +__break_tlb_miss_common:
    +	LEDS		0x2101,gr2
    +	
    +	# cancel single-stepping mode
    +	movsg		dcr,gr2
    +	sethi.p		%hi(~DCR_SE),gr3
    +	setlo		%lo(~DCR_SE),gr3
    +	and		gr2,gr3,gr2
    +	movgs		gr2,dcr
    +
    +	# we'll swap the real return address for one with a BREAK insn so that we can re-enable
    +	# single stepping on return
    +	movsg		pcsr,gr2
    +	sethi.p		%hi(__break_tlb_miss_real_return_info),gr3
    +	setlo		%lo(__break_tlb_miss_real_return_info),gr3
    +	sti		gr2,@(gr3,#0)
    +
    +	sethi.p		%hi(__break_tlb_miss_return_break),gr2
    +	setlo		%lo(__break_tlb_miss_return_break),gr2
    +	movgs		gr2,pcsr
    +
    +	# we also have to fudge PSR because the return BREAK is in kernel space and we want
    +	# to get a BREAK fault not an access violation should the return be to userspace
    +	movsg		psr,gr2
    +	sti.p		gr2,@(gr3,#4)
    +	ori		gr2,#PSR_PS,gr2
    +	movgs		gr2,psr
    +
    +	LEDS		0x2102,gr2
    +	
    +	ldi		@(gr31,#REG_CCR),gr3
    +	movgs		gr3,ccr
    +	lddi		@(gr31,#REG_GR(2)),gr2
    +	movsg		scr3,gr31
    +	movgs		gr0,brr
    +	rett		#1
    +
    +# step through a DTLB-miss handler from user mode
    +	.globl		__break_user_data_tlb_miss
    +__break_user_data_tlb_miss:
    +	# we'll want to try the trap stub again
    +	sethi.p		%hi(__trap_user_data_tlb_miss),gr2
    +	setlo		%lo(__trap_user_data_tlb_miss),gr2
    +	movgs		gr2,bpcsr
    +	bra		__break_tlb_miss_common
    +
    +# step through an ITLB-miss handler from kernel mode
    +	.globl		__break_kernel_insn_tlb_miss
    +__break_kernel_insn_tlb_miss:
    +	# we'll want to try the trap stub again
    +	sethi.p		%hi(__trap_kernel_insn_tlb_miss),gr2
    +	setlo		%lo(__trap_kernel_insn_tlb_miss),gr2
    +	movgs		gr2,bpcsr
    +	bra		__break_tlb_miss_common
    +
    +# step through a DTLB-miss handler from kernel mode
    +	.globl		__break_kernel_data_tlb_miss
    +__break_kernel_data_tlb_miss:
    +	# we'll want to try the trap stub again
    +	sethi.p		%hi(__trap_kernel_data_tlb_miss),gr2
    +	setlo		%lo(__trap_kernel_data_tlb_miss),gr2
    +	movgs		gr2,bpcsr
    +	bra		__break_tlb_miss_common
    +#endif
    +
    +###############################################################################
    +#
    +# handle debug events originating with userspace
    +#
    +###############################################################################
    +__break_maybe_userspace:
    +	LEDS		0x3003,gr2
    +
    +	setlos		#BPSR_BS,gr2
    +	andcc		gr3,gr2,gr0,icc0
    +	bne		icc0,#0,__break_continue	/* skip if PSR.S was 1 */
    +
    +	movsg		brr,gr2
    +	andicc		gr2,#BRR_ST|BRR_SB,gr0,icc0
    +	beq		icc0,#0,__break_continue	/* jump if not BREAK or single-step */
    +
    +	LEDS		0x3007,gr2
    +
    +	# do the first part of the exception prologue here
    +	sethi.p		%hi(__kernel_frame0_ptr),gr28
    +	setlo		%lo(__kernel_frame0_ptr),gr28
    +	ldi		@(gr28,#0),gr28
    +	andi		gr28,#~7,gr28
    +
    +	# set up the kernel stack pointer
    +	sti		sp  ,@(gr28,#REG_SP)
    +	ori		gr28,0,sp
    +	sti		gr0 ,@(gr28,#REG_GR(28))
    +
    +	stdi		gr20,@(gr28,#REG_GR(20))
    +	stdi		gr22,@(gr28,#REG_GR(22))
    +
    +	movsg		tbr,gr20
    +	movsg		bpcsr,gr21
    +	movsg		psr,gr22
    +
    +	# determine the exception type and cancel single-stepping mode
    +	or		gr0,gr0,gr23
    +
    +	movsg		dcr,gr2
    +	sethi.p		%hi(DCR_SE),gr3
    +	setlo		%lo(DCR_SE),gr3
    +	andcc		gr2,gr3,gr0,icc0
    +	beq		icc0,#0,__break_no_user_sstep	/* must have been a BREAK insn */
    +
    +	not		gr3,gr3
    +	and		gr2,gr3,gr2
    +	movgs		gr2,dcr
    +	ori		gr23,#REG__STATUS_STEP,gr23
    +
    +__break_no_user_sstep:
    +	LEDS		0x300f,gr2
    +
    +	movsg		brr,gr2
    +	andi		gr2,#BRR_ST|BRR_SB,gr2
    +	slli		gr2,#1,gr2
    +	or		gr23,gr2,gr23
    +	sti.p		gr23,@(gr28,#REG__STATUS)	/* record single step status */
    +
    +	# adjust the value acquired from TBR - this indicates the exception
    +	setlos		#~TBR_TT,gr2
    +	and.p		gr20,gr2,gr20
    +	setlos		#TBR_TT_BREAK,gr2
    +	or.p		gr20,gr2,gr20
    +
    +	# fudge PSR.PS and BPSR.BS to return to kernel mode through the trap
    +	# table as trap 126
    +	andi		gr22,#~PSR_PS,gr22		/* PSR.PS should be 0 */
    +	movgs		gr22,psr
    +
    +	setlos		#BPSR_BS,gr2			/* BPSR.BS should be 1 and BPSR.BET 0 */
    +	movgs		gr2,bpsr
    +
    +	# return through remainder of the exception prologue
    +	sethi.p		%hi(__entry_common),gr3
    +	setlo		%lo(__entry_common),gr3
    +	movgs		gr3,bpcsr
    +
    +	LEDS		0x301f,gr2
    +
    +	ldi		@(gr31,#REG_CCR),gr3
    +	movgs		gr3,ccr
    +	lddi.p		@(gr31,#REG_GR(2)),gr2
    +	xor		gr31,gr31,gr31
    +	movgs		gr0,brr
    +#ifdef CONFIG_MMU
    +	movsg		scr3,gr31
    +#endif
    +	rett		#1
    +
    +###############################################################################
    +#
    +# resume normal debug-mode entry
    +#
    +###############################################################################
    +__break_continue:
    +	LEDS		0x4003,gr2
    +
    +	# set up the kernel stack pointer
    +	sti		sp,@(gr31,#REG_SP)
    +
    +	sethi.p		%hi(__break_stack_tos),sp
    +	setlo		%lo(__break_stack_tos),sp
    +
    +	# finish building the exception frame
    +	stdi		gr4 ,@(gr31,#REG_GR(4))
    +	stdi		gr6 ,@(gr31,#REG_GR(6))
    +	stdi		gr8 ,@(gr31,#REG_GR(8))
    +	stdi		gr10,@(gr31,#REG_GR(10))
    +	stdi		gr12,@(gr31,#REG_GR(12))
    +	stdi		gr14,@(gr31,#REG_GR(14))
    +	stdi		gr16,@(gr31,#REG_GR(16))
    +	stdi		gr18,@(gr31,#REG_GR(18))
    +	stdi		gr20,@(gr31,#REG_GR(20))
    +	stdi		gr22,@(gr31,#REG_GR(22))
    +	stdi		gr24,@(gr31,#REG_GR(24))
    +	stdi		gr26,@(gr31,#REG_GR(26))
    +	sti		gr0 ,@(gr31,#REG_GR(28))	/* NULL frame pointer */
    +	sti		gr29,@(gr31,#REG_GR(29))
    +	sti		gr30,@(gr31,#REG_GR(30))
    +	sti		gr8 ,@(gr31,#REG_ORIG_GR8)
    +
    +#ifdef CONFIG_MMU
    +	movsg		scr3,gr19
    +	sti		gr19,@(gr31,#REG_GR(31))
    +#endif
    +
    +	movsg		bpsr ,gr19
    +	movsg		tbr  ,gr20
    +	movsg		bpcsr,gr21
    +	movsg		psr  ,gr22
    +	movsg		isr  ,gr23
    +	movsg		cccr ,gr25
    +	movsg		lr   ,gr26
    +	movsg		lcr  ,gr27
    +
    +	andi.p		gr22,#~(PSR_S|PSR_ET),gr5	/* rebuild PSR */
    +	andi		gr19,#PSR_ET,gr4
    +	or.p		gr4,gr5,gr5
    +	srli		gr19,#10,gr4
    +	andi		gr4,#PSR_S,gr4
    +	or.p		gr4,gr5,gr5
    +
    +	setlos		#-1,gr6
    +	sti		gr20,@(gr31,#REG_TBR)
    +	sti		gr21,@(gr31,#REG_PC)
    +	sti		gr5 ,@(gr31,#REG_PSR)
    +	sti		gr23,@(gr31,#REG_ISR)
    +	sti		gr25,@(gr31,#REG_CCCR)
    +	stdi		gr26,@(gr31,#REG_LR)
    +	sti		gr6 ,@(gr31,#REG_SYSCALLNO)
    +
    +	# store CPU-specific regs
    +	movsg		iacc0h,gr4
    +	movsg		iacc0l,gr5
    +	stdi		gr4,@(gr31,#REG_IACC0)
    +
    +	movsg		gner0,gr4
    +	movsg		gner1,gr5
    +	stdi		gr4,@(gr31,#REG_GNER0)
    +
    +	# build the debug register frame
    +	movsg		brr,gr4
    +	movgs		gr0,brr
    +	movsg		nmar,gr5
    +	movsg		dcr,gr6
    +
    +	stdi		gr4 ,@(gr31,#REG_BRR)
    +	sti		gr19,@(gr31,#REG_BPSR)
    +	sti.p		gr6 ,@(gr31,#REG_DCR)
    +
    +	# trap exceptions during break handling and disable h/w breakpoints/watchpoints
    +	sethi		%hi(DCR_EBE),gr5
    +	setlo.p		%lo(DCR_EBE),gr5
    +	sethi		%hi(__entry_breaktrap_table),gr4
    +	setlo		%lo(__entry_breaktrap_table),gr4
    +	movgs		gr5,dcr
    +	movgs		gr4,tbr
    +
    +	# set up kernel global registers
    +	sethi.p		%hi(__kernel_current_task),gr5
    +	setlo		%lo(__kernel_current_task),gr5
    +	ld		@(gr5,gr0),gr29
    +	ldi.p		@(gr29,#4),gr15		; __current_thread_info = current->thread_info
    +
    +	sethi		%hi(_gp),gr16
    +	setlo.p		%lo(_gp),gr16
    +
    +	# make sure we (the kernel) get div-zero and misalignment exceptions
    +	setlos		#ISR_EDE|ISR_DTT_DIVBYZERO|ISR_EMAM_EXCEPTION,gr5
    +	movgs		gr5,isr
    +
    +	# enter the GDB stub
    +	LEDS		0x4007,gr2
    +
    +	or.p		gr0,gr0,fp
    +	call		debug_stub
    +
    +	LEDS		0x403f,gr2
    +
    +	# return from break
    +	lddi		@(gr31,#REG_IACC0),gr4
    +	movgs		gr4,iacc0h
    +	movgs		gr5,iacc0l
    +
    +	lddi		@(gr31,#REG_GNER0),gr4
    +	movgs		gr4,gner0
    +	movgs		gr5,gner1
    +
    +	lddi		@(gr31,#REG_LR)  ,gr26
    +	lddi		@(gr31,#REG_CCR) ,gr24
    +	lddi		@(gr31,#REG_PSR) ,gr22
    +	ldi		@(gr31,#REG_PC)  ,gr21
    +	ldi		@(gr31,#REG_TBR) ,gr20
    +	ldi.p		@(gr31,#REG_DCR) ,gr6
    +
    +	andi		gr22,#PSR_S,gr19		/* rebuild BPSR */
    +	andi.p		gr22,#PSR_ET,gr5
    +	slli		gr19,#10,gr19
    +	or		gr5,gr19,gr19
    +
    +	movgs		gr6 ,dcr
    +	movgs		gr19,bpsr
    +	movgs		gr20,tbr
    +	movgs		gr21,bpcsr
    +	movgs		gr23,isr
    +	movgs		gr24,ccr
    +	movgs		gr25,cccr
    +	movgs		gr26,lr
    +	movgs		gr27,lcr
    +
    +	LEDS		0x407f,gr2
    +
    +#ifdef CONFIG_MMU
    +	ldi		@(gr31,#REG_GR(31)),gr2
    +	movgs		gr2,scr3
    +#endif
    +
    +	ldi		@(gr31,#REG_GR(30)),gr30
    +	ldi		@(gr31,#REG_GR(29)),gr29
    +	lddi		@(gr31,#REG_GR(26)),gr26
    +	lddi		@(gr31,#REG_GR(24)),gr24
    +	lddi		@(gr31,#REG_GR(22)),gr22
    +	lddi		@(gr31,#REG_GR(20)),gr20
    +	lddi		@(gr31,#REG_GR(18)),gr18
    +	lddi		@(gr31,#REG_GR(16)),gr16
    +	lddi		@(gr31,#REG_GR(14)),gr14
    +	lddi		@(gr31,#REG_GR(12)),gr12
    +	lddi		@(gr31,#REG_GR(10)),gr10
    +	lddi		@(gr31,#REG_GR(8)) ,gr8
    +	lddi		@(gr31,#REG_GR(6)) ,gr6
    +	lddi		@(gr31,#REG_GR(4)) ,gr4
    +	lddi		@(gr31,#REG_GR(2)) ,gr2
    +	ldi.p		@(gr31,#REG_SP)    ,sp
    +
    +	xor		gr31,gr31,gr31
    +	movgs		gr0,brr
    +#ifdef CONFIG_MMU
    +	movsg		scr3,gr31
    +#endif
    +	rett		#1
    +
    +###################################################################################################
    +#
    +# GDB stub "system calls"
    +#
    +###################################################################################################
    +
    +#ifdef CONFIG_GDBSTUB
    +	# void gdbstub_console_write(struct console *con, const char *p, unsigned n)
    +	.globl		gdbstub_console_write
    +gdbstub_console_write:
    +	break
    +	bralr
    +#endif
    +
    +	# GDB stub BUG() trap
    +	# GR8 is the proposed signal number
    +	.globl		__debug_bug_trap
    +__debug_bug_trap:
    +	break
    +	bralr
    +
    +	# transfer kernel exeception to GDB for handling
    +	.globl		__break_hijack_kernel_event
    +__break_hijack_kernel_event:
    +	break
    +	.globl		__break_hijack_kernel_event_breaks_here
    +__break_hijack_kernel_event_breaks_here:
    +	nop
    +
    +#ifdef CONFIG_MMU
    +	# handle a return from TLB-miss that requires single-step reactivation
    +	.globl		__break_tlb_miss_return_break
    +__break_tlb_miss_return_break:
    +	break
    +__break_tlb_miss_return_breaks_here:
    +	nop
    +#endif
    +
    +	# guard the first .text label in the next file from confusion
    +	nop
    diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/cmode.S linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/cmode.S
    --- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/cmode.S	1970-01-01 01:00:00.000000000 +0100
    +++ linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/cmode.S	2004-11-05 14:13:03.070566125 +0000
    @@ -0,0 +1,190 @@
    +/* cmode.S: clock mode management
    + *
    + * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
    + * Written by David Woodhouse (dwmw2@redhat.com)
    + *
    + * 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 the Free Software Foundation; either version
    + * 2 of the License, or (at your option) any later version.
    + *
    + */
    +
    +#include <linux/sys.h>
    +#include <linux/config.h>
    +#include <linux/linkage.h>
    +#include <asm/setup.h>
    +#include <asm/segment.h>
    +#include <asm/ptrace.h>
    +#include <asm/errno.h>
    +#include <asm/cache.h>
    +#include <asm/spr-regs.h>
    +	
    +#define __addr_MASK	0xfeff9820	/* interrupt controller mask */
    +
    +#define __addr_SDRAMC	0xfe000400	/* SDRAM controller regs */
    +#define SDRAMC_DSTS	0x28		/* SDRAM status */
    +#define SDRAMC_DSTS_SSI	0x00000001	/* indicates that the SDRAM is in self-refresh mode */
    +#define SDRAMC_DRCN	0x30		/* SDRAM refresh control */
    +#define SDRAMC_DRCN_SR	0x00000001	/* transition SDRAM into self-refresh mode */
    +#define __addr_CLKC	0xfeff9a00
    +#define CLKC_SWCMODE	0x00000008
    +#define __addr_LEDS	0xe1200004	
    +
    +.macro li v r
    +	sethi.p		%hi(\v),\r
    +	setlo		%lo(\v),\r
    +.endm
    +
    +	.text
    +	.balign		4
    +
    +	
    +###############################################################################
    +#
    +# Change CMODE
    +# - void frv_change_cmode(int cmode)
    +#
    +###############################################################################
    +	.globl		frv_change_cmode
    +        .type		frv_change_cmode,@function
    +
    +.macro	LEDS v
    +#ifdef DEBUG_CMODE
    +	setlos	#~\v,gr10
    +	sti	gr10,@(gr11,#0)
    +	membar
    +#endif
    +.endm
    +		
    +frv_change_cmode:	
    +	movsg		lr,gr9
    +#ifdef DEBUG_CMODE
    +	li		__addr_LEDS,gr11
    +#endif
    +	dcef		@(gr0,gr0),#1
    +
    +	# Shift argument left by 24 bits to fit in SWCMODE register later.
    +	slli		gr8,#24,gr8
    +
    +	# (1) Set '0' in the PSR.ET bit, and prohibit interrupts. 
    +	movsg		psr,gr14
    +	andi		gr14,#~PSR_ET,gr3
    +	movgs		gr3,psr
    +
    +#if 0 // Fujitsu recommend to skip this and will update docs.
    +	# (2) Set '0' to all bits of the MASK register of the interrupt 
    +	#     controller, and mask interrupts. 
    +	li		__addr_MASK,gr12
    +	ldi		@(gr12,#0),gr13
    +	li		0xffff0000,gr4
    +	sti		gr4,@(gr12,#0)
    +#endif
    +	
    +	# (3) Stop the transfer function of DMAC. Stop all the bus masters 
    +	#     to access SDRAM and the internal resources.
    +
    +	# (already done by caller)
    +	
    +	# (4) Preload a series of following instructions to the instruction
    +	#     cache. 
    +	li		#__cmode_icache_lock_start,gr3
    +	li		#__cmode_icache_lock_end,gr4
    +
    +1:	icpl		gr3,gr0,#1
    +	addi		gr3,#L1_CACHE_BYTES,gr3
    +	cmp		gr4,gr3,icc0
    +	bhi		icc0,#0,1b
    +
    +	# Set up addresses in regs for later steps.
    +	setlos		SDRAMC_DRCN_SR,gr3
    +	li		__addr_SDRAMC,gr4
    +	li		__addr_CLKC,gr5
    +	ldi		@(gr5,#0),gr6
    +	li		#0x80000000,gr7
    +	or		gr6,gr7,gr6
    +	
    +	bra		__cmode_icache_lock_start
    +
    +	.balign	L1_CACHE_BYTES
    +__cmode_icache_lock_start:		
    +
    +	# (5) Flush the content of all caches by the DCEF instruction. 
    +	dcef		@(gr0,gr0),#1
    +
    +	# (6) Execute loading the dummy for SDRAM.
    +	ldi		@(gr9,#0),gr0
    +
    +	# (7) Set '1' to the DRCN.SR bit, and change SDRAM to the 
    +	#     self-refresh mode. Execute the dummy load to all memory
    +	#     devices set to cacheable on the external bus side in parallel
    +	#     with this.
    +	sti		gr3,@(gr4,#SDRAMC_DRCN)
    +
    +	# (8) Execute memory barrier instruction (MEMBAR).
    +	membar
    +	
    +	# (9) Read the DSTS register repeatedly until '1' stands in the 
    +	#     DSTS.SSI field.
    +1:	ldi		@(gr4,#SDRAMC_DSTS),gr3
    +	andicc		gr3,#SDRAMC_DSTS_SSI,gr3,icc0
    +	beq		icc0,#0,1b
    +
    +	# (10) Execute memory barrier instruction (MEMBAR).
    +	membar
    +	
    +#if 1
    +	# (11) Set the value of CMODE that you want to change to 
    +	#      SWCMODE.SWCM[3:0].
    +	sti		gr8,@(gr5,#CLKC_SWCMODE)
    +
    +	# (12) Set '1' to the CLKC.SWEN bit. In that case, do not change 
    +	#      fields other than SWEN of the CLKC register.
    +	sti		gr6,@(gr5,#0)
    +#endif
    +	# (13) Execute the instruction just after the memory barrier 
    +	# instruction that executes the self-loop 256 times. (Meanwhile,
    +	# the CMODE switch is done.) 
    +	membar
    +	setlos		#256,gr7
    +2:	subicc		gr7,#1,gr7,icc0
    +	bne		icc0,#2,2b
    +
    +	LEDS	0x36	
    +
    +	# (14) Release the self-refresh of SDRAM.
    +	sti		gr0,@(gr4,#SDRAMC_DRCN)
    +
    +	# Wait for it...
    +3:	ldi		@(gr4,#SDRAMC_DSTS),gr3
    +	andicc		gr3,#SDRAMC_DSTS_SSI,gr3,icc0
    +	bne		icc0,#2,3b
    +
    +#if 0
    +	li		0x0100000,gr10
    +4:	subicc		gr10,#1,gr10,icc0
    +
    +	bne		icc0,#0,4b
    +#endif
    +
    +__cmode_icache_lock_end:		
    +
    +	li		#__cmode_icache_lock_start,gr3
    +	li		#__cmode_icache_lock_end,gr4
    +
    +4:	icul		gr3
    +	addi		gr3,#L1_CACHE_BYTES,gr3
    +	cmp		gr4,gr3,icc0
    +	bhi		icc0,#0,4b
    +
    +#if 0 // Fujitsu recommend to skip this and will update docs.
    +	# (15) Release the interrupt mask setting of the MASK register of 
    +	# the interrupt controller if necessary.
    +	sti		gr13,@(gr12,#0)
    +#endif	
    +	# (16) Set  1' in the PSR.ET bit, and permit interrupt.
    +	movgs		gr14,psr
    +
    +	bralr
    +	
    +	.size		frv_change_cmode, .-frv_change_cmode
    diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/debug-stub.c linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/debug-stub.c
    --- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/debug-stub.c	1970-01-01 01:00:00.000000000 +0100
    +++ linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/debug-stub.c	2004-11-05 16:28:59.087204150 +0000
    @@ -0,0 +1,259 @@
    +/* debug-stub.c: debug-mode stub
    + *
    + * Copyright (C) 2004 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 License
    + * as published by the Free Software Foundation; either version
    + * 2 of the License, or (at your option) any later version.
    + */
    +
    +#include <linux/string.h>
    +#include <linux/kernel.h>
    +#include <linux/signal.h>
    +#include <linux/sched.h>
    +#include <linux/init.h>
    +#include <linux/serial_reg.h>
    +
    +#include <asm/system.h>
    +#include <asm/serial-regs.h>
    +#include <asm/timer-regs.h>
    +#include <asm/irc-regs.h>
    +#include <asm/gdb-stub.h>
    +#include "gdb-io.h"
    +
    +/* CPU board CON5 */
    +#define __UART0(X) (*(volatile uint8_t *)(UART0_BASE + (UART_##X)))
    +
    +#define LSR_WAIT_FOR0(STATE)			\
    +do {						\
    +} while (!(__UART0(LSR) & UART_LSR_##STATE))
    +
    +#define FLOWCTL_QUERY0(LINE)	({ __UART0(MSR) & UART_MSR_##LINE; })
    +#define FLOWCTL_CLEAR0(LINE)	do { __UART0(MCR) &= ~UART_MCR_##LINE; } while (0)
    +#define FLOWCTL_SET0(LINE)	do { __UART0(MCR) |= UART_MCR_##LINE; } while (0)
    +
    +#define FLOWCTL_WAIT_FOR0(LINE)			\
    +do {						\
    +	gdbstub_do_rx();			\
    +} while(!FLOWCTL_QUERY(LINE))
    +
    +static void __init debug_stub_init(void);
    +
    +extern asmlinkage void __break_hijack_kernel_event(void);
    +extern asmlinkage void __break_hijack_kernel_event_breaks_here(void);
    +
    +/*****************************************************************************/
    +/*
    + * debug mode handler stub
    + * - we come here with the CPU in debug mode and with exceptions disabled
    + * - handle debugging services for userspace
    + */
    +asmlinkage void debug_stub(void)
    +{
    +	unsigned long hsr0;
    +	int type = 0;
    +
    +	static u8 inited = 0;
    +	if (!inited) {
    +		debug_stub_init();
    +		type = -1;
    +		inited = 1;
    +	}
    +
    +	hsr0 = __get_HSR(0);
    +	if (hsr0 & HSR0_ETMD)
    +		__set_HSR(0, hsr0 & ~HSR0_ETMD);
    +
    +	/* disable single stepping */
    +	__debug_regs->dcr &= ~DCR_SE;
    +
    +	/* kernel mode can propose an exception be handled in debug mode by jumping to a special
    +	 * location */
    +	if (__debug_frame->pc == (unsigned long) __break_hijack_kernel_event_breaks_here) {
    +		/* replace the debug frame with the kernel frame and discard
    +		 * the top kernel context */
    +		*__debug_frame = *__frame;
    +		__frame = __debug_frame->next_frame;
    +		__debug_regs->brr = (__debug_frame->tbr & TBR_TT) << 12;
    +		__debug_regs->brr |= BRR_EB;
    +	}
    +
    +	if (__debug_frame->pc == (unsigned long) __debug_bug_trap + 4) {
    +		__debug_frame->pc = __debug_frame->lr;
    +		type = __debug_frame->gr8;
    +	}
    +
    +#ifdef CONFIG_GDBSTUB
    +	gdbstub(type);
    +#endif
    +
    +	if (hsr0 & HSR0_ETMD)
    +		__set_HSR(0, __get_HSR(0) | HSR0_ETMD);
    +
    +} /* end debug_stub() */
    +
    +/*****************************************************************************/
    +/*
    + * debug stub initialisation
    + */
    +static void __init debug_stub_init(void)
    +{
    +	__set_IRR(6, 0xff000000);	/* map ERRs to NMI */
    +	__set_IITMR(1, 0x20000000);	/* ERR0/1, UART0/1 IRQ detect levels */
    +
    +	asm volatile("	movgs	gr0,ibar0	\n"
    +		     "	movgs	gr0,ibar1	\n"
    +		     "	movgs	gr0,ibar2	\n"
    +		     "	movgs	gr0,ibar3	\n"
    +		     "	movgs	gr0,dbar0	\n"
    +		     "	movgs	gr0,dbmr00	\n"
    +		     "	movgs	gr0,dbmr01	\n"
    +		     "	movgs	gr0,dbdr00	\n"
    +		     "	movgs	gr0,dbdr01	\n"
    +		     "	movgs	gr0,dbar1	\n"
    +		     "	movgs	gr0,dbmr10	\n"
    +		     "	movgs	gr0,dbmr11	\n"
    +		     "	movgs	gr0,dbdr10	\n"
    +		     "	movgs	gr0,dbdr11	\n"
    +		     );
    +
    +	/* deal with debugging stub initialisation and initial pause */
    +	if (__debug_frame->pc == (unsigned long) __debug_stub_init_break)
    +		__debug_frame->pc = (unsigned long) start_kernel;
    +
    +	/* enable the debug events we want to trap */
    +	__debug_regs->dcr = DCR_EBE;
    +
    +#ifdef CONFIG_GDBSTUB
    +	gdbstub_init();
    +#endif
    +
    +	__clr_MASK_all();
    +	__clr_MASK(15);
    +	__clr_RC(15);
    +
    +} /* end debug_stub_init() */
    +
    +/*****************************************************************************/
    +/*
    + * kernel "exit" trap for gdb stub
    + */
    +void debug_stub_exit(int status)
    +{
    +
    +#ifdef CONFIG_GDBSTUB
    +	gdbstub_exit(status);
    +#endif
    +
    +} /* end debug_stub_exit() */
    +
    +/*****************************************************************************/
    +/*
    + * send string to serial port
    + */
    +void debug_to_serial(const char *p, int n)
    +{
    +	char ch;
    +
    +	for (; n > 0; n--) {
    +		ch = *p++;
    +		FLOWCTL_SET0(DTR);
    +		LSR_WAIT_FOR0(THRE);
    +		// FLOWCTL_WAIT_FOR(CTS);
    +
    +		if (ch == 0x0a) {
    +			__UART0(TX) = 0x0d;
    +			mb();
    +			LSR_WAIT_FOR0(THRE);
    +			// FLOWCTL_WAIT_FOR(CTS);
    +		}
    +		__UART0(TX) = ch;
    +		mb();
    +
    +		FLOWCTL_CLEAR0(DTR);
    +	}
    +
    +} /* end debug_to_serial() */
    +
    +/*****************************************************************************/
    +/*
    + * send string to serial port
    + */
    +void debug_to_serial2(const char *fmt, ...)
    +{
    +	va_list va;
    +	char buf[64];
    +	int n;
    +
    +	va_start(va, fmt);
    +	n = vsprintf(buf, fmt, va);
    +	va_end(va);
    +
    +	debug_to_serial(buf, n);
    +
    +} /* end debug_to_serial2() */
    +
    +/*****************************************************************************/
    +/*
    + * set up the ttyS0 serial port baud rate timers
    + */
    +void __init console_set_baud(unsigned baud)
    +{
    +	unsigned value, high, low;
    +	u8 lcr;
    +
    +	/* work out the divisor to give us the nearest higher baud rate */
    +	value = __serial_clock_speed_HZ / 16 / baud;
    +
    +	/* determine the baud rate range */
    +	high = __serial_clock_speed_HZ / 16 / value;
    +	low = __serial_clock_speed_HZ / 16 / (value + 1);
    +
    +	/* pick the nearest bound */
    +	if (low + (high - low) / 2 > baud)
    +		value++;
    +
    +	lcr = __UART0(LCR);
    +	__UART0(LCR) |= UART_LCR_DLAB;
    +	mb();
    +	__UART0(DLL) = value & 0xff;
    +	__UART0(DLM) = (value >> 8) & 0xff;
    +	mb();
    +	__UART0(LCR) = lcr;
    +	mb();
    +
    +} /* end console_set_baud() */
    +
    +/*****************************************************************************/
    +/*
    + *
    + */
    +int __init console_get_baud(void)
    +{
    +	unsigned value;
    +	u8 lcr;
    +
    +	lcr = __UART0(LCR);
    +	__UART0(LCR) |= UART_LCR_DLAB;
    +	mb();
    +	value =  __UART0(DLM) << 8;
    +	value |= __UART0(DLL);
    +	__UART0(LCR) = lcr;
    +	mb();
    +
    +	return value;
    +} /* end console_get_baud() */
    +
    +/*****************************************************************************/
    +/*
    + * display BUG() info
    + */
    +#ifndef CONFIG_NO_KERNEL_MSG
    +void __debug_bug_printk(const char *file, unsigned line)
    +{
    +	printk("kernel BUG at %s:%d!\n", file, line);
    +
    +} /* end __debug_bug_printk() */
    +#endif
    diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/dma.c linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/dma.c
    --- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/dma.c	1970-01-01 01:00:00.000000000 +0100
    +++ linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/dma.c	2004-11-05 14:13:03.073565872 +0000
    @@ -0,0 +1,464 @@
    +/* dma.c: DMA controller management on FR401 and the like
    + *
    + * Copyright (C) 2004 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 License
    + * as published by the Free Software Foundation; either version
    + * 2 of the License, or (at your option) any later version.
    + */
    +
    +#include <linux/module.h>
    +#include <linux/sched.h>
    +#include <linux/spinlock.h>
    +#include <linux/errno.h>
    +#include <linux/init.h>
    +#include <asm/dma.h>
    +#include <asm/gpio-regs.h>
    +#include <asm/irc-regs.h>
    +#include <asm/cpu-irqs.h>
    +
    +struct frv_dma_channel {
    +	uint8_t			flags;
    +#define FRV_DMA_FLAGS_RESERVED	0x01
    +#define FRV_DMA_FLAGS_INUSE	0x02
    +#define FRV_DMA_FLAGS_PAUSED	0x04
    +	uint8_t			cap;		/* capabilities available */
    +	int			irq;		/* completion IRQ */
    +	uint32_t		dreqbit;
    +	uint32_t		dackbit;
    +	uint32_t		donebit;
    +	const unsigned long	ioaddr;		/* DMA controller regs addr */
    +	const char		*devname;
    +	dma_irq_handler_t	handler;
    +	void			*data;
    +};
    +
    +
    +#define __get_DMAC(IO,X)	({ *(volatile unsigned long *)((IO) + DMAC_##X##x); })
    +
    +#define __set_DMAC(IO,X,V)					\
    +do {								\
    +	*(volatile unsigned long *)((IO) + DMAC_##X##x) = (V);	\
    +	mb();							\
    +} while(0)
    +
    +#define ___set_DMAC(IO,X,V)					\
    +do {								\
    +	*(volatile unsigned long *)((IO) + DMAC_##X##x) = (V);	\
    +} while(0)
    +
    +
    +static struct frv_dma_channel frv_dma_channels[FRV_DMA_NCHANS] = {
    +	[0] = {
    +		.cap		= FRV_DMA_CAP_DREQ | FRV_DMA_CAP_DACK | FRV_DMA_CAP_DONE,
    +		.irq		= IRQ_CPU_DMA0,
    +		.dreqbit	= SIR_DREQ0_INPUT,
    +		.dackbit	= SOR_DACK0_OUTPUT,
    +		.donebit	= SOR_DONE0_OUTPUT,
    +		.ioaddr		= 0xfe000900,
    +	},
    +	[1] = {
    +		.cap		= FRV_DMA_CAP_DREQ | FRV_DMA_CAP_DACK | FRV_DMA_CAP_DONE,
    +		.irq		= IRQ_CPU_DMA1,
    +		.dreqbit	= SIR_DREQ1_INPUT,
    +		.dackbit	= SOR_DACK1_OUTPUT,
    +		.donebit	= SOR_DONE1_OUTPUT,
    +		.ioaddr		= 0xfe000980,
    +	},
    +	[2] = {
    +		.cap		= FRV_DMA_CAP_DREQ | FRV_DMA_CAP_DACK,
    +		.irq		= IRQ_CPU_DMA2,
    +		.dreqbit	= SIR_DREQ2_INPUT,
    +		.dackbit	= SOR_DACK2_OUTPUT,
    +		.ioaddr		= 0xfe000a00,
    +	},
    +	[3] = {
    +		.cap		= FRV_DMA_CAP_DREQ | FRV_DMA_CAP_DACK,
    +		.irq		= IRQ_CPU_DMA3,
    +		.dreqbit	= SIR_DREQ3_INPUT,
    +		.dackbit	= SOR_DACK3_OUTPUT,
    +		.ioaddr		= 0xfe000a80,
    +	},
    +	[4] = {
    +		.cap		= FRV_DMA_CAP_DREQ,
    +		.irq		= IRQ_CPU_DMA4,
    +		.dreqbit	= SIR_DREQ4_INPUT,
    +		.ioaddr		= 0xfe001000,
    +	},
    +	[5] = {
    +		.cap		= FRV_DMA_CAP_DREQ,
    +		.irq		= IRQ_CPU_DMA5,
    +		.dreqbit	= SIR_DREQ5_INPUT,
    +		.ioaddr		= 0xfe001080,
    +	},
    +	[6] = {
    +		.cap		= FRV_DMA_CAP_DREQ,
    +		.irq		= IRQ_CPU_DMA6,
    +		.dreqbit	= SIR_DREQ6_INPUT,
    +		.ioaddr		= 0xfe001100,
    +	},
    +	[7] = {
    +		.cap		= FRV_DMA_CAP_DREQ,
    +		.irq		= IRQ_CPU_DMA7,
    +		.dreqbit	= SIR_DREQ7_INPUT,
    +		.ioaddr		= 0xfe001180,
    +	},
    +};
    +
    +static rwlock_t frv_dma_channels_lock = RW_LOCK_UNLOCKED;
    +
    +unsigned long frv_dma_inprogress;
    +
    +#define frv_clear_dma_inprogress(channel) \
    +	atomic_clear_mask(1 << (channel), &frv_dma_inprogress);
    +
    +#define frv_set_dma_inprogress(channel) \
    +	atomic_set_mask(1 << (channel), &frv_dma_inprogress);
    +
    +/*****************************************************************************/
    +/*
    + * DMA irq handler - determine channel involved, grab status and call real handler
    + */
    +static irqreturn_t dma_irq_handler(int irq, void *_channel, struct pt_regs *regs)
    +{
    +	struct frv_dma_channel *channel = _channel;
    +
    +	frv_clear_dma_inprogress(channel - frv_dma_channels);
    +	return channel->handler(channel - frv_dma_channels,
    +				__get_DMAC(channel->ioaddr, CSTR),
    +				channel->data,
    +				regs);
    +
    +} /* end dma_irq_handler() */
    +
    +/*****************************************************************************/
    +/*
    + * Determine which DMA controllers are present on this CPU
    + */
    +void __init frv_dma_init(void)
    +{
    +	unsigned long psr = __get_PSR();
    +	int num_dma, i;
    +
    +	/* First, determine how many DMA channels are available */
    +	switch (PSR_IMPLE(psr)) {
    +	case PSR_IMPLE_FR405:
    +	case PSR_IMPLE_FR451:
    +	case PSR_IMPLE_FR501:
    +	case PSR_IMPLE_FR551:
    +		num_dma = FRV_DMA_8CHANS;
    +		break;
    +
    +	case PSR_IMPLE_FR401:
    +	default:
    +		num_dma = FRV_DMA_4CHANS;
    +		break;
    +	}
    +
    +	/* Now mark all of the non-existent channels as reserved */
    +	for(i = num_dma; i < FRV_DMA_NCHANS; i++)
    +		frv_dma_channels[i].flags = FRV_DMA_FLAGS_RESERVED;
    +
    +} /* end frv_dma_init() */
    +
    +/*****************************************************************************/
    +/*
    + * allocate a DMA controller channel and the IRQ associated with it
    + */
    +int frv_dma_open(const char *devname,
    +		 unsigned long dmamask,
    +		 int dmacap,
    +		 dma_irq_handler_t handler,
    +		 unsigned long irq_flags,
    +		 void *data)
    +{
    +	struct frv_dma_channel *channel;
    +	int dma, ret;
    +	uint32_t val;
    +
    +	write_lock(&frv_dma_channels_lock);
    +
    +	ret = -ENOSPC;
    +
    +	for (dma = FRV_DMA_NCHANS - 1; dma >= 0; dma--) {
    +		channel = &frv_dma_channels[dma];
    +
    +		if (!test_bit(dma, &dmamask))
    +			continue;
    +
    +		if ((channel->cap & dmacap) != dmacap)
    +			continue;
    +
    +		if (!frv_dma_channels[dma].flags)
    +			goto found;
    +	}
    +
    +	goto out;
    +
    + found:
    +	ret = request_irq(channel->irq, dma_irq_handler, irq_flags, devname, channel);
    +	if (ret < 0)
    +		goto out;
    +
    +	/* okay, we've allocated all the resources */
    +	channel = &frv_dma_channels[dma];
    +
    +	channel->flags		|= FRV_DMA_FLAGS_INUSE;
    +	channel->devname	= devname;
    +	channel->handler	= handler;
    +	channel->data		= data;
    +
    +	/* Now make sure we are set up for DMA and not GPIO */
    +	/* SIR bit must be set for DMA to work */
    +	__set_SIR(channel->dreqbit | __get_SIR());
    +	/* SOR bits depend on what the caller requests */
    +	val = __get_SOR();
    +	if(dmacap & FRV_DMA_CAP_DACK)
    +		val |= channel->dackbit;
    +	else
    +		val &= ~channel->dackbit;
    +	if(dmacap & FRV_DMA_CAP_DONE)
    +		val |= channel->donebit;
    +	else
    +		val &= ~channel->donebit;
    +	__set_SOR(val);
    +
    +	ret = dma;
    + out:
    +	write_unlock(&frv_dma_channels_lock);
    +	return ret;
    +} /* end frv_dma_open() */
    +
    +EXPORT_SYMBOL(frv_dma_open);
    +
    +/*****************************************************************************/
    +/*
    + * close a DMA channel and its associated interrupt
    + */
    +void frv_dma_close(int dma)
    +{
    +	struct frv_dma_channel *channel = &frv_dma_channels[dma];
    +	unsigned long flags;
    +
    +	write_lock_irqsave(&frv_dma_channels_lock, flags);
    +
    +	free_irq(channel->irq, channel);
    +	frv_dma_stop(dma);
    +
    +	channel->flags &= ~FRV_DMA_FLAGS_INUSE;
    +
    +	write_unlock_irqrestore(&frv_dma_channels_lock, flags);
    +} /* end frv_dma_close() */
    +
    +EXPORT_SYMBOL(frv_dma_close);
    +
    +/*****************************************************************************/
    +/*
    + * set static configuration on a DMA channel
    + */
    +void frv_dma_config(int dma, unsigned long ccfr, unsigned long cctr, unsigned long apr)
    +{
    +	unsigned long ioaddr = frv_dma_channels[dma].ioaddr;
    +
    +	___set_DMAC(ioaddr, CCFR, ccfr);
    +	___set_DMAC(ioaddr, CCTR, cctr);
    +	___set_DMAC(ioaddr, APR,  apr);
    +	mb();
    +
    +} /* end frv_dma_config() */
    +
    +EXPORT_SYMBOL(frv_dma_config);
    +
    +/*****************************************************************************/
    +/*
    + * start a DMA channel
    + */
    +void frv_dma_start(int dma,
    +		   unsigned long sba, unsigned long dba,
    +		   unsigned long pix, unsigned long six, unsigned long bcl)
    +{
    +	unsigned long ioaddr = frv_dma_channels[dma].ioaddr;
    +
    +	___set_DMAC(ioaddr, SBA,  sba);
    +	___set_DMAC(ioaddr, DBA,  dba);
    +	___set_DMAC(ioaddr, PIX,  pix);
    +	___set_DMAC(ioaddr, SIX,  six);
    +	___set_DMAC(ioaddr, BCL,  bcl);
    +	___set_DMAC(ioaddr, CSTR, 0);
    +	mb();
    +
    +	__set_DMAC(ioaddr, CCTR, __get_DMAC(ioaddr, CCTR) | DMAC_CCTRx_ACT);
    +	frv_set_dma_inprogress(dma);
    +
    +} /* end frv_dma_start() */
    +
    +EXPORT_SYMBOL(frv_dma_start);
    +
    +/*****************************************************************************/
    +/*
    + * restart a DMA channel that's been stopped in circular addressing mode by comparison-end
    + */
    +void frv_dma_restart_circular(int dma, unsigned long six)
    +{
    +	unsigned long ioaddr = frv_dma_channels[dma].ioaddr;
    +
    +	___set_DMAC(ioaddr, SIX,  six);
    +	___set_DMAC(ioaddr, CSTR, __get_DMAC(ioaddr, CSTR) & ~DMAC_CSTRx_CE);
    +	mb();
    +
    +	__set_DMAC(ioaddr, CCTR, __get_DMAC(ioaddr, CCTR) | DMAC_CCTRx_ACT);
    +	frv_set_dma_inprogress(dma);
    +
    +} /* end frv_dma_restart_circular() */
    +
    +EXPORT_SYMBOL(frv_dma_restart_circular);
    +
    +/*****************************************************************************/
    +/*
    + * stop a DMA channel
    + */
    +void frv_dma_stop(int dma)
    +{
    +	unsigned long ioaddr = frv_dma_channels[dma].ioaddr;
    +	uint32_t cctr;
    +
    +	___set_DMAC(ioaddr, CSTR, 0);
    +	cctr = __get_DMAC(ioaddr, CCTR);
    +	cctr &= ~(DMAC_CCTRx_IE | DMAC_CCTRx_ACT);
    +	cctr |= DMAC_CCTRx_FC; 	/* fifo clear */
    +	__set_DMAC(ioaddr, CCTR, cctr);
    +	__set_DMAC(ioaddr, BCL,  0);
    +	frv_clear_dma_inprogress(dma);
    +} /* end frv_dma_stop() */
    +
    +EXPORT_SYMBOL(frv_dma_stop);
    +
    +/*****************************************************************************/
    +/*
    + * test interrupt status of DMA channel
    + */
    +int is_frv_dma_interrupting(int dma)
    +{
    +	unsigned long ioaddr = frv_dma_channels[dma].ioaddr;
    +
    +	return __get_DMAC(ioaddr, CSTR) & (1 << 23);
    +
    +} /* end is_frv_dma_interrupting() */
    +
    +EXPORT_SYMBOL(is_frv_dma_interrupting);
    +
    +/*****************************************************************************/
    +/*
    + * dump data about a DMA channel
    + */
    +void frv_dma_dump(int dma)
    +{
    +	unsigned long ioaddr = frv_dma_channels[dma].ioaddr;
    +	unsigned long cstr, pix, six, bcl;
    +
    +	cstr = __get_DMAC(ioaddr, CSTR);
    +	pix  = __get_DMAC(ioaddr, PIX);
    +	six  = __get_DMAC(ioaddr, SIX);
    +	bcl  = __get_DMAC(ioaddr, BCL);
    +
    +	printk("DMA[%d] cstr=%lx pix=%lx six=%lx bcl=%lx\n", dma, cstr, pix, six, bcl);
    +
    +} /* end frv_dma_dump() */
    +
    +EXPORT_SYMBOL(frv_dma_dump);
    +
    +/*****************************************************************************/
    +/*
    + * pause all DMA controllers
    + * - called by clock mangling routines
    + * - caller must be holding interrupts disabled
    + */
    +void frv_dma_pause_all(void)
    +{
    +	struct frv_dma_channel *channel;
    +	unsigned long ioaddr;
    +	unsigned long cstr, cctr;
    +	int dma;
    +
    +	write_lock(&frv_dma_channels_lock);
    +
    +	for (dma = FRV_DMA_NCHANS - 1; dma >= 0; dma--) {
    +		channel = &frv_dma_channels[dma];
    +
    +		if (!(channel->flags & FRV_DMA_FLAGS_INUSE))
    +			continue;
    +
    +		ioaddr = channel->ioaddr;
    +		cctr = __get_DMAC(ioaddr, CCTR);
    +		if (cctr & DMAC_CCTRx_ACT) {
    +			cctr &= ~DMAC_CCTRx_ACT;
    +			__set_DMAC(ioaddr, CCTR, cctr);
    +
    +			do {
    +				cstr = __get_DMAC(ioaddr, CSTR);
    +			} while (cstr & DMAC_CSTRx_BUSY);
    +
    +			if (cstr & DMAC_CSTRx_FED)
    +				channel->flags |= FRV_DMA_FLAGS_PAUSED;
    +			frv_clear_dma_inprogress(dma);
    +		}
    +	}
    +
    +} /* end frv_dma_pause_all() */
    +
    +EXPORT_SYMBOL(frv_dma_pause_all);
    +
    +/*****************************************************************************/
    +/*
    + * resume paused DMA controllers
    + * - called by clock mangling routines
    + * - caller must be holding interrupts disabled
    + */
    +void frv_dma_resume_all(void)
    +{
    +	struct frv_dma_channel *channel;
    +	unsigned long ioaddr;
    +	unsigned long cstr, cctr;
    +	int dma;
    +
    +	for (dma = FRV_DMA_NCHANS - 1; dma >= 0; dma--) {
    +		channel = &frv_dma_channels[dma];
    +
    +		if (!(channel->flags & FRV_DMA_FLAGS_PAUSED))
    +			continue;
    +
    +		ioaddr = channel->ioaddr;
    +		cstr = __get_DMAC(ioaddr, CSTR);
    +		cstr &= ~(DMAC_CSTRx_FED | DMAC_CSTRx_INT);
    +		__set_DMAC(ioaddr, CSTR, cstr);
    +
    +		cctr = __get_DMAC(ioaddr, CCTR);
    +		cctr |= DMAC_CCTRx_ACT;
    +		__set_DMAC(ioaddr, CCTR, cctr);
    +
    +		channel->flags &= ~FRV_DMA_FLAGS_PAUSED;
    +		frv_set_dma_inprogress(dma);
    +	}
    +
    +	write_unlock(&frv_dma_channels_lock);
    +
    +} /* end frv_dma_resume_all() */
    +
    +EXPORT_SYMBOL(frv_dma_resume_all);
    +
    +/*****************************************************************************/
    +/*
    + * dma status clear
    + */
    +void frv_dma_status_clear(int dma)
    +{
    +	unsigned long ioaddr = frv_dma_channels[dma].ioaddr;
    +	uint32_t cctr;
    +	___set_DMAC(ioaddr, CSTR, 0);
    +
    +	cctr = __get_DMAC(ioaddr, CCTR);
    +} /* end frv_dma_status_clear() */
    +
    +EXPORT_SYMBOL(frv_dma_status_clear);
    diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/entry.S linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/entry.S
    --- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/entry.S	1970-01-01 01:00:00.000000000 +0100
    +++ linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/entry.S	2004-11-05 14:13:03.077565534 +0000
    @@ -0,0 +1,1420 @@
    +/* entry.S: FR-V entry
    + *
    + * Copyright (C) 2003 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 License
    + * as published by the Free Software Foundation; either version
    + * 2 of the License, or (at your option) any later version.
    + *
    + *
    + * Entry to the kernel is "interesting":
    + *  (1) There are no stack pointers, not even for the kernel
    + *  (2) General Registers should not be clobbered
    + *  (3) There are no kernel-only data registers
    + *  (4) Since all addressing modes are wrt to a General Register, no global
    + *      variables can be reached
    + *
    + * We deal with this by declaring that we shall kill GR28 on entering the
    + * kernel from userspace
    + *
    + * However, since break interrupts can interrupt the CPU even when PSR.ET==0,
    + * they can't rely on GR28 to be anything useful, and so need to clobber a
    + * separate register (GR31). Break interrupts are managed in break.S
    + *
    + * GR29 _is_ saved, and holds the current task pointer globally
    + *
    + */
    +
    +#include <linux/sys.h>
    +#include <linux/config.h>
    +#include <linux/linkage.h>
    +#include <asm/thread_info.h>
    +#include <asm/setup.h>
    +#include <asm/segment.h>
    +#include <asm/ptrace.h>
    +#include <asm/errno.h>
    +#include <asm/cache.h>
    +#include <asm/spr-regs.h>
    +
    +#define nr_syscalls ((syscall_table_size)/4)
    +
    +	.text
    +	.balign		4
    +
    +.macro LEDS val
    +#	sethi.p		%hi(0xe1200004),gr30
    +#	setlo		%lo(0xe1200004),gr30
    +#	setlos		#~\val,gr31
    +#	st		gr31,@(gr30,gr0)
    +#	sethi.p		%hi(0xffc00100),gr30
    +#	setlo		%lo(0xffc00100),gr30
    +#	sth		gr0,@(gr30,gr0)
    +#	membar
    +.endm
    +
    +.macro LEDS32
    +#	not		gr31,gr31
    +#	sethi.p		%hi(0xe1200004),gr30
    +#	setlo		%lo(0xe1200004),gr30
    +#	st.p		gr31,@(gr30,gr0)
    +#	srli		gr31,#16,gr31
    +#	sethi.p		%hi(0xffc00100),gr30
    +#	setlo		%lo(0xffc00100),gr30
    +#	sth		gr31,@(gr30,gr0)
    +#	membar
    +.endm
    +
    +###############################################################################
    +#
    +# entry point for External interrupts received whilst executing userspace code
    +#
    +###############################################################################
    +	.globl		__entry_uspace_external_interrupt
    +        .type		__entry_uspace_external_interrupt,@function
    +__entry_uspace_external_interrupt:
    +	LEDS		0x6200
    +	sethi.p		%hi(__kernel_frame0_ptr),gr28
    +	setlo		%lo(__kernel_frame0_ptr),gr28
    +	ldi		@(gr28,#0),gr28
    +
    +	# handle h/w single-step through exceptions
    +	sti		gr0,@(gr28,#REG__STATUS)
    +
    +	.globl		__entry_uspace_external_interrupt_reentry
    +__entry_uspace_external_interrupt_reentry:
    +	LEDS		0x6201
    +
    +	setlos		#REG__END,gr30
    +	dcpl		gr28,gr30,#0
    +
    +	# finish building the exception frame
    +	sti		sp,  @(gr28,#REG_SP)
    +	stdi		gr2, @(gr28,#REG_GR(2))
    +	stdi		gr4, @(gr28,#REG_GR(4))
    +	stdi		gr6, @(gr28,#REG_GR(6))
    +	stdi		gr8, @(gr28,#REG_GR(8))
    +	stdi		gr10,@(gr28,#REG_GR(10))
    +	stdi		gr12,@(gr28,#REG_GR(12))
    +	stdi		gr14,@(gr28,#REG_GR(14))
    +	stdi		gr16,@(gr28,#REG_GR(16))
    +	stdi		gr18,@(gr28,#REG_GR(18))
    +	stdi		gr20,@(gr28,#REG_GR(20))
    +	stdi		gr22,@(gr28,#REG_GR(22))
    +	stdi		gr24,@(gr28,#REG_GR(24))
    +	stdi		gr26,@(gr28,#REG_GR(26))
    +	sti		gr0, @(gr28,#REG_GR(28))
    +	sti		gr29,@(gr28,#REG_GR(29))
    +	stdi.p		gr30,@(gr28,#REG_GR(30))
    +
    +	# set up the kernel stack pointer
    +	ori		gr28,0,sp
    +
    +	movsg		tbr ,gr20
    +	movsg		psr ,gr22
    +	movsg		pcsr,gr21
    +	movsg		isr ,gr23
    +	movsg		ccr ,gr24
    +	movsg		cccr,gr25
    +	movsg		lr  ,gr26
    +	movsg		lcr ,gr27
    +
    +	setlos.p	#-1,gr4
    +	andi		gr22,#PSR_PS,gr5		/* try to rebuild original PSR value */
    +	andi.p		gr22,#~(PSR_PS|PSR_S),gr6
    +	slli		gr5,#1,gr5
    +	or		gr6,gr5,gr5
    +	andi		gr5,#~PSR_ET,gr5
    +
    +	sti		gr20,@(gr28,#REG_TBR)
    +	sti		gr21,@(gr28,#REG_PC)
    +	sti		gr5 ,@(gr28,#REG_PSR)
    +	sti		gr23,@(gr28,#REG_ISR)
    +	stdi		gr24,@(gr28,#REG_CCR)
    +	stdi		gr26,@(gr28,#REG_LR)
    +	sti		gr4 ,@(gr28,#REG_SYSCALLNO)
    +
    +	movsg		iacc0h,gr4
    +	movsg		iacc0l,gr5
    +	stdi		gr4,@(gr28,#REG_IACC0)
    +
    +	movsg		gner0,gr4
    +	movsg		gner1,gr5
    +	stdi		gr4,@(gr28,#REG_GNER0)
    +
    +	# set up kernel global registers
    +	sethi.p		%hi(__kernel_current_task),gr5
    +	setlo		%lo(__kernel_current_task),gr5
    +	sethi.p		%hi(_gp),gr16
    +	setlo		%lo(_gp),gr16
    +	ldi		@(gr5,#0),gr29
    +	ldi.p		@(gr29,#4),gr15		; __current_thread_info = current->thread_info
    +
    +	# make sure we (the kernel) get div-zero and misalignment exceptions
    +	setlos		#ISR_EDE|ISR_DTT_DIVBYZERO|ISR_EMAM_EXCEPTION,gr5
    +	movgs		gr5,isr
    +
    +	# switch to the kernel trap table
    +	sethi.p		%hi(__entry_kerneltrap_table),gr6
    +	setlo		%lo(__entry_kerneltrap_table),gr6
    +	movgs		gr6,tbr
    +
    +	# set the return address
    +	sethi.p		%hi(__entry_return_from_user_interrupt),gr4
    +	setlo		%lo(__entry_return_from_user_interrupt),gr4
    +	movgs		gr4,lr
    +
    +	# raise the minimum interrupt priority to 15 (NMI only) and enable exceptions
    +	movsg		psr,gr4
    +
    +	ori		gr4,#PSR_PIL_14,gr4
    +	movgs		gr4,psr
    +	ori		gr4,#PSR_PIL_14|PSR_ET,gr4
    +	movgs		gr4,psr
    +
    +	LEDS		0x6202
    +	bra		do_IRQ
    +
    +	.size		__entry_uspace_external_interrupt,.-__entry_uspace_external_interrupt
    +
    +###############################################################################
    +#
    +# entry point for External interrupts received whilst executing kernel code
    +# - on arriving here, the following registers should already be set up:
    +#	GR15	- current thread_info struct pointer
    +#	GR16	- kernel GP-REL pointer
    +#	GR29	- current task struct pointer
    +#	TBR	- kernel trap vector table
    +#	ISR	- kernel's preferred integer controls
    +#
    +###############################################################################
    +	.globl		__entry_kernel_external_interrupt
    +        .type		__entry_kernel_external_interrupt,@function
    +__entry_kernel_external_interrupt:
    +	LEDS		0x6210
    +
    +	sub		sp,gr15,gr31
    +	LEDS32
    +
    +	# set up the stack pointer
    +	or.p		sp,gr0,gr30
    +	subi		sp,#REG__END,sp
    +	sti		gr30,@(sp,#REG_SP)
    +
    +	# handle h/w single-step through exceptions
    +	sti		gr0,@(sp,#REG__STATUS)
    +
    +	.globl		__entry_kernel_external_interrupt_reentry
    +__entry_kernel_external_interrupt_reentry:
    +	LEDS		0x6211
    +
    +	# set up the exception frame
    +	setlos		#REG__END,gr30
    +	dcpl		sp,gr30,#0
    +
    +	sti.p		gr28,@(sp,#REG_GR(28))
    +	ori		sp,0,gr28
    +
    +	# finish building the exception frame
    +	stdi		gr2,@(gr28,#REG_GR(2))
    +	stdi		gr4,@(gr28,#REG_GR(4))
    +	stdi		gr6,@(gr28,#REG_GR(6))
    +	stdi		gr8,@(gr28,#REG_GR(8))
    +	stdi		gr10,@(gr28,#REG_GR(10))
    +	stdi		gr12,@(gr28,#REG_GR(12))
    +	stdi		gr14,@(gr28,#REG_GR(14))
    +	stdi		gr16,@(gr28,#REG_GR(16))
    +	stdi		gr18,@(gr28,#REG_GR(18))
    +	stdi		gr20,@(gr28,#REG_GR(20))
    +	stdi		gr22,@(gr28,#REG_GR(22))
    +	stdi		gr24,@(gr28,#REG_GR(24))
    +	stdi		gr26,@(gr28,#REG_GR(26))
    +	sti		gr29,@(gr28,#REG_GR(29))
    +	stdi		gr30,@(gr28,#REG_GR(30))
    +
    +	movsg		tbr ,gr20
    +	movsg		psr ,gr22
    +	movsg		pcsr,gr21
    +	movsg		isr ,gr23
    +	movsg		ccr ,gr24
    +	movsg		cccr,gr25
    +	movsg		lr  ,gr26
    +	movsg		lcr ,gr27
    +
    +	setlos.p	#-1,gr4
    +	andi		gr22,#PSR_PS,gr5		/* try to rebuild original PSR value */
    +	andi.p		gr22,#~(PSR_PS|PSR_S),gr6
    +	slli		gr5,#1,gr5
    +	or		gr6,gr5,gr5
    +	andi.p		gr5,#~PSR_ET,gr5
    +
    +	# set CCCR.CC3 to Undefined to abort atomic-modify completion inside the kernel
    +	# - for an explanation of how it works, see: Documentation/fujitsu/frv/atomic-ops.txt
    +	andi		gr25,#~0xc0,gr25
    +
    +	sti		gr20,@(gr28,#REG_TBR)
    +	sti		gr21,@(gr28,#REG_PC)
    +	sti		gr5 ,@(gr28,#REG_PSR)
    +	sti		gr23,@(gr28,#REG_ISR)
    +	stdi		gr24,@(gr28,#REG_CCR)
    +	stdi		gr26,@(gr28,#REG_LR)
    +	sti		gr4 ,@(gr28,#REG_SYSCALLNO)
    +
    +	movsg		iacc0h,gr4
    +	movsg		iacc0l,gr5
    +	stdi		gr4,@(gr28,#REG_IACC0)
    +
    +	movsg		gner0,gr4
    +	movsg		gner1,gr5
    +	stdi		gr4,@(gr28,#REG_GNER0)
    +
    +	# set the return address
    +	sethi.p		%hi(__entry_return_from_kernel_interrupt),gr4
    +	setlo		%lo(__entry_return_from_kernel_interrupt),gr4
    +	movgs		gr4,lr
    +
    +	# clear power-saving mode flags
    +	movsg		hsr0,gr4
    +	andi		gr4,#~HSR0_PDM,gr4
    +	movgs		gr4,hsr0
    +
    +	# raise the minimum interrupt priority to 15 (NMI only) and enable exceptions
    +	movsg		psr,gr4
    +	ori		gr4,#PSR_PIL_14,gr4
    +	movgs		gr4,psr
    +	ori		gr4,#PSR_ET,gr4
    +	movgs		gr4,psr
    +
    +	LEDS		0x6212
    +	bra		do_IRQ
    +
    +	.size		__entry_kernel_external_interrupt,.-__entry_kernel_external_interrupt
    +
    +
    +###############################################################################
    +#
    +# entry point for Software and Progam interrupts generated whilst executing userspace code
    +#
    +###############################################################################
    +	.globl		__entry_uspace_softprog_interrupt
    +        .type		__entry_uspace_softprog_interrupt,@function
    +	.globl		__entry_uspace_handle_mmu_fault
    +__entry_uspace_softprog_interrupt:
    +	LEDS		0x6000
    +#ifdef CONFIG_MMU
    +	movsg		ear0,gr28
    +__entry_uspace_handle_mmu_fault:
    +	movgs		gr28,scr2
    +#endif
    +	sethi.p		%hi(__kernel_frame0_ptr),gr28
    +	setlo		%lo(__kernel_frame0_ptr),gr28
    +	ldi		@(gr28,#0),gr28
    +
    +	# handle h/w single-step through exceptions
    +	sti		gr0,@(gr28,#REG__STATUS)
    +
    +	.globl		__entry_uspace_softprog_interrupt_reentry
    +__entry_uspace_softprog_interrupt_reentry:
    +	LEDS		0x6001
    +
    +	setlos		#REG__END,gr30
    +	dcpl		gr28,gr30,#0
    +
    +	# set up the kernel stack pointer
    +	sti.p		sp,@(gr28,#REG_SP)
    +	ori		gr28,0,sp
    +	sti		gr0,@(gr28,#REG_GR(28))
    +
    +	stdi		gr20,@(gr28,#REG_GR(20))
    +	stdi		gr22,@(gr28,#REG_GR(22))
    +
    +	movsg		tbr,gr20
    +	movsg		pcsr,gr21
    +	movsg		psr,gr22
    +
    +	sethi.p		%hi(__entry_return_from_user_exception),gr23
    +	setlo		%lo(__entry_return_from_user_exception),gr23
    +	bra		__entry_common
    +
    +	.size		__entry_uspace_softprog_interrupt,.-__entry_uspace_softprog_interrupt
    +
    +	# single-stepping was disabled on entry to a TLB handler that then faulted
    +#ifdef CONFIG_MMU
    +	.globl		__entry_uspace_handle_mmu_fault_sstep
    +__entry_uspace_handle_mmu_fault_sstep:
    +	movgs		gr28,scr2
    +	sethi.p		%hi(__kernel_frame0_ptr),gr28
    +	setlo		%lo(__kernel_frame0_ptr),gr28
    +	ldi		@(gr28,#0),gr28
    +
    +	# flag single-step re-enablement
    +	sti		gr0,@(gr28,#REG__STATUS)
    +	bra		__entry_uspace_softprog_interrupt_reentry
    +#endif
    +
    +
    +###############################################################################
    +#
    +# entry point for Software and Progam interrupts generated whilst executing kernel code
    +#
    +###############################################################################
    +	.globl		__entry_kernel_softprog_interrupt
    +        .type		__entry_kernel_softprog_interrupt,@function
    +__entry_kernel_softprog_interrupt:
    +	LEDS		0x6004
    +
    +#ifdef CONFIG_MMU
    +	movsg		ear0,gr30
    +	movgs		gr30,scr2
    +#endif
    +
    +	.globl		__entry_kernel_handle_mmu_fault
    +__entry_kernel_handle_mmu_fault:
    +	# set up the stack pointer
    +	subi		sp,#REG__END,sp
    +	sti		sp,@(sp,#REG_SP)
    +	sti		sp,@(sp,#REG_SP-4)
    +	andi		sp,#~7,sp
    +
    +	# handle h/w single-step through exceptions
    +	sti		gr0,@(sp,#REG__STATUS)
    +
    +	.globl		__entry_kernel_softprog_interrupt_reentry
    +__entry_kernel_softprog_interrupt_reentry:
    +	LEDS		0x6005
    +
    +	setlos		#REG__END,gr30
    +	dcpl		sp,gr30,#0
    +
    +	# set up the exception frame
    +	sti.p		gr28,@(sp,#REG_GR(28))
    +	ori		sp,0,gr28
    +
    +	stdi		gr20,@(gr28,#REG_GR(20))
    +	stdi		gr22,@(gr28,#REG_GR(22))
    +
    +	ldi		@(sp,#REG_SP),gr22		/* reconstruct the old SP */
    +	addi		gr22,#REG__END,gr22
    +	sti		gr22,@(sp,#REG_SP)
    +
    +	# set CCCR.CC3 to Undefined to abort atomic-modify completion inside the kernel
    +	# - for an explanation of how it works, see: Documentation/fujitsu/frv/atomic-ops.txt
    +	movsg		cccr,gr20
    +	andi		gr20,#~0xc0,gr20
    +	movgs		gr20,cccr
    +
    +	movsg		tbr,gr20
    +	movsg		pcsr,gr21
    +	movsg		psr,gr22
    +
    +	sethi.p		%hi(__entry_return_from_kernel_exception),gr23
    +	setlo		%lo(__entry_return_from_kernel_exception),gr23
    +	bra		__entry_common
    +
    +	.size		__entry_kernel_softprog_interrupt,.-__entry_kernel_softprog_interrupt
    +
    +	# single-stepping was disabled on entry to a TLB handler that then faulted
    +#ifdef CONFIG_MMU
    +	.globl		__entry_kernel_handle_mmu_fault_sstep
    +__entry_kernel_handle_mmu_fault_sstep:
    +	# set up the stack pointer
    +	subi		sp,#REG__END,sp
    +	sti		sp,@(sp,#REG_SP)
    +	sti		sp,@(sp,#REG_SP-4)
    +	andi		sp,#~7,sp
    +
    +	# flag single-step re-enablement
    +	sethi		#REG__STATUS_STEP,gr30
    +	sti		gr30,@(sp,#REG__STATUS)
    +	bra		__entry_kernel_softprog_interrupt_reentry
    +#endif
    +
    +
    +###############################################################################
    +#
    +# the rest of the kernel entry point code
    +# - on arriving here, the following registers should be set up:
    +#	GR1	- kernel stack pointer
    +#	GR7	- syscall number (trap 0 only)
    +#	GR8-13	- syscall args (trap 0 only)
    +#	GR20	- saved TBR
    +#	GR21	- saved PC
    +#	GR22	- saved PSR
    +#	GR23	- return handler address
    +#	GR28	- exception frame on stack
    +#	SCR2	- saved EAR0 where applicable (clobbered by ICI & ICEF insns on FR451)
    +#	PSR	- PSR.S 1, PSR.ET 0
    +#
    +###############################################################################
    +	.globl		__entry_common
    +        .type		__entry_common,@function
    +__entry_common:
    +	LEDS		0x6008
    +
    +	# finish building the exception frame
    +	stdi		gr2,@(gr28,#REG_GR(2))
    +	stdi		gr4,@(gr28,#REG_GR(4))
    +	stdi		gr6,@(gr28,#REG_GR(6))
    +	stdi		gr8,@(gr28,#REG_GR(8))
    +	stdi		gr10,@(gr28,#REG_GR(10))
    +	stdi		gr12,@(gr28,#REG_GR(12))
    +	stdi		gr14,@(gr28,#REG_GR(14))
    +	stdi		gr16,@(gr28,#REG_GR(16))
    +	stdi		gr18,@(gr28,#REG_GR(18))
    +	stdi		gr24,@(gr28,#REG_GR(24))
    +	stdi		gr26,@(gr28,#REG_GR(26))
    +	sti		gr29,@(gr28,#REG_GR(29))
    +	stdi		gr30,@(gr28,#REG_GR(30))
    +
    +	movsg		lcr ,gr27
    +	movsg		lr  ,gr26
    +	movgs		gr23,lr
    +	movsg		cccr,gr25
    +	movsg		ccr ,gr24
    +	movsg		isr ,gr23
    +
    +	setlos.p	#-1,gr4
    +	andi		gr22,#PSR_PS,gr5		/* try to rebuild original PSR value */
    +	andi.p		gr22,#~(PSR_PS|PSR_S),gr6
    +	slli		gr5,#1,gr5
    +	or		gr6,gr5,gr5
    +	andi		gr5,#~PSR_ET,gr5
    +
    +	sti		gr20,@(gr28,#REG_TBR)
    +	sti		gr21,@(gr28,#REG_PC)
    +	sti		gr5 ,@(gr28,#REG_PSR)
    +	sti		gr23,@(gr28,#REG_ISR)
    +	stdi		gr24,@(gr28,#REG_CCR)
    +	stdi		gr26,@(gr28,#REG_LR)
    +	sti		gr4 ,@(gr28,#REG_SYSCALLNO)
    +
    +	movsg		iacc0h,gr4
    +	movsg		iacc0l,gr5
    +	stdi		gr4,@(gr28,#REG_IACC0)
    +
    +	movsg		gner0,gr4
    +	movsg		gner1,gr5
    +	stdi		gr4,@(gr28,#REG_GNER0)
    +
    +	# set up kernel global registers
    +	sethi.p		%hi(__kernel_current_task),gr5
    +	setlo		%lo(__kernel_current_task),gr5
    +	sethi.p		%hi(_gp),gr16
    +	setlo		%lo(_gp),gr16
    +	ldi		@(gr5,#0),gr29
    +	ldi		@(gr29,#4),gr15		; __current_thread_info = current->thread_info
    +
    +	# switch to the kernel trap table
    +	sethi.p		%hi(__entry_kerneltrap_table),gr6
    +	setlo		%lo(__entry_kerneltrap_table),gr6
    +	movgs		gr6,tbr
    +
    +	# make sure we (the kernel) get div-zero and misalignment exceptions
    +	setlos		#ISR_EDE|ISR_DTT_DIVBYZERO|ISR_EMAM_EXCEPTION,gr5
    +	movgs		gr5,isr
    +
    +	# clear power-saving mode flags
    +	movsg		hsr0,gr4
    +	andi		gr4,#~HSR0_PDM,gr4
    +	movgs		gr4,hsr0
    +
    +	# multiplex again using old TBR as a guide
    +	setlos.p	#TBR_TT,gr3
    +	sethi		%hi(__entry_vector_table),gr6
    +	and.p		gr20,gr3,gr5
    +	setlo		%lo(__entry_vector_table),gr6
    +	srli		gr5,#2,gr5
    +	ld		@(gr5,gr6),gr5
    +
    +	LEDS		0x6009
    +	jmpl		@(gr5,gr0)
    +
    +
    +	.size		__entry_common,.-__entry_common
    +
    +###############################################################################
    +#
    +# handle instruction MMU fault
    +#
    +###############################################################################
    +#ifdef CONFIG_MMU
    +	.globl		__entry_insn_mmu_fault
    +__entry_insn_mmu_fault:
    +	LEDS		0x6010
    +	setlos		#0,gr8
    +	movsg		esr0,gr9
    +	movsg		scr2,gr10
    +
    +	# now that we've accessed the exception regs, we can enable exceptions
    +	movsg		psr,gr4
    +	ori		gr4,#PSR_ET,gr4
    +	movgs		gr4,psr
    +
    +	sethi.p		%hi(do_page_fault),gr5
    +	setlo		%lo(do_page_fault),gr5
    +	jmpl		@(gr5,gr0)	; call do_page_fault(0,esr0,ear0)
    +#endif
    +
    +
    +###############################################################################
    +#
    +# handle instruction access error
    +#
    +###############################################################################
    +	.globl		__entry_insn_access_error
    +__entry_insn_access_error:
    +	LEDS		0x6011
    +	sethi.p		%hi(insn_access_error),gr5
    +	setlo		%lo(insn_access_error),gr5
    +	movsg		esfr1,gr8
    +	movsg		epcr0,gr9
    +	movsg		esr0,gr10
    +
    +	# now that we've accessed the exception regs, we can enable exceptions
    +	movsg		psr,gr4
    +	ori		gr4,#PSR_ET,gr4
    +	movgs		gr4,psr
    +	jmpl		@(gr5,gr0)	; call insn_access_error(esfr1,epcr0,esr0)
    +
    +###############################################################################
    +#
    +# handle various instructions of dubious legality
    +#
    +###############################################################################
    +	.globl		__entry_unsupported_trap
    +	.globl		__entry_illegal_instruction
    +	.globl		__entry_privileged_instruction
    +	.globl		__entry_debug_exception
    +__entry_unsupported_trap:
    +	subi		gr21,#4,gr21
    +	sti		gr21,@(gr28,#REG_PC)
    +__entry_illegal_instruction:
    +__entry_privileged_instruction:
    +__entry_debug_exception:
    +	LEDS		0x6012
    +	sethi.p		%hi(illegal_instruction),gr5
    +	setlo		%lo(illegal_instruction),gr5
    +	movsg		esfr1,gr8
    +	movsg		epcr0,gr9
    +	movsg		esr0,gr10
    +
    +	# now that we've accessed the exception regs, we can enable exceptions
    +	movsg		psr,gr4
    +	ori		gr4,#PSR_ET,gr4
    +	movgs		gr4,psr
    +	jmpl		@(gr5,gr0)	; call ill_insn(esfr1,epcr0,esr0)
    +
    +###############################################################################
    +#
    +# handle media exception
    +#
    +###############################################################################
    +	.globl		__entry_media_exception
    +__entry_media_exception:
    +	LEDS		0x6013
    +	sethi.p		%hi(media_exception),gr5
    +	setlo		%lo(media_exception),gr5
    +	movsg		msr0,gr8
    +	movsg		msr1,gr9
    +
    +	# now that we've accessed the exception regs, we can enable exceptions
    +	movsg		psr,gr4
    +	ori		gr4,#PSR_ET,gr4
    +	movgs		gr4,psr
    +	jmpl		@(gr5,gr0)	; call media_excep(msr0,msr1)
    +
    +###############################################################################
    +#
    +# handle data MMU fault
    +# handle data DAT fault (write-protect exception)
    +#
    +###############################################################################
    +#ifdef CONFIG_MMU
    +	.globl		__entry_data_mmu_fault
    +__entry_data_mmu_fault:
    +	.globl		__entry_data_dat_fault
    +__entry_data_dat_fault:
    +	LEDS		0x6014
    +	setlos		#1,gr8
    +	movsg		esr0,gr9
    +	movsg		scr2,gr10	; saved EAR0
    +
    +	# now that we've accessed the exception regs, we can enable exceptions
    +	movsg		psr,gr4
    +	ori		gr4,#PSR_ET,gr4
    +	movgs		gr4,psr
    +
    +	sethi.p		%hi(do_page_fault),gr5
    +	setlo		%lo(do_page_fault),gr5
    +	jmpl		@(gr5,gr0)	; call do_page_fault(1,esr0,ear0)
    +#endif
    +
    +###############################################################################
    +#
    +# handle data and instruction access exceptions
    +#
    +###############################################################################
    +	.globl		__entry_insn_access_exception
    +	.globl		__entry_data_access_exception
    +__entry_insn_access_exception:
    +__entry_data_access_exception:
    +	LEDS		0x6016
    +	sethi.p		%hi(memory_access_exception),gr5
    +	setlo		%lo(memory_access_exception),gr5
    +	movsg		esr0,gr8
    +	movsg		scr2,gr9	; saved EAR0
    +	movsg		epcr0,gr10
    +
    +	# now that we've accessed the exception regs, we can enable exceptions
    +	movsg		psr,gr4
    +	ori		gr4,#PSR_ET,gr4
    +	movgs		gr4,psr
    +	jmpl		@(gr5,gr0)	; call memory_access_error(esr0,ear0,epcr0)
    +
    +###############################################################################
    +#
    +# handle data access error
    +#
    +###############################################################################
    +	.globl		__entry_data_access_error
    +__entry_data_access_error:
    +	LEDS		0x6016
    +	sethi.p		%hi(data_access_error),gr5
    +	setlo		%lo(data_access_error),gr5
    +	movsg		esfr1,gr8
    +	movsg		esr15,gr9
    +	movsg		ear15,gr10
    +
    +	# now that we've accessed the exception regs, we can enable exceptions
    +	movsg		psr,gr4
    +	ori		gr4,#PSR_ET,gr4
    +	movgs		gr4,psr
    +	jmpl		@(gr5,gr0)	; call data_access_error(esfr1,esr15,ear15)
    +
    +###############################################################################
    +#
    +# handle data store error
    +#
    +###############################################################################
    +	.globl		__entry_data_store_error
    +__entry_data_store_error:
    +	LEDS		0x6017
    +	sethi.p		%hi(data_store_error),gr5
    +	setlo		%lo(data_store_error),gr5
    +	movsg		esfr1,gr8
    +	movsg		esr14,gr9
    +
    +	# now that we've accessed the exception regs, we can enable exceptions
    +	movsg		psr,gr4
    +	ori		gr4,#PSR_ET,gr4
    +	movgs		gr4,psr
    +	jmpl		@(gr5,gr0)	; call data_store_error(esfr1,esr14)
    +
    +###############################################################################
    +#
    +# handle division exception
    +#
    +###############################################################################
    +	.globl		__entry_division_exception
    +__entry_division_exception:
    +	LEDS		0x6018
    +	sethi.p		%hi(division_exception),gr5
    +	setlo		%lo(division_exception),gr5
    +	movsg		esfr1,gr8
    +	movsg		esr0,gr9
    +	movsg		isr,gr10
    +
    +	# now that we've accessed the exception regs, we can enable exceptions
    +	movsg		psr,gr4
    +	ori		gr4,#PSR_ET,gr4
    +	movgs		gr4,psr
    +	jmpl		@(gr5,gr0)	; call div_excep(esfr1,esr0,isr)
    +
    +###############################################################################
    +#
    +# handle compound exception
    +#
    +###############################################################################
    +	.globl		__entry_compound_exception
    +__entry_compound_exception:
    +	LEDS		0x6019
    +	sethi.p		%hi(compound_exception),gr5
    +	setlo		%lo(compound_exception),gr5
    +	movsg		esfr1,gr8
    +	movsg		esr0,gr9
    +	movsg		esr14,gr10
    +	movsg		esr15,gr11
    +	movsg		msr0,gr12
    +	movsg		msr1,gr13
    +
    +	# now that we've accessed the exception regs, we can enable exceptions
    +	movsg		psr,gr4
    +	ori		gr4,#PSR_ET,gr4
    +	movgs		gr4,psr
    +	jmpl		@(gr5,gr0)	; call comp_excep(esfr1,esr0,esr14,esr15,msr0,msr1)
    +
    +###############################################################################
    +#
    +# handle interrupts and NMIs
    +#
    +###############################################################################
    +	.globl		__entry_do_IRQ
    +__entry_do_IRQ:
    +	LEDS		0x6020
    +
    +	# we can enable exceptions
    +	movsg		psr,gr4
    +	ori		gr4,#PSR_ET,gr4
    +	movgs		gr4,psr
    +	bra		do_IRQ
    +
    +	.globl		__entry_do_NMI
    +__entry_do_NMI:
    +	LEDS		0x6021
    +
    +	# we can enable exceptions
    +	movsg		psr,gr4
    +	ori		gr4,#PSR_ET,gr4
    +	movgs		gr4,psr
    +	bra		do_NMI
    +
    +###############################################################################
    +#
    +# the return path for a newly forked child process
    +# - __switch_to() saved the old current pointer in GR27 for us
    +#
    +###############################################################################
    +	.globl		ret_from_fork
    +ret_from_fork:
    +	LEDS		0x6100
    +	ori.p		gr27,0,gr8
    +	call		schedule_tail
    +
    +	# fork & co. return 0 to child
    +	setlos.p	#0,gr8
    +	bra		__syscall_exit
    +
    +###################################################################################################
    +#
    +# Return to user mode is not as complex as all this looks,
    +# but we want the default path for a system call return to
    +# go as quickly as possible which is why some of this is
    +# less clear than it otherwise should be.
    +#
    +###################################################################################################
    +	.balign		L1_CACHE_BYTES
    +	.globl		system_call
    +system_call:
    +	LEDS		0x6101
    +	movsg		psr,gr4			; enable exceptions
    +	ori		gr4,#PSR_ET,gr4
    +	movgs		gr4,psr
    +
    +	sti		gr7,@(gr28,#REG_SYSCALLNO)
    +	sti.p		gr8,@(gr28,#REG_ORIG_GR8)
    +
    +	subicc		gr7,#nr_syscalls,gr0,icc0
    +	bnc		icc0,#0,__syscall_badsys
    +
    +	ldi		@(gr15,#TI_FLAGS),gr4
    +	ori		gr4,#_TIF_SYSCALL_TRACE,gr4
    +	andicc		gr4,#_TIF_SYSCALL_TRACE,gr0,icc0
    +	bne		icc0,#0,__syscall_trace_entry
    +	bra		__syscall_trace_entry
    +
    +__syscall_call:
    +	slli.p		gr7,#2,gr7
    +	sethi		%hi(sys_call_table),gr5
    +	setlo		%lo(sys_call_table),gr5
    +	ld		@(gr5,gr7),gr4
    +	calll		@(gr4,gr0)
    +
    +
    +###############################################################################
    +#
    +# return to interrupted process
    +#
    +###############################################################################
    +__syscall_exit:
    +	LEDS		0x6300
    +
    +	sti		gr8,@(gr28,#REG_GR(8))	; save return value
    +
    +	# rebuild saved psr - execve will change it for init/main.c
    +	ldi		@(gr28,#REG_PSR),gr22
    +	srli		gr22,#1,gr5
    +	andi.p		gr22,#~PSR_PS,gr22
    +	andi		gr5,#PSR_PS,gr5
    +	or		gr5,gr22,gr22
    +	ori		gr22,#PSR_S,gr22
    +
    +	# keep current PSR in GR23
    +	movsg		psr,gr23
    +
    +	# make sure we don't miss an interrupt setting need_resched or sigpending between
    +	# sampling and the RETT
    +	ori		gr23,#PSR_PIL_14,gr23
    +	movgs		gr23,psr
    +
    +	ldi		@(gr15,#TI_FLAGS),gr4
    +//	ori		gr4,#_TIF_SYSCALL_TRACE,gr4		/////////////////////////////////
    +	sethi.p		%hi(_TIF_ALLWORK_MASK),gr5
    +	setlo		%lo(_TIF_ALLWORK_MASK),gr5
    +	andcc		gr4,gr5,gr0,icc0
    +	bne		icc0,#0,__syscall_exit_work
    +
    +	# restore all registers and return
    +__entry_return_direct:
    +	LEDS		0x6301
    +
    +	andi		gr22,#~PSR_ET,gr22
    +	movgs		gr22,psr
    +
    +	ldi		@(gr28,#REG_ISR),gr23
    +	lddi		@(gr28,#REG_CCR),gr24
    +	lddi		@(gr28,#REG_LR) ,gr26
    +	ldi		@(gr28,#REG_PC) ,gr21
    +	ldi		@(gr28,#REG_TBR),gr20
    +
    +	movgs		gr20,tbr
    +	movgs		gr21,pcsr
    +	movgs		gr23,isr
    +	movgs		gr24,ccr
    +	movgs		gr25,cccr
    +	movgs		gr26,lr
    +	movgs		gr27,lcr
    +
    +	lddi		@(gr28,#REG_GNER0),gr4
    +	movgs		gr4,gner0
    +	movgs		gr5,gner1
    +
    +	lddi		@(gr28,#REG_IACC0),gr4
    +	movgs		gr4,iacc0h
    +	movgs		gr5,iacc0l
    +
    +	lddi		@(gr28,#REG_GR(4)) ,gr4
    +	lddi		@(gr28,#REG_GR(6)) ,gr6
    +	lddi		@(gr28,#REG_GR(8)) ,gr8
    +	lddi		@(gr28,#REG_GR(10)),gr10
    +	lddi		@(gr28,#REG_GR(12)),gr12
    +	lddi		@(gr28,#REG_GR(14)),gr14
    +	lddi		@(gr28,#REG_GR(16)),gr16
    +	lddi		@(gr28,#REG_GR(18)),gr18
    +	lddi		@(gr28,#REG_GR(20)),gr20
    +	lddi		@(gr28,#REG_GR(22)),gr22
    +	lddi		@(gr28,#REG_GR(24)),gr24
    +	lddi		@(gr28,#REG_GR(26)),gr26
    +	ldi		@(gr28,#REG_GR(29)),gr29
    +	lddi		@(gr28,#REG_GR(30)),gr30
    +
    +	# check to see if a debugging return is required
    +	LEDS		0x67f0
    +	movsg		ccr,gr2
    +	ldi		@(gr28,#REG__STATUS),gr3
    +	andicc		gr3,#REG__STATUS_STEP,gr0,icc0
    +	bne		icc0,#0,__entry_return_singlestep
    +	movgs		gr2,ccr
    +
    +	ldi		@(gr28,#REG_SP)    ,sp
    +	lddi		@(gr28,#REG_GR(2)) ,gr2
    +	ldi		@(gr28,#REG_GR(28)),gr28
    +
    +	LEDS		0x67fe
    +//	movsg		pcsr,gr31
    +//	LEDS32
    +
    +#if 0
    +	# store the current frame in the workram on the FR451
    +	movgs		gr28,scr2
    +	sethi.p		%hi(0xfe800000),gr28
    +	setlo		%lo(0xfe800000),gr28
    +
    +	stdi		gr2,@(gr28,#REG_GR(2))
    +	stdi		gr4,@(gr28,#REG_GR(4))
    +	stdi		gr6,@(gr28,#REG_GR(6))
    +	stdi		gr8,@(gr28,#REG_GR(8))
    +	stdi		gr10,@(gr28,#REG_GR(10))
    +	stdi		gr12,@(gr28,#REG_GR(12))
    +	stdi		gr14,@(gr28,#REG_GR(14))
    +	stdi		gr16,@(gr28,#REG_GR(16))
    +	stdi		gr18,@(gr28,#REG_GR(18))
    +	stdi		gr24,@(gr28,#REG_GR(24))
    +	stdi		gr26,@(gr28,#REG_GR(26))
    +	sti		gr29,@(gr28,#REG_GR(29))
    +	stdi		gr30,@(gr28,#REG_GR(30))
    +
    +	movsg		tbr ,gr30
    +	sti		gr30,@(gr28,#REG_TBR)
    +	movsg		pcsr,gr30
    +	sti		gr30,@(gr28,#REG_PC)
    +	movsg		psr ,gr30
    +	sti		gr30,@(gr28,#REG_PSR)
    +	movsg		isr ,gr30
    +	sti		gr30,@(gr28,#REG_ISR)
    +	movsg		ccr ,gr30
    +	movsg		cccr,gr31
    +	stdi		gr30,@(gr28,#REG_CCR)
    +	movsg		lr  ,gr30
    +	movsg		lcr ,gr31
    +	stdi		gr30,@(gr28,#REG_LR)
    +	sti		gr0 ,@(gr28,#REG_SYSCALLNO)
    +	movsg		scr2,gr28
    +#endif
    +
    +	rett		#0
    +
    +	# return via break.S
    +__entry_return_singlestep:
    +	movgs		gr2,ccr
    +	lddi		@(gr28,#REG_GR(2)) ,gr2
    +	ldi		@(gr28,#REG_SP)    ,sp
    +	ldi		@(gr28,#REG_GR(28)),gr28
    +	LEDS		0x67ff
    +	break
    +	.globl		__entry_return_singlestep_breaks_here
    +__entry_return_singlestep_breaks_here:
    +	nop
    +
    +
    +###############################################################################
    +#
    +# return to a process interrupted in kernel space
    +# - we need to consider preemption if that is enabled
    +#
    +###############################################################################
    +	.balign		L1_CACHE_BYTES
    +__entry_return_from_kernel_exception:
    +	LEDS		0x6302
    +	movsg		psr,gr23
    +	ori		gr23,#PSR_PIL_14,gr23
    +	movgs		gr23,psr
    +	bra		__entry_return_direct
    +
    +	.balign		L1_CACHE_BYTES
    +__entry_return_from_kernel_interrupt:
    +	LEDS		0x6303
    +	movsg		psr,gr23
    +	ori		gr23,#PSR_PIL_14,gr23
    +	movgs		gr23,psr
    +
    +#ifdef CONFIG_PREEMPT
    +	ldi		@(gr15,#TI_PRE_COUNT),gr5
    +	subicc		gr5,#0,gr0,icc0
    +	beq		icc0,#0,__entry_return_direct
    +
    +__entry_preempt_need_resched:
    +	ldi		@(gr15,#TI_FLAGS),gr4
    +	andicc		gr4,#_TIF_NEED_RESCHED,gr0,icc0
    +	beq		icc0,#1,__entry_return_direct
    +
    +	setlos		#PREEMPT_ACTIVE,gr5
    +	sti		gr5,@(gr15,#TI_FLAGS)
    +
    +	andi		gr23,#~PSR_PIL,gr23
    +	movgs		gr23,psr
    +
    +	call		schedule
    +	sti		gr0,@(gr15,#TI_PRE_COUNT)
    +
    +	movsg		psr,gr23
    +	ori		gr23,#PSR_PIL_14,gr23
    +	movgs		gr23,psr
    +	bra		__entry_preempt_need_resched
    +#else
    +	bra		__entry_return_direct
    +#endif
    +
    +
    +###############################################################################
    +#
    +# perform work that needs to be done immediately before resumption
    +#
    +###############################################################################
    +	.balign		L1_CACHE_BYTES
    +__entry_return_from_user_exception:
    +	LEDS		0x6501
    +
    +__entry_resume_userspace:
    +	# make sure we don't miss an interrupt setting need_resched or sigpending between
    +	# sampling and the RETT
    +	movsg		psr,gr23
    +	ori		gr23,#PSR_PIL_14,gr23
    +	movgs		gr23,psr
    +
    +__entry_return_from_user_interrupt:
    +	LEDS		0x6402
    +	ldi		@(gr15,#TI_FLAGS),gr4
    +	sethi.p		%hi(_TIF_WORK_MASK),gr5
    +	setlo		%lo(_TIF_WORK_MASK),gr5
    +	andcc		gr4,gr5,gr0,icc0
    +	beq		icc0,#1,__entry_return_direct
    +
    +__entry_work_pending:
    +	LEDS		0x6404
    +	andicc		gr4,#_TIF_NEED_RESCHED,gr0,icc0
    +	beq		icc0,#1,__entry_work_notifysig
    +
    +__entry_work_resched:
    +	LEDS		0x6408
    +	movsg		psr,gr23
    +	andi		gr23,#~PSR_PIL,gr23
    +	movgs		gr23,psr
    +	call		schedule
    +	movsg		psr,gr23
    +	ori		gr23,#PSR_PIL_14,gr23
    +	movgs		gr23,psr
    +
    +	LEDS		0x6401
    +	ldi		@(gr15,#TI_FLAGS),gr4
    +	sethi.p		%hi(_TIF_WORK_MASK),gr5
    +	setlo		%lo(_TIF_WORK_MASK),gr5
    +	andcc		gr4,gr5,gr0,icc0
    +	beq		icc0,#1,__entry_return_direct
    +	andicc		gr4,#_TIF_NEED_RESCHED,gr0,icc0
    +	bne		icc0,#1,__entry_work_resched
    +
    + __entry_work_notifysig:
    +	LEDS		0x6410
    +	ori.p		gr4,#0,gr8
    +	call		do_notify_resume
    +	bra		__entry_return_direct
    +
    +	# perform syscall entry tracing
    +__syscall_trace_entry:
    +	LEDS		0x6320
    +	setlos.p	#0,gr8
    +	call		do_syscall_trace
    +
    +	ldi		@(gr28,#REG_SYSCALLNO),gr7
    +	lddi		@(gr28,#REG_GR(8)) ,gr8
    +	lddi		@(gr28,#REG_GR(10)),gr10
    +	lddi.p		@(gr28,#REG_GR(12)),gr12
    +
    +	subicc		gr7,#nr_syscalls,gr0,icc0
    +	bnc		icc0,#0,__syscall_badsys
    +	bra		__syscall_call
    +
    +	# perform syscall exit tracing
    +__syscall_exit_work:
    +	LEDS		0x6340
    +	andicc		gr4,#_TIF_SYSCALL_TRACE,gr0,icc0
    +	beq		icc0,#1,__entry_work_pending
    +
    +	movsg		psr,gr23
    +	andi		gr23,#~PSR_PIL,gr23	; could let do_syscall_trace() call schedule()
    +	movgs		gr23,psr
    +
    +	setlos.p	#1,gr8
    +	call		do_syscall_trace
    +	bra		__entry_resume_userspace
    +
    +__syscall_badsys:
    +	LEDS		0x6380
    +	setlos		#-ENOSYS,gr8
    +	sti		gr8,@(gr28,#REG_GR(8))	; save return value
    +	bra		__entry_resume_userspace
    +
    +
    +###############################################################################
    +#
    +# syscall vector table
    +#
    +###############################################################################
    +#ifdef CONFIG_MMU
    +#define __MMU(X) X
    +#else
    +#define __MMU(X) sys_ni_syscall
    +#endif
    +
    +	.section .rodata
    +ALIGN
    +	.globl		sys_call_table
    +sys_call_table:
    +	.long sys_restart_syscall	/* 0 - old "setup()" system call, used for restarting */
    +	.long sys_exit
    +	.long sys_fork
    +	.long sys_read
    +	.long sys_write
    +	.long sys_open		/* 5 */
    +	.long sys_close
    +	.long sys_waitpid
    +	.long sys_creat
    +	.long sys_link
    +	.long sys_unlink		/* 10 */
    +	.long sys_execve
    +	.long sys_chdir
    +	.long sys_time
    +	.long sys_mknod
    +	.long sys_chmod		/* 15 */
    +	.long sys_lchown16
    +	.long sys_ni_syscall			/* old break syscall holder */
    +	.long sys_stat
    +	.long sys_lseek
    +	.long sys_getpid		/* 20 */
    +	.long sys_mount
    +	.long sys_oldumount
    +	.long sys_setuid16
    +	.long sys_getuid16
    +	.long sys_ni_syscall // sys_stime		/* 25 */
    +	.long sys_ptrace
    +	.long sys_alarm
    +	.long sys_fstat
    +	.long sys_pause
    +	.long sys_utime		/* 30 */
    +	.long sys_ni_syscall			/* old stty syscall holder */
    +	.long sys_ni_syscall			/* old gtty syscall holder */
    +	.long sys_access
    +	.long sys_nice
    +	.long sys_ni_syscall	/* 35 */	/* old ftime syscall holder */
    +	.long sys_sync
    +	.long sys_kill
    +	.long sys_rename
    +	.long sys_mkdir
    +	.long sys_rmdir		/* 40 */
    +	.long sys_dup
    +	.long sys_pipe
    +	.long sys_times
    +	.long sys_ni_syscall			/* old prof syscall holder */
    +	.long sys_brk		/* 45 */
    +	.long sys_setgid16
    +	.long sys_getgid16
    +	.long sys_ni_syscall // sys_signal
    +	.long sys_geteuid16
    +	.long sys_getegid16	/* 50 */
    +	.long sys_acct
    +	.long sys_umount				/* recycled never used phys( */
    +	.long sys_ni_syscall			/* old lock syscall holder */
    +	.long sys_ioctl
    +	.long sys_fcntl		/* 55 */
    +	.long sys_ni_syscall			/* old mpx syscall holder */
    +	.long sys_setpgid
    +	.long sys_ni_syscall			/* old ulimit syscall holder */
    +	.long sys_ni_syscall			/* old old uname syscall */
    +	.long sys_umask		/* 60 */
    +	.long sys_chroot
    +	.long sys_ustat
    +	.long sys_dup2
    +	.long sys_getppid
    +	.long sys_getpgrp	/* 65 */
    +	.long sys_setsid
    +	.long sys_sigaction
    +	.long sys_ni_syscall // sys_sgetmask
    +	.long sys_ni_syscall // sys_ssetmask
    +	.long sys_setreuid16	/* 70 */
    +	.long sys_setregid16
    +	.long sys_sigsuspend
    +	.long sys_ni_syscall // sys_sigpending
    +	.long sys_sethostname
    +	.long sys_setrlimit	/* 75 */
    +	.long sys_ni_syscall // sys_old_getrlimit
    +	.long sys_getrusage
    +	.long sys_gettimeofday
    +	.long sys_settimeofday
    +	.long sys_getgroups16	/* 80 */
    +	.long sys_setgroups16
    +	.long sys_ni_syscall			/* old_select slot */
    +	.long sys_symlink
    +	.long sys_lstat
    +	.long sys_readlink		/* 85 */
    +	.long sys_uselib
    +	.long sys_swapon
    +	.long sys_reboot
    +	.long sys_ni_syscall // old_readdir
    +	.long sys_ni_syscall	/* 90 */	/* old_mmap slot */
    +	.long sys_munmap
    +	.long sys_truncate
    +	.long sys_ftruncate
    +	.long sys_fchmod
    +	.long sys_fchown16		/* 95 */
    +	.long sys_getpriority
    +	.long sys_setpriority
    +	.long sys_ni_syscall			/* old profil syscall holder */
    +	.long sys_statfs
    +	.long sys_fstatfs		/* 100 */
    +	.long sys_ni_syscall			/* ioperm for i386 */
    +	.long sys_socketcall
    +	.long sys_syslog
    +	.long sys_setitimer
    +	.long sys_getitimer	/* 105 */
    +	.long sys_newstat
    +	.long sys_newlstat
    +	.long sys_newfstat
    +	.long sys_ni_syscall	/* obsolete olduname( syscall */
    +	.long sys_ni_syscall	/* iopl for i386 */ /* 110 */
    +	.long sys_vhangup
    +	.long sys_ni_syscall	/* obsolete idle( syscall */
    +	.long sys_ni_syscall	/* vm86old for i386 */
    +	.long sys_wait4
    +	.long sys_swapoff		/* 115 */
    +	.long sys_sysinfo
    +	.long sys_ipc
    +	.long sys_fsync
    +	.long sys_sigreturn
    +	.long sys_clone		/* 120 */
    +	.long sys_setdomainname
    +	.long sys_newuname
    +	.long sys_ni_syscall	/* old "cacheflush" */
    +	.long sys_adjtimex
    +	.long __MMU(sys_mprotect) /* 125 */
    +	.long sys_sigprocmask
    +	.long sys_ni_syscall	/* old "create_module" */
    +	.long sys_init_module
    +	.long sys_delete_module
    +	.long sys_ni_syscall	/* old "get_kernel_syms" */
    +	.long sys_quotactl
    +	.long sys_getpgid
    +	.long sys_fchdir
    +	.long sys_bdflush
    +	.long sys_sysfs		/* 135 */
    +	.long sys_personality
    +	.long sys_ni_syscall	/* for afs_syscall */
    +	.long sys_setfsuid16
    +	.long sys_setfsgid16
    +	.long sys_llseek		/* 140 */
    +	.long sys_getdents
    +	.long sys_select
    +	.long sys_flock
    +	.long __MMU(sys_msync)
    +	.long sys_readv		/* 145 */
    +	.long sys_writev
    +	.long sys_getsid
    +	.long sys_fdatasync
    +	.long sys_sysctl
    +	.long __MMU(sys_mlock)		/* 150 */
    +	.long __MMU(sys_munlock)
    +	.long __MMU(sys_mlockall)
    +	.long __MMU(sys_munlockall)
    +	.long sys_sched_setparam
    +	.long sys_sched_getparam   /* 155 */
    +	.long sys_sched_setscheduler
    +	.long sys_sched_getscheduler
    +	.long sys_sched_yield
    +	.long sys_sched_get_priority_max
    +	.long sys_sched_get_priority_min  /* 160 */
    +	.long sys_sched_rr_get_interval
    +	.long sys_nanosleep
    +	.long __MMU(sys_mremap)
    +	.long sys_setresuid16
    +	.long sys_getresuid16	/* 165 */
    +	.long sys_ni_syscall	/* for vm86 */
    +	.long sys_ni_syscall	/* Old sys_query_module */
    +	.long sys_poll
    +	.long sys_nfsservctl
    +	.long sys_setresgid16	/* 170 */
    +	.long sys_getresgid16
    +	.long sys_prctl
    +	.long sys_rt_sigreturn
    +	.long sys_rt_sigaction
    +	.long sys_rt_sigprocmask	/* 175 */
    +	.long sys_rt_sigpending
    +	.long sys_rt_sigtimedwait
    +	.long sys_rt_sigqueueinfo
    +	.long sys_rt_sigsuspend
    +	.long sys_pread64		/* 180 */
    +	.long sys_pwrite64
    +	.long sys_chown16
    +	.long sys_getcwd
    +	.long sys_capget
    +	.long sys_capset           /* 185 */
    +	.long sys_sigaltstack
    +	.long sys_sendfile
    +	.long sys_ni_syscall		/* streams1 */
    +	.long sys_ni_syscall		/* streams2 */
    +	.long sys_vfork            /* 190 */
    +	.long sys_getrlimit
    +	.long sys_mmap2
    +	.long sys_truncate64
    +	.long sys_ftruncate64
    +	.long sys_stat64		/* 195 */
    +	.long sys_lstat64
    +	.long sys_fstat64
    +	.long sys_lchown
    +	.long sys_getuid
    +	.long sys_getgid		/* 200 */
    +	.long sys_geteuid
    +	.long sys_getegid
    +	.long sys_setreuid
    +	.long sys_setregid
    +	.long sys_getgroups	/* 205 */
    +	.long sys_setgroups
    +	.long sys_fchown
    +	.long sys_setresuid
    +	.long sys_getresuid
    +	.long sys_setresgid	/* 210 */
    +	.long sys_getresgid
    +	.long sys_chown
    +	.long sys_setuid
    +	.long sys_setgid
    +	.long sys_setfsuid		/* 215 */
    +	.long sys_setfsgid
    +	.long sys_pivot_root
    +	.long __MMU(sys_mincore)
    +	.long __MMU(sys_madvise)
    +	.long sys_getdents64	/* 220 */
    +	.long sys_fcntl64
    +	.long sys_ni_syscall	/* reserved for TUX */
    +	.long sys_ni_syscall	/* Reserved for Security */
    +	.long sys_gettid
    +	.long sys_readahead	/* 225 */
    +	.long sys_setxattr
    +	.long sys_lsetxattr
    +	.long sys_fsetxattr
    +	.long sys_getxattr
    +	.long sys_lgetxattr	/* 230 */
    +	.long sys_fgetxattr
    +	.long sys_listxattr
    +	.long sys_llistxattr
    +	.long sys_flistxattr
    +	.long sys_removexattr	/* 235 */
    +	.long sys_lremovexattr
    +	.long sys_fremovexattr
    + 	.long sys_tkill
    +	.long sys_sendfile64
    +	.long sys_futex		/* 240 */
    +	.long sys_sched_setaffinity
    +	.long sys_sched_getaffinity
    +	.long sys_ni_syscall	//sys_set_thread_area
    +	.long sys_ni_syscall	//sys_get_thread_area
    +	.long sys_io_setup	/* 245 */
    +	.long sys_io_destroy
    +	.long sys_io_getevents
    +	.long sys_io_submit
    +	.long sys_io_cancel
    +	.long sys_fadvise64	/* 250 */
    +	.long sys_ni_syscall
    +	.long sys_exit_group
    +	.long sys_lookup_dcookie
    +	.long sys_epoll_create
    +	.long sys_epoll_ctl	/* 255 */
    +	.long sys_epoll_wait
    + 	.long __MMU(sys_remap_file_pages)
    + 	.long sys_ni_syscall	//sys_set_tid_address
    + 	.long sys_timer_create
    + 	.long sys_timer_settime		/* 260 */
    + 	.long sys_timer_gettime
    + 	.long sys_timer_getoverrun
    + 	.long sys_timer_delete
    + 	.long sys_clock_settime
    + 	.long sys_clock_gettime		/* 265 */
    + 	.long sys_clock_getres
    + 	.long sys_clock_nanosleep
    +	.long sys_statfs64
    +	.long sys_fstatfs64
    +	.long sys_tgkill	/* 270 */
    +	.long sys_utimes
    + 	.long sys_fadvise64_64
    +	.long sys_ni_syscall	/* sys_vserver */
    +	.long sys_mbind
    +	.long sys_get_mempolicy
    +	.long sys_set_mempolicy
    +	.long sys_mq_open
    +	.long sys_mq_unlink
    +	.long sys_mq_timedsend
    +	.long sys_mq_timedreceive	/* 280 */
    +	.long sys_mq_notify
    +	.long sys_mq_getsetattr
    +	.long sys_ni_syscall		/* reserved for kexec */
    +
    +
    +syscall_table_size = (. - sys_call_table)
    diff -uNrp /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/entry-table.S linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/entry-table.S
    --- /warthog/kernels/linux-2.6.10-rc1-mm3/arch/frv/kernel/entry-table.S	1970-01-01 01:00:00.000000000 +0100
    +++ linux-2.6.10-rc1-mm3-frv/arch/frv/kernel/entry-table.S	2004-11-05 14:13:03.079565365 +0000
    @@ -0,0 +1,277 @@
    +/* entry-table.S: main trap vector tables and exception jump table
    + *
    + * Copyright (C) 2003 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 License
    + * as published by the Free Software Foundation; either version
    + * 2 of the License, or (at your option) any later version.
    + *
    + */
    +
    +#include <linux/sys.h>
    +#include <linux/config.h>
    +#include <linux/linkage.h>
    +#include <asm/spr-regs.h>
    +
    +###############################################################################
    +#
    +# declare the main trap and vector tables
    +#
    +# - the first instruction in each slot is a branch to the appropriate
    +#   kernel-mode handler routine
    +#
    +# - the second instruction in each slot is a branch to the debug-mode hardware
    +#   single-step bypass handler - this is called from break.S to deal with the
    +#   CPU stepping in to exception handlers (particular where external interrupts
    +#   are concerned)
    +#
    +# - the linker script places the user mode and kernel mode trap tables on to
    +#   the same 8Kb page, so that break.S can be more efficient when performing
    +#   single-step bypass management
    +#
    +###############################################################################
    +
    +	# trap table for entry from debug mode
    +	.section	.trap.break,"ax"
    +	.balign		256*16
    +	.globl		__entry_breaktrap_table
    +__entry_breaktrap_table:
    +
    +	# trap table for entry from user mode
    +	.section	.trap.user,"ax"
    +	.balign		256*16
    +	.globl		__entry_usertrap_table
    +__entry_usertrap_table:
    +
    +	# trap table for entry from kernel mode
    +	.section	.trap.kernel,"ax"
    +	.balign		256*16
    +	.globl		__entry_kerneltrap_table
    +__entry_kerneltrap_table:
    +
    +	# exception handler jump table
    +	.section	.trap.vector,"ax"
    +	.balign		256*4
    +	.globl		__entry_vector_table
    +__entry_vector_table:
    +
    +	# trap fixup table for single-stepping in user mode
    +	.section	.trap.fixup.user,"a"
    +	.balign		256*4
    +	.globl		__break_usertrap_fixup_table
    +__break_usertrap_fixup_table:
    +
    +	# trap fixup table for single-stepping in user mode
    +	.section	.trap.fixup.kernel,"a"
    +	.balign		256*4
    +	.globl		__break_kerneltrap_fixup_table
    +__break_kerneltrap_fixup_table:
    +
    +	# handler declaration for a sofware or program interrupt
    +.macro VECTOR_SOFTPROG tbr_tt, vec
    +	.section .trap.user
    +	.org		\tbr_tt
    +	bra		__entry_uspace_softprog_interrupt
    +	.section .trap.fixup.user
    +	.org		\tbr_tt >> 2
    +	.long		__break_step_uspace_softprog_interrupt
    +	.section .trap.kernel
    +	.org		\tbr_tt
    +	bra		__entry_kernel_softprog_interrupt
    +	.section .trap.fixup.kernel
    +	.org		\tbr_tt >> 2
    +	.long		__break_step_kernel_softprog_interrupt
    +	.section .trap.vector
    +	.org		\tbr_tt >> 2
    +	.long		\vec
    +.endm
    +
    +	# handler declaration for a maskable external interrupt
    +.macro VECTOR_IRQ tbr_tt, vec
    +	.section .trap.user
    +	.org		\tbr_tt
    +	bra		__entry_uspace_external_interrupt
    +	.section .trap.fixup.user
    +	.org		\tbr_tt >> 2
    +	.long		__break_step_uspace_external_interrupt
    +	.section .trap.kernel
    +	.org		\tbr_tt
    +	bra		__entry_kernel_external_interrupt
    +	.section .trap.fixup.kernel
    +	.org		\tbr_tt >> 2
    +	.long		__break_step_kernel_external_interrupt
    +	.section .trap.vector
    +	.org		\tbr_tt >> 2
    +	.long		\vec
    +.endm
    +
    +	# handler declaration for an NMI external interrupt
    +.macro VECTOR_NMI tbr_tt, vec
    +	.section .trap.user
    +	.org		\tbr_tt
    +	break
    +	break
    +	break
    +	break
    +	.section .trap.kernel
    +	.org		\tbr_tt
    +	break
    +	break
    +	break
    +	break
    +	.section .trap.vector
    +	.org		\tbr_tt >> 2
    +	.long		\vec
    +.endm
    +
    +	# handler declaration for an MMU only sofware or program interrupt
    +.macro VECTOR_SP_MMU tbr_tt, vec
    +#ifdef CONFIG_MMU
    + 	VECTOR_SOFTPROG	\tbr_tt, \vec
    +#else
    +	VECTOR_NMI	\tbr_tt, 0
    +#endif
    +.endm
    +
    +
    +###############################################################################
    +#
    +# specification of the vectors
    +# - note: each macro inserts code into multiple sections
    +#
    +###############################################################################
    +	VECTOR_SP_MMU	TBR_TT_INSTR_MMU_MISS,	__entry_insn_mmu_miss
    +	VECTOR_SOFTPROG	TBR_TT_INSTR_ACC_ERROR,	__entry_insn_access_error
    +	VECTOR_SOFTPROG	TBR_TT_INSTR_ACC_EXCEP,	__entry_insn_access_exception
    +	VECTOR_SOFTPROG	TBR_TT_PRIV_INSTR,	__entry_privileged_instruction
    +	VECTOR_SOFTPROG	TBR_TT_ILLEGAL_INSTR,	__entry_illegal_instruction
    +	VECTOR_SOFTPROG	TBR_TT_FP_EXCEPTION,	__entry_media_exception
    +	VECTOR_SOFTPROG	TBR_TT_MP_EXCEPTION,	__entry_media_exception
    +	VECTOR_SOFTPROG	TBR_TT_DATA_ACC_ERROR,	__entry_data_access_error
    +	VECTOR_SP_MMU	TBR_TT_DATA_MMU_MISS,	__entry_data_mmu_miss
    +	VECTOR_SOFTPROG	TBR_TT_DATA_ACC_EXCEP,	__entry_data_access_exception
    +	VECTOR_SOFTPROG	TBR_TT_DATA_STR_ERROR,	__entry_data_store_error
    +	VECTOR_SOFTPROG	TBR_TT_DIVISION_EXCEP,	__entry_division_exception
    +
    +#ifdef CONFIG_MMU
    +	.section .trap.user
    +	.org		TBR_TT_INSTR_TLB_MISS
    +	.globl		__trap_user_insn_tlb_miss
    +__trap_user_insn_tlb_miss:
    +	movsg		ear0,gr28			/* faulting address */
    +	movsg		scr0,gr31			/* get mapped PTD coverage start address */
    +	xor.p		gr28,gr31,gr31			/* compare addresses */
    +	bra		__entry_user_insn_tlb_miss
    +
    +	.org		TBR_TT_DATA_TLB_MISS
    +	.globl		__trap_user_data_tlb_miss
    +__trap_user_data_tlb_miss:
    +	movsg		ear0,gr28			/* faulting address */
    +	movsg		scr1,gr31			/* get mapped PTD coverage start address */
    +	xor.p		gr28,gr31,gr31			/* compare addresses */
    +	bra		__entry_user_data_tlb_miss
    +
    +	.section .trap.kernel
    +	.org		TBR_TT_INSTR_TLB_MISS
    +	.globl		__trap_kernel_insn_tlb_miss
    +__trap_kernel_insn_tlb_miss:
    +	movsg		ear0,gr29			/* faulting address */
    +	movsg		scr0,gr31			/* get mapped PTD coverage start address */
    +	xor.p		gr29,gr31,gr31			/* compare addresses */
    +	bra		__entry_kernel_insn_tlb_miss
    +
    +	.org		TBR_TT_DATA_TLB_MISS
    +	.globl		__trap_kernel_data_tlb_miss
    +__trap_kernel_data_tlb_miss:
    +	movsg		ear0,gr29			/* faulting address */
    +	movsg		scr1,gr31			/* get mapped PTD coverage start address */
    +	xor.p		gr29,gr31,gr31			/* compare addresses */
    +	bra		__entry_kernel_data_tlb_miss
    +
    +	.section .trap.fixup.user
    +	.org		TBR_TT_INSTR_TLB_MISS >> 2
    +	.globl		__trap_fixup_user_insn_tlb_miss
    +__trap_fixup_user_insn_tlb_miss:
    +	.long		__break_user_insn_tlb_miss
    +	.org		TBR_TT_DATA_TLB_MISS >> 2
    +	.globl		__trap_fixup_user_data_tlb_miss
    +__trap_fixup_user_data_tlb_miss:
    +	.long		__break_user_data_tlb_miss
    +
    +	.section .trap.fixup.kernel
    +	.org		TBR_TT_INSTR_TLB_MISS >> 2
    +	.globl		__trap_fixup_kernel_insn_tlb_miss
    +__trap_fixup_kernel_insn_tlb_miss:
    +	.long		__break_kernel_insn_tlb_miss
    +	.org		TBR_TT_DATA_TLB_MISS >> 2
    +	.globl		__trap_fixup_kernel_data_tlb_miss
    +__trap_fixup_kernel_data_tlb_miss:
    +	.long		__break_kernel_data_tlb_miss
    +	
    +	.section .trap.vector
    +	.org		TBR_TT_INSTR_TLB_MISS >> 2
    +	.long		__entry_insn_mmu_fault
    +	.org		TBR_TT_DATA_TLB_MISS >> 2
    +	.long		__entry_data_mmu_fault
    +#endif
    +
    +	VECTOR_SP_MMU	TBR_TT_DATA_DAT_EXCEP,	__entry_data_dat_fault
    +	VECTOR_NMI	TBR_TT_DECREMENT_TIMER,	__entry_do_NMI
    +	VECTOR_SOFTPROG	TBR_TT_COMPOUND_EXCEP,	__entry_compound_exception
    +	VECTOR_IRQ	TBR_TT_INTERRUPT_1,	__entry_do_IRQ
    +	VECTOR_IRQ	TBR_TT_INTERRUPT_2,	__entry_do_IRQ
    +	VECTOR_IRQ	TBR_TT_INTERRUPT_3,	__entry_do_IRQ
    +	VECTOR_IRQ	TBR_TT_INTERRUPT_4,	__entry_do_IRQ
    +	VECTOR_IRQ	TBR_TT_INTERRUPT_5,	__entry_do_IRQ
    +	VECTOR_IRQ	TBR_TT_INTERRUPT_6,	__entry_do_IRQ
    +	VECTOR_IRQ	TBR_TT_INTERRUPT_7,	__entry_do_IRQ
    +	VECTOR_IRQ	TBR_TT_INTERRUPT_8,	__entry_do_IRQ
    +	VECTOR_IRQ	TBR_TT_INTERRUPT_9,	__entry_do_IRQ
    +	VECTOR_IRQ	TBR_TT_INTERRUPT_10,	__entry_do_IRQ
    +	VECTOR_IRQ	TBR_TT_INTERRUPT_11,	__entry_do_IRQ
    +	VECTOR_IRQ	TBR_TT_INTERRUPT_12,	__entry_do_IRQ
    +	VECTOR_IRQ	TBR_TT_INTERRUPT_13,	__entry_do_IRQ
    +	VECTOR_IRQ	TBR_TT_INTERRUPT_14,	__entry_do_IRQ
    +	VECTOR_NMI	TBR_TT_INTERRUPT_15,	__entry_do_NMI
    +
    +	# miscellaneous user mode entry points
    +	.section	.trap.user
    +	.org		TBR_TT_TRAP0
    +	.rept		127
    +	bra		__entry_uspace_softprog_interrupt
    +	bra		__break_step_uspace_softprog_interrupt
    +	.long		0,0
    +	.endr
    +	.org		TBR_TT_BREAK
    +	bra		__entry_break
    +	.long		0,0,0
    +
    +	# miscellaneous kernel mode entry points
    +	.section	.trap.kernel
    +	.org		TBR_TT_TRAP0
    +	.rept		127
    +	bra		__entry_kernel_softprog_interrupt
    +	bra		__break_step_kernel_softprog_interrupt
    +	.long		0,0
    +	.endr
    +	.org		TBR_TT_BREAK
    +	bra		__entry_break
    +	.long		0,0,0
    +
    +	# miscellaneous debug mode entry points
    +	.section	.trap.break
    +	.org		TBR_TT_BREAK
    +	movsg		bpcsr,gr30
    +	jmpl		@(gr30,gr0)
    +
    +	# miscellaneous vectors
    +	.section	.trap.vector
    +	.org		TBR_TT_TRAP0 >> 2
    +	.long		system_call
    +	.rept		126
    +	.long		__entry_unsupported_trap
    +	.endr
    +	.org		TBR_TT_BREAK >> 2
    +	.long		__entry_debug_exception
    -
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at  http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at  http://www.tux.org/lkml/
    

  • Next message: dhowells_at_redhat.com: "[PATCH 17/20] FRV: Better mmap support in uClinux"

    Relevant Pages