Skip to content

Instantly share code, notes, and snippets.

@clickCA
Created March 2, 2023 13:23
Show Gist options
  • Select an option

  • Save clickCA/a56784df4bdcf7cc5aa19b29fb4965c6 to your computer and use it in GitHub Desktop.

Select an option

Save clickCA/a56784df4bdcf7cc5aa19b29fb4965c6 to your computer and use it in GitHub Desktop.
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#define FRAME_SIZE 256
#define FRAME_ENTRIES 128
#define PAGE_SIZE 256
#define PAGE_ENTRIES 16
#define OUTER_PAGE_ENTRIES 16
typedef struct PageTableEntry {
uint16_t present : 1;
uint16_t frame : 15;
} PageTableEntry;
PageTableEntry *page_table;
PageTableEntry *outer_page_table[OUTER_PAGE_ENTRIES];
uint8_t *physical_memory;
uint16_t translate_address(uint16_t logical_address) {
// Get outer page number and page number from logical address
uint8_t outer_page_number = logical_address >> 12;
uint8_t page_number = (logical_address >> 8) & 0xF;
// Allocate inner page table if it's not present
if (outer_page_table[outer_page_number] == NULL) {
// Inner page table not present, allocate an inner page table for it
outer_page_table[outer_page_number] = malloc(PAGE_ENTRIES * sizeof(PageTableEntry));
}
if (outer_page_table[outer_page_number][page_number].present == 0) {
// Page not present, allocate a frame for it
// For simplicity, just random a frame. Must fix this later.
uint16_t frame_number = rand() % FRAME_ENTRIES;
// Fill in page table
outer_page_table[outer_page_number][page_number].present = 1;
outer_page_table[outer_page_number][page_number].frame = frame_number;
}
// Construct physical address from frame number and offset
uint16_t physical_address = (outer_page_table[outer_page_number][page_number].frame << 8) + (logical_address & 0xFF);
printf("Translate logical address 0x%X (outer page number 0x%X, page number 0x%X, offset 0x%X) to physical address 0x%X\n",
logical_address, outer_page_number, page_number, logical_address & 0xFF, physical_address);
return physical_address;
}
void read_from_memory(uint16_t logical_address, uint8_t *value) {
uint16_t physical_address = translate_address(logical_address);
*value = physical_memory[physical_address];
}
void write_to_memory(uint16_t logical_address, uint8_t value) {
uint16_t physical_address = translate_address(logical_address);
physical_memory[physical_address] = value;
}
int main() {
// Allocate physical memory
physical_memory = calloc(PAGE_ENTRIES, PAGE_SIZE);
// Initialize random seed for frame allocation
srand(42);
// Read and write to memory
uint8_t value;
write_to_memory(0x123, 0xA);
read_from_memory(0x123, &value);
printf("Value read from memory: 0x%02X\n", value);
write_to_memory(0x1234, 0xAB);
read_from_memory(0x1234, &value);
printf("Value read from memory: 0x%02X\n", value);
// Calculate total size of outer page table and inner page tables
size_t page_table_size = 0;
for (int i = 0; i < OUTER_PAGE_ENTRIES; i++) {
if (outer_page_table[i] != NULL) {
page_table_size += PAGE_ENTRIES * sizeof(PageTableEntry);
}
}
printf("Outer page table size: %zu bytes\n", sizeof(outer_page_table));
printf("Inner page table size: %zu bytes\n", page_table_size);
printf("Total page table size: %zu bytes\n", sizeof(outer_page_table)+page_table_size);
// Deallocate inner page tables
for (int i = 0; i < OUTER_PAGE_ENTRIES; i++) {
if (outer_page_table[i] != NULL) {
free(outer_page_table[i]);
}
}
// Deallocate physical memory and page table
free(physical_memory);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment