8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / lib / libproc / common / Psyscall.c
blobaf2f229641c12eb11a6f5f2c8e9e0cc6fe00e659
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
27 * Copyright (c) 2013, Joyent, Inc. All rights reserved.
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <unistd.h>
33 #include <ctype.h>
34 #include <fcntl.h>
35 #include <string.h>
36 #include <memory.h>
37 #include <errno.h>
38 #include <dirent.h>
39 #include <limits.h>
40 #include <signal.h>
41 #include <sys/types.h>
42 #include <sys/uio.h>
43 #include <sys/stat.h>
44 #include <sys/resource.h>
45 #include <sys/param.h>
46 #include <sys/stack.h>
47 #include <sys/fault.h>
48 #include <sys/syscall.h>
49 #include <sys/sysmacros.h>
51 #include "libproc.h"
52 #include "Pcontrol.h"
53 #include "Putil.h"
54 #include "P32ton.h"
55 #include "Pisadep.h"
57 extern sigset_t blockable_sigs;
59 static void
60 Pabort_agent(struct ps_prochandle *P)
62 int sysnum = P->status.pr_lwp.pr_syscall;
63 int stop;
65 dprintf("agent LWP is stopped or asleep in syscall %d\n", sysnum);
66 (void) Pstop(P, 0);
67 stop = Psysexit(P, sysnum, TRUE);
69 if (Psetrun(P, 0, PRSABORT) == 0) {
70 while (Pwait(P, 0) == -1 && errno == EINTR)
71 continue;
72 (void) Psysexit(P, sysnum, stop);
73 dprintf("agent LWP system call aborted\n");
78 * Create the /proc agent LWP for further operations.
80 int
81 Pcreate_agent(struct ps_prochandle *P)
83 int fd;
84 char pathname[PATH_MAX];
85 char *fname;
86 struct {
87 long cmd;
88 prgregset_t regs;
89 } cmd;
92 * If not first reference, we already have the /proc agent LWP active.
94 if (P->agentcnt > 0) {
95 P->agentcnt++;
96 return (0);
100 * The agent is not available for use as a mortician or as an
101 * obstetrician.
103 if (P->state == PS_DEAD || P->state == PS_UNDEAD ||
104 P->state == PS_IDLE) {
105 errno = ENOENT;
106 return (-1);
110 * Create the special /proc agent LWP if it doesn't already exist.
111 * Give it the registers of the representative LWP.
113 (void) Pstop(P, 0);
114 Psync(P);
115 if (!(P->status.pr_lwp.pr_flags & PR_AGENT)) {
116 cmd.cmd = PCAGENT;
117 (void) memcpy(&cmd.regs, &P->status.pr_lwp.pr_reg[0],
118 sizeof (P->status.pr_lwp.pr_reg));
119 if (write(P->ctlfd, &cmd, sizeof (cmd)) != sizeof (cmd))
120 goto bad;
123 /* refresh the process status */
124 (void) Pstopstatus(P, PCNULL, 0);
126 /* open the agent LWP files */
127 (void) snprintf(pathname, sizeof (pathname), "%s/%d/lwp/agent/",
128 procfs_path, (int)P->pid);
129 fname = pathname + strlen(pathname);
130 (void) set_minfd();
133 * It is difficult to know how to recover from the two errors
134 * that follow. The agent LWP exists and we need to kill it,
135 * but we can't because we need it active in order to kill it.
136 * We just hope that these failures never occur.
138 (void) strcpy(fname, "lwpstatus");
139 if ((fd = open(pathname, O_RDONLY)) < 0 ||
140 (fd = dupfd(fd, 0)) < 0)
141 goto bad;
142 P->agentstatfd = fd;
144 (void) strcpy(fname, "lwpctl");
145 if ((fd = open(pathname, O_WRONLY)) < 0 ||
146 (fd = dupfd(fd, 0)) < 0)
147 goto bad;
148 P->agentctlfd = fd;
151 * If the agent is currently asleep in a system call or stopped on
152 * system call entry, attempt to abort the system call so it's ready to
153 * serve.
155 if ((P->status.pr_lwp.pr_flags & PR_ASLEEP) ||
156 ((P->status.pr_lwp.pr_flags & PR_STOPPED) &&
157 P->status.pr_lwp.pr_why == PR_SYSENTRY)) {
158 dprintf("Pcreate_agent: aborting agent syscall; lwp is %s\n",
159 (P->status.pr_lwp.pr_flags & PR_ASLEEP) ?
160 "asleep" : "stopped");
161 Pabort_agent(P);
164 /* get the agent LWP status */
165 P->agentcnt++;
166 if (Pstopstatus(P, PCNULL, 0) != 0) {
167 Pdestroy_agent(P);
168 return (-1);
171 return (0);
173 bad:
174 if (P->agentstatfd >= 0)
175 (void) close(P->agentstatfd);
176 if (P->agentctlfd >= 0)
177 (void) close(P->agentctlfd);
178 P->agentstatfd = -1;
179 P->agentctlfd = -1;
180 /* refresh the process status */
181 (void) Pstopstatus(P, PCNULL, 0);
182 return (-1);
186 * Decrement the /proc agent agent reference count.
187 * On last reference, destroy the agent.
189 void
190 Pdestroy_agent(struct ps_prochandle *P)
192 if (P->agentcnt > 1)
193 P->agentcnt--;
194 else {
195 int flags;
197 Psync(P); /* Flush out any pending changes */
199 (void) Pstopstatus(P, PCNULL, 0);
200 flags = P->status.pr_lwp.pr_flags;
203 * If the agent is currently asleep in a system call, attempt
204 * to abort the system call so we can terminate the agent.
206 if ((flags & (PR_AGENT|PR_ASLEEP)) == (PR_AGENT|PR_ASLEEP)) {
207 dprintf("Pdestroy_agent: aborting agent syscall\n");
208 Pabort_agent(P);
212 * The agent itself is destroyed by forcing it to execute
213 * the _lwp_exit(2) system call. Close our agent descriptors
214 * regardless of whether this is successful.
216 (void) pr_lwp_exit(P);
217 (void) close(P->agentctlfd);
218 (void) close(P->agentstatfd);
219 P->agentctlfd = -1;
220 P->agentstatfd = -1;
221 P->agentcnt = 0;
224 * Now that (hopefully) the agent has exited, refresh the
225 * status: the representative LWP is no longer the agent.
227 (void) Pstopstatus(P, PCNULL, 0);
232 * Execute the syscall instruction.
234 static int
235 execute(struct ps_prochandle *P, int sysindex)
237 int ctlfd = (P->agentctlfd >= 0)? P->agentctlfd : P->ctlfd;
238 int washeld = FALSE;
239 sigset_t hold; /* mask of held signals */
240 int cursig;
241 struct {
242 long cmd;
243 siginfo_t siginfo;
244 } ctl;
245 int sentry; /* old value of stop-on-syscall-entry */
247 sentry = Psysentry(P, sysindex, TRUE); /* set stop-on-syscall-entry */
250 * If not already blocked, block all signals now.
252 if (memcmp(&P->status.pr_lwp.pr_lwphold, &blockable_sigs,
253 sizeof (sigset_t)) != 0) {
254 hold = P->status.pr_lwp.pr_lwphold;
255 P->status.pr_lwp.pr_lwphold = blockable_sigs;
256 P->flags |= SETHOLD;
257 washeld = TRUE;
261 * If there is a current signal, remember it and cancel it.
263 if ((cursig = P->status.pr_lwp.pr_cursig) != 0) {
264 ctl.cmd = PCSSIG;
265 ctl.siginfo = P->status.pr_lwp.pr_info;
268 if (Psetrun(P, 0, PRCSIG | PRCFAULT) == -1)
269 goto bad;
271 while (P->state == PS_RUN) {
272 (void) Pwait(P, 0);
274 if (P->state != PS_STOP)
275 goto bad;
277 if (cursig) /* restore cursig */
278 (void) write(ctlfd, &ctl, sizeof (ctl));
279 if (washeld) { /* restore the signal mask if we set it */
280 P->status.pr_lwp.pr_lwphold = hold;
281 P->flags |= SETHOLD;
284 (void) Psysentry(P, sysindex, sentry); /* restore sysentry stop */
286 if (P->status.pr_lwp.pr_why == PR_SYSENTRY &&
287 P->status.pr_lwp.pr_what == sysindex)
288 return (0);
289 bad:
290 return (-1);
295 * Perform system call in controlled process.
298 Psyscall(struct ps_prochandle *P,
299 sysret_t *rval, /* syscall return values */
300 int sysindex, /* system call index */
301 uint_t nargs, /* number of arguments to system call */
302 argdes_t *argp) /* argument descriptor array */
304 int agent_created = FALSE;
305 pstatus_t save_pstatus;
306 argdes_t *adp; /* pointer to argument descriptor */
307 int i; /* general index value */
308 int model; /* data model */
309 int error = 0; /* syscall errno */
310 int Perr = 0; /* local error number */
311 int sexit; /* old value of stop-on-syscall-exit */
312 prgreg_t sp; /* adjusted stack pointer */
313 prgreg_t ap; /* adjusted argument pointer */
314 sigset_t unblock;
316 (void) sigprocmask(SIG_BLOCK, &blockable_sigs, &unblock);
318 rval->sys_rval1 = 0; /* initialize return values */
319 rval->sys_rval2 = 0;
321 if (sysindex <= 0 || sysindex > PRMAXSYS || nargs > MAXARGS)
322 goto bad1; /* programming error */
324 if (P->state == PS_DEAD || P->state == PS_UNDEAD || P->state == PS_IDLE)
325 goto bad1; /* dead processes can't perform system calls */
327 model = P->status.pr_dmodel;
328 #ifndef _LP64
329 /* We must be a 64-bit process to deal with a 64-bit process */
330 if (model == PR_MODEL_LP64)
331 goto bad9;
332 #endif
335 * Create the /proc agent LWP in the process to do all the work.
336 * (It may already exist; nested create/destroy is permitted
337 * by virtue of the reference count.)
339 if (Pcreate_agent(P) != 0)
340 goto bad8;
343 * Save agent's status to restore on exit.
345 agent_created = TRUE;
346 save_pstatus = P->status;
348 if (P->state != PS_STOP || /* check state of LWP */
349 (P->status.pr_flags & PR_ASLEEP))
350 goto bad2;
352 if (Pscantext(P)) /* bad text ? */
353 goto bad3;
356 * Validate arguments and compute the stack frame parameters.
357 * Begin with the current stack pointer.
359 #ifdef _LP64
360 if (model == PR_MODEL_LP64) {
361 sp = P->status.pr_lwp.pr_reg[R_SP] + STACK_BIAS;
362 #if defined(__amd64)
364 * To offset the expense of computerised subtraction, the AMD64
365 * ABI allows a process the use of a 128-byte area beyond the
366 * location pointed to by %rsp. We must advance the agent's
367 * stack pointer by at least the size of this region or else it
368 * may corrupt this temporary storage.
370 sp -= STACK_RESERVE64;
371 #endif
372 sp = PSTACK_ALIGN64(sp);
373 } else {
374 #endif
375 sp = (uint32_t)P->status.pr_lwp.pr_reg[R_SP];
376 sp = PSTACK_ALIGN32(sp);
377 #ifdef _LP64
379 #endif
382 * For each AT_BYREF argument, compute the necessary
383 * stack space and the object's stack address.
385 for (i = 0, adp = argp; i < nargs; i++, adp++) {
386 rval->sys_rval1 = i; /* in case of error */
387 switch (adp->arg_type) {
388 default: /* programming error */
389 goto bad4;
390 case AT_BYVAL: /* simple argument */
391 break;
392 case AT_BYREF: /* must allocate space */
393 switch (adp->arg_inout) {
394 case AI_INPUT:
395 case AI_OUTPUT:
396 case AI_INOUT:
397 if (adp->arg_object == NULL)
398 goto bad5; /* programming error */
399 break;
400 default: /* programming error */
401 goto bad6;
403 /* allocate stack space for BYREF argument */
404 if (adp->arg_size == 0 || adp->arg_size > MAXARGL)
405 goto bad7; /* programming error */
406 #ifdef _LP64
407 if (model == PR_MODEL_LP64)
408 sp = PSTACK_ALIGN64(sp - adp->arg_size);
409 else
410 #endif
411 sp = PSTACK_ALIGN32(sp - adp->arg_size);
412 adp->arg_value = sp; /* stack address for object */
413 break;
416 rval->sys_rval1 = 0; /* in case of error */
418 * Point of no return.
419 * Perform the system call entry, adjusting %sp.
420 * This moves the LWP to the stopped-on-syscall-entry state
421 * just before the arguments to the system call are fetched.
423 ap = Psyscall_setup(P, nargs, sysindex, sp);
424 P->flags |= SETREGS; /* set registers before continuing */
425 dprintf("Psyscall(): execute(sysindex = %d)\n", sysindex);
428 * Execute the syscall instruction and stop on syscall entry.
430 if (execute(P, sysindex) != 0 ||
431 (!Pissyscall(P, P->status.pr_lwp.pr_reg[R_PC]) &&
432 !Pissyscall_prev(P, P->status.pr_lwp.pr_reg[R_PC], NULL)))
433 goto bad10;
435 dprintf("Psyscall(): copying arguments\n");
438 * The LWP is stopped at syscall entry.
439 * Copy objects to stack frame for each argument.
441 for (i = 0, adp = argp; i < nargs; i++, adp++) {
442 rval->sys_rval1 = i; /* in case of error */
443 if (adp->arg_type != AT_BYVAL &&
444 adp->arg_inout != AI_OUTPUT) {
445 /* copy input byref parameter to process */
446 if (Pwrite(P, adp->arg_object, adp->arg_size,
447 (uintptr_t)adp->arg_value) != adp->arg_size)
448 goto bad17;
451 rval->sys_rval1 = 0; /* in case of error */
452 if (Psyscall_copyinargs(P, nargs, argp, ap) != 0)
453 goto bad18;
456 * Complete the system call.
457 * This moves the LWP to the stopped-on-syscall-exit state.
459 dprintf("Psyscall(): set running at sysentry\n");
461 sexit = Psysexit(P, sysindex, TRUE); /* catch this syscall exit */
462 do {
463 if (Psetrun(P, 0, 0) == -1)
464 goto bad21;
465 while (P->state == PS_RUN)
466 (void) Pwait(P, 0);
467 } while (P->state == PS_STOP && P->status.pr_lwp.pr_why != PR_SYSEXIT);
468 (void) Psysexit(P, sysindex, sexit); /* restore original setting */
471 * If the system call was _lwp_exit(), we expect that our last call
472 * to Pwait() will yield ENOENT because the LWP no longer exists.
474 if (sysindex == SYS_lwp_exit && errno == ENOENT) {
475 dprintf("Psyscall(): _lwp_exit successful\n");
476 rval->sys_rval1 = rval->sys_rval2 = 0;
477 goto out;
480 if (P->state != PS_STOP || P->status.pr_lwp.pr_why != PR_SYSEXIT)
481 goto bad22;
483 if (P->status.pr_lwp.pr_what != sysindex)
484 goto bad23;
486 if (!Pissyscall_prev(P, P->status.pr_lwp.pr_reg[R_PC], NULL)) {
487 dprintf("Pissyscall_prev() failed\n");
488 goto bad24;
491 dprintf("Psyscall(): caught at sysexit\n");
494 * For each argument.
496 for (i = 0, adp = argp; i < nargs; i++, adp++) {
497 rval->sys_rval1 = i; /* in case of error */
498 if (adp->arg_type != AT_BYVAL &&
499 adp->arg_inout != AI_INPUT) {
500 /* copy output byref parameter from process */
501 if (Pread(P, adp->arg_object, adp->arg_size,
502 (uintptr_t)adp->arg_value) != adp->arg_size)
503 goto bad25;
507 if (Psyscall_copyoutargs(P, nargs, argp, ap) != 0)
508 goto bad26;
511 * Get the return values from the syscall.
513 if (P->status.pr_lwp.pr_errno) { /* error return */
514 error = P->status.pr_lwp.pr_errno;
515 rval->sys_rval1 = -1L;
516 rval->sys_rval2 = -1L;
517 dprintf("Psyscall(%d) fails with errno %d\n",
518 sysindex, error);
519 } else { /* normal return */
520 rval->sys_rval1 = P->status.pr_lwp.pr_rval1;
521 rval->sys_rval2 = P->status.pr_lwp.pr_rval2;
522 dprintf("Psyscall(%d) returns 0x%lx 0x%lx\n", sysindex,
523 P->status.pr_lwp.pr_rval1, P->status.pr_lwp.pr_rval2);
526 goto out;
528 bad26: Perr++;
529 bad25: Perr++;
530 bad24: Perr++;
531 bad23: Perr++;
532 bad22: Perr++;
533 bad21: Perr++;
534 Perr++;
535 Perr++;
536 bad18: Perr++;
537 bad17: Perr++;
538 Perr++;
539 Perr++;
540 Perr++;
541 Perr++;
542 Perr++;
543 Perr++;
544 bad10: Perr++;
545 bad9: Perr++;
546 bad8: Perr++;
547 bad7: Perr++;
548 bad6: Perr++;
549 bad5: Perr++;
550 bad4: Perr++;
551 bad3: Perr++;
552 bad2: Perr++;
553 bad1: Perr++;
554 error = -1;
555 dprintf("Psyscall(%d) fails with local error %d\n", sysindex, Perr);
557 out:
559 * Destroy the /proc agent LWP now (or just bump down the ref count).
561 if (agent_created) {
562 if (P->state != PS_UNDEAD) {
563 P->status = save_pstatus;
564 P->flags |= SETREGS;
565 Psync(P);
567 Pdestroy_agent(P);
570 (void) sigprocmask(SIG_SETMASK, &unblock, NULL);
571 return (error);