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]
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.
41 #include <sys/types.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>
57 extern sigset_t blockable_sigs
;
60 Pabort_agent(struct ps_prochandle
*P
)
62 int sysnum
= P
->status
.pr_lwp
.pr_syscall
;
65 dprintf("agent LWP is stopped or asleep in syscall %d\n", sysnum
);
67 stop
= Psysexit(P
, sysnum
, TRUE
);
69 if (Psetrun(P
, 0, PRSABORT
) == 0) {
70 while (Pwait(P
, 0) == -1 && errno
== EINTR
)
72 (void) Psysexit(P
, sysnum
, stop
);
73 dprintf("agent LWP system call aborted\n");
78 * Create the /proc agent LWP for further operations.
81 Pcreate_agent(struct ps_prochandle
*P
)
84 char pathname
[PATH_MAX
];
92 * If not first reference, we already have the /proc agent LWP active.
94 if (P
->agentcnt
> 0) {
100 * The agent is not available for use as a mortician or as an
103 if (P
->state
== PS_DEAD
|| P
->state
== PS_UNDEAD
||
104 P
->state
== PS_IDLE
) {
110 * Create the special /proc agent LWP if it doesn't already exist.
111 * Give it the registers of the representative LWP.
115 if (!(P
->status
.pr_lwp
.pr_flags
& PR_AGENT
)) {
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
))
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
);
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)
144 (void) strcpy(fname
, "lwpctl");
145 if ((fd
= open(pathname
, O_WRONLY
)) < 0 ||
146 (fd
= dupfd(fd
, 0)) < 0)
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
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");
164 /* get the agent LWP status */
166 if (Pstopstatus(P
, PCNULL
, 0) != 0) {
174 if (P
->agentstatfd
>= 0)
175 (void) close(P
->agentstatfd
);
176 if (P
->agentctlfd
>= 0)
177 (void) close(P
->agentctlfd
);
180 /* refresh the process status */
181 (void) Pstopstatus(P
, PCNULL
, 0);
186 * Decrement the /proc agent agent reference count.
187 * On last reference, destroy the agent.
190 Pdestroy_agent(struct ps_prochandle
*P
)
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");
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
);
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.
235 execute(struct ps_prochandle
*P
, int sysindex
)
237 int ctlfd
= (P
->agentctlfd
>= 0)? P
->agentctlfd
: P
->ctlfd
;
239 sigset_t hold
; /* mask of held signals */
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
;
261 * If there is a current signal, remember it and cancel it.
263 if ((cursig
= P
->status
.pr_lwp
.pr_cursig
) != 0) {
265 ctl
.siginfo
= P
->status
.pr_lwp
.pr_info
;
268 if (Psetrun(P
, 0, PRCSIG
| PRCFAULT
) == -1)
271 while (P
->state
== PS_RUN
) {
274 if (P
->state
!= PS_STOP
)
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
;
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
)
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 */
316 (void) sigprocmask(SIG_BLOCK
, &blockable_sigs
, &unblock
);
318 rval
->sys_rval1
= 0; /* initialize return values */
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
;
329 /* We must be a 64-bit process to deal with a 64-bit process */
330 if (model
== PR_MODEL_LP64
)
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)
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
))
352 if (Pscantext(P
)) /* bad text ? */
356 * Validate arguments and compute the stack frame parameters.
357 * Begin with the current stack pointer.
360 if (model
== PR_MODEL_LP64
) {
361 sp
= P
->status
.pr_lwp
.pr_reg
[R_SP
] + STACK_BIAS
;
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
;
372 sp
= PSTACK_ALIGN64(sp
);
375 sp
= (uint32_t)P
->status
.pr_lwp
.pr_reg
[R_SP
];
376 sp
= PSTACK_ALIGN32(sp
);
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 */
390 case AT_BYVAL
: /* simple argument */
392 case AT_BYREF
: /* must allocate space */
393 switch (adp
->arg_inout
) {
397 if (adp
->arg_object
== NULL
)
398 goto bad5
; /* programming error */
400 default: /* programming error */
403 /* allocate stack space for BYREF argument */
404 if (adp
->arg_size
== 0 || adp
->arg_size
> MAXARGL
)
405 goto bad7
; /* programming error */
407 if (model
== PR_MODEL_LP64
)
408 sp
= PSTACK_ALIGN64(sp
- adp
->arg_size
);
411 sp
= PSTACK_ALIGN32(sp
- adp
->arg_size
);
412 adp
->arg_value
= sp
; /* stack address for object */
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
)))
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
)
451 rval
->sys_rval1
= 0; /* in case of error */
452 if (Psyscall_copyinargs(P
, nargs
, argp
, ap
) != 0)
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 */
463 if (Psetrun(P
, 0, 0) == -1)
465 while (P
->state
== PS_RUN
)
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;
480 if (P
->state
!= PS_STOP
|| P
->status
.pr_lwp
.pr_why
!= PR_SYSEXIT
)
483 if (P
->status
.pr_lwp
.pr_what
!= sysindex
)
486 if (!Pissyscall_prev(P
, P
->status
.pr_lwp
.pr_reg
[R_PC
], NULL
)) {
487 dprintf("Pissyscall_prev() failed\n");
491 dprintf("Psyscall(): caught at sysexit\n");
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
)
507 if (Psyscall_copyoutargs(P
, nargs
, argp
, ap
) != 0)
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",
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
);
555 dprintf("Psyscall(%d) fails with local error %d\n", sysindex
, Perr
);
559 * Destroy the /proc agent LWP now (or just bump down the ref count).
562 if (P
->state
!= PS_UNDEAD
) {
563 P
->status
= save_pstatus
;
570 (void) sigprocmask(SIG_SETMASK
, &unblock
, NULL
);