source: rtems/c/src/lib/libcpu/i386/cpu.h @ 74d2d940

4.115
Last change on this file since 74d2d940 was 74d2d940, checked in by Jan Dolezal <dolezj21@…>, on Nov 20, 2014 at 2:00:30 PM

i386: global descriptor table manipulation functions

  • Property mode set to 100644
File size: 12.5 KB
Line 
1/*
2 * cpu.h  - This file contains definitions for data structure related
3 *          to Intel system programming. More information can be found
4 *          on Intel site and more precisely in the following book :
5 *
6 *              Pentium Processor familly
7 *              Developper's Manual
8 *
9 *              Volume 3 : Architecture and Programming Manual
10 *
11 * Copyright (C) 1998  Eric Valette (valette@crf.canon.fr)
12 *                     Canon Centre Recherche France.
13 *
14 *  The license and distribution terms for this file may be
15 *  found in the file LICENSE in this distribution or at
16 *  http://www.rtems.org/license/LICENSE.
17 */
18
19#ifndef _LIBCPU_i386_CPU_H
20#define _LIBCPU_i386_CPU_H
21
22#include <rtems/score/registers.h>
23
24#ifndef ASM
25
26/*
27 *  Interrupt Level Macros
28 */
29#include <rtems/score/interrupts.h>
30
31#include <rtems/score/basedefs.h>
32
33/*
34 *  Segment Access Routines
35 *
36 *  NOTE:  Unfortunately, these are still static inlines even when the
37 *         "macro" implementation of the generic code is used.
38 */
39
40static __inline__ unsigned short i386_get_cs(void)
41{
42  register unsigned short segment = 0;
43
44  __asm__ volatile ( "movw %%cs,%0" : "=r" (segment) : "0" (segment) );
45
46  return segment;
47}
48
49static __inline__ unsigned short i386_get_ds(void)
50{
51  register unsigned short segment = 0;
52
53  __asm__ volatile ( "movw %%ds,%0" : "=r" (segment) : "0" (segment) );
54
55  return segment;
56}
57
58static __inline__ unsigned short i386_get_es(void)
59{
60  register unsigned short segment = 0;
61
62  __asm__ volatile ( "movw %%es,%0" : "=r" (segment) : "0" (segment) );
63
64  return segment;
65}
66
67static __inline__ unsigned short i386_get_ss(void)
68{
69  register unsigned short segment = 0;
70
71  __asm__ volatile ( "movw %%ss,%0" : "=r" (segment) : "0" (segment) );
72
73  return segment;
74}
75
76static __inline__ unsigned short i386_get_fs(void)
77{
78  register unsigned short segment = 0;
79
80  __asm__ volatile ( "movw %%fs,%0" : "=r" (segment) : "0" (segment) );
81
82  return segment;
83}
84
85static __inline__ unsigned short i386_get_gs(void)
86{
87  register unsigned short segment = 0;
88
89  __asm__ volatile ( "movw %%gs,%0" : "=r" (segment) : "0" (segment) );
90
91  return segment;
92}
93
94/*
95 *  IO Port Access Routines
96 */
97
98#define i386_outport_byte( _port, _value ) \
99do { register unsigned short __port  = _port; \
100     register unsigned char  __value = _value; \
101     \
102     __asm__ volatile ( "outb %0,%1" : : "a" (__value), "d" (__port) ); \
103   } while (0)
104
105#define i386_outport_word( _port, _value ) \
106do { register unsigned short __port  = _port; \
107     register unsigned short __value = _value; \
108     \
109     __asm__ volatile ( "outw %0,%1" : : "a" (__value), "d" (__port) ); \
110   } while (0)
111
112#define i386_outport_long( _port, _value ) \
113do { register unsigned short __port  = _port; \
114     register unsigned int  __value = _value; \
115     \
116     __asm__ volatile ( "outl %0,%1" : : "a" (__value), "d" (__port) ); \
117   } while (0)
118
119#define i386_inport_byte( _port, _value ) \
120do { register unsigned short __port  = _port; \
121     register unsigned char  __value = 0; \
122     \
123     __asm__ volatile ( "inb %1,%0" : "=a" (__value) \
124                                : "d"  (__port) \
125                  ); \
126     _value = __value; \
127   } while (0)
128
129#define i386_inport_word( _port, _value ) \
130do { register unsigned short __port  = _port; \
131     register unsigned short __value = 0; \
132     \
133     __asm__ volatile ( "inw %1,%0" : "=a" (__value) \
134                                : "d"  (__port) \
135                  ); \
136     _value = __value; \
137   } while (0)
138
139#define i386_inport_long( _port, _value ) \
140do { register unsigned short __port  = _port; \
141     register unsigned int  __value = 0; \
142     \
143     __asm__ volatile ( "inl %1,%0" : "=a" (__value) \
144                                : "d"  (__port) \
145                  ); \
146     _value = __value; \
147   } while (0)
148
149/*
150 * Type definition for raw interrupts.
151 */
152
153typedef unsigned char  rtems_vector_offset;
154
155typedef struct __rtems_raw_irq_connect_data__{
156 /*
157  * IDT vector offset (IRQ line + PC386_IRQ_VECTOR_BASE)
158  */
159  rtems_vector_offset           idtIndex;
160  /*
161   * IDT raw handler. See comment on handler properties below in function prototype.
162   */
163  rtems_raw_irq_hdl             hdl;
164  /*
165   * function for enabling raw interrupts. In order to be consistent
166   * with the fact that the raw connexion can defined in the
167   * libcpu library, this library should have no knowledge of
168   * board specific hardware to manage interrupts and thus the
169   * "on" routine must enable the irq both at device and PIC level.
170   *
171   */
172    rtems_raw_irq_enable        on;
173  /*
174   * function for disabling raw interrupts. In order to be consistent
175   * with the fact that the raw connexion can defined in the
176   * libcpu library, this library should have no knowledge of
177   * board specific hardware to manage interrupts and thus the
178   * "on" routine must disable the irq both at device and PIC level.
179   *
180   */
181  rtems_raw_irq_disable         off;
182  /*
183   * function enabling to know what interrupt may currently occur
184   */
185  rtems_raw_irq_is_enabled      isOn;
186}rtems_raw_irq_connect_data;
187
188typedef struct {
189  /*
190   * size of all the table fields (*Tbl) described below.
191   */
192  unsigned int                  idtSize;
193  /*
194   * Default handler used when disconnecting interrupts.
195   */
196  rtems_raw_irq_connect_data    defaultRawEntry;
197  /*
198   * Table containing initials/current value.
199   */
200  rtems_raw_irq_connect_data*   rawIrqHdlTbl;
201}rtems_raw_irq_global_settings;
202
203#include <rtems/score/idtr.h>
204
205/*
206 * C callable function enabling to get handler currently connected to a vector
207 *
208 */
209rtems_raw_irq_hdl get_hdl_from_vector(rtems_vector_offset);
210
211/*
212 * C callable function enabling to set up one raw idt entry
213 */
214extern int i386_set_idt_entry (const rtems_raw_irq_connect_data*);
215
216/*
217 * C callable function enabling to get one current raw idt entry
218 */
219extern int i386_get_current_idt_entry (rtems_raw_irq_connect_data*);
220
221/*
222 * C callable function enabling to remove one current raw idt entry
223 */
224extern int i386_delete_idt_entry (const rtems_raw_irq_connect_data*);
225
226/*
227 * C callable function enabling to init idt.
228 *
229 * CAUTION : this function assumes that the IDTR register
230 * has been already set.
231 */
232extern int i386_init_idt (rtems_raw_irq_global_settings* config);
233
234/*
235 * C callable function enabling to get actual idt configuration
236 */
237extern int i386_get_idt_config (rtems_raw_irq_global_settings** config);
238
239
240/*
241 * See page 11.12 Figure 11-8.
242 *
243 */
244
245typedef struct {
246  unsigned int limit_15_0               : 16;
247  unsigned int base_address_15_0        : 16;
248  unsigned int base_address_23_16       : 8;
249  unsigned int type                     : 4;
250  unsigned int descriptor_type          : 1;
251  unsigned int privilege                : 2;
252  unsigned int present                  : 1;
253  unsigned int limit_19_16              : 4;
254  unsigned int available                : 1;
255  unsigned int fixed_value_bits         : 1;
256  unsigned int operation_size           : 1;
257  unsigned int granularity              : 1;
258  unsigned int base_address_31_24       : 8;
259} RTEMS_COMPILER_PACKED_ATTRIBUTE segment_descriptors;
260
261/*
262 * C callable function enabling to get easilly usable info from
263 * the actual value of GDT register.
264 */
265extern void i386_get_info_from_GDTR (segment_descriptors** table,
266                                     uint16_t* limit);
267/*
268 * C callable function enabling to change the value of GDT register. Must be called
269 * with interrupts masked at processor level!!!.
270 */
271extern void i386_set_GDTR (segment_descriptors*,
272                           uint16_t limit);
273
274/**
275 * C callable function:
276 * Puts global descriptor @sd to the global descriptor table on index
277 * @segment_selector_index
278 *
279 * @retval  0 FAILED out of GDT range or index is 0, which is not valid
280 *                   index in GDT
281 *          1 SUCCESS
282 */
283extern uint32_t i386_raw_gdt_entry (uint16_t segment_selector_index,
284                               segment_descriptors* sd);
285
286/**
287 * C callable function
288 * fills @sd with provided @base in appropriate fields of @sd
289 *
290 * @param base 32-bit address to be set as descriptor's base
291 * @param sd descriptor being filled with @base
292 */
293extern void i386_fill_segment_desc_base (uint32_t base,
294                                         segment_descriptors* sd);
295
296/**
297 * C callable function
298 * fills @sd with provided @limit in appropriate fields of @sd
299 * also influences granularity bit
300 *
301 * @param limit 32-bit value representing number of limit bytes
302 * @param sd descriptor being filled with @limit
303 */
304extern void i386_fill_segment_desc_limit (uint32_t limit,
305                                          segment_descriptors* sd);
306
307/*
308 * C callable function enabling to set up one raw interrupt handler
309 */
310extern uint32_t i386_set_gdt_entry (uint16_t segment_selector,
311                                    uint32_t base,
312                                    uint32_t limit);
313
314/**
315 * C callable function returns next empty descriptor in GDT.
316 *
317 * @retval  0 FAILED GDT is full
318 *          <1;65535> segment_selector number as index to GDT
319 */
320extern uint16_t i386_next_empty_gdt_entry (void);
321
322/**
323 * Copies GDT entry at index @segment_selector to structure
324 * pointed to by @struct_to_fill
325 *
326 * @param  segment_selector index to GDT table for specifying descriptor to copy
327 * @retval  0 FAILED segment_selector out of GDT range
328 *          <1;65535> retrieved segment_selector
329 */
330extern uint16_t i386_cpy_gdt_entry (uint16_t segment_selector,
331                                    segment_descriptors* struct_to_fill);
332
333/**
334 * Returns pointer to GDT table at index given by @segment_selector
335 *
336 * @param   segment_selector index to GDT table for specifying descriptor to get
337 * @retval  NULL FAILED segment_selector out of GDT range
338 *          pointer to GDT table at @segment_selector
339 */
340extern segment_descriptors* i386_get_gdt_entry (uint16_t sgmnt_selector);
341
342/**
343 * Extracts base address from GDT entry pointed to by @gdt_entry
344 *
345 * @param  gdt_entry pointer to entry from which base should be retrieved
346 * @retval base address from GDT entry
347*/
348RTEMS_INLINE_ROUTINE void* i386_base_gdt_entry (segment_descriptors* gdt_entry)
349{
350    return (void*)(gdt_entry->base_address_15_0 |
351            (gdt_entry->base_address_23_16<<16) |
352            (gdt_entry->base_address_31_24<<24));
353}
354
355/**
356 * Extracts limit in bytes from GDT entry pointed to by @gdt_entry
357 *
358 * @param  gdt_entry pointer to entry from which limit should be retrieved
359 * @retval limit value in bytes from GDT entry
360 */
361extern uint32_t i386_limit_gdt_entry (segment_descriptors* gdt_entry);
362
363/*
364 * See page 11.18 Figure 11-12.
365 *
366 */
367
368typedef struct {
369  unsigned int offset                   : 12;
370  unsigned int page                     : 10;
371  unsigned int directory                : 10;
372}la_bits;
373
374typedef union {
375  la_bits       bits;
376  unsigned int  address;
377}linear_address;
378
379
380/*
381 * See page 11.20 Figure 11-14.
382 *
383 */
384
385typedef struct {
386  unsigned int present                  : 1;
387  unsigned int writable                 : 1;
388  unsigned int user                     : 1;
389  unsigned int write_through            : 1;
390  unsigned int cache_disable            : 1;
391  unsigned int accessed                 : 1;
392  unsigned int reserved1                : 1;
393  unsigned int page_size                : 1;
394  unsigned int reserved2                : 1;
395  unsigned int available                : 3;
396  unsigned int page_frame_address       : 20;
397}page_dir_bits;
398
399typedef union {
400  page_dir_bits bits;
401  unsigned int  dir_entry;
402}page_dir_entry;
403
404typedef struct {
405  unsigned int present                  : 1;
406  unsigned int writable                 : 1;
407  unsigned int user                     : 1;
408  unsigned int write_through            : 1;
409  unsigned int cache_disable            : 1;
410  unsigned int accessed                 : 1;
411  unsigned int dirty                    : 1;
412  unsigned int reserved2                : 2;
413  unsigned int available                : 3;
414  unsigned int page_frame_address       : 20;
415}page_table_bits;
416
417typedef union {
418  page_table_bits       bits;
419  unsigned int          table_entry;
420} page_table_entry;
421
422/*
423 * definitions related to page table entry
424 */
425#define PG_SIZE 0x1000
426#define MASK_OFFSET 0xFFF
427#define MAX_ENTRY (PG_SIZE/sizeof(page_dir_entry))
428#define FOUR_MB       0x400000
429#define MASK_FLAGS 0x1A
430
431#define PTE_PRESENT             0x01
432#define PTE_WRITABLE            0x02
433#define PTE_USER                0x04
434#define PTE_WRITE_THROUGH       0x08
435#define PTE_CACHE_DISABLE       0x10
436
437typedef struct {
438  page_dir_entry pageDirEntry[MAX_ENTRY];
439} page_directory;
440
441typedef struct {
442  page_table_entry pageTableEntry[MAX_ENTRY];
443} page_table;
444
445
446/* C declaration for paging management */
447
448extern int      _CPU_is_cache_enabled(void);
449extern int      _CPU_is_paging_enabled(void);
450extern int      init_paging(void);
451extern void     _CPU_enable_paging(void);
452extern void     _CPU_disable_paging(void);
453extern void     _CPU_disable_cache(void);
454extern void     _CPU_enable_cache(void);
455extern int      _CPU_map_phys_address
456                      (void **mappedAddress, void *physAddress,
457                       int size, int flag);
458extern int      _CPU_unmap_virt_address (void *mappedAddress, int size);
459extern int      _CPU_change_memory_mapping_attribute
460                         (void **newAddress, void *mappedAddress,
461                          unsigned int size, unsigned int flag);
462extern int      _CPU_display_memory_attribute(void);
463
464# endif /* ASM */
465
466#endif
Note: See TracBrowser for help on using the repository browser.