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_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 */ begin = read_tsc(); retval = vcore_request(max_vcores()); if (retval) printf("F****d!\n"); mcs_barrier_wait(&b, vcoreid); end = read_tsc(); printf("Took %llu usec (%llu nsec) to receive %d cores (cold).\n", udiff(begin, end), ndiff(begin, end), max_vcores()); printf("[T]:001:%llu:%llu:%d:C.\n", udiff(begin, end), ndiff(begin, end), max_vcores()); udelay(5000000); begin = read_tsc(); retval = vcore_request(max_vcores() - 1); if (retval) printf("F****d!\n"); mcs_barrier_wait(&b, vcoreid); end = read_tsc(); printf("Took %llu usec (%llu nsec) to receive %d cores (warm).\n", udiff(begin, end), ndiff(begin, end), max_vcores()); printf("[T]:001:%llu:%llu:%d:W.\n", udiff(begin, end), ndiff(begin, end), max_vcores()); return 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); }
/** * 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); }
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; }