Custom-OS-Kernel / phase3 / vmSupport.c
vmSupport.c
Raw
// Shahir Ahmed and Boosung Kim
#include "../h/vmSupport.h"

extern state_t* savedException;
extern int flashSemaphores[UPROCMAX]; // Semaphores to represent the flash devices
extern pcb_t* currentProcess;
swap_t swapPoolTable[POOLSIZE];
int swapPoolSemaphore; // for controlling access to the swap pool table

void initSwapStructs()
{
    swapPoolSemaphore = 1;
    for (int i = 0; i < POOLSIZE; i++) {
        swapPoolTable[i].sw_asid = NOPROC;
    }
}


/*
 * Handles page fault exceptions
 */

void Support_Pager()
{
    // obtain a pointer to the current proccess's support structure
    support_t* supportPtr = (support_t*) SYSCALL(GETSUPPORTPTR, 0, 0, 0);
    // determine the cause of the TLB exception
    int execCode = GET_EXEC_CODE(supportPtr->sup_exceptState[PGFAULTEXCEPT].cause);
    if (execCode == 1) {
        // TLB modification exception
        SYSCALL(TERMINATE, 0, 0, 0);  //I changed code here. Call the Level 4 SYSCALL 
    }

    // Gain mutual exclusion over the swap pool table
    SYSCALL(PASSERN, (memaddr) &swapPoolSemaphore, 0, 0); //I changed code here. Added missing &
    // Determine the page number that caused the page fault
    int pgNo = (supportPtr->sup_exceptState[PGFAULTEXCEPT].entry_hi - 0x80000000) >> 12;
    if (pgNo < 0 || pgNo > 30) {
        pgNo = 31; // 31 represents the stack page
    }

    int frame = -1;
    // Find the first free frame in the swap pool and assign its number to frame
    for (int i = 0; i < POOLSIZE; i++) {
        if (swapPoolTable[i].sw_asid == NOPROC) {
            frame = i;
            break;
        }
    }
    if (frame == -1) {
        frame = replacementAlgorithm();
    }

    int frameAsid = swapPoolTable[frame].sw_asid; // asid associated with the returned frame number
    int asid = supportPtr->sup_asid; // asid of the current process

    // 0x20020000 is the starting address of the swap pool. Each frame is 4096 bits. To get 
    // to the base address of the frame, we need to add number of frames * 4096 bits + starting address of the swap pool 
    memaddr frameAddress = (0x20020000) + (frame * 4096);
    
    if (frameAsid != NOPROC) {
        // the frame was occupied by a process page 
        DISABLE_INTERRUPTS_COMMAND; // ATOMIC
        UNSET_BIT(swapPoolTable[frame].sw_pte->pte_entryLO, 9); // clear the valid bit
        // update the TLB to reflect the entry corresponding to the page removed from the swap pool
        updateTLB(swapPoolTable[frame].sw_pte); 
        ENABLE_INTERRUPTS_COMMAND; // ATOMIC END
        // Update the process's backing store. Write the contents of removed frame to the correct location on 
        // the process's backing store
        int blockNo =  (swapPoolTable[frame].sw_pte->pte_entryHI - 0x80000000) >> 12;
        backStoreManager(3, frameAsid, frameAddress, blockNo);
    }
    // Read the contents of the current process's backing store/flash device logical page pgNo into frame because
    // the process is not in the RAM and needs to load the frame from the backing store/flash device
    backStoreManager(2, asid, frameAddress, pgNo);

    DISABLE_INTERRUPTS_COMMAND; // ATOMIC
    // Update the swap pool table's entry at index frame to reflect the new frame contents
    swapPoolTable[frame].sw_asid = asid;
    swapPoolTable[frame].sw_pageNo = pgNo;
    swapPoolTable[frame].sw_pte = &(supportPtr->sup_privatePgTbl[pgNo]);
    
    supportPtr->sup_privatePgTbl[pgNo].pte_entryLO = (frameAddress & 0xFFFFF000) | VALIDON | DIRTYON;
    updateTLB(&(supportPtr->sup_privatePgTbl[pgNo]));
    ENABLE_INTERRUPTS_COMMAND;

    SYSCALL(VERHOGEN, (int) &swapPoolSemaphore, 0, 0); // release mutual exclusion over the swap pool table ////I changed code here. Added missing &
    LDST((state_t*) &(supportPtr->sup_exceptState[PGFAULTEXCEPT])); // return control to the current process
}




void backStoreManager(unsigned int command, int flash_asid, unsigned int data_addr, unsigned int deviceBlockNumber)
{
    SYSCALL(PASSERN, (memaddr) &flashSemaphores[flash_asid - 1], 0, 0); // Gain mutual exclusion on the flash device //I changed code here (added missing &)
    devreg_t* deviceRegister = GET_DEV_ADDR(4, flash_asid - 1); // Get the address of the device register
    deviceRegister->dtp.data0 = data_addr;

    DISABLE_INTERRUPTS_COMMAND; // ATOMIC
    deviceRegister->dtp.command = (deviceBlockNumber << 8) | command;
    SYSCALL(IOWAIT, 4, flash_asid - 1, 0);
    ENABLE_INTERRUPTS_COMMAND; // ATOMIC END

    SYSCALL(VERHOGEN, (int) &flashSemaphores[flash_asid - 1], 0, 0);

    if (deviceRegister->dtp.status != DEV0ON){
        SYSCALL(TERMPROCESS, 0, 0, 0);
    }
}



// Update a specific mapping in the TLB
// updated_entry is the address of the support page table field at index pgNo.
void updateTLB(pteEntry_t *updated_entry)
{   
    setENTRYHI(updated_entry->pte_entryHI);
    TLBP(); // Search for the TLB and update the probe bit.
    
    if ((getINDEX() & 0x80000000) == 0){
        // The entry is present in the TLB.
        setENTRYLO(updated_entry->pte_entryLO);
        TLBWI();
    }
}

int replacementAlgorithm()
{
    static int frameNum = 0;
    int frameReturn = frameNum;
    frameNum = (frameNum + 1) % POOLSIZE;
    return frameReturn;
}


void uTLB_RefillHandler() {
    GET_BDP_STATUS(savedException); // Create a passed variable and make it a pointer to the BIOSDATAPAGE

    int pgNum = (savedException->entry_hi - 0x80000000) >> 12; // Get the missing page number

    if (pgNum < 0 || pgNum > 30) {
        pgNum = 31; // stack page num
    }

    setENTRYHI(currentProcess->p_supportStruct->sup_privatePgTbl[pgNum].pte_entryHI);
    setENTRYLO(currentProcess->p_supportStruct->sup_privatePgTbl[pgNum].pte_entryLO);

    TLBWR();
    LDST(savedException);
}