1 static char *rcsid = "$Id: mpx.c,v 1.2 1996/07/09 19:41:39 paul Exp $";
2
3 /*
4 * This file contains functions to handle context switching and SunOS signals
5 * in smx. As signals cause context switches, the two are closely related.
6 * The entry points for the file are:
7 *
8 * restart - called from the bootstrap code to schedule the first process
9 * idle_task - the main body of the idle task.
10 *
11 * The SunOSsig function could also be considered an entry point. It is
12 * the handler for all SunOS signals, and so is called whenever a SunOS
13 * signal occurs. It is the sole entry point for the layer 1 code once
14 * the first process has been scheduled for the first time.
15 */
16
17 #include "kernel.h"
18 #include "proc.h"
19 #include "sunsighandle.h"
20
21 #include <sun/syscall.h>
22
23 /*
24 * Check that the context size calculated by make_context (UC_SIZE)
25 * matches the smx CONTEXT_SIZE.
26 */
27 #if (CONTEXT_SIZE != UC_SIZE)
28 error "p_reg is the wrong size"
29 #endif
30
31 static double gwin_save_area[GWIN_SIZE / sizeof(double) + 1];
32 struct proc *gwin_proc = 0;
33
34
35 /*
36 * mpx_start and mpx_end are dummy functions used to delimit the section
37 * of this file (the resume and SunOSsig functions) that must remain
38 * executable even when execution is outside the kernel. These labels
39 * are needed by code in sunprotect.c
40 */
41
42 void mpx_start() {}
43
44 /*
45 * Function: resume
46 * Parameter: ctxt - double-word aligned context area that we can copy
47 * the context of proc_ptr.
48 *
49 * Resume execution of the the current process as given by proc_ptr.
50 * We make a local copy of the context to restore for two reasons: to double
51 * word align it, and so that if full memory protection is enabled we
52 * still have access to the context after leaving_kernel has done its work.
53 * Callers must ensure that ctxt points to a double-word aligned area on the
54 * stack. If a gwin structure is to be restored, it is first copied to
55 * an array local to resume for the same reasons.
56 */
57 static void resume(reg_t *ctxt)
58 {
59 double local_save_area[GWIN_SIZE / sizeof(double) + 1];
60
61 memcpy(ctxt, &proc_ptr->p_reg, sizeof(proc_ptr->p_reg));
62
63 /*
64 * Clear signal mask---no SunOS signals are masked when execution is
65 * outside layer 1.
66 */
67 memset(&ctxt[UC_SIGMASK], 0, SIGSET_SIZE);
68
69 /*
70 * Set the sig mask flag bit to ensure the signal mask gets restored.
71 */
72 ctxt[UC_FLAGS] |= 1;
73 if (ctxt[UC_GWINS] != 0) {
74 /*
75 * A gwins structure must be restored. Copy it in, and update the
76 * gwin pointer in the context to be restored.
77 */
78 gwin_proc = 0;
79 memcpy(local_save_area, gwin_save_area, sizeof(local_save_area));
80 ctxt[UC_GWINS] = (reg_t) local_save_area;
81 }
82 leaving_kernel();
83
84 /*
85 * Do a context switch. This call should never return, with layer 1 code
86 * being re-entered via SunOSsig.
87 */
88 SunOS(SYS_context, 1, ctxt);
89 printf("Gwin = 0x%x, fpuq = 0x%x, ctxt = 0x%x\n", ctxt[UC_GWINS],
90 ctxt[UC_FPU_Q], ctxt);
91 panic("resume: failed to resume an smx process", errno);
92 }
93
94
95 /*
96 * Function: SunOSsig
97 * Parameters: sig - the SunOS signal that has occurred
98 * siginfo - additional info about the signal
99 * ucontext - context for the smx process that was running when
100 * the SunOS signal ocurred.
101 *
102 * This function is the handler for all signals received by the SunOS
103 * process running smx. The 'ucontext' structure pushed onto the
104 * kernel (signal) stack by Solaris is copied into the MINIX proc
105 * table entry of the currently executing MINIX process. The array
106 * 'vectors' is used to determine which function within the smx
107 * kernel should then take responsibilty for the signal. Finally, the
108 * context of an smx process is restored.
109 */
110 void SunOSsig(int sig, void *siginfo, reg_t ucontext[])
111 {
112 entering_kernel();
113
114 /*
115 * Is there a gwins structure to save (should only happen when the stack
116 * of a user process needs extending). The single save area is sufficient
117 * because once it is in use the process using it will be the next user
118 * process to run (the scheduler ensures this).
119 */
120 if (ucontext[UC_GWINS] != 0) {
121 if (gwin_proc != 0) {
122 panic("SunOSsig---save area used", NO_NUM);
123 }
124 if (!isuserp(proc_ptr)) {
125 panic("UC_GWINS non-zero in process", proc_number(proc_ptr));
126 }
127 gwin_proc = proc_ptr;
128 memcpy(gwin_save_area, (char *) ucontext[UC_GWINS],
129 sizeof(gwin_save_area));
130 }
131 /*
132 * Save the ucontext structure into the current proc table entry.
133 */
134 memcpy(&proc_ptr->p_reg, ucontext, sizeof(proc_ptr->p_reg));
135
136
137 if (sig < 0 || sig >= vectorlen)
138 panic("SunOS signal too large or too small", sig);
139 (*vectors[sig])(sig, siginfo, ucontext); /* Call the handler */
140
141 lock_pick_proc(); /* (possibly) choose a new process */
142
143 resume(ucontext);
144 /*NOTREACHED*/
145 }
146
147 void mpx_end() {}
148
149
150 /*
151 * Function: restart
152 *
153 * The 'restart' function is called (only once) from 'main.c' in order
154 * to get the the first process running.
155 */
156 void restart(void)
157 {
158 struct stackframe_s dummy_regs;
159
160 k_reenter = 0; /* Nested interrupt handling is not supported */
161
162 resume((reg_t *) &dummy_regs);
163 /*NOTREACHED*/
164 }
165
166
167 /*****************************************************************************
168 * Some of the functions found in the vectors array. *
169 *****************************************************************************/
170
171 /*
172 * Function: s_call
173 *
174 * s_call is called from SunOSsig to handle the SunOS USR1 signal,
175 * which is sent by an smx process in layers 2-4 to force execution
176 * into layer 1 of smx. The three system calls are send, receive,
177 * and sndrcv. s_call simply sets up parameters for a call to the
178 * standard MINIX sys_call function, and passes the return result
179 * back to the calling smx process.
180 */
181 void s_call(void)
182 {
183 phys_bytes param_ptr; /* ptr to the system call parameters */
184 int function; /* SEND, RECEIVE, or BOTH */
185 int src_dest; /* source to receive from or dest to send to */
186 message *m_ptr; /* pointer to message */
187 int params[3];
188 struct proc *this_proc = proc_ptr;
189
190 /*
191 * The arguments to sys_call are on the stack. For the SPARC
192 * stack frame, the first argument is at sp + 92.
193 */
194 param_ptr = umap(this_proc, D, this_proc->p_reg.sp + 92, sizeof(params));
195 if (param_ptr == 0) {
196 panic("s_call: Can't map in parameter to system call", NO_NUM);
197 }
198
199 /* Load the parameters */
200 phys_copy(param_ptr, vir2phys(¶ms[0]), sizeof(params));
201 function = params[0];
202 src_dest = params[1];
203 m_ptr = (message *)params[2]; /* Assumes ints can hold a pointer */
204
205 this_proc->p_reg.retreg = sys_call(function, src_dest, m_ptr);
206 }
207
208
209 /*
210 * Function: smx_clock_handler
211 *
212 * Called by SunOSsig whenever a SIGALRM occurs. Calls clock handler
213 * with 0 ticks, as in smx the SunOS clock is always consulted to
214 * update the time on a clock tick.
215 */
216 void smx_clock_handler(void)
217 {
218 clock_handler(0);
219 }
220
221
222 /*==========================================================================*
223 * idle_task *
224 *==========================================================================*/
225
226 #define SIGPAUSE 0x1000
227
228 /* Does nothing but sleep waiting for a signal*/
229
230 void idle_task(void)
231 {
232 for (;;) {
233 SunOS(SYS_signal, (SIGPAUSE | 1));
234 }
235 }
236
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.