From 83bba2b4a81b05183e2f81f5601e23cba9972fad Mon Sep 17 00:00:00 2001 From: Toomas Soome Date: Sun, 2 Feb 2020 20:37:22 +0200 Subject: 12272 loader: bc_add can not use any other probes than ah=0x4b Reviewed by: Alexander Eremin Reviewed by: Matthias Scheler Approved by: Dan McDonald --- usr/src/boot/Makefile.version | 2 +- usr/src/boot/sys/boot/i386/libi386/biosdisk.c | 148 +++++++++++++++++--------- 2 files changed, 98 insertions(+), 52 deletions(-) diff --git a/usr/src/boot/Makefile.version b/usr/src/boot/Makefile.version index f11337041e..b4fb4691f4 100644 --- a/usr/src/boot/Makefile.version +++ b/usr/src/boot/Makefile.version @@ -33,4 +33,4 @@ LOADER_VERSION = 1.1 # Use date like formatting here, YYYY.MM.DD.XX, without leading zeroes. # The version is processed from left to right, the version number can only # be increased. -BOOT_VERSION = $(LOADER_VERSION)-2020.01.17.1 +BOOT_VERSION = $(LOADER_VERSION)-2020.02.02.1 diff --git a/usr/src/boot/sys/boot/i386/libi386/biosdisk.c b/usr/src/boot/sys/boot/i386/libi386/biosdisk.c index 3d1ab645d5..343b8b0df9 100644 --- a/usr/src/boot/sys/boot/i386/libi386/biosdisk.c +++ b/usr/src/boot/sys/boot/i386/libi386/biosdisk.c @@ -97,7 +97,8 @@ struct specification_packet { uint16_t sp_sectorcount; uint16_t sp_cylsec; uint8_t sp_head; -}; + uint8_t sp_dummy[16]; /* Avoid memory corruption */ +} __packed; /* * List of BIOS devices, translation from disk unit number to @@ -367,54 +368,92 @@ cd_init(void) return (0); } -int -bc_add(int biosdev) +/* + * Information from bootable CD-ROM. + */ +static int +bd_get_diskinfo_cd(struct bdinfo *bd) { - bdinfo_t *bd; struct specification_packet bc_sp; - int nbcinfo = 0; + int ret = -1; - if (!STAILQ_EMPTY(&cdinfo)) - return (-1); + (void) memset(&bc_sp, 0, sizeof (bc_sp)); + /* Set sp_size as per specification. */ + bc_sp.sp_size = sizeof (bc_sp) - sizeof (bc_sp.sp_dummy); v86.ctl = V86_FLAGS; v86.addr = DISK_BIOS; v86.eax = CMD_CD_GET_STATUS; - v86.edx = biosdev; + v86.edx = bd->bd_unit; v86.ds = VTOPSEG(&bc_sp); v86.esi = VTOPOFF(&bc_sp); v86int(); - if ((v86.eax & 0xff00) != 0) - return (-1); - if ((bd = calloc(1, sizeof (*bd))) == NULL) - return (-1); + if ((v86.eax & 0xff00) == 0 && + bc_sp.sp_drive == bd->bd_unit) { + bd->bd_cyl = ((bc_sp.sp_cylsec & 0xc0) << 2) + + ((bc_sp.sp_cylsec & 0xff00) >> 8) + 1; + bd->bd_sec = bc_sp.sp_cylsec & 0x3f; + bd->bd_hds = bc_sp.sp_head + 1; + bd->bd_sectors = (uint64_t)bd->bd_cyl * bd->bd_hds * bd->bd_sec; - bd->bd_flags = BD_CDROM; - bd->bd_unit = biosdev; - bd->bd_sectorsize = 2048; + if (bc_sp.sp_bootmedia & 0x0F) { + /* Floppy or hard-disk emulation */ + bd->bd_sectorsize = BIOSDISK_SECSIZE; + return (-1); + } else { + bd->bd_sectorsize = 2048; + bd->bd_flags = BD_MODEEDD | BD_CDROM; + ret = 0; + } + } /* - * Ignore result from bd_int13probe(), we will use local - * workaround below. + * If this is the boot_drive, default to non-emulation bootable CD-ROM. */ - (void) bd_int13probe(bd); - - if (bd->bd_cyl == 0) { - bd->bd_cyl = ((bc_sp.sp_cylsec & 0xc0) << 2) + - ((bc_sp.sp_cylsec & 0xff00) >> 8) + 1; + if (ret != 0 && bd->bd_unit >= 0x88) { + bd->bd_cyl = 0; + bd->bd_hds = 1; + bd->bd_sec = 15; + bd->bd_sectorsize = 2048; + bd->bd_flags = BD_MODEEDD | BD_CDROM; + bd->bd_sectors = 0; + ret = 0; } - if (bd->bd_hds == 0) - bd->bd_hds = bc_sp.sp_head + 1; - if (bd->bd_sec == 0) - bd->bd_sec = bc_sp.sp_cylsec & 0x3f; - if (bd->bd_sectors == 0) - bd->bd_sectors = (uint64_t)bd->bd_cyl * bd->bd_hds * bd->bd_sec; - /* Still no size? use 7.961GB */ + /* + * Note we can not use bd_get_diskinfo_ext() nor bd_get_diskinfo_std() + * here - some systems do get hung with those. + */ + /* + * Still no size? use 7.961GB. The size does not really matter + * as long as it is reasonably large to make our reads to pass + * the sector count check. + */ if (bd->bd_sectors == 0) bd->bd_sectors = 4173824; + return (ret); +} + +int +bc_add(int biosdev) +{ + bdinfo_t *bd; + int nbcinfo = 0; + + if (!STAILQ_EMPTY(&cdinfo)) + return (-1); + + if ((bd = calloc(1, sizeof (*bd))) == NULL) + return (-1); + + bd->bd_unit = biosdev; + if (bd_get_diskinfo_cd(bd) < 0) { + free(bd); + return (-1); + } + STAILQ_INSERT_TAIL(&cdinfo, bd, bd_link); printf("BIOS CD is cd%d\n", nbcinfo); nbcinfo++; @@ -494,22 +533,31 @@ bd_get_diskinfo_std(struct bdinfo *bd) /* * Read EDD info. Return 0 on success, error otherwise. + * + * Avoid stack corruption on some systems by adding extra bytes to + * params block. */ static int bd_get_diskinfo_ext(struct bdinfo *bd) { - struct edd_params params; + struct disk_params { + struct edd_params head; + struct edd_device_path_v3 device_path; + uint8_t dummy[16]; + } __packed dparams; + struct edd_params *params; uint64_t total; + params = &dparams.head; /* Get disk params */ - bzero(¶ms, sizeof (params)); - params.len = sizeof (params); + bzero(&dparams, sizeof (dparams)); + params->len = sizeof (struct edd_params_v3); v86.ctl = V86_FLAGS; v86.addr = DISK_BIOS; v86.eax = CMD_EXT_PARAM; v86.edx = bd->bd_unit; - v86.ds = VTOPSEG(¶ms); - v86.esi = VTOPOFF(¶ms); + v86.ds = VTOPSEG(&dparams); + v86.esi = VTOPOFF(&dparams); v86int(); if (V86_CY(v86.efl) && ((v86.eax & 0xff00) != 0)) @@ -521,20 +569,20 @@ bd_get_diskinfo_ext(struct bdinfo *bd) * powerof2(params.sector_size). * 16K is largest read buffer we can use at this time. */ - if (params.sector_size >= 512 && - params.sector_size <= 16384 && - (params.sector_size % BIOSDISK_SECSIZE) == 0) - bd->bd_sectorsize = params.sector_size; + if (params->sector_size >= 512 && + params->sector_size <= 16384 && + (params->sector_size % BIOSDISK_SECSIZE) == 0) + bd->bd_sectorsize = params->sector_size; - bd->bd_cyl = params.cylinders; - bd->bd_hds = params.heads; - bd->bd_sec = params.sectors_per_track; + bd->bd_cyl = params->cylinders; + bd->bd_hds = params->heads; + bd->bd_sec = params->sectors_per_track; - if (params.sectors != 0) { - total = params.sectors; + if (params->sectors != 0) { + total = params->sectors; } else { - total = (uint64_t)params.cylinders * - params.heads * params.sectors_per_track; + total = (uint64_t)params->cylinders * + params->heads * params->sectors_per_track; } bd->bd_sectors = total; @@ -551,6 +599,10 @@ bd_int13probe(bdinfo_t *bd) bd->bd_flags &= ~BD_NO_MEDIA; + if ((bd->bd_flags & BD_CDROM) != 0) { + return (bd_get_diskinfo_cd(bd) == 0); + } + edd = bd_check_extensions(bd->bd_unit); if (edd == 0) bd->bd_flags |= BD_MODEINT13; @@ -599,10 +651,6 @@ bd_int13probe(bdinfo_t *bd) } if (ret != 0) { - /* CD is special case, bc_add() has its own fallback. */ - if ((bd->bd_flags & BD_CDROM) != 0) - return (true); - if (bd->bd_sectors != 0 && edd != 0) { bd->bd_sec = 63; bd->bd_hds = 255; @@ -614,8 +662,6 @@ bd_int13probe(bdinfo_t *bd) if ((bd->bd_flags & BD_FLOPPY) != 0) dv_name = biosfd.dv_name; - else if ((bd->bd_flags & BD_CDROM) != 0) - dv_name = bioscd.dv_name; else dv_name = bioshd.dv_name; -- cgit v1.2.3 From 442c994cdeb1e51c84e6d7ba987af00893aa84c4 Mon Sep 17 00:00:00 2001 From: Jason King Date: Fri, 31 Jan 2020 14:25:13 -0600 Subject: 12269 mdb multilist walker should be a layered walker Reviewed by: Kody Kantor Reviewed by: Jerry Jelinek Approved by: Dan McDonald --- usr/src/cmd/mdb/common/modules/zfs/zfs.c | 62 +++++++++++++++----------------- 1 file changed, 29 insertions(+), 33 deletions(-) diff --git a/usr/src/cmd/mdb/common/modules/zfs/zfs.c b/usr/src/cmd/mdb/common/modules/zfs/zfs.c index aaa29cdb17..431dce10b3 100644 --- a/usr/src/cmd/mdb/common/modules/zfs/zfs.c +++ b/usr/src/cmd/mdb/common/modules/zfs/zfs.c @@ -22,7 +22,7 @@ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright 2011 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 2011, 2018 by Delphix. All rights reserved. - * Copyright 2019 Joyent, Inc. + * Copyright 2020 Joyent, Inc. */ /* Portions Copyright 2010 Robert Milkowski */ @@ -2869,61 +2869,57 @@ typedef struct mdb_multilist { uintptr_t ml_sublists; } mdb_multilist_t; -typedef struct multilist_walk_data { - uint64_t mwd_idx; - mdb_multilist_t mwd_ml; -} multilist_walk_data_t; - -/* ARGSUSED */ -static int -multilist_print_cb(uintptr_t addr, const void *unknown, void *arg) -{ - mdb_printf("%#lr\n", addr); - return (WALK_NEXT); -} - static int multilist_walk_step(mdb_walk_state_t *wsp) { - multilist_walk_data_t *mwd = wsp->walk_data; - - if (mwd->mwd_idx >= mwd->mwd_ml.ml_num_sublists) - return (WALK_DONE); - - wsp->walk_addr = mwd->mwd_ml.ml_sublists + - mdb_ctf_sizeof_by_name("multilist_sublist_t") * mwd->mwd_idx + - mdb_ctf_offsetof_by_name("multilist_sublist_t", "mls_list"); - - mdb_pwalk("list", multilist_print_cb, (void*)NULL, wsp->walk_addr); - mwd->mwd_idx++; - - return (WALK_NEXT); + return (wsp->walk_callback(wsp->walk_addr, wsp->walk_layer, + wsp->walk_cbdata)); } static int multilist_walk_init(mdb_walk_state_t *wsp) { - multilist_walk_data_t *mwd; + mdb_multilist_t ml; + ssize_t sublist_sz; + int list_offset; + size_t i; if (wsp->walk_addr == 0) { mdb_warn("must supply address of multilist_t\n"); return (WALK_ERR); } - mwd = mdb_zalloc(sizeof (multilist_walk_data_t), UM_SLEEP | UM_GC); - if (mdb_ctf_vread(&mwd->mwd_ml, "multilist_t", "mdb_multilist_t", + if (mdb_ctf_vread(&ml, "multilist_t", "mdb_multilist_t", wsp->walk_addr, 0) == -1) { return (WALK_ERR); } - if (mwd->mwd_ml.ml_num_sublists == 0 || - mwd->mwd_ml.ml_sublists == 0) { + if (ml.ml_num_sublists == 0 || ml.ml_sublists == 0) { mdb_warn("invalid or uninitialized multilist at %#lx\n", wsp->walk_addr); return (WALK_ERR); } - wsp->walk_data = mwd; + /* mdb_ctf_sizeof_by_name() will print an error for us */ + sublist_sz = mdb_ctf_sizeof_by_name("multilist_sublist_t"); + if (sublist_sz == -1) + return (WALK_ERR); + + /* mdb_ctf_offsetof_by_name will print an error for us */ + list_offset = mdb_ctf_offsetof_by_name("multilist_sublist_t", + "mls_list"); + if (list_offset == -1) + return (WALK_ERR); + + for (i = 0; i < ml.ml_num_sublists; i++) { + wsp->walk_addr = ml.ml_sublists + i * sublist_sz + list_offset; + + if (mdb_layered_walk("list", wsp) == -1) { + mdb_warn("can't walk multilist sublist"); + return (WALK_ERR); + } + } + return (WALK_NEXT); } -- cgit v1.2.3 From 2d85dedb8eaa3ba69c85560030efe4cbc815efb8 Mon Sep 17 00:00:00 2001 From: Jason King Date: Thu, 23 Jan 2020 17:12:56 -0600 Subject: 12245 Support inheriting properties in zfs channel programs Reviewed by: Brian Behlendorf Reviewed by: Jerry Jelinek Approved by: Dan McDonald --- usr/src/man/man1m/zfs-program.1m | 24 +++++- usr/src/pkg/manifests/system-test-zfstest.mf | 5 +- .../channel_program/synctask_core/tst.inherit.ksh | 39 ++++++++++ usr/src/uts/common/fs/zfs/dsl_prop.c | 12 +-- usr/src/uts/common/fs/zfs/sys/dsl_prop.h | 9 +++ usr/src/uts/common/fs/zfs/zcp_synctask.c | 86 ++++++++++++++++++++++ 6 files changed, 164 insertions(+), 11 deletions(-) create mode 100755 usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.inherit.ksh diff --git a/usr/src/man/man1m/zfs-program.1m b/usr/src/man/man1m/zfs-program.1m index cf617136bd..12802319b0 100644 --- a/usr/src/man/man1m/zfs-program.1m +++ b/usr/src/man/man1m/zfs-program.1m @@ -10,8 +10,9 @@ .\" .\" Copyright (c) 2016, 2017 by Delphix. All rights reserved. .\" Copyright (c) 2018 Datto Inc. +.\" Copyright 2020 Joyent, Inc. .\" -.Dd January 21, 2016 +.Dd January 15, 2020 .Dt ZFS-PROGRAM 1M .Os .Sh NAME @@ -366,6 +367,27 @@ Valid only for destroying snapshots. If set to true, and the snapshot has holds or clones, allows the snapshot to be marked for deferred deletion rather than failing. .Ed +.It Em zfs.sync.inherit(dataset, property) +Clears the specified property in the given dataset, causing it to be inherited +from an ancestor, or restored to the default if no ancestor property is set. +The +.Ql zfs inherit -S +option has not been implemented. +Returns 0 on success, or a nonzero error code if the property could not be +cleared. +.Pp +dataset (string) +.Bd -ragged -compact -offset "xxxx" +Filesystem or snapshot containing the property to clear. +.Ed +.Pp +property (string) +.Bd -ragged -compact -offset "xxxx" +The property to clear. +Allowed properties are the same as those for the +.Nm zfs Cm inherit +command. +.Ed .It Em zfs.sync.promote(dataset) Promote the given clone to a filesystem. Returns 0 on successful promotion, or a nonzero error code otherwise. diff --git a/usr/src/pkg/manifests/system-test-zfstest.mf b/usr/src/pkg/manifests/system-test-zfstest.mf index 0a95e4d759..d4432b45a1 100644 --- a/usr/src/pkg/manifests/system-test-zfstest.mf +++ b/usr/src/pkg/manifests/system-test-zfstest.mf @@ -13,7 +13,7 @@ # Copyright (c) 2012, 2017 by Delphix. All rights reserved. # Copyright 2015, 2016 Nexenta Systems, Inc. All rights reserved. # Copyright 2016, OmniTI Computer Consulting, Inc. All rights reserved. -# Copyright 2019 Joyent, Inc. +# Copyright 2020 Joyent, Inc. # Copyright (c) 2018 Datto Inc. # @@ -599,6 +599,9 @@ file \ file \ path=opt/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_written \ mode=0555 +file \ + path=opt/zfs-tests/tests/functional/channel_program/synctask_core/tst.inherit \ + mode=0555 file \ path=opt/zfs-tests/tests/functional/channel_program/synctask_core/tst.list_children \ mode=0555 diff --git a/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.inherit.ksh b/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.inherit.ksh new file mode 100755 index 0000000000..e199b4c8b0 --- /dev/null +++ b/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.inherit.ksh @@ -0,0 +1,39 @@ +#!/bin/ksh -p +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright 2020 Joyent, Inc. +# + +. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib + +verify_runnable "global" + +fs=$TESTPOOL/$TESTFS +testprop="com.joyent:testprop" +testval="testval" + +log_must dataset_setprop $fs $testprop $testval +log_must_program_sync $TESTPOOL - $fs $testprop <<-EOF + arg = ... + fs = arg["argv"][1] + prop = arg["argv"][2] + err = zfs.sync.inherit(fs, prop) + msg = "resetting " .. prop .. " on " .. fs .. " err=" .. err + return msg +EOF + + +prop=$(get_prop $testprop $fs) +[[ "$prop" == "-" ]] || log_fail "Property still set after inheriting" + +log_pass "Inherit/clear property with channel program works." diff --git a/usr/src/uts/common/fs/zfs/dsl_prop.c b/usr/src/uts/common/fs/zfs/dsl_prop.c index 8197f0685a..7fc8553493 100644 --- a/usr/src/uts/common/fs/zfs/dsl_prop.c +++ b/usr/src/uts/common/fs/zfs/dsl_prop.c @@ -22,7 +22,7 @@ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2015 by Delphix. All rights reserved. * Copyright (c) 2013 Martin Matuska. All rights reserved. - * Copyright 2015, Joyent, Inc. + * Copyright 2019 Joyent, Inc. */ #include @@ -802,13 +802,7 @@ dsl_prop_inherit(const char *dsname, const char *propname, return (error); } -typedef struct dsl_props_set_arg { - const char *dpsa_dsname; - zprop_source_t dpsa_source; - nvlist_t *dpsa_props; -} dsl_props_set_arg_t; - -static int +int dsl_props_set_check(void *arg, dmu_tx_t *tx) { dsl_props_set_arg_t *dpsa = arg; @@ -886,7 +880,7 @@ dsl_props_set_sync_impl(dsl_dataset_t *ds, zprop_source_t source, } } -static void +void dsl_props_set_sync(void *arg, dmu_tx_t *tx) { dsl_props_set_arg_t *dpsa = arg; diff --git a/usr/src/uts/common/fs/zfs/sys/dsl_prop.h b/usr/src/uts/common/fs/zfs/sys/dsl_prop.h index 21e6f4674b..9afaf6f2b7 100644 --- a/usr/src/uts/common/fs/zfs/sys/dsl_prop.h +++ b/usr/src/uts/common/fs/zfs/sys/dsl_prop.h @@ -21,6 +21,7 @@ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012 by Delphix. All rights reserved. + * Copyright 2019 Joyent, Inc. */ #ifndef _SYS_DSL_PROP_H @@ -61,6 +62,12 @@ typedef struct dsl_props_arg { zprop_source_t pa_source; } dsl_props_arg_t; +typedef struct dsl_props_set_arg { + const char *dpsa_dsname; + zprop_source_t dpsa_source; + nvlist_t *dpsa_props; +} dsl_props_set_arg_t; + void dsl_prop_init(dsl_dir_t *dd); void dsl_prop_fini(dsl_dir_t *dd); int dsl_prop_register(struct dsl_dataset *ds, const char *propname, @@ -83,6 +90,8 @@ int dsl_prop_get_dd(struct dsl_dir *dd, const char *propname, int intsz, int numints, void *buf, char *setpoint, boolean_t snapshot); +int dsl_props_set_check(void *arg, dmu_tx_t *tx); +void dsl_props_set_sync(void *arg, dmu_tx_t *tx); void dsl_props_set_sync_impl(struct dsl_dataset *ds, zprop_source_t source, nvlist_t *props, dmu_tx_t *tx); void dsl_prop_set_sync_impl(struct dsl_dataset *ds, const char *propname, diff --git a/usr/src/uts/common/fs/zfs/zcp_synctask.c b/usr/src/uts/common/fs/zfs/zcp_synctask.c index 25d970ec08..f479a50ea3 100644 --- a/usr/src/uts/common/fs/zfs/zcp_synctask.c +++ b/usr/src/uts/common/fs/zfs/zcp_synctask.c @@ -15,6 +15,7 @@ /* * Copyright (c) 2016, 2017 by Delphix. All rights reserved. + * Copyright 2020 Joyent, Inc. */ #include "lua.h" @@ -35,6 +36,12 @@ #define DST_AVG_BLKSHIFT 14 +typedef struct zcp_inherit_prop_arg { + lua_State *zipa_state; + const char *zipa_prop; + dsl_props_set_arg_t zipa_dpsa; +} zcp_inherit_prop_arg_t; + typedef int (zcp_synctask_func_t)(lua_State *, boolean_t, nvlist_t *); typedef struct zcp_synctask_info { const char *name; @@ -275,6 +282,84 @@ zcp_synctask_snapshot(lua_State *state, boolean_t sync, nvlist_t *err_details) return (err); } +static int zcp_synctask_inherit_prop(lua_State *, boolean_t, + nvlist_t *err_details); +static zcp_synctask_info_t zcp_synctask_inherit_prop_info = { + .name = "inherit", + .func = zcp_synctask_inherit_prop, + .space_check = ZFS_SPACE_CHECK_RESERVED, + .blocks_modified = 2, /* 2 * numprops */ + .pargs = { + { .za_name = "dataset", .za_lua_type = LUA_TSTRING }, + { .za_name = "property", .za_lua_type = LUA_TSTRING }, + { NULL, 0 } + }, + .kwargs = { + { NULL, 0 } + }, +}; + +static int +zcp_synctask_inherit_prop_check(void *arg, dmu_tx_t *tx) +{ + zcp_inherit_prop_arg_t *args = arg; + zfs_prop_t prop = zfs_name_to_prop(args->zipa_prop); + + if (prop == ZPROP_INVAL) { + if (zfs_prop_user(args->zipa_prop)) + return (0); + + return (EINVAL); + } + + if (zfs_prop_readonly(prop)) + return (EINVAL); + + if (!zfs_prop_inheritable(prop)) + return (EINVAL); + + return (dsl_props_set_check(&args->zipa_dpsa, tx)); +} + +static void +zcp_synctask_inherit_prop_sync(void *arg, dmu_tx_t *tx) +{ + zcp_inherit_prop_arg_t *args = arg; + dsl_props_set_arg_t *dpsa = &args->zipa_dpsa; + + dsl_props_set_sync(dpsa, tx); +} + +static int +zcp_synctask_inherit_prop(lua_State *state, boolean_t sync, + nvlist_t *err_details) +{ + int err; + zcp_inherit_prop_arg_t zipa = { 0 }; + dsl_props_set_arg_t *dpsa = &zipa.zipa_dpsa; + + const char *dsname = lua_tostring(state, 1); + const char *prop = lua_tostring(state, 2); + + zipa.zipa_state = state; + zipa.zipa_prop = prop; + dpsa->dpsa_dsname = dsname; + dpsa->dpsa_source = ZPROP_SRC_INHERITED; + dpsa->dpsa_props = fnvlist_alloc(); + fnvlist_add_boolean(dpsa->dpsa_props, prop); + + zcp_cleanup_handler_t *zch = zcp_register_cleanup(state, + (zcp_cleanup_t *)&fnvlist_free, dpsa->dpsa_props); + + err = zcp_sync_task(state, zcp_synctask_inherit_prop_check, + zcp_synctask_inherit_prop_sync, &zipa, sync, dsname); + + zcp_deregister_cleanup(state, zch); + fnvlist_free(dpsa->dpsa_props); + + return (err); +} + static int zcp_synctask_wrapper(lua_State *state) { @@ -342,6 +427,7 @@ zcp_load_synctask_lib(lua_State *state, boolean_t sync) &zcp_synctask_promote_info, &zcp_synctask_rollback_info, &zcp_synctask_snapshot_info, + &zcp_synctask_inherit_prop_info, NULL }; -- cgit v1.2.3 From 31ad075e90bf5afda8ab4b8cc4d3ca3e89946115 Mon Sep 17 00:00:00 2001 From: John Levon Date: Wed, 22 Jan 2020 16:05:13 -0800 Subject: 12257 resync smatch to 0.6.1-rc1-il-4 Reviewed by: Toomas Soome Reviewed by: Robert Mustacchi Approved by: Dan McDonald --- usr/src/tools/smatch/Makefile | 3 +- usr/src/tools/smatch/src/Makefile | 3 +- usr/src/tools/smatch/src/check_list.h | 1 + usr/src/tools/smatch/src/check_locking.c | 9 +- usr/src/tools/smatch/src/lib.c | 29 ++-- usr/src/tools/smatch/src/lib.h | 15 ++ usr/src/tools/smatch/src/machine.h | 2 +- usr/src/tools/smatch/src/pre-process.c | 8 + usr/src/tools/smatch/src/smatch.h | 11 ++ usr/src/tools/smatch/src/smatch_container_of.c | 59 +++---- usr/src/tools/smatch/src/smatch_db.c | 90 +--------- usr/src/tools/smatch/src/smatch_fresh_alloc.c | 195 ++++++++++++++++++++++ usr/src/tools/smatch/src/smatch_math.c | 20 +++ usr/src/tools/smatch/src/smatch_mtag.c | 16 +- usr/src/tools/smatch/src/smatch_slist.c | 8 +- usr/src/tools/smatch/src/smatch_type.c | 2 +- usr/src/tools/smatch/src/validation/sm_locking2.c | 9 +- usr/src/tools/smatch/src/validation/sm_locking3.c | 9 +- usr/src/tools/smatch/src/validation/sm_locking4.c | 7 +- usr/src/tools/smatch/src/validation/sm_locking6.c | 16 +- usr/src/tools/smatch/src/validation/sm_locking7.c | 12 +- 21 files changed, 353 insertions(+), 171 deletions(-) create mode 100644 usr/src/tools/smatch/src/smatch_fresh_alloc.c diff --git a/usr/src/tools/smatch/Makefile b/usr/src/tools/smatch/Makefile index c8f3c74f78..902c874624 100644 --- a/usr/src/tools/smatch/Makefile +++ b/usr/src/tools/smatch/Makefile @@ -20,7 +20,7 @@ # PROG = smatch -SPARSE_VERSION = 0.6.1-rc1-il-3 +SPARSE_VERSION = 0.6.1-rc1-il-4 include ../Makefile.tools @@ -123,6 +123,7 @@ SMATCH_OBJS += smatch_expression_stacks.o SMATCH_OBJS += smatch_extra.o SMATCH_OBJS += smatch_files.o SMATCH_OBJS += smatch_flow.o +SMATCH_OBJS += smatch_fresh_alloc.o SMATCH_OBJS += smatch_fn_arg_link.o SMATCH_OBJS += smatch_function_hooks.o SMATCH_OBJS += smatch_function_info.o diff --git a/usr/src/tools/smatch/src/Makefile b/usr/src/tools/smatch/src/Makefile index e9fb252972..bc8b3071a1 100644 --- a/usr/src/tools/smatch/src/Makefile +++ b/usr/src/tools/smatch/src/Makefile @@ -1,4 +1,4 @@ -VERSION=0.6.1-rc1-il-3 +VERSION=0.6.1-rc1-il-4 ######################################################################## # The following variables can be overwritten from the command line @@ -226,6 +226,7 @@ SMATCH_OBJS += smatch_extra.o SMATCH_OBJS += smatch_files.o SMATCH_OBJS += smatch_flow.o SMATCH_OBJS += smatch_fn_arg_link.o +SMATCH_OBJS += smatch_fresh_alloc.o SMATCH_OBJS += smatch_function_hooks.o SMATCH_OBJS += smatch_function_info.o SMATCH_OBJS += smatch_function_ptrs.o diff --git a/usr/src/tools/smatch/src/check_list.h b/usr/src/tools/smatch/src/check_list.h index b687018e48..1841676ce3 100644 --- a/usr/src/tools/smatch/src/check_list.h +++ b/usr/src/tools/smatch/src/check_list.h @@ -72,6 +72,7 @@ CK(register_array_values) CK(register_nul_terminator) CK(register_nul_terminator_param_set) CK(register_statement_count) +CK(register_fresh_alloc) CK(register_kernel_user_data) CK(register_kernel_user_data2) diff --git a/usr/src/tools/smatch/src/check_locking.c b/usr/src/tools/smatch/src/check_locking.c index 285a52cedf..9af6b46c46 100644 --- a/usr/src/tools/smatch/src/check_locking.c +++ b/usr/src/tools/smatch/src/check_locking.c @@ -1021,10 +1021,13 @@ static void check_lock(char *name, struct symbol *sym) if (parent_is_gone_var_sym(sm->name, sm->sym)) goto swap_stree; - if (sm->state != &locked && sm->state != &unlocked) + if (sm->state != &locked && + sm->state != &unlocked && + sm->state != &restore) goto swap_stree; - if (sm->state == &unlocked && is_EINTR(estate_rl(return_sm->state))) + if ((sm->state == &unlocked || sm->state == &restore) && + is_EINTR(estate_rl(return_sm->state))) goto swap_stree; bucket = success_fail_positive(estate_rl(return_sm->state)); @@ -1032,7 +1035,7 @@ static void check_lock(char *name, struct symbol *sym) add_range(&locked_lines, line, line); locked_buckets[bucket] = true; } - if (sm->state == &unlocked) { + if (sm->state == &unlocked || sm->state == &restore) { add_range(&unlocked_lines, line, line); unlocked_buckets[bucket] = true; } diff --git a/usr/src/tools/smatch/src/lib.c b/usr/src/tools/smatch/src/lib.c index bc80001d55..50241937b5 100644 --- a/usr/src/tools/smatch/src/lib.c +++ b/usr/src/tools/smatch/src/lib.c @@ -318,13 +318,7 @@ int funsigned_char = UNSIGNED_CHAR; int preprocess_only; -static enum { STANDARD_C89, - STANDARD_C94, - STANDARD_C99, - STANDARD_C11, - STANDARD_GNU11, - STANDARD_GNU89, - STANDARD_GNU99, } standard = STANDARD_GNU89; +enum standard standard = STANDARD_GNU89; int arch_m64 = ARCH_M64_DEFAULT; int arch_msize_long = 0; @@ -1313,6 +1307,8 @@ static void predefined_macros(void) if (optimize_size) predefine("__OPTIMIZE_SIZE__", 0, "1"); + predefine("__PRAGMA_REDEFINE_EXTNAME", 1, "1"); + // Temporary hacks predefine("__extension__", 0, NULL); predefine("__pragma__", 0, NULL); @@ -1326,7 +1322,6 @@ static void predefined_macros(void) break; case ARCH_LP64: predefine("__LP64__", 1, "1"); - predefine("__LP64", 1, "1"); predefine("_LP64", 1, "1"); break; case ARCH_LLP64: @@ -1389,32 +1384,38 @@ static void predefined_macros(void) case MACH_SPARC32: predefine("__sparc__", 1, "1"); predefine("__sparc", 1, "1"); + predefine_nostd("sparc"); break; case MACH_X86_64: if (arch_m64 != ARCH_LP32) { predefine("__x86_64__", 1, "1"); predefine("__x86_64", 1, "1"); + predefine("__amd64__", 1, "1"); + predefine("__amd64", 1, "1"); break; } /* fall-through */ case MACH_I386: predefine("__i386__", 1, "1"); predefine("__i386", 1, "1"); - predefine("i386", 1, "1"); + predefine_nostd("i386"); break; } - predefine("__PRAGMA_REDEFINE_EXTNAME", 1, "1"); - -#ifdef __sun +#if defined(__unix__) predefine("__unix__", 1, "1"); predefine("__unix", 1, "1"); - predefine("unix", 1, "1"); + predefine_nostd("unix"); +#endif + + +#if defined(__sun__) || defined(__sun) predefine("__sun__", 1, "1"); predefine("__sun", 1, "1"); - predefine("sun", 1, "1"); + predefine_nostd("sun"); predefine("__svr4__", 1, "1"); #endif + } static void create_builtin_stream(void) diff --git a/usr/src/tools/smatch/src/lib.h b/usr/src/tools/smatch/src/lib.h index de8f1132fa..70b2ba3928 100644 --- a/usr/src/tools/smatch/src/lib.h +++ b/usr/src/tools/smatch/src/lib.h @@ -134,6 +134,7 @@ enum phase { extern void add_pre_buffer(const char *fmt, ...) FORMAT_ATTR(1); extern void predefine(const char *name, int weak, const char *fmt, ...) FORMAT_ATTR(3); +extern void predefine_nostd(const char *name); extern int preprocess_only; @@ -206,6 +207,20 @@ extern int arch_msize_long; extern int arch_big_endian; extern int arch_mach; +enum standard { + STANDARD_NONE, + STANDARD_GNU, + STANDARD_C89, + STANDARD_GNU89 = STANDARD_C89 | STANDARD_GNU, + STANDARD_C94, + STANDARD_GNU94 = STANDARD_C94 | STANDARD_GNU, + STANDARD_C99, + STANDARD_GNU99 = STANDARD_C99 | STANDARD_GNU, + STANDARD_C11, + STANDARD_GNU11 = STANDARD_C11 | STANDARD_GNU, +}; +extern enum standard standard; + extern void dump_macro_definitions(void); extern struct symbol_list *sparse_initialize(int argc, char **argv, struct string_list **files); extern struct symbol_list *__sparse(char *filename); diff --git a/usr/src/tools/smatch/src/machine.h b/usr/src/tools/smatch/src/machine.h index b46383ac1d..af5c96f16f 100644 --- a/usr/src/tools/smatch/src/machine.h +++ b/usr/src/tools/smatch/src/machine.h @@ -62,7 +62,7 @@ enum machine { #define MACH_NATIVE MACH_RISCV64 #elif defined(__riscv) && (__riscv_xlen == 32) #define MACH_NATIVE MACH_RISCV32 -#elif defined(__sparc_v9__) +#elif defined(__sparc_v9__) || defined(__sparcv9) #define MACH_NATIVE MACH_SPARC64 #elif defined(__sparc__) || defined(__sparc) #define MACH_NATIVE MACH_SPARC32 diff --git a/usr/src/tools/smatch/src/pre-process.c b/usr/src/tools/smatch/src/pre-process.c index c35cbcfb3c..5a9313a358 100644 --- a/usr/src/tools/smatch/src/pre-process.c +++ b/usr/src/tools/smatch/src/pre-process.c @@ -1568,6 +1568,14 @@ void predefine(const char *name, int weak, const char *fmt, ...) do_define(value->pos, NULL, ident, NULL, value, attr); } +/// +// like predefine() but only if one of the non-standard dialect is chosen +void predefine_nostd(const char *name) +{ + if ((standard & STANDARD_GNU) || (standard == STANDARD_NONE)) + predefine(name, 1, "1"); +} + static int do_handle_define(struct stream *stream, struct token **line, struct token *token, int attr) { struct token *arglist, *expansion; diff --git a/usr/src/tools/smatch/src/smatch.h b/usr/src/tools/smatch/src/smatch.h index 062dffc9d2..6e0698085e 100644 --- a/usr/src/tools/smatch/src/smatch.h +++ b/usr/src/tools/smatch/src/smatch.h @@ -104,6 +104,12 @@ struct constraint { }; DECLARE_PTR_LIST(constraint_list, struct constraint); +struct alloc_info { + const char *fn; + int size_param, nr; +}; +extern struct alloc_info *alloc_funcs; + struct bit_info { unsigned long long set; unsigned long long possible; @@ -398,6 +404,7 @@ int sym_name_is(const char *name, struct expression *expr); int get_const_value(struct expression *expr, sval_t *sval); int get_value(struct expression *expr, sval_t *val); int get_implied_value(struct expression *expr, sval_t *val); +int get_implied_value_fast(struct expression *expr, sval_t *sval); int get_implied_min(struct expression *expr, sval_t *sval); int get_implied_max(struct expression *expr, sval_t *val); int get_hard_max(struct expression *expr, sval_t *sval); @@ -839,6 +846,7 @@ enum info_type { NOSPEC_WB = 1036, STMT_CNT = 1037, TERMINATED = 1038, + FRESH_ALLOC = 1044, /* put random temporary stuff in the 7000-7999 range for testing */ USER_DATA = 8017, @@ -1249,6 +1257,7 @@ int get_offset_from_container_of(struct expression *expr); char *get_container_name(struct expression *container, struct expression *expr); /* smatch_mtag.c */ +mtag_t str_to_mtag(const char *str); int get_string_mtag(struct expression *expr, mtag_t *tag); int get_toplevel_mtag(struct symbol *sym, mtag_t *tag); int create_mtag_alias(mtag_t tag, struct expression *expr, mtag_t *new); @@ -1278,6 +1287,8 @@ bool is_nul_terminated(struct expression *expr); /* check_kernel.c */ bool is_ignored_kernel_data(const char *name); +bool is_fresh_alloc_var_sym(const char *var, struct symbol *sym); +bool is_fresh_alloc(struct expression *expr); static inline bool type_is_ptr(struct symbol *type) { return type && diff --git a/usr/src/tools/smatch/src/smatch_container_of.c b/usr/src/tools/smatch/src/smatch_container_of.c index bd9039cf75..65d4a8d8ac 100644 --- a/usr/src/tools/smatch/src/smatch_container_of.c +++ b/usr/src/tools/smatch/src/smatch_container_of.c @@ -215,17 +215,17 @@ static char *get_stored_container_name(struct expression *container, return NULL; } -char *get_container_name(struct expression *container, struct expression *expr) +static char *get_container_name_helper(struct expression *container, struct expression *expr) { struct symbol *container_sym, *sym; - struct expression *tmp; static char buf[64]; char *ret, *shared; bool star; - int cnt; expr = strip_expr(expr); container = strip_expr(container); + if (!expr || !container) + return NULL; ret = get_stored_container_name(container, expr); if (ret) @@ -233,24 +233,10 @@ char *get_container_name(struct expression *container, struct expression *expr) sym = expr_to_sym(expr); container_sym = expr_to_sym(container); - if (sym && sym == container_sym) - goto found; - - cnt = 0; - while ((tmp = get_assigned_expr(container))) { - container = strip_expr(tmp); - if (cnt++ > 3) - break; - } - - cnt = 0; - while ((tmp = get_assigned_expr(expr))) { - expr = strip_expr(tmp); - if (cnt++ > 3) - break; - } - -found: + if (!sym || !container_sym) + return NULL; + if (sym != container_sym) + return NULL; if (container->type == EXPR_DEREF) star = true; @@ -262,13 +248,6 @@ found: if (expr->type == EXPR_PREOP && expr->op == '&') expr = strip_expr(expr->unop); - sym = expr_to_sym(expr); - if (!sym) - return NULL; - container_sym = expr_to_sym(container); - if (!container_sym || sym != container_sym) - return NULL; - shared = get_shared_str(expr, container); if (!shared) return NULL; @@ -280,6 +259,30 @@ found: return buf; } +char *get_container_name(struct expression *container, struct expression *expr) +{ + char *ret; + + ret = get_container_name_helper(container, expr); + if (ret) + return ret; + + ret = get_container_name_helper(get_assigned_expr(container), expr); + if (ret) + return ret; + + ret = get_container_name_helper(container, get_assigned_expr(expr)); + if (ret) + return ret; + + ret = get_container_name_helper(get_assigned_expr(container), + get_assigned_expr(expr)); + if (ret) + return ret; + + return NULL; +} + static bool is_fn_ptr(struct expression *expr) { struct symbol *type; diff --git a/usr/src/tools/smatch/src/smatch_db.c b/usr/src/tools/smatch/src/smatch_db.c index e932d315ab..70be64093d 100644 --- a/usr/src/tools/smatch/src/smatch_db.c +++ b/usr/src/tools/smatch/src/smatch_db.c @@ -768,16 +768,6 @@ static void match_call_marker(struct expression *expr) sql_insert_caller_info(expr, INTERNAL, -1, "%call_marker%", type_to_str(type)); } -static char *show_offset(int offset) -{ - static char buf[64]; - - buf[0] = '\0'; - if (offset != -1) - snprintf(buf, sizeof(buf), "(-%d)", offset); - return buf; -} - int is_recursive_member(const char *name) { char buf[256]; @@ -860,7 +850,7 @@ free: return ret; } -static void print_struct_members(struct expression *call, struct expression *expr, int param, int offset, struct stree *stree, +static void print_struct_members(struct expression *call, struct expression *expr, int param, struct stree *stree, void (*callback)(struct expression *call, int param, char *printed_name, struct sm_state *sm)) { struct sm_state *sm; @@ -902,23 +892,23 @@ static void print_struct_members(struct expression *call, struct expression *exp // FIXME: simplify? if (!add_star && strcmp(name, sm_name) == 0) { if (is_address) - snprintf(printed_name, sizeof(printed_name), "*$%s", show_offset(offset)); + snprintf(printed_name, sizeof(printed_name), "*$"); else /* these are already handled. fixme: handle them here */ continue; } else if (add_star && strcmp(name, sm_name) == 0) { - snprintf(printed_name, sizeof(printed_name), "%s*$%s", - is_address ? "*" : "", show_offset(offset)); + snprintf(printed_name, sizeof(printed_name), "%s*$", + is_address ? "*" : ""); } else if (strncmp(name, sm_name, len) == 0) { if (sm_name[len] != '.' && sm_name[len] != '-') continue; if (is_address) snprintf(printed_name, sizeof(printed_name), - "%s$%s->%s", add_star ? "*" : "", - show_offset(offset), sm_name + len + 1); + "%s$->%s", add_star ? "*" : "", + sm_name + len + 1); else snprintf(printed_name, sizeof(printed_name), - "%s$%s%s", add_star ? "*" : "", - show_offset(offset), sm_name + len); + "%s$%s", add_star ? "*" : "", + sm_name + len); } else { continue; } @@ -930,67 +920,6 @@ free: free_string(name); } -static int param_used_callback(void *_container, int argc, char **argv, char **azColName) -{ - char **container = _container; - static char buf[256]; - - snprintf(buf, sizeof(buf), "%s", argv[0]); - *container = buf; - return 0; -} - -static void print_container_struct_members(struct expression *call, struct expression *expr, int param, struct stree *stree, - void (*callback)(struct expression *call, int param, char *printed_name, struct sm_state *sm)) -{ - struct expression *tmp; - char *container = NULL; - int offset; - int holder_offset; - char *p; - - if (!call->fn || call->fn->type != EXPR_SYMBOL || !call->fn->symbol) - return; - - /* - * We can't use the in-mem DB because we have to parse the function - * first, then we know if it takes a container, then we know to pass it - * the container data. - * - */ - run_sql(¶m_used_callback, &container, - "select key from return_implies where %s and type = %d and key like '%%$(%%' and parameter = %d limit 1;", - get_static_filter(call->fn->symbol), CONTAINER, param); - if (!container) - return; - - p = strchr(container, '-'); - if (!p) - return; - offset = atoi(p); - p = strchr(p, ')'); - if (!p) - return; - p++; - - tmp = get_assigned_expr(expr); - if (tmp) - expr = tmp; - - if (expr->type != EXPR_PREOP || expr->op != '&') - return; - expr = strip_expr(expr->unop); - holder_offset = get_member_offset_from_deref(expr); - if (-holder_offset != offset) - return; - - expr = strip_expr(expr->deref); - if (expr->type == EXPR_PREOP && expr->op == '*') - expr = strip_expr(expr->unop); - - print_struct_members(call, expr, param, holder_offset, stree, callback); -} - static void match_call_info(struct expression *call) { struct member_info_callback *cb; @@ -1007,8 +936,7 @@ static void match_call_info(struct expression *call) stree = get_all_states_stree(cb->owner); i = 0; FOR_EACH_PTR(call->args, arg) { - print_struct_members(call, arg, i, -1, stree, cb->callback); - print_container_struct_members(call, arg, i, stree, cb->callback); + print_struct_members(call, arg, i, stree, cb->callback); i++; } END_FOR_EACH_PTR(arg); free_stree(&stree); diff --git a/usr/src/tools/smatch/src/smatch_fresh_alloc.c b/usr/src/tools/smatch/src/smatch_fresh_alloc.c new file mode 100644 index 0000000000..d7104f6b53 --- /dev/null +++ b/usr/src/tools/smatch/src/smatch_fresh_alloc.c @@ -0,0 +1,195 @@ +/* + * Copyright (C) 2019 Oracle. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see http://www.gnu.org/copyleft/gpl.txt + */ + +/* + * There are a bunch of allocation functions where we allocate some memory, + * set up some struct members and then return the allocated memory. One + * nice thing about this is that we just one pointer to the allocated memory + * so what we can do is we can generate a mtag alias for it in the caller. + */ + +#include "smatch.h" +#include "smatch_slist.h" + +static int my_id; + +STATE(fresh); + +struct alloc_info *alloc_funcs; + +struct alloc_info kernel_allocation_funcs[] = { + {"kmalloc", 0}, + {"kmalloc_node", 0}, + {"kzalloc", 0}, + {"kzalloc_node", 0}, + {"vmalloc", 0}, + {"__vmalloc", 0}, + {"kvmalloc", 0}, + {"kcalloc", 0, 1}, + {"kmalloc_array", 0, 1}, + {"sock_kmalloc", 1}, + {"kmemdup", 1}, + {"kmemdup_user", 1}, + {"dma_alloc_attrs", 1}, + {"pci_alloc_consistent", 1}, + {"pci_alloc_coherent", 1}, + {"devm_kmalloc", 1}, + {"devm_kzalloc", 1}, + {"krealloc", 1}, + {"__alloc_bootmem", 0}, + {"alloc_bootmem", 0}, + {"dma_alloc_contiguous", 1}, + {"dma_alloc_coherent", 1}, + {}, +}; + +struct alloc_info general_allocation_funcs[] = { + {"malloc", 0}, + {"calloc", 0, 1}, + {"memdup", 1}, + {"realloc", 1}, + {}, +}; + +static int fresh_callback(void *fresh, int argc, char **argv, char **azColName) +{ + *(int *)fresh = 1; + return 0; +} + +static int fresh_from_db(struct expression *call) +{ + int fresh = 0; + + /* for function pointers assume everything is used */ + if (call->fn->type != EXPR_SYMBOL) + return 0; + + run_sql(&fresh_callback, &fresh, + "select * from return_states where %s and type = %d and parameter = -1 and key = '$' limit 1;", + get_static_filter(call->fn->symbol), FRESH_ALLOC); + return fresh; +} + +bool is_fresh_alloc_var_sym(const char *var, struct symbol *sym) +{ + return get_state(my_id, var, sym) == &fresh; +} + +bool is_fresh_alloc(struct expression *expr) +{ + sval_t sval; + int i; + + if (!expr) + return false; + + if (get_implied_value_fast(expr, &sval) && sval.value == 0) + return false; + + if (get_state_expr(my_id, expr) == &fresh) + return true; + + if (expr->type != EXPR_CALL) + return false; + if (fresh_from_db(expr)) + return true; + i = -1; + while (alloc_funcs[++i].fn) { + if (sym_name_is(kernel_allocation_funcs[i].fn, expr->fn)) + return true; + } + return false; +} + +static void record_alloc_func(int return_id, char *return_ranges, struct expression *expr) +{ + if (!is_fresh_alloc(expr)) + return; + sql_insert_return_states(return_id, return_ranges, FRESH_ALLOC, -1, "$", ""); +} + +static void set_unfresh(struct expression *expr) +{ + struct sm_state *sm; + + sm = get_sm_state_expr(my_id, expr); + if (!sm) + return; + if (!slist_has_state(sm->possible, &fresh)) + return; + // TODO call unfresh hooks + set_state_expr(my_id, expr, &undefined); +} + +static void match_assign(struct expression *expr) +{ + set_unfresh(expr->right); +} + +static void match_call(struct expression *expr) +{ + struct expression *arg; + + FOR_EACH_PTR(expr->args, arg) { + set_unfresh(arg); + } END_FOR_EACH_PTR(arg); +} + +static void set_fresh(struct expression *expr) +{ + expr = strip_expr(expr); + if (expr->type != EXPR_SYMBOL) + return; + set_state_expr(my_id, expr, &fresh); +} + +static void returns_fresh_alloc(struct expression *expr, int param, char *key, char *value) +{ + if (param != -1 || !key || strcmp(key, "$") != 0) + return; + if (expr->type != EXPR_ASSIGNMENT) + return; + + set_fresh(expr->left); +} + +static void match_alloc(const char *fn, struct expression *expr, void *_size_arg) +{ + set_fresh(expr->left); +} + +void register_fresh_alloc(int id) +{ + int i; + + my_id = id; + + if (option_project == PROJ_KERNEL) + alloc_funcs = kernel_allocation_funcs; + else + alloc_funcs = general_allocation_funcs; + + i = -1; + while (alloc_funcs[++i].fn) + add_function_assign_hook(alloc_funcs[i].fn, &match_alloc, 0); + + add_split_return_callback(&record_alloc_func); + select_return_states_hook(FRESH_ALLOC, &returns_fresh_alloc); + add_hook(&match_assign, ASSIGNMENT_HOOK); + add_hook(&match_call, FUNCTION_CALL_HOOK); +} diff --git a/usr/src/tools/smatch/src/smatch_math.c b/usr/src/tools/smatch/src/smatch_math.c index 68ca445619..e6e033172f 100644 --- a/usr/src/tools/smatch/src/smatch_math.c +++ b/usr/src/tools/smatch/src/smatch_math.c @@ -1606,6 +1606,26 @@ int get_implied_value(struct expression *expr, sval_t *sval) return 1; } +int get_implied_value_fast(struct expression *expr, sval_t *sval) +{ + struct range_list *rl; + static int recurse; + int ret = 0; + + if (recurse) + return 0; + + recurse = 1; + set_fast_math_only(); + if (get_rl_helper(expr, RL_IMPLIED, &rl) && + rl_to_sval(rl, sval)) + ret = 1; + clear_fast_math_only(); + recurse = 0; + + return ret; +} + int get_implied_min(struct expression *expr, sval_t *sval) { struct range_list *rl; diff --git a/usr/src/tools/smatch/src/smatch_mtag.c b/usr/src/tools/smatch/src/smatch_mtag.c index 37d1f18579..607ede688b 100644 --- a/usr/src/tools/smatch/src/smatch_mtag.c +++ b/usr/src/tools/smatch/src/smatch_mtag.c @@ -50,7 +50,7 @@ static int my_id; -static mtag_t str_to_tag(const char *str) +mtag_t str_to_mtag(const char *str) { unsigned char c[MD5_DIGEST_LENGTH]; unsigned long long *tag = (unsigned long long *)&c; @@ -132,7 +132,7 @@ struct smatch_state *swap_mtag_return(struct expression *expr, struct smatch_sta snprintf(buf, sizeof(buf), "%s %s %s %s", get_filename(), get_function(), left_name, right_name); - tag = str_to_tag(buf); + tag = str_to_mtag(buf); tag_sval.type = estate_type(state); tag_sval.uvalue = tag; @@ -156,8 +156,8 @@ int get_string_mtag(struct expression *expr, mtag_t *tag) return 0; /* I was worried about collisions so I added a xor */ - xor = str_to_tag("__smatch string"); - *tag = str_to_tag(expr->string->data); + xor = str_to_mtag("__smatch string"); + *tag = str_to_mtag(expr->string->data); *tag = *tag ^ xor; return 1; @@ -177,7 +177,7 @@ int get_toplevel_mtag(struct symbol *sym, mtag_t *tag) snprintf(buf, sizeof(buf), "%s %s", (sym->ctype.modifiers & MOD_STATIC) ? get_filename() : "extern", sym->ident->name); - *tag = str_to_tag(buf); + *tag = str_to_mtag(buf); return 1; } @@ -196,7 +196,7 @@ bool get_symbol_mtag(struct symbol *sym, mtag_t *tag) snprintf(buf, sizeof(buf), "%s %s %s", get_filename(), get_function(), sym->ident->name); - *tag = str_to_tag(buf); + *tag = str_to_mtag(buf); return true; } @@ -258,7 +258,7 @@ struct range_list *swap_mtag_seed(struct expression *expr, struct range_list *rl name = expr_to_str(expr); snprintf(buf, sizeof(buf), "%s %s %s", get_filename(), get_function(), name); free_string(name); - tag = str_to_tag(buf); + tag = str_to_mtag(buf); sval.value = tag; return alloc_rl(sval, sval); } @@ -284,7 +284,7 @@ int create_mtag_alias(mtag_t tag, struct expression *expr, mtag_t *new) snprintf(buf, sizeof(buf), "%lld %d %s", tag, lines_from_start, str); free_string(str); - *new = str_to_tag(buf); + *new = str_to_mtag(buf); sql_insert_mtag_alias(tag, *new); return 1; diff --git a/usr/src/tools/smatch/src/smatch_slist.c b/usr/src/tools/smatch/src/smatch_slist.c index 5c20dd739c..c95133f282 100644 --- a/usr/src/tools/smatch/src/smatch_slist.c +++ b/usr/src/tools/smatch/src/smatch_slist.c @@ -78,11 +78,13 @@ void __print_stree(struct stree *stree) { struct sm_state *sm; - printf("dumping stree at %d [%ld states]\n", get_lineno(), stree_count(stree)); + option_debug++; + sm_msg("dumping stree [%ld states]", stree_count(stree)); FOR_EACH_SM(stree, sm) { - printf("%s\n", show_sm(sm)); + sm_printf("%s\n", show_sm(sm)); } END_FOR_EACH_SM(sm); - printf("---\n"); + sm_printf("---\n"); + option_debug--; } /* NULL states go at the end to simplify merge_slist */ diff --git a/usr/src/tools/smatch/src/smatch_type.c b/usr/src/tools/smatch/src/smatch_type.c index 7e2e29ade5..be54ced235 100644 --- a/usr/src/tools/smatch/src/smatch_type.c +++ b/usr/src/tools/smatch/src/smatch_type.c @@ -789,7 +789,7 @@ static int type_str_helper(char *buf, int size, struct symbol *type) int n; if (!type) - return snprintf(buf, size, ""); + return snprintf(buf, size, ""); if (type->type == SYM_BASETYPE) { return snprintf(buf, size, "%s", base_type_str(type)); diff --git a/usr/src/tools/smatch/src/validation/sm_locking2.c b/usr/src/tools/smatch/src/validation/sm_locking2.c index 37ce24869d..23294b07a1 100644 --- a/usr/src/tools/smatch/src/validation/sm_locking2.c +++ b/usr/src/tools/smatch/src/validation/sm_locking2.c @@ -30,10 +30,9 @@ int func (void) * check-command: smatch --project=kernel sm_locking2.c * * check-output-start -sm_locking2.c:21 func() error: double unlock 'spin_lock:mylock' -sm_locking2.c:26 func() warn: inconsistent returns 'spin_lock:mylock3'. - Locked on: line 26 - Unlocked on: line 14 - line 25 +sm_locking2.c:21 func() error: double unlocked 'mylock' (orig line 17) +sm_locking2.c:26 func() warn: inconsistent returns 'mylock3'. + Locked on : 26 + Unlocked on: 25 * check-output-end */ diff --git a/usr/src/tools/smatch/src/validation/sm_locking3.c b/usr/src/tools/smatch/src/validation/sm_locking3.c index c63ec5cab2..d69f005214 100644 --- a/usr/src/tools/smatch/src/validation/sm_locking3.c +++ b/usr/src/tools/smatch/src/validation/sm_locking3.c @@ -24,10 +24,9 @@ int func (void) * check-command: smatch --project=kernel sm_locking3.c * * check-output-start -sm_locking3.c:18 func() error: double unlock 'spin_lock:mylock' -sm_locking3.c:20 func() warn: inconsistent returns 'spin_lock:mylock'. - Locked on: line 16 - Unlocked on: line 10 - line 20 +sm_locking3.c:18 func() error: double unlocked 'mylock' (orig line 15) +sm_locking3.c:20 func() warn: inconsistent returns 'mylock'. + Locked on : 16 + Unlocked on: 10,20 * check-output-end */ diff --git a/usr/src/tools/smatch/src/validation/sm_locking4.c b/usr/src/tools/smatch/src/validation/sm_locking4.c index 301fac7086..6c44a269ad 100644 --- a/usr/src/tools/smatch/src/validation/sm_locking4.c +++ b/usr/src/tools/smatch/src/validation/sm_locking4.c @@ -28,9 +28,8 @@ void func (void) * check-command: smatch --project=kernel sm_locking4.c * * check-output-start -sm_locking4.c:23 func() warn: inconsistent returns 'spin_lock:mylock'. - Locked on: line 22 - line 23 - Unlocked on: line 16 +sm_locking4.c:23 func() warn: inconsistent returns 'mylock'. + Locked on : 22-23 + Unlocked on: 16 * check-output-end */ diff --git a/usr/src/tools/smatch/src/validation/sm_locking6.c b/usr/src/tools/smatch/src/validation/sm_locking6.c index 9366c2c11f..b59fb1321a 100644 --- a/usr/src/tools/smatch/src/validation/sm_locking6.c +++ b/usr/src/tools/smatch/src/validation/sm_locking6.c @@ -31,15 +31,11 @@ void func (void) * check-command: smatch -p=kernel sm_locking6.c * * check-output-start -sm_locking6.c:27 func() warn: inconsistent returns 'irqsave:flags'. - Locked on: line 26 - Unlocked on: line 21 - line 24 - line 27 -sm_locking6.c:27 func() warn: inconsistent returns 'spin_lock:lock'. - Locked on: line 26 - Unlocked on: line 21 - line 24 - line 27 +sm_locking6.c:27 func() warn: inconsistent returns 'flags'. + Locked on : 26 + Unlocked on: 21,24,27 +sm_locking6.c:27 func() warn: inconsistent returns 'lock'. + Locked on : 26 + Unlocked on: 21,24,27 * check-output-end */ diff --git a/usr/src/tools/smatch/src/validation/sm_locking7.c b/usr/src/tools/smatch/src/validation/sm_locking7.c index f2177ff3e0..ca96bb6867 100644 --- a/usr/src/tools/smatch/src/validation/sm_locking7.c +++ b/usr/src/tools/smatch/src/validation/sm_locking7.c @@ -27,11 +27,11 @@ void func(int *y) * check-command: smatch -p=kernel -I.. sm_locking7.c * * check-output-start -sm_locking7.c:22 func() warn: inconsistent returns 'irqsave:flags'. - Locked on: line 21 - Unlocked on: line 22 -sm_locking7.c:22 func() warn: inconsistent returns 'spin_lock:&lock'. - Locked on: line 21 - Unlocked on: line 22 +sm_locking7.c:22 func() warn: inconsistent returns 'flags'. + Locked on : 21 + Unlocked on: 22 +sm_locking7.c:22 func() warn: inconsistent returns 'lock'. + Locked on : 21 + Unlocked on: 22 * check-output-end */ -- cgit v1.2.3 From 9a63ec2733c93e3ee31e95779a4f2f45a57eda59 Mon Sep 17 00:00:00 2001 From: Robert Mustacchi Date: Wed, 18 Dec 2019 06:18:35 +0000 Subject: 12183 Want new IPD 13 DMA Cookie APIs Reviewed by: Alex Wilson Reviewed by: Paul Winder Reviewed by: Hans Rosenfeld Reviewed by: Garrett D'Amore Approved by: Garrett D'Amore --- usr/src/man/man9f/Intro.9f | 4 + usr/src/man/man9f/Makefile | 11 +- usr/src/man/man9f/ddi_dma_addr_bind_handle.9f | 36 +-- usr/src/man/man9f/ddi_dma_buf_bind_handle.9f | 34 +-- usr/src/man/man9f/ddi_dma_cookie_iter.9f | 282 ++++++++++++++++++++++++ usr/src/man/man9f/ddi_dma_getwin.9f | 32 +-- usr/src/man/man9f/ddi_dma_nextcookie.9f | 104 --------- usr/src/man/man9f/ddi_dmae.9f | 21 +- usr/src/pkg/manifests/system-kernel.man9f.inc | 6 +- usr/src/uts/common/io/scsi/impl/scsi_resource.c | 1 + usr/src/uts/common/os/sunddi.c | 98 ++++++++ usr/src/uts/common/sys/ddi_impldefs.h | 4 + usr/src/uts/common/sys/sunddi.h | 14 ++ usr/src/uts/i86pc/io/rootnex.c | 13 ++ usr/src/uts/sun4/io/px/px.c | 12 + usr/src/uts/sun4/io/px/px_dma.c | 6 +- usr/src/uts/sun4u/io/pci/pci.c | 12 + usr/src/uts/sun4u/io/pci/pci_dma.c | 6 +- usr/src/uts/sun4v/io/niumx/niumx.c | 5 + 19 files changed, 526 insertions(+), 175 deletions(-) create mode 100644 usr/src/man/man9f/ddi_dma_cookie_iter.9f delete mode 100644 usr/src/man/man9f/ddi_dma_nextcookie.9f diff --git a/usr/src/man/man9f/Intro.9f b/usr/src/man/man9f/Intro.9f index ba32b2978e..3b72a53425 100644 --- a/usr/src/man/man9f/Intro.9f +++ b/usr/src/man/man9f/Intro.9f @@ -356,10 +356,14 @@ _ \fBddi_dma_alloc_handle\fR illumos DDI \fBddi_dma_buf_bind_handle\fR illumos DDI \fBddi_dma_burstsizes\fR illumos DDI +\fBddi_dma_cookie_get\fR illumos DDI +\fBddi_dma_cookie_next\fR illumos DDI +\fBddi_dma_cookie_one\fR illumos DDI \fBddi_dma_free_handle\fR illumos DDI \fBddi_dma_getwin\fR illumos DDI \fBddi_dma_mem_alloc\fR illumos DDI \fBddi_dma_mem_free\fR illumos DDI +\fBddi_dma_ncookies\fR illumos DDI \fBddi_dma_nextcookie\fR illumos DDI \fBddi_dma_numwin\fR illumos DDI \fBddi_dma_set_sbus64\fR illumos DDI diff --git a/usr/src/man/man9f/Makefile b/usr/src/man/man9f/Makefile index 825dab0e0c..24d74a300e 100644 --- a/usr/src/man/man9f/Makefile +++ b/usr/src/man/man9f/Makefile @@ -154,11 +154,11 @@ MANFILES= ASSERT.9f \ ddi_dma_alloc_handle.9f \ ddi_dma_buf_bind_handle.9f \ ddi_dma_burstsizes.9f \ + ddi_dma_cookie_iter.9f \ ddi_dma_free_handle.9f \ ddi_dma_getwin.9f \ ddi_dma_mem_alloc.9f \ ddi_dma_mem_free.9f \ - ddi_dma_nextcookie.9f \ ddi_dma_numwin.9f \ ddi_dma_set_sbus64.9f \ ddi_dma_sync.9f \ @@ -748,6 +748,10 @@ MANLINKS= AVL_NEXT.9f \ ddi_devid_unregister.9f \ ddi_devid_valid.9f \ ddi_devmap_segmap.9f \ + ddi_dma_cookie_get.9f \ + ddi_dma_cookie_one.9f \ + ddi_dma_ncookies.9f \ + ddi_dma_nextcookie.9f \ ddi_dmae_1stparty.9f \ ddi_dmae_alloc.9f \ ddi_dmae_disable.9f \ @@ -1557,6 +1561,11 @@ ddi_devid_str_free.9f := LINKSRC = ddi_devid_compare.9f ddi_devid_unregister.9f := LINKSRC = ddi_devid_compare.9f ddi_devid_valid.9f := LINKSRC = ddi_devid_compare.9f +ddi_dma_cookie_get.9f := LINKSRC = ddi_dma_cookie_iter.9f +ddi_dma_cookie_one.9f := LINKSRC = ddi_dma_cookie_iter.9f +ddi_dma_ncookies.9f := LINKSRC = ddi_dma_cookie_iter.9f +ddi_dma_nextcookie.9f := LINKSRC = ddi_dma_cookie_iter.9f + ddi_dmae_1stparty.9f := LINKSRC = ddi_dmae.9f ddi_dmae_alloc.9f := LINKSRC = ddi_dmae.9f ddi_dmae_disable.9f := LINKSRC = ddi_dmae.9f diff --git a/usr/src/man/man9f/ddi_dma_addr_bind_handle.9f b/usr/src/man/man9f/ddi_dma_addr_bind_handle.9f index 71f9a00354..fa94c3cdf5 100644 --- a/usr/src/man/man9f/ddi_dma_addr_bind_handle.9f +++ b/usr/src/man/man9f/ddi_dma_addr_bind_handle.9f @@ -3,7 +3,7 @@ .\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License"). You may not use this file except in compliance with the License. .\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing. See the License for the specific language governing permissions and limitations under the License. .\" When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE. If applicable, add the following below this CDDL HEADER, with the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner] -.TH DDI_DMA_ADDR_BIND_HANDLE 9F "Jul 26, 1996" +.TH DDI_DMA_ADDR_BIND_HANDLE 9F "Jan 18, 2020" .SH NAME ddi_dma_addr_bind_handle \- binds an address to a DMA handle .SH SYNOPSIS @@ -20,11 +20,9 @@ ddi_dma_addr_bind_handle \- binds an address to a DMA handle .fi .SH INTERFACE LEVEL -.sp .LP Solaris DDI specific (Solaris DDI). .SH PARAMETERS -.sp .ne 2 .na \fB\fIhandle\fR \fR @@ -178,7 +176,8 @@ function is specified. \fB\fIcookiep\fR \fR .ad .RS 13n -A pointer to the first \fBddi_dma_cookie\fR(9S) structure. +A pointer to the first \fBddi_dma_cookie\fR(9S) structure. This should +be left as \fBNULL\fR in new callers. .RE .sp @@ -188,11 +187,12 @@ A pointer to the first \fBddi_dma_cookie\fR(9S) structure. .ad .RS 13n Upon a successful return, \fIccountp\fR points to a value representing the -number of cookies for this \fBDMA\fR object. +number of cookies for this \fBDMA\fR object. This can +be left as \fBNULL\fR in new callers. The cookie count can be obtained +by calling \fBddi_dma_ncookies\fR(9F). .RE .SH DESCRIPTION -.sp .LP \fBddi_dma_addr_bind_handle()\fR allocates \fBDMA\fR resources for a memory object such that a device can perform \fBDMA\fR to or from the object. @@ -200,12 +200,15 @@ object such that a device can perform \fBDMA\fR to or from the object. as expressed by \fBddi_dma_attr\fR(9S) (see \fBddi_dma_alloc_handle\fR(9F)). .sp .LP -\fBddi_dma_addr_bind_handle()\fR fills in the first \fBDMA\fR cookie pointed to -by \fIcookiep\fR with the appropriate address, length, and bus type. -\fB*\fR\fIccountp\fR is set to the number of \fBDMA\fR cookies representing -this \fBDMA\fR object. Subsequent \fBDMA\fR cookies must be retrieved by -calling \fBddi_dma_nextcookie\fR(9F) the number of times specified by -\fB*\fR\fIcountp\fR-1. +\fBddi_dma_addr_bind_handle()\fR allocates and associates a number of +\fBDMA\fR cookies with \fIhandle\fR. To get the total number of +cookies, callers should use the \fBddi_dma_ncookies\fR(9F) function. To +get all of the cookies, callers should use the +\fBddi_dma_cookie_iter\fR(9F) or \fBddi_dma_cookie_get\fR(9F) functions. +Callers should pass \fBNULL\fR for \fIcookiep\fR and \fIccountp\fR. +These values are required if using the deprecated +\fBddi_dma_nextcookie\fR(9F) interface, in which case \fIcookiep\fR is +filled in with the first \fBddi_dma_cookie\fR(9S) structure. .sp .LP When a \fBDMA\fR transfer completes, the driver frees up system \fBDMA\fR @@ -307,7 +310,6 @@ functions accessible from interrupt context are be available. The callback function must take whatever steps are necessary to protect its critical resources, data structures, queues, and so on. .SH RETURN VALUES -.sp .LP \fBddi_dma_addr_bind_handle()\fR returns: .sp @@ -369,24 +371,22 @@ configuration. .RE .SH CONTEXT -.sp .LP \fBddi_dma_addr_bind_handle()\fR can be called from user, kernel, or interrupt context, except when \fIcallback\fR is set to \fBDDI_DMA_SLEEP\fR, in which case it can only be called from user or kernel context. .SH SEE ALSO -.sp .LP -\fBddi_dma_alloc_handle\fR(9F), \fBddi_dma_free_handle\fR(9F), +\fBddi_dma_alloc_handle\fR(9F), \fBddi_dma_cookie_get\fR(9F), +\fBddi_dma_cookie_iter\fR(9F), \fBddi_dma_free_handle\fR(9F), \fBddi_dma_getwin\fR(9F), \fBddi_dma_mem_alloc\fR(9F), -\fBddi_dma_mem_free\fR(9F), \fBddi_dma_nextcookie\fR(9F), +\fBddi_dma_mem_free\fR(9F), \fBddi_dma_ncookies\fR(9F), \fBddi_dma_sync\fR(9F), \fBddi_dma_unbind_handle\fR(9F), \fBddi_umem_iosetup\fR(9F), \fBddi_dma_attr\fR(9S), \fBddi_dma_cookie\fR(9S) .sp .LP \fIWriting Device Drivers\fR .SH NOTES -.sp .LP If the driver permits partial mapping with the \fBDDI_DMA_PARTIAL\fR flag, the number of cookies in each window may exceed the size of the device's diff --git a/usr/src/man/man9f/ddi_dma_buf_bind_handle.9f b/usr/src/man/man9f/ddi_dma_buf_bind_handle.9f index 5b8265605e..e68135a8bd 100644 --- a/usr/src/man/man9f/ddi_dma_buf_bind_handle.9f +++ b/usr/src/man/man9f/ddi_dma_buf_bind_handle.9f @@ -3,7 +3,7 @@ .\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License"). You may not use this file except in compliance with the License. .\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing. See the License for the specific language governing permissions and limitations under the License. .\" When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE. If applicable, add the following below this CDDL HEADER, with the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner] -.TH DDI_DMA_BUF_BIND_HANDLE 9F "Jul 27, 1996" +.TH DDI_DMA_BUF_BIND_HANDLE 9F "Jan 18, 2020" .SH NAME ddi_dma_buf_bind_handle \- binds a system buffer to a DMA handle .SH SYNOPSIS @@ -20,11 +20,9 @@ ddi_dma_buf_bind_handle \- binds a system buffer to a DMA handle .fi .SH INTERFACE LEVEL -.sp .LP Solaris DDI specific (Solaris DDI). .SH PARAMETERS -.sp .ne 2 .na \fB\fIhandle\fR\fR @@ -159,7 +157,8 @@ function is specified. \fB\fIcookiep\fR\fR .ad .RS 12n -A pointer to the first \fBddi_dma_cookie\fR(9S) structure. +A pointer to the first \fBddi_dma_cookie\fR(9S) structure. This should +be left as \fBNULL\fR in new callers. .RE .sp @@ -169,11 +168,12 @@ A pointer to the first \fBddi_dma_cookie\fR(9S) structure. .ad .RS 12n Upon a successful return, \fIccountp\fR points to a value representing the -number of cookies for this \fBDMA\fR object. +number of cookies for this \fBDMA\fR object. This can +be left as \fBNULL\fR in new callers. The cookie count can be obtained +by calling \fBddi_dma_ncookies\fR(9F). .RE .SH DESCRIPTION -.sp .LP \fBddi_dma_buf_bind_handle()\fR allocates \fBDMA\fR resources for a system buffer such that a device can perform \fBDMA\fR to or from the buffer. @@ -181,11 +181,16 @@ buffer such that a device can perform \fBDMA\fR to or from the buffer. as expressed by \fBddi_dma_attr\fR(9S) (see \fBddi_dma_alloc_handle\fR(9F)). .sp .LP -\fBddi_dma_buf_bind_handle()\fR fills in the first \fBDMA\fR cookie pointed to -by \fIcookiep\fR with the appropriate address, length, and bus type. -\fB*\fR\fIccountp\fR is set to the number of \fBDMA\fR cookies representing -this \fBDMA\fR object. Subsequent \fBDMA\fR cookies must be retrieved by -calling \fBddi_dma_nextcookie\fR(9F) \fB*\fR\fIcountp\fR-1 times. +\fBddi_dma_buf_bind_handle()\fR allocates and associates a number of +\fBDMA\fR cookies with \fIhandle\fR. To get the total number of +cookies, callers should use the \fBddi_dma_ncookies\fR(9F) function. To +get all of the cookies, callers should use the +\fBddi_dma_cookie_iter\fR(9F) or \fBddi_dma_cookie_get\fR(9F) functions. +Callers should pass \fBNULL\fR for \fIcookiep\fR and \fIccountp\fR. +These values are required if using the deprecated +\fBddi_dma_nextcookie\fR(9F) interface, in which case \fIcookiep\fR is +filled in with the first \fBddi_dma_cookie\fR(9S) structure. + .sp .LP When a \fBDMA\fR transfer completes, the driver should free up system \fBDMA\fR @@ -287,7 +292,6 @@ functions accessible from interrupt context are be available. The callback function must take whatever steps necessary to protect its critical resources, data structures, queues, etc. .SH RETURN VALUES -.sp .LP \fBddi_dma_buf_bind_handle()\fR returns: .sp @@ -349,24 +353,22 @@ configuration. .RE .SH CONTEXT -.sp .LP \fBddi_dma_buf_bind_handle()\fR can be called from user, kernel, or interrupt context, except when \fIcallback\fR is set to \fBDDI_DMA_SLEEP\fR, in which case it can be called from user or kernel context only. .SH SEE ALSO -.sp .LP \fBddi_dma_addr_bind_handle\fR(9F), \fBddi_dma_alloc_handle\fR(9F), +\fBddi_dma_cookie_get\fR(9F), \fBddi_dma_cookie_iter\fR(9F), \fBddi_dma_free_handle\fR(9F), \fBddi_dma_getwin\fR(9F), -\fBddi_dma_nextcookie\fR(9F), \fBddi_dma_sync\fR(9F), +\fBddi_dma_ncookies\fR(9F), \fBddi_dma_sync\fR(9F), \fBddi_dma_unbind_handle\fR(9F), \fBbuf\fR(9S), \fBddi_dma_attr\fR(9S), \fBddi_dma_cookie\fR(9S) .sp .LP \fIWriting Device Drivers\fR .SH NOTES -.sp .LP If the driver permits partial mapping with the \fBDDI_DMA_PARTIAL\fR flag, the number of cookies in each window may exceed the size of the device's diff --git a/usr/src/man/man9f/ddi_dma_cookie_iter.9f b/usr/src/man/man9f/ddi_dma_cookie_iter.9f new file mode 100644 index 0000000000..5f10d4fcf2 --- /dev/null +++ b/usr/src/man/man9f/ddi_dma_cookie_iter.9f @@ -0,0 +1,282 @@ +.\" +.\" This file and its contents are supplied under the terms of the +.\" Common Development and Distribution License ("CDDL"), version 1.0. +.\" You may only use this file in accordance with the terms of version +.\" 1.0 of the CDDL. +.\" +.\" A full copy of the text of the CDDL should have accompanied this +.\" source. A copy of the CDDL is also available via the Internet at +.\" http://www.illumos.org/license/CDDL. +.\" +.\" +.\" Copyright 2019 Robert Mustacchi +.\" +.Dd December 9, 2019 +.Dt DDI_DMA_COOKIE_ITER 9F +.Os +.Sh NAME +.Nm ddi_dma_cookie_get , +.Nm ddi_dma_cookie_iter , +.Nm ddi_dma_cookie_one , +.Nm ddi_dma_ncookies , +.Nm ddi_dma_nextcookie +.Nd retrieve DMA cookies +.Sh SYNOPSIS +.In sys/ddi.h +.In sys/sunddi.h +.Ft "const ddi_dma_cookie_t *" +.Fo ddi_dma_cookie_iter +.Fa "ddi_dma_handle_t handle" +.Fa "const ddi_dma_cookie_t *cookiep" +.Fc +.Ft "const ddi_dma_cookie_t *" +.Fo ddi_dma_cookie_get +.Fa "ddi_dma_handle_t handle" +.Fa "uint_t index" +.Fc +.Ft "const ddi_dma_cookie_t *" +.Fo ddi_dma_cookie_one +.Fa "ddi_dma_handle_t handle" +.Fc +.Ft "uint_t" +.Fo ddi_dma_ncookies +.Fa "ddi_dma_handle_t handle" +.Fc +.Ft void +.Fo ddi_dma_nextcookie +.Fa "ddi_dma_handle_t handle" +.Fa "ddi_dma_cookie_t *cookiep" +.Fc +.Sh PARAMETERS +.Bl -tag -width Fa +.It Fa handle +The DMA handle obtained by a call to +.Xr ddi_dma_alloc_handle 9F . +.It Fa cookie +A pointer to a +.Xr ddi_dma_cookie 9S +structure. +.It Fa index +An unsigned integer that represents the index of a cookie to obtain. +The first entry is at index zero. +.El +.Sh DESCRIPTION +The +.Fn ddi_dma_cookie_iter , +.Fn ddi_dma_cookie_get , +and +.Fn ddi_dma_cookie_one +functions obtain information about DMA cookies. +When a DMA request, represented by the DMA handle +.Fa handle , +has been bound to a series of addresses with the +.Xr ddi_dma_addr_bind_handle 9F +or +.Xr ddi_dma_buf_bind_handle 9F +functions, the resulting addresses are stored in one or more +.Xr ddi_dma_cookie 9S +structures. +the three different functions provide different ways to obtain cookies +and are safe alternatives to the unsafe +.Fn ddi_dma_nextcookie +function. +To see how to use these functions, please see the +.Sx EXAMPLES +section. +.Pp +The +.Fn ddi_dma_cookie_iter +function provides a way to iterate over all the cookies that are +associated with the DMA handle +.Fa handle . +To get the first handle, pass +.Dv NULL +in +.Fa cookiep . +Do not use the DMA cookie returned from either of the +.Xr ddi_dma_addr_bind_handle 9F +or +.Xr ddi_dma_buf_bind_handle 9F +functions. +To get subsequent cookies, pass the returned cookie as the argument +.Fa cookiep . +When the function returns +.Dv NULL +then that indicates that the last handle has been iterated over. +.Pp +The +.Fn ddi_dma_cookie_get +function returns a specific cookie. +The +.Fa index +indicates which of the cookies should be returned. +The first cookie is at index +.Sy 0 . +If an invalid index is specified, the function returns +.Dv NULL . +.Pp +The +.Ft ddi_dma_cookie_one +function is a convenience function for DMA requests that have a single +cookie. +This function always returns the single cookie assosciated with the DMA +handle +.Fa handle . +If this function is used when there is a DMA request with multiple +cookies, then it will panic the system. +It can never return +.Dv NULL . +.Pp +The +.Fn ddi_dma_ncookies +function returns the number of DMA cookies that are associated with the +DMA handle +.Fa handle . +If there are no DMA resources bound to the handle, then this will return +.Sy 0 . +.Pp +The +.Fn ddi_dma_nextcookie +function was the historical function that was associated with obtaining +DMA cookies. +It should not be used due to several flaws. +The +.Fn ddi_dma_nextcookie +function mutates the underlying DMA handle meaning that a driver cannot +obtain a cookie a second time and thus a device driver using this +interface must either manually keep storage of the cookie around wasting +space or rebind the handle, wasting time. +In addition, there is no way for the function to indicate that a driver +has consumed all of its cookies. +If for some reason a device driver calls the +.Fn ddi_dma_nextcookie +function more times than there are cookies, the results are undefined. +In short, this function should not be used for any purpose. +Use the +.Fn ddi_dma_cookie_iter , +.Fn ddi_dma_cookie_get , +or +.Fn ddi_dma_cookie_one +functions instead. +.Sh CONTEXT +The +.Fn ddi_dma_cookie_iter , +.Fn ddi_dma_cookie_get , +.Fn ddi_dma_cookie_one , +.Fn ddi_dma_ncookies , +and +.Fn ddi_dma_nextcookie +functions may be called from +.Sy user , +.Sy kernel , +or +.Sy interrupt +context. +.Sh RETURN VALUES +Upon successful completion, the +.Fn ddi_dma_cookie_iter , +.Fn ddi_dma_cookie_get , +.Fn ddi_dma_cookie_one +functions will return the requested DMA cookie. +If there are no more cookies, or +.Fa coookiep +is invalid, the +.Fn ddi_dma_cookie_iter +function will return +.Dv NULL . +If +.Fa index +does not correspond to a valid cookie, the +.Fn ddi_dma_cookie_get +function will return +.Dv NULL . +If there is not exactly one DMA cookie, or another issue occurs, then the +.Fn ddi_dma_cookie_one +function will panic the system. +.Pp +Upon successful completion, the +.Fn ddi_dma_ncookies +function returns the number of cookies associated with +.Fa handle . +If there are none, then +.Sy 0 +is returned. +.Pp +The +.Fn ddi_dma_nextcookie +function always updates +.Fa cookiep +regardless of whether it is valid or not. +.Sh EXAMPLES +.Sy Example 1 +Using the +.Fn ddi_dma_cookie_iter +function to obtain all DMA cookies. +.Bd -literal +/* + * This example assumes that either ddi_dma_addr_bind_handle() or + * ddi_dma_buf_bind_handle() has already been successfully called. + */ +void +program_dma(ddi_dma_handle_t handle) +{ + const ddi_dma_cookie_t *c; + + for (cookie = ddi_dma_cookie_iter(handle, NULL); c != NULL; + c = ddi_dma_cookie_iter(handle, c)) { + /* + * Use the dmac_laddress and dmac_size members to + * properly program the device or descriptor rings. + */ + } +} +.Ed +.Pp +.Sy Example 2 +Using the +.Fn ddi_dma_cookie_get +function. +.Bd -literal +/* + * This example assumes that either ddi_dma_mem_alloc() has already + * been successfully called. + */ +int +bind_dma(ddi_dma_handle_t handle, void *addr, size_t len) +{ + int ret; + uint_t i, ncookies; + ddi_dma_cookie_t first; + + ret = ddi_dma_addr_bind_handle(handle, NULL, addr, len, + DDI_DMA_RDWR | DDI_DMA_CONSISTENT, NULL, NULL, &first, + &ncookies); + if (ret != DDI_DMA_MAPPED) { + return (ret); + } + + /* + * A driver doesn't need to store ncookies. It can get it again + * by simply calling ddi_dma_ncookies() and using the result in + * place of ncookies from ddi_dma_addr_bind_handle(). + */ + for (i = 0; i < ncookies; i++) { + const ddi_dma_cookie_t *cookie; + + cookie = ddi_dma_coookie_get(handle, i); + /* + * Use the dmac_laddress and dmac_size members to + * properly program the device or descriptor rings. + */ + } +} +.Ed +.Sh SEE ALSO +.Xr ddi_dma_addr_bind_handle 9F , +.Xr ddi_dma_alloc_handle 9F , +.Xr ddi_dma_buf_bind_handle 9F , +.Xr ddi_dma_unbind_handle 9F , +.Xr ddi_dma_cookie 9S +.Rs +.%T Writing Device Drivers +.Re diff --git a/usr/src/man/man9f/ddi_dma_getwin.9f b/usr/src/man/man9f/ddi_dma_getwin.9f index b092ae66e9..aee028587d 100644 --- a/usr/src/man/man9f/ddi_dma_getwin.9f +++ b/usr/src/man/man9f/ddi_dma_getwin.9f @@ -3,7 +3,7 @@ .\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License"). You may not use this file except in compliance with the License. .\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing. See the License for the specific language governing permissions and limitations under the License. .\" When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE. If applicable, add the following below this CDDL HEADER, with the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner] -.TH DDI_DMA_GETWIN 9F "Nov 15, 1996" +.TH DDI_DMA_GETWIN 9F "Jan 18, 2020" .SH NAME ddi_dma_getwin \- activate a new DMA window .SH SYNOPSIS @@ -20,11 +20,9 @@ ddi_dma_getwin \- activate a new DMA window .fi .SH INTERFACE LEVEL -.sp .LP Solaris DDI specific (Solaris DDI). .SH PARAMETERS -.sp .ne 2 .na \fB\fIhandle\fR \fR @@ -69,7 +67,8 @@ current window. \fB\fIcookiep\fR \fR .ad .RS 12n -A pointer to the first \fBddi_dma_cookie\fR(9S) structure. +A pointer to the first \fBddi_dma_cookie\fR(9S) structure. This should +be left as \fBNULL\fR in new callers. .RE .sp @@ -79,11 +78,12 @@ A pointer to the first \fBddi_dma_cookie\fR(9S) structure. .ad .RS 12n Upon a successful return, \fIccountp\fR will contain the number of cookies for -this \fBDMA\fR window. +this \fBDMA\fR window. This can +be left as \fBNULL\fR in new callers. The cookie count can be obtained +by calling \fBddi_dma_ncookies\fR(9F). .RE .SH DESCRIPTION -.sp .LP \fBddi_dma_getwin()\fR activates a new \fBDMA\fR window. If a \fBDMA\fR resource allocation request returns \fBDDI_DMA_PARTIAL_MAP\fR indicating that @@ -97,11 +97,15 @@ window number from the range \fI[0..N-1]\fR as the parameter \fIwin\fR and makes it the current \fBDMA\fR window. .sp .LP -\fBddi_dma_getwin()\fR fills in the first \fBDMA\fR cookie pointed to by -\fIcookiep\fR with the appropriate address, length, and bus type. -\fB*\fR\fIccountp\fR is set to the number of \fBDMA\fR cookies representing -this \fBDMA \fRobject. Subsequent \fBDMA\fR cookies must be retrieved using -\fBddi_dma_nextcookie\fR(9F). +\fBddi_dma_getwin()\fR allocates and assosciates a number of +\fBDMA\fR cookies with \fIhandle\fR. To get the total number of +cookies, callers should use the \fBddi_dma_ncookies\fR(9F) function. To +get all of the cookies, callers should use the +\fBddi_dma_cookie_iter\fR(9F) or \fBddi_dma_cookie_get\fR(9F) functions. +Callers should pass \fBNULL\fR for \fIcookiep\fR and \fIccountp\fR. +These values are required if using the deprecated +\fBddi_dma_nextcookie\fR(9F) interface, in which case \fIcookiep\fR is +filled in with the first \fBddi_dma_cookie\fR(9S) structure. .sp .LP \fBddi_dma_getwin()\fR takes care of underlying resource synchronizations @@ -118,7 +122,6 @@ the interrupt routine returns without invoking another \fBDMA\fR transfer. Otherwise, it calls \fBddi_dma_getwin()\fR to shift the current window and start another \fBDMA\fR transfer. .SH RETURN VALUES -.sp .LP \fBddi_dma_getwin()\fR returns: .sp @@ -140,14 +143,13 @@ Resources for the specified \fBDMA\fR window are allocated. .RE .SH CONTEXT -.sp .LP \fBddi_dma_getwin()\fR can be called from user, kernel, or interrupt context. .SH SEE ALSO -.sp .LP \fBddi_dma_addr_bind_handle\fR(9F), \fBddi_dma_alloc_handle\fR(9F), -\fBddi_dma_buf_bind_handle\fR(9F), \fBddi_dma_nextcookie\fR(9F), +\fBddi_dma_buf_bind_handle\fR(9F), \fBddi_dma_cookie_get\fR(9F), +\fBddi_dma_cookie_iter\fR(9F), \fBddi_dma_ncookies\fR(9F), \fBddi_dma_numwin\fR(9F), \fBddi_dma_sync\fR(9F), \fBddi_dma_unbind_handle\fR(9F), \fBddi_dma_cookie\fR(9S) .sp diff --git a/usr/src/man/man9f/ddi_dma_nextcookie.9f b/usr/src/man/man9f/ddi_dma_nextcookie.9f deleted file mode 100644 index 527e2b8361..0000000000 --- a/usr/src/man/man9f/ddi_dma_nextcookie.9f +++ /dev/null @@ -1,104 +0,0 @@ -'\" te -.\" Copyright (c) 1994, Sun Microsystems, Inc. -.\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License"). You may not use this file except in compliance with the License. -.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing. See the License for the specific language governing permissions and limitations under the License. -.\" When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE. If applicable, add the following below this CDDL HEADER, with the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner] -.TH DDI_DMA_NEXTCOOKIE 9F "Sep 26, 1994" -.SH NAME -ddi_dma_nextcookie \- retrieve subsequent DMA cookie -.SH SYNOPSIS -.LP -.nf -#include -#include - - - -\fBvoid\fR \fBddi_dma_nextcookie\fR(\fBddi_dma_handle_t\fR \fIhandle\fR, - \fBddi_dma_cookie_t *\fR\fIcookiep\fR); -.fi - -.SH PARAMETERS -.sp -.ne 2 -.na -\fB\fIhandle\fR\fR -.ad -.RS 11n -The handle previously allocated by a call to \fBddi_dma_alloc_handle\fR(9F). -.RE - -.sp -.ne 2 -.na -\fB\fIcookiep\fR\fR -.ad -.RS 11n -A pointer to a \fBddi_dma_cookie\fR(9S) structure. -.RE - -.SH INTERFACE LEVEL -.sp -.LP -Solaris DDI specific (Solaris DDI). -.SH DESCRIPTION -.sp -.LP -\fBddi_dma_nextcookie()\fR retrieves subsequent \fBDMA\fR cookies for a -\fBDMA\fR object. \fBddi_dma_nextcookie()\fR fills in the -\fBddi_dma_cookie\fR(9S) structure pointed to by \fIcookiep\fR. The -\fBddi_dma_cookie\fR(9S) structure must be allocated prior to calling -\fBddi_dma_nextcookie()\fR. -.sp -.LP -The \fBDMA\fR cookie count returned by \fBddi_dma_buf_bind_handle\fR(9F), -\fBddi_dma_addr_bind_handle\fR(9F), or \fBddi_dma_getwin\fR(9F) indicates the -number of \fBDMA\fR cookies a \fBDMA\fR object consists of. If the resulting -cookie count, \fIN\fR, is larger than 1, \fBddi_dma_nextcookie()\fR must be -called \fIN\fR-1 times to retrieve all \fBDMA\fR cookies. -.SH CONTEXT -.sp -.LP -\fBddi_dma_nextcookie()\fR can be called from user, kernel, or interrupt -context. -.SH EXAMPLES -.LP -\fBExample 1 \fRProcess a scatter-gather list of I/O requests. -.sp -.LP -This example demonstrates the use of \fBddi_dma_nextcookie()\fR to process a -scatter-gather list of I/O requests. - -.sp -.in +2 -.nf -/* setup scatter-gather list with multiple DMA cookies */ -ddi_dma_cookie_t dmacookie; -uint_t ccount; -\&... - -status = ddi_dma_buf_bind_handle(handle, bp, DDI_DMA_READ, - NULL, NULL, &dmacookie, &ccount); - -if (status == DDI_DMA_MAPPED) { - - /* program DMA engine with first cookie */ - - while (--ccount > 0) { - ddi_dma_nextcookie(handle, &dmacookie); - /* program DMA engine with next cookie */ - } -} -\&... -.fi -.in -2 - -.SH SEE ALSO -.sp -.LP -\fBddi_dma_addr_bind_handle\fR(9F), \fBddi_dma_alloc_handle\fR(9F), -\fBddi_dma_buf_bind_handle\fR(9F), \fBddi_dma_unbind_handle\fR(9F), -\fBddi_dma_cookie\fR(9S) -.sp -.LP -\fIWriting Device Drivers\fR diff --git a/usr/src/man/man9f/ddi_dmae.9f b/usr/src/man/man9f/ddi_dmae.9f index 27f045114c..8bb2d955bd 100644 --- a/usr/src/man/man9f/ddi_dmae.9f +++ b/usr/src/man/man9f/ddi_dmae.9f @@ -4,7 +4,7 @@ .\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License"). You may not use this file except in compliance with the License. .\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing. See the License for the specific language governing permissions and limitations under the License. .\" When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE. If applicable, add the following below this CDDL HEADER, with the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner] -.TH DDI_DMAE 9F "May 24, 2014" +.TH DDI_DMAE 9F "Jan 18, 2020" .SH NAME ddi_dmae, ddi_dmae_alloc, ddi_dmae_release, ddi_dmae_prog, ddi_dmae_disable, ddi_dmae_enable, ddi_dmae_stop, ddi_dmae_getcnt, ddi_dmae_1stparty, @@ -58,11 +58,9 @@ ddi_dmae_getattr \- system DMA engine functions .fi .SH INTERFACE LEVEL -.sp .LP Solaris DDI specific (Solaris DDI). .SH PARAMETERS -.sp .ne 2 .na \fB\fIdip\fR\fR @@ -157,7 +155,6 @@ A pointer to a \fBDMA \fR attribute structure. See \fBddi_dma_attr\fR(9S). .RE .SH DESCRIPTION -.sp .LP There are three possible ways that a device can perform \fBDMA\fR engine functions: @@ -201,7 +198,6 @@ configuration is necessary to enable this mode. .RE .SS "\fBddi_dmae_alloc()\fR" -.sp .LP The \fBddi_dmae_alloc()\fR function is used to acquire a \fBDMA\fR channel of the system \fBDMA\fR engine. \fBddi_dmae_alloc()\fR allows only one device at a @@ -228,7 +224,6 @@ the value \fBDDI_DMA_CALLBACK_DONE\fR. If it tries to allocate the channel but fails to do so, it must return the value \fBDDI_DMA_CALLBACK_RUNOUT\fR. In this case, the callback function is put back on a list to be called again later. .SS "\fBddi_dmae_prog()\fR" -.sp .LP The \fBddi_dmae_prog()\fR function programs the \fBDMA\fR channel for a \fBDMA\fR transfer. The \fBddi_dmae_req\fR structure contains all the @@ -250,30 +245,25 @@ resources using \fBDMA\fR setup functions such as \fBddi_dma_mem_alloc\fR(9F). contains the address and count. Then this cookie is passed to \fBddi_dmae_prog()\fR. .SS "\fBddi_dmae_disable()\fR" -.sp .LP The \fBddi_dmae_disable()\fR function disables the \fBDMA\fR channel so that it no longer responds to a device's \fBDMA\fR service requests. .SS "\fBddi_dmae_enable()\fR" -.sp .LP The \fBddi_dmae_enable()\fR function enables the \fBDMA\fR channel for operation. This may be used to re-enable the channel after a call to \fBddi_dmae_disable()\fR. The channel is automatically enabled after successful programming by \fBddi_dmae_prog()\fR. .SS "\fBddi_dmae_stop()\fR" -.sp .LP The \fBddi_dmae_stop()\fR function disables the channel and terminates any active operation. .SS "\fBddi_dmae_getcnt()\fR" -.sp .LP The \fBddi_dmae_getcnt()\fR function examines the count register of the \fBDMA\fR channel and sets \fI*countp\fR to the number of bytes remaining to be transferred. The channel is assumed to be stopped. .SS "\fBddi_dmae_1stparty()\fR" -.sp .LP In the case of \fBISA\fR buses, \fBddi_dmae_1stparty()\fR configures a channel in the system's \fBDMA\fR engine to operate in a ``slave'' (``cascade'') mode. @@ -285,7 +275,6 @@ first be allocated using \fBddi_dmae_alloc()\fR and then configured using I/O, including the necessary \fBDMA\fR address and count values obtained from the \fBddi_dma_cookie\fR(9S). .SS "\fBddi_dmae_getattr()\fR" -.sp .LP The \fBddi_dmae_getattr()\fR function fills in the \fBDMA\fR attribute structure, pointed to by \fIattrp\fR, with the \fBDMA\fR attributes of the @@ -295,9 +284,8 @@ mastering or use first-party \fBDMA\fR must create and initialize their own The \fBDMA\fR attribute structure must be passed to the \fBDMA\fR resource allocation functions to provide the information necessary to break the \fBDMA\fR request into \fBDMA\fR windows and \fBDMA\fR cookies. See -\fBddi_dma_nextcookie\fR(9F) and \fBddi_dma_getwin\fR(9F). +\fBddi_dma_cookie_iter\fR(9F) and \fBddi_dma_getwin\fR(9F). .SH RETURN VALUES -.sp .ne 2 .na \fB\fBDDI_SUCCESS\fR\fR @@ -326,14 +314,12 @@ available and the value of \fIdmae_waitfp\fR is not \fBDDI_DMA_SLEEP\fR. .RE .SH CONTEXT -.sp .LP If \fBddi_dmae_alloc()\fR is called from interrupt context, then its \fIdmae_waitfp\fR argument and the callback function must not have the value \fBDDI_DMA_SLEEP\fR. Otherwise, all these routines can be called from user, interrupt, or kernel context. .SH ATTRIBUTES -.sp .LP See \fBattributes\fR(5) for descriptions of the following attributes: .sp @@ -349,10 +335,9 @@ Architecture x86 .TE .SH SEE ALSO -.sp .LP \fBisa\fR(4), \fBattributes\fR(5), \fBddi_dma_buf_setup\fR(9F), -\fBddi_dma_getwin\fR(9F), \fBddi_dma_nextcookie\fR(9F), +\fBddi_dma_cookie_iter\fR(9F), \fBddi_dma_getwin\fR(9F), \fBddi_dma_mem_alloc\fR(9F), \fBddi_dma_addr_bind_handle\fR(9F), \fBddi_dma_attr\fR(9S), \fBddi_dma_cookie\fR(9S), \fBddi_dmae_req\fR(9S) diff --git a/usr/src/pkg/manifests/system-kernel.man9f.inc b/usr/src/pkg/manifests/system-kernel.man9f.inc index 4076044314..3d10b9ddc9 100644 --- a/usr/src/pkg/manifests/system-kernel.man9f.inc +++ b/usr/src/pkg/manifests/system-kernel.man9f.inc @@ -150,11 +150,11 @@ file path=usr/share/man/man9f/ddi_dma_addr_bind_handle.9f file path=usr/share/man/man9f/ddi_dma_alloc_handle.9f file path=usr/share/man/man9f/ddi_dma_buf_bind_handle.9f file path=usr/share/man/man9f/ddi_dma_burstsizes.9f +file path=usr/share/man/man9f/ddi_dma_cookie_iter.9f file path=usr/share/man/man9f/ddi_dma_free_handle.9f file path=usr/share/man/man9f/ddi_dma_getwin.9f file path=usr/share/man/man9f/ddi_dma_mem_alloc.9f file path=usr/share/man/man9f/ddi_dma_mem_free.9f -file path=usr/share/man/man9f/ddi_dma_nextcookie.9f file path=usr/share/man/man9f/ddi_dma_numwin.9f file path=usr/share/man/man9f/ddi_dma_set_sbus64.9f file path=usr/share/man/man9f/ddi_dma_sync.9f @@ -719,6 +719,10 @@ link path=usr/share/man/man9f/ddi_devid_unregister.9f \ target=ddi_devid_compare.9f link path=usr/share/man/man9f/ddi_devid_valid.9f target=ddi_devid_compare.9f link path=usr/share/man/man9f/ddi_devmap_segmap.9f target=devmap_setup.9f +link path=usr/share/man/man9f/ddi_dma_cookie_get.9f target=ddi_dma_cookie_iter.9f +link path=usr/share/man/man9f/ddi_dma_cookie_one.9f target=ddi_dma_cookie_iter.9f +link path=usr/share/man/man9f/ddi_dma_ncookies.9f target=ddi_dma_cookie_iter.9f +link path=usr/share/man/man9f/ddi_dma_nextcookie.9f target=ddi_dma_cookie_iter.9f link path=usr/share/man/man9f/ddi_dmae_1stparty.9f target=ddi_dmae.9f link path=usr/share/man/man9f/ddi_dmae_alloc.9f target=ddi_dmae.9f link path=usr/share/man/man9f/ddi_dmae_disable.9f target=ddi_dmae.9f diff --git a/usr/src/uts/common/io/scsi/impl/scsi_resource.c b/usr/src/uts/common/io/scsi/impl/scsi_resource.c index cd58cd1981..5477435026 100644 --- a/usr/src/uts/common/io/scsi/impl/scsi_resource.c +++ b/usr/src/uts/common/io/scsi/impl/scsi_resource.c @@ -258,6 +258,7 @@ scsi_dmaget_attr(struct scsi_pkt_cache_wrapper *pktw) pktw->pcw_total_xfer += pktp->pkt_dma_len; pktp->pkt_cookies = hp->dmai_cookie - 1; hp->dmai_cookie = cp; + hp->dmai_curcookie = num_segs; return (1); } diff --git a/usr/src/uts/common/os/sunddi.c b/usr/src/uts/common/os/sunddi.c index dce7c40462..eee666190f 100644 --- a/usr/src/uts/common/os/sunddi.c +++ b/usr/src/uts/common/os/sunddi.c @@ -7074,6 +7074,14 @@ ddi_dma_buf_bind_handle(ddi_dma_handle_t handle, struct buf *bp, dev_info_t *dip, *rdip; struct ddi_dma_req dmareq; int (*funcp)(); + ddi_dma_cookie_t cookie; + uint_t count; + + if (cookiep == NULL) + cookiep = &cookie; + + if (ccountp == NULL) + ccountp = &count; dmareq.dmar_flags = flags; dmareq.dmar_fp = waitfp; @@ -7130,10 +7138,19 @@ ddi_dma_addr_bind_handle(ddi_dma_handle_t handle, struct as *as, dev_info_t *dip, *rdip; struct ddi_dma_req dmareq; int (*funcp)(); + ddi_dma_cookie_t cookie; + uint_t count; if (len == (uint_t)0) { return (DDI_DMA_NOMAPPING); } + + if (cookiep == NULL) + cookiep = &cookie; + + if (ccountp == NULL) + ccountp = &count; + dmareq.dmar_flags = flags; dmareq.dmar_fp = waitfp; dmareq.dmar_arg = arg; @@ -7156,6 +7173,11 @@ ddi_dma_nextcookie(ddi_dma_handle_t handle, ddi_dma_cookie_t *cookiep) ddi_dma_impl_t *hp = (ddi_dma_impl_t *)handle; ddi_dma_cookie_t *cp; + if (hp->dmai_curcookie >= hp->dmai_ncookies) { + panic("ddi_dma_nextcookie() called too many times on handle %p", + hp); + } + cp = hp->dmai_cookie; ASSERT(cp); @@ -7164,6 +7186,74 @@ ddi_dma_nextcookie(ddi_dma_handle_t handle, ddi_dma_cookie_t *cookiep) cookiep->dmac_address = cp->dmac_address; cookiep->dmac_size = cp->dmac_size; hp->dmai_cookie++; + hp->dmai_curcookie++; +} + +int +ddi_dma_ncookies(ddi_dma_handle_t handle) +{ + ddi_dma_impl_t *hp = (ddi_dma_impl_t *)handle; + + return (hp->dmai_ncookies); +} + +const ddi_dma_cookie_t * +ddi_dma_cookie_iter(ddi_dma_handle_t handle, const ddi_dma_cookie_t *iter) +{ + ddi_dma_impl_t *hp = (ddi_dma_impl_t *)handle; + const ddi_dma_cookie_t *base, *end; + + if (hp->dmai_ncookies == 0) { + return (NULL); + } + + base = hp->dmai_cookie - hp->dmai_curcookie; + end = base + hp->dmai_ncookies; + if (iter == NULL) { + return (base); + } + + if ((uintptr_t)iter < (uintptr_t)base || + (uintptr_t)iter >= (uintptr_t)end) { + return (NULL); + } + + iter++; + if (iter == end) { + return (NULL); + } + + return (iter); +} + +const ddi_dma_cookie_t * +ddi_dma_cookie_get(ddi_dma_handle_t handle, uint_t index) +{ + ddi_dma_impl_t *hp = (ddi_dma_impl_t *)handle; + const ddi_dma_cookie_t *base; + + if (index >= hp->dmai_ncookies) { + return (NULL); + } + + base = hp->dmai_cookie - hp->dmai_curcookie; + return (base + index); +} + +const ddi_dma_cookie_t * +ddi_dma_cookie_one(ddi_dma_handle_t handle) +{ + ddi_dma_impl_t *hp = (ddi_dma_impl_t *)handle; + const ddi_dma_cookie_t *base; + + if (hp->dmai_ncookies != 1) { + panic("ddi_dma_cookie_one() called with improper handle %p", + hp); + } + ASSERT3P(hp->dmai_cookie, !=, NULL); + + base = hp->dmai_cookie - hp->dmai_curcookie; + return (base); } int @@ -7184,11 +7274,19 @@ ddi_dma_getwin(ddi_dma_handle_t h, uint_t win, off_t *offp, { int (*funcp)() = ddi_dma_win; struct bus_ops *bop; + ddi_dma_cookie_t cookie; + uint_t count; bop = DEVI(HD)->devi_ops->devo_bus_ops; if (bop && bop->bus_dma_win) funcp = bop->bus_dma_win; + if (cookiep == NULL) + cookiep = &cookie; + + if (ccountp == NULL) + ccountp = &count; + return ((*funcp)(HD, HD, h, win, offp, lenp, cookiep, ccountp)); } diff --git a/usr/src/uts/common/sys/ddi_impldefs.h b/usr/src/uts/common/sys/ddi_impldefs.h index 37329a1c18..1012c904fd 100644 --- a/usr/src/uts/common/sys/ddi_impldefs.h +++ b/usr/src/uts/common/sys/ddi_impldefs.h @@ -877,6 +877,8 @@ typedef struct ddi_dma_impl { uint_t dmai_inuse; /* active handle? */ uint_t dmai_nwin; uint_t dmai_winsize; + uint_t dmai_ncookies; + uint_t dmai_curcookie; caddr_t dmai_nexus_private; void *dmai_iopte; uint_t *dmai_sbi; @@ -901,6 +903,8 @@ typedef struct ddi_dma_impl { */ typedef struct ddi_dma_impl { ddi_dma_cookie_t *dmai_cookie; /* array of DMA cookies */ + uint_t dmai_ncookies; + uint_t dmai_curcookie; void *dmai_private; /* diff --git a/usr/src/uts/common/sys/sunddi.h b/usr/src/uts/common/sys/sunddi.h index f81a391f41..6d5f4304b4 100644 --- a/usr/src/uts/common/sys/sunddi.h +++ b/usr/src/uts/common/sys/sunddi.h @@ -1368,6 +1368,10 @@ ddi_dma_unbind_handle(ddi_dma_handle_t handle); /* * get next DMA cookie + * + * This function has been deprecated because it is unsafe. Please use + * ddi_dma_cookie_iter(), ddi_dma_cookie_get(), or ddi_dma_cookie_one() instead. + * For more information on the problems, please see the manual page. */ void @@ -1850,6 +1854,16 @@ extern void ddi_dev_report_fault(dev_info_t *, ddi_fault_impact_t, ddi_fault_location_t, const char *); extern ddi_devstate_t ddi_get_devstate(dev_info_t *); +/* + * Replacement DMA cookie functions for ddi_dma_nextcookie(). + */ +extern int ddi_dma_ncookies(ddi_dma_handle_t); +extern const ddi_dma_cookie_t *ddi_dma_cookie_iter(ddi_dma_handle_t, + const ddi_dma_cookie_t *); +extern const ddi_dma_cookie_t *ddi_dma_cookie_get(ddi_dma_handle_t, uint_t); +extern const ddi_dma_cookie_t *ddi_dma_cookie_one(ddi_dma_handle_t); + + /* * Miscellaneous redefines */ diff --git a/usr/src/uts/i86pc/io/rootnex.c b/usr/src/uts/i86pc/io/rootnex.c index 6cbc2132c1..972f726287 100644 --- a/usr/src/uts/i86pc/io/rootnex.c +++ b/usr/src/uts/i86pc/io/rootnex.c @@ -2186,6 +2186,8 @@ fast: *ccountp = sinfo->si_sgl_size; hp->dmai_cookie++; hp->dmai_rflags &= ~DDI_DMA_PARTIAL; + hp->dmai_ncookies = *ccountp; + hp->dmai_curcookie = 1; ROOTNEX_DPROF_INC(&rootnex_cnt[ROOTNEX_CNT_ACTIVE_BINDS]); ROOTNEX_DPROBE4(rootnex__bind__fast, dev_info_t *, rdip, uint64_t, rootnex_cnt[ROOTNEX_CNT_ACTIVE_BINDS], @@ -2259,6 +2261,8 @@ fast: } *cookiep = dma->dp_cookies[0]; hp->dmai_cookie++; + hp->dmai_ncookies = *ccountp; + hp->dmai_curcookie = 1; ROOTNEX_DPROF_INC(&rootnex_cnt[ROOTNEX_CNT_ACTIVE_BINDS]); ROOTNEX_DPROBE4(rootnex__bind__slow, dev_info_t *, rdip, uint64_t, @@ -2411,6 +2415,7 @@ rootnex_coredma_reset_cookies(dev_info_t *dip, ddi_dma_handle_t handle) hp->dmai_cookie = dma->dp_cookies; } hp->dmai_cookie++; + hp->dmai_curcookie = 1; } /*ARGSUSED*/ @@ -2671,6 +2676,10 @@ rootnex_clean_dmahdl(ddi_dma_impl_t *hp) hp->dmai_error.err_status = DDI_FM_OK; hp->dmai_error.err_expected = DDI_FM_ERR_UNEXPECTED; hp->dmai_error.err_ontrap = NULL; + + /* Cookie tracking */ + hp->dmai_ncookies = 0; + hp->dmai_curcookie = 0; } @@ -4770,6 +4779,8 @@ rootnex_coredma_win(dev_info_t *dip, dev_info_t *rdip, ddi_dma_handle_t handle, *ccountp = dma->dp_sglinfo.si_sgl_size; *cookiep = hp->dmai_cookie[0]; hp->dmai_cookie++; + hp->dmai_ncookies = *ccountp; + hp->dmai_curcookie = 1; return (DDI_SUCCESS); } @@ -4865,6 +4876,8 @@ rootnex_coredma_win(dev_info_t *dip, dev_info_t *rdip, ddi_dma_handle_t handle, *lenp = window->wd_size; *ccountp = window->wd_cookie_cnt; *cookiep = hp->dmai_cookie[0]; + hp->dmai_ncookies = *ccountp; + hp->dmai_curcookie = 1; hp->dmai_cookie++; #if !defined(__amd64) diff --git a/usr/src/uts/sun4/io/px/px.c b/usr/src/uts/sun4/io/px/px.c index 9f8e18e458..6d9c5797c4 100644 --- a/usr/src/uts/sun4/io/px/px.c +++ b/usr/src/uts/sun4/io/px/px.c @@ -999,6 +999,8 @@ px_dma_bindhdl(dev_info_t *dip, dev_info_t *rdip, mapped: *ccountp = 1; MAKE_DMA_COOKIE(cookiep, mp->dmai_mapping, mp->dmai_size); + mp->dmai_ncookies = 1; + mp->dmai_curcookie = 1; break; case PX_DMAI_FLAGS_BYPASS: case PX_DMAI_FLAGS_PTP: @@ -1007,6 +1009,10 @@ mapped: *ccountp = PX_WINLST(mp)->win_ncookies; *cookiep = *(ddi_dma_cookie_t *)(PX_WINLST(mp) + 1); /* wholeobj */ + /* + * mp->dmai_ncookies and mp->dmai_curcookie are set by + * px_dma_physwin(). + */ break; default: cmn_err(CE_PANIC, "%s%d: px_dma_bindhdl(%p): bad dma type", @@ -1078,6 +1084,8 @@ px_dma_unbindhdl(dev_info_t *dip, dev_info_t *rdip, ddi_dma_handle_t handle) ddi_run_callback(&px_kmem_clid); } mp->dmai_flags &= PX_DMAI_FLAGS_PRESERVE; + mp->dmai_ncookies = 0; + mp->dmai_curcookie = 0; return (DDI_SUCCESS); } @@ -1120,6 +1128,8 @@ px_dma_win(dev_info_t *dip, dev_info_t *rdip, mp->dmai_size); if (ccountp) *ccountp = 1; + mp->dmai_ncookies = 1; + mp->dmai_curcookie = 1; break; case PX_DMAI_FLAGS_PTP: case PX_DMAI_FLAGS_BYPASS: { @@ -1137,6 +1147,8 @@ px_dma_win(dev_info_t *dip, dev_info_t *rdip, win_p->win_curseg = 0; if (ccountp) *ccountp = win_p->win_ncookies; + mp->dmai_ncookies = win_p->win_ncookies; + mp->dmai_curcookie = 1; } break; default: diff --git a/usr/src/uts/sun4/io/px/px_dma.c b/usr/src/uts/sun4/io/px/px_dma.c index 148699c267..2c88281260 100644 --- a/usr/src/uts/sun4/io/px/px_dma.c +++ b/usr/src/uts/sun4/io/px/px_dma.c @@ -76,6 +76,8 @@ px_dma_allocmp(dev_info_t *dip, dev_info_t *rdip, int (*waitfp)(caddr_t), mp->dmai_flags = 0; mp->dmai_pfnlst = NULL; mp->dmai_winlst = NULL; + mp->dmai_ncookies = 0; + mp->dmai_curcookie = 0; /* * kmem_alloc debug: the following fields are not zero-ed @@ -1229,7 +1231,9 @@ px_dma_physwin(px_t *px_p, ddi_dma_req_t *dmareq, ddi_dma_impl_t *mp) mp->dmai_rflags &= ~DDI_DMA_REDZONE; mp->dmai_flags |= PX_DMAI_FLAGS_NOSYNC; cookie0_p = (ddi_dma_cookie_t *)(PX_WINLST(mp) + 1); - mp->dmai_cookie = PX_WINLST(mp)->win_ncookies > 1 ? cookie0_p + 1 : 0; + mp->dmai_cookie = cookie0_p + 1; + mp->dmai_curcookie = 1; + mp->dmai_ncookies = PX_WINLST(mp)->win_ncookies; mp->dmai_mapping = cookie0_p->dmac_laddress; px_dma_freepfn(mp); diff --git a/usr/src/uts/sun4u/io/pci/pci.c b/usr/src/uts/sun4u/io/pci/pci.c index 15cb498378..d52c973b30 100644 --- a/usr/src/uts/sun4u/io/pci/pci.c +++ b/usr/src/uts/sun4u/io/pci/pci.c @@ -731,6 +731,8 @@ pci_dma_bindhdl(dev_info_t *dip, dev_info_t *rdip, mapped: *ccountp = 1; MAKE_DMA_COOKIE(cookiep, mp->dmai_mapping, mp->dmai_size); + mp->dmai_ncookies = 1; + mp->dmai_curcookie = 1; break; case DMAI_FLAGS_BYPASS: case DMAI_FLAGS_PEER_TO_PEER: @@ -738,6 +740,10 @@ mapped: goto map_err; *ccountp = WINLST(mp)->win_ncookies; *cookiep = *(ddi_dma_cookie_t *)(WINLST(mp) + 1); /* wholeobj */ + /* + * mp->dmai_ncookies and mp->dmai_curcookie are set by + * pci_dma_physwin(). + */ break; default: panic("%s%d: pci_dma_bindhdl(%p): bad dma type", @@ -809,6 +815,8 @@ pci_dma_unbindhdl(dev_info_t *dip, dev_info_t *rdip, ddi_dma_handle_t handle) SYNC_BUF_PA(mp) = 0; mp->dmai_error.err_cf = NULL; + mp->dmai_ncookies = 0; + mp->dmai_curcookie = 0; return (DDI_SUCCESS); } @@ -845,6 +853,8 @@ pci_dma_win(dev_info_t *dip, dev_info_t *rdip, mp->dmai_size); if (ccountp) *ccountp = 1; + mp->dmai_ncookies = 1; + mp->dmai_curcookie = 1; break; case DMAI_FLAGS_PEER_TO_PEER: case DMAI_FLAGS_BYPASS: { @@ -863,6 +873,8 @@ pci_dma_win(dev_info_t *dip, dev_info_t *rdip, win_p->win_curseg = 0; if (ccountp) *ccountp = win_p->win_ncookies; + mp->dmai_ncookies = win_p->win_ncookies; + mp->dmai_curcookie = 1; } break; default: diff --git a/usr/src/uts/sun4u/io/pci/pci_dma.c b/usr/src/uts/sun4u/io/pci/pci_dma.c index 9814a69e68..af68d98c98 100644 --- a/usr/src/uts/sun4u/io/pci/pci_dma.c +++ b/usr/src/uts/sun4u/io/pci/pci_dma.c @@ -267,6 +267,8 @@ pci_dma_allocmp(dev_info_t *dip, dev_info_t *rdip, int (*waitfp)(caddr_t), mp->dmai_flags = 0; mp->dmai_pfnlst = NULL; mp->dmai_winlst = NULL; + mp->dmai_ncookies = 0; + mp->dmai_curcookie = 0; /* * kmem_alloc debug: the following fields are not zero-ed @@ -1410,8 +1412,10 @@ pci_dma_physwin(pci_t *pci_p, ddi_dma_req_t *dmareq, ddi_dma_impl_t *mp) } mp->dmai_rflags &= ~DDI_DMA_REDZONE; cookie0_p = (ddi_dma_cookie_t *)(WINLST(mp) + 1); - mp->dmai_cookie = WINLST(mp)->win_ncookies > 1 ? cookie0_p + 1 : 0; + mp->dmai_cookie = cookie0_p + 1; mp->dmai_mapping = cookie0_p->dmac_laddress; + mp->dmai_ncookies = WINLST(mp)->win_ncookies; + mp->dmai_curcookie = 1; pci_dma_freepfn(mp); return (DDI_DMA_MAPPED); diff --git a/usr/src/uts/sun4v/io/niumx/niumx.c b/usr/src/uts/sun4v/io/niumx/niumx.c index d91b9c4872..b455d287e6 100644 --- a/usr/src/uts/sun4v/io/niumx/niumx.c +++ b/usr/src/uts/sun4v/io/niumx/niumx.c @@ -665,6 +665,8 @@ niumx_dma_allochdl(dev_info_t *dip, dev_info_t *rdip, ddi_dma_attr_t *attrp, mp->dmai_rdip = rdip; mp->dmai_pfnlst = NULL; mp->dmai_cookie = NULL; + mp->dmai_ncookies = 0; + mp->dmai_curcookie = 0; mp->dmai_fault = 0; mp->dmai_fault_check = NULL; mp->dmai_fault_notify = NULL; @@ -775,6 +777,8 @@ niumx_dma_bindhdl(dev_info_t *dip, dev_info_t *rdip, } mp->dmai_cookie->dmac_laddress = mp->dmai_mapping; mp->dmai_cookie->dmac_size = mp->dmai_size; + mp->dmai_ncookies = 1; + mp->dmai_curcookie = 0; *ccountp = 1; *cookiep = *mp->dmai_cookie; DBG(NIUMX_DBG_DMA_BINDH, dip, "cookie %" PRIx64 "+%x, count=%d\n", @@ -801,6 +805,7 @@ niumx_dma_unbindhdl(dev_info_t *dip, dev_info_t *rdip, ddi_dma_handle_t handle) if (mp->dmai_cookie) { kmem_free(mp->dmai_cookie, sizeof (ddi_dma_cookie_t)); mp->dmai_cookie = NULL; + mp->dmai_ncookies = mp->dmai_curcookie = 0; } return (DDI_SUCCESS); -- cgit v1.2.3 From 46782190b8c59b1b5fd7df81b2231ef50061fe2a Mon Sep 17 00:00:00 2001 From: Robert Mustacchi Date: Mon, 20 Jan 2020 03:34:49 +0000 Subject: 12234 Want smbios battery support Reviewed by: John Levon Approved by: Dan McDonald --- usr/src/cmd/smbios/smbios.c | 52 +++++++++++++++++++++++ usr/src/common/smbios/mktables.sh | 1 + usr/src/common/smbios/smb_info.c | 70 +++++++++++++++++++++++++++++++ usr/src/lib/libsmbios/common/mapfile-vers | 2 + usr/src/uts/common/sys/smbios.h | 31 ++++++++++++++ 5 files changed, 156 insertions(+) diff --git a/usr/src/cmd/smbios/smbios.c b/usr/src/cmd/smbios/smbios.c index 2c0c844674..0d3f110961 100644 --- a/usr/src/cmd/smbios/smbios.c +++ b/usr/src/cmd/smbios/smbios.c @@ -1466,6 +1466,54 @@ print_processor_info(smbios_hdl_t *shp, id_t id, FILE *fp) } } +static void +print_battery(smbios_hdl_t *shp, id_t id, FILE *fp) +{ + smbios_battery_t bat; + + if (smbios_info_battery(shp, id, &bat) != 0) { + smbios_warn(shp, "failed to read battery information"); + return; + } + + if (bat.smbb_date != NULL) { + oprintf(fp, " Manufacture Date: %s\n", bat.smbb_date); + } + + if (bat.smbb_serial != NULL) { + oprintf(fp, " Serial Number: %s\n", bat.smbb_serial); + } + + if (bat.smbb_chem != SMB_BDC_UNKNOWN) { + desc_printf(smbios_battery_chem_desc(bat.smbb_chem), + fp, " Battery Chemistry: 0x%x", bat.smbb_chem); + } + + if (bat.smbb_cap != 0) { + oprintf(fp, " Design Capacity: %u mWh\n", bat.smbb_cap); + } else { + oprintf(fp, " Design Capacity: unknown\n"); + } + + if (bat.smbb_volt != 0) { + oprintf(fp, " Design Voltage: %u mV\n", bat.smbb_volt); + } else { + oprintf(fp, " Design Voltage: unknown\n"); + } + + oprintf(fp, " SBDS Version Number: %s\n", bat.smbb_version); + if (bat.smbb_err != UINT8_MAX) { + oprintf(fp, " Maximum Error: %u\n", bat.smbb_err); + } else { + oprintf(fp, " Maximum Error: unknown\n", bat.smbb_err); + } + oprintf(fp, " SBDS Serial Number: %04x\n", bat.smbb_ssn); + oprintf(fp, " SBDS Manufacture Date: %u-%02u-%02u\n", bat.smbb_syear, + bat.smbb_smonth, bat.smbb_sday); + oprintf(fp, " SBDS Device Chemistry: %s\n", bat.smbb_schem); + oprintf(fp, " OEM-specific Information: 0x%08x\n", bat.smbb_oemdata); +} + static void print_pointdev(smbios_hdl_t *shp, id_t id, FILE *fp) { @@ -1678,6 +1726,10 @@ print_struct(smbios_hdl_t *shp, const smbios_struct_t *sp, void *fp) oprintf(fp, "\n"); print_memdevmap(shp, sp->smbstr_id, fp); break; + case SMB_TYPE_BATTERY: + oprintf(fp, "\n"); + print_battery(shp, sp->smbstr_id, fp); + break; case SMB_TYPE_POINTDEV: oprintf(fp, "\n"); print_pointdev(shp, sp->smbstr_id, fp); diff --git a/usr/src/common/smbios/mktables.sh b/usr/src/common/smbios/mktables.sh index bb6c077791..95bd9d6f8b 100644 --- a/usr/src/common/smbios/mktables.sh +++ b/usr/src/common/smbios/mktables.sh @@ -62,6 +62,7 @@ SMB_SLCH2_ smbios_slot_ch2_name uint_t desc_funcs=' SMB_BBFL_ smbios_bboard_flag_desc uint_t SMB_BBT_ smbios_bboard_type_desc uint_t +SMB_BDC_ smbios_battery_chem_desc uint_t SMB_BIOSFL_ smbios_bios_flag_desc uint64_t SMB_BIOSXB1_ smbios_bios_xb1_desc uint_t SMB_BIOSXB2_ smbios_bios_xb2_desc uint_t diff --git a/usr/src/common/smbios/smb_info.c b/usr/src/common/smbios/smb_info.c index c4376fd081..47c19e7fcb 100644 --- a/usr/src/common/smbios/smb_info.c +++ b/usr/src/common/smbios/smb_info.c @@ -198,6 +198,23 @@ static const struct smb_infospec { 0, 0, 0 }, + { SMB_TYPE_BATTERY, + offsetof(smb_battery_t, smbbat_manufacturer), + offsetof(smb_battery_t, smbbat_devname), + 0, + /* + * While the serial number is a part of the device, because of + * the fact that the battery has two different serial numbers, + * we don't include it here. + */ + 0, + 0, + offsetof(smb_battery_t, smbbat_loc), + 0, + 0, + 0, + 0 + }, { SMB_TYPE_EOT } }; @@ -1698,3 +1715,56 @@ smbios_info_pointdev(smbios_hdl_t *shp, id_t id, smbios_pointdev_t *pd) return (0); } + +int +smbios_info_battery(smbios_hdl_t *shp, id_t id, smbios_battery_t *bp) +{ + const smb_struct_t *stp = smb_lookup_id(shp, id); + smb_battery_t bat; + + if (stp->smbst_hdr->smbh_type != SMB_TYPE_BATTERY) { + return (smb_set_errno(shp, ESMB_TYPE)); + } + + if (stp->smbst_hdr->smbh_len < sizeof (bat)) { + return (smb_set_errno(shp, ESMB_SHORT)); + } + + bzero(bp, sizeof (*bp)); + smb_info_bcopy(stp->smbst_hdr, &bat, sizeof (bat)); + + /* + * This may be superseded by the SBDS data. + */ + if (bat.smbbat_date != 0) { + bp->smbb_date = smb_strptr(stp, bat.smbbat_date); + } else { + bp->smbb_date = NULL; + } + + /* + * This may be superseded by the SBDS data. + */ + if (bat.smbbat_serial != 0) { + bp->smbb_serial = smb_strptr(stp, bat.smbbat_serial); + } else { + bp->smbb_serial = NULL; + } + + bp->smbb_chem = bat.smbbat_chem; + bp->smbb_cap = bat.smbbat_cap; + if (bat.smbbat_mult > 0) { + bp->smbb_cap *= bat.smbbat_mult; + } + bp->smbb_volt = bat.smbbat_volt; + bp->smbb_version = smb_strptr(stp, bat.smbbat_version); + bp->smbb_err = bat.smbbat_err; + bp->smbb_ssn = bat.smbbat_ssn; + bp->smbb_syear = 1980 + (bat.smbbat_sdate >> 9); + bp->smbb_smonth = (bat.smbbat_sdate >> 5) & 0xf; + bp->smbb_sday = bat.smbbat_sdate & 0x1f; + bp->smbb_schem = smb_strptr(stp, bat.smbbat_schem); + bp->smbb_oemdata = bat.smbbat_oemdata; + + return (0); +} diff --git a/usr/src/lib/libsmbios/common/mapfile-vers b/usr/src/lib/libsmbios/common/mapfile-vers index dd09785fe3..1016220cd7 100644 --- a/usr/src/lib/libsmbios/common/mapfile-vers +++ b/usr/src/lib/libsmbios/common/mapfile-vers @@ -43,6 +43,7 @@ $mapfile_version 2 SYMBOL_VERSION SUNWprivate_1.1 { global: _smb_debug; + smbios_battery_chem_desc; smbios_bboard_flag_desc; smbios_bboard_flag_name; smbios_bboard_type_desc; @@ -80,6 +81,7 @@ SYMBOL_VERSION SUNWprivate_1.1 { smbios_evlog_method_desc; smbios_fdopen; smbios_hwsec_desc; + smbios_info_battery; smbios_info_bboard; smbios_info_bios; smbios_info_boot; diff --git a/usr/src/uts/common/sys/smbios.h b/usr/src/uts/common/sys/smbios.h index 82a81b5a28..34281898e0 100644 --- a/usr/src/uts/common/sys/smbios.h +++ b/usr/src/uts/common/sys/smbios.h @@ -1378,6 +1378,34 @@ typedef struct smbios_pointdev { #define SMB_PDI_BUSM_UDIN 0xA1 /* Bus mouse micro-DIN */ #define SMB_PDI_BUSM_USB 0xA2 /* USB */ +/* + * SMBIOS Portable Battery. See DSP0134 Section 7.23 for more information. + */ +typedef struct smbios_battery { + const char *smbb_date; /* Manufacture date */ + const char *smbb_serial; /* Serial number */ + uint8_t smbb_chem; /* Device Chemistry */ + uint32_t smbb_cap; /* Design Capacity */ + uint16_t smbb_volt; /* Design Voltage */ + const char *smbb_version; /* Smart Battery version */ + uint8_t smbb_err; /* Maximum error */ + uint16_t smbb_ssn; /* SBDS serial number */ + uint16_t smbb_syear; /* SBDS manufacture year */ + uint8_t smbb_smonth; /* SBDS manufacture month */ + uint8_t smbb_sday; /* SBDS manufacture day */ + const char *smbb_schem; /* SBDS chemistry */ + uint32_t smbb_oemdata; /* OEM data */ +} smbios_battery_t; + +#define SMB_BDC_OTHER 0x01 /* Other */ +#define SMB_BDC_UNKNOWN 0x02 /* Unknown */ +#define SMB_BDC_LEADACID 0x03 /* Lead Acid */ +#define SMB_BDC_NICD 0x04 /* Nickel Cadmium */ +#define SMB_BDC_NIMH 0x05 /* Nickel Metal hydride */ +#define SMB_BDC_LIB 0x06 /* Lithium-ion */ +#define SMB_BDC_ZINCAIR 0x07 /* Zinc air */ +#define SMB_BDC_LIPO 0x08 /* Lithium Polymer */ + /* * SMBIOS Hardware Security Settings. See DSP0134 Section 7.25 for more * information. Only one such record will be present in the SMBIOS. @@ -1867,6 +1895,7 @@ extern int smbios_info_extprocessor(smbios_hdl_t *, id_t, smbios_processor_ext_t *); extern int smbios_info_cache(smbios_hdl_t *, id_t, smbios_cache_t *); extern int smbios_info_pointdev(smbios_hdl_t *, id_t, smbios_pointdev_t *); +extern int smbios_info_battery(smbios_hdl_t *, id_t, smbios_battery_t *); extern int smbios_info_port(smbios_hdl_t *, id_t, smbios_port_t *); extern int smbios_info_extport(smbios_hdl_t *, id_t, smbios_port_ext_t *); extern int smbios_info_slot(smbios_hdl_t *, id_t, smbios_slot_t *); @@ -1912,6 +1941,8 @@ extern const char *smbios_csn(smbios_hdl_t *); * functions return the comment string next to the #defines listed above, and * the _name functions return the appropriate #define identifier itself. */ +extern const char *smbios_battery_chem_desc(uint_t); + extern const char *smbios_bboard_flag_desc(uint_t); extern const char *smbios_bboard_flag_name(uint_t); extern const char *smbios_bboard_type_desc(uint_t); -- cgit v1.2.3 From b5c83661f3899fe50c949117084b15d6478d9f5f Mon Sep 17 00:00:00 2001 From: Peter Tribble Date: Sun, 26 Jan 2020 11:32:45 +0000 Subject: 12251 remove sunfire-specific man pages Reviewed by: GergÅ‘ Doma Approved by: Dan McDonald MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- usr/src/man/man1m/Makefile | 4 +- usr/src/man/man1m/cfgadm_ac.1m | 310 ------------------------------ usr/src/man/man1m/cfgadm_sysctrl.1m | 337 --------------------------------- usr/src/pkg/manifests/SUNWcs.man1m.inc | 2 - 4 files changed, 1 insertion(+), 652 deletions(-) delete mode 100644 usr/src/man/man1m/cfgadm_ac.1m delete mode 100644 usr/src/man/man1m/cfgadm_sysctrl.1m diff --git a/usr/src/man/man1m/Makefile b/usr/src/man/man1m/Makefile index 9b9cacb853..0ce35da597 100644 --- a/usr/src/man/man1m/Makefile +++ b/usr/src/man/man1m/Makefile @@ -17,7 +17,7 @@ # Copyright 2016 Toomas Soome # Copyright 2018 Nexenta Systems, Inc. # Copyright (c) 2017, Chris Fraire . -# Copyright 2019 Peter Tribble +# Copyright 2020 Peter Tribble # Copyright 2019 OmniOS Community Edition (OmniOSce) Association. # @@ -61,7 +61,6 @@ _MANFILES= 6to4relay.1m \ captoinfo.1m \ catman.1m \ cfgadm.1m \ - cfgadm_ac.1m \ cfgadm_cardbus.1m \ cfgadm_fp.1m \ cfgadm_ib.1m \ @@ -69,7 +68,6 @@ _MANFILES= 6to4relay.1m \ cfgadm_sata.1m \ cfgadm_sbd.1m \ cfgadm_scsi.1m \ - cfgadm_sysctrl.1m \ cfgadm_usb.1m \ chat.1m \ check-hostname.1m \ diff --git a/usr/src/man/man1m/cfgadm_ac.1m b/usr/src/man/man1m/cfgadm_ac.1m deleted file mode 100644 index 248df05ef2..0000000000 --- a/usr/src/man/man1m/cfgadm_ac.1m +++ /dev/null @@ -1,310 +0,0 @@ -'\" te -.\" Copyright (c) 1999 Sun Microsystems, Inc. All Rights Reserved. -.\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License"). You may not use this file except in compliance with the License. -.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing. See the License for the specific language governing permissions and limitations under the License. -.\" When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE. If applicable, add the following below this CDDL HEADER, with the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner] -.TH CFGADM_AC 1M "Sep 29, 1999" -.SH NAME -cfgadm_ac \- EXX00 memory system administration -.SH SYNOPSIS -.LP -.nf -\fB/usr/sbin/cfgadm\fR [\fB-c\fR configure] [\fB-f\fR] - [\fB-o\fR disable-at-boot | enable-at-boot ] ac\fI#\fR:bank\fI#\fR ... -.fi - -.LP -.nf -\fB/usr/sbin/cfgadm\fR [\fB-c\fR unconfigure] - [\fB-o\fR disable-at-bootp | enable-at-boot ] ac\fI#\fR:bank\fI#\fR ... -.fi - -.LP -.nf -\fB/usr/sbin/cfgadm\fR [\fB-v\fR] - [\fB-o\fR quick | normal | extended, [max_errors=\fI#\fR] ] \fB-t\fR ac\fI#\fR:bank\fI#\fR... -.fi - -.LP -.nf -\fB/usr/sbin/cfgadm\fR \fB-x\fR relocate-test ac\fI#\fR:bank\fI#\fR ... -.fi - -.LP -.nf -\fB/usr/sbin/cfgadm\fR [\fB-l\fR] \fB-o\fR disable-at-boot | enable-at-boot ac\fI#\fR:bank\fI#\fR ... -.fi - -.SH DESCRIPTION -.sp -.LP -The \fBac\fR hardware specific library -\fB/usr/platform/sun4u/lib/cfgadm/cfgadm_ac.so.1\fR provides the functionality -for configuring and unconfiguring memory banks on \fBE6X00\fR, \fBE5X00\fR, -\fBE4X00\fR and \fBE3X00\fR systems as part of the Dynamic Reconfiguration of -\fBCPU\fR/Memory boards using \fBcfgadm_sysctrl\fR(1M). -.sp -.LP -Memory banks appear as attachment points in the device tree. For each -\fBCPU\fR/Memory board, two attachment points are published, one for each bank -on the board: \fBbank0\fR and \fBbank1\fR. If the bank is unpopulated, the -receptacle state is empty. If the bank is populated, the receptacle state is -connected. The receptacle state of a memory bank can never be disconnected. The -occupant state of a connected memory bank can be configured or unconfigured. If -the occupant state is configured, the memory is in use by Solaris, if -unconfigured it is not. -.SH OPTIONS -.sp -.LP -Refer to \fBcfgadm\fR(1M) for complete descriptions of the command options. -.sp -.LP -The following options are supported: -.sp -.ne 2 -.na -\fB\fB-c\fR configure | unconfigure\fR -.ad -.sp .6 -.RS 4n -Change the occupant state. The \fBconfigure\fR argument ensures that the memory -is initialized and adds the memory to the Solaris memory pool. The -\fBunconfigure\fR argument removes the memory from use by Solaris. When a -\fBCPU\fR/Memory board is to be removed from a system, both banks of memory -must be unconfigured. -.sp -\fBcfgadm\fR refuses the \fBconfigure\fR operation if the memory on the board -is marked \fBdisabled-at-boot\fR (see \fBinfo\fR field), unless either the -\fB-f\fR (force) option or the enable at boot flag, (\fB-o\fR -\fBenable-at-boot\fR), is given. The configure operation takes a short time -proportional to the size of memory that must be initialized. -.sp -\fBcfgadm\fR refuses the \fBunconfigure\fR operation if there is not enough -uncommitted memory in the system (\fBVM viability\fR error) or if the bank to -be unconfigured has memory that can't be removed (\fBnon-relocatable pages\fR -error). The presence of non-relocatable pages is indicated by the word -\fBpermanent\fR in the \fBinfo\fR listing field. Removing memory from use by -Solaris may take a significant time due to factors such as system load and how -much paging to secondary storage is required. The \fBunconfigure\fR operation -can be cancelled at any time and the memory returned to the fully configured -state by interrupting the command invocation with a signal. The -\fBunconfigure\fR operation self-cancels if no memory can be removed within a -timeout period. The default timeout period of \fB60\fR seconds can be changed -using the \fB-o\fR \fBtimeout=\fR\fI#\fR option, with a value of \fB0\fR -disabling the timeout. -.RE - -.sp -.ne 2 -.na -\fB\fB-f\fR\fR -.ad -.sp .6 -.RS 4n -Force option. Use this option to override the block on configuring a memory -bank marked as disabled at boot in the non-volatile \fBdisabled-memory-list\fR -variable. See \fBPlatform Notes:Sun Enterprise 6x00/5x00/4x00/3x00 Systems\fR -.RE - -.sp -.ne 2 -.na -\fB\fB-l\fR\fR -.ad -.sp .6 -.RS 4n -List option. This option is supported as described in \fBcfgadm\fR(1M). -.sp -The type field is always \fImemory\fR. -.sp -The \fIinfo\fR field has the following information for empty banks: -.sp -.in +2 -.nf -slot# empty -.fi -.in -2 -.sp - -The slot# indicates the system slot into which the CPU/Memory board is -inserted. For example, if this were slot11 the attachment point for use with -cfgadm to manipulate the associated board would be sysctrl0:slot11. The info -field has the following information for connected banks: -.sp -.in +2 -.nf -slot# sizeMb|sizeGb [(sizeMb|sizeGb used)] base 0x### - [interleaved #-way] [disabled at boot] [permanent] -.fi -.in -2 -.sp - -The size of the bank is given in Mb or Gb as appropriate. If the memory is less -than completely used, the used size is reported. The physical base address is -given in hexadecimal. If the memory bank is interleaved with some other bank, -the interleave factor is reported. If the memory on the board is disabled at -boot using the non-volatile \fBdisabled-memory-list\fR variable, this is -reported. If the bank has memory that cannot be removed this is reported as -permanent. -.RE - -.sp -.ne 2 -.na -\fB\fB-o\fR disable-at-boot | enable-at-boot\fR -.ad -.sp .6 -.RS 4n -These options allow the state of the non-volatile disabled-memory-list variable -to be modified. These options can be used in conjunction with the issuing of a -\fB-c\fR option or with the explicit or implied listing command, -l, if no -command is required. Use of \fB-o\fR \fBenable-at-boot\fR with the -\fBconfigure\fR command to override the block on configuring memory on a board -in the disabled memory list. -.RE - -.sp -.ne 2 -.na -\fB\fB-o\fR extended | normal | quick\fR -.ad -.sp .6 -.RS 4n -Use with the \fB-t\fR option to specify test level. -.sp -The \fBnormal\fR test level ensures that each memory cell stores both a \fB0\fR -and a \fB1\fR, and checks that all cells are separately addressable. The -\fBquick\fR test level only does the \fB0\fRs and \fB1\fRs test, and typically -misses address line problems. The \fBextended\fR test uses patterns to test for -adjacent cell interference problems. The default test level is \fBnormal\fR. -See \fB-t\fR option. -.RE - -.sp -.ne 2 -.na -\fB\fB-o\fR max_errors=\fI#\fR\fR -.ad -.sp .6 -.RS 4n -Use with the \fB-t\fR option to specify the maximum number of allowed errors. -If not specified, a default of \fB32\fR is assumed. -.RE - -.sp -.ne 2 -.na -\fB\fB-o\fR timeout=\fI#\fR\fR -.ad -.sp .6 -.RS 4n -Use with the \fBunconfigure\fR command to set the self-cancelling timeout. The -default value is \fB60\fR and the unit is seconds. A value of \fB0\fR means no -timeout. -.RE - -.sp -.ne 2 -.na -\fB\fB-t\fR\fR -.ad -.sp .6 -.RS 4n -Test an unconfigured bank of memory. Specify the test level using the \fB-o\fR -\fBquick\fR | \fBnormal\fR | \fBextended\fR option. -.sp -\fBcfgadm\fR exits with a \fB0\fR (success) if the \fBtest\fR was able to run -on the memory bank. The result of the test is available in the condition for -the attachment point. -.RE - -.sp -.ne 2 -.na -\fB\fB-v\fR\fR -.ad -.sp .6 -.RS 4n -Verbose option. Use this option in combination with the \fB-t\fR option -to display detailed progress and results of tests. -.RE - -.sp -.ne 2 -.na -\fB\fB-x\fR relocate-test\fR -.ad -.sp .6 -.RS 4n -For all pages of memory in use on the specified memory bank, a relocation -operation as used in the unconfigure command is attempted. The success of this -operation does not guarantee that the bank can be unconfigured. Failure -indicates that it probably cannot be unconfigured. This option is for test -purposes only. -.RE - -.SH OPERANDS -.sp -.LP -The following operand is supported: -.sp -.ne 2 -.na -\fB\fIac#\fR:\fIbank#\fR\fR -.ad -.RS 13n -The attachment points for memory banks are published by instances of the -address controller (\fBac\fR) driver (\fIac#\fR). One instance of the \fBac\fR -driver is created for each system board, but only those instances associated -with \fBCPU\fR/Memory boards publish the two bank attachment points, bank0 and -bank1. -.sp - This form conforms to the logical \fBap_id\fR specification given in -\fBcfgadm\fR(1M). The corresponding physical \fBap_id\fRs are listed in the -\fBFILES\fR section. -.sp -The \fBac\fR driver instance numbering has no relation to the slot number for -the corresponding board. The full physical attachment point identifier has the -slot number incorporated into it as twice the slot number in hexadecimal -directly following the \fBfhc@\fR part. -.RE - -.SH FILES -.sp -.ne 2 -.na -\fB/devices/fhc@*,f8800000/ac@0,1000000:bank?\fR -.ad -.sp .6 -.RS 4n -attachment points -.RE - -.sp -.ne 2 -.na -\fB/usr/platform/sun4u/lib/cfgadm/cfgadm_ac.so.1\fR -.ad -.sp .6 -.RS 4n -hardware specific library file -.RE - -.SH SEE ALSO -.sp -.LP -\fBcfgadm\fR(1M), \fBcfgadm_sysctrl\fR(1M), \fBconfig_admin\fR(3CFGADM), -\fBattributes\fR(5) -.sp -.LP -\fBSun Enterprise 6x00, 5x00, 4x00 and 3x00 Systems Dynamic Reconfiguration -User's Guide\fR -.sp -.LP -\fBPlatform Notes:Sun Enterprise 6x00/5x00/4x00/3x00 Systems\fR -.SH NOTES -.sp -.LP -Refer to the \fBSun Enterprise 6x00, 5x00, 4x00 and 3x00 Systems Dynamic -Reconfiguration User's Guide\fR for additional details regarding dynamic -reconfiguration of EXX00 system CPU/Memory boards. diff --git a/usr/src/man/man1m/cfgadm_sysctrl.1m b/usr/src/man/man1m/cfgadm_sysctrl.1m deleted file mode 100644 index 0ea59a89da..0000000000 --- a/usr/src/man/man1m/cfgadm_sysctrl.1m +++ /dev/null @@ -1,337 +0,0 @@ -'\" te -.\" Copyright (c) 1999 Sun Microsystems, Inc. All Rights Reserved. -.\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License"). You may not use this file except in compliance with the License. -.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing. See the License for the specific language governing permissions and limitations under the License. -.\" When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE. If applicable, add the following below this CDDL HEADER, with the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner] -.TH CFGADM_SYSCTRL 1M "Mar 10, 1999" -.SH NAME -cfgadm_sysctrl \- EXX00 system board administration -.SH SYNOPSIS -.LP -.nf -\fB/usr/sbin/cfgadm\fR \fB-c\fR \fIfunction\fR [\fB-f\fR] - [\fB-o\fR disable-at-boot | enable-at-boot] [\fB-n\fR | \fB-y\fR] sysctrl0:slot# ... -.fi - -.LP -.nf -\fB/usr/sbin/cfgadm\fR \fB-x\fR quiesce-test sysctrl0:slot# -.fi - -.LP -.nf -\fB/usr/sbin/cfgadm\fR \fB-x\fR insert-test | remove-test sysctrl0:slot# ... -.fi - -.LP -.nf -\fB/usr/sbin/cfgadm\fR \fB-x\fR set-condition-test=# sysctrl0:slot# ... -.fi - -.LP -.nf -\fB/usr/sbin/cfgadm\fR [\fB-l\fR] - \fB-o\fR disable-at-boot | enable-at-boot sysctrl0:slot# ... -.fi - -.SH DESCRIPTION -.sp -.LP -The \fBsysctrl\fR hardware specific library -\fB/usr/platform/sun4u/lib/cfgadm/sysctrl.so.1\fR provides dynamic -reconfiguration functionality for configuring and disconnecting system boards -on \fBE6X00\fR, \fBE5X00\fR, \fBE4X00\fR, and \fBE3X00\fR systems. You can -insert both \fBI/O\fR and \fBCPU\fR boards into a slot on a running system that -is configured for Solaris without rebooting. You can also disconnect and remove -both types of boards from a running system without rebooting. -.sp -.LP -System slots appear as attachment points in the device tree, one attachment -point for each actual slot in the system chassis. If a board is not in a slot, -the receptacle state is \fBempty\fR. If a board is powered-off and ready to -remove, the receptacle state is \fBdisconnected\fR. If a board is powered-on -and is connected to the system bus, the receptacle state is \fBconnected\fR. -.sp -.LP - The occupant state is \fBunconfigured\fR when the receptacle state is -\fBempty\fR or \fBdisconnected\fR. The occupant state is either -\fBunconfigured\fR or \fBconfigured\fR when the receptacle state is -\fBconnected\fR. -.sp -.LP -In the \fBconfigured\fR state the devices on a board are available for use by -Solaris. In the \fBunconfigured\fR state, the devices on the board are not. -.sp -.LP -Inserting a board changes the receptacle state from \fBempty\fR to -\fBdisconnected\fR. Removing a board changes the receptacle state from -\fBdisconnected\fR to \fBempty\fR. Removing a board that is in the -\fBconnected\fR state crashes the operating system and can result in permanent -damage to the system. -.SH OPTIONS -.sp -.LP -Refer to \fBcfgadm\fR(1M) for a more complete description options. -.sp -.LP -The following options are supported: -.sp -.ne 2 -.na -\fB\fB-c\fR \fIfunction\fR\fR -.ad -.sp .6 -.RS 4n -Perform the state change function. Specify \fIfunction\fR as \fBconnect\fR, -\fBdisconnect\fR, \fBconfigure\fR or \fBunconfigure\fR. -.sp -.ne 2 -.na -\fBconfigure\fR -.ad -.RS 15n -Change the occupant state to \fBconfigure\fR. -.sp -If the receptacle state is \fBdisconnect\fRed, the \fBconfigure\fR function -first attempts to connect the receptacle. The \fBconfigure\fR function walks -the \fBOBP\fR device tree created as part of the \fBconnect\fR function and -creates the Solaris device tree nodes, attaching devices as required. For -\fBCPU\fR/Memory boards, \fBconfigure\fR adds \fBCPU\fRs to the \fBCPU\fR list -in the \fBpowered-off \fRstate. These are visible to the \fBpsrinfo\fR(1M) and -\fBpsradm\fR(1M) commands. Two memory attachment points are published for -CPU/memory boards. Use \fBmount\fR(1M) and \fBifconfig\fR(1M) to use \fBI/O\fR -devices on the new board. To use \fBCPU\fRs, use \fBpsradm\fR \fB-n\fR to -on-line the new processors. Use \fBcfgadm_ac\fR(1M) to test and configure the -memory banks. -.RE - -.sp -.ne 2 -.na -\fBconnect\fR -.ad -.RS 15n -Change the receptacle state to \fBconnect\fRed. -.sp -Changing the receptacle state requires that the system bus be frozen while the -bus signals are connected and the board tested. The bus is frozen by running a -\fBquiesce\fR operation which stops all process activity and suspends all -drivers. Because the \fBquiesce\fR operation and the subsequent resume can be -time consuming, and are not supported by all drivers, the \fB-x\fR -\fBquiesce-test\fR is provided. While the system bus is frozen, the board being -connected is tested by firmware. This operation takes a short time for -\fBI/O\fR boards and a significant time for \fBCPU\fR/Memory boards due to CPU -external cache testing. This does not provide memory testing. The user is -prompted for confirmation before proceeding with the \fBquiesce\fR. Use the -\fB-y\fR or \fB-n\fR option to override the prompt. The \fBconnect\fR operation -is refused if the board is marked as \fBdisabled-at-boot\fR, unless either the -force flag, \fB-f\fR, or the enable at boot flag, \fB-o\fR -\fBenable-at-boot\fR, is given. See \fB-l\fR. -.RE - -.sp -.ne 2 -.na -\fBdisconnect\fR -.ad -.RS 15n - Change the receptacle state to \fBdisconnect\fRed. -.sp -If the occupant state is \fBconfigure\fR, the \fBdisconnect\fR function first -attempts to unconfigure the occupant. The \fBdisconnect\fR operation does not -require a \fBquiesce\fR operation and operates quickly. The board is -powered-off ready for removal. -.RE - -.sp -.ne 2 -.na -\fBunconfigure\fR -.ad -.RS 15n -Change the occupant state to \fBunconfigure\fRed. -.sp -Devices on the board are made invisible to Solaris during this process. The -\fBI/O\fR devices on an \fBI/O\fR board are removed from the Solaris device -tree. Any device that is still in use stops the unconfigure process and be -reported as in use. The unconfigure operation must be retried after the device -is made non-busy. For \fBCPU\fR/Memory boards, the memory must have been -changed to the unconfigured state prior to issuing the board unconfigure -operation. The \fBCPU\fRs on the board are off-lined, powered off and removed -from the Solaris \fBCPU\fR list. \fBCPU\fRs that have processes bound to them -cannot be off-lined. See \fBpsradm\fR(1M), \fBpsrinfo\fR(1M), \fBpbind\fR(1M), -and \fBp_online\fR(2) for more information on off-lining \fBCPU\fRs. -.RE - -.RE - -.sp -.ne 2 -.na -\fB\fB-f\fR\fR -.ad -.sp .6 -.RS 4n - Force a block on connecting a board marked as \fBdisabled-at-boot\fR in the -non-volatile \fBdisabled-board-list\fR variable. See \fIPlatform Notes:Sun -Enterprise 6x00/5x00/4x00/3x00 Systems\fR -.RE - -.sp -.ne 2 -.na -\fB\fB-l\fR\fR -.ad -.sp .6 -.RS 4n -List options. Supported as described in \fBcfgadm\fR(1M)cfgadm(1M). -.sp -The \fItype\fR field can be one of \fBcpu/mem\fR, \fBmem\fR, \fBdual-sbus\fR, -\fBsbus-upa\fR, \fBdual-pci\fR, \fBsoc+sbus\fR, \fBsoc+upa\fR, \fBdisk\fR or -\fBunknown\fR. -.sp -The hardware-specific info field is set as follows:\fB [disabled at boot] -[non-detachable] [100 MHz capable] \fR -.sp -For \fBsbus-upa\fR and \fBsoc+upa\fR type boards, the following additional -information appears first: [\fBsingle buffered\fR \fBffb|double\fR -\fBbuffered\fR \fBffb|no\fR \fBffb installed\fR] For disk type boards, the -following additional information appears first: \fB{target: # | no disk} -{target: # | no disk}\fR -.RE - -.sp -.ne 2 -.na -\fB\fB-o\fR disable-at-boot | enable-at-boot\fR -.ad -.sp .6 -.RS 4n -Modify the state of the non\(emvolatile \fB disabled-board-list\fR variable. -Use this the \fB-o\fR option in conjunction with the \fB-c\fR \fIfunction\fR or -\fB-l\fR option. -.sp -Use \fB-o\fR \fBenable-at-boot\fR with the \fB-c\fR \fBconnect\fR to override a -block on connecting a \fBdisabled-at-boot\fR board. -.RE - -.sp -.ne 2 -.na -\fB\fB-x\fR insert-test | remove-test\fR -.ad -.sp .6 -.RS 4n -Perform a test. -.sp - Specify \fBremove-test\fR to change the driver state for the specified slot -from \fBdisconnected\fR to \fBempty\fR without the need for physically removing -the board during automated test sequences. -.sp -Specify \fBinsert-test\fR to change the driver state of a slot made to appear -empty using the \fBremove-test\fR command to the d\fBisconnected\fR state as if -it had been inserted. -.RE - -.sp -.ne 2 -.na -\fB\fB-x\fR quiesce-test sysctrl0:slot1\fR -.ad -.sp .6 -.RS 4n -Perform a test. -.sp -Allows the \fBquiesce\fR operation required for board connect operations to be -exercised. The execution of this test confirms that, with the current software -and hardware configuration, it is possible to quiesce the system. If a device -or process cannot be quiesced, its name is printed in an error message. Any -valid board attachment point can be used with this command, but since all -systems have a slot1 the given form is recommended. -.RE - -.sp -.ne 2 -.na -\fB\fB-x\fR set-condition-test=# \fR -.ad -.sp .6 -.RS 4n -Perform a test. -.sp -Allows the condition of a system board attachment point to be set for testing -the policy logic for state change commands. The new setting is given as a -number indicating one of the following condition values: -.sp -.in +2 -.nf -0 unknown -1 ok -2 failing -3 failed -4 unusable -.fi -.in -2 -.sp - -.RE - -.SH OPERANDS -.sp -.LP -The following operand is supported: -.sp -.ne 2 -.na -\fBsysctrl0:slot\fI#\fR\fR -.ad -.RS 28n -The attachment points for boards on \fBEXX00\fR systems are published by -instance \fB0\fR of the \fBsysctrl\fR driver (\fBsysctrl0\fR). The names of the -attachment points are numbered from \fBslot0\fR through \fBslot15\fR. Specify -\fI#\fR as a number between \fB0\fR and \fB15\fR, indicating the slot number. -This form conforms to the logical \fBap_id\fR specification given in -\fBcfgadm\fR(1M). The corresponding physical \fBap_id\fRs are listed in the -\fBFILES\fR section. -.RE - -.SH FILES -.sp -.ne 2 -.na -\fB/usr/platform/sun4u/lib/cfgadm/sysctrl.so.1\fR -.ad -.sp .6 -.RS 4n -Hardware specific library -.RE - -.sp -.ne 2 -.na -\fB/devices/central@1f,0/fhc@0,f8800000/clock-board@0,900000:slot*\fR -.ad -.sp .6 -.RS 4n -Attachment Points -.RE - -.SH SEE ALSO -.sp -.LP -\fBcfgadm\fR(1M), \fBcfgadm_ac\fR(1M), \fBifconfig\fR(1M), \fBmount\fR(1M), -\fBpbind\fR(1M), \fBpsradm\fR(1M), , \fBpsrinfo\fR(1M), -\fBconfig_admin\fR(3CFGADM), \fBattributes\fR(5) -.sp -.LP -\fISun Enterprise 6x00, 5x00, 4x00 and 3x00 Systems Dynamic Reconfiguration -User's Guide\fR -.sp -.LP -\fIPlatform Notes:Sun Enterprise 6x00/5x00/4x00/3x00 Systems\fR -.SH NOTES -.sp -.LP -Refer to the \fISun Enterprise 6x00, 5x00, 4x00 and 3x00 Systems Dynamic -Reconfiguration User's Guide\fR for additional details regarding dynamic -reconfiguration of EXX00 system CPU/Memory boards. diff --git a/usr/src/pkg/manifests/SUNWcs.man1m.inc b/usr/src/pkg/manifests/SUNWcs.man1m.inc index 3c900d36bf..ac241ac262 100644 --- a/usr/src/pkg/manifests/SUNWcs.man1m.inc +++ b/usr/src/pkg/manifests/SUNWcs.man1m.inc @@ -36,7 +36,6 @@ file path=usr/share/man/man1m/bootadm.1m file path=usr/share/man/man1m/busstat.1m file path=usr/share/man/man1m/captoinfo.1m file path=usr/share/man/man1m/cfgadm.1m -file path=usr/share/man/man1m/cfgadm_ac.1m file path=usr/share/man/man1m/cfgadm_cardbus.1m file path=usr/share/man/man1m/cfgadm_fp.1m file path=usr/share/man/man1m/cfgadm_ib.1m @@ -44,7 +43,6 @@ file path=usr/share/man/man1m/cfgadm_pci.1m file path=usr/share/man/man1m/cfgadm_sata.1m file path=usr/share/man/man1m/cfgadm_sbd.1m file path=usr/share/man/man1m/cfgadm_scsi.1m -file path=usr/share/man/man1m/cfgadm_sysctrl.1m file path=usr/share/man/man1m/cfgadm_usb.1m file path=usr/share/man/man1m/chroot.1m file path=usr/share/man/man1m/clear_locks.1m -- cgit v1.2.3 From a52121ea720d327228a95e9d0c4a426339f08c7f Mon Sep 17 00:00:00 2001 From: Chunwei Chen Date: Thu, 30 Jan 2020 12:57:07 -0700 Subject: 12260 Fix zpool history unbounded memory usage Portions contributed by: Jerry Jelinek Reviewed by: Tom Caputi Reviewed by: Matt Ahrens Reviewed by: Igor Kozhukhov Reviewed by: Brian Behlendorf Reviewed by: Sanjay Nadkarni Approved by: Dan McDonald --- usr/src/cmd/zpool/zpool_main.c | 44 +++++++++++++++++++++------------ usr/src/lib/libzfs/common/libzfs.h | 3 ++- usr/src/lib/libzfs/common/libzfs_pool.c | 22 +++++++++-------- 3 files changed, 42 insertions(+), 27 deletions(-) diff --git a/usr/src/cmd/zpool/zpool_main.c b/usr/src/cmd/zpool/zpool_main.c index 50935f4112..0a8b06db2f 100644 --- a/usr/src/cmd/zpool/zpool_main.c +++ b/usr/src/cmd/zpool/zpool_main.c @@ -6529,24 +6529,12 @@ typedef struct hist_cbdata { boolean_t internal; } hist_cbdata_t; -/* - * Print out the command history for a specific pool. - */ -static int -get_history_one(zpool_handle_t *zhp, void *data) +static void +print_history_records(nvlist_t *nvhis, hist_cbdata_t *cb) { - nvlist_t *nvhis; nvlist_t **records; uint_t numrecords; - int ret, i; - hist_cbdata_t *cb = (hist_cbdata_t *)data; - - cb->first = B_FALSE; - - (void) printf(gettext("History for '%s':\n"), zpool_get_name(zhp)); - - if ((ret = zpool_get_history(zhp, &nvhis)) != 0) - return (ret); + int i; verify(nvlist_lookup_nvlist_array(nvhis, ZPOOL_HIST_RECORD, &records, &numrecords) == 0); @@ -6647,8 +6635,32 @@ get_history_one(zpool_handle_t *zhp, void *data) (void) printf("]"); (void) printf("\n"); } +} + +/* + * Print out the command history for a specific pool. + */ +static int +get_history_one(zpool_handle_t *zhp, void *data) +{ + nvlist_t *nvhis; + int ret; + hist_cbdata_t *cb = (hist_cbdata_t *)data; + uint64_t off = 0; + boolean_t eof = B_FALSE; + + cb->first = B_FALSE; + + (void) printf(gettext("History for '%s':\n"), zpool_get_name(zhp)); + + while (!eof) { + if ((ret = zpool_get_history(zhp, &nvhis, &off, &eof)) != 0) + return (ret); + + print_history_records(nvhis, cb); + nvlist_free(nvhis); + } (void) printf("\n"); - nvlist_free(nvhis); return (ret); } diff --git a/usr/src/lib/libzfs/common/libzfs.h b/usr/src/lib/libzfs/common/libzfs.h index 36b70c11fb..d7411f0b85 100644 --- a/usr/src/lib/libzfs/common/libzfs.h +++ b/usr/src/lib/libzfs/common/libzfs.h @@ -459,7 +459,8 @@ typedef enum { extern char *zpool_vdev_name(libzfs_handle_t *, zpool_handle_t *, nvlist_t *, int name_flags); extern int zpool_upgrade(zpool_handle_t *, uint64_t); -extern int zpool_get_history(zpool_handle_t *, nvlist_t **); +extern int zpool_get_history(zpool_handle_t *, nvlist_t **, uint64_t *, + boolean_t *); extern int zpool_history_unpack(char *, uint64_t, uint64_t *, nvlist_t ***, uint_t *); extern void zpool_obj_to_path(zpool_handle_t *, uint64_t, uint64_t, char *, diff --git a/usr/src/lib/libzfs/common/libzfs_pool.c b/usr/src/lib/libzfs/common/libzfs_pool.c index b7c95489c8..20894d450a 100644 --- a/usr/src/lib/libzfs/common/libzfs_pool.c +++ b/usr/src/lib/libzfs/common/libzfs_pool.c @@ -4342,33 +4342,37 @@ zpool_history_unpack(char *buf, uint64_t bytes_read, uint64_t *leftover, * Retrieve the command history of a pool. */ int -zpool_get_history(zpool_handle_t *zhp, nvlist_t **nvhisp) +zpool_get_history(zpool_handle_t *zhp, nvlist_t **nvhisp, uint64_t *off, + boolean_t *eof) { char *buf; int buflen = 128 * 1024; - uint64_t off = 0; nvlist_t **records = NULL; uint_t numrecords = 0; - int err, i; + int err = 0, i; + uint64_t start = *off; buf = malloc(buflen); if (buf == NULL) return (ENOMEM); - do { + /* process about 1MB a time */ + while (*off - start < 1024 * 1024) { uint64_t bytes_read = buflen; uint64_t leftover; - if ((err = get_history(zhp, buf, &off, &bytes_read)) != 0) + if ((err = get_history(zhp, buf, off, &bytes_read)) != 0) break; /* if nothing else was read in, we're at EOF, just return */ - if (!bytes_read) + if (!bytes_read) { + *eof = B_TRUE; break; + } if ((err = zpool_history_unpack(buf, bytes_read, &leftover, &records, &numrecords)) != 0) break; - off -= leftover; + *off -= leftover; if (leftover == bytes_read) { /* * no progress made, because buffer is not big enough @@ -4380,9 +4384,7 @@ zpool_get_history(zpool_handle_t *zhp, nvlist_t **nvhisp) if (buf == NULL) return (ENOMEM); } - - /* CONSTCOND */ - } while (1); + } free(buf); -- cgit v1.2.3 From 8b06eaf6acc31eaadddc0fec3df9d1a4294b7cc2 Mon Sep 17 00:00:00 2001 From: Jason King Date: Fri, 31 Jan 2020 13:21:59 -0600 Subject: 12267 zfs '::abuf_find' dcmd is broken Reviewed by: Jerry Jelinek Reviewed by: Kody Kantor Reviewed by: Igor Kozhukhov Approved by: Dan McDonald --- usr/src/cmd/mdb/common/modules/zfs/zfs.c | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/usr/src/cmd/mdb/common/modules/zfs/zfs.c b/usr/src/cmd/mdb/common/modules/zfs/zfs.c index 431dce10b3..05caf276cd 100644 --- a/usr/src/cmd/mdb/common/modules/zfs/zfs.c +++ b/usr/src/cmd/mdb/common/modules/zfs/zfs.c @@ -1006,13 +1006,17 @@ abuf_find_cb(uintptr_t addr, const void *unknown, void *arg) return (WALK_NEXT); } +typedef struct mdb_arc_state { + uintptr_t arcs_list[ARC_BUFC_NUMTYPES]; +} mdb_arc_state_t; + /* ARGSUSED */ static int abuf_find(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) { abuf_find_data_t data; GElf_Sym sym; - int i; + int i, j; const char *syms[] = { "ARC_mru", "ARC_mru_ghost", @@ -1042,15 +1046,31 @@ abuf_find(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) } for (i = 0; i < sizeof (syms) / sizeof (syms[0]); i++) { + mdb_arc_state_t mas; + if (mdb_lookup_by_obj(ZFS_OBJ_NAME, syms[i], &sym)) { mdb_warn("can't find symbol %s", syms[i]); return (DCMD_ERR); } - if (mdb_pwalk("list", abuf_find_cb, &data, sym.st_value) != 0) { - mdb_warn("can't walk %s", syms[i]); + if (mdb_ctf_vread(&mas, "arc_state_t", "mdb_arc_state_t", + sym.st_value, 0) != 0) { + mdb_warn("can't read arcs_list of %s", syms[i]); return (DCMD_ERR); } + + for (j = 0; j < ARC_BUFC_NUMTYPES; j++) { + uintptr_t addr = mas.arcs_list[j]; + + if (addr == 0) + continue; + + if (mdb_pwalk("multilist", abuf_find_cb, &data, + addr) != 0) { + mdb_warn("can't walk %s", syms[i]); + return (DCMD_ERR); + } + } } return (DCMD_OK); -- cgit v1.2.3 From 8bd53a1ca9fba2d5585cc775422e4d1db161bf96 Mon Sep 17 00:00:00 2001 From: Andy Fiddaman Date: Mon, 27 Jan 2020 22:05:34 +0000 Subject: 12255 proc_get_fdinfo() crash if fdinfo file grows Reviewed by: John Levon Reviewed by: Robert Mustacchi Approved by: Dan McDonald --- usr/src/lib/libproc/common/proc_fd.c | 6 +++++- usr/src/man/man3proc/proc_get_fdinfo.3proc | 3 ++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/usr/src/lib/libproc/common/proc_fd.c b/usr/src/lib/libproc/common/proc_fd.c index e491934c16..6d5c09315a 100644 --- a/usr/src/lib/libproc/common/proc_fd.c +++ b/usr/src/lib/libproc/common/proc_fd.c @@ -155,7 +155,8 @@ proc_get_fdinfo(pid_t pid, int fd) break; } - if ((l = read(ifd, info, st.st_size)) == -1) { + if (lseek(ifd, 0, SEEK_SET) != 0 || + (l = read(ifd, info, st.st_size)) == -1) { err = errno; break; } @@ -164,6 +165,9 @@ proc_get_fdinfo(pid_t pid, int fd) off = offsetof(prfdinfo_t, pr_misc); + if (l < off + sizeof (pr_misc_header_t)) + continue; + while (off <= l - sizeof (pr_misc_header_t)) { pr_misc_header_t *misc; diff --git a/usr/src/man/man3proc/proc_get_fdinfo.3proc b/usr/src/man/man3proc/proc_get_fdinfo.3proc index b85eef16f9..1985230f4c 100644 --- a/usr/src/man/man3proc/proc_get_fdinfo.3proc +++ b/usr/src/man/man3proc/proc_get_fdinfo.3proc @@ -11,7 +11,7 @@ .\" .\" Copyright 2020 OmniOS Community Edition (OmniOSce) Association. .\" -.Dd January 6, 2020 +.Dd January 29, 2020 .Dt PROC_GET_FDINFO 3PROC .Os .Sh NAME @@ -76,6 +76,7 @@ In addition to the errors listed below, the .Fn proc_get_fdinfo function may fail for the same reasons as the .Xr fstat 2 , +.Xr lseek 2 , .Xr malloc 3C , .Xr open 2 , and -- cgit v1.2.3