sogang university advanced operating systems (enhanced device driver operations) advanced operating...
TRANSCRIPT
Sogang University
Advanced Operating SystemsAdvanced Operating Systems
(Enhanced Device Driver Operations)(Enhanced Device Driver Operations)
Sang Gue Oh, Ph.D.Sang Gue Oh, Ph.D.
Email : [email protected] : [email protected]
Page 2Sogang University
Enhanced Device Driver Operations
IntroductionIntroduction IntroductionIntroduction
Controlling the hardware using ioctl delivers commands to the device other than read/write.
adjusting baud rate, …
Blocking I/O puts the requesting process in wait state (e.g., sleep_on(), etc). the kernel may schedule other process (e.g., schedule(), etc). why? the kernel cannot be preempted and the device takes time to p
rocess the request.
Interrupt Handling
Page 3Sogang University
Enhanced Device Driver Operations
Controlling the Hardware using Controlling the Hardware using ioctlioctl Controlling the Hardware using Controlling the Hardware using ioctlioctl ioctl is a system call with 3 arguments
int ioctl(int fd, int cmd, … ); the 3rd argument is optional (argument for the command).
Inside kernelint (*ioctl) (struct inode *inode, struct file filp, unsigned int cmd,
unsigned long arg); Since type checking is disabled on the extra argument, the compiler
can’t warn if an invalid argument is passed to ioctl (3rd argument). The programmer won’t notice the error until run time.
Command is an integer You may define meaningful names in the header file. The command numbers should be unique across the system to prev
ent errors caused by issuing the right commands to the wrong device.
Page 4Sogang University
Enhanced Device Driver Operations
Choosing the Choosing the ioctlioctl Commands Commands Choosing the Choosing the ioctlioctl Commands Commands The commands generally consist of four bit-fields
type (magic number) : used throughout the driver. number : ordinal number to denote a device. direction : no data, read (from device), write (to device). size : size of data transfer involved (pass the instance without sizeof).
Macros to encode/decode a command (defined in <asm/ioctl.h>) Encoding
_IO(type, number) : for no data transferring command _IOR(type, number, size) : for read _IOW(type, number, size) : for write _IOWR(type, number, size) : for read and write
Decoding four bit-fields _IOC_TYPE(command), _IOC_NR(command) _IOC_DIR(command), _IOC_SIZE(command)
Page 5Sogang University
Enhanced Device Driver Operations
Blocking I/OBlocking I/OBlocking I/OBlocking I/O
What if there is no data ready for read ? go sleep waiting for the data
Go to sleep void interruptible_sleep_on(struct wait_queue **q);
a signal can abort the sleep void sleep_on(struct wait_queue **q);
Wake up void wake_up_interruptible(struct wait_queue **q); void wake_up(struct wait_queue **q);
One wait queue for each event E.g., one for read and one for write for each device
Page 6Sogang University
Enhanced Device Driver Operations
Writing Reentrant CodeWriting Reentrant Code Writing Reentrant CodeWriting Reentrant Code
When a process is put to sleep, the driver is still alive and can be called by another process.
Such situations can be handled by writing “reentrant code”. Reentrant code
for processes that can be on sleep all blocking functions and functions that call them need to store state information for each process
Where to put the state information ? filp->private_data
works only when one process uses the file local static variable in the driver
each process has its own stack use kmalloc if large space is needed
Page 7Sogang University
Enhanced Device Driver Operations
Asynchronous Operations – Interrupt HandlingAsynchronous Operations – Interrupt Handling Asynchronous Operations – Interrupt HandlingAsynchronous Operations – Interrupt Handling
Installing/Freeing an Interrupt Handler int request_irq(unsigned int irq,
void (*handler)(int, void*, struct pt_regs*),
unsigned long flags,
const char *device,
void *dev_id ); irg : interrupt number. handler : pointer to the handling function being installed. flag : bit-mask of options related to interrupt management.
– SA_INTERRUPT : set when “fast” interrupt. Cleared when “slow” interrupt.– SA_SHIRQ : interrupt can be shared between devices.
device : string used in /proc/interrupts to show the owner. device_id : usually set to NULL. Used only for shared interrupt.
void free_irq(unsigned int irq, void *dev_id);
Page 8Sogang University
Enhanced Device Driver Operations
Example of Installing an Interrupt HandlerExample of Installing an Interrupt Handler Example of Installing an Interrupt HandlerExample of Installing an Interrupt Handler
Short Interrupt Handler IRQ Requesting Example
If ( short_irq >= 0 ) {
request = request_irq(short_irq, short_interrupt, SA_INTERRUPT, “short”,
NULL );
if ( request ) { /* return 0 if successful */
printk( KERN_INFO “cannot be assigned irq %I\n”, short_irq );
short_irq = -1;
}
else {
outb( 0x10, short_base + 2 );
}
}
Page 9Sogang University
Enhanced Device Driver Operations
Initializing an Interrupt HandlerInitializing an Interrupt Handler Initializing an Interrupt HandlerInitializing an Interrupt Handler
Init module time Sounds like a good idea but it actually isn’t. If a module requests an IRQ at initialization, it prevents any other dri
ver from using the interrupts, even if the device holding it is never used.
Device open time The correct place to call request_irq is when the device is first opene
d, before the hardware is instructed to generate interrupts. The place to call free_irq is the last time the device is closed, after th
e hardware is told not to interrupt the processor any more.
Page 10Sogang University
Enhanced Device Driver Operations
Statistics for Interrupts (/proc/interrupt) Statistics for Interrupts (/proc/interrupt) Statistics for Interrupts (/proc/interrupt) Statistics for Interrupts (/proc/interrupt)
IRQ #IRQ #
(installed)(installed)
InterruptInterrupt
countcount
Page 11Sogang University
Enhanced Device Driver Operations
Low-Level Statistics for Interrupts (/proc/stat)Low-Level Statistics for Interrupts (/proc/stat) Low-Level Statistics for Interrupts (/proc/stat)Low-Level Statistics for Interrupts (/proc/stat)Total # of all interrupts Interrupt 0 count Interrupt 1 count ……….Total # of all interrupts Interrupt 0 count Interrupt 1 count ……….
Page 12Sogang University
Enhanced Device Driver Operations
Assigning an IRQ NumberAssigning an IRQ Number Assigning an IRQ NumberAssigning an IRQ Number
<Case 1 : Based on the default behavior>
if ( short_irq < 0 ) {
switch ( short_base ) {
case 0x378: short_irq = 7; break;
case 0x278: short_irq = 2; break;
case 0x3bc: short_irq = 5; break;
}
}
<Case 2 : Users override the default at load time>
insmod short short_irq = x [enter]
Page 13Sogang University
Enhanced Device Driver Operations
Probing (Kernel-Helped Probing)Probing (Kernel-Helped Probing) Probing (Kernel-Helped Probing)Probing (Kernel-Helped Probing)
int count = 0;
do {
unsigned long mask;
mask = probe_irq_on();
outb_p(0x10, short_base + 2); // Enable reporting
outb_p(0x00, short_base); // Clear bits
outb_p(0xff, short_base); // Set the bit: Interrupt
outb_p(0x00, short_base + 2); // Disable reporting
short_irq = probe_irq_off(mask);
if ( short_irq == 0 ) { /* return 0 if no interrupt, otherwise return interrupt #,
return negative if more than one interrupt occurred */
printk( KERN_INFO “No irq reported by probe.\n” );
short_irq = -1;
}
} while ( short_irq < 0 && count++ < 5 );
Page 14Sogang University
Enhanced Device Driver Operations
Probing (Do-It-Yourself Probing) (1)Probing (Do-It-Yourself Probing) (1) Probing (Do-It-Yourself Probing) (1)Probing (Do-It-Yourself Probing) (1)
Page 15Sogang University
Enhanced Device Driver Operations
Probing (Do-It-Yourself Probing) (2)Probing (Do-It-Yourself Probing) (2) Probing (Do-It-Yourself Probing) (2)Probing (Do-It-Yourself Probing) (2)
Page 16Sogang University
Enhanced Device Driver Operations
Probing (Do-It-Yourself Probing) (3)Probing (Do-It-Yourself Probing) (3) Probing (Do-It-Yourself Probing) (3)Probing (Do-It-Yourself Probing) (3)
Page 17Sogang University
Enhanced Device Driver Operations
Fast and Slow HandlersFast and Slow Handlers Fast and Slow HandlersFast and Slow Handlers
What is the difference? The main difference between the two kinds of interrupt handlers is th
at fast handlers guarantee atomic processing of interrupts and slow interrupts don’t.
While a slow handler is invoked, on the other hand, the kernel re-enables interrupt reporting in the microprocessor, so other interrupts can be serviced while a slow handler runs.
A fast handler runs with interrupt reporting disabled in the microprocessor, and the interrupt being serviced is disabled in the interrupt controller. The handler can nonetheless enable reporting in the processor by calling sti.
A slow handler runs with interrupt reporting enabled in the processor,and the interrupt being serviced is disabled in the interrupt controller.
Page 18Sogang University
Enhanced Device Driver Operations
Example of a Short Interrupt HandlerExample of a Short Interrupt Handler Example of a Short Interrupt HandlerExample of a Short Interrupt Handler
The role of an interrupt handler is to give feedback to its device about interrupt reception and to read or write data according to the meaning of the interrupt being serviced.
Interrupt numberInterrupt number Snapshot of the processor’s contextSnapshot of the processor’s context
Usually 0 but can be used to pass argumentsUsually 0 but can be used to pass arguments
Page 19Sogang University
Enhanced Device Driver Operations
Bottom Halves (1)Bottom Halves (1) Bottom Halves (1)Bottom Halves (1) One of the main problems with interrupt handling is how to perf
orm longish tasks within a handler. Split the handler into two halves: “top half” and “bottom half”.
Top half is the routine you register through request_irq. The bottom half (“bh” for short) is a routine that is scheduled by the top
half, to be executed later, at a safer time.
In the typical scenario, the top half saves device data to a device-specific buffer, marks its bottom handler, and exits. The bh then dispatches newly arrived data to the processes, awakening them if necessary.
Network processing: when a network interface reports the arrival of a new packet, the handler just retrieves the data and pushes it up to the protocol layer; actual processing of the packet is performed in a bottom half.
Page 20Sogang University
Enhanced Device Driver Operations
Bottom Halves (2)Bottom Halves (2) Bottom Halves (2)Bottom Halves (2)
The bottom halves exist as an array of 32 function pointers and a bit-mask.
Once a bottom half handler is activated, it is executed when do_bottom_half function is invoked, which happens within ret_from_sys_call. The ret_from_sys_call is executed whenever a process exits from a system call or when a slow interrupt handler exits.
That is, after every ret_from_sys_call, a list of up to 32 bottom halves is scanned. If they are marked active, they are each carried out once in turn and then automatically marked as inactive.
Page 21Sogang University
Enhanced Device Driver Operations
Install and Activate a Bottom Half handlerInstall and Activate a Bottom Half handler Install and Activate a Bottom Half handlerInstall and Activate a Bottom Half handler
Whenever some code wants to schedule a bottom half for running, it calls mark_bh, which sets a bit in the bit-mask variable to queue the corresponding function for execution.
#include <linux/interrupt.h>
void mark_bh(int nr); -> nr is the # of the bh to activate
The function to install a bottom half is init_bh which enters the bottom half into the function pointer table.
void init_bh(int nr, void (*routine)(void));
The function that corresponds to each bh is provided by the driver that owns the bottom half.
For example, when mark_bh(KEYBOARD_BH) is called, the function being scheduled for execution is kbd_bh, which is part of the keyboard driver.
Page 22Sogang University
Enhanced Device Driver Operations
Pre-Defined Bottom HalvesPre-Defined Bottom Halves Pre-Defined Bottom HalvesPre-Defined Bottom Halves
IMMEDIATE_BH Use tq_immediate task queue. A driver that doesn’t own a bottom h
alf can use the immediate queue as if it were its own bh. Need to call mark_bh to execute the code.
TQUEUE_BH Use tq_timer task queue. Activated at each timer tick. No need to c
all mark_bh. TQUEUE_BH is always executed later than IMMEDIATE_BH.
NET_BH Network drivers should mark this queue to notify the upper network l
ayers of events.
TIMER_BH Marked by do_timer, the function in charge of the clock tick.
Page 23Sogang University
Enhanced Device Driver Operations
Example of a Top HalfExample of a Top Half Example of a Top HalfExample of a Top Half
Task queue structureTask queue structure
Page 24Sogang University
Enhanced Device Driver Operations
Example of a Bottom Half (1) Example of a Bottom Half (1) Example of a Bottom Half (1) Example of a Bottom Half (1)
Page 25Sogang University
Enhanced Device Driver Operations
Example of a Bottom Half (2)Example of a Bottom Half (2) Example of a Bottom Half (2)Example of a Bottom Half (2)