source: rtems/c/src/lib/libcpu/i386/cpu.h @ 8dcbc16b

4.104.114.84.95
Last change on this file since 8dcbc16b was 8dcbc16b, checked in by Joel Sherrill <joel.sherrill@…>, on 02/18/99 at 21:41:59

Patch from Ian Lance Taylor <ian@…>:

Here is a patch which slightly improves the i386 interrupt handling
macros. These macros were written to use both input and output
parameters, which is not necessary. This patch changes them to use
only an input or output parameter, as appropriate. It also changes
the constraints to permit the interrupt level to be loaded directly in
and out of memory, rather than always requiring a register.

  • Property mode set to 100644
File size: 12.9 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 found in the file LICENSE in this distribution or at
16 *  http://www.OARcorp.com/rtems/license.html.
17 *
18 * $Id$
19 */
20
21#ifndef _LIBCPU_i386_CPU_H
22#define _LIBCPU_i386_CPU_H
23
24#include <libcpu/registers.h>
25
26
27#ifndef ASM
28
29/*
30 *  Interrupt Level Macros
31 */
32
33#define i386_disable_interrupts( _level ) \
34  { \
35    _level = 0;   /* avoids warnings */ \
36    asm volatile ( "pushf ; \
37                    cli ; \
38                    pop %0" \
39                   : "=rm" ((_level)) \
40    ); \
41  }
42
43#define i386_enable_interrupts( _level )  \
44  { \
45    asm volatile ( "push %0 ; \
46                    popf" \
47                    : "=rm" ((_level)) \
48    ); \
49  }
50
51#define i386_flash_interrupts( _level ) \
52  { \
53    asm volatile ( "push %0 ; \
54                    popf ; \
55                    cli" \
56                    : "=rm" ((_level)) \
57    ); \
58  }
59
60#define i386_get_interrupt_level( _level ) \
61  do { \
62    register unsigned32 _eflags; \
63    \
64    asm volatile ( "pushf ; \
65                    pop %0" \
66                    : "=rm" ((_eflags)) \
67    ); \
68    \
69    _level = (_eflags & EFLAGS_INTR_ENABLE) ? 0 : 1; \
70  } while (0)
71
72#define _CPU_ISR_Disable( _level ) i386_disable_interrupts( _level )
73#define _CPU_ISR_Enable( _level ) i386_enable_interrupts( _level )
74     
75/*
76 *  Segment Access Routines
77 *
78 *  NOTE:  Unfortunately, these are still static inlines even when the
79 *         "macro" implementation of the generic code is used.
80 */
81
82static inline unsigned short i386_get_cs()
83{
84  register unsigned short segment = 0;
85
86  asm volatile ( "movw %%cs,%0" : "=r" (segment) : "0" (segment) );
87
88  return segment;
89}
90
91static inline unsigned short i386_get_ds()
92{
93  register unsigned short segment = 0;
94
95  asm volatile ( "movw %%ds,%0" : "=r" (segment) : "0" (segment) );
96
97  return segment;
98}
99
100static inline unsigned short i386_get_es()
101{
102  register unsigned short segment = 0;
103
104  asm volatile ( "movw %%es,%0" : "=r" (segment) : "0" (segment) );
105
106  return segment;
107}
108
109static inline unsigned short i386_get_ss()
110{
111  register unsigned short segment = 0;
112
113  asm volatile ( "movw %%ss,%0" : "=r" (segment) : "0" (segment) );
114
115  return segment;
116}
117
118static inline unsigned short i386_get_fs()
119{
120  register unsigned short segment = 0;
121
122  asm volatile ( "movw %%fs,%0" : "=r" (segment) : "0" (segment) );
123
124  return segment;
125}
126
127static inline unsigned short i386_get_gs()
128{
129  register unsigned short segment = 0;
130
131  asm volatile ( "movw %%gs,%0" : "=r" (segment) : "0" (segment) );
132
133  return segment;
134}
135
136/*
137 * Added for pagination management
138 */
139
140static inline unsigned int i386_get_cr0()
141{
142  register unsigned int segment = 0;
143
144  asm volatile ( "movl %%cr0,%0" : "=r" (segment) : "0" (segment) );
145
146  return segment;
147}
148
149static inline void i386_set_cr0(unsigned int segment)
150{
151  asm volatile ( "movl %0,%%cr0" : "=r" (segment) : "0" (segment) );
152}
153
154static inline unsigned int i386_get_cr2()
155{
156  register unsigned int segment = 0;
157
158  asm volatile ( "movl %%cr2,%0" : "=r" (segment) : "0" (segment) );
159
160  return segment;
161}
162
163static inline unsigned int i386_get_cr3()
164{
165  register unsigned int segment = 0;
166
167  asm volatile ( "movl %%cr3,%0" : "=r" (segment) : "0" (segment) );
168
169  return segment;
170}
171
172static inline void i386_set_cr3(unsigned int segment)
173{
174  asm volatile ( "movl %0,%%cr3" : "=r" (segment) : "0" (segment) );
175}
176
177/*
178 *  IO Port Access Routines
179 */
180
181#define i386_outport_byte( _port, _value ) \
182   { register unsigned short __port  = _port; \
183     register unsigned char  __value = _value; \
184     \
185     asm volatile ( "outb %0,%1" : "=a" (__value), "=d" (__port) \
186                                 : "0"   (__value), "1"  (__port) \
187                  ); \
188   }
189
190#define i386_outport_word( _port, _value ) \
191   { register unsigned short __port  = _port; \
192     register unsigned short __value = _value; \
193     \
194     asm volatile ( "outw %0,%1" : "=a" (__value), "=d" (__port) \
195                                 : "0"   (__value), "1"  (__port) \
196                  ); \
197   }
198
199#define i386_outport_long( _port, _value ) \
200   { register unsigned short __port  = _port; \
201     register unsigned int  __value = _value; \
202     \
203     asm volatile ( "outl %0,%1" : "=a" (__value), "=d" (__port) \
204                                 : "0"   (__value), "1"  (__port) \
205                  ); \
206   }
207
208#define i386_inport_byte( _port, _value ) \
209   { register unsigned short __port  = _port; \
210     register unsigned char  __value = 0; \
211     \
212     asm volatile ( "inb %1,%0" : "=a" (__value), "=d" (__port) \
213                                : "0"   (__value), "1"  (__port) \
214                  ); \
215     _value = __value; \
216   }
217
218#define i386_inport_word( _port, _value ) \
219   { register unsigned short __port  = _port; \
220     register unsigned short __value = 0; \
221     \
222     asm volatile ( "inw %1,%0" : "=a" (__value), "=d" (__port) \
223                                : "0"   (__value), "1"  (__port) \
224                  ); \
225     _value = __value; \
226   }
227
228#define i386_inport_long( _port, _value ) \
229   { register unsigned short __port  = _port; \
230     register unsigned int  __value = 0; \
231     \
232     asm volatile ( "inl %1,%0" : "=a" (__value), "=d" (__port) \
233                                : "0"   (__value), "1"  (__port) \
234                  ); \
235     _value = __value; \
236   }
237
238/*
239 * Type definition for raw interrupts.
240 */
241
242typedef unsigned char  rtems_vector_offset;
243
244struct  __rtems_raw_irq_connect_data__;
245
246typedef void (*rtems_raw_irq_hdl)               (void);
247typedef void (*rtems_raw_irq_enable)            (const struct __rtems_raw_irq_connect_data__*);
248typedef void (*rtems_raw_irq_disable)           (const struct __rtems_raw_irq_connect_data__*);
249typedef int  (*rtems_raw_irq_is_enabled)        (const struct __rtems_raw_irq_connect_data__*);
250
251typedef struct __rtems_raw_irq_connect_data__{
252 /*
253  * IDT vector offset (IRQ line + PC386_IRQ_VECTOR_BASE)
254  */
255  rtems_vector_offset           idtIndex;
256  /*
257   * IDT raw handler. See comment on handler properties below in function prototype.
258   */
259  rtems_raw_irq_hdl             hdl;
260  /*
261   * function for enabling raw interrupts. In order to be consistent
262   * with the fact that the raw connexion can defined in the
263   * libcpu library, this library should have no knowledge of
264   * board specific hardware to manage interrupts and thus the
265   * "on" routine must enable the irq both at device and PIC level.
266   *
267   */
268    rtems_raw_irq_enable        on;     
269  /*
270   * function for disabling raw interrupts. In order to be consistent
271   * with the fact that the raw connexion can defined in the
272   * libcpu library, this library should have no knowledge of
273   * board specific hardware to manage interrupts and thus the
274   * "on" routine must disable the irq both at device and PIC level.
275   *
276   */
277  rtems_raw_irq_disable         off;
278  /*
279   * function enabling to know what interrupt may currently occur
280   */
281  rtems_raw_irq_is_enabled      isOn;
282}rtems_raw_irq_connect_data;
283
284typedef struct {
285  /*
286   * size of all the table fields (*Tbl) described below.
287   */
288  unsigned int                  idtSize;
289  /*
290   * Default handler used when disconnecting interrupts.
291   */
292  rtems_raw_irq_connect_data    defaultRawEntry;
293  /*
294   * Table containing initials/current value.
295   */
296  rtems_raw_irq_connect_data*   rawIrqHdlTbl;
297}rtems_raw_irq_global_settings;
298
299/*
300 * See page 14.9 Figure 14-2.
301 *
302 */
303typedef struct {
304  unsigned int low_offsets_bits : 16;
305  unsigned int segment_selector : 16;
306  unsigned int fixed_value_bits : 8;
307  unsigned int gate_type        : 5;
308  unsigned int privilege        : 2;
309  unsigned int present          : 1;
310  unsigned int high_offsets_bits: 16;
311}interrupt_gate_descriptor;
312
313
314/*
315 * C callable function enabling to create a interrupt_gate_descriptor
316 */
317void create_interrupt_gate_descriptor (interrupt_gate_descriptor*, rtems_raw_irq_hdl);
318
319/*
320 * C callable function enabling to get handler currently connected to a vector
321 *
322 */
323rtems_raw_irq_hdl get_hdl_from_vector(rtems_vector_offset);
324
325/*
326 * C callable function enabling to get easilly usable info from
327 * the actual value of IDT register.
328 */
329extern void i386_get_info_from_IDTR (interrupt_gate_descriptor** table,
330                                unsigned* limit);
331/*
332 * C callable function enabling to change the value of IDT register. Must be called
333 * with interrupts masked at processor level!!!.
334 */
335extern void i386_set_IDTR (interrupt_gate_descriptor* table,
336                      unsigned limit);
337
338/*
339 * C callable function enabling to set up one raw idt entry
340 */
341extern int i386_set_idt_entry (const rtems_raw_irq_connect_data*);
342
343/*
344 * C callable function enabling to get one current raw idt entry
345 */
346extern int i386_get_current_idt_entry (rtems_raw_irq_connect_data*);
347
348/*
349 * C callable function enabling to remove one current raw idt entry
350 */
351extern int i386_delete_idt_entry (const rtems_raw_irq_connect_data*);
352
353/*
354 * C callable function enabling to init idt.
355 *
356 * CAUTION : this function assumes that the IDTR register
357 * has been already set.
358 */
359extern int i386_init_idt (rtems_raw_irq_global_settings* config);
360
361/*
362 * C callable function enabling to get actual idt configuration
363 */
364extern int i386_get_idt_config (rtems_raw_irq_global_settings** config);
365
366
367/*
368 * See page 11.12 Figure 11-8.
369 *
370 */
371
372typedef struct {
373  unsigned int limit_15_0               : 16;
374  unsigned int base_address_15_0        : 16;
375  unsigned int base_address_23_16       : 8;
376  unsigned int type                     : 4;
377  unsigned int descriptor_type          : 1;
378  unsigned int privilege                : 2;
379  unsigned int present                  : 1;
380  unsigned int limit_19_16              : 4;
381  unsigned int available                : 1;
382  unsigned int fixed_value_bits         : 1;
383  unsigned int operation_size           : 1;
384  unsigned int granularity              : 1;
385  unsigned int base_address_31_24       : 8;
386}segment_descriptors;
387
388/*
389 * C callable function enabling to get easilly usable info from
390 * the actual value of GDT register.
391 */
392extern void i386_get_info_from_GDTR (segment_descriptors** table,
393                                     unsigned* limit);
394/*
395 * C callable function enabling to change the value of GDT register. Must be called
396 * with interrupts masked at processor level!!!.
397 */
398extern void i386_set_GDTR (segment_descriptors*,
399                           unsigned limit);
400
401/*
402 * C callable function enabling to set up one raw interrupt handler
403 */
404extern int i386_set_gdt_entry (unsigned short segment_selector, unsigned base,
405                                             unsigned limit);
406
407/*
408 * See page 11.18 Figure 11-12.
409 *
410 */
411
412typedef struct {
413  unsigned int offset                   : 12;
414  unsigned int page                     : 10;
415  unsigned int directory                : 10;
416}la_bits;
417
418typedef union {
419  la_bits       bits;
420  unsigned int  address;
421}linear_address;
422
423
424/*
425 * See page 11.20 Figure 11-14.
426 *
427 */
428
429typedef struct {
430  unsigned int present                  : 1;
431  unsigned int writable                 : 1;
432  unsigned int user                     : 1;
433  unsigned int write_through            : 1;
434  unsigned int cache_disable            : 1;
435  unsigned int accessed                 : 1;
436  unsigned int reserved1                : 1;
437  unsigned int page_size                : 1;
438  unsigned int reserved2                : 1;
439  unsigned int available                : 3;
440  unsigned int page_frame_address       : 20;
441}page_dir_bits;
442
443typedef union {
444  page_dir_bits bits;
445  unsigned int  dir_entry;
446}page_dir_entry;
447
448typedef struct {
449  unsigned int present                  : 1;
450  unsigned int writable                 : 1;
451  unsigned int user                     : 1;
452  unsigned int write_through            : 1;
453  unsigned int cache_disable            : 1;
454  unsigned int accessed                 : 1;
455  unsigned int dirty                    : 1;
456  unsigned int reserved2                : 2;
457  unsigned int available                : 3;
458  unsigned int page_frame_address       : 20;
459}page_table_bits;
460
461typedef union {
462  page_table_bits       bits;
463  unsigned int          table_entry;
464}page_table_entry;
465 
466/*
467 * definitions related to page table entry
468 */
469#define PG_SIZE 0x1000
470#define MASK_OFFSET 0xFFF
471#define MAX_ENTRY (PG_SIZE/sizeof(page_dir_entry))
472#define FOUR_MB       0x400000
473#define MASK_FLAGS 0x1A
474
475#define PTE_PRESENT             0x01
476#define PTE_WRITABLE            0x02
477#define PTE_USER                0x04
478#define PTE_WRITE_THROUGH       0x08
479#define PTE_CACHE_DISABLE       0x10
480
481typedef struct {
482  page_dir_entry pageDirEntry[MAX_ENTRY];
483}page_directory;
484
485typedef struct {
486  page_table_entry pageTableEntry[MAX_ENTRY];
487}page_table;
488
489static inline void flush_cache(){
490  asm volatile ("wbinvd");
491}
492
493
494/* C declaration for paging management */
495
496extern int      _CPU_is_cache_enabled();
497extern int      _CPU_is_paging_enabled();
498extern int      init_paging();
499extern void     _CPU_enable_paging();
500extern void     _CPU_disable_paging();
501extern void     _CPU_disable_cache();
502extern void     _CPU_enable_cache();
503extern int      _CPU_map_phys_address
504                      (void **mappedAddress, void *physAddress,
505                       int size, int flag);
506extern int      _CPU_unmap_virt_address (void *mappedAddress, int size);
507extern int      _CPU_change_memory_mapping_attribute
508                         (void **newAddress, void *mappedAddress,
509                          unsigned int size, unsigned int flag);
510extern int      _CPU_display_memory_attribute();
511
512# endif /* ASM */
513
514#endif
515
Note: See TracBrowser for help on using the repository browser.