Beispiel #1
0
/* Like smp_idle(), this will put the core in a state that it can only be woken
 * up by an IPI.  For now, this is a halt.  Maybe an mwait in the future.
 *
 * This will return if an event was pending (could be the one you were waiting
 * for) or if the halt failed for some reason, such as a concurrent RKM.  If
 * successful, this will not return at all, and the vcore will restart from the
 * top next time it wakes.  Any sort of IRQ will wake the core.
 *
 * Alternatively, I might make this so it never returns, if that's easier to
 * work with (similar issues with yield). */
void vcore_idle(void)
{
    uint32_t vcoreid = vcore_id();
    /* Once we enable notifs, the calling context will be treated like a uthread
     * (saved into the uth slot).  We don't want to ever run it again, so we
     * need to make sure there's no cur_uth. */
    assert(!current_uthread);
    /* This clears notif_pending (check, signal, check again pattern). */
    if (handle_events(vcoreid))
        return;
    /* This enables notifs, but also checks notif pending.  At this point, any
     * new notifs will restart the vcore from the top. */
    enable_notifs(vcoreid);
    /* From now, til we get into the kernel, any notifs will permanently destroy
     * this context and start the VC from the top.
     *
     * Once we're in the kernel, any messages (__notify, __preempt), will be
     * RKMs.  halt will need to check for those atomically.  Checking for
     * notif_pending in the kernel (sleep only if not set) is not enough, since
     * not all reasons for the kernel to stay awak set notif_pending (e.g.,
     * __preempts and __death).
     *
     * At this point, we're out of VC ctx, so anyone who sets notif_pending
     * should also send an IPI / __notify */
    sys_halt_core(0);
    /* in case halt returns without actually restarting the VC ctx. */
    disable_notifs(vcoreid);
}
Beispiel #2
0
void ghetto_vcore_entry(void)
{
	uint32_t vcoreid = vcore_id();
	static bool first_time = TRUE;

	temp = 0xcafebabe;
	/* vcore_context test (don't need to do this anywhere) */
	assert(in_vcore_context());

	/* old logic was moved to parlib code */
	if (current_uthread) {
		assert(vcoreid == 0);
		run_current_uthread();
	}
	/* unmask notifications once you can let go of the notif_tf and it is okay
	 * to clobber the transition stack.
	 * Check Documentation/processes.txt: 4.2.4.  In real code, you should be
	 * popping the tf of whatever user process you want (get off the x-stack) */
	enable_notifs(vcoreid);

/* end: stuff userspace needs to do to handle notifications */

	printf("Hello from vcore_entry in vcore %d with temp addr %p and temp %p\n",
	       vcoreid, &temp, temp);
	vcore_request(1);
	//mcs_barrier_wait(&b,vcore_id());
	udelay(vcoreid * 10000000);
	//exit(0);
	while(1);
}
Beispiel #3
0
/* Like smp_idle(), this will put the core in a state that it can only be woken
 * up by an IPI.  In the future, we may halt or something.  This will return if
 * an event was pending (could be the one you were waiting for). */
void vcore_idle(void)
{
	uint32_t vcoreid = vcore_id();
	if (handle_events(vcoreid))
		return;
	enable_notifs(vcoreid);
	while (1) {
		cpu_relax();
	}
}
Beispiel #4
0
void ghetto_vcore_entry(void)
{
	uint32_t vcoreid = vcore_id();
	static bool first_time = TRUE;

	temp = 0xcafebabe;
	/* vcore_context test (don't need to do this anywhere) */
	assert(in_vcore_context());

	/* old logic was moved to parlib code */
	if (current_uthread) {
		assert(vcoreid == 0);
		run_current_uthread();
	}
	/* unmask notifications once you can let go of the uthread_ctx and it is
	 * okay to clobber the transition stack.
	 * Check Documentation/processes.txt: 4.2.4.  In real code, you should be
	 * popping the tf of whatever user process you want (get off the x-stack) */
	enable_notifs(vcoreid);

/* end: stuff userspace needs to do to handle notifications */

	printf("Hello from vcore_entry in vcore %d with temp addr %p and temp %p\n",
	       vcoreid, &temp, temp);

	#if 0
	/* Test sys change vcore.  Need to manually preempt the pcore vcore4 is
	 * mapped to from the monitor */
	udelay(20000000);
	if (vcoreid == 1) {
		disable_notifs(vcoreid);
		printf("VC1 changing to VC4\n");
		sys_change_vcore(4, TRUE);		/* try both of these manually */
		//sys_change_vcore(4, FALSE);		/* try both of these manually */
		printf("VC1 returned\n");
	}
	udelay(10000000);
	#endif

	vcore_request(1);
	//mcs_barrier_wait(&b,vcore_id());
	udelay(vcoreid * 10000000);
	//exit(0);
	while(1);
}
Beispiel #5
0
int main(int argc, char** argv)
{
	int num_started, retval;
	unsigned int ev_type;

	/* register our syscall handler (2LS does this) */
	register_ev_handler(EV_SYSCALL, handle_syscall, 0);

	printf("Trying to block\n");
	/* Not doing anything else to it: no EVENT_IPI yet, etc. */
	ev_q = get_eventq();
	/* issue the diagnostic block syscall */
	sysc.num = SYS_block;
	sysc.arg0 = 5000;	/* 5ms */
	sysc.ev_q = ev_q;
	/* Trap */
	num_started = __ros_arch_syscall((long)&sysc, 1);
	if (!(atomic_read(&sysc.flags) & SC_DONE))
		printf("Not done, looping!\n");
	/* You could poll on this.  This is really ghetto, but i got rid of
	 * event_activity, whose sole purpose was to encourage spinning. */
	while (!(atomic_read(&sysc.flags) & SC_DONE))
		cpu_relax();
	handle_event_q(ev_q);
	/* by now, we should have run our handler */
	/********************************************************/
	/* Start MCP / IPI test */
	printf("Switching to _M mode and testing an IPI-d ev_q\n");
	printf("Our indirect ev_q is %08p\n", ev_q);

/* begin: stuff userspace needs to do before switching to multi-mode */
	/* Note we don't need to set up event reception for any particular kevent.
	 * The ev_q in the syscall said to send an IPI to vcore 0 which means an
	 * EV_EVENT will be sent straight to vcore0. */
	/* Inits a thread for us, though we won't use it.  Just a hack to get into
	 * _M mode.  Note this requests one vcore for us */
	struct uthread dummy = {0};
	uthread_2ls_init(&dummy, &ghetto_sched_ops);
	uthread_mcs_init();
	/* Need to save our floating point state somewhere (like in the
	 * user_thread_tcb so it can be restarted too */
	enable_notifs(0);
/* end: stuff userspace needs to do before switching to multi-mode */

	retval = vcore_request(1);
	if (retval < 0)
		printf("No cores granted, Rut Ro Raggy!\n");
	/* now we're back in thread 0 on vcore 0 */
	ev_q->ev_flags = EVENT_IPI;
	ev_q->ev_vcore = 0;
	sysc.u_data = (void*)1;	/* using this to loop on */
	/* issue the diagnostic blocking syscall */
	sysc.num = SYS_block;
	sysc.arg0 = 5000;	/* 5ms */
	sysc.ev_q = ev_q;
	num_started = __ros_arch_syscall((long)&sysc, 1);
	/* have this thread "wait" */
	if (!(atomic_read(&sysc.flags) & SC_DONE))
		printf("Not done, looping on a local variable!\n");
	while (sysc.u_data)
		cpu_relax();
	assert(atomic_read(&sysc.flags) & SC_DONE);
	printf("Syscall unblocked, IPI broke me out of the loop.\n");

	/* done */
	put_eventq(ev_q);
	printf("Syscall test exiting\n");
	return 0;
}