无法使用pure64将cr3寄存器更改为指向新的pml4方向

时间:2015-10-28 14:47:23

标签: c x86 operating-system virtual-memory

我一直在努力改变存储在CR3寄存器中的方向,将Pure64加载的方向替换为我加载的新方法。

我正在做的是我从8 Mib内存的方向上取一个4 KiB页面,以确保我不会使用任何内核,用户空间和Pure64模块,并将其用作新的PML4的方向。
我用我需要的东西加载新的PML4,但是当我执行行

mov cr3,rdi

其中rdi存储新的PML4方向,然后qemu无限地重启自己。

现在,如果我硬编码Pure64 PML4方向(0x2008)并执行与之前相同的操作,则调用指令时没有问题

mov cr3,rdi

并且操作系统正确执行。

可能是因为Pure64仍然需要使用CR3寄存器中加载的表吗?

这里我将代码保留在我加载pml4方向的位置:
(请注意,有一些注释,我一直在用于调试目的。)

/* Ideas and Code extracted and modified from Wyrm OS.
Project Repository: https://bitbucket.org/RowDaBoat/wyrm/wiki/Home */

#include <virtualMemoryManager.h>
#include <mem.h>
#include <libc.h>
#include <terminal.h>
#include <own_cpu.h>

static const uint32_t presentBit = 0;
static const uint32_t writeBit = 1;
static const uint32_t userBit = 2;
static const uint32_t pageWriteThroughBit = 3;
static const uint32_t pageCacheDisableBit = 4;
static const uint32_t accessedBit = 5;
static const uint32_t dirtyBit = 6;
static const uint32_t pageSizeBit = 7;
static const uint32_t globalBit = 8;
static const uint32_t pageAttributeTableBit = 12;
static const uint32_t addressBit = 30;
static const uint64_t addressMask4KiB = 0x0000000FFFFFFFFF000;
static const uint64_t addressMask2MiB = 0x0000000FFFFFFE00000;
static const uint64_t addressMask1GiB = 0x0000000FFFFC0000000;
static const uint32_t executeDisableBit = 63;
// static const uint64_t pageSize = 4092; /* no entiendo xqq setea este tamaño de página */

static inline void setBit(uint64_t * bits, uint32_t n, bool value) {
    if (value)
        *bits |= (1 << n);
    else
        *bits &= ~(1 << n);
}

static inline bool getBit(uint64_t bits, uint32_t n) {
    return bits & (1 << n);
}

static PageTableEntry* createTable() {
    PageTableEntry * table = (PageTableEntry*) mt_mem_alloc(1);
    memset(table, 0, PAGESIZE); /* defined at libc.h */
    return table;
}

static inline PageTableEntry * clear(PageTableEntry * page) {
    for (uint64_t i = 0; i < PAGESIZE / sizeof(PageTableEntry); i++)
        page[i].contents = 0;

    return page;
}

int initializeVirtualMemory()
{

    PageTableEntry * pml4 = createTable();

    /* +++xdebug */
    if (pml4 == NULL) {
        print("\nCANNOT SET PML4.\n");
        return false;
    }

    PageTableEntry * pageDirectoryPointerTable = createTable();

    /* +++xdebug */
    if (pml4 == NULL) {
        print("\nCANNOT SET PML4.\n");
        return false;
    }

    /* +++xdebug */
//  pml4 = 0x00002000;
//  pml4 = 0;
    pml4 = 0x00804008;
//  pml4 = (uint64_t pml4) & 0x8;


    //Set up the pml4, this table will be used by all mappings, kernel and user
    PageTableEntry *currentEntry = &(pml4[0]);

    print("\ncurrentEntry: ");
    printHex(pml4);
    println();

    /* +++xdebug */
    print("\nAntes de setar Presente: ");
    printHex(currentEntry->contents);
    //printInt(PageTableEntry_getPresent(currentEntry));

    PageTableEntry_setPresent(currentEntry, false);
    PageTableEntry_setWritable(currentEntry, false);
    PageTableEntry_setUser(currentEntry, false);
    PageTableEntry_setPageWriteThrough(currentEntry, true);
    PageTableEntry_setPageCacheDisable(currentEntry, false);
    PageTableEntry_setAccessed(currentEntry, false);
    PageTableEntry_setPageSize(currentEntry, false);
    PageTableEntry_setExecuteDisable(currentEntry, false);
    PageTableEntry_set4KiBPageAddress(currentEntry, pageDirectoryPointerTable);

    print("\nDespues de setar Presente: ");
    printHex(currentEntry->contents);
    //printInt(PageTableEntry_getPresent(currentEntry));


    char * page1GiB = (char*)0x0;

    //Identity map first 512 GiB (that should be all memory)
    for (int i = 0; i < 512; i++, page1GiB += oneGiB) {

        currentEntry = &(pageDirectoryPointerTable[i]);
        PageTableEntry_setPresent(currentEntry, true);
        PageTableEntry_setWritable(currentEntry, true);
        PageTableEntry_setUser(currentEntry, true);
        PageTableEntry_setPageWriteThrough(currentEntry, false);
        PageTableEntry_setPageCacheDisable(currentEntry, false);
        PageTableEntry_setAccessed(currentEntry, false);
        PageTableEntry_setPageSize(currentEntry, true);
        PageTableEntry_set1GiBPageAddress(currentEntry, page1GiB);

        /* +++xdebug */
        if (i < 5) {
            print("\nPage Start at: ");
            printHex(currentEntry->contents);
            println();
        }
    }

    //Update CR3 with the new mapping
    _writeCR3((uint64_t)pml4);

    return true;
}

PageTableEntry * PageTableEntry_setPresent(PageTableEntry * entry, bool value) {
    setBit(&(entry->contents), presentBit, value);
    return entry;
}

PageTableEntry * PageTableEntry_setWritable(PageTableEntry * entry, bool value) {
    setBit(&(entry->contents), writeBit, value);
    return entry;
}

PageTableEntry * PageTableEntry_setUser(PageTableEntry * entry, bool value) {
    setBit(&(entry->contents), userBit, value);
    return entry;
}

PageTableEntry * PageTableEntry_setPageWriteThrough(PageTableEntry * entry, bool value) {
    setBit(&(entry->contents), pageWriteThroughBit, value);
    return entry;
}

PageTableEntry * PageTableEntry_setPageCacheDisable(PageTableEntry * entry, bool value) {
    setBit(&(entry->contents), pageCacheDisableBit, value);
    return entry;
}

PageTableEntry * PageTableEntry_setAccessed(PageTableEntry * entry, bool value) {
    setBit(&(entry->contents), accessedBit, value);
    return entry;
}

PageTableEntry * PageTableEntry_setDirty(PageTableEntry * entry, bool value) {
    setBit(&(entry->contents), dirtyBit, value);
    return entry;
}

PageTableEntry * PageTableEntry_setPageSize(PageTableEntry * entry, bool value) {
    setBit(&(entry->contents), pageSizeBit, value);
    return entry;
}

PageTableEntry * PageTableEntry_setGlobal(PageTableEntry * entry, bool value) {
    setBit(&(entry->contents), globalBit, value);
    return entry;
}

PageTableEntry * PageTableEntry_setPageAttribueTable(PageTableEntry * entry, bool value) {
    setBit(&(entry->contents), pageAttributeTableBit, value);
    return entry;
}

PageTableEntry * PageTableEntry_set4KiBPageAddress(PageTableEntry * entry, void * address) {
    entry->contents = ((uint64_t)address & addressMask4KiB) | (entry->contents & ~addressMask4KiB);
    return entry;
}

PageTableEntry * PageTableEntry_set2MiBPageAddress(PageTableEntry * entry, void * address) {
    entry->contents = ((uint64_t)address & addressMask2MiB) | (entry->contents & ~addressMask2MiB);
    return entry;
}

PageTableEntry * PageTableEntry_set1GiBPageAddress(PageTableEntry * entry, void * address) {
    entry->contents = ((uint64_t)address & addressMask1GiB) | (entry->contents & ~addressMask1GiB);
    return entry;
}

PageTableEntry * PageTableEntry_setExecuteDisable(PageTableEntry * entry, bool value) {
    setBit(&(entry->contents), executeDisableBit, value);
    return entry;
}

bool PageTableEntry_getPresent(PageTableEntry * entry) {
    return getBit(entry->contents, presentBit);
}

bool PageTableEntry_getWritable(PageTableEntry * entry) {
    return getBit(entry->contents, writeBit);
}

bool PageTableEntry_getUser(PageTableEntry * entry) {
    return getBit(entry->contents, userBit);
}

bool PageTableEntry_getPageWriteThrough(PageTableEntry * entry) {
    return getBit(entry->contents, pageWriteThroughBit);
}

bool PageTableEntry_getPageCacheDisable(PageTableEntry * entry) {
    return getBit(entry->contents, pageCacheDisableBit);
}

bool PageTableEntry_getAccessed(PageTableEntry * entry) {
    return getBit(entry->contents, accessedBit);
}

bool PageTableEntry_getDirty(PageTableEntry * entry) {
    return getBit(entry->contents, dirtyBit);
}

bool PageTableEntry_getPageSize(PageTableEntry * entry) {
    return getBit(entry->contents, pageSizeBit);
}

bool PageTableEntry_getGlobal(PageTableEntry * entry) {
    return getBit(entry->contents, globalBit);
}

bool PageTableEntry_getPageAttribueTable(PageTableEntry * entry) {
    return getBit(entry->contents, pageAttributeTableBit);
}

void * PageTableEntry_get4KiBPageAddress(PageTableEntry * entry) {
    return (void*)(entry->contents & addressMask4KiB);
}

void * PageTableEntry_get2MiBPageAddress(PageTableEntry * entry) {
    return (void*)(entry->contents & addressMask2MiB);
}

void * PageTableEntry_get1GiBPageAddress(PageTableEntry * entry) {
    return (void*)(entry->contents & addressMask1GiB);
}

bool PageTableEntry_getExecuteDisable(PageTableEntry * entry) {
    return getBit(entry->contents, executeDisableBit);
}

2 个答案:

答案 0 :(得分:1)

问题是我试图直接映射1GB的物理内存,而qemu 2.0.0.0并没有为此做好准备。 我必须做的是安装qemu 2.4.0.1并运行禁用kvm的VM。

我希望没有其他人有这个问题。

答案 1 :(得分:0)

Is %rdi correct? 
Bit[39~47] is the index of the pml4 table, 
and the bit [12~51] of cr3 stores the first address of the pml4 table.