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



Similar documents
Kernel Synchronization and Interrupt Handling

Linux Driver Devices. Why, When, Which, How?

Red Hat Linux Internals

An Implementation Of Multiprocessor Linux

Common clock framework: how to use it

SYSTEM ecos Embedded Configurable Operating System

Mouse Drivers. Alan Cox.

Linux Process Scheduling Policy

Linux Kernel Networking. Raoul Rivas

Chapter 3: Operating-System Structures. System Components Operating System Services System Calls System Programs System Structure Virtual Machines

Department of Electrical Engineering and Computer Science MASSACHUSETTS INSTITUTE OF TECHNOLOGY Operating System Engineering: Fall 2005

Keil C51 Cross Compiler

Embedded Programming in C/C++: Lesson-1: Programming Elements and Programming in C

Have both hardware and software. Want to hide the details from the programmer (user).

First-class User Level Threads

Computer Systems II. Unix system calls. fork( ) wait( ) exit( ) How To Create New Processes? Creating and Executing Processes

Code Injection From the Hypervisor: Removing the need for in-guest agents. Matt Conover & Tzi-cker Chiueh Core Research Group, Symantec Research Labs

W4118 Operating Systems. Junfeng Yang

Linux Firewall Lab. 1 Overview. 2 Lab Tasks. 2.1 Task 1: Firewall Policies. Laboratory for Computer Security Education 1

COS 318: Operating Systems. I/O Device and Drivers. Input and Output. Definitions and General Method. Revisit Hardware

White Paper. Real-time Capabilities for Linux SGI REACT Real-Time for Linux

KVM: A Hypervisor for All Seasons. Avi Kivity avi@qumranet.com

CSE 120 Principles of Operating Systems. Modules, Interfaces, Structure

Fastboot Techniques for x86 Architectures. Marcus Bortel Field Application Engineer QNX Software Systems

How do Users and Processes interact with the Operating System? Services for Processes. OS Structure with Services. Services for the OS Itself

Introduction. What is an Operating System?

Downloading <Jumping PRO> from Page 2

DRM Driver Development For Embedded Systems

Exception and Interrupt Handling in ARM

REAL TIME OPERATING SYSTEM PROGRAMMING-II: II: Windows CE, OSEK and Real time Linux. Lesson-12: Real Time Linux

Chapter 6, The Operating System Machine Level

CS414 SP 2007 Assignment 1

Real-time KVM from the ground up

Jorix kernel: real-time scheduling

STUDY OF PERFORMANCE COUNTERS AND PROFILING TOOLS TO MONITOR PERFORMANCE OF APPLICATION

A Survey of Parallel Processing in Linux

I/O. Input/Output. Types of devices. Interface. Computer hardware

Operating Systems. Lecture 03. February 11, 2013

A Comparison of the Linux and Windows Device Driver Architectures

CSI 402 Lecture 13 (Unix Process Related System Calls) 13 1 / 17

Real-Time Systems Prof. Dr. Rajib Mall Department of Computer Science and Engineering Indian Institute of Technology, Kharagpur

Last Class: OS and Computer Architecture. Last Class: OS and Computer Architecture

I/O Device and Drivers

Lecture 5. User-Mode Linux. Jeff Dike. November 7, Operating Systems Practical. OSP Lecture 5, UML 1/33

Last Class: OS and Computer Architecture. Last Class: OS and Computer Architecture

1. Computer System Structure and Components

COS 318: Operating Systems

CS 377: Operating Systems. Outline. A review of what you ve learned, and how it applies to a real operating system. Lecture 25 - Linux Case Study

Network packet capture in Linux kernelspace

USB readout board for PEBS Performance test

Operating Systems. 12. Devices. Paul Krzyzanowski. Rutgers University. Spring /9/ Paul Krzyzanowski

Design and Implementation of the Heterogeneous Multikernel Operating System

Lecture 22: C Programming 4 Embedded Systems

Lesson Objectives. To provide a grand tour of the major operating systems components To provide coverage of basic computer system organization

Page 18. Using Software To Make More Money With Surveys. Visit us on the web at:

Lab 2 : Basic File Server. Introduction

Operating System Manual. Realtime Communication System for netx. Kernel API Function Reference.

CS161: Operating Systems

Review from last time. CS 537 Lecture 3 OS Structure. OS structure. What you should learn from this lecture

Thomas Fahrig Senior Developer Hypervisor Team. Hypervisor Architecture Terminology Goals Basics Details

Lecture 6: Interrupts. CSC 469H1F Fall 2006 Angela Demke Brown

GETTING STARTED WITH ANDROID DEVELOPMENT FOR EMBEDDED SYSTEMS

Computer-System Architecture

Configuring CoreNet Platform Cache (CPC) as SRAM For Use by Linux Applications

Operating System Components

Linux Load Balancing

Compiler Construction

Performance Comparison of RTOS

ReactOS is (not) Windows. Windows internals and why ReactOS couldn t just use a Linux kernel

3F6 - Software Engineering and Design. Handout 10 Distributed Systems I With Markup. Steve Young

Process Description and Control william stallings, maurizio pizzonia - sistemi operativi

6.828 Operating System Engineering: Fall Quiz II Solutions THIS IS AN OPEN BOOK, OPEN NOTES QUIZ.

Boolean Expressions, Conditions, Loops, and Enumerations. Precedence Rules (from highest to lowest priority)

CSE 544 Principles of Database Management Systems. Magdalena Balazinska Fall 2007 Lecture 5 - DBMS Architecture

UNIT 4 Software Development Flow

Chapter 13 Embedded Operating Systems

Embedded & Real-time Operating Systems

MPLAB Harmony System Service Libraries Help

10 Things Every Linux Programmer Should Know Linux Misconceptions in 30 Minutes

Kernel Optimizations for KVM. Rik van Riel Senior Software Engineer, Red Hat June

Xenomai: integration and qualification of a real time operating system ARMadeus Systems

EECS 678: Introduction to Operating Systems

Real Time Control Under UNIX for RCCL

Twitter and Notifications of Linux Server Events

Replication on Virtual Machines

Operating Systems Design 16. Networking: Sockets

Linux Scheduler. Linux Scheduler

Chapter 1 Computer System Overview

Agenda. Enterprise Application Performance Factors. Current form of Enterprise Applications. Factors to Application Performance.

Power Management in the Linux Kernel

Virtual Private Systems for FreeBSD

Process definition Concurrency Process status Process attributes PROCESES 1.3

Agenda. Context. System Power Management Issues. Power Capping Overview. Power capping participants. Recommendations

Static Code Analysis Procedures in the Development Cycle

Quality of Service su Linux: Passato Presente e Futuro

Sistemi Operativi. Lezione 25: JOS processes (ENVS) Corso: Sistemi Operativi Danilo Bruschi A.A. 2015/2016

Survey of Filesystems for Embedded Linux. Presented by Gene Sally CELF

Transcription:

Introduction to Linux Device Drivers Recreating Life One Driver At a Time Muli Ben-Yehuda mulix at mulix.org IBM Haifa Research Labs and Haifux - Haifa Linux Club Linux Device Drivers, Technion, Jan 2005 p.1/50

Why Write Linux Device Drivers? For fun, For profit (Linux is hot right now, especially embedded Linux), To scratch an itch. Because you can! OK, but why Linux drivers? Because the source is available. Because of the community s cooperation and involvement. Have I mentioned it s fun yet? Linux Device Drivers, Technion, Jan 2005 p.2/50

klife - Linux kernel game of life klife is a Linux kernel Game of Life implementation. It is a software device driver, developed specifically for this talk. The game of life is played on a square grid, where some of the cells are alive and the rest are dead. Each generation, based on each cell s neighbors, we mark the cell as alive or dead. With time, amazing patterns develop. The only reason to implement the game of life inside the kernel is for demonstration purposes. Software device drivers are very common on Unix systems and provide many services to the user. Think about /dev/null, /dev/zero, /dev/random, /dev/kmem... Linux Device Drivers, Technion, Jan 2005 p.3/50

Anatomy of a Device Driver A device driver has three sides: one side talks to the rest of the kernel, one talks to the hardware, and one talks to the user: User Kernel Device Driver Device File Hardware Linux Device Drivers, Technion, Jan 2005 p.4/50

Kernel Interface of a Device Driver In order to talk to the kernel, the driver registers with subsystems to respond to events. Such an event might be the opening of a file, a page fault, the plugging in of a new USB device, etc. Kernel Event List x File Open x Interrupt...... x x Page Fault Hotplug Device Driver Linux Device Drivers, Technion, Jan 2005 p.5/50

User Interface of a Device driver Since Linux follows the UNIX model, and in UNIX everything is a file, users talk with device drivers through device files. Device files are a mechanism, supplied by the kernel, precisely for this direct User-Driver interface. klife is a character device, and thus the user talks to it through a character device file. The other common kind of device file is a block device file. We will only discuss character device files today. Linux Device Drivers, Technion, Jan 2005 p.6/50

Anatomy of klife device driver The user talks with klife through the /dev/klife device file. When the user opens /dev/klife, the kernel calls klife s open routine When the user closes /dev/klife, the kernel calls klife s release routine When the user reads or writes from or to /dev/klife - you get the idea... klife talks to the kernel through its initialization function... and through register_chrdev... and through hooking into the timer interrupt We will elaborate on all of these later Linux Device Drivers, Technion, Jan 2005 p.7/50

Driver Initialization Code s t a t i c i n t i n i t k l i f e _ m o d u l e _ i n i t ( void ) { i n t r e t ; pr_debug ( " k l i f e module i n i t c a l l e d \ n " ) ; i f ( ( r e t = r e g i s t e r _ c h r d e v (KLIFE_MAJOR_NUM, " k l i f e ", & k l i f e _ f o p s p r i n t k (KERN_ERR " r e g i s t e r _ c h r d e v : %d \ n ", r e t ) ; } r e t u r n r e t ; Linux Device Drivers, Technion, Jan 2005 p.8/50

Driver Initialization One function (init) is called on the driver s initialization. One function (exit) is called when the driver is removed from the system. Question: what happens if the driver is compiled into the kernel, rather than as a module? The init function will register hooks that will get the driver s code called when the appropriate event happens. Question: what if the init function doesn t register any hooks? There are various hooks that can be registered: file operations, pci operations, USB operations, network operations - it all depends on what kind of device this is. Linux Device Drivers, Technion, Jan 2005 p.9/50

Registering Chardev Hooks s t r u c t f i l e _ o p e r a t i o n s k l i f e _ f o p s = {. owner = THIS_MODULE,. open = k l i f e _ o p e n,. release = k l i f e _ r e l e a s e,. read = k l i f e _ r e a d,. w r i t e = k l i f e _ w r i t e,.mmap = klife_mmap,. i o c t l = k l i f e _ i o c t l } ;... i f ( ( r e t = r e g i s t e r _ c h r d e v (KLIFE_MAJOR_NUM, " k l i f e ", & k l i f e _ f o p s ) ) < 0 ) p r i n t k (KERN_ERR " r e g i s t e r _ c h r d e v : %d \ n ", r e t ) ; Linux Device Drivers, Technion, Jan 2005 p.10/50

User Space Access to the Driver We saw that the driver registers a character device tied to a given major number, but how does the user create such a file? # mknod /dev/klife c 250 0 And how does the user open it? if ((kfd = open("/dev/klife", O_RDWR)) < 0) { perror("open /dev/klife"); exit(exit_failure); } And then what? Linux Device Drivers, Technion, Jan 2005 p.11/50

File Operations... and then you start talking to the device. klife uses the following device file operations: open for starting a game (allocating resources). release for finishing a game (releasing resources). write for initializing the game (setting the starting positions on the grid). read for generating and then reading the next state of the game s grid. ioctl for querying the current generation number, and for enabling or disabling hooking into the timer interrupt (more on this later). mmap for potentially faster but more complex direct access to the game s grid. Linux Device Drivers, Technion, Jan 2005 p.12/50

The open and release Routines open and release are where you perform any setup not done in initialization time and any cleanup not done in module unload time. Linux Device Drivers, Technion, Jan 2005 p.13/50

klife_open klife s open routine allocates the klife structure which holds all of the state for this game (the grid, starting positions, current generation, etc). s t a t i c i n t k l i f e _ o p e n ( s t r u c t inode inode, s t r u c t f i l e f i l p ) { s t r u c t k l i f e k ; i n t r e t ; r e t = a l l o c _ k l i f e (&k ) ; i f ( r e t ) r e t u r n r e t ; f i l p >p r i v a t e _ d a t a = k ; } r e t u r n 0 ; Linux Device Drivers, Technion, Jan 2005 p.14/50

klife_open - alloc_klife s t a t i c i n t a l l o c _ k l i f e ( s t r u c t k l i f e pk ) { i n t r e t ; s t r u c t k l i f e k ; k = kmalloc ( s i z e o f ( k ), GFP_KERNEL ) ; i f (! k ) r e t u r n ENOMEM; r e t = i n i t _ k l i f e ( k ) ; i f ( r e t ) { k f r e e ( k ) ; k = NULL ; } } pk = k ; r e t u r n r e t ; Linux Device Drivers, Technion, Jan 2005 p.15/50

klife_open - init_klife s t a t i c i n t i n i t _ k l i f e ( s t r u c t k l i f e k ) { i n t r e t ; memset ( k, 0, s i z e o f ( k ) ) ; s p i n _ l o c k _ i n i t (&k >lock ) ; r e t = ENOMEM; / one page to be exported to userspace / k >g r i d = ( void ) get_zeroed_page (GFP_KERNEL ) ; i f (! k >g r i d ) goto done ; k >tmpgrid = kmalloc ( s i z e o f ( k >tmpgrid ), GFP_KERNEL ) ; i f (! k >tmpgrid ) goto f r e e _ g r i d ; Linux Device Drivers, Technion, Jan 2005 p.16/50

klife_open - init_klife cont k >timer_hook. func = k l i f e _ t i m e r _ i r q _ h a n d l e r ; k >timer_hook. data = k ; r e t u r n 0 ; f r e e _ g r i d : free_page ( ( unsigned long ) k >g r i d ) ; done : r e t u r n r e t ; } Linux Device Drivers, Technion, Jan 2005 p.17/50

klife_release klife s release routine frees the resource allocated during open time. s t a t i c i n t k l i f e _ r e l e a s e ( s t r u c t inode inode, s t r u c t f i l e f i l p ) { s t r u c t k l i f e k = f i l p >p r i v a t e _ d a t a ; i f ( k >t i m e r ) k l i f e _ t i m e r _ u n r e g i s t e r ( k ) ; i f ( k >mapped ) { / undo s e t t i n g the g r i d page to be reserved / ClearPageReserved ( v i r t _ t o _ p a g e ( k >g r i d ) ) ; } f r e e _ k l i f e ( k ) ; r e t u r n 0 ; } Linux Device Drivers, Technion, Jan 2005 p.18/50

Commentary on open and release Beware of races if you have any global data... many a driver author stumble on this point. Note also that release can fail, but almost no one checks errors from close(), so it s better if it doesn t... Question: what happens if the userspace program crashes while holding your device file open? Linux Device Drivers, Technion, Jan 2005 p.19/50

write For klife, I hijacked write to mean please initialize the grid to these starting positions. There are no hard and fast rules to what write has to mean, but it s good to KISS (Keep It Simple, Silly...) Linux Device Drivers, Technion, Jan 2005 p.20/50

klife_write - 1 s t a t i c s s i z e _ t k l i f e _ w r i t e ( s t r u c t f i l e f i l p, const char user ubuf, s i z e _ t count, l o f f _ t f_pos ) { s i z e _ t sz ; char kbuf ; s t r u c t k l i f e k = f i l p >p r i v a t e _ d a t a ; s s i z e _ t r e t ; sz = count > PAGE_SIZE? PAGE_SIZE : count ; kbuf = kmalloc ( sz, GFP_KERNEL ) ; i f (! kbuf ) r e t u r n ENOMEM; Not trusting users: checking the size of the user s buffer Linux Device Drivers, Technion, Jan 2005 p.21/50

klife_write - 2 r e t = EFAULT ; i f ( copy_from_user ( kbuf, ubuf, sz ) ) goto f r e e _ b u f ; r e t = k l i f e _ a d d _ p o s i t i o n ( k, kbuf, sz ) ; i f ( r e t = = 0 ) r e t = sz ; f r e e _ b u f : k f r e e ( kbuf ) ; r e t u r n r e t ; } Use copy_from_user in case the user is passing a bad pointer. Linux Device Drivers, Technion, Jan 2005 p.22/50

Commentary on write Note that even for such a simple function, care must be exercised when dealing with untrusted users. Users are always untrusted. Always be prepared to handle errors! Linux Device Drivers, Technion, Jan 2005 p.23/50

read For klife, read means please calculate and give me the next generation. The bulk of the work is done in two other routines: klife_next_generation calculates the next generation based on the current one, according to the rules of the game of life. klife_draw takes a grid and draws it as a single string in a page of memory. Linux Device Drivers, Technion, Jan 2005 p.24/50

klife_read - 1 s t a t i c s s i z e _ t k l i f e _ r e a d ( s t r u c t f i l e f i l p, char ubuf, s i z e _ t count, l o f f _ t f_pos ) { s t r u c t k l i f e k l i f e ; char page ; s s i z e _ t len ; s s i z e _ t r e t ; unsigned long f l a g s ; k l i f e = f i l p >p r i v a t e _ d a t a ; / s p e c i a l handling f o r mmap / i f ( k l i f e >mapped ) r e t u r n klife_read_mapped ( f i l p, ubuf, count, f_pos ) ; i f (! ( page = kmalloc (PAGE_SIZE, GFP_KERNEL ) ) ) r e t u r n ENOMEM; Linux Device Drivers, Technion, Jan 2005 p.25/50

klife_read - 2 s p i n _ l o c k _ i r q s a v e (& k l i f e >lock, f l a g s ) ; k l i f e _ n e x t _ g e n e r a t i o n ( k l i f e ) ; len = k l i f e _ d r a w ( k l i f e, page ) ; s p i n _ u n l o c k _ i r q r e s t o r e (& k l i f e >lock, f l a g s ) ; i f ( len < 0 ) { r e t = len ; goto free_page ; } / len can t be negative / len = min ( count, ( s i z e _ t ) len ) ; Note that the lock is held for the shortest possible time. We will see later what the lock protects us against. Linux Device Drivers, Technion, Jan 2005 p.26/50

klife_read - 3 i f ( copy_to_user ( ubuf, page, len ) ) { r e t = EFAULT ; goto free_page ; } f_pos + = len ; r e t = len ; free_page : k f r e e ( page ) ; r e t u r n r e t ; } copy_to_user in case the user is passing us a bad page. Linux Device Drivers, Technion, Jan 2005 p.27/50

klife_read - 4 s t a t i c s s i z e _ t klife_read_mapped ( s t r u c t f i l e f i l p, char ubuf, s i z e _ t count, l o f f _ t f_pos ) { s t r u c t k l i f e k l i f e ; unsigned long f l a g s ; k l i f e = f i l p >p r i v a t e _ d a t a ; s p i n _ l o c k _ i r q s a v e (& k l i f e >lock, f l a g s ) ; k l i f e _ n e x t _ g e n e r a t i o n ( k l i f e ) ; s p i n _ u n l o c k _ i r q r e s t o r e (& k l i f e >lock, f l a g s ) ; } r e t u r n 0 ; Again, mind the short lock holding time. Linux Device Drivers, Technion, Jan 2005 p.28/50

Commentary on read There s plenty of room for optimization in this code... can you see where? Linux Device Drivers, Technion, Jan 2005 p.29/50

ioctl ioctl is a special access mechanism, for operations that do not cleanly map anywhere else. It is considered extremely bad taste to use ioctls in Linux where not absolutely necessary. New drivers should use either sysfs (a /proc -like virtual file system) or a driver specific file system (you can write a Linux file system in less than a 100 lines of code). In klife, we use ioctl to get the current generation number, for demonstration purposes only... Linux Device Drivers, Technion, Jan 2005 p.30/50

klife_ioctl - 1 s t a t i c i n t k l i f e _ i o c t l ( s t r u c t inode inode, s t r u c t f i l e f i l e, unsigned i n t cmd, unsigned long data ) { s t r u c t k l i f e k l i f e = f i l e >p r i v a t e _ d a t a ; unsigned long gen ; i n t enable ; i n t r e t ; unsigned long f l a g s ; r e t = 0 ; switch ( cmd ) { case KLIFE_GET_GENERATION : s p i n _ l o c k _ i r q s a v e (& k l i f e >lock, f l a g s ) ; gen = k l i f e >gen ; s p i n _ u n l o c k _ i r q r e s t o r e (& k l i f e >lock, f l a g s ) ; i f ( copy_to_user ( ( void ) data, & gen, s i z e o f ( gen ) ) ) { r e t = EFAULT ; goto done ; } Linux Device Drivers, Technion, Jan 2005 p.31/50

klife_ioctl - 2 done : } break ; case KLIFE_SET_TIMER_MODE : i f ( copy_from_user (& enable, ( void ) data, s i z e o f ( enable ) ) r e t = EFAULT ; goto done ; } pr_debug ( " user request to %s t i m e r mode \ n ", enable? " enable " : " d i s a b l e " ) ; i f ( k l i f e >t i m e r & &! enable ) k l i f e _ t i m e r _ u n r e g i s t e r ( k l i f e ) ; else i f (! k l i f e >t i m e r && enable ) k l i f e _ t i m e r _ r e g i s t e r ( k l i f e ) ; break ; } r e t u r n r e t ; Linux Device Drivers, Technion, Jan 2005 p.32/50

memory mapping The read-write mechanism, previously described, involves an overhead of a system call and related context switching and of memory copying. mmap maps pages of a file into memory, thus enabling programs to directly access the memory directly and save the overhead,... but: fast synchronization between kernel space and user space is a pain (why do we need it?), and Linux read and write are really quite fast. mmap is implemented in klife for demonstration purposes, with read() calls used for synchronization and triggering a generation update. Linux Device Drivers, Technion, Jan 2005 p.33/50

klife_mmap... SetPageReserved ( v i r t _ t o _ p a g e ( k l i f e >g r i d ) ) ; r e t = remap_pfn_range (vma, vma >vm_start, v i r t _ t o _ p h y s ( k l i f e >g r i d ) > > PAGE_SHIFT, PAGE_SIZE, vma >vm_page_prot ) ; pr_debug ( " io_remap_page_range returned %d \ n ", r e t ) ; i f ( r e t = = 0 ) k l i f e >mapped = 1 ; } r e t u r n r e t ; Linux Device Drivers, Technion, Jan 2005 p.34/50

klife Interrupt Handler What if we want a new generation on every raised interrupt? Since we don t have a hardware device to raise interrupts for us, let s hook into the one hardware every PC has - the clock - and steal its interrupt! Linux Device Drivers, Technion, Jan 2005 p.35/50

Usual Request For an Interrupt Handler Usually, interrupts are requested using request_irq(): / claim our i r q / rc = ENODEV; i f ( r e q u e s t _ i r q ( card >i r q, & t r i d e n t _ i n t e r r u p t, SA_SHIRQ, card_names [ p c i _ i d >d r i v e r _ d a t a ], card ) ) { p r i n t k (KERN_ERR " t r i d e n t : unable to a l l o c a t e i r q %d \ n ", card >i r q ) ; goto out_proc_fs ; } Linux Device Drivers, Technion, Jan 2005 p.36/50

klife Interrupt Handler It is impossible to request the timer interrupt. Instead, we will directly modify the kernel code to call our interrupt handler, if it s registered. We can do this, because the code is open... Linux Device Drivers, Technion, Jan 2005 p.37/50

Aren t Timers Good Enough For You? Does every driver which wishes to get periodic notifications need to hook the timer interrupt? - Nope. Linux provides an excellent timer mechanism which can be used for periodic notifications. The reason for hooking into the timer interrupt in klife is because we wish to be called from hard interrupt context, also known as top half context...... whereas timer functions are called in softirq bottom half context. Why insist on getting called from hard interrupt context? So we can demonstrate deferring work. Linux Device Drivers, Technion, Jan 2005 p.38/50

The Timer Interrupt Hook Patch The patch adds a hook which a driver can register for, to be called directly from the timer interrupt handler. It also creates two functions: register_timer_interrupt unregister_timer_interrupt Linux Device Drivers, Technion, Jan 2005 p.39/50

ook Into The Timer Interrupt Routine 1 + marks the lines added to the kernel. + s t r u c t t i m e r _ i n t e r r u p t _ h o o k t i m e r _ i n t e r r u p t _ h o o k ; + + s t a t i c void call_timer_hook ( s t r u c t pt_regs regs ) +{ + s t r u c t t i m e r _ i n t e r r u p t _ h o o k hook = t i m e r _ i n t e r r u p t _ h o o k ; + + i f ( hook && hook >func ) + hook >func ( hook >data ) ; +} @@ 851,6 +862,8 @@ void do_timer ( s t r u c t pt_regs regs ) update_process_times ( user_mode ( regs ) ) ; # e n d i f update_times ( ) ; + + call_timer_hook ( regs ) ; } Linux Device Drivers, Technion, Jan 2005 p.40/50

ook Into The Timer Interrupt Routine 2 + i n t r e g i s t e r _ t i m e r _ i n t e r r u p t ( s t r u c t t i m e r _ i n t e r r u p t _ h o o k hook ) +{ + p r i n t k (KERN_INFO " r e g i s t e r i n g a t i m e r i n t e r r u p t hook %p " + " ( func %p, data %p ) \ n ", hook, hook >func, + hook >data ) ; + + xchg(& timer_hook, hook ) ; + r e t u r n 0 ; +} + +void u n r e g i s t e r _ t i m e r _ i n t e r r u p t ( s t r u c t t i m e r _ i n t e r r u p t _ h o o k hook ) +{ + p r i n t k (KERN_INFO " u n r e g i s t e r i n g a t i m e r i n t e r r u p t hook \ n " ) ; + + xchg(& timer_hook, NULL ) ; +} Linux Device Drivers, Technion, Jan 2005 p.41/50

ommentary - The Timer Interrupt Hook Note that the register and unregister calls use xchg(), to ensure atomic replacement of the pointer to the handler. Why use xchg() rather than a lock? What context (hard interrupt, bottom half, process context) will we be called in? Which CPU s timer interrupts would we be called in? What happens on an SMP system? Linux Device Drivers, Technion, Jan 2005 p.42/50

Deferring Work You were supposed to learn in class about bottom halves, softirqs, tasklets and other such curse words. The timer interrupt (and every other interrupt) has to happen very quickly. Why? The interrupt handler (top half, hard irq) usually just sets a flag which says there is work to be done. The work is then deferred to a bottom half context, where it is done by an (old style) bottom half, softirq, or tasklet. For klife, we defer the work we wish to do (updating the grid) to a bottom half context by scheduling a tasklet. Linux Device Drivers, Technion, Jan 2005 p.43/50

Preparing The Tasklet DECLARE_TASKLET_DISABLED( k l i f e _ t a s k l e t, k l i f e _ t a s k l e t _ f u n c, 0 ) ; s t a t i c void k l i f e _ t i m e r _ r e g i s t e r ( s t r u c t k l i f e k l i f e ) { unsigned long f l a g s ; i n t r e t ; s p i n _ l o c k _ i r q s a v e (& k l i f e >lock, f l a g s ) ; / prime the t a s k l e t with the c o r r e c t data ours / t a s k l e t _ i n i t (& k l i f e _ t a s k l e t, k l i f e _ t a s k l e t _ f u n c, ( unsigned long ) k l i f e ) ; r e t = r e g i s t e r _ t i m e r _ i n t e r r u p t (& k l i f e >timer_hook ) ; i f (! r e t ) k l i f e >t i m e r = 1 ; s p i n _ u n l o c k _ i r q r e s t o r e (& k l i f e >lock, f l a g s ) ; pr_debug ( " r e g i s t e r _ t i m e r _ i n t e r r u p t returned %d \ n ", r e t ) ; } Linux Device Drivers, Technion, Jan 2005 p.44/50

The klife Tasklet Here s what our klife tasklet does: First, it derives the klife structure from the parameter it gets. Then, it locks it, to prevent concurrent access on another CPU. What are we protecting against? Then, it generates the new generation. What must we never do here? Hint: can tasklets block? Last, it releases the lock. Linux Device Drivers, Technion, Jan 2005 p.45/50

Deferring Work - The klife Tasklet s t a t i c void k l i f e _ t i m e r _ i r q _ h a n d l e r ( void data ) { s t r u c t k l i f e k l i f e = data ; } / 2 times a second / i f ( k l i f e >t i m e r _ i n v o c a t i o n ++ % (HZ / 2 ) = = 0 ) t a s k l e t _ s c h e d u l e (& k l i f e _ t a s k l e t ) ; s t a t i c void k l i f e _ t a s k l e t _ f u n c ( unsigned long data ) { s t r u c t k l i f e k l i f e = ( void ) data ; spin_lock (& k l i f e >lock ) ; k l i f e _ n e x t _ g e n e r a t i o n ( k l i f e ) ; spin_unlock (& k l i f e >lock ) ; } Linux Device Drivers, Technion, Jan 2005 p.46/50

Adding klife To The Build System Building the module in kernel 2.6 is a breeze. All that s required to add klife to the kernel s build system are these tiny patches: In drivers/char/kconfig: + c o n f i g GAME_OF_LIFE + t r i s t a t e " k e r n e l game of l i f e " + help + Kernel implementation of the Game of L i f e. in drivers/char/makefile +obj $ (CONFIG_GAME_OF_LIFE) + = k l i f e. o Linux Device Drivers, Technion, Jan 2005 p.47/50

Summary Writing Linux drivers is easy...... and fun! Most drivers do fairly simple things, which Linux provides APIs for. The real fun is when dealing with the hardware s quirks. It gets easier with practice...... but it never gets boring. Questions? Linux Device Drivers, Technion, Jan 2005 p.48/50

Where To Get Help google Community resources: web sites and mailing lists. Distributed documentation (books, articles, magazines) Use The Source, Luke! Your fellow kernel hackers. Linux Device Drivers, Technion, Jan 2005 p.49/50

Bibliography kernelnewbies - http://www.kernelnewbies.org linux-kernel mailing list archives - h t t p : / / marc. theaimsgroup. com/? l = l i n u x k e r n e l&w=2 Understanding the Linux Kernel, by Bovet and Cesati Linux Device Drivers, 3rd edition, by Rubini et. al. Linux Kernel Development, 2nd edition, by Robert Love /usr/src/linux-xxx/ Linux Device Drivers, Technion, Jan 2005 p.50/50