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

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