~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/arm/kernel/fiq.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0
  2 /*
  3  *  linux/arch/arm/kernel/fiq.c
  4  *
  5  *  Copyright (C) 1998 Russell King
  6  *  Copyright (C) 1998, 1999 Phil Blundell
  7  *
  8  *  FIQ support written by Philip Blundell <philb@gnu.org>, 1998.
  9  *
 10  *  FIQ support re-written by Russell King to be more generic
 11  *
 12  * We now properly support a method by which the FIQ handlers can
 13  * be stacked onto the vector.  We still do not support sharing
 14  * the FIQ vector itself.
 15  *
 16  * Operation is as follows:
 17  *  1. Owner A claims FIQ:
 18  *     - default_fiq relinquishes control.
 19  *  2. Owner A:
 20  *     - inserts code.
 21  *     - sets any registers,
 22  *     - enables FIQ.
 23  *  3. Owner B claims FIQ:
 24  *     - if owner A has a relinquish function.
 25  *       - disable FIQs.
 26  *       - saves any registers.
 27  *       - returns zero.
 28  *  4. Owner B:
 29  *     - inserts code.
 30  *     - sets any registers,
 31  *     - enables FIQ.
 32  *  5. Owner B releases FIQ:
 33  *     - Owner A is asked to reacquire FIQ:
 34  *       - inserts code.
 35  *       - restores saved registers.
 36  *       - enables FIQ.
 37  *  6. Goto 3
 38  */
 39 #include <linux/module.h>
 40 #include <linux/kernel.h>
 41 #include <linux/init.h>
 42 #include <linux/interrupt.h>
 43 #include <linux/seq_file.h>
 44 
 45 #include <asm/cacheflush.h>
 46 #include <asm/cp15.h>
 47 #include <asm/fiq.h>
 48 #include <asm/mach/irq.h>
 49 #include <asm/irq.h>
 50 #include <asm/traps.h>
 51 
 52 #define FIQ_OFFSET ({                                   \
 53                 extern void *vector_fiq_offset;         \
 54                 (unsigned)&vector_fiq_offset;           \
 55         })
 56 
 57 static unsigned long dfl_fiq_insn;
 58 static struct pt_regs dfl_fiq_regs;
 59 
 60 /* Default reacquire function
 61  * - we always relinquish FIQ control
 62  * - we always reacquire FIQ control
 63  */
 64 static int fiq_def_op(void *ref, int relinquish)
 65 {
 66         if (!relinquish) {
 67                 /* Restore default handler and registers */
 68                 local_fiq_disable();
 69                 set_fiq_regs(&dfl_fiq_regs);
 70                 set_fiq_handler(&dfl_fiq_insn, sizeof(dfl_fiq_insn));
 71                 local_fiq_enable();
 72 
 73                 /* FIXME: notify irq controller to standard enable FIQs */
 74         }
 75 
 76         return 0;
 77 }
 78 
 79 static struct fiq_handler default_owner = {
 80         .name   = "default",
 81         .fiq_op = fiq_def_op,
 82 };
 83 
 84 static struct fiq_handler *current_fiq = &default_owner;
 85 
 86 int show_fiq_list(struct seq_file *p, int prec)
 87 {
 88         if (current_fiq != &default_owner)
 89                 seq_printf(p, "%*s:              %s\n", prec, "FIQ",
 90                         current_fiq->name);
 91 
 92         return 0;
 93 }
 94 
 95 void set_fiq_handler(void *start, unsigned int length)
 96 {
 97         void *base = vectors_page;
 98         unsigned offset = FIQ_OFFSET;
 99 
100         memcpy(base + offset, start, length);
101         if (!cache_is_vipt_nonaliasing())
102                 flush_icache_range((unsigned long)base + offset,
103                                    (unsigned long)base + offset + length);
104         flush_icache_range(0xffff0000 + offset, 0xffff0000 + offset + length);
105 }
106 
107 int claim_fiq(struct fiq_handler *f)
108 {
109         int ret = 0;
110 
111         if (current_fiq) {
112                 ret = -EBUSY;
113 
114                 if (current_fiq->fiq_op != NULL)
115                         ret = current_fiq->fiq_op(current_fiq->dev_id, 1);
116         }
117 
118         if (!ret) {
119                 f->next = current_fiq;
120                 current_fiq = f;
121         }
122 
123         return ret;
124 }
125 
126 void release_fiq(struct fiq_handler *f)
127 {
128         if (current_fiq != f) {
129                 pr_err("%s FIQ trying to release %s FIQ\n",
130                        f->name, current_fiq->name);
131                 dump_stack();
132                 return;
133         }
134 
135         do
136                 current_fiq = current_fiq->next;
137         while (current_fiq->fiq_op(current_fiq->dev_id, 0));
138 }
139 
140 static int fiq_start;
141 
142 void enable_fiq(int fiq)
143 {
144         enable_irq(fiq + fiq_start);
145 }
146 
147 void disable_fiq(int fiq)
148 {
149         disable_irq(fiq + fiq_start);
150 }
151 
152 EXPORT_SYMBOL(set_fiq_handler);
153 EXPORT_SYMBOL(__set_fiq_regs);  /* defined in fiqasm.S */
154 EXPORT_SYMBOL(__get_fiq_regs);  /* defined in fiqasm.S */
155 EXPORT_SYMBOL(claim_fiq);
156 EXPORT_SYMBOL(release_fiq);
157 EXPORT_SYMBOL(enable_fiq);
158 EXPORT_SYMBOL(disable_fiq);
159 
160 void __init init_FIQ(int start)
161 {
162         unsigned offset = FIQ_OFFSET;
163         dfl_fiq_insn = *(unsigned long *)(0xffff0000 + offset);
164         get_fiq_regs(&dfl_fiq_regs);
165         fiq_start = start;
166 }
167 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php