00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
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)));
00030
00031 DD _svgapgte[1024] __attribute__((aligned (_4KB)));
00032 DD frmlist[PHYS_MEM/(0x20*_4KB)] = {0};
00033
00034 void mm_init()
00035 {
00036
00037
00038
00039
00040
00041 DD i = 0, j = 0;
00042 DD cr0 = 0, cr3 = 0 ;
00043 int *p;
00044
00045
00046
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
00055 for(i= PHYS_MEM/_4MB ; i < 1024 ; i++)
00056 {
00057 _kpgde[i] |= 0;
00058 }
00059
00060
00061
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
00073 for(i=0; i < (PHYS_MEM/_4MB) ;i++)
00074 {
00075 for(j=0 ; j < 1024 ; j++)
00076 {
00077 _kpgte[i][j] = i<<22 | j<<12 | 3;
00078 }
00079 }
00080
00081 if(vbe_mode.PhysBasePtr)
00082 map_linear(vbe_mode.PhysBasePtr);
00083
00084
00085
00086 getCR0(cr0);
00087 cr0 |= (1<<31);
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
00106 tindex = pindex;
00107
00108 while((frmlist[pindex] & 0xFFFFFFFF) == 0xFFFFFFFF)
00109 {
00110 pindex++;
00111 pindex %= (NUM_PAGES/32);
00112
00113
00114
00115 if(pindex == tindex)
00116 return PAGE_NOT_FOUND;
00117 }
00118
00119 for(i = 0 ; i < 4 ; i++)
00120 {
00121 and = 0xFF<<(i*8);
00122
00123
00124
00125 if( (freebyte=(frmlist[pindex] & and)) != and )
00126 {
00127
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 }
00164
00165 }
00166
00167 }
00168
00169 }
00170
00171
00172 void freepage(DD index)
00173 {
00174
00175 frmlist[index/32] ^= (1<<index%32);
00176
00177 }
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;
00185 tabent = (linear_addr >> 12) & 0x3FF ;
00186 offset = (linear_addr & 0xFFF);
00187
00188
00189
00190
00191
00192
00193 if(pid == KERNEL_PID || pid == GUI_PID || pid == FLOPPY_PID || pid == FS_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)
00212 {
00213 getDesc(seg_sel>>3,&tmp);
00214 }
00215 else
00216 {
00217 tmp = _ldte[pid][seg_sel>>3];
00218 }
00219
00220
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++)
00327 {
00328 _svgapgte[i] = (dir<<22) | (i<<12) | 3;
00329 }
00330 }
00331
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