CS代考 ECE391- Computer System

ECE391- Computer System
Engineering

Lecture 11

Copyright By PowCoder代写 加微信 powcoder

Linux abstraction of PIC (cont)

University of Illinois at Urbana- Champaign

Announcements

• If an online student wishes to attend the in-person exam,
they must email by the
end of Thursday (9/23).
• If any student has a conflict, please also email the professors

with your proof of conflict and availability by the end of
Thursday (9/23).
• NO Lecture on Tuesday, September 28

• Review Session
• EXAM I – Wednesday, September 29th, 7:00pm-9:00 PM

• Location: ECEB 1002
• MP2 Posted – All checkpoints should be committed to the

master(main) branch on GitLab by:
• Checkpoint 1: 5:59PM on 10/5
• Final Checkpoint: 5:59PM on 10/12

Exam 1 info for online students

• Your first exam is on Wednesday 9/29 at 7pm-9pm CST
(same as in-person).
• The exam will be distributed on compass at 6:55pm on the

• You will be asked to join a zoom meeting and share

your screen with the camera on that shows your hands
and above.
• The zoom link will be announced later.

• Once you are done with the exam you have to
scan/take pictures of your solution and upload on
• You will have additional 10 minutes for this, so you should

finish uploading by 7:10pm.

Lecture Topics

• Linux abstraction of PIC
• General interrupt abstractions
• Linux interrupt system
• data structures
• handler installation & removal
• invocation
• execution
• tasklets

Interrupt Descriptor Table (IDT)

• Before the kernel

enables interrupts it
must initialize the idtr
register to point to the
IDT table (set by the kernel
using lidt instruction)

• Kernel initialization
(setup_idt()) fills all
the 256 entries of IDT
with the provisional (or
null) handler

• Associates the interrupt line
with the int. handler routine.

• 256 entries (each 8-bytes) or
descriptors; each corresponds
to an interrupt vector
• hardware interrupts mapped

into vectors 0x20 to 0x2F

• All Linux interrupt handlers are
activated by so called: interrupt
gates (a descriptor type)

• Whenever an interrupt gate is
hit, interrupts are disabled
automatically by the processor

interrupt[x]

irq_desc Array

• Every interrupt vector has its
own irq_desc_t
descriptor

• Descriptors are grouped
together in irq_desc array,
a data structure supported

• When a device driver calls
the request_irq()
function a new structure to
represent the handler is
allocated and initialized

IRQ descriptor array (irq_desc)

action list

disable depth

device name

struct irqaction
flow handler

Basic functions

• Installing an interrupt handler
• Uninstalling an interrupt handler
• Interrupt invocation
• Interrupt Execution

device name

Add the new action structure
to the link list of actions

Upon failure free the action structure

Dynamically allocate
new action structure for
linked list of actions

Fill in the new
action structure

irq # (0-15 for PIC)

bit vector
pointer to interrupt handler

pointer to device-specific

human-readable device name

Linux’ request_irq
(kernel/irq/manage.c)

Comments on request_irq

• Arguments
• irq – irq # (0-15 for PIC)
• handler – pointer to interrupt handler with following arguments

• dev_id pointer (type void*)
• handlers should return 1 if handled, 0 if not

• irqflags – bit vector
• IRQF_SHARED – interrupt chaining is allowed
• IRQF_DISABLED – execute handlers with IF=0
• IRQF_SAMPLE_RANDOM – use device timing as source of random

• devname – human-readable device name (visible in

/proc/interrupts)
• dev_id – pointer to device-specific data (returned to handler when

Comments on request_irq

• Start by checking values
• Dynamically allocate new action structure for

linked list of actions
• Fill in the new action structure
• Try to add it
• using setup_irq
• if call fails, free the action structure

Critical section begins

Critical section ends

New action is added at the end of the link list

Startup PIC for this interrupt

Create new /proc/irq/ directory

action list

disable depth

flow handler

descriptor

human-readable name
startup function
shutdown function

disable function
enable function

(+ several others…)

mask function
mask_ack function
unmask function

jump table

Add handler subdirectory in /proc/irq//

Linux setup_irq
(kernel/irq/manage.c)

Comments on setup_irq

• Start with a couple of sanity checks
• If random sampling flag is set
• initialize as source of random numbers
• good random numbers are hard to find!
• devices such as disks can be used because of “random”

rotational latency to read data (for example)

Comments on setup_irq (cont.)

• Critical section (most of function)
• blocks other activity on descriptor
• uses irqsave/restore to allow handlers to be added from

any context

• Note that new action goes at the end of the linked
list, not the start
• Interrupt chaining only allowed
• if all handlers agree to it
• otherwise only first handler is successfully added

Comments on setup_irq (cont.)

• If this handler is the first
• make sure that PIC jump table has proper default

• clear some status flags
• clear any previous software disablement (depth)
• call the PIC startup function

• After critical section
• create /proc/irq/ directory if necessary
• add handler subdirectory in /proc/irq///

Free the action structure

Linux free_irq
(kernel/irq/manage.c)

Comments on free_irq

• Arguments
• irq – irq # (0-15 for PIC)
• dev_id – MUST match pointer value used in request_irq

• Start by checking arguments
• Critical section starts to prevent manipulations of

descriptor
• blocks interrupt from starting to execute
• (interrupt may already be executing on another

processor)

Comments on free_irq (cont.)

• Search for action in list
• based on dev_id pointer
• hence need for matching pointer
• passing NULL dev_id not allowed with chained interrupts

• Once found (notice that most of the loop executes
exactly once)
• remove the action
• if this action/handler was the last for this interrupt,

• turn on software disablement
• (doing so signals interrupts waiting for descriptor lock

to abort once they obtain the lock)
• call the PIC shutdown function

Comments on free_irq (cont.)

• Remove the /proc/irq// entry
• On an SMP
• interrupt may be executing on another processor
• need to wait for it to finish after releasing descriptor

• Finally, free the action structure

Interrupt Invocation

interrupt[4]

PUSHL $0xFFFFFFFB
JMP common_interrupt

save all regs
linkage to C func
ESP->EAX (first arg.)
call do_IRQ
JMP ret_from_intr

context switch?
restore all registers

Saves the IRQ
through negative
(-5 in the example)

movl %esp, %eax

Interrupt Invocation (cont.)

• Why funnel all IRQs into one piece of code(instead
of producing one function per IRQ) ?
• kernel code/size versus speed tradeoff

• perhaps no big deal for 16
• keep in mind that you’re saving a tiny number of instructions
• APIC used by most SMPs has 256 vectors

• Signature for do_IRQ
fastcall unsigned int do_IRQ

(struct pt_regs* regs);

• fastcall macro in Linux tells gcc to pass args in EAX, EDX,
• EAX points to saved registers (regs argument)
• saved registers already on stack
• note that processor clears IF when it takes an interrupt
• EFLAGS stored by processor include original IF value

Interrupt Invocation (cont.)

Linux do_IRQ
arch/i386/kernel/irq.c

fastcall convention used to pass arguments in registers;
reduces the number of memory accesses required for the call

call interrupt flow handler handle_level_irq for all 8259A interrupts

Exit irq context and process softirqs if needed

gets the interrupt number from the orig_eax filed in the regs structure

Increments counter of nested interrupt handlers
Record registers at time of interrupt

• Value pushed by irq-specific code re-converted to find
• Start with a sanity check
• set_irq_regs calls record registers at time of

• per-CPU storage
• Example use: CPU state accounting on timer interrupts
• Chained via local old_regs

Comments on do_irq

• irq_enter / irq_exit
• necessary for proper priority

• e.g., second hard interrupt occurs
• after new interrupt handled, should return to first
• must delay processing of soft interrupts

• irq_exit processes soft interrupts when appropriate

Comments on do_irq (cont.)

• Central component
• call interrupt flow handler
• handle_level_irq for all 8259A interrupts

• Return value ignored (probably intended to indicate interrupt

Comments on do_irq (cont.)

Critical section begins

Critical section ends

Critical section ends

Call PIC’s mask_ack function

If interrupt already in progress, do nothing

Atomically decide whether to execute handlers

Set status for execution: in-progress and no longer pending

Handler execution done via handle_IRQ_event

Critical section begins

When done, remove in-progress flag
and unmask on PIC (unless disabled)

Linux handle_level_irq
kernel/irq/chip.c

• Critical section starts
• to read descriptor status and action (handler) list
• IF=0 at this point (set by processor when taking interrupt)

• Immediately call PIC’s mask_ack function (via a
wrapper function)
• If interrupt already in progress, do nothing

• Interrupt already re-masked and re-acknowledged on PIC
• extra interrupt can be lost [makes no sense of edge triggered]

• Remove software replay and autoprobe flags
• Kernel statistics track # of interrupts seen (see

/proc/interrupts)

Comments on handle_level_irq

Comments on handle_level_irq
• Atomically decide whether to execute handlers

immediately
• do so if handler defined and not disabled by software
• if not, skip to end

• mark as pending and end interrupt handling
• replayed after last nested enable_irq call

• Set status for execution: in-progress, and no longer
• Handler execution done via handle_IRQ_event
• done without descriptor lock

• allows handlers to use infrastructure
• e.g., enable_irq/disable_irq,
request_irq/free_irq

• usually done with IF=1 (changed inside
handle_IRQ_event)
• done without descriptor lock
• otherwise this code can deadlock with self

• When done, remove in-progress flag and unmask on
PIC (unless disabled)

Comments on handle_level_irq

call translates basically to STI
(local means “on this CPU”)

Walk through list; call each handler
(return value 1 means handled)

Turn interrupts back off (IF=0 / CLI)

Linux handle_IRQ_event
kernel/irq/handle.c

• Set IF=1 unless the first handler asked to be
executed with IF=0
• indicated by IRQF_DISABLED flag
• call translates basically to STI (local means “on this

• Walk through list
• call each handler
• return value 1 means handled

• Generate random numbers if desired
• Turn interrupts back off (IF=0 / CLI)

Comments on
handle_IRQ_event

• IRQ_PENDING—interrupt raised by hardware;
waiting to be executed
• IRQ_INPROGRESS—some processor is executing

• IRQ_DISABLED—interrupt disabled in software;

postpone execution
• IRQ_REPLAY—software replay of previously

postponed execution

Summary on Descriptor Flags

Soft Interrupts in Linux
linux/interrupt.h and kernel/softirq.c

• When are soft interrupts executed?
• after a hard interrupt completes
• periodically by a daemon in the kernel

• seven or eight prioritized types, including high and low tasklet

priorities
• linked list for each tasklet priority
• run on processor on which interrupt is scheduled
• each handler atomic with respect to itself (only)

Soft Interrupts in Linux (cont.)
linux/interrupt.h and kernel/softirq.c

Declaring a handler
name for tasklet_struct

an unsigned long

DECLARE_TASKLET (name, func, data);

void (*func) (unsigned long);

linked list

TASKLET_STATE_SCHED, TASKLET_STATE_RUN
# of disables
pointer to the tasklet function
integer which can be used by the tasklet function

Tasklet Scheduling
• The following two calls schedule a tasklet for execution
void tasklet_schedule (struct tasklet_struct* t);

void tasklet_hi_schedule (struct tasklet_struct* t);

• First form
• schedules tasklet at low priority
• on the executing processor

• Second form schedules at high priority
• Enable and disable calls analogous to hard interrupts

(including nesting)

Tasklet Execution

• do_softirq call
• checks per-processor bit vector of pending priorities (high,

low, etc.)
• executes action for each priority [softirq_vec]
• tasklet_action walks through linked list

[tasklet_hi_action walks through high-priority list ]
• repeats up to 10 times or until no softirqs are raised

Tasklet Execution Atomicity

• Two bits in state changed atomically
• TASKLET_STATE_SCHED – tasklet scheduled for execution
• TASKLET_STATE_RUN – tasklet executing on some processor

• When scheduling
• set TASKLET_STATE_SCHED atomically
• if already set, schedule call does nothing

Tasklet Execution Atomicity (cont.)
When executing, for each tasklet in linked list (at either priority)
A. set TASKLET_STATE_RUN atomically (if already set, stop)

B. check if tasklet is software disabled (count field)

• if so, clear TASKLET_STATE_RUN
• leave the tasklet in the linked list for this priority
• set the pending bit for this priority
• daemon will try again later

C. clear TASKLET_STATE_SCHED

D. execute handler

E. clear TASKLET_STATE_RUN

flags SCHED

execute/step C

(disabled)

execution (execute/step D) occurs in lower two states (and execute/step A fails in these states)

程序代写 CS代考 加微信: powcoder QQ: 1823890830 Email: powcoder@163.com