|
|
9ae3a8 |
From e27159f910abe099eba5d6959ace2f2de42e5f46 Mon Sep 17 00:00:00 2001
|
|
|
9ae3a8 |
Message-Id: <e27159f910abe099eba5d6959ace2f2de42e5f46.1387298827.git.minovotn@redhat.com>
|
|
|
9ae3a8 |
In-Reply-To: <3ed0fb61a3dc912ef036d7ef450bed192090709e.1387298827.git.minovotn@redhat.com>
|
|
|
9ae3a8 |
References: <3ed0fb61a3dc912ef036d7ef450bed192090709e.1387298827.git.minovotn@redhat.com>
|
|
|
9ae3a8 |
From: "Michael S. Tsirkin" <mst@redhat.com>
|
|
|
9ae3a8 |
Date: Tue, 17 Dec 2013 15:17:34 +0100
|
|
|
9ae3a8 |
Subject: [PATCH 18/56] pc: limit 64 bit hole to 2G by default
|
|
|
9ae3a8 |
MIME-Version: 1.0
|
|
|
9ae3a8 |
Content-Type: text/plain; charset=UTF-8
|
|
|
9ae3a8 |
Content-Transfer-Encoding: 8bit
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
RH-Author: Michael S. Tsirkin <mst@redhat.com>
|
|
|
9ae3a8 |
Message-id: <1387293161-4085-19-git-send-email-mst@redhat.com>
|
|
|
9ae3a8 |
Patchwork-id: 56324
|
|
|
9ae3a8 |
O-Subject: [PATCH qemu-kvm RHEL7.0 v2 18/57] pc: limit 64 bit hole to 2G by default
|
|
|
9ae3a8 |
Bugzilla: 1034876
|
|
|
9ae3a8 |
RH-Acked-by: Igor Mammedov <imammedo@redhat.com>
|
|
|
9ae3a8 |
RH-Acked-by: Marcel Apfelbaum <marcel.a@redhat.com>
|
|
|
9ae3a8 |
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
From: Igor Mammedov <imammedo@redhat.com>
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
It turns out that some 32 bit windows guests crash
|
|
|
9ae3a8 |
if 64 bit PCI hole size is >2G.
|
|
|
9ae3a8 |
Limit it to 2G for piix and q35 by default.
|
|
|
9ae3a8 |
User may override default 64-bit PCI hole size by
|
|
|
9ae3a8 |
using "pci-hole64-size" property.
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
Examples:
|
|
|
9ae3a8 |
-global i440FX-pcihost.pci-hole64-size=4G
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
-global q35-pcihost.pci-hole64-size=4G
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
Reported-by: Igor Mammedov <imammedo@redhat.com>,
|
|
|
9ae3a8 |
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
|
|
|
9ae3a8 |
Signed-off-by: Igor Mammedov <imammedo@redhat.com>
|
|
|
9ae3a8 |
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
|
|
|
9ae3a8 |
Reviewed-by: Andreas Färber <afaerber@suse.de>
|
|
|
9ae3a8 |
Message-id: 1375109277-25561-8-git-send-email-imammedo@redhat.com
|
|
|
9ae3a8 |
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
|
|
|
9ae3a8 |
(cherry picked from commit 398489018183d613306ab022653552247d93919f)
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
Conflicts:
|
|
|
9ae3a8 |
hw/i386/pc.c
|
|
|
9ae3a8 |
hw/pci-host/piix.c
|
|
|
9ae3a8 |
hw/pci-host/q35.c
|
|
|
9ae3a8 |
---
|
|
|
9ae3a8 |
include/hw/i386/pc.h | 14 +++++--
|
|
|
9ae3a8 |
include/hw/pci-host/q35.h | 2 +
|
|
|
9ae3a8 |
hw/i386/pc.c | 56 ++++++++++++++++-----------
|
|
|
9ae3a8 |
hw/i386/pc_piix.c | 14 +------
|
|
|
9ae3a8 |
hw/pci-host/piix.c | 99 ++++++++++++++++++++++++++++++++++++++++++++---
|
|
|
9ae3a8 |
hw/pci-host/q35.c | 88 ++++++++++++++++++++++++++++++++++-------
|
|
|
9ae3a8 |
6 files changed, 215 insertions(+), 58 deletions(-)
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
Signed-off-by: Michal Novotny <minovotn@redhat.com>
|
|
|
9ae3a8 |
---
|
|
|
9ae3a8 |
hw/i386/pc.c | 56 ++++++++++++++++-----------
|
|
|
9ae3a8 |
hw/i386/pc_piix.c | 14 +------
|
|
|
9ae3a8 |
hw/pci-host/piix.c | 99 ++++++++++++++++++++++++++++++++++++++++++++---
|
|
|
9ae3a8 |
hw/pci-host/q35.c | 88 ++++++++++++++++++++++++++++++++++-------
|
|
|
9ae3a8 |
include/hw/i386/pc.h | 14 +++++--
|
|
|
9ae3a8 |
include/hw/pci-host/q35.h | 2 +
|
|
|
9ae3a8 |
6 files changed, 215 insertions(+), 58 deletions(-)
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
|
|
|
9ae3a8 |
index 9d9f5d2..e5ebd52 100644
|
|
|
9ae3a8 |
--- a/hw/i386/pc.c
|
|
|
9ae3a8 |
+++ b/hw/i386/pc.c
|
|
|
9ae3a8 |
@@ -55,6 +55,7 @@
|
|
|
9ae3a8 |
#include "hw/acpi/acpi.h"
|
|
|
9ae3a8 |
#include "hw/cpu/icc_bus.h"
|
|
|
9ae3a8 |
#include "hw/boards.h"
|
|
|
9ae3a8 |
+#include "hw/pci/pci_host.h"
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
/* debug PC/ISA interrupts */
|
|
|
9ae3a8 |
//#define DEBUG_IRQ
|
|
|
9ae3a8 |
@@ -996,15 +997,27 @@ typedef struct PcRomPciInfo {
|
|
|
9ae3a8 |
static void pc_fw_cfg_guest_info(PcGuestInfo *guest_info)
|
|
|
9ae3a8 |
{
|
|
|
9ae3a8 |
PcRomPciInfo *info;
|
|
|
9ae3a8 |
+ Object *pci_info;
|
|
|
9ae3a8 |
+ bool ambiguous = false;
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
if (!guest_info->has_pci_info || !guest_info->fw_cfg) {
|
|
|
9ae3a8 |
return;
|
|
|
9ae3a8 |
}
|
|
|
9ae3a8 |
+ pci_info = object_resolve_path_type("", TYPE_PCI_HOST_BRIDGE, &ambiguous);
|
|
|
9ae3a8 |
+ g_assert(!ambiguous);
|
|
|
9ae3a8 |
+ if (!pci_info) {
|
|
|
9ae3a8 |
+ return;
|
|
|
9ae3a8 |
+ }
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
info = g_malloc(sizeof *info);
|
|
|
9ae3a8 |
- info->w32_min = cpu_to_le64(guest_info->pci_info.w32.begin);
|
|
|
9ae3a8 |
- info->w32_max = cpu_to_le64(guest_info->pci_info.w32.end);
|
|
|
9ae3a8 |
- info->w64_min = cpu_to_le64(guest_info->pci_info.w64.begin);
|
|
|
9ae3a8 |
- info->w64_max = cpu_to_le64(guest_info->pci_info.w64.end);
|
|
|
9ae3a8 |
+ info->w32_min = cpu_to_le64(object_property_get_int(pci_info,
|
|
|
9ae3a8 |
+ PCI_HOST_PROP_PCI_HOLE_START, NULL));
|
|
|
9ae3a8 |
+ info->w32_max = cpu_to_le64(object_property_get_int(pci_info,
|
|
|
9ae3a8 |
+ PCI_HOST_PROP_PCI_HOLE_END, NULL));
|
|
|
9ae3a8 |
+ info->w64_min = cpu_to_le64(object_property_get_int(pci_info,
|
|
|
9ae3a8 |
+ PCI_HOST_PROP_PCI_HOLE64_START, NULL));
|
|
|
9ae3a8 |
+ info->w64_max = cpu_to_le64(object_property_get_int(pci_info,
|
|
|
9ae3a8 |
+ PCI_HOST_PROP_PCI_HOLE64_END, NULL));
|
|
|
9ae3a8 |
/* Pass PCI hole info to guest via a side channel.
|
|
|
9ae3a8 |
* Required so guest PCI enumeration does the right thing. */
|
|
|
9ae3a8 |
fw_cfg_add_file(guest_info->fw_cfg, "etc/pci-info", info, sizeof *info);
|
|
|
9ae3a8 |
@@ -1030,29 +1043,28 @@ PcGuestInfo *pc_guest_info_init(ram_addr_t below_4g_mem_size,
|
|
|
9ae3a8 |
PcGuestInfoState *guest_info_state = g_malloc0(sizeof *guest_info_state);
|
|
|
9ae3a8 |
PcGuestInfo *guest_info = &guest_info_state->info;
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
- guest_info->pci_info.w32.end = IO_APIC_DEFAULT_ADDRESS;
|
|
|
9ae3a8 |
- if (sizeof(hwaddr) == 4) {
|
|
|
9ae3a8 |
- guest_info->pci_info.w64.begin = 0;
|
|
|
9ae3a8 |
- guest_info->pci_info.w64.end = 0;
|
|
|
9ae3a8 |
- } else {
|
|
|
9ae3a8 |
- /*
|
|
|
9ae3a8 |
- * BIOS does not set MTRR entries for the 64 bit window, so no need to
|
|
|
9ae3a8 |
- * align address to power of two. Align address at 1G, this makes sure
|
|
|
9ae3a8 |
- * it can be exactly covered with a PAT entry even when using huge
|
|
|
9ae3a8 |
- * pages.
|
|
|
9ae3a8 |
- */
|
|
|
9ae3a8 |
- guest_info->pci_info.w64.begin =
|
|
|
9ae3a8 |
- ROUND_UP((0x1ULL << 32) + above_4g_mem_size, 0x1ULL << 30);
|
|
|
9ae3a8 |
- guest_info->pci_info.w64.end = guest_info->pci_info.w64.begin +
|
|
|
9ae3a8 |
- (0x1ULL << 62);
|
|
|
9ae3a8 |
- assert(guest_info->pci_info.w64.begin <= guest_info->pci_info.w64.end);
|
|
|
9ae3a8 |
- }
|
|
|
9ae3a8 |
-
|
|
|
9ae3a8 |
guest_info_state->machine_done.notify = pc_guest_info_machine_done;
|
|
|
9ae3a8 |
qemu_add_machine_init_done_notifier(&guest_info_state->machine_done);
|
|
|
9ae3a8 |
return guest_info;
|
|
|
9ae3a8 |
}
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
+void pc_init_pci64_hole(PcPciInfo *pci_info, uint64_t pci_hole64_start,
|
|
|
9ae3a8 |
+ uint64_t pci_hole64_size)
|
|
|
9ae3a8 |
+{
|
|
|
9ae3a8 |
+ if ((sizeof(hwaddr) == 4) || (!pci_hole64_size)) {
|
|
|
9ae3a8 |
+ return;
|
|
|
9ae3a8 |
+ }
|
|
|
9ae3a8 |
+ /*
|
|
|
9ae3a8 |
+ * BIOS does not set MTRR entries for the 64 bit window, so no need to
|
|
|
9ae3a8 |
+ * align address to power of two. Align address at 1G, this makes sure
|
|
|
9ae3a8 |
+ * it can be exactly covered with a PAT entry even when using huge
|
|
|
9ae3a8 |
+ * pages.
|
|
|
9ae3a8 |
+ */
|
|
|
9ae3a8 |
+ pci_info->w64.begin = ROUND_UP(pci_hole64_start, 0x1ULL << 30);
|
|
|
9ae3a8 |
+ pci_info->w64.end = pci_info->w64.begin + pci_hole64_size;
|
|
|
9ae3a8 |
+ assert(pci_info->w64.begin <= pci_info->w64.end);
|
|
|
9ae3a8 |
+}
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
void pc_acpi_init(const char *default_dsdt)
|
|
|
9ae3a8 |
{
|
|
|
9ae3a8 |
char *filename;
|
|
|
9ae3a8 |
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
|
|
|
9ae3a8 |
index 6d50a4e..211ff8e 100644
|
|
|
9ae3a8 |
--- a/hw/i386/pc_piix.c
|
|
|
9ae3a8 |
+++ b/hw/i386/pc_piix.c
|
|
|
9ae3a8 |
@@ -125,15 +125,6 @@ static void pc_init1(QEMUMachineInitArgs *args,
|
|
|
9ae3a8 |
guest_info = pc_guest_info_init(below_4g_mem_size, above_4g_mem_size);
|
|
|
9ae3a8 |
guest_info->has_pci_info = has_pci_info;
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
- /* Set PCI window size the way seabios has always done it. */
|
|
|
9ae3a8 |
- /* Power of 2 so bios can cover it with a single MTRR */
|
|
|
9ae3a8 |
- if (ram_size <= 0x80000000)
|
|
|
9ae3a8 |
- guest_info->pci_info.w32.begin = 0x80000000;
|
|
|
9ae3a8 |
- else if (ram_size <= 0xc0000000)
|
|
|
9ae3a8 |
- guest_info->pci_info.w32.begin = 0xc0000000;
|
|
|
9ae3a8 |
- else
|
|
|
9ae3a8 |
- guest_info->pci_info.w32.begin = 0xe0000000;
|
|
|
9ae3a8 |
-
|
|
|
9ae3a8 |
/* allocate ram and load rom/bios */
|
|
|
9ae3a8 |
if (!xen_enabled()) {
|
|
|
9ae3a8 |
fw_cfg = pc_memory_init(system_memory,
|
|
|
9ae3a8 |
@@ -157,10 +148,7 @@ static void pc_init1(QEMUMachineInitArgs *args,
|
|
|
9ae3a8 |
system_memory, system_io, args->ram_size,
|
|
|
9ae3a8 |
below_4g_mem_size,
|
|
|
9ae3a8 |
0x100000000ULL - below_4g_mem_size,
|
|
|
9ae3a8 |
- 0x100000000ULL + above_4g_mem_size,
|
|
|
9ae3a8 |
- (sizeof(hwaddr) == 4
|
|
|
9ae3a8 |
- ? 0
|
|
|
9ae3a8 |
- : ((uint64_t)1 << 62)),
|
|
|
9ae3a8 |
+ above_4g_mem_size,
|
|
|
9ae3a8 |
pci_memory, ram_memory);
|
|
|
9ae3a8 |
} else {
|
|
|
9ae3a8 |
pci_bus = NULL;
|
|
|
9ae3a8 |
diff --git a/hw/pci-host/piix.c b/hw/pci-host/piix.c
|
|
|
9ae3a8 |
index adc094a..167d1fd 100644
|
|
|
9ae3a8 |
--- a/hw/pci-host/piix.c
|
|
|
9ae3a8 |
+++ b/hw/pci-host/piix.c
|
|
|
9ae3a8 |
@@ -32,6 +32,8 @@
|
|
|
9ae3a8 |
#include "hw/xen/xen.h"
|
|
|
9ae3a8 |
#include "hw/pci-host/pam.h"
|
|
|
9ae3a8 |
#include "sysemu/sysemu.h"
|
|
|
9ae3a8 |
+#include "hw/i386/ioapic.h"
|
|
|
9ae3a8 |
+#include "qapi/visitor.h"
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
/*
|
|
|
9ae3a8 |
* I440FX chipset data sheet.
|
|
|
9ae3a8 |
@@ -44,6 +46,8 @@
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
typedef struct I440FXState {
|
|
|
9ae3a8 |
PCIHostState parent_obj;
|
|
|
9ae3a8 |
+ PcPciInfo pci_info;
|
|
|
9ae3a8 |
+ uint64_t pci_hole64_size;
|
|
|
9ae3a8 |
} I440FXState;
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
#define PIIX_NUM_PIC_IRQS 16 /* i8259 * 2 */
|
|
|
9ae3a8 |
@@ -201,9 +205,49 @@ static const VMStateDescription vmstate_i440fx = {
|
|
|
9ae3a8 |
}
|
|
|
9ae3a8 |
};
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
+static void i440fx_pcihost_get_pci_hole_start(Object *obj, Visitor *v,
|
|
|
9ae3a8 |
+ void *opaque, const char *name,
|
|
|
9ae3a8 |
+ Error **errp)
|
|
|
9ae3a8 |
+{
|
|
|
9ae3a8 |
+ I440FXState *s = I440FX_PCI_HOST_BRIDGE(obj);
|
|
|
9ae3a8 |
+ uint32_t value = s->pci_info.w32.begin;
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
+ visit_type_uint32(v, &value, name, errp);
|
|
|
9ae3a8 |
+}
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
+static void i440fx_pcihost_get_pci_hole_end(Object *obj, Visitor *v,
|
|
|
9ae3a8 |
+ void *opaque, const char *name,
|
|
|
9ae3a8 |
+ Error **errp)
|
|
|
9ae3a8 |
+{
|
|
|
9ae3a8 |
+ I440FXState *s = I440FX_PCI_HOST_BRIDGE(obj);
|
|
|
9ae3a8 |
+ uint32_t value = s->pci_info.w32.end;
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
+ visit_type_uint32(v, &value, name, errp);
|
|
|
9ae3a8 |
+}
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
+static void i440fx_pcihost_get_pci_hole64_start(Object *obj, Visitor *v,
|
|
|
9ae3a8 |
+ void *opaque, const char *name,
|
|
|
9ae3a8 |
+ Error **errp)
|
|
|
9ae3a8 |
+{
|
|
|
9ae3a8 |
+ I440FXState *s = I440FX_PCI_HOST_BRIDGE(obj);
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
+ visit_type_uint64(v, &s->pci_info.w64.begin, name, errp);
|
|
|
9ae3a8 |
+}
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
+static void i440fx_pcihost_get_pci_hole64_end(Object *obj, Visitor *v,
|
|
|
9ae3a8 |
+ void *opaque, const char *name,
|
|
|
9ae3a8 |
+ Error **errp)
|
|
|
9ae3a8 |
+{
|
|
|
9ae3a8 |
+ I440FXState *s = I440FX_PCI_HOST_BRIDGE(obj);
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
+ visit_type_uint64(v, &s->pci_info.w64.end, name, errp);
|
|
|
9ae3a8 |
+}
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
static int i440fx_pcihost_initfn(SysBusDevice *dev)
|
|
|
9ae3a8 |
{
|
|
|
9ae3a8 |
PCIHostState *s = PCI_HOST_BRIDGE(dev);
|
|
|
9ae3a8 |
+ I440FXState *d = I440FX_PCI_HOST_BRIDGE(s);
|
|
|
9ae3a8 |
+ Object *obj = OBJECT(s);
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
memory_region_init_io(&s->conf_mem, &pci_host_conf_le_ops, s,
|
|
|
9ae3a8 |
"pci-conf-idx", 4);
|
|
|
9ae3a8 |
@@ -212,6 +256,27 @@ static int i440fx_pcihost_initfn(SysBusDevice *dev)
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
memory_region_init_io(&s->data_mem, &pci_host_data_le_ops, s,
|
|
|
9ae3a8 |
"pci-conf-data", 4);
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
+ object_property_add(obj, PCI_HOST_PROP_PCI_HOLE_START, "int",
|
|
|
9ae3a8 |
+ i440fx_pcihost_get_pci_hole_start,
|
|
|
9ae3a8 |
+ NULL, NULL, NULL, NULL);
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
+ object_property_add(obj, PCI_HOST_PROP_PCI_HOLE_END, "int",
|
|
|
9ae3a8 |
+ i440fx_pcihost_get_pci_hole_end,
|
|
|
9ae3a8 |
+ NULL, NULL, NULL, NULL);
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
+ object_property_add(obj, PCI_HOST_PROP_PCI_HOLE64_START, "int",
|
|
|
9ae3a8 |
+ i440fx_pcihost_get_pci_hole64_start,
|
|
|
9ae3a8 |
+ NULL, NULL, NULL, NULL);
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
+ object_property_add(obj, PCI_HOST_PROP_PCI_HOLE64_END, "int",
|
|
|
9ae3a8 |
+ i440fx_pcihost_get_pci_hole64_end,
|
|
|
9ae3a8 |
+ NULL, NULL, NULL, NULL);
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
+ d->pci_info.w32.end = IO_APIC_DEFAULT_ADDRESS;
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
+ memory_region_init_io(&s->data_mem, &pci_host_data_le_ops, s,
|
|
|
9ae3a8 |
+ "pci-conf-data", 4);
|
|
|
9ae3a8 |
sysbus_add_io(dev, 0xcfc, &s->data_mem);
|
|
|
9ae3a8 |
sysbus_init_ioports(&s->busdev, 0xcfc, 4);
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
@@ -236,8 +301,7 @@ PCIBus *i440fx_init(PCII440FXState **pi440fx_state,
|
|
|
9ae3a8 |
ram_addr_t ram_size,
|
|
|
9ae3a8 |
hwaddr pci_hole_start,
|
|
|
9ae3a8 |
hwaddr pci_hole_size,
|
|
|
9ae3a8 |
- hwaddr pci_hole64_start,
|
|
|
9ae3a8 |
- hwaddr pci_hole64_size,
|
|
|
9ae3a8 |
+ ram_addr_t above_4g_mem_size,
|
|
|
9ae3a8 |
MemoryRegion *pci_address_space,
|
|
|
9ae3a8 |
MemoryRegion *ram_memory)
|
|
|
9ae3a8 |
{
|
|
|
9ae3a8 |
@@ -248,6 +312,7 @@ PCIBus *i440fx_init(PCII440FXState **pi440fx_state,
|
|
|
9ae3a8 |
PIIX3State *piix3;
|
|
|
9ae3a8 |
PCII440FXState *f;
|
|
|
9ae3a8 |
unsigned i;
|
|
|
9ae3a8 |
+ I440FXState *i440fx;
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
dev = qdev_create(NULL, TYPE_I440FX_PCI_HOST_BRIDGE);
|
|
|
9ae3a8 |
s = PCI_HOST_BRIDGE(dev);
|
|
|
9ae3a8 |
@@ -263,14 +328,31 @@ PCIBus *i440fx_init(PCII440FXState **pi440fx_state,
|
|
|
9ae3a8 |
f->system_memory = address_space_mem;
|
|
|
9ae3a8 |
f->pci_address_space = pci_address_space;
|
|
|
9ae3a8 |
f->ram_memory = ram_memory;
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
+ i440fx = I440FX_PCI_HOST_BRIDGE(dev);
|
|
|
9ae3a8 |
+ /* Set PCI window size the way seabios has always done it. */
|
|
|
9ae3a8 |
+ /* Power of 2 so bios can cover it with a single MTRR */
|
|
|
9ae3a8 |
+ if (ram_size <= 0x80000000) {
|
|
|
9ae3a8 |
+ i440fx->pci_info.w32.begin = 0x80000000;
|
|
|
9ae3a8 |
+ } else if (ram_size <= 0xc0000000) {
|
|
|
9ae3a8 |
+ i440fx->pci_info.w32.begin = 0xc0000000;
|
|
|
9ae3a8 |
+ } else {
|
|
|
9ae3a8 |
+ i440fx->pci_info.w32.begin = 0xe0000000;
|
|
|
9ae3a8 |
+ }
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
memory_region_init_alias(&f->pci_hole, "pci-hole", f->pci_address_space,
|
|
|
9ae3a8 |
pci_hole_start, pci_hole_size);
|
|
|
9ae3a8 |
memory_region_add_subregion(f->system_memory, pci_hole_start, &f->pci_hole);
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
+ pc_init_pci64_hole(&i440fx->pci_info, 0x100000000ULL + above_4g_mem_size,
|
|
|
9ae3a8 |
+ i440fx->pci_hole64_size);
|
|
|
9ae3a8 |
memory_region_init_alias(&f->pci_hole_64bit, "pci-hole64",
|
|
|
9ae3a8 |
f->pci_address_space,
|
|
|
9ae3a8 |
- pci_hole64_start, pci_hole64_size);
|
|
|
9ae3a8 |
- if (pci_hole64_size) {
|
|
|
9ae3a8 |
- memory_region_add_subregion(f->system_memory, pci_hole64_start,
|
|
|
9ae3a8 |
+ i440fx->pci_info.w64.begin,
|
|
|
9ae3a8 |
+ i440fx->pci_hole64_size);
|
|
|
9ae3a8 |
+ if (i440fx->pci_hole64_size) {
|
|
|
9ae3a8 |
+ memory_region_add_subregion(f->system_memory,
|
|
|
9ae3a8 |
+ i440fx->pci_info.w64.begin,
|
|
|
9ae3a8 |
&f->pci_hole_64bit);
|
|
|
9ae3a8 |
}
|
|
|
9ae3a8 |
memory_region_init_alias(&f->smram_region, "smram-region",
|
|
|
9ae3a8 |
@@ -621,6 +703,12 @@ static const TypeInfo i440fx_info = {
|
|
|
9ae3a8 |
.class_init = i440fx_class_init,
|
|
|
9ae3a8 |
};
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
+static Property i440fx_props[] = {
|
|
|
9ae3a8 |
+ DEFINE_PROP_SIZE(PCI_HOST_PROP_PCI_HOLE64_SIZE, I440FXState,
|
|
|
9ae3a8 |
+ pci_hole64_size, DEFAULT_PCI_HOLE64_SIZE),
|
|
|
9ae3a8 |
+ DEFINE_PROP_END_OF_LIST(),
|
|
|
9ae3a8 |
+};
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
static void i440fx_pcihost_class_init(ObjectClass *klass, void *data)
|
|
|
9ae3a8 |
{
|
|
|
9ae3a8 |
DeviceClass *dc = DEVICE_CLASS(klass);
|
|
|
9ae3a8 |
@@ -628,6 +716,7 @@ static void i440fx_pcihost_class_init(ObjectClass *klass, void *data)
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
k->init = i440fx_pcihost_initfn;
|
|
|
9ae3a8 |
dc->fw_name = "pci";
|
|
|
9ae3a8 |
+ dc->props = i440fx_props;
|
|
|
9ae3a8 |
}
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
static const TypeInfo i440fx_pcihost_info = {
|
|
|
9ae3a8 |
diff --git a/hw/pci-host/q35.c b/hw/pci-host/q35.c
|
|
|
9ae3a8 |
index 0989fc5..be12eee 100644
|
|
|
9ae3a8 |
--- a/hw/pci-host/q35.c
|
|
|
9ae3a8 |
+++ b/hw/pci-host/q35.c
|
|
|
9ae3a8 |
@@ -29,6 +29,7 @@
|
|
|
9ae3a8 |
*/
|
|
|
9ae3a8 |
#include "hw/hw.h"
|
|
|
9ae3a8 |
#include "hw/pci-host/q35.h"
|
|
|
9ae3a8 |
+#include "qapi/visitor.h"
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
/****************************************************************************
|
|
|
9ae3a8 |
* Q35 host
|
|
|
9ae3a8 |
@@ -63,9 +64,49 @@ static int q35_host_init(SysBusDevice *dev)
|
|
|
9ae3a8 |
return 0;
|
|
|
9ae3a8 |
}
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
+static void q35_host_get_pci_hole_start(Object *obj, Visitor *v,
|
|
|
9ae3a8 |
+ void *opaque, const char *name,
|
|
|
9ae3a8 |
+ Error **errp)
|
|
|
9ae3a8 |
+{
|
|
|
9ae3a8 |
+ Q35PCIHost *s = Q35_HOST_DEVICE(obj);
|
|
|
9ae3a8 |
+ uint32_t value = s->mch.pci_info.w32.begin;
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
+ visit_type_uint32(v, &value, name, errp);
|
|
|
9ae3a8 |
+}
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
+static void q35_host_get_pci_hole_end(Object *obj, Visitor *v,
|
|
|
9ae3a8 |
+ void *opaque, const char *name,
|
|
|
9ae3a8 |
+ Error **errp)
|
|
|
9ae3a8 |
+{
|
|
|
9ae3a8 |
+ Q35PCIHost *s = Q35_HOST_DEVICE(obj);
|
|
|
9ae3a8 |
+ uint32_t value = s->mch.pci_info.w32.end;
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
+ visit_type_uint32(v, &value, name, errp);
|
|
|
9ae3a8 |
+}
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
+static void q35_host_get_pci_hole64_start(Object *obj, Visitor *v,
|
|
|
9ae3a8 |
+ void *opaque, const char *name,
|
|
|
9ae3a8 |
+ Error **errp)
|
|
|
9ae3a8 |
+{
|
|
|
9ae3a8 |
+ Q35PCIHost *s = Q35_HOST_DEVICE(obj);
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
+ visit_type_uint64(v, &s->mch.pci_info.w64.begin, name, errp);
|
|
|
9ae3a8 |
+}
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
+static void q35_host_get_pci_hole64_end(Object *obj, Visitor *v,
|
|
|
9ae3a8 |
+ void *opaque, const char *name,
|
|
|
9ae3a8 |
+ Error **errp)
|
|
|
9ae3a8 |
+{
|
|
|
9ae3a8 |
+ Q35PCIHost *s = Q35_HOST_DEVICE(obj);
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
+ visit_type_uint64(v, &s->mch.pci_info.w64.end, name, errp);
|
|
|
9ae3a8 |
+}
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
static Property mch_props[] = {
|
|
|
9ae3a8 |
DEFINE_PROP_UINT64("MCFG", Q35PCIHost, host.base_addr,
|
|
|
9ae3a8 |
MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT),
|
|
|
9ae3a8 |
+ DEFINE_PROP_SIZE(PCI_HOST_PROP_PCI_HOLE64_SIZE, Q35PCIHost,
|
|
|
9ae3a8 |
+ mch.pci_hole64_size, DEFAULT_PCI_HOLE64_SIZE),
|
|
|
9ae3a8 |
DEFINE_PROP_END_OF_LIST(),
|
|
|
9ae3a8 |
};
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
@@ -88,6 +129,31 @@ static void q35_host_initfn(Object *obj)
|
|
|
9ae3a8 |
object_property_add_child(OBJECT(s), "mch", OBJECT(&s->mch), NULL);
|
|
|
9ae3a8 |
qdev_prop_set_uint32(DEVICE(&s->mch), "addr", PCI_DEVFN(0, 0));
|
|
|
9ae3a8 |
qdev_prop_set_bit(DEVICE(&s->mch), "multifunction", false);
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
+ object_property_add(obj, PCI_HOST_PROP_PCI_HOLE_START, "int",
|
|
|
9ae3a8 |
+ q35_host_get_pci_hole_start,
|
|
|
9ae3a8 |
+ NULL, NULL, NULL, NULL);
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
+ object_property_add(obj, PCI_HOST_PROP_PCI_HOLE_END, "int",
|
|
|
9ae3a8 |
+ q35_host_get_pci_hole_end,
|
|
|
9ae3a8 |
+ NULL, NULL, NULL, NULL);
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
+ object_property_add(obj, PCI_HOST_PROP_PCI_HOLE64_START, "int",
|
|
|
9ae3a8 |
+ q35_host_get_pci_hole64_start,
|
|
|
9ae3a8 |
+ NULL, NULL, NULL, NULL);
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
+ object_property_add(obj, PCI_HOST_PROP_PCI_HOLE64_END, "int",
|
|
|
9ae3a8 |
+ q35_host_get_pci_hole64_end,
|
|
|
9ae3a8 |
+ NULL, NULL, NULL, NULL);
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
+ /* Leave enough space for the biggest MCFG BAR */
|
|
|
9ae3a8 |
+ /* TODO: this matches current bios behaviour, but
|
|
|
9ae3a8 |
+ * it's not a power of two, which means an MTRR
|
|
|
9ae3a8 |
+ * can't cover it exactly.
|
|
|
9ae3a8 |
+ */
|
|
|
9ae3a8 |
+ s->mch.pci_info.w32.begin = MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT +
|
|
|
9ae3a8 |
+ MCH_HOST_BRIDGE_PCIEXBAR_MAX;
|
|
|
9ae3a8 |
+ s->mch.pci_info.w32.end = IO_APIC_DEFAULT_ADDRESS;
|
|
|
9ae3a8 |
}
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
static const TypeInfo q35_host_info = {
|
|
|
9ae3a8 |
@@ -242,17 +308,8 @@ static void mch_reset(DeviceState *qdev)
|
|
|
9ae3a8 |
static int mch_init(PCIDevice *d)
|
|
|
9ae3a8 |
{
|
|
|
9ae3a8 |
int i;
|
|
|
9ae3a8 |
- hwaddr pci_hole64_size;
|
|
|
9ae3a8 |
MCHPCIState *mch = MCH_PCI_DEVICE(d);
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
- /* Leave enough space for the biggest MCFG BAR */
|
|
|
9ae3a8 |
- /* TODO: this matches current bios behaviour, but
|
|
|
9ae3a8 |
- * it's not a power of two, which means an MTRR
|
|
|
9ae3a8 |
- * can't cover it exactly.
|
|
|
9ae3a8 |
- */
|
|
|
9ae3a8 |
- mch->guest_info->pci_info.w32.begin = MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT +
|
|
|
9ae3a8 |
- MCH_HOST_BRIDGE_PCIEXBAR_MAX;
|
|
|
9ae3a8 |
-
|
|
|
9ae3a8 |
/* setup pci memory regions */
|
|
|
9ae3a8 |
memory_region_init_alias(&mch->pci_hole, "pci-hole",
|
|
|
9ae3a8 |
mch->pci_address_space,
|
|
|
9ae3a8 |
@@ -260,15 +317,16 @@ static int mch_init(PCIDevice *d)
|
|
|
9ae3a8 |
0x100000000ULL - mch->below_4g_mem_size);
|
|
|
9ae3a8 |
memory_region_add_subregion(mch->system_memory, mch->below_4g_mem_size,
|
|
|
9ae3a8 |
&mch->pci_hole);
|
|
|
9ae3a8 |
- pci_hole64_size = (sizeof(hwaddr) == 4 ? 0 :
|
|
|
9ae3a8 |
- ((uint64_t)1 << 62));
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
+ pc_init_pci64_hole(&mch->pci_info, 0x100000000ULL + mch->above_4g_mem_size,
|
|
|
9ae3a8 |
+ mch->pci_hole64_size);
|
|
|
9ae3a8 |
memory_region_init_alias(&mch->pci_hole_64bit, "pci-hole64",
|
|
|
9ae3a8 |
mch->pci_address_space,
|
|
|
9ae3a8 |
- 0x100000000ULL + mch->above_4g_mem_size,
|
|
|
9ae3a8 |
- pci_hole64_size);
|
|
|
9ae3a8 |
- if (pci_hole64_size) {
|
|
|
9ae3a8 |
+ mch->pci_info.w64.begin,
|
|
|
9ae3a8 |
+ mch->pci_hole64_size);
|
|
|
9ae3a8 |
+ if (mch->pci_hole64_size) {
|
|
|
9ae3a8 |
memory_region_add_subregion(mch->system_memory,
|
|
|
9ae3a8 |
- 0x100000000ULL + mch->above_4g_mem_size,
|
|
|
9ae3a8 |
+ mch->pci_info.w64.begin,
|
|
|
9ae3a8 |
&mch->pci_hole_64bit);
|
|
|
9ae3a8 |
}
|
|
|
9ae3a8 |
/* smram */
|
|
|
9ae3a8 |
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
|
|
|
9ae3a8 |
index 2992464..fe21bc3 100644
|
|
|
9ae3a8 |
--- a/include/hw/i386/pc.h
|
|
|
9ae3a8 |
+++ b/include/hw/i386/pc.h
|
|
|
9ae3a8 |
@@ -20,7 +20,6 @@ typedef struct PcPciInfo {
|
|
|
9ae3a8 |
} PcPciInfo;
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
struct PcGuestInfo {
|
|
|
9ae3a8 |
- PcPciInfo pci_info;
|
|
|
9ae3a8 |
bool has_pci_info;
|
|
|
9ae3a8 |
FWCfgState *fw_cfg;
|
|
|
9ae3a8 |
};
|
|
|
9ae3a8 |
@@ -101,6 +100,16 @@ void pc_acpi_init(const char *default_dsdt);
|
|
|
9ae3a8 |
PcGuestInfo *pc_guest_info_init(ram_addr_t below_4g_mem_size,
|
|
|
9ae3a8 |
ram_addr_t above_4g_mem_size);
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
+#define PCI_HOST_PROP_PCI_HOLE_START "pci-hole-start"
|
|
|
9ae3a8 |
+#define PCI_HOST_PROP_PCI_HOLE_END "pci-hole-end"
|
|
|
9ae3a8 |
+#define PCI_HOST_PROP_PCI_HOLE64_START "pci-hole64-start"
|
|
|
9ae3a8 |
+#define PCI_HOST_PROP_PCI_HOLE64_END "pci-hole64-end"
|
|
|
9ae3a8 |
+#define PCI_HOST_PROP_PCI_HOLE64_SIZE "pci-hole64-size"
|
|
|
9ae3a8 |
+#define DEFAULT_PCI_HOLE64_SIZE (1ULL << 31)
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
+void pc_init_pci64_hole(PcPciInfo *pci_info, uint64_t pci_hole64_start,
|
|
|
9ae3a8 |
+ uint64_t pci_hole64_size);
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
FWCfgState *pc_memory_init(MemoryRegion *system_memory,
|
|
|
9ae3a8 |
const char *kernel_filename,
|
|
|
9ae3a8 |
const char *kernel_cmdline,
|
|
|
9ae3a8 |
@@ -150,8 +159,7 @@ PCIBus *i440fx_init(PCII440FXState **pi440fx_state, int *piix_devfn,
|
|
|
9ae3a8 |
ram_addr_t ram_size,
|
|
|
9ae3a8 |
hwaddr pci_hole_start,
|
|
|
9ae3a8 |
hwaddr pci_hole_size,
|
|
|
9ae3a8 |
- hwaddr pci_hole64_start,
|
|
|
9ae3a8 |
- hwaddr pci_hole64_size,
|
|
|
9ae3a8 |
+ ram_addr_t above_4g_mem_size,
|
|
|
9ae3a8 |
MemoryRegion *pci_memory,
|
|
|
9ae3a8 |
MemoryRegion *ram_memory);
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
diff --git a/include/hw/pci-host/q35.h b/include/hw/pci-host/q35.h
|
|
|
9ae3a8 |
index b083831..e660a40 100644
|
|
|
9ae3a8 |
--- a/include/hw/pci-host/q35.h
|
|
|
9ae3a8 |
+++ b/include/hw/pci-host/q35.h
|
|
|
9ae3a8 |
@@ -52,9 +52,11 @@ typedef struct MCHPCIState {
|
|
|
9ae3a8 |
MemoryRegion smram_region;
|
|
|
9ae3a8 |
MemoryRegion pci_hole;
|
|
|
9ae3a8 |
MemoryRegion pci_hole_64bit;
|
|
|
9ae3a8 |
+ PcPciInfo pci_info;
|
|
|
9ae3a8 |
uint8_t smm_enabled;
|
|
|
9ae3a8 |
ram_addr_t below_4g_mem_size;
|
|
|
9ae3a8 |
ram_addr_t above_4g_mem_size;
|
|
|
9ae3a8 |
+ uint64_t pci_hole64_size;
|
|
|
9ae3a8 |
PcGuestInfo *guest_info;
|
|
|
9ae3a8 |
} MCHPCIState;
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
--
|
|
|
9ae3a8 |
1.7.11.7
|
|
|
9ae3a8 |
|