* cormen book
[mascara-docs.git] / i86 / mtx-16-bit / mtx / notes5.html
blobd0f7fe83dfb8fb6b3f6b4e8096d95c89a22eee36
1 <Title>460 Class Notes</Title> <Body bgcolor="#00cccc" text="#000000"><H1>460 Notes #5</H1><Pre>
2 CS460 NOTES #5 Kernel & User Modes
4 1. Process Image:
5 The execution image of a process consists of 3 (logical) segments:
7 -----------------------------
8 | CODE | DATA | STACK |
9 -----------------------------
10 | ^ | | ^
11 CS | DS SS |
12 pc sp
14 Figure 1. Process Image
16 In theory, the 3 segments can be independent; each can be at a different memory
17 location, as long as they are pointed by the segment registers of CPU.
18 In practice, some of the segments may coincide. For example, in the combined
19 I and D space model, all segments are the same, i.e. CS=DS=SS all point at the
20 same segment. In the separate I and D space model, CS points to the I (code)
21 segment, but DS and SS point to the same Data+Stack segment.
22 For simplicity, we shall use the combined I and D space model in MTX so that
23 a process image has only ONE segment. The segment size is (up to) 64KB.
25 2. Kmode and Umode Images:
26 From now on we shall assume that a process may execute in two different
27 modes, Kernel mode or User mode, denoted by Kmode or Umode for short. While
28 in Kmode, all processes share the same Code and Data segments, which are
29 those of the Kernel, but each process has its own Kstack. The Umode images
30 are in general all different, i.e. each process has a separate Umode memory
31 area consisting of its own Ucode, Udata and Ustack. Also, for simplicity, we
32 shall assume:
34 MTX Kernel at (segment) 0x1000.
35 9 PROC structures but P0 runs only in Kernel.
36 So, only P1 to P8 have U mode images. Each process has a 64KB Umode image
37 in the segment (pid + 1)*0x1000, i.e. P1 at 0x2000, P2 at 0x3000, etc.
38 (This "FIXED SEGMENT" limitation can be removed later when we implement
39 memory management).
41 Next, assume that
43 P5 is running in Umode NOW, P2 is READY but not running.
45 ************************* Helpful Reviews ***********************************
46 Try to answer these questions. They will help you understand the MTX Kernel:
47 If P2 is not running but READY, where is its PROC? (i.e. in which Kernel data
48 structure?) How can P2 run again? When P2 runs again, where does it "resume"
49 to?
50 *****************************************************************************
52 The memory map is shown below:
54 -------------------------------------------------------------------------
55 |Vector | Kernel | | UImage2 | | | UImage5 |
56 -------------------------------------------------------------------------
57 ^ 0x1000 ^ 0x3000 ^ 0x6000
58 | | |
59 kCS,kDS,kSS uCS,uDS,uSS
61 At this moment, the CPU's CS,DS,SS registers all point at P5's Umode image
62 at 0x6000. P5's ustack is somewhere in the upper region of UImage5.
64 When P5 enters Kmode, it will execute the Kernel image at 0x1000. The CPU's
65 CS,DS,SS registers MUST be changed to point at 0x1000, as shown by the
66 kCS,kDS,kSS in the diagram. In order for P5 to execute in Kernel, the stack
67 pointer (sp) must also be changed to point at the Kstack of P5. Naturally, P5
68 must save its Umode uCS,uDS,uSS and usp in order for it to return to UImage5
69 later.
71 While in Kmode, P5 may switch to P2. P2 may return to its Umode image at
72 0x3000. If so, P2 must load CPU's CS,DS,SS with its own uCS,uDS,uSS, all of
73 which must point at 0x3000. P2's ustack is in the upper region of UImage2.
75 Similarly, you should be able to deduce what would happen when P2 enters Kmode
76 to switch to another process, ..... etc.
79 3. Transition between Umode and Kmode.
81 A process migrates between Umode and Kmode MANY times during its life time.
82 Although every process begins (comes into existence) in Kmode, we shall assume
83 that a process is already executing in Umode. This sounds like another
84 chicken-egg problem, but we can handle it easily.
86 A process in Umode will enter Kmode if any of these events occurs:
88 =====================================================================
89 (1). traps : divideByZero, IllegalInstruction, InvalidAddress,...
90 (2). Interrupts : timer interrupts, device I/O completion, etc.
91 (3). syscalls : INT # (or equivalent instructions on other CPUs).
92 =====================================================================
94 Traps and Interrupts will be covered later in the course. Here, we shall
95 consider only syscalls.
97 syscall is a mechanism that allows a Umode process to enter Kmode to execute
98 Kernel functions. syscalls are not ordinary function calls because they involve
99 CPU operating in different modes (U to K) and accessing different address
100 spaces. Assume that there are N Kernel functions, each corresponds to a
101 Type = 0,1,2, ..., N-1, e.g.
103 Type KernelFunction
104 ----- --------------
105 0 getpid
106 1 fork
107 2 wait
108 ...................
109 99 exit
111 A Umode process may call
113 int syscall(type, arg1, arg2, .... ) int type, arg1, arg2, ....;
115 which acts as an interface between U mode "calls" to the corresponding
116 Kernel functions. The implementation of syscall(), assuming 4 arguments,
117 is shown below:
119 |========================================================================
120 | syscall(a,b,c,d) int a,b,c,d; issue INT 80 to enter Kerenl
121 |========================================================================
122 _syscall:
123 int 80 <==== This is the magic wand!
126 On the Intel CPU, syscalls are implemented as INT #, where # is a (byte) value.
127 Although we may use different INT numbers to implement different syscall
128 fucntions, it suffices to use one number: INT 80 (because the parameter a
129 indicates the syscall type number). The choice of 80 is quite arbitrary. You
130 may choose any number, as long as it is not used as IRQ or by BIOS.
132 When CPU executes the instruction INT 80, it performs the following actions.
133 --------------------
134 PUSH: push uFlag
135 clear T-bit,I-bit of flag register to 0
136 (trace off, mask off interrupts)
137 push uCS
138 push uPC
139 ------------------------------------------------
140 LOAD: load (PC, CS) with CONTENTs of (4*80, 4*80+2);
141 ------------------------------------------------
142 HANDLER: continue execution from the loaded (PC, CS) ===>
143 CPU enters INT80 handler in kernel's Code segment.
144 ------------------------------------------------
147 Details of the PUSH, LOAD and HANDLER actions follow.
149 (1). PUSH:
150 INT # causes the CPU to push current uFlag, uCS, uPC into stack. On most other
151 machines, INT # causes the CPU to enter a separate Kmode, and switches stack
152 from ustack to kstack automatically. However, we are using the Intel CPU in
153 UNPROTECTED mode, which does not have a separate Kmode. After an INT 80, all
154 it does is to switch execution point from (uPC,uCS) to (kPC,kCS), which changes
155 the code segment from UCode to KCode. All other segments (DS and SS) and CPU
156 registers are still those in the Umode. Thus, when CPU first enters the
157 INT80 handler, the stack is still ustack in the uSS segment. It contains
158 uFlag, uCS, uPC at the top:
160 --------------------------------
161 ///////|uFlag| uCS | uPC |
162 --------------------------------
165 High usp Low
168 Corresponding to INT #, the instruction IRET pops 3 items off the current
169 stack into CPU's PC,CS,Flag registers, in that order. It is used to return from
170 interrupt handler (in Kmode) to Umode.
173 (2). LOAD
174 After an INT 80, CPU loads PC, CS from memory locations corresponding to the
175 vector number 80. Naturally, the vector 80 locations MUST be initialized
176 properly first, such as
178 int int80h(); /* handler function prototype */
179 set_vector(80, int80h); /* 80*4=kPC=int80h, 80*4+2=kCS=0x1000 */
182 (3). HANDLER:
184 The INT80 handler is shown below:
185 |=======================================================================
186 | int80h() is the entry point for INT 80 interrupts
187 |=======================================================================
188 _int80h:
190 ! (1). SAVE Umode registers in ustack, save uSS,uSP in running task's PROC,
191 ! Accordingly, we modify the proc structure as follows.
193 ! typedef struct proc{
194 ! struct proc *next;
195 ! int *ksp;
197 ! int uss, usp; /* ADD 2 items at offset 4,6 */
199 ! int pid;
200 ! int ppid;
201 ! int status;
202 ! int pri;
203 ! int event;
204 ! char name[32];
206 ! int kstack[SSIZE]; // task's Kernel mode stack
207 }PROC;
209 ! int procSzie = sizeof(PROC): // a global imported in assembly
211 ! The added PROC fields (uss, usp) are for saving (uSS, uSP) of that process.
213 ! (2). Change to stack pointer sp to running proc's kstack[ ] HIGH END (see below)
214 ! Then, call handler function in C
216 ! (3). RETURN to Umode
218 ! Details of these steps follow.
220 ! **************** SAVE U mode registers *********************************
221 push ax ! save all Umode registers in ustack
222 push bx
223 push cx
224 push dx
225 push bp
226 push si
227 push di
228 push es
229 push ds
231 ! ustack contains : flag,uCS,uPC | ax,bx,cx,dx,bp,si,di,ues,uds
233 ! HIGH ----------> LOW uSP
236 ! ************** Change DS,SS,sp to K space *****************
238 ! change DS to KDS in order to access data in Kernel space
239 push cs ! push kCS (0x1000)
240 pop ds ! let DS=CS = 0x1000
242 USS = 4
243 USP = 6
245 ! NOTE: All variables (offsets) are now relative to DS=0x1000 of Kernel space
246 ! save running proc's U mode uSS and uSP into its PROC
247 mov si,_running ! ready to access running PROC in K space
249 mov USS(si),ss ! save uSS in proc.uss
250 mov USP(si),sp ! save uSP in proc.usp
252 ! change ES SS to K space segment 0x1000
253 mov di,ds ! stupid CPU must mov segments this way!
254 mov es,di
255 mov ss,di ! SS is now KSS = 0x1000
257 ! We are now ready to switch (running proc's) stack from U space to K space.
258 mov sp,si ! sp points at running proc
259 add sp,_procSize ! sp -> HIGH END of running's kstack[]
261 ! We are now completely in K space, and stack is running task's (empty) kstack
263 ! ************* CALL handler in C ******************************
264 call _kcinth ! call kcinth() in C;
266 ! ************* RETURN TO U Mode ********************************
267 _goUmode:
268 cli ! mask out interrupts
269 mov bx,_running ! bx -> proc
270 mov cx,USS(bx)
271 mov ss,cx ! restore uSS
272 mov sp,USP(bx) ! restore uSP
274 pop ds
275 pop es
276 pop di
277 pop si
278 pop bp
279 pop dx
280 pop cx
281 pop bx
282 pop ax ! NOTE: return value must be in AX in ustack
284 iret
285 =============================================================================
286 The assembly function goUmode() restores Umode stack, then restores Umode
287 registers, followed by an IRET, causing the process to return to Umode.
289 These assembly functions are keys to understanding Umode/Kmode transitions.
290 STUDY THEM CAREFULLY and make sure you know what they do.
291 *****************************************************************************
293 4. Handler Function in C
294 kcinth(){.............}
295 is the syscall handler function in C. The parameters used in
296 syscall(a,b,c,d)
297 are still in ustack, which contains
299 LOW High
300 | uds,ues,udi,usi,ubp,udx,ucx,ubx,uax |upc,ucs,uflag|retPC, a, b, c, d |...
301 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
304 The segment of ustack is saved in proc.uss, and usp is saved in proc.usp
306 In Lab #2, you have used the get_byte()/put_byte() functions to implement
307 implement YOUR own get_word()/put_word() functions. With these functions,
308 you can easily copy bytes/words from/to U space.
310 In particular, you can get the syscall parameter from ustack AND also
311 modify the ustack contents, e.g. the saved AX register for return value
312 to U mode.
314 5. Action Functions:
315 In syscall(a,b,c,d), the parameter a is the syscall number. Based on the
316 value of a, you can execute the desired action function, passing any needed
317 parameters b,c,d to it.
319 RETURN VALUE:
320 Each action function returns a value back to Umode. The return value is
321 carried in the AX register. Since goUmode() pops the saved AX from ustack,
322 you must fix the saved AX in ustack before goUmode().