Sistemi operativi Lez.19 Protected mode in Minix
A.A. 2010/2011
1
Corso: Sistemi Operativi © Danilo Bruschi
http://www.raspberryginger.com/jbailey/minix/ html/index.html
A.A. 2010/2011
2
Corso: Sistemi Operativi © Danilo Bruschi
Introduzione • Dopo un avvio hw il processore è in real mode • Per poter passare alla modalità protected è necessario che il sw di inizializzazione provveda a predisporre una serie di strutture dati e codice necessarie per poter operare correttamente in protected mode
A.A. 2010/2011
3
Corso: Sistemi Operativi © Danilo Bruschi
Strutture dati • • • • •
IDT GDT Un TSS Una LDT (opzionale) Un segmento codice che contiene il codice da eseguire quando il processore entra in modalità protetta
•
Uno o più segmenti in cui sono caricati i gestori di interrupt ed eccezioni
A.A. 2010/2011
4
Corso: Sistemi Operativi © Danilo Bruschi
Registri • Vanno inoltre inizializzati i seguenti registri: • GDTR • IDTR: va inizializzato a interrupt disabilitati, prima della loro riabilitazione • I registri di controllo CR1 … CR4
A.A. 2010/2011
5
Corso: Sistemi Operativi © Danilo Bruschi
Switching a protected mode • Le istruzioni per lo switching a protected mode sono: ! enter protected mode! PE_BIT EQU 1B! MOV EBX,CR0! OR EBX,PE_BIT! MOV CR0,EBX!
A.A. 2010/2011
6
Corso: Sistemi Operativi © Danilo Bruschi
CR0
A.A. 2010/2011
7
Corso: Sistemi Operativi © Danilo Bruschi
Per questa parte di lezione fare riferimento al file Minix kernel/protect.c
GDT
A.A. 2010/2011
8
Corso: Sistemi Operativi © Danilo Bruschi
Boot file ! Call C startup code to set up a proper environment to run main(). ! push edx ! push ebx ! push SS_SELECTOR ! push MON_CS_SELECTOR ! push DS_SELECTOR ! push CS_SELECTOR ! call _cstart
! Procedura che prevede al caricamento di GDT, IDT e TSS!
add esp, 6*4! ! ! Reload gdtr, idtr and the segment registers to global descriptor !! ! table set
up by prot_init().!
lgdt (_gdt+GDT_SELECTOR) ! lidt (_gdt+IDT_SELECTOR)!
A.A. 2010/2011
9
Corso: Sistemi Operativi © Danilo Bruschi
GDT e LDT
A.A. 2010/2011
10
Corso: Sistemi Operativi © Danilo Bruschi
Layout Segment Descritpor
A.A. 2010/2011
11
Corso: Sistemi Operativi © Danilo Bruschi
Descrittore e GDT in C Minix 00081 struct segdesc_s {/* segment descriptor for protected ! ! ! ! ! ! ! !mode */! 00082 u16_t limit_low;! 00083 u16_t base_low;! 00084 u8_t base_middle;! 00085 u8_t access; /* |P|DL|1|X|E|R|A| */! 00086 u8_t granularity; /* |G|X|0|A|LIMT| */! 00087 u8_t base_high;! 00088 };!
00068 PUBLIC struct segdesc_s gdt[GDT_SIZE]!
A.A. 2010/2011
12
Corso: Sistemi Operativi © Danilo Bruschi
Costanti usate per costruire GDT 00003 /* Table sizes. */! 00004 #define GDT_SIZE (FIRST_LDT_INDEX + NR_TASKS + NR_PROCS) ! 00005
/* spec. and LDT's */!
00006 #define IDT_SIZE (IRQ8_VECTOR + 8)
/* only up to the highest vector */!
00007 #define LDT_SIZE (2 + NR_REMOTE_SEGS)
/* CS, DS and remote segments */!
00008 ! 00009 /* Fixed global descriptors.
1 to 7 are prescribed by the BIOS. */!
00010 #define GDT_INDEX
1
/* GDT descriptor */!
00011 #define IDT_INDEX
2
/* IDT descriptor */!
00012 #define DS_INDEX
3
/* kernel DS */!
00013 #define ES_INDEX
4
/* kernel ES (386: flag 4 Gb at startup) */!
00014 #define SS_INDEX
5
/* kernel SS (386: monitor SS at startup) */!
00015 #define CS_INDEX
6
/* kernel CS */!
00016 #define MON_CS_INDEX
7
/* temp for BIOS (386: monitor CS at startup) */!
00017 #define TSS_INDEX
8
/* kernel TSS */!
00018 #define DS_286_INDEX
9
/* scratch 16-bit source segment */!
00019 #define ES_286_INDEX
10
/* scratch 16-bit destination segment */!
00020 #define A_INDEX
11
/* 64K memory segment at A0000 */!
00021 #define B_INDEX
12
/* 64K memory segment at B0000 */!
A.A. 2010/2011
13
Corso: Sistemi Operativi © Danilo Bruschi
Costanti usate per costruire GDT 00022 #define C_INDEX
13
/* 64K memory segment at C0000 */!
00023 #define D_INDEX
14
/* 64K memory segment at D0000 */!
00024 #define FIRST_LDT_INDEX
15
/* rest of descriptors are LDT's */!
00025 ! 00026 #define GDT_SELECTOR
0x08
/* (GDT_INDEX * DESC_SIZE) bad for asld */!
00027 #define IDT_SELECTOR
0x10
/* (IDT_INDEX * DESC_SIZE) */!
00028 #define DS_SELECTOR
0x18
/* (DS_INDEX * DESC_SIZE) */!
00029 #define ES_SELECTOR
0x20
/* (ES_INDEX * DESC_SIZE) */!
00030 #define FLAT_DS_SELECTOR
0x21
/* less privileged ES */!
00031 #define SS_SELECTOR
0x28
/* (SS_INDEX * DESC_SIZE) */!
00032 #define CS_SELECTOR
0x30
/* (CS_INDEX * DESC_SIZE) */!
00033 #define MON_CS_SELECTOR
0x38
/* (MON_CS_INDEX * DESC_SIZE) */!
00034 #define TSS_SELECTOR
0x40
/* (TSS_INDEX * DESC_SIZE) */!
00035 #define DS_286_SELECTOR
0x49
/* (DS_286_INDEX*DESC_SIZE+TASK_PRIVILEGE) */!
00036 #define ES_286_SELECTOR
0x51
/* (ES_286_INDEX*DESC_SIZE+TASK_PRIVILEGE) */!
00037 ! 00038 /* Fixed local descriptors. */! 00039 #define CS_LDT_INDEX
0
/* process CS */!
00040 #define DS_LDT_INDEX
1
/* process DS=ES=FS=GS=SS */!
00041 #define EXTRA_LDT_INDEX
2
/* first of the extra LDT entries */!
A.A. 2010/2011
14
Corso: Sistemi Operativi © Danilo Bruschi
0043 /* Privileges. */! 00044 #define INTR_PRIVILEGE
0
/* kernel and interrupt handlers */!
00045 #define TASK_PRIVILEGE
1
/* kernel tasks */!
00046 #define USER_PRIVILEGE
3
/* servers and user !processes */!
00074 /* Access-byte and type-byte bits. */! 00075 #define PRESENT
0x80
/* set for descriptor present */!
00076 #define DPL
0x60
/* descriptor privilege level mask */!
00077 #define DPL_SHIFT
5!
00078 #define SEGMENT
0x10
/* set for segment-type descriptors */!
00081 #define EXECUTABLE
0x08
/* set for executable segment */!
00082 #define CONFORMING ! ! ! ! ! !
!
0x04 ! !
/* set for conforming segment if !executable */!
00083 #define EXPAND_DOWN ! ! ! ! ! ! !
0x04 ! !
/* set for expand-down segment if ! ! !executable*/!
00080 /* Access-byte bits. */!
00084 #define READABLE 00085 #define WRITEABLE ! ! ! ! ! !
0x02 /* set for readable segment if executable */! !
0x02 ! !
/* set for writeable segment if ! ! !executable */!
00086 #define TSS_BUSY
0x02
/* set if TSS descriptor is busy */!
00087 #define ACCESSED
0x01
/* set if segment accessed */!
A.A. 2010/2011
15
Corso: Sistemi Operativi © Danilo Bruschi
Caricamento primi elementi di GDT /* Build gdt and idt pointers in GDT where the BIOS expects them. */! ! 00139 dtp= (struct desctableptr_s *) &gdt[GDT_INDEX];! 00140 * (u16_t *) dtp->limit = (sizeof gdt) - 1;! 00141 * (u32_t *) dtp->base = vir2phys(gdt);! 00142 ! 00143 dtp= (struct desctableptr_s *) &gdt[IDT_INDEX];! 00144 * (u16_t *) dtp->limit = (sizeof idt) - 1;! 00145 * (u32_t *) dtp->base = vir2phys(idt);! 00146 ! ! /* Build segment descriptors for tasks and interrupt handlers. */! ! 00148 init_codeseg(&gdt[CS_INDEX],! 00149 kinfo.code_base, kinfo.code_size, INTR_PRIVILEGE);! 00150 init_dataseg(&gdt[DS_INDEX],! 00151 kinfo.data_base, kinfo.data_size, INTR_PRIVILEGE);! 00152 init_dataseg(&gdt[ES_INDEX], 0L, 0, TASK_PRIVILEGE);! A.A. 2010/2011
16
Corso: Sistemi Operativi © Danilo Bruschi
Procedura per il caricamento dei segmenti codice dal file protect.c *==================================================================*! 00195 * init_codeseg *! 00196 *============================================================*/! 00197 PUBLIC void init_codeseg(segdp, base, size, privilege)! 00198 register struct segdesc_s *segdp;! 00199 phys_bytes base;! 00200 vir_bytes size;! 00201 int privilege;! 00202 {! 00203 /* Build descriptor for a code segment. */! 00204 sdesc(segdp, base, size);! 00205 segdp->access = (privilege vec_nr, (vir_bytes) gtp->gate, PRESENT| INT_GATE_TYPE| (gtp->privilege offset_low = offset; 00318 idp->selector = CS_SELECTOR; 00319 idp->p_dpl_type = dpl_type; 00320 #if _WORD_SIZE == 4 00321 idp->offset_high = offset >> OFFSET_HIGH_SHIFT; 00322 #endif 00323 }
A.A. 2010/2011
30
Corso: Sistemi Operativi © Danilo Bruschi
TSS
A.A. 2010/2011
31
Corso: Sistemi Operativi © Danilo Bruschi
TSS
A.A. 2010/2011
32
Corso: Sistemi Operativi © Danilo Bruschi
TSS in C 00031 struct tss_s {! 00032
reg_t backlink;!
00033
reg_t sp0;
/* stack pointer to use during interrupt */!
00034
reg_t ss0;
/*
00035
reg_t sp1;!
00036
reg_t ss1;!
00037
reg_t sp2;!
00038
reg_t ss2;!
"
segment
"
"
"
"
*/!
00039 #if _WORD_SIZE == 4! 00040
reg_t cr3;!
00041 #endif! 00042
reg_t ip;!
00043
reg_t flags;!
00044
reg_t ax;!
00045
reg_t cx;!
00046
reg_t dx;!
00047
reg_t bx;!
00048
reg_t sp;!
A.A. 2010/2011
33
Corso: Sistemi Operativi © Danilo Bruschi
TSS in C 00049
reg_t bp;!
00050
reg_t si;!
00051
reg_t di;!
00052
reg_t es;!
00053
reg_t cs;!
00054
reg_t ss;!
00055
reg_t ds;!
00056 #if _WORD_SIZE == 4! 00057
reg_t fs;!
00058
reg_t gs;!
00059 #endif! 00060
reg_t ldt;!
00061 #if _WORD_SIZE == 4! 00062
u16_t trap;!
00063
u16_t iobase;!
00064 /* u8_t iomap[0]; */! 00065 #endif! 00066 };!
A.A. 2010/2011
34
Corso: Sistemi Operativi © Danilo Bruschi
TSS (protect.c) /* Build main TSS. This is used only to record the stack * ! pointer to be used after an interrupt. The pointer is set up ! so that an interrupt automatically saves the ! current process's registers ip:cs:f:sp:ss in the correct slots in the process table. */ ! ! tss.ss0 = DS_SELECTOR;! init_dataseg(&gdt[TSS_INDEX], vir2phys(&tss), sizeof(tss), INTR_PRIVILEGE); ! gdt[TSS_INDEX].access = PRESENT | (INTR_PRIVILEGE access = (privilege