Re: [Qemu-devel] [PATCH 23/27] pc: ACPI BIOS: implement memory hotplug interface
On Mon, Nov 25, 2013 at 03:39:13PM +0100, Igor Mammedov wrote: On Thu, 21 Nov 2013 11:37:01 +0200 Michael S. Tsirkin m...@redhat.com wrote: On Thu, Nov 21, 2013 at 03:38:44AM +0100, Igor Mammedov wrote: - provides static SSDT object for memory hotplug - SSDT template for memory devices and runtime generator of them in SSDT table. Signed-off-by: Vasilis Liaskovitis vasilis.liaskovi...@profitbricks.com Signed-off-by: Igor Mammedov imamm...@redhat.com --- [...] diff --git a/hw/i386/ssdt-misc.dsl b/hw/i386/ssdt-misc.dsl index a4484b8..b0c581e 100644 --- a/hw/i386/ssdt-misc.dsl +++ b/hw/i386/ssdt-misc.dsl @@ -116,4 +116,183 @@ DefinitionBlock (ssdt-misc.aml, SSDT, 0x01, BXPC, BXSSDTSUSP, 0x1) } } } + +External(MTFY, MethodObj) + +Scope(\_SB) { +Device(MHPD) { +Name(_HID, EISAID(PNP0C08)) + +ACPI_EXTRACT_NAME_WORD_CONST ssdt_mctrl_port +Name(MHPP, 0x) + +ACPI_EXTRACT_NAME_DWORD_CONST ssdt_mctrl_nr_slots +Name(MDNR, 0x12345678) + +/* Memory hotplug IO registers */ +OperationRegion(HPMR, SystemIO, MHPP, 24) + +Method(_CRS, 0, Serialized) { +Name(CRS, ResourceTemplate() { +IO(Decode16, 0x00, 0x00, 0x01, 24, IO) +}) Declaring name makes us serialize it. Can't we use a local variable? If that works, I'll change it. But I have a question of my own perhaps to Paolo or Gerd, Do we really need this _CRS, because if you look at next hunk _STA should report not present but functioning to avoid windows BSOD. So there is not guaranties that OSPM would care or even query it and honor _CRS provided range. Yes this worries me too. Making _STA non present looks wrong. I suspect we need to look for some other way to make windows not crash that will make it respect the _CRS. Also which windows? All of them? [...] + +Method(_STA, 0) { +If (LEqual(MDNR, Zero)) { +Return(0x0) +} +/* Leave bit 0 cleared to avoid Windows BSOD */ +Return(0xA) +} [...]
Re: [Qemu-devel] [PATCH 23/27] pc: ACPI BIOS: implement memory hotplug interface
On Mon, 16 Dec 2013 21:50:53 +0200 Michael S. Tsirkin m...@redhat.com wrote: On Mon, Nov 25, 2013 at 03:39:13PM +0100, Igor Mammedov wrote: On Thu, 21 Nov 2013 11:37:01 +0200 Michael S. Tsirkin m...@redhat.com wrote: On Thu, Nov 21, 2013 at 03:38:44AM +0100, Igor Mammedov wrote: - provides static SSDT object for memory hotplug - SSDT template for memory devices and runtime generator of them in SSDT table. Signed-off-by: Vasilis Liaskovitis vasilis.liaskovi...@profitbricks.com Signed-off-by: Igor Mammedov imamm...@redhat.com --- [...] diff --git a/hw/i386/ssdt-misc.dsl b/hw/i386/ssdt-misc.dsl index a4484b8..b0c581e 100644 --- a/hw/i386/ssdt-misc.dsl +++ b/hw/i386/ssdt-misc.dsl @@ -116,4 +116,183 @@ DefinitionBlock (ssdt-misc.aml, SSDT, 0x01, BXPC, BXSSDTSUSP, 0x1) } } } + +External(MTFY, MethodObj) + +Scope(\_SB) { +Device(MHPD) { +Name(_HID, EISAID(PNP0C08)) + +ACPI_EXTRACT_NAME_WORD_CONST ssdt_mctrl_port +Name(MHPP, 0x) + +ACPI_EXTRACT_NAME_DWORD_CONST ssdt_mctrl_nr_slots +Name(MDNR, 0x12345678) + +/* Memory hotplug IO registers */ +OperationRegion(HPMR, SystemIO, MHPP, 24) + +Method(_CRS, 0, Serialized) { +Name(CRS, ResourceTemplate() { +IO(Decode16, 0x00, 0x00, 0x01, 24, IO) +}) Declaring name makes us serialize it. Can't we use a local variable? If that works, I'll change it. But I have a question of my own perhaps to Paolo or Gerd, Do we really need this _CRS, because if you look at next hunk _STA should report not present but functioning to avoid windows BSOD. So there is not guaranties that OSPM would care or even query it and honor _CRS provided range. Yes this worries me too. Making _STA non present looks wrong. I've made status as not present and enabled/decoding and functioning, but that doesn't mean that OSPM respects its _CRS. I suspect we need to look for some other way to make windows not crash that will make it respect the _CRS. Also which windows? All of them? I've tested with WS2012DCx64, PV panic doesn't crash windows because it's showed as Unknown device, which also doesn't guaranty that windows would respects it's _CRS. OSPM already knows that range is used by OperationRegion. Question is do we really need to expose OperationRegion as _CRS? [...] + +Method(_STA, 0) { +If (LEqual(MDNR, Zero)) { +Return(0x0) +} +/* Leave bit 0 cleared to avoid Windows BSOD */ +Return(0xA) +} [...] -- Regards, Igor
Re: [Qemu-devel] [PATCH 23/27] pc: ACPI BIOS: implement memory hotplug interface
Il 21/11/2013 03:38, Igor Mammedov ha scritto: +// 64-bit math: MAX = MIN + LEN - 1 +Add(MINL, LENL, MAXL) +Add(MINH, LENH, MAXH) +If (Or(LLess(MAXL, MINL), LLess(MAXL, LENL))) { The Or is not necessary, LLess(MAXL, MINL) is enough. +Add(MAXH, 1, MAXH) One? (Just for consistency, iasl does it already). +} +// Ignore (MAXL == 0 MAXH == 0) case +If (LEqual(MAXL, Zero)) { +Subtract(MAXH, One, MAXH) +Store(0x, MAXL) +} Else { +Subtract(MAXL, One, MAXL) +} + Why not this: If (LLess(MAXL, One)) { Subtract(MAXH, One, MAXH) } Subtract(MAXL, One, MAXL) Paolo
Re: [Qemu-devel] [PATCH 23/27] pc: ACPI BIOS: implement memory hotplug interface
On Mon, 25 Nov 2013 14:42:44 +0100 Paolo Bonzini pbonz...@redhat.com wrote: Il 21/11/2013 03:38, Igor Mammedov ha scritto: +// 64-bit math: MAX = MIN + LEN - 1 +Add(MINL, LENL, MAXL) +Add(MINH, LENH, MAXH) +If (Or(LLess(MAXL, MINL), LLess(MAXL, LENL))) { The Or is not necessary, LLess(MAXL, MINL) is enough. ok, I'll fix it. +Add(MAXH, 1, MAXH) One? (Just for consistency, iasl does it already). sure +} +// Ignore (MAXL == 0 MAXH == 0) case +If (LEqual(MAXL, Zero)) { +Subtract(MAXH, One, MAXH) +Store(0x, MAXL) +} Else { +Subtract(MAXL, One, MAXL) +} + Why not this: If (LLess(MAXL, One)) { Subtract(MAXH, One, MAXH) } Subtract(MAXL, One, MAXL) I'll try it, thanks! Paolo
Re: [Qemu-devel] [PATCH 23/27] pc: ACPI BIOS: implement memory hotplug interface
On Thu, 21 Nov 2013 11:37:01 +0200 Michael S. Tsirkin m...@redhat.com wrote: On Thu, Nov 21, 2013 at 03:38:44AM +0100, Igor Mammedov wrote: - provides static SSDT object for memory hotplug - SSDT template for memory devices and runtime generator of them in SSDT table. Signed-off-by: Vasilis Liaskovitis vasilis.liaskovi...@profitbricks.com Signed-off-by: Igor Mammedov imamm...@redhat.com --- [...] diff --git a/hw/i386/ssdt-misc.dsl b/hw/i386/ssdt-misc.dsl index a4484b8..b0c581e 100644 --- a/hw/i386/ssdt-misc.dsl +++ b/hw/i386/ssdt-misc.dsl @@ -116,4 +116,183 @@ DefinitionBlock (ssdt-misc.aml, SSDT, 0x01, BXPC, BXSSDTSUSP, 0x1) } } } + +External(MTFY, MethodObj) + +Scope(\_SB) { +Device(MHPD) { +Name(_HID, EISAID(PNP0C08)) + +ACPI_EXTRACT_NAME_WORD_CONST ssdt_mctrl_port +Name(MHPP, 0x) + +ACPI_EXTRACT_NAME_DWORD_CONST ssdt_mctrl_nr_slots +Name(MDNR, 0x12345678) + +/* Memory hotplug IO registers */ +OperationRegion(HPMR, SystemIO, MHPP, 24) + +Method(_CRS, 0, Serialized) { +Name(CRS, ResourceTemplate() { +IO(Decode16, 0x00, 0x00, 0x01, 24, IO) +}) Declaring name makes us serialize it. Can't we use a local variable? If that works, I'll change it. But I have a question of my own perhaps to Paolo or Gerd, Do we really need this _CRS, because if you look at next hunk _STA should report not present but functioning to avoid windows BSOD. So there is not guaranties that OSPM would care or even query it and honor _CRS provided range. [...] + +Method(_STA, 0) { +If (LEqual(MDNR, Zero)) { +Return(0x0) +} +/* Leave bit 0 cleared to avoid Windows BSOD */ +Return(0xA) +} [...]
Re: [Qemu-devel] [PATCH 23/27] pc: ACPI BIOS: implement memory hotplug interface
On Thu, Nov 21, 2013 at 03:38:44AM +0100, Igor Mammedov wrote: - provides static SSDT object for memory hotplug - SSDT template for memory devices and runtime generator of them in SSDT table. Signed-off-by: Vasilis Liaskovitis vasilis.liaskovi...@profitbricks.com Signed-off-by: Igor Mammedov imamm...@redhat.com --- mst/pci tree specific change: acpi-build: s/build_append_notify/build_append_notify_method/ introduced by acpi-build: enable hotplug for PCI bridges should be moved to separate patch since it's generic internal API rename. --- hw/i386/Makefile.objs |3 +- hw/i386/acpi-build.c | 36 ++ hw/i386/ssdt-mem.dsl | 75 hw/i386/ssdt-misc.dsl | 179 + 4 files changed, 292 insertions(+), 1 deletions(-) create mode 100644 hw/i386/ssdt-mem.dsl diff --git a/hw/i386/Makefile.objs b/hw/i386/Makefile.objs index 185aacb..f9262a1 100644 --- a/hw/i386/Makefile.objs +++ b/hw/i386/Makefile.objs @@ -9,7 +9,8 @@ obj-y += acpi-build.o obj-y += bios-linker-loader.o hw/i386/acpi-build.o: hw/i386/acpi-build.c hw/i386/acpi-dsdt.hex \ hw/i386/ssdt-proc.hex hw/i386/ssdt-pcihp.hex hw/i386/ssdt-misc.hex \ - hw/i386/acpi-dsdt.hex hw/i386/q35-acpi-dsdt.hex + hw/i386/acpi-dsdt.hex hw/i386/q35-acpi-dsdt.hex \ + hw/i386/q35-acpi-dsdt.hex hw/i386/ssdt-mem.hex iasl-option=$(shell if test -z `$(1) $(2) 21 /dev/null` \ ; then echo $(2); else echo $(3); fi ;) diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index 93ffb17..d41fd81 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -36,6 +36,7 @@ #include hw/nvram/fw_cfg.h #include bios-linker-loader.h #include hw/loader.h +#include qemu/config-file.h /* Supported chipsets: */ #include hw/acpi/piix4.h @@ -69,6 +70,7 @@ typedef struct AcpiPmInfo { uint32_t gpe0_blk; uint32_t gpe0_blk_len; uint32_t io_base; +uint16_t mem_hotplug_io_base; } AcpiPmInfo; typedef struct AcpiMiscInfo { @@ -176,6 +178,8 @@ static void acpi_get_pm_info(AcpiPmInfo *pm) NULL); pm-gpe0_blk_len = object_property_get_int(obj, ACPI_PM_PROP_GPE0_BLK_LEN, NULL); +pm-mem_hotplug_io_base = +object_property_get_int(obj, ACPI_MEMORY_HOTPLUG_IO_BASE_PROP, NULL); } static void acpi_get_misc_info(AcpiMiscInfo *info) @@ -632,6 +636,14 @@ static inline char acpi_get_hex(uint32_t val) #define ACPI_PCIHP_SIZEOF (*ssdt_pcihp_end - *ssdt_pcihp_start) #define ACPI_PCIHP_AML (ssdp_pcihp_aml + *ssdt_pcihp_start) +#include hw/i386/ssdt-mem.hex + +/* 0x5B 0x82 DeviceOp PkgLength NameString DimmID */ +#define ACPI_MEM_OFFSET_HEX (*ssdt_mem_name - *ssdt_mem_start + 2) +#define ACPI_MEM_OFFSET_ID (*ssdt_mem_id - *ssdt_mem_start + 7) +#define ACPI_MEM_SIZEOF (*ssdt_mem_end - *ssdt_mem_start) +#define ACPI_MEM_AML (ssdm_mem_aml + *ssdt_mem_start) + #define ACPI_SSDT_SIGNATURE 0x54445353 /* SSDT */ #define ACPI_SSDT_HEADER_LENGTH 36 @@ -897,6 +909,8 @@ build_ssdt(GArray *table_data, GArray *linker, AcpiCpuInfo *cpu, AcpiPmInfo *pm, AcpiMiscInfo *misc, PcPciInfo *pci, PcGuestInfo *guest_info) { +QemuOpts *opts = qemu_opts_find(qemu_find_opts(memory-opts), NULL); +uint32_t nr_mem = qemu_opt_get_number(opts, slots, 0); int acpi_cpus = MIN(0xff, guest_info-apic_id_limit); int ssdt_start = table_data-len; uint8_t *ssdt_ptr; @@ -920,6 +934,10 @@ build_ssdt(GArray *table_data, GArray *linker, *(uint16_t *)(ssdt_ptr + *ssdt_isa_pest) = cpu_to_le16(misc-pvpanic_port); +*(uint16_t *)(ssdt_ptr + *ssdt_mctrl_port) = +cpu_to_le16(pm-mem_hotplug_io_base); +*(int32_t *)(ssdt_ptr + *ssdt_mctrl_nr_slots) = cpu_to_le32(nr_mem); + { GArray *sb_scope = build_alloc_array(); uint8_t op = 0x10; /* ScopeOp */ @@ -961,6 +979,24 @@ build_ssdt(GArray *table_data, GArray *linker, build_free_array(package); } +if (nr_mem) { +/* build memory devices */ +for (i = 0; i nr_mem; i++) { +char id[3]; +uint8_t *mem = acpi_data_push(sb_scope, ACPI_MEM_SIZEOF); + +snprintf(id, sizeof(id), %02x, i); +memcpy(mem, ACPI_MEM_AML, ACPI_MEM_SIZEOF); +memcpy(mem + ACPI_MEM_OFFSET_HEX, id, 2); +memcpy(mem + ACPI_MEM_OFFSET_ID, id, 2); +} + +/* build Method(MTFY, 2) { + * If (LEqual(Arg0, 0x00)) {Notify(MP00, Arg1)} ... + */ +build_append_notify_method(sb_scope, MTFY, MP%0.02X, nr_mem); +} + { AcpiBuildPciBusHotplugState hotplug_state; PCIBus *bus = find_i440fx(); /* TODO: Q35 support */ diff --git a/hw/i386/ssdt-mem.dsl
[Qemu-devel] [PATCH 23/27] pc: ACPI BIOS: implement memory hotplug interface
- provides static SSDT object for memory hotplug - SSDT template for memory devices and runtime generator of them in SSDT table. Signed-off-by: Vasilis Liaskovitis vasilis.liaskovi...@profitbricks.com Signed-off-by: Igor Mammedov imamm...@redhat.com --- mst/pci tree specific change: acpi-build: s/build_append_notify/build_append_notify_method/ introduced by acpi-build: enable hotplug for PCI bridges should be moved to separate patch since it's generic internal API rename. --- hw/i386/Makefile.objs |3 +- hw/i386/acpi-build.c | 36 ++ hw/i386/ssdt-mem.dsl | 75 hw/i386/ssdt-misc.dsl | 179 + 4 files changed, 292 insertions(+), 1 deletions(-) create mode 100644 hw/i386/ssdt-mem.dsl diff --git a/hw/i386/Makefile.objs b/hw/i386/Makefile.objs index 185aacb..f9262a1 100644 --- a/hw/i386/Makefile.objs +++ b/hw/i386/Makefile.objs @@ -9,7 +9,8 @@ obj-y += acpi-build.o obj-y += bios-linker-loader.o hw/i386/acpi-build.o: hw/i386/acpi-build.c hw/i386/acpi-dsdt.hex \ hw/i386/ssdt-proc.hex hw/i386/ssdt-pcihp.hex hw/i386/ssdt-misc.hex \ - hw/i386/acpi-dsdt.hex hw/i386/q35-acpi-dsdt.hex + hw/i386/acpi-dsdt.hex hw/i386/q35-acpi-dsdt.hex \ + hw/i386/q35-acpi-dsdt.hex hw/i386/ssdt-mem.hex iasl-option=$(shell if test -z `$(1) $(2) 21 /dev/null` \ ; then echo $(2); else echo $(3); fi ;) diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index 93ffb17..d41fd81 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -36,6 +36,7 @@ #include hw/nvram/fw_cfg.h #include bios-linker-loader.h #include hw/loader.h +#include qemu/config-file.h /* Supported chipsets: */ #include hw/acpi/piix4.h @@ -69,6 +70,7 @@ typedef struct AcpiPmInfo { uint32_t gpe0_blk; uint32_t gpe0_blk_len; uint32_t io_base; +uint16_t mem_hotplug_io_base; } AcpiPmInfo; typedef struct AcpiMiscInfo { @@ -176,6 +178,8 @@ static void acpi_get_pm_info(AcpiPmInfo *pm) NULL); pm-gpe0_blk_len = object_property_get_int(obj, ACPI_PM_PROP_GPE0_BLK_LEN, NULL); +pm-mem_hotplug_io_base = +object_property_get_int(obj, ACPI_MEMORY_HOTPLUG_IO_BASE_PROP, NULL); } static void acpi_get_misc_info(AcpiMiscInfo *info) @@ -632,6 +636,14 @@ static inline char acpi_get_hex(uint32_t val) #define ACPI_PCIHP_SIZEOF (*ssdt_pcihp_end - *ssdt_pcihp_start) #define ACPI_PCIHP_AML (ssdp_pcihp_aml + *ssdt_pcihp_start) +#include hw/i386/ssdt-mem.hex + +/* 0x5B 0x82 DeviceOp PkgLength NameString DimmID */ +#define ACPI_MEM_OFFSET_HEX (*ssdt_mem_name - *ssdt_mem_start + 2) +#define ACPI_MEM_OFFSET_ID (*ssdt_mem_id - *ssdt_mem_start + 7) +#define ACPI_MEM_SIZEOF (*ssdt_mem_end - *ssdt_mem_start) +#define ACPI_MEM_AML (ssdm_mem_aml + *ssdt_mem_start) + #define ACPI_SSDT_SIGNATURE 0x54445353 /* SSDT */ #define ACPI_SSDT_HEADER_LENGTH 36 @@ -897,6 +909,8 @@ build_ssdt(GArray *table_data, GArray *linker, AcpiCpuInfo *cpu, AcpiPmInfo *pm, AcpiMiscInfo *misc, PcPciInfo *pci, PcGuestInfo *guest_info) { +QemuOpts *opts = qemu_opts_find(qemu_find_opts(memory-opts), NULL); +uint32_t nr_mem = qemu_opt_get_number(opts, slots, 0); int acpi_cpus = MIN(0xff, guest_info-apic_id_limit); int ssdt_start = table_data-len; uint8_t *ssdt_ptr; @@ -920,6 +934,10 @@ build_ssdt(GArray *table_data, GArray *linker, *(uint16_t *)(ssdt_ptr + *ssdt_isa_pest) = cpu_to_le16(misc-pvpanic_port); +*(uint16_t *)(ssdt_ptr + *ssdt_mctrl_port) = +cpu_to_le16(pm-mem_hotplug_io_base); +*(int32_t *)(ssdt_ptr + *ssdt_mctrl_nr_slots) = cpu_to_le32(nr_mem); + { GArray *sb_scope = build_alloc_array(); uint8_t op = 0x10; /* ScopeOp */ @@ -961,6 +979,24 @@ build_ssdt(GArray *table_data, GArray *linker, build_free_array(package); } +if (nr_mem) { +/* build memory devices */ +for (i = 0; i nr_mem; i++) { +char id[3]; +uint8_t *mem = acpi_data_push(sb_scope, ACPI_MEM_SIZEOF); + +snprintf(id, sizeof(id), %02x, i); +memcpy(mem, ACPI_MEM_AML, ACPI_MEM_SIZEOF); +memcpy(mem + ACPI_MEM_OFFSET_HEX, id, 2); +memcpy(mem + ACPI_MEM_OFFSET_ID, id, 2); +} + +/* build Method(MTFY, 2) { + * If (LEqual(Arg0, 0x00)) {Notify(MP00, Arg1)} ... + */ +build_append_notify_method(sb_scope, MTFY, MP%0.02X, nr_mem); +} + { AcpiBuildPciBusHotplugState hotplug_state; PCIBus *bus = find_i440fx(); /* TODO: Q35 support */ diff --git a/hw/i386/ssdt-mem.dsl b/hw/i386/ssdt-mem.dsl new file mode 100644 index 000..7f68750 --- /dev/null +++ b/hw/i386/ssdt-mem.dsl @@ -0,0 +1,75 @@ +/* + * Memory hotplug ACPI DSDT static objects