source: branches/minix3-book/kernel/protect.c@ 15

Last change on this file since 15 was 4, checked in by Mattia Monga, 14 years ago

Importazione sorgenti libro

File size: 11.4 KB
Line 
1/* This file contains code for initialization of protected mode, to initialize
2 * code and data segment descriptors, and to initialize global descriptors
3 * for local descriptors in the process table.
4 */
5
6#include "kernel.h"
7#include "proc.h"
8#include "protect.h"
9
10#define INT_GATE_TYPE (INT_286_GATE | DESC_386_BIT)
11#define TSS_TYPE (AVL_286_TSS | DESC_386_BIT)
12
13struct desctableptr_s {
14 char limit[sizeof(u16_t)];
15 char base[sizeof(u32_t)]; /* really u24_t + pad for 286 */
16};
17
18struct gatedesc_s {
19 u16_t offset_low;
20 u16_t selector;
21 u8_t pad; /* |000|XXXXX| ig & trpg, |XXXXXXXX| task g */
22 u8_t p_dpl_type; /* |P|DL|0|TYPE| */
23 u16_t offset_high;
24};
25
26struct tss_s {
27 reg_t backlink;
28 reg_t sp0; /* stack pointer to use during interrupt */
29 reg_t ss0; /* " segment " " " " */
30 reg_t sp1;
31 reg_t ss1;
32 reg_t sp2;
33 reg_t ss2;
34 reg_t cr3;
35 reg_t ip;
36 reg_t flags;
37 reg_t ax;
38 reg_t cx;
39 reg_t dx;
40 reg_t bx;
41 reg_t sp;
42 reg_t bp;
43 reg_t si;
44 reg_t di;
45 reg_t es;
46 reg_t cs;
47 reg_t ss;
48 reg_t ds;
49 reg_t fs;
50 reg_t gs;
51 reg_t ldt;
52 u16_t trap;
53 u16_t iobase;
54/* u8_t iomap[0]; */
55};
56
57PUBLIC struct segdesc_s gdt[GDT_SIZE]; /* used in klib.s and mpx.s */
58PRIVATE struct gatedesc_s idt[IDT_SIZE]; /* zero-init so none present */
59PUBLIC struct tss_s tss; /* zero init */
60
61FORWARD _PROTOTYPE( void int_gate, (unsigned vec_nr, vir_bytes offset,
62 unsigned dpl_type) );
63FORWARD _PROTOTYPE( void sdesc, (struct segdesc_s *segdp, phys_bytes base,
64 vir_bytes size) );
65
66/*===========================================================================*
67 * prot_init *
68 *===========================================================================*/
69PUBLIC void prot_init()
70{
71/* Set up tables for protected mode.
72 * All GDT slots are allocated at compile time.
73 */
74 struct gate_table_s *gtp;
75 struct desctableptr_s *dtp;
76 unsigned ldt_index;
77 register struct proc *rp;
78
79 static struct gate_table_s {
80 _PROTOTYPE( void (*gate), (void) );
81 unsigned char vec_nr;
82 unsigned char privilege;
83 }
84 gate_table[] = {
85 { divide_error, DIVIDE_VECTOR, INTR_PRIVILEGE },
86 { single_step_exception, DEBUG_VECTOR, INTR_PRIVILEGE },
87 { nmi, NMI_VECTOR, INTR_PRIVILEGE },
88 { breakpoint_exception, BREAKPOINT_VECTOR, USER_PRIVILEGE },
89 { overflow, OVERFLOW_VECTOR, USER_PRIVILEGE },
90 { bounds_check, BOUNDS_VECTOR, INTR_PRIVILEGE },
91 { inval_opcode, INVAL_OP_VECTOR, INTR_PRIVILEGE },
92 { copr_not_available, COPROC_NOT_VECTOR, INTR_PRIVILEGE },
93 { double_fault, DOUBLE_FAULT_VECTOR, INTR_PRIVILEGE },
94 { copr_seg_overrun, COPROC_SEG_VECTOR, INTR_PRIVILEGE },
95 { inval_tss, INVAL_TSS_VECTOR, INTR_PRIVILEGE },
96 { segment_not_present, SEG_NOT_VECTOR, INTR_PRIVILEGE },
97 { stack_exception, STACK_FAULT_VECTOR, INTR_PRIVILEGE },
98 { general_protection, PROTECTION_VECTOR, INTR_PRIVILEGE },
99 { page_fault, PAGE_FAULT_VECTOR, INTR_PRIVILEGE },
100 { copr_error, COPROC_ERR_VECTOR, INTR_PRIVILEGE },
101 { hwint00, VECTOR( 0), INTR_PRIVILEGE },
102 { hwint01, VECTOR( 1), INTR_PRIVILEGE },
103 { hwint02, VECTOR( 2), INTR_PRIVILEGE },
104 { hwint03, VECTOR( 3), INTR_PRIVILEGE },
105 { hwint04, VECTOR( 4), INTR_PRIVILEGE },
106 { hwint05, VECTOR( 5), INTR_PRIVILEGE },
107 { hwint06, VECTOR( 6), INTR_PRIVILEGE },
108 { hwint07, VECTOR( 7), INTR_PRIVILEGE },
109 { hwint08, VECTOR( 8), INTR_PRIVILEGE },
110 { hwint09, VECTOR( 9), INTR_PRIVILEGE },
111 { hwint10, VECTOR(10), INTR_PRIVILEGE },
112 { hwint11, VECTOR(11), INTR_PRIVILEGE },
113 { hwint12, VECTOR(12), INTR_PRIVILEGE },
114 { hwint13, VECTOR(13), INTR_PRIVILEGE },
115 { hwint14, VECTOR(14), INTR_PRIVILEGE },
116 { hwint15, VECTOR(15), INTR_PRIVILEGE },
117 { s_call, SYS386_VECTOR, USER_PRIVILEGE }, /* 386 system call */
118 { level0_call, LEVEL0_VECTOR, TASK_PRIVILEGE },
119 };
120
121 /* Build gdt and idt pointers in GDT where the BIOS expects them. */
122 dtp= (struct desctableptr_s *) &gdt[GDT_INDEX];
123 * (u16_t *) dtp->limit = (sizeof gdt) - 1;
124 * (u32_t *) dtp->base = vir2phys(gdt);
125
126 dtp= (struct desctableptr_s *) &gdt[IDT_INDEX];
127 * (u16_t *) dtp->limit = (sizeof idt) - 1;
128 * (u32_t *) dtp->base = vir2phys(idt);
129
130 /* Build segment descriptors for tasks and interrupt handlers. */
131 init_codeseg(&gdt[CS_INDEX],
132 kinfo.code_base, kinfo.code_size, INTR_PRIVILEGE);
133 init_dataseg(&gdt[DS_INDEX],
134 kinfo.data_base, kinfo.data_size, INTR_PRIVILEGE);
135 init_dataseg(&gdt[ES_INDEX], 0L, 0, TASK_PRIVILEGE);
136
137 /* Build scratch descriptors for functions in klib88. */
138 init_dataseg(&gdt[DS_286_INDEX], 0L, 0, TASK_PRIVILEGE);
139 init_dataseg(&gdt[ES_286_INDEX], 0L, 0, TASK_PRIVILEGE);
140
141 /* Build local descriptors in GDT for LDT's in process table.
142 * The LDT's are allocated at compile time in the process table, and
143 * initialized whenever a process' map is initialized or changed.
144 */
145 for (rp = BEG_PROC_ADDR, ldt_index = FIRST_LDT_INDEX;
146 rp < END_PROC_ADDR; ++rp, ldt_index++) {
147 init_dataseg(&gdt[ldt_index], vir2phys(rp->p_ldt),
148 sizeof(rp->p_ldt), INTR_PRIVILEGE);
149 gdt[ldt_index].access = PRESENT | LDT;
150 rp->p_ldt_sel = ldt_index * DESC_SIZE;
151 }
152
153 /* Build main TSS.
154 * This is used only to record the stack pointer to be used after an
155 * interrupt.
156 * The pointer is set up so that an interrupt automatically saves the
157 * current process's registers ip:cs:f:sp:ss in the correct slots in the
158 * process table.
159 */
160 tss.ss0 = DS_SELECTOR;
161 init_dataseg(&gdt[TSS_INDEX], vir2phys(&tss), sizeof(tss), INTR_PRIVILEGE);
162 gdt[TSS_INDEX].access = PRESENT | (INTR_PRIVILEGE << DPL_SHIFT) | TSS_TYPE;
163
164 /* Build descriptors for interrupt gates in IDT. */
165 for (gtp = &gate_table[0];
166 gtp < &gate_table[sizeof gate_table / sizeof gate_table[0]]; ++gtp) {
167 int_gate(gtp->vec_nr, (vir_bytes) gtp->gate,
168 PRESENT | INT_GATE_TYPE | (gtp->privilege << DPL_SHIFT));
169 }
170
171 /* Complete building of main TSS. */
172 tss.iobase = sizeof tss; /* empty i/o permissions map */
173}
174
175/*===========================================================================*
176 * init_codeseg *
177 *===========================================================================*/
178PUBLIC void init_codeseg(segdp, base, size, privilege)
179register struct segdesc_s *segdp;
180phys_bytes base;
181vir_bytes size;
182int privilege;
183{
184/* Build descriptor for a code segment. */
185 sdesc(segdp, base, size);
186 segdp->access = (privilege << DPL_SHIFT)
187 | (PRESENT | SEGMENT | EXECUTABLE | READABLE);
188 /* CONFORMING = 0, ACCESSED = 0 */
189}
190
191/*===========================================================================*
192 * init_dataseg *
193 *===========================================================================*/
194PUBLIC void init_dataseg(segdp, base, size, privilege)
195register struct segdesc_s *segdp;
196phys_bytes base;
197vir_bytes size;
198int privilege;
199{
200/* Build descriptor for a data segment. */
201 sdesc(segdp, base, size);
202 segdp->access = (privilege << DPL_SHIFT) | (PRESENT | SEGMENT | WRITEABLE);
203 /* EXECUTABLE = 0, EXPAND_DOWN = 0, ACCESSED = 0 */
204}
205
206/*===========================================================================*
207 * sdesc *
208 *===========================================================================*/
209PRIVATE void sdesc(segdp, base, size)
210register struct segdesc_s *segdp;
211phys_bytes base;
212vir_bytes size;
213{
214/* Fill in the size fields (base, limit and granularity) of a descriptor. */
215 segdp->base_low = base;
216 segdp->base_middle = base >> BASE_MIDDLE_SHIFT;
217 segdp->base_high = base >> BASE_HIGH_SHIFT;
218
219 --size; /* convert to a limit, 0 size means 4G */
220 if (size > BYTE_GRAN_MAX) {
221 segdp->limit_low = size >> PAGE_GRAN_SHIFT;
222 segdp->granularity = GRANULAR | (size >>
223 (PAGE_GRAN_SHIFT + GRANULARITY_SHIFT));
224 } else {
225 segdp->limit_low = size;
226 segdp->granularity = size >> GRANULARITY_SHIFT;
227 }
228 segdp->granularity |= DEFAULT; /* means BIG for data seg */
229}
230
231/*===========================================================================*
232 * seg2phys *
233 *===========================================================================*/
234PUBLIC phys_bytes seg2phys(seg)
235U16_t seg;
236{
237/* Return the base address of a segment, with seg being either a 8086 segment
238 * register, or a 286/386 segment selector.
239 */
240 phys_bytes base;
241 struct segdesc_s *segdp;
242
243 if (! machine.protected) {
244 base = hclick_to_physb(seg);
245 } else {
246 segdp = &gdt[seg >> 3];
247 base = ((u32_t) segdp->base_low << 0)
248 | ((u32_t) segdp->base_middle << 16)
249 | ((u32_t) segdp->base_high << 24);
250 }
251 return base;
252}
253
254/*===========================================================================*
255 * phys2seg *
256 *===========================================================================*/
257PUBLIC void phys2seg(seg, off, phys)
258u16_t *seg;
259vir_bytes *off;
260phys_bytes phys;
261{
262/* Return a segment selector and offset that can be used to reach a physical
263 * address, for use by a driver doing memory I/O in the A0000 - DFFFF range.
264 */
265 *seg = FLAT_DS_SELECTOR;
266 *off = phys;
267}
268
269/*===========================================================================*
270 * int_gate *
271 *===========================================================================*/
272PRIVATE void int_gate(vec_nr, offset, dpl_type)
273unsigned vec_nr;
274vir_bytes offset;
275unsigned dpl_type;
276{
277/* Build descriptor for an interrupt gate. */
278 register struct gatedesc_s *idp;
279
280 idp = &idt[vec_nr];
281 idp->offset_low = offset;
282 idp->selector = CS_SELECTOR;
283 idp->p_dpl_type = dpl_type;
284 idp->offset_high = offset >> OFFSET_HIGH_SHIFT;
285}
286
287/*===========================================================================*
288 * enable_iop *
289 *===========================================================================*/
290PUBLIC void enable_iop(pp)
291struct proc *pp;
292{
293/* Allow a user process to use I/O instructions. Change the I/O Permission
294 * Level bits in the psw. These specify least-privileged Current Permission
295 * Level allowed to execute I/O instructions. Users and servers have CPL 3.
296 * You can't have less privilege than that. Kernel has CPL 0, tasks CPL 1.
297 */
298 pp->p_reg.psw |= 0x3000;
299}
300
301/*===========================================================================*
302 * alloc_segments *
303 *===========================================================================*/
304PUBLIC void alloc_segments(rp)
305register struct proc *rp;
306{
307/* This is called at system initialization from main() and by do_newmap().
308 * The code has a separate function because of all hardware-dependencies.
309 * Note that IDLE is part of the kernel and gets TASK_PRIVILEGE here.
310 */
311 phys_bytes code_bytes;
312 phys_bytes data_bytes;
313 int privilege;
314
315 if (machine.protected) {
316 data_bytes = (phys_bytes) (rp->p_memmap[S].mem_vir +
317 rp->p_memmap[S].mem_len) << CLICK_SHIFT;
318 if (rp->p_memmap[T].mem_len == 0)
319 code_bytes = data_bytes; /* common I&D, poor protect */
320 else
321 code_bytes = (phys_bytes) rp->p_memmap[T].mem_len << CLICK_SHIFT;
322 privilege = (iskernelp(rp)) ? TASK_PRIVILEGE : USER_PRIVILEGE;
323 init_codeseg(&rp->p_ldt[CS_LDT_INDEX],
324 (phys_bytes) rp->p_memmap[T].mem_phys << CLICK_SHIFT,
325 code_bytes, privilege);
326 init_dataseg(&rp->p_ldt[DS_LDT_INDEX],
327 (phys_bytes) rp->p_memmap[D].mem_phys << CLICK_SHIFT,
328 data_bytes, privilege);
329 rp->p_reg.cs = (CS_LDT_INDEX * DESC_SIZE) | TI | privilege;
330 rp->p_reg.gs =
331 rp->p_reg.fs =
332 rp->p_reg.ss =
333 rp->p_reg.es =
334 rp->p_reg.ds = (DS_LDT_INDEX*DESC_SIZE) | TI | privilege;
335 } else {
336 rp->p_reg.cs = click_to_hclick(rp->p_memmap[T].mem_phys);
337 rp->p_reg.ss =
338 rp->p_reg.es =
339 rp->p_reg.ds = click_to_hclick(rp->p_memmap[D].mem_phys);
340 }
341}
342
Note: See TracBrowser for help on using the repository browser.