|
@@ -275,20 +275,20 @@ static const TypeInfo q35_host_info = {
|
|
|
* MCH D0:F0
|
|
|
*/
|
|
|
|
|
|
-static uint64_t tseg_blackhole_read(void *ptr, hwaddr reg, unsigned size)
|
|
|
+static uint64_t blackhole_read(void *ptr, hwaddr reg, unsigned size)
|
|
|
{
|
|
|
return 0xffffffff;
|
|
|
}
|
|
|
|
|
|
-static void tseg_blackhole_write(void *opaque, hwaddr addr, uint64_t val,
|
|
|
- unsigned width)
|
|
|
+static void blackhole_write(void *opaque, hwaddr addr, uint64_t val,
|
|
|
+ unsigned width)
|
|
|
{
|
|
|
/* nothing */
|
|
|
}
|
|
|
|
|
|
-static const MemoryRegionOps tseg_blackhole_ops = {
|
|
|
- .read = tseg_blackhole_read,
|
|
|
- .write = tseg_blackhole_write,
|
|
|
+static const MemoryRegionOps blackhole_ops = {
|
|
|
+ .read = blackhole_read,
|
|
|
+ .write = blackhole_write,
|
|
|
.endianness = DEVICE_NATIVE_ENDIAN,
|
|
|
.valid.min_access_size = 1,
|
|
|
.valid.max_access_size = 4,
|
|
@@ -430,6 +430,46 @@ static void mch_update_ext_tseg_mbytes(MCHPCIState *mch)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+static void mch_update_smbase_smram(MCHPCIState *mch)
|
|
|
+{
|
|
|
+ PCIDevice *pd = PCI_DEVICE(mch);
|
|
|
+ uint8_t *reg = pd->config + MCH_HOST_BRIDGE_F_SMBASE;
|
|
|
+ bool lck;
|
|
|
+
|
|
|
+ if (!mch->has_smram_at_smbase) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (*reg == MCH_HOST_BRIDGE_F_SMBASE_QUERY) {
|
|
|
+ pd->wmask[MCH_HOST_BRIDGE_F_SMBASE] =
|
|
|
+ MCH_HOST_BRIDGE_F_SMBASE_LCK;
|
|
|
+ *reg = MCH_HOST_BRIDGE_F_SMBASE_IN_RAM;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ * default/reset state, discard written value
|
|
|
+ * which will disable SMRAM balackhole at SMBASE
|
|
|
+ */
|
|
|
+ if (pd->wmask[MCH_HOST_BRIDGE_F_SMBASE] == 0xff) {
|
|
|
+ *reg = 0x00;
|
|
|
+ }
|
|
|
+
|
|
|
+ memory_region_transaction_begin();
|
|
|
+ if (*reg & MCH_HOST_BRIDGE_F_SMBASE_LCK) {
|
|
|
+ /* disable all writes */
|
|
|
+ pd->wmask[MCH_HOST_BRIDGE_F_SMBASE] &=
|
|
|
+ ~MCH_HOST_BRIDGE_F_SMBASE_LCK;
|
|
|
+ *reg = MCH_HOST_BRIDGE_F_SMBASE_LCK;
|
|
|
+ lck = true;
|
|
|
+ } else {
|
|
|
+ lck = false;
|
|
|
+ }
|
|
|
+ memory_region_set_enabled(&mch->smbase_blackhole, lck);
|
|
|
+ memory_region_set_enabled(&mch->smbase_window, lck);
|
|
|
+ memory_region_transaction_commit();
|
|
|
+}
|
|
|
+
|
|
|
static void mch_write_config(PCIDevice *d,
|
|
|
uint32_t address, uint32_t val, int len)
|
|
|
{
|
|
@@ -456,6 +496,10 @@ static void mch_write_config(PCIDevice *d,
|
|
|
MCH_HOST_BRIDGE_EXT_TSEG_MBYTES_SIZE)) {
|
|
|
mch_update_ext_tseg_mbytes(mch);
|
|
|
}
|
|
|
+
|
|
|
+ if (ranges_overlap(address, len, MCH_HOST_BRIDGE_F_SMBASE, 1)) {
|
|
|
+ mch_update_smbase_smram(mch);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
static void mch_update(MCHPCIState *mch)
|
|
@@ -464,6 +508,7 @@ static void mch_update(MCHPCIState *mch)
|
|
|
mch_update_pam(mch);
|
|
|
mch_update_smram(mch);
|
|
|
mch_update_ext_tseg_mbytes(mch);
|
|
|
+ mch_update_smbase_smram(mch);
|
|
|
|
|
|
/*
|
|
|
* pci hole goes from end-of-low-ram to io-apic.
|
|
@@ -514,6 +559,9 @@ static void mch_reset(DeviceState *qdev)
|
|
|
MCH_HOST_BRIDGE_EXT_TSEG_MBYTES_QUERY);
|
|
|
}
|
|
|
|
|
|
+ d->config[MCH_HOST_BRIDGE_F_SMBASE] = 0;
|
|
|
+ d->wmask[MCH_HOST_BRIDGE_F_SMBASE] = 0xff;
|
|
|
+
|
|
|
mch_update(mch);
|
|
|
}
|
|
|
|
|
@@ -563,7 +611,7 @@ static void mch_realize(PCIDevice *d, Error **errp)
|
|
|
memory_region_add_subregion(&mch->smram, 0xfeda0000, &mch->high_smram);
|
|
|
|
|
|
memory_region_init_io(&mch->tseg_blackhole, OBJECT(mch),
|
|
|
- &tseg_blackhole_ops, NULL,
|
|
|
+ &blackhole_ops, NULL,
|
|
|
"tseg-blackhole", 0);
|
|
|
memory_region_set_enabled(&mch->tseg_blackhole, false);
|
|
|
memory_region_add_subregion_overlap(mch->system_memory,
|
|
@@ -575,6 +623,27 @@ static void mch_realize(PCIDevice *d, Error **errp)
|
|
|
memory_region_set_enabled(&mch->tseg_window, false);
|
|
|
memory_region_add_subregion(&mch->smram, mch->below_4g_mem_size,
|
|
|
&mch->tseg_window);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * This is not what hardware does, so it's QEMU specific hack.
|
|
|
+ * See commit message for details.
|
|
|
+ */
|
|
|
+ memory_region_init_io(&mch->smbase_blackhole, OBJECT(mch), &blackhole_ops,
|
|
|
+ NULL, "smbase-blackhole",
|
|
|
+ MCH_HOST_BRIDGE_SMBASE_SIZE);
|
|
|
+ memory_region_set_enabled(&mch->smbase_blackhole, false);
|
|
|
+ memory_region_add_subregion_overlap(mch->system_memory,
|
|
|
+ MCH_HOST_BRIDGE_SMBASE_ADDR,
|
|
|
+ &mch->smbase_blackhole, 1);
|
|
|
+
|
|
|
+ memory_region_init_alias(&mch->smbase_window, OBJECT(mch),
|
|
|
+ "smbase-window", mch->ram_memory,
|
|
|
+ MCH_HOST_BRIDGE_SMBASE_ADDR,
|
|
|
+ MCH_HOST_BRIDGE_SMBASE_SIZE);
|
|
|
+ memory_region_set_enabled(&mch->smbase_window, false);
|
|
|
+ memory_region_add_subregion(&mch->smram, MCH_HOST_BRIDGE_SMBASE_ADDR,
|
|
|
+ &mch->smbase_window);
|
|
|
+
|
|
|
object_property_add_const_link(qdev_get_machine(), "smram",
|
|
|
OBJECT(&mch->smram), &error_abort);
|
|
|
|
|
@@ -601,6 +670,7 @@ uint64_t mch_mcfg_base(void)
|
|
|
static Property mch_props[] = {
|
|
|
DEFINE_PROP_UINT16("extended-tseg-mbytes", MCHPCIState, ext_tseg_mbytes,
|
|
|
16),
|
|
|
+ DEFINE_PROP_BOOL("smbase-smram", MCHPCIState, has_smram_at_smbase, true),
|
|
|
DEFINE_PROP_END_OF_LIST(),
|
|
|
};
|
|
|
|