diff options
Diffstat (limited to 'sys/cddl')
-rw-r--r-- | sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c | 161 | ||||
-rw-r--r-- | sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c | 9 | ||||
-rw-r--r-- | sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu.c | 20 | ||||
-rw-r--r-- | sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_pool.c | 4 | ||||
-rw-r--r-- | sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c | 2 | ||||
-rw-r--r-- | sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_misc.c | 84 | ||||
-rw-r--r-- | sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c | 10 | ||||
-rw-r--r-- | sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio.c | 4 | ||||
-rw-r--r-- | sys/cddl/contrib/opensolaris/uts/common/sys/fs/zfs.h | 4 | ||||
-rw-r--r-- | sys/cddl/dev/dtrace/aarch64/dtrace_isa.c | 119 | ||||
-rw-r--r-- | sys/cddl/dev/dtrace/amd64/dtrace_subr.c | 48 | ||||
-rw-r--r-- | sys/cddl/dev/dtrace/i386/dtrace_subr.c | 48 | ||||
-rw-r--r-- | sys/cddl/dev/sdt/sdt.c | 18 |
13 files changed, 389 insertions, 142 deletions
diff --git a/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c b/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c index 7ec7dfd..0012975 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c +++ b/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c @@ -117,6 +117,7 @@ #include <sys/ctype.h> #include <sys/eventhandler.h> #include <sys/limits.h> +#include <sys/linker.h> #include <sys/kdb.h> #include <sys/kernel.h> #include <sys/malloc.h> @@ -11916,6 +11917,21 @@ dtrace_buffer_activate(dtrace_state_t *state) dtrace_interrupt_enable(cookie); } +#ifdef __FreeBSD__ +/* + * Activate the specified per-CPU buffer. This is used instead of + * dtrace_buffer_activate() when APs have not yet started, i.e. when + * activating anonymous state. + */ +static void +dtrace_buffer_activate_cpu(dtrace_state_t *state, int cpu) +{ + + if (state->dts_buffer[cpu].dtb_tomax != NULL) + state->dts_buffer[cpu].dtb_flags &= ~DTRACEBUF_INACTIVE; +} +#endif + static int dtrace_buffer_alloc(dtrace_buffer_t *bufs, size_t size, int flags, processorid_t cpu, int *factor) @@ -12532,9 +12548,15 @@ dtrace_enabling_dump(dtrace_enabling_t *enab) for (i = 0; i < enab->dten_ndesc; i++) { dtrace_probedesc_t *desc = &enab->dten_desc[i]->dted_probe; +#ifdef __FreeBSD__ + printf("dtrace: enabling probe %d (%s:%s:%s:%s)\n", i, + desc->dtpd_provider, desc->dtpd_mod, + desc->dtpd_func, desc->dtpd_name); +#else cmn_err(CE_NOTE, "enabling probe %d (%s:%s:%s:%s)", i, desc->dtpd_provider, desc->dtpd_mod, desc->dtpd_func, desc->dtpd_name); +#endif } } @@ -13185,19 +13207,91 @@ dtrace_dof_char(char c) return (c - 'a' + 10); } /* Should not reach here. */ - return (0); + return (UCHAR_MAX); } #endif /* __FreeBSD__ */ static dof_hdr_t * dtrace_dof_property(const char *name) { +#ifdef __FreeBSD__ + uint8_t *dofbuf; + u_char *data, *eol; + caddr_t doffile; + size_t bytes, len, i; + dof_hdr_t *dof; + u_char c1, c2; + + dof = NULL; + + doffile = preload_search_by_type("dtrace_dof"); + if (doffile == NULL) + return (NULL); + + data = preload_fetch_addr(doffile); + len = preload_fetch_size(doffile); + for (;;) { + /* Look for the end of the line. All lines end in a newline. */ + eol = memchr(data, '\n', len); + if (eol == NULL) + return (NULL); + + if (strncmp(name, data, strlen(name)) == 0) + break; + + eol++; /* skip past the newline */ + len -= eol - data; + data = eol; + } + + /* We've found the data corresponding to the specified key. */ + + data += strlen(name) + 1; /* skip past the '=' */ + len = eol - data; + bytes = len / 2; + + if (bytes < sizeof(dof_hdr_t)) { + dtrace_dof_error(NULL, "truncated header"); + goto doferr; + } + + /* + * Each byte is represented by the two ASCII characters in its hex + * representation. + */ + dofbuf = malloc(bytes, M_SOLARIS, M_WAITOK); + for (i = 0; i < bytes; i++) { + c1 = dtrace_dof_char(data[i * 2]); + c2 = dtrace_dof_char(data[i * 2 + 1]); + if (c1 == UCHAR_MAX || c2 == UCHAR_MAX) { + dtrace_dof_error(NULL, "invalid hex char in DOF"); + goto doferr; + } + dofbuf[i] = c1 * 16 + c2; + } + + dof = (dof_hdr_t *)dofbuf; + if (bytes < dof->dofh_loadsz) { + dtrace_dof_error(NULL, "truncated DOF"); + goto doferr; + } + + if (dof->dofh_loadsz >= dtrace_dof_maxsize) { + dtrace_dof_error(NULL, "oversized DOF"); + goto doferr; + } + + return (dof); + +doferr: + free(dof, M_SOLARIS); + return (NULL); +#else /* __FreeBSD__ */ uchar_t *buf; uint64_t loadsz; unsigned int len, i; dof_hdr_t *dof; -#ifdef illumos /* * Unfortunately, array of values in .conf files are always (and * only) interpreted to be integer arrays. We must read our DOF @@ -13231,49 +13325,9 @@ dtrace_dof_property(const char *name) dof = kmem_alloc(loadsz, KM_SLEEP); bcopy(buf, dof, loadsz); ddi_prop_free(buf); -#else - char *p; - char *p_env; - - if ((p_env = kern_getenv(name)) == NULL) - return (NULL); - - len = strlen(p_env) / 2; - - buf = kmem_alloc(len, KM_SLEEP); - - dof = (dof_hdr_t *) buf; - - p = p_env; - - for (i = 0; i < len; i++) { - buf[i] = (dtrace_dof_char(p[0]) << 4) | - dtrace_dof_char(p[1]); - p += 2; - } - - freeenv(p_env); - - if (len < sizeof (dof_hdr_t)) { - kmem_free(buf, 0); - dtrace_dof_error(NULL, "truncated header"); - return (NULL); - } - - if (len < (loadsz = dof->dofh_loadsz)) { - kmem_free(buf, 0); - dtrace_dof_error(NULL, "truncated DOF"); - return (NULL); - } - - if (loadsz >= dtrace_dof_maxsize) { - kmem_free(buf, 0); - dtrace_dof_error(NULL, "oversized DOF"); - return (NULL); - } -#endif return (dof); +#endif /* !__FreeBSD__ */ } static void @@ -14332,7 +14386,7 @@ static dtrace_state_t * #ifdef illumos dtrace_state_create(dev_t *devp, cred_t *cr) #else -dtrace_state_create(struct cdev *dev) +dtrace_state_create(struct cdev *dev, struct ucred *cred __unused) #endif { #ifdef illumos @@ -14945,6 +14999,18 @@ dtrace_state_go(dtrace_state_t *state, processorid_t *cpu) if (state->dts_activity == DTRACE_ACTIVITY_WARMUP) state->dts_activity = DTRACE_ACTIVITY_ACTIVE; +#ifdef __FreeBSD__ + /* + * We enable anonymous tracing before APs are started, so we must + * activate buffers using the current CPU. + */ + if (state == dtrace_anon.dta_state) + for (int i = 0; i < NCPU; i++) + dtrace_buffer_activate_cpu(state, i); + else + dtrace_xcall(DTRACE_CPUALL, + (dtrace_xcall_t)dtrace_buffer_activate, state); +#else /* * Regardless of whether or not now we're in ACTIVE or DRAINING, we * want each CPU to transition its principal buffer out of the @@ -14955,6 +15021,7 @@ dtrace_state_go(dtrace_state_t *state, processorid_t *cpu) */ dtrace_xcall(DTRACE_CPUALL, (dtrace_xcall_t)dtrace_buffer_activate, state); +#endif goto out; err: @@ -15316,11 +15383,7 @@ dtrace_anon_property(void) * If we haven't allocated an anonymous state, we'll do so now. */ if ((state = dtrace_anon.dta_state) == NULL) { -#ifdef illumos state = dtrace_state_create(NULL, NULL); -#else - state = dtrace_state_create(NULL); -#endif dtrace_anon.dta_state = state; if (state == NULL) { @@ -17001,7 +17064,7 @@ dtrace_open(struct cdev *dev, int oflags, int devtype, struct thread *td) state = dtrace_state_create(devp, cred_p); #else - state = dtrace_state_create(dev); + state = dtrace_state_create(dev, NULL); devfs_set_cdevpriv(state, dtrace_dtr); #endif diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c index f944903..534dfb2 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c @@ -132,6 +132,7 @@ #include <sys/multilist.h> #ifdef _KERNEL #include <sys/dnlc.h> +#include <sys/racct.h> #endif #include <sys/callb.h> #include <sys/kstat.h> @@ -4503,6 +4504,14 @@ top: demand, prefetch, !HDR_ISTYPE_METADATA(hdr), data, metadata, misses); #ifdef _KERNEL +#ifdef RACCT + if (racct_enable) { + PROC_LOCK(curproc); + racct_add_force(curproc, RACCT_READBPS, size); + racct_add_force(curproc, RACCT_READIOPS, 1); + PROC_UNLOCK(curproc); + } +#endif /* RACCT */ curthread->td_ru.ru_inblock++; #endif diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu.c index b60236f..af8d366 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu.c @@ -47,6 +47,7 @@ #include <sys/sa.h> #include <sys/zfeature.h> #ifdef _KERNEL +#include <sys/racct.h> #include <sys/vm.h> #include <sys/zfs_znode.h> #endif @@ -427,6 +428,15 @@ dmu_buf_hold_array_by_dnode(dnode_t *dn, uint64_t offset, uint64_t length, } dbp = kmem_zalloc(sizeof (dmu_buf_t *) * nblks, KM_SLEEP); +#if defined(_KERNEL) && defined(RACCT) + if (racct_enable && !read) { + PROC_LOCK(curproc); + racct_add_force(curproc, RACCT_WRITEBPS, length); + racct_add_force(curproc, RACCT_WRITEIOPS, nblks); + PROC_UNLOCK(curproc); + } +#endif + zio = zio_root(dn->dn_objset->os_spa, NULL, NULL, ZIO_FLAG_CANFAIL); blkid = dbuf_whichblock(dn, 0, offset); for (i = 0; i < nblks; i++) { @@ -1422,7 +1432,15 @@ dmu_assign_arcbuf(dmu_buf_t *handle, uint64_t offset, arc_buf_t *buf, DBUF_GET_BUFC_TYPE(db) == ARC_BUFC_DATA) { #ifdef _KERNEL curthread->td_ru.ru_oublock++; -#endif +#ifdef RACCT + if (racct_enable) { + PROC_LOCK(curproc); + racct_add_force(curproc, RACCT_WRITEBPS, blksz); + racct_add_force(curproc, RACCT_WRITEIOPS, 1); + PROC_UNLOCK(curproc); + } +#endif /* RACCT */ +#endif /* _KERNEL */ dbuf_assign_arcbuf(db, buf, tx); dbuf_rele(db, FTAG); } else { diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_pool.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_pool.c index 30a0710..95e741f 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_pool.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_pool.c @@ -48,7 +48,7 @@ #include <sys/zil_impl.h> #include <sys/dsl_userhold.h> -#ifdef __FreeBSD__ +#if defined(__FreeBSD__) && defined(_KERNEL) #include <sys/sysctl.h> #include <sys/types.h> #endif @@ -132,7 +132,7 @@ int zfs_delay_min_dirty_percent = 60; uint64_t zfs_delay_scale = 1000 * 1000 * 1000 / 2000; -#ifdef __FreeBSD__ +#if defined(__FreeBSD__) && defined(_KERNEL) extern int zfs_vdev_async_write_active_max_dirty_percent; diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c index f69a5e7..2e039ed 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c @@ -929,7 +929,7 @@ spa_taskqs_init(spa_t *spa, zio_type_t t, zio_taskq_type_t q) * than the other taskqs. */ if (t == ZIO_TYPE_WRITE && q == ZIO_TASKQ_ISSUE) - pri--; + pri++; tq = taskq_create_proc(name, value, pri, 50, INT_MAX, spa->spa_proc, flags); diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_misc.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_misc.c index 6080594..63350b3 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_misc.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_misc.c @@ -55,6 +55,11 @@ #include "zfs_prop.h" #include <sys/zfeature.h> +#if defined(__FreeBSD__) && defined(_KERNEL) +#include <sys/types.h> +#include <sys/sysctl.h> +#endif + /* * SPA locking * @@ -255,35 +260,6 @@ int zfs_flags = 0; * in leaked space, or worse. */ boolean_t zfs_recover = B_FALSE; -SYSCTL_DECL(_vfs_zfs); -SYSCTL_INT(_vfs_zfs, OID_AUTO, recover, CTLFLAG_RWTUN, &zfs_recover, 0, - "Try to recover from otherwise-fatal errors."); - -static int -sysctl_vfs_zfs_debug_flags(SYSCTL_HANDLER_ARGS) -{ - int err, val; - - val = zfs_flags; - err = sysctl_handle_int(oidp, &val, 0, req); - if (err != 0 || req->newptr == NULL) - return (err); - - /* - * ZFS_DEBUG_MODIFY must be enabled prior to boot so all - * arc buffers in the system have the necessary additional - * checksum data. However, it is safe to disable at any - * time. - */ - if (!(zfs_flags & ZFS_DEBUG_MODIFY)) - val &= ~ZFS_DEBUG_MODIFY; - zfs_flags = val; - - return (0); -} -SYSCTL_PROC(_vfs_zfs, OID_AUTO, debug_flags, - CTLTYPE_UINT | CTLFLAG_MPSAFE | CTLFLAG_RWTUN, 0, sizeof(int), - sysctl_vfs_zfs_debug_flags, "IU", "Debug flags for ZFS testing."); /* * If destroy encounters an EIO while reading metadata (e.g. indirect @@ -325,26 +301,18 @@ boolean_t zfs_free_leak_on_eio = B_FALSE; * in a system panic. */ uint64_t zfs_deadman_synctime_ms = 1000000ULL; -SYSCTL_UQUAD(_vfs_zfs, OID_AUTO, deadman_synctime_ms, CTLFLAG_RDTUN, - &zfs_deadman_synctime_ms, 0, - "Stalled ZFS I/O expiration time in milliseconds"); /* * Check time in milliseconds. This defines the frequency at which we check * for hung I/O. */ uint64_t zfs_deadman_checktime_ms = 5000ULL; -SYSCTL_UQUAD(_vfs_zfs, OID_AUTO, deadman_checktime_ms, CTLFLAG_RDTUN, - &zfs_deadman_checktime_ms, 0, - "Period of checks for stalled ZFS I/O in milliseconds"); /* * Default value of -1 for zfs_deadman_enabled is resolved in * zfs_deadman_init() */ int zfs_deadman_enabled = -1; -SYSCTL_INT(_vfs_zfs, OID_AUTO, deadman_enabled, CTLFLAG_RDTUN, - &zfs_deadman_enabled, 0, "Kernel panic on stalled ZFS I/O"); /* * The worst case is single-sector max-parity RAID-Z blocks, in which @@ -356,8 +324,50 @@ SYSCTL_INT(_vfs_zfs, OID_AUTO, deadman_enabled, CTLFLAG_RDTUN, * (VDEV_RAIDZ_MAXPARITY + 1) * SPA_DVAS_PER_BP * 2 == 24 */ int spa_asize_inflation = 24; + +#if defined(__FreeBSD__) && defined(_KERNEL) +SYSCTL_DECL(_vfs_zfs); +SYSCTL_INT(_vfs_zfs, OID_AUTO, recover, CTLFLAG_RWTUN, &zfs_recover, 0, + "Try to recover from otherwise-fatal errors."); + +static int +sysctl_vfs_zfs_debug_flags(SYSCTL_HANDLER_ARGS) +{ + int err, val; + + val = zfs_flags; + err = sysctl_handle_int(oidp, &val, 0, req); + if (err != 0 || req->newptr == NULL) + return (err); + + /* + * ZFS_DEBUG_MODIFY must be enabled prior to boot so all + * arc buffers in the system have the necessary additional + * checksum data. However, it is safe to disable at any + * time. + */ + if (!(zfs_flags & ZFS_DEBUG_MODIFY)) + val &= ~ZFS_DEBUG_MODIFY; + zfs_flags = val; + + return (0); +} + +SYSCTL_PROC(_vfs_zfs, OID_AUTO, debug_flags, + CTLTYPE_UINT | CTLFLAG_MPSAFE | CTLFLAG_RWTUN, 0, sizeof(int), + sysctl_vfs_zfs_debug_flags, "IU", "Debug flags for ZFS testing."); + +SYSCTL_UQUAD(_vfs_zfs, OID_AUTO, deadman_synctime_ms, CTLFLAG_RDTUN, + &zfs_deadman_synctime_ms, 0, + "Stalled ZFS I/O expiration time in milliseconds"); +SYSCTL_UQUAD(_vfs_zfs, OID_AUTO, deadman_checktime_ms, CTLFLAG_RDTUN, + &zfs_deadman_checktime_ms, 0, + "Period of checks for stalled ZFS I/O in milliseconds"); +SYSCTL_INT(_vfs_zfs, OID_AUTO, deadman_enabled, CTLFLAG_RDTUN, + &zfs_deadman_enabled, 0, "Kernel panic on stalled ZFS I/O"); SYSCTL_INT(_vfs_zfs, OID_AUTO, spa_asize_inflation, CTLFLAG_RWTUN, &spa_asize_inflation, 0, "Worst case inflation factor for single sector writes"); +#endif #ifndef illumos #ifdef _KERNEL diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c index 1fd9623..f459655 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c @@ -679,7 +679,15 @@ vdev_geom_open_by_path(vdev_t *vd, int check_guid) g_topology_unlock(); vdev_geom_read_guids(cp, &pguid, &vguid); g_topology_lock(); - if (pguid != spa_guid(vd->vdev_spa) || + /* + * Check that the label's vdev guid matches the + * desired guid. If the label has a pool guid, + * check that it matches too. (Inactive spares + * and L2ARCs do not have any pool guid in the + * label.) + */ + if ((pguid != 0 && + pguid != spa_guid(vd->vdev_spa)) || vguid != vd->vdev_guid) { vdev_geom_close_locked(vd); cp = NULL; diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio.c index 05e16ba..6dc0ad3 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio.c @@ -128,11 +128,13 @@ SYSCTL_INT(_vfs_zfs, OID_AUTO, sync_pass_rewrite, CTLFLAG_RDTUN, boolean_t zio_requeue_io_start_cut_in_line = B_TRUE; +#ifdef illumos #ifdef ZFS_DEBUG int zio_buf_debug_limit = 16384; #else int zio_buf_debug_limit = 0; #endif +#endif void zio_init(void) @@ -154,7 +156,7 @@ zio_init(void) size_t size = (c + 1) << SPA_MINBLOCKSHIFT; size_t p2 = size; size_t align = 0; - size_t cflags = (size > zio_buf_debug_limit) ? KMC_NODEBUG : 0; + int cflags = zio_exclude_metadata ? KMC_NODEBUG : 0; while (!ISP2(p2)) p2 &= p2 - 1; diff --git a/sys/cddl/contrib/opensolaris/uts/common/sys/fs/zfs.h b/sys/cddl/contrib/opensolaris/uts/common/sys/fs/zfs.h index 3818616..7c25ddd 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/sys/fs/zfs.h +++ b/sys/cddl/contrib/opensolaris/uts/common/sys/fs/zfs.h @@ -785,6 +785,10 @@ typedef struct ddt_histogram { #define ZFS_DRIVER "zfs" #define ZFS_DEV_NAME "zfs" #define ZFS_DEV "/dev/" ZFS_DEV_NAME +#define ZFS_DISK_ROOT "/dev/dsk" +#define ZFS_DISK_ROOTD ZFS_DISK_ROOT "/" +#define ZFS_RDISK_ROOT "/dev/rdsk" +#define ZFS_RDISK_ROOTD ZFS_RDISK_ROOT "/" /* general zvol path */ #define ZVOL_DIR "/dev/zvol" diff --git a/sys/cddl/dev/dtrace/aarch64/dtrace_isa.c b/sys/cddl/dev/dtrace/aarch64/dtrace_isa.c index 3d7e044..442367f 100644 --- a/sys/cddl/dev/dtrace/aarch64/dtrace_isa.c +++ b/sys/cddl/dev/dtrace/aarch64/dtrace_isa.c @@ -57,6 +57,7 @@ */ #define MAX_FUNCTION_SIZE 0x10000 #define MAX_PROLOGUE_SIZE 0x100 +#define MAX_USTACK_DEPTH 2048 uint8_t dtrace_fuword8_nocheck(void *); uint16_t dtrace_fuword16_nocheck(void *); @@ -111,11 +112,127 @@ dtrace_getpcstack(pc_t *pcstack, int pcstack_limit, int aframes, } } +static int +dtrace_getustack_common(uint64_t *pcstack, int pcstack_limit, uintptr_t pc, + uintptr_t fp) +{ + volatile uint16_t *flags = + (volatile uint16_t *)&cpu_core[curcpu].cpuc_dtrace_flags; + int ret = 0; + uintptr_t oldfp; + + ASSERT(pcstack == NULL || pcstack_limit > 0); + + while (pc != 0) { + /* + * We limit the number of times we can go around this + * loop to account for a circular stack. + */ + if (ret++ >= MAX_USTACK_DEPTH) { + *flags |= CPU_DTRACE_BADSTACK; + cpu_core[curcpu].cpuc_dtrace_illval = fp; + break; + } + + if (pcstack != NULL) { + *pcstack++ = (uint64_t)pc; + pcstack_limit--; + if (pcstack_limit <= 0) + break; + } + + if (fp == 0) + break; + + pc = dtrace_fuword64((void *)(fp + + offsetof(struct arm64_frame, f_retaddr))); + fp = dtrace_fuword64((void *)fp); + + if (fp == oldfp) { + *flags |= CPU_DTRACE_BADSTACK; + cpu_core[curcpu].cpuc_dtrace_illval = fp; + break; + } + + /* + * ARM64TODO: + * This workaround might not be necessary. It needs to be + * revised and removed from all architectures if found + * unwanted. Leaving the original x86 comment for reference. + * + * This is totally bogus: if we faulted, we're going to clear + * the fault and break. This is to deal with the apparently + * broken Java stacks on x86. + */ + if (*flags & CPU_DTRACE_FAULT) { + *flags &= ~CPU_DTRACE_FAULT; + break; + } + } + + return (ret); +} + void dtrace_getupcstack(uint64_t *pcstack, int pcstack_limit) { + proc_t *p = curproc; + struct trapframe *tf; + uintptr_t pc, sp, fp; + volatile uint16_t *flags = + (volatile uint16_t *)&cpu_core[curcpu].cpuc_dtrace_flags; + int n; - printf("IMPLEMENT ME: %s\n", __func__); + if (*flags & CPU_DTRACE_FAULT) + return; + + if (pcstack_limit <= 0) + return; + + /* + * If there's no user context we still need to zero the stack. + */ + if (p == NULL || (tf = curthread->td_frame) == NULL) + goto zero; + + *pcstack++ = (uint64_t)p->p_pid; + pcstack_limit--; + + if (pcstack_limit <= 0) + return; + + pc = tf->tf_elr; + sp = tf->tf_sp; + fp = tf->tf_x[29]; + + if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_ENTRY)) { + /* + * In an entry probe. The frame pointer has not yet been + * pushed (that happens in the function prologue). The + * best approach is to add the current pc as a missing top + * of stack and back the pc up to the caller, which is stored + * at the current stack pointer address since the call + * instruction puts it there right before the branch. + */ + + *pcstack++ = (uint64_t)pc; + pcstack_limit--; + if (pcstack_limit <= 0) + return; + + pc = tf->tf_lr; + } + + n = dtrace_getustack_common(pcstack, pcstack_limit, pc, fp); + ASSERT(n >= 0); + ASSERT(n <= pcstack_limit); + + pcstack += n; + pcstack_limit -= n; + +zero: + while (pcstack_limit-- > 0) + *pcstack++ = 0; } int diff --git a/sys/cddl/dev/dtrace/amd64/dtrace_subr.c b/sys/cddl/dev/dtrace/amd64/dtrace_subr.c index f6577d5..2a26b65 100644 --- a/sys/cddl/dev/dtrace/amd64/dtrace_subr.c +++ b/sys/cddl/dev/dtrace/amd64/dtrace_subr.c @@ -246,24 +246,14 @@ static uint64_t nsec_scale; /* See below for the explanation of this macro. */ #define SCALE_SHIFT 28 +/* + * Get the frequency and scale factor as early as possible so that they can be + * used for boot-time tracing. + */ static void -dtrace_gethrtime_init_cpu(void *arg) -{ - uintptr_t cpu = (uintptr_t) arg; - - if (cpu == curcpu) - tgt_cpu_tsc = rdtsc(); - else - hst_cpu_tsc = rdtsc(); -} - -static void -dtrace_gethrtime_init(void *arg) +dtrace_gethrtime_init_early(void *arg) { - struct pcpu *pc; uint64_t tsc_f; - cpuset_t map; - int i; /* * Get TSC frequency known at this moment. @@ -279,7 +269,8 @@ dtrace_gethrtime_init(void *arg) * another 32-bit integer without overflowing 64-bit. * Thus minimum supported TSC frequency is 62.5MHz. */ - KASSERT(tsc_f > (NANOSEC >> (32 - SCALE_SHIFT)), ("TSC frequency is too low")); + KASSERT(tsc_f > (NANOSEC >> (32 - SCALE_SHIFT)), + ("TSC frequency is too low")); /* * We scale up NANOSEC/tsc_f ratio to preserve as much precision @@ -291,6 +282,27 @@ dtrace_gethrtime_init(void *arg) * (terahertz) values; */ nsec_scale = ((uint64_t)NANOSEC << SCALE_SHIFT) / tsc_f; +} +SYSINIT(dtrace_gethrtime_init_early, SI_SUB_CPU, SI_ORDER_ANY, + dtrace_gethrtime_init_early, NULL); + +static void +dtrace_gethrtime_init_cpu(void *arg) +{ + uintptr_t cpu = (uintptr_t) arg; + + if (cpu == curcpu) + tgt_cpu_tsc = rdtsc(); + else + hst_cpu_tsc = rdtsc(); +} + +static void +dtrace_gethrtime_init(void *arg) +{ + struct pcpu *pc; + cpuset_t map; + int i; /* The current CPU is the reference one. */ sched_pin(); @@ -311,8 +323,8 @@ dtrace_gethrtime_init(void *arg) } sched_unpin(); } - -SYSINIT(dtrace_gethrtime_init, SI_SUB_SMP, SI_ORDER_ANY, dtrace_gethrtime_init, NULL); +SYSINIT(dtrace_gethrtime_init, SI_SUB_SMP, SI_ORDER_ANY, dtrace_gethrtime_init, + NULL); /* * DTrace needs a high resolution time function which can diff --git a/sys/cddl/dev/dtrace/i386/dtrace_subr.c b/sys/cddl/dev/dtrace/i386/dtrace_subr.c index be5bd4b..daca7dd 100644 --- a/sys/cddl/dev/dtrace/i386/dtrace_subr.c +++ b/sys/cddl/dev/dtrace/i386/dtrace_subr.c @@ -248,24 +248,14 @@ static uint64_t nsec_scale; /* See below for the explanation of this macro. */ #define SCALE_SHIFT 28 +/* + * Get the frequency and scale factor as early as possible so that they can be + * used for boot-time tracing. + */ static void -dtrace_gethrtime_init_cpu(void *arg) -{ - uintptr_t cpu = (uintptr_t) arg; - - if (cpu == curcpu) - tgt_cpu_tsc = rdtsc(); - else - hst_cpu_tsc = rdtsc(); -} - -static void -dtrace_gethrtime_init(void *arg) +dtrace_gethrtime_init_early(void *arg) { - cpuset_t map; - struct pcpu *pc; uint64_t tsc_f; - int i; /* * Get TSC frequency known at this moment. @@ -281,7 +271,8 @@ dtrace_gethrtime_init(void *arg) * another 32-bit integer without overflowing 64-bit. * Thus minimum supported TSC frequency is 62.5MHz. */ - KASSERT(tsc_f > (NANOSEC >> (32 - SCALE_SHIFT)), ("TSC frequency is too low")); + KASSERT(tsc_f > (NANOSEC >> (32 - SCALE_SHIFT)), + ("TSC frequency is too low")); /* * We scale up NANOSEC/tsc_f ratio to preserve as much precision @@ -293,6 +284,27 @@ dtrace_gethrtime_init(void *arg) * (terahertz) values; */ nsec_scale = ((uint64_t)NANOSEC << SCALE_SHIFT) / tsc_f; +} +SYSINIT(dtrace_gethrtime_init_early, SI_SUB_CPU, SI_ORDER_ANY, + dtrace_gethrtime_init_early, NULL); + +static void +dtrace_gethrtime_init_cpu(void *arg) +{ + uintptr_t cpu = (uintptr_t) arg; + + if (cpu == curcpu) + tgt_cpu_tsc = rdtsc(); + else + hst_cpu_tsc = rdtsc(); +} + +static void +dtrace_gethrtime_init(void *arg) +{ + cpuset_t map; + struct pcpu *pc; + int i; /* The current CPU is the reference one. */ sched_pin(); @@ -313,8 +325,8 @@ dtrace_gethrtime_init(void *arg) } sched_unpin(); } - -SYSINIT(dtrace_gethrtime_init, SI_SUB_SMP, SI_ORDER_ANY, dtrace_gethrtime_init, NULL); +SYSINIT(dtrace_gethrtime_init, SI_SUB_SMP, SI_ORDER_ANY, dtrace_gethrtime_init, + NULL); /* * DTrace needs a high resolution time function which can diff --git a/sys/cddl/dev/sdt/sdt.c b/sys/cddl/dev/sdt/sdt.c index 4e5dd71..cef816f 100644 --- a/sys/cddl/dev/sdt/sdt.c +++ b/sys/cddl/dev/sdt/sdt.c @@ -384,28 +384,20 @@ sdt_unload() static int sdt_modevent(module_t mod __unused, int type, void *data __unused) { - int error = 0; switch (type) { case MOD_LOAD: - sdt_load(); - break; - case MOD_UNLOAD: - error = sdt_unload(); - break; - case MOD_SHUTDOWN: - break; - + return (0); default: - error = EOPNOTSUPP; - break; + return (EOPNOTSUPP); } - - return (error); } +SYSINIT(sdt_load, SI_SUB_DTRACE_PROVIDER, SI_ORDER_ANY, sdt_load, NULL); +SYSUNINIT(sdt_unload, SI_SUB_DTRACE_PROVIDER, SI_ORDER_ANY, sdt_unload, NULL); + DEV_MODULE(sdt, sdt_modevent, NULL); MODULE_VERSION(sdt, 1); MODULE_DEPEND(sdt, dtrace, 1, 1, 1); |