mm.c

00001 /***************************************************************************
00002                           mm.c  -  description
00003                              -------------------
00004     begin                : Sat Dec 27 2003
00005     copyright            : (C) 2003 by Dynacube Team
00006     email                : mdshah82@yahoo.com
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  *                                                                         *
00011  *   This program is free software; you can redistribute it and/or modify  *
00012  *   it under the terms of the GNU General Public License as published by  *
00013  *   the Free Software Foundation; either version 2 of the License, or     *
00014  *   (at your option) any later version.                                   *
00015  *                                                                         *
00016  ***************************************************************************/
00017 
00018  #include "mm/mm.h"
00019  #include "core/kerror.h"
00020  #include "common/ktypes.h"
00021  #include "core/kasm.h"
00022  #include "common/stdlib.h"
00023  #include "gui/svga.h"
00024  
00025 
00026  DD _pgde[1024] __attribute__((aligned (_4KB)));
00027  DD _pgte[MAX_PROC][1024] __attribute__((aligned (_4KB)));
00028  DD _kpgde[1024] __attribute__((aligned (_4KB)));
00029  DD _kpgte[PHYS_MEM/_4MB][1024] __attribute__((aligned (_4KB))); //PHYS_MEM/4Mb
00030 
00031  DD _svgapgte[1024] __attribute__((aligned (_4KB))); //PHYS_MEM/4Mb
00032  DD frmlist[PHYS_MEM/(0x20*_4KB)] = {0}; //Each Byte contains 8 pages
00033 
00034  void mm_init()
00035  {
00036          /* Assumptions PHYS_MEM is a multiple of _4MB
00037                         Don't do anything to _kpgde and _kpgte as they should
00038             do 1-to-1 linear-to-physical mapping.
00039          */
00040          
00041          DD i = 0, j = 0;
00042    DD cr0 = 0, cr3 = 0 ;
00043          int *p;
00044    
00045 
00046          //Page
00047    printf(" PHYS_MEM/_4MB %d %x\n", PHYS_MEM/_4MB, PHYS_MEM/_4MB);
00048    
00049          for(i=0;i< PHYS_MEM/_4MB;i++)
00050          {
00051          _kpgde[i] = (DD)_kpgte[i] | 3;
00052    }
00053 
00054    //Directories that do not point to valid Memory  
00055    for(i= PHYS_MEM/_4MB ; i < 1024 ; i++)
00056    {
00057      _kpgde[i] |= 0;
00058    }
00059 
00060    //To get sufficient Pg Dir Entries even when KERNEL_SIZE != m * _4MB
00061    //Kernel Mapping - Priviliege Level 0 - Highest
00062    for(i=0; i<(KERNEL_SIZE/_4MB)+((KERNEL_SIZE%_4MB)?1:0); i++)
00063    {
00064          _pgde[i] = (DD)_kpgte[i] | 3;
00065    }
00066   
00067          for(i=(KERNEL_SIZE/_4MB)+((KERNEL_SIZE%_4MB)?1:0) ; i < (PHYS_MEM/_4MB) ; i++)
00068          {
00069                         _pgde[i] |=  3;
00070          }
00071 
00072          //Page Table Init
00073    for(i=0; i < (PHYS_MEM/_4MB) ;i++) //Each DirEnt contains 4Mb
00074    {
00075           for(j=0 ; j < 1024 ; j++) //1024 pg table entries
00076         {
00077                                 _kpgte[i][j] = i<<22 | j<<12 | 3;
00078     }
00079    }
00080 
00081    if(vbe_mode.PhysBasePtr)
00082      map_linear(vbe_mode.PhysBasePtr);//0xD0000000); //vbe_mode.PhysBasePtr
00083    //Setting for linear frame buffer of SVGA
00084 
00085   
00086   getCR0(cr0);
00087         cr0 |= (1<<31); // | (1 << 1) | (1 << 5); // MP bit for FPU init
00088   getCR3(cr3);  
00089         cr3 = (cr3 & 0xFFF) | (((DD)_kpgde) & 0xFFFFF000);
00090         
00091   setCR3(cr3);
00092   setCR0(cr0);
00093     
00094   printf("\nPAGING enabled");
00095  }
00096  
00097  DD pindex = 0;
00098 
00099  SDD findpage()
00100  {
00101          DD tindex = 0, and = 0, freebyte = 0, freenibble = 0;   
00102          DB i = 0,j = 0;
00103 
00104     
00105    //printf("\npin %d tin %d fr %b",pindex,tindex,frmlist[pindex]);
00106          tindex = pindex;
00107          
00108          while((frmlist[pindex] & 0xFFFFFFFF) == 0xFFFFFFFF)
00109          {
00110                         pindex++;
00111                   pindex %= (NUM_PAGES/32);
00112                   
00113       //printf("\nInside loop pindex %d tindex %d",pindex,tindex);
00114    
00115                   if(pindex == tindex) //No Free pages
00116                          return PAGE_NOT_FOUND;
00117          }
00118 
00119     for(i = 0 ; i < 4 ; i++)
00120     {
00121                         and = 0xFF<<(i*8);
00122 
00123                         //printf("\tand %x",and);
00124                         
00125                         if( (freebyte=(frmlist[pindex] & and)) != and ) //We have a free page here
00126                         {
00127                                 //printf("fb %x",freebyte);
00128 
00129                                 freebyte >>= (i*8);
00130                                 
00131                                 if( (freenibble=(freebyte & 0xF)) != 0xF )
00132                                 {
00133                                         for(j = 0 ; j < 4 ; j++)
00134                                         {
00135                                                 if(!(freenibble & 0x1))
00136                                                 {
00137                                                         frmlist[pindex] |= (1<<(i*8+j));
00138                                                         return pindex * 32 + i * 8 + j;
00139                                                 }
00140                                                 else
00141                                                 {
00142                                                         freenibble>>=1;
00143                                                 }
00144                                         }                                       
00145                                 }
00146                                 else
00147                                 {
00148                                         freenibble = (freebyte >> 4);
00149                                         
00150                                         for(j = 0 ; j < 4 ; j++)
00151                                         {
00152                                                 if(!(freenibble & 0x1))
00153                                                 {
00154                                                         frmlist[pindex] |= (1<<(i*8+j+4));
00155                                                         return pindex * 32 + i * 8 + j+4;
00156                                                 }
00157                                                 else
00158                                                 {
00159                                                         freenibble>>=1;
00160                                                 }
00161                                         }
00162                                                                                                                         
00163                                 }//else
00164                                                                 
00165                         }//if( (freebyte=(frmlist[pindex] & and)) != and ) //We have a free page here
00166                         
00167                 }//for
00168                 
00169  }// DD findpage()
00170 
00171 
00172   void freepage(DD index)
00173   {
00174      
00175                 frmlist[index/32] ^= (1<<index%32);
00176                 
00177         }//void freepage(DD index)
00178 
00179   DD lin_to_phy(SDW pid, DD linear_addr)
00180   {
00181    DW dirent, tabent, offset;
00182    DD *ptr;
00183 
00184    dirent = linear_addr >> 22; //10bits
00185    tabent = (linear_addr >> 12) & 0x3FF ; //10bits
00186    offset = (linear_addr & 0xFFF); //12 bits
00187 
00188 //   printf("\nlin_addr %b",linear_addr);
00189 //   printf("\nlin_addr %x DE %d TE %d OE %d",linear_addr,dirent,tabent,offset);
00190 //
00191 //   printf("\nbase _kde %x _kpte %x",(_kpgde[dirent] & 0xFFFFF000),_kpgte[2][256]);
00192 
00193    if(pid == KERNEL_PID || pid == GUI_PID || pid == FLOPPY_PID || pid == FS_PID) // || pid == GUI_PID
00194    {
00195     ptr = (DD *)(_kpgde[dirent] & 0xFFFFF000);
00196    }
00197 
00198    else
00199    {
00200     ptr = (DD *)(_pgde[dirent] & 0xFFFFF000);
00201          }
00202          
00203    return (((DD)*(ptr+tabent)) & 0xFFFFF000)|offset;
00204   }
00205 
00206   DD logi_to_lin(SDW pid ,DW seg_sel, DD offset)
00207 
00208   {
00209                 SEG_DESC tmp;
00210                 
00211                 if((seg_sel & 0x1) == 0) // || pid == GUI_PID
00212                 {
00213                         getDesc(seg_sel>>3,&tmp);
00214                 }
00215                 else
00216                 {
00217                         tmp = _ldte[pid][seg_sel>>3];
00218                 }
00219 
00220 //              printDESC(&tmp);
00221                 
00222                 return (tmp.base_24_31<<24|tmp.base_16_23<<16|tmp.base_0_15)+offset;
00223                 
00224         }
00225 
00226  void phys_mem_copy(DW pid_s,void * src,DW pid_d,void *dest,DD size)
00227   {
00228     DW seg;
00229     DD linear, phy_s,phy_d;
00230 
00231     linear = logi_to_lin(pid_s,_proc[pid_s].cs,(DD)src);
00232     phy_s = lin_to_phy(pid_s,linear);
00233     
00234     linear = logi_to_lin(pid_d,_proc[pid_d].cs,(DD)dest);
00235     phy_d = lin_to_phy(pid_d,linear);
00236 
00237     memcpy((void *) phy_d, (void *) phy_s,size);
00238 
00239   }
00240 
00241  struct MHEADER base = {0,0};
00242  struct MHEADER *freep = NULL;
00243 
00244  void *kmalloc(size_t nbytes)
00245   {
00246     struct MHEADER *p,*prevp;
00247     DD nunits;
00248     DD fp;
00249 
00250     nunits = (nbytes + sizeof(struct MHEADER)-1)/sizeof(struct MHEADER) +1;
00251     if((prevp = freep) == NULL)
00252     {
00253       base.ptr = freep = prevp = &base;
00254       base.size = 0;
00255     }
00256     for(p = prevp->ptr; ; prevp=p, p=p->ptr)
00257     {
00258       if(p->size >= nunits)
00259       {
00260        if(p->size == nunits)
00261           {
00262             prevp->ptr = p->ptr;
00263           }          
00264        else
00265         {
00266           p->size -= nunits;
00267           p += p->size;
00268           p->size = nunits;
00269         }   
00270        freep = prevp;
00271        return (void *)(p+1);          
00272       }
00273       if(p == freep)
00274       {
00275         if((fp = findpage()) != PAGE_NOT_FOUND)
00276         {
00277           p = KERNEL_SIZE + fp * _4KB;
00278           p->size = _4KB/sizeof(struct MHEADER);
00279           free((void *)(p+1));
00280           p = freep;
00281         }        
00282         else
00283           return NULL;        
00284       }
00285     }          
00286   }
00287 
00288   void free(void *ap)
00289   {
00290     struct MHEADER *bp,*p;
00291 
00292     bp = (struct MHEADER *)ap -1;
00293     for(p=freep; !(bp >p && bp < p->ptr); p =p->ptr)
00294       if(p >= p->ptr && (bp > p || bp < p->ptr))
00295         break;
00296 
00297     if(bp + bp->size == p->ptr)
00298       {
00299         bp->size += p->ptr->size;
00300         bp->ptr = p->ptr->ptr;
00301       }
00302     else
00303       bp->ptr = p->ptr;
00304 
00305     if(p + p->size ==  bp)
00306     {
00307        p->size += bp->size;
00308        p->ptr  = bp->ptr;
00309     }
00310     else
00311       p->ptr = bp;
00312       
00313     freep = p;     
00314  }    
00315 
00316  void map_linear(DD addr)
00317  {
00318    DD dir;
00319    DD i;
00320    DD phys;
00321    
00322    dir = addr >> 22;
00323    _kpgde[dir] = (DD)(& _svgapgte[0]) | 3;
00324    cls();
00325   
00326    for(i=0;i<1024 ;i++)  // 1MB frame buffer
00327     {
00328       _svgapgte[i] = (dir<<22) | (i<<12) | 3;
00329     }
00330  }
00331 //change
00332  DD get_phys(DW pid,DD ptr)
00333   {
00334    DD linear,phy;
00335    linear = logi_to_lin(pid,_proc[pid].ss,ptr);
00336    phy = lin_to_phy(pid,linear);
00337    return phy;
00338   }
00339 
00340 
00341 
00342 
00343 
00344 
00345 

Generated on Thu Jul 27 23:52:27 2006 for Dynacube by  doxygen 1.4.7