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