diff options
Diffstat (limited to 'sys')
-rw-r--r-- | sys/amd64/acpica/acpi_wakeup.c | 4 | ||||
-rw-r--r-- | sys/arm64/include/armreg.h | 5 | ||||
-rw-r--r-- | sys/arm64/vmm/arm64.h | 1 | ||||
-rw-r--r-- | sys/arm64/vmm/vmm.c | 34 | ||||
-rw-r--r-- | sys/cam/ata/ata_da.c | 9 | ||||
-rw-r--r-- | sys/cam/nvme/nvme_da.c | 5 | ||||
-rw-r--r-- | sys/compat/linuxkpi/common/src/linux_acpi.c | 33 | ||||
-rw-r--r-- | sys/dev/acpica/acpi.c | 6 | ||||
-rw-r--r-- | sys/dev/acpica/acpi_timer.c | 11 | ||||
-rw-r--r-- | sys/dev/ahci/ahci_pci.c | 46 | ||||
-rw-r--r-- | sys/dev/vt/vt_core.c | 8 | ||||
-rw-r--r-- | sys/dev/xen/control/control.c | 7 | ||||
-rw-r--r-- | sys/fs/nullfs/null.h | 2 | ||||
-rw-r--r-- | sys/fs/nullfs/null_subr.c | 20 | ||||
-rw-r--r-- | sys/fs/nullfs/null_vnops.c | 7 | ||||
-rw-r--r-- | sys/i386/acpica/acpi_wakeup.c | 4 | ||||
-rw-r--r-- | sys/kern/kern_exit.c | 46 | ||||
-rw-r--r-- | sys/kern/kern_mutex.c | 23 | ||||
-rw-r--r-- | sys/kern/vfs_vnops.c | 22 | ||||
-rw-r--r-- | sys/netgraph/netflow/netflow.c | 6 | ||||
-rw-r--r-- | sys/netinet/sctp_lock_bsd.h | 6 | ||||
-rw-r--r-- | sys/netinet/tcp_syncache.c | 5 | ||||
-rw-r--r-- | sys/netinet6/in6.c | 14 | ||||
-rw-r--r-- | sys/netlink/netlink_snl.h | 6 | ||||
-rw-r--r-- | sys/sys/eventhandler.h | 3 | ||||
-rw-r--r-- | sys/sys/mutex.h | 6 | ||||
-rw-r--r-- | sys/x86/x86/mca.c | 92 |
27 files changed, 264 insertions, 167 deletions
diff --git a/sys/amd64/acpica/acpi_wakeup.c b/sys/amd64/acpica/acpi_wakeup.c index 99565fbb69ca..8cada2f4f911 100644 --- a/sys/amd64/acpica/acpi_wakeup.c +++ b/sys/amd64/acpica/acpi_wakeup.c @@ -74,7 +74,7 @@ extern int acpi_susp_bounce; extern struct susppcb **susppcbs; static cpuset_t suspcpus; -static void acpi_stop_beep(void *); +static void acpi_stop_beep(void *, enum power_stype); static int acpi_wakeup_ap(struct acpi_softc *, int); static void acpi_wakeup_cpus(struct acpi_softc *); @@ -88,7 +88,7 @@ static void acpi_wakeup_cpus(struct acpi_softc *); } while (0) static void -acpi_stop_beep(void *arg) +acpi_stop_beep(void *arg, enum power_stype stype) { if (acpi_resume_beep != 0) diff --git a/sys/arm64/include/armreg.h b/sys/arm64/include/armreg.h index da051e8f7c8a..393d6d89da0c 100644 --- a/sys/arm64/include/armreg.h +++ b/sys/arm64/include/armreg.h @@ -2180,6 +2180,7 @@ #define OSLAR_EL1_CRn 1 #define OSLAR_EL1_CRm 0 #define OSLAR_EL1_op2 4 +#define OSLAR_OSLK (0x1ul << 0) /* OSLSR_EL1 */ #define OSLSR_EL1_op0 2 @@ -2187,6 +2188,10 @@ #define OSLSR_EL1_CRn 1 #define OSLSR_EL1_CRm 1 #define OSLSR_EL1_op2 4 +#define OSLSR_OSLM_1 (0x1ul << 3) +#define OSLSR_nTT (0x1ul << 2) +#define OSLSR_OSLK (0x1ul << 1) +#define OSLSR_OSLM_0 (0x1ul << 0) /* PAR_EL1 - Physical Address Register */ #define PAR_F_SHIFT 0 diff --git a/sys/arm64/vmm/arm64.h b/sys/arm64/vmm/arm64.h index 334b795832a3..f9b74aef7188 100644 --- a/sys/arm64/vmm/arm64.h +++ b/sys/arm64/vmm/arm64.h @@ -119,6 +119,7 @@ struct hypctx { struct vgic_v3_regs vgic_v3_regs; struct vgic_v3_cpu *vgic_cpu; bool has_exception; + bool dbg_oslock; }; struct hyp { diff --git a/sys/arm64/vmm/vmm.c b/sys/arm64/vmm/vmm.c index 1dcefa1489e9..a551a2807183 100644 --- a/sys/arm64/vmm/vmm.c +++ b/sys/arm64/vmm/vmm.c @@ -651,6 +651,33 @@ vmm_reg_wi(struct vcpu *vcpu, uint64_t wval, void *arg) return (0); } +static int +vmm_write_oslar_el1(struct vcpu *vcpu, uint64_t wval, void *arg) +{ + struct hypctx *hypctx; + + hypctx = vcpu_get_cookie(vcpu); + /* All other fields are RES0 & we don't do anything with this */ + /* TODO: Disable access to other debug state when locked */ + hypctx->dbg_oslock = (wval & OSLAR_OSLK) == OSLAR_OSLK; + return (0); +} + +static int +vmm_read_oslsr_el1(struct vcpu *vcpu, uint64_t *rval, void *arg) +{ + struct hypctx *hypctx; + uint64_t val; + + hypctx = vcpu_get_cookie(vcpu); + val = OSLSR_OSLM_1; + if (hypctx->dbg_oslock) + val |= OSLSR_OSLK; + *rval = val; + + return (0); +} + static const struct vmm_special_reg vmm_special_regs[] = { #define SPECIAL_REG(_reg, _read, _write) \ { \ @@ -707,6 +734,13 @@ static const struct vmm_special_reg vmm_special_regs[] = { SPECIAL_REG(CNTP_TVAL_EL0, vtimer_phys_tval_read, vtimer_phys_tval_write), SPECIAL_REG(CNTPCT_EL0, vtimer_phys_cnt_read, vtimer_phys_cnt_write), + + /* Debug registers */ + SPECIAL_REG(DBGPRCR_EL1, vmm_reg_raz, vmm_reg_wi), + SPECIAL_REG(OSDLR_EL1, vmm_reg_raz, vmm_reg_wi), + /* TODO: Exceptions on invalid access */ + SPECIAL_REG(OSLAR_EL1, vmm_reg_raz, vmm_write_oslar_el1), + SPECIAL_REG(OSLSR_EL1, vmm_read_oslsr_el1, vmm_reg_wi), #undef SPECIAL_REG }; diff --git a/sys/cam/ata/ata_da.c b/sys/cam/ata/ata_da.c index 1facab47473c..0d844a6fbf9e 100644 --- a/sys/cam/ata/ata_da.c +++ b/sys/cam/ata/ata_da.c @@ -44,6 +44,7 @@ #include <sys/malloc.h> #include <sys/endian.h> #include <sys/cons.h> +#include <sys/power.h> #include <sys/proc.h> #include <sys/reboot.h> #include <sys/sbuf.h> @@ -878,8 +879,8 @@ static int adaerror(union ccb *ccb, uint32_t cam_flags, uint32_t sense_flags); static callout_func_t adasendorderedtag; static void adashutdown(void *arg, int howto); -static void adasuspend(void *arg); -static void adaresume(void *arg); +static void adasuspend(void *arg, enum power_stype stype); +static void adaresume(void *arg, enum power_stype stype); #ifndef ADA_DEFAULT_TIMEOUT #define ADA_DEFAULT_TIMEOUT 30 /* Timeout in seconds */ @@ -3747,7 +3748,7 @@ adashutdown(void *arg, int howto) } static void -adasuspend(void *arg) +adasuspend(void *arg, enum power_stype stype) { adaflush(); @@ -3760,7 +3761,7 @@ adasuspend(void *arg) } static void -adaresume(void *arg) +adaresume(void *arg, enum power_stype stype) { struct cam_periph *periph; struct ada_softc *softc; diff --git a/sys/cam/nvme/nvme_da.c b/sys/cam/nvme/nvme_da.c index 1c0d5e8381d8..9c4707da482c 100644 --- a/sys/cam/nvme/nvme_da.c +++ b/sys/cam/nvme/nvme_da.c @@ -43,6 +43,7 @@ #include <sys/eventhandler.h> #include <sys/malloc.h> #include <sys/cons.h> +#include <sys/power.h> #include <sys/proc.h> #include <sys/reboot.h> #include <sys/sbuf.h> @@ -159,7 +160,7 @@ static void ndadone(struct cam_periph *periph, static int ndaerror(union ccb *ccb, uint32_t cam_flags, uint32_t sense_flags); static void ndashutdown(void *arg, int howto); -static void ndasuspend(void *arg); +static void ndasuspend(void *arg, enum power_stype stype); #ifndef NDA_DEFAULT_SEND_ORDERED #define NDA_DEFAULT_SEND_ORDERED 1 @@ -1365,7 +1366,7 @@ ndashutdown(void *arg, int howto) } static void -ndasuspend(void *arg) +ndasuspend(void *arg, enum power_stype stype) { ndaflush(); diff --git a/sys/compat/linuxkpi/common/src/linux_acpi.c b/sys/compat/linuxkpi/common/src/linux_acpi.c index 43783bb8727b..c7d62c745c7e 100644 --- a/sys/compat/linuxkpi/common/src/linux_acpi.c +++ b/sys/compat/linuxkpi/common/src/linux_acpi.c @@ -33,6 +33,7 @@ #include <sys/bus.h> #include <sys/eventhandler.h> #include <sys/kernel.h> +#include <sys/power.h> #include <contrib/dev/acpica/include/acpi.h> #include <dev/acpica/acpivar.h> @@ -118,20 +119,32 @@ acpi_evaluate_dsm(ACPI_HANDLE ObjHandle, const guid_t *guid, } static void -linux_handle_power_suspend_event(void *arg __unused) +linux_handle_power_suspend_event(void *arg __unused, enum power_stype stype) { - /* - * Only support S3 for now. - * acpi_sleep_event isn't always called so we use power_suspend_early - * instead which means we don't know what state we're switching to. - * TODO: Make acpi_sleep_event consistent - */ - linux_acpi_target_sleep_state = ACPI_STATE_S3; - pm_suspend_target_state = PM_SUSPEND_MEM; + switch (stype) { + case POWER_STYPE_SUSPEND_TO_IDLE: + /* + * XXX: obiwac Not 100% sure this is correct, but + * acpi_target_sleep_state does seem to be set to + * ACPI_STATE_S3 during s2idle on Linux. + */ + linux_acpi_target_sleep_state = ACPI_STATE_S3; + pm_suspend_target_state = PM_SUSPEND_TO_IDLE; + break; + case POWER_STYPE_SUSPEND_TO_MEM: + linux_acpi_target_sleep_state = ACPI_STATE_S3; + pm_suspend_target_state = PM_SUSPEND_MEM; + break; + default: + printf("%s: sleep type %d not yet supported\n", + __func__, stype); + break; + } } static void -linux_handle_power_resume_event(void *arg __unused) +linux_handle_power_resume_event(void *arg __unused, + enum power_stype stype __unused) { linux_acpi_target_sleep_state = ACPI_STATE_S0; pm_suspend_target_state = PM_SUSPEND_ON; diff --git a/sys/dev/acpica/acpi.c b/sys/dev/acpica/acpi.c index 7f9ca6e39df8..3f0a7b40245d 100644 --- a/sys/dev/acpica/acpi.c +++ b/sys/dev/acpica/acpi.c @@ -3468,10 +3468,10 @@ acpi_EnterSleepState(struct acpi_softc *sc, enum power_stype stype) return_ACPI_STATUS (AE_OK); } - EVENTHANDLER_INVOKE(power_suspend_early); + EVENTHANDLER_INVOKE(power_suspend_early, stype); stop_all_proc(); suspend_all_fs(); - EVENTHANDLER_INVOKE(power_suspend); + EVENTHANDLER_INVOKE(power_suspend, stype); #ifdef EARLY_AP_STARTUP MPASS(mp_ncpus == 1 || smp_started); @@ -3632,7 +3632,7 @@ backout: resume_all_fs(); resume_all_proc(); - EVENTHANDLER_INVOKE(power_resume); + EVENTHANDLER_INVOKE(power_resume, stype); /* Allow another sleep request after a while. */ callout_schedule(&acpi_sleep_timer, hz * ACPI_MINIMUM_AWAKETIME); diff --git a/sys/dev/acpica/acpi_timer.c b/sys/dev/acpica/acpi_timer.c index 3d51a4211b80..b20912e2f5fb 100644 --- a/sys/dev/acpica/acpi_timer.c +++ b/sys/dev/acpica/acpi_timer.c @@ -34,6 +34,7 @@ #include <sys/module.h> #include <sys/sysctl.h> #include <sys/timetc.h> +#include <sys/power.h> #include <machine/bus.h> #include <machine/resource.h> @@ -69,8 +70,10 @@ bool acpi_timer_disabled = false; static void acpi_timer_identify(driver_t *driver, device_t parent); static int acpi_timer_probe(device_t dev); static int acpi_timer_attach(device_t dev); -static void acpi_timer_resume_handler(struct timecounter *); -static void acpi_timer_suspend_handler(struct timecounter *); +static void acpi_timer_resume_handler(struct timecounter *, + enum power_stype); +static void acpi_timer_suspend_handler(struct timecounter *, + enum power_stype); static u_int acpi_timer_get_timecount(struct timecounter *tc); static u_int acpi_timer_get_timecount_safe(struct timecounter *tc); static int acpi_timer_sysctl_freq(SYSCTL_HANDLER_ARGS); @@ -235,7 +238,7 @@ acpi_timer_attach(device_t dev) } static void -acpi_timer_resume_handler(struct timecounter *newtc) +acpi_timer_resume_handler(struct timecounter *newtc, enum power_stype stype) { struct timecounter *tc; @@ -251,7 +254,7 @@ acpi_timer_resume_handler(struct timecounter *newtc) } static void -acpi_timer_suspend_handler(struct timecounter *newtc) +acpi_timer_suspend_handler(struct timecounter *newtc, enum power_stype stype) { struct timecounter *tc; diff --git a/sys/dev/ahci/ahci_pci.c b/sys/dev/ahci/ahci_pci.c index 82f56fc0d19e..2b4cb37275a6 100644 --- a/sys/dev/ahci/ahci_pci.c +++ b/sys/dev/ahci/ahci_pci.c @@ -467,28 +467,6 @@ ahci_ata_probe(device_t dev) } static int -ahci_pci_read_msix_bars(device_t dev, uint8_t *table_bar, uint8_t *pba_bar) -{ - int cap_offset = 0, ret; - uint32_t val; - - if ((table_bar == NULL) || (pba_bar == NULL)) - return (EINVAL); - - ret = pci_find_cap(dev, PCIY_MSIX, &cap_offset); - if (ret != 0) - return (EINVAL); - - val = pci_read_config(dev, cap_offset + PCIR_MSIX_TABLE, 4); - *table_bar = PCIR_BAR(val & PCIM_MSIX_BIR_MASK); - - val = pci_read_config(dev, cap_offset + PCIR_MSIX_PBA, 4); - *pba_bar = PCIR_BAR(val & PCIM_MSIX_BIR_MASK); - - return (0); -} - -static int ahci_pci_attach(device_t dev) { struct ahci_controller *ctlr = device_get_softc(dev); @@ -496,7 +474,6 @@ ahci_pci_attach(device_t dev) uint32_t devid = pci_get_devid(dev); uint8_t revid = pci_get_revid(dev); int msi_count, msix_count; - uint8_t table_bar = 0, pba_bar = 0; uint32_t caps, pi; msi_count = pci_msi_count(dev); @@ -584,20 +561,11 @@ ahci_pci_attach(device_t dev) if (ctlr->quirks & AHCI_Q_NOMSIX) msix_count = 0; - /* Read MSI-x BAR IDs if supported */ - if (msix_count > 0) { - error = ahci_pci_read_msix_bars(dev, &table_bar, &pba_bar); - if (error == 0) { - ctlr->r_msix_tab_rid = table_bar; - ctlr->r_msix_pba_rid = pba_bar; - } else { - /* Failed to read BARs, disable MSI-x */ - msix_count = 0; - } - } - /* Allocate resources for MSI-x table and PBA */ if (msix_count > 0) { + ctlr->r_msix_tab_rid = pci_msix_table_bar(dev); + ctlr->r_msix_pba_rid = pci_msix_pba_bar(dev); + /* * Allocate new MSI-x table only if not * allocated before. @@ -608,8 +576,8 @@ ahci_pci_attach(device_t dev) ctlr->r_msix_table = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &ctlr->r_msix_tab_rid, RF_ACTIVE); if (ctlr->r_msix_table == NULL) { - ahci_free_mem(dev); - return (ENXIO); + msix_count = 0; + goto no_msix; } } @@ -624,12 +592,12 @@ ahci_pci_attach(device_t dev) ctlr->r_msix_pba = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &ctlr->r_msix_pba_rid, RF_ACTIVE); if (ctlr->r_msix_pba == NULL) { - ahci_free_mem(dev); - return (ENXIO); + msix_count = 0; } } } +no_msix: pci_enable_busmaster(dev); /* Reset controller */ if ((error = ahci_pci_ctlr_reset(dev)) != 0) { diff --git a/sys/dev/vt/vt_core.c b/sys/dev/vt/vt_core.c index b51ef6766de4..bcf67ddc9689 100644 --- a/sys/dev/vt/vt_core.c +++ b/sys/dev/vt/vt_core.c @@ -195,8 +195,8 @@ static void vt_update_static(void *); #ifndef SC_NO_CUTPASTE static void vt_mouse_paste(void); #endif -static void vt_suspend_handler(void *priv); -static void vt_resume_handler(void *priv); +static void vt_suspend_handler(void *priv, enum power_stype stype); +static void vt_resume_handler(void *priv, enum power_stype stype); SET_DECLARE(vt_drv_set, struct vt_driver); @@ -3330,7 +3330,7 @@ vt_replace_backend(const struct vt_driver *drv, void *softc) } static void -vt_suspend_handler(void *priv) +vt_suspend_handler(void *priv, enum power_stype stype) { struct vt_device *vd; @@ -3341,7 +3341,7 @@ vt_suspend_handler(void *priv) } static void -vt_resume_handler(void *priv) +vt_resume_handler(void *priv, enum power_stype stype) { struct vt_device *vd; diff --git a/sys/dev/xen/control/control.c b/sys/dev/xen/control/control.c index 123df4992894..2c61b48c0451 100644 --- a/sys/dev/xen/control/control.c +++ b/sys/dev/xen/control/control.c @@ -91,6 +91,7 @@ #include <sys/smp.h> #include <sys/eventhandler.h> #include <sys/timetc.h> +#include <sys/power.h> #include <geom/geom.h> @@ -175,12 +176,12 @@ xctrl_suspend(void) cpuset_t cpu_suspend_map; #endif - EVENTHANDLER_INVOKE(power_suspend_early); + EVENTHANDLER_INVOKE(power_suspend_early, POWER_STYPE_SUSPEND_TO_MEM); xs_lock(); stop_all_proc(); xs_unlock(); suspend_all_fs(); - EVENTHANDLER_INVOKE(power_suspend); + EVENTHANDLER_INVOKE(power_suspend, POWER_STYPE_SUSPEND_TO_MEM); #ifdef EARLY_AP_STARTUP MPASS(mp_ncpus == 1 || smp_started); @@ -297,7 +298,7 @@ xctrl_suspend(void) resume_all_fs(); resume_all_proc(); - EVENTHANDLER_INVOKE(power_resume); + EVENTHANDLER_INVOKE(power_resume, POWER_STYPE_SUSPEND_TO_MEM); if (bootverbose) printf("System resumed after suspension\n"); diff --git a/sys/fs/nullfs/null.h b/sys/fs/nullfs/null.h index aa7a689bec34..ad3f7779e108 100644 --- a/sys/fs/nullfs/null.h +++ b/sys/fs/nullfs/null.h @@ -53,7 +53,7 @@ struct null_mount { * A cache of vnode references */ struct null_node { - CK_LIST_ENTRY(null_node) null_hash; /* Hash list */ + CK_SLIST_ENTRY(null_node) null_hash; /* Hash list */ struct vnode *null_lowervp; /* VREFed once */ struct vnode *null_vnode; /* Back pointer */ u_int null_flags; diff --git a/sys/fs/nullfs/null_subr.c b/sys/fs/nullfs/null_subr.c index 146d3bbdaedd..d7f847d449d0 100644 --- a/sys/fs/nullfs/null_subr.c +++ b/sys/fs/nullfs/null_subr.c @@ -36,12 +36,12 @@ #include <sys/systm.h> #include <sys/kernel.h> #include <sys/lock.h> -#include <sys/rwlock.h> #include <sys/malloc.h> #include <sys/mount.h> #include <sys/proc.h> -#include <sys/vnode.h> +#include <sys/rwlock.h> #include <sys/smr.h> +#include <sys/vnode.h> #include <fs/nullfs/null.h> @@ -59,7 +59,7 @@ VFS_SMR_DECLARE; #define NULL_NHASH(vp) (&null_node_hashtbl[vfs_hash_index(vp) & null_hash_mask]) -static CK_LIST_HEAD(null_node_hashhead, null_node) *null_node_hashtbl; +static CK_SLIST_HEAD(null_node_hashhead, null_node) *null_node_hashtbl; static struct rwlock null_hash_lock; static u_long null_hash_mask; @@ -116,7 +116,7 @@ null_hashget_locked(struct mount *mp, struct vnode *lowervp) * reference count (but NOT the lower vnode's VREF counter). */ hd = NULL_NHASH(lowervp); - CK_LIST_FOREACH(a, hd, null_hash) { + CK_SLIST_FOREACH(a, hd, null_hash) { if (a->null_lowervp != lowervp) continue; /* @@ -143,12 +143,12 @@ null_hashget(struct mount *mp, struct vnode *lowervp) struct vnode *vp; enum vgetstate vs; - ASSERT_VOP_LOCKED(lowervp, "null_hashget"); + ASSERT_VOP_LOCKED(lowervp, __func__); rw_assert(&null_hash_lock, RA_UNLOCKED); vfs_smr_enter(); hd = NULL_NHASH(lowervp); - CK_LIST_FOREACH(a, hd, null_hash) { + CK_SLIST_FOREACH(a, hd, null_hash) { if (a->null_lowervp != lowervp) continue; /* @@ -181,7 +181,7 @@ null_hashins(struct mount *mp, struct null_node *xp) hd = NULL_NHASH(xp->null_lowervp); #ifdef INVARIANTS - CK_LIST_FOREACH(oxp, hd, null_hash) { + CK_SLIST_FOREACH(oxp, hd, null_hash) { if (oxp->null_lowervp == xp->null_lowervp && NULLTOV(oxp)->v_mount == mp) { VNASSERT(0, NULLTOV(oxp), @@ -189,7 +189,7 @@ null_hashins(struct mount *mp, struct null_node *xp) } } #endif - CK_LIST_INSERT_HEAD(hd, xp, null_hash); + CK_SLIST_INSERT_HEAD(hd, xp, null_hash); } static void @@ -305,9 +305,11 @@ null_nodeget(struct mount *mp, struct vnode *lowervp, struct vnode **vpp) void null_hashrem(struct null_node *xp) { + struct null_node_hashhead *hd; + hd = NULL_NHASH(xp->null_lowervp); rw_wlock(&null_hash_lock); - CK_LIST_REMOVE(xp, null_hash); + CK_SLIST_REMOVE(hd, xp, null_node, null_hash); rw_wunlock(&null_hash_lock); } diff --git a/sys/fs/nullfs/null_vnops.c b/sys/fs/nullfs/null_vnops.c index 375b6aa27531..ec8a6b10b13f 100644 --- a/sys/fs/nullfs/null_vnops.c +++ b/sys/fs/nullfs/null_vnops.c @@ -788,10 +788,10 @@ null_lock_prep_with_smr(struct vop_lock1_args *ap) struct null_node *nn; struct vnode *lvp; - vfs_smr_enter(); - lvp = NULL; + vfs_smr_enter(); + nn = VTONULL_SMR(ap->a_vp); if (__predict_true(nn != NULL)) { lvp = nn->null_lowervp; @@ -855,6 +855,8 @@ null_lock(struct vop_lock1_args *ap) * case by reacquiring correct lock in requested mode. */ if (VTONULL(ap->a_vp) == NULL && error == 0) { + VOP_UNLOCK(lvp); + flags = ap->a_flags; ap->a_flags &= ~LK_TYPE_MASK; switch (flags & LK_TYPE_MASK) { @@ -869,7 +871,6 @@ null_lock(struct vop_lock1_args *ap) panic("Unsupported lock request %d\n", flags); } - VOP_UNLOCK(lvp); error = vop_stdlock(ap); } vdrop(lvp); diff --git a/sys/i386/acpica/acpi_wakeup.c b/sys/i386/acpica/acpi_wakeup.c index 2d60d5e037a0..96be64de017b 100644 --- a/sys/i386/acpica/acpi_wakeup.c +++ b/sys/i386/acpica/acpi_wakeup.c @@ -84,7 +84,7 @@ static cpuset_t suspcpus; static struct susppcb **susppcbs; #endif -static void acpi_stop_beep(void *); +static void acpi_stop_beep(void *, enum power_stype); #ifdef SMP static int acpi_wakeup_ap(struct acpi_softc *, int); @@ -100,7 +100,7 @@ static void acpi_wakeup_cpus(struct acpi_softc *); } while (0) static void -acpi_stop_beep(void *arg) +acpi_stop_beep(void *arg, enum power_stype stype) { if (acpi_resume_beep != 0) diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c index a32b5a1b3354..ab8ed32ad189 100644 --- a/sys/kern/kern_exit.c +++ b/sys/kern/kern_exit.c @@ -127,6 +127,27 @@ proc_realparent(struct proc *child) return (parent); } +static void +reaper_clear(struct proc *p, struct proc *rp) +{ + struct proc *p1; + bool clear; + + sx_assert(&proctree_lock, SX_XLOCKED); + LIST_REMOVE(p, p_reapsibling); + if (p->p_reapsubtree == 1) + return; + clear = true; + LIST_FOREACH(p1, &rp->p_reaplist, p_reapsibling) { + if (p1->p_reapsubtree == p->p_reapsubtree) { + clear = false; + break; + } + } + if (clear) + proc_id_clear(PROC_ID_REAP, p->p_reapsubtree); +} + void reaper_abandon_children(struct proc *p, bool exiting) { @@ -138,7 +159,7 @@ reaper_abandon_children(struct proc *p, bool exiting) return; p1 = p->p_reaper; LIST_FOREACH_SAFE(p2, &p->p_reaplist, p_reapsibling, ptmp) { - LIST_REMOVE(p2, p_reapsibling); + reaper_clear(p2, p); p2->p_reaper = p1; p2->p_reapsubtree = p->p_reapsubtree; LIST_INSERT_HEAD(&p1->p_reaplist, p2, p_reapsibling); @@ -152,27 +173,6 @@ reaper_abandon_children(struct proc *p, bool exiting) p->p_treeflag &= ~P_TREE_REAPER; } -static void -reaper_clear(struct proc *p) -{ - struct proc *p1; - bool clear; - - sx_assert(&proctree_lock, SX_LOCKED); - LIST_REMOVE(p, p_reapsibling); - if (p->p_reapsubtree == 1) - return; - clear = true; - LIST_FOREACH(p1, &p->p_reaper->p_reaplist, p_reapsibling) { - if (p1->p_reapsubtree == p->p_reapsubtree) { - clear = false; - break; - } - } - if (clear) - proc_id_clear(PROC_ID_REAP, p->p_reapsubtree); -} - void proc_clear_orphan(struct proc *p) { @@ -972,7 +972,7 @@ proc_reap(struct thread *td, struct proc *p, int *status, int options) sx_xunlock(PIDHASHLOCK(p->p_pid)); LIST_REMOVE(p, p_sibling); reaper_abandon_children(p, true); - reaper_clear(p); + reaper_clear(p, p->p_reaper); PROC_LOCK(p); proc_clear_orphan(p); PROC_UNLOCK(p); diff --git a/sys/kern/kern_mutex.c b/sys/kern/kern_mutex.c index b7316ea5f387..d67c70984528 100644 --- a/sys/kern/kern_mutex.c +++ b/sys/kern/kern_mutex.c @@ -503,8 +503,8 @@ _mtx_trylock_flags_(volatile uintptr_t *c, int opts, const char *file, int line) /* * __mtx_lock_sleep: the tougher part of acquiring an MTX_DEF lock. * - * We call this if the lock is either contested (i.e. we need to go to - * sleep waiting for it), or if we need to recurse on it. + * We get here if lock profiling is enabled, the lock is already held by + * someone else or we are recursing on it. */ #if LOCK_DEBUG > 0 void @@ -660,13 +660,8 @@ retry_turnstile: } #endif - /* - * If the mutex isn't already contested and a failure occurs - * setting the contested bit, the mutex was either released - * or the state of the MTX_RECURSED bit changed. - */ - if ((v & MTX_CONTESTED) == 0 && - !atomic_fcmpset_ptr(&m->mtx_lock, &v, v | MTX_CONTESTED)) { + if ((v & MTX_WAITERS) == 0 && + !atomic_fcmpset_ptr(&m->mtx_lock, &v, v | MTX_WAITERS)) { goto retry_turnstile; } @@ -1029,8 +1024,8 @@ thread_lock_set(struct thread *td, struct mtx *new) /* * __mtx_unlock_sleep: the tougher part of releasing an MTX_DEF lock. * - * We are only called here if the lock is recursed, contested (i.e. we - * need to wake up a blocked thread) or lockstat probe is active. + * We get here if lock profiling is enabled, the lock is already held by + * someone else or we are recursing on it. */ #if LOCK_DEBUG > 0 void @@ -1207,7 +1202,7 @@ _mtx_destroy(volatile uintptr_t *c) if (!mtx_owned(m)) MPASS(mtx_unowned(m)); else { - MPASS((m->mtx_lock & (MTX_RECURSED|MTX_CONTESTED)) == 0); + MPASS((m->mtx_lock & (MTX_RECURSED|MTX_WAITERS)) == 0); /* Perform the non-mtx related part of mtx_unlock_spin(). */ if (LOCK_CLASS(&m->lock_object) == &lock_class_mtx_spin) { @@ -1359,8 +1354,8 @@ db_show_mtx(const struct lock_object *lock) db_printf("DESTROYED"); else { db_printf("OWNED"); - if (m->mtx_lock & MTX_CONTESTED) - db_printf(", CONTESTED"); + if (m->mtx_lock & MTX_WAITERS) + db_printf(", WAITERS"); if (m->mtx_lock & MTX_RECURSED) db_printf(", RECURSED"); } diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c index 3d4567b6ab1e..a53df50c06bd 100644 --- a/sys/kern/vfs_vnops.c +++ b/sys/kern/vfs_vnops.c @@ -806,9 +806,12 @@ file_v_lock(struct file *fp, short lock_bit, short lock_wait_bit) flagsp = &fp->f_vflags; state = atomic_load_16(flagsp); - if ((state & lock_bit) == 0 && - atomic_cmpset_acq_16(flagsp, state, state | lock_bit)) - return; + for (;;) { + if ((state & lock_bit) != 0) + break; + if (atomic_fcmpset_acq_16(flagsp, &state, state | lock_bit)) + return; + } sleepq_lock(flagsp); state = atomic_load_16(flagsp); @@ -842,9 +845,12 @@ file_v_unlock(struct file *fp, short lock_bit, short lock_wait_bit) flagsp = &fp->f_vflags; state = atomic_load_16(flagsp); - if ((state & lock_wait_bit) == 0 && - atomic_cmpset_rel_16(flagsp, state, state & ~lock_bit)) - return; + for (;;) { + if ((state & lock_wait_bit) != 0) + break; + if (atomic_fcmpset_rel_16(flagsp, &state, state & ~lock_bit)) + return; + } sleepq_lock(flagsp); MPASS((*flagsp & lock_bit) != 0); @@ -864,10 +870,6 @@ foffset_lock(struct file *fp, int flags) FILE_V_FOFFSET_LOCK_WAITING); } - /* - * According to McKusick the vn lock was protecting f_offset here. - * It is now protected by the FOFFSET_LOCKED flag. - */ return (atomic_load_long(&fp->f_offset)); } diff --git a/sys/netgraph/netflow/netflow.c b/sys/netgraph/netflow/netflow.c index 978d6fd0b54d..05c6062463be 100644 --- a/sys/netgraph/netflow/netflow.c +++ b/sys/netgraph/netflow/netflow.c @@ -960,7 +960,7 @@ struct ngnf_show_header *resp) list_id = 0; TAILQ_FOREACH(fle, &hsh->head, fle_hash) { - if (hsh->mtx.mtx_lock & MTX_CONTESTED) { + if (hsh->mtx.mtx_lock & MTX_WAITERS) { resp->hash_id = i; resp->list_id = list_id; mtx_unlock(&hsh->mtx); @@ -1111,7 +1111,7 @@ ng_netflow_expire(void *arg) * Interrupt thread wants this entry! * Quick! Quick! Bail out! */ - if (hsh->mtx.mtx_lock & MTX_CONTESTED) + if (hsh->mtx.mtx_lock & MTX_WAITERS) break; /* @@ -1150,7 +1150,7 @@ ng_netflow_expire(void *arg) * Interrupt thread wants this entry! * Quick! Quick! Bail out! */ - if (hsh->mtx.mtx_lock & MTX_CONTESTED) + if (hsh->mtx.mtx_lock & MTX_WAITERS) break; /* diff --git a/sys/netinet/sctp_lock_bsd.h b/sys/netinet/sctp_lock_bsd.h index ec66be0cf371..a60983cb30e3 100644 --- a/sys/netinet/sctp_lock_bsd.h +++ b/sys/netinet/sctp_lock_bsd.h @@ -263,10 +263,10 @@ } while (0) #define SCTP_INP_LOCK_CONTENDED(_inp) \ - ((_inp)->inp_mtx.mtx_lock & MTX_CONTESTED) + ((_inp)->inp_mtx.mtx_lock & MTX_WAITERS) #define SCTP_INP_READ_CONTENDED(_inp) \ - ((_inp)->inp_rdata_mtx.mtx_lock & MTX_CONTESTED) + ((_inp)->inp_rdata_mtx.mtx_lock & MTX_WAITERS) #ifdef SCTP_LOCK_LOGGING #define SCTP_INP_RLOCK(_inp) do { \ @@ -337,7 +337,7 @@ } while (0) #define SCTP_ASOC_CREATE_LOCK_CONTENDED(_inp) \ - ((_inp)->inp_create_mtx.mtx_lock & MTX_CONTESTED) + ((_inp)->inp_create_mtx.mtx_lock & MTX_WAITERS) /* * For the majority of things (once we have found the association) we will diff --git a/sys/netinet/tcp_syncache.c b/sys/netinet/tcp_syncache.c index def6bc886617..f842a5678fa1 100644 --- a/sys/netinet/tcp_syncache.c +++ b/sys/netinet/tcp_syncache.c @@ -1272,7 +1272,7 @@ syncache_expand(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th, syncache_send_challenge_ack(sc, m); SCH_UNLOCK(sch); free(s, M_TCPLOG); - return (-1); /* Do not send RST */; + return (-1); /* Do not send RST */ } /* @@ -1285,7 +1285,8 @@ syncache_expand(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th, "segment rejected\n", s, __func__, th->th_ack, sc->sc_iss + 1); SCH_UNLOCK(sch); - goto failed; + free(s, M_TCPLOG); + return (0); /* Do send RST, do not free sc. */ } TAILQ_REMOVE(&sch->sch_bucket, sc, sc_hash); diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c index 4f756a75fac7..b98703bdfbfe 100644 --- a/sys/netinet6/in6.c +++ b/sys/netinet6/in6.c @@ -1295,8 +1295,8 @@ in6_addifaddr(struct ifnet *ifp, struct in6_aliasreq *ifra, struct in6_ifaddr *i */ bzero(&pr0, sizeof(pr0)); pr0.ndpr_ifp = ifp; - pr0.ndpr_plen = in6_mask2len(&ifra->ifra_prefixmask.sin6_addr, - NULL); + pr0.ndpr_plen = ia->ia_plen = + in6_mask2len(&ifra->ifra_prefixmask.sin6_addr, NULL); if (pr0.ndpr_plen == 128) { /* we don't need to install a host route. */ goto aifaddr_out; @@ -1490,16 +1490,16 @@ in6_unlink_ifa(struct in6_ifaddr *ia, struct ifnet *ifp) * positive reference. */ remove_lle = 0; - if (ia->ia6_ndpr == NULL) { - nd6log((LOG_NOTICE, - "in6_unlink_ifa: autoconf'ed address " - "%s has no prefix\n", ip6_sprintf(ip6buf, IA6_IN6(ia)))); - } else { + if (ia->ia6_ndpr != NULL) { ia->ia6_ndpr->ndpr_addrcnt--; /* Do not delete lles within prefix if refcont != 0 */ if (ia->ia6_ndpr->ndpr_addrcnt == 0) remove_lle = 1; ia->ia6_ndpr = NULL; + } else if (ia->ia_plen < 128) { + nd6log((LOG_NOTICE, + "in6_unlink_ifa: autoconf'ed address " + "%s has no prefix\n", ip6_sprintf(ip6buf, IA6_IN6(ia)))); } nd6_rem_ifa_lle(ia, remove_lle); diff --git a/sys/netlink/netlink_snl.h b/sys/netlink/netlink_snl.h index 6dd8a9cbdb35..57f7e1e29d08 100644 --- a/sys/netlink/netlink_snl.h +++ b/sys/netlink/netlink_snl.h @@ -1068,14 +1068,14 @@ snl_init_writer(struct snl_state *ss, struct snl_writer *nw) { nw->size = SNL_WRITER_BUFFER_SIZE; nw->base = (char *)snl_allocz(ss, nw->size); - if (nw->base == NULL) { + if (__predict_false(nw->base == NULL)) { nw->error = true; nw->size = 0; - } + } else + nw->error = false; nw->offset = 0; nw->hdr = NULL; - nw->error = false; nw->ss = ss; } diff --git a/sys/sys/eventhandler.h b/sys/sys/eventhandler.h index c0d9811dd1b9..29a16b393b52 100644 --- a/sys/sys/eventhandler.h +++ b/sys/sys/eventhandler.h @@ -33,6 +33,7 @@ #include <sys/lock.h> #include <sys/ktr.h> #include <sys/mutex.h> +#include <sys/power.h> #include <sys/queue.h> #ifdef VIMAGE @@ -201,7 +202,7 @@ EVENTHANDLER_DECLARE(shutdown_post_sync, shutdown_fn); /* after fs sync */ EVENTHANDLER_DECLARE(shutdown_final, shutdown_fn); /* Power state change events */ -typedef void (*power_change_fn)(void *); +typedef void (*power_change_fn)(void *, enum power_stype stype); EVENTHANDLER_DECLARE(power_resume, power_change_fn); EVENTHANDLER_DECLARE(power_suspend, power_change_fn); EVENTHANDLER_DECLARE(power_suspend_early, power_change_fn); diff --git a/sys/sys/mutex.h b/sys/sys/mutex.h index 83300d4eb593..4f6b45d78a88 100644 --- a/sys/sys/mutex.h +++ b/sys/sys/mutex.h @@ -68,9 +68,9 @@ */ #define MTX_UNOWNED 0x00000000 /* Cookie for free mutex */ #define MTX_RECURSED 0x00000001 /* lock recursed (for MTX_DEF only) */ -#define MTX_CONTESTED 0x00000002 /* lock contested (for MTX_DEF only) */ +#define MTX_WAITERS 0x00000002 /* lock has waiters (for MTX_DEF only) */ #define MTX_DESTROYED 0x00000004 /* lock destroyed */ -#define MTX_FLAGMASK (MTX_RECURSED | MTX_CONTESTED | MTX_DESTROYED) +#define MTX_FLAGMASK (MTX_RECURSED | MTX_WAITERS | MTX_DESTROYED) /* * Prototypes @@ -217,7 +217,7 @@ void _thread_lock(struct thread *); #define _mtx_obtain_lock_fetch(mp, vp, tid) \ atomic_fcmpset_acq_ptr(&(mp)->mtx_lock, vp, (tid)) -/* Try to release mtx_lock if it is unrecursed and uncontested. */ +/* Try to release mtx_lock if it is unrecursed and without waiters. */ #define _mtx_release_lock(mp, tid) \ atomic_cmpset_rel_ptr(&(mp)->mtx_lock, (tid), MTX_UNOWNED) diff --git a/sys/x86/x86/mca.c b/sys/x86/x86/mca.c index 1851df8d00a0..4b40f343ac90 100644 --- a/sys/x86/x86/mca.c +++ b/sys/x86/x86/mca.c @@ -124,6 +124,17 @@ SYSCTL_INT(_hw_mca, OID_AUTO, erratum383, CTLFLAG_RDTUN, &workaround_erratum383, 0, "Is the workaround for Erratum 383 on AMD Family 10h processors enabled?"); +#ifdef DIAGNOSTIC +static uint64_t fake_status; +SYSCTL_U64(_hw_mca, OID_AUTO, fake_status, CTLFLAG_RW, + &fake_status, 0, + "Insert artificial MCA with given status (testing purpose only)"); +static int fake_bank; +SYSCTL_INT(_hw_mca, OID_AUTO, fake_bank, CTLFLAG_RW, + &fake_bank, 0, + "Bank to use for artificial MCAs (testing purpose only)"); +#endif + static STAILQ_HEAD(, mca_internal) mca_freelist; static int mca_freecount; static STAILQ_HEAD(, mca_internal) mca_records; @@ -131,8 +142,10 @@ static STAILQ_HEAD(, mca_internal) mca_pending; static int mca_ticks = 300; static struct taskqueue *mca_tq; static struct task mca_resize_task; +static struct task mca_postscan_task; static struct timeout_task mca_scan_task; static struct mtx mca_lock; +static bool mca_startup_done = false; /* Statistics on number of MCA events by type, updated atomically. */ static uint64_t mca_stats[MCA_T_COUNT]; @@ -699,8 +712,24 @@ mca_check_status(enum scan_mode mode, uint64_t mcg_cap, int bank, bool mce, recover; status = rdmsr(mca_msr_ops.status(bank)); - if (!(status & MC_STATUS_VAL)) + if (!(status & MC_STATUS_VAL)) { +#ifdef DIAGNOSTIC + /* + * Check if we have a pending artificial event to generate. + * Note that this is potentially racy with the sysctl. The + * tradeoff is deemed acceptable given the test nature + * of the code. + */ + if (fake_status && bank == fake_bank) { + status = fake_status; + fake_status = 0; + } + if (!(status & MC_STATUS_VAL)) + return (0); +#else return (0); +#endif + } recover = *recoverablep; mce = mca_is_mce(mcg_cap, status, &recover); @@ -794,9 +823,9 @@ mca_record_entry(enum scan_mode mode, const struct mca_record *record) mtx_lock_spin(&mca_lock); rec = STAILQ_FIRST(&mca_freelist); if (rec == NULL) { + mtx_unlock_spin(&mca_lock); printf("MCA: Unable to allocate space for an event.\n"); mca_log(record); - mtx_unlock_spin(&mca_lock); return; } STAILQ_REMOVE_HEAD(&mca_freelist, link); @@ -1015,18 +1044,49 @@ static void mca_process_records(enum scan_mode mode) { struct mca_internal *mca; + STAILQ_HEAD(, mca_internal) tmplist; + /* + * If in an interrupt context, defer the post-scan activities to a + * task queue. + */ + if (mode != POLLED) { + if (mca_startup_done) + taskqueue_enqueue(mca_tq, &mca_postscan_task); + return; + } + + /* + * Copy the pending list to the stack so we can drop the spin lock + * while we are emitting logs. + */ + STAILQ_INIT(&tmplist); mtx_lock_spin(&mca_lock); - while ((mca = STAILQ_FIRST(&mca_pending)) != NULL) { - STAILQ_REMOVE_HEAD(&mca_pending, link); + STAILQ_SWAP(&mca_pending, &tmplist, mca_internal); + mtx_unlock_spin(&mca_lock); + + STAILQ_FOREACH(mca, &tmplist, link) mca_log(&mca->rec); + + mtx_lock_spin(&mca_lock); + while ((mca = STAILQ_FIRST(&tmplist)) != NULL) { + STAILQ_REMOVE_HEAD(&tmplist, link); mca_store_record(mca); } mtx_unlock_spin(&mca_lock); - if (mode == POLLED) - mca_resize_freelist(); - else if (!cold) - taskqueue_enqueue(mca_tq, &mca_resize_task); + mca_resize_freelist(); +} + +/* + * Emit log entries and resize the free list. This is intended to be called + * from a task queue to handle work which does not need to be done (or cannot + * be done) in an interrupt context. + */ +static void +mca_postscan(void *context __unused, int pending __unused) +{ + + mca_process_records(POLLED); } /* @@ -1097,7 +1157,7 @@ sysctl_mca_maxcount(SYSCTL_HANDLER_ARGS) doresize = true; } mtx_unlock_spin(&mca_lock); - if (doresize && !cold) + if (doresize && mca_startup_done) taskqueue_enqueue(mca_tq, &mca_resize_task); return (error); } @@ -1109,12 +1169,16 @@ mca_startup(void *dummy) if (mca_banks <= 0) return; - /* CMCIs during boot may have claimed items from the freelist. */ - mca_resize_freelist(); - taskqueue_start_threads(&mca_tq, 1, PI_SWI(SWI_TQ), "mca taskq"); taskqueue_enqueue_timeout_sbt(mca_tq, &mca_scan_task, mca_ticks * SBT_1S, 0, C_PREL(1)); + mca_startup_done = true; + + /* + * CMCIs during boot may have recorded entries. Conduct the post-scan + * activities now. + */ + mca_postscan(NULL, 0); } SYSINIT(mca_startup, SI_SUB_KICK_SCHEDULER, SI_ORDER_ANY, mca_startup, NULL); @@ -1174,6 +1238,7 @@ mca_setup(uint64_t mcg_cap) TIMEOUT_TASK_INIT(mca_tq, &mca_scan_task, 0, mca_scan_cpus, NULL); STAILQ_INIT(&mca_freelist); TASK_INIT(&mca_resize_task, 0, mca_resize, NULL); + TASK_INIT(&mca_postscan_task, 0, mca_postscan, NULL); mca_resize_freelist(); SYSCTL_ADD_INT(NULL, SYSCTL_STATIC_CHILDREN(_hw_mca), OID_AUTO, "count", CTLFLAG_RD, (int *)(uintptr_t)&mca_count, 0, @@ -1577,6 +1642,9 @@ mca_intr(void) panic("Unrecoverable machine check exception"); } + if (count) + mca_process_records(MCE); + /* Clear MCIP. */ wrmsr(MSR_MCG_STATUS, mcg_status & ~MCG_STATUS_MCIP); } |