Ignored \0 in VT_Write, Added out of memory message
[tpg/acess2.git] / Kernel / arch / x86 / mm_phys.c
1 /*
2  AcessOS Microkernel Version
3  mm_phys.c
4 */
5 #include <common.h>
6 #include <mboot.h>
7 #include <mm_virt.h>
8
9 #define REFERENCE_BASE  0xE0400000
10
11 // === IMPORTS ===
12 extern void     gKernelEnd;
13
14 // === PROTOTYPES ===
15 Uint32  MM_AllocPhys();
16 void    MM_RefPhys(Uint32 Addr);
17 void    MM_DerefPhys(Uint32 Addr);
18
19 // === GLOBALS ===
20  int    giPhysAlloc = 0;
21 Uint    giPageCount = 0;
22 Uint32  gaSuperBitmap[1024];    // Blocks of 1024 Pages
23 Uint32  gaPageBitmap[1024*1024/32];     // Individual pages
24 Uint32  *gaPageReferences;
25
26 // === CODE ===
27 void MM_Install(tMBoot_Info *MBoot)
28 {
29         Uint    kernelPages, num;
30         Uint    i;
31         tMBoot_Module   *mods;
32         
33         // Initialise globals
34         giPageCount = (MBoot->HighMem >> 2) + 256;      // HighMem is a kByte value
35         Log("giPageCount = %i", giPageCount);
36         
37         // Get used page count
38         kernelPages = (Uint)&gKernelEnd - KERNEL_BASE;
39         kernelPages += 0xFFF;   // Page Align
40         kernelPages >>= 12;
41         
42         // Fill page bitmap
43         num = kernelPages/32;
44         memsetd(gaPageBitmap, -1, num);
45         gaPageBitmap[ num ] = (1 << (kernelPages & 31)) - 1;
46         
47         // Fill Superpage bitmap
48         num = kernelPages/(32*32);
49         memsetd(gaSuperBitmap, -1, num);
50         gaSuperBitmap[ num ] = (1 << ((kernelPages / 32) & 31)) - 1;
51         
52         // Mark Multiboot's pages as taken
53         // - Structure
54         MM_RefPhys( (Uint)MBoot - KERNEL_BASE );
55         // - Module List
56         for(i = (MBoot->ModuleCount*sizeof(tMBoot_Module)+0xFFF)>12; i--; )
57                 MM_RefPhys( MBoot->Modules + (i << 12) );
58         // - Modules
59         mods = (void*)(MBoot->Modules + KERNEL_BASE);
60         for(i = 0; i < MBoot->ModuleCount; i++)
61         {
62                 num = (mods[i].End - mods[i].Start + 0xFFF) >> 12;
63                 while(num--)
64                         MM_RefPhys( (mods[i].Start & ~0xFFF) + (num<<12) );
65         }
66         
67         // Allocate References
68         Log("Reference Pages %i", (giPageCount*4+0xFFF)>>12);
69         for(num = 0; num < (giPageCount*4+0xFFF)>>12; num++)
70         {
71                 MM_Allocate( REFERENCE_BASE + (num<<12) );
72         }
73         
74         // Fill references
75         gaPageReferences = (void*)REFERENCE_BASE;
76         memsetd(gaPageReferences, 1, kernelPages);
77         for( num = kernelPages; num < giPageCount; num++ )
78         {
79                 //if(gaPageBitmap[ num2 / 32 ] == 0) {
80                 //      memsetd(&gaPageReferences[num2], 0, 31-(num2&31));
81                 //      num2 = (num2 + 32) & ~31;
82                 //} else
83                         gaPageReferences[num] = (gaPageBitmap[ num / 32 ] >> (num&31)) & 1;
84         }
85 }
86
87 /**
88  * \fn tPAddr MM_AllocPhys()
89  * \brief Allocates a physical page
90  */
91 tPAddr MM_AllocPhys()
92 {
93          int    num = giPageCount / 32 / 32;
94          int    a, b, c;
95         Uint32  ret;
96         
97         LOCK( &giPhysAlloc );
98         
99         // Find free page
100         for(a=0;gaSuperBitmap[a]==-1&&a<num;a++);
101         if(a == num) {
102                 RELEASE( &giPhysAlloc );
103                 Warning("MM_AllocPhys - OUT OF MEMORY\n");
104                 return 0;
105         }
106         for(b=0;gaSuperBitmap[a]&(1<<b);b++);
107         for(c=0;gaPageBitmap[a*32+b]&(1<<c);c++);
108         //for(c=0;gaPageReferences[a*32*32+b*32+c]>0;c++);
109         
110         // Mark page used
111         if(gaPageReferences)
112                 gaPageReferences[a*32*32+b*32+c] = 1;
113         gaPageBitmap[ a*32+b ] |= 1 << c;
114         
115         // Get address
116         ret = (a << 22) + (b << 17) + (c << 12);
117         
118         // Mark used block
119         if(gaPageBitmap[ a*32+b ] == -1)        gaSuperBitmap[a] |= 1 << b;
120
121         // Release Spinlock
122         RELEASE( &giPhysAlloc );
123         //LOG("ret = %x", ret);
124         return ret;
125 }
126
127 /**
128  * \fn void MM_RefPhys(tPAddr Addr)
129  */
130 void MM_RefPhys(tPAddr Addr)
131 {
132         // Get page number
133         Addr >>= 12;
134         
135         // We don't care about non-ram pages
136         if(Addr >= giPageCount) return;
137         
138         // Lock Structures
139         LOCK( &giPhysAlloc );
140         
141         // Reference the page
142         if(gaPageReferences)
143                 gaPageReferences[ Addr ] ++;
144         
145         // Mark as used
146         gaPageBitmap[ Addr / 32 ] |= 1 << (Addr&31);
147         
148         // Mark used block
149         if(gaPageBitmap[ Addr / 32 ] == -1)     gaSuperBitmap[Addr/1024] |= 1 << ((Addr/32)&31);
150         
151         // Release Spinlock
152         RELEASE( &giPhysAlloc );
153 }
154
155 /**
156  * \fn void MM_DerefPhys(Uint32 Addr)
157  */
158 void MM_DerefPhys(tPAddr Addr)
159 {
160         // Get page number
161         Addr >>= 12;
162         
163         // We don't care about non-ram pages
164         if(Addr >= giPageCount) return;
165         
166         // Check if it is freed
167         if(gaPageReferences[ Addr ] == 0) {
168                 Warning("MM_DerefPhys - Non-referenced memory dereferenced");
169                 return;
170         }
171         
172         // Lock Structures
173         LOCK( &giPhysAlloc );
174         
175         // Dereference
176         gaPageReferences[ Addr ] --;
177         
178         // Mark as free in bitmaps
179         if( gaPageReferences[ Addr ] == 0 )
180         {
181                 gaPageBitmap[ Addr / 32 ] &= ~(1 << (Addr&31));
182                 if(gaPageReferences[ Addr ] == 0)
183                         gaSuperBitmap[ Addr >> 10 ] &= ~(1 << ((Addr >> 5)&31));
184         }
185         
186         // Release spinlock
187         RELEASE( &giPhysAlloc );
188 }
189
190 /**
191  * \fn int MM_GetRefCount(tPAddr Addr)
192  */
193 int MM_GetRefCount(tPAddr Addr)
194 {
195         // Get page number
196         Addr >>= 12;
197         
198         // We don't care about non-ram pages
199         if(Addr >= giPageCount) return -1;
200         
201         // Check if it is freed
202         return gaPageReferences[ Addr ];
203 }

UCC git Repository :: git.ucc.asn.au