Untitled

 avatar
unknown
plain_text
a year ago
3.6 kB
7
Indexable
#include "VirtualMemory.h"
#include "PhysicalMemory.h"

void clearFrame(uint64_t base_address) {
    for (uint64_t i = 0; i < PAGE_SIZE; i++) {
        PMwrite(base_address * PAGE_SIZE + i, 0);
    }
}

bool is_valid_address(uint64_t virtualAddress) {
    if ((virtualAddress >= VIRTUAL_MEMORY_SIZE) || (TABLES_DEPTH > NUM_FRAMES)) {
        return false;
    }
    return true;
}

void dfs(uint64_t parent_address, uint64_t base_address, int &max_frame, word_t &empty_frame, word_t &frame_to_evict) {
    for (uint64_t i = 0; i < PAGE_SIZE; i++) {
        word_t value;
        PMread(base_address + i, &value);
        if (value != 0) {
            max_frame = std::max(max_frame, static_cast<int>(value));
            dfs(base_address, value * PAGE_SIZE, max_frame, empty_frame, frame_to_evict);
        } else if (empty_frame == -1) {
            empty_frame = base_address / PAGE_SIZE;
        }
    }

    // If all entries in the frame are zero, it is an empty frame
    bool is_empty = true;
    for (uint64_t i = 0; i < PAGE_SIZE; i++) {
        word_t value;
        PMread(base_address + i, &value);
        if (value != 0) {
            is_empty = false;
            break;
        }
    }

    if (is_empty && empty_frame == -1) {
        empty_frame = base_address / PAGE_SIZE;
    }

    // Update the parent to point to zero
    if (empty_frame != -1 && parent_address != base_address) {
        uint64_t parent_index = base_address / PAGE_SIZE % PAGE_SIZE;
        PMwrite(parent_address + parent_index, 0);
    }

    // If no empty frame is found, choose the frame to evict
    if (empty_frame == -1 && frame_to_evict == -1) {
        frame_to_evict = base_address / PAGE_SIZE;
    }
}

uint64_t find_frame() {
    int max_frame = 0;
    word_t empty_frame = -1;
    word_t frame_to_evict = -1;

    dfs(0, 0, max_frame, empty_frame, frame_to_evict);

    if (empty_frame != -1) {
        return empty_frame;
    }

    if (frame_to_evict != -1) {
        clearFrame(frame_to_evict);
        return frame_to_evict;
    }

    return max_frame + 1;
}

uint64_t translate_address(uint64_t virtualAddress) {
    word_t cur_address = 0;

    for (word_t level = 0; level < TABLES_DEPTH; level++) {
        uint64_t trans_level = (virtualAddress >> ((TABLES_DEPTH - level) * OFFSET_WIDTH)) & (PAGE_SIZE - 1);
        word_t next_address;
        PMread(cur_address * PAGE_SIZE + trans_level, &next_address);

        if (next_address == 0) {
            uint64_t new_frame = find_frame();
            PMwrite(cur_address * PAGE_SIZE + trans_level, new_frame);
            clearFrame(new_frame);
            next_address = new_frame;
        }

        cur_address = next_address;
    }

    return cur_address * PAGE_SIZE + (virtualAddress % PAGE_SIZE);
}

/* reads a word from the given virtual address
 * and puts its content in *value.
 *
 * returns 1 on success.
 * returns 0 on failure (if the address cannot be mapped to a physical
 * address for any reason)
 */
int VMread(uint64_t virtualAddress, word_t* value) {
    if (!is_valid_address(virtualAddress)) {
        return 0;
    }
    uint64_t address = translate_address(virtualAddress);
    PMread(address, value);
    return 1;
}

/* writes a word to the given virtual address
 *
 * returns 1 on success.
 * returns 0 on failure (if the address cannot be mapped to a physical
 * address for any reason)
 */
int VMwrite(uint64_t virtualAddress, word_t value) {
    if (!is_valid_address(virtualAddress)) {
        return 0;
    }
    uint64_t address = translate_address(virtualAddress);
    PMwrite(address, value);
    return 1;
}
Editor is loading...
Leave a Comment