Module Name:    src
Committed By:   maxv
Date:           Sun Jun  7 09:45:20 UTC 2020

Modified Files:
        src/etc: MAKEDEV.tmpl
        src/sys/arch/amd64/conf: ALL GENERIC
        src/sys/conf: files majors
        src/sys/kern: files.kern subr_pool.c
Added Files:
        src/sys/kern: subr_fault.c
        src/sys/sys: fault.h

Log Message:
Add fault(4).


To generate a diff of this commit:
cvs rdiff -u -r1.219 -r1.220 src/etc/MAKEDEV.tmpl
cvs rdiff -u -r1.152 -r1.153 src/sys/arch/amd64/conf/ALL
cvs rdiff -u -r1.568 -r1.569 src/sys/arch/amd64/conf/GENERIC
cvs rdiff -u -r1.1267 -r1.1268 src/sys/conf/files
cvs rdiff -u -r1.93 -r1.94 src/sys/conf/majors
cvs rdiff -u -r1.48 -r1.49 src/sys/kern/files.kern
cvs rdiff -u -r0 -r1.1 src/sys/kern/subr_fault.c
cvs rdiff -u -r1.269 -r1.270 src/sys/kern/subr_pool.c
cvs rdiff -u -r0 -r1.1 src/sys/sys/fault.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/etc/MAKEDEV.tmpl
diff -u src/etc/MAKEDEV.tmpl:1.219 src/etc/MAKEDEV.tmpl:1.220
--- src/etc/MAKEDEV.tmpl:1.219	Fri Jun  5 17:20:56 2020
+++ src/etc/MAKEDEV.tmpl	Sun Jun  7 09:45:19 2020
@@ -1,5 +1,5 @@
 #!/bin/sh -
-#	$NetBSD: MAKEDEV.tmpl,v 1.219 2020/06/05 17:20:56 maxv Exp $
+#	$NetBSD: MAKEDEV.tmpl,v 1.220 2020/06/07 09:45:19 maxv Exp $
 #
 # Copyright (c) 2003,2007,2008 The NetBSD Foundation, Inc.
 # All rights reserved.
@@ -1761,6 +1761,10 @@ vio9p[0-9]*)
 	mkdev vio9p$unit c %vio9p_chr% $unit 660
 	;;
 
+fault)
+	mkdev fault c %fault_chr% 0
+	;;
+
 nvram)
 	mkdev nvram c %nvram_chr% 0 644
 	;;

Index: src/sys/arch/amd64/conf/ALL
diff -u src/sys/arch/amd64/conf/ALL:1.152 src/sys/arch/amd64/conf/ALL:1.153
--- src/sys/arch/amd64/conf/ALL:1.152	Sat May 30 13:35:31 2020
+++ src/sys/arch/amd64/conf/ALL	Sun Jun  7 09:45:19 2020
@@ -1,4 +1,4 @@
-# $NetBSD: ALL,v 1.152 2020/05/30 13:35:31 jdolecek Exp $
+# $NetBSD: ALL,v 1.153 2020/06/07 09:45:19 maxv Exp $
 # From NetBSD: GENERIC,v 1.787 2006/10/01 18:37:54 bouyer Exp
 #
 # ALL machine description file
@@ -17,7 +17,7 @@ include 	"arch/amd64/conf/std.amd64"
 
 options 	INCLUDE_CONFIG_FILE	# embed config file in kernel binary
 
-#ident		"ALL-$Revision: 1.152 $"
+#ident		"ALL-$Revision: 1.153 $"
 
 maxusers	64		# estimated number of users
 
@@ -137,6 +137,9 @@ options		KASAN
 makeoptions	KCOV=1
 options		KCOV
 
+# Fault Injection Driver.
+options 	FAULT
+
 # Compatibility options
 options 	EXEC_AOUT	# required by binaries from before 1.5
 options 	COMPAT_386BSD_MBRPART # recognize old partition ID

Index: src/sys/arch/amd64/conf/GENERIC
diff -u src/sys/arch/amd64/conf/GENERIC:1.568 src/sys/arch/amd64/conf/GENERIC:1.569
--- src/sys/arch/amd64/conf/GENERIC:1.568	Sat May 16 18:31:48 2020
+++ src/sys/arch/amd64/conf/GENERIC	Sun Jun  7 09:45:19 2020
@@ -1,4 +1,4 @@
-# $NetBSD: GENERIC,v 1.568 2020/05/16 18:31:48 christos Exp $
+# $NetBSD: GENERIC,v 1.569 2020/06/07 09:45:19 maxv Exp $
 #
 # GENERIC machine description file
 #
@@ -22,7 +22,7 @@ include 	"arch/amd64/conf/std.amd64"
 
 options 	INCLUDE_CONFIG_FILE	# embed config file in kernel binary
 
-#ident		"GENERIC-$Revision: 1.568 $"
+#ident		"GENERIC-$Revision: 1.569 $"
 
 maxusers	64		# estimated number of users
 
@@ -158,6 +158,9 @@ options 	KDTRACE_HOOKS	# kernel DTrace h
 #makeoptions	KCOV=1
 #options 	KCOV
 
+# Fault Injection Driver.
+#options 	FAULT
+
 # Compatibility options
 # x86_64 never shipped with a.out binaries; the two options below are
 # only relevant to 32-bit i386 binaries

Index: src/sys/conf/files
diff -u src/sys/conf/files:1.1267 src/sys/conf/files:1.1268
--- src/sys/conf/files:1.1267	Wed May 20 09:18:25 2020
+++ src/sys/conf/files	Sun Jun  7 09:45:19 2020
@@ -1,4 +1,4 @@
-#	$NetBSD: files,v 1.1267 2020/05/20 09:18:25 hkenken Exp $
+#	$NetBSD: files,v 1.1268 2020/06/07 09:45:19 maxv Exp $
 #	@(#)files.newconf	7.5 (Berkeley) 5/10/93
 
 version 	20171118
@@ -38,6 +38,7 @@ defflag opt_kmsan.h		KMSAN_PANIC
 defflag				KCOV
 defflag opt_pool.h		POOL_QUARANTINE
 defflag opt_pool.h		POOL_NOCACHE
+defflag				FAULT
 
 defparam opt_copy_symtab.h	makeoptions_COPY_SYMTAB
 

Index: src/sys/conf/majors
diff -u src/sys/conf/majors:1.93 src/sys/conf/majors:1.94
--- src/sys/conf/majors:1.93	Sun Jan 19 20:41:18 2020
+++ src/sys/conf/majors	Sun Jun  7 09:45:19 2020
@@ -1,4 +1,4 @@
-# $NetBSD: majors,v 1.93 2020/01/19 20:41:18 riastradh Exp $
+# $NetBSD: majors,v 1.94 2020/06/07 09:45:19 maxv Exp $
 #
 # Device majors for Machine-Independent drivers.
 #
@@ -88,3 +88,4 @@ device-major spi       char 347		   spi
 device-major ipmi      char 354		   ipmi
 device-major vhci      char 355            vhci
 device-major vio9p     char 356		   vio9p
+device-major fault     char 357		   fault

Index: src/sys/kern/files.kern
diff -u src/sys/kern/files.kern:1.48 src/sys/kern/files.kern:1.49
--- src/sys/kern/files.kern:1.48	Sat May 16 18:31:50 2020
+++ src/sys/kern/files.kern	Sun Jun  7 09:45:19 2020
@@ -1,4 +1,4 @@
-#	$NetBSD: files.kern,v 1.48 2020/05/16 18:31:50 christos Exp $
+#	$NetBSD: files.kern,v 1.49 2020/06/07 09:45:19 maxv Exp $
 
 #
 # kernel sources
@@ -118,6 +118,7 @@ file	kern/subr_emul.c		kern
 file	kern/subr_evcnt.c		kern
 file	kern/subr_exec_fd.c		kern
 file	kern/subr_extent.c		kern
+file	kern/subr_fault.c		fault
 file	kern/subr_hash.c		kern
 file	kern/subr_humanize.c		kern
 file	kern/subr_interrupt.c		kern

Index: src/sys/kern/subr_pool.c
diff -u src/sys/kern/subr_pool.c:1.269 src/sys/kern/subr_pool.c:1.270
--- src/sys/kern/subr_pool.c:1.269	Sat Jun  6 06:42:54 2020
+++ src/sys/kern/subr_pool.c	Sun Jun  7 09:45:19 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: subr_pool.c,v 1.269 2020/06/06 06:42:54 maxv Exp $	*/
+/*	$NetBSD: subr_pool.c,v 1.270 2020/06/07 09:45:19 maxv Exp $	*/
 
 /*
  * Copyright (c) 1997, 1999, 2000, 2002, 2007, 2008, 2010, 2014, 2015, 2018
@@ -33,7 +33,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: subr_pool.c,v 1.269 2020/06/06 06:42:54 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: subr_pool.c,v 1.270 2020/06/07 09:45:19 maxv Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_ddb.h"
@@ -58,6 +58,7 @@ __KERNEL_RCSID(0, "$NetBSD: subr_pool.c,
 #include <sys/atomic.h>
 #include <sys/asan.h>
 #include <sys/msan.h>
+#include <sys/fault.h>
 
 #include <uvm/uvm_extern.h>
 
@@ -1056,6 +1057,11 @@ pool_get(struct pool *pp, int flags)
 		ASSERT_SLEEPABLE();
 	}
 
+	if (flags & PR_NOWAIT) {
+		if (fault_inject())
+			return NULL;
+	}
+
 	mutex_enter(&pp->pr_lock);
  startover:
 	/*
@@ -2533,6 +2539,11 @@ pool_cache_get_paddr(pool_cache_t pc, in
 		ASSERT_SLEEPABLE();
 	}
 
+	if (flags & PR_NOWAIT) {
+		if (fault_inject())
+			return NULL;
+	}
+
 	/* Lock out interrupts and disable preemption. */
 	s = splvm();
 	while (/* CONSTCOND */ true) {

Added files:

Index: src/sys/kern/subr_fault.c
diff -u /dev/null src/sys/kern/subr_fault.c:1.1
--- /dev/null	Sun Jun  7 09:45:20 2020
+++ src/sys/kern/subr_fault.c	Sun Jun  7 09:45:19 2020
@@ -0,0 +1,271 @@
+/*	$NetBSD: subr_fault.c,v 1.1 2020/06/07 09:45:19 maxv Exp $	*/
+
+/*
+ * Copyright (c) 2020 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Maxime Villard.
+ *
+ * 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.
+ *
+ * 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: subr_fault.c,v 1.1 2020/06/07 09:45:19 maxv Exp $");
+
+#include <sys/module.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+
+#include <sys/conf.h>
+#include <sys/types.h>
+#include <sys/specificdata.h>
+#include <sys/kmem.h>
+#include <sys/atomic.h>
+#include <sys/ioccom.h>
+#include <sys/lwp.h>
+#include <sys/fault.h>
+
+typedef struct {
+	volatile bool enabled;
+	volatile unsigned long nth;
+	volatile unsigned long cnt;
+	volatile unsigned long nfaults;
+} fault_t;
+
+static fault_t fault_global __cacheline_aligned = {
+	.enabled = false,
+	.nth = 2,
+	.cnt = 0,
+	.nfaults = 0
+};
+
+static kmutex_t fault_global_lock __cacheline_aligned;
+static specificdata_key_t fault_lwp_key;
+
+/* -------------------------------------------------------------------------- */
+
+bool
+fault_inject(void)
+{
+	volatile unsigned long cnt;
+	fault_t *f;
+
+	if (__predict_false(cold))
+		return false;
+
+	if (__predict_false(atomic_load_acquire(&fault_global.enabled))) {
+		f = &fault_global;
+	} else {
+		f = lwp_getspecific(fault_lwp_key);
+		if (__predict_true(f == NULL))
+			return false;
+		if (__predict_false(!f->enabled))
+			return false;
+	}
+
+	cnt = atomic_inc_ulong_nv(&f->cnt);
+	if (__predict_false(cnt % atomic_load_relaxed(&f->nth) == 0)) {
+		atomic_inc_ulong(&f->nfaults);
+		return true;
+	}
+
+	return false;
+}
+
+/* -------------------------------------------------------------------------- */
+
+static int
+fault_open(dev_t dev, int flag, int mode, struct lwp *l)
+{
+	return 0;
+}
+
+static int
+fault_close(dev_t dev, int flag, int mode, struct lwp *l)
+{
+	return 0;
+}
+
+static int
+fault_ioc_enable(struct fault_ioc_enable *args)
+{
+	fault_t *f;
+
+	if (args->mode != FAULT_MODE_NTH)
+		return EINVAL;
+	if (args->nth < 2)
+		return EINVAL;
+
+	switch (args->scope) {
+	case FAULT_SCOPE_GLOBAL:
+		mutex_enter(&fault_global_lock);
+		if (fault_global.enabled) {
+			mutex_exit(&fault_global_lock);
+			return EEXIST;
+		}
+		atomic_store_relaxed(&fault_global.nth, args->nth);
+		fault_global.cnt = 0;
+		fault_global.nfaults = 0;
+		atomic_store_release(&fault_global.enabled, true);
+		mutex_exit(&fault_global_lock);
+		break;
+	case FAULT_SCOPE_LWP:
+		f = lwp_getspecific(fault_lwp_key);
+		if (f != NULL) {
+			if (f->enabled)
+				return EEXIST;
+		} else {
+			f = kmem_zalloc(sizeof(*f), KM_SLEEP);
+			lwp_setspecific(fault_lwp_key, f);
+		}
+		atomic_store_relaxed(&f->nth, args->nth);
+		f->cnt = 0;
+		f->nfaults = 0;
+		atomic_store_release(&f->enabled, true);
+		break;
+	default:
+		return EINVAL;
+	}
+
+	return 0;
+}
+
+static int
+fault_ioc_disable(struct fault_ioc_disable *args)
+{
+	fault_t *f;
+
+	switch (args->scope) {
+	case FAULT_SCOPE_GLOBAL:
+		mutex_enter(&fault_global_lock);
+		if (!fault_global.enabled) {
+			mutex_exit(&fault_global_lock);
+			return ENOENT;
+		}
+		atomic_store_release(&fault_global.enabled, false);
+		mutex_exit(&fault_global_lock);
+		break;
+	case FAULT_SCOPE_LWP:
+		f = lwp_getspecific(fault_lwp_key);
+		if (f == NULL)
+			return ENOENT;
+		if (!f->enabled)
+			return ENOENT;
+		atomic_store_release(&f->enabled, false);
+		break;
+	default:
+		return EINVAL;
+	}
+
+	return 0;
+}
+
+static int
+fault_ioc_getinfo(struct fault_ioc_getinfo *args)
+{
+	fault_t *f;
+
+	switch (args->scope) {
+	case FAULT_SCOPE_GLOBAL:
+		args->nfaults = atomic_load_relaxed(&fault_global.nfaults);
+		break;
+	case FAULT_SCOPE_LWP:
+		f = lwp_getspecific(fault_lwp_key);
+		if (f == NULL)
+			return ENOENT;
+		args->nfaults = atomic_load_relaxed(&f->nfaults);
+		break;
+	default:
+		return EINVAL;
+	}
+
+	return 0;
+}
+
+static int
+fault_ioctl(dev_t dev, u_long cmd, void *addr, int flag, struct lwp *l)
+{
+	switch (cmd) {
+	case FAULT_IOC_ENABLE:
+		return fault_ioc_enable(addr);
+	case FAULT_IOC_DISABLE:
+		return fault_ioc_disable(addr);
+	case FAULT_IOC_GETINFO:
+		return fault_ioc_getinfo(addr);
+	default:
+		return EINVAL;
+	}
+}
+
+const struct cdevsw fault_cdevsw = {
+	.d_open = fault_open,
+	.d_close = fault_close,
+	.d_read = noread,
+	.d_write = nowrite,
+	.d_ioctl = fault_ioctl,
+	.d_stop = nostop,
+	.d_tty = notty,
+	.d_poll = nopoll,
+	.d_mmap = nommap,
+	.d_kqfilter = nokqfilter,
+	.d_discard = nodiscard,
+	.d_flag = D_OTHER | D_MPSAFE
+};
+
+/* -------------------------------------------------------------------------- */
+
+MODULE(MODULE_CLASS_MISC, fault, NULL);
+
+static void
+fault_lwp_free(void *arg)
+{
+	fault_t *f = (fault_t *)arg;
+
+	if (f == NULL) {
+		return;
+	}
+
+	kmem_free(f, sizeof(*f));
+}
+
+static void
+fault_init(void)
+{
+	mutex_init(&fault_global_lock, MUTEX_DEFAULT, IPL_NONE);
+	lwp_specific_key_create(&fault_lwp_key, fault_lwp_free);
+}
+
+static int
+fault_modcmd(modcmd_t cmd, void *arg)
+{
+   	switch (cmd) {
+	case MODULE_CMD_INIT:
+		fault_init();
+		return 0;
+	case MODULE_CMD_FINI:
+		return EINVAL;
+	default:
+		return ENOTTY;
+	}
+}

Index: src/sys/sys/fault.h
diff -u /dev/null src/sys/sys/fault.h:1.1
--- /dev/null	Sun Jun  7 09:45:20 2020
+++ src/sys/sys/fault.h	Sun Jun  7 09:45:19 2020
@@ -0,0 +1,77 @@
+/*	$NetBSD: fault.h,v 1.1 2020/06/07 09:45:19 maxv Exp $	*/
+
+/*
+ * Copyright (c) 2020 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Maxime Villard.
+ *
+ * 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.
+ *
+ * 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_FAULT_H_
+#define _SYS_FAULT_H_
+
+#ifdef _KERNEL_OPT
+#include "opt_fault.h"
+#endif
+
+#if !defined(_KERNEL) || defined(FAULT)
+
+#define FAULT_SCOPE_GLOBAL	0
+#define FAULT_SCOPE_LWP		1
+
+#define FAULT_MODE_NTH		0
+
+struct fault_ioc_enable {
+	int scope;
+	int mode;
+	union {
+		unsigned long nth;
+	};
+};
+
+struct fault_ioc_disable {
+	int scope;
+};
+
+struct fault_ioc_getinfo {
+	int scope;
+	unsigned long nfaults;
+};
+
+#define FAULT_IOC_ENABLE	_IOW ('F', 1, struct fault_ioc_enable)
+#define FAULT_IOC_DISABLE	_IOW ('F', 2, struct fault_ioc_disable)
+#define FAULT_IOC_GETINFO	_IOWR('F', 3, struct fault_ioc_getinfo)
+
+#endif /* !_KERNEL || FAULT */
+
+#ifdef _KERNEL
+#ifdef FAULT
+bool fault_inject(void);
+#else
+#define fault_inject() false
+#endif
+#endif /* _KERNEL */
+
+#endif /* !_SYS_FAULT_H_ */

Reply via email to