summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Mustacchi <rm@joyent.com>2018-08-24 23:15:55 +0000
committerRobert Mustacchi <rm@joyent.com>2018-08-27 23:40:43 +0000
commitb55712a7295a33023eab23147df4d72b5c128fe1 (patch)
treef1b8bddf031ed398052eae5b098b78d856477346
parentc9808d714ccc28dc72535483d2747dc5245e2169 (diff)
downloadillumos-joyent-b55712a7295a33023eab23147df4d72b5c128fe1.tar.gz
OS-7176 ehci_take_control() can infinite loop due to PCI invalid reads
Reviewed by: Dan McDonald <danmcd@joyent.com> Reviewed by: Jason King <jason.king@joyent.com> Reviewed by: Patrick Mooney <patrick.mooney@joyent.com> Approved by: Patrick Mooney <patrick.mooney@joyent.com>
-rw-r--r--usr/src/uts/common/io/usb/hcd/ehci/ehci_util.c24
-rw-r--r--usr/src/uts/common/sys/usb/hcd/ehci/ehci.h1
2 files changed, 20 insertions, 5 deletions
diff --git a/usr/src/uts/common/io/usb/hcd/ehci/ehci_util.c b/usr/src/uts/common/io/usb/hcd/ehci/ehci_util.c
index 3900fbd6d6..7e0e658601 100644
--- a/usr/src/uts/common/io/usb/hcd/ehci/ehci_util.c
+++ b/usr/src/uts/common/io/usb/hcd/ehci/ehci_util.c
@@ -21,6 +21,7 @@
/*
* Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, Joyent, Inc.
*/
/*
@@ -834,8 +835,7 @@ skip_intr:
* Register FIXED or MSI interrupts.
*/
static int
-ehci_add_intrs(ehci_state_t *ehcip,
- int intr_type)
+ehci_add_intrs(ehci_state_t *ehcip, int intr_type)
{
int actual, avail, intr_size, count = 0;
int i, flag, ret;
@@ -1232,8 +1232,7 @@ ehci_init_check_status(ehci_state_t *ehcip)
* Initialize the Host Controller (HC).
*/
int
-ehci_init_ctlr(ehci_state_t *ehcip,
- int init_type)
+ehci_init_ctlr(ehci_state_t *ehcip, int init_type)
{
USB_DPRINTF_L4(PRINT_MASK_ATTA, ehcip->ehci_log_hdl, "ehci_init_ctlr:");
@@ -1406,6 +1405,19 @@ ehci_take_control(ehci_state_t *ehcip)
extended_cap = pci_config_get32(ehcip->ehci_config_handle,
extended_cap_offset);
+ /*
+ * It's possible that we'll receive an invalid PCI read here due
+ * to something going wrong due to platform firmware. This has
+ * been observed in the wild depending on the version of ACPI in
+ * use. If this happens, we'll assume that the capability does
+ * not exist and that we do not need to take control from the
+ * BIOS.
+ */
+ if (extended_cap == PCI_EINVAL32) {
+ extended_cap_id = EHCI_EX_CAP_ID_RESERVED;
+ break;
+ }
+
/* Get the capability ID */
extended_cap_id = (extended_cap & EHCI_EX_CAP_ID) >>
EHCI_EX_CAP_ID_SHIFT;
@@ -1418,6 +1430,7 @@ ehci_take_control(ehci_state_t *ehcip)
/* Get the offset of the next capability */
extended_cap_offset = (extended_cap & EHCI_EX_CAP_NEXT_PTR) >>
EHCI_EX_CAP_NEXT_PTR_SHIFT;
+
}
/*
@@ -2976,7 +2989,8 @@ ehci_lattice_parent(uint_t node)
* Based on the "real" array leaf node and interval, get the periodic node.
*/
static uint_t
-ehci_find_periodic_node(uint_t leaf, int interval) {
+ehci_find_periodic_node(uint_t leaf, int interval)
+{
uint_t lattice_leaf;
uint_t height = ehci_lattice_height(interval);
uint_t pnode;
diff --git a/usr/src/uts/common/sys/usb/hcd/ehci/ehci.h b/usr/src/uts/common/sys/usb/hcd/ehci/ehci.h
index 76766ce68e..ce8d735ac8 100644
--- a/usr/src/uts/common/sys/usb/hcd/ehci/ehci.h
+++ b/usr/src/uts/common/sys/usb/hcd/ehci/ehci.h
@@ -280,6 +280,7 @@ typedef volatile struct ehci_regs {
#define EHCI_EX_CAP_NEXT_PTR_SHIFT 8
#define EHCI_EX_CAP_ID 0x000000FF
#define EHCI_EX_CAP_ID_SHIFT 0
+#define EHCI_EX_CAP_ID_RESERVED 0
#define EHCI_EX_CAP_ID_BIOS_HANDOFF 1
#define EHCI_LEGSUP_OS_OWNED_SEM 0x01000000