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, const char * const path,
19 void (*bootstrap_func)());
20 static void irq_prov_shutdown();
21 static unsigned int get_pid_for_irq_prov(unsigned);
22 static bool get_ipi_gate(unsigned irq, unsigned long &gate);
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(Cpu_number _cpu, unsigned char data);
47 static bool setup_ipi(Cpu_number _cpu, int _tid);
50 typedef Per_cpu_array<unsigned> Fd_array;
51 static Fd_array ipi_fds;
54 // ------------------------------------------------------------------------
57 #include <cassert> // for assert
58 #include <csignal> // for SIGIO
59 #include <cstdio> // for stdin
60 #include <cstdlib> // for EXIT_FAILURE
61 #include <fcntl.h> // for fcntl
62 #include <pty.h> // for termios
63 #include <unistd.h> // for fork
64 #include <sys/types.h> // for fork
66 #include "boot_info.h" // for boot_info::fd()
67 #include "emulation.h"
68 #include "initcalls.h"
70 unsigned int Pic::highest_irq;
71 unsigned int Pic::pids[Num_irqs];
72 struct pollfd Pic::pfd[Num_irqs];
77 { return Num_dev_irqs; }
83 atexit (&irq_prov_shutdown);
88 Pic::prepare_irq(int sockets[2])
92 if (openpty(&sockets[0], &sockets[1], NULL, NULL, NULL))
98 if (tcgetattr(sockets[0], &tt) < 0)
106 if (tcsetattr(sockets[0], TCSADRAIN, &tt) < 0)
119 Pic::setup_irq_prov(unsigned irq, const char * const path,
120 void (*bootstrap_func)())
124 if (access(path, X_OK | F_OK))
130 if (prepare_irq(sockets) == false)
133 switch (pids[irq] = fork())
143 fcntl(sockets[0], F_SETFD, FD_CLOEXEC);
144 pfd[irq].fd = sockets[0];
148 // Unblock all signals except SIGINT, we enter jdb with it and don't want
149 // the irq providers to die
152 sigaddset(&mask, SIGINT);
153 sigprocmask(SIG_SETMASK, &mask, NULL);
169 Pic::irq_prov_shutdown()
171 for (unsigned int i = 0; i < Num_irqs; i++)
173 kill(pids[i], SIGTERM);
176 IMPLEMENT inline NEEDS [<cassert>, <csignal>, <fcntl.h>, "boot_info.h"]
178 Pic::enable_locked(unsigned irq, unsigned /*prio*/)
182 // If fd is zero, someone tried to activate an IRQ without provider
183 assert (pfd[irq].fd);
185 if ((flags = fcntl(pfd[irq].fd, F_GETFL)) < 0 ||
186 fcntl(pfd[irq].fd, F_SETFL, flags | O_NONBLOCK | O_ASYNC) < 0 ||
187 fcntl(pfd[irq].fd, F_SETSIG, SIGIO) < 0 ||
188 fcntl(pfd[irq].fd, F_SETOWN, Boot_info::pid()) < 0)
191 pfd[irq].events = POLLIN;
193 if (irq >= highest_irq)
194 highest_irq = irq + 1;
199 Pic::disable_locked(unsigned)
204 Pic::acknowledge_locked(unsigned)
209 Pic::block_locked(unsigned)
218 for (i = 0; i < highest_irq; i++)
221 if (poll(pfd, highest_irq, 0) > 0)
222 for (i = 0; i < highest_irq; i++)
223 if (pfd[i].revents & POLLIN)
225 if (!Emulation::idt_vector_present(0x20 + i))
234 IMPLEMENT inline NEEDS [<cassert>, <unistd.h>]
236 Pic::eat(unsigned irq)
240 assert (pfd[irq].events & POLLIN);
242 while (read(pfd[irq].fd, buffer, sizeof (buffer)) > 0)
247 * Possible problem if an IRQ gets enabled and the system is already
248 * long running and the owner is set wrong?
252 Pic::set_owner(int pid)
254 for (unsigned int i = 0; i < highest_irq; i++)
255 if (pfd[i].events & POLLIN)
256 fcntl(pfd[i].fd, F_SETOWN, pid);
261 Pic::map_irq_to_gate(unsigned irq)
268 Pic::get_pid_for_irq_prov(unsigned irq)
273 // ---------------------------------------------------------------------
274 IMPLEMENTATION[ux && !mp]:
278 Pic::get_ipi_gate(unsigned, unsigned long &)
282 // ---------------------------------------------------------------------
283 IMPLEMENTATION[ux && mp]:
287 Pic::Fd_array Pic::ipi_fds;
291 Pic::set_cpu(unsigned irq_num, Cpu_number cpu)
293 printf("Pic::set_cpu(%d, %d)\n", irq_num, cpu);
298 Pic::setup_ipi(Cpu_number _cpu, int _tid)
300 int sockets[2], flags;
302 if (prepare_irq(sockets) == false)
305 unsigned i = Irq_ipi_base + _cpu;
307 pfd[i].fd = sockets[0];
308 ipi_fds[_cpu] = sockets[1];
310 if ((flags = fcntl(pfd[i].fd, F_GETFL)) < 0 ||
311 fcntl(pfd[i].fd, F_SETFL, flags | O_NONBLOCK | O_ASYNC) < 0 ||
312 fcntl(pfd[i].fd, F_SETSIG, SIGIO) < 0 ||
313 fcntl(pfd[i].fd, F_SETOWN, _tid) < 0)
316 pfd[i].events = POLLIN;
318 if (i >= highest_irq)
326 Pic::send_ipi(Cpu_number _cpu, unsigned char data)
329 if (write(ipi_fds[_cpu], &data, sizeof(data)) != sizeof(data))
330 printf("Write error\n");
335 Pic::get_ipi_gate(unsigned irq, unsigned long &gate)
337 if (irq < Irq_ipi_base)
340 // XXX check if irq is the irq for our current context/cpu
342 if (read(pfd[irq].fd, &b, sizeof(b)) < 1)
344 printf("read failure\n");
348 printf("IPI message: %c\n", b);