我一直在努力改变存储在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);
}
答案 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.