PKUOS - Pintos
Pintos source browser for PKU Operating System course
|
#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/vaddr.h"
#include "devices/timer.h"
Go to the source code of this file.
Macros | |
#define | PIC0_CTRL 0x20 |
Programmable Interrupt Controller (PIC) registers. More... | |
#define | PIC0_DATA 0x21 |
Master PIC data register address. More... | |
#define | PIC1_CTRL 0xa0 |
Slave PIC control register address. More... | |
#define | PIC1_DATA 0xa1 |
Slave PIC data register address. More... | |
#define | INTR_CNT 256 |
Number of x86 interrupts. More... | |
Functions | |
static void | pic_init (void) |
Programmable Interrupt Controller helpers. More... | |
static void | pic_end_of_interrupt (int irq) |
Sends an end-of-interrupt signal to the PIC for the given IRQ. More... | |
static uint64_t | make_intr_gate (void(*)(void), int dpl) |
Interrupt Descriptor Table helpers. More... | |
static uint64_t | make_trap_gate (void(*function)(void), int dpl) |
Creates a trap gate that invokes FUNCTION with the given DPL. More... | |
static uint64_t | make_idtr_operand (uint16_t limit, void *base) |
Returns a descriptor that yields the given LIMIT and BASE when used as an operand for the LIDT instruction. More... | |
void | intr_handler (struct intr_frame *args) |
Interrupt handlers. More... | |
static void | unexpected_interrupt (const struct intr_frame *f) |
Handles an unexpected interrupt with interrupt frame F. More... | |
enum intr_level | intr_get_level (void) |
Returns the current interrupt status. More... | |
enum intr_level | intr_set_level (enum intr_level level) |
Enables or disables interrupts as specified by LEVEL and returns the previous interrupt status. More... | |
enum intr_level | intr_enable (void) |
Enables interrupts and returns the previous interrupt status. More... | |
enum intr_level | intr_disable (void) |
Disables interrupts and returns the previous interrupt status. More... | |
void | intr_init (void) |
Initializes the interrupt system. More... | |
static void | register_handler (uint8_t vec_no, int dpl, enum intr_level level, intr_handler_func *handler, const char *name) |
Registers interrupt VEC_NO to invoke HANDLER with descriptor privilege level DPL. More... | |
void | intr_register_ext (uint8_t vec_no, intr_handler_func *handler, const char *name) |
Registers external interrupt VEC_NO to invoke HANDLER, which is named NAME for debugging purposes. More... | |
void | intr_register_int (uint8_t vec_no, int dpl, enum intr_level level, intr_handler_func *handler, const char *name) |
Registers internal interrupt VEC_NO to invoke HANDLER, which is named NAME for debugging purposes. More... | |
bool | intr_context (void) |
Returns true during processing of an external interrupt and false at all other times. More... | |
void | intr_yield_on_return (void) |
During processing of an external interrupt, directs the interrupt handler to yield to a new process just before returning from the interrupt. More... | |
static uint64_t | make_gate (void(*function)(void), int dpl, int type) |
Creates an gate that invokes FUNCTION. More... | |
void | intr_dump_frame (const struct intr_frame *f) |
Dumps interrupt frame F to the console, for debugging. More... | |
const char * | intr_name (uint8_t vec) |
Returns the name of interrupt VEC. More... | |
Variables | |
static uint64_t | idt [INTR_CNT] |
The Interrupt Descriptor Table (IDT). More... | |
static intr_handler_func * | intr_handlers [INTR_CNT] |
Interrupt handler functions for each interrupt. More... | |
static const char * | intr_names [INTR_CNT] |
Names for each interrupt, for debugging purposes. More... | |
static unsigned int | unexpected_cnt [INTR_CNT] |
Number of unexpected interrupts for each vector. More... | |
static bool | in_external_intr |
External interrupts are those generated by devices outside the CPU, such as the timer. More... | |
static bool | yield_on_return |
Should we yield on interrupt return? More... | |
#define INTR_CNT 256 |
Number of x86 interrupts.
Definition at line 22 of file interrupt.c.
#define PIC0_CTRL 0x20 |
Programmable Interrupt Controller (PIC) registers.
A PC has two PICs, called the master and slave PICs, with the slave attached ("cascaded") to the master IRQ line 2. Master PIC control register address.
Definition at line 16 of file interrupt.c.
#define PIC0_DATA 0x21 |
Master PIC data register address.
Definition at line 17 of file interrupt.c.
#define PIC1_CTRL 0xa0 |
Slave PIC control register address.
Definition at line 18 of file interrupt.c.
#define PIC1_DATA 0xa1 |
Slave PIC data register address.
Definition at line 19 of file interrupt.c.
bool intr_context | ( | void | ) |
Returns true during processing of an external interrupt and false at all other times.
Definition at line 212 of file interrupt.c.
References in_external_intr.
Referenced by acquire_console(), cond_signal(), cond_wait(), console_locked_by_current_thread(), intq_getc(), intq_putc(), intr_enable(), intr_handler(), intr_yield_on_return(), lock_acquire(), release_console(), sema_down(), thread_block(), thread_exit(), thread_yield(), and wait().
enum intr_level intr_disable | ( | void | ) |
Disables interrupts and returns the previous interrupt status.
Definition at line 104 of file interrupt.c.
References intr_get_level().
Referenced by debug_backtrace_all(), debug_panic(), idle(), init_thread(), input_getc(), intr_set_level(), pit_configure_channel(), sema_down(), sema_try_down(), sema_up(), serial_flush(), serial_init_queue(), serial_putc(), speaker_off(), speaker_on(), thread_exit(), thread_unblock(), thread_yield(), timer_ticks(), and vga_putc().
void intr_dump_frame | ( | const struct intr_frame * | f | ) |
Dumps interrupt frame F to the console, for debugging.
Definition at line 411 of file interrupt.c.
References intr_frame::cs, intr_frame::ds, intr_frame::eax, intr_frame::ebp, intr_frame::ebx, intr_frame::ecx, intr_frame::edi, intr_frame::edx, intr_frame::eip, intr_frame::error_code, intr_frame::es, intr_frame::esi, intr_frame::esp, intr_names, printf(), PRIx16, PRIx32, intr_frame::ss, and intr_frame::vec_no.
Referenced by kill().
enum intr_level intr_enable | ( | void | ) |
Enables interrupts and returns the previous interrupt status.
Definition at line 88 of file interrupt.c.
References ASSERT, intr_context(), and intr_get_level().
Referenced by intr_set_level(), kernel_thread(), page_fault(), and thread_start().
enum intr_level intr_get_level | ( | void | ) |
Returns the current interrupt status.
Definition at line 65 of file interrupt.c.
References FLAG_IF, INTR_OFF, and INTR_ON.
Referenced by input_full(), input_putc(), intq_empty(), intq_full(), intq_getc(), intq_putc(), intr_disable(), intr_enable(), intr_handler(), issue_pio_command(), putc_poll(), real_time_sleep(), schedule(), serial_notify(), signal(), speaker_beep(), thread_block(), thread_foreach(), thread_schedule_tail(), timer_calibrate(), timer_sleep(), wait(), and write_ier().
void intr_handler | ( | struct intr_frame * | frame | ) |
Interrupt handlers.
Handler for all interrupts, faults, and exceptions. This function is called by the assembly language interrupt stubs in intr-stubs.S. FRAME describes the interrupt and the interrupted thread's registers.
Definition at line 345 of file interrupt.c.
References ASSERT, in_external_intr, intr_context(), intr_get_level(), intr_handlers, INTR_OFF, NULL, pic_end_of_interrupt(), thread_yield(), unexpected_interrupt(), intr_frame::vec_no, and yield_on_return.
void intr_init | ( | void | ) |
Initializes the interrupt system.
Definition at line 118 of file interrupt.c.
References idt, INTR_CNT, intr_names, intr_stubs, make_idtr_operand(), make_intr_gate(), and pic_init().
Referenced by pintos_init().
const char * intr_name | ( | uint8_t | vec | ) |
Returns the name of interrupt VEC.
Definition at line 435 of file interrupt.c.
References intr_names.
Referenced by kill().
void intr_register_ext | ( | uint8_t | vec_no, |
intr_handler_func * | handler, | ||
const char * | name | ||
) |
Registers external interrupt VEC_NO to invoke HANDLER, which is named NAME for debugging purposes.
The handler will execute with interrupts disabled.
Definition at line 181 of file interrupt.c.
References ASSERT, INTR_OFF, name, and register_handler().
Referenced by ide_init(), kbd_init(), serial_init_queue(), and timer_init().
void intr_register_int | ( | uint8_t | vec_no, |
int | dpl, | ||
enum intr_level | level, | ||
intr_handler_func * | handler, | ||
const char * | name | ||
) |
Registers internal interrupt VEC_NO to invoke HANDLER, which is named NAME for debugging purposes.
The interrupt handler will be invoked with interrupt status LEVEL.
The handler will have descriptor privilege level DPL, meaning that it can be invoked intentionally when the processor is in the DPL or lower-numbered ring. In practice, DPL==3 allows user mode to invoke the interrupts and DPL==0 prevents such invocation. Faults and exceptions that occur in user mode still cause interrupts with DPL==0 to be invoked. See [IA32-v3a] sections 4.5 "Privilege Levels" and 4.8.1.1 "Accessing Nonconforming Code Segments" for further discussion.
Definition at line 202 of file interrupt.c.
References ASSERT, name, and register_handler().
Referenced by exception_init(), and syscall_init().
enum intr_level intr_set_level | ( | enum intr_level | level | ) |
Enables or disables interrupts as specified by LEVEL and returns the previous interrupt status.
Definition at line 81 of file interrupt.c.
References intr_disable(), intr_enable(), and INTR_ON.
Referenced by debug_backtrace_all(), init_thread(), input_getc(), pit_configure_channel(), sema_down(), sema_try_down(), sema_up(), serial_flush(), serial_init_queue(), serial_putc(), speaker_off(), speaker_on(), thread_unblock(), thread_yield(), timer_ticks(), and vga_putc().
void intr_yield_on_return | ( | void | ) |
During processing of an external interrupt, directs the interrupt handler to yield to a new process just before returning from the interrupt.
May not be called at any other time.
Definition at line 222 of file interrupt.c.
References ASSERT, intr_context(), and yield_on_return.
Referenced by thread_tick().
|
static |
Creates an gate that invokes FUNCTION.
The gate has descriptor privilege level DPL, meaning that it can be invoked intentionally when the processor is in the DPL or lower-numbered ring. In practice, DPL==3 allows user mode to call into the gate and DPL==0 prevents such calls. Faults and exceptions that occur in user mode still cause gates with DPL==0 to be invoked. See [IA32-v3a] sections 4.5 "Privilege Levels" and 4.8.1.1 "Accessing Nonconforming Code Segments" for further discussion.
TYPE must be either 14 (for an interrupt gate) or 15 (for a trap gate). The difference is that entering an interrupt gate disables interrupts, but entering a trap gate does not. See [IA32-v3a] section 5.12.1.2 "Flag Usage By Exception- or Interrupt-Handler Procedure" for discussion.
< Offset 15:0.
< Target code segment.
< Offset 31:16.
< Present.
< Descriptor privilege level.
< System.
< Gate type.
Definition at line 294 of file interrupt.c.
References ASSERT, NULL, and SEL_KCSEG.
Referenced by make_intr_gate(), and make_trap_gate().
Returns a descriptor that yields the given LIMIT and BASE when used as an operand for the LIDT instruction.
Definition at line 333 of file interrupt.c.
Referenced by intr_init().
|
static |
Interrupt Descriptor Table helpers.
Creates an interrupt gate that invokes FUNCTION with the given DPL.
Definition at line 317 of file interrupt.c.
References make_gate().
Referenced by intr_init(), and register_handler().
|
static |
Creates a trap gate that invokes FUNCTION with the given DPL.
Definition at line 325 of file interrupt.c.
References make_gate().
Referenced by register_handler().
|
static |
Sends an end-of-interrupt signal to the PIC for the given IRQ.
If we don't acknowledge the IRQ, it will never be delivered to us again, so this is important.
Definition at line 265 of file interrupt.c.
References ASSERT, and outb().
Referenced by intr_handler().
|
static |
Programmable Interrupt Controller helpers.
8259A Programmable Interrupt Controller.
Initializes the PICs. Refer to [8259A] for details.
By default, interrupts 0...15 delivered by the PICs will go to interrupt vectors 0...15. Those vectors are also used for CPU traps and exceptions, so we reprogram the PICs so that interrupts 0...15 are delivered to interrupt vectors 32...47 (0x20...0x2f) instead.
< ICW1: single mode, edge triggered, expect ICW4.
< ICW2: line IR0...7 -> irq 0x20...0x27.
< ICW3: slave PIC on line IR2.
< ICW4: 8086 mode, normal EOI, non-buffered.
< ICW1: single mode, edge triggered, expect ICW4.
< ICW2: line IR0...7 -> irq 0x28...0x2f.
< ICW3: slave ID is 2.
< ICW4: 8086 mode, normal EOI, non-buffered.
Definition at line 238 of file interrupt.c.
References outb(), PIC0_CTRL, PIC0_DATA, PIC1_CTRL, and PIC1_DATA.
Referenced by intr_init().
|
static |
Registers interrupt VEC_NO to invoke HANDLER with descriptor privilege level DPL.
Names the interrupt NAME for debugging purposes. The interrupt handler will be invoked with interrupt status set to LEVEL.
Definition at line 165 of file interrupt.c.
References ASSERT, idt, intr_handlers, intr_names, INTR_ON, intr_stubs, make_intr_gate(), make_trap_gate(), name, and NULL.
Referenced by intr_register_ext(), and intr_register_int().
|
static |
Handles an unexpected interrupt with interrupt frame F.
An unexpected interrupt is one that has no registered handler.
Definition at line 394 of file interrupt.c.
References intr_names, printf(), unexpected_cnt, and intr_frame::vec_no.
Referenced by intr_handler().
The Interrupt Descriptor Table (IDT).
The format is fixed by the CPU. See [IA32-v3a] sections 5.10 "Interrupt Descriptor Table (IDT)", 5.11 "IDT Descriptors", 5.12.1.2 "Flag Usage By Exception- or Interrupt-Handler Procedure".
Definition at line 28 of file interrupt.c.
Referenced by intr_init(), and register_handler().
|
static |
External interrupts are those generated by devices outside the CPU, such as the timer.
External interrupts run with interrupts turned off, so they never nest, nor are they ever pre-empted. Handlers for external interrupts also may not sleep, although they may invoke intr_yield_on_return() to request that a new process be scheduled just before the interrupt returns. Are we processing an external interrupt?
Definition at line 47 of file interrupt.c.
Referenced by intr_context(), and intr_handler().
|
static |
Interrupt handler functions for each interrupt.
Definition at line 31 of file interrupt.c.
Referenced by intr_handler(), and register_handler().
|
static |
Names for each interrupt, for debugging purposes.
Definition at line 34 of file interrupt.c.
Referenced by intr_dump_frame(), intr_init(), intr_name(), register_handler(), and unexpected_interrupt().
|
static |
Number of unexpected interrupts for each vector.
An unexpected interrupt is one that has no registered handler.
Definition at line 38 of file interrupt.c.
Referenced by unexpected_interrupt().
|
static |
Should we yield on interrupt return?
Definition at line 48 of file interrupt.c.
Referenced by intr_handler(), and intr_yield_on_return().