Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/blackfin/include/asm/entry.h
15126 views
1
/*
2
* Copyright 2004-2009 Analog Devices Inc.
3
*
4
* Licensed under the GPL-2 or later.
5
*/
6
7
#ifndef __BFIN_ENTRY_H
8
#define __BFIN_ENTRY_H
9
10
#include <asm/setup.h>
11
#include <asm/page.h>
12
13
#ifdef __ASSEMBLY__
14
15
#define LFLUSH_I_AND_D 0x00000808
16
#define LSIGTRAP 5
17
18
/*
19
* NOTE! The single-stepping code assumes that all interrupt handlers
20
* start by saving SYSCFG on the stack with their first instruction.
21
*/
22
23
/* This one is used for exceptions, emulation, and NMI. It doesn't push
24
RETI and doesn't do cli. */
25
#define SAVE_ALL_SYS save_context_no_interrupts
26
/* This is used for all normal interrupts. It saves a minimum of registers
27
to the stack, loads the IRQ number, and jumps to common code. */
28
#ifdef CONFIG_IPIPE
29
# define LOAD_IPIPE_IPEND \
30
P0.l = lo(IPEND); \
31
P0.h = hi(IPEND); \
32
R1 = [P0];
33
#else
34
# define LOAD_IPIPE_IPEND
35
#endif
36
37
/*
38
* Workaround for anomalies 05000283 and 05000315
39
*/
40
#if ANOMALY_05000283 || ANOMALY_05000315
41
# define ANOMALY_283_315_WORKAROUND(preg, dreg) \
42
cc = dreg == dreg; \
43
preg.h = HI(CHIPID); \
44
preg.l = LO(CHIPID); \
45
if cc jump 1f; \
46
dreg.l = W[preg]; \
47
1:
48
#else
49
# define ANOMALY_283_315_WORKAROUND(preg, dreg)
50
#endif /* ANOMALY_05000283 || ANOMALY_05000315 */
51
52
#ifndef CONFIG_EXACT_HWERR
53
/* As a debugging aid - we save IPEND when DEBUG_KERNEL is on,
54
* otherwise it is a waste of cycles.
55
*/
56
# ifndef CONFIG_DEBUG_KERNEL
57
#define INTERRUPT_ENTRY(N) \
58
[--sp] = SYSCFG; \
59
[--sp] = P0; /*orig_p0*/ \
60
[--sp] = R0; /*orig_r0*/ \
61
[--sp] = (R7:0,P5:0); \
62
R0 = (N); \
63
LOAD_IPIPE_IPEND \
64
jump __common_int_entry;
65
# else /* CONFIG_DEBUG_KERNEL */
66
#define INTERRUPT_ENTRY(N) \
67
[--sp] = SYSCFG; \
68
[--sp] = P0; /*orig_p0*/ \
69
[--sp] = R0; /*orig_r0*/ \
70
[--sp] = (R7:0,P5:0); \
71
p0.l = lo(IPEND); \
72
p0.h = hi(IPEND); \
73
r1 = [p0]; \
74
R0 = (N); \
75
LOAD_IPIPE_IPEND \
76
jump __common_int_entry;
77
# endif /* CONFIG_DEBUG_KERNEL */
78
79
/* For timer interrupts, we need to save IPEND, since the user_mode
80
*macro accesses it to determine where to account time.
81
*/
82
#define TIMER_INTERRUPT_ENTRY(N) \
83
[--sp] = SYSCFG; \
84
[--sp] = P0; /*orig_p0*/ \
85
[--sp] = R0; /*orig_r0*/ \
86
[--sp] = (R7:0,P5:0); \
87
p0.l = lo(IPEND); \
88
p0.h = hi(IPEND); \
89
r1 = [p0]; \
90
R0 = (N); \
91
jump __common_int_entry;
92
#else /* CONFIG_EXACT_HWERR is defined */
93
94
/* if we want hardware error to be exact, we need to do a SSYNC (which forces
95
* read/writes to complete to the memory controllers), and check to see that
96
* caused a pending HW error condition. If so, we assume it was caused by user
97
* space, by setting the same interrupt that we are in (so it goes off again)
98
* and context restore, and a RTI (without servicing anything). This should
99
* cause the pending HWERR to fire, and when that is done, this interrupt will
100
* be re-serviced properly.
101
* As you can see by the code - we actually need to do two SSYNCS - one to
102
* make sure the read/writes complete, and another to make sure the hardware
103
* error is recognized by the core.
104
*
105
* The extra nop before the SSYNC is to make sure we work around 05000244,
106
* since the 283/315 workaround includes a branch to the end
107
*/
108
#define INTERRUPT_ENTRY(N) \
109
[--sp] = SYSCFG; \
110
[--sp] = P0; /*orig_p0*/ \
111
[--sp] = R0; /*orig_r0*/ \
112
[--sp] = (R7:0,P5:0); \
113
R1 = ASTAT; \
114
ANOMALY_283_315_WORKAROUND(p0, r0) \
115
P0.L = LO(ILAT); \
116
P0.H = HI(ILAT); \
117
NOP; \
118
SSYNC; \
119
SSYNC; \
120
R0 = [P0]; \
121
CC = BITTST(R0, EVT_IVHW_P); \
122
IF CC JUMP 1f; \
123
ASTAT = R1; \
124
p0.l = lo(IPEND); \
125
p0.h = hi(IPEND); \
126
r1 = [p0]; \
127
R0 = (N); \
128
LOAD_IPIPE_IPEND \
129
jump __common_int_entry; \
130
1: ASTAT = R1; \
131
RAISE N; \
132
(R7:0, P5:0) = [SP++]; \
133
SP += 0x8; \
134
SYSCFG = [SP++]; \
135
CSYNC; \
136
RTI;
137
138
#define TIMER_INTERRUPT_ENTRY(N) \
139
[--sp] = SYSCFG; \
140
[--sp] = P0; /*orig_p0*/ \
141
[--sp] = R0; /*orig_r0*/ \
142
[--sp] = (R7:0,P5:0); \
143
R1 = ASTAT; \
144
ANOMALY_283_315_WORKAROUND(p0, r0) \
145
P0.L = LO(ILAT); \
146
P0.H = HI(ILAT); \
147
NOP; \
148
SSYNC; \
149
SSYNC; \
150
R0 = [P0]; \
151
CC = BITTST(R0, EVT_IVHW_P); \
152
IF CC JUMP 1f; \
153
ASTAT = R1; \
154
p0.l = lo(IPEND); \
155
p0.h = hi(IPEND); \
156
r1 = [p0]; \
157
R0 = (N); \
158
jump __common_int_entry; \
159
1: ASTAT = R1; \
160
RAISE N; \
161
(R7:0, P5:0) = [SP++]; \
162
SP += 0x8; \
163
SYSCFG = [SP++]; \
164
CSYNC; \
165
RTI;
166
#endif /* CONFIG_EXACT_HWERR */
167
168
/* This one pushes RETI without using CLI. Interrupts are enabled. */
169
#define SAVE_CONTEXT_SYSCALL save_context_syscall
170
#define SAVE_CONTEXT save_context_with_interrupts
171
#define SAVE_CONTEXT_CPLB save_context_cplb
172
173
#define RESTORE_ALL_SYS restore_context_no_interrupts
174
#define RESTORE_CONTEXT restore_context_with_interrupts
175
#define RESTORE_CONTEXT_CPLB restore_context_cplb
176
177
#endif /* __ASSEMBLY__ */
178
#endif /* __BFIN_ENTRY_H */
179
180