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