[Krafton Jungle] PintOS 2.0.0
크래프톤 정글 PintOS
 
Loading...
Searching...
No Matches
interrupt.c File Reference
#include "threads/interrupt.h"
#include <debug.h>
#include <inttypes.h>
#include <stdint.h>
#include <stdio.h>
#include "threads/flags.h"
#include "threads/intr-stubs.h"
#include "threads/io.h"
#include "threads/thread.h"
#include "threads/mmu.h"
#include "threads/vaddr.h"
#include "devices/timer.h"
#include "intrinsic.h"
Include dependency graph for interrupt.c:

Classes

struct  gate
 

Macros

#define INTR_CNT   256
 
#define make_gate(g, function, d, t)
 
#define make_intr_gate(g, function, dpl)   make_gate((g), (function), (dpl), 14)
 
#define make_trap_gate(g, function, dpl)   make_gate((g), (function), (dpl), 15)
 

Functions

static void pic_init (void)
 
static void pic_end_of_interrupt (int irq)
 
void intr_handler (struct intr_frame *args)
 
enum intr_level intr_get_level (void)
 
enum intr_level intr_set_level (enum intr_level level)
 
enum intr_level intr_enable (void)
 
enum intr_level intr_disable (void)
 
void intr_init (void)
 
static void register_handler (uint8_t vec_no, int dpl, enum intr_level level, intr_handler_func *handler, const char *name)
 
void intr_register_ext (uint8_t vec_no, intr_handler_func *handler, const char *name)
 
void intr_register_int (uint8_t vec_no, int dpl, enum intr_level level, intr_handler_func *handler, const char *name)
 
bool intr_context (void)
 
void intr_yield_on_return (void)
 
void intr_dump_frame (const struct intr_frame *f)
 
const char * intr_name (uint8_t vec)
 

Variables

static struct gate idt [INTR_CNT]
 
static struct desc_ptr idt_desc
 
static intr_handler_funcintr_handlers [INTR_CNT]
 
static const char * intr_names [INTR_CNT]
 
static bool in_external_intr
 
static bool yield_on_return
 

Macro Definition Documentation

◆ INTR_CNT

#define INTR_CNT   256

◆ make_gate

#define make_gate (   g,
  function,
  d,
 
)
Value:
{ \
ASSERT ((function) != NULL); \
ASSERT ((d) >= 0 && (d) <= 3); \
ASSERT ((t) >= 0 && (t) <= 15); \
*(g) = (struct gate) { \
.off_15_0 = (uint64_t) (function) & 0xffff, \
.ss = SEL_KCSEG, \
.ist = 0, \
.rsv1 = 0, \
.type = (t), \
.s = 0, \
.dpl = (d), \
.p = 1, \
.off_31_16 = ((uint64_t) (function) >> 16) & 0xffff, \
.off_32_63 = ((uint64_t) (function) >> 32) & 0xffffffff, \
.rsv2 = 0, \
}; \
}
#define SEL_KCSEG
Definition: loader.h:36
static uint8_t s[256]
Definition: random.c:17
#define NULL
Definition: stddef.h:4
unsigned long long int uint64_t
Definition: stdint.h:29
Definition: interrupt.c:36

◆ make_intr_gate

#define make_intr_gate (   g,
  function,
  dpl 
)    make_gate((g), (function), (dpl), 14)

◆ make_trap_gate

#define make_trap_gate (   g,
  function,
  dpl 
)    make_gate((g), (function), (dpl), 15)

Function Documentation

◆ intr_context()

bool intr_context ( void  )
258 {
259 return in_external_intr;
260}
static bool in_external_intr
Definition: interrupt.c:103
Here is the caller graph for this function:

◆ intr_disable()

enum intr_level intr_disable ( void  )
151 {
152 enum intr_level old_level = intr_get_level ();
153
154 /* Disable interrupts by clearing the interrupt flag.
155 See [IA32-v2b] "CLI" and [IA32-v3a] 5.8.1 "Masking Maskable
156 Hardware Interrupts". */
157 asm volatile ("cli" : : : "memory");
158
159 return old_level;
160}
enum intr_level intr_get_level(void)
Definition: interrupt.c:115
intr_level
Definition: interrupt.h:8
Here is the call graph for this function:
Here is the caller graph for this function:

◆ intr_dump_frame()

void intr_dump_frame ( const struct intr_frame f)
381 {
382 /* CR2 is the linear address of the last page fault.
383 See [IA32-v2a] "MOV--Move to/from Control Registers" and
384 [IA32-v3a] 5.14 "Interrupt 14--Page Fault Exception
385 (#PF)". */
386 uint64_t cr2 = rcr2();
387 printf ("Interrupt %#04llx (%s) at rip=%llx\n",
388 f->vec_no, intr_names[f->vec_no], f->rip);
389 printf (" cr2=%016llx error=%16llx\n", cr2, f->error_code);
390 printf ("rax %016llx rbx %016llx rcx %016llx rdx %016llx\n",
391 f->R.rax, f->R.rbx, f->R.rcx, f->R.rdx);
392 printf ("rsp %016llx rbp %016llx rsi %016llx rdi %016llx\n",
393 f->rsp, f->R.rbp, f->R.rsi, f->R.rdi);
394 printf ("rip %016llx r8 %016llx r9 %016llx r10 %016llx\n",
395 f->rip, f->R.r8, f->R.r9, f->R.r10);
396 printf ("r11 %016llx r12 %016llx r13 %016llx r14 %016llx\n",
397 f->R.r11, f->R.r12, f->R.r13, f->R.r14);
398 printf ("r15 %016llx rflags %08llx\n", f->R.r15, f->eflags);
399 printf ("es: %04x ds: %04x cs: %04x ss: %04x\n",
400 f->es, f->ds, f->cs, f->ss);
401}
static const char * intr_names[INTR_CNT]
Definition: interrupt.c:94
int printf(const char *,...) PRINTF_FORMAT(1
uint64_t rbp
Definition: interrupt.h:30
uint64_t r12
Definition: interrupt.h:23
uint64_t r14
Definition: interrupt.h:21
uint64_t rax
Definition: interrupt.h:34
uint64_t rdi
Definition: interrupt.h:29
uint64_t r8
Definition: interrupt.h:27
uint64_t rbx
Definition: interrupt.h:33
uint64_t r11
Definition: interrupt.h:24
uint64_t r13
Definition: interrupt.h:22
uint64_t r10
Definition: interrupt.h:25
uint64_t r15
Definition: interrupt.h:20
uint64_t rsi
Definition: interrupt.h:28
uint64_t rdx
Definition: interrupt.h:31
uint64_t rcx
Definition: interrupt.h:32
uint64_t r9
Definition: interrupt.h:26
uint16_t ss
Definition: interrupt.h:61
uintptr_t rip
Definition: interrupt.h:55
uint64_t vec_no
Definition: interrupt.h:48
uint16_t es
Definition: interrupt.h:41
uint16_t ds
Definition: interrupt.h:44
uint16_t cs
Definition: interrupt.h:56
uint64_t eflags
Definition: interrupt.h:59
struct gp_registers R
Definition: interrupt.h:40
uintptr_t rsp
Definition: interrupt.h:60
uint64_t error_code
Definition: interrupt.h:52
Here is the call graph for this function:
Here is the caller graph for this function:

◆ intr_enable()

enum intr_level intr_enable ( void  )
136 {
137 enum intr_level old_level = intr_get_level ();
138 ASSERT (!intr_context ());
139
140 /* Enable interrupts by setting the interrupt flag.
141
142 See [IA32-v2b] "STI" and [IA32-v3a] 5.8.1 "Masking Maskable
143 Hardware Interrupts". */
144 asm volatile ("sti");
145
146 return old_level;
147}
#define ASSERT(CONDITION)
Definition: debug.h:30
bool intr_context(void)
Definition: interrupt.c:258
Here is the call graph for this function:
Here is the caller graph for this function:

◆ intr_get_level()

enum intr_level intr_get_level ( void  )
115 {
116 uint64_t flags;
117
118 /* Push the flags register on the processor stack, then pop the
119 value off the stack into `flags'. See [IA32-v2b] "PUSHF"
120 and "POP" and [IA32-v3a] 5.8.1 "Masking Maskable Hardware
121 Interrupts". */
122 asm volatile ("pushfq; popq %0" : "=g" (flags));
123
124 return flags & FLAG_IF ? INTR_ON : INTR_OFF;
125}
#define FLAG_IF
Definition: flags.h:6
@ INTR_ON
Definition: interrupt.h:10
@ INTR_OFF
Definition: interrupt.h:9
Here is the caller graph for this function:

◆ intr_handler()

void intr_handler ( struct intr_frame args)
334 {
335 bool external;
336 intr_handler_func *handler;
337
338 /* External interrupts are special.
339 We only handle one at a time (so interrupts must be off)
340 and they need to be acknowledged on the PIC (see below).
341 An external interrupt handler cannot sleep. */
342 external = frame->vec_no >= 0x20 && frame->vec_no < 0x30;
343 if (external) {
345 ASSERT (!intr_context ());
346
347 in_external_intr = true;
348 yield_on_return = false;
349 }
350
351 /* Invoke the interrupt's handler. */
352 handler = intr_handlers[frame->vec_no];
353 if (handler != NULL)
354 handler (frame);
355 else if (frame->vec_no == 0x27 || frame->vec_no == 0x2f) {
356 /* There is no handler, but this interrupt can trigger
357 spuriously due to a hardware fault or hardware race
358 condition. Ignore it. */
359 } else {
360 /* No handler and not spurious. Invoke the unexpected
361 interrupt handler. */
363 PANIC ("Unexpected interrupt");
364 }
365
366 /* Complete the processing of an external interrupt. */
367 if (external) {
369 ASSERT (intr_context ());
370
371 in_external_intr = false;
372 pic_end_of_interrupt (frame->vec_no);
373
374 if (yield_on_return)
375 thread_yield ();
376 }
377}
#define PANIC(...)
Definition: debug.h:14
static void pic_end_of_interrupt(int irq)
Definition: interrupt.c:317
static intr_handler_func * intr_handlers[INTR_CNT]
Definition: interrupt.c:91
void intr_dump_frame(const struct intr_frame *f)
Definition: interrupt.c:381
static bool yield_on_return
Definition: interrupt.c:104
void intr_handler_func(struct intr_frame *)
Definition: interrupt.h:66
Definition: vm.h:77
void thread_yield(void)
Definition: thread.c:343
Here is the call graph for this function:

◆ intr_init()

void intr_init ( void  )
164 {
165 int i;
166
167 /* Initialize interrupt controller. */
168 pic_init ();
169
170 /* Initialize IDT. */
171 for (i = 0; i < INTR_CNT; i++) {
172 make_intr_gate(&idt[i], intr_stubs[i], 0);
173 intr_names[i] = "unknown";
174 }
175
176#ifdef USERPROG
177 /* Load TSS. */
178 ltr (SEL_TSS);
179#endif
180
181 /* Load IDT register. */
182 lidt(&idt_desc);
183
184 /* Initialize intr_names. */
185 intr_names[0] = "#DE Divide Error";
186 intr_names[1] = "#DB Debug Exception";
187 intr_names[2] = "NMI Interrupt";
188 intr_names[3] = "#BP Breakpoint Exception";
189 intr_names[4] = "#OF Overflow Exception";
190 intr_names[5] = "#BR BOUND Range Exceeded Exception";
191 intr_names[6] = "#UD Invalid Opcode Exception";
192 intr_names[7] = "#NM Device Not Available Exception";
193 intr_names[8] = "#DF Double Fault Exception";
194 intr_names[9] = "Coprocessor Segment Overrun";
195 intr_names[10] = "#TS Invalid TSS Exception";
196 intr_names[11] = "#NP Segment Not Present";
197 intr_names[12] = "#SS Stack Fault Exception";
198 intr_names[13] = "#GP General Protection Exception";
199 intr_names[14] = "#PF Page-Fault Exception";
200 intr_names[16] = "#MF x87 FPU Floating-Point Error";
201 intr_names[17] = "#AC Alignment Check Exception";
202 intr_names[18] = "#MC Machine-Check Exception";
203 intr_names[19] = "#XF SIMD Floating-Point Exception";
204}
#define make_intr_gate(g, function, dpl)
Definition: interrupt.c:83
static void pic_init(void)
Definition: interrupt.c:291
static struct desc_ptr idt_desc
Definition: interrupt.c:56
static struct gate idt[INTR_CNT]
Definition: interrupt.c:54
#define INTR_CNT
Definition: interrupt.c:19
intr_stub_func * intr_stubs[256]
#define SEL_TSS
Definition: loader.h:40
Here is the call graph for this function:
Here is the caller graph for this function:

◆ intr_name()

const char * intr_name ( uint8_t  vec)
405 {
406 return intr_names[vec];
407}
Here is the caller graph for this function:

◆ intr_register_ext()

void intr_register_ext ( uint8_t  vec_no,
intr_handler_func handler,
const char *  name 
)
229 {
230 ASSERT (vec_no >= 0x20 && vec_no <= 0x2f);
231 register_handler (vec_no, 0, INTR_OFF, handler, name);
232}
static void register_handler(uint8_t vec_no, int dpl, enum intr_level level, intr_handler_func *handler, const char *name)
Definition: interrupt.c:211
uint64_t vec_no
Definition: interrupt.h:10
Here is the call graph for this function:
Here is the caller graph for this function:

◆ intr_register_int()

void intr_register_int ( uint8_t  vec_no,
int  dpl,
enum intr_level  level,
intr_handler_func handler,
const char *  name 
)
250{
251 ASSERT (vec_no < 0x20 || vec_no > 0x2f);
252 register_handler (vec_no, dpl, level, handler, name);
253}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ intr_set_level()

enum intr_level intr_set_level ( enum intr_level  level)
130 {
131 return level == INTR_ON ? intr_enable () : intr_disable ();
132}
enum intr_level intr_enable(void)
Definition: interrupt.c:136
enum intr_level intr_disable(void)
Definition: interrupt.c:151
Here is the call graph for this function:
Here is the caller graph for this function:

◆ intr_yield_on_return()

void intr_yield_on_return ( void  )
269 {
270 ASSERT (intr_context ());
271 yield_on_return = true;
272}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ pic_end_of_interrupt()

static void pic_end_of_interrupt ( int  irq)
static
317 {
318 ASSERT (irq >= 0x20 && irq < 0x30);
319
320 /* Acknowledge master PIC. */
321 outb (0x20, 0x20);
322
323 /* Acknowledge slave PIC if this is a slave interrupt. */
324 if (irq >= 0x28)
325 outb (0xa0, 0x20);
326}
static void outb(uint16_t port, uint8_t data)
Definition: io.h:109
Here is the call graph for this function:
Here is the caller graph for this function:

◆ pic_init()

static void pic_init ( void  )
static
291 {
292 /* Mask all interrupts on both PICs. */
293 outb (0x21, 0xff);
294 outb (0xa1, 0xff);
295
296 /* Initialize master. */
297 outb (0x20, 0x11); /* ICW1: single mode, edge triggered, expect ICW4. */
298 outb (0x21, 0x20); /* ICW2: line IR0...7 -> irq 0x20...0x27. */
299 outb (0x21, 0x04); /* ICW3: slave PIC on line IR2. */
300 outb (0x21, 0x01); /* ICW4: 8086 mode, normal EOI, non-buffered. */
301
302 /* Initialize slave. */
303 outb (0xa0, 0x11); /* ICW1: single mode, edge triggered, expect ICW4. */
304 outb (0xa1, 0x28); /* ICW2: line IR0...7 -> irq 0x28...0x2f. */
305 outb (0xa1, 0x02); /* ICW3: slave ID is 2. */
306 outb (0xa1, 0x01); /* ICW4: 8086 mode, normal EOI, non-buffered. */
307
308 /* Unmask all interrupts. */
309 outb (0x21, 0x00);
310 outb (0xa1, 0x00);
311}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ register_handler()

static void register_handler ( uint8_t  vec_no,
int  dpl,
enum intr_level  level,
intr_handler_func handler,
const char *  name 
)
static
212 {
214 if (level == INTR_ON) {
216 }
217 else {
219 }
220 intr_handlers[vec_no] = handler;
221 intr_names[vec_no] = name;
222}
#define make_trap_gate(g, function, dpl)
Definition: interrupt.c:86
Here is the caller graph for this function:

Variable Documentation

◆ idt

struct gate idt[INTR_CNT]
static

◆ idt_desc

struct desc_ptr idt_desc
static
Initial value:
= {
.size = sizeof(idt) - 1,
}
uint64_t address
Definition: mmu.h:1

◆ in_external_intr

bool in_external_intr
static

◆ intr_handlers

intr_handler_func* intr_handlers[INTR_CNT]
static

◆ intr_names

const char* intr_names[INTR_CNT]
static

◆ yield_on_return

bool yield_on_return
static