source: rtems/cpukit/score/cpu/i386/include/rtems/score/i386.h @ 2afb22b

5
Last change on this file since 2afb22b was 2afb22b, checked in by Chris Johns <chrisj@…>, on 12/23/17 at 07:18:56

Remove make preinstall

A speciality of the RTEMS build system was the make preinstall step. It
copied header files from arbitrary locations into the build tree. The
header files were included via the -Bsome/build/tree/path GCC command
line option.

This has at least seven problems:

  • The make preinstall step itself needs time and disk space.
  • Errors in header files show up in the build tree copy. This makes it hard for editors to open the right file to fix the error.
  • There is no clear relationship between source and build tree header files. This makes an audit of the build process difficult.
  • The visibility of all header files in the build tree makes it difficult to enforce API barriers. For example it is discouraged to use BSP-specifics in the cpukit.
  • An introduction of a new build system is difficult.
  • Include paths specified by the -B option are system headers. This may suppress warnings.
  • The parallel build had sporadic failures on some hosts.

This patch removes the make preinstall step. All installed header
files are moved to dedicated include directories in the source tree.
Let @RTEMS_CPU@ be the target architecture, e.g. arm, powerpc, sparc,
etc. Let @RTEMS_BSP_FAMILIY@ be a BSP family base directory, e.g.
erc32, imx, qoriq, etc.

The new cpukit include directories are:

  • cpukit/include
  • cpukit/score/cpu/@RTEMS_CPU@/include
  • cpukit/libnetworking

The new BSP include directories are:

  • bsps/include
  • bsps/@RTEMS_CPU@/include
  • bsps/@RTEMS_CPU@/@RTEMS_BSP_FAMILIY@/include

There are build tree include directories for generated files.

The include directory order favours the most general header file, e.g.
it is not possible to override general header files via the include path
order.

The "bootstrap -p" option was removed. The new "bootstrap -H" option
should be used to regenerate the "headers.am" files.

Update #3254.

  • Property mode set to 100644
File size: 17.3 KB
Line 
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
26extern "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
106static 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
123static 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 */
137static 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
146static inline void i386_set_cr0(unsigned int segment)
147{
148  __asm__ volatile ( "movl %0,%%cr0" : "=r" (segment) : "0" (segment) );
149}
150
151static 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
160static 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
169static 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 */
181void *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 */
191void *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 */
205RTEMS_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 */
231int 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
244static __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
253static __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
262static __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
271static __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
280static __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
289static __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 ) \
303do { 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 ) \
310do { 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 ) \
317do { 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 ) \
324do { 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 ) \
334do { 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 ) \
344do { 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
357typedef unsigned char  rtems_vector_offset;
358
359typedef 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
392typedef 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 */
413rtems_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 */
418extern 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 */
423extern 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 */
428extern 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 */
436extern int i386_init_idt (rtems_raw_irq_global_settings* config);
437
438/*
439 * C callable function enabling to get actual idt configuration
440 */
441extern 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 */
451typedef 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 */
471extern 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 */
477extern 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 */
492extern 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 */
501extern 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 */
512extern 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 */
518extern 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 */
530extern 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 */
541extern 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 */
551extern 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*/
559RTEMS_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 */
572extern uint32_t i386_limit_gdt_entry (segment_descriptors* gdt_entry);
573
574/*
575 * See page 11.18 Figure 11-12.
576 *
577 */
578
579typedef struct {
580  unsigned int offset                   : 12;
581  unsigned int page                     : 10;
582  unsigned int directory                : 10;
583}la_bits;
584
585typedef 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
596typedef 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
610typedef union {
611  page_dir_bits bits;
612  unsigned int  dir_entry;
613}page_dir_entry;
614
615typedef 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
628typedef 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
648typedef struct {
649  page_dir_entry pageDirEntry[MAX_ENTRY];
650} page_directory;
651
652typedef 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
Note: See TracBrowser for help on using the repository browser.