dev_alert(adap->pdev_dev, "encountered fatal error, adapter stopped\n");
 }
 
+/* Return the specified PCI-E Configuration Space register from our Physical
+ * Function.  We try first via a Firmware LDST Command since we prefer to let
+ * the firmware own all of these registers, but if that fails we go for it
+ * directly ourselves.
+ */
+static u32 t4_read_pcie_cfg4(struct adapter *adap, int reg)
+{
+       struct fw_ldst_cmd ldst_cmd;
+       u32 val;
+       int ret;
+
+       /* Construct and send the Firmware LDST Command to retrieve the
+        * specified PCI-E Configuration Space register.
+        */
+       memset(&ldst_cmd, 0, sizeof(ldst_cmd));
+       ldst_cmd.op_to_addrspace =
+               htonl(FW_CMD_OP(FW_LDST_CMD) |
+                     FW_CMD_REQUEST |
+                     FW_CMD_READ |
+                     FW_LDST_CMD_ADDRSPACE(FW_LDST_ADDRSPC_FUNC_PCIE));
+       ldst_cmd.cycles_to_len16 = htonl(FW_LEN16(ldst_cmd));
+       ldst_cmd.u.pcie.select_naccess = FW_LDST_CMD_NACCESS(1);
+       ldst_cmd.u.pcie.ctrl_to_fn =
+               (FW_LDST_CMD_LC | FW_LDST_CMD_FN(adap->fn));
+       ldst_cmd.u.pcie.r = reg;
+       ret = t4_wr_mbox(adap, adap->mbox, &ldst_cmd, sizeof(ldst_cmd),
+                        &ldst_cmd);
+
+       /* If the LDST Command suucceeded, exctract the returned register
+        * value.  Otherwise read it directly ourself.
+        */
+       if (ret == 0)
+               val = ntohl(ldst_cmd.u.pcie.data[0]);
+       else
+               t4_hw_pci_read_cfg4(adap, reg, &val);
+
+       return val;
+}
+
 static void setup_memwin(struct adapter *adap)
 {
-       u32 bar0, mem_win0_base, mem_win1_base, mem_win2_base;
+       u32 mem_win0_base, mem_win1_base, mem_win2_base, mem_win2_aperture;
 
-       bar0 = pci_resource_start(adap->pdev, 0);  /* truncation intentional */
        if (is_t4(adap->params.chip)) {
+               u32 bar0;
+
+               /* Truncation intentional: we only read the bottom 32-bits of
+                * the 64-bit BAR0/BAR1 ...  We use the hardware backdoor
+                * mechanism to read BAR0 instead of using
+                * pci_resource_start() because we could be operating from
+                * within a Virtual Machine which is trapping our accesses to
+                * our Configuration Space and we need to set up the PCI-E
+                * Memory Window decoders with the actual addresses which will
+                * be coming across the PCI-E link.
+                */
+               bar0 = t4_read_pcie_cfg4(adap, PCI_BASE_ADDRESS_0);
+               bar0 &= PCI_BASE_ADDRESS_MEM_MASK;
+               adap->t4_bar0 = bar0;
+
                mem_win0_base = bar0 + MEMWIN0_BASE;
                mem_win1_base = bar0 + MEMWIN1_BASE;
                mem_win2_base = bar0 + MEMWIN2_BASE;
+               mem_win2_aperture = MEMWIN2_APERTURE;
        } else {
                /* For T5, only relative offset inside the PCIe BAR is passed */
                mem_win0_base = MEMWIN0_BASE;
-               mem_win1_base = MEMWIN1_BASE_T5;
+               mem_win1_base = MEMWIN1_BASE;
                mem_win2_base = MEMWIN2_BASE_T5;
+               mem_win2_aperture = MEMWIN2_APERTURE_T5;
        }
        t4_write_reg(adap, PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_BASE_WIN, 0),
                     mem_win0_base | BIR(0) |
                     WINDOW(ilog2(MEMWIN1_APERTURE) - 10));
        t4_write_reg(adap, PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_BASE_WIN, 2),
                     mem_win2_base | BIR(0) |
-                    WINDOW(ilog2(MEMWIN2_APERTURE) - 10));
+                    WINDOW(ilog2(mem_win2_aperture) - 10));
+       t4_read_reg(adap, PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_BASE_WIN, 2));
 }
 
 static void setup_memwin_rdma(struct adapter *adap)
 {
        if (adap->vres.ocq.size) {
-               unsigned int start, sz_kb;
+               u32 start;
+               unsigned int sz_kb;
 
-               start = pci_resource_start(adap->pdev, 2) +
-                       OCQ_WIN_OFFSET(adap->pdev, &adap->vres);
+               start = t4_read_pcie_cfg4(adap, PCI_BASE_ADDRESS_2);
+               start &= PCI_BASE_ADDRESS_MEM_MASK;
+               start += OCQ_WIN_OFFSET(adap->pdev, &adap->vres);
                sz_kb = roundup_pow_of_two(adap->vres.ocq.size) >> 10;
                t4_write_reg(adap,
                             PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_BASE_WIN, 3),
 
        }
 }
 
+/*
+ * Read a 32-bit PCI Configuration Space register via the PCI-E backdoor
+ * mechanism.  This guarantees that we get the real value even if we're
+ * operating within a Virtual Machine and the Hypervisor is trapping our
+ * Configuration Space accesses.
+ */
+void t4_hw_pci_read_cfg4(struct adapter *adap, int reg, u32 *val)
+{
+       u32 req = ENABLE | FUNCTION(adap->fn) | reg;
+
+       if (is_t4(adap->params.chip))
+               req |= F_LOCALCFG;
+
+       t4_write_reg(adap, PCIE_CFG_SPACE_REQ, req);
+       *val = t4_read_reg(adap, PCIE_CFG_SPACE_DATA);
+
+       /* Reset ENABLE to 0 so reads of PCIE_CFG_SPACE_DATA won't cause a
+        * Configuration Space read.  (None of the other fields matter when
+        * ENABLE is 0 so a simple register write is easier than a
+        * read-modify-write via t4_set_reg_field().)
+        */
+       t4_write_reg(adap, PCIE_CFG_SPACE_REQ, 0);
+}
+
 /*
  * Get the reply to a mailbox command and store it in @rpl in big-endian order.
  */