SimpleOS

LXR

Navigation



Site hébergé par : enix

The LXR Cross Referencer for SOS

source navigation ]
diff markup ]
identifier search ]
general search ]
 
 
Article:1 ] [ 2 ] [ 3 ] [ 4 ] [ 5 ] [ 6 ] [ 6.5 ] [ 7 ] [ 7.5 ] [ 8 ] [ 9 ] [ 9.5 ]

001 /* Copyright (C) 2004  David Decotigny
002 
003    This program is free software; you can redistribute it and/or
004    modify it under the terms of the GNU General Public License
005    as published by the Free Software Foundation; either version 2
006    of the License, or (at your option) any later version.
007    
008    This program is distributed in the hope that it will be useful,
009    but WITHOUT ANY WARRANTY; without even the implied warranty of
010    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
011    GNU General Public License for more details.
012    
013    You should have received a copy of the GNU General Public License
014    along with this program; if not, write to the Free Software
015    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
016    USA. 
017 */
018 #include "segment.h"
019 
020 #include "idt.h"
021 
022 /**
023  * An entry in the IDT, or "IDTE" in the following, ie a reference to
024  * a interrupt/trap routine or a task gate to handle the sw/hw
025  * interrupts and exceptions.
026  *
027  * @see figure 5-2, intel x86 doc, vol 3
028  */
029 struct x86_idt_entry
030 {
031   /* Low dword */
032   sos_ui16_t offset_low;  /* 15..0, offset of the routine in the segment */
033   sos_ui16_t seg_sel;     /* 31..16, the ID of the segment */
034 
035   /* High dword */
036   sos_ui8_t reserved:5;   /* 4..0 */
037   sos_ui8_t flags:3;      /* 7..5 */
038   sos_ui8_t type:3;       /* 10..8 (interrupt gate, trap gate...) */
039   sos_ui8_t op_size:1;    /* 11 (0=16bits instructions, 1=32bits instr.) */
040   sos_ui8_t zero:1;       /* 12 */
041   sos_ui8_t dpl:2;        /* 14..13 */
042   sos_ui8_t present:1;    /* 15 */
043   sos_ui16_t offset_high; /* 31..16 */
044 } __attribute__((packed));
045 
046 
047 /**
048  * The IDT register, which stores the address and size of the
049  * IDT.
050  *
051  * @see Intel x86 doc vol 3, section 2.4, figure 2-4
052  */
053 struct x86_idt_register
054 {
055   /* The maximum GDT offset allowed to access an entry in the GDT */
056   sos_ui16_t  limit;
057 
058   /* This is not exactly a "virtual" address, ie an adddress such as
059      those of instructions and data; this is a "linear" address, ie an
060      address in the paged memory. However, in SOS we configure the
061      segmented memory as a "flat" space: the 0-4GB segment-based (ie
062      "virtual") addresses directly map to the 0-4GB paged memory (ie
063      "linear"), so that the "linear" addresses are numerically equal
064      to the "virtual" addresses: this base_addr will thus be the same
065      as the address of the gdt array */
066   sos_ui32_t base_addr;
067 } __attribute__((packed, aligned (8)));
068 
069 
070 static struct x86_idt_entry    idt[SOS_IDTE_NUM];
071 
072 sos_ret_t sos_idt_subsystem_setup()
073 {
074   struct x86_idt_register idtr;
075   int i;
076 
077   for (i = 0 ;
078        i < SOS_IDTE_NUM ;
079        i++)
080     {
081       struct x86_idt_entry *idte = idt + i;
082 
083       /* Setup an empty IDTE interrupt gate, see figure 5-2 in Intel
084          x86 doc, vol 3 */
085       idte->seg_sel   = SOS_BUILD_SEGMENT_REG_VALUE(0, FALSE, SOS_SEG_KCODE);
086       idte->reserved  = 0;
087       idte->flags     = 0;
088       idte->type      = 0x6; /* Interrupt gate (110b) */
089       idte->op_size   = 1;   /* 32bits instructions */
090       idte->zero      = 0;
091 
092       /* Disable this IDT entry for the moment */
093       sos_idt_set_handler(i, (sos_vaddr_t)NULL, 0/* Don't care */);
094     }
095 
096   /*
097    * Setup the IDT register, see Intel x86 doc vol 3, section 5.8.
098    */
099 
100   /* Address of the IDT */
101   idtr.base_addr  = (sos_ui32_t) idt;
102 
103   /* The limit is the maximum offset in bytes from the base address of
104      the IDT */
105   idtr.limit      = sizeof(idt) - 1;
106 
107   /* Commit the IDT into the CPU */
108   asm volatile ("lidt %0\n"::"m"(idtr):"memory");
109   
110   return SOS_OK;
111 }
112 
113 
114 sos_ret_t sos_idt_set_handler(int index,
115                               sos_vaddr_t handler_address,
116                               int lowest_priviledge /* 0..3 */)
117 {
118   struct x86_idt_entry *idte;
119 
120   if ((index < 0) || (index >= SOS_IDTE_NUM))
121     return -SOS_EINVAL;
122   if ((lowest_priviledge < 0) || (lowest_priviledge > 3))
123     return -SOS_EINVAL;
124   
125   idte = idt + index;
126   if (handler_address != (sos_vaddr_t)NULL)
127     {
128       idte->offset_low  = handler_address & 0xffff;
129       idte->offset_high = (handler_address >> 16) & 0xffff;
130       idte->dpl         = lowest_priviledge;
131       idte->present     = 1;   /* Yes, there is a handler */
132     }
133   else /* Disable this IDT entry */
134     {
135       idte->offset_low  = 0;
136       idte->offset_high = 0;
137       idte->dpl         = 0;
138       idte->present     = 0;   /* No, there is no handler */
139     }
140 
141   return SOS_OK;
142 }
143 
144 
145 sos_ret_t sos_idt_get_handler(int index,
146                               sos_vaddr_t *handler_address,
147                               int *lowest_priviledge)
148 {
149   if ((index < 0) || (index >= SOS_IDTE_NUM))
150     return -SOS_EINVAL;
151 
152   if (handler_address != NULL)
153     *handler_address = idt[index].offset_low
154                        | (idt[index].offset_high << 16);
155   if (lowest_priviledge != NULL)
156     *lowest_priviledge = idt[index].dpl;
157 
158   return SOS_OK;
159 }

source navigation ] diff markup ] identifier search ] general search ]