RTEMS 6.1-rc6
Loading...
Searching...
No Matches
i386.h
Go to the documentation of this file.
1/* SPDX-License-Identifier: BSD-2-Clause */
2
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
47extern "C" {
48#endif
49
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
127static 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
144static 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 */
158static 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
167static inline void i386_set_cr0(unsigned int segment)
168{
169 __asm__ volatile ( "movl %0,%%cr0" : "=r" (segment) : "0" (segment) );
170}
171
172static 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
181static 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
190static 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 */
202void *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 */
212void *i386_Physical_to_logical(
213 unsigned short segment,
214 void *address
215);
216
226static 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
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
265static __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
274static __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
283static __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
292static __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
301static __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
310static __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 ) \
324do { 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 ) \
331do { 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 ) \
338do { 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 ) \
345do { 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 ) \
355do { 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 ) \
365do { 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
378typedef unsigned char rtems_vector_offset;
379
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;
412
413typedef 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;
427
428#include <rtems/score/idtr.h>
429
430/*
431 * C callable function enabling to get handler currently connected to a vector
432 *
433 */
434rtems_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 */
439extern 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 */
444extern 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 */
449extern 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 */
457extern int i386_init_idt (rtems_raw_irq_global_settings* config);
458
459/*
460 * C callable function enabling to get actual idt configuration
461 */
462extern int i386_get_idt_config (rtems_raw_irq_global_settings** config);
463
464
465/*
466 * See page 11.12 Figure 11-8.
467 *
468 */
472typedef 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 */
492extern 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 */
498extern void i386_set_GDTR (segment_descriptors*,
499 uint16_t limit);
500
513extern uint32_t i386_raw_gdt_entry (uint16_t segment_selector_index,
514 segment_descriptors* sd);
515
522extern void i386_fill_segment_desc_base (uint32_t base,
523 segment_descriptors* sd);
524
533extern 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 */
539extern uint32_t i386_set_gdt_entry (uint16_t segment_selector,
540 uint32_t base,
541 uint32_t limit);
542
551extern uint16_t i386_next_empty_gdt_entry (void);
552
562extern uint16_t i386_cpy_gdt_entry (uint16_t segment_selector,
563 segment_descriptors* struct_to_fill);
564
572extern segment_descriptors* i386_get_gdt_entry (uint16_t sgmnt_selector);
573
580static 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
593extern uint32_t i386_limit_gdt_entry (segment_descriptors* gdt_entry);
594
595/*
596 * See page 11.18 Figure 11-12.
597 *
598 */
599
600typedef struct {
601 unsigned int offset : 12;
602 unsigned int page : 10;
603 unsigned int directory : 10;
604}la_bits;
605
606typedef union {
607 la_bits bits;
608 unsigned int address;
610
611
612/*
613 * See page 11.20 Figure 11-14.
614 *
615 */
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 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;
630
631typedef union {
632 page_dir_bits bits;
633 unsigned int dir_entry;
635
636typedef 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;
648
649typedef union {
650 page_table_bits bits;
651 unsigned int 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
669typedef struct {
670 page_dir_entry pageDirEntry[MAX_ENTRY];
672
673typedef 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
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
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
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:380
Definition: deflate.c:114
Definition: i386.h:600
Definition: i386.h:617
Definition: i386.h:669
Definition: i386.h:636
Definition: i386.h:673
Definition: misc.c:38
Definition: i386.h:413
Definition: i386.h:606
Definition: i386.h:631
Definition: i386.h:649