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