3 * Architecture specific interrupt code
14 static int irq_pending();
15 static void eat(unsigned);
16 static void set_owner(int);
17 static unsigned int map_irq_to_gate(unsigned);
18 static bool setup_irq_prov (unsigned irq,
19 const char * const path,
20 void (*bootstrap_func)());
21 static void irq_prov_shutdown();
22 static unsigned int get_pid_for_irq_prov(unsigned);
23 static bool get_ipi_gate(unsigned irq, unsigned long &gate);
26 IRQ_TIMER = Config::Scheduling_irq,
31 Num_irqs = 4 + Config::Max_num_cpus,
35 static unsigned int highest_irq;
36 static unsigned int pids[Pic::Num_irqs];
37 static struct pollfd pfd[Pic::Num_irqs];
40 // ------------------------------------------------------------------------
46 static void send_ipi(unsigned _cpu, unsigned char data);
47 static bool setup_ipi(unsigned _cpu, int _tid);
50 static unsigned int ipi_fds[Config::Max_num_cpus];
53 // ------------------------------------------------------------------------
56 #include <cassert> // for assert
57 #include <csignal> // for SIGIO
58 #include <cstdio> // for stdin
59 #include <cstdlib> // for EXIT_FAILURE
60 #include <fcntl.h> // for fcntl
61 #include <pty.h> // for termios
62 #include <unistd.h> // for fork
63 #include <sys/types.h> // for fork
65 #include "boot_info.h" // for boot_info::fd()
66 #include "emulation.h"
67 #include "initcalls.h"
69 unsigned int Pic::highest_irq;
70 unsigned int Pic::pids[Num_irqs];
71 struct pollfd Pic::pfd[Num_irqs];
76 { return Num_dev_irqs; }
82 atexit (&irq_prov_shutdown);
87 Pic::prepare_irq(int sockets[2])
91 if (openpty (&sockets[0], &sockets[1], NULL, NULL, NULL))
97 if (tcgetattr (sockets[0], &tt) < 0)
105 if (tcsetattr (sockets[0], TCSADRAIN, &tt) < 0)
107 perror ("tcsetattr");
118 Pic::setup_irq_prov (unsigned irq, const char * const path,
119 void (*bootstrap_func)())
123 if (access (path, X_OK | F_OK))
129 if (prepare_irq(sockets) == false)
132 switch (pids[irq] = fork())
142 fcntl (sockets[0], F_SETFD, FD_CLOEXEC);
143 pfd[irq].fd = sockets[0];
147 // Unblock all signals except SIGINT, we enter jdb with it and don't want
148 // the irq providers to die
151 sigaddset (&mask, SIGINT);
152 sigprocmask (SIG_SETMASK, &mask, NULL);
158 dup2 (sockets[1], 0);
163 _exit (EXIT_FAILURE);
168 Pic::irq_prov_shutdown()
170 for (unsigned int i = 0; i < Num_irqs; i++)
172 kill(pids[i], SIGTERM);
175 IMPLEMENT inline NEEDS [<cassert>, <csignal>, <fcntl.h>, "boot_info.h"]
177 Pic::enable_locked (unsigned irq, unsigned /*prio*/)
181 // If fd is zero, someone tried to activate an IRQ without provider
182 assert (pfd[irq].fd);
184 if ((flags = fcntl (pfd[irq].fd, F_GETFL)) < 0 ||
185 fcntl (pfd[irq].fd, F_SETFL, flags | O_NONBLOCK | O_ASYNC) < 0 ||
186 fcntl (pfd[irq].fd, F_SETSIG, SIGIO) < 0 ||
187 fcntl (pfd[irq].fd, F_SETOWN, Boot_info::pid()) < 0)
190 pfd[irq].events = POLLIN;
192 if (irq >= highest_irq)
193 highest_irq = irq + 1;
198 Pic::disable_locked (unsigned)
203 Pic::acknowledge_locked (unsigned)
208 Pic::block_locked (unsigned)
217 for (i = 0; i < highest_irq; i++)
220 if (poll (pfd, highest_irq, 0) > 0)
221 for (i = 0; i < highest_irq; i++)
222 if (pfd[i].revents & POLLIN)
224 if (!Emulation::idt_vector_present(0x20 + i))
233 IMPLEMENT inline NEEDS [<cassert>, <unistd.h>]
235 Pic::eat (unsigned irq)
239 assert (pfd[irq].events & POLLIN);
241 while (read (pfd[irq].fd, buffer, sizeof (buffer)) > 0)
246 * Possible problem if an IRQ gets enabled and the system is already
247 * long running and the owner is set wrong?
251 Pic::set_owner (int pid)
253 for (unsigned int i = 0; i < highest_irq; i++)
254 if (pfd[i].events & POLLIN)
255 fcntl (pfd[i].fd, F_SETOWN, pid);
260 Pic::map_irq_to_gate (unsigned irq)
267 Pic::get_pid_for_irq_prov(unsigned irq)
272 // ---------------------------------------------------------------------
273 IMPLEMENTATION[ux && !mp]:
277 Pic::get_ipi_gate(unsigned, unsigned long &)
281 // ---------------------------------------------------------------------
282 IMPLEMENTATION[ux && mp]:
286 unsigned int Pic::ipi_fds[Config::Max_num_cpus];
290 Pic::set_cpu(unsigned irq_num, unsigned cpu)
292 printf("Pic::set_cpu(%d, %d)\n", irq_num, cpu);
297 Pic::setup_ipi(unsigned _cpu, int _tid)
299 int sockets[2], flags;
301 if (prepare_irq(sockets) == false)
304 unsigned i = IRQ_IPI_base + _cpu;
306 pfd[i].fd = sockets[0];
307 ipi_fds[_cpu] = sockets[1];
309 if ((flags = fcntl (pfd[i].fd, F_GETFL)) < 0 ||
310 fcntl (pfd[i].fd, F_SETFL, flags | O_NONBLOCK | O_ASYNC) < 0 ||
311 fcntl (pfd[i].fd, F_SETSIG, SIGIO) < 0 ||
312 fcntl (pfd[i].fd, F_SETOWN, _tid) < 0)
315 pfd[i].events = POLLIN;
317 if (i >= highest_irq)
325 Pic::send_ipi(unsigned _cpu, unsigned char data)
328 if (write(ipi_fds[_cpu], &data, sizeof(data)) != sizeof(data))
329 printf("Write error\n");
334 Pic::get_ipi_gate(unsigned irq, unsigned long &gate)
336 if (irq < IRQ_IPI_base)
339 // XXX check if irq is the irq for our current context/cpu
341 if (read (pfd[irq].fd, &b, sizeof(b)) < 1)
343 printf("read failure\n");
347 printf("IPI message: %c\n", b);