[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
RE: [microblaze-uclinux] [PATCH] return from interrupt.
Well then you need to investigate more. The patch is correct and
needed.
but If you have the same problem with the interrupt disable I have seen
all sort of interesting things can happen.
you could try to run with the attaches files
arch/microblaze/kernel/entry.S
include/asm-microblaze/system.h
On Wed, 2007-11-14 at 09:01 +0100, Brettschneider Falk wrote:
> Hi,
>
> kenneth johansson wrote:
> > Sorry to hear you have problems but the patch is right and
> > necessary for
> > every possible combination of configurations.good to hear it's more stable for you, but nevertheless the patch doesn't seem to be right for all cases because
> both boot loggings I showed to you just differ in 1 line with your 'disable_irq'. I went the safe way and did a 'make clean all' for both of my trials.
>
> CU, F@lk
>
>
> ___________________________
> microblaze-uclinux mailing list
> microblaze-uclinux@xxxxxxxxxxxxxx
> Project Home Page : http://www.itee.uq.edu.au/~jwilliams/mblaze-uclinux
> Mailing List Archive : http://www.itee.uq.edu.au/~listarch/microblaze-uclinux/
>
>
/*
* arch/microblaze/kernel/entry.S
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) 2006 Atmark Techno, Inc.
*/
#include <linux/linkage.h>
#include <asm/thread_info.h>
#include <asm/errno.h>
#include <asm/asm-offsets.h>
#include <asm/registers.h>
#include <asm/unistd.h>
#include <asm/percpu.h>
#include <asm/signal.h>
#define PER_CPU(var) per_cpu__##var
#if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR
.macro disable_irq
nop
msrclr r0, MSR_IE
nop
.endm
.macro enable_irq
nop
msrset r0, MSR_IE
nop
.endm
.macro clear_bip
nop
msrclr r0, MSR_BIP
nop
.endm
#else
.macro disable_irq
nop
mfs r11, rmsr
andi r11, r11, ~MSR_IE
mts rmsr, r11
nop
.endm
.macro enable_irq
nop
mfs r11, rmsr
ori r11, r11, MSR_IE
mts rmsr, r11
nop
.endm
.macro clear_bip
nop
mfs r11, rmsr
andi r11, r11, ~MSR_BIP
mts rmsr, r11
nop
.endm
#endif
ENTRY(_interrupt)
swi r1, r0, PER_CPU(ENTRY_SP) /* save the current sp */
swi r11, r0, PER_CPU(R11_SAVE) /* temporarily save r11 */
lwi r11, r0, PER_CPU(KM) /* load mode indicator */
beqid r11, 1f
nop
brid 2f /* jump over */
addik r1, r1, (-PT_SIZE) /* room for pt_regs (delay slot) */
1: /* switch to kernel stack */
lwi r1, r0, PER_CPU(CURRENT_SAVE) /* get the saved current */
lwi r1, r1, TS_THREAD_INFO /* get the thread info */
addik r1, r1, THREAD_SIZE - PT_SIZE /* calculate kernel stack pointer */
2:
swi r11, r1, PT_MODE /* store the mode */
lwi r11, r0, PER_CPU(R11_SAVE) /* reload r11 */
swi r2, r1, PT_R2
swi r3, r1, PT_R3
swi r4, r1, PT_R4
swi r5, r1, PT_R5
swi r6, r1, PT_R6
swi r7, r1, PT_R7
swi r8, r1, PT_R8
swi r9, r1, PT_R9
swi r10, r1, PT_R10
swi r11, r1, PT_R11
swi r12, r1, PT_R12
swi r13, r1, PT_R13
swi r14, r1, PT_R14
swi r14, r1, PT_PC
swi r15, r1, PT_R15
swi r16, r1, PT_R16
swi r17, r1, PT_R17
swi r18, r1, PT_R18
swi r19, r1, PT_R19
swi r20, r1, PT_R20
swi r21, r1, PT_R21
swi r22, r1, PT_R22
swi r23, r1, PT_R23
swi r24, r1, PT_R24
swi r25, r1, PT_R25
swi r26, r1, PT_R26
swi r27, r1, PT_R27
swi r28, r1, PT_R28
swi r29, r1, PT_R29
swi r30, r1, PT_R30
swi r31, r1, PT_R31
/* special purpose registers */
mfs r11, rmsr
swi r11, r1, PT_MSR
mfs r11, rear
swi r11, r1, PT_EAR
mfs r11, resr
swi r11, r1, PT_ESR
mfs r11, rfsr
swi r11, r1, PT_FSR
/* reload original stack pointer and save it */
lwi r11, r0, PER_CPU(ENTRY_SP)
swi r11, r1, PT_R1
/* update mode indicator we are in kernel mode */
addik r11, r0, 1
swi r11, r0, PER_CPU(KM)
/* restore r31 */
lwi r31, r0, PER_CPU(CURRENT_SAVE)
/* prepare the link register, the argument and jump */
la r15, r0, ret_from_intr - 8
addk r6, r0, r15
braid do_IRQ
add r5, r0, r1
.globl ret_from_intr
ret_from_intr:
lwi r11, r1, PT_MODE
bneid r11, 3f
lwi r6, r31, TS_THREAD_INFO /* get thread info */
lwi r19, r6, TI_FLAGS /* get flags in thread info */
/* do an extra work if any bits are set */
andi r11, r19, _TIF_NEED_RESCHED
beqi r11, 1f
bralid r15, schedule
nop
1: andi r11, r19, _TIF_SIGPENDING
beqid r11, no_intr_reshed
addk r5, r1, r0
addk r7, r0, r0
bralid r15, do_signal
addk r6, r0, r0
no_intr_reshed:
/* save mode indicator */
lwi r11, r1, PT_MODE
3:
2: /* disable irq until it's done */
disable_irq
mfs r19, rmsr
nop
andi r19,r19,0x2
bnei r19,2b
.global ret_intr_min
ret_intr_min:
4:
swi r11, r0, PER_CPU(KM)
/* save r31 */
swi r31, r0, PER_CPU(CURRENT_SAVE)
restore_context:
/* special purpose registers */
lwi r11, r1, PT_FSR
mts rfsr, r11
lwi r11, r1, PT_ESR
mts resr, r11
lwi r11, r1, PT_EAR
mts rear, r11
lwi r11, r1, PT_MSR
mts rmsr, r11
lwi r31, r1, PT_R31
lwi r30, r1, PT_R30
lwi r29, r1, PT_R29
lwi r28, r1, PT_R28
lwi r27, r1, PT_R27
lwi r26, r1, PT_R26
lwi r25, r1, PT_R25
lwi r24, r1, PT_R24
lwi r23, r1, PT_R23
lwi r22, r1, PT_R22
lwi r21, r1, PT_R21
lwi r20, r1, PT_R20
lwi r19, r1, PT_R19
lwi r18, r1, PT_R18
lwi r17, r1, PT_R17
lwi r16, r1, PT_R16
lwi r15, r1, PT_R15
lwi r14, r1, PT_PC
lwi r13, r1, PT_R13
lwi r12, r1, PT_R12
lwi r11, r1, PT_R11
lwi r10, r1, PT_R10
lwi r9, r1, PT_R9
lwi r8, r1, PT_R8
lwi r7, r1, PT_R7
lwi r6, r1, PT_R6
lwi r5, r1, PT_R5
lwi r4, r1, PT_R4
lwi r3, r1, PT_R3
lwi r2, r1, PT_R2
lwi r1, r1, PT_R1
rtid r14, 0
nop
.global ret_intr_max
ret_intr_max:
ENTRY(_reset)
bri 0
ENTRY(_user_exception)
swi r1, r0, PER_CPU(ENTRY_SP) /* save the current sp */
swi r11, r0, PER_CPU(R11_SAVE) /* temporarily save r11 */
lwi r11, r0, PER_CPU(KM) /* load mode indicator */
beqid r11, 1f /* Already in kernel mode? */
nop
brid 2f /* jump over */
addik r1, r1, (-PT_SIZE) /* Room for pt_regs (delay slot) */
1: /* Switch to kernel stack */
lwi r1, r0, PER_CPU(CURRENT_SAVE) /* get the saved current */
lwi r1, r1, TS_THREAD_INFO /* get the thread info */
addik r1, r1, THREAD_SIZE - PT_SIZE /* calculate kernel stack pointer */
swi r11, r0, PER_CPU(R11_SAVE) /* temporarily save r11 */
lwi r11, r0, PER_CPU(KM) /* load mode indicator */
2:
swi r11, r1, PT_MODE /* store the mode */
lwi r11, r0, PER_CPU(R11_SAVE) /* reload r11 */
/* save them on stack */
swi r2, r1, PT_R2
swi r3, r1, PT_R3 /* r3: _always_ in clobber list; see unistd.h */
swi r4, r1, PT_R4 /* r4: _always_ in clobber list; see unistd.h */
swi r5, r1, PT_R5
swi r6, r1, PT_R6
swi r7, r1, PT_R7
swi r8, r1, PT_R8
swi r9, r1, PT_R9
swi r10, r1, PT_R10
swi r11, r1, PT_R11
swi r12, r1, PT_R12 /* r12: _always_ in clobber list; see unistd.h */
swi r13, r1, PT_R13
swi r14, r1, PT_R14 /* r14: _always_ in clobber list; see unistd.h */
addik r14, r14, 0x4 /* but we want to return to the next inst. */
swi r14, r1, PT_PC /* increment by 4 and store in pc */
swi r15, r1, PT_R15
swi r16, r1, PT_R16
swi r17, r1, PT_R17
swi r18, r1, PT_R18
swi r19, r1, PT_R19
swi r20, r1, PT_R20
swi r21, r1, PT_R21
swi r22, r1, PT_R22
swi r23, r1, PT_R23
swi r24, r1, PT_R24
swi r25, r1, PT_R25
swi r26, r1, PT_R26
swi r27, r1, PT_R27
swi r28, r1, PT_R28
swi r29, r1, PT_R29
swi r30, r1, PT_R30
swi r31, r1, PT_R31
3: /* disable irq until it's done */
disable_irq
mfs r11, rmsr
nop
andi r11,r11,0x2
bnei r11,3b
nop /* make sure IE bit is in effect */
clear_bip /* once IE is in effect it is safe to clear BIP */
nop
/* special purpose registers */
mfs r11, rmsr
swi r11, r1, PT_MSR
mfs r11, rear
swi r11, r1, PT_EAR
mfs r11, resr
swi r11, r1, PT_ESR
mfs r11, rfsr
swi r11, r1, PT_FSR
/* reload original stack pointer and save it */
lwi r11, r0, PER_CPU(ENTRY_SP)
swi r11, r1, PT_R1
/* update mode indicator we are in kernel mode */
addik r11, r0, 1
swi r11, r0, PER_CPU(KM)
/* restore r31 */
lwi r31, r0, PER_CPU(CURRENT_SAVE)
/* re-enable interrupts now we are in kernel mode */
4: /* enable interrupt until it's done */
enable_irq
mfs r11, rmsr
nop
andi r11,r11,0x2
beqi r11,4b
addi r11, r12, -NR_syscalls /* See if the system call number is valid. */
bgei r11, 1f /* return to user if not valid
/* Figure out which function to use for this system call. */
/* Note Microblaze barrel shift is optional, so don't rely on it */
add r12, r12, r12 /* convert num -> ptr */
add r12, r12, r12
lwi r12, r12, sys_call_table /* Get function pointer */
la r15, r0, ret_to_user-8 /* set return address */
bra r12 /* Make the system call. */
bri 0 /* won't reach here */
1:
brid ret_to_user /* jump to syscall epilogue */
addi r3, r0, -ENOSYS /* set errno in delay slot */
/* Debug traps are like a system call, but entered via brki r14, 0x60
All we need to do is send the SIGTRAP signal to current, ptrace and do_signal
will handle the rest */
ENTRY(_debug_exception)
swi r1, r0, PER_CPU(ENTRY_SP) /* save the current sp */
lwi r1, r0, PER_CPU(CURRENT_SAVE) /* get the saved current */
lwi r1, r1, TS_THREAD_INFO /* get the thread info */
addik r1, r1, THREAD_SIZE - PT_SIZE /* get the kernel stack */
swi r11, r0, PER_CPU(R11_SAVE) /* temporarily save r11 */
lwi r11, r0, PER_CPU(KM) /* load mode indicator */
//save_context:
swi r11, r1, PT_MODE /* store the mode */
lwi r11, r0, PER_CPU(R11_SAVE) /* reload r11 */
/* save them on stack */
swi r2, r1, PT_R2
swi r3, r1, PT_R3 /* r3: _always_ in clobber list; see unistd.h */
swi r4, r1, PT_R4 /* r4: _always_ in clobber list; see unistd.h */
swi r5, r1, PT_R5
swi r6, r1, PT_R6
swi r7, r1, PT_R7
swi r8, r1, PT_R8
swi r9, r1, PT_R9
swi r10, r1, PT_R10
swi r11, r1, PT_R11
swi r12, r1, PT_R12 /* r12: _always_ in clobber list; see unistd.h */
swi r13, r1, PT_R13
swi r14, r1, PT_R14 /* r14: _always_ in clobber list; see unistd.h */
swi r14, r1, PT_PC /* Will return to interrupted instruction */
swi r15, r1, PT_R15
swi r16, r1, PT_R16
swi r17, r1, PT_R17
swi r18, r1, PT_R18
swi r19, r1, PT_R19
swi r20, r1, PT_R20
swi r21, r1, PT_R21
swi r22, r1, PT_R22
swi r23, r1, PT_R23
swi r24, r1, PT_R24
swi r25, r1, PT_R25
swi r26, r1, PT_R26
swi r27, r1, PT_R27
swi r28, r1, PT_R28
swi r29, r1, PT_R29
swi r30, r1, PT_R30
swi r31, r1, PT_R31
3: /* disable irq until it's done */
disable_irq
mfs r11, rmsr
nop
andi r11,r11,0x2
bnei r11,3b
nop /* make sure IE bit is in effect */
clear_bip /* once IE is in effect it is safe to clear BIP */
nop
/* special purpose registers */
mfs r11, rmsr
swi r11, r1, PT_MSR
mfs r11, rear
swi r11, r1, PT_EAR
mfs r11, resr
swi r11, r1, PT_ESR
mfs r11, rfsr
swi r11, r1, PT_FSR
/* reload original stack pointer and save it */
lwi r11, r0, PER_CPU(ENTRY_SP)
swi r11, r1, PT_R1
/* update mode indicator we are in kernel mode */
addik r11, r0, 1
swi r11, r0, PER_CPU(KM)
/* restore r31 */
lwi r31, r0, PER_CPU(CURRENT_SAVE)
/* re-enable interrupts now we are in kernel mode */
4: /* enable interrupt until it's done */
enable_irq
mfs r11, rmsr
nop
andi r11,r11,0x2
beqi r11,4b
addi r5, r0, SIGTRAP /* sending the trap signal */
add r6, r0, r31 /* to current */
bralid r15, send_sig
add r7, r0, r0 /* 3rd param zero */
/* Restore r3/r4 to work around how ret_to_user works */
lwi r3, r1, PT_R3
lwi r4, r1, PT_R4
bri ret_to_user
ENTRY(_break)
bri 0
/* struct task_struct *_switch_to(struct thread_info *prev, struct thread_info *next); */
ENTRY(_switch_to)
/* prepare return value */
addk r3, r0, r31
/* save registers in cpu_context */
/* use r11 and r12, volatile registers, as temp register */
addik r11, r5, TI_CPU_CONTEXT
swi r1, r11, CC_SP
swi r2, r11, CC_R2
/* skip volatile registers.
* they are saved on stack when we jumped to _switch_to() */
/* dedicated registers */
swi r13, r11, CC_R13
swi r14, r11, CC_R14
swi r15, r11, CC_R15
swi r16, r11, CC_R16
swi r17, r11, CC_R17
swi r18, r11, CC_R18
/* save non-volatile registers */
swi r19, r11, CC_R19
swi r20, r11, CC_R20
swi r21, r11, CC_R21
swi r22, r11, CC_R22
swi r23, r11, CC_R23
swi r24, r11, CC_R24
swi r25, r11, CC_R25
swi r26, r11, CC_R26
swi r27, r11, CC_R27
swi r28, r11, CC_R28
swi r29, r11, CC_R29
swi r30, r11, CC_R30
/* special purpose registers */
mfs r12, rmsr
swi r12, r11, CC_MSR
mfs r12, rear
swi r12, r11, CC_EAR
mfs r12, resr
swi r12, r11, CC_ESR
mfs r12, rfsr
swi r12, r11, CC_FSR
/* update r31, the current */
lwi r31, r6, TI_TASK
swi r31, r0, PER_CPU(CURRENT_SAVE)
/* get new process' cpu context and restore */
addik r11, r6, TI_CPU_CONTEXT
/* special purpose registers */
lwi r12, r11, CC_FSR
mts rfsr, r12
lwi r12, r11, CC_ESR
mts resr, r12
lwi r12, r11, CC_EAR
mts rear, r12
lwi r12, r11, CC_MSR
mts rmsr, r12
/* non-volatile registers */
lwi r30, r11, CC_R30
lwi r29, r11, CC_R29
lwi r28, r11, CC_R28
lwi r27, r11, CC_R27
lwi r26, r11, CC_R26
lwi r25, r11, CC_R25
lwi r24, r11, CC_R24
lwi r23, r11, CC_R23
lwi r22, r11, CC_R22
lwi r21, r11, CC_R21
lwi r20, r11, CC_R20
lwi r19, r11, CC_R19
/* dedicated registers */
lwi r18, r11, CC_R18
lwi r17, r11, CC_R17
lwi r16, r11, CC_R16
lwi r15, r11, CC_R15
lwi r14, r11, CC_R14
lwi r13, r11, CC_R13
/* skip volatile registers */
lwi r2, r11, CC_R2
lwi r1, r11, CC_SP
rtsd r15, 8
nop
ENTRY(ret_from_fork)
addk r5, r0, r3
addk r6, r0, r1
brlid r15, schedule_tail
nop
swi r31, r1, PT_R31 /* save r31 in user context. */
/* will soon be restored to r31 in ret_to_user */
addk r3, r0, r0
brid ret_to_user
nop
work_pending:
andi r11, r19, _TIF_NEED_RESCHED
beqi r11, 1f
bralid r15, schedule
nop
1: andi r11, r19, _TIF_SIGPENDING
beqi r11, no_work_pending
addk r5, r1, r0
addik r7, r0, 1
bralid r15, do_signal
addk r6, r0, r0
bri no_work_pending
ENTRY(ret_to_user)
3: /* disable irq until it's done */
disable_irq
mfs r19, rmsr
nop
andi r19,r19,0x2
bnei r19,3b
swi r4, r1, PT_R4 /* return val */
swi r3, r1, PT_R3 /* return val */
lwi r6, r31, TS_THREAD_INFO /* get thread info */
lwi r19, r6, TI_FLAGS /* get flags in thread info */
bnei r19, work_pending /* do an extra work if any bits are set */
no_work_pending:
3: /* disable irq until it's done */
disable_irq
mfs r19, rmsr
nop
andi r19,r19,0x2
bnei r19,3b
/* save r31 */
swi r31, r0, PER_CPU(CURRENT_SAVE)
/* save mode indicator */
lwi r18, r1, PT_MODE
swi r18, r0, PER_CPU(KM)
//restore_context:
/* special purpose registers */
lwi r18, r1, PT_FSR
mts rfsr, r18
lwi r18, r1, PT_ESR
mts resr, r18
lwi r18, r1, PT_EAR
mts rear, r18
lwi r18, r1, PT_MSR
mts rmsr, r18
lwi r31, r1, PT_R31
lwi r30, r1, PT_R30
lwi r29, r1, PT_R29
lwi r28, r1, PT_R28
lwi r27, r1, PT_R27
lwi r26, r1, PT_R26
lwi r25, r1, PT_R25
lwi r24, r1, PT_R24
lwi r23, r1, PT_R23
lwi r22, r1, PT_R22
lwi r21, r1, PT_R21
lwi r20, r1, PT_R20
lwi r19, r1, PT_R19
lwi r18, r1, PT_R18
lwi r17, r1, PT_R17
lwi r16, r1, PT_R16
lwi r15, r1, PT_R15
lwi r14, r1, PT_PC
lwi r13, r1, PT_R13
lwi r12, r1, PT_R12
lwi r11, r1, PT_R11
lwi r10, r1, PT_R10
lwi r9, r1, PT_R9
lwi r8, r1, PT_R8
lwi r7, r1, PT_R7
lwi r6, r1, PT_R6
lwi r5, r1, PT_R5
lwi r4, r1, PT_R4 /* return val */
lwi r3, r1, PT_R3 /* return val */
lwi r2, r1, PT_R2
lwi r1, r1, PT_R1
rtid r14, 0
nop
sys_vfork_wrapper:
brid sys_vfork
addk r5, r1, r0
sys_clone_wrapper:
brid sys_clone
addk r7, r1, r0
sys_execve_wrapper:
brid sys_execve
addk r8, r1, r0
sys_sigreturn_wrapper:
brid sys_sigreturn
addk r5, r1, r0
sys_rt_sigreturn_wrapper:
brid sys_rt_sigreturn
addk r5, r1, r0
sys_sigsuspend_wrapper:
brid sys_rt_sigsuspend
addk r6, r1, r0
sys_rt_sigsuspend_wrapper:
brid sys_rt_sigsuspend
addk r7, r1, r0
/* Interrupt vector table */
.section .init.ivt, "ax"
.org 0x0
brai _reset
brai _user_exception
brai _interrupt
brai _break
brai _hw_exception_handler
.org 0x60
brai _debug_exception
.section .rodata,"a"
#include "syscall_table.S"
syscall_table_size=(.-sys_call_table)
/*
* include/asm-microblaze/system.h
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) 2006 Atmark Techno, Inc.
*/
#ifndef _ASM_SYSTEM_H
#define _ASM_SYSTEM_H
#include <linux/autoconf.h>
#include <asm/registers.h>
struct task_struct;
struct thread_info;
extern struct task_struct * _switch_to(struct thread_info *prev, struct thread_info *next);
#define switch_to(prev, next, last) \
do { \
(last) = _switch_to(task_thread_info(prev), task_thread_info(next)); \
} while(0)
#if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR
int printk(const char * fmt, ...)
__attribute__ ((format (printf, 1, 2)));
#define local_irq_save(flags) \
do { \
asm volatile ("# local_irq_save \n\t" \
"nop\n\t" \
"msrclr %0, %1 \n\t" \
"nop\n\t" \
: "=r"(flags) \
: "i"(MSR_IE) \
: "memory"); \
} while(!irqs_disabled())
#define local_irq_disable() \
do { \
asm volatile ("# local_irq_disable \n\t" \
"nop\n\t" \
"msrclr r0, %0 \n\t" \
"nop\n\t" \
: \
: "i"(MSR_IE) \
: "memory"); \
} while(!irqs_disabled())
#define local_irq_enable() \
do { \
asm volatile ("# local_irq_enable \n\t" \
"nop\n\t" \
"msrset r0, %0 \n\t" \
"nop\n\t" \
: \
: "i"(MSR_IE) \
: "memory"); \
} while(irqs_disabled())
#else /* CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR == 0 */
#define local_irq_save(flags) \
do { \
register unsigned tmp; \
asm volatile ("# local_irq_save \n\t" \
"nop\n\t" \
"mfs %0, rmsr \n\t" \
"andi %1, %0, %2 \n\t" \
"mts rmsr, %1 \n\t" \
"nop \n\t" \
: "=r"(flags), "=r" (tmp) \
: "i"(~MSR_IE) \
: "memory"); \
} while(0)
#define local_irq_disable() \
do { \
register unsigned tmp; \
asm volatile ("# local_irq_disable \n\t" \
"nop\n\t" \
"mfs %0, rmsr \n\t" \
"andi %0, %0, %1 \n\t" \
"mts rmsr, %0 \n\t" \
"nop \n\t" \
: "=r"(tmp) \
: "i"(~MSR_IE) \
: "memory"); \
} while(0UL)
#define local_irq_enable() \
do { \
register unsigned tmp; \
asm volatile ("# local_irq_enable \n\t" \
"nop\n\t" \
"mfs %0, rmsr \n\t" \
"ori %0, %0, %1 \n\t" \
"mts rmsr, %0 \n\t" \
"nop \n\t" \
: "=r"(tmp) \
: "i"(MSR_IE) \
: "memory"); \
} while(0)
#endif /* CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR */
#define local_save_flags(flags) \
do { \
asm volatile ("# local_save_flags \n\t" \
"nop\n\t" \
"mfs %0, rmsr \n\t" \
"nop\n\t" \
: "=r"(flags) \
: \
: "memory"); \
} while(0)
#define local_irq_restore(flags) \
do { \
asm volatile ("# local_irq_restore \n\t" \
"nop\n\t" \
"mts rmsr, %0 \n\t" \
"nop\n\t" \
: \
: "r"(flags) \
: "memory"); \
} while((flags & MSR_IE) && irqs_disabled())
static inline int irqs_disabled(void)
{
unsigned long flags;
local_save_flags(flags);
return ((flags & MSR_IE) == 0);
}
#define smp_read_barrier_depends() do {} while(0)
#define read_barrier_depends() do {} while(0)
#define nop() asm volatile ("nop")
#define mb() barrier()
#define rmb() mb()
#define wmb() mb()
#define set_mb(var, value) do { var = value; mb(); } while (0)
#define set_wmb(var, value) do { var = value; wmb(); } while (0)
#define smp_mb() mb()
#define smp_rmb() rmb()
#define smp_wmb() wmb()
static inline unsigned long __xchg(unsigned long x, volatile void *ptr, int size)
{
extern void __bad_xchg(volatile void *, int);
unsigned long ret;
unsigned long flags;
switch (size) {
case 1:
local_irq_save(flags);
ret = *(volatile unsigned char *)ptr;
*(volatile unsigned char *)ptr = x;
local_irq_restore(flags);
break;
case 4:
local_irq_save(flags);
ret = *(volatile unsigned long *)ptr;
*(volatile unsigned long *)ptr = x;
local_irq_restore(flags);
break;
default:
__bad_xchg(ptr, size), ret = 0;
break;
}
return ret;
}
#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
extern void *cacheable_memcpy(void *, const void *, unsigned int);
#endif /* _ASM_SYSTEM_H */