The document discusses system calls and how they are handled in operating systems. It explains that system calls allow user processes to request services from the kernel by generating an interrupt that switches the processor into kernel mode. On x86 processors, the interrupt handler saves process state and routes the call to the appropriate kernel code based on an interrupt descriptor table with 256 entries. The document provides details on how Linux/x86 implements system calls, exceptions, and interrupts using the IDT, and switches between user and kernel mode to maintain isolation.
1. Lab 5: System calls
Advanced Operating Systems
Zubair Nabi
zubair.nabi@itu.edu.pk
February 27, 2013
2. Normal execution of a processor
While running a user process:
1
Read an instruction
2
Advance the program counter
3
Execute the instruction
4
Jump to 1
3. Normal execution of a processor
While running a user process:
1
Read an instruction
2
Advance the program counter
3
Execute the instruction
4
Jump to 1
4. Normal execution of a processor
While running a user process:
1
Read an instruction
2
Advance the program counter
3
Execute the instruction
4
Jump to 1
5. Normal execution of a processor
While running a user process:
1
Read an instruction
2
Advance the program counter
3
Execute the instruction
4
Jump to 1
6. Normal execution of a processor
While running a user process:
1
Read an instruction
2
Advance the program counter
3
Execute the instruction
4
Jump to 1
7. Extraordinary events
Events that break normal processor flow, to return control to the
kernel:
1
A device signals that it needs attention (e.g. Timer): Interrupt
2
A user program does something illegal (e.g. divide by zero):
Exception
3
A user program asks the kernel for a service: System call
8. Extraordinary events
Events that break normal processor flow, to return control to the
kernel:
1
A device signals that it needs attention (e.g. Timer): Interrupt
2
A user program does something illegal (e.g. divide by zero):
Exception
3
A user program asks the kernel for a service: System call
9. Extraordinary events
Events that break normal processor flow, to return control to the
kernel:
1
A device signals that it needs attention (e.g. Timer): Interrupt
2
A user program does something illegal (e.g. divide by zero):
Exception
3
A user program asks the kernel for a service: System call
10. Extraordinary events
Events that break normal processor flow, to return control to the
kernel:
1
A device signals that it needs attention (e.g. Timer): Interrupt
2
A user program does something illegal (e.g. divide by zero):
Exception
3
A user program asks the kernel for a service: System call
11. Handling extraordinary events
The operating system must:
1
Save the processor’s registers for future resumption
2
Set up system for execution in the kernel
3
Choose a place for the kernel to start execution
4
Retrieve information about the event and call corresponding
interrupt handler
5
All the while, maintain isolation between user processes and the
kernel
12. Handling extraordinary events
The operating system must:
1
Save the processor’s registers for future resumption
2
Set up system for execution in the kernel
3
Choose a place for the kernel to start execution
4
Retrieve information about the event and call corresponding
interrupt handler
5
All the while, maintain isolation between user processes and the
kernel
13. Handling extraordinary events
The operating system must:
1
Save the processor’s registers for future resumption
2
Set up system for execution in the kernel
3
Choose a place for the kernel to start execution
4
Retrieve information about the event and call corresponding
interrupt handler
5
All the while, maintain isolation between user processes and the
kernel
14. Handling extraordinary events
The operating system must:
1
Save the processor’s registers for future resumption
2
Set up system for execution in the kernel
3
Choose a place for the kernel to start execution
4
Retrieve information about the event and call corresponding
interrupt handler
5
All the while, maintain isolation between user processes and the
kernel
15. Handling extraordinary events
The operating system must:
1
Save the processor’s registers for future resumption
2
Set up system for execution in the kernel
3
Choose a place for the kernel to start execution
4
Retrieve information about the event and call corresponding
interrupt handler
5
All the while, maintain isolation between user processes and the
kernel
16. Handling extraordinary events
The operating system must:
1
Save the processor’s registers for future resumption
2
Set up system for execution in the kernel
3
Choose a place for the kernel to start execution
4
Retrieve information about the event and call corresponding
interrupt handler
5
All the while, maintain isolation between user processes and the
kernel
17. Handling extraordinary events (2)
• Need hardware support
• On the x86, system calls generate an interrupt via the int
instruction
• The same mechanism for handling interrupts is used for handling
system calls and exceptions
• Traps are caused by the current running process
• Interrupts are caused by devices
• Can happen concurrently
18. Handling extraordinary events (2)
• Need hardware support
• On the x86, system calls generate an interrupt via the int
instruction
• The same mechanism for handling interrupts is used for handling
system calls and exceptions
• Traps are caused by the current running process
• Interrupts are caused by devices
• Can happen concurrently
19. Handling extraordinary events (2)
• Need hardware support
• On the x86, system calls generate an interrupt via the int
instruction
• The same mechanism for handling interrupts is used for handling
system calls and exceptions
• Traps are caused by the current running process
• Interrupts are caused by devices
• Can happen concurrently
20. Handling extraordinary events (2)
• Need hardware support
• On the x86, system calls generate an interrupt via the int
instruction
• The same mechanism for handling interrupts is used for handling
system calls and exceptions
• Traps are caused by the current running process
• Interrupts are caused by devices
• Can happen concurrently
21. Handling extraordinary events (2)
• Need hardware support
• On the x86, system calls generate an interrupt via the int
instruction
• The same mechanism for handling interrupts is used for handling
system calls and exceptions
• Traps are caused by the current running process
• Interrupts are caused by devices
• Can happen concurrently
22. Handling extraordinary events (2)
• Need hardware support
• On the x86, system calls generate an interrupt via the int
instruction
• The same mechanism for handling interrupts is used for handling
system calls and exceptions
• Traps are caused by the current running process
• Interrupts are caused by devices
• Can happen concurrently
23. x86 protection
• 4 protection levels: 0 to 3
• Privilege decreases in ascending order
• Most operating systems only use 2 levels: 0 (kernel mode) and 3
(user mode)
• Interrupt handlers are defined in an interrupt descriptor table
(idt) with a total of 256 entries
• int n generates a system call, where n is used to index the
idt
• It is the job of the operating system to implement a handler for
each entry in the idt
24. x86 protection
• 4 protection levels: 0 to 3
• Privilege decreases in ascending order
• Most operating systems only use 2 levels: 0 (kernel mode) and 3
(user mode)
• Interrupt handlers are defined in an interrupt descriptor table
(idt) with a total of 256 entries
• int n generates a system call, where n is used to index the
idt
• It is the job of the operating system to implement a handler for
each entry in the idt
25. x86 protection
• 4 protection levels: 0 to 3
• Privilege decreases in ascending order
• Most operating systems only use 2 levels: 0 (kernel mode) and 3
(user mode)
• Interrupt handlers are defined in an interrupt descriptor table
(idt) with a total of 256 entries
• int n generates a system call, where n is used to index the
idt
• It is the job of the operating system to implement a handler for
each entry in the idt
26. x86 protection
• 4 protection levels: 0 to 3
• Privilege decreases in ascending order
• Most operating systems only use 2 levels: 0 (kernel mode) and 3
(user mode)
• Interrupt handlers are defined in an interrupt descriptor table
(idt) with a total of 256 entries
• int n generates a system call, where n is used to index the
idt
• It is the job of the operating system to implement a handler for
each entry in the idt
27. x86 protection
• 4 protection levels: 0 to 3
• Privilege decreases in ascending order
• Most operating systems only use 2 levels: 0 (kernel mode) and 3
(user mode)
• Interrupt handlers are defined in an interrupt descriptor table
(idt) with a total of 256 entries
• int n generates a system call, where n is used to index the
idt
• It is the job of the operating system to implement a handler for
each entry in the idt
28. x86 protection
• 4 protection levels: 0 to 3
• Privilege decreases in ascending order
• Most operating systems only use 2 levels: 0 (kernel mode) and 3
(user mode)
• Interrupt handlers are defined in an interrupt descriptor table
(idt) with a total of 256 entries
• int n generates a system call, where n is used to index the
idt
• It is the job of the operating system to implement a handler for
each entry in the idt
29. x86 protection
• 4 protection levels: 0 to 3
• Privilege decreases in ascending order
• Most operating systems only use 2 levels: 0 (kernel mode) and 3
(user mode)
• Interrupt handlers are defined in an interrupt descriptor table
(idt) with a total of 256 entries
• int n generates a system call, where n is used to index the
idt
• It is the job of the operating system to implement a handler for
each entry in the idt
30. int
• Fetches the nth descriptor from idt
• Ensures that the privilege level in the descriptor is 3
• As the interrupt is due to a user process, saves the process state
(change in privilege level)
• Sets the instructor pointer to the required starting address in the
descriptor table and starts execution
• After execution, the OS calls iret to resume previous execution
state
31. int
• Fetches the nth descriptor from idt
• Ensures that the privilege level in the descriptor is 3
• As the interrupt is due to a user process, saves the process state
(change in privilege level)
• Sets the instructor pointer to the required starting address in the
descriptor table and starts execution
• After execution, the OS calls iret to resume previous execution
state
32. int
• Fetches the nth descriptor from idt
• Ensures that the privilege level in the descriptor is 3
• As the interrupt is due to a user process, saves the process state
(change in privilege level)
• Sets the instructor pointer to the required starting address in the
descriptor table and starts execution
• After execution, the OS calls iret to resume previous execution
state
33. int
• Fetches the nth descriptor from idt
• Ensures that the privilege level in the descriptor is 3
• As the interrupt is due to a user process, saves the process state
(change in privilege level)
• Sets the instructor pointer to the required starting address in the
descriptor table and starts execution
• After execution, the OS calls iret to resume previous execution
state
34. int
• Fetches the nth descriptor from idt
• Ensures that the privilege level in the descriptor is 3
• As the interrupt is due to a user process, saves the process state
(change in privilege level)
• Sets the instructor pointer to the required starting address in the
descriptor table and starts execution
• After execution, the OS calls iret to resume previous execution
state
35. The first system call
• Recall that initcode.S started off by invoking an exec
system call to load the init process (/init)
• Flow:
1 Push the arguments and binary for exec on the process’s stack
2 Put the system call number (SYS_exec) in %eax (obviously this
number should already be present in the system call table,
*syscalls[])
3 Execute int T_SYSCALL
36. The first system call
• Recall that initcode.S started off by invoking an exec
system call to load the init process (/init)
• Flow:
1 Push the arguments and binary for exec on the process’s stack
2 Put the system call number (SYS_exec) in %eax (obviously this
number should already be present in the system call table,
*syscalls[])
3 Execute int T_SYSCALL
37. The first system call
• Recall that initcode.S started off by invoking an exec
system call to load the init process (/init)
• Flow:
1 Push the arguments and binary for exec on the process’s stack
2 Put the system call number (SYS_exec) in %eax (obviously this
number should already be present in the system call table,
*syscalls[])
3 Execute int T_SYSCALL
38. The first system call
• Recall that initcode.S started off by invoking an exec
system call to load the init process (/init)
• Flow:
1 Push the arguments and binary for exec on the process’s stack
2 Put the system call number (SYS_exec) in %eax (obviously this
number should already be present in the system call table,
*syscalls[])
3 Execute int T_SYSCALL
39. The first system call
• Recall that initcode.S started off by invoking an exec
system call to load the init process (/init)
• Flow:
1 Push the arguments and binary for exec on the process’s stack
2 Put the system call number (SYS_exec) in %eax (obviously this
number should already be present in the system call table,
*syscalls[])
3 Execute int T_SYSCALL
40. x86 traps
• 256 different interrupts
• 0-31 software
• 32-63 hardware
• 64 system calls (T_SYSCALL)
41. x86 traps
• 256 different interrupts
• 0-31 software
• 32-63 hardware
• 64 system calls (T_SYSCALL)
42. x86 traps
• 256 different interrupts
• 0-31 software
• 32-63 hardware
• 64 system calls (T_SYSCALL)
43. x86 traps
• 256 different interrupts
• 0-31 software
• 32-63 hardware
• 64 system calls (T_SYSCALL)
44. Setting up idt
• tvinit, called from main, sets up the entries in idt
• The address of the handler for each interrupt in idt is present in
vectors[], i.e. Interrupt i is handled by vectors[i]
• T_SYSCALL is handled specially: it is distinguished as a trap
allowing multiple system calls to execute simultaneously
45. Setting up idt
• tvinit, called from main, sets up the entries in idt
• The address of the handler for each interrupt in idt is present in
vectors[], i.e. Interrupt i is handled by vectors[i]
• T_SYSCALL is handled specially: it is distinguished as a trap
allowing multiple system calls to execute simultaneously
46. Setting up idt
• tvinit, called from main, sets up the entries in idt
• The address of the handler for each interrupt in idt is present in
vectors[], i.e. Interrupt i is handled by vectors[i]
• T_SYSCALL is handled specially: it is distinguished as a trap
allowing multiple system calls to execute simultaneously
48. Addresses of interrupt handlers
• xv6 uses a custom Perl script vectors.pl to generate
vectors.S which holds entry points of interrupt handlers in
vectors[]
• Each entry point:
Pushes an error code
Pushes the interrupt number
3 Jumps to alltraps
1
2
49. Addresses of interrupt handlers
• xv6 uses a custom Perl script vectors.pl to generate
vectors.S which holds entry points of interrupt handlers in
vectors[]
• Each entry point:
Pushes an error code
Pushes the interrupt number
3 Jumps to alltraps
1
2
50. Addresses of interrupt handlers
• xv6 uses a custom Perl script vectors.pl to generate
vectors.S which holds entry points of interrupt handlers in
vectors[]
• Each entry point:
Pushes an error code
Pushes the interrupt number
3 Jumps to alltraps
1
2
51. Addresses of interrupt handlers
• xv6 uses a custom Perl script vectors.pl to generate
vectors.S which holds entry points of interrupt handlers in
vectors[]
• Each entry point:
Pushes an error code
Pushes the interrupt number
3 Jumps to alltraps
1
2
52. alltraps
1
Pushes all processor registers into a struct trapframe
• Once the call completes, the kernel can restore state from this
structure
2
Sets up the processor to run kernel C code (load SEG_KCPU,
per-CPU data segment)
3
Calls the C trap handler trap
4
Once trap returns, alltraps restores struct
trapframe and then calls iret to return control back to user
space
53. alltraps
1
Pushes all processor registers into a struct trapframe
• Once the call completes, the kernel can restore state from this
structure
2
Sets up the processor to run kernel C code (load SEG_KCPU,
per-CPU data segment)
3
Calls the C trap handler trap
4
Once trap returns, alltraps restores struct
trapframe and then calls iret to return control back to user
space
54. alltraps
1
Pushes all processor registers into a struct trapframe
• Once the call completes, the kernel can restore state from this
structure
2
Sets up the processor to run kernel C code (load SEG_KCPU,
per-CPU data segment)
3
Calls the C trap handler trap
4
Once trap returns, alltraps restores struct
trapframe and then calls iret to return control back to user
space
55. alltraps
1
Pushes all processor registers into a struct trapframe
• Once the call completes, the kernel can restore state from this
structure
2
Sets up the processor to run kernel C code (load SEG_KCPU,
per-CPU data segment)
3
Calls the C trap handler trap
4
Once trap returns, alltraps restores struct
trapframe and then calls iret to return control back to user
space
56. alltraps
1
Pushes all processor registers into a struct trapframe
• Once the call completes, the kernel can restore state from this
structure
2
Sets up the processor to run kernel C code (load SEG_KCPU,
per-CPU data segment)
3
Calls the C trap handler trap
4
Once trap returns, alltraps restores struct
trapframe and then calls iret to return control back to user
space
57. trap
• Gets passed struct trapframe *tf
• Checks tf->trapno to decide if it was called for a system call
(T_SYSCALL) or a hardware interrupt or an exception
• In case of:
1 System call, it invokes syscall
2
3
Hardware interrupt, it calls the hardware interrupt controller
Exception, it prints the details and kills the user process
58. trap
• Gets passed struct trapframe *tf
• Checks tf->trapno to decide if it was called for a system call
(T_SYSCALL) or a hardware interrupt or an exception
• In case of:
1 System call, it invokes syscall
2
3
Hardware interrupt, it calls the hardware interrupt controller
Exception, it prints the details and kills the user process
59. trap
• Gets passed struct trapframe *tf
• Checks tf->trapno to decide if it was called for a system call
(T_SYSCALL) or a hardware interrupt or an exception
• In case of:
1 System call, it invokes syscall
2
3
Hardware interrupt, it calls the hardware interrupt controller
Exception, it prints the details and kills the user process
60. trap
• Gets passed struct trapframe *tf
• Checks tf->trapno to decide if it was called for a system call
(T_SYSCALL) or a hardware interrupt or an exception
• In case of:
1 System call, it invokes syscall
2
3
Hardware interrupt, it calls the hardware interrupt controller
Exception, it prints the details and kills the user process
61. trap
• Gets passed struct trapframe *tf
• Checks tf->trapno to decide if it was called for a system call
(T_SYSCALL) or a hardware interrupt or an exception
• In case of:
1 System call, it invokes syscall
2
3
Hardware interrupt, it calls the hardware interrupt controller
Exception, it prints the details and kills the user process
62. syscall
• Loads the system call number through proc->tf->eax
• Calls the corresponding system call from the syscalls table
• Puts its return value in proc->tf->eax (available on return to
user space)
• Conventionally negative numbers indicate errors while positive
ones indicate success
• System call arguments are retrieved using either argint,
argptr, or argstr
63. syscall
• Loads the system call number through proc->tf->eax
• Calls the corresponding system call from the syscalls table
• Puts its return value in proc->tf->eax (available on return to
user space)
• Conventionally negative numbers indicate errors while positive
ones indicate success
• System call arguments are retrieved using either argint,
argptr, or argstr
64. syscall
• Loads the system call number through proc->tf->eax
• Calls the corresponding system call from the syscalls table
• Puts its return value in proc->tf->eax (available on return to
user space)
• Conventionally negative numbers indicate errors while positive
ones indicate success
• System call arguments are retrieved using either argint,
argptr, or argstr
65. syscall
• Loads the system call number through proc->tf->eax
• Calls the corresponding system call from the syscalls table
• Puts its return value in proc->tf->eax (available on return to
user space)
• Conventionally negative numbers indicate errors while positive
ones indicate success
• System call arguments are retrieved using either argint,
argptr, or argstr
66. syscall
• Loads the system call number through proc->tf->eax
• Calls the corresponding system call from the syscalls table
• Puts its return value in proc->tf->eax (available on return to
user space)
• Conventionally negative numbers indicate errors while positive
ones indicate success
• System call arguments are retrieved using either argint,
argptr, or argstr
67. Reading(s)
• Chapter 3, “Traps, interrupts, and drivers”, till section “Code:
System calls" from “xv6: a simple, Unix-like teaching operating
system”