Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging

vhost, virtio, pci, pc, acpi

nvdimm work
sparse cpu id rework
ipmi enhancements
fixes all over the place
pxb option to tweak chassis number

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>

# gpg: Signature made Tue 15 Mar 2016 14:33:10 GMT using RSA key ID D28D5469
# gpg: Good signature from "Michael S. Tsirkin <mst@kernel.org>"
# gpg:                 aka "Michael S. Tsirkin <mst@redhat.com>"

* remotes/mst/tags/for_upstream: (51 commits)
  hw/acpi: fix GSI links UID
  ipmi: add some local variables in ipmi_sdr_init
  ipmi: remove the need of an ending record in the SDR table
  ipmi: use a function to initialize the SDR table
  ipmi: add a realize function to the device class
  ipmi: add rsp_buffer_set_error() helper
  ipmi: remove IPMI_CHECK_RESERVATION() macro
  ipmi: replace IPMI_ADD_RSP_DATA() macro with inline helpers
  ipmi: remove IPMI_CHECK_CMD_LEN() macro
  MAINTAINERS: machine core
  MAINTAINERS: Add an entry for virtio header files
  pc: acpi: clarify why possible LAPIC entries must be present in MADT
  pc: acpi: drop cpu->found_cpus bitmap
  pc: acpi: create Processor and Notify objects only for valid lapics
  pc: acpi: create MADT.lapic entries only for valid lapics
  pc: acpi: SRAT: create only valid processor lapic entries
  pc: acpi: cleanup qdev_get_machine() calls
  machine: introduce MachineClass.possible_cpu_arch_ids() hook
  pc: init pcms->apic_id_limit once and use it throughout pc.c
  pc: acpi: remove NOP assignment
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell
2016-03-15 16:43:48 +00:00
44 changed files with 1113 additions and 618 deletions
+7
View File
@@ -717,6 +717,12 @@ F: hw/timer/hpet*
F: hw/timer/i8254*
F: hw/timer/mc146818rtc*
Machine core
M: Eduardo Habkost <ehabkost@redhat.com>
M: Marcel Apfelbaum <marcel@redhat.com>
S: Supported
F: hw/core/machine.c
F: include/hw/boards.h
Xtensa Machines
---------------
@@ -878,6 +884,7 @@ M: Michael S. Tsirkin <mst@redhat.com>
S: Supported
F: hw/*/virtio*
F: net/vhost-user.c
F: include/hw/virtio/
virtio-9p
M: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
+3 -3
View File
@@ -24,8 +24,8 @@ A detailed command line would be:
-object memory-backend-ram,size=1024M,policy=bind,host-nodes=0,id=ram-node0 -numa node,nodeid=0,cpus=0,memdev=ram-node0
-object memory-backend-ram,size=1024M,policy=bind,host-nodes=1,id=ram-node1 -numa node,nodeid=1,cpus=1,memdev=ram-node1
-device pxb,id=bridge1,bus=pci.0,numa_node=1,bus_nr=4 -netdev user,id=nd -device e1000,bus=bridge1,addr=0x4,netdev=nd
-device pxb,id=bridge2,bus=pci.0,numa_node=0,bus_nr=8, -device e1000,bus=bridge2,addr=0x3
-device pxb,id=bridge3,bus=pci.0,bus_nr=40, -drive if=none,id=drive0,file=[img] -device virtio-blk-pci,drive=drive0,scsi=off,bus=bridge3,addr=1
-device pxb,id=bridge2,bus=pci.0,numa_node=0,bus_nr=8 -device e1000,bus=bridge2,addr=0x3
-device pxb,id=bridge3,bus=pci.0,bus_nr=40 -drive if=none,id=drive0,file=[img] -device virtio-blk-pci,drive=drive0,scsi=off,bus=bridge3,addr=1
Here you have:
- 2 NUMA nodes for the guest, 0 and 1. (both mapped to the same NUMA node in host, but you can and should put it in different host NUMA nodes)
@@ -43,7 +43,7 @@ Implementation
==============
The PXB is composed by:
- HostBridge (TYPE_PXB_HOST)
The host bridge allows to register and query the PXB's rPCI root bus in QEMU.
The host bridge allows to register and query the PXB's PCI root bus in QEMU.
- PXBDev(TYPE_PXB_DEVICE)
It is a regular PCI Device that resides on the piix host-bridge bus and its bus uses the same PCI domain.
However, the bus behind is exposed through ACPI as a primary PCI bus and starts a new PCI hierarchy.
+17 -7
View File
@@ -15,13 +15,23 @@ The 1000 -> 10ff device ID range is used as follows for virtio-pci devices.
Note that this allocation separate from the virtio device IDs, which are
maintained as part of the virtio specification.
1af4:1000 network device
1af4:1001 block device
1af4:1002 balloon device
1af4:1003 console device
1af4:1004 SCSI host bus adapter device
1af4:1005 entropy generator device
1af4:1009 9p filesystem device
1af4:1000 network device (legacy)
1af4:1001 block device (legacy)
1af4:1002 balloon device (legacy)
1af4:1003 console device (legacy)
1af4:1004 SCSI host bus adapter device (legacy)
1af4:1005 entropy generator device (legacy)
1af4:1009 9p filesystem device (legacy)
1af4:1041 network device (modern)
1af4:1042 block device (modern)
1af4:1043 console device (modern)
1af4:1044 entropy generator device (modern)
1af4:1045 balloon device (modern)
1af4:1048 SCSI host bus adapter device (modern)
1af4:1049 9p filesystem device (modern)
1af4:1050 virtio gpu device (modern)
1af4:1052 virtio input device (modern)
1af4:10f0 Available for experimental usage without registration. Must get
to official ID when the code leaves the test lab (i.e. when seeking
+1 -1
View File
@@ -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
+51 -2
View File
@@ -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)
@@ -942,14 +970,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;
}
@@ -997,6 +1025,20 @@ Aml *create_field_common(int opcode, Aml *srcbuf, Aml *index, const char *name)
return var;
}
/* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: DefCreateField */
Aml *aml_create_field(Aml *srcbuf, Aml *bit_index, Aml *num_bits,
const char *name)
{
Aml *var = aml_alloc();
build_append_byte(var->buf, 0x5B); /* ExtOpPrefix */
build_append_byte(var->buf, 0x13); /* CreateFieldOp */
aml_append(var, srcbuf);
aml_append(var, bit_index);
aml_append(var, num_bits);
build_append_namestring(var->buf, "%s", name);
return var;
}
/* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: DefCreateDWordField */
Aml *aml_create_dword_field(Aml *srcbuf, Aml *index, const char *name)
{
@@ -1423,6 +1465,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,
+223 -8
View File
@@ -29,6 +29,8 @@
#include "qemu/osdep.h"
#include "hw/acpi/acpi.h"
#include "hw/acpi/aml-build.h"
#include "hw/acpi/bios-linker-loader.h"
#include "hw/nvram/fw_cfg.h"
#include "hw/mem/nvdimm.h"
static int nvdimm_plugged_device_list(Object *obj, void *opaque)
@@ -370,15 +372,131 @@ static void nvdimm_build_nfit(GSList *device_list, GArray *table_offsets,
g_array_free(structures, true);
}
struct NvdimmDsmIn {
uint32_t handle;
uint32_t revision;
uint32_t function;
/* the remaining size in the page is used by arg3. */
union {
uint8_t arg3[0];
};
} QEMU_PACKED;
typedef struct NvdimmDsmIn NvdimmDsmIn;
struct NvdimmDsmOut {
/* the size of buffer filled by QEMU. */
uint32_t len;
uint8_t data[0];
} 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 = {
.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"
#define NVDIMM_ACPI_MEM_ADDR "MEMA"
static void nvdimm_build_common_dsm(Aml *dev)
{
Aml *method, *ifctx, *function;
Aml *method, *ifctx, *function, *dsm_mem, *unpatched, *result_size;
uint8_t byte_list[1];
method = aml_method(NVDIMM_COMMON_DSM, 4, AML_NOTSERIALIZED);
method = aml_method(NVDIMM_COMMON_DSM, 4, AML_SERIALIZED);
function = aml_arg(2);
dsm_mem = aml_name(NVDIMM_ACPI_MEM_ADDR);
/*
* do not support any method if DSM memory address has not been
* patched.
*/
unpatched = aml_if(aml_equal(dsm_mem, aml_int(0x0)));
/*
* function 0 is called to inquire what functions are supported by
@@ -387,12 +505,38 @@ static void nvdimm_build_common_dsm(Aml *dev)
ifctx = aml_if(aml_equal(function, aml_int(0)));
byte_list[0] = 0 /* No function Supported */;
aml_append(ifctx, aml_return(aml_buffer(1, byte_list)));
aml_append(method, ifctx);
aml_append(unpatched, ifctx);
/* No function is supported yet. */
byte_list[0] = 1 /* Not Supported */;
aml_append(method, aml_return(aml_buffer(1, byte_list)));
aml_append(unpatched, aml_return(aml_buffer(1, byte_list)));
aml_append(method, unpatched);
/*
* The HDLE indicates the DSM function is issued from which device,
* it is not used at this time as no function is supported yet.
* Currently we make it always be 0 for all the devices and will set
* the appropriate value once real function is implemented.
*/
aml_append(method, aml_store(aml_int(0x0), aml_name("HDLE")));
aml_append(method, aml_store(aml_arg(1), aml_name("REVS")));
aml_append(method, aml_store(aml_arg(2), aml_name("FUNC")));
/*
* tell QEMU about the real address of DSM memory, then QEMU
* gets the control and fills the result in DSM memory.
*/
aml_append(method, aml_store(dsm_mem, aml_name("NTFI")));
result_size = aml_local(1);
aml_append(method, aml_store(aml_name("RLEN"), result_size));
aml_append(method, aml_store(aml_shiftleft(result_size, aml_int(3)),
result_size));
aml_append(method, aml_create_field(aml_name("ODAT"), aml_int(0),
result_size, "OBUF"));
aml_append(method, aml_concatenate(aml_buffer(0, NULL), aml_name("OBUF"),
aml_arg(6)));
aml_append(method, aml_return(aml_arg(6)));
aml_append(dev, method);
}
@@ -435,7 +579,8 @@ static void nvdimm_build_nvdimm_devices(GSList *device_list, Aml *root_dev)
static void nvdimm_build_ssdt(GSList *device_list, GArray *table_offsets,
GArray *table_data, GArray *linker)
{
Aml *ssdt, *sb_scope, *dev;
Aml *ssdt, *sb_scope, *dev, *field;
int mem_addr_offset, nvdimm_ssdt;
acpi_add_table(table_offsets, table_data);
@@ -459,19 +604,89 @@ static void nvdimm_build_ssdt(GSList *device_list, GArray *table_offsets,
*/
aml_append(dev, aml_name_decl("_HID", aml_string("ACPI0012")));
/* map DSM memory and IO into ACPI namespace. */
aml_append(dev, aml_operation_region("NPIO", AML_SYSTEM_IO,
aml_int(NVDIMM_ACPI_IO_BASE), NVDIMM_ACPI_IO_LEN));
aml_append(dev, aml_operation_region("NRAM", AML_SYSTEM_MEMORY,
aml_name(NVDIMM_ACPI_MEM_ADDR), TARGET_PAGE_SIZE));
/*
* DSM notifier:
* NTFI: write the address of DSM memory and notify QEMU to emulate
* the access.
*
* It is the IO port so that accessing them will cause VM-exit, the
* control will be transferred to QEMU.
*/
field = aml_field("NPIO", AML_DWORD_ACC, AML_NOLOCK, AML_PRESERVE);
aml_append(field, aml_named_field("NTFI",
sizeof(uint32_t) * BITS_PER_BYTE));
aml_append(dev, field);
/*
* DSM input:
* HDLE: store device's handle, it's zero if the _DSM call happens
* on NVDIMM Root Device.
* REVS: store the Arg1 of _DSM call.
* FUNC: store the Arg2 of _DSM call.
* ARG3: store the Arg3 of _DSM call.
*
* They are RAM mapping on host so that these accesses never cause
* VM-EXIT.
*/
field = aml_field("NRAM", AML_DWORD_ACC, AML_NOLOCK, AML_PRESERVE);
aml_append(field, aml_named_field("HDLE",
sizeof(typeof_field(NvdimmDsmIn, handle)) * BITS_PER_BYTE));
aml_append(field, aml_named_field("REVS",
sizeof(typeof_field(NvdimmDsmIn, revision)) * BITS_PER_BYTE));
aml_append(field, aml_named_field("FUNC",
sizeof(typeof_field(NvdimmDsmIn, function)) * BITS_PER_BYTE));
aml_append(field, aml_named_field("ARG3",
(TARGET_PAGE_SIZE - offsetof(NvdimmDsmIn, arg3)) *
BITS_PER_BYTE));
aml_append(dev, field);
/*
* DSM output:
* RLEN: the size of the buffer filled by QEMU.
* ODAT: the buffer QEMU uses to store the result.
*
* Since the page is reused by both input and out, the input data
* will be lost after storing new result into ODAT so we should fetch
* all the input data before writing the result.
*/
field = aml_field("NRAM", AML_DWORD_ACC, AML_NOLOCK, AML_PRESERVE);
aml_append(field, aml_named_field("RLEN",
sizeof(typeof_field(NvdimmDsmOut, len)) * BITS_PER_BYTE));
aml_append(field, aml_named_field("ODAT",
(TARGET_PAGE_SIZE - offsetof(NvdimmDsmOut, data)) *
BITS_PER_BYTE));
aml_append(dev, field);
nvdimm_build_common_dsm(dev);
nvdimm_build_device_dsm(dev);
nvdimm_build_nvdimm_devices(device_list, dev);
aml_append(sb_scope, dev);
aml_append(ssdt, sb_scope);
nvdimm_ssdt = table_data->len;
/* copy AML table into ACPI tables blob and patch header there */
g_array_append_vals(table_data, ssdt->buf->data, ssdt->buf->len);
mem_addr_offset = build_append_named_dword(table_data,
NVDIMM_ACPI_MEM_ADDR);
bios_linker_loader_alloc(linker, NVDIMM_DSM_MEM_FILE, TARGET_PAGE_SIZE,
false /* high memory */);
bios_linker_loader_add_pointer(linker, ACPI_BUILD_TABLE_FILE,
NVDIMM_DSM_MEM_FILE, table_data,
table_data->data + mem_addr_offset,
sizeof(uint32_t));
build_header(linker, table_data,
(void *)(table_data->data + table_data->len - ssdt->buf->len),
"SSDT", ssdt->buf->len, 1, NULL, "NVDIMM");
(void *)(table_data->data + nvdimm_ssdt),
"SSDT", table_data->len - nvdimm_ssdt, 1, NULL, "NVDIMM");
free_aml_allocator();
}
+23
View File
@@ -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,
+168 -133
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -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;
}
}
+63 -34
View File
@@ -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;
@@ -699,18 +699,6 @@ static uint32_t x86_cpu_apic_id_from_index(unsigned int cpu_index)
}
}
/* Calculates the limit to CPU APIC ID values
*
* This function returns the limit for the APIC ID value, so that all
* CPU APIC IDs are < pc_apic_id_limit().
*
* This is used for FW_CFG_MAX_CPUS. See comments on bochs_bios_init().
*/
static unsigned int pc_apic_id_limit(unsigned int max_cpus)
{
return x86_cpu_apic_id_from_index(max_cpus - 1) + 1;
}
static void pc_build_smbios(FWCfgState *fw_cfg)
{
uint8_t *smbios_tables, *smbios_anchor;
@@ -748,12 +736,11 @@ static void pc_build_smbios(FWCfgState *fw_cfg)
}
}
static FWCfgState *bochs_bios_init(AddressSpace *as)
static FWCfgState *bochs_bios_init(AddressSpace *as, PCMachineState *pcms)
{
FWCfgState *fw_cfg;
uint64_t *numa_fw_cfg;
int i, j;
unsigned int apic_id_limit = pc_apic_id_limit(max_cpus);
fw_cfg = fw_cfg_init_io_dma(FW_CFG_IO_BASE, FW_CFG_IO_BASE + 4, as);
@@ -771,7 +758,7 @@ static FWCfgState *bochs_bios_init(AddressSpace *as)
* [1] The only kind of "CPU identifier" used between SeaBIOS and QEMU is
* the APIC ID, not the "CPU index"
*/
fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)apic_id_limit);
fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)pcms->apic_id_limit);
fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size);
fw_cfg_add_bytes(fw_cfg, FW_CFG_ACPI_TABLES,
acpi_tables, acpi_tables_len);
@@ -789,11 +776,11 @@ static FWCfgState *bochs_bios_init(AddressSpace *as)
* of nodes, one word for each VCPU->node and one word for each node to
* hold the amount of memory.
*/
numa_fw_cfg = g_new0(uint64_t, 1 + apic_id_limit + nb_numa_nodes);
numa_fw_cfg = g_new0(uint64_t, 1 + pcms->apic_id_limit + nb_numa_nodes);
numa_fw_cfg[0] = cpu_to_le64(nb_numa_nodes);
for (i = 0; i < max_cpus; i++) {
unsigned int apic_id = x86_cpu_apic_id_from_index(i);
assert(apic_id < apic_id_limit);
assert(apic_id < pcms->apic_id_limit);
for (j = 0; j < nb_numa_nodes; j++) {
if (test_bit(i, numa_info[j].node_cpu)) {
numa_fw_cfg[apic_id + 1] = cpu_to_le64(j);
@@ -802,10 +789,11 @@ static FWCfgState *bochs_bios_init(AddressSpace *as)
}
}
for (i = 0; i < nb_numa_nodes; i++) {
numa_fw_cfg[apic_id_limit + 1 + i] = cpu_to_le64(numa_info[i].node_mem);
numa_fw_cfg[pcms->apic_id_limit + 1 + i] =
cpu_to_le64(numa_info[i].node_mem);
}
fw_cfg_add_bytes(fw_cfg, FW_CFG_NUMA, numa_fw_cfg,
(1 + apic_id_limit + nb_numa_nodes) *
(1 + pcms->apic_id_limit + nb_numa_nodes) *
sizeof(*numa_fw_cfg));
return fw_cfg;
@@ -1119,7 +1107,6 @@ void pc_cpus_init(PCMachineState *pcms)
int i;
X86CPU *cpu = NULL;
MachineState *machine = MACHINE(pcms);
unsigned long apic_id_limit;
/* init CPUs */
if (machine->cpu_model == NULL) {
@@ -1130,17 +1117,31 @@ void pc_cpus_init(PCMachineState *pcms)
#endif
}
apic_id_limit = pc_apic_id_limit(max_cpus);
if (apic_id_limit > ACPI_CPU_HOTPLUG_ID_LIMIT) {
error_report("max_cpus is too large. APIC ID of last CPU is %lu",
apic_id_limit - 1);
/* Calculates the limit to CPU APIC ID values
*
* Limit for the APIC ID value, so that all
* CPU APIC IDs are < pcms->apic_id_limit.
*
* This is used for FW_CFG_MAX_CPUS. See comments on bochs_bios_init().
*/
pcms->apic_id_limit = x86_cpu_apic_id_from_index(max_cpus - 1) + 1;
if (pcms->apic_id_limit > ACPI_CPU_HOTPLUG_ID_LIMIT) {
error_report("max_cpus is too large. APIC ID of last CPU is %u",
pcms->apic_id_limit - 1);
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 */
@@ -1186,7 +1187,6 @@ void pc_guest_info_init(PCMachineState *pcms)
{
int i, j;
pcms->apic_id_limit = pc_apic_id_limit(max_cpus);
pcms->apic_xrupt_override = kvm_allows_irq0_override();
pcms->numa_nodes = nb_numa_nodes;
pcms->node_mem = g_malloc0(pcms->numa_nodes *
@@ -1371,7 +1371,7 @@ void pc_memory_init(PCMachineState *pcms,
option_rom_mr,
1);
fw_cfg = bochs_bios_init(&address_space_memory);
fw_cfg = bochs_bios_init(&address_space_memory, pcms);
rom_set_fw(fw_cfg);
@@ -1664,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);
@@ -1689,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);
}
@@ -1853,14 +1870,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 +1916,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);
}
@@ -1931,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);
@@ -1953,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;
+5
View File
@@ -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.
+7 -1
View File
@@ -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) \
+1 -1
View File
@@ -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)
+1 -1
View File
@@ -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)
+1 -1
View File
@@ -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();
}
+1 -1
View File
@@ -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;
}
+1 -1
View File
@@ -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;
+360 -365
View File
File diff suppressed because it is too large Load Diff
+18 -17
View File
@@ -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;
+10 -3
View File
@@ -364,15 +364,22 @@ static void pc_dimm_check_memdev_is_busy(Object *obj, const char *name,
Object *val, Error **errp)
{
MemoryRegion *mr;
Error *local_err = NULL;
mr = host_memory_backend_get_memory(MEMORY_BACKEND(val), errp);
mr = host_memory_backend_get_memory(MEMORY_BACKEND(val), &local_err);
if (local_err) {
goto out;
}
if (memory_region_is_mapped(mr)) {
char *path = object_get_canonical_path_component(val);
error_setg(errp, "can't use already busy memdev: %s", path);
error_setg(&local_err, "can't use already busy memdev: %s", path);
g_free(path);
} else {
qdev_prop_allow_set_link_before_realize(obj, name, val, errp);
qdev_prop_allow_set_link_before_realize(obj, name, val, &local_err);
}
out:
error_propagate(errp, local_err);
}
static void pc_dimm_init(Object *obj)

Some files were not shown because too many files have changed in this diff Show More