helos1/memory/paging_physical.c
2021-10-10 14:11:45 +08:00

137 lines
4.4 KiB
C

#include "memory.h"
#include "paging_internal.h"
#include "../runtime/stdio.h"
#include <string.h>
uint64_t paging_physical_Bitmap[MAX_SYSTEM_MEMORY_PAGES / BITMAP_BITS];
static inline uint64_t fillBits(int begin, int last) {
if (last == BITMAP_BITS - 1)
return ~((1ull << begin) - 1ull);
if (begin == 0)
return (1ull << (last + 1ull)) - 1ull;
return (~((1ull << begin) - 1ull)) & ((1ull << (last + 1ull)) - 1ull);
}
void paging_physical_BitmapWriteOne(int begin, int end) {
int whereBegin = begin / BITMAP_BITS, whereLast = (end - 1) / BITMAP_BITS;
if (whereBegin == whereLast)
paging_physical_Bitmap[whereBegin] |= fillBits(begin % BITMAP_BITS, (end - 1) % BITMAP_BITS);
else {
paging_physical_Bitmap[whereBegin] |= fillBits(begin % BITMAP_BITS, BITMAP_BITS - 1);
paging_physical_Bitmap[whereLast] |= fillBits(0, (end - 1) % BITMAP_BITS);
for (int i = whereBegin + 1; i < whereLast; i++)
paging_physical_Bitmap[i] = (~0ull);
}
}
void paging_physical_BitmapWriteZero(int begin, int end) {
int whereBegin = begin / BITMAP_BITS, whereLast = (end - 1) / BITMAP_BITS;
if (whereBegin == whereLast)
paging_physical_Bitmap[whereBegin] &= ~fillBits(begin % BITMAP_BITS, (end - 1) % BITMAP_BITS);
else {
paging_physical_Bitmap[whereBegin] &= ~fillBits(begin % BITMAP_BITS, BITMAP_BITS - 1);
paging_physical_Bitmap[whereLast] &= ~fillBits(0, (end - 1) % BITMAP_BITS);
for (int i = whereBegin + 1; i < whereLast; i++)
paging_physical_Bitmap[i] = 0;
}
}
static int phy_i = 1024 / 4 / BITMAP_BITS;
uint64_t paging_physical_AllocateOneFrame() {
// skip the first 1M
/*for (; phy_i < paging_EndPhysicalPage / BITMAP_BITS; phy_i++)
if (paging_physical_Bitmap[phy_i] != ~0ull)
for (int j = 0; j < BITMAP_BITS; j++)
if ((paging_physical_Bitmap[phy_i] & (1ull << j)) == 0) {
paging_physical_Bitmap[phy_i] |= (1ull << j);
uint64_t addr = (((uint64_t)phy_i) * BITMAP_BITS + j) * SYSTEM_PAGE_SIZE;
memset((void *)addr, 0, SYSTEM_PAGE_SIZE);
return addr;
}*/
uint64_t addr;
paging_physical_AllocateFrames(1, &addr);
return addr;
}
// skip the first 2M
static int phy_i_2M = 2048 / 4 / BITMAP_BITS;
uint64_t paging_physical_AllocateOneFrame2M() {
// skip the first 2M
/*for (; phy_i_2M < paging_EndPhysicalPage / BITMAP_BITS; phy_i_2M += 8) {
for (int j = 0; j < 8; j++)
if (paging_physical_Bitmap[phy_i_2M + j] != 0)
goto for_end;
// now here we have a whole chunk at [i, i+8)
for (int j = 0; j < 8; j++)
paging_physical_Bitmap[phy_i_2M + j] = ~0ull;
uint64_t addr = (((uint64_t)phy_i_2M) * BITMAP_BITS) * SYSTEM_PAGE_SIZE;
memset((void *)addr, 0, SYSTEM_PAGE_2M_SIZE);
return addr;
for_end:;
}*/
uint64_t addr;
paging_physical_AllocateFrames2M(1, &addr);
return addr;
}
int paging_physical_AllocateFrames(int pageCount, uint64_t frames[]) {
// this code is in sync with paging_map.c, paging_map_PageAllocated, so you have to modify both
int page = 0;
for (; page < pageCount; page++) {
frames[page] = 0;
for (; phy_i < paging_EndPhysicalPage / BITMAP_BITS; phy_i++)
if (paging_physical_Bitmap[phy_i] != ~0ull)
for (int j = 0; j < BITMAP_BITS; j++)
if ((paging_physical_Bitmap[phy_i] & (1ull << j)) == 0) {
paging_physical_Bitmap[phy_i] |= (1ull << j);
uint64_t addr = (((uint64_t)phy_i) * BITMAP_BITS + j) * SYSTEM_PAGE_SIZE;
memset((void *)addr, 0, SYSTEM_PAGE_SIZE);
frames[page] = addr;
goto for_end; // break the phy_i loop
}
if (frames[page] == 0)
break;
for_end:;
}
return page;
}
int paging_physical_AllocateFrames2M(int pageCount, uint64_t frames[]) {
int page = 0;
for (; page < pageCount; page++) {
frames[page] = 0;
for (; phy_i_2M < paging_EndPhysicalPage / BITMAP_BITS; phy_i_2M += 8) {
for (int j = 0; j < 8; j++)
if (paging_physical_Bitmap[phy_i_2M + j] != 0)
goto for_end; // continue the outer for loop
// now here we have a whole chunk at [i, i+8)
for (int j = 0; j < 8; j++)
paging_physical_Bitmap[phy_i_2M + j] = ~0ull;
uint64_t addr = (((uint64_t)phy_i_2M) * BITMAP_BITS) * SYSTEM_PAGE_SIZE;
memset((void *)addr, 0, SYSTEM_PAGE_2M_SIZE);
frames[page] = addr;
break;
for_end:;
}
if (frames[page] == 0)
break;
}
return page;
}
void paging_physical_FreeFrame(uint64_t frame, int pageCount) {
if (frame % SYSTEM_PAGE_SIZE != 0) {
io_Printf("paging_physical_FreeFrame: frame %08llx is not aligned\n", frame);
return;
}
paging_physical_BitmapWriteZero(frame / SYSTEM_PAGE_SIZE, frame / SYSTEM_PAGE_SIZE + pageCount);
}