svn commit: r256093 - in user/glebius/course: . 02.entering_kernel 02.entering_kernel/syscall 02.entering_kernel/syscall/application 02.entering_kernel/syscall/module
Gleb Smirnoff
glebius at FreeBSD.org
Sun Oct 6 20:46:03 UTC 2013
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=<value optimized out>, 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 <bsd.subdir.mk>
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 <bsd.prog.mk>
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 <sys/types.h>
+#include <sys/module.h>
+#include <sys/syscall.h>
+
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+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 <bsd.kmod.mk>
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 <sys/param.h>
+#include <sys/proc.h>
+#include <sys/module.h>
+#include <sys/sysproto.h>
+#include <sys/sysent.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+
+/*
+ * 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}
+}
More information about the svn-src-user
mailing list