1 | /** |
---|
2 | * @file |
---|
3 | * |
---|
4 | * @brief Intel I386 CPU Dependent Source |
---|
5 | * |
---|
6 | * This include file contains information pertaining to the Intel |
---|
7 | * i386 processor. |
---|
8 | */ |
---|
9 | |
---|
10 | /* |
---|
11 | * COPYRIGHT (c) 1989-2016. |
---|
12 | * On-Line Applications Research Corporation (OAR). |
---|
13 | * |
---|
14 | * Copyright (C) 1998 Eric Valette (valette@crf.canon.fr) |
---|
15 | * Canon Centre Recherche France. |
---|
16 | * |
---|
17 | * The license and distribution terms for this file may be |
---|
18 | * found in the file LICENSE in this distribution or at |
---|
19 | * http://www.rtems.org/license/LICENSE. |
---|
20 | */ |
---|
21 | |
---|
22 | #ifndef _RTEMS_SCORE_I386_H |
---|
23 | #define _RTEMS_SCORE_I386_H |
---|
24 | |
---|
25 | #ifdef __cplusplus |
---|
26 | extern "C" { |
---|
27 | #endif |
---|
28 | |
---|
29 | #include <rtems/score/interrupts.h> |
---|
30 | #include <rtems/score/registers.h> |
---|
31 | |
---|
32 | /* |
---|
33 | * This section contains the information required to build |
---|
34 | * RTEMS for a particular member of the Intel i386 |
---|
35 | * family when executing in protected mode. It does |
---|
36 | * this by setting variables to indicate which implementation |
---|
37 | * dependent features are present in a particular member |
---|
38 | * of the family. |
---|
39 | * |
---|
40 | * Currently recognized: |
---|
41 | * i386_fp (i386 DX or SX w/i387) |
---|
42 | * i486dx |
---|
43 | * pentium |
---|
44 | * pentiumpro |
---|
45 | * |
---|
46 | * CPU Model Feature Flags: |
---|
47 | * |
---|
48 | * I386_HAS_BSWAP: Defined to "1" if the instruction for endian swapping |
---|
49 | * (bswap) should be used. This instruction appears to |
---|
50 | * be present in all i486's and above. |
---|
51 | * |
---|
52 | * I386_HAS_FPU: Defined to "1" if the CPU has an FPU. |
---|
53 | * As of at least gcc 4.7, i386 soft-float was obsoleted. |
---|
54 | * Thus this is always set to "1". |
---|
55 | */ |
---|
56 | #define I386_HAS_FPU 1 |
---|
57 | |
---|
58 | #if defined(__pentiumpro__) |
---|
59 | |
---|
60 | #define CPU_MODEL_NAME "Pentium Pro" |
---|
61 | |
---|
62 | #elif defined(__i586__) |
---|
63 | |
---|
64 | #if defined(__pentium__) |
---|
65 | #define CPU_MODEL_NAME "Pentium" |
---|
66 | #elif defined(__k6__) |
---|
67 | #define CPU_MODEL_NAME "K6" |
---|
68 | #else |
---|
69 | #define CPU_MODEL_NAME "i586" |
---|
70 | #endif |
---|
71 | |
---|
72 | #elif defined(__i486__) |
---|
73 | |
---|
74 | #define CPU_MODEL_NAME "i486dx" |
---|
75 | |
---|
76 | #elif defined(__i386__) |
---|
77 | |
---|
78 | #define I386_HAS_BSWAP 0 |
---|
79 | #define CPU_MODEL_NAME "i386 with i387" |
---|
80 | |
---|
81 | #else |
---|
82 | #error "Unknown CPU Model" |
---|
83 | #endif |
---|
84 | |
---|
85 | /* |
---|
86 | * Set default values for CPU model feature flags |
---|
87 | * |
---|
88 | * NOTE: These settings are chosen to reflect most of the family members. |
---|
89 | */ |
---|
90 | #ifndef I386_HAS_BSWAP |
---|
91 | #define I386_HAS_BSWAP 1 |
---|
92 | #endif |
---|
93 | |
---|
94 | /* |
---|
95 | * Define the name of the CPU family. |
---|
96 | */ |
---|
97 | #define CPU_NAME "Intel i386" |
---|
98 | |
---|
99 | #ifndef ASM |
---|
100 | |
---|
101 | /* |
---|
102 | * The following routine swaps the endian format of an unsigned int. |
---|
103 | * It must be static so it can be referenced indirectly. |
---|
104 | */ |
---|
105 | |
---|
106 | static inline uint32_t i386_swap_u32( |
---|
107 | uint32_t value |
---|
108 | ) |
---|
109 | { |
---|
110 | uint32_t lout; |
---|
111 | |
---|
112 | #if (I386_HAS_BSWAP == 0) |
---|
113 | __asm__ volatile( "rorw $8,%%ax;" |
---|
114 | "rorl $16,%0;" |
---|
115 | "rorw $8,%%ax" : "=a" (lout) : "0" (value) ); |
---|
116 | #else |
---|
117 | __asm__ volatile( "bswap %0" : "=r" (lout) : "0" (value)); |
---|
118 | #endif |
---|
119 | return( lout ); |
---|
120 | } |
---|
121 | #define CPU_swap_u32( _value ) i386_swap_u32( _value ) |
---|
122 | |
---|
123 | static inline uint16_t i386_swap_u16( |
---|
124 | uint16_t value |
---|
125 | ) |
---|
126 | { |
---|
127 | unsigned short sout; |
---|
128 | |
---|
129 | __asm__ volatile( "rorw $8,%0" : "=r" (sout) : "0" (value)); |
---|
130 | return (sout); |
---|
131 | } |
---|
132 | #define CPU_swap_u16( _value ) i386_swap_u16( _value ) |
---|
133 | |
---|
134 | /* |
---|
135 | * Added for pagination management |
---|
136 | */ |
---|
137 | static inline unsigned int i386_get_cr0(void) |
---|
138 | { |
---|
139 | register unsigned int segment = 0; |
---|
140 | |
---|
141 | __asm__ volatile ( "movl %%cr0,%0" : "=r" (segment) : "0" (segment) ); |
---|
142 | |
---|
143 | return segment; |
---|
144 | } |
---|
145 | |
---|
146 | static inline void i386_set_cr0(unsigned int segment) |
---|
147 | { |
---|
148 | __asm__ volatile ( "movl %0,%%cr0" : "=r" (segment) : "0" (segment) ); |
---|
149 | } |
---|
150 | |
---|
151 | static inline unsigned int i386_get_cr2(void) |
---|
152 | { |
---|
153 | register unsigned int segment = 0; |
---|
154 | |
---|
155 | __asm__ volatile ( "movl %%cr2,%0" : "=r" (segment) : "0" (segment) ); |
---|
156 | |
---|
157 | return segment; |
---|
158 | } |
---|
159 | |
---|
160 | static inline unsigned int i386_get_cr3(void) |
---|
161 | { |
---|
162 | register unsigned int segment = 0; |
---|
163 | |
---|
164 | __asm__ volatile ( "movl %%cr3,%0" : "=r" (segment) : "0" (segment) ); |
---|
165 | |
---|
166 | return segment; |
---|
167 | } |
---|
168 | |
---|
169 | static inline void i386_set_cr3(unsigned int segment) |
---|
170 | { |
---|
171 | __asm__ volatile ( "movl %0,%%cr3" : "=r" (segment) : "0" (segment) ); |
---|
172 | } |
---|
173 | |
---|
174 | /* routines */ |
---|
175 | |
---|
176 | /* |
---|
177 | * i386_Logical_to_physical |
---|
178 | * |
---|
179 | * Converts logical address to physical address. |
---|
180 | */ |
---|
181 | void *i386_Logical_to_physical( |
---|
182 | unsigned short segment, |
---|
183 | void *address |
---|
184 | ); |
---|
185 | |
---|
186 | /* |
---|
187 | * i386_Physical_to_logical |
---|
188 | * |
---|
189 | * Converts physical address to logical address. |
---|
190 | */ |
---|
191 | void *i386_Physical_to_logical( |
---|
192 | unsigned short segment, |
---|
193 | void *address |
---|
194 | ); |
---|
195 | |
---|
196 | /** |
---|
197 | * @brief Converts real mode pointer {segment, offset} to physical address. |
---|
198 | * |
---|
199 | * i386_Real_to_physical |
---|
200 | * |
---|
201 | * @param[in] segment used with \p offset to compute physical address |
---|
202 | * @param[in] offset used with \p segment to compute physical address |
---|
203 | * @retval physical address |
---|
204 | */ |
---|
205 | RTEMS_INLINE_ROUTINE void *i386_Real_to_physical( |
---|
206 | uint16_t segment, |
---|
207 | uint16_t offset) |
---|
208 | { |
---|
209 | return (void *)(((uint32_t)segment<<4)+offset); |
---|
210 | } |
---|
211 | |
---|
212 | /** |
---|
213 | * @brief Retrieves real mode pointer elements {segmnet, offset} from |
---|
214 | * physical address. |
---|
215 | * |
---|
216 | * i386_Physical_to_real |
---|
217 | * Function returns the highest segment (base) address possible. |
---|
218 | * Example: input address - 0x4B3A2 |
---|
219 | * output segment - 0x4B3A |
---|
220 | * offset - 0x2 |
---|
221 | * input address - 0x10F12E |
---|
222 | * output segment - 0xFFFF |
---|
223 | * offset - 0xF13E |
---|
224 | * |
---|
225 | * @param[in] address address to be converted, must be less than 0x10FFEF |
---|
226 | * @param[out] segment segment computed from \p address |
---|
227 | * @param[out] offset offset computed from \p address |
---|
228 | * @retval 0 address not convertible |
---|
229 | * @retval 1 segment and offset extracted |
---|
230 | */ |
---|
231 | int i386_Physical_to_real( |
---|
232 | void *address, |
---|
233 | uint16_t *segment, |
---|
234 | uint16_t *offset |
---|
235 | ); |
---|
236 | |
---|
237 | /* |
---|
238 | * Segment Access Routines |
---|
239 | * |
---|
240 | * NOTE: Unfortunately, these are still static inlines even when the |
---|
241 | * "macro" implementation of the generic code is used. |
---|
242 | */ |
---|
243 | |
---|
244 | static __inline__ unsigned short i386_get_cs(void) |
---|
245 | { |
---|
246 | register unsigned short segment = 0; |
---|
247 | |
---|
248 | __asm__ volatile ( "movw %%cs,%0" : "=r" (segment) : "0" (segment) ); |
---|
249 | |
---|
250 | return segment; |
---|
251 | } |
---|
252 | |
---|
253 | static __inline__ unsigned short i386_get_ds(void) |
---|
254 | { |
---|
255 | register unsigned short segment = 0; |
---|
256 | |
---|
257 | __asm__ volatile ( "movw %%ds,%0" : "=r" (segment) : "0" (segment) ); |
---|
258 | |
---|
259 | return segment; |
---|
260 | } |
---|
261 | |
---|
262 | static __inline__ unsigned short i386_get_es(void) |
---|
263 | { |
---|
264 | register unsigned short segment = 0; |
---|
265 | |
---|
266 | __asm__ volatile ( "movw %%es,%0" : "=r" (segment) : "0" (segment) ); |
---|
267 | |
---|
268 | return segment; |
---|
269 | } |
---|
270 | |
---|
271 | static __inline__ unsigned short i386_get_ss(void) |
---|
272 | { |
---|
273 | register unsigned short segment = 0; |
---|
274 | |
---|
275 | __asm__ volatile ( "movw %%ss,%0" : "=r" (segment) : "0" (segment) ); |
---|
276 | |
---|
277 | return segment; |
---|
278 | } |
---|
279 | |
---|
280 | static __inline__ unsigned short i386_get_fs(void) |
---|
281 | { |
---|
282 | register unsigned short segment = 0; |
---|
283 | |
---|
284 | __asm__ volatile ( "movw %%fs,%0" : "=r" (segment) : "0" (segment) ); |
---|
285 | |
---|
286 | return segment; |
---|
287 | } |
---|
288 | |
---|
289 | static __inline__ unsigned short i386_get_gs(void) |
---|
290 | { |
---|
291 | register unsigned short segment = 0; |
---|
292 | |
---|
293 | __asm__ volatile ( "movw %%gs,%0" : "=r" (segment) : "0" (segment) ); |
---|
294 | |
---|
295 | return segment; |
---|
296 | } |
---|
297 | |
---|
298 | /* |
---|
299 | * IO Port Access Routines |
---|
300 | */ |
---|
301 | |
---|
302 | #define i386_outport_byte( _port, _value ) \ |
---|
303 | do { register unsigned short __port = _port; \ |
---|
304 | register unsigned char __value = _value; \ |
---|
305 | \ |
---|
306 | __asm__ volatile ( "outb %0,%1" : : "a" (__value), "d" (__port) ); \ |
---|
307 | } while (0) |
---|
308 | |
---|
309 | #define i386_outport_word( _port, _value ) \ |
---|
310 | do { register unsigned short __port = _port; \ |
---|
311 | register unsigned short __value = _value; \ |
---|
312 | \ |
---|
313 | __asm__ volatile ( "outw %0,%1" : : "a" (__value), "d" (__port) ); \ |
---|
314 | } while (0) |
---|
315 | |
---|
316 | #define i386_outport_long( _port, _value ) \ |
---|
317 | do { register unsigned short __port = _port; \ |
---|
318 | register unsigned int __value = _value; \ |
---|
319 | \ |
---|
320 | __asm__ volatile ( "outl %0,%1" : : "a" (__value), "d" (__port) ); \ |
---|
321 | } while (0) |
---|
322 | |
---|
323 | #define i386_inport_byte( _port, _value ) \ |
---|
324 | do { register unsigned short __port = _port; \ |
---|
325 | register unsigned char __value = 0; \ |
---|
326 | \ |
---|
327 | __asm__ volatile ( "inb %1,%0" : "=a" (__value) \ |
---|
328 | : "d" (__port) \ |
---|
329 | ); \ |
---|
330 | _value = __value; \ |
---|
331 | } while (0) |
---|
332 | |
---|
333 | #define i386_inport_word( _port, _value ) \ |
---|
334 | do { register unsigned short __port = _port; \ |
---|
335 | register unsigned short __value = 0; \ |
---|
336 | \ |
---|
337 | __asm__ volatile ( "inw %1,%0" : "=a" (__value) \ |
---|
338 | : "d" (__port) \ |
---|
339 | ); \ |
---|
340 | _value = __value; \ |
---|
341 | } while (0) |
---|
342 | |
---|
343 | #define i386_inport_long( _port, _value ) \ |
---|
344 | do { register unsigned short __port = _port; \ |
---|
345 | register unsigned int __value = 0; \ |
---|
346 | \ |
---|
347 | __asm__ volatile ( "inl %1,%0" : "=a" (__value) \ |
---|
348 | : "d" (__port) \ |
---|
349 | ); \ |
---|
350 | _value = __value; \ |
---|
351 | } while (0) |
---|
352 | |
---|
353 | /* |
---|
354 | * Type definition for raw interrupts. |
---|
355 | */ |
---|
356 | |
---|
357 | typedef unsigned char rtems_vector_offset; |
---|
358 | |
---|
359 | typedef struct __rtems_raw_irq_connect_data__{ |
---|
360 | /* |
---|
361 | * IDT vector offset (IRQ line + PC386_IRQ_VECTOR_BASE) |
---|
362 | */ |
---|
363 | rtems_vector_offset idtIndex; |
---|
364 | /* |
---|
365 | * IDT raw handler. See comment on handler properties below in function prototype. |
---|
366 | */ |
---|
367 | rtems_raw_irq_hdl hdl; |
---|
368 | /* |
---|
369 | * function for enabling raw interrupts. In order to be consistent |
---|
370 | * with the fact that the raw connexion can defined in the |
---|
371 | * libcpu library, this library should have no knowledge of |
---|
372 | * board specific hardware to manage interrupts and thus the |
---|
373 | * "on" routine must enable the irq both at device and PIC level. |
---|
374 | * |
---|
375 | */ |
---|
376 | rtems_raw_irq_enable on; |
---|
377 | /* |
---|
378 | * function for disabling raw interrupts. In order to be consistent |
---|
379 | * with the fact that the raw connexion can defined in the |
---|
380 | * libcpu library, this library should have no knowledge of |
---|
381 | * board specific hardware to manage interrupts and thus the |
---|
382 | * "on" routine must disable the irq both at device and PIC level. |
---|
383 | * |
---|
384 | */ |
---|
385 | rtems_raw_irq_disable off; |
---|
386 | /* |
---|
387 | * function enabling to know what interrupt may currently occur |
---|
388 | */ |
---|
389 | rtems_raw_irq_is_enabled isOn; |
---|
390 | }rtems_raw_irq_connect_data; |
---|
391 | |
---|
392 | typedef struct { |
---|
393 | /* |
---|
394 | * size of all the table fields (*Tbl) described below. |
---|
395 | */ |
---|
396 | unsigned int idtSize; |
---|
397 | /* |
---|
398 | * Default handler used when disconnecting interrupts. |
---|
399 | */ |
---|
400 | rtems_raw_irq_connect_data defaultRawEntry; |
---|
401 | /* |
---|
402 | * Table containing initials/current value. |
---|
403 | */ |
---|
404 | rtems_raw_irq_connect_data* rawIrqHdlTbl; |
---|
405 | }rtems_raw_irq_global_settings; |
---|
406 | |
---|
407 | #include <rtems/score/idtr.h> |
---|
408 | |
---|
409 | /* |
---|
410 | * C callable function enabling to get handler currently connected to a vector |
---|
411 | * |
---|
412 | */ |
---|
413 | rtems_raw_irq_hdl get_hdl_from_vector(rtems_vector_offset); |
---|
414 | |
---|
415 | /* |
---|
416 | * C callable function enabling to set up one raw idt entry |
---|
417 | */ |
---|
418 | extern int i386_set_idt_entry (const rtems_raw_irq_connect_data*); |
---|
419 | |
---|
420 | /* |
---|
421 | * C callable function enabling to get one current raw idt entry |
---|
422 | */ |
---|
423 | extern int i386_get_current_idt_entry (rtems_raw_irq_connect_data*); |
---|
424 | |
---|
425 | /* |
---|
426 | * C callable function enabling to remove one current raw idt entry |
---|
427 | */ |
---|
428 | extern int i386_delete_idt_entry (const rtems_raw_irq_connect_data*); |
---|
429 | |
---|
430 | /* |
---|
431 | * C callable function enabling to init idt. |
---|
432 | * |
---|
433 | * CAUTION : this function assumes that the IDTR register |
---|
434 | * has been already set. |
---|
435 | */ |
---|
436 | extern int i386_init_idt (rtems_raw_irq_global_settings* config); |
---|
437 | |
---|
438 | /* |
---|
439 | * C callable function enabling to get actual idt configuration |
---|
440 | */ |
---|
441 | extern int i386_get_idt_config (rtems_raw_irq_global_settings** config); |
---|
442 | |
---|
443 | |
---|
444 | /* |
---|
445 | * See page 11.12 Figure 11-8. |
---|
446 | * |
---|
447 | */ |
---|
448 | /** |
---|
449 | * @brief describes one entry of Global/Local Descriptor Table |
---|
450 | */ |
---|
451 | typedef struct { |
---|
452 | unsigned int limit_15_0 : 16; |
---|
453 | unsigned int base_address_15_0 : 16; |
---|
454 | unsigned int base_address_23_16 : 8; |
---|
455 | unsigned int type : 4; |
---|
456 | unsigned int descriptor_type : 1; |
---|
457 | unsigned int privilege : 2; |
---|
458 | unsigned int present : 1; |
---|
459 | unsigned int limit_19_16 : 4; |
---|
460 | unsigned int available : 1; |
---|
461 | unsigned int fixed_value_bits : 1; |
---|
462 | unsigned int operation_size : 1; |
---|
463 | unsigned int granularity : 1; |
---|
464 | unsigned int base_address_31_24 : 8; |
---|
465 | } RTEMS_PACKED segment_descriptors; |
---|
466 | |
---|
467 | /* |
---|
468 | * C callable function enabling to get easilly usable info from |
---|
469 | * the actual value of GDT register. |
---|
470 | */ |
---|
471 | extern void i386_get_info_from_GDTR (segment_descriptors** table, |
---|
472 | uint16_t* limit); |
---|
473 | /* |
---|
474 | * C callable function enabling to change the value of GDT register. Must be called |
---|
475 | * with interrupts masked at processor level!!!. |
---|
476 | */ |
---|
477 | extern void i386_set_GDTR (segment_descriptors*, |
---|
478 | uint16_t limit); |
---|
479 | |
---|
480 | /** |
---|
481 | * @brief Allows to set a GDT entry. |
---|
482 | * |
---|
483 | * Puts global descriptor \p sd to the global descriptor table on index |
---|
484 | * \p segment_selector_index |
---|
485 | * |
---|
486 | * @param[in] segment_selector_index index to GDT entry |
---|
487 | * @param[in] sd structure to be coppied to given \p segment_selector in GDT |
---|
488 | * @retval 0 FAILED out of GDT range or index is 0, which is not valid |
---|
489 | * index in GDT |
---|
490 | * @retval 1 SUCCESS |
---|
491 | */ |
---|
492 | extern uint32_t i386_raw_gdt_entry (uint16_t segment_selector_index, |
---|
493 | segment_descriptors* sd); |
---|
494 | |
---|
495 | /** |
---|
496 | * @brief fills \p sd with provided \p base in appropriate fields of \p sd |
---|
497 | * |
---|
498 | * @param[in] base 32-bit address to be set as descriptor's base |
---|
499 | * @param[out] sd descriptor being filled with \p base |
---|
500 | */ |
---|
501 | extern void i386_fill_segment_desc_base (uint32_t base, |
---|
502 | segment_descriptors* sd); |
---|
503 | |
---|
504 | /** |
---|
505 | * @brief fills \p sd with provided \p limit in appropriate fields of \p sd |
---|
506 | * |
---|
507 | * sets granularity bit if necessary |
---|
508 | * |
---|
509 | * @param[in] limit 32-bit value representing number of limit bytes |
---|
510 | * @param[out] sd descriptor being filled with \p limit |
---|
511 | */ |
---|
512 | extern void i386_fill_segment_desc_limit (uint32_t limit, |
---|
513 | segment_descriptors* sd); |
---|
514 | |
---|
515 | /* |
---|
516 | * C callable function enabling to set up one raw interrupt handler |
---|
517 | */ |
---|
518 | extern uint32_t i386_set_gdt_entry (uint16_t segment_selector, |
---|
519 | uint32_t base, |
---|
520 | uint32_t limit); |
---|
521 | |
---|
522 | /** |
---|
523 | * @brief Returns next empty descriptor in GDT. |
---|
524 | * |
---|
525 | * Number of descriptors that can be returned depends on \a GDT_SIZE |
---|
526 | * |
---|
527 | * @retval 0 FAILED GDT is full |
---|
528 | * @retval <1;65535> segment_selector number as index to GDT |
---|
529 | */ |
---|
530 | extern uint16_t i386_next_empty_gdt_entry (void); |
---|
531 | |
---|
532 | /** |
---|
533 | * @brief Copies GDT entry at index \p segment_selector to structure |
---|
534 | * pointed to by \p struct_to_fill |
---|
535 | * |
---|
536 | * @param[in] segment_selector index to GDT table specifying descriptor to copy |
---|
537 | * @param[out] struct_to_fill pointer to memory where will be descriptor coppied |
---|
538 | * @retval 0 FAILED segment_selector out of GDT range |
---|
539 | * @retval <1;65535> retrieved segment_selector |
---|
540 | */ |
---|
541 | extern uint16_t i386_cpy_gdt_entry (uint16_t segment_selector, |
---|
542 | segment_descriptors* struct_to_fill); |
---|
543 | |
---|
544 | /** |
---|
545 | * @brief Returns pointer to GDT table at index given by \p segment_selector |
---|
546 | * |
---|
547 | * @param[in] sgmnt_selector index to GDT table for specifying descriptor to get |
---|
548 | * @retval NULL FAILED segment_selector out of GDT range |
---|
549 | * @retval pointer to GDT table at \p segment_selector |
---|
550 | */ |
---|
551 | extern segment_descriptors* i386_get_gdt_entry (uint16_t sgmnt_selector); |
---|
552 | |
---|
553 | /** |
---|
554 | * @brief Extracts base address from GDT entry pointed to by \p gdt_entry |
---|
555 | * |
---|
556 | * @param[in] gdt_entry pointer to entry from which base should be retrieved |
---|
557 | * @retval base address from GDT entry |
---|
558 | */ |
---|
559 | RTEMS_INLINE_ROUTINE void* i386_base_gdt_entry (segment_descriptors* gdt_entry) |
---|
560 | { |
---|
561 | return (void*)(gdt_entry->base_address_15_0 | |
---|
562 | (gdt_entry->base_address_23_16<<16) | |
---|
563 | (gdt_entry->base_address_31_24<<24)); |
---|
564 | } |
---|
565 | |
---|
566 | /** |
---|
567 | * @brief Extracts limit in bytes from GDT entry pointed to by \p gdt_entry |
---|
568 | * |
---|
569 | * @param[in] gdt_entry pointer to entry from which limit should be retrieved |
---|
570 | * @retval limit value in bytes from GDT entry |
---|
571 | */ |
---|
572 | extern uint32_t i386_limit_gdt_entry (segment_descriptors* gdt_entry); |
---|
573 | |
---|
574 | /* |
---|
575 | * See page 11.18 Figure 11-12. |
---|
576 | * |
---|
577 | */ |
---|
578 | |
---|
579 | typedef struct { |
---|
580 | unsigned int offset : 12; |
---|
581 | unsigned int page : 10; |
---|
582 | unsigned int directory : 10; |
---|
583 | }la_bits; |
---|
584 | |
---|
585 | typedef union { |
---|
586 | la_bits bits; |
---|
587 | unsigned int address; |
---|
588 | }linear_address; |
---|
589 | |
---|
590 | |
---|
591 | /* |
---|
592 | * See page 11.20 Figure 11-14. |
---|
593 | * |
---|
594 | */ |
---|
595 | |
---|
596 | typedef struct { |
---|
597 | unsigned int present : 1; |
---|
598 | unsigned int writable : 1; |
---|
599 | unsigned int user : 1; |
---|
600 | unsigned int write_through : 1; |
---|
601 | unsigned int cache_disable : 1; |
---|
602 | unsigned int accessed : 1; |
---|
603 | unsigned int reserved1 : 1; |
---|
604 | unsigned int page_size : 1; |
---|
605 | unsigned int reserved2 : 1; |
---|
606 | unsigned int available : 3; |
---|
607 | unsigned int page_frame_address : 20; |
---|
608 | }page_dir_bits; |
---|
609 | |
---|
610 | typedef union { |
---|
611 | page_dir_bits bits; |
---|
612 | unsigned int dir_entry; |
---|
613 | }page_dir_entry; |
---|
614 | |
---|
615 | typedef struct { |
---|
616 | unsigned int present : 1; |
---|
617 | unsigned int writable : 1; |
---|
618 | unsigned int user : 1; |
---|
619 | unsigned int write_through : 1; |
---|
620 | unsigned int cache_disable : 1; |
---|
621 | unsigned int accessed : 1; |
---|
622 | unsigned int dirty : 1; |
---|
623 | unsigned int reserved2 : 2; |
---|
624 | unsigned int available : 3; |
---|
625 | unsigned int page_frame_address : 20; |
---|
626 | }page_table_bits; |
---|
627 | |
---|
628 | typedef union { |
---|
629 | page_table_bits bits; |
---|
630 | unsigned int table_entry; |
---|
631 | } page_table_entry; |
---|
632 | |
---|
633 | /* |
---|
634 | * definitions related to page table entry |
---|
635 | */ |
---|
636 | #define PG_SIZE 0x1000 |
---|
637 | #define MASK_OFFSET 0xFFF |
---|
638 | #define MAX_ENTRY (PG_SIZE/sizeof(page_dir_entry)) |
---|
639 | #define FOUR_MB 0x400000 |
---|
640 | #define MASK_FLAGS 0x1A |
---|
641 | |
---|
642 | #define PTE_PRESENT 0x01 |
---|
643 | #define PTE_WRITABLE 0x02 |
---|
644 | #define PTE_USER 0x04 |
---|
645 | #define PTE_WRITE_THROUGH 0x08 |
---|
646 | #define PTE_CACHE_DISABLE 0x10 |
---|
647 | |
---|
648 | typedef struct { |
---|
649 | page_dir_entry pageDirEntry[MAX_ENTRY]; |
---|
650 | } page_directory; |
---|
651 | |
---|
652 | typedef struct { |
---|
653 | page_table_entry pageTableEntry[MAX_ENTRY]; |
---|
654 | } page_table; |
---|
655 | |
---|
656 | /* Simpler names for the i80x86 I/O instructions */ |
---|
657 | #define outport_byte( _port, _value ) i386_outport_byte( _port, _value ) |
---|
658 | #define outport_word( _port, _value ) i386_outport_word( _port, _value ) |
---|
659 | #define outport_long( _port, _value ) i386_outport_long( _port, _value ) |
---|
660 | #define inport_byte( _port, _value ) i386_inport_byte( _port, _value ) |
---|
661 | #define inport_word( _port, _value ) i386_inport_word( _port, _value ) |
---|
662 | #define inport_long( _port, _value ) i386_inport_long( _port, _value ) |
---|
663 | |
---|
664 | #ifdef __cplusplus |
---|
665 | } |
---|
666 | #endif |
---|
667 | |
---|
668 | #endif /* !ASM */ |
---|
669 | |
---|
670 | #endif |
---|