Merge branch 'stable-10.0' into cr16-wip

This commit is contained in:
Jonas Bewig 2025-07-30 15:14:03 +02:00
commit 86f9d26689
No known key found for this signature in database
GPG key ID: 8D99867797A4886F
64 changed files with 743 additions and 378 deletions

View file

@ -1 +1 @@
10.0.2
10.0.3

View file

@ -2556,8 +2556,7 @@ static int kvm_init(MachineState *ms)
{
MachineClass *mc = MACHINE_GET_CLASS(ms);
static const char upgrade_note[] =
"Please upgrade to at least kernel 2.6.29 or recent kvm-kmod\n"
"(see http://sourceforge.net/projects/kvm).\n";
"Please upgrade to at least kernel 4.5.\n";
const struct {
const char *name;
int num;

View file

@ -905,6 +905,14 @@ size_t AUD_read(SWVoiceIn *sw, void *buf, size_t size)
int AUD_get_buffer_size_out(SWVoiceOut *sw)
{
if (!sw) {
return 0;
}
if (audio_get_pdo_out(sw->s->dev)->mixing_engine) {
return sw->resample_buf.size * sw->info.bytes_per_frame;
}
return sw->hw->samples * sw->hw->info.bytes_per_frame;
}

View file

@ -2484,9 +2484,9 @@ static inline bool raw_check_linux_aio(BDRVRawState *s)
}
#endif
static int coroutine_fn raw_co_prw(BlockDriverState *bs, int64_t *offset_ptr,
uint64_t bytes, QEMUIOVector *qiov, int type,
int flags)
static int coroutine_fn GRAPH_RDLOCK
raw_co_prw(BlockDriverState *bs, int64_t *offset_ptr, uint64_t bytes,
QEMUIOVector *qiov, int type, int flags)
{
BDRVRawState *s = bs->opaque;
RawPosixAIOData acb;
@ -2545,7 +2545,7 @@ static int coroutine_fn raw_co_prw(BlockDriverState *bs, int64_t *offset_ptr,
ret = raw_thread_pool_submit(handle_aiocb_rw, &acb);
if (ret == 0 && (flags & BDRV_REQ_FUA)) {
/* TODO Use pwritev2() instead if it's available */
ret = raw_co_flush_to_disk(bs);
ret = bdrv_co_flush(bs);
}
goto out; /* Avoid the compiler err of unused label */
@ -2580,16 +2580,16 @@ out:
return ret;
}
static int coroutine_fn raw_co_preadv(BlockDriverState *bs, int64_t offset,
int64_t bytes, QEMUIOVector *qiov,
BdrvRequestFlags flags)
static int coroutine_fn GRAPH_RDLOCK
raw_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
QEMUIOVector *qiov, BdrvRequestFlags flags)
{
return raw_co_prw(bs, &offset, bytes, qiov, QEMU_AIO_READ, flags);
}
static int coroutine_fn raw_co_pwritev(BlockDriverState *bs, int64_t offset,
int64_t bytes, QEMUIOVector *qiov,
BdrvRequestFlags flags)
static int coroutine_fn GRAPH_RDLOCK
raw_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
QEMUIOVector *qiov, BdrvRequestFlags flags)
{
return raw_co_prw(bs, &offset, bytes, qiov, QEMU_AIO_WRITE, flags);
}
@ -3525,10 +3525,11 @@ static int coroutine_fn raw_co_zone_mgmt(BlockDriverState *bs, BlockZoneOp op,
#endif
#if defined(CONFIG_BLKZONED)
static int coroutine_fn raw_co_zone_append(BlockDriverState *bs,
int64_t *offset,
QEMUIOVector *qiov,
BdrvRequestFlags flags) {
static int coroutine_fn GRAPH_RDLOCK
raw_co_zone_append(BlockDriverState *bs,
int64_t *offset,
QEMUIOVector *qiov,
BdrvRequestFlags flags) {
assert(flags == 0);
int64_t zone_size_mask = bs->bl.zone_size - 1;
int64_t iov_len = 0;

View file

@ -325,8 +325,9 @@ static void aspeed_ram_capacity_write(void *opaque, hwaddr addr, uint64_t data,
* If writes the data to the address which is beyond the ram size,
* it would write the data to the "address % ram_size".
*/
result = address_space_write(&s->dram_as, addr % ram_size,
MEMTXATTRS_UNSPECIFIED, &data, 4);
address_space_stl_le(&s->dram_as, addr % ram_size, data,
MEMTXATTRS_UNSPECIFIED, &result);
if (result != MEMTX_OK) {
qemu_log_mask(LOG_GUEST_ERROR,
"%s: DRAM write failed, addr:0x%" HWADDR_PRIx
@ -339,9 +340,10 @@ static const MemoryRegionOps aspeed_ram_capacity_ops = {
.read = aspeed_ram_capacity_read,
.write = aspeed_ram_capacity_write,
.endianness = DEVICE_LITTLE_ENDIAN,
.impl.min_access_size = 4,
.valid = {
.min_access_size = 1,
.max_access_size = 8,
.min_access_size = 4,
.max_access_size = 4,
},
};

View file

@ -356,6 +356,10 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
qdev_get_gpio_in(cpudev, ARM_CPU_IRQ));
sysbus_connect_irq(gicsbd, i + ms->smp.cpus,
qdev_get_gpio_in(cpudev, ARM_CPU_FIQ));
sysbus_connect_irq(gicsbd, i + 2 * ms->smp.cpus,
qdev_get_gpio_in(cpudev, ARM_CPU_VIRQ));
sysbus_connect_irq(gicsbd, i + 3 * ms->smp.cpus,
qdev_get_gpio_in(cpudev, ARM_CPU_VFIQ));
}
}

View file

@ -224,7 +224,11 @@ static void mps2_common_init(MachineState *machine)
switch (mmc->fpga_type) {
case FPGA_AN385:
case FPGA_AN386:
qdev_prop_set_uint32(armv7m, "num-irq", 32);
break;
case FPGA_AN500:
/* The AN500 configures its Cortex-M7 with 16 MPU regions */
qdev_prop_set_uint32(armv7m, "mpu-ns-regions", 16);
qdev_prop_set_uint32(armv7m, "num-irq", 32);
break;
case FPGA_AN511:

View file

@ -346,6 +346,7 @@ static struct arm_boot_info npcm8xx_binfo = {
.secure_boot = false,
.board_id = -1,
.board_setup_addr = NPCM8XX_BOARD_SETUP_ADDR,
.psci_conduit = QEMU_PSCI_CONDUIT_SMC,
};
void npcm8xx_load_kernel(MachineState *machine, NPCM8xxState *soc)

View file

@ -1492,9 +1492,12 @@ static void create_virtio_iommu_dt_bindings(VirtMachineState *vms)
qemu_fdt_setprop_cell(ms->fdt, node, "phandle", vms->iommu_phandle);
g_free(node);
qemu_fdt_setprop_cells(ms->fdt, vms->pciehb_nodename, "iommu-map",
0x0, vms->iommu_phandle, 0x0, bdf,
bdf + 1, vms->iommu_phandle, bdf + 1, 0xffff - bdf);
if (!vms->default_bus_bypass_iommu) {
qemu_fdt_setprop_cells(ms->fdt, vms->pciehb_nodename, "iommu-map",
0x0, vms->iommu_phandle, 0x0, bdf,
bdf + 1, vms->iommu_phandle, bdf + 1,
0xffff - bdf);
}
}
static void create_pcie(VirtMachineState *vms)
@ -1617,8 +1620,10 @@ static void create_pcie(VirtMachineState *vms)
switch (vms->iommu) {
case VIRT_IOMMU_SMMUV3:
create_smmu(vms, vms->bus);
qemu_fdt_setprop_cells(ms->fdt, nodename, "iommu-map",
0x0, vms->iommu_phandle, 0x0, 0x10000);
if (!vms->default_bus_bypass_iommu) {
qemu_fdt_setprop_cells(ms->fdt, nodename, "iommu-map",
0x0, vms->iommu_phandle, 0x0, 0x10000);
}
break;
default:
g_assert_not_reached();

View file

@ -12,6 +12,7 @@
#include "qemu/osdep.h"
#include "qemu/timer.h"
#include "qapi/error.h"
#include "hw/sysbus.h"
#include "hw/irq.h"
#include "audio/audio.h"
@ -654,6 +655,12 @@ static void asc_realize(DeviceState *dev, Error **errp)
s->voice = AUD_open_out(&s->card, s->voice, "asc.out", s, asc_out_cb,
&as);
if (!s->voice) {
AUD_remove_card(&s->card);
error_setg(errp, "Initializing audio stream failed");
return;
}
s->shift = 1;
s->samples = AUD_get_buffer_size_out(s->voice) >> s->shift;
s->mixbuf = g_malloc0(s->samples << s->shift);

View file

@ -145,6 +145,7 @@ static void set_drive_helper(Object *obj, Visitor *v, const char *name,
if (ctx != bdrv_get_aio_context(bs)) {
error_setg(errp, "Different aio context is not supported for new "
"node");
return;
}
blk_replace_bs(blk, bs, errp);

View file

@ -970,6 +970,15 @@ void virtio_gpu_virgl_process_cmd(VirtIOGPU *g,
}
trace_virtio_gpu_fence_ctrl(cmd->cmd_hdr.fence_id, cmd->cmd_hdr.type);
#if VIRGL_VERSION_MAJOR >= 1
if (cmd->cmd_hdr.flags & VIRTIO_GPU_FLAG_INFO_RING_IDX) {
virgl_renderer_context_create_fence(cmd->cmd_hdr.ctx_id,
VIRGL_RENDERER_FENCE_FLAG_MERGEABLE,
cmd->cmd_hdr.ring_idx,
cmd->cmd_hdr.fence_id);
return;
}
#endif
virgl_renderer_create_fence(cmd->cmd_hdr.fence_id, cmd->cmd_hdr.type);
}
@ -983,6 +992,11 @@ static void virgl_write_fence(void *opaque, uint32_t fence)
* the guest can end up emitting fences out of order
* so we should check all fenced cmds not just the first one.
*/
#if VIRGL_VERSION_MAJOR >= 1
if (cmd->cmd_hdr.flags & VIRTIO_GPU_FLAG_INFO_RING_IDX) {
continue;
}
#endif
if (cmd->cmd_hdr.fence_id > fence) {
continue;
}
@ -997,6 +1011,29 @@ static void virgl_write_fence(void *opaque, uint32_t fence)
}
}
#if VIRGL_VERSION_MAJOR >= 1
static void virgl_write_context_fence(void *opaque, uint32_t ctx_id,
uint32_t ring_idx, uint64_t fence_id) {
VirtIOGPU *g = opaque;
struct virtio_gpu_ctrl_command *cmd, *tmp;
QTAILQ_FOREACH_SAFE(cmd, &g->fenceq, next, tmp) {
if (cmd->cmd_hdr.flags & VIRTIO_GPU_FLAG_INFO_RING_IDX &&
cmd->cmd_hdr.ctx_id == ctx_id && cmd->cmd_hdr.ring_idx == ring_idx &&
cmd->cmd_hdr.fence_id <= fence_id) {
trace_virtio_gpu_fence_resp(cmd->cmd_hdr.fence_id);
virtio_gpu_ctrl_response_nodata(g, cmd, VIRTIO_GPU_RESP_OK_NODATA);
QTAILQ_REMOVE(&g->fenceq, cmd, next);
g_free(cmd);
g->inflight--;
if (virtio_gpu_stats_enabled(g->parent_obj.conf)) {
trace_virtio_gpu_dec_inflight_fences(g->inflight);
}
}
}
}
#endif
static virgl_renderer_gl_context
virgl_create_context(void *opaque, int scanout_idx,
struct virgl_renderer_gl_ctx_param *params)
@ -1031,11 +1068,18 @@ static int virgl_make_context_current(void *opaque, int scanout_idx,
}
static struct virgl_renderer_callbacks virtio_gpu_3d_cbs = {
#if VIRGL_VERSION_MAJOR >= 1
.version = 3,
#else
.version = 1,
#endif
.write_fence = virgl_write_fence,
.create_gl_context = virgl_create_context,
.destroy_gl_context = virgl_destroy_context,
.make_current = virgl_make_context_current,
#if VIRGL_VERSION_MAJOR >= 1
.write_context_fence = virgl_write_context_fence,
#endif
};
static void virtio_gpu_print_stats(void *opaque)

View file

@ -140,7 +140,7 @@ static void amdvi_writeq(AMDVIState *s, hwaddr addr, uint64_t val)
{
uint64_t romask = ldq_le_p(&s->romask[addr]);
uint64_t w1cmask = ldq_le_p(&s->w1cmask[addr]);
uint32_t oldval = ldq_le_p(&s->mmior[addr]);
uint64_t oldval = ldq_le_p(&s->mmior[addr]);
stq_le_p(&s->mmior[addr],
((oldval & romask) | (val & ~romask)) & ~(val & w1cmask));
}
@ -508,7 +508,7 @@ static void amdvi_inval_inttable(AMDVIState *s, uint64_t *cmd)
static void iommu_inval_iotlb(AMDVIState *s, uint64_t *cmd)
{
uint16_t devid = extract64(cmd[0], 0, 16);
uint16_t devid = cpu_to_le16(extract64(cmd[0], 0, 16));
if (extract64(cmd[1], 1, 1) || extract64(cmd[1], 3, 1) ||
extract64(cmd[1], 6, 6)) {
amdvi_log_illegalcom_error(s, extract64(cmd[0], 60, 4),
@ -521,7 +521,7 @@ static void iommu_inval_iotlb(AMDVIState *s, uint64_t *cmd)
&devid);
} else {
amdvi_iotlb_remove_page(s, cpu_to_le64(extract64(cmd[1], 12, 52)) << 12,
cpu_to_le16(extract64(cmd[1], 0, 16)));
devid);
}
trace_amdvi_iotlb_inval();
}
@ -665,8 +665,8 @@ static inline void amdvi_handle_devtab_write(AMDVIState *s)
uint64_t val = amdvi_readq(s, AMDVI_MMIO_DEVICE_TABLE);
s->devtab = (val & AMDVI_MMIO_DEVTAB_BASE_MASK);
/* set device table length */
s->devtab_len = ((val & AMDVI_MMIO_DEVTAB_SIZE_MASK) + 1 *
/* set device table length (i.e. number of entries table can hold) */
s->devtab_len = (((val & AMDVI_MMIO_DEVTAB_SIZE_MASK) + 1) *
(AMDVI_MMIO_DEVTAB_SIZE_UNIT /
AMDVI_MMIO_DEVTAB_ENTRY_SIZE));
}
@ -848,9 +848,10 @@ static inline uint64_t amdvi_get_perms(uint64_t entry)
static bool amdvi_validate_dte(AMDVIState *s, uint16_t devid,
uint64_t *dte)
{
if ((dte[0] & AMDVI_DTE_LOWER_QUAD_RESERVED)
|| (dte[1] & AMDVI_DTE_MIDDLE_QUAD_RESERVED)
|| (dte[2] & AMDVI_DTE_UPPER_QUAD_RESERVED) || dte[3]) {
if ((dte[0] & AMDVI_DTE_QUAD0_RESERVED) ||
(dte[1] & AMDVI_DTE_QUAD1_RESERVED) ||
(dte[2] & AMDVI_DTE_QUAD2_RESERVED) ||
(dte[3] & AMDVI_DTE_QUAD3_RESERVED)) {
amdvi_log_illegaldevtab_error(s, devid,
s->devtab +
devid * AMDVI_DEVTAB_ENTRY_SIZE, 0);
@ -1426,7 +1427,6 @@ static AddressSpace *amdvi_host_dma_iommu(PCIBus *bus, void *opaque, int devfn)
AMDVIState *s = opaque;
AMDVIAddressSpace **iommu_as, *amdvi_dev_as;
int bus_num = pci_bus_num(bus);
X86IOMMUState *x86_iommu = X86_IOMMU_DEVICE(s);
iommu_as = s->address_spaces[bus_num];
@ -1486,15 +1486,8 @@ static AddressSpace *amdvi_host_dma_iommu(PCIBus *bus, void *opaque, int devfn)
AMDVI_INT_ADDR_FIRST,
&amdvi_dev_as->iommu_ir, 1);
if (!x86_iommu->pt_supported) {
memory_region_set_enabled(&amdvi_dev_as->iommu_nodma, false);
memory_region_set_enabled(MEMORY_REGION(&amdvi_dev_as->iommu),
true);
} else {
memory_region_set_enabled(MEMORY_REGION(&amdvi_dev_as->iommu),
false);
memory_region_set_enabled(&amdvi_dev_as->iommu_nodma, true);
}
memory_region_set_enabled(&amdvi_dev_as->iommu_nodma, false);
memory_region_set_enabled(MEMORY_REGION(&amdvi_dev_as->iommu), true);
}
return &iommu_as[devfn]->as;
}
@ -1657,6 +1650,14 @@ static void amdvi_sysbus_realize(DeviceState *dev, Error **errp)
exit(EXIT_FAILURE);
}
if (s->xtsup) {
if (kvm_irqchip_is_split() && !kvm_enable_x2apic()) {
error_report("AMD IOMMU xtsup=on requires x2APIC support on "
"the KVM side");
exit(EXIT_FAILURE);
}
}
pci_setup_iommu(bus, &amdvi_iommu_ops, s);
amdvi_init(s);
}

View file

@ -25,6 +25,8 @@
#include "hw/i386/x86-iommu.h"
#include "qom/object.h"
#define GENMASK64(h, l) (((~0ULL) >> (63 - (h) + (l))) << (l))
/* Capability registers */
#define AMDVI_CAPAB_BAR_LOW 0x04
#define AMDVI_CAPAB_BAR_HIGH 0x08
@ -66,34 +68,34 @@
#define AMDVI_MMIO_SIZE 0x4000
#define AMDVI_MMIO_DEVTAB_SIZE_MASK ((1ULL << 12) - 1)
#define AMDVI_MMIO_DEVTAB_BASE_MASK (((1ULL << 52) - 1) & ~ \
AMDVI_MMIO_DEVTAB_SIZE_MASK)
#define AMDVI_MMIO_DEVTAB_SIZE_MASK GENMASK64(8, 0)
#define AMDVI_MMIO_DEVTAB_BASE_MASK GENMASK64(51, 12)
#define AMDVI_MMIO_DEVTAB_ENTRY_SIZE 32
#define AMDVI_MMIO_DEVTAB_SIZE_UNIT 4096
/* some of this are similar but just for readability */
#define AMDVI_MMIO_CMDBUF_SIZE_BYTE (AMDVI_MMIO_COMMAND_BASE + 7)
#define AMDVI_MMIO_CMDBUF_SIZE_MASK 0x0f
#define AMDVI_MMIO_CMDBUF_BASE_MASK AMDVI_MMIO_DEVTAB_BASE_MASK
#define AMDVI_MMIO_CMDBUF_HEAD_MASK (((1ULL << 19) - 1) & ~0x0f)
#define AMDVI_MMIO_CMDBUF_TAIL_MASK AMDVI_MMIO_EVTLOG_HEAD_MASK
#define AMDVI_MMIO_CMDBUF_BASE_MASK GENMASK64(51, 12)
#define AMDVI_MMIO_CMDBUF_HEAD_MASK GENMASK64(18, 4)
#define AMDVI_MMIO_CMDBUF_TAIL_MASK GENMASK64(18, 4)
#define AMDVI_MMIO_EVTLOG_SIZE_BYTE (AMDVI_MMIO_EVENT_BASE + 7)
#define AMDVI_MMIO_EVTLOG_SIZE_MASK AMDVI_MMIO_CMDBUF_SIZE_MASK
#define AMDVI_MMIO_EVTLOG_BASE_MASK AMDVI_MMIO_CMDBUF_BASE_MASK
#define AMDVI_MMIO_EVTLOG_HEAD_MASK (((1ULL << 19) - 1) & ~0x0f)
#define AMDVI_MMIO_EVTLOG_TAIL_MASK AMDVI_MMIO_EVTLOG_HEAD_MASK
#define AMDVI_MMIO_EVTLOG_SIZE_MASK 0x0f
#define AMDVI_MMIO_EVTLOG_BASE_MASK GENMASK64(51, 12)
#define AMDVI_MMIO_EVTLOG_HEAD_MASK GENMASK64(18, 4)
#define AMDVI_MMIO_EVTLOG_TAIL_MASK GENMASK64(18, 4)
#define AMDVI_MMIO_PPRLOG_SIZE_BYTE (AMDVI_MMIO_EVENT_BASE + 7)
#define AMDVI_MMIO_PPRLOG_HEAD_MASK AMDVI_MMIO_EVTLOG_HEAD_MASK
#define AMDVI_MMIO_PPRLOG_TAIL_MASK AMDVI_MMIO_EVTLOG_HEAD_MASK
#define AMDVI_MMIO_PPRLOG_BASE_MASK AMDVI_MMIO_EVTLOG_BASE_MASK
#define AMDVI_MMIO_PPRLOG_SIZE_MASK AMDVI_MMIO_EVTLOG_SIZE_MASK
#define AMDVI_MMIO_PPRLOG_SIZE_BYTE (AMDVI_MMIO_PPR_BASE + 7)
#define AMDVI_MMIO_PPRLOG_SIZE_MASK 0x0f
#define AMDVI_MMIO_PPRLOG_BASE_MASK GENMASK64(51, 12)
#define AMDVI_MMIO_PPRLOG_HEAD_MASK GENMASK64(18, 4)
#define AMDVI_MMIO_PPRLOG_TAIL_MASK GENMASK64(18, 4)
#define AMDVI_MMIO_EXCL_ENABLED_MASK (1ULL << 0)
#define AMDVI_MMIO_EXCL_ALLOW_MASK (1ULL << 1)
#define AMDVI_MMIO_EXCL_LIMIT_MASK AMDVI_MMIO_DEVTAB_BASE_MASK
#define AMDVI_MMIO_EXCL_LIMIT_MASK GENMASK64(51, 12)
#define AMDVI_MMIO_EXCL_LIMIT_LOW 0xfff
/* mmio control register flags */
@ -130,14 +132,14 @@
#define AMDVI_DEV_TRANSLATION_VALID (1ULL << 1)
#define AMDVI_DEV_MODE_MASK 0x7
#define AMDVI_DEV_MODE_RSHIFT 9
#define AMDVI_DEV_PT_ROOT_MASK 0xffffffffff000
#define AMDVI_DEV_PT_ROOT_MASK GENMASK64(51, 12)
#define AMDVI_DEV_PT_ROOT_RSHIFT 12
#define AMDVI_DEV_PERM_SHIFT 61
#define AMDVI_DEV_PERM_READ (1ULL << 61)
#define AMDVI_DEV_PERM_WRITE (1ULL << 62)
/* Device table entry bits 64:127 */
#define AMDVI_DEV_DOMID_ID_MASK ((1ULL << 16) - 1)
#define AMDVI_DEV_DOMID_ID_MASK GENMASK64(15, 0)
/* Event codes and flags, as stored in the info field */
#define AMDVI_EVENT_ILLEGAL_DEVTAB_ENTRY (0x1U << 12)
@ -162,9 +164,10 @@
#define AMDVI_FEATURE_PC (1ULL << 9) /* Perf counters */
/* reserved DTE bits */
#define AMDVI_DTE_LOWER_QUAD_RESERVED 0x80300000000000fc
#define AMDVI_DTE_MIDDLE_QUAD_RESERVED 0x0000000000000100
#define AMDVI_DTE_UPPER_QUAD_RESERVED 0x08f0000000000000
#define AMDVI_DTE_QUAD0_RESERVED (GENMASK64(6, 2) | GENMASK64(63, 63))
#define AMDVI_DTE_QUAD1_RESERVED 0
#define AMDVI_DTE_QUAD2_RESERVED GENMASK64(53, 52)
#define AMDVI_DTE_QUAD3_RESERVED (GENMASK64(14, 0) | GENMASK64(53, 48))
/* AMDVI paging mode */
#define AMDVI_GATS_MODE (2ULL << 12)
@ -194,19 +197,15 @@
#define AMDVI_PAGE_SIZE (1ULL << AMDVI_PAGE_SHIFT)
#define AMDVI_PAGE_SHIFT_4K 12
#define AMDVI_PAGE_MASK_4K (~((1ULL << AMDVI_PAGE_SHIFT_4K) - 1))
#define AMDVI_PAGE_MASK_4K GENMASK64(63, 12)
#define AMDVI_MAX_VA_ADDR (48UL << 5)
#define AMDVI_MAX_PH_ADDR (40UL << 8)
#define AMDVI_MAX_GVA_ADDR (48UL << 15)
#define AMDVI_MAX_GVA_ADDR (2UL << 5)
#define AMDVI_MAX_PH_ADDR (40UL << 8)
#define AMDVI_MAX_VA_ADDR (48UL << 15)
/* Completion Wait data size */
#define AMDVI_COMPLETION_DATA_SIZE 8
#define AMDVI_COMMAND_SIZE 16
/* Completion Wait data size */
#define AMDVI_COMPLETION_DATA_SIZE 8
#define AMDVI_COMMAND_SIZE 16
#define AMDVI_INT_ADDR_FIRST 0xfee00000
@ -228,7 +227,7 @@
#define AMDVI_IR_INTCTL_PASS 1
#define AMDVI_IR_INTCTL_REMAP 2
#define AMDVI_IR_PHYS_ADDR_MASK (((1ULL << 45) - 1) << 6)
#define AMDVI_IR_PHYS_ADDR_MASK GENMASK64(51, 6)
/* MSI data 10:0 bits (section 2.2.5.1 Fig 14) */
#define AMDVI_IRTE_OFFSET 0x7ff

View file

@ -285,6 +285,8 @@ static void pc_init1(MachineState *machine, const char *pci_type)
pcms->idebus[0] = qdev_get_child_bus(dev, "ide.0");
pcms->idebus[1] = qdev_get_child_bus(dev, "ide.1");
} else {
uint32_t irq;
isa_bus = isa_bus_new(NULL, system_memory, system_io,
&error_abort);
isa_bus_register_input_irqs(isa_bus, x86ms->gsi);
@ -292,6 +294,9 @@ static void pc_init1(MachineState *machine, const char *pci_type)
x86ms->rtc = isa_new(TYPE_MC146818_RTC);
qdev_prop_set_int32(DEVICE(x86ms->rtc), "base_year", 2000);
isa_realize_and_unref(x86ms->rtc, isa_bus, &error_fatal);
irq = object_property_get_uint(OBJECT(x86ms->rtc), "irq",
&error_fatal);
isa_connect_gpio_out(ISA_DEVICE(x86ms->rtc), 0, irq);
i8257_dma_init(OBJECT(machine), isa_bus, 0);
pcms->hpet_enabled = false;

View file

@ -575,8 +575,8 @@ static void acpi_build(AcpiBuildTables *tables, MachineState *machine)
acpi_add_table(table_offsets, tables_blob);
{
AcpiMcfgInfo mcfg = {
.base = cpu_to_le64(VIRT_PCI_CFG_BASE),
.size = cpu_to_le64(VIRT_PCI_CFG_SIZE),
.base = VIRT_PCI_CFG_BASE,
.size = VIRT_PCI_CFG_SIZE,
};
build_mcfg(tables_blob, tables->linker, &mcfg, lvms->oem_id,
lvms->oem_table_id);

View file

@ -301,12 +301,6 @@ static void do_hash_operation(AspeedHACEState *s, int algo, bool sg_mode,
iov[i - 1].iov_len, false,
iov[i - 1].iov_len);
}
/*
* Set status bits to indicate completion. Testing shows hardware sets
* these irrespective of HASH_IRQ_EN.
*/
s->regs[R_STATUS] |= HASH_IRQ;
}
static uint64_t aspeed_hace_read(void *opaque, hwaddr addr, unsigned int size)
@ -390,10 +384,16 @@ static void aspeed_hace_write(void *opaque, hwaddr addr, uint64_t data,
qemu_log_mask(LOG_GUEST_ERROR,
"%s: Invalid hash algorithm selection 0x%"PRIx64"\n",
__func__, data & ahc->hash_mask);
break;
} else {
do_hash_operation(s, algo, data & HASH_SG_EN,
((data & HASH_HMAC_MASK) == HASH_DIGEST_ACCUM));
}
do_hash_operation(s, algo, data & HASH_SG_EN,
((data & HASH_HMAC_MASK) == HASH_DIGEST_ACCUM));
/*
* Set status bits to indicate completion. Testing shows hardware sets
* these irrespective of HASH_IRQ_EN.
*/
s->regs[R_STATUS] |= HASH_IRQ;
if (data & HASH_IRQ_EN) {
qemu_irq_raise(s->irq);

View file

@ -615,6 +615,7 @@ static void gmac_try_send_next_packet(NPCMGMACState *gmac)
trace_npcm_gmac_packet_sent(DEVICE(gmac)->canonical_path, length);
buf = tx_send_buffer;
length = 0;
prev_buf_size = 0;
}
/* step 6 */

View file

@ -3021,11 +3021,10 @@ static void virtio_net_del_queue(VirtIONet *n, int index)
virtio_del_queue(vdev, index * 2 + 1);
}
static void virtio_net_change_num_queue_pairs(VirtIONet *n, int new_max_queue_pairs)
static void virtio_net_change_num_queues(VirtIONet *n, int new_num_queues)
{
VirtIODevice *vdev = VIRTIO_DEVICE(n);
int old_num_queues = virtio_get_num_queues(vdev);
int new_num_queues = new_max_queue_pairs * 2 + 1;
int i;
assert(old_num_queues >= 3);
@ -3061,16 +3060,14 @@ static void virtio_net_set_multiqueue(VirtIONet *n, int multiqueue)
int max = multiqueue ? n->max_queue_pairs : 1;
n->multiqueue = multiqueue;
virtio_net_change_num_queue_pairs(n, max);
virtio_net_change_num_queues(n, max * 2 + 1);
virtio_net_set_queue_pairs(n);
}
static int virtio_net_pre_load_queues(VirtIODevice *vdev)
static int virtio_net_pre_load_queues(VirtIODevice *vdev, uint32_t n)
{
virtio_net_set_multiqueue(VIRTIO_NET(vdev),
virtio_has_feature(vdev->guest_features, VIRTIO_NET_F_RSS) ||
virtio_has_feature(vdev->guest_features, VIRTIO_NET_F_MQ));
virtio_net_change_num_queues(VIRTIO_NET(vdev), n);
return 0;
}

View file

@ -1719,7 +1719,7 @@ static void pci_update_mappings(PCIDevice *d)
pci_update_vga(d);
}
static inline int pci_irq_disabled(PCIDevice *d)
int pci_irq_disabled(PCIDevice *d)
{
return pci_get_word(d->config + PCI_COMMAND) & PCI_COMMAND_INTX_DISABLE;
}

View file

@ -57,7 +57,7 @@ static void ccw_device_set_loadparm(Object *obj, Visitor *v,
Error **errp)
{
CcwDevice *dev = CCW_DEVICE(obj);
char *val;
g_autofree char *val = NULL;
int index;
index = object_property_get_int(obj, "bootindex", NULL);

View file

@ -47,12 +47,6 @@ static struct vhost_log *vhost_log[VHOST_BACKEND_TYPE_MAX];
static struct vhost_log *vhost_log_shm[VHOST_BACKEND_TYPE_MAX];
static QLIST_HEAD(, vhost_dev) vhost_log_devs[VHOST_BACKEND_TYPE_MAX];
/* Memslots used by backends that support private memslots (without an fd). */
static unsigned int used_memslots;
/* Memslots used by backends that only support shared memslots (with an fd). */
static unsigned int used_shared_memslots;
static QLIST_HEAD(, vhost_dev) vhost_devices =
QLIST_HEAD_INITIALIZER(vhost_devices);
@ -74,15 +68,15 @@ unsigned int vhost_get_free_memslots(void)
QLIST_FOREACH(hdev, &vhost_devices, entry) {
unsigned int r = hdev->vhost_ops->vhost_backend_memslots_limit(hdev);
unsigned int cur_free;
unsigned int cur_free = r - hdev->mem->nregions;
if (hdev->vhost_ops->vhost_backend_no_private_memslots &&
hdev->vhost_ops->vhost_backend_no_private_memslots(hdev)) {
cur_free = r - used_shared_memslots;
if (unlikely(r < hdev->mem->nregions)) {
warn_report_once("used (%u) vhost backend memory slots exceed"
" the device limit (%u).", hdev->mem->nregions, r);
free = 0;
} else {
cur_free = r - used_memslots;
free = MIN(free, cur_free);
}
free = MIN(free, cur_free);
}
return free;
}
@ -666,13 +660,6 @@ static void vhost_commit(MemoryListener *listener)
dev->mem = g_realloc(dev->mem, regions_size);
dev->mem->nregions = dev->n_mem_sections;
if (dev->vhost_ops->vhost_backend_no_private_memslots &&
dev->vhost_ops->vhost_backend_no_private_memslots(dev)) {
used_shared_memslots = dev->mem->nregions;
} else {
used_memslots = dev->mem->nregions;
}
for (i = 0; i < dev->n_mem_sections; i++) {
struct vhost_memory_region *cur_vmr = dev->mem->regions + i;
struct MemoryRegionSection *mrs = dev->mem_sections + i;
@ -1619,15 +1606,11 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
QLIST_INSERT_HEAD(&vhost_devices, hdev, entry);
/*
* The listener we registered properly updated the corresponding counter.
* So we can trust that these values are accurate.
* The listener we registered properly setup the number of required
* memslots in vhost_commit().
*/
if (hdev->vhost_ops->vhost_backend_no_private_memslots &&
hdev->vhost_ops->vhost_backend_no_private_memslots(hdev)) {
used = used_shared_memslots;
} else {
used = used_memslots;
}
used = hdev->mem->nregions;
/*
* We assume that all reserved memslots actually require a real memslot
* in our vhost backend. This might not be true, for example, if the

View file

@ -1215,7 +1215,12 @@ static int virtio_pci_set_guest_notifier(DeviceState *d, int n, bool assign,
static bool virtio_pci_query_guest_notifiers(DeviceState *d)
{
VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d);
return msix_enabled(&proxy->pci_dev);
if (msix_enabled(&proxy->pci_dev)) {
return true;
} else {
return pci_irq_disabled(&proxy->pci_dev);
}
}
static int virtio_pci_set_guest_notifiers(DeviceState *d, int nvqs, bool assign)

View file

@ -3257,13 +3257,6 @@ virtio_load(VirtIODevice *vdev, QEMUFile *f, int version_id)
config_len--;
}
if (vdc->pre_load_queues) {
ret = vdc->pre_load_queues(vdev);
if (ret) {
return ret;
}
}
num = qemu_get_be32(f);
if (num > VIRTIO_QUEUE_MAX) {
@ -3271,6 +3264,13 @@ virtio_load(VirtIODevice *vdev, QEMUFile *f, int version_id)
return -1;
}
if (vdc->pre_load_queues) {
ret = vdc->pre_load_queues(vdev, num);
if (ret) {
return ret;
}
}
for (i = 0; i < num; i++) {
vdev->vq[i].vring.num = qemu_get_be32(f);
if (k->has_variable_vring_alignment) {

View file

@ -668,6 +668,7 @@ void lsi53c8xx_handle_legacy_cmdline(DeviceState *lsi_dev);
qemu_irq pci_allocate_irq(PCIDevice *pci_dev);
void pci_set_irq(PCIDevice *pci_dev, int level);
int pci_irq_disabled(PCIDevice *d);
static inline void pci_irq_assert(PCIDevice *pci_dev)
{

View file

@ -210,8 +210,14 @@ struct VirtioDeviceClass {
void (*guest_notifier_mask)(VirtIODevice *vdev, int n, bool mask);
int (*start_ioeventfd)(VirtIODevice *vdev);
void (*stop_ioeventfd)(VirtIODevice *vdev);
/* Called before loading queues. Useful to add queues before loading. */
int (*pre_load_queues)(VirtIODevice *vdev);
/*
* Called before loading queues.
* If the number of queues change at runtime, use @n to know the
* number and add or remove queues accordingly.
* Note that this function is called in the middle of loading vmsd;
* no assumption should be made on states being loaded from vmsd.
*/
int (*pre_load_queues)(VirtIODevice *vdev, uint32_t n);
/* Saving and loading of a device; trying to deprecate save/load
* use vmsd for new devices.
*/

View file

@ -224,4 +224,6 @@ int gd_gl_area_make_current(DisplayGLCtx *dgc,
/* gtk-clipboard.c */
void gd_clipboard_init(GtkDisplayState *gd);
void gd_update_scale(VirtualConsole *vc, int ww, int wh, int fbw, int fbh);
#endif /* UI_GTK_H */

View file

@ -75,12 +75,12 @@ PixelFormat qemu_pixelformat_from_pixman(pixman_format_code_t format);
pixman_format_code_t qemu_default_pixman_format(int bpp, bool native_endian);
pixman_format_code_t qemu_drm_format_to_pixman(uint32_t drm_format);
uint32_t qemu_pixman_to_drm_format(pixman_format_code_t pixman);
int qemu_pixman_get_type(int rshift, int gshift, int bshift);
int qemu_pixman_get_type(int rshift, int gshift, int bshift, int endian);
bool qemu_pixman_check_format(DisplayChangeListener *dcl,
pixman_format_code_t format);
#ifdef CONFIG_PIXMAN
pixman_format_code_t qemu_pixman_get_format(PixelFormat *pf);
pixman_format_code_t qemu_pixman_get_format(PixelFormat *pf, int endian);
pixman_image_t *qemu_pixman_linebuf_create(pixman_format_code_t format,
int width);
void qemu_pixman_linebuf_fill(pixman_image_t *linebuf, pixman_image_t *fb,

View file

@ -362,6 +362,7 @@ void cpu_loop(CPUARMState *env)
switch (n) {
case ARM_NR_cacheflush:
/* nop */
env->regs[0] = 0;
break;
case ARM_NR_set_tls:
cpu_set_tls(env, env->regs[0]);

View file

@ -36,6 +36,16 @@ static inline void fd_trans_init(void)
qemu_mutex_init(&target_fd_trans_lock);
}
static inline void fd_trans_prefork(void)
{
qemu_mutex_lock(&target_fd_trans_lock);
}
static inline void fd_trans_postfork(void)
{
qemu_mutex_unlock(&target_fd_trans_lock);
}
static inline TargetFdDataFunc fd_trans_target_to_host_data(int fd)
{
if (fd < 0) {

View file

@ -149,12 +149,14 @@ void fork_start(void)
cpu_list_lock();
qemu_plugin_user_prefork_lock();
gdbserver_fork_start();
fd_trans_prefork();
}
void fork_end(pid_t pid)
{
bool child = pid == 0;
fd_trans_postfork();
qemu_plugin_user_postfork(child);
mmap_fork_end(child);
if (child) {

View file

@ -789,6 +789,10 @@ safe_syscall6(ssize_t, copy_file_range, int, infd, loff_t *, pinoff,
int, outfd, loff_t *, poutoff, size_t, length,
unsigned int, flags)
#endif
#if defined(TARGET_NR_fchmodat2) && defined(__NR_fchmodat2)
safe_syscall4(int, fchmodat2, int, dfd, const char *, filename,
unsigned short, mode, unsigned int, flags)
#endif
/* We do ioctl like this rather than via safe_syscall3 to preserve the
* "third argument might be integer or pointer or not present" behaviour of
@ -6742,10 +6746,9 @@ static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp,
int pid_child = ret;
pid_fd = pidfd_open(pid_child, 0);
if (pid_fd >= 0) {
fcntl(pid_fd, F_SETFD, fcntl(pid_fd, F_GETFL)
| FD_CLOEXEC);
qemu_set_cloexec(pid_fd);
} else {
pid_fd = 0;
pid_fd = 0;
}
#endif
put_user_u32(pid_fd, parent_tidptr);
@ -10709,6 +10712,15 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
ret = get_errno(fchmodat(arg1, p, arg3, 0));
unlock_user(p, arg2, 0);
return ret;
#endif
#if defined(TARGET_NR_fchmodat2) && defined(__NR_fchmodat2)
case TARGET_NR_fchmodat2:
if (!(p = lock_user_string(arg2))) {
return -TARGET_EFAULT;
}
ret = get_errno(safe_fchmodat2(arg1, p, arg3, arg4));
unlock_user(p, arg2, 0);
return ret;
#endif
case TARGET_NR_getpriority:
/* Note that negative values are valid for getpriority, so we must
@ -11626,10 +11638,14 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
case TARGET_NR_nanosleep:
{
struct timespec req, rem;
target_to_host_timespec(&req, arg1);
if (target_to_host_timespec(&req, arg1)) {
return -TARGET_EFAULT;
}
ret = get_errno(safe_nanosleep(&req, &rem));
if (is_error(ret) && arg2) {
host_to_target_timespec(arg2, &rem);
if (host_to_target_timespec(arg2, &rem)) {
return -TARGET_EFAULT;
}
}
}
return ret;

View file

@ -3598,7 +3598,9 @@ static int ram_load_cleanup(void *opaque)
RAMBlock *rb;
RAMBLOCK_FOREACH_NOT_IGNORED(rb) {
qemu_ram_block_writeback(rb);
if (memory_region_is_nonvolatile(rb->mr)) {
qemu_ram_block_writeback(rb);
}
}
xbzrle_load_cleanup();

View file

@ -323,7 +323,7 @@ static int af_xdp_umem_create(AFXDPState *s, int sock_fd, Error **errp)
s->pool = g_new(uint64_t, n_descs);
/* Fill the pool in the opposite order, because it's a LIFO queue. */
for (i = n_descs; i >= 0; i--) {
for (i = n_descs - 1; i >= 0; i--) {
s->pool[i] = i * XSK_UMEM__DEFAULT_FRAME_SIZE;
}
s->n_pool = n_descs;

0
pc-bios/hppa-firmware.img Executable file → Normal file
View file

0
pc-bios/hppa-firmware64.img Executable file → Normal file
View file

View file

@ -4936,13 +4936,13 @@ SRST
with actual performance.
When the virtual cpu is sleeping, the virtual time will advance at
default speed unless ``sleep=on`` is specified. With
``sleep=on``, the virtual time will jump to the next timer
default speed unless ``sleep=off`` is specified. With
``sleep=off``, the virtual time will jump to the next timer
deadline instantly whenever the virtual cpu goes to sleep mode and
will not advance if no timer is enabled. This behavior gives
deterministic execution times from the guest point of view.
The default if icount is enabled is ``sleep=off``.
``sleep=on`` cannot be used together with either ``shift=auto``
The default if icount is enabled is ``sleep=on``.
``sleep=off`` cannot be used together with either ``shift=auto``
or ``align=on``.
``align=on`` will activate the delay algorithm which will try to

View file

@ -986,11 +986,20 @@ static const ARMCPRegInfo debug_cp_reginfo[] = {
.opc0 = 2, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 2,
.access = PL1_RW, .accessfn = access_tdcc,
.type = ARM_CP_CONST, .resetvalue = 0 },
/* DBGDTRTX_EL0/DBGDTRRX_EL0 depend on direction */
{ .name = "DBGDTR_EL0", .state = ARM_CP_STATE_BOTH, .cp = 14,
/* Architecturally DBGDTRTX is named DBGDTRRX when used for reads */
{ .name = "DBGDTRTX_EL0", .state = ARM_CP_STATE_AA64,
.opc0 = 2, .opc1 = 3, .crn = 0, .crm = 5, .opc2 = 0,
.access = PL0_RW, .accessfn = access_tdcc,
.type = ARM_CP_CONST, .resetvalue = 0 },
{ .name = "DBGDTRTX", .state = ARM_CP_STATE_AA32, .cp = 14,
.opc1 = 0, .crn = 0, .crm = 5, .opc2 = 0,
.access = PL0_RW, .accessfn = access_tdcc,
.type = ARM_CP_CONST, .resetvalue = 0 },
/* This is AArch64-only and is a combination of DBGDTRTX and DBGDTRRX */
{ .name = "DBGDTR_EL0", .state = ARM_CP_STATE_AA64,
.opc0 = 2, .opc1 = 3, .crn = 0, .crm = 4, .opc2 = 0,
.access = PL0_RW, .accessfn = access_tdcc,
.type = ARM_CP_CONST, .resetvalue = 0 },
/*
* OSECCR_EL1 provides a mechanism for an operating system
* to access the contents of EDECCR. EDECCR is not implemented though,

View file

@ -878,7 +878,7 @@ static bool hvf_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
hv_vcpu_exit_t *exit;
int i;
ahcf->dtb_compatible = "arm,arm-v8";
ahcf->dtb_compatible = "arm,armv8";
ahcf->features = (1ULL << ARM_FEATURE_V8) |
(1ULL << ARM_FEATURE_NEON) |
(1ULL << ARM_FEATURE_AARCH64) |
@ -1352,6 +1352,7 @@ static int hvf_sysreg_read(CPUState *cpu, uint32_t reg, uint64_t *val)
case SYSREG_ICC_IGRPEN0_EL1:
case SYSREG_ICC_IGRPEN1_EL1:
case SYSREG_ICC_PMR_EL1:
case SYSREG_ICC_RPR_EL1:
case SYSREG_ICC_SGI0R_EL1:
case SYSREG_ICC_SGI1R_EL1:
case SYSREG_ICC_SRE_EL1:
@ -1666,6 +1667,7 @@ static int hvf_sysreg_write(CPUState *cpu, uint32_t reg, uint64_t val)
case SYSREG_ICC_IGRPEN0_EL1:
case SYSREG_ICC_IGRPEN1_EL1:
case SYSREG_ICC_PMR_EL1:
case SYSREG_ICC_RPR_EL1:
case SYSREG_ICC_SGI0R_EL1:
case SYSREG_ICC_SGI1R_EL1:
case SYSREG_ICC_SRE_EL1:

View file

@ -305,7 +305,7 @@ static bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
}
ahcf->target = init.target;
ahcf->dtb_compatible = "arm,arm-v8";
ahcf->dtb_compatible = "arm,armv8";
err = read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64pfr0,
ARM64_SYS_REG(3, 0, 0, 4, 0));

View file

@ -653,15 +653,6 @@ void HELPER(exception_return)(CPUARMState *env, uint64_t new_pc)
spsr &= ~PSTATE_SS;
}
/*
* FEAT_RME forbids return from EL3 with an invalid security state.
* We don't need an explicit check for FEAT_RME here because we enforce
* in scr_write() that you can't set the NSE bit without it.
*/
if (cur_el == 3 && (env->cp15.scr_el3 & (SCR_NS | SCR_NSE)) == SCR_NSE) {
goto illegal_return;
}
new_el = el_from_spsr(spsr);
if (new_el == -1) {
goto illegal_return;
@ -673,6 +664,17 @@ void HELPER(exception_return)(CPUARMState *env, uint64_t new_pc)
goto illegal_return;
}
/*
* FEAT_RME forbids return from EL3 to a lower exception level
* with an invalid security state.
* We don't need an explicit check for FEAT_RME here because we enforce
* in scr_write() that you can't set the NSE bit without it.
*/
if (cur_el == 3 && new_el < 3 &&
(env->cp15.scr_el3 & (SCR_NS | SCR_NSE)) == SCR_NSE) {
goto illegal_return;
}
if (new_el != 0 && arm_el_is_aa64(env, new_el) != return_to_aa64) {
/* Return to an EL which is configured for a different register width */
goto illegal_return;

View file

@ -1005,25 +1005,55 @@ static float32 f16_dotadd(float32 sum, uint32_t e1, uint32_t e2,
* - we have pre-set-up copy of s_std which is set to round-to-odd,
* for the multiply (see below)
*/
float64 e1r = float16_to_float64(e1 & 0xffff, true, s_f16);
float64 e1c = float16_to_float64(e1 >> 16, true, s_f16);
float64 e2r = float16_to_float64(e2 & 0xffff, true, s_f16);
float64 e2c = float16_to_float64(e2 >> 16, true, s_f16);
float64 t64;
float16 h1r = e1 & 0xffff;
float16 h1c = e1 >> 16;
float16 h2r = e2 & 0xffff;
float16 h2c = e2 >> 16;
float32 t32;
/*
* The ARM pseudocode function FPDot performs both multiplies
* and the add with a single rounding operation. Emulate this
* by performing the first multiply in round-to-odd, then doing
* the second multiply as fused multiply-add, and rounding to
* float32 all in one step.
*/
t64 = float64_mul(e1r, e2r, s_odd);
t64 = float64r32_muladd(e1c, e2c, t64, 0, s_std);
/* C.f. FPProcessNaNs4 */
if (float16_is_any_nan(h1r) || float16_is_any_nan(h1c) ||
float16_is_any_nan(h2r) || float16_is_any_nan(h2c)) {
float16 t16;
/* This conversion is exact, because we've already rounded. */
t32 = float64_to_float32(t64, s_std);
if (float16_is_signaling_nan(h1r, s_f16)) {
t16 = h1r;
} else if (float16_is_signaling_nan(h1c, s_f16)) {
t16 = h1c;
} else if (float16_is_signaling_nan(h2r, s_f16)) {
t16 = h2r;
} else if (float16_is_signaling_nan(h2c, s_f16)) {
t16 = h2c;
} else if (float16_is_any_nan(h1r)) {
t16 = h1r;
} else if (float16_is_any_nan(h1c)) {
t16 = h1c;
} else if (float16_is_any_nan(h2r)) {
t16 = h2r;
} else {
t16 = h2c;
}
t32 = float16_to_float32(t16, true, s_f16);
} else {
float64 e1r = float16_to_float64(h1r, true, s_f16);
float64 e1c = float16_to_float64(h1c, true, s_f16);
float64 e2r = float16_to_float64(h2r, true, s_f16);
float64 e2c = float16_to_float64(h2c, true, s_f16);
float64 t64;
/*
* The ARM pseudocode function FPDot performs both multiplies
* and the add with a single rounding operation. Emulate this
* by performing the first multiply in round-to-odd, then doing
* the second multiply as fused multiply-add, and rounding to
* float32 all in one step.
*/
t64 = float64_mul(e1r, e2r, s_odd);
t64 = float64r32_muladd(e1c, e2c, t64, 0, s_std);
/* This conversion is exact, because we've already rounded. */
t32 = float64_to_float32(t64, s_std);
}
/* The final accumulation step is not fused. */
return float32_add(sum, t32, s_std);

View file

@ -1392,11 +1392,8 @@ static bool fp_access_check_only(DisasContext *s)
return true;
}
static bool fp_access_check(DisasContext *s)
static bool nonstreaming_check(DisasContext *s)
{
if (!fp_access_check_only(s)) {
return false;
}
if (s->sme_trap_nonstreaming && s->is_nonstreaming) {
gen_exception_insn(s, 0, EXCP_UDEF,
syn_smetrap(SME_ET_Streaming, false));
@ -1405,6 +1402,11 @@ static bool fp_access_check(DisasContext *s)
return true;
}
static bool fp_access_check(DisasContext *s)
{
return fp_access_check_only(s) && nonstreaming_check(s);
}
/*
* Return <0 for non-supported element sizes, with MO_16 controlled by
* FEAT_FP16; return 0 for fp disabled; otherwise return >0 for success.
@ -1455,14 +1457,24 @@ static int fp_access_check_vector_hsd(DisasContext *s, bool is_q, MemOp esz)
*/
bool sve_access_check(DisasContext *s)
{
if (s->pstate_sm || !dc_isar_feature(aa64_sve, s)) {
if (dc_isar_feature(aa64_sme, s)) {
bool ret;
assert(dc_isar_feature(aa64_sme, s));
ret = sme_sm_enabled_check(s);
if (s->pstate_sm) {
ret = sme_enabled_check(s);
} else if (dc_isar_feature(aa64_sve, s)) {
goto continue_sve;
} else {
ret = sme_sm_enabled_check(s);
}
if (ret) {
ret = nonstreaming_check(s);
}
s->sve_access_checked = (ret ? 1 : -1);
return ret;
}
continue_sve:
if (s->sve_excp_el) {
/* Assert that we only raise one exception per instruction. */
assert(!s->sve_access_checked);
@ -1499,7 +1511,8 @@ bool sme_enabled_check(DisasContext *s)
* to be zero when fp_excp_el has priority. This is because we need
* sme_excp_el by itself for cpregs access checks.
*/
if (!s->fp_excp_el || s->sme_excp_el < s->fp_excp_el) {
if (s->sme_excp_el
&& (!s->fp_excp_el || s->sme_excp_el <= s->fp_excp_el)) {
bool ret = sme_access_check(s);
s->fp_access_checked = (ret ? 1 : -1);
return ret;
@ -1821,6 +1834,10 @@ static bool trans_RETA(DisasContext *s, arg_reta *a)
{
TCGv_i64 dst;
if (!dc_isar_feature(aa64_pauth, s)) {
return false;
}
dst = auth_branch_target(s, cpu_reg(s, 30), cpu_X[31], !a->m);
gen_a64_set_pc(s, dst);
s->base.is_jmp = DISAS_JUMP;

View file

@ -2352,6 +2352,23 @@ TRANS_FEAT(PUNPKHI, aa64_sve, do_perm_pred2, a, 1, gen_helper_sve_punpk_p)
*** SVE Permute - Interleaving Group
*/
static bool do_interleave_q(DisasContext *s, gen_helper_gvec_3 *fn,
arg_rrr_esz *a, int data)
{
if (sve_access_check(s)) {
unsigned vsz = vec_full_reg_size(s);
if (vsz < 32) {
unallocated_encoding(s);
} else {
tcg_gen_gvec_3_ool(vec_full_reg_offset(s, a->rd),
vec_full_reg_offset(s, a->rn),
vec_full_reg_offset(s, a->rm),
vsz, vsz, data, fn);
}
}
return true;
}
static gen_helper_gvec_3 * const zip_fns[4] = {
gen_helper_sve_zip_b, gen_helper_sve_zip_h,
gen_helper_sve_zip_s, gen_helper_sve_zip_d,
@ -2361,11 +2378,11 @@ TRANS_FEAT(ZIP1_z, aa64_sve, gen_gvec_ool_arg_zzz,
TRANS_FEAT(ZIP2_z, aa64_sve, gen_gvec_ool_arg_zzz,
zip_fns[a->esz], a, vec_full_reg_size(s) / 2)
TRANS_FEAT(ZIP1_q, aa64_sve_f64mm, gen_gvec_ool_arg_zzz,
gen_helper_sve2_zip_q, a, 0)
TRANS_FEAT(ZIP2_q, aa64_sve_f64mm, gen_gvec_ool_arg_zzz,
gen_helper_sve2_zip_q, a,
QEMU_ALIGN_DOWN(vec_full_reg_size(s), 32) / 2)
TRANS_FEAT_NONSTREAMING(ZIP1_q, aa64_sve_f64mm, do_interleave_q,
gen_helper_sve2_zip_q, a, 0)
TRANS_FEAT_NONSTREAMING(ZIP2_q, aa64_sve_f64mm, do_interleave_q,
gen_helper_sve2_zip_q, a,
QEMU_ALIGN_DOWN(vec_full_reg_size(s), 32) / 2)
static gen_helper_gvec_3 * const uzp_fns[4] = {
gen_helper_sve_uzp_b, gen_helper_sve_uzp_h,
@ -2377,10 +2394,10 @@ TRANS_FEAT(UZP1_z, aa64_sve, gen_gvec_ool_arg_zzz,
TRANS_FEAT(UZP2_z, aa64_sve, gen_gvec_ool_arg_zzz,
uzp_fns[a->esz], a, 1 << a->esz)
TRANS_FEAT(UZP1_q, aa64_sve_f64mm, gen_gvec_ool_arg_zzz,
gen_helper_sve2_uzp_q, a, 0)
TRANS_FEAT(UZP2_q, aa64_sve_f64mm, gen_gvec_ool_arg_zzz,
gen_helper_sve2_uzp_q, a, 16)
TRANS_FEAT_NONSTREAMING(UZP1_q, aa64_sve_f64mm, do_interleave_q,
gen_helper_sve2_uzp_q, a, 0)
TRANS_FEAT_NONSTREAMING(UZP2_q, aa64_sve_f64mm, do_interleave_q,
gen_helper_sve2_uzp_q, a, 16)
static gen_helper_gvec_3 * const trn_fns[4] = {
gen_helper_sve_trn_b, gen_helper_sve_trn_h,
@ -2392,10 +2409,10 @@ TRANS_FEAT(TRN1_z, aa64_sve, gen_gvec_ool_arg_zzz,
TRANS_FEAT(TRN2_z, aa64_sve, gen_gvec_ool_arg_zzz,
trn_fns[a->esz], a, 1 << a->esz)
TRANS_FEAT(TRN1_q, aa64_sve_f64mm, gen_gvec_ool_arg_zzz,
gen_helper_sve2_trn_q, a, 0)
TRANS_FEAT(TRN2_q, aa64_sve_f64mm, gen_gvec_ool_arg_zzz,
gen_helper_sve2_trn_q, a, 16)
TRANS_FEAT_NONSTREAMING(TRN1_q, aa64_sve_f64mm, do_interleave_q,
gen_helper_sve2_trn_q, a, 0)
TRANS_FEAT_NONSTREAMING(TRN2_q, aa64_sve_f64mm, do_interleave_q,
gen_helper_sve2_trn_q, a, 16)
/*
*** SVE Permute Vector - Predicated Group
@ -7265,6 +7282,7 @@ static bool trans_PSEL(DisasContext *s, arg_psel *a)
tcg_gen_neg_i64(tmp, tmp);
/* Apply to either copy the source, or write zeros. */
pl = size_for_gvec(pl);
tcg_gen_gvec_ands(MO_64, pred_full_reg_offset(s, a->pd),
pred_full_reg_offset(s, a->pn), tmp, pl, pl);
return true;

View file

@ -2989,31 +2989,62 @@ float32 bfdotadd(float32 sum, uint32_t e1, uint32_t e2, float_status *fpst)
float32 bfdotadd_ebf(float32 sum, uint32_t e1, uint32_t e2,
float_status *fpst, float_status *fpst_odd)
{
/*
* Compare f16_dotadd() in sme_helper.c, but here we have
* bfloat16 inputs. In particular that means that we do not
* want the FPCR.FZ16 flush semantics, so we use the normal
* float_status for the input handling here.
*/
float64 e1r = float32_to_float64(e1 << 16, fpst);
float64 e1c = float32_to_float64(e1 & 0xffff0000u, fpst);
float64 e2r = float32_to_float64(e2 << 16, fpst);
float64 e2c = float32_to_float64(e2 & 0xffff0000u, fpst);
float64 t64;
float32 s1r = e1 << 16;
float32 s1c = e1 & 0xffff0000u;
float32 s2r = e2 << 16;
float32 s2c = e2 & 0xffff0000u;
float32 t32;
/*
* The ARM pseudocode function FPDot performs both multiplies
* and the add with a single rounding operation. Emulate this
* by performing the first multiply in round-to-odd, then doing
* the second multiply as fused multiply-add, and rounding to
* float32 all in one step.
*/
t64 = float64_mul(e1r, e2r, fpst_odd);
t64 = float64r32_muladd(e1c, e2c, t64, 0, fpst);
/* C.f. FPProcessNaNs4 */
if (float32_is_any_nan(s1r) || float32_is_any_nan(s1c) ||
float32_is_any_nan(s2r) || float32_is_any_nan(s2c)) {
if (float32_is_signaling_nan(s1r, fpst)) {
t32 = s1r;
} else if (float32_is_signaling_nan(s1c, fpst)) {
t32 = s1c;
} else if (float32_is_signaling_nan(s2r, fpst)) {
t32 = s2r;
} else if (float32_is_signaling_nan(s2c, fpst)) {
t32 = s2c;
} else if (float32_is_any_nan(s1r)) {
t32 = s1r;
} else if (float32_is_any_nan(s1c)) {
t32 = s1c;
} else if (float32_is_any_nan(s2r)) {
t32 = s2r;
} else {
t32 = s2c;
}
/*
* FPConvertNaN(FPProcessNaN(t32)) will be done as part
* of the final addition below.
*/
} else {
/*
* Compare f16_dotadd() in sme_helper.c, but here we have
* bfloat16 inputs. In particular that means that we do not
* want the FPCR.FZ16 flush semantics, so we use the normal
* float_status for the input handling here.
*/
float64 e1r = float32_to_float64(s1r, fpst);
float64 e1c = float32_to_float64(s1c, fpst);
float64 e2r = float32_to_float64(s2r, fpst);
float64 e2c = float32_to_float64(s2c, fpst);
float64 t64;
/* This conversion is exact, because we've already rounded. */
t32 = float64_to_float32(t64, fpst);
/*
* The ARM pseudocode function FPDot performs both multiplies
* and the add with a single rounding operation. Emulate this
* by performing the first multiply in round-to-odd, then doing
* the second multiply as fused multiply-add, and rounding to
* float32 all in one step.
*/
t64 = float64_mul(e1r, e2r, fpst_odd);
t64 = float64r32_muladd(e1c, e2c, t64, 0, fpst);
/* This conversion is exact, because we've already rounded. */
t32 = float64_to_float32(t64, fpst);
}
/* The final accumulation step is not fused. */
return float32_add(sum, t32, fpst);

View file

@ -283,11 +283,17 @@ static void encode_cache_cpuid4(CPUCacheInfo *cache,
assert(cache->size == cache->line_size * cache->associativity *
cache->partitions * cache->sets);
/*
* The following fields have bit-width limitations, so consider the
* maximum values to avoid overflow:
* Bits 25-14: maximum 4095.
* Bits 31-26: maximum 63.
*/
*eax = CACHE_TYPE(cache->type) |
CACHE_LEVEL(cache->level) |
(cache->self_init ? CACHE_SELF_INIT_LEVEL : 0) |
(max_core_ids_in_package(topo_info) << 26) |
(max_thread_ids_for_cache(topo_info, cache->share_level) << 14);
(MIN(max_core_ids_in_package(topo_info), 63) << 26) |
(MIN(max_thread_ids_for_cache(topo_info, cache->share_level), 4095) << 14);
assert(cache->line_size > 0);
assert(cache->partitions > 0);
@ -490,7 +496,8 @@ static void encode_cache_cpuid8000001d(CPUCacheInfo *cache,
*eax = CACHE_TYPE(cache->type) | CACHE_LEVEL(cache->level) |
(cache->self_init ? CACHE_SELF_INIT_LEVEL : 0);
*eax |= max_thread_ids_for_cache(topo_info, cache->share_level) << 14;
/* Bits 25:14 - NumSharingCache: maximum 4095. */
*eax |= MIN(max_thread_ids_for_cache(topo_info, cache->share_level), 4095) << 14;
assert(cache->line_size > 0);
assert(cache->partitions > 0);
@ -1774,10 +1781,6 @@ static FeatureDep feature_dependencies[] = {
.from = { FEAT_7_1_EAX, CPUID_7_1_EAX_LKGS },
.to = { FEAT_7_1_EAX, CPUID_7_1_EAX_FRED },
},
{
.from = { FEAT_7_1_EAX, CPUID_7_1_EAX_WRMSRNS },
.to = { FEAT_7_1_EAX, CPUID_7_1_EAX_FRED },
},
{
.from = { FEAT_7_0_EBX, CPUID_7_0_EBX_SGX },
.to = { FEAT_7_0_ECX, CPUID_7_0_ECX_SGX_LC },
@ -6832,7 +6835,8 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
}
*edx = env->features[FEAT_1_EDX];
if (threads_per_pkg > 1) {
*ebx |= threads_per_pkg << 16;
/* Fixup overflow: max value for bits 23-16 is 255. */
*ebx |= MIN(threads_per_pkg, 255) << 16;
}
if (!cpu->enable_pmu) {
*ecx &= ~CPUID_EXT_PDCM;
@ -6870,13 +6874,13 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
int host_vcpus_per_cache = 1 + ((*eax & 0x3FFC000) >> 14);
*eax &= ~0xFC000000;
*eax |= max_core_ids_in_package(topo_info) << 26;
*eax |= MIN(max_core_ids_in_package(topo_info), 63) << 26;
if (host_vcpus_per_cache > threads_per_pkg) {
*eax &= ~0x3FFC000;
/* Share the cache at package level. */
*eax |= max_thread_ids_for_cache(topo_info,
CPU_TOPOLOGY_LEVEL_SOCKET) << 14;
*eax |= MIN(max_thread_ids_for_cache(topo_info,
CPU_TOPOLOGY_LEVEL_SOCKET), 4095) << 14;
}
}
} else if (cpu->vendor_cpuid_only && IS_AMD_CPU(env)) {

View file

@ -500,8 +500,12 @@ uint32_t kvm_arch_get_supported_cpuid(KVMState *s, uint32_t function,
* Linux v4.17-v4.20 incorrectly return ARCH_CAPABILITIES on SVM hosts.
* We can detect the bug by checking if MSR_IA32_ARCH_CAPABILITIES is
* returned by KVM_GET_MSR_INDEX_LIST.
*
* But also, because Windows does not like ARCH_CAPABILITIES on AMD
* mcahines at all, do not show the fake ARCH_CAPABILITIES MSR that
* KVM sets up.
*/
if (!has_msr_arch_capabs) {
if (!has_msr_arch_capabs || !(edx & CPUID_7_0_EDX_ARCH_CAPABILITIES)) {
ret &= ~CPUID_7_0_EDX_ARCH_CAPABILITIES;
}
} else if (function == 7 && index == 1 && reg == R_EAX) {

View file

@ -2000,8 +2000,11 @@ static void gen_movl_seg(DisasContext *s, X86Seg seg_reg, TCGv src, bool inhibit
tcg_gen_trunc_tl_i32(sel, src);
gen_helper_load_seg(tcg_env, tcg_constant_i32(seg_reg), sel);
/* For move to DS/ES/SS, the addseg or ss32 flags may change. */
if (CODE32(s) && seg_reg < R_FS) {
/*
* For moves to SS, the SS32 flag may change. For CODE32 only, changes
* to SS, DS and ES may change the ADDSEG flags.
*/
if (seg_reg == R_SS || (CODE32(s) && seg_reg < R_FS)) {
s->base.is_jmp = DISAS_EOB_NEXT;
}
} else {

View file

@ -4,10 +4,15 @@
*/
/* bit0(signaling/quiet) bit1(lt) bit2(eq) bit3(un) bit4(neq) */
static uint32_t get_fcmp_flags(int cond)
static uint32_t get_fcmp_flags(DisasContext *ctx, int cond)
{
uint32_t flags = 0;
/*check cond , cond =[0-8,10,12] */
if ((cond > 8) &&(cond != 10) && (cond != 12)) {
return -1;
}
if (cond & 0x1) {
flags |= FCMP_LT;
}
@ -26,9 +31,14 @@ static uint32_t get_fcmp_flags(int cond)
static bool trans_fcmp_cond_s(DisasContext *ctx, arg_fcmp_cond_s *a)
{
TCGv var, src1, src2;
uint32_t flags;
uint32_t flags = get_fcmp_flags(ctx, a->fcond >>1);
void (*fn)(TCGv, TCGv_env, TCGv, TCGv, TCGv_i32);
if (flags == -1) {
generate_exception(ctx, EXCCODE_INE);
return true;
}
if (!avail_FP_SP(ctx)) {
return false;
}
@ -39,8 +49,6 @@ static bool trans_fcmp_cond_s(DisasContext *ctx, arg_fcmp_cond_s *a)
src1 = get_fpr(ctx, a->fj);
src2 = get_fpr(ctx, a->fk);
fn = (a->fcond & 1 ? gen_helper_fcmp_s_s : gen_helper_fcmp_c_s);
flags = get_fcmp_flags(a->fcond >> 1);
fn(var, tcg_env, src1, src2, tcg_constant_i32(flags));
tcg_gen_st8_tl(var, tcg_env, offsetof(CPULoongArchState, cf[a->cd]));
@ -50,9 +58,14 @@ static bool trans_fcmp_cond_s(DisasContext *ctx, arg_fcmp_cond_s *a)
static bool trans_fcmp_cond_d(DisasContext *ctx, arg_fcmp_cond_d *a)
{
TCGv var, src1, src2;
uint32_t flags;
uint32_t flags = get_fcmp_flags(ctx, a->fcond >> 1);
void (*fn)(TCGv, TCGv_env, TCGv, TCGv, TCGv_i32);
if (flags == -1) {
generate_exception(ctx, EXCCODE_INE);
return true;
}
if (!avail_FP_DP(ctx)) {
return false;
}
@ -63,8 +76,6 @@ static bool trans_fcmp_cond_d(DisasContext *ctx, arg_fcmp_cond_d *a)
src1 = get_fpr(ctx, a->fj);
src2 = get_fpr(ctx, a->fk);
fn = (a->fcond & 1 ? gen_helper_fcmp_s_d : gen_helper_fcmp_c_d);
flags = get_fcmp_flags(a->fcond >> 1);
fn(var, tcg_env, src1, src2, tcg_constant_i32(flags));
tcg_gen_st8_tl(var, tcg_env, offsetof(CPULoongArchState, cf[a->cd]));

View file

@ -3465,7 +3465,7 @@ TRANS(xvmsknz_b, LASX, gen_xx, gen_helper_vmsknz_b)
static uint64_t vldi_get_value(DisasContext *ctx, uint32_t imm)
{
int mode;
uint64_t data, t;
uint64_t data = 0, t;
/*
* imm bit [11:8] is mode, mode value is 0-12.
@ -3570,17 +3570,26 @@ static uint64_t vldi_get_value(DisasContext *ctx, uint32_t imm)
}
break;
default:
generate_exception(ctx, EXCCODE_INE);
g_assert_not_reached();
}
return data;
}
static bool check_valid_vldi_mode(arg_vldi *a)
{
return extract32(a->imm, 8, 4) <= 12;
}
static bool gen_vldi(DisasContext *ctx, arg_vldi *a, uint32_t oprsz)
{
int sel, vece;
uint64_t value;
if (!check_valid_vldi_mode(a)) {
generate_exception(ctx, EXCCODE_INE);
return true;
}
if (!check_vec(ctx, oprsz)) {
return true;
}
@ -4655,19 +4664,23 @@ TRANS(xvslti_du, LASX, do_xcmpi, MO_64, TCG_COND_LTU)
static bool do_vfcmp_cond_s(DisasContext *ctx, arg_vvv_fcond *a, uint32_t sz)
{
uint32_t flags;
uint32_t flags = get_fcmp_flags(ctx, a->fcond >> 1);
void (*fn)(TCGv_env, TCGv_i32, TCGv_i32, TCGv_i32, TCGv_i32, TCGv_i32);
TCGv_i32 vd = tcg_constant_i32(a->vd);
TCGv_i32 vj = tcg_constant_i32(a->vj);
TCGv_i32 vk = tcg_constant_i32(a->vk);
TCGv_i32 oprsz = tcg_constant_i32(sz);
if(flags == -1){
generate_exception(ctx, EXCCODE_INE);
return true;
}
if (!check_vec(ctx, sz)) {
return true;
}
fn = (a->fcond & 1 ? gen_helper_vfcmp_s_s : gen_helper_vfcmp_c_s);
flags = get_fcmp_flags(a->fcond >> 1);
fn(tcg_env, oprsz, vd, vj, vk, tcg_constant_i32(flags));
return true;
@ -4675,19 +4688,23 @@ static bool do_vfcmp_cond_s(DisasContext *ctx, arg_vvv_fcond *a, uint32_t sz)
static bool do_vfcmp_cond_d(DisasContext *ctx, arg_vvv_fcond *a, uint32_t sz)
{
uint32_t flags;
uint32_t flags = get_fcmp_flags(ctx, a->fcond >> 1);
void (*fn)(TCGv_env, TCGv_i32, TCGv_i32, TCGv_i32, TCGv_i32, TCGv_i32);
TCGv_i32 vd = tcg_constant_i32(a->vd);
TCGv_i32 vj = tcg_constant_i32(a->vj);
TCGv_i32 vk = tcg_constant_i32(a->vk);
TCGv_i32 oprsz = tcg_constant_i32(sz);
if (flags == -1) {
generate_exception(ctx, EXCCODE_INE);
return true;
}
if (!check_vec(ctx, sz)) {
return true;
}
fn = (a->fcond & 1 ? gen_helper_vfcmp_s_d : gen_helper_vfcmp_c_d);
flags = get_fcmp_flags(a->fcond >> 1);
fn(tcg_env, oprsz, vd, vj, vk, tcg_constant_i32(flags));
return true;

View file

@ -4927,7 +4927,7 @@ static void tcg_reg_alloc_dup(TCGContext *s, const TCGOp *op)
if (its->val_type == TEMP_VAL_CONST) {
/* Propagate constant via movi -> dupi. */
tcg_target_ulong val = its->val;
tcg_target_ulong val = dup_const(vece, its->val);
if (IS_DEAD_ARG(1)) {
temp_dead(s, its);
}

View file

@ -81,8 +81,6 @@ class TestCase(iotests.QMPTestCase):
self.vm.qmp_log('device_del', id='scsi-hd0')
self.vm.event_wait('DEVICE_DELETED')
self.vm.qmp_log('device_add', id='scsi-hd1', driver='scsi-hd', drive='hd0', bus="scsi1.0")
self.vm.qmp_log('device_del', id='scsi-hd1')
self.vm.event_wait('DEVICE_DELETED')
self.vm.qmp_log('blockdev-del', node_name='hd0')

View file

@ -46,10 +46,8 @@
{"execute": "device_add", "arguments": {"bus": "scsi0.0", "drive": "hd0", "driver": "scsi-hd", "id": "scsi-hd0"}}
{"return": {}}
{"execute": "device_add", "arguments": {"bus": "scsi1.0", "drive": "hd0", "driver": "scsi-hd", "id": "scsi-hd1"}}
{"error": {"class": "GenericError", "desc": "Cannot change iothread of active block backend"}}
{"execute": "device_del", "arguments": {"id": "scsi-hd0"}}
{"return": {}}
{"execute": "device_add", "arguments": {"bus": "scsi1.0", "drive": "hd0", "driver": "scsi-hd", "id": "scsi-hd1"}}
{"execute": "device_del", "arguments": {"id": "scsi-hd0"}}
{"return": {}}
{"execute": "device_del", "arguments": {"id": "scsi-hd1"}}
{"return": {}}

View file

@ -70,16 +70,18 @@ void gd_egl_draw(VirtualConsole *vc)
QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf;
int fence_fd;
#endif
int ww, wh, ws;
int ww, wh, pw, ph, gs;
if (!vc->gfx.gls) {
return;
}
window = gtk_widget_get_window(vc->gfx.drawing_area);
ws = gdk_window_get_scale_factor(window);
ww = gdk_window_get_width(window) * ws;
wh = gdk_window_get_height(window) * ws;
gs = gdk_window_get_scale_factor(window);
ww = gdk_window_get_width(window);
wh = gdk_window_get_height(window);
pw = ww * gs;
ph = wh * gs;
if (vc->gfx.scanout_mode) {
#ifdef CONFIG_GBM
@ -115,7 +117,7 @@ void gd_egl_draw(VirtualConsole *vc)
eglMakeCurrent(qemu_egl_display, vc->gfx.esurface,
vc->gfx.esurface, vc->gfx.ectx);
surface_gl_setup_viewport(vc->gfx.gls, vc->gfx.ds, ww, wh);
surface_gl_setup_viewport(vc->gfx.gls, vc->gfx.ds, pw, ph);
surface_gl_render_texture(vc->gfx.gls, vc->gfx.ds);
eglSwapBuffers(qemu_egl_display, vc->gfx.esurface);

View file

@ -42,16 +42,24 @@ void gd_gl_area_draw(VirtualConsole *vc)
#ifdef CONFIG_GBM
QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf;
#endif
int ww, wh, ws, y1, y2;
int pw, ph, gs, y1, y2;
int ww, wh;
int fbw, fbh;
if (!vc->gfx.gls) {
return;
}
gtk_gl_area_make_current(GTK_GL_AREA(vc->gfx.drawing_area));
ws = gdk_window_get_scale_factor(gtk_widget_get_window(vc->gfx.drawing_area));
ww = gtk_widget_get_allocated_width(vc->gfx.drawing_area) * ws;
wh = gtk_widget_get_allocated_height(vc->gfx.drawing_area) * ws;
gs = gdk_window_get_scale_factor(gtk_widget_get_window(vc->gfx.drawing_area));
fbw = surface_width(vc->gfx.ds);
fbh = surface_height(vc->gfx.ds);
ww = gtk_widget_get_allocated_width(vc->gfx.drawing_area);
wh = gtk_widget_get_allocated_height(vc->gfx.drawing_area);
pw = ww * gs;
ph = wh * gs;
gd_update_scale(vc, ww, wh, fbw, fbh);
if (vc->gfx.scanout_mode) {
if (!vc->gfx.guest_fb.framebuffer) {
@ -71,11 +79,11 @@ void gd_gl_area_draw(VirtualConsole *vc)
glBindFramebuffer(GL_READ_FRAMEBUFFER, vc->gfx.guest_fb.framebuffer);
/* GtkGLArea sets GL_DRAW_FRAMEBUFFER for us */
glViewport(0, 0, ww, wh);
glViewport(0, 0, pw, ph);
y1 = vc->gfx.y0_top ? 0 : vc->gfx.h;
y2 = vc->gfx.y0_top ? vc->gfx.h : 0;
glBlitFramebuffer(0, y1, vc->gfx.w, y2,
0, 0, ww, wh,
0, 0, pw, ph,
GL_COLOR_BUFFER_BIT, GL_NEAREST);
#ifdef CONFIG_GBM
if (dmabuf) {
@ -101,7 +109,7 @@ void gd_gl_area_draw(VirtualConsole *vc)
}
gtk_gl_area_make_current(GTK_GL_AREA(vc->gfx.drawing_area));
surface_gl_setup_viewport(vc->gfx.gls, vc->gfx.ds, ww, wh);
surface_gl_setup_viewport(vc->gfx.gls, vc->gfx.ds, pw, ph);
surface_gl_render_texture(vc->gfx.gls, vc->gfx.ds);
}
}

222
ui/gtk.c
View file

@ -387,16 +387,16 @@ static void *gd_win32_get_hwnd(VirtualConsole *vc)
/** DisplayState Callbacks **/
static void gd_update(DisplayChangeListener *dcl,
int x, int y, int w, int h)
int fbx, int fby, int fbw, int fbh)
{
VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl);
GdkWindow *win;
int x1, x2, y1, y2;
int mx, my;
int fbw, fbh;
int ww, wh;
int wx1, wx2, wy1, wy2;
int wx_offset, wy_offset;
int ww_surface, wh_surface;
int ww_widget, wh_widget;
trace_gd_update(vc->label, x, y, w, h);
trace_gd_update(vc->label, fbx, fby, fbw, fbh);
if (!gtk_widget_get_realized(vc->gfx.drawing_area)) {
return;
@ -405,35 +405,36 @@ static void gd_update(DisplayChangeListener *dcl,
if (vc->gfx.convert) {
pixman_image_composite(PIXMAN_OP_SRC, vc->gfx.ds->image,
NULL, vc->gfx.convert,
x, y, 0, 0, x, y, w, h);
fbx, fby, 0, 0, fbx, fby, fbw, fbh);
}
x1 = floor(x * vc->gfx.scale_x);
y1 = floor(y * vc->gfx.scale_y);
wx1 = floor(fbx * vc->gfx.scale_x);
wy1 = floor(fby * vc->gfx.scale_y);
x2 = ceil(x * vc->gfx.scale_x + w * vc->gfx.scale_x);
y2 = ceil(y * vc->gfx.scale_y + h * vc->gfx.scale_y);
wx2 = ceil(fbx * vc->gfx.scale_x + fbw * vc->gfx.scale_x);
wy2 = ceil(fby * vc->gfx.scale_y + fbh * vc->gfx.scale_y);
fbw = surface_width(vc->gfx.ds) * vc->gfx.scale_x;
fbh = surface_height(vc->gfx.ds) * vc->gfx.scale_y;
ww_surface = surface_width(vc->gfx.ds) * vc->gfx.scale_x;
wh_surface = surface_height(vc->gfx.ds) * vc->gfx.scale_y;
win = gtk_widget_get_window(vc->gfx.drawing_area);
if (!win) {
return;
}
ww = gdk_window_get_width(win);
wh = gdk_window_get_height(win);
ww_widget = gdk_window_get_width(win);
wh_widget = gdk_window_get_height(win);
mx = my = 0;
if (ww > fbw) {
mx = (ww - fbw) / 2;
wx_offset = wy_offset = 0;
if (ww_widget > ww_surface) {
wx_offset = (ww_widget - ww_surface) / 2;
}
if (wh > fbh) {
my = (wh - fbh) / 2;
if (wh_widget > wh_surface) {
wy_offset = (wh_widget - wh_surface) / 2;
}
gtk_widget_queue_draw_area(vc->gfx.drawing_area,
mx + x1, my + y1, (x2 - x1), (y2 - y1));
wx_offset + wx1, wy_offset + wy1,
(wx2 - wx1), (wy2 - wy1));
}
static void gd_refresh(DisplayChangeListener *dcl)
@ -800,12 +801,95 @@ void gd_update_monitor_refresh_rate(VirtualConsole *vc, GtkWidget *widget)
#endif
}
void gd_update_scale(VirtualConsole *vc, int ww, int wh, int fbw, int fbh)
{
if (!vc) {
return;
}
if (vc->s->full_screen) {
vc->gfx.scale_x = (double)ww / fbw;
vc->gfx.scale_y = (double)wh / fbh;
} else if (vc->s->free_scale) {
double sx, sy;
sx = (double)ww / fbw;
sy = (double)wh / fbh;
vc->gfx.scale_x = vc->gfx.scale_y = MIN(sx, sy);
}
}
/**
* DOC: Coordinate handling.
*
* We are coping with sizes and positions in various coordinates and the
* handling of these coordinates is somewhat confusing. It would benefit us
* all if we define these coordinates explicitly and clearly. Besides, it's
* also helpful to follow the same naming convention for variables
* representing values in different coordinates.
*
* I. Definitions
*
* - (guest) buffer coordinate: this is the coordinates that the guest will
* see. The x/y offsets and width/height specified in commands sent by
* guest is basically in buffer coordinate.
*
* - (host) pixel coordinate: this is the coordinate in pixel level on the
* host destop. A window/widget of width 300 in pixel coordinate means it
* occupies 300 pixels horizontally.
*
* - (host) logical window coordinate: the existence of global scaling
* factor in desktop level makes this kind of coordinate play a role. It
* always holds that (logical window size) * (global scale factor) =
* (pixel size).
*
* - global scale factor: this is specified in desktop level and is
* typically invariant during the life cycle of the process. Users with
* high-DPI monitors might set this scale, for example, to 2, in order to
* make the UI look larger.
*
* - zooming scale: this can be freely controlled by the QEMU user to zoom
* in/out the guest content.
*
* II. Representation
*
* We'd like to use consistent representation for variables in different
* coordinates:
* - buffer coordinate: prefix fb
* - pixel coordinate: prefix p
* - logical window coordinate: prefix w
*
* For scales:
* - global scale factor: prefix gs
* - zooming scale: prefix scale/s
*
* Example: fbw, pw, ww for width in different coordinates
*
* III. Equation
*
* - fbw * gs * scale_x = pw
* - pw = gs * ww
*
* Consequently we have
*
* - fbw * scale_x = ww
*
* Example: assuming we are running QEMU on a 3840x2160 screen and have set
* global scaling factor to 2, if the guest buffer size is 1920x1080 and the
* zooming scale is 0.5, then we have:
* - fbw = 1920, fbh = 1080
* - pw = 1920, ph = 1080
* - ww = 960, wh = 540
* A bonus of this configuration is that we can achieve pixel to pixel
* presentation of the guest content.
*/
static gboolean gd_draw_event(GtkWidget *widget, cairo_t *cr, void *opaque)
{
VirtualConsole *vc = opaque;
GtkDisplayState *s = vc->s;
int mx, my;
int ww, wh;
int wx_offset, wy_offset;
int ww_widget, wh_widget, ww_surface, wh_surface;
int fbw, fbh;
#if defined(CONFIG_OPENGL)
@ -839,46 +923,37 @@ static gboolean gd_draw_event(GtkWidget *widget, cairo_t *cr, void *opaque)
fbw = surface_width(vc->gfx.ds);
fbh = surface_height(vc->gfx.ds);
ww = gdk_window_get_width(gtk_widget_get_window(widget));
wh = gdk_window_get_height(gtk_widget_get_window(widget));
ww_widget = gdk_window_get_width(gtk_widget_get_window(widget));
wh_widget = gdk_window_get_height(gtk_widget_get_window(widget));
if (s->full_screen) {
vc->gfx.scale_x = (double)ww / fbw;
vc->gfx.scale_y = (double)wh / fbh;
} else if (s->free_scale) {
double sx, sy;
gd_update_scale(vc, ww_widget, wh_widget, fbw, fbh);
sx = (double)ww / fbw;
sy = (double)wh / fbh;
ww_surface = fbw * vc->gfx.scale_x;
wh_surface = fbh * vc->gfx.scale_y;
vc->gfx.scale_x = vc->gfx.scale_y = MIN(sx, sy);
wx_offset = wy_offset = 0;
if (ww_widget > ww_surface) {
wx_offset = (ww_widget - ww_surface) / 2;
}
if (wh_widget > wh_surface) {
wy_offset = (wh_widget - wh_surface) / 2;
}
fbw *= vc->gfx.scale_x;
fbh *= vc->gfx.scale_y;
mx = my = 0;
if (ww > fbw) {
mx = (ww - fbw) / 2;
}
if (wh > fbh) {
my = (wh - fbh) / 2;
}
cairo_rectangle(cr, 0, 0, ww, wh);
cairo_rectangle(cr, 0, 0, ww_widget, wh_widget);
/* Optionally cut out the inner area where the pixmap
will be drawn. This avoids 'flashing' since we're
not double-buffering. Note we're using the undocumented
behaviour of drawing the rectangle from right to left
to cut out the whole */
cairo_rectangle(cr, mx + fbw, my,
-1 * fbw, fbh);
cairo_rectangle(cr, wx_offset + ww_surface, wy_offset,
-1 * ww_surface, wh_surface);
cairo_fill(cr);
cairo_scale(cr, vc->gfx.scale_x, vc->gfx.scale_y);
cairo_set_source_surface(cr, vc->gfx.surface,
mx / vc->gfx.scale_x, my / vc->gfx.scale_y);
wx_offset / vc->gfx.scale_x,
wy_offset / vc->gfx.scale_y);
cairo_paint(cr);
return TRUE;
@ -889,19 +964,19 @@ static gboolean gd_motion_event(GtkWidget *widget, GdkEventMotion *motion,
{
VirtualConsole *vc = opaque;
GtkDisplayState *s = vc->s;
int x, y;
int mx, my;
int fbh, fbw;
int ww, wh;
int fbx, fby;
int wx_offset, wy_offset;
int wh_surface, ww_surface;
int ww_widget, wh_widget;
if (!vc->gfx.ds) {
return TRUE;
}
fbw = surface_width(vc->gfx.ds) * vc->gfx.scale_x;
fbh = surface_height(vc->gfx.ds) * vc->gfx.scale_y;
ww = gtk_widget_get_allocated_width(widget);
wh = gtk_widget_get_allocated_height(widget);
ww_surface = surface_width(vc->gfx.ds) * vc->gfx.scale_x;
wh_surface = surface_height(vc->gfx.ds) * vc->gfx.scale_y;
ww_widget = gtk_widget_get_allocated_width(widget);
wh_widget = gtk_widget_get_allocated_height(widget);
/*
* `widget` may not have the same size with the frame buffer.
@ -909,41 +984,42 @@ static gboolean gd_motion_event(GtkWidget *widget, GdkEventMotion *motion,
* To achieve that, `vc` will be displayed at (mx, my)
* so that it is displayed at the center of the widget.
*/
mx = my = 0;
if (ww > fbw) {
mx = (ww - fbw) / 2;
wx_offset = wy_offset = 0;
if (ww_widget > ww_surface) {
wx_offset = (ww_widget - ww_surface) / 2;
}
if (wh > fbh) {
my = (wh - fbh) / 2;
if (wh_widget > wh_surface) {
wy_offset = (wh_widget - wh_surface) / 2;
}
/*
* `motion` is reported in `widget` coordinates
* so translating it to the coordinates in `vc`.
*/
x = (motion->x - mx) / vc->gfx.scale_x;
y = (motion->y - my) / vc->gfx.scale_y;
fbx = (motion->x - wx_offset) / vc->gfx.scale_x;
fby = (motion->y - wy_offset) / vc->gfx.scale_y;
trace_gd_motion_event(ww, wh, gtk_widget_get_scale_factor(widget), x, y);
trace_gd_motion_event(ww_widget, wh_widget,
gtk_widget_get_scale_factor(widget), fbx, fby);
if (qemu_input_is_absolute(vc->gfx.dcl.con)) {
if (x < 0 || y < 0 ||
x >= surface_width(vc->gfx.ds) ||
y >= surface_height(vc->gfx.ds)) {
if (fbx < 0 || fby < 0 ||
fbx >= surface_width(vc->gfx.ds) ||
fby >= surface_height(vc->gfx.ds)) {
return TRUE;
}
qemu_input_queue_abs(vc->gfx.dcl.con, INPUT_AXIS_X, x,
qemu_input_queue_abs(vc->gfx.dcl.con, INPUT_AXIS_X, fbx,
0, surface_width(vc->gfx.ds));
qemu_input_queue_abs(vc->gfx.dcl.con, INPUT_AXIS_Y, y,
qemu_input_queue_abs(vc->gfx.dcl.con, INPUT_AXIS_Y, fby,
0, surface_height(vc->gfx.ds));
qemu_input_event_sync();
} else if (s->last_set && s->ptr_owner == vc) {
qemu_input_queue_rel(vc->gfx.dcl.con, INPUT_AXIS_X, x - s->last_x);
qemu_input_queue_rel(vc->gfx.dcl.con, INPUT_AXIS_Y, y - s->last_y);
qemu_input_queue_rel(vc->gfx.dcl.con, INPUT_AXIS_X, fbx - s->last_x);
qemu_input_queue_rel(vc->gfx.dcl.con, INPUT_AXIS_Y, fby - s->last_y);
qemu_input_event_sync();
}
s->last_x = x;
s->last_y = y;
s->last_x = fbx;
s->last_y = fby;
s->last_set = TRUE;
if (!qemu_input_is_absolute(vc->gfx.dcl.con) && s->ptr_owner == vc) {

View file

@ -126,33 +126,34 @@ uint32_t qemu_pixman_to_drm_format(pixman_format_code_t pixman_format)
return 0;
}
int qemu_pixman_get_type(int rshift, int gshift, int bshift)
int qemu_pixman_get_type(int rshift, int gshift, int bshift, int endian)
{
int type = PIXMAN_TYPE_OTHER;
bool native_endian = (endian == G_BYTE_ORDER);
if (rshift > gshift && gshift > bshift) {
if (bshift == 0) {
type = PIXMAN_TYPE_ARGB;
type = native_endian ? PIXMAN_TYPE_ARGB : PIXMAN_TYPE_BGRA;
} else {
type = PIXMAN_TYPE_RGBA;
type = native_endian ? PIXMAN_TYPE_RGBA : PIXMAN_TYPE_ABGR;
}
} else if (rshift < gshift && gshift < bshift) {
if (rshift == 0) {
type = PIXMAN_TYPE_ABGR;
type = native_endian ? PIXMAN_TYPE_ABGR : PIXMAN_TYPE_RGBA;
} else {
type = PIXMAN_TYPE_BGRA;
type = native_endian ? PIXMAN_TYPE_BGRA : PIXMAN_TYPE_ARGB;
}
}
return type;
}
#ifdef CONFIG_PIXMAN
pixman_format_code_t qemu_pixman_get_format(PixelFormat *pf)
pixman_format_code_t qemu_pixman_get_format(PixelFormat *pf, int endian)
{
pixman_format_code_t format;
int type;
type = qemu_pixman_get_type(pf->rshift, pf->gshift, pf->bshift);
type = qemu_pixman_get_type(pf->rshift, pf->gshift, pf->bshift, endian);
format = PIXMAN_FORMAT(pf->bits_per_pixel, type,
pf->abits, pf->rbits, pf->gbits, pf->bbits);
if (!pixman_format_supported_source(format)) {

View file

@ -488,14 +488,14 @@ static void handle_mousemotion(SDL_Event *ev)
{
int max_x, max_y;
struct sdl2_console *scon = get_scon_from_window(ev->motion.windowID);
int scr_w, scr_h, surf_w, surf_h, x, y, dx, dy;
if (!scon || !qemu_console_is_graphic(scon->dcl.con)) {
return;
}
SDL_GetWindowSize(scon->real_window, &scr_w, &scr_h);
if (qemu_input_is_absolute(scon->dcl.con) || absolute_enabled) {
int scr_w, scr_h;
SDL_GetWindowSize(scon->real_window, &scr_w, &scr_h);
max_x = scr_w - 1;
max_y = scr_h - 1;
if (gui_grab && !gui_fullscreen
@ -509,9 +509,14 @@ static void handle_mousemotion(SDL_Event *ev)
sdl_grab_start(scon);
}
}
surf_w = surface_width(scon->surface);
surf_h = surface_height(scon->surface);
x = (int64_t)ev->motion.x * surf_w / scr_w;
y = (int64_t)ev->motion.y * surf_h / scr_h;
dx = (int64_t)ev->motion.xrel * surf_w / scr_w;
dy = (int64_t)ev->motion.yrel * surf_h / scr_h;
if (gui_grab || qemu_input_is_absolute(scon->dcl.con) || absolute_enabled) {
sdl_send_mouse_event(scon, ev->motion.xrel, ev->motion.yrel,
ev->motion.x, ev->motion.y, ev->motion.state);
sdl_send_mouse_event(scon, dx, dy, x, y, ev->motion.state);
}
}
@ -520,12 +525,17 @@ static void handle_mousebutton(SDL_Event *ev)
int buttonstate = SDL_GetMouseState(NULL, NULL);
SDL_MouseButtonEvent *bev;
struct sdl2_console *scon = get_scon_from_window(ev->button.windowID);
int scr_w, scr_h, x, y;
if (!scon || !qemu_console_is_graphic(scon->dcl.con)) {
return;
}
bev = &ev->button;
SDL_GetWindowSize(scon->real_window, &scr_w, &scr_h);
x = (int64_t)bev->x * surface_width(scon->surface) / scr_w;
y = (int64_t)bev->y * surface_height(scon->surface) / scr_h;
if (!gui_grab && !qemu_input_is_absolute(scon->dcl.con)) {
if (ev->type == SDL_MOUSEBUTTONUP && bev->button == SDL_BUTTON_LEFT) {
/* start grabbing all events */
@ -537,7 +547,7 @@ static void handle_mousebutton(SDL_Event *ev)
} else {
buttonstate &= ~SDL_BUTTON(bev->button);
}
sdl_send_mouse_event(scon, 0, 0, bev->x, bev->y, buttonstate);
sdl_send_mouse_event(scon, 0, 0, x, y, buttonstate);
}
}

View file

@ -150,7 +150,7 @@ tight_detect_smooth_image24(VncState *vs, int w, int h)
* If client is big-endian, color samples begin from the second
* byte (offset 1) of a 32-bit pixel value.
*/
off = vs->client_be;
off = vs->client_endian == G_BIG_ENDIAN ? 1 : 0;
memset(stats, 0, sizeof (stats));
@ -891,7 +891,7 @@ static void tight_pack24(VncState *vs, uint8_t *buf, size_t count, size_t *ret)
buf8 = buf;
if (1 /* FIXME */) {
if (vs->client_endian == G_BYTE_ORDER) {
rshift = vs->client_pf.rshift;
gshift = vs->client_pf.gshift;
bshift = vs->client_pf.bshift;
@ -1001,16 +1001,24 @@ static int send_mono_rect(VncState *vs, int x, int y,
break;
}
case 2:
vnc_write(vs, &bg, 2);
vnc_write(vs, &fg, 2);
{
uint16_t bg16 = bg;
uint16_t fg16 = fg;
vnc_write(vs, &bg16, 2);
vnc_write(vs, &fg16, 2);
tight_encode_mono_rect16(vs->tight->tight.buffer, w, h, bg, fg);
break;
}
default:
vnc_write_u8(vs, bg);
vnc_write_u8(vs, fg);
{
uint8_t bg8 = bg;
uint8_t fg8 = fg;
vnc_write_u8(vs, bg8);
vnc_write_u8(vs, fg8);
tight_encode_mono_rect8(vs->tight->tight.buffer, w, h, bg, fg);
break;
}
}
vs->tight->tight.offset = bytes;
bytes = tight_compress_data(vs, stream, bytes, level, Z_DEFAULT_STRATEGY);

View file

@ -48,21 +48,21 @@ void vnc_zlib_zfree(void *x, void *addr)
static void vnc_zlib_start(VncState *vs)
{
buffer_reset(&vs->zlib.zlib);
buffer_reset(&vs->zlib->zlib);
// make the output buffer be the zlib buffer, so we can compress it later
vs->zlib.tmp = vs->output;
vs->output = vs->zlib.zlib;
vs->zlib->tmp = vs->output;
vs->output = vs->zlib->zlib;
}
static int vnc_zlib_stop(VncState *vs)
{
z_streamp zstream = &vs->zlib.stream;
z_streamp zstream = &vs->zlib->stream;
int previous_out;
// switch back to normal output/zlib buffers
vs->zlib.zlib = vs->output;
vs->output = vs->zlib.tmp;
vs->zlib->zlib = vs->output;
vs->output = vs->zlib->tmp;
// compress the zlib buffer
@ -85,24 +85,24 @@ static int vnc_zlib_stop(VncState *vs)
return -1;
}
vs->zlib.level = vs->tight->compression;
vs->zlib->level = vs->tight->compression;
zstream->opaque = vs;
}
if (vs->tight->compression != vs->zlib.level) {
if (vs->tight->compression != vs->zlib->level) {
if (deflateParams(zstream, vs->tight->compression,
Z_DEFAULT_STRATEGY) != Z_OK) {
return -1;
}
vs->zlib.level = vs->tight->compression;
vs->zlib->level = vs->tight->compression;
}
// reserve memory in output buffer
buffer_reserve(&vs->output, vs->zlib.zlib.offset + 64);
buffer_reserve(&vs->output, vs->zlib->zlib.offset + 64);
// set pointers
zstream->next_in = vs->zlib.zlib.buffer;
zstream->avail_in = vs->zlib.zlib.offset;
zstream->next_in = vs->zlib->zlib.buffer;
zstream->avail_in = vs->zlib->zlib.offset;
zstream->next_out = vs->output.buffer + vs->output.offset;
zstream->avail_out = vs->output.capacity - vs->output.offset;
previous_out = zstream->avail_out;
@ -147,8 +147,8 @@ int vnc_zlib_send_framebuffer_update(VncState *vs, int x, int y, int w, int h)
void vnc_zlib_clear(VncState *vs)
{
if (vs->zlib.stream.opaque) {
deflateEnd(&vs->zlib.stream);
if (vs->zlib->stream.opaque) {
deflateEnd(&vs->zlib->stream);
}
buffer_free(&vs->zlib.zlib);
buffer_free(&vs->zlib->zlib);
}

View file

@ -255,7 +255,7 @@ static void zrle_write_u8(VncState *vs, uint8_t value)
static int zrle_send_framebuffer_update(VncState *vs, int x, int y,
int w, int h)
{
bool be = vs->client_be;
bool be = vs->client_endian == G_BIG_ENDIAN;
size_t bytes;
int zywrle_level;

View file

@ -188,7 +188,7 @@ static void vnc_async_encoding_start(VncState *orig, VncState *local)
local->lossy_rect = orig->lossy_rect;
local->write_pixels = orig->write_pixels;
local->client_pf = orig->client_pf;
local->client_be = orig->client_be;
local->client_endian = orig->client_endian;
local->tight = orig->tight;
local->zlib = orig->zlib;
local->hextile = orig->hextile;

View file

@ -56,6 +56,11 @@
#include "io/dns-resolver.h"
#include "monitor/monitor.h"
typedef struct VncConnection {
VncState vs;
VncZlib zlib;
} VncConnection;
#define VNC_REFRESH_INTERVAL_BASE GUI_REFRESH_INTERVAL_DEFAULT
#define VNC_REFRESH_INTERVAL_INC 50
#define VNC_REFRESH_INTERVAL_MAX GUI_REFRESH_INTERVAL_IDLE
@ -893,7 +898,7 @@ void vnc_convert_pixel(VncState *vs, uint8_t *buf, uint32_t v)
buf[0] = v;
break;
case 2:
if (vs->client_be) {
if (vs->client_endian == G_BIG_ENDIAN) {
buf[0] = v >> 8;
buf[1] = v;
} else {
@ -903,7 +908,7 @@ void vnc_convert_pixel(VncState *vs, uint8_t *buf, uint32_t v)
break;
default:
case 4:
if (vs->client_be) {
if (vs->client_endian == G_BIG_ENDIAN) {
buf[0] = v >> 24;
buf[1] = v >> 16;
buf[2] = v >> 8;
@ -1364,7 +1369,7 @@ void vnc_disconnect_finish(VncState *vs)
vs->magic = 0;
g_free(vs->zrle);
g_free(vs->tight);
g_free(vs);
g_free(container_of(vs, VncConnection, vs));
}
size_t vnc_client_io_error(VncState *vs, ssize_t ret, Error *err)
@ -2242,7 +2247,8 @@ static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings)
static void set_pixel_conversion(VncState *vs)
{
pixman_format_code_t fmt = qemu_pixman_get_format(&vs->client_pf);
pixman_format_code_t fmt = qemu_pixman_get_format(&vs->client_pf,
vs->client_endian);
if (fmt == VNC_SERVER_FB_FORMAT) {
vs->write_pixels = vnc_write_pixels_copy;
@ -2314,7 +2320,7 @@ static void set_pixel_format(VncState *vs, int bits_per_pixel,
vs->client_pf.bits_per_pixel = bits_per_pixel;
vs->client_pf.bytes_per_pixel = bits_per_pixel / 8;
vs->client_pf.depth = bits_per_pixel == 32 ? 24 : bits_per_pixel;
vs->client_be = big_endian_flag;
vs->client_endian = big_endian_flag ? G_BIG_ENDIAN : G_LITTLE_ENDIAN;
if (!true_color_flag) {
send_color_map(vs);
@ -2330,6 +2336,7 @@ static void pixel_format_message (VncState *vs) {
char pad[3] = { 0, 0, 0 };
vs->client_pf = qemu_default_pixelformat(32);
vs->client_endian = G_BYTE_ORDER;
vnc_write_u8(vs, vs->client_pf.bits_per_pixel); /* bits-per-pixel */
vnc_write_u8(vs, vs->client_pf.depth); /* depth */
@ -3242,11 +3249,13 @@ static void vnc_refresh(DisplayChangeListener *dcl)
static void vnc_connect(VncDisplay *vd, QIOChannelSocket *sioc,
bool skipauth, bool websocket)
{
VncState *vs = g_new0(VncState, 1);
VncConnection *vc = g_new0(VncConnection, 1);
VncState *vs = &vc->vs;
bool first_client = QTAILQ_EMPTY(&vd->clients);
int i;
trace_vnc_client_connect(vs, sioc);
vs->zlib = &vc->zlib;
vs->zrle = g_new0(VncZrle, 1);
vs->tight = g_new0(VncTight, 1);
vs->magic = VNC_MAGIC;
@ -3269,7 +3278,7 @@ static void vnc_connect(VncDisplay *vd, QIOChannelSocket *sioc,
#ifdef CONFIG_PNG
buffer_init(&vs->tight->png, "vnc-tight-png/%p", sioc);
#endif
buffer_init(&vs->zlib.zlib, "vnc-zlib/%p", sioc);
buffer_init(&vc->zlib.zlib, "vnc-zlib/%p", sioc);
buffer_init(&vs->zrle->zrle, "vnc-zrle/%p", sioc);
buffer_init(&vs->zrle->fb, "vnc-zrle-fb/%p", sioc);
buffer_init(&vs->zrle->zlib, "vnc-zrle-zlib/%p", sioc);

View file

@ -323,7 +323,7 @@ struct VncState
VncWritePixels *write_pixels;
PixelFormat client_pf;
pixman_format_code_t client_format;
bool client_be;
int client_endian; /* G_LITTLE_ENDIAN or G_BIG_ENDIAN */
CaptureVoiceOut *audio_cap;
struct audsettings as;
@ -340,7 +340,7 @@ struct VncState
* update vnc_async_encoding_start()
*/
VncTight *tight;
VncZlib zlib;
VncZlib *zlib;
VncHextile hextile;
VncZrle *zrle;
VncZywrle zywrle;