1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
|
/*
* Mach Operating System
* Copyright (c) 1991,1990 Carnegie Mellon University
* Copyright (c) 1991 IBM Corporation
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation,
* and that the name IBM not be used in advertising or publicity
* pertaining to distribution of the software without specific, written
* prior permission.
*
* CARNEGIE MELLON AND IBM ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS IS"
* CONDITION. CARNEGIE MELLON AND IBM DISCLAIM ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie Mellon
* the rights to redistribute these changes.
*/
#ifndef _I386_SEG_H_
#define _I386_SEG_H_
#include <mach/inline.h>
/*
* i386 segmentation.
*/
/* Note: the value of KERNEL_RING is handled by hand in locore.S */
#ifdef MACH_RING1
#define KERNEL_RING 1
#else /* MACH_RING1 */
#define KERNEL_RING 0
#endif /* MACH_RING1 */
#ifndef __ASSEMBLER__
/*
* Real segment descriptor.
*/
struct real_descriptor {
unsigned int limit_low:16, /* limit 0..15 */
base_low:16, /* base 0..15 */
base_med:8, /* base 16..23 */
access:8, /* access byte */
limit_high:4, /* limit 16..19 */
granularity:4, /* granularity */
base_high:8; /* base 24..31 */
};
struct real_gate {
unsigned int offset_low:16, /* offset 0..15 */
selector:16,
word_count:8,
access:8,
offset_high:16; /* offset 16..31 */
#ifdef __x86_64__
unsigned int offset_ext:32, /* offset 32..63 */
reserved:32;
#endif
};
#endif /* !__ASSEMBLER__ */
#define SZ_64 0x2 /* 64-bit segment */
#define SZ_32 0x4 /* 32-bit segment */
#define SZ_16 0x0 /* 16-bit segment */
#define SZ_G 0x8 /* 4K limit field */
#define ACC_A 0x01 /* accessed */
#define ACC_TYPE 0x1e /* type field: */
#define ACC_TYPE_SYSTEM 0x00 /* system descriptors: */
#define ACC_LDT 0x02 /* LDT */
#define ACC_CALL_GATE_16 0x04 /* 16-bit call gate */
#define ACC_TASK_GATE 0x05 /* task gate */
#define ACC_TSS 0x09 /* task segment */
#define ACC_CALL_GATE 0x0c /* call gate */
#define ACC_INTR_GATE 0x0e /* interrupt gate */
#define ACC_TRAP_GATE 0x0f /* trap gate */
#define ACC_TSS_BUSY 0x02 /* task busy */
#define ACC_TYPE_USER 0x10 /* user descriptors */
#define ACC_DATA 0x10 /* data */
#define ACC_DATA_W 0x12 /* data, writable */
#define ACC_DATA_E 0x14 /* data, expand-down */
#define ACC_DATA_EW 0x16 /* data, expand-down,
writable */
#define ACC_CODE 0x18 /* code */
#define ACC_CODE_R 0x1a /* code, readable */
#define ACC_CODE_C 0x1c /* code, conforming */
#define ACC_CODE_CR 0x1e /* code, conforming,
readable */
#define ACC_PL 0x60 /* access rights: */
#define ACC_PL_K (KERNEL_RING << 5) /* kernel access only */
#define ACC_PL_U 0x60 /* user access */
#define ACC_P 0x80 /* segment present */
/*
* Components of a selector
*/
#define SEL_LDT 0x04 /* local selector */
#define SEL_PL 0x03 /* privilege level: */
#define SEL_PL_K KERNEL_RING /* kernel selector */
#define SEL_PL_U 0x03 /* user selector */
/*
* Convert selector to descriptor table index.
*/
#define sel_idx(sel) ((sel)>>3)
#ifndef __ASSEMBLER__
#include <mach/inline.h>
#include <mach/xen.h>
/* Format of a "pseudo-descriptor", used for loading the IDT and GDT. */
struct pseudo_descriptor
{
unsigned short limit;
unsigned long linear_base;
short pad;
} __attribute__((packed));
/* Load the processor's IDT, GDT, or LDT pointers. */
MACH_INLINE void lgdt(struct pseudo_descriptor *pdesc)
{
__asm volatile("lgdt %0" : : "m" (*pdesc));
}
MACH_INLINE void lidt(struct pseudo_descriptor *pdesc)
{
__asm volatile("lidt %0" : : "m" (*pdesc));
}
MACH_INLINE void lldt(unsigned short ldt_selector)
{
__asm volatile("lldt %w0" : : "r" (ldt_selector) : "memory");
}
#ifdef CODE16
#define i16_lgdt lgdt
#define i16_lidt lidt
#define i16_lldt lldt
#endif
/* Fill a segment descriptor. */
MACH_INLINE void
fill_descriptor(struct real_descriptor *_desc, unsigned base, unsigned limit,
unsigned char access, unsigned char sizebits)
{
/* TODO: when !MACH_PV_DESCRIPTORS, setting desc and just memcpy isn't simpler actually */
#ifdef MACH_PV_DESCRIPTORS
struct real_descriptor __desc, *desc = &__desc;
#else /* MACH_PV_DESCRIPTORS */
struct real_descriptor *desc = _desc;
#endif /* MACH_PV_DESCRIPTORS */
if (limit > 0xfffff)
{
limit >>= 12;
sizebits |= SZ_G;
}
desc->limit_low = limit & 0xffff;
desc->base_low = base & 0xffff;
desc->base_med = (base >> 16) & 0xff;
desc->access = access | ACC_P;
desc->limit_high = limit >> 16;
desc->granularity = sizebits;
desc->base_high = base >> 24;
#ifdef MACH_PV_DESCRIPTORS
if (hyp_do_update_descriptor(kv_to_ma(_desc), *(uint64_t*)desc))
panic("couldn't update descriptor(%lu to %08lx%08lx)\n", (vm_offset_t) kv_to_ma(_desc), *(((unsigned long*)desc)+1), *(unsigned long *)desc);
#endif /* MACH_PV_DESCRIPTORS */
}
/* Fill a gate with particular values. */
MACH_INLINE void
fill_gate(struct real_gate *gate, unsigned offset, unsigned short selector,
unsigned char access, unsigned char word_count)
{
gate->offset_low = offset & 0xffff;
gate->selector = selector;
gate->word_count = word_count;
gate->access = access | ACC_P;
gate->offset_high = (offset >> 16) & 0xffff;
#ifdef __x86_64__
gate->offset_ext = offset >> 32;
gate->reserved = 0;
#endif
}
#endif /* !__ASSEMBLER__ */
#endif /* _I386_SEG_H_ */
|