Beispiel #1
0
static void global_tests(uint32_t vcoreid)
{
	int retval;
	switch (test) {
		case TEST_YIELD_ALL:
			printf("Core %d yielding\n", vcoreid);
			sys_yield(0);
			// should be RUNNABLE_M now, amt_wanted == 1
			while(1);
		case TEST_SWITCH_TO_RUNNABLE_S:
			if (vcoreid == 2) {
				printf("Core %d trying to request 0/ switch to _S\n", vcoreid);
				udelay(3000000);
				retval = vcore_request(0);
				// will only see this if we are scheduled()
				printf("Core %d back up! (retval:%d)\n", vcoreid, retval);
				printf("And exiting\n");
				exit(0);
			} 
			while(1);
		case TEST_CRAZY_YIELDS:
			udelay(300000*vcoreid);
			vcore_request(5);
			sys_yield(0);
			printf("should  never see me, unless you slip into *_S\n");
			break;
		case TEST_CONCURRENT_SYSCALLS:
			for (int i = 0; i < 10; i++) {
				for (int j = 0; j < 100; j++)
					sys_null();
				printf("Hello from vcore %d, iteration %d\n", vcoreid, i);
			}
			break;
	}
}
int main(int argc, char** argv)
{
	uint32_t vcoreid = vcore_id();
	int retval = 0;

	mcs_barrier_init(&b, max_vcores());

/* begin: stuff userspace needs to do before switching to multi-mode */
	vcore_lib_init();
	#if 0
	/* tell the kernel where and how we want to receive notifications */
	struct notif_method *nm;
	for (int i = 0; i < MAX_NR_NOTIF; i++) {
		nm = &__procdata.notif_methods[i];
		nm->flags |= NOTIF_WANTED | NOTIF_MSG | NOTIF_IPI;
		nm->vcoreid = i % 2; // vcore0 or 1, keepin' it fresh.
	}
	#endif
	/* Need to save this somewhere that you can find it again when restarting
	 * core0 */
	core0_tls = get_tls_desc(0);
	/* Need to save our floating point state somewhere (like in the
	 * user_thread_tcb so it can be restarted too */
/* end: stuff userspace needs to do before switching to multi-mode */

	/* get into multi mode */
	retval = vcore_request(1);
	if (retval)
		printf("F****d!\n");

	printf("Proc %d requesting another vcore\n", getpid());
	begin = read_tsc();
	retval = vcore_request(1);
	if (retval)
		printf("F****d!\n");
	while (!core1_up)
		cpu_relax;
	end = read_tsc();
	printf("Took %llu usec (%llu nsec) to receive 1 core (cold).\n",
	       udiff(begin, end), ndiff(begin, end));
	printf("[T]:002:%llu:%llu:1:C.\n",
	       udiff(begin, end), ndiff(begin, end));
	core1_up = FALSE;
	udelay(2000000);
	printf("Proc %d requesting the vcore again\n", getpid());
	begin = read_tsc();
	retval = vcore_request(1);
	if (retval)
		printf("F****d!\n");
	while (!core1_up)
		cpu_relax();
	end = read_tsc();
	printf("Took %llu usec (%llu nsec) to receive 1 core (warm).\n",
	       udiff(begin, end), ndiff(begin, end));
	printf("[T]:002:%llu:%llu:1:W.\n",
	       udiff(begin, end), ndiff(begin, end));
	return 0;
}
Beispiel #3
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 #4
0
/* GIANT WARNING: if you make any changes to this, also change the broadcast
 * wakeups (cond var, barrier, etc) */
static void pth_thread_runnable(struct uthread *uthread)
{
	struct pthread_tcb *pthread = (struct pthread_tcb*)uthread;
	/* At this point, the 2LS can see why the thread blocked and was woken up in
	 * the first place (coupling these things together).  On the yield path, the
	 * 2LS was involved and was able to set the state.  Now when we get the
	 * thread back, we can take a look. */
	printd("pthread %08p runnable, state was %d\n", pthread, pthread->state);
	switch (pthread->state) {
		case (PTH_CREATED):
		case (PTH_BLK_YIELDING):
		case (PTH_BLK_JOINING):
		case (PTH_BLK_SYSC):
		case (PTH_BLK_PAUSED):
		case (PTH_BLK_MUTEX):
			/* can do whatever for each of these cases */
			break;
		default:
			printf("Odd state %d for pthread %08p\n", pthread->state, pthread);
	}
	pthread->state = PTH_RUNNABLE;
	/* Insert the newly created thread into the ready queue of threads.
	 * It will be removed from this queue later when vcore_entry() comes up */
	mcs_pdr_lock(&queue_lock);
	/* Again, GIANT WARNING: if you change this, change batch wakeup code */
	TAILQ_INSERT_TAIL(&ready_queue, pthread, tq_next);
	threads_ready++;
	mcs_pdr_unlock(&queue_lock);
	/* Smarter schedulers should look at the num_vcores() and how much work is
	 * going on to make a decision about how many vcores to request. */
	if (can_adjust_vcores)
		vcore_request(threads_ready);
}
Beispiel #5
0
int main(int argc, char** argv)
{
	uint32_t vcoreid;
	int nr_vcores;

	if (argc < 2)
		nr_vcores = max_vcores();
	else
		nr_vcores = atoi(argv[1]);

	/* 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_mcp_init();

	/* Reset the blockon to be the spinner...  This is really shitty.  Any
	 * blocking calls after we become an MCP and before this will fail.  This is
	 * just mhello showing its warts due to trying to work outside uthread.c */
	ros_syscall_blockon = __ros_syscall_spinon;

	vcore_request(nr_vcores - 1); /* since we already have 1 */

	while (1)
		sys_halt_core(0);

	return 0;
}
Beispiel #6
0
int main(int argc, char** argv) 
{
	struct timeval start_tv = {0};
	struct timeval end_tv = {0};
	long usec_diff;
	long nr_ctx_switches;

	if (argc > 1)
		nr_yield_threads = strtol(argv[1], 0, 10);
	if (argc > 2)
		nr_yield_loops = strtol(argv[2], 0, 10);
	if (argc > 3)
		nr_vcores = strtol(argv[3], 0, 10);
	if (argc > 4)
		amt_fake_work = strtol(argv[4], 0, 10);
	nr_yield_threads = MIN(nr_yield_threads, MAX_NR_TEST_THREADS);
	printf("Making %d threads of %d loops each, on %d vcore(s), %d work\n",
	       nr_yield_threads, nr_yield_loops, nr_vcores, amt_fake_work);

	/* OS dependent prep work */
	if (nr_vcores) {
		/* Only do the vcore trickery if requested */
		vcore_request(nr_vcores - 1);		/* ghetto incremental interface */
		for (int i = 0; i < nr_vcores; i++) {
			printf("Vcore %d not mapped to a particular pcore\n", i);
		}
	}

	/* create and join on yield */
	for (int i = 0; i < nr_yield_threads; i++) {
		printd("[A] About to create thread %d\n", i);
		assert(!upthread_create(&my_threads[i], NULL, &yield_thread, (void*)(long)i));
	}
	if (gettimeofday(&start_tv, 0))
		perror("Start time error...");
	ready = TRUE;			/* signal to any spinning uthreads to start */
	for (int i = 0; i < nr_yield_threads; i++) {
		printd("[A] About to join on thread %d(%p)\n", i, my_threads[i]);
		upthread_join(my_threads[i], &my_retvals[i]);
		printd("[A] Successfully joined on thread %d (retval: %p)\n", i,
		            my_retvals[i]);
	}
	if (gettimeofday(&end_tv, 0))
		perror("End time error...");
	nr_ctx_switches = nr_yield_threads * nr_yield_loops;
	usec_diff = (end_tv.tv_sec - start_tv.tv_sec) * 1000000 +
	            (end_tv.tv_usec - start_tv.tv_usec);
	printf("Done: %d uthreads, %d loops, %d vcores, %d work\n",
	       nr_yield_threads, nr_yield_loops, nr_vcores, amt_fake_work);
	printf("Nr context switches: %ld\n", nr_ctx_switches);
	printf("Time to run: %ld usec\n", usec_diff);
	if (nr_vcores == 1)
		printf("Context switch latency: %d nsec\n",
		       (int)(1000LL*usec_diff / nr_ctx_switches));
	printf("Context switches / sec: %d\n\n",
	       (int)(1000000LL*nr_ctx_switches / usec_diff));
} 
Beispiel #7
0
void pth_thread_runnable(struct uthread *uthread)
{
	struct pthread_tcb *pthread = (struct pthread_tcb*)uthread;
	struct mcs_lock_qnode local_qn = {0};
	/* Insert the newly created thread into the ready queue of threads.
	 * It will be removed from this queue later when vcore_entry() comes up */
	mcs_lock_notifsafe(&queue_lock, &local_qn);
	TAILQ_INSERT_TAIL(&ready_queue, pthread, next);
	threads_ready++;
	mcs_unlock_notifsafe(&queue_lock, &local_qn);
	/* Smarter schedulers should look at the num_vcores() and how much work is
	 * going on to make a decision about how many vcores to request. */
	vcore_request(threads_ready);
}
Beispiel #8
0
void vcore_entry(void)
{
	uint32_t vcoreid;
	static int first_time = 1; // used by vcore2
	int retval;

	vcoreid = vcore_id();
	printf("Hello from vcore_entry in vcore %d\n", vcoreid);

	if ((vcoreid == 2) && first_time) {
		first_time = 0;
		switch (test) {
			case TEST_INCREMENTAL_CHANGES:
				// Testing asking for less than we already have
				udelay(1000000);
				printf("Asking for too few:\n");
				retval = vcore_request(2);
				printf("Should be -EINVAL(7): %d\n", retval);
				// Testing getting more while running
				printf("Asking for more while running:\n");
				udelay(1000000);
				retval = vcore_request(5);
				printf("core2's retval: %d\n", retval);
				break;
			case TEST_YIELD_OUT_OF_ORDER:
				printf("Core %d yielding\n", vcoreid);
				sys_yield(0);
				break;
			case TEST_YIELD_0_OUT_OF_ORDER:
				udelay(7500000);
				printf("Core 0 should have yielded, asking for another\n");
				retval = vcore_request(5);
		}
	}
	global_tests(vcoreid);
	printf("Vcore %d Done!\n", vcoreid);
}
Beispiel #9
0
/* Test program for the audio device.  mmap()s the stuff, sets up a notif
 * handler, and switches to multi_mode.
 *
 * Note: this has a lot of mhello-like MCP infrastructure.  When Lithe is
 * working, you won't need any of this.  Just the mmap stuff and the notif
 * handler.  Stuff specific to the ethernet audio device is marked ETH_AUD. */
int main() 
{ 
	int retval;
	int in_fd, out_fd;
	/* ETHAUD mmap the input and output buffers */
	in_fd = open("/dev/eth_audio_in", O_RDONLY);
	out_fd = open("/dev/eth_audio_out", O_RDWR);
	assert(in_fd != -1);
	assert(out_fd != -1);
	in_buf = mmap(0, PGSIZE, PROT_READ, 0, in_fd, 0);
	if (in_buf == MAP_FAILED) {
		int err = errno;
		perror("Can't mmap the input buf:");
	}
	out_buf = mmap(0, PGSIZE, PROT_READ | PROT_WRITE, MAP_POPULATE, out_fd, 0);
	if (out_buf == MAP_FAILED) {
		int err = errno;
		perror("Can't mmap the output buf:");
	}
	//strncpy(out_buf, "Nanwan loves you!\n", 19);

/* begin: stuff userspace needs to do before switching to multi-mode */
	vcore_init();

	/* ETHAUD Turn on Free apple pie (which is the network packet) */
	enable_kevent(EV_FREE_APPLE_PIE, 0, EVENT_IPI);

	/* Need to save this somewhere that you can find it again when restarting
	 * core0 */
	core0_tls = get_tls_desc(0);
	/* Need to save our floating point state somewhere (like in the
	 * user_thread_tcb so it can be restarted too */

/* end: stuff userspace needs to do before switching to multi-mode */
	/* ETHAUD */
	/* Switch into _M mode */
	retval = vcore_request(1);

	/* Stay alive for a minute (will take interrupts) */
	udelay(60000000);

	printf("Eth aud, finishing up!\n");
	/* Need to do unmap it, due to some limitations in the kernel */
	munmap(in_buf, PGSIZE);
	munmap(out_buf, PGSIZE);
	close(in_fd);
	close(out_fd);
}
Beispiel #10
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 #11
0
int main(int argc, char** argv)
{

	/* don't forget to enable notifs on vcore0.  if you don't, the kernel will
	 * restart your _S with notifs disabled, which is a path to confusion. */
	struct preempt_data *vcpd = &__procdata.vcore_preempt_data[0];
	vcpd->notif_enabled = TRUE;

	mcs_barrier_init(&b, max_vcores());

	vcore_request(max_vcores());
	printf("not enough vcores, going to try it manually\n");
	sys_resource_req(RES_CORES, max_vcores(), 1, REQ_SOFT);
	printf("We're screwed!\n");

	/* should never make it here */
	return -1;
}
Beispiel #12
0
/**
 * Initialize the vcores, including jumping into muticore mode.
 **/
void vcore_startup()
{
	/* Initilize the bootstrap code for using the vcores */
	if (vcore_init())
		printf("vcore_init() failed, we're f****d!\n");
	assert(vcore_id() == 0);

	/* Tell the kernel where and how we want to receive events.  This is just an
	 * example of what to do to have a notification turned on.  We're turning on
	 * USER_IPIs, posting events to vcore 0's vcpd, and telling the kernel to
	 * send to vcore 0.  Note sys_self_notify will ignore the vcoreid pref.
	 * Also note that enable_kevent() is just an example, and you probably want
	 * to use parts of event.c to do what you want. */
	enable_kevent(EV_USER_IPI, 0, EVENT_IPI);

	/* Don't forget to enable notifs on vcore0.  if you don't, the kernel will
	 * restart your _S with notifs disabled, which is a path to confusion. */
	struct preempt_data *vcpd = &__procdata.vcore_preempt_data[0];
	vcpd->notif_enabled = TRUE;

	/* Grab a reference to the main_thread on the current stack (i.e.
	 * current_thread, since we know this has been set up for us properly by
	 * the fact that the constructor calls main_thread_init() before this
	 * function.  We will need this reference below. */
	thread_t *t = current_thread;

    /* Change temporarily to vcore0s tls region so we can save the main_thread
	 * into its thread local current_thread variable.  One minor issue is that
	 * vcore0's transition-TLS isn't TLS_INITed yet.  Until it is (right before
	 * vcore_entry(), don't try and take the address of any of its TLS vars. */
	extern void** vcore_thread_control_blocks;
	set_tls_desc(vcore_thread_control_blocks[0], 0);
	current_thread = t;
	set_tls_desc(t->context->tls_desc, 0);

	/* Jump into multi-core mode! */
	/* The next line of code that will run is inside vcore_entry().  When this
	 * thread is resumed, it will continue directly after this call to
	 * vcore_request() */
	vcore_request(1);
}
Beispiel #13
0
int bthread_create(bthread_t* thread, const bthread_attr_t* attr,
                   void *(*start_routine)(void *), void* arg)
{
  struct mcs_lock_qnode local_qn = {0};
  bthread_once(&init_once,&_bthread_init);

  *thread = (bthread_t)malloc(sizeof(work_queue_t));
  (*thread)->start_routine = start_routine;
  (*thread)->arg = arg;
  (*thread)->next = 0;
  (*thread)->finished = 0;
  (*thread)->detached = 0;
  mcs_lock_lock(&work_queue_lock, &local_qn);
  {
    threads_active++;
    queue_insert(&work_queue_head,&work_queue_tail,*thread);
    // don't return until we get a vcore
    while(threads_active > num_vcores() && vcore_request(1));
  }
  mcs_lock_unlock(&work_queue_lock, &local_qn);

  return 0;
}
Beispiel #14
0
int main(int argc, char** argv)
{
	uint32_t vcoreid;
	int retval;
	vcore_init();

	if ((vcoreid = vcore_id())) {
		printf("Should never see me! (from vcore %d)\n", vcoreid);
	} else { // core 0
		printf("Hello from else vcore 0\n");
		printf("Multi-Goodbye, world, from PID: %d!\n", sys_getpid());
		switch (test) {
			case TEST_MMAP:
				printf("Testing MMAP\n");
				void *addr;
				addr = sys_mmap((void*)USTACKTOP - 20*PGSIZE, 8*PGSIZE, 3,
				                MAP_FIXED | MAP_ANONYMOUS, -1, 0);
				printf("got addr = 0x%08x\n", addr);
				*(int*)addr = 0xdeadbeef;
				*(int*)(addr + 3*PGSIZE) = 0xcafebabe;
				// these should work
				printf("reading addr: 0x%08x\n", *(int*)addr);
				printf("reading addr+3pg: 0x%08x\n", *(int*)(addr + 3*PGSIZE));
				// this should fault
				printf("Should page fault and die now.\n");
				*(int*)(addr - 3*PGSIZE) = 0xdeadbeef;
				printf("Should not see me!!!!!!!!!!!!!!!!!!\n");
				while(1);
			case TEST_ONE_CORE:
				retval = vcore_request(1);
				printf("One core test's core0's retval: %d\n", retval);
				printf("Check to see it's on a worker core.\n");
				while(1);
			case TEST_ASK_FOR_TOO_MANY_CORES:
				retval = vcore_request(12);
				printf("Asked for too many, retval: %d\n", retval);
				return 0;
			case TEST_INCREMENTAL_CHANGES:
				retval = vcore_request(4);
				break;
			default:
				retval = vcore_request(5);
		}
		if (retval)
			panic("failed to allocate cores!");
		printf("Should see me if you want to relocate core0's context "
		        "when moving from RUNNING_S\n");
	}

	// vcore0 only below here
	switch (test) {
		case TEST_YIELD_OUT_OF_ORDER:
			udelay(10000000);
			printf("Core 2 should have yielded, asking for another\n");
			retval = vcore_request(5);
			break;
		case TEST_YIELD_0_OUT_OF_ORDER:
			udelay(5000000);
			printf("Core %d yielding\n", vcoreid);
			sys_yield(0);
			printf("Core 0 came back where it left off in RUNNING_M!!!\n");
			break;
	}
	global_tests(vcoreid);
	printf("Vcore %d Done!\n", vcoreid);
	while (1);
	return 0;
}
Beispiel #15
0
int main(int argc, char **argv)
{
	int i, amt;
	int nr_gpcs = 1;
	uint64_t entry;
	int fd = open("#c/sysctl", O_RDWR), ret;
	int kfd = -1;
	bool smallkernel = false;
	void * x;
	static char cmd[512];
	if (fd < 0) {
		perror("#c/sysctl");
		exit(1);
	}
	argc--,argv++;
	if (argc != 2) {
		fprintf(stderr, "Usage: %s vmimage entrypoint\n", argv[0]);
		exit(1);
	}
	entry = strtoull(argv[1], 0, 0);
	kfd = open(argv[0], O_RDONLY);
	if (kfd < 0) {
		perror(argv[0]);
		exit(1);
	}
	if (ros_syscall(SYS_setup_vmm, nr_gpcs, 0, 0, 0, 0, 0) != nr_gpcs) {
		perror("Guest pcore setup failed");
		exit(1);
	}
		my_threads = malloc(sizeof(pthread_t) * nr_threads);
		my_retvals = malloc(sizeof(void*) * nr_threads);
		if (!(my_retvals && my_threads))
			perror("Init threads/malloc");

		pthread_can_vcore_request(FALSE);	/* 2LS won't manage vcores */
		pthread_need_tls(FALSE);
		pthread_mcp_init();					/* gives us one vcore */
		vcore_request(nr_threads - 1);		/* ghetto incremental interface */
		for (int i = 0; i < nr_threads; i++) {
			x = __procinfo.vcoremap;
			printf("%p\n", __procinfo.vcoremap);
			printf("Vcore %d mapped to pcore %d\n", i,
			    	__procinfo.vcoremap[i].pcoreid);
		}
		if (pthread_create(&my_threads[0], NULL, &talk_thread, NULL))
			perror("pth_create failed");
//		if (pthread_create(&my_threads[1], NULL, &fail, NULL))
//			perror("pth_create failed");
	printf("threads started\n");

	if (0) for (int i = 0; i < nr_threads-1; i++) {
		int ret;
		if (pthread_join(my_threads[i], &my_retvals[i]))
			perror("pth_join failed");
		printf("%d %d\n", i, ret);
	}
	

	ret = syscall(33, 1);
	if (ret < 0) {
		perror("vm setup");
		exit(1);
	}
	/* blob that is faulted in from the EPT first.  we need this to be in low
	 * memory (not above the normal mmap_break), so the EPT can look it up.
	 * Note that we won't get 4096.  The min is 1MB now, and ld is there. */

	mmap_blob = mmap((int*)(15*1048576), 16 * 1048576, PROT_EXEC | PROT_READ | PROT_WRITE,
	                 MAP_ANONYMOUS, -1, 0);
	if (mmap_blob == MAP_FAILED) {
		perror("Unable to mmap");
		exit(1);
	}

	memset(mmap_blob, 0, 16*1048576);
	// read in the kernel.
	x = mmap_blob + 0x1000000;
	for(;;) {
		amt = read(kfd, x, 1048576);
		if (amt < 0) {
			perror("read");
			exit(1);
		}
		if (amt == 0) {
			break;
		}
		x += amt;
	}
	fprintf(stderr, "Read in %d bytes\n", x-mmap_blob);

	p512 = mmap_blob;
	p1 = &p512[512];
	p2m = &p512[1024];
	
	// We had thought to enter the kernel at the high address. But
	// there's just too much state the kernel has to clean up to
	// make this really work -- consider all the segment
	// descriptors that have to move, etc.  So we will enter the
	// kernel in the low part of the address space, and let it
	// work up its page tables and the other good fun.  Map the
	// kernel address space at low virtual, for 1G.  It's ok to
	// map memory we have no access to.
#define _2MiB 0x200000
	p512[0] = (unsigned long long)p1 | 7;
	// if only we could guarantee 1G pages everywhere!
	p1[0] = /*0x87; */(unsigned long long)p2m | 7;
	for(i = 0; i < 16; i++) {
		p2m[i] = 0x87 | i * _2MiB;
		printf("pwm[%d] = 0x%llx\n", i, p2m[i]);
	}
	printf("p512 %p p512[0] is 0x%lx p1 %p p1[0] is 0x%x\n", p512, p512[0], p1, p1[0]);
	sprintf(cmd, "V 0x%llx 0x%llx 0x%llx", entry, (unsigned long long) &stack[1024], (unsigned long long) p512);
	printf("Writing command :%s:\n", cmd);
	ret = write(fd, cmd, strlen(cmd));
	if (ret != strlen(cmd)) {
		perror(cmd);
	}

	sprintf(cmd, "V 0 0 0");
	while (! done) {
		char c[1];
		printf("hit return\n"); read(0, c, 1);
		if (debug)
			fprintf(stderr, "RESUME\n");
		ret = write(fd, cmd, strlen(cmd));
		if (ret != strlen(cmd)) {
			perror(cmd);
		}
	}
	return 0;
}
Beispiel #16
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;
}
Beispiel #17
0
int main(int argc, char** argv)
{
	uint32_t vcoreid;
	int retval;

	mcs_barrier_init(&b, max_vcores());

	/* vcore_context test */
	assert(!in_vcore_context());
	
	/* prep indirect ev_q.  Note we grab a big one */
	indirect_q = get_big_event_q();
	indirect_q->ev_flags = EVENT_IPI;
	indirect_q->ev_vcore = 1;			/* IPI core 1 */
	indirect_q->ev_handler = 0;
	printf("Registering %08p for event type %d\n", indirect_q,
	       EV_FREE_APPLE_PIE);
	register_kevent_q(indirect_q, EV_FREE_APPLE_PIE);

	/* handle events: just want to print out what we get.  This is just a
	 * quick set of handlers, not a registration for a kevent. */
	for (int i = 0; i < MAX_NR_EVENT; i++)
		ev_handlers[i] = handle_generic;
	/* Want to use the default ev_ev (which we just overwrote) */
	ev_handlers[EV_EVENT] = handle_ev_ev;
	/* vcore_init() done in vcore_request() now. */
	/* Set up event reception.  For example, this will allow us to receive an
	 * event and IPI for USER_IPIs on vcore 0.  Check event.c for more stuff.
	 * Note you don't have to register for USER_IPIs to receive ones you send
	 * yourself with sys_self_notify(). */
	enable_kevent(EV_USER_IPI, 0, EVENT_IPI);
	/* Receive pending preemption events.  Can also get a MSG if you want. */
	struct event_queue *ev_q = get_event_q();
	ev_q->ev_flags = EVENT_IPI | EVENT_NOMSG | EVENT_VCORE_APPRO;
	register_kevent_q(ev_q, EV_PREEMPT_PENDING);

	/* Makes 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 */
	uthread_create(dummy, 0);

	if ((vcoreid = vcore_id())) {
		printf("Should never see me! (from vcore %d)\n", vcoreid);
	} else { // core 0
		temp = 0xdeadbeef;
		printf("Hello from vcore %d with temp addr = %p and temp = %p\n",
		       vcoreid, &temp, temp);
		printf("Multi-Goodbye, world, from PID: %d!\n", sys_getpid());
		//retval = sys_resource_req(RES_CORES, 2, 0);
		printf("Requesting %d vcores\n", max_vcores() - 1);
		retval = vcore_request(max_vcores() - 1); /* since we already have 1 */
		//retval = vcore_request(5);
		printf("This is vcore0, right after vcore_request, retval=%d\n", retval);
		/* vcore_context test */
		assert(!in_vcore_context());
	}

	/* test notifying my vcore2 */
	udelay(5000000);
	printf("Vcore 0 self-notifying vcore 2 with notif 4!\n");
	struct event_msg msg;
	msg.ev_type = 4;
	sys_self_notify(2, 4, &msg);
	udelay(5000000);
	printf("Vcore 0 notifying itself with notif 3!\n");
	msg.ev_type = 3;
	sys_notify(sys_getpid(), 3, &msg);
	udelay(1000000);

	/* test loop for restarting a notif_tf */
	if (vcoreid == 0) {
		int ctr = 0;
		while(1) {
			printf("Vcore %d Spinning (%d), temp = %08x!\n", vcoreid, ctr++, temp);
			udelay(5000000);
			//exit(0);
		}
	}

	printf("Vcore %d Done!\n", vcoreid);
	//mcs_barrier_wait(&b,vcore_id());

	printf("All Cores Done!\n", vcoreid);
	while(1); // manually kill from the monitor
	return 0;
}
Beispiel #18
0
/* to trick uthread_create() */
int main(int argc, char** argv)
{
	uint32_t vcoreid;
	int retval;

	/* Initialize our barrier. */
	mcs_barrier_init(&b, max_vcores());

	/* vcore_context test */
	assert(!in_vcore_context());
	
	/* prep indirect ev_q.  Note we grab a big one */
	indirect_q = get_eventq(EV_MBOX_UCQ);
	indirect_q->ev_flags = EVENT_IPI;
	indirect_q->ev_vcore = 1;			/* IPI core 1 */
	indirect_q->ev_handler = 0;
	printf("Registering %08p for event type %d\n", indirect_q,
	       EV_FREE_APPLE_PIE);
	register_kevent_q(indirect_q, EV_FREE_APPLE_PIE);

	/* handle events: just want to print out what we get.  This is just a
	 * quick set of handlers, not a registration for a kevent. */
	for (int i = 0; i < MAX_NR_EVENT; i++)
		register_ev_handler(i, handle_generic, 0);
	/* Want to use the default ev_ev (which we just overwrote) */
	register_ev_handler(EV_EVENT, handle_ev_ev, 0);
	/* vcore_lib_init() done in vcore_request() now. */
	/* Set up event reception.  For example, this will allow us to receive an
	 * event and IPI for USER_IPIs on vcore 0.  Check event.c for more stuff.
	 * Note you don't have to register for USER_IPIs to receive ones you send
	 * yourself with sys_self_notify(). */
	enable_kevent(EV_USER_IPI, 0, EVENT_IPI | EVENT_VCORE_PRIVATE);
	/* Receive pending preemption events.  (though there's no PP handler) */
	struct event_queue *ev_q = get_eventq_vcpd(0, EVENT_VCORE_PRIVATE);
	ev_q->ev_flags = EVENT_IPI | EVENT_VCORE_APPRO;
	register_kevent_q(ev_q, EV_PREEMPT_PENDING);
	/* We also receive preemption events, it is set up in uthread.c */

	/* 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_mcp_init();
	/* Reset the blockon to be the spinner...  This is really shitty.  Any
	 * blocking calls after we become an MCP and before this will fail.  This is
	 * just mhello showing its warts due to trying to work outside uthread.c */
	ros_syscall_blockon = __ros_syscall_spinon;

	if ((vcoreid = vcore_id())) {
		printf("Should never see me! (from vcore %d)\n", vcoreid);
	} else { // core 0
		temp = 0xdeadbeef;
		printf("Hello from vcore %d with temp addr = %p and temp = %p\n",
		       vcoreid, &temp, temp);
		printf("Multi-Goodbye, world, from PID: %d!\n", sys_getpid());
		printf("Requesting %d vcores\n", max_vcores() - 1);
		retval = vcore_request(max_vcores() - 1); /* since we already have 1 */
		//retval = vcore_request(5);
		printf("This is vcore0, right after vcore_request, retval=%d\n", retval);
		/* vcore_context test */
		assert(!in_vcore_context());
	}

	//#if 0
	/* test notifying my vcore2 */
	udelay(5000000);
	printf("Vcore 0 self-notifying vcore 2 with notif 4!\n");
	struct event_msg msg;
	msg.ev_type = 4;
	sys_self_notify(2, 4, &msg, TRUE);
	udelay(5000000);
	printf("Vcore 0 notifying itself with notif 6!\n");
	msg.ev_type = 6;
	sys_notify(sys_getpid(), 6, &msg);
	udelay(1000000);
	//#endif

	/* test loop for restarting a uthread_ctx */
	if (vcoreid == 0) {
		int ctr = 0;
		while(1) {
			printf("Vcore %d Spinning (%d), temp = %08x!\n", vcoreid, ctr++, temp);
			udelay(5000000);
			//exit(0);
		}
	}

	printf("Vcore %d Done!\n", vcoreid);
	//mcs_barrier_wait(&b,vcore_id());

	printf("All Cores Done!\n", vcoreid);
	while(1); // manually kill from the monitor
	/* since everyone should cleanup their uthreads, even if they don't plan on
	 * calling their code or want uthreads in the first place. <3 */
	uthread_cleanup(&dummy);
	return 0;
}