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);