9796 want support for PCI BAR size >= 4G
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Reviewed by: Patrick Mooney <patrick.mooney@joyent.com>
Reviewed by: Robert Mustacchi <rm@joyent.com>
Reviewed by: Toomas Soome <tsoome@me.com>
Reviewed by: Andy Fiddaman <omnios@citrus-it.net>
Reviewed by: Garrett D'Amore <garrett@damore.org>
Approved by: Garrett D'Amore <garrett@damore.org>
diff --git a/usr/src/uts/common/sys/pci.h b/usr/src/uts/common/sys/pci.h
index f5f0b23..66ce71b 100644
--- a/usr/src/uts/common/sys/pci.h
+++ b/usr/src/uts/common/sys/pci.h
@@ -21,7 +21,7 @@
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
- * Copyright 2016 Joyent, Inc.
+ * Copyright 2018 Joyent, Inc.
*/
#ifndef _SYS_PCI_H
@@ -582,6 +582,7 @@
#define PCI_BASE_TYPE_M 0x00000006 /* type indicator mask */
#define PCI_BASE_PREF_M 0x00000008 /* prefetch mask */
#define PCI_BASE_M_ADDR_M 0xfffffff0 /* memory address mask */
+#define PCI_BASE_M_ADDR64_M 0xfffffffffffffff0ULL /* 64bit mem addr mask */
#define PCI_BASE_IO_ADDR_M 0xfffffffe /* I/O address mask */
#define PCI_BASE_ROM_ADDR_M 0xfffff800 /* ROM address mask */
diff --git a/usr/src/uts/common/sys/pci_impl.h b/usr/src/uts/common/sys/pci_impl.h
index bdd3116..3bfdef9 100644
--- a/usr/src/uts/common/sys/pci_impl.h
+++ b/usr/src/uts/common/sys/pci_impl.h
@@ -21,6 +21,7 @@
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ * Copyright 2018 Joyent, Inc.
*/
#ifndef _SYS_PCI_IMPL_H
@@ -107,7 +108,7 @@
boolean_t io_reprogram; /* need io reprog on this bus */
boolean_t mem_reprogram; /* need mem reprog on this bus */
boolean_t subtractive; /* subtractive PPB */
- uint_t mem_size; /* existing children required MEM space size */
+ uint64_t mem_size; /* existing children required MEM space size */
uint_t io_size; /* existing children required I/O space size */
};
diff --git a/usr/src/uts/intel/io/pci/pci_boot.c b/usr/src/uts/intel/io/pci/pci_boot.c
index 730aee7..601153d 100644
--- a/usr/src/uts/intel/io/pci/pci_boot.c
+++ b/usr/src/uts/intel/io/pci/pci_boot.c
@@ -20,7 +20,7 @@
*/
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2016 Joyent, Inc.
+ * Copyright 2018 Joyent, Inc.
*/
#include <sys/types.h>
@@ -893,8 +893,9 @@
{
uchar_t bus, dev, func;
uchar_t parbus, subbus;
- uint_t io_base, io_limit, mem_base, mem_limit;
- uint_t io_size, mem_size, io_align, mem_align;
+ uint_t io_base, io_limit, mem_base;
+ uint_t io_size, io_align;
+ uint64_t mem_size, mem_align, mem_limit;
uint64_t addr = 0;
int *regp = NULL;
uint_t reglen;
@@ -1049,9 +1050,9 @@
pci_bus_res[parbus].io_reprogram;
cmn_err(CE_NOTE, "!add io-range on subtractive"
- " ppb[%x/%x/%x]: 0x%x ~ 0x%x\n",
- bus, dev, func, (uint32_t)addr,
- (uint32_t)addr + io_size - 1);
+ " ppb[%x/%x/%x]: "
+ "0x%"PRIx64" ~ 0x%"PRIx64"\n",
+ bus, dev, func, addr, addr + io_size - 1);
}
}
/*
@@ -1066,9 +1067,10 @@
pci_bus_res[parbus].mem_reprogram;
cmn_err(CE_NOTE, "!add mem-range on "
- "subtractive ppb[%x/%x/%x]: 0x%x ~ 0x%x\n",
- bus, dev, func, (uint32_t)addr,
- (uint32_t)addr + mem_size - 1);
+ "subtractive ppb[%x/%x/%x]: "
+ "0x%"PRIx64" ~ 0x%"PRIx64"\n",
+ bus, dev, func,
+ addr, addr + mem_size - 1);
}
}
@@ -1197,15 +1199,15 @@
if (is_vga(list, MEM))
continue;
if (mem_base == 0) {
- mem_base = (uint_t)list->ml_address;
+ mem_base = list->ml_address;
mem_base = P2ALIGN(mem_base,
PPB_MEM_ALIGNMENT);
- mem_limit = (uint_t)(list->ml_address +
+ mem_limit = (list->ml_address +
list->ml_size - 1);
} else {
if ((list->ml_address + list->ml_size) >
mem_limit) {
- mem_limit = (uint_t)
+ mem_limit =
(list->ml_address +
list->ml_size - 1);
}
@@ -1265,7 +1267,7 @@
add_ranges_prop(secbus, 1);
cmn_err(CE_NOTE, "!reprogram mem-range on"
- " ppb[%x/%x/%x]: 0x%x ~ 0x%x\n",
+ " ppb[%x/%x/%x]: 0x%x ~ 0x%"PRIx64"\n",
bus, dev, func, mem_base, mem_limit);
}
}
@@ -2360,7 +2362,8 @@
{
uchar_t baseclass, subclass, progclass, header;
ushort_t bar_sz;
- uint_t value = 0, len, devloc;
+ uint64_t value = 0;
+ uint_t devloc;
uint_t base, base_hi, type;
ushort_t offset, end;
int max_basereg, j, reprogram = 0;
@@ -2444,6 +2447,7 @@
/* construct phys hi,med.lo, size hi, lo */
if ((pciide && j < 4) || (base & PCI_BASE_SPACE_IO)) {
int hard_decode = 0;
+ uint_t len;
/* i/o space */
bar_sz = PCI_BAR_SZ_32;
@@ -2528,26 +2532,34 @@
nreg++, nasgn++;
} else {
+ uint64_t len;
/* memory space */
if ((base & PCI_BASE_TYPE_M) == PCI_BASE_TYPE_ALL) {
bar_sz = PCI_BAR_SZ_64;
base_hi = pci_getl(bus, dev, func, offset + 4);
+ pci_putl(bus, dev, func, offset + 4,
+ 0xffffffff);
+ value |= (uint64_t)pci_getl(bus, dev, func,
+ offset + 4) << 32;
+ pci_putl(bus, dev, func, offset + 4, base_hi);
phys_hi = PCI_ADDR_MEM64;
+ value &= PCI_BASE_M_ADDR64_M;
} else {
bar_sz = PCI_BAR_SZ_32;
base_hi = 0;
phys_hi = PCI_ADDR_MEM32;
+ value &= PCI_BASE_M_ADDR_M;
}
/* skip base regs with size of 0 */
- value &= PCI_BASE_M_ADDR_M;
-
if (value == 0)
continue;
len = ((value ^ (value-1)) + 1) >> 1;
regs[nreg].pci_size_low =
- assigned[nasgn].pci_size_low = len;
+ assigned[nasgn].pci_size_low = len & 0xffffffff;
+ regs[nreg].pci_size_hi =
+ assigned[nasgn].pci_size_hi = len >> 32;
phys_hi |= (devloc | offset);
if (base & PCI_BASE_PREF_M)
@@ -2644,7 +2656,7 @@
} else
cmn_err(CE_WARN, "failed to program "
"mem space [%d/%d/%d] BAR@0x%x"
- " length 0x%x",
+ " length 0x%"PRIx64,
bus, dev, func, offset, len);
}
assigned[nasgn].pci_phys_low = base;
@@ -2677,6 +2689,8 @@
value = 0;
if (value != 0) {
+ uint_t len;
+
regs[nreg].pci_phys_hi = (PCI_ADDR_MEM32 | devloc) + offset;
assigned[nasgn].pci_phys_hi = (PCI_RELOCAT_B |
PCI_ADDR_MEM32 | devloc) + offset;
diff --git a/usr/src/uts/intel/io/pci/pci_pci.c b/usr/src/uts/intel/io/pci/pci_pci.c
index b15c057..eeb62a8 100644
--- a/usr/src/uts/intel/io/pci/pci_pci.c
+++ b/usr/src/uts/intel/io/pci/pci_pci.c
@@ -24,6 +24,7 @@
*/
/*
* Copyright 2012 Garrett D'Amore <garrett@damore.org>. All rights reserved.
+ * Copyright 2018 Joyent, Inc.
*/
/*
@@ -561,12 +562,21 @@
if (ctlop == DDI_CTLOPS_NREGS)
*(int *)result = totreg;
else if (ctlop == DDI_CTLOPS_REGSIZE) {
+ uint64_t rs;
+
rn = *(int *)arg;
if (rn >= totreg) {
kmem_free(drv_regp, reglen);
return (DDI_FAILURE);
}
- *(off_t *)result = drv_regp[rn].pci_size_low;
+
+ rs = drv_regp[rn].pci_size_low |
+ ((uint64_t)drv_regp[rn].pci_size_hi << 32);
+ if (rs > OFF_MAX) {
+ kmem_free(drv_regp, reglen);
+ return (DDI_FAILURE);
+ }
+ *(off_t *)result = rs;
}
kmem_free(drv_regp, reglen);