[6d6891e] | 1 | /** |
---|
[d9e0006] | 2 | * @file |
---|
[d23c44d5] | 3 | * |
---|
[d9e0006] | 4 | * @brief Intel I386 CPU Dependent Source |
---|
[d23c44d5] | 5 | * |
---|
[d9e0006] | 6 | * This include file contains information pertaining to the Intel |
---|
| 7 | * i386 processor. |
---|
[6d6891e] | 8 | */ |
---|
| 9 | |
---|
| 10 | /* |
---|
[328bd35] | 11 | * COPYRIGHT (c) 1989-2016. |
---|
[7908ba5b] | 12 | * On-Line Applications Research Corporation (OAR). |
---|
| 13 | * |
---|
[328bd35] | 14 | * Copyright (C) 1998 Eric Valette (valette@crf.canon.fr) |
---|
| 15 | * Canon Centre Recherche France. |
---|
| 16 | * |
---|
[7908ba5b] | 17 | * The license and distribution terms for this file may be |
---|
| 18 | * found in the file LICENSE in this distribution or at |
---|
[c499856] | 19 | * http://www.rtems.org/license/LICENSE. |
---|
[7908ba5b] | 20 | */ |
---|
| 21 | |
---|
[7f70d1b7] | 22 | #ifndef _RTEMS_SCORE_I386_H |
---|
| 23 | #define _RTEMS_SCORE_I386_H |
---|
[7908ba5b] | 24 | |
---|
| 25 | #ifdef __cplusplus |
---|
| 26 | extern "C" { |
---|
| 27 | #endif |
---|
| 28 | |
---|
[328bd35] | 29 | #include <rtems/score/interrupts.h> |
---|
| 30 | #include <rtems/score/registers.h> |
---|
| 31 | |
---|
[7908ba5b] | 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 |
---|
[318f591] | 44 | * pentiumpro |
---|
[7908ba5b] | 45 | * |
---|
| 46 | * CPU Model Feature Flags: |
---|
| 47 | * |
---|
[84c53452] | 48 | * I386_HAS_BSWAP: Defined to "1" if the instruction for endian swapping |
---|
[7908ba5b] | 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. |
---|
[d23c44d5] | 53 | * As of at least gcc 4.7, i386 soft-float was obsoleted. |
---|
| 54 | * Thus this is always set to "1". |
---|
[7908ba5b] | 55 | */ |
---|
[95990b57] | 56 | #define I386_HAS_FPU 1 |
---|
[7908ba5b] | 57 | |
---|
[95990b57] | 58 | #if defined(__pentiumpro__) |
---|
[7908ba5b] | 59 | |
---|
[d23c44d5] | 60 | #define CPU_MODEL_NAME "Pentium Pro" |
---|
[7908ba5b] | 61 | |
---|
[95990b57] | 62 | #elif defined(__i586__) |
---|
[7908ba5b] | 63 | |
---|
[d23c44d5] | 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 |
---|
[7908ba5b] | 71 | |
---|
[95990b57] | 72 | #elif defined(__i486__) |
---|
[7908ba5b] | 73 | |
---|
[d23c44d5] | 74 | #define CPU_MODEL_NAME "i486dx" |
---|
[7908ba5b] | 75 | |
---|
[95990b57] | 76 | #elif defined(__i386__) |
---|
[7908ba5b] | 77 | |
---|
[d23c44d5] | 78 | #define I386_HAS_BSWAP 0 |
---|
| 79 | #define CPU_MODEL_NAME "i386 with i387" |
---|
[318f591] | 80 | |
---|
[7908ba5b] | 81 | #else |
---|
[d23c44d5] | 82 | #error "Unknown CPU Model" |
---|
[7908ba5b] | 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 | |
---|
[962c247e] | 106 | static inline uint32_t i386_swap_u32( |
---|
| 107 | uint32_t value |
---|
[7908ba5b] | 108 | ) |
---|
| 109 | { |
---|
[962c247e] | 110 | uint32_t lout; |
---|
[7908ba5b] | 111 | |
---|
| 112 | #if (I386_HAS_BSWAP == 0) |
---|
[c05f6238] | 113 | __asm__ volatile( "rorw $8,%%ax;" |
---|
[7908ba5b] | 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 | } |
---|
[328bd35] | 121 | #define CPU_swap_u32( _value ) i386_swap_u32( _value ) |
---|
[7908ba5b] | 122 | |
---|
[afbadfb] | 123 | static inline uint16_t i386_swap_u16( |
---|
| 124 | uint16_t value |
---|
[7908ba5b] | 125 | ) |
---|
| 126 | { |
---|
[d23c44d5] | 127 | unsigned short sout; |
---|
[7908ba5b] | 128 | |
---|
[d23c44d5] | 129 | __asm__ volatile( "rorw $8,%0" : "=r" (sout) : "0" (value)); |
---|
| 130 | return (sout); |
---|
[7908ba5b] | 131 | } |
---|
[328bd35] | 132 | #define CPU_swap_u16( _value ) i386_swap_u16( _value ) |
---|
[7908ba5b] | 133 | |
---|
[8ef3818] | 134 | /* |
---|
| 135 | * Added for pagination management |
---|
| 136 | */ |
---|
[1b502424] | 137 | static inline unsigned int i386_get_cr0(void) |
---|
[8ef3818] | 138 | { |
---|
| 139 | register unsigned int segment = 0; |
---|
| 140 | |
---|
[c05f6238] | 141 | __asm__ volatile ( "movl %%cr0,%0" : "=r" (segment) : "0" (segment) ); |
---|
[8ef3818] | 142 | |
---|
| 143 | return segment; |
---|
| 144 | } |
---|
| 145 | |
---|
| 146 | static inline void i386_set_cr0(unsigned int segment) |
---|
| 147 | { |
---|
[c05f6238] | 148 | __asm__ volatile ( "movl %0,%%cr0" : "=r" (segment) : "0" (segment) ); |
---|
[8ef3818] | 149 | } |
---|
| 150 | |
---|
[1b502424] | 151 | static inline unsigned int i386_get_cr2(void) |
---|
[8ef3818] | 152 | { |
---|
| 153 | register unsigned int segment = 0; |
---|
| 154 | |
---|
[c05f6238] | 155 | __asm__ volatile ( "movl %%cr2,%0" : "=r" (segment) : "0" (segment) ); |
---|
[8ef3818] | 156 | |
---|
| 157 | return segment; |
---|
| 158 | } |
---|
| 159 | |
---|
[1b502424] | 160 | static inline unsigned int i386_get_cr3(void) |
---|
[8ef3818] | 161 | { |
---|
| 162 | register unsigned int segment = 0; |
---|
| 163 | |
---|
[c05f6238] | 164 | __asm__ volatile ( "movl %%cr3,%0" : "=r" (segment) : "0" (segment) ); |
---|
[8ef3818] | 165 | |
---|
| 166 | return segment; |
---|
| 167 | } |
---|
| 168 | |
---|
| 169 | static inline void i386_set_cr3(unsigned int segment) |
---|
| 170 | { |
---|
[c05f6238] | 171 | __asm__ volatile ( "movl %0,%%cr3" : "=r" (segment) : "0" (segment) ); |
---|
[8ef3818] | 172 | } |
---|
| 173 | |
---|
[7908ba5b] | 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 | |
---|
[038e1dba] | 196 | /** |
---|
| 197 | * @brief Converts real mode pointer {segment, offset} to physical address. |
---|
| 198 | * |
---|
| 199 | * i386_Real_to_physical |
---|
[58af50d] | 200 | * |
---|
[038e1dba] | 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 |
---|
[58af50d] | 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 | |
---|
[038e1dba] | 212 | /** |
---|
[328bd35] | 213 | * @brief Retrieves real mode pointer elements {segmnet, offset} from |
---|
[038e1dba] | 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 |
---|
[58af50d] | 224 | * |
---|
[038e1dba] | 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 |
---|
[58af50d] | 230 | */ |
---|
| 231 | int i386_Physical_to_real( |
---|
| 232 | void *address, |
---|
| 233 | uint16_t *segment, |
---|
| 234 | uint16_t *offset |
---|
| 235 | ); |
---|
| 236 | |
---|
[7908ba5b] | 237 | /* |
---|
[328bd35] | 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. |
---|
[7908ba5b] | 242 | */ |
---|
| 243 | |
---|
[328bd35] | 244 | static __inline__ unsigned short i386_get_cs(void) |
---|
| 245 | { |
---|
| 246 | register unsigned short segment = 0; |
---|
[84c53452] | 247 | |
---|
[328bd35] | 248 | __asm__ volatile ( "movw %%cs,%0" : "=r" (segment) : "0" (segment) ); |
---|
[84c53452] | 249 | |
---|
[328bd35] | 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 | } |
---|
[84c53452] | 288 | |
---|
[328bd35] | 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); |
---|
[84c53452] | 442 | |
---|
[328bd35] | 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 */ |
---|
[7908ba5b] | 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 ) |
---|
[84c53452] | 663 | |
---|
[7908ba5b] | 664 | #ifdef __cplusplus |
---|
| 665 | } |
---|
| 666 | #endif |
---|
| 667 | |
---|
| 668 | #endif /* !ASM */ |
---|
| 669 | |
---|
| 670 | #endif |
---|