From owner-svn-src-user@FreeBSD.ORG Sun Oct 6 20:46:03 2013 Return-Path: Delivered-To: svn-src-user@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTP id 10B1EC3E; Sun, 6 Oct 2013 20:46:03 +0000 (UTC) (envelope-from glebius@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.freebsd.org (Postfix) with ESMTPS id F07842EA9; Sun, 6 Oct 2013 20:46:02 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.7/8.14.7) with ESMTP id r96Kk2bd093182; Sun, 6 Oct 2013 20:46:02 GMT (envelope-from glebius@svn.freebsd.org) Received: (from glebius@localhost) by svn.freebsd.org (8.14.7/8.14.5/Submit) id r96Kk1iS093157; Sun, 6 Oct 2013 20:46:01 GMT (envelope-from glebius@svn.freebsd.org) Message-Id: <201310062046.r96Kk1iS093157@svn.freebsd.org> From: Gleb Smirnoff Date: Sun, 6 Oct 2013 20:46:01 +0000 (UTC) To: src-committers@freebsd.org, svn-src-user@freebsd.org Subject: svn commit: r256093 - in user/glebius/course: . 02.entering_kernel 02.entering_kernel/syscall 02.entering_kernel/syscall/application 02.entering_kernel/syscall/module X-SVN-Group: user MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-user@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "SVN commit messages for the experimental " user" src tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 06 Oct 2013 20:46:03 -0000 Author: glebius Date: Sun Oct 6 20:46:01 2013 New Revision: 256093 URL: http://svnweb.freebsd.org/changeset/base/256093 Log: Lection that tries to embrace multitasking, context switching, privelege separation, entering and exiting kernel and ends in implementing a syscall. Added: user/glebius/course/02.entering_kernel/ user/glebius/course/02.entering_kernel/Makefile (contents, props changed) user/glebius/course/02.entering_kernel/lection.tex user/glebius/course/02.entering_kernel/syscall/ user/glebius/course/02.entering_kernel/syscall/Makefile (contents, props changed) user/glebius/course/02.entering_kernel/syscall/application/ user/glebius/course/02.entering_kernel/syscall/application/Makefile (contents, props changed) user/glebius/course/02.entering_kernel/syscall/application/call.c (contents, props changed) user/glebius/course/02.entering_kernel/syscall/module/ user/glebius/course/02.entering_kernel/syscall/module/Makefile (contents, props changed) user/glebius/course/02.entering_kernel/syscall/module/foo_syscall.c (contents, props changed) user/glebius/course/course.tex Added: user/glebius/course/02.entering_kernel/Makefile ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ user/glebius/course/02.entering_kernel/Makefile Sun Oct 6 20:46:01 2013 (r256093) @@ -0,0 +1,13 @@ +NAME?= lection + +TMP= $(NAME).aux $(NAME).log $(NAME).nav $(NAME).out $(NAME).snm \ + $(NAME).toc $(NAME).vrb + +.MAIN: $(NAME).pdf + +.SUFFIXES: .pdf .tex +.tex.pdf: + pdflatex -file-line-error -halt-on-error ${.IMPSRC} + +clean: + rm -f -- $(TMP) texput.log Added: user/glebius/course/02.entering_kernel/lection.tex ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ user/glebius/course/02.entering_kernel/lection.tex Sun Oct 6 20:46:01 2013 (r256093) @@ -0,0 +1,513 @@ +\documentclass{beamer} + +\usepackage[utf8]{inputenc} +\usepackage[russian]{babel} +\usepackage{tikz} +\usepackage{adjustbox} +\usepackage{url} +\usepackage{array} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{verbatim} + +\usetikzlibrary{positioning} +\usetikzlibrary{shapes.arrows} +\usetikzlibrary{decorations.pathmorphing} + +\input{../course.tex} + +\title{Entering and exiting the kernel: +interrupts, traps, system calls} + +\begin{document} + +\begin{frame} +\titlepage +\end{frame} + + +\begin{frame} +\frametitle<1>{CPU is a Turing maching} +\frametitle<2>{Interrupt} +\frametitle<3>{Saving entire context} +\begin{tikzpicture}[node distance=2mm, very thick] + \draw [anchor=north] (2, 0) node[name=cpu, draw, rounded corners=3mm, + minimum height=5cm, minimum width=4cm]{}; + \node [name=cputext, below=of cpu.north]{CPU}; + \node [name=ip, below=of cputext, draw, text width=3cm, align=center] + { instruction pointer (program counter) }; + \node [name=sp, below=of ip, draw, text width=3cm, align=center] + { stack pointer }; + \node [name=reg0, below=of sp.south west, anchor=north west, draw, + align=center, minimum width = 1.5 cm] + { reg0 }; + \node [name=reg1, below=of sp.south east, anchor=north east, draw, + align=center, minimum width = 1.5 cm] + { reg1 }; + \node [name=reg2, below=of reg0.south west, anchor=north west, draw, + align=center, minimum width = 1.5 cm] + { reg2 }; + \node [name=reg3, below=of reg1.south east, anchor=north east, draw, + align=center, minimum width = 1.5 cm] + { reg3 }; + + \draw [anchor=north] (8, 0) node[name=mem, draw, rounded corners=3mm, + minimum height=7cm, minimum width=7cm]{}; + \node [name=memtext, below=of mem.north]{Memory}; + + % Stack + \node [name=stack0, above right=1cm and 0.5cm of mem.west, draw, + outer sep=0pt, minimum height=1cm, minimum width=2cm] { }; + \node [name=stack1, node distance = 0mm, below=of stack0, draw, outer sep=0pt, + minimum height=1cm, minimum width=2cm] { 0 }; + \node [name=stack2, node distance = 0mm, below=of stack1, draw, outer sep=0pt, + minimum height=1cm, minimum width=2cm] { 2 }; + \node [name=stack3, node distance = 0mm, below=of stack2, draw, outer sep=0pt, + minimum height=1cm, minimum width=2cm] { 1 }; + \node [name=stacktext, node distance = 0mm, above=of stack0] { stack }; + \draw [loosely dashed] (stack0.north east) -- +(0,1); + \draw [loosely dashed] (stack0.north west) -- +(0,1); + \draw [loosely dashed] (stack3.south east) -- +(0,-1); + \draw [loosely dashed] (stack3.south west) -- +(0,-1); + + % Code + \node [name=code0, above left=1cm and 0.5cm of mem.east, draw, outer sep=0pt, + minimum height=1cm, minimum width=3cm] { and reg1,reg2 }; + \node [name=code1, node distance = 0mm, below=of code0, draw, outer sep=0pt, + minimum height=1cm, minimum width=3cm] { test reg1, 0xf }; + \node [name=code2, node distance = 0mm, below=of code1, draw, outer sep=0pt, + minimum height=1cm, minimum width=3cm] { jnz +0x10 }; + \draw [loosely dashed] (code0.north east) -- +(0,1); + \draw [loosely dashed] (code0.north west) -- +(0,1); + \draw [loosely dashed] (code2.south east) -- +(0,-1); + \draw [loosely dashed] (code2.south west) -- +(0,-1); + + \onslide<1> { + \note { + - CPU is like a Turing machine. + - Explain what IP or program counter means. + - Why pure TM doesn't represent what we want from a computer? + We don't want computer to endlessly run a calculation, we want + it to be interactive. User input should interrupt it. And not + only user input. + } + \draw [->] (sp.east) to [out=15, in=165] (stack1.west); + \draw [->] (ip.east) to [out=-15, in=165] (code0.west); + } + + \onslide<2> { + \note { + - So, interruption of computing is important. + - Interrupt should be transparent for current execution. How + can this be achieved? + } + \draw [->, dashed] (sp.east) to [out=15, in=165] (stack1.west); + \draw [->, dashed] (ip.east) to [out=-15, in=165] (code0.west); + \draw [->, color=red] (sp.east) to [out=15, in=165] (stack0.west); + \node [name=addr0, draw, circle, color=red, minimum width=5mm] + at (code0.west) {}; + \draw [->, color=red] (addr0.south west) to [out=200, in=300] + (stack0.center); + + % Intr + \node [name=intr0, node distance = 0mm, below=1cm of code2, draw, + outer sep=0pt, minimum height=1cm, minimum width=3cm] { push reg1 }; + \node [node distance=0, above=of intr0] { \footnotesize interrupt handler }; + \draw [->, color=red] (ip.east) to [out=30,in=165] (intr0.west); + } + + \onslide<3> { + \note { + - Saving entire context is important in some cases. + - And what if on return interrupt handler provides another context? + - Handling multiple contexts == multitasking. + } + \node [name=ctx, draw, circle, color=red, minimum width=4cm] + at (cpu.center) {}; + \draw [->, color=red] (ctx.north east) to [out=30, in=140] + (stacktext.north); + } +\end{tikzpicture} +\onslide<3> { + \srcref{sys/i386/i386/swtch.s, sys/amd64/amd64/cpu\_switch.S +} +} +\end{frame} + + +\begin{frame} +\frametitle{Interrupts} +\note { + - Let's see what kind of interrupts we got. +} +\begin{itemize} + \onslide<1->{ + \note { + - Okay, now we can do multitasking and interactivity. + } + \item{Hardware interrupt (asynchoronous, involuntary) + \begin{itemize} + \item I/O ready + \item I/O done + \item timer tick + \end{itemize} + } + } + \onslide<2->{ + \note { + - We can handle (and "fix") traps, and even implement paging. + } + \item{Trap (synchoronous, involuntary) + \begin{itemize} + \item page fault + \item general protection fault + \end{itemize} + } + } + \onslide<3->{ + \note { + - Via interrupts we can provide a library of functions, what + actually MS DOS did via INT 0x21. Actually many software of + the DOS era were setting a library on a particular interrupt. + } + \item{Software interrupt (synchoronous, voluntary)\\ + On x86 the ``int'' instruction + } + } +\end{itemize} +\end{frame} + + +\begin{frame} +\frametitle{Protection} +\note { + - What isn't enough for a true OS is protection of tasks against + each other. + - We need individual address space for each, and only a supervisor + (the kernel) that can set 'em up. + - We need to forbid certain priveleged instructions to anyone + except supervisor. + - This is what 80386 processor gave us. + - Now the library of functions lives in ring0, and is called + kernel. +} +\begin{tikzpicture}[very thick] + \node[name=ring3, draw, rounded corners=3mm, + minimum width=11cm, minimum height=3cm] {}; + \node[name=ring0, node distance=1.4cm, below=of ring3, draw, + rounded corners=3mm, minimum width=11cm, minimum height=3cm] {}; + \node[name=int, single arrow, node distance=2mm, anchor=north, + below right=1mm and 2 cm of ring3.south west, draw, + minimum width=4em, minimum height=3em, shape border rotate=270] + { int }; + \node[name=trap, single arrow, right=of int, draw, + minimum width=4em, minimum height=3em, shape border rotate=270] + { \emph{trap} }; + \node[name=iret, single arrow, node distance=2mm, anchor=north, + above left=1mm and 2 cm of ring0.north east, draw, + minimum width=4em, minimum height=3em, shape border rotate=90] + { iret }; + + \onslide<1>{ + \node at (ring3.center) { \LARGE{ring 3} }; + \node at (ring0.center) { \LARGE{ring 0} }; + } + + \onslide<2>{ + \node at (ring3.center) { \color{red}\LARGE{userland} }; + \node at (ring0.center) { \color{red}\LARGE{kernel} }; + } +\end{tikzpicture} +\end{frame} + + +\begin{frame} +\frametitle{System call} +\note { + - Let's make an agreement that certain software interrupt has an + ABI that would provide a gate into kernel. + - Using variety of syscall numbers we can implement all needed + services that kernel offers to userland. + - The int 0x80 is already a history. Modern hardware provide + special much more efficient instruction designed for syscall. + There also were "call gates". +} +\onslide<1->{ + \begin{beamercolorbox}[rounded=true,shadow=true,sep=0pt,ht=2.9cm]{trace} + Application + \begin{itemize} + \item Puts syscall number into a register + \item Puts arguments into registers or into memory + \item Triggers interrupt (i386: \emph{int 0x80}, amd64: \emph{syscall}) + \onslide<3->{ + \item Resumes execution, checks return value, reads data, etc. + } + \end{itemize} + \end{beamercolorbox} +} +\onslide<2->{ + \begin{beamercolorbox}[rounded=true,shadow=true,sep=0pt,ht=3.4cm]{trace} + Kernel + \begin{itemize} + \item Reads syscall number from a register + \item Reads arguments from registers or into memory + \item Does the processing + \item Puts return value into a register, copies data + \item Returns from interrupt (i386: \emph{iret}, amd64: \emph{sysret}) + \end{itemize} + \end{beamercolorbox} +} +\srcref{lib/libc/i386/sys/syscall.S, sys/i386/i386/trap.c, +lib/libc/amd64/sys/SYS.h, sys/amd64/amd64/trap.c} +\end{frame} + + +\begin{frame}[fragile] +\frametitle{System call example} +\note { + - Let's trace an application ping(8). It sends data to network, + so we expect it to use send(2). Our outbound interface is Ethernet, + so we expect ether_output() to be in action. + - Arm gdb & dtrace appropriately! + - Note that data is taken from dtrace and gdb, but order is + reversed! + - Note that we expected ICMP but got UDP on first send() due to + resolving, but that still works for us as an example! Also, it + demonstrates that library calls can use syscalls implicitly. + - Explain user stack and kernel stack. + - Let's trace recvfrom(), too. +} +\shellcmd{\# ping www.ru} +\begin{scriptsize} +\begin{onlyenv}<1> + \begin{beamercolorbox}[rounded=true,shadow=true,sep=0pt,ht=3.5cm]{trace} + \begin{verbatim} + #9 main () at ping.c:563 + #8 gethostbyname2 () from /lib/libc.so.7 + #7 gethostbyname_r () from /lib/libc.so.7 + #6 nsdispatch () from /lib/libc.so.7 + #5 __dns_getanswer () from /lib/libc.so.7 + #4 __res_nsearch () from /lib/libc.so.7 + #3 __res_nquerydomain () from /lib/libc.so.7 + #2 __res_nquery () from /lib/libc.so.7 + #1 __res_nsend () from /lib/libc.so.7 + #0 send () from /lib/libc.so.7 + \end{verbatim} + \end{beamercolorbox} + \begin{beamercolorbox}[rounded=true,shadow=true,sep=0pt,ht=3cm]{trace} + \begin{verbatim} + kernel`amd64_syscall+0x357 + kernel`sys_sendto+0x4d + kernel`sendit+0x116 + kernel`kern_sendit+0x224 + kernel`sosend_dgram+0x2f2 + kernel`udp_send+0x855 + kernel`ip_output+0xf0a + ether_output:entry + \end{verbatim} + \end{beamercolorbox} +\end{onlyenv} +\begin{onlyenv}<2> + \begin{beamercolorbox}[rounded=true,shadow=true,sep=0pt,ht=3.5cm]{trace} + \begin{verbatim} + #9 main (argc=, argv=0x0) at ping.c:563 + #8 gethostbyname2 () from /lib/libc.so.7 + #7 gethostbyname_r () from /lib/libc.so.7 + #6 nsdispatch () from /lib/libc.so.7 + #5 __dns_getanswer () from /lib/libc.so.7 + #4 __res_nsearch () from /lib/libc.so.7 + #3 __res_nquerydomain () from /lib/libc.so.7 + #2 __res_nquery () from /lib/libc.so.7 + #1 __res_nsend () from /lib/libc.so.7 + #0 recvfrom () from /lib/libc.so.7 + \end{verbatim} + \end{beamercolorbox} + \begin{beamercolorbox}[rounded=true,shadow=true,sep=0pt,ht=2cm]{trace} + \begin{verbatim} + kernel`amd64_syscall+0x357 + kernel`sys_recvfrom+0x86 + kernel`kern_recvit+0x22f + kernel`soreceive_dgram+0x45d + uiomove:entry + \end{verbatim} + \end{beamercolorbox} +\end{onlyenv} +\end{scriptsize} +\end{frame} + + +\begin{frame} +\frametitle{Hardware interrupts and system calls} +\note{ + - We can enter kernel from a hardware interrupt, or from + a software interrupt. The former is usually a driver entry, + and the latter is a syscall. + - Drivers can have pure interrupt handlers, but more often + have ISRs. + - Kernel is somewhat divided into two parts... Well, it is + really not. :) But some threads are always calling "down", + and some are calling "up". And they are tightly interconnected. + - They usually synchronise at a some data structure, a generic + buffer. +} +\begin{tikzpicture}[very thick] + \node[name=user, draw, rounded corners=3mm, + minimum width=11cm, minimum height=2cm] {}; + \node [name=usertext] at (user.center) + { \LARGE{userland} }; + \node [name=ping, right=of user.west, draw, rounded corners=1mm] + { ping }; + \node[name=kernel, node distance=2mm, below=of user, draw, + rounded corners=3mm, minimum width=11cm, minimum height=6cm] {}; + \draw [loosely dashed,decorate,decoration={snake,amplitude=0.25cm,segment length=2cm}] (kernel.west) -- (kernel.east); + \node [name=top, node distance=2mm, below right=of kernel.north] + { \LARGE{kernel (top half)} }; + \node [name=bottom, node distance=2mm, above right=of kernel.south] + { \LARGE{kernel (bottom half)} }; + \node [name=buf, left=of kernel.center, draw, fill=white, circle] + { buffer }; + \node [name=ether, above right=2mm and 1cm of kernel.south west, + draw, rounded corners=1mm] + { Ethernet driver }; + \draw [->] (ether.north) to [out=110, in=250] + node [midway, sloped, below] {\footnotesize interrupt} + (buf.south west); + \draw [->] (ping.south) to [out=250, in=110] + node [midway, sloped, above] {\footnotesize send()} + (buf.north west); + \draw [->] (ping.south) to [out=290, in=40] + node [midway, sloped, above] {\footnotesize recv()} + (buf.north east); + + \onslide<2>{ + \note{ + - A thread coming from userland can eventually reach the very + bottom of a driver. + - A thread coming from a driver can't pass kernel to userland + boundary. + } + \draw [->] (ping.south) to [out=230, in=120] + node [midway, sloped, below] {\footnotesize send()} + (ether.north west); + } + + \onslide<3>{ + \note{ + - An interrupt isn't necessarily related to some user task. + } + \node [name=timer, right=5mm of ether, draw, rounded corners=1mm] + { timer }; + \draw [->] (timer.north) .. controls +(-1cm,2cm) and +(1cm,2cm) .. + (timer.north); + } + + \onslide<4>{ + \note{ + - Let students think theirselves on possibility of such + upcall. Provide hints if needed. + } + \draw [color=red, ->] (bottom.north) to [out=140, in=270] + node[midway, sloped, above] {is that possible?} + (usertext.south west); + } +\end{tikzpicture} +\end{frame} + + +\begin{frame}[fragile] +\frametitle{Adding a system call in FreeBSD} +\note { + - It is simple. Let's go through the steps. + - Explain all fields. +} +\shellcmd{% +\# cd /usr/src/sys/kern\\ +\# vi syscalls.master\\ +} +\begin{beamercolorbox}[rounded=true,shadow=true,sep=0pt,ht=3.2cm]{editor} +\scriptsize \begin{verbatim} +541 AUE_ACCEPT STD { int accept4(int s, \ + struct sockaddr * __restrict name, \ + __socklen_t * __restrict anamelen, \ + int flags); } +542 AUE_PIPE STD { int pipe2(int *fildes, int flags); } +543 AUE_NULL NOSTD { int aio_mlock(struct aiocb *aiocbp); } +544 AUE_NULL STD { int procctl(idtype_t idtype, id_t id, \ + int com, void *data); } +545 AUE_NULL NOSTD { int foobar(int foo, void *bar +\end{verbatim} +\end{beamercolorbox} +\shellcmd{% +\# make sysent\\ +\# cd ../..\\ +\# make buildkernel installkernel +} +\onslide<2->{ + \color{red}{ + I forgot to implement the sys\_foobar() function. + } +} +\end{frame} + + +\begin{frame} +\frametitle{syscall ABI} +\note { + - What actually 'make sysent' does: + - /usr/include/sys/syscall.h + - /usr/include/sys/sysproto.h + - ABI is a convention on how arguments are passed between userland + and kernel. + - A table of syscalls. + - What if provide multiple ABIs? Yep, and that's the case. + - Emphasize that Linux ABI isn't an emulator, but a compatibility + layer, very much like freebsd32 layer. The open(2) is special. +} +\emph{make sysent} generates: +\begin{itemize} + \item /usr/include/sys/syscall.h (for userland) + \item /usr/include/sys/sysproto.h (for kernel) +\end{itemize} + +\onslide<2-> { + There are many of them: + \begin{itemize} + \item sys/kern/syscalls.master + \item sys/compat/freebsd32/syscalls.master + \item sys/i386/linux/syscalls.master + \item sys/amd64/linux32/syscalls.master + \color{Agrey}{ + \item sys/compat/svr4/syscalls.master + \item sys/i386/ibcs2/syscalls.master + } + \end{itemize} +} +\end{frame} + + +\begin{frame}[fragile] +\frametitle{Adding a system call in FreeBSD (dynamic way)} +\note{ +} +\begin{itemize} + \begin{item}Kernel side + \begin{itemize} + \item \Man{SYSCALL\_MODULE}{9} + \item \Man{module}{9} + \end{itemize} + \end{item} + \begin{item}Application side + \begin{itemize} + \item \Man{modstat}{2} + \item \Man{syscall}{2} + \end{itemize} + \end{item} +\end{itemize} +\shellcmd{% +\# svn co http://svn.freebsd.org/base/user/glebius/course\\ +\# cd course/02.entering\_kernel/syscall/module\\ +\# vi foo\_syscall.c +} +\end{frame} + +\end{document} Added: user/glebius/course/02.entering_kernel/syscall/Makefile ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ user/glebius/course/02.entering_kernel/syscall/Makefile Sun Oct 6 20:46:01 2013 (r256093) @@ -0,0 +1,3 @@ +SUBDIR= module application + +.include Added: user/glebius/course/02.entering_kernel/syscall/application/Makefile ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ user/glebius/course/02.entering_kernel/syscall/application/Makefile Sun Oct 6 20:46:01 2013 (r256093) @@ -0,0 +1,4 @@ +PROG= call +NO_MAN= + +.include Added: user/glebius/course/02.entering_kernel/syscall/application/call.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ user/glebius/course/02.entering_kernel/syscall/application/call.c Sun Oct 6 20:46:01 2013 (r256093) @@ -0,0 +1,24 @@ +#include +#include +#include + +#include +#include +#include +#include + +int +main(int argc, char **argv) +{ + int modid, syscall_num; + struct module_stat stat; + + stat.version = sizeof(stat); + if ((modid = modfind("sys/foo_syscall")) == -1) + err(1, "modfind"); + if (modstat(modid, &stat) != 0) + err(1, "modstat"); + syscall_num = stat.data.intval; + + return syscall(syscall_num, argc, argv); +} Added: user/glebius/course/02.entering_kernel/syscall/module/Makefile ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ user/glebius/course/02.entering_kernel/syscall/module/Makefile Sun Oct 6 20:46:01 2013 (r256093) @@ -0,0 +1,4 @@ +KMOD= foo_syscall +SRCS= foo_syscall.c + +.include Added: user/glebius/course/02.entering_kernel/syscall/module/foo_syscall.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ user/glebius/course/02.entering_kernel/syscall/module/foo_syscall.c Sun Oct 6 20:46:01 2013 (r256093) @@ -0,0 +1,74 @@ +#include +#include +#include +#include +#include +#include +#include + +/* + * ABI for arguments. Arguments should be aligned by + * register size. + */ +#define PAD_(t) (sizeof(register_t) <= sizeof(t) ? \ + 0 : sizeof(register_t) - sizeof(t)) +#if BYTE_ORDER == LITTLE_ENDIAN +#define PADL_(t) 0 +#define PADR_(t) PAD_(t) +#else +#define PADL_(t) PAD_(t) +#define PADR_(t) 0 +#endif +struct foo_args { + char d_l_[PADL_(int)]; int d; char d_r_[PADR_(int)]; + char p_l_[PADL_(int)]; void *p; char p_r_[PADR_(int)]; +}; + +/* + * The function implementing the syscall. + */ +static int +foo_syscall(struct thread *td, void *arg) +{ + struct foo_args *args = (struct foo_args *)arg; + + printf("arguments %d %p\n", + args->d, args->p); + return (0); +} + +/* + * The `sysent' for the new syscall. + */ +static struct sysent foo_sysent = { + 2, /* sy_narg */ + foo_syscall /* sy_call */ +}; + +/* + * The offset in sysent where the syscall is allocated. + */ +static int offset = NO_SYSCALL; + +/* + * The function called at load/unload. + */ +static int +foo_load(struct module *module, int cmd, void *arg) +{ + + switch (cmd) { + case MOD_LOAD : + printf("syscall loaded at %d\n", offset); + break; + case MOD_UNLOAD : + printf("syscall unloaded from %d\n", offset); + break; + default : + return (EOPNOTSUPP); + } + + return (0); +} + +SYSCALL_MODULE(foo_syscall, &offset, &foo_sysent, foo_load, NULL); Added: user/glebius/course/course.tex ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ user/glebius/course/course.tex Sun Oct 6 20:46:01 2013 (r256093) @@ -0,0 +1,42 @@ +\definecolor{yellowgreen}{HTML}{D0F000} +\definecolor{man}{HTML}{FF5E7C} +\definecolor{Agrey}{HTML}{AAAAAA} +\definecolor{Bgrey}{HTML}{BBBBBB} +\definecolor{Cgrey}{HTML}{CCCCCC} +\definecolor{Dgrey}{HTML}{DDDDDD} +\definecolor{Egrey}{HTML}{EEEEEE} + +% trace +\setbeamercolor{trace}{fg=black,bg=Cgrey} + +% terminal +\setbeamercolor{terminal}{fg=white,bg=black} + +% editor +\setbeamercolor{editor}{fg=black,bg=Cgrey} + +% manual pages +\newcommand{\Man}[2]{ + \colorbox{white}{\color{man}#1(#2)} +} +\setbeamercolor{manlabel}{fg=black,bg=man} +\newcommand{\manlabel}[1]{ + \begin{beamercolorbox}[rounded=true,shadow=true,sep=0pt,colsep=0pt]{manlabel} + \small{#1} + \end{beamercolorbox} +} + +% Source reference box +\setbeamercolor{srcref}{fg=black,bg=yellowgreen} +\newcommand{\srcref}[1]{ + \begin{beamercolorbox}[rounded=true,shadow=true,sep=0pt,colsep=0pt]{srcref} + \tiny{Source code reference:}\footnotesize{ #1} + \end{beamercolorbox} +} + +% Shell command +\newcommand{\shellcmd}[1]{ + \begin{beamercolorbox}[rounded=true,shadow=true,sep=0pt,colsep=0pt]{terminal} + \small{#1} + \end{beamercolorbox} +}