2015-10-28 1 views
0

J'ai essayé pendant des heures de changer la direction stockée au registre CR3, en remplaçant celle chargée par Pure64 par une nouvelle chargée par moi. Ce que je fais, c'est que je prends une page de 4 KiB à partir d'une direction au-dessus de la mémoire de 8 Mib, afin de m'assurer de ne pas piétiner le noyau, l'espace utilisateur, ni le module Pure64, et de l'utiliser comme nouvelle direction pour le PML4.
je charge le nouveau PML4 avec les choses que je dois, mais quand j'exécute la ligneImpossible de changer le registre cr3 pour pointer vers une nouvelle direction pml4 en utilisant pure64

mov cr3,rdi 

rdi stocke la nouvelle direction de PML4, puis qemu ne cesse de se redémarrer à l'infini.

Maintenant, si je hardcode la direction Pure64 PML4 (0x2008) et faire les mêmes opérations que précédemment, il n'y a pas de problème lors de l'appel de l'instruction

mov cr3,rdi 

et le système d'exploitation se termine correctement.

Se pourrait-il que cela se produise parce que Pure64 doit toujours utiliser la table chargée au registre CR3?

Ici, je laisse le code où je charge ma direction pml4:
(Notez qu'il ya des lignes fait remarquer que je l'ai utilisé pour le débogage.)

/* 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); 
} 

Répondre

0

Le problème était que je tentais pour mapper 1 Go de mémoire physique directement, et qemu 2.0.0.0 n'était pas préparé pour cela. Ce que je devais faire était d'installer qemu 2.4.0.1 et d'exécuter la VM avec kvm désactivé.

J'espère que personne d'autre n'a ce problème.