Пример #1
0
void _init( void ) {
	pcb_t *pcb;
	context_t *context;
	status_t stat;

	/*
	** BOILERPLATE CODE - taken from basic framework
	**
	** Initialize interrupt stuff.
	*/

	__init_interrupts();	// IDT and PIC initialization

	/*
	** Console I/O system.
	*/

	c_io_init();
	c_setscroll( 0, 7, 99, 99 );
	c_puts_at( 0, 6, "================================================================================" );

	/*
	** 20103-SPECIFIC CODE STARTS HERE
	*/

	/*
	** Initialize various OS modules
	*/

	c_puts( "Starting module init: " );

	_q_init();		// must be first
	_pcb_init();
	_stack_init();
	_sio_init();
	_syscall_init();
	_sched_init();
	_clock_init();
	//_pci_init();
	build_lapic_info();
	_paging_init();

	c_puts( "\n" );

	c_puts(" Ending init\n");
	initSMP();

	/*
	** Create the initial system ESP
	**
	** This will be the address of the next-to-last
	** longword in the system stack.
	*/

	_system_esp = ((uint32_t *) ( (&_system_stack) + 1)) - 2;

	/*
	** Install the ISRs
	*/

	__install_isr( INT_VEC_TIMER, _isr_clock );
	__install_isr( INT_VEC_SYSCALL, _isr_syscall );
	__install_isr( INT_VEC_SERIAL_PORT_1, _isr_sio );

	/*
	** Create the initial process
	**
	** Code mostly stolen from _sys_fork() and _sys_exec();
	** if either of those routines change, SO MUST THIS!!!
	**
	** First, get a PCB and a stack
	*/

	stat = _pcb_alloc( &pcb );
	if( stat != E_SUCCESS ) {
		_kpanic( "_init", "first pcb alloc status %s", stat );
	}

	stat = _stack_alloc( &(pcb->stack) );
	if( stat != E_SUCCESS ) {
		_kpanic( "_init", "first stack alloc status %s", stat );
	}

	/*
	** Next, set up various PCB fields
	*/

	pcb->pid  = PID_INIT;
	pcb->ppid = PID_INIT;
	pcb->prio = PRIO_MAXIMUM;

	/*
	** Set up the initial process context.
	*/

	context = _setup_stack( pcb->stack, (uint32_t) init );

	// Finally, set up the process' ESP

	context->esp = (uint32_t) context;

	// Make it the "current" process

	_current = pcb;
	_current->context = context;

	/*
	** Starting up the idle routine is the responsibility
	** of the initial user process.
	*/

	/*
	** Turn on the SIO receiver (the transmitter will be turned
	** on/off as characters are being sent)
	*/

	_sio_enable( SIO_RX );

	/*
	** END OF 20103-SPECIFIC CODE
	**
	** Finally, report that we're all done.
	*/


	c_puts( "System initialization complete.\n" );

}
Пример #2
0
pcb_t *_create_process( pcb_t *curr ) {
	pcb_t *pcb;
	stack_t *stack;
	int offset;
	uint32_t *ptr;
	
	// allocate the new structures

	pcb = _pcb_alloc();
	if( pcb == NULL ) {
		return( NULL );
	}

	stack = _stack_alloc();
	if( stack == NULL ) {
		_pcb_free(pcb);
		return( NULL );
	}
	
	/*
	** The PCB argument will be NULL if this function is called
	** from the system initialization, and non-NULL if called 
	** from the fork() implementation.
	**
	** In the former case, we initialize the new data structures for
	** a brand-new process.
	**
	** In the latter case, we replicate the information from the
	** existing process whose PCB was passed in.
	*/

	if( curr != NULL ) {	// called from fork()
	
		// duplicate the PCB and stack contents

		_kmemcpy( (void *) pcb, (void *) curr, sizeof(pcb_t) );
		_kmemcpy( (void *) stack, (void *) curr->stack, sizeof(stack_t) );
		
		// update the entries which should be changed in the PCB

		pcb->pid = _next_pid++;
		pcb->ppid = curr->pid;
		pcb->stack = stack;
		
	        /*
		** We duplicated the original stack contents, which
		** means that the context pointer and ESP and EBP values
		** in the new stack are still pointing into the original
		** stack.  We need to correct all of these.
		**
		** We have to change EBP because that's how the compiled
		** code for the user process accesses its local variables.
		** If we didn't change this, as soon as the new process
		** was dispatched, it would start to stomp on the local
		** variables in the original process' stack.  We also
       		** have to fix the EBP chain in the child process.
		**
		** None of this would be an issue if we were doing "real"
		** virtual memory, as we would be talking about virtual
		** addresses here rather than physical addresses, and all
		** processes would share the same virtual address space
		** layout.
		**
		** First, determine the distance (in bytes) between the
		** two stacks.  This is the adjustment value we must add
		** to the three pointers to correct them.  Note that this
		** distance may be positive or negative, depending on the
		** relative placement of the two stacks in memory.
		*/

		offset = (void *) (pcb->stack) - (void *) (curr->stack);
		
		// modify the context pointer for the new process

		pcb->context = (context_t *)( (void *) (pcb->context) + offset );
		// now, change ESP and EBP in the new process (easy to
		// do because they're just uint32_t values, not really
		// pointers)

		pcb->context->esp += offset;
		pcb->context->ebp += offset;

		/*
        	** Next, we must fix the EBP chain in the new stack.  This
		** is necessary in the situation where the fork() occurred
		** in a nested function call sequence; we fixed EBP, but
		** the "saved" EBP in the stack frame is pointing to the
		** calling function's frame in the original stack, not the
		** new stack.
		**
		** We are guaranteed that the chain of frames ends at the
		** frame for the original process' main() routine, because
		** exec() will initialize EBP for the process to 0, and the
		** entry prologue code in main() routine will push EBP,
		** ensuring a NULL pointer in the chain.
        	*/

		// start at the current frame

		ptr = (uint32_t *) pcb->context->ebp;

		// follow the chain of frame pointers to its end
		while( *ptr != 0 ) {
			// update the link from this frame to the previous
			*ptr += offset;
			// follow the updated link
			ptr = (uint32_t *) *ptr;
		}
		
	} else {		// called from init

		pcb->pid = pcb->ppid = PID_INIT;
		pcb->stack = stack;
	
	}
	
	// all done - return the new PCB

	return( pcb );
}