Main Page   Modules   Alphabetical List   Data Structures   File List   Data Fields   Globals   Related Pages  

mem.h

Go to the documentation of this file.
00001 /*!     \file include/arch/mem.h
00002  *      \brief Low level (i386) memory manager header.
00003  *      \author Andrea Righi <drizzt@inwind.it>
00004  *      \date Last update:\n
00005  *              2004-01-04 Andrea Righi:
00006                         Improved assembler routies.\n
00007  *      \note Copyright (C) 2003 Andrea Righi
00008  */
00009 
00010 #ifndef MEM_H
00011 #define MEM_H
00012 
00013 // Kernel virtual memory map //
00014 #include <kernel/kernel_map.h>
00015 
00016 /** \ingroup Memory
00017  *  \defgroup KLowLevelMemoryManager Low-Level Memory Manager
00018  *  The low level memory operators (based on i386-architecture).
00019  *  @{
00020  */
00021 
00022 //! Number of entries in the GDT (Global Descriptor Table).
00023 #define GDT_DIM         8192
00024 //! GDT entry dimension in bytes.
00025 #define GDT_ENTRY_DIM   sizeof(gdt_entry_t)
00026 
00027 // Segment Constants //
00028 #define PRESENT         0x80    //!< The segment is present.
00029 #define CODE            0x18    //!< A code segment type.
00030 #define DATA            0x10    //!< A data segment type.
00031 #define EXP_DOWN        0x04    //!< The segment grows downward.
00032 #define CONFORMING      0x04    //!< A conforming code segment.
00033 #define READABLE        0x02    //!< A readable segment.
00034 #define WRITEABLE       0x02    //!< A writeable segment.
00035 
00036 //! A standard code segment.
00037 #define CODE_SEG        (CODE | PRESENT | READABLE)
00038 //! A standard data segment.
00039 #define DATA_SEG        (DATA | PRESENT | WRITEABLE)
00040 //! A standard stack segment.
00041 #define STACK_SEG       DATA_SEG
00042 //! A standard TSS segment.
00043 #define TSS_SEG         (PRESENT | 0x09)
00044 //! A real-mode area segment.
00045 #define REAL_SEG        (CODE | PRESENT | READABLE)
00046 
00047 #define INT_GATE        (PRESENT | 0x0E) //!< 32-bit Interrupt Gate.
00048 #define TASK_GATE       (PRESENT | 0x05) //!< Task Gate.
00049 #define TRAP_GATE       (PRESENT | 0x0F) //!< 32-bit Trap Gate.
00050 
00051 //! Descriptor Privilege Level 0 (maximum privilege).
00052 #define DPL_0           0x00
00053 //! Descriptor Privilege Level 1.
00054 #define DPL_1           0x20
00055 //! Descriptor Privilege Level 2.
00056 #define DPL_2           0x40
00057 //! Descriptor Privilege Level 3 (minimum privilege).
00058 #define DPL_3           0x60
00059 
00060 //! The busy bit of the TSS descriptor (to avoid recursive tasks).
00061 #define BUSY_FLAG       0x02
00062 
00063 //! Default size of the istructions (for a code segment) or
00064 //! the stack alignment (for a stack segment).
00065 #define ATTR_32BIT      0x40
00066 //! The granularity of the segment size (limit field):
00067 //! \li 0 => byte granularity;
00068 //! \li 1 => page granularity (4096 bytes).
00069 #define ATTR_GRANUL     0x80
00070 
00071 //! This is the data selector for the kernel.
00072 //! REMEBER!!! It is defined also into irq.S!
00073 #define KERNEL_DATA             0x08
00074 //! This is the stack selector for the kernel.
00075 #define KERNEL_STACK            0x08
00076 //! This is the code selector for the kernel.
00077 #define KERNEL_CODE             0x10
00078 
00079 //! This is the selector for the user data segment.
00080 #define USER_DATA               0x18
00081 //! This is the selector for the user stack segment.
00082 #define USER_STACK              0x18
00083 //! This is the selector for the user code segment.
00084 #define USER_CODE               0x20
00085 
00086 //! (real-mode) Extract the segment part of a linear address.
00087 #define SEGMENT(linear)         ( (word)(((dword)(linear) & 0xFFFF0000) >> 4) )
00088 //! (real-mode) Extract the offset part of a linear address.
00089 #define OFFSET(linear)          ( (word)((dword)(linear) & 0xFFFF) )
00090 //! (real-mode) Make a linear address from a segment:offset address.
00091 #define LINEAR(seg, off)        ( (dword)(((word)(seg) << 4) + (word)(off)) )
00092 
00093 //! (i386) far pointer.
00094 typedef uint32_t FARPTR;
00095 //! (i386) far pointer.
00096 typedef uint32_t far;
00097 
00098 //! (i386) Make a far pointer from \p seg segment and \p off offset.
00099 //! \note In this case a segment is considered as 65536(0x10000) bytes.
00100 #define MK_FP(seg, off)         ((FARPTR) (((uint32_t) (seg) << 16) | (uint16_t) (off)))
00101 //! (i386) Get the segment from the far pointer \p fp.
00102 #define FP_SEG(fp)              (((FARPTR) fp) >> 16)
00103 //! (i386) Get the offset from the far pointer \p fp.
00104 #define FP_OFF(fp)              (((FARPTR) fp) & 0xffff)
00105 //! Translate a real-mode segment:offset address to the linear address.
00106 //! This macro is equivalent to LINEAR(seg, off) macro.
00107 #define FP_TO_LINEAR(seg, off)  ((void*) ((((uint16_t) (seg)) << 4) + ((uint16_t) (off))))
00108 
00109 //! GDT structure.
00110 /** P=Present, DPL=Descriptor Privilege Level, S=Descriptor type (0=system; 1=code or data),
00111  * Type=Segment type, G=Granularity, D/B=Default operation size(0=16bit; 1=32bit segment),
00112  * AVL=Available for use by system software.
00113  */
00114 typedef struct gdt_entry
00115 {
00116         word limit;
00117         word base0_15;
00118         byte base16_23;
00119         byte attribs0_7;  //!< P(1bit) | DPL(2bit) | S(1bit) | Type(4bit)
00120         byte attribs8_15; //!< G(1bit) | D/B(1bit) | 0(1bit) | AVL(1bit) | limit16_19(4bit)
00121         byte base24_31;
00122 } __attribute__ ((packed)) gdt_entry_t;
00123 
00124 //! The GDT register format.
00125 typedef struct gdt_register
00126 {
00127         uint16_t limit;
00128         uint32_t base;
00129 } __attribute__ ((packed)) gdt_reg;
00130 
00131 //! \brief Sets \p count bytes to \p val.
00132 //! \param dest_ptr The destination pointer.
00133 //! \param val The value to set.
00134 //! \param count How many bytes to set.
00135 static __inline__ void memsetb(void *dest_ptr, int val, dword count)
00136 {
00137         __asm__ __volatile__ (
00138                 "cld\n"
00139                 "rep stosb"
00140                 : :"D"(dest_ptr), "c"(count), "a"(val));
00141         __asm__("": : :"%edi", "%ecx");
00142 }
00143 
00144 //! \brief Sets \p count words to \p val.
00145 //! \param dest_ptr The destination pointer.
00146 //! \param val The value to set.
00147 //! \param count How many words to set.
00148 static __inline__ void memsetw(void *dest_ptr, word val, dword count)
00149 {
00150         __asm__ __volatile__ (
00151                 "cld\n"
00152                 "rep stosw"
00153                 : :"D"(dest_ptr), "c"(count), "a"(val));
00154         __asm__("": : :"%edi", "%ecx");
00155 }
00156 
00157 //! \brief Sets \p count double words to \p val.
00158 //! \param dest_ptr The destination pointer.
00159 //! \param val The value to set.
00160 //! \param count How many double words to set.
00161 static __inline__ void memsetl(void *dest_ptr, dword val, dword count)
00162 {
00163         __asm__ __volatile__ (
00164                 "cld\n"
00165                 "rep stosl"
00166                 : :"D"(dest_ptr), "c"(count), "a"(val));
00167         __asm__("": : :"%edi", "%ecx");
00168 }
00169 
00170 //! \brief Optimized version of memset.
00171 //! \param s The destination pointer.
00172 //! \param c The value to set.
00173 //! \param count How many bytes to set.
00174 //! \return The destination pointer.
00175 static __inline__ void *memset(void *s, unsigned long c, size_t count)
00176 {
00177         int d0, d1;
00178         __asm__ __volatile__(
00179                 "cld\n\t"
00180                 "rep ; stosl\n\t"
00181                 "testb $2,%b3\n\t"
00182                 "je 1f\n\t"
00183                 "stosw\n"
00184                 "1:\ttestb $1,%b3\n\t"
00185                 "je 2f\n\t"
00186                 "stosb\n"
00187                 "2:"
00188                 : "=&c" (d0), "=&D" (d1)
00189                 :"a" (c), "q" (count), "0" (count/4), "1" ((long)s)
00190                 :"memory");
00191         return( s );
00192 }
00193 
00194 //! \brief Copy \p count bytes from \p org_ptr to \p dest_ptr.
00195 //! \param dest_ptr The destination pointer.
00196 //! \param org_ptr The source pointer.
00197 //! \param count How many bytes to copy.
00198 static __inline__ void memcpyb(void *dest_ptr, const void *org_ptr, dword count)
00199 {
00200         __asm__ __volatile__ (
00201                 "cld\n"
00202                 "rep movsb"
00203                 : :"D"(dest_ptr), "S"(org_ptr), "c"(count));
00204         __asm__("": : :"%ecx", "%edi", "%esi");
00205 }
00206 
00207 //! \brief Copy \p count words from \p org_ptr to \p dest_ptr.
00208 //! \param dest_ptr The destination pointer.
00209 //! \param org_ptr The source pointer.
00210 //! \param count How many words to copy.
00211 static __inline__ void memcpyw(void *dest_ptr, const void *org_ptr, dword count)
00212 {
00213         __asm__ __volatile__ (
00214                 "cld\n"
00215                 "rep movsw"
00216                 : :"D"(dest_ptr), "S"(org_ptr), "c"(count));
00217         __asm__("": : :"%ecx", "%edi", "%esi");
00218 }
00219 
00220 //! \brief Copy \p count double words from \p org_ptr to \p dest_ptr.
00221 //! \param dest_ptr The destination pointer.
00222 //! \param org_ptr The source pointer.
00223 //! \param count How many double words to copy.
00224 static __inline__ void memcpyl(void *dest_ptr, const void *org_ptr, dword count)
00225 {
00226         __asm__ __volatile__ (
00227                 "cld\n"
00228                 "rep movsl"
00229                 : :"D"(dest_ptr), "S"(org_ptr), "c"(count));
00230         __asm__("": : :"%ecx", "%edi", "%esi");
00231 }
00232 
00233 //! \brief Optimized version of memcpy.
00234 //! \param to The destination pointer.
00235 //! \param from The source pointer.
00236 //! \param n How many bytes to copy.
00237 //! \return The destination pointer.
00238 static __inline__ void *memcpy(void *to, const void *from, size_t n)
00239 {
00240         int d0, d1, d2;
00241         __asm__ __volatile__(
00242                 "cld\n\t"
00243                 "rep ; movsl\n\t"
00244                 "testb $2,%b4\n\t"
00245                 "je 1f\n\t"
00246                 "movsw\n"
00247                 "1:\ttestb $1,%b4\n\t"
00248                 "je 2f\n\t"
00249                 "movsb\n"
00250                 "2:"
00251                 : "=&c" (d0), "=&D" (d1), "=&S" (d2)
00252                 :"0" (n/4), "q" (n),"1" ((long) to),"2" ((long) from)
00253                 : "memory");
00254         return( to );
00255 }
00256 
00257 //! \brief
00258 //!     Compares the first \p n bytes of memory areas \p s1 and \p s2.
00259 //!     It returns an integer less than, equal to, or greater than zero
00260 //!     if \p s1 is found, respectively, to be less than, to match, or
00261 //!     be greater than \p s2.
00262 //! \param s1 The first memory pointer of the area to compare.
00263 //! \param s2 The second memory pointer of the area to compare.
00264 //! \param n How many words to compare.
00265 static __inline__ int memcmp(const void *s1, const void *s2, size_t n)
00266 {
00267         int     d0, d1, d2;
00268         register int __res;
00269         __asm__ __volatile__(
00270                 "cld\n\t"
00271                 "repe\n\t"
00272                 "cmpsb\n\t"
00273                 "je 1f\n\t"
00274                 "sbbl %0,%0\n\t"
00275                 "orb $1,%b0\n"
00276                 "1:"
00277         :"=a" (__res), "=&S" (d0), "=&D" (d1), "=&c" (d2)
00278         :"0" (0), "1" (s1), "2" (s2), "3" (n));
00279         return( __res );
00280 }
00281 
00282 //! \brief Find a byte into a memory area.
00283 //! \param cs The pointer of the memory area.
00284 //! \param c The character to find.
00285 //! \param count The size of the memory area.
00286 //! \return
00287 //!     The address of the first occurrence or 0 if the char has not
00288 //!     been found.
00289 static __inline__ void *memchr(const void *cs, int c, size_t count)
00290 {
00291         int d0;
00292         register void * __res;
00293         if (!count)
00294                 return( 0 );
00295         __asm__ __volatile__(
00296                 "cld\n\t"
00297                 "repne\n\t"
00298                 "scasb\n\t"
00299                 "je 1f\n\t"
00300                 "movl $1,%0\n"
00301                 "1:\tdecl %0"
00302                 :"=D" (__res), "=&c" (d0) : "a" (c),"0" (cs),"1" (count));
00303         return( __res );
00304 }
00305 
00306 //! \brief Update segment registers with kernel selectors.
00307 static __inline__ void k_update_segment_regs()
00308 {
00309         __asm__ __volatile__(
00310                 "ljmp %0, $1f\n"
00311                 "nop\n"
00312                 "1: mov %1, %%ds\n"
00313                 "mov %1, %%es\n"
00314                 "mov %1, %%ss\n"
00315                 "nop\n"
00316                 "mov %1, %%fs\n"
00317                 "mov %1, %%gs\n"
00318                 : : "i"(KERNEL_CODE), "r"(KERNEL_DATA) );
00319 }
00320 
00321 word setup_GDT_entry(word limit, dword base, byte attribs0_7, byte attribs8_15);
00322 void remove_GDT_entry(word sel);
00323 void install_GDT();
00324 
00325 /** @} */ // end of KLowLevelMemoryManager
00326 
00327 #endif

Generated on Fri Feb 20 15:32:16 2004 for Minirighi by doxygen1.2.18