UnnamedOS
isr.c
Go to the documentation of this file.
1 
16 #include <common.h>
17 #include <interrupts/isr.h>
18 #include <interrupts/idt.h>
19 #include <interrupts/pic.h>
20 #include <interrupts/syscall.h>
21 #include <hardware/pit.h>
22 #include <hardware/io/ps2.h>
23 #include <syscall.h>
24 
26 #define IS_EXCEPTION(intr) ((intr) <= 0x1F)
27 #define IS_IRQ(intr) ((intr) >= 0x20 && intr <= 0x2F)
29 #define IS_SYSCALL(intr) ((intr) == 0x30)
31 
35 static void* syscalls[SYSCALL_NUMBER] = {0};
36 
42 uint8_t isr_enable_interrupts(uint8_t enable) {
44  if (enable && !old_interrupts) {
45  asm volatile("sti");
46  } else if (!enable && old_interrupts)
47  asm volatile("cli");
48  return old_interrupts;
49 }
50 
55 uint8_t isr_get_interrupts() {
56  isr_eflags_t eflags;
57  asm volatile("pushfl; pop %%eax; mov %%eax, %0" : "=r" (eflags.dword));
58  return eflags.bits._if;
59 }
60 
66 void isr_register_handler(size_t intr, isr_handler_t handler) {
67  if (intr >= IDT_ENTRIES) {
68  println("%4ainterrupt vector %d not allowed%a", intr);
69  return;
70  }
71  handlers[intr] = handler;
72 }
73 
80 void isr_register_syscall(size_t id, void* syscall) {
81  if (id >= SYSCALL_NUMBER) {
82  println("%4asyscall %d not allowed%a", id);
83  return;
84  }
85  syscalls[id] = syscall;
86 }
87 
103  uint32_t intr = cpu->intr; // save intr so we might change the cpu state
104  if (handlers[intr])
105  cpu = handlers[intr](cpu); // execute a handler if registered
106  else {
107  if (IS_EXCEPTION(intr))
108  panic("%4aEX%02x (EIP=%08x)", intr, cpu->eip);
109  if (IS_IRQ(intr))
110  print("%2aIRQ%d%a", intr - ISR_IRQ(0));
111  if (IS_SYSCALL(intr))
112  print("%4aSYS%08x%a", cpu->r.eax);
113  }
114  if (IS_IRQ(intr))
115  pic_send_eoi(intr);
116  return cpu;
117 }
118 
124  logln("ISR", "uss=%08x usp=%08x efl=%08x cs= %04x eip=%08x err=%08x "
125  "int=%08x eax=%08x ecx=%08x edx=%08x",
126  cpu->user_ss, cpu->user_esp, cpu->eflags, cpu->cs, cpu->eip,
127  cpu->error, cpu->intr, cpu->r.eax, cpu->r.ecx, cpu->r.edx);
128  logln("ISR", "ebx=%08x esp=%08x ebp=%08x esi=%08x edi=%08x "
129  "ds= %04x es= %04x fs= %04x gs= %04x",
130  cpu->r.ebx, cpu->r.esp, cpu->r.ebp, cpu->r.esi, cpu->r.edi,
131  cpu->ds, cpu->es, cpu->fs, cpu->gs);
132 }
133 
140  if (cpu->r.eax < SYSCALL_NUMBER && syscalls[cpu->r.eax]) {
141  cpu_state_t* old_cpu = cpu;
142  uint32_t ret = ((isr_syscall_t) syscalls[cpu->r.eax])
143  (cpu->r.ebx, cpu->r.ecx, cpu->r.edx, cpu->r.esi, cpu->r.edi, &cpu);
144  if (cpu == old_cpu) // change EAX only if we didn't switch tasks,
145  cpu->r.eax = ret; // otherwise tasks might run havoc!
146  } else
147  println("%4aUnknown syscall %08x%a", cpu->r.eax);
148  return cpu;
149 }
150 
152 void isr_init() {
153  print("ISR init ... ");
155  syscall_init();
157  println("%2aok%a.");
158 }
159 
void isr_dump_cpu(cpu_state_t *cpu)
Dumps a CPU state.
Definition: isr.c:123
uint8_t isr_enable_interrupts(uint8_t enable)
Enables or disables interrupts.
Definition: isr.c:42
uint16_t gs
GS segment register.
Definition: isr.h:60
cpu_state_t * isr_handle_interrupt(cpu_state_t *cpu)
Handles all interrupts.
Definition: isr.c:102
static isr_handler_t handlers[IDT_ENTRIES]
a table that associates interrupt vectors with handlers
Definition: isr.c:33
cpu_state_t *(* isr_handler_t)(cpu_state_t *cpu)
Handles a specific interrupt.
Definition: isr.h:90
void pic_send_eoi(uint8_t intr)
Sends an "end of interrupt" signal.
Definition: pic.c:61
uint32_t edx
data register
Definition: isr.h:43
static cpu_state_t * isr_handle_syscall(cpu_state_t *cpu)
Handles all syscalls.
Definition: isr.c:139
#define IS_EXCEPTION(intr)
whether the given interrupt vector is an exception
Definition: isr.c:26
The CPU&#39;s state when an interrupt occurs.
Definition: isr.h:58
#define IS_SYSCALL(intr)
whether the given interrupt vector is the syscall
Definition: isr.c:30
uint32_t esp
stack pointer register
Definition: isr.h:43
static uint8_t old_interrupts
for temporary modifications
Definition: vmm.c:46
#define ISR_SYSCALL
the interrupt vector for the syscall
Definition: isr.h:14
uint32_t user_ss
stack segment (only pushed and popped in user space)
Definition: isr.h:74
uint8_t _if
interrupt flag
Definition: isr.h:19
#define ISR_IRQ(irq)
the interrupt vector for an IRQ
Definition: isr.h:13
uint32_t eip
the instruction to return to after the interrupt
Definition: isr.h:68
void isr_register_handler(size_t intr, isr_handler_t handler)
Registers a handler to call whenever a given interrupt is fired.
Definition: isr.c:66
uint16_t es
ES segment register.
Definition: isr.h:60
void isr_init()
Initializes syscalls and enables interrupts.
Definition: isr.c:152
void isr_register_syscall(size_t id, void *syscall)
Registers a syscall handler to call whenever a specified syscall is requested.
Definition: isr.c:80
uint32_t dword
useful for casting
Definition: isr.h:38
uint32_t esi
source index register
Definition: isr.h:43
#define IDT_ENTRIES
Number of entries in the IDT.
Definition: idt.h:11
void syscall_init()
Initializes the syscall interface.
Definition: syscall.c:53
uint32_t ebp
base pointer register
Definition: isr.h:43
uint16_t fs
FS segment register.
Definition: isr.h:60
struct isr_eflags_t::@8 bits
bit field
uint32_t eax
accumulator register
Definition: isr.h:43
uint16_t cs
the code segment to return to after the interrupt
Definition: isr.h:71
uint16_t isr_eflags_t eflags
the EFLAGS register before the interrupt was fired
Definition: isr.h:71
uint32_t ebx
base register
Definition: isr.h:43
The EFLAGS register.
Definition: isr.h:17
uint32_t edi
destination index register
Definition: isr.h:43
uint32_t error
hold an error code if an error occured, otherwise 0
Definition: isr.h:68
uint32_t user_esp
stack pointer (only pushed and popped in user space)
Definition: isr.h:74
uint16_t ds
DS segment register.
Definition: isr.h:60
uint32_t ecx
counter register
Definition: isr.h:43
uint32_t intr
the interrupt vector of the fired interrupt
Definition: isr.h:68
uint32_t(* isr_syscall_t)(uint32_t ebx, uint32_t ecx, uint32_t edx, uint32_t esi, uint32_t edi, cpu_state_t **cpu)
Handles a specific syscall.
Definition: isr.h:106
uint8_t isr_get_interrupts()
Returns whether interrupts are enabled or disabled.
Definition: isr.c:55
#define IS_IRQ(intr)
whether the given interrupt vector is an IRQ
Definition: isr.c:28
static void * syscalls[SYSCALL_NUMBER]
a table that associates syscall IDs with handlers
Definition: isr.c:35
uint16_t isr_registers_t r
The general purpose registers.
Definition: isr.h:60