void os_alloc(uint32_t addr) { //search for a free frame if (PAGEOFFSET(addr)) { // offset must be *00; fprintf(stderr, "Invalid Alloc on address :[%x]\n", addr); return; } uint32_t dir, dirFrame, pt, ptFrame; //make page table point to the found frame dir = dccvmm_phy_read(procTable_ << 8 | currentPID_); dirFrame = PTEFRAME(dir); pt = dccvmm_phy_read( dirFrame << 8 | PTE1OFF(addr)); ptFrame = PTEFRAME(pt); if ((pt & PTE_VALID) != PTE_VALID) { //pointed frame is not a valid frame ptFrame = getFreeFrame(); dccvmm_phy_write(dirFrame << 8 | PTE1OFF(addr), ptFrame | PTE_VALID | PTE_INMEM | PTE_RW); } if (dccvmm_phy_read(ptFrame << 8 | PTE2OFF(addr)) & PTE_VALID) { fprintf(stderr, "\tDouble Alloc Detected\n"); return; } uint32_t freeFrame = getFreeFrame(); // frame is not avaliable anymore; //write on the page table the allocated Frame dccvmm_phy_write(ptFrame << 8 | PTE2OFF(addr), freeFrame | PTE_VALID | PTE_INMEM | PTE_RW); }
/* dccvmm_read retorna a palavra de 32-bits apontada pelo endereco virtual * address na tabela de paginas atual. * OU SEJA, dccvmm_read devolve a entrada da tabela de paginas apontada pelo endereço virtual address * OU SEJA, dccvmm_read vai na tabela de pagina, no endereco apontado por address e devolve o frame daquela pagina (16 bits) */ uint32_t dccvmm_read(uint32_t address) { //printf("\n\n(RETIRAR ESTE PRINT) Entrando na função \"dccvmm_read\"\n"); //printf("(RETIRAR ESTE PRINT) address: %X\n", address); uint32_t perms = PTE_RW | PTE_INMEM | PTE_VALID; /* A operação acima eh uma combinação de: * PTE_RW 0x00800000 o quadro apontado pelo pte tem permissao de leitura e escrita * PTE_VALID 0x00100000 o endereco virtual foi alocado pelo processo * PTE_INMEM 0x00400000 o quadro apontado pelo pte esta na memoria * resultado 0x00D00000 ou seja, a permissao eh de leitura e escrita + é do processo + está na memória */ /*PTE1OFF(address) = Separa os bitos 23 a 16 de address e os coloca na posição 7 a 0 dccvmm_get_pte(uint32_t frame, uint8_t ptenum, uint32_t perms, uint32_t address) */ //printf("(RETIRAR ESTE PRINT) __pagetable: 0x%X\n", __pagetable); //printf("(RETIRAR ESTE PRINT) PTE1OFF(address): %X\n", PTE1OFF(address)); //printf("(RETIRAR ESTE PRINT) perms: 0x%X\n", perms); uint32_t pte1 = dccvmm_get_pte(__pagetable, PTE1OFF(address), perms, address); if (pte1 == VM_ABORT) return 0; uint32_t pte1frame = PTEFRAME(pte1); /*Separa os 12 bits menos significativos de pte1*/ /*PTE2OFF(address) = Separa os bitos 15 a 8 de address e os coloca na posição 7 a 0 dccvmm_get_pte(uint32_t frame, uint8_t ptenum, uint32_t perms, uint32_t address) */ uint32_t pte2 = dccvmm_get_pte(pte1frame, PTE2OFF(address), perms, address); if (pte2 == VM_ABORT) return 0; uint32_t pte2frame = PTEFRAME(pte2); /*Separa os 12 bits menos significativos de pte2*/ uint32_t data = __frames[pte2frame].words[PAGEOFFSET(address)]; /*Separa os bitos 7 a 0 de address*/ printf("vmm %x phy %x read %x\n", address, (pte2frame << 8) + PAGEOFFSET(address), data); /*Separa os bitos 7 a 0 de address*/ return data; }
void os_free(uint32_t addr) { //find the phy addres relative to the virtual address uint32_t dir, dirFrame, pt, ptFrame, pte, pteFrame; dir = (dccvmm_phy_read(procTable_ << 8 | currentPID_)); dirFrame = PTEFRAME(dir); pt = dccvmm_phy_read(dirFrame << 8 | PTE1OFF(addr)); ptFrame = PTEFRAME(pt); pte = dccvmm_phy_read(ptFrame << 8 | PTE2OFF(addr)); pteFrame = PTEFRAME(pte); //update the page table dccvmm_phy_write(ptFrame << 8 | PTE2OFF(addr), 0); //update the free list: dccvmm_phy_write(pteFrame << 8, freesStart_); // make the freed frame the freeStart and make it point to the old freeStart freesStart_ = pteFrame; if (outOfMemory_)outOfMemory_ = FALSE; int emptyFlag = TRUE; int i = 0; for (i = 0; i < NUMWORDS; i++) { uint32_t pte = dccvmm_phy_read(ptFrame << 8 | i); if ((pte & PTE_INMEM) == PTE_INMEM) { //page Table has valid pages emptyFlag = FALSE; } } if (emptyFlag) { ptFrame = PTEFRAME(ptFrame); dumpPageTable(addr, dirFrame, &pt); } }