From 39b6dbd8d7bbaa864ce42dcdcffe79313de9f2d6 Mon Sep 17 00:00:00 2001 From: Xiao Guangrong Date: Tue, 1 Mar 2016 18:56:03 +0800 Subject: acpi: add aml_create_field() It will be used by nvdimm acpi Signed-off-by: Xiao Guangrong Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- include/hw/acpi/aml-build.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include') diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h index d3e0c8fe87..7d26911d17 100644 --- a/include/hw/acpi/aml-build.h +++ b/include/hw/acpi/aml-build.h @@ -344,6 +344,8 @@ Aml *aml_mutex(const char *name, uint8_t sync_level); Aml *aml_acquire(Aml *mutex, uint16_t timeout); Aml *aml_release(Aml *mutex); Aml *aml_alias(const char *source_object, const char *alias_object); +Aml *aml_create_field(Aml *srcbuf, Aml *bit_index, Aml *num_bits, + const char *name); Aml *aml_create_dword_field(Aml *srcbuf, Aml *index, const char *name); Aml *aml_create_qword_field(Aml *srcbuf, Aml *index, const char *name); Aml *aml_varpackage(uint32_t num_elements); -- cgit v1.2.3-55-g7522 From 9815cba5027b0a8732733dc2a908b4e06d6b8ffc Mon Sep 17 00:00:00 2001 From: Xiao Guangrong Date: Tue, 1 Mar 2016 18:56:04 +0800 Subject: acpi: add aml_concatenate() It will be used by nvdimm acpi Signed-off-by: Xiao Guangrong Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/acpi/aml-build.c | 7 +++++++ include/hw/acpi/aml-build.h | 1 + 2 files changed, 8 insertions(+) (limited to 'include') diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c index 45b7f0abed..bb0cf523ce 100644 --- a/hw/acpi/aml-build.c +++ b/hw/acpi/aml-build.c @@ -1437,6 +1437,13 @@ Aml *aml_alias(const char *source_object, const char *alias_object) return var; } +/* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefConcat */ +Aml *aml_concatenate(Aml *source1, Aml *source2, Aml *target) +{ + return build_opcode_2arg_dst(0x73 /* ConcatOp */, source1, source2, + target); +} + void build_header(GArray *linker, GArray *table_data, AcpiTableHeader *h, const char *sig, int len, uint8_t rev, diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h index 7d26911d17..258cbf32d5 100644 --- a/include/hw/acpi/aml-build.h +++ b/include/hw/acpi/aml-build.h @@ -353,6 +353,7 @@ Aml *aml_touuid(const char *uuid); Aml *aml_unicode(const char *str); Aml *aml_derefof(Aml *arg); Aml *aml_sizeof(Aml *arg); +Aml *aml_concatenate(Aml *source1, Aml *source2, Aml *target); void build_header(GArray *linker, GArray *table_data, -- cgit v1.2.3-55-g7522 From 3f3009c0983428f517b743c9de14858b1fdaacb7 Mon Sep 17 00:00:00 2001 From: Xiao Guangrong Date: Tue, 1 Mar 2016 18:56:05 +0800 Subject: acpi: allow using object as offset for OperationRegion Extend aml_operation_region() to use object as offset Reviewed-by: Igor Mammedov Signed-off-by: Xiao Guangrong Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/acpi/aml-build.c | 4 ++-- hw/i386/acpi-build.c | 31 ++++++++++++++++--------------- include/hw/acpi/aml-build.h | 2 +- 3 files changed, 19 insertions(+), 18 deletions(-) (limited to 'include') diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c index bb0cf523ce..f26fa26802 100644 --- a/hw/acpi/aml-build.c +++ b/hw/acpi/aml-build.c @@ -942,14 +942,14 @@ Aml *aml_package(uint8_t num_elements) /* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: DefOpRegion */ Aml *aml_operation_region(const char *name, AmlRegionSpace rs, - uint32_t offset, uint32_t len) + Aml *offset, uint32_t len) { Aml *var = aml_alloc(); build_append_byte(var->buf, 0x5B); /* ExtOpPrefix */ build_append_byte(var->buf, 0x80); /* OpRegionOp */ build_append_namestring(var->buf, "%s", name); build_append_byte(var->buf, rs); - build_append_int(var->buf, offset); + aml_append(var, offset); build_append_int(var->buf, len); return var; } diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index b888008839..f322230885 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -993,7 +993,7 @@ static void build_processor_devices(Aml *sb_scope, unsigned acpi_cpus, aml_append(sb_scope, dev); /* declare CPU hotplug MMIO region and PRS field to access it */ aml_append(sb_scope, aml_operation_region( - "PRST", AML_SYSTEM_IO, pm->cpu_hp_io_base, pm->cpu_hp_io_len)); + "PRST", AML_SYSTEM_IO, aml_int(pm->cpu_hp_io_base), pm->cpu_hp_io_len)); field = aml_field("PRST", AML_BYTE_ACC, AML_NOLOCK, AML_PRESERVE); aml_append(field, aml_named_field("PRS", 256)); aml_append(sb_scope, field); @@ -1078,7 +1078,7 @@ static void build_memory_devices(Aml *sb_scope, int nr_mem, aml_append(scope, aml_operation_region( MEMORY_HOTPLUG_IO_REGION, AML_SYSTEM_IO, - io_base, io_len) + aml_int(io_base), io_len) ); field = aml_field(MEMORY_HOTPLUG_IO_REGION, AML_DWORD_ACC, @@ -1192,7 +1192,8 @@ static void build_hpet_aml(Aml *table) aml_append(dev, aml_name_decl("_UID", zero)); aml_append(dev, - aml_operation_region("HPTM", AML_SYSTEM_MEMORY, HPET_BASE, HPET_LEN)); + aml_operation_region("HPTM", AML_SYSTEM_MEMORY, aml_int(HPET_BASE), + HPET_LEN)); field = aml_field("HPTM", AML_DWORD_ACC, AML_LOCK, AML_PRESERVE); aml_append(field, aml_named_field("VEND", 32)); aml_append(field, aml_named_field("PRD", 32)); @@ -1430,7 +1431,7 @@ static void build_dbg_aml(Aml *table) Aml *idx = aml_local(2); aml_append(scope, - aml_operation_region("DBG", AML_SYSTEM_IO, 0x0402, 0x01)); + aml_operation_region("DBG", AML_SYSTEM_IO, aml_int(0x0402), 0x01)); field = aml_field("DBG", AML_BYTE_ACC, AML_NOLOCK, AML_PRESERVE); aml_append(field, aml_named_field("DBGB", 8)); aml_append(scope, field); @@ -1770,10 +1771,10 @@ static void build_q35_isa_bridge(Aml *table) /* ICH9 PCI to ISA irq remapping */ aml_append(dev, aml_operation_region("PIRQ", AML_PCI_CONFIG, - 0x60, 0x0C)); + aml_int(0x60), 0x0C)); aml_append(dev, aml_operation_region("LPCD", AML_PCI_CONFIG, - 0x80, 0x02)); + aml_int(0x80), 0x02)); field = aml_field("LPCD", AML_ANY_ACC, AML_NOLOCK, AML_PRESERVE); aml_append(field, aml_named_field("COMA", 3)); aml_append(field, aml_reserved_field(1)); @@ -1785,7 +1786,7 @@ static void build_q35_isa_bridge(Aml *table) aml_append(dev, field); aml_append(dev, aml_operation_region("LPCE", AML_PCI_CONFIG, - 0x82, 0x02)); + aml_int(0x82), 0x02)); /* enable bits */ field = aml_field("LPCE", AML_ANY_ACC, AML_NOLOCK, AML_PRESERVE); aml_append(field, aml_named_field("CAEN", 1)); @@ -1808,7 +1809,7 @@ static void build_piix4_pm(Aml *table) aml_append(dev, aml_name_decl("_ADR", aml_int(0x00010003))); aml_append(dev, aml_operation_region("P13C", AML_PCI_CONFIG, - 0x00, 0xff)); + aml_int(0x00), 0xff)); aml_append(scope, dev); aml_append(table, scope); } @@ -1825,7 +1826,7 @@ static void build_piix4_isa_bridge(Aml *table) /* PIIX PCI to ISA irq remapping */ aml_append(dev, aml_operation_region("P40C", AML_PCI_CONFIG, - 0x60, 0x04)); + aml_int(0x60), 0x04)); /* enable bits */ field = aml_field("^PX13.P13C", AML_ANY_ACC, AML_NOLOCK, AML_PRESERVE); /* Offset(0x5f),, 7, */ @@ -1854,20 +1855,20 @@ static void build_piix4_pci_hotplug(Aml *table) scope = aml_scope("_SB.PCI0"); aml_append(scope, - aml_operation_region("PCST", AML_SYSTEM_IO, 0xae00, 0x08)); + aml_operation_region("PCST", AML_SYSTEM_IO, aml_int(0xae00), 0x08)); field = aml_field("PCST", AML_DWORD_ACC, AML_NOLOCK, AML_WRITE_AS_ZEROS); aml_append(field, aml_named_field("PCIU", 32)); aml_append(field, aml_named_field("PCID", 32)); aml_append(scope, field); aml_append(scope, - aml_operation_region("SEJ", AML_SYSTEM_IO, 0xae08, 0x04)); + aml_operation_region("SEJ", AML_SYSTEM_IO, aml_int(0xae08), 0x04)); field = aml_field("SEJ", AML_DWORD_ACC, AML_NOLOCK, AML_WRITE_AS_ZEROS); aml_append(field, aml_named_field("B0EJ", 32)); aml_append(scope, field); aml_append(scope, - aml_operation_region("BNMR", AML_SYSTEM_IO, 0xae10, 0x04)); + aml_operation_region("BNMR", AML_SYSTEM_IO, aml_int(0xae10), 0x04)); field = aml_field("BNMR", AML_DWORD_ACC, AML_NOLOCK, AML_WRITE_AS_ZEROS); aml_append(field, aml_named_field("BNUM", 32)); aml_append(scope, field); @@ -1975,9 +1976,9 @@ build_dsdt(GArray *table_data, GArray *linker, } else { sb_scope = aml_scope("_SB"); aml_append(sb_scope, - aml_operation_region("PCST", AML_SYSTEM_IO, 0xae00, 0x0c)); + aml_operation_region("PCST", AML_SYSTEM_IO, aml_int(0xae00), 0x0c)); aml_append(sb_scope, - aml_operation_region("PCSB", AML_SYSTEM_IO, 0xae0c, 0x01)); + aml_operation_region("PCSB", AML_SYSTEM_IO, aml_int(0xae0c), 0x01)); field = aml_field("PCSB", AML_ANY_ACC, AML_NOLOCK, AML_WRITE_AS_ZEROS); aml_append(field, aml_named_field("PCIB", 8)); aml_append(sb_scope, field); @@ -2252,7 +2253,7 @@ build_dsdt(GArray *table_data, GArray *linker, aml_append(dev, aml_name_decl("_CRS", crs)); aml_append(dev, aml_operation_region("PEOR", AML_SYSTEM_IO, - misc->pvpanic_port, 1)); + aml_int(misc->pvpanic_port), 1)); field = aml_field("PEOR", AML_BYTE_ACC, AML_NOLOCK, AML_PRESERVE); aml_append(field, aml_named_field("PEPT", 8)); aml_append(dev, field); diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h index 258cbf32d5..b16017ed71 100644 --- a/include/hw/acpi/aml-build.h +++ b/include/hw/acpi/aml-build.h @@ -285,7 +285,7 @@ Aml *aml_interrupt(AmlConsumerAndProducer con_and_pro, Aml *aml_io(AmlIODecode dec, uint16_t min_base, uint16_t max_base, uint8_t aln, uint8_t len); Aml *aml_operation_region(const char *name, AmlRegionSpace rs, - uint32_t offset, uint32_t len); + Aml *offset, uint32_t len); Aml *aml_irq_no_flags(uint8_t irq); Aml *aml_named_field(const char *name, unsigned length); Aml *aml_reserved_field(unsigned length); -- cgit v1.2.3-55-g7522 From f20354910893310d5496ebb6edfc551d83d95343 Mon Sep 17 00:00:00 2001 From: Michael S. Tsirkin Date: Tue, 1 Mar 2016 18:56:07 +0800 Subject: acpi: add build_append_named_dword, returning an offset in buffer This is a very limited form of support for runtime patching - similar in functionality to what we can do with ACPI_EXTRACT macros in python, but implemented in C. This is to allow ACPI code direct access to data tables - which is exactly what DataTableRegion is there for, except no known windows release so far implements DataTableRegion. Signed-off-by: Michael S. Tsirkin Signed-off-by: Xiao Guangrong Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/acpi/aml-build.c | 28 ++++++++++++++++++++++++++++ include/hw/acpi/aml-build.h | 3 +++ 2 files changed, 31 insertions(+) (limited to 'include') diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c index f26fa26802..ab89ca6380 100644 --- a/hw/acpi/aml-build.c +++ b/hw/acpi/aml-build.c @@ -258,6 +258,34 @@ static void build_append_int(GArray *table, uint64_t value) } } +/* + * Build NAME(XXXX, 0x00000000) where 0x00000000 is encoded as a dword, + * and return the offset to 0x00000000 for runtime patching. + * + * Warning: runtime patching is best avoided. Only use this as + * a replacement for DataTableRegion (for guests that don't + * support it). + */ +int +build_append_named_dword(GArray *array, const char *name_format, ...) +{ + int offset; + va_list ap; + + build_append_byte(array, 0x08); /* NameOp */ + va_start(ap, name_format); + build_append_namestringv(array, name_format, ap); + va_end(ap); + + build_append_byte(array, 0x0C); /* DWordPrefix */ + + offset = array->len; + build_append_int_noprefix(array, 0x00000000, 4); + assert(array->len == offset + 4); + + return offset; +} + static GPtrArray *alloc_list; static Aml *aml_alloc(void) diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h index b16017ed71..66f48ec04f 100644 --- a/include/hw/acpi/aml-build.h +++ b/include/hw/acpi/aml-build.h @@ -368,4 +368,7 @@ void build_rsdt(GArray *table_data, GArray *linker, GArray *table_offsets, const char *oem_id, const char *oem_table_id); +int +build_append_named_dword(GArray *array, const char *name_format, ...); + #endif -- cgit v1.2.3-55-g7522 From a0d06486b445985b8d128df172daefbae205bffd Mon Sep 17 00:00:00 2001 From: Denis V. Lunev Date: Wed, 24 Feb 2016 10:50:48 +0300 Subject: virtio-balloon: add 'available' counter The patch for the kernel part is in linux-next already: commit ac88e7c908b920866e529862f2b2f0129b254ab2 Author: Igor Redko Date: Thu Feb 18 09:23:01 2016 +1100 virtio_balloon: export 'available' memory to balloon statistics Add a new field, VIRTIO_BALLOON_S_AVAIL, to virtio_balloon memory statistics protocol, corresponding to 'Available' in /proc/meminfo. Signed-off-by: Denis V. Lunev CC: Igor Redko CC: Michael S. Tsirkin Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/virtio/virtio-balloon.c | 1 + include/standard-headers/linux/virtio_balloon.h | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c index e97d403c6a..22ad25cc97 100644 --- a/hw/virtio/virtio-balloon.c +++ b/hw/virtio/virtio-balloon.c @@ -53,6 +53,7 @@ static const char *balloon_stat_names[] = { [VIRTIO_BALLOON_S_MINFLT] = "stat-minor-faults", [VIRTIO_BALLOON_S_MEMFREE] = "stat-free-memory", [VIRTIO_BALLOON_S_MEMTOT] = "stat-total-memory", + [VIRTIO_BALLOON_S_AVAIL] = "stat-available-memory", [VIRTIO_BALLOON_S_NR] = NULL }; diff --git a/include/standard-headers/linux/virtio_balloon.h b/include/standard-headers/linux/virtio_balloon.h index 2e2a6dcf3a..0df7c2efdd 100644 --- a/include/standard-headers/linux/virtio_balloon.h +++ b/include/standard-headers/linux/virtio_balloon.h @@ -51,7 +51,8 @@ struct virtio_balloon_config { #define VIRTIO_BALLOON_S_MINFLT 3 /* Number of minor faults */ #define VIRTIO_BALLOON_S_MEMFREE 4 /* Total amount of free memory */ #define VIRTIO_BALLOON_S_MEMTOT 5 /* Total amount of memory */ -#define VIRTIO_BALLOON_S_NR 6 +#define VIRTIO_BALLOON_S_AVAIL 6 /* Amount of available memory in guest */ +#define VIRTIO_BALLOON_S_NR 7 /* * Memory statistics structure. -- cgit v1.2.3-55-g7522 From bda055096be9a91d602af457f8bedeede86eb3f6 Mon Sep 17 00:00:00 2001 From: Roman Kagan Date: Wed, 17 Feb 2016 21:25:31 +0300 Subject: i386: expose floppy drive CMOS type Make it possible to query the CMOS type of a floppy drive outside of the source file where it's defined. It will allow to properly populate the corresponding ACPI objects and thus enable Windows on BIOS-less systems to access the floppy drives. Signed-off-by: Roman Kagan Cc: Igor Mammedov Cc: "Michael S. Tsirkin" Cc: Marcel Apfelbaum Cc: John Snow Cc: Laszlo Ersek Cc: Kevin O'Connor Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/i386/pc.c | 2 +- include/hw/i386/pc.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 56ec6cd6c6..898f119977 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -199,7 +199,7 @@ static void pic_irq_request(void *opaque, int irq, int level) #define REG_EQUIPMENT_BYTE 0x14 -static int cmos_get_fd_drive_type(FloppyDriveType fd0) +int cmos_get_fd_drive_type(FloppyDriveType fd0) { int val; diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h index 79ffe5b3ee..6151ba7021 100644 --- a/include/hw/i386/pc.h +++ b/include/hw/i386/pc.h @@ -265,6 +265,7 @@ typedef void (*cpu_set_smm_t)(int smm, void *arg); void ioapic_init_gsi(GSIState *gsi_state, const char *parent_name); ISADevice *pc_find_fdc0(void); +int cmos_get_fd_drive_type(FloppyDriveType fd0); #define FW_CFG_IO_BASE 0x510 -- cgit v1.2.3-55-g7522 From e08fde0c5ee4e7f3ec319a44b846fb9e127c1db2 Mon Sep 17 00:00:00 2001 From: Roman Kagan Date: Wed, 17 Feb 2016 21:25:32 +0300 Subject: fdc: add function to determine drive chs limits When populating ACPI objects for floppy drives one needs to provide the maximum values for cylinder, sector, and head number the drive supports. This patch adds a function that iterates through the array of predefined floppy drive formats and returns the maximum values of c, h, s, out of those matching the given floppy drive type. Signed-off-by: Roman Kagan Cc: Igor Mammedov Cc: "Michael S. Tsirkin" Cc: Marcel Apfelbaum Cc: John Snow Cc: Laszlo Ersek Cc: Kevin O'Connor Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Reviewed-by: John Snow --- hw/block/fdc.c | 23 +++++++++++++++++++++++ include/hw/block/fdc.h | 2 ++ 2 files changed, 25 insertions(+) (limited to 'include') diff --git a/hw/block/fdc.c b/hw/block/fdc.c index 9838d21cf5..fc3aef9cd1 100644 --- a/hw/block/fdc.c +++ b/hw/block/fdc.c @@ -2557,6 +2557,29 @@ FloppyDriveType isa_fdc_get_drive_type(ISADevice *fdc, int i) return isa->state.drives[i].drive; } +void isa_fdc_get_drive_max_chs(FloppyDriveType type, + uint8_t *maxc, uint8_t *maxh, uint8_t *maxs) +{ + const FDFormat *fdf; + + *maxc = *maxh = *maxs = 0; + for (fdf = fd_formats; fdf->drive != FLOPPY_DRIVE_TYPE_NONE; fdf++) { + if (fdf->drive != type) { + continue; + } + if (*maxc < fdf->max_track) { + *maxc = fdf->max_track; + } + if (*maxh < fdf->max_head) { + *maxh = fdf->max_head; + } + if (*maxs < fdf->last_sect) { + *maxs = fdf->last_sect; + } + } + (*maxc)--; +} + static const VMStateDescription vmstate_isa_fdc ={ .name = "fdc", .version_id = 2, diff --git a/include/hw/block/fdc.h b/include/hw/block/fdc.h index adce14f479..1749dabf25 100644 --- a/include/hw/block/fdc.h +++ b/include/hw/block/fdc.h @@ -15,5 +15,7 @@ void sun4m_fdctrl_init(qemu_irq irq, hwaddr io_base, DriveInfo **fds, qemu_irq *fdc_tc); FloppyDriveType isa_fdc_get_drive_type(ISADevice *fdc, int i); +void isa_fdc_get_drive_max_chs(FloppyDriveType type, + uint8_t *maxc, uint8_t *maxh, uint8_t *maxs); #endif -- cgit v1.2.3-55-g7522 From 226419d6153048cdba2fe722636220b01a1f9e96 Mon Sep 17 00:00:00 2001 From: Michael S. Tsirkin Date: Fri, 4 Mar 2016 11:24:28 +0200 Subject: msi_supported -> msi_nonbroken Rename controller flag to make it clearer what it means. Add some documentation as well. Signed-off-by: Michael S. Tsirkin --- hw/i386/kvm/apic.c | 2 +- hw/i386/xen/xen_apic.c | 2 +- hw/intc/apic.c | 2 +- hw/intc/arm_gicv2m.c | 2 +- hw/intc/openpic.c | 2 +- hw/intc/openpic_kvm.c | 2 +- hw/pci-bridge/pci_bridge_dev.c | 2 +- hw/pci/msi.c | 19 ++++++++++++++++--- hw/pci/msix.c | 2 +- hw/ppc/spapr.c | 4 ++-- hw/ppc/spapr_pci.c | 2 +- hw/s390x/s390-pci-bus.c | 2 +- include/hw/pci/msi.h | 2 +- 13 files changed, 29 insertions(+), 16 deletions(-) (limited to 'include') diff --git a/hw/i386/kvm/apic.c b/hw/i386/kvm/apic.c index 694d3989b2..3c7c8fa007 100644 --- a/hw/i386/kvm/apic.c +++ b/hw/i386/kvm/apic.c @@ -186,7 +186,7 @@ static void kvm_apic_realize(DeviceState *dev, Error **errp) APIC_SPACE_SIZE); if (kvm_has_gsi_routing()) { - msi_supported = true; + msi_nonbroken = true; } } diff --git a/hw/i386/xen/xen_apic.c b/hw/i386/xen/xen_apic.c index 2b8d709d4d..21d68ee04b 100644 --- a/hw/i386/xen/xen_apic.c +++ b/hw/i386/xen/xen_apic.c @@ -44,7 +44,7 @@ static void xen_apic_realize(DeviceState *dev, Error **errp) s->vapic_control = 0; memory_region_init_io(&s->io_memory, OBJECT(s), &xen_apic_io_ops, s, "xen-apic-msi", APIC_SPACE_SIZE); - msi_supported = true; + msi_nonbroken = true; } static void xen_apic_set_base(APICCommonState *s, uint64_t val) diff --git a/hw/intc/apic.c b/hw/intc/apic.c index a2994624f5..28c2ea5406 100644 --- a/hw/intc/apic.c +++ b/hw/intc/apic.c @@ -874,7 +874,7 @@ static void apic_realize(DeviceState *dev, Error **errp) s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, apic_timer, s); local_apics[s->idx] = s; - msi_supported = true; + msi_nonbroken = true; } static void apic_class_init(ObjectClass *klass, void *data) diff --git a/hw/intc/arm_gicv2m.c b/hw/intc/arm_gicv2m.c index 70c0b97d99..ebd368bbad 100644 --- a/hw/intc/arm_gicv2m.c +++ b/hw/intc/arm_gicv2m.c @@ -148,7 +148,7 @@ static void gicv2m_realize(DeviceState *dev, Error **errp) sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->spi[i]); } - msi_supported = true; + msi_nonbroken = true; kvm_gsi_direct_mapping = true; kvm_msi_via_irqfd_allowed = kvm_irqfds_enabled(); } diff --git a/hw/intc/openpic.c b/hw/intc/openpic.c index 903888c02e..7685250bf4 100644 --- a/hw/intc/openpic.c +++ b/hw/intc/openpic.c @@ -1375,7 +1375,7 @@ static void fsl_common_init(OpenPICState *opp) opp->irq_msi = 224; - msi_supported = true; + msi_nonbroken = true; for (i = 0; i < opp->fsl->max_ext; i++) { opp->src[i].level = false; } diff --git a/hw/intc/openpic_kvm.c b/hw/intc/openpic_kvm.c index 4dcdb61a09..778af4a7d4 100644 --- a/hw/intc/openpic_kvm.c +++ b/hw/intc/openpic_kvm.c @@ -239,7 +239,7 @@ static void kvm_openpic_realize(DeviceState *dev, Error **errp) memory_listener_register(&opp->mem_listener, &address_space_memory); /* indicate pic capabilities */ - msi_supported = true; + msi_nonbroken = true; kvm_kernel_irqchip = true; kvm_async_interrupts_allowed = true; diff --git a/hw/pci-bridge/pci_bridge_dev.c b/hw/pci-bridge/pci_bridge_dev.c index 100bb5ebf6..862a2366f2 100644 --- a/hw/pci-bridge/pci_bridge_dev.c +++ b/hw/pci-bridge/pci_bridge_dev.c @@ -72,7 +72,7 @@ static int pci_bridge_dev_initfn(PCIDevice *dev) goto slotid_error; } if ((bridge_dev->flags & (1 << PCI_BRIDGE_DEV_F_MSI_REQ)) && - msi_supported) { + msi_nonbroken) { err = msi_init(dev, 0, 1, true, true); if (err < 0) { goto msi_error; diff --git a/hw/pci/msi.c b/hw/pci/msi.c index 85f21b8c4b..e0e64c2d9e 100644 --- a/hw/pci/msi.c +++ b/hw/pci/msi.c @@ -34,8 +34,21 @@ #define PCI_MSI_VECTORS_MAX 32 -/* Flag for interrupt controller to declare MSI/MSI-X support */ -bool msi_supported; +/* + * Flag for interrupt controllers to declare broken MSI/MSI-X support. + * values: false - broken; true - non-broken. + * + * Setting this flag to false will remove MSI/MSI-X capability from all devices. + * + * It is preferrable for controllers to set this to true (non-broken) even if + * they do not actually support MSI/MSI-X: guests normally probe the controller + * type and do not attempt to enable MSI/MSI-X with interrupt controllers not + * supporting such, so removing the capability is not required, and + * it seems cleaner to have a given device look the same for all boards. + * + * TODO: some existing controllers violate the above rule. Identify and fix them. + */ +bool msi_nonbroken; /* If we get rid of cap allocator, we won't need this. */ static inline uint8_t msi_cap_sizeof(uint16_t flags) @@ -160,7 +173,7 @@ int msi_init(struct PCIDevice *dev, uint8_t offset, uint8_t cap_size; int config_offset; - if (!msi_supported) { + if (!msi_nonbroken) { return -ENOTSUP; } diff --git a/hw/pci/msix.c b/hw/pci/msix.c index 537fdba747..b75f0e9c47 100644 --- a/hw/pci/msix.c +++ b/hw/pci/msix.c @@ -249,7 +249,7 @@ int msix_init(struct PCIDevice *dev, unsigned short nentries, uint8_t *config; /* Nothing to do if MSI is not supported by interrupt controller */ - if (!msi_supported) { + if (!msi_nonbroken) { return -ENOTSUP; } diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 64c4acce06..298171a205 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -439,7 +439,7 @@ static void *spapr_create_fdt_skel(hwaddr initrd_base, _FDT((fdt_property_cell(fdt, "rtas-event-scan-rate", RTAS_EVENT_SCAN_RATE))); - if (msi_supported) { + if (msi_nonbroken) { _FDT((fdt_property(fdt, "ibm,change-msix-capable", NULL, 0))); } @@ -1743,7 +1743,7 @@ static void ppc_spapr_init(MachineState *machine) bool kernel_le = false; char *filename; - msi_supported = true; + msi_nonbroken = true; QLIST_INIT(&spapr->phbs); diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c index e8edad3ab7..3fc78955ec 100644 --- a/hw/ppc/spapr_pci.c +++ b/hw/ppc/spapr_pci.c @@ -1790,7 +1790,7 @@ void spapr_pci_rtas_init(void) rtas_ibm_read_pci_config); spapr_rtas_register(RTAS_IBM_WRITE_PCI_CONFIG, "ibm,write-pci-config", rtas_ibm_write_pci_config); - if (msi_supported) { + if (msi_nonbroken) { spapr_rtas_register(RTAS_IBM_QUERY_INTERRUPT_SOURCE_NUMBER, "ibm,query-interrupt-source-number", rtas_ibm_query_interrupt_source_number); diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c index dba0202b70..f5f679f82c 100644 --- a/hw/s390x/s390-pci-bus.c +++ b/hw/s390x/s390-pci-bus.c @@ -597,7 +597,7 @@ static void s390_pcihost_class_init(ObjectClass *klass, void *data) k->init = s390_pcihost_init; hc->plug = s390_pcihost_hot_plug; hc->unplug = s390_pcihost_hot_unplug; - msi_supported = true; + msi_nonbroken = true; } static const TypeInfo s390_pcihost_info = { diff --git a/include/hw/pci/msi.h b/include/hw/pci/msi.h index 50e452bd05..8124908abd 100644 --- a/include/hw/pci/msi.h +++ b/include/hw/pci/msi.h @@ -29,7 +29,7 @@ struct MSIMessage { uint32_t data; }; -extern bool msi_supported; +extern bool msi_nonbroken; void msi_set_message(PCIDevice *dev, MSIMessage msg); MSIMessage msi_get_message(PCIDevice *dev, unsigned int vector); -- cgit v1.2.3-55-g7522 From 7335a95abd400127b46f3b641e6cd15dd11703fd Mon Sep 17 00:00:00 2001 From: Cao jin Date: Mon, 7 Mar 2016 20:38:58 +0800 Subject: ich9lpc: fix typo change some "rbca" to "rcrb"(root complex register block) while the other to "rcba"(root complex base address). Bonus: add more comments and fix some indentation. Signed-off-by: Cao jin Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/isa/lpc_ich9.c | 35 ++++++++++++++++++----------------- include/hw/i386/ich9.h | 4 ++-- 2 files changed, 20 insertions(+), 19 deletions(-) (limited to 'include') diff --git a/hw/isa/lpc_ich9.c b/hw/isa/lpc_ich9.c index 4e896b29f1..0ee29c0ad2 100644 --- a/hw/isa/lpc_ich9.c +++ b/hw/isa/lpc_ich9.c @@ -409,18 +409,18 @@ ich9_lpc_pmbase_update(ICH9LPCState *lpc) ich9_pm_iospace_update(&lpc->pm, pm_io_base); } -/* config:RBCA */ -static void ich9_lpc_rcba_update(ICH9LPCState *lpc, uint32_t rbca_old) +/* config:RCBA */ +static void ich9_lpc_rcba_update(ICH9LPCState *lpc, uint32_t rcba_old) { - uint32_t rbca = pci_get_long(lpc->d.config + ICH9_LPC_RCBA); + uint32_t rcba = pci_get_long(lpc->d.config + ICH9_LPC_RCBA); - if (rbca_old & ICH9_LPC_RCBA_EN) { - memory_region_del_subregion(get_system_memory(), &lpc->rbca_mem); + if (rcba_old & ICH9_LPC_RCBA_EN) { + memory_region_del_subregion(get_system_memory(), &lpc->rcrb_mem); } - if (rbca & ICH9_LPC_RCBA_EN) { - memory_region_add_subregion_overlap(get_system_memory(), - rbca & ICH9_LPC_RCBA_BA_MASK, - &lpc->rbca_mem, 1); + if (rcba & ICH9_LPC_RCBA_EN) { + memory_region_add_subregion_overlap(get_system_memory(), + rcba & ICH9_LPC_RCBA_BA_MASK, + &lpc->rcrb_mem, 1); } } @@ -444,7 +444,7 @@ static int ich9_lpc_post_load(void *opaque, int version_id) ICH9LPCState *lpc = opaque; ich9_lpc_pmbase_update(lpc); - ich9_lpc_rcba_update(lpc, 0 /* disabled ICH9_LPC_RBCA_EN */); + ich9_lpc_rcba_update(lpc, 0 /* disabled ICH9_LPC_RCBA_EN */); ich9_lpc_pmcon_update(lpc); return 0; } @@ -453,14 +453,14 @@ static void ich9_lpc_config_write(PCIDevice *d, uint32_t addr, uint32_t val, int len) { ICH9LPCState *lpc = ICH9_LPC_DEVICE(d); - uint32_t rbca_old = pci_get_long(d->config + ICH9_LPC_RCBA); + uint32_t rcba_old = pci_get_long(d->config + ICH9_LPC_RCBA); pci_default_write_config(d, addr, val, len); if (ranges_overlap(addr, len, ICH9_LPC_PMBASE, 4)) { ich9_lpc_pmbase_update(lpc); } if (ranges_overlap(addr, len, ICH9_LPC_RCBA, 4)) { - ich9_lpc_rcba_update(lpc, rbca_old); + ich9_lpc_rcba_update(lpc, rcba_old); } if (ranges_overlap(addr, len, ICH9_LPC_PIRQA_ROUT, 4)) { pci_bus_fire_intx_routing_notifier(lpc->d.bus); @@ -477,7 +477,7 @@ static void ich9_lpc_reset(DeviceState *qdev) { PCIDevice *d = PCI_DEVICE(qdev); ICH9LPCState *lpc = ICH9_LPC_DEVICE(d); - uint32_t rbca_old = pci_get_long(d->config + ICH9_LPC_RCBA); + uint32_t rcba_old = pci_get_long(d->config + ICH9_LPC_RCBA); int i; for (i = 0; i < 4; i++) { @@ -496,13 +496,14 @@ static void ich9_lpc_reset(DeviceState *qdev) ich9_cc_reset(lpc); ich9_lpc_pmbase_update(lpc); - ich9_lpc_rcba_update(lpc, rbca_old); + ich9_lpc_rcba_update(lpc, rcba_old); lpc->sci_level = 0; lpc->rst_cnt = 0; } -static const MemoryRegionOps rbca_mmio_ops = { +/* root complex register block is mapped into memory space */ +static const MemoryRegionOps rcrb_mmio_ops = { .read = ich9_cc_read, .write = ich9_cc_write, .endianness = DEVICE_LITTLE_ENDIAN, @@ -616,8 +617,8 @@ static void ich9_lpc_realize(PCIDevice *d, Error **errp) pci_set_long(d->wmask + ICH9_LPC_PMBASE, ICH9_LPC_PMBASE_BASE_ADDRESS_MASK); - memory_region_init_io(&lpc->rbca_mem, OBJECT(d), &rbca_mmio_ops, lpc, - "lpc-rbca-mmio", ICH9_CC_SIZE); + memory_region_init_io(&lpc->rcrb_mem, OBJECT(d), &rcrb_mmio_ops, lpc, + "lpc-rcrb-mmio", ICH9_CC_SIZE); lpc->isa_bus = isa_bus; diff --git a/include/hw/i386/ich9.h b/include/hw/i386/ich9.h index b411434984..d04dcdcfb3 100644 --- a/include/hw/i386/ich9.h +++ b/include/hw/i386/ich9.h @@ -23,7 +23,7 @@ I2CBus *ich9_smb_init(PCIBus *bus, int devfn, uint32_t smb_io_base); void ich9_generate_smi(void); void ich9_generate_nmi(void); -#define ICH9_CC_SIZE (16 * 1024) /* 16KB */ +#define ICH9_CC_SIZE (16 * 1024) /* 16KB. Chipset configuration registers */ #define TYPE_ICH9_LPC_DEVICE "ICH9-LPC" #define ICH9_LPC_DEVICE(obj) \ @@ -65,7 +65,7 @@ typedef struct ICH9LPCState { /* isa bus */ ISABus *isa_bus; - MemoryRegion rbca_mem; + MemoryRegion rcrb_mem; /* root complex register block */ Notifier machine_ready; qemu_irq *pic; -- cgit v1.2.3-55-g7522 From 5fe79386ba3cdc86fd808dde301bfc5bb7e9bded Mon Sep 17 00:00:00 2001 From: Xiao Guangrong Date: Sat, 5 Mar 2016 00:00:32 +0800 Subject: nvdimm acpi: initialize the resource used by NVDIMM ACPI 32 bits IO port starting from 0x0a18 in guest is reserved for NVDIMM ACPI emulation. The table, NVDIMM_DSM_MEM_FILE, will be patched into NVDIMM ACPI binary code OSPM uses this port to tell QEMU the final address of the DSM memory and notify QEMU to emulate the DSM method Signed-off-by: Xiao Guangrong Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/acpi/Makefile.objs | 2 +- hw/acpi/nvdimm.c | 35 +++++++++++++++++++++++++++++++++++ hw/i386/acpi-build.c | 10 +--------- hw/i386/pc.c | 6 +++--- hw/i386/pc_piix.c | 5 +++++ hw/i386/pc_q35.c | 8 +++++++- include/hw/i386/pc.h | 4 +++- include/hw/mem/nvdimm.h | 24 +++++++++++++++++++++++- 8 files changed, 78 insertions(+), 16 deletions(-) (limited to 'include') diff --git a/hw/acpi/Makefile.objs b/hw/acpi/Makefile.objs index f3ade9a28e..faee86c5c4 100644 --- a/hw/acpi/Makefile.objs +++ b/hw/acpi/Makefile.objs @@ -2,7 +2,7 @@ common-obj-$(CONFIG_ACPI_X86) += core.o piix4.o pcihp.o common-obj-$(CONFIG_ACPI_X86_ICH) += ich9.o tco.o common-obj-$(CONFIG_ACPI_CPU_HOTPLUG) += cpu_hotplug.o cpu_hotplug_acpi_table.o common-obj-$(CONFIG_ACPI_MEMORY_HOTPLUG) += memory_hotplug.o memory_hotplug_acpi_table.o -common-obj-$(CONFIG_ACPI_NVDIMM) += nvdimm.o +obj-$(CONFIG_ACPI_NVDIMM) += nvdimm.o common-obj-$(CONFIG_ACPI) += acpi_interface.o common-obj-$(CONFIG_ACPI) += bios-linker-loader.o common-obj-$(CONFIG_ACPI) += aml-build.o diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c index 49ee68e614..8568b20341 100644 --- a/hw/acpi/nvdimm.c +++ b/hw/acpi/nvdimm.c @@ -29,6 +29,7 @@ #include "qemu/osdep.h" #include "hw/acpi/acpi.h" #include "hw/acpi/aml-build.h" +#include "hw/nvram/fw_cfg.h" #include "hw/mem/nvdimm.h" static int nvdimm_plugged_device_list(Object *obj, void *opaque) @@ -370,6 +371,40 @@ static void nvdimm_build_nfit(GSList *device_list, GArray *table_offsets, g_array_free(structures, true); } +static uint64_t +nvdimm_dsm_read(void *opaque, hwaddr addr, unsigned size) +{ + return 0; +} + +static void +nvdimm_dsm_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) +{ +} + +static const MemoryRegionOps nvdimm_dsm_ops = { + .read = nvdimm_dsm_read, + .write = nvdimm_dsm_write, + .endianness = DEVICE_LITTLE_ENDIAN, + .valid = { + .min_access_size = 4, + .max_access_size = 4, + }, +}; + +void nvdimm_init_acpi_state(AcpiNVDIMMState *state, MemoryRegion *io, + FWCfgState *fw_cfg, Object *owner) +{ + memory_region_init_io(&state->io_mr, owner, &nvdimm_dsm_ops, state, + "nvdimm-acpi-io", NVDIMM_ACPI_IO_LEN); + memory_region_add_subregion(io, NVDIMM_ACPI_IO_BASE, &state->io_mr); + + state->dsm_mem = g_array_new(false, true /* clear */, 1); + acpi_data_push(state->dsm_mem, TARGET_PAGE_SIZE); + fw_cfg_add_file(fw_cfg, NVDIMM_DSM_MEM_FILE, state->dsm_mem->data, + state->dsm_mem->len); +} + #define NVDIMM_COMMON_DSM "NCAL" static void nvdimm_build_common_dsm(Aml *dev) diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index 0e32395604..9ff3f5c94f 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -39,7 +39,6 @@ #include "hw/isa/isa.h" #include "hw/block/fdc.h" #include "hw/acpi/memory_hotplug.h" -#include "hw/mem/nvdimm.h" #include "sysemu/tpm.h" #include "hw/acpi/tpm.h" #include "sysemu/tpm_backend.h" @@ -2659,13 +2658,6 @@ static bool acpi_has_iommu(void) return intel_iommu && !ambiguous; } -static bool acpi_has_nvdimm(void) -{ - PCMachineState *pcms = PC_MACHINE(qdev_get_machine()); - - return pcms->nvdimm; -} - static void acpi_build(AcpiBuildTables *tables) { @@ -2750,7 +2742,7 @@ void acpi_build(AcpiBuildTables *tables) build_dmar_q35(tables_blob, tables->linker); } - if (acpi_has_nvdimm()) { + if (pcms->acpi_nvdimm_state.is_enabled) { nvdimm_build_acpi(table_offsets, tables_blob, tables->linker); } diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 898f119977..b9541348ca 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -1853,14 +1853,14 @@ static bool pc_machine_get_nvdimm(Object *obj, Error **errp) { PCMachineState *pcms = PC_MACHINE(obj); - return pcms->nvdimm; + return pcms->acpi_nvdimm_state.is_enabled; } static void pc_machine_set_nvdimm(Object *obj, bool value, Error **errp) { PCMachineState *pcms = PC_MACHINE(obj); - pcms->nvdimm = value; + pcms->acpi_nvdimm_state.is_enabled = value; } static void pc_machine_initfn(Object *obj) @@ -1899,7 +1899,7 @@ static void pc_machine_initfn(Object *obj) &error_abort); /* nvdimm is disabled on default. */ - pcms->nvdimm = false; + pcms->acpi_nvdimm_state.is_enabled = false; object_property_add_bool(obj, PC_MACHINE_NVDIMM, pc_machine_get_nvdimm, pc_machine_set_nvdimm, &error_abort); } diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index 6f8c2cd816..6a69b23abc 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -274,6 +274,11 @@ static void pc_init1(MachineState *machine, if (pcmc->pci_enabled) { pc_pci_device_init(pci_bus); } + + if (pcms->acpi_nvdimm_state.is_enabled) { + nvdimm_init_acpi_state(&pcms->acpi_nvdimm_state, system_io, + pcms->fw_cfg, OBJECT(pcms)); + } } /* Looking for a pc_compat_2_4() function? It doesn't exist. diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c index 46522c90da..17915b05c4 100644 --- a/hw/i386/pc_q35.c +++ b/hw/i386/pc_q35.c @@ -61,6 +61,7 @@ static void pc_q35_init(MachineState *machine) PCIDevice *lpc; BusState *idebus[MAX_SATA_PORTS]; ISADevice *rtc_state; + MemoryRegion *system_io = get_system_io(); MemoryRegion *pci_memory; MemoryRegion *rom_memory; MemoryRegion *ram_memory; @@ -160,7 +161,7 @@ static void pc_q35_init(MachineState *machine) q35_host->mch.ram_memory = ram_memory; q35_host->mch.pci_address_space = pci_memory; q35_host->mch.system_memory = get_system_memory(); - q35_host->mch.address_space_io = get_system_io(); + q35_host->mch.address_space_io = system_io; q35_host->mch.below_4g_mem_size = pcms->below_4g_mem_size; q35_host->mch.above_4g_mem_size = pcms->above_4g_mem_size; /* pci */ @@ -251,6 +252,11 @@ static void pc_q35_init(MachineState *machine) if (pcmc->pci_enabled) { pc_pci_device_init(host_bus); } + + if (pcms->acpi_nvdimm_state.is_enabled) { + nvdimm_init_acpi_state(&pcms->acpi_nvdimm_state, system_io, + pcms->fw_cfg, OBJECT(pcms)); + } } #define DEFINE_Q35_MACHINE(suffix, name, compatfn, optionfn) \ diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h index 6151ba7021..b0497769a1 100644 --- a/include/hw/i386/pc.h +++ b/include/hw/i386/pc.h @@ -17,6 +17,7 @@ #include "hw/boards.h" #include "hw/compat.h" #include "hw/mem/pc-dimm.h" +#include "hw/mem/nvdimm.h" #define HPET_INTCAP "hpet-intcap" @@ -57,7 +58,8 @@ struct PCMachineState { uint64_t max_ram_below_4g; OnOffAuto vmport; OnOffAuto smm; - bool nvdimm; + + AcpiNVDIMMState acpi_nvdimm_state; /* RAM information (sizes, addresses, configuration): */ ram_addr_t below_4g_mem_size, above_4g_mem_size; diff --git a/include/hw/mem/nvdimm.h b/include/hw/mem/nvdimm.h index 49183c126b..26d5b78911 100644 --- a/include/hw/mem/nvdimm.h +++ b/include/hw/mem/nvdimm.h @@ -25,8 +25,30 @@ #include "hw/mem/pc-dimm.h" -#define TYPE_NVDIMM "nvdimm" +#define TYPE_NVDIMM "nvdimm" +#define NVDIMM_DSM_MEM_FILE "etc/acpi/nvdimm-mem" + +/* + * 32 bits IO port starting from 0x0a18 in guest is reserved for + * NVDIMM ACPI emulation. + */ +#define NVDIMM_ACPI_IO_BASE 0x0a18 +#define NVDIMM_ACPI_IO_LEN 4 + +struct AcpiNVDIMMState { + /* detect if NVDIMM support is enabled. */ + bool is_enabled; + + /* the data of the fw_cfg file NVDIMM_DSM_MEM_FILE. */ + GArray *dsm_mem; + /* the IO region used by OSPM to transfer control to QEMU. */ + MemoryRegion io_mr; +}; +typedef struct AcpiNVDIMMState AcpiNVDIMMState; + +void nvdimm_init_acpi_state(AcpiNVDIMMState *state, MemoryRegion *io, + FWCfgState *fw_cfg, Object *owner); void nvdimm_build_acpi(GArray *table_offsets, GArray *table_data, GArray *linker); #endif -- cgit v1.2.3-55-g7522 From f7df22de561721e3804f5d27da9df6e77bbff274 Mon Sep 17 00:00:00 2001 From: Xiao Guangrong Date: Sat, 5 Mar 2016 00:00:35 +0800 Subject: nvdimm acpi: emulate dsm method Emulate dsm method after IO VM-exit Currently, we only introduce the framework and no function is actually supported Signed-off-by: Xiao Guangrong Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/acpi/nvdimm.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++++ include/hw/mem/nvdimm.h | 8 +++++++ 2 files changed, 64 insertions(+) (limited to 'include') diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c index 19c2642efa..9531340e56 100644 --- a/hw/acpi/nvdimm.c +++ b/hw/acpi/nvdimm.c @@ -390,15 +390,71 @@ struct NvdimmDsmOut { } QEMU_PACKED; typedef struct NvdimmDsmOut NvdimmDsmOut; +struct NvdimmDsmFunc0Out { + /* the size of buffer filled by QEMU. */ + uint32_t len; + uint32_t supported_func; +} QEMU_PACKED; +typedef struct NvdimmDsmFunc0Out NvdimmDsmFunc0Out; + +struct NvdimmDsmFuncNoPayloadOut { + /* the size of buffer filled by QEMU. */ + uint32_t len; + uint32_t func_ret_status; +} QEMU_PACKED; +typedef struct NvdimmDsmFuncNoPayloadOut NvdimmDsmFuncNoPayloadOut; + static uint64_t nvdimm_dsm_read(void *opaque, hwaddr addr, unsigned size) { + nvdimm_debug("BUG: we never read _DSM IO Port.\n"); return 0; } static void nvdimm_dsm_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { + NvdimmDsmIn *in; + hwaddr dsm_mem_addr = val; + + nvdimm_debug("dsm memory address %#" HWADDR_PRIx ".\n", dsm_mem_addr); + + /* + * The DSM memory is mapped to guest address space so an evil guest + * can change its content while we are doing DSM emulation. Avoid + * this by copying DSM memory to QEMU local memory. + */ + in = g_malloc(TARGET_PAGE_SIZE); + cpu_physical_memory_read(dsm_mem_addr, in, TARGET_PAGE_SIZE); + + le32_to_cpus(&in->revision); + le32_to_cpus(&in->function); + le32_to_cpus(&in->handle); + + nvdimm_debug("Revision %#x Handler %#x Function %#x.\n", in->revision, + in->handle, in->function); + + /* + * function 0 is called to inquire which functions are supported by + * OSPM + */ + if (in->function == 0) { + NvdimmDsmFunc0Out func0 = { + .len = cpu_to_le32(sizeof(func0)), + /* No function supported other than function 0 */ + .supported_func = cpu_to_le32(0), + }; + cpu_physical_memory_write(dsm_mem_addr, &func0, sizeof func0); + } else { + /* No function except function 0 is supported yet. */ + NvdimmDsmFuncNoPayloadOut out = { + .len = cpu_to_le32(sizeof(out)), + .func_ret_status = cpu_to_le32(1) /* Not Supported */, + }; + cpu_physical_memory_write(dsm_mem_addr, &out, sizeof(out)); + } + + g_free(in); } static const MemoryRegionOps nvdimm_dsm_ops = { diff --git a/include/hw/mem/nvdimm.h b/include/hw/mem/nvdimm.h index 26d5b78911..517de9c366 100644 --- a/include/hw/mem/nvdimm.h +++ b/include/hw/mem/nvdimm.h @@ -25,6 +25,14 @@ #include "hw/mem/pc-dimm.h" +#define NVDIMM_DEBUG 0 +#define nvdimm_debug(fmt, ...) \ + do { \ + if (NVDIMM_DEBUG) { \ + fprintf(stderr, "nvdimm: " fmt, ## __VA_ARGS__); \ + } \ + } while (0) + #define TYPE_NVDIMM "nvdimm" #define NVDIMM_DSM_MEM_FILE "etc/acpi/nvdimm-mem" -- cgit v1.2.3-55-g7522 From 3811ef14f59f9b0f9d9ad660a8d035c30944ca44 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Thu, 3 Mar 2016 15:28:56 +0100 Subject: machine: introduce MachineClass.possible_cpu_arch_ids() hook on x86 currently range 0..max_cpus is used to generate architecture-dependent CPU ID (APIC Id) for each present and possible CPUs. However architecture-dependent CPU IDs list could be sparse and code that needs to enumerate all IDs (ACPI) ended up doing guess work enumerating all possible and impossible IDs up to apic_id_limit = x86_cpu_apic_id_from_index(max_cpus). That leads to creation of MADT entries and Processor objects in ACPI tables for not possible CPUs. Fix it by allowing board specify a concrete list of CPU IDs accourding its own rules (which for x86 depends on topology). So that code that needs this list could request it from board instead of trying to guess what IDs are correct on its own. This interface will also allow to help making AML part of CPU hotplug target independent so it could be reused for ARM target. Signed-off-by: Igor Mammedov Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Reviewed-by: Marcel Apfelbaum --- hw/i386/pc.c | 44 ++++++++++++++++++++++++++++++++++++++++---- include/hw/boards.h | 26 ++++++++++++++++++++++++++ include/hw/i386/pc.h | 1 + 3 files changed, 67 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/hw/i386/pc.c b/hw/i386/pc.c index a469979f4a..2ac97c4f29 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -1131,10 +1131,17 @@ void pc_cpus_init(PCMachineState *pcms) exit(1); } - for (i = 0; i < smp_cpus; i++) { - cpu = pc_new_cpu(machine->cpu_model, x86_cpu_apic_id_from_index(i), - &error_fatal); - object_unref(OBJECT(cpu)); + pcms->possible_cpus = g_malloc0(sizeof(CPUArchIdList) + + sizeof(CPUArchId) * max_cpus); + for (i = 0; i < max_cpus; i++) { + pcms->possible_cpus->cpus[i].arch_id = x86_cpu_apic_id_from_index(i); + pcms->possible_cpus->len++; + if (i < smp_cpus) { + cpu = pc_new_cpu(machine->cpu_model, x86_cpu_apic_id_from_index(i), + &error_fatal); + pcms->possible_cpus->cpus[i].cpu = CPU(cpu); + object_unref(OBJECT(cpu)); + } } /* tell smbios about cpuid version and features */ @@ -1657,9 +1664,19 @@ static void pc_dimm_unplug(HotplugHandler *hotplug_dev, error_propagate(errp, local_err); } +static int pc_apic_cmp(const void *a, const void *b) +{ + CPUArchId *apic_a = (CPUArchId *)a; + CPUArchId *apic_b = (CPUArchId *)b; + + return apic_a->arch_id - apic_b->arch_id; +} + static void pc_cpu_plug(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { + CPUClass *cc = CPU_GET_CLASS(dev); + CPUArchId apic_id, *found_cpu; HotplugHandlerClass *hhc; Error *local_err = NULL; PCMachineState *pcms = PC_MACHINE(hotplug_dev); @@ -1682,6 +1699,13 @@ static void pc_cpu_plug(HotplugHandler *hotplug_dev, /* increment the number of CPUs */ rtc_set_memory(pcms->rtc, 0x5f, rtc_get_memory(pcms->rtc, 0x5f) + 1); + + apic_id.arch_id = cc->get_arch_id(CPU(dev)); + found_cpu = bsearch(&apic_id, pcms->possible_cpus->cpus, + pcms->possible_cpus->len, sizeof(*pcms->possible_cpus->cpus), + pc_apic_cmp); + assert(found_cpu); + found_cpu->cpu = CPU(dev); out: error_propagate(errp, local_err); } @@ -1924,6 +1948,17 @@ static unsigned pc_cpu_index_to_socket_id(unsigned cpu_index) return topo.pkg_id; } +static CPUArchIdList *pc_possible_cpu_arch_ids(MachineState *machine) +{ + PCMachineState *pcms = PC_MACHINE(machine); + int len = sizeof(CPUArchIdList) + + sizeof(CPUArchId) * (pcms->possible_cpus->len); + CPUArchIdList *list = g_malloc(len); + + memcpy(list, pcms->possible_cpus, len); + return list; +} + static void pc_machine_class_init(ObjectClass *oc, void *data) { MachineClass *mc = MACHINE_CLASS(oc); @@ -1946,6 +1981,7 @@ static void pc_machine_class_init(ObjectClass *oc, void *data) pcmc->save_tsc_khz = true; mc->get_hotplug_handler = pc_get_hotpug_handler; mc->cpu_index_to_socket_id = pc_cpu_index_to_socket_id; + mc->possible_cpu_arch_ids = pc_possible_cpu_arch_ids; mc->default_boot_order = "cad"; mc->hot_add_cpu = pc_hot_add_cpu; mc->max_cpus = 255; diff --git a/include/hw/boards.h b/include/hw/boards.h index b5d7eae3f3..4b3fdbea9d 100644 --- a/include/hw/boards.h +++ b/include/hw/boards.h @@ -8,6 +8,7 @@ #include "sysemu/accel.h" #include "hw/qdev.h" #include "qom/object.h" +#include "qom/cpu.h" void memory_region_allocate_system_memory(MemoryRegion *mr, Object *owner, const char *name, @@ -41,6 +42,26 @@ int machine_phandle_start(MachineState *machine); bool machine_dump_guest_core(MachineState *machine); bool machine_mem_merge(MachineState *machine); +/** + * CPUArchId: + * @arch_id - architecture-dependent CPU ID of present or possible CPU + * @cpu - pointer to corresponding CPU object if it's present on NULL otherwise + */ +typedef struct { + uint64_t arch_id; + struct CPUState *cpu; +} CPUArchId; + +/** + * CPUArchIdList: + * @len - number of @CPUArchId items in @cpus array + * @cpus - array of present or possible CPUs for current machine configuration + */ +typedef struct { + int len; + CPUArchId cpus[0]; +} CPUArchIdList; + /** * MachineClass: * @get_hotplug_handler: this function is called during bus-less @@ -57,6 +78,10 @@ bool machine_mem_merge(MachineState *machine); * Set only by old machines because they need to keep * compatibility on code that exposed QEMU_VERSION to guests in * the past (and now use qemu_hw_version()). + * @possible_cpu_arch_ids: + * Returns an array of @CPUArchId architecture-dependent CPU IDs + * which includes CPU IDs for present and possible to hotplug CPUs. + * Caller is responsible for freeing returned list. */ struct MachineClass { /*< private >*/ @@ -98,6 +123,7 @@ struct MachineClass { HotplugHandler *(*get_hotplug_handler)(MachineState *machine, DeviceState *dev); unsigned (*cpu_index_to_socket_id)(unsigned cpu_index); + CPUArchIdList *(*possible_cpu_arch_ids)(MachineState *machine); }; /** diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h index b0497769a1..8c2bf7fd67 100644 --- a/include/hw/i386/pc.h +++ b/include/hw/i386/pc.h @@ -67,6 +67,7 @@ struct PCMachineState { /* CPU and apic information: */ bool apic_xrupt_override; unsigned apic_id_limit; + CPUArchIdList *possible_cpus; /* NUMA information: */ uint64_t numa_nodes; -- cgit v1.2.3-55-g7522