mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge tag 'for_upstream' of https://git.kernel.org/pub/scm/virt/kvm/mst/qemu into staging
virtio,pci: features, cleanups
vdpa:
shadow vq vlan support
net migration with cvq
cxl:
support emulating 4 HDM decoders
serial number extended capability
virtio:
hared dma-buf
Fixes, cleanups all over the place.
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
* tag 'for_upstream' of https://git.kernel.org/pub/scm/virt/kvm/mst/qemu: (53 commits)
libvhost-user: handle shared_object msg
vhost-user: add shared_object msg
hw/display: introduce virtio-dmabuf
util/uuid: add a hash function
virtio: remove unused next argument from virtqueue_split_read_next_desc()
virtio: remove unnecessary thread fence while reading next descriptor
virtio: use shadow_avail_idx while checking number of heads
libvhost-user.c: add assertion to vu_message_read_default
pcie_sriov: unregister_vfs(): fix error path
hw/i386/pc: improve physical address space bound check for 32-bit x86 systems
amd_iommu: Fix APIC address check
vdpa net: follow VirtIO initialization properly at cvq isolation probing
vdpa net: stop probing if cannot set features
vdpa net: fix error message setting virtio status
hw/pci-bridge/cxl-upstream: Add serial number extended capability support
hw/cxl: Support 4 HDM decoders at all levels of topology
hw/cxl: Fix and use same calculation for HDM decoder block size everywhere
hw/cxl: Add utility functions decoder interleave ways and target count.
hw/cxl: Push cxl_decoder_count_enc() and cxl_decode_ig() into .c
vdpa net: zero vhost_vdpa iova_tree pointer at cleanup
...
Conflicts:
hw/core/machine.c
Context conflict with commit 314e0a84cd ("hw/core: remove needless
includes") because it removed an adjacent #include.
This commit is contained in:
@@ -2154,6 +2154,13 @@ T: git https://gitlab.com/cohuck/qemu.git s390-next
|
||||
T: git https://github.com/borntraeger/qemu.git s390-next
|
||||
L: qemu-s390x@nongnu.org
|
||||
|
||||
virtio-dmabuf
|
||||
M: Albert Esteve <aesteve@redhat.com>
|
||||
S: Supported
|
||||
F: hw/display/virtio-dmabuf.c
|
||||
F: include/hw/virtio/virtio-dmabuf.h
|
||||
F: tests/unit/test-virtio-dmabuf.c
|
||||
|
||||
virtiofs
|
||||
M: Stefan Hajnoczi <stefanha@redhat.com>
|
||||
S: Supported
|
||||
|
||||
@@ -1440,6 +1440,18 @@ Front-end message types
|
||||
query the back-end for its device status as defined in the Virtio
|
||||
specification.
|
||||
|
||||
``VHOST_USER_GET_SHARED_OBJECT``
|
||||
:id: 41
|
||||
:equivalent ioctl: N/A
|
||||
:request payload: ``struct VhostUserShared``
|
||||
:reply payload: dmabuf fd
|
||||
|
||||
When the ``VHOST_USER_PROTOCOL_F_SHARED_OBJECT`` protocol
|
||||
feature has been successfully negotiated, and the UUID is found
|
||||
in the exporters cache, this message is submitted by the front-end
|
||||
to retrieve a given dma-buf fd from a given back-end, determined by
|
||||
the requested UUID. Back-end will reply passing the fd when the operation
|
||||
is successful, or no fd otherwise.
|
||||
|
||||
Back-end message types
|
||||
----------------------
|
||||
@@ -1528,6 +1540,51 @@ is sent by the front-end.
|
||||
|
||||
The state.num field is currently reserved and must be set to 0.
|
||||
|
||||
``VHOST_USER_BACKEND_SHARED_OBJECT_ADD``
|
||||
:id: 6
|
||||
:equivalent ioctl: N/A
|
||||
:request payload: ``struct VhostUserShared``
|
||||
:reply payload: N/A
|
||||
|
||||
When the ``VHOST_USER_PROTOCOL_F_SHARED_OBJECT`` protocol
|
||||
feature has been successfully negotiated, this message can be submitted
|
||||
by the backends to add themselves as exporters to the virtio shared lookup
|
||||
table. The back-end device gets associated with a UUID in the shared table.
|
||||
The back-end is responsible of keeping its own table with exported dma-buf fds.
|
||||
When another back-end tries to import the resource associated with the UUID,
|
||||
it will send a message to the front-end, which will act as a proxy to the
|
||||
exporter back-end. If ``VHOST_USER_PROTOCOL_F_REPLY_ACK`` is negotiated, and
|
||||
the back-end sets the ``VHOST_USER_NEED_REPLY`` flag, the front-end must
|
||||
respond with zero when operation is successfully completed, or non-zero
|
||||
otherwise.
|
||||
|
||||
``VHOST_USER_BACKEND_SHARED_OBJECT_REMOVE``
|
||||
:id: 7
|
||||
:equivalent ioctl: N/A
|
||||
:request payload: ``struct VhostUserShared``
|
||||
:reply payload: N/A
|
||||
|
||||
When the ``VHOST_USER_PROTOCOL_F_SHARED_OBJECT`` protocol
|
||||
feature has been successfully negotiated, this message can be submitted
|
||||
by the backend to remove themselves from to the virtio-dmabuf shared
|
||||
table API. The shared table will remove the back-end device associated with
|
||||
the UUID. If ``VHOST_USER_PROTOCOL_F_REPLY_ACK`` is negotiated, and the
|
||||
back-end sets the ``VHOST_USER_NEED_REPLY`` flag, the front-end must respond
|
||||
with zero when operation is successfully completed, or non-zero otherwise.
|
||||
|
||||
``VHOST_USER_BACKEND_SHARED_OBJECT_LOOKUP``
|
||||
:id: 8
|
||||
:equivalent ioctl: N/A
|
||||
:request payload: ``struct VhostUserShared``
|
||||
:reply payload: dmabuf fd and ``u64``
|
||||
|
||||
When the ``VHOST_USER_PROTOCOL_F_SHARED_OBJECT`` protocol
|
||||
feature has been successfully negotiated, this message can be submitted
|
||||
by the backends to retrieve a given dma-buf fd from the virtio-dmabuf
|
||||
shared table given a UUID. Frontend will reply passing the fd and a zero
|
||||
when the operation is successful, or non-zero otherwise. Note that if the
|
||||
operation fails, no fd is sent to the backend.
|
||||
|
||||
.. _reply_ack:
|
||||
|
||||
VHOST_USER_PROTOCOL_F_REPLY_ACK
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "hw/i386/pc.h"
|
||||
#include "hw/i386/acpi-build.h"
|
||||
|
||||
void pc_madt_cpu_entry(int uid, const CPUArchIdList *apic_ids,
|
||||
GArray *entry, bool force_enabled)
|
||||
{
|
||||
}
|
||||
|
||||
Object *acpi_get_i386_pci_host(void)
|
||||
{
|
||||
return NULL;
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include "qemu/module.h"
|
||||
#include "qemu/option.h"
|
||||
#include "sysemu/runstate.h"
|
||||
#include "trace.h"
|
||||
|
||||
struct acpi_table_header {
|
||||
uint16_t _length; /* our length, not actual part of the hdr */
|
||||
@@ -688,9 +689,11 @@ void acpi_gpe_ioport_writeb(ACPIREGS *ar, uint32_t addr, uint32_t val)
|
||||
|
||||
cur = acpi_gpe_ioport_get_ptr(ar, addr);
|
||||
if (addr < ar->gpe.len / 2) {
|
||||
trace_acpi_gpe_sts_ioport_writeb(addr, val);
|
||||
/* GPE_STS */
|
||||
*cur = (*cur) & ~val;
|
||||
} else if (addr < ar->gpe.len) {
|
||||
trace_acpi_gpe_en_ioport_writeb(addr - (ar->gpe.len / 2), val);
|
||||
/* GPE_EN */
|
||||
*cur = val;
|
||||
} else {
|
||||
@@ -709,6 +712,12 @@ uint32_t acpi_gpe_ioport_readb(ACPIREGS *ar, uint32_t addr)
|
||||
val = *cur;
|
||||
}
|
||||
|
||||
if (addr < ar->gpe.len / 2) {
|
||||
trace_acpi_gpe_sts_ioport_readb(addr, val);
|
||||
} else {
|
||||
trace_acpi_gpe_en_ioport_readb(addr - (ar->gpe.len / 2), val);
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
|
||||
+3
-6
@@ -1,6 +1,7 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "migration/vmstate.h"
|
||||
#include "hw/acpi/cpu.h"
|
||||
#include "hw/core/cpu.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qapi/qapi-events-acpi.h"
|
||||
#include "trace.h"
|
||||
@@ -338,7 +339,7 @@ const VMStateDescription vmstate_cpu_hotplug = {
|
||||
#define CPU_FW_EJECT_EVENT "CEJF"
|
||||
|
||||
void build_cpus_aml(Aml *table, MachineState *machine, CPUHotplugFeatures opts,
|
||||
hwaddr io_base,
|
||||
build_madt_cpu_fn build_madt_cpu, hwaddr io_base,
|
||||
const char *res_root,
|
||||
const char *event_handler_method)
|
||||
{
|
||||
@@ -353,8 +354,6 @@ void build_cpus_aml(Aml *table, MachineState *machine, CPUHotplugFeatures opts,
|
||||
MachineClass *mc = MACHINE_GET_CLASS(machine);
|
||||
const CPUArchIdList *arch_ids = mc->possible_cpu_arch_ids(machine);
|
||||
char *cphp_res_path = g_strdup_printf("%s." CPUHP_RES_DEVICE, res_root);
|
||||
Object *obj = object_resolve_path_type("", TYPE_ACPI_DEVICE_IF, NULL);
|
||||
AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_GET_CLASS(obj);
|
||||
|
||||
cpu_ctrl_dev = aml_device("%s", cphp_res_path);
|
||||
{
|
||||
@@ -664,9 +663,7 @@ void build_cpus_aml(Aml *table, MachineState *machine, CPUHotplugFeatures opts,
|
||||
aml_append(dev, method);
|
||||
|
||||
/* build _MAT object */
|
||||
assert(adevc && adevc->madt_cpu);
|
||||
adevc->madt_cpu(i, arch_ids, madt_buf,
|
||||
true); /* set enabled flag */
|
||||
build_madt_cpu(i, arch_ids, madt_buf, true); /* set enabled flag */
|
||||
aml_append(dev, aml_name_decl("_MAT",
|
||||
aml_buffer(madt_buf->len, (uint8_t *)madt_buf->data)));
|
||||
g_array_free(madt_buf, true);
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/units.h"
|
||||
#include "sysemu/numa.h"
|
||||
#include "hw/acpi/aml-build.h"
|
||||
#include "hw/acpi/hmat.h"
|
||||
|
||||
/*
|
||||
|
||||
+2
-1
@@ -27,7 +27,8 @@
|
||||
#ifndef HMAT_H
|
||||
#define HMAT_H
|
||||
|
||||
#include "hw/acpi/aml-build.h"
|
||||
#include "hw/acpi/bios-linker-loader.h"
|
||||
#include "sysemu/numa.h"
|
||||
|
||||
/*
|
||||
* ACPI 6.3: 5.2.27.3 Memory Proximity Domain Attributes Structure,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "hw/acpi/memory_hotplug.h"
|
||||
#include "hw/mem/pc-dimm.h"
|
||||
#include "hw/boards.h"
|
||||
#include "hw/qdev-core.h"
|
||||
#include "migration/vmstate.h"
|
||||
#include "trace.h"
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "hw/i386/pc.h"
|
||||
#include "hw/irq.h"
|
||||
#include "hw/isa/apm.h"
|
||||
#include "hw/i2c/pm_smbus.h"
|
||||
@@ -43,7 +42,6 @@
|
||||
#include "hw/acpi/acpi_dev_interface.h"
|
||||
#include "migration/vmstate.h"
|
||||
#include "hw/core/cpu.h"
|
||||
#include "trace.h"
|
||||
#include "qom/object.h"
|
||||
|
||||
#define GPE_BASE 0xafe0
|
||||
@@ -518,7 +516,6 @@ static uint64_t gpe_readb(void *opaque, hwaddr addr, unsigned width)
|
||||
PIIX4PMState *s = opaque;
|
||||
uint32_t val = acpi_gpe_ioport_readb(&s->ar, addr);
|
||||
|
||||
trace_piix4_gpe_readb(addr, width, val);
|
||||
return val;
|
||||
}
|
||||
|
||||
@@ -527,7 +524,6 @@ static void gpe_writeb(void *opaque, hwaddr addr, uint64_t val,
|
||||
{
|
||||
PIIX4PMState *s = opaque;
|
||||
|
||||
trace_piix4_gpe_writeb(addr, width, val);
|
||||
acpi_gpe_ioport_writeb(&s->ar, addr, val);
|
||||
acpi_update_sci(&s->ar, s->irq);
|
||||
}
|
||||
@@ -654,7 +650,6 @@ static void piix4_pm_class_init(ObjectClass *klass, void *data)
|
||||
hc->is_hotpluggable_bus = piix4_is_hotpluggable_bus;
|
||||
adevc->ospm_status = piix4_ospm_status;
|
||||
adevc->send_event = piix4_send_gpe;
|
||||
adevc->madt_cpu = pc_madt_cpu_entry;
|
||||
}
|
||||
|
||||
static const TypeInfo piix4_pm_info = {
|
||||
|
||||
@@ -17,6 +17,12 @@ mhp_acpi_clear_remove_evt(uint32_t slot) "slot[0x%"PRIx32"] clear remove event"
|
||||
mhp_acpi_pc_dimm_deleted(uint32_t slot) "slot[0x%"PRIx32"] pc-dimm deleted"
|
||||
mhp_acpi_pc_dimm_delete_failed(uint32_t slot) "slot[0x%"PRIx32"] pc-dimm delete failed"
|
||||
|
||||
# core.c
|
||||
acpi_gpe_en_ioport_readb(uint32_t addr, uint8_t val) "addr: 0x%" PRIx32 " ==> 0x%02" PRIx8
|
||||
acpi_gpe_en_ioport_writeb(uint32_t addr, uint8_t val) "addr: 0x%" PRIx32 " <== 0x%02" PRIx8
|
||||
acpi_gpe_sts_ioport_readb(uint32_t addr, uint8_t val) "addr: 0x%" PRIx32 " ==> 0x%02" PRIx8
|
||||
acpi_gpe_sts_ioport_writeb(uint32_t addr, uint8_t val) "addr: 0x%" PRIx32 " <== 0x%02" PRIx8
|
||||
|
||||
# cpu.c
|
||||
cpuhp_acpi_invalid_idx_selected(uint32_t idx) "0x%"PRIx32
|
||||
cpuhp_acpi_read_flags(uint32_t idx, uint8_t flags) "idx[0x%"PRIx32"] flags: 0x%"PRIx8
|
||||
@@ -48,10 +54,6 @@ acpi_pci_sel_read(uint32_t val) "%" PRIu32
|
||||
acpi_pci_ej_write(uint64_t addr, uint64_t data) "0x%" PRIx64 " <== %" PRIu64
|
||||
acpi_pci_sel_write(uint64_t addr, uint64_t data) "0x%" PRIx64 " <== %" PRIu64
|
||||
|
||||
# piix4.c
|
||||
piix4_gpe_readb(uint64_t addr, unsigned width, uint64_t val) "addr: 0x%" PRIx64 " width: %d ==> 0x%" PRIx64
|
||||
piix4_gpe_writeb(uint64_t addr, unsigned width, uint64_t val) "addr: 0x%" PRIx64 " width: %d <== 0x%" PRIx64
|
||||
|
||||
# tco.c
|
||||
tco_timer_reload(int ticks, int msec) "ticks=%d (%d ms)"
|
||||
tco_timer_expired(int timeouts_no, bool strap, bool no_reboot) "timeouts_no=%d no_reboot=%d/%d"
|
||||
|
||||
+4
-1
@@ -24,6 +24,7 @@
|
||||
#include "sysemu/runstate.h"
|
||||
#include "sysemu/xen.h"
|
||||
#include "sysemu/qtest.h"
|
||||
#include "hw/pci/pci_bridge.h"
|
||||
#include "hw/mem/nvdimm.h"
|
||||
#include "migration/global_state.h"
|
||||
#include "exec/confidential-guest-support.h"
|
||||
@@ -31,7 +32,9 @@
|
||||
#include "hw/virtio/virtio-net.h"
|
||||
#include "audio/audio.h"
|
||||
|
||||
GlobalProperty hw_compat_8_1[] = {};
|
||||
GlobalProperty hw_compat_8_1[] = {
|
||||
{ TYPE_PCI_BRIDGE, "x-pci-express-writeable-slt-bug", "true" },
|
||||
};
|
||||
const size_t hw_compat_8_1_len = G_N_ELEMENTS(hw_compat_8_1);
|
||||
|
||||
GlobalProperty hw_compat_8_0[] = {
|
||||
|
||||
@@ -13,6 +13,54 @@
|
||||
#include "hw/pci/pci.h"
|
||||
#include "hw/cxl/cxl.h"
|
||||
|
||||
/* CXL r3.0 Section 8.2.4.19.1 CXL HDM Decoder Capability Register */
|
||||
int cxl_decoder_count_enc(int count)
|
||||
{
|
||||
switch (count) {
|
||||
case 1: return 0x0;
|
||||
case 2: return 0x1;
|
||||
case 4: return 0x2;
|
||||
case 6: return 0x3;
|
||||
case 8: return 0x4;
|
||||
case 10: return 0x5;
|
||||
/* Switches and Host Bridges may have more than 10 decoders */
|
||||
case 12: return 0x6;
|
||||
case 14: return 0x7;
|
||||
case 16: return 0x8;
|
||||
case 20: return 0x9;
|
||||
case 24: return 0xa;
|
||||
case 28: return 0xb;
|
||||
case 32: return 0xc;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cxl_decoder_count_dec(int enc_cnt)
|
||||
{
|
||||
switch (enc_cnt) {
|
||||
case 0x0: return 1;
|
||||
case 0x1: return 2;
|
||||
case 0x2: return 4;
|
||||
case 0x3: return 6;
|
||||
case 0x4: return 8;
|
||||
case 0x5: return 10;
|
||||
/* Switches and Host Bridges may have more than 10 decoders */
|
||||
case 0x6: return 12;
|
||||
case 0x7: return 14;
|
||||
case 0x8: return 16;
|
||||
case 0x9: return 20;
|
||||
case 0xa: return 24;
|
||||
case 0xb: return 28;
|
||||
case 0xc: return 32;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
hwaddr cxl_decode_ig(int ig)
|
||||
{
|
||||
return 1ULL << (ig + 8);
|
||||
}
|
||||
|
||||
static uint64_t cxl_cache_mem_read_reg(void *opaque, hwaddr offset,
|
||||
unsigned size)
|
||||
{
|
||||
@@ -42,6 +90,9 @@ static void dumb_hdm_handler(CXLComponentState *cxl_cstate, hwaddr offset,
|
||||
|
||||
switch (offset) {
|
||||
case A_CXL_HDM_DECODER0_CTRL:
|
||||
case A_CXL_HDM_DECODER1_CTRL:
|
||||
case A_CXL_HDM_DECODER2_CTRL:
|
||||
case A_CXL_HDM_DECODER3_CTRL:
|
||||
should_commit = FIELD_EX32(value, CXL_HDM_DECODER0_CTRL, COMMIT);
|
||||
should_uncommit = !should_commit;
|
||||
break;
|
||||
@@ -81,7 +132,7 @@ static void cxl_cache_mem_write_reg(void *opaque, hwaddr offset, uint64_t value,
|
||||
}
|
||||
|
||||
if (offset >= A_CXL_HDM_DECODER_CAPABILITY &&
|
||||
offset <= A_CXL_HDM_DECODER0_TARGET_LIST_HI) {
|
||||
offset <= A_CXL_HDM_DECODER3_TARGET_LIST_HI) {
|
||||
dumb_hdm_handler(cxl_cstate, offset, value);
|
||||
} else {
|
||||
cregs->cache_mem_registers[offset / sizeof(*cregs->cache_mem_registers)] = value;
|
||||
@@ -161,7 +212,8 @@ static void ras_init_common(uint32_t *reg_state, uint32_t *write_msk)
|
||||
static void hdm_init_common(uint32_t *reg_state, uint32_t *write_msk,
|
||||
enum reg_type type)
|
||||
{
|
||||
int decoder_count = 1;
|
||||
int decoder_count = CXL_HDM_DECODER_COUNT;
|
||||
int hdm_inc = R_CXL_HDM_DECODER1_BASE_LO - R_CXL_HDM_DECODER0_BASE_LO;
|
||||
int i;
|
||||
|
||||
ARRAY_FIELD_DP32(reg_state, CXL_HDM_DECODER_CAPABILITY, DECODER_COUNT,
|
||||
@@ -174,19 +226,21 @@ static void hdm_init_common(uint32_t *reg_state, uint32_t *write_msk,
|
||||
HDM_DECODER_ENABLE, 0);
|
||||
write_msk[R_CXL_HDM_DECODER_GLOBAL_CONTROL] = 0x3;
|
||||
for (i = 0; i < decoder_count; i++) {
|
||||
write_msk[R_CXL_HDM_DECODER0_BASE_LO + i * 0x20] = 0xf0000000;
|
||||
write_msk[R_CXL_HDM_DECODER0_BASE_HI + i * 0x20] = 0xffffffff;
|
||||
write_msk[R_CXL_HDM_DECODER0_SIZE_LO + i * 0x20] = 0xf0000000;
|
||||
write_msk[R_CXL_HDM_DECODER0_SIZE_HI + i * 0x20] = 0xffffffff;
|
||||
write_msk[R_CXL_HDM_DECODER0_CTRL + i * 0x20] = 0x13ff;
|
||||
write_msk[R_CXL_HDM_DECODER0_BASE_LO + i * hdm_inc] = 0xf0000000;
|
||||
write_msk[R_CXL_HDM_DECODER0_BASE_HI + i * hdm_inc] = 0xffffffff;
|
||||
write_msk[R_CXL_HDM_DECODER0_SIZE_LO + i * hdm_inc] = 0xf0000000;
|
||||
write_msk[R_CXL_HDM_DECODER0_SIZE_HI + i * hdm_inc] = 0xffffffff;
|
||||
write_msk[R_CXL_HDM_DECODER0_CTRL + i * hdm_inc] = 0x13ff;
|
||||
if (type == CXL2_DEVICE ||
|
||||
type == CXL2_TYPE3_DEVICE ||
|
||||
type == CXL2_LOGICAL_DEVICE) {
|
||||
write_msk[R_CXL_HDM_DECODER0_TARGET_LIST_LO + i * 0x20] = 0xf0000000;
|
||||
write_msk[R_CXL_HDM_DECODER0_TARGET_LIST_LO + i * hdm_inc] =
|
||||
0xf0000000;
|
||||
} else {
|
||||
write_msk[R_CXL_HDM_DECODER0_TARGET_LIST_LO + i * 0x20] = 0xffffffff;
|
||||
write_msk[R_CXL_HDM_DECODER0_TARGET_LIST_LO + i * hdm_inc] =
|
||||
0xffffffff;
|
||||
}
|
||||
write_msk[R_CXL_HDM_DECODER0_TARGET_LIST_HI + i * 0x20] = 0xffffffff;
|
||||
write_msk[R_CXL_HDM_DECODER0_TARGET_LIST_HI + i * hdm_inc] = 0xffffffff;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -375,6 +429,7 @@ void cxl_component_create_dvsec(CXLComponentState *cxl,
|
||||
cxl->dvsec_offset += length;
|
||||
}
|
||||
|
||||
/* CXL r3.0 Section 8.2.4.19.7 CXL HDM Decoder n Control Register */
|
||||
uint8_t cxl_interleave_ways_enc(int iw, Error **errp)
|
||||
{
|
||||
switch (iw) {
|
||||
@@ -392,6 +447,23 @@ uint8_t cxl_interleave_ways_enc(int iw, Error **errp)
|
||||
}
|
||||
}
|
||||
|
||||
int cxl_interleave_ways_dec(uint8_t iw_enc, Error **errp)
|
||||
{
|
||||
switch (iw_enc) {
|
||||
case 0x0: return 1;
|
||||
case 0x1: return 2;
|
||||
case 0x2: return 4;
|
||||
case 0x3: return 8;
|
||||
case 0x4: return 16;
|
||||
case 0x8: return 3;
|
||||
case 0x9: return 6;
|
||||
case 0xa: return 12;
|
||||
default:
|
||||
error_setg(errp, "Encoded interleave ways: %d not supported", iw_enc);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t cxl_interleave_granularity_enc(uint64_t gran, Error **errp)
|
||||
{
|
||||
switch (gran) {
|
||||
|
||||
+46
-21
@@ -97,33 +97,58 @@ void cxl_fmws_link_targets(CXLState *cxl_state, Error **errp)
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: support, multiple hdm decoders */
|
||||
static bool cxl_hdm_find_target(uint32_t *cache_mem, hwaddr addr,
|
||||
uint8_t *target)
|
||||
{
|
||||
uint32_t ctrl;
|
||||
uint32_t ig_enc;
|
||||
uint32_t iw_enc;
|
||||
uint32_t target_idx;
|
||||
int hdm_inc = R_CXL_HDM_DECODER1_BASE_LO - R_CXL_HDM_DECODER0_BASE_LO;
|
||||
unsigned int hdm_count;
|
||||
bool found = false;
|
||||
int i;
|
||||
uint32_t cap;
|
||||
|
||||
ctrl = cache_mem[R_CXL_HDM_DECODER0_CTRL];
|
||||
if (!FIELD_EX32(ctrl, CXL_HDM_DECODER0_CTRL, COMMITTED)) {
|
||||
return false;
|
||||
cap = ldl_le_p(cache_mem + R_CXL_HDM_DECODER_CAPABILITY);
|
||||
hdm_count = cxl_decoder_count_dec(FIELD_EX32(cap,
|
||||
CXL_HDM_DECODER_CAPABILITY,
|
||||
DECODER_COUNT));
|
||||
for (i = 0; i < hdm_count; i++) {
|
||||
uint32_t ctrl, ig_enc, iw_enc, target_idx;
|
||||
uint32_t low, high;
|
||||
uint64_t base, size;
|
||||
|
||||
low = ldl_le_p(cache_mem + R_CXL_HDM_DECODER0_BASE_LO + i * hdm_inc);
|
||||
high = ldl_le_p(cache_mem + R_CXL_HDM_DECODER0_BASE_HI + i * hdm_inc);
|
||||
base = (low & 0xf0000000) | ((uint64_t)high << 32);
|
||||
low = ldl_le_p(cache_mem + R_CXL_HDM_DECODER0_SIZE_LO + i * hdm_inc);
|
||||
high = ldl_le_p(cache_mem + R_CXL_HDM_DECODER0_SIZE_HI + i * hdm_inc);
|
||||
size = (low & 0xf0000000) | ((uint64_t)high << 32);
|
||||
if (addr < base || addr >= base + size) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ctrl = ldl_le_p(cache_mem + R_CXL_HDM_DECODER0_CTRL + i * hdm_inc);
|
||||
if (!FIELD_EX32(ctrl, CXL_HDM_DECODER0_CTRL, COMMITTED)) {
|
||||
return false;
|
||||
}
|
||||
found = true;
|
||||
ig_enc = FIELD_EX32(ctrl, CXL_HDM_DECODER0_CTRL, IG);
|
||||
iw_enc = FIELD_EX32(ctrl, CXL_HDM_DECODER0_CTRL, IW);
|
||||
target_idx = (addr / cxl_decode_ig(ig_enc)) % (1 << iw_enc);
|
||||
|
||||
if (target_idx < 4) {
|
||||
uint32_t val = ldl_le_p(cache_mem +
|
||||
R_CXL_HDM_DECODER0_TARGET_LIST_LO +
|
||||
i * hdm_inc);
|
||||
*target = extract32(val, target_idx * 8, 8);
|
||||
} else {
|
||||
uint32_t val = ldl_le_p(cache_mem +
|
||||
R_CXL_HDM_DECODER0_TARGET_LIST_HI +
|
||||
i * hdm_inc);
|
||||
*target = extract32(val, (target_idx - 4) * 8, 8);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
ig_enc = FIELD_EX32(ctrl, CXL_HDM_DECODER0_CTRL, IG);
|
||||
iw_enc = FIELD_EX32(ctrl, CXL_HDM_DECODER0_CTRL, IW);
|
||||
target_idx = (addr / cxl_decode_ig(ig_enc)) % (1 << iw_enc);
|
||||
|
||||
if (target_idx < 4) {
|
||||
*target = extract32(cache_mem[R_CXL_HDM_DECODER0_TARGET_LIST_LO],
|
||||
target_idx * 8, 8);
|
||||
} else {
|
||||
*target = extract32(cache_mem[R_CXL_HDM_DECODER0_TARGET_LIST_HI],
|
||||
(target_idx - 4) * 8, 8);
|
||||
}
|
||||
|
||||
return true;
|
||||
return found;
|
||||
}
|
||||
|
||||
static PCIDevice *cxl_cfmws_find_device(CXLFixedWindow *fw, hwaddr addr)
|
||||
|
||||
@@ -37,6 +37,7 @@ system_ss.add(when: 'CONFIG_MACFB', if_true: files('macfb.c'))
|
||||
system_ss.add(when: 'CONFIG_NEXTCUBE', if_true: files('next-fb.c'))
|
||||
|
||||
system_ss.add(when: 'CONFIG_VGA', if_true: files('vga.c'))
|
||||
system_ss.add(when: 'CONFIG_VIRTIO', if_true: files('virtio-dmabuf.c'))
|
||||
|
||||
if (config_all_devices.has_key('CONFIG_VGA_CIRRUS') or
|
||||
config_all_devices.has_key('CONFIG_VGA_PCI') or
|
||||
|
||||
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
* Virtio Shared dma-buf
|
||||
*
|
||||
* Copyright Red Hat, Inc. 2023
|
||||
*
|
||||
* Authors:
|
||||
* Albert Esteve <aesteve@redhat.com>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
|
||||
#include "hw/virtio/virtio-dmabuf.h"
|
||||
|
||||
|
||||
static GMutex lock;
|
||||
static GHashTable *resource_uuids;
|
||||
|
||||
/*
|
||||
* uuid_equal_func: wrapper for UUID is_equal function to
|
||||
* satisfy g_hash_table_new expected parameters signatures.
|
||||
*/
|
||||
static int uuid_equal_func(const void *lhv, const void *rhv)
|
||||
{
|
||||
return qemu_uuid_is_equal(lhv, rhv);
|
||||
}
|
||||
|
||||
static bool virtio_add_resource(QemuUUID *uuid, VirtioSharedObject *value)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
g_mutex_lock(&lock);
|
||||
if (resource_uuids == NULL) {
|
||||
resource_uuids = g_hash_table_new_full(qemu_uuid_hash,
|
||||
uuid_equal_func,
|
||||
NULL,
|
||||
g_free);
|
||||
}
|
||||
if (g_hash_table_lookup(resource_uuids, uuid) == NULL) {
|
||||
result = g_hash_table_insert(resource_uuids, uuid, value);
|
||||
}
|
||||
g_mutex_unlock(&lock);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool virtio_add_dmabuf(QemuUUID *uuid, int udmabuf_fd)
|
||||
{
|
||||
bool result;
|
||||
VirtioSharedObject *vso;
|
||||
if (udmabuf_fd < 0) {
|
||||
return false;
|
||||
}
|
||||
vso = g_new(VirtioSharedObject, 1);
|
||||
vso->type = TYPE_DMABUF;
|
||||
vso->value = GINT_TO_POINTER(udmabuf_fd);
|
||||
result = virtio_add_resource(uuid, vso);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool virtio_add_vhost_device(QemuUUID *uuid, struct vhost_dev *dev)
|
||||
{
|
||||
bool result;
|
||||
VirtioSharedObject *vso;
|
||||
if (dev == NULL) {
|
||||
return false;
|
||||
}
|
||||
vso = g_new(VirtioSharedObject, 1);
|
||||
vso->type = TYPE_VHOST_DEV;
|
||||
vso->value = dev;
|
||||
result = virtio_add_resource(uuid, vso);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool virtio_remove_resource(const QemuUUID *uuid)
|
||||
{
|
||||
bool result;
|
||||
g_mutex_lock(&lock);
|
||||
result = g_hash_table_remove(resource_uuids, uuid);
|
||||
g_mutex_unlock(&lock);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static VirtioSharedObject *get_shared_object(const QemuUUID *uuid)
|
||||
{
|
||||
gpointer lookup_res = NULL;
|
||||
|
||||
g_mutex_lock(&lock);
|
||||
if (resource_uuids != NULL) {
|
||||
lookup_res = g_hash_table_lookup(resource_uuids, uuid);
|
||||
}
|
||||
g_mutex_unlock(&lock);
|
||||
|
||||
return (VirtioSharedObject *) lookup_res;
|
||||
}
|
||||
|
||||
int virtio_lookup_dmabuf(const QemuUUID *uuid)
|
||||
{
|
||||
VirtioSharedObject *vso = get_shared_object(uuid);
|
||||
if (vso == NULL) {
|
||||
return -1;
|
||||
}
|
||||
assert(vso->type == TYPE_DMABUF);
|
||||
return GPOINTER_TO_INT(vso->value);
|
||||
}
|
||||
|
||||
struct vhost_dev *virtio_lookup_vhost_device(const QemuUUID *uuid)
|
||||
{
|
||||
VirtioSharedObject *vso = get_shared_object(uuid);
|
||||
if (vso == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
assert(vso->type == TYPE_VHOST_DEV);
|
||||
return (struct vhost_dev *) vso->value;
|
||||
}
|
||||
|
||||
SharedObjectType virtio_object_type(const QemuUUID *uuid)
|
||||
{
|
||||
VirtioSharedObject *vso = get_shared_object(uuid);
|
||||
if (vso == NULL) {
|
||||
return TYPE_INVALID;
|
||||
}
|
||||
return vso->type;
|
||||
}
|
||||
|
||||
void virtio_free_resources(void)
|
||||
{
|
||||
g_mutex_lock(&lock);
|
||||
g_hash_table_destroy(resource_uuids);
|
||||
/* Reference count shall be 0 after the implicit unref on destroy */
|
||||
resource_uuids = NULL;
|
||||
g_mutex_unlock(&lock);
|
||||
}
|
||||
@@ -1495,14 +1495,14 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
|
||||
aml_append(crs,
|
||||
aml_io(
|
||||
AML_DECODE16,
|
||||
ACPI_PORT_SMI_CMD,
|
||||
ACPI_PORT_SMI_CMD,
|
||||
pm->fadt.smi_cmd,
|
||||
pm->fadt.smi_cmd,
|
||||
1,
|
||||
2)
|
||||
);
|
||||
aml_append(dev, aml_name_decl("_CRS", crs));
|
||||
aml_append(dev, aml_operation_region("SMIR", AML_SYSTEM_IO,
|
||||
aml_int(ACPI_PORT_SMI_CMD), 2));
|
||||
aml_int(pm->fadt.smi_cmd), 2));
|
||||
field = aml_field("SMIR", AML_BYTE_ACC, AML_NOLOCK,
|
||||
AML_WRITE_AS_ZEROS);
|
||||
aml_append(field, aml_named_field("SMIC", 8));
|
||||
@@ -1549,8 +1549,8 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
|
||||
.smi_path = pm->smi_on_cpuhp ? "\\_SB.PCI0.SMI0.SMIC" : NULL,
|
||||
.fw_unplugs_cpu = pm->smi_on_cpu_unplug,
|
||||
};
|
||||
build_cpus_aml(dsdt, machine, opts, pm->cpu_hp_io_base,
|
||||
"\\_SB.PCI0", "\\_GPE._E02");
|
||||
build_cpus_aml(dsdt, machine, opts, pc_madt_cpu_entry,
|
||||
pm->cpu_hp_io_base, "\\_SB.PCI0", "\\_GPE._E02");
|
||||
}
|
||||
|
||||
if (pcms->memhp_io_base && nr_mem) {
|
||||
@@ -2547,8 +2547,7 @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine)
|
||||
|
||||
acpi_add_table(table_offsets, tables_blob);
|
||||
acpi_build_madt(tables_blob, tables->linker, x86ms,
|
||||
ACPI_DEVICE_IF(x86ms->acpi_dev), x86ms->oem_id,
|
||||
x86ms->oem_table_id);
|
||||
x86ms->oem_id, x86ms->oem_table_id);
|
||||
|
||||
#ifdef CONFIG_ACPI_ERST
|
||||
{
|
||||
|
||||
@@ -94,14 +94,13 @@ build_xrupt_override(GArray *entry, uint8_t src, uint32_t gsi, uint16_t flags)
|
||||
* 5.2.8 Multiple APIC Description Table
|
||||
*/
|
||||
void acpi_build_madt(GArray *table_data, BIOSLinker *linker,
|
||||
X86MachineState *x86ms, AcpiDeviceIf *adev,
|
||||
X86MachineState *x86ms,
|
||||
const char *oem_id, const char *oem_table_id)
|
||||
{
|
||||
int i;
|
||||
bool x2apic_mode = false;
|
||||
MachineClass *mc = MACHINE_GET_CLASS(x86ms);
|
||||
const CPUArchIdList *apic_ids = mc->possible_cpu_arch_ids(MACHINE(x86ms));
|
||||
AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_GET_CLASS(adev);
|
||||
AcpiTable table = { .sig = "APIC", .rev = 3, .oem_id = oem_id,
|
||||
.oem_table_id = oem_table_id };
|
||||
|
||||
@@ -111,7 +110,7 @@ void acpi_build_madt(GArray *table_data, BIOSLinker *linker,
|
||||
build_append_int_noprefix(table_data, 1 /* PCAT_COMPAT */, 4); /* Flags */
|
||||
|
||||
for (i = 0; i < apic_ids->len; i++) {
|
||||
adevc->madt_cpu(i, apic_ids, table_data, false);
|
||||
pc_madt_cpu_entry(i, apic_ids, table_data, false);
|
||||
if (apic_ids->cpus[i].arch_id > 254) {
|
||||
x2apic_mode = true;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#ifndef HW_I386_ACPI_COMMON_H
|
||||
#define HW_I386_ACPI_COMMON_H
|
||||
|
||||
#include "hw/acpi/acpi_dev_interface.h"
|
||||
#include "hw/acpi/bios-linker-loader.h"
|
||||
#include "hw/i386/x86.h"
|
||||
|
||||
@@ -9,7 +8,7 @@
|
||||
#define ACPI_BUILD_IOAPIC_ID 0x0
|
||||
|
||||
void acpi_build_madt(GArray *table_data, BIOSLinker *linker,
|
||||
X86MachineState *x86ms, AcpiDeviceIf *adev,
|
||||
X86MachineState *x86ms,
|
||||
const char *oem_id, const char *oem_table_id);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -214,8 +214,7 @@ static void acpi_build_microvm(AcpiBuildTables *tables,
|
||||
|
||||
acpi_add_table(table_offsets, tables_blob);
|
||||
acpi_build_madt(tables_blob, tables->linker, X86_MACHINE(machine),
|
||||
ACPI_DEVICE_IF(x86ms->acpi_dev), x86ms->oem_id,
|
||||
x86ms->oem_table_id);
|
||||
x86ms->oem_id, x86ms->oem_table_id);
|
||||
|
||||
#ifdef CONFIG_ACPI_ERST
|
||||
{
|
||||
|
||||
+2
-7
@@ -1246,13 +1246,8 @@ static int amdvi_int_remap_msi(AMDVIState *iommu,
|
||||
return -AMDVI_IR_ERR;
|
||||
}
|
||||
|
||||
if (origin->address & AMDVI_MSI_ADDR_HI_MASK) {
|
||||
trace_amdvi_err("MSI address high 32 bits non-zero when "
|
||||
"Interrupt Remapping enabled.");
|
||||
return -AMDVI_IR_ERR;
|
||||
}
|
||||
|
||||
if ((origin->address & AMDVI_MSI_ADDR_LO_MASK) != APIC_DEFAULT_ADDRESS) {
|
||||
if (origin->address < AMDVI_INT_ADDR_FIRST ||
|
||||
origin->address + sizeof(origin->data) > AMDVI_INT_ADDR_LAST + 1) {
|
||||
trace_amdvi_err("MSI is not from IOAPIC.");
|
||||
return -AMDVI_IR_ERR;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user