LINUX Device Drivers: Partha
LINUX Device Drivers: Partha
LINUX Device Drivers: Partha
Partha
Kernel
• The central component of
operating system
• Since the system call interface is exclusively register-parametered, six parameters at most can be used
with a single system call. %eax is the syscall number; %ebx, %ecx, %edx, %esi, %edi and %ebp are the six
generic registers used as param0-5; and %esp cannot be used because it's overwritten by the kernel
when it enters ring 0 (i.e., kernel mode). In case more parameters are needed, some structure can be
placed wherever you want within your address space and pointed to from a register (not the instruction
pointer, nor the stack pointer; the kernel-space functions use the stack for parameters and local
variables). This case is extremely rare, though; most system calls have either no parameters or only one.
An Example
• read(fd,buffer,size) corresponds to a system call with three arguments. So this will
be expanded by the _syscall3 macro. A statement
static inline syscall3(int,read,int,fd,char *,buf,off_t,len)
has been added in the header file for the macro expansion to take place. After the
expansion the system call number will be in register 'zero' and the argument to the
system call will be in the general purpose registers of the processor. Also the macro
will call the int 0x80 instruction after loading the registers. So the kernel mode is
initiated and kernel will execute on behalf of the process initiated by the system call.
• The int 0x80 instruction will call the system call handler. Each system call will have a
routine or program defined in the kernel. Address of each of these routine are
stored in the in array named sys_call_table (code in the file
/usr/src/linux-/arch/i386/kernel/entry.S).The path name has to be filled accordingly
for different kernel version. The system call handler will call the service routine
corresponding to the system call, by looking at the system call number loaded in the
register "zero". So the service routine corresponding to the read system call will be
executed. After executing the service routing the control comes back to the system
call handler and it will then give control back to the user process, also the mode of
operation is changed to user mode.
Interrupt
• Vector 0x80 is used to transfer control to the kernel. This interrupt vector
is initialized during system startup, along with other important vectors
such as the system clock vector.
• The startup_32() code found in /usr/src/linux/boot/head.S starts
everything off by calling setup_idt(). This routine sets up an IDT (Interrupt
Descriptor Table) with 256 entries. No interrupt entry points are actually
loaded by this routine, as that is done only after paging has been enabled
and the kernel has been moved to 0xC0000000. An IDT has 256 entries,
each 4 bytes long, for a total of 1024 bytes. When start_kernel() (found
in /usr/src/linux/init/main.c) is called it invokes trap_init() (found in
/usr/src/linux/kernel/traps.c). trap_init() sets up the IDT via the macro
set_trap_gate() (found in /usr/include/asm/system.h). trap_init()
initializes the interrupt descriptor table as shown here:
User/kernel space