int paging_init(uint32_t mem_size) { uint64_t mem_end = (uint64_t)mem_size * 1024ULL; frames_count = (uint32_t)(mem_end / 0x1000ULL); frames = (uint32_t*)static_alloc(BIT_INDEX(frames_count)); memset(frames, 0, BIT_INDEX(frames_count)); /* Create kernel page directory. */ kernel_directory = static_alloc(sizeof(*kernel_directory)); memset(kernel_directory, 0, sizeof(*kernel_directory)); /* Identity map pages up to heap address. We make the first page non-present so that NULL-pointer dereferences cause * a page fault. */ frame_alloc(page_get(0, kernel_directory, true), 0); uint32_t i = 0; for (i = PAGE_SIZE; i < heap_addr; i += PAGE_SIZE) { frame_alloc(page_get(i, kernel_directory, true), PAGE_FLAGS_PRESENT); } /* Map pages for the heap. */ for (; i < HEAP_ADDRESS + HEAP_SIZE_INIT; i += PAGE_SIZE) { page_get(i, kernel_directory, true); } /* Set page fault handler. */ set_interrupt_handler(ISR_PAGE_FAULT, page_fault_handler); page_directory_load(kernel_directory); page_enable(); return 0; }
void bitset_unset(bitset *b, unsigned int bit) { if (bit >= b->bs_nbits) return; b->bs_bits[BIT_INDEX(bit)] &= ~(1 << BIT_IN_OBJ(bit)); }
int bit_test(struct bitset *b, int bit) { uint32_t idx; uint32_t off; idx = BIT_INDEX(bit); off = BIT_OFFSET(bit); return ((b->bits[idx] & (1 << off)) ? 1 : 0); }
unsigned int bitset_test(bitset *b, unsigned int bit) { bits mask = (1 << BIT_IN_OBJ(bit)); if (bit >= b->bs_nbits) return 0; return (b->bs_bits[BIT_INDEX(bit)] & mask) == mask; }
void bit_clear(struct bitset *b, int bit) { uint32_t idx; uint32_t off; if (!b) return; idx = BIT_INDEX(bit); off = BIT_OFFSET(bit); if (idx > b->len) return; b->bits[idx] &= ~(1 << off); }
bitset *bitset_new(int nbits) { bitset *b; b = (bitset *)malloc(sizeof(bitset)); b->bs_nbits = nbits; b->bs_size = BIT_INDEX(nbits-1) + 1; b->bs_bits = (bits *)malloc(SIZE_TO_BYTES(b->bs_size)); memset(b->bs_bits, 0, SIZE_TO_BYTES(b->bs_size)); return b; }
static uint32_t frame_get_first_free(void) { uint32_t i, j; for (i = 0; i < BIT_INDEX(frames_count); ++i) { if (frames[i] != 0xFFFFFFFF) { for (j = 0; j < 32; ++j) { if (!(TEST_BIT(frames[i], j))) { return i * 4 * 8 + j; } } } } return 0; }
/** * Mark frame allocated * @param paddr - physical address to mark */ static void page_set_frame(uint64 paddr){ uint64 page = paddr / 4069; uint64 idx = BIT_INDEX(page); uint64 offset = BIT_OFFSET(page); _page_frames[idx] |= (0x1 << offset); }
/** * Check if frame is allocated or free * @param paddr - physical address to check * @return true if set false if not */ static bool page_check_frame(uint64 paddr){ uint64 page = paddr / 4069; uint64 idx = BIT_INDEX(page); uint64 offset = BIT_OFFSET(page); return (_page_frames[idx] & (0x1 << offset)); }
static uint32_t frame_test(uint32_t addr) { uint32_t frame = addr / PAGE_SIZE; return TEST_BIT(frames[BIT_INDEX(frame)], BIT_OFFSET(frame)); }
static void frame_clear(uint32_t addr) { uint32_t frame = addr / PAGE_SIZE; CLEAR_BIT(frames[BIT_INDEX(frame)], BIT_OFFSET(frame)); }
static void frame_set(uint32_t addr) { uint32_t frame = addr / PAGE_SIZE; SET_BIT(frames[BIT_INDEX(frame)], BIT_OFFSET(frame)); }