Commit f6e3035f authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/bonzini/tags/for-upstream-smm' into staging



This series implements KVM support for SMM, and lets you enable/disable
it through the "smm" property of x86 machine types.

# gpg: Signature made Mon Jul  6 17:41:05 2015 BST using RSA key ID 78C7AE83
# gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>"
# gpg:                 aka "Paolo Bonzini <pbonzini@redhat.com>"
# gpg: WARNING: This key is not certified with sufficiently trusted signatures!
# gpg:          It is not certain that the signature belongs to the owner.
# Primary key fingerprint: 46F5 9FBD 57D6 12E7 BFD4  E2F7 7E15 100C CD36 69B1
#      Subkey fingerprint: F133 3857 4B66 2389 866C  7682 BFFB D25F 78C7 AE83

* remotes/bonzini/tags/for-upstream-smm:
  pc: add SMM property
  ich9: add smm_enabled field and arguments
  pc_piix: rename kvm_enabled to smm_enabled
  target-i386: register a separate KVM address space including SMRAM regions
  kvm-all: kvm_irqchip_create is not expected to fail
  kvm-all: add support for multiple address spaces
  kvm-all: make KVM's memory listener more generic
  kvm-all: move internal types to kvm_int.h
  kvm-all: remove useless typedef
  kvm-all: put kvm_mem_flags to more work
  target-i386: add support for SMBASE MSR and SMIs
  piix4/ich9: do not raise SMI on ACPI enable/disable commands
  linux-headers: Update to 4.2-rc1

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents 7edd8e46 355023f2
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -192,7 +192,7 @@ static void pm_reset(void *opaque)
    acpi_pm_tmr_reset(&pm->acpi_regs);
    acpi_gpe_reset(&pm->acpi_regs);

    if (kvm_enabled()) {
    if (!pm->smm_enabled) {
        /* Mark SMM as already inited to prevent SMM from running. KVM does not
         * support SMM mode. */
        pm->smi_en |= ICH9_PMIO_SMI_EN_APMC_EN;
@@ -209,7 +209,7 @@ static void pm_powerdown_req(Notifier *n, void *opaque)
    acpi_pm1_evt_power_down(&pm->acpi_regs);
}

void ich9_pm_init(PCIDevice *lpc_pci, ICH9LPCPMRegs *pm,
void ich9_pm_init(PCIDevice *lpc_pci, ICH9LPCPMRegs *pm, bool smm_enabled,
                  qemu_irq sci_irq)
{
    memory_region_init(&pm->io, OBJECT(lpc_pci), "ich9-pm", ICH9_PMIO_SIZE);
@@ -231,6 +231,7 @@ void ich9_pm_init(PCIDevice *lpc_pci, ICH9LPCPMRegs *pm,
                          "acpi-smi", 8);
    memory_region_add_subregion(&pm->io, ICH9_PMIO_SMI_EN, &pm->io_smi);

    pm->smm_enabled = smm_enabled;
    pm->irq = sci_irq;
    qemu_register_reset(pm_reset, pm);
    pm->powerdown_notifier.notify = pm_powerdown_req;
+8 −5
Original line number Diff line number Diff line
@@ -72,7 +72,7 @@ typedef struct PIIX4PMState {

    qemu_irq irq;
    qemu_irq smi_irq;
    int kvm_enabled;
    int smm_enabled;
    Notifier machine_ready;
    Notifier powerdown_notifier;

@@ -112,6 +112,9 @@ static void apm_ctrl_changed(uint32_t val, void *arg)

    /* ACPI specs 3.0, 4.7.2.5 */
    acpi_pm1_cnt_update(&s->ar, val == ACPI_ENABLE, val == ACPI_DISABLE);
    if (val == ACPI_ENABLE || val == ACPI_DISABLE) {
        return;
    }

    if (d->config[0x5b] & (1 << 1)) {
        if (s->smi_irq) {
@@ -319,7 +322,7 @@ static void piix4_reset(void *opaque)
    pci_conf[0x40] = 0x01; /* PM io base read only bit */
    pci_conf[0x80] = 0;

    if (s->kvm_enabled) {
    if (!s->smm_enabled) {
        /* Mark SMM as already inited (until KVM supports SMM). */
        pci_conf[0x5B] = 0x02;
    }
@@ -450,7 +453,7 @@ static void piix4_pm_realize(PCIDevice *dev, Error **errp)
    /* APM */
    apm_init(dev, &s->apm, apm_ctrl_changed, s);

    if (s->kvm_enabled) {
    if (!s->smm_enabled) {
        /* Mark SMM as already inited to prevent SMM from running.  KVM does not
         * support SMM mode. */
        pci_conf[0x5B] = 0x02;
@@ -501,7 +504,7 @@ Object *piix4_pm_find(void)

I2CBus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base,
                      qemu_irq sci_irq, qemu_irq smi_irq,
                      int kvm_enabled, DeviceState **piix4_pm)
                      int smm_enabled, DeviceState **piix4_pm)
{
    DeviceState *dev;
    PIIX4PMState *s;
@@ -515,7 +518,7 @@ I2CBus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base,
    s = PIIX4_PM(dev);
    s->irq = sci_irq;
    s->smi_irq = smi_irq;
    s->kvm_enabled = kvm_enabled;
    s->smm_enabled = smm_enabled;
    if (xen_enabled()) {
        s->use_acpi_pci_hotplug = false;
    }
+51 −0
Original line number Diff line number Diff line
@@ -1768,6 +1768,48 @@ static void pc_machine_set_vmport(Object *obj, Visitor *v, void *opaque,
    visit_type_OnOffAuto(v, &pcms->vmport, name, errp);
}

bool pc_machine_is_smm_enabled(PCMachineState *pcms)
{
    bool smm_available = false;

    if (pcms->smm == ON_OFF_AUTO_OFF) {
        return false;
    }

    if (tcg_enabled() || qtest_enabled()) {
        smm_available = true;
    } else if (kvm_enabled()) {
        smm_available = kvm_has_smm();
    }

    if (smm_available) {
        return true;
    }

    if (pcms->smm == ON_OFF_AUTO_ON) {
        error_report("System Management Mode not supported by this hypervisor.");
        exit(1);
    }
    return false;
}

static void pc_machine_get_smm(Object *obj, Visitor *v, void *opaque,
                              const char *name, Error **errp)
{
    PCMachineState *pcms = PC_MACHINE(obj);
    OnOffAuto smm = pcms->smm;

    visit_type_OnOffAuto(v, &smm, name, errp);
}

static void pc_machine_set_smm(Object *obj, Visitor *v, void *opaque,
                                  const char *name, Error **errp)
{
    PCMachineState *pcms = PC_MACHINE(obj);

    visit_type_OnOffAuto(v, &pcms->smm, name, errp);
}

static bool pc_machine_get_aligned_dimm(Object *obj, Error **errp)
{
    PCMachineState *pcms = PC_MACHINE(obj);
@@ -1792,6 +1834,15 @@ static void pc_machine_initfn(Object *obj)
                                    "Maximum ram below the 4G boundary (32bit boundary)",
                                    NULL);

    pcms->smm = ON_OFF_AUTO_AUTO;
    object_property_add(obj, PC_MACHINE_SMM, "OnOffAuto",
                        pc_machine_get_smm,
                        pc_machine_set_smm,
                        NULL, NULL, NULL);
    object_property_set_description(obj, PC_MACHINE_SMM,
                                    "Enable SMM (pc & q35)",
                                    NULL);

    pcms->vmport = ON_OFF_AUTO_AUTO;
    object_property_add(obj, PC_MACHINE_VMPORT, "OnOffAuto",
                        pc_machine_get_vmport,
+6 −1
Original line number Diff line number Diff line
@@ -287,7 +287,8 @@ static void pc_init1(MachineState *machine)
        /* TODO: Populate SPD eeprom data.  */
        smbus = piix4_pm_init(pci_bus, piix3_devfn + 3, 0xb100,
                              gsi[9], smi_irq,
                              kvm_enabled(), &piix4_pm);
                              pc_machine_is_smm_enabled(pc_machine),
                              &piix4_pm);
        smbus_eeprom_init(smbus, 8, NULL, 0);

        object_property_add_link(OBJECT(machine), PC_MACHINE_ACPI_DEVICE_PROP,
@@ -306,7 +307,11 @@ static void pc_init1(MachineState *machine)

static void pc_compat_2_3(MachineState *machine)
{
    PCMachineState *pcms = PC_MACHINE(machine);
    savevm_skip_section_footers();
    if (kvm_enabled()) {
        pcms->smm = ON_OFF_AUTO_OFF;
    }
}

static void pc_compat_2_2(MachineState *machine)
+5 −1
Original line number Diff line number Diff line
@@ -253,7 +253,7 @@ static void pc_q35_init(MachineState *machine)
                         (pc_machine->vmport != ON_OFF_AUTO_ON), 0xff0104);

    /* connect pm stuff to lpc */
    ich9_lpc_pm_init(lpc);
    ich9_lpc_pm_init(lpc, pc_machine_is_smm_enabled(pc_machine));

    /* ahci and SATA device, for q35 1 ahci controller is built-in */
    ahci = pci_create_simple_multifunction(host_bus,
@@ -290,7 +290,11 @@ static void pc_q35_init(MachineState *machine)

static void pc_compat_2_3(MachineState *machine)
{
    PCMachineState *pcms = PC_MACHINE(machine);
    savevm_skip_section_footers();
    if (kvm_enabled()) {
        pcms->smm = ON_OFF_AUTO_OFF;
    }
}

static void pc_compat_2_2(MachineState *machine)
Loading