Linux Device Drivers Interrupt Requests

Similar documents
Real Time and Embedded Systems. by Dr. Lesley Shannon Course Website:

INTERRUPT HANDLING CHAPTER NINE

Introduction to Operating Systems. Device Drivers. John Franco. Dept. of Electrical Engineering and Computing Systems University of Cincinnati

ECEN 449 Microprocessor System Design. Hardware-Software Communication. Texas A&M University

PCI Bus & Interrupts

REVISION HISTORY NUMBER DATE DESCRIPTION NAME

NPTEL Course Jan K. Gopinath Indian Institute of Science

MP3: VIRTUAL MEMORY PAGE FAULT MEASUREMENT

Operating systems for embedded systems

Operating systems for embedded systems. Embedded Operating Systems

Interrupt Handler: Top Half. Changwoo Min

CS 423 Operating System Design: Introduction to Linux Kernel Programming (MP1 Q&A)

CS 378 (Spring 2003)

Spring 2017 :: CSE 506. Device Programming. Nima Honarmand

Introduction to Linux Device Drivers Recreating Life One Driver At a Time

I/O Management Software. Chapter 5

I/O Management Software. Chapter 5

- Knowledge of basic computer architecture and organization, ECE 445

Interrupt Handler: Bottom Half. Changwoo Min

Any of the descriptors in the set {1, 4} have an exception condition pending

Using kgdb and the kgdb Internals

NPTEL Course Jan K. Gopinath Indian Institute of Science

Timers 1 / 46. Jiffies. Potent and Evil Magic

Today: Synchronization. Recap: Synchronization

1 #include <linux/module.h> 2 #include <linux/sched.h> 3 #include <linux/interrupt.h> 4 #include <linux/init.h> 5 #include <linux/kernel.

Linux Device Drivers. 5. Interrupts. 1. Introduction 2. Kernel Modules 3. Char Drivers 4. Advanced Char Drivers 5. Interrupts

Embedded Systems Programming

Embedded Systems Programming

Kernel Modules. Kartik Gopalan

Applying User-level Drivers on

Overview. This Lecture. Interrupts and exceptions Source: ULK ch 4, ELDD ch1, ch2 & ch4. COSC440 Lecture 3: Interrupts 1

SpiNNaker Application Programming Interface (API)

Scuola Superiore Sant Anna. I/O subsystem. Giuseppe Lipari

CSC369 Lecture 2. Larry Zhang

20-EECE-4029 Operating Systems Fall, 2015 John Franco

7.4 Simple example of Linux drivers

I/O Devices. Nima Honarmand (Based on slides by Prof. Andrea Arpaci-Dusseau)

A brief overview of DRM/KMS and its status in NetBSD

PC Interrupt Structure and 8259 DMA Controllers

Formal Verification of Linux Device Drivers

Linux Kernel Development (LKD)

Emulation 2. G. Lettieri. 15 Oct. 2014

Suggested Solutions (Midterm Exam October 27, 2005)

CSC369 Lecture 2. Larry Zhang, September 21, 2015

Loadable Kernel Module

Input / Output. Kevin Webb Swarthmore College April 12, 2018

Concurrency, Thread. Dongkun Shin, SKKU

Process & Thread Management II. Queues. Sleep() and Sleep Queues CIS 657

Process & Thread Management II CIS 657

Processes (Intro) Yannis Smaragdakis, U. Athens

I/O Management Intro. Chapter 5

CS5460/6460: Operating Systems. Lecture 24: Device drivers. Anton Burtsev April, 2014

The K Project. Interrupt and Exception Handling. LSE Team. May 14, 2018 EPITA. The K Project. LSE Team. Introduction. Interrupt Descriptor Table

Chapter 6. Buffer cache. Code: Data structures

Process Synchronization and Communication

Yielding, General Switching. November Winter Term 2008/2009 Gerd Liefländer Universität Karlsruhe (TH), System Architecture Group

Advanced Operating Systems #13

ECE 391 Exam 1 Review Session - Spring Brought to you by HKN

FAME Operatinf Systems - Modules

Parallel Programming: Background Information

Parallel Programming: Background Information

Interrupts Peter Rounce

This resource describes how to program the myrio in C to perform timer interrupts.

An Interrupt is either a Hardware generated CALL (externally derived from a hardware signal)

Implementing Mutual Exclusion. Sarah Diesburg Operating Systems CS 3430

Analysis of User Level Device Driver usability in embedded application

Device I/O Programming

20-EECE-4029 Operating Systems Fall, 2015 John Franco

Character Device Drivers One Module - Multiple Devices

Homework / Exam. Return and Review Exam #1 Reading. Machine Projects. Labs. S&S Extracts , PIC Data Sheet. Start on mp3 (Due Class 19)

Interrupts Peter Rounce - room 6.18

Concurrent programming: Introduction I

The Process Abstraction. CMPU 334 Operating Systems Jason Waterman

Homework. Reading. Machine Projects. Labs. Intel 8254 Programmable Interval Timer (PIT) Data Sheet. Continue on MP3

CprE 288 Spring 2014 Homework 5 Due Fri. Feb. 21

CS 453: Operating Systems Programming Project 5 (100 points) Linux Device Driver

Programming Languages

Overhead Evaluation about Kprobes and Djprobe (Direct Jump Probe)

Stanford University Computer Science Department CS 295 midterm. May 14, (45 points) (30 points) total

C Language Programming

Review: Hardware user/kernel boundary

CSE 451 Midterm 1. Name:

Module 11: I/O Systems

Synchronization. CS61, Lecture 18. Prof. Stephen Chong November 3, 2011

CS 550 Operating Systems Spring Interrupt

Prof. Dr. Hasan Hüseyin

Real-Time Performance of Linux. OS Latency

Building Ethernet Drivers on RTLinux-GPL 1

Lecture 13 Condition Variables

[537] Locks. Tyler Harter

MaRTE OS Misc utilities

Last Class: CPU Scheduling! Adjusting Priorities in MLFQ!

Signals. POSIX defines a variety of signal types, each for a particular

RCU. ò Walk through two system calls in some detail. ò Open and read. ò Too much code to cover all FS system calls. ò 3 Cases for a dentry:

Processes. Johan Montelius KTH

I/O Systems. Amir H. Payberah. Amirkabir University of Technology (Tehran Polytechnic)

VFS, Continued. Don Porter CSE 506

The control of I/O devices is a major concern for OS designers

A process. the stack

Section 3: File I/O, JSON, Generics. Meghan Cowan

Transcription:

Overview 1 2 3 Installation of an interrupt handler Interface /proc 4 5 6 7

primitive devices can be managed only with I/O regions, most devices require a more complicated approach, devices cooperate with the environment: disk rotates, data is sent to remote locations, tape is moved to the desired location, processor can not wait for slow devices, use interrupts.

interrupt is a signal, triggered by hardware, when the processor needs attention, Linux handles interrupts the same as signals (user space), driver only registers an interrupt handler, the example code will talk with a parallel interface, extension of module short.

Installation of an interrupt handler Interface /proc The parallel interface sends an interrupt when the electrical signal changes from low-high on the pin 10 (ACK bit), this is done by the printer when requesting data, interrupts are generated only when the bit 4 is on at the port 2, short makes the call outb at 0x37a, interrupt is triggered when the device changes pin 10: from low to high state, this can be done by connecting pins 9 and 10, a piece of wire can be used, can be connected to the printer.

Installation of an interrupt handler Installation of an interrupt handler Interface /proc hardware generates interrupts, we need a program handler, the handler responds to interrupts, without the handler kernel only accepts interruptions, module requires interrup channel or IRQ - Interrupt ReQuest.

Installation of an interrupt handler Installation of an interrupt handler Interface /proc <linux/interrupt.h> int request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *), unsigned long flags,const char *dev_name, void *dev_id); void free_irq(unsigned int irq, void *dev_id); request irq registers the handler, free irq frees the handler,

Installation of an interrupt handler Installation of an interrupt handler Interface /proc unsigned int irq number of requested interrupt, irqreturn t (*handler)(int, void *, struct pt regs *) pointer to interrupt function, unsigned long flags bit mask, that chooses options, const char *dev name string, written to /proc/interrupts (owner), void *dev id pointer to shared interrupt lines.

Installation of an interrupt handler Installation of an interrupt handler Interface /proc SA INTERRUPT fast handler, interrupts are masked, SA SHIRQ interrupt can be shared between devices, SA SAMPLE RANDOM used to increase entropy for /dev/random and /dev/urandom.

Installation of an interrupt handler Installation of an interrupt handler Interface /proc if (short_irq >= 0) { result = request_irq(short_irq, short_interrupt, SA_INTERRUPT, "short", NULL); if (result) { printk(kern_info "short: can t get assigned irq %i\n", short_irq); short_irq = -1; } else { /* pišemo na 4. bit drugih vrat */ outb(0x10,short_base+2); } } driver handler for short, the handler is fast type, does not support interrupts, does not increase entropy.

Interface /proc Installation of an interrupt handler Interface /proc root@montalcino:/bike/corbet/write/ldd3/src/short# m /proc/interrupts CPU0 CPU1 0: 4848108 34 IO-APIC-edge timer 2: 0 0 XT-PIC cascade 8: 3 1 IO-APIC-edge rtc 10: 4335 1 IO-APIC-level aic7xxx 11: 8903 0 IO-APIC-level uhci_hcd 12: 49 1 IO-APIC-edge i8042 NMI: 0 0 LOC: 4848187 4848186 ERR: 0 MIS: 0 output to /proc/interrupts, two processors, columns: 1 interrupt number. 2 number of interrupts for CPU0. 3 number of interrupts for CPU1. 4 programmable interrupt controller (not interresting).

Interface /proc Installation of an interrupt handler Interface /proc more /proc/stat cpu 12767861 277112 3399214 145240432 657031 15929 150065 0 0 cpu0 6295455 34237 1425503 69413239 550892 14165 7462 0 0 cpu1 6472406 242874 1973710 75827193 106139 1764 142602 0 0 intr 645970816 2633 126790 0 0 3 0 0 0 1 0 0... ctxt 2162516636 btime 1331725015 processes 79217 procs_running 2 procs_blocked 0 softirq 730115300 0 311183802 2953860 4968292 3034293 0 898854 103466656 23267 303586276 intr 5167833 5154006 2 0 2 4907 0 2 68 4 0 4406 9291 50 0 0 interrupt statistics.

can not transfer data to/from the user space, should not be put to sleep (call event wait), memory can only be allocated with GFP ATOMIC, can not run schedule, Purpose of the handler: send information to device, reading from device, writing to the device,

execution time is critical, if it takes longer, use: tasklet, workqueue, the execution will be executed at an appropriate time,

- SHORT irqreturn_t short_interrupt(int irq, void *dev_id, struct pt_regs *regs) { struct timeval tv; int written; do_gettimeofday(&tv); /* Write a 16 byte record. Assume PAGE_SIZE is a multiple of 16 */ written = sprintf((char *)short_head,"%08u.%06u\n", (int)(tv.tv_sec % 100000000), (int)(tv.tv_usec)); BUG_ON(written!= 16); short_incr_bp(&short_head, written); wake_up_interruptible(&short_queue); /* awake any reading process */ return IRQ_HANDLED; }

call function to gettimeofday, displays the current time in a circular buffer, wakes up all sleeping processes (data are coming), represents a typical interrupt handler task. calls function short incr bp:

static inline void short_incr_bp(volatile unsigned long *index, int delta) { unsigned long new = *index + delta; barrier( ); /* Don t optimize these two together */ *index = (new >= (short_buffer + PAGE_SIZE))? short_buffer : new; } pointer is wrapped in a circular buffer, never uses the wrong location (checks), uses a barrier (to prevent optimization),

, no barrier compiler could optimize code: new = *index, for a moment could be a wrong value in index, the other thread could use the wrong value. now we can use the circular buffer without locking.

device file for reading the described buffer is /dev/shortint, it is not described in the previous chapter, a special file showing the use of interrupts, writing to a file triggers an interrupt for each other byte, reading shows when an interrupt occurred,

connect pins 9 and 10, we can set the most important bit (high bit) of the parallel data port, write data to /dev/short0 or /dev/shortint,

ssize_t short_i_read (struct file *filp, char user *buf, size_t count, loff_t *f_pos) { int count0; DEFINE_WAIT(wait); while (short_head = = short_tail) { prepare_to_wait(&short_queue, &wait, TASK_INTERRUPTIBLE); if (short_head = = short_tail) schedule( ); finish_wait(&short_queue, &wait); if (signal_pending (current)) /* a signal arrived */ return -ERESTARTSYS; /* tell the fs layer to handle it */ } /* count0 is the number of readable data bytes */ count0 = short_head - short_tail; if (count0 < 0) /* wrapped */ count0 = short_buffer + PAGE_SIZE - short_tail; if (count0 < count) count = count0; if (copy_to_user(buf, (char *)short_tail, count)) return -EFAULT; short_incr_bp (&short_tail, count); return count; }

ssize_t short_i_write (struct file *filp, const char user *buf, size_t count, loff_t *f_pos) { int written = 0, odd = *f_pos & 1; unsigned long port = short_base; /* output to the parallel data latch */ void *address = (void *) short_base; if (use_mem) { while (written < count) iowrite8(0xff * ((++written + odd) & 1), address); } else { while (written < count) outb(0xff * ((++written + odd) & 1), port); } *f_pos += count; return written; }

/dev/shortprint allows you to talk to the printer, slightly modified example described, it is not necessary to connect the pins 9 and 10, writing uses a buffer to store data for printing, reading gets the time the printer needs to read one character.

Often handlers must perform long-lasting operations, handlers must end as soon as possible (other interruptions are blocked), these two requests are exclusive. Linux solves this problem by dividing the handler into two parts.

Division in two parts two halves, not only Linux, top half: routine that is actually called at the interrupt, this is registered with function request irq, bottom half: routine that is scheduled by first routine (put into queue), it is executed at an appropriate time, interrupts are not masked at bottom half,

Division in two parts typical scenario for the top half: the top half saves the data from the device to the buffer, allocates its lower half to later implementation, top half ends, this happens very fast.

Division in two parts typical scenario for the bottom half: it is executed when the time is right, enabled interrupts, performs all necessary work: wakes up sleeping processes, runs other I/O operations,...

Division in two parts almost every handler is such, example of a network driver: network interface logs a new packet, the handler only retrieves the data, moves them to protocol layer, the processing is done in the bottom half, is carried out at an appropriate time, a new packet might come in the middle.

Division in two parts Linux has two mechanisms: tasklets: fast, still need atomic code, mostly used, workqueues: code can be put to sleep, slower execution

Tasklets special features, run in the context of interrupts, running in reasonable time = system-determined safe time, tasklet can be triggered several times, it will only be executed once, tasklet is never executed in parallel with itself, tasklets can be run in parallel with other tasklets (on multiple processors).

Tasklets tasklet is executed on the same CPU as the handler, never in parallel,

Tasklets DECLARE_TASKLET(name, function, data); declare tasklets, name tasklet name, function function, called by (tasklet), data unsigned long function parameter, example in short: void short_do_tasklet(unsigned long); DECLARE_TASKLET(short_tasklet, short_do_tasklet, 0);

Tasklets irqreturn_t short_tl_interrupt(int irq, void *dev_id, struct pt_regs *regs) { do_gettimeofday((struct timeval *) tv_head); /* cast to stop volatile warning */ short_incr_tv(&tv_head); tasklet_schedule(&short_tasklet); short_wq_count++; /* record that an interrupt arrived */ return IRQ_HANDLED; } this handler is used if we start short with the parameter tasklet = 1, a second handler is installed, tasklet schedule - this function is used when scheduling tasklets, tasklet routine short do tasklet is executed when the system wants it,

Tasklets void short_do_tasklet (unsigned long unused) { int savecount = short_wq_count, written; short_wq_count = 0; /* we have already been removed from the queue */ /* * The bottom half reads the tv array, filled by the top half, * and prints it to the circular text buffer, which is then consumed * by reading processes */ /* First write the number of interrupts that occurred before this bh */ written = sprintf((char *)short_head,"bh after %6i\n",savecount); short_incr_bp(&short_head, written); /* * Then, write the time values. Write exactly 16 bytes at a time, * so it aligns with PAGE_SIZE */ do { written = sprintf((char *)short_head,"%08u.%06u\n", (int)(tv_tail->tv_sec % 100000000), (int)(tv_tail->tv_usec)); short_incr_bp(&short_head, written); short_incr_tv(&tv_tail); } while (tv_tail!= tv_head); wake_up_interruptible(&short_queue); /* awake any reading process */ }

workqueues call the function, special context worker process, functions can sleep, we can not copy the data to/from the user space, except in special ways (it does not matter for us),

static struct work_struct short_wq; /* this line is in short_init( ) */ INIT_WORK(&short_wq, (void (*)(void *)) short_do_tasklet, NULL); use the driver with parameter wq = 1, work struct this structure is used for workqueues.

irqreturn_t short_wq_interrupt(int irq, void *dev_id, struct pt_regs *regs) { /* Grab the current time information. */ do_gettimeofday((struct timeval *) tv_head); short_incr_tv(&tv_head); /* Queue the bh. Don t worry about multiple enqueueing */ schedule_work(&short_wq); short_wq_count++; /* record that an interrupt arrived */ return IRQ_HANDLED; } new handler, similar to tasklet, calls schedule work for scheduling lower part.