3 #include <parlib/parlib.h>
4 #include <parlib/event.h>
5 #include <parlib/vcore.h>
6 #include <parlib/assert.h>
8 #include <parlib/uthread.h>
10 /* Deprecated, don't use this in any serious way */
12 static void handle_syscall(struct event_msg *ev_msg, unsigned int ev_type,
14 struct syscall sysc = {0};
15 struct event_queue *ev_q;
16 void ghetto_vcore_entry(void);
18 struct schedule_ops ghetto_sched_ops = {
19 .sched_entry = ghetto_vcore_entry,
22 int main(int argc, char** argv)
27 /* register our syscall handler (2LS does this) */
28 register_ev_handler(EV_SYSCALL, handle_syscall, 0);
30 printf("Trying to block\n");
31 /* Not doing anything else to it: no EVENT_IPI yet, etc. */
33 /* issue the diagnostic block syscall */
35 sysc.arg0 = 5000; /* 5ms */
38 num_started = __ros_arch_syscall((long)&sysc, 1);
39 if (!(atomic_read(&sysc.flags) & SC_DONE))
40 printf("Not done, looping!\n");
41 /* You could poll on this. This is really ghetto, but i got rid of
42 * event_activity, whose sole purpose was to encourage spinning. */
43 while (!(atomic_read(&sysc.flags) & SC_DONE))
46 /* by now, we should have run our handler */
47 /********************************************************/
48 /* Start MCP / IPI test */
49 printf("Switching to _M mode and testing an IPI-d ev_q\n");
50 printf("Our indirect ev_q is %08p\n", ev_q);
52 /* begin: stuff userspace needs to do before switching to multi-mode */
53 /* Note we don't need to set up event reception for any particular kevent.
54 * The ev_q in the syscall said to send an IPI to vcore 0 which means an
55 * EV_EVENT will be sent straight to vcore0. */
56 /* Inits a thread for us, though we won't use it. Just a hack to get into
57 * _M mode. Note this requests one vcore for us */
58 struct uthread dummy = {0};
59 uthread_2ls_init(&dummy, &ghetto_sched_ops);
61 /* Need to save our floating point state somewhere (like in the
62 * user_thread_tcb so it can be restarted too */
64 /* end: stuff userspace needs to do before switching to multi-mode */
66 vcore_request_total(1);
67 /* now we're back in thread 0 on vcore 0 */
68 ev_q->ev_flags = EVENT_IPI;
70 sysc.u_data = (void*)1; /* using this to loop on */
71 /* issue the diagnostic blocking syscall */
73 sysc.arg0 = 5000; /* 5ms */
75 num_started = __ros_arch_syscall((long)&sysc, 1);
76 /* have this thread "wait" */
77 if (!(atomic_read(&sysc.flags) & SC_DONE))
78 printf("Not done, looping on a local variable!\n");
81 assert(atomic_read(&sysc.flags) & SC_DONE);
82 printf("Syscall unblocked, IPI broke me out of the loop.\n");
86 printf("Syscall test exiting\n");
90 static void handle_syscall(struct event_msg *ev_msg, unsigned int ev_type,
93 struct syscall *my_sysc;
96 my_sysc = ev_msg->ev_arg3;
97 printf("Handling syscall event for sysc %08p (%08p)\n",
99 /* our syscall should be done (we ought to check the msg pointer) */
100 if (atomic_read(&sysc.flags) & SC_DONE)
101 printf("Syscall is done, retval: %d\n", sysc.retval);
103 printf("BUG! Syscall wasn't done!\n");
104 /* signal to thread 0 that the sysc is done, just to show this
105 * is getting done in vcore context. */
109 void ghetto_vcore_entry(void)
111 uint32_t vcoreid = vcore_id();
112 static bool first_time = TRUE;
114 /* begin: stuff userspace needs to do to handle notifications */
116 /* Restart vcore0's context. */
118 run_current_uthread();
119 panic("should never see me!");
121 /* unmask notifications once you can let go of the uthread_ctx and it is
122 * okay to clobber the transition stack.
123 * Check Documentation/processes.txt: 4.2.4. In real code, you should be
124 * popping the tf of whatever user process you want (get off the x-stack) */
125 struct preempt_data *vcpd;
126 vcpd = &__procdata.vcore_preempt_data[vcoreid];
127 vcpd->notif_disabled = FALSE;
129 /* end: stuff userspace needs to do to handle notifications */
130 /* if you have other vcores, they'll just chill here */