From fe6567d5fddfb7501a352c5e080a9eecf7b89177 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 31 Mar 2015 14:10:22 +0200 Subject: hw/i386: add a separate region that tracks the SMRAME bit This region is exported at /machine/smram. It is "empty" if SMRAME=0 and points to SMRAM if SMRAME=1. The CPU will enable/disable it as it enters or exits SMRAM. While touching nearby code, the existing memory region setup was slightly inconsistent. The smram_region is *disabled* in order to open SMRAM (because the smram_region shows the low VRAM instead of the RAM at 0xa0000). Because SMRAM is closed at startup, the smram_region must be enabled when creating the i440fx or q35 devices. Acked-by: Michael S. Tsirkin Signed-off-by: Paolo Bonzini --- hw/pci-host/piix.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'hw/pci-host/piix.c') diff --git a/hw/pci-host/piix.c b/hw/pci-host/piix.c index 723836fb0e..0e439c5d52 100644 --- a/hw/pci-host/piix.c +++ b/hw/pci-host/piix.c @@ -105,6 +105,7 @@ struct PCII440FXState { MemoryRegion *ram_memory; PAMMemoryRegion pam_regions[13]; MemoryRegion smram_region; + MemoryRegion smram, low_smram; uint8_t smm_enabled; }; @@ -139,6 +140,8 @@ static void i440fx_update_memory_mappings(PCII440FXState *d) pd->config[I440FX_PAM + ((i + 1) / 2)]); } smram_update(&d->smram_region, pd->config[I440FX_SMRAM], d->smm_enabled); + memory_region_set_enabled(&d->smram, + pd->config[I440FX_SMRAM] & SMRAM_G_SMRAME); memory_region_transaction_commit(); } @@ -346,11 +349,23 @@ PCIBus *i440fx_init(PCII440FXState **pi440fx_state, pc_pci_as_mapping_init(OBJECT(f), f->system_memory, f->pci_address_space); + /* if *disabled* show SMRAM to all CPUs */ memory_region_init_alias(&f->smram_region, OBJECT(d), "smram-region", f->pci_address_space, 0xa0000, 0x20000); memory_region_add_subregion_overlap(f->system_memory, 0xa0000, &f->smram_region, 1); - memory_region_set_enabled(&f->smram_region, false); + memory_region_set_enabled(&f->smram_region, true); + + /* smram, as seen by SMM CPUs */ + memory_region_init(&f->smram, OBJECT(d), "smram", 1ull << 32); + memory_region_set_enabled(&f->smram, true); + memory_region_init_alias(&f->low_smram, OBJECT(d), "smram-low", + f->system_memory, 0xa0000, 0x20000); + memory_region_set_enabled(&f->low_smram, true); + memory_region_add_subregion(&f->smram, 0xa0000, &f->low_smram); + object_property_add_const_link(qdev_get_machine(), "smram", + OBJECT(&f->smram), &error_abort); + init_pam(dev, f->ram_memory, f->system_memory, f->pci_address_space, &f->pam_regions[0], PAM_BIOS_BASE, PAM_BIOS_SIZE); for (i = 0; i < 12; ++i) { -- cgit v1.2.3 From f809c605122df291bbb9004dc487bde0969134b5 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 31 Mar 2015 14:12:25 +0200 Subject: target-i386: use memory API to implement SMRAM Remove cpu_smm_register and cpu_smm_update. Instead, each CPU address space gets an extra region which is an alias of /machine/smram. This extra region is enabled or disabled as the CPU enters/exits SMM. Signed-off-by: Paolo Bonzini --- hw/pci-host/piix.c | 28 ++++++++-------------------- 1 file changed, 8 insertions(+), 20 deletions(-) (limited to 'hw/pci-host/piix.c') diff --git a/hw/pci-host/piix.c b/hw/pci-host/piix.c index 0e439c5d52..a91ad73705 100644 --- a/hw/pci-host/piix.c +++ b/hw/pci-host/piix.c @@ -106,7 +106,6 @@ struct PCII440FXState { PAMMemoryRegion pam_regions[13]; MemoryRegion smram_region; MemoryRegion smram, low_smram; - uint8_t smm_enabled; }; @@ -139,23 +138,12 @@ static void i440fx_update_memory_mappings(PCII440FXState *d) pam_update(&d->pam_regions[i], i, pd->config[I440FX_PAM + ((i + 1) / 2)]); } - smram_update(&d->smram_region, pd->config[I440FX_SMRAM], d->smm_enabled); + smram_update(&d->smram_region, pd->config[I440FX_SMRAM]); memory_region_set_enabled(&d->smram, pd->config[I440FX_SMRAM] & SMRAM_G_SMRAME); memory_region_transaction_commit(); } -static void i440fx_set_smm(int val, void *arg) -{ - PCII440FXState *d = arg; - PCIDevice *pd = PCI_DEVICE(d); - - memory_region_transaction_begin(); - smram_set_smm(&d->smm_enabled, val, pd->config[I440FX_SMRAM], - &d->smram_region); - memory_region_transaction_commit(); -} - static void i440fx_write_config(PCIDevice *dev, uint32_t address, uint32_t val, int len) @@ -175,12 +163,13 @@ static int i440fx_load_old(QEMUFile* f, void *opaque, int version_id) PCII440FXState *d = opaque; PCIDevice *pd = PCI_DEVICE(d); int ret, i; + uint8_t smm_enabled; ret = pci_device_load(pd, f); if (ret < 0) return ret; i440fx_update_memory_mappings(d); - qemu_get_8s(f, &d->smm_enabled); + qemu_get_8s(f, &smm_enabled); if (version_id == 2) { for (i = 0; i < PIIX_NUM_PIRQS; i++) { @@ -208,7 +197,10 @@ static const VMStateDescription vmstate_i440fx = { .post_load = i440fx_post_load, .fields = (VMStateField[]) { VMSTATE_PCI_DEVICE(parent_obj, PCII440FXState), - VMSTATE_UINT8(smm_enabled, PCII440FXState), + /* Used to be smm_enabled, which was basically always zero because + * SeaBIOS hardly uses SMM. SMRAM is now handled by CPU code. + */ + VMSTATE_UNUSED(1), VMSTATE_END_OF_LIST() } }; @@ -300,11 +292,7 @@ static void i440fx_pcihost_realize(DeviceState *dev, Error **errp) static void i440fx_realize(PCIDevice *dev, Error **errp) { - PCII440FXState *d = I440FX_PCI_DEVICE(dev); - dev->config[I440FX_SMRAM] = 0x02; - - cpu_smm_register(&i440fx_set_smm, d); } PCIBus *i440fx_init(PCII440FXState **pi440fx_state, @@ -360,7 +348,7 @@ PCIBus *i440fx_init(PCII440FXState **pi440fx_state, memory_region_init(&f->smram, OBJECT(d), "smram", 1ull << 32); memory_region_set_enabled(&f->smram, true); memory_region_init_alias(&f->low_smram, OBJECT(d), "smram-low", - f->system_memory, 0xa0000, 0x20000); + f->ram_memory, 0xa0000, 0x20000); memory_region_set_enabled(&f->low_smram, true); memory_region_add_subregion(&f->smram, 0xa0000, &f->low_smram); object_property_add_const_link(qdev_get_machine(), "smram", -- cgit v1.2.3 From 3de70c0899db2712a5ae321093aa6173d6f76706 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 31 Mar 2015 14:14:28 +0200 Subject: hw/i386: remove smram_update It's easier to inline it now that most of its work is done by the CPU (rather than the chipset) through /machine/smram and the memory API. Acked-by: Michael S. Tsirkin Signed-off-by: Paolo Bonzini --- hw/pci-host/piix.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'hw/pci-host/piix.c') diff --git a/hw/pci-host/piix.c b/hw/pci-host/piix.c index a91ad73705..f1712b86fe 100644 --- a/hw/pci-host/piix.c +++ b/hw/pci-host/piix.c @@ -138,7 +138,8 @@ static void i440fx_update_memory_mappings(PCII440FXState *d) pam_update(&d->pam_regions[i], i, pd->config[I440FX_PAM + ((i + 1) / 2)]); } - smram_update(&d->smram_region, pd->config[I440FX_SMRAM]); + memory_region_set_enabled(&d->smram_region, + !(pd->config[I440FX_SMRAM] & SMRAM_D_OPEN)); memory_region_set_enabled(&d->smram, pd->config[I440FX_SMRAM] & SMRAM_G_SMRAME); memory_region_transaction_commit(); -- cgit v1.2.3