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