Exemple #1
0
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);
}
Exemple #2
0
void KernelStart(char *cmd_args[], unsigned int pmem_size, UserContext *uctxt) {
	//mark the initial KernelBrk
	KernelBrk = KernelDataEnd;

	//FreeFrameCount is only used page_table.c
	FreeFrameCount = pmem_size / PAGESIZE;

	ipc_table = (ObjectNode **) malloc(sizeof(ObjectNode *) * HASH_LEN);
	if (NULL == ipc_table) {
		TracePrintf(0, "ipc_table cannot be initialized!\n");
		return;
	}
	memset(ipc_table, 0, sizeof(ObjectNode *) * HASH_LEN);

	ReadyQueue	= (Queue *) malloc(sizeof(Queue));
	DelayQueue	= (Queue *) malloc(sizeof(Queue));
	if (NULL == ReadyQueue) {
		TracePrintf(0, "ReadyQueue cannot be initialized!\n");
		return;
	}
	if (NULL == DelayQueue) {
		TracePrintf(0, "DelayQueue cannot be initialized!\n");
		return;
	}

	memset(ReadyQueue,	0, sizeof(Queue));
	memset(DelayQueue,	0, sizeof(Queue));

	u_int i;
	for (i = 0; i < NUM_TERMINALS; i++) {
		BufferQueue[i]		= (Queue *) malloc(sizeof(Queue));
		ReceiveQueue[i]		= (Queue *) malloc(sizeof(Queue));
		TransmitQueue[i]	= (Queue *) malloc(sizeof(Queue));
		if (NULL == BufferQueue[i]) {
			TracePrintf(0, "BufferQueue[%d] cannot be initialized!\n", i);
			return;
		}
		if (NULL == ReceiveQueue[i]) {
			TracePrintf(0, "ReceiveQueue[%d] cannot be initialized!\n", i);
			return;
		}
		if (NULL == TransmitQueue[i]) {
			TracePrintf(0, "TransmitQueue[%d] cannot be initialized!\n", i);
			return;
		}


		memset(BufferQueue[i], 0, sizeof(Queue));
		memset(ReceiveQueue[i], 0, sizeof(Queue));
		memset(TransmitQueue[i], 0, sizeof(Queue));
	}

	//create interrupt vector table in kernel
	void **interruptVectorTable =
			 (void **) malloc(sizeof(void *) * TRAP_VECTOR_SIZE);
	if (NULL == interruptVectorTable) {
		TracePrintf(0, "Interrupt Vector Table cannot be initialized!\n");
		return;
	}

	//fill each entry in table with pointer to correct handler
	interruptVectorTable[TRAP_KERNEL] 	= &TrapKernelHandler;
	interruptVectorTable[TRAP_CLOCK] 	= &TrapClockHandler;
	interruptVectorTable[TRAP_ILLEGAL] 	= &TrapIllegalHandler;
	interruptVectorTable[TRAP_MEMORY] 	= &TrapMemoryHandler;
	interruptVectorTable[TRAP_MATH] 	= &TrapMathHandler;
	interruptVectorTable[TRAP_TTY_RECEIVE] 	= &TrapTtyReceiveHandler;
	interruptVectorTable[TRAP_TTY_TRANSMIT]	= &TrapTtyTransmitHandler;
	interruptVectorTable[TRAP_DISK] 	= &TrapDiskHandler;
	for (i = 8; i < 16; i++) {
		interruptVectorTable[i] 	= &TrapErrorHandler;
	}	

	//point REG_VECTOR_BASE to interrupt vector table
	WriteRegister(REG_VECTOR_BASE, (u_int) interruptVectorTable);
	TracePrintf(0, "Interrupt vector table initialization completed.\n");

	//Build page table for Region 0
	KernelPageTable = (PTE *) malloc(sizeof(PTE) * MAX_PT_LEN);
	if (NULL == KernelPageTable) {
		TracePrintf(0, "KernelPageTable cannot be initialized!\n");
		return;
	}
	memset(KernelPageTable, 0, sizeof(PTE) * MAX_PT_LEN);

	TracePrintf(0, "Page tables built successfully.\n");

	//create kernel stack union
	KS = (KernelStack *) KERNEL_STACK_BASE;
	TracePrintf(0, "Kernel stack initialization completed.\n");

	//build input init process PCB
	KS->CurrentPCB = InitPCB = InitializePCB();
	if (NULL == InitPCB) {
		TracePrintf(0, "InitPCB cannot be initialized!\n");
		return;
	}

	// We enablePTE after using all the malloc in the kernel because
	// only in this way we can make sure the getFreeFrame will be called
	// and update the FreeFrameCount.
	enablePTE(0, Page(KernelDataStart), PROT_READ | PROT_EXEC);
	enablePTE(Page(KernelDataStart), Page(KernelBrk), PROT_READ | PROT_WRITE);
	enablePTE(INTERFACE, Page(KERNEL_STACK_LIMIT), PROT_READ | PROT_WRITE);

	// initialize virtual memory registers
	WriteRegister(REG_PTBR0, (u_int) KernelPageTable);
	WriteRegister(REG_PTLR0, MAX_PT_LEN);
	WriteRegister(REG_PTBR1, (u_int) KS->CurrentPCB->pagetable);
	WriteRegister(REG_PTLR1, MAX_PT_LEN);
	TracePrintf(0, "Table information loading to hardware completed.\n");

	//set up the link list to keep track of free frames
	//from KernelBrk to KERNEL_STACK_BASE
	*FrameNumber(INTERFACE) = Page(KernelBrk);
	for (i = Page(KernelBrk); i < INTERFACE - 1; i++) {
		*FrameNumber(i) = i + 1;
	}
	*FrameNumber(INTERFACE - 1) = Page(VMEM_0_LIMIT);
	for (i = Page(VMEM_0_LIMIT); i < Page(pmem_size - 1); i++) {
		*FrameNumber(i) = i + 1;
	}
	TracePrintf(0, "Free frames' linked list has been set up.\n");

	//enable virtual memory
	WriteRegister(REG_VM_ENABLE, 1);
	VM_ENABLED = 1;
	TracePrintf(0, "Virtual memory has been enabled.\n");

	TracePrintf(0, "Load input program. (Default init)\n");
	if (NULL != cmd_args[0]) {
		if (FAILURE == LoadProgram(cmd_args[0], cmd_args, InitPCB)) {
			TracePrintf(0, "Load input program failed!\n");
			return;
		}
	} else {
		char *args[] = {"init", NULL};
		if (FAILURE == LoadProgram(args[0], args, InitPCB)) {
			TracePrintf(0, "Load input program failed!\n");
			return;
		}
	}

	TracePrintf(0, "Build the Idle process.\n");
	//build kernel idle process PCB
	IdlePCB = InitializePCB();
	if (NULL == IdlePCB) {
		TracePrintf(0, "IdlePCB cannot be initialized!\n");
		return;
	}

	//sp = virtual address of top of stack
	IdlePCB->uctxt.sp  = (void *) (VMEM_1_LIMIT
				     - INITIAL_STACK_FRAME_SIZE
				     - POST_ARGV_NULL_SPACE);
	//pc = virtual address of DoIdle function
	IdlePCB->uctxt.pc  = &DoIdle;

	//enable user stack for idle process	
	IdlePCB->pagetable[MAX_PT_LEN - 1].valid = 1;
	IdlePCB->pagetable[MAX_PT_LEN - 1].prot = PROT_READ | PROT_WRITE;

	if (0 == FreeFrameCount) {
		TracePrintf(0, "No frame for Idle process pagetable!\n");
		return;
	}

	IdlePCB->pagetable[MAX_PT_LEN - 1].pfn = getFreeFrame(0);

	//use MyKCS initialize IdlePCB's KC and KS
	KernelContextSwitch(KCKSInit, (void *) IdlePCB, NULL);
	TracePrintf(0, "How many time will this line be printed?\n");

	//copy current context into hardware provided context
	*uctxt = KS->CurrentPCB->uctxt;

	TracePrintf(0, "KernelStart finished.\n");
}