visit_type_uint32(v, name, &value, errp);
}
-static Property mch_props[] = {
+static Property q35_host_props[] = {
DEFINE_PROP_UINT64(PCIE_HOST_MCFG_BASE, Q35PCIHost, parent_obj.base_addr,
MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT),
DEFINE_PROP_SIZE(PCI_HOST_PROP_PCI_HOLE64_SIZE, Q35PCIHost,
hc->root_bus_path = q35_host_root_bus_path;
dc->realize = q35_host_realize;
- dc->props = mch_props;
+ dc->props = q35_host_props;
/* Reason: needs to be wired up by pc_q35_init */
dc->user_creatable = false;
set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
tseg_size = 1024 * 1024 * 8;
break;
default:
- tseg_size = 0;
+ tseg_size = 1024 * 1024 * (uint32_t)mch->ext_tseg_mbytes;
break;
}
} else {
memory_region_transaction_commit();
}
+static void mch_update_ext_tseg_mbytes(MCHPCIState *mch)
+{
+ PCIDevice *pd = PCI_DEVICE(mch);
+ uint8_t *reg = pd->config + MCH_HOST_BRIDGE_EXT_TSEG_MBYTES;
+
+ if (mch->ext_tseg_mbytes > 0 &&
+ pci_get_word(reg) == MCH_HOST_BRIDGE_EXT_TSEG_MBYTES_QUERY) {
+ pci_set_word(reg, mch->ext_tseg_mbytes);
+ }
+}
+
static void mch_write_config(PCIDevice *d,
uint32_t address, uint32_t val, int len)
{
MCH_HOST_BRIDGE_SMRAM_SIZE)) {
mch_update_smram(mch);
}
+
+ if (ranges_overlap(address, len, MCH_HOST_BRIDGE_EXT_TSEG_MBYTES,
+ MCH_HOST_BRIDGE_EXT_TSEG_MBYTES_SIZE)) {
+ mch_update_ext_tseg_mbytes(mch);
+ }
}
static void mch_update(MCHPCIState *mch)
mch_update_pciexbar(mch);
mch_update_pam(mch);
mch_update_smram(mch);
+ mch_update_ext_tseg_mbytes(mch);
}
static int mch_post_load(void *opaque, int version_id)
d->wmask[MCH_HOST_BRIDGE_SMRAM] = MCH_HOST_BRIDGE_SMRAM_WMASK;
d->wmask[MCH_HOST_BRIDGE_ESMRAMC] = MCH_HOST_BRIDGE_ESMRAMC_WMASK;
+ if (mch->ext_tseg_mbytes > 0) {
+ pci_set_word(d->config + MCH_HOST_BRIDGE_EXT_TSEG_MBYTES,
+ MCH_HOST_BRIDGE_EXT_TSEG_MBYTES_QUERY);
+ }
+
mch_update(mch);
}
int i;
MCHPCIState *mch = MCH_PCI_DEVICE(d);
+ if (mch->ext_tseg_mbytes > MCH_HOST_BRIDGE_EXT_TSEG_MBYTES_MAX) {
+ error_setg(errp, "invalid extended-tseg-mbytes value: %" PRIu16,
+ mch->ext_tseg_mbytes);
+ return;
+ }
+
/* setup pci memory mapping */
pc_pci_as_mapping_init(OBJECT(mch), mch->system_memory,
mch->pci_address_space);
return MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT;
}
+static Property mch_props[] = {
+ DEFINE_PROP_UINT16("extended-tseg-mbytes", MCHPCIState, ext_tseg_mbytes,
+ 16),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
static void mch_class_init(ObjectClass *klass, void *data)
{
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
k->realize = mch_realize;
k->config_write = mch_write_config;
dc->reset = mch_reset;
+ dc->props = mch_props;
set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
dc->desc = "Host bridge";
dc->vmsd = &vmstate_mch;
uint64_t above_4g_mem_size;
uint64_t pci_hole64_size;
uint32_t short_root_bus;
+ uint16_t ext_tseg_mbytes;
} MCHPCIState;
typedef struct Q35PCIHost {
/* D0:F0 configuration space */
#define MCH_HOST_BRIDGE_REVISION_DEFAULT 0x0
+#define MCH_HOST_BRIDGE_EXT_TSEG_MBYTES 0x50
+#define MCH_HOST_BRIDGE_EXT_TSEG_MBYTES_SIZE 2
+#define MCH_HOST_BRIDGE_EXT_TSEG_MBYTES_QUERY 0xffff
+#define MCH_HOST_BRIDGE_EXT_TSEG_MBYTES_MAX 0xfff
+
#define MCH_HOST_BRIDGE_PCIEXBAR 0x60 /* 64bit register */
#define MCH_HOST_BRIDGE_PCIEXBAR_SIZE 8 /* 64bit register */
#define MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT 0xb0000000