MI kernel support for user-level Restartable Atomic Sequences (RAS).

This commit is contained in:
gmcgarry 2002-08-28 07:16:33 +00:00
parent 05980fc1da
commit 5bcbbd40bf
9 changed files with 385 additions and 12 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: kern_exec.c,v 1.154 2002/08/26 21:07:39 christos Exp $ */
/* $NetBSD: kern_exec.c,v 1.155 2002/08/28 07:16:35 gmcgarry Exp $ */
/*-
* Copyright (C) 1993, 1994, 1996 Christopher G. Demetriou
@ -33,7 +33,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: kern_exec.c,v 1.154 2002/08/26 21:07:39 christos Exp $");
__KERNEL_RCSID(0, "$NetBSD: kern_exec.c,v 1.155 2002/08/28 07:16:35 gmcgarry Exp $");
#include "opt_ktrace.h"
#include "opt_syscall_debug.h"
@ -54,6 +54,7 @@ __KERNEL_RCSID(0, "$NetBSD: kern_exec.c,v 1.154 2002/08/26 21:07:39 christos Exp
#include <sys/resourcevar.h>
#include <sys/wait.h>
#include <sys/mman.h>
#include <sys/ras.h>
#include <sys/signalvar.h>
#include <sys/stat.h>
#include <sys/syscall.h>
@ -649,6 +650,13 @@ sys_execve(struct proc *p, void *v, register_t *retval)
p->p_cred->p_svuid = p->p_ucred->cr_uid;
p->p_cred->p_svgid = p->p_ucred->cr_gid;
#if defined(__HAVE_RAS)
/*
* Remove all RASs from the address space.
*/
ras_purgeall(p);
#endif
doexechooks(p);
uvm_km_free_wakeup(exec_map, (vaddr_t) argp, NCARGS);

View File

@ -1,4 +1,4 @@
/* $NetBSD: kern_exit.c,v 1.99 2002/08/13 05:42:27 manu Exp $ */
/* $NetBSD: kern_exit.c,v 1.100 2002/08/28 07:16:36 gmcgarry Exp $ */
/*-
* Copyright (c) 1998, 1999 The NetBSD Foundation, Inc.
@ -78,7 +78,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: kern_exit.c,v 1.99 2002/08/13 05:42:27 manu Exp $");
__KERNEL_RCSID(0, "$NetBSD: kern_exit.c,v 1.100 2002/08/28 07:16:36 gmcgarry Exp $");
#include "opt_ktrace.h"
#include "opt_perfctrs.h"
@ -110,6 +110,7 @@ __KERNEL_RCSID(0, "$NetBSD: kern_exit.c,v 1.99 2002/08/13 05:42:27 manu Exp $");
#include <sys/ptrace.h>
#include <sys/acct.h>
#include <sys/filedesc.h>
#include <sys/ras.h>
#include <sys/signalvar.h>
#include <sys/sched.h>
#include <sys/mount.h>
@ -172,6 +173,10 @@ exit1(struct proc *p, int rv)
p->p_sigctx.ps_sigcheck = 0;
callout_stop(&p->p_realit_ch);
#if defined(__HAVE_RAS)
ras_purgeall(p);
#endif
/*
* Close open files and release open-file table.
* This may block!

View File

@ -1,4 +1,4 @@
/* $NetBSD: kern_fork.c,v 1.91 2002/08/06 13:58:08 pooka Exp $ */
/* $NetBSD: kern_fork.c,v 1.92 2002/08/28 07:16:37 gmcgarry Exp $ */
/*-
* Copyright (c) 1999, 2001 The NetBSD Foundation, Inc.
@ -78,7 +78,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: kern_fork.c,v 1.91 2002/08/06 13:58:08 pooka Exp $");
__KERNEL_RCSID(0, "$NetBSD: kern_fork.c,v 1.92 2002/08/28 07:16:37 gmcgarry Exp $");
#include "opt_ktrace.h"
#include "opt_systrace.h"
@ -93,6 +93,7 @@ __KERNEL_RCSID(0, "$NetBSD: kern_fork.c,v 1.91 2002/08/06 13:58:08 pooka Exp $")
#include <sys/pool.h>
#include <sys/mount.h>
#include <sys/proc.h>
#include <sys/ras.h>
#include <sys/resourcevar.h>
#include <sys/vnode.h>
#include <sys/file.h>
@ -374,6 +375,13 @@ fork1(struct proc *p1, int flags, int exitsig, void *stack, size_t stacksize,
p2->p_cred->p_refcnt = 1;
crhold(p1->p_ucred);
LIST_INIT(&p2->p_raslist);
p2->p_nras = 0;
simple_lock_init(&p2->p_raslock);
#if defined(__HAVE_RAS)
ras_fork(p1, p2);
#endif
/* bump references to the text vnode (for procfs) */
p2->p_textvp = p1->p_textvp;
if (p2->p_textvp)

View File

@ -1,4 +1,4 @@
/* $NetBSD: kern_proc.c,v 1.50 2002/07/26 06:04:57 enami Exp $ */
/* $NetBSD: kern_proc.c,v 1.51 2002/08/28 07:16:38 gmcgarry Exp $ */
/*-
* Copyright (c) 1999 The NetBSD Foundation, Inc.
@ -73,7 +73,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: kern_proc.c,v 1.50 2002/07/26 06:04:57 enami Exp $");
__KERNEL_RCSID(0, "$NetBSD: kern_proc.c,v 1.51 2002/08/28 07:16:38 gmcgarry Exp $");
#include "opt_kstack.h"
@ -95,6 +95,7 @@ __KERNEL_RCSID(0, "$NetBSD: kern_proc.c,v 1.50 2002/07/26 06:04:57 enami Exp $")
#include <sys/ioctl.h>
#include <sys/tty.h>
#include <sys/signalvar.h>
#include <sys/ras.h>
/*
* Structure associated with user cacheing.
@ -151,6 +152,7 @@ struct pool pcred_pool;
struct pool plimit_pool;
struct pool pgrp_pool;
struct pool rusage_pool;
struct pool ras_pool;
/*
* The process list descriptors, used during pid allocation and
@ -201,6 +203,8 @@ procinit()
&pool_allocator_nointr);
pool_init(&rusage_pool, sizeof(struct rusage), 0, 0, 0, "rusgepl",
&pool_allocator_nointr);
pool_init(&ras_pool, sizeof(struct ras), 0, 0, 0, "raspl",
&pool_allocator_nointr);
}
/*

269
sys/kern/kern_ras.c Normal file
View File

@ -0,0 +1,269 @@
/* $NetBSD: kern_ras.c,v 1.1 2002/08/28 07:16:39 gmcgarry Exp $ */
/*-
* Copyright (c) 2002 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Gregory McGarry.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: kern_ras.c,v 1.1 2002/08/28 07:16:39 gmcgarry Exp $");
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/systm.h>
#include <sys/pool.h>
#include <sys/proc.h>
#include <sys/ras.h>
#include <sys/mount.h>
#include <sys/syscallargs.h>
#include <uvm/uvm_extern.h>
#define MAX_RAS_PER_PROC 16
int ras_per_proc = MAX_RAS_PER_PROC;
#ifdef DEBUG
int ras_debug = 0;
#define DPRINTF(x) if (ras_debug) printf x
#else
#define DPRINTF(x) /* nothing */
#endif
int ras_install(struct proc *, caddr_t, size_t);
int ras_purge(struct proc *, caddr_t, size_t);
extern struct pool ras_pool;
/*
* Check the specified address to see if it is within the
* sequence. If it is found, we return the restart address,
* otherwise we return -1. If we do perform a restart, we
* mark the sequence as hit.
*/
caddr_t
ras_lookup(struct proc *p, caddr_t addr)
{
struct ras *rp;
#ifdef DIAGNOSTIC
if (addr < (caddr_t)VM_MIN_ADDRESS ||
addr > (caddr_t)VM_MAXUSER_ADDRESS)
return ((caddr_t)-1);
#endif
simple_lock(&p->p_raslock);
LIST_FOREACH(rp, &p->p_raslist, ras_list) {
if (addr > rp->ras_startaddr && addr < rp->ras_endaddr) {
rp->ras_hits++;
simple_unlock(&p->p_raslock);
#ifdef DIAGNOSTIC
DPRINTF(("RAS hit: p=%p %p\n", p, addr));
#endif
return (rp->ras_startaddr);
}
}
simple_unlock(&p->p_raslock);
return ((caddr_t)-1);
}
/*
* During a fork, we copy all of the sequences from parent p1 to
* the child p2.
*/
int
ras_fork(struct proc *p1, struct proc *p2)
{
struct ras *rp, *nrp;
DPRINTF(("ras_fork: p1=%p, p2=%p, p1->p_nras=%d\n",
p1, p2, p1->p_nras));
simple_lock(&p1->p_raslock);
LIST_FOREACH(rp, &p1->p_raslist, ras_list) {
nrp = pool_get(&ras_pool, PR_NOWAIT);
nrp->ras_startaddr = rp->ras_startaddr;
nrp->ras_endaddr = rp->ras_endaddr;
nrp->ras_hits = 0;
LIST_INSERT_HEAD(&p2->p_raslist, nrp, ras_list);
}
p2->p_nras = p1->p_nras;
simple_unlock(&p1->p_raslock);
return (0);
}
/*
* Nuke all sequences for this process.
*/
int
ras_purgeall(struct proc *p)
{
struct ras *rp;
simple_lock(&p->p_raslock);
while (!LIST_EMPTY(&p->p_raslist)) {
rp = LIST_FIRST(&p->p_raslist);
DPRINTF(("RAS %p-%p, hits %d\n", rp->ras_startaddr,
rp->ras_endaddr, rp->ras_hits));
LIST_REMOVE(rp, ras_list);
pool_put(&ras_pool, rp);
}
p->p_nras = 0;
simple_unlock(&p->p_raslock);
return (0);
}
/*
* Install the new sequence. If it already exists, return
* an error.
*/
int
ras_install(struct proc *p, caddr_t addr, size_t len)
{
struct ras *rp;
caddr_t endaddr = addr + len;
if (addr < (caddr_t)VM_MIN_ADDRESS ||
addr > (caddr_t)VM_MAXUSER_ADDRESS)
return (EINVAL);
if (len <= 0)
return (EINVAL);
if (p->p_nras >= ras_per_proc)
return (EINVAL);
simple_lock(&p->p_raslock);
LIST_FOREACH(rp, &p->p_raslist, ras_list) {
if ((addr > rp->ras_startaddr && addr < rp->ras_endaddr) ||
(endaddr > rp->ras_startaddr &&
endaddr < rp->ras_endaddr) ||
(addr < rp->ras_startaddr && endaddr > rp->ras_endaddr)) {
simple_unlock(&p->p_raslock);
return (EINVAL);
}
}
rp = pool_get(&ras_pool, PR_NOWAIT);
rp->ras_startaddr = addr;
rp->ras_endaddr = endaddr;
rp->ras_hits = 0;
LIST_INSERT_HEAD(&p->p_raslist, rp, ras_list);
p->p_nras++;
simple_unlock(&p->p_raslock);
return (0);
}
/*
* Nuke the specified sequence. Both address and len must
* match, otherwise we return an error.
*/
int
ras_purge(struct proc *p, caddr_t addr, size_t len)
{
struct ras *rp;
caddr_t endaddr = addr + len;
int error = ESRCH;
simple_lock(&p->p_raslock);
LIST_FOREACH(rp, &p->p_raslist, ras_list) {
if (addr == rp->ras_startaddr && endaddr == rp->ras_endaddr) {
LIST_REMOVE(rp, ras_list);
pool_put(&ras_pool, rp);
p->p_nras--;
error = 0;
break;
}
}
simple_unlock(&p->p_raslock);
return (error);
}
/*ARGSUSED*/
int
sys_rasctl(struct proc *p, void *v, register_t *retval)
{
#if defined(__HAVE_RAS)
struct sys_rasctl_args /* {
syscallarg(caddr_t) addr;
syscallarg(size_t) len;
syscallarg(int) op;
} */ *uap = v;
caddr_t addr;
size_t len;
int op;
int error;
/*
* first, extract syscall args from the uap.
*/
addr = (caddr_t)SCARG(uap, addr);
len = (size_t)SCARG(uap, len);
op = SCARG(uap, op);
DPRINTF(("sys_rasctl: p=%p addr=%p, len=%d, op=0x%x\n",
p, addr, len, op));
switch (op) {
case RAS_INSTALL:
error = ras_install(p, addr, len);
break;
case RAS_PURGE:
error = ras_purge(p, addr, len);
break;
case RAS_PURGE_ALL:
error = ras_purgeall(p);
break;
default:
error = EINVAL;
break;
}
return (error);
#else
return (EOPNOTSUPP);
#endif
}

View File

@ -1,4 +1,4 @@
$NetBSD: syscalls.master,v 1.113 2002/08/07 04:52:53 briggs Exp $
$NetBSD: syscalls.master,v 1.114 2002/08/28 07:16:39 gmcgarry Exp $
; @(#)syscalls.master 8.2 (Berkeley) 1/13/94
@ -655,3 +655,4 @@
void *tramp, int vers); }
341 STD { int sys_pmc_get_info(int ctr, int op, void *args); }
342 STD { int sys_pmc_control(int ctr, int op, void *args); }
343 STD { int sys_rasctl(caddr_t addr, size_t len, int op); }

View File

@ -1,4 +1,4 @@
# $NetBSD: Makefile,v 1.42 2002/08/07 05:16:27 briggs Exp $
# $NetBSD: Makefile,v 1.43 2002/08/28 07:16:34 gmcgarry Exp $
KDIR= /sys/sys
INCSDIR= /usr/include/sys
@ -16,7 +16,7 @@ INCS= acct.h agpio.h ansi.h ataio.h audioio.h \
localedef.h lock.h lockf.h malloc.h map.h mbuf.h md4.h md5.h midiio.h \
mman.h mount.h msg.h msgbuf.h mtio.h namei.h null.h param.h pipe.h \
pmc.h poll.h pool.h proc.h properties.h \
protosw.h ptrace.h queue.h reboot.h radioio.h resource.h \
protosw.h ptrace.h queue.h ras.h reboot.h radioio.h resource.h \
resourcevar.h rnd.h scanio.h sched.h scsiio.h select.h sem.h sha1.h \
shm.h signal.h signalvar.h socket.h socketvar.h sockio.h stat.h \
syscall.h syscallargs.h sysctl.h stdint.h swap.h syslimits.h syslog.h \

View File

@ -1,4 +1,4 @@
/* $NetBSD: proc.h,v 1.143 2002/08/06 13:58:09 pooka Exp $ */
/* $NetBSD: proc.h,v 1.144 2002/08/28 07:16:33 gmcgarry Exp $ */
/*-
* Copyright (c) 1986, 1989, 1991, 1993
@ -88,6 +88,7 @@ struct pgrp {
*/
struct exec_package;
struct ps_strings;
struct ras;
struct emul {
const char *e_name; /* Symbolic name */
@ -174,6 +175,10 @@ struct proc {
LIST_ENTRY(proc) p_sibling; /* List of sibling processes */
LIST_HEAD(, proc) p_children; /* Pointer to list of children */
LIST_HEAD(, ras) p_raslist; /* Pointer to RAS queue */
u_int p_nras; /* number of RASs */
struct simplelock p_raslock; /* Lock for RAS queue */
/*
* The following fields are all zeroed upon creation in fork.
*/

73
sys/sys/ras.h Normal file
View File

@ -0,0 +1,73 @@
/* $NetBSD: ras.h,v 1.1 2002/08/28 07:16:33 gmcgarry Exp $ */
/*-
* Copyright (c) 2002 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Gregory McGarry.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _SYS_RAS_H_
#define _SYS_RAS_H_
#include <sys/types.h>
#include <sys/queue.h>
struct ras {
LIST_ENTRY(ras) ras_list;
caddr_t ras_startaddr;
caddr_t ras_endaddr;
int ras_hits;
};
#define RAS_INSTALL 0
#define RAS_PURGE 1
#define RAS_PURGE_ALL 2
#ifdef _KERNEL
struct proc;
caddr_t ras_lookup(struct proc *, caddr_t);
int ras_fork(struct proc *, struct proc *);
int ras_purgeall(struct proc *);
#else
__BEGIN_DECLS
int rasctl(caddr_t, size_t, int);
__END_DECLS
#endif /* _KERNEL */
#endif /* !_SYS_RAS_H_ */