Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/arm/kernel/fiq.c
10817 views
1
/*
2
* linux/arch/arm/kernel/fiq.c
3
*
4
* Copyright (C) 1998 Russell King
5
* Copyright (C) 1998, 1999 Phil Blundell
6
*
7
* FIQ support written by Philip Blundell <[email protected]>, 1998.
8
*
9
* FIQ support re-written by Russell King to be more generic
10
*
11
* We now properly support a method by which the FIQ handlers can
12
* be stacked onto the vector. We still do not support sharing
13
* the FIQ vector itself.
14
*
15
* Operation is as follows:
16
* 1. Owner A claims FIQ:
17
* - default_fiq relinquishes control.
18
* 2. Owner A:
19
* - inserts code.
20
* - sets any registers,
21
* - enables FIQ.
22
* 3. Owner B claims FIQ:
23
* - if owner A has a relinquish function.
24
* - disable FIQs.
25
* - saves any registers.
26
* - returns zero.
27
* 4. Owner B:
28
* - inserts code.
29
* - sets any registers,
30
* - enables FIQ.
31
* 5. Owner B releases FIQ:
32
* - Owner A is asked to reacquire FIQ:
33
* - inserts code.
34
* - restores saved registers.
35
* - enables FIQ.
36
* 6. Goto 3
37
*/
38
#include <linux/module.h>
39
#include <linux/kernel.h>
40
#include <linux/init.h>
41
#include <linux/interrupt.h>
42
#include <linux/seq_file.h>
43
44
#include <asm/cacheflush.h>
45
#include <asm/fiq.h>
46
#include <asm/irq.h>
47
#include <asm/system.h>
48
#include <asm/traps.h>
49
50
static unsigned long no_fiq_insn;
51
52
/* Default reacquire function
53
* - we always relinquish FIQ control
54
* - we always reacquire FIQ control
55
*/
56
static int fiq_def_op(void *ref, int relinquish)
57
{
58
if (!relinquish)
59
set_fiq_handler(&no_fiq_insn, sizeof(no_fiq_insn));
60
61
return 0;
62
}
63
64
static struct fiq_handler default_owner = {
65
.name = "default",
66
.fiq_op = fiq_def_op,
67
};
68
69
static struct fiq_handler *current_fiq = &default_owner;
70
71
int show_fiq_list(struct seq_file *p, int prec)
72
{
73
if (current_fiq != &default_owner)
74
seq_printf(p, "%*s: %s\n", prec, "FIQ",
75
current_fiq->name);
76
77
return 0;
78
}
79
80
void set_fiq_handler(void *start, unsigned int length)
81
{
82
#if defined(CONFIG_CPU_USE_DOMAINS)
83
memcpy((void *)0xffff001c, start, length);
84
#else
85
memcpy(vectors_page + 0x1c, start, length);
86
#endif
87
flush_icache_range(0xffff001c, 0xffff001c + length);
88
if (!vectors_high())
89
flush_icache_range(0x1c, 0x1c + length);
90
}
91
92
int claim_fiq(struct fiq_handler *f)
93
{
94
int ret = 0;
95
96
if (current_fiq) {
97
ret = -EBUSY;
98
99
if (current_fiq->fiq_op != NULL)
100
ret = current_fiq->fiq_op(current_fiq->dev_id, 1);
101
}
102
103
if (!ret) {
104
f->next = current_fiq;
105
current_fiq = f;
106
}
107
108
return ret;
109
}
110
111
void release_fiq(struct fiq_handler *f)
112
{
113
if (current_fiq != f) {
114
printk(KERN_ERR "%s FIQ trying to release %s FIQ\n",
115
f->name, current_fiq->name);
116
dump_stack();
117
return;
118
}
119
120
do
121
current_fiq = current_fiq->next;
122
while (current_fiq->fiq_op(current_fiq->dev_id, 0));
123
}
124
125
void enable_fiq(int fiq)
126
{
127
enable_irq(fiq + FIQ_START);
128
}
129
130
void disable_fiq(int fiq)
131
{
132
disable_irq(fiq + FIQ_START);
133
}
134
135
EXPORT_SYMBOL(set_fiq_handler);
136
EXPORT_SYMBOL(__set_fiq_regs); /* defined in fiqasm.S */
137
EXPORT_SYMBOL(__get_fiq_regs); /* defined in fiqasm.S */
138
EXPORT_SYMBOL(claim_fiq);
139
EXPORT_SYMBOL(release_fiq);
140
EXPORT_SYMBOL(enable_fiq);
141
EXPORT_SYMBOL(disable_fiq);
142
143
void __init init_FIQ(void)
144
{
145
no_fiq_insn = *(unsigned long *)0xffff001c;
146
}
147
148