Compare commits
80
Commits
stable-8.2
...
v2.11.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7c1beb52ed | ||
|
|
00e9fba2be | ||
|
|
63112b16a6 | ||
|
|
30c3b4823c | ||
|
|
88ab85384d | ||
|
|
64653b7fbe | ||
|
|
9a26ca6b94 | ||
|
|
172f4e5a31 | ||
|
|
0c85a40e71 | ||
|
|
f9e53c77ea | ||
|
|
f9c8767828 | ||
|
|
5af9f2504f | ||
|
|
2e6571e671 | ||
|
|
126617e6f8 | ||
|
|
8a9c5c34ac | ||
|
|
616d64ac06 | ||
|
|
a7b2537f8a | ||
|
|
de1e7a91c8 | ||
|
|
0181686a98 | ||
|
|
a3fd64f2fe | ||
|
|
68d7e24475 | ||
|
|
2095c5a2e3 | ||
|
|
c8847f5565 | ||
|
|
b9eec804f4 | ||
|
|
b8aa511bc0 | ||
|
|
ab7b4f6734 | ||
|
|
ed8b4ecc68 | ||
|
|
eab4b5170f | ||
|
|
d7aa3d0a0a | ||
|
|
3dc12273b7 | ||
|
|
e9a8747cd2 | ||
|
|
49b1fa33a3 | ||
|
|
43a29f0025 | ||
|
|
d72e0a69ea | ||
|
|
4374cbca95 | ||
|
|
a1f33a5b93 | ||
|
|
6a47136799 | ||
|
|
e4f4fa00eb | ||
|
|
ff6f7e10c6 | ||
|
|
7c578cbc37 | ||
|
|
804e5ea9ed | ||
|
|
9070f408f4 | ||
|
|
78a38cd47e | ||
|
|
0fac4aa930 | ||
|
|
97d17551b5 | ||
|
|
7e25155a7b | ||
|
|
80277d7cd5 | ||
|
|
50c6998c20 | ||
|
|
dccdaacc3d | ||
|
|
5683983e99 | ||
|
|
4d79c0e434 | ||
|
|
098132386d | ||
|
|
61c8e67a66 | ||
|
|
e7857ad997 | ||
|
|
9327a8e2d6 | ||
|
|
8ebfafa796 | ||
|
|
61efbbf869 | ||
|
|
1ade973f52 | ||
|
|
803d42fa65 | ||
|
|
cb2637a5ae | ||
|
|
4b220d88ba | ||
|
|
1027f3419b | ||
|
|
ccf82aee58 | ||
|
|
1e14820884 | ||
|
|
a22b8096b6 | ||
|
|
3f44190cb6 | ||
|
|
88bf4a70df | ||
|
|
f793121539 | ||
|
|
0af294d774 | ||
|
|
62425350b5 | ||
|
|
d6f1448277 | ||
|
|
7f53a81073 | ||
|
|
2b0c34cf61 | ||
|
|
057364da77 | ||
|
|
b9da3c1de7 | ||
|
|
c184e17c75 | ||
|
|
5ba945f1cb | ||
|
|
ea311a9959 | ||
|
|
fd89d93e85 | ||
|
|
817a9fcba8 |
@@ -4593,10 +4593,11 @@ void bdrv_img_create(const char *filename, const char *fmt,
|
||||
back_flags = flags;
|
||||
back_flags &= ~(BDRV_O_RDWR | BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING);
|
||||
|
||||
backing_options = qdict_new();
|
||||
if (backing_fmt) {
|
||||
backing_options = qdict_new();
|
||||
qdict_put_str(backing_options, "driver", backing_fmt);
|
||||
}
|
||||
qdict_put_bool(backing_options, BDRV_OPT_FORCE_SHARE, true);
|
||||
|
||||
bs = bdrv_open(full_backing, NULL, backing_options, back_flags,
|
||||
&local_err);
|
||||
|
||||
+10
-3
@@ -175,8 +175,10 @@ static void coroutine_fn bdrv_drain_invoke_entry(void *opaque)
|
||||
bdrv_wakeup(bs);
|
||||
}
|
||||
|
||||
/* Recursively call BlockDriver.bdrv_co_drain_begin/end callbacks */
|
||||
static void bdrv_drain_invoke(BlockDriverState *bs, bool begin)
|
||||
{
|
||||
BdrvChild *child, *tmp;
|
||||
BdrvCoDrainData data = { .bs = bs, .done = false, .begin = begin};
|
||||
|
||||
if (!bs->drv || (begin && !bs->drv->bdrv_co_drain_begin) ||
|
||||
@@ -187,6 +189,10 @@ static void bdrv_drain_invoke(BlockDriverState *bs, bool begin)
|
||||
data.co = qemu_coroutine_create(bdrv_drain_invoke_entry, &data);
|
||||
bdrv_coroutine_enter(bs, data.co);
|
||||
BDRV_POLL_WHILE(bs, !data.done);
|
||||
|
||||
QLIST_FOREACH_SAFE(child, &bs->children, next, tmp) {
|
||||
bdrv_drain_invoke(child->bs, begin);
|
||||
}
|
||||
}
|
||||
|
||||
static bool bdrv_drain_recurse(BlockDriverState *bs, bool begin)
|
||||
@@ -194,9 +200,6 @@ static bool bdrv_drain_recurse(BlockDriverState *bs, bool begin)
|
||||
BdrvChild *child, *tmp;
|
||||
bool waited;
|
||||
|
||||
/* Ensure any pending metadata writes are submitted to bs->file. */
|
||||
bdrv_drain_invoke(bs, begin);
|
||||
|
||||
/* Wait for drained requests to finish */
|
||||
waited = BDRV_POLL_WHILE(bs, atomic_read(&bs->in_flight) > 0);
|
||||
|
||||
@@ -279,6 +282,7 @@ void bdrv_drained_begin(BlockDriverState *bs)
|
||||
bdrv_parent_drained_begin(bs);
|
||||
}
|
||||
|
||||
bdrv_drain_invoke(bs, true);
|
||||
bdrv_drain_recurse(bs, true);
|
||||
}
|
||||
|
||||
@@ -294,6 +298,7 @@ void bdrv_drained_end(BlockDriverState *bs)
|
||||
}
|
||||
|
||||
bdrv_parent_drained_end(bs);
|
||||
bdrv_drain_invoke(bs, false);
|
||||
bdrv_drain_recurse(bs, false);
|
||||
aio_enable_external(bdrv_get_aio_context(bs));
|
||||
}
|
||||
@@ -350,6 +355,7 @@ void bdrv_drain_all_begin(void)
|
||||
aio_context_acquire(aio_context);
|
||||
bdrv_parent_drained_begin(bs);
|
||||
aio_disable_external(aio_context);
|
||||
bdrv_drain_invoke(bs, true);
|
||||
aio_context_release(aio_context);
|
||||
|
||||
if (!g_slist_find(aio_ctxs, aio_context)) {
|
||||
@@ -393,6 +399,7 @@ void bdrv_drain_all_end(void)
|
||||
aio_context_acquire(aio_context);
|
||||
aio_enable_external(aio_context);
|
||||
bdrv_parent_drained_end(bs);
|
||||
bdrv_drain_invoke(bs, false);
|
||||
bdrv_drain_recurse(bs, false);
|
||||
aio_context_release(aio_context);
|
||||
}
|
||||
|
||||
+4
-4
@@ -2,7 +2,7 @@
|
||||
* QEMU Block driver for iSCSI images
|
||||
*
|
||||
* Copyright (c) 2010-2011 Ronnie Sahlberg <ronniesahlberg@gmail.com>
|
||||
* Copyright (c) 2012-2016 Peter Lieven <pl@kamp.de>
|
||||
* Copyright (c) 2012-2017 Peter Lieven <pl@kamp.de>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -1128,6 +1128,9 @@ retry:
|
||||
goto retry;
|
||||
}
|
||||
|
||||
iscsi_allocmap_set_invalid(iscsilun, offset >> BDRV_SECTOR_BITS,
|
||||
bytes >> BDRV_SECTOR_BITS);
|
||||
|
||||
if (iTask.status == SCSI_STATUS_CHECK_CONDITION) {
|
||||
/* the target might fail with a check condition if it
|
||||
is not happy with the alignment of the UNMAP request
|
||||
@@ -1140,9 +1143,6 @@ retry:
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
iscsi_allocmap_set_invalid(iscsilun, offset >> BDRV_SECTOR_BITS,
|
||||
bytes >> BDRV_SECTOR_BITS);
|
||||
|
||||
out_unlock:
|
||||
qemu_mutex_unlock(&iscsilun->mutex);
|
||||
return r;
|
||||
|
||||
@@ -388,6 +388,7 @@ static QemuOptsList nbd_runtime_opts = {
|
||||
.type = QEMU_OPT_STRING,
|
||||
.help = "ID of the TLS credentials to use",
|
||||
},
|
||||
{ /* end of list */ }
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -1280,6 +1280,9 @@ static void vga_draw_text(VGACommonState *s, int full_update)
|
||||
cx_min = width;
|
||||
cx_max = -1;
|
||||
for(cx = 0; cx < width; cx++) {
|
||||
if (src + sizeof(uint16_t) > s->vram_ptr + s->vram_size) {
|
||||
break;
|
||||
}
|
||||
ch_attr = *(uint16_t *)src;
|
||||
if (full_update || ch_attr != *ch_attr_ptr || src == cursor_ptr) {
|
||||
if (cx < cx_min)
|
||||
|
||||
+3
-2
@@ -1261,7 +1261,8 @@ static MemTxResult gic_cpu_read(GICState *s, int cpu, int offset,
|
||||
default:
|
||||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
"gic_cpu_read: Bad offset %x\n", (int)offset);
|
||||
return MEMTX_ERROR;
|
||||
*data = 0;
|
||||
break;
|
||||
}
|
||||
return MEMTX_OK;
|
||||
}
|
||||
@@ -1329,7 +1330,7 @@ static MemTxResult gic_cpu_write(GICState *s, int cpu, int offset,
|
||||
default:
|
||||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
"gic_cpu_write: Bad offset %x\n", (int)offset);
|
||||
return MEMTX_ERROR;
|
||||
return MEMTX_OK;
|
||||
}
|
||||
gic_update(s);
|
||||
return MEMTX_OK;
|
||||
|
||||
@@ -817,6 +817,13 @@ MemTxResult gicv3_dist_read(void *opaque, hwaddr offset, uint64_t *data,
|
||||
"%s: invalid guest read at offset " TARGET_FMT_plx
|
||||
"size %u\n", __func__, offset, size);
|
||||
trace_gicv3_dist_badread(offset, size, attrs.secure);
|
||||
/* The spec requires that reserved registers are RAZ/WI;
|
||||
* so use MEMTX_ERROR returns from leaf functions as a way to
|
||||
* trigger the guest-error logging but don't return it to
|
||||
* the caller, or we'll cause a spurious guest data abort.
|
||||
*/
|
||||
r = MEMTX_OK;
|
||||
*data = 0;
|
||||
} else {
|
||||
trace_gicv3_dist_read(offset, *data, size, attrs.secure);
|
||||
}
|
||||
@@ -852,6 +859,12 @@ MemTxResult gicv3_dist_write(void *opaque, hwaddr offset, uint64_t data,
|
||||
"%s: invalid guest write at offset " TARGET_FMT_plx
|
||||
"size %u\n", __func__, offset, size);
|
||||
trace_gicv3_dist_badwrite(offset, data, size, attrs.secure);
|
||||
/* The spec requires that reserved registers are RAZ/WI;
|
||||
* so use MEMTX_ERROR returns from leaf functions as a way to
|
||||
* trigger the guest-error logging but don't return it to
|
||||
* the caller, or we'll cause a spurious guest data abort.
|
||||
*/
|
||||
r = MEMTX_OK;
|
||||
} else {
|
||||
trace_gicv3_dist_write(offset, data, size, attrs.secure);
|
||||
}
|
||||
|
||||
@@ -67,7 +67,8 @@ static MemTxResult gicv3_its_trans_read(void *opaque, hwaddr offset,
|
||||
MemTxAttrs attrs)
|
||||
{
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "ITS read at offset 0x%"PRIx64"\n", offset);
|
||||
return MEMTX_ERROR;
|
||||
*data = 0;
|
||||
return MEMTX_OK;
|
||||
}
|
||||
|
||||
static MemTxResult gicv3_its_trans_write(void *opaque, hwaddr offset,
|
||||
@@ -82,15 +83,12 @@ static MemTxResult gicv3_its_trans_write(void *opaque, hwaddr offset,
|
||||
if (ret <= 0) {
|
||||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
"ITS: Error sending MSI: %s\n", strerror(-ret));
|
||||
return MEMTX_DECODE_ERROR;
|
||||
}
|
||||
|
||||
return MEMTX_OK;
|
||||
} else {
|
||||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
"ITS write at bad offset 0x%"PRIx64"\n", offset);
|
||||
return MEMTX_DECODE_ERROR;
|
||||
}
|
||||
return MEMTX_OK;
|
||||
}
|
||||
|
||||
static const MemoryRegionOps gicv3_its_trans_ops = {
|
||||
|
||||
@@ -455,6 +455,13 @@ MemTxResult gicv3_redist_read(void *opaque, hwaddr offset, uint64_t *data,
|
||||
"size %u\n", __func__, offset, size);
|
||||
trace_gicv3_redist_badread(gicv3_redist_affid(cs), offset,
|
||||
size, attrs.secure);
|
||||
/* The spec requires that reserved registers are RAZ/WI;
|
||||
* so use MEMTX_ERROR returns from leaf functions as a way to
|
||||
* trigger the guest-error logging but don't return it to
|
||||
* the caller, or we'll cause a spurious guest data abort.
|
||||
*/
|
||||
r = MEMTX_OK;
|
||||
*data = 0;
|
||||
} else {
|
||||
trace_gicv3_redist_read(gicv3_redist_affid(cs), offset, *data,
|
||||
size, attrs.secure);
|
||||
@@ -505,6 +512,12 @@ MemTxResult gicv3_redist_write(void *opaque, hwaddr offset, uint64_t data,
|
||||
"size %u\n", __func__, offset, size);
|
||||
trace_gicv3_redist_badwrite(gicv3_redist_affid(cs), offset, data,
|
||||
size, attrs.secure);
|
||||
/* The spec requires that reserved registers are RAZ/WI;
|
||||
* so use MEMTX_ERROR returns from leaf functions as a way to
|
||||
* trigger the guest-error logging but don't return it to
|
||||
* the caller, or we'll cause a spurious guest data abort.
|
||||
*/
|
||||
r = MEMTX_OK;
|
||||
} else {
|
||||
trace_gicv3_redist_write(gicv3_redist_affid(cs), offset, data,
|
||||
size, attrs.secure);
|
||||
|
||||
@@ -74,8 +74,13 @@ static void gen_rp_realize(DeviceState *dev, Error **errp)
|
||||
PCIDevice *d = PCI_DEVICE(dev);
|
||||
GenPCIERootPort *grp = GEN_PCIE_ROOT_PORT(d);
|
||||
PCIERootPortClass *rpc = PCIE_ROOT_PORT_GET_CLASS(d);
|
||||
Error *local_err = NULL;
|
||||
|
||||
rpc->parent_realize(dev, errp);
|
||||
rpc->parent_realize(dev, &local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
return;
|
||||
}
|
||||
|
||||
int rc = pci_bridge_qemu_reserve_cap_init(d, 0, grp->bus_reserve,
|
||||
grp->io_reserve, grp->mem_reserve, grp->pref32_reserve,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# shared objects
|
||||
obj-y += ppc.o ppc_booke.o fdt.o
|
||||
# IBM pSeries (sPAPR)
|
||||
obj-$(CONFIG_PSERIES) += spapr.o spapr_vio.o spapr_events.o
|
||||
obj-$(CONFIG_PSERIES) += spapr.o spapr_caps.o spapr_vio.o spapr_events.o
|
||||
obj-$(CONFIG_PSERIES) += spapr_hcall.o spapr_iommu.o spapr_rtas.o
|
||||
obj-$(CONFIG_PSERIES) += spapr_pci.o spapr_rtc.o spapr_drc.o spapr_rng.o
|
||||
obj-$(CONFIG_PSERIES) += spapr_cpu_core.o spapr_ovec.o
|
||||
|
||||
+105
-29
@@ -253,7 +253,9 @@ static int spapr_fixup_cpu_numa_dt(void *fdt, int offset, PowerPCCPU *cpu)
|
||||
}
|
||||
|
||||
/* Populate the "ibm,pa-features" property */
|
||||
static void spapr_populate_pa_features(PowerPCCPU *cpu, void *fdt, int offset,
|
||||
static void spapr_populate_pa_features(sPAPRMachineState *spapr,
|
||||
PowerPCCPU *cpu,
|
||||
void *fdt, int offset,
|
||||
bool legacy_guest)
|
||||
{
|
||||
CPUPPCState *env = &cpu->env;
|
||||
@@ -318,7 +320,7 @@ static void spapr_populate_pa_features(PowerPCCPU *cpu, void *fdt, int offset,
|
||||
*/
|
||||
pa_features[3] |= 0x20;
|
||||
}
|
||||
if (kvmppc_has_cap_htm() && pa_size > 24) {
|
||||
if ((spapr_get_cap(spapr, SPAPR_CAP_HTM) != 0) && pa_size > 24) {
|
||||
pa_features[24] |= 0x80; /* Transactional memory support */
|
||||
}
|
||||
if (legacy_guest && pa_size > 40) {
|
||||
@@ -384,8 +386,8 @@ static int spapr_fixup_cpu_dt(void *fdt, sPAPRMachineState *spapr)
|
||||
return ret;
|
||||
}
|
||||
|
||||
spapr_populate_pa_features(cpu, fdt, offset,
|
||||
spapr->cas_legacy_guest_workaround);
|
||||
spapr_populate_pa_features(spapr, cpu, fdt, offset,
|
||||
spapr->cas_legacy_guest_workaround);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -555,20 +557,22 @@ static void spapr_populate_cpu_dt(CPUState *cs, void *fdt, int offset,
|
||||
segs, sizeof(segs))));
|
||||
}
|
||||
|
||||
/* Advertise VMX/VSX (vector extensions) if available
|
||||
* 0 / no property == no vector extensions
|
||||
/* Advertise VSX (vector extensions) if available
|
||||
* 1 == VMX / Altivec available
|
||||
* 2 == VSX available */
|
||||
if (env->insns_flags & PPC_ALTIVEC) {
|
||||
uint32_t vmx = (env->insns_flags2 & PPC2_VSX) ? 2 : 1;
|
||||
|
||||
_FDT((fdt_setprop_cell(fdt, offset, "ibm,vmx", vmx)));
|
||||
* 2 == VSX available
|
||||
*
|
||||
* Only CPUs for which we create core types in spapr_cpu_core.c
|
||||
* are possible, and all of those have VMX */
|
||||
if (spapr_get_cap(spapr, SPAPR_CAP_VSX) != 0) {
|
||||
_FDT((fdt_setprop_cell(fdt, offset, "ibm,vmx", 2)));
|
||||
} else {
|
||||
_FDT((fdt_setprop_cell(fdt, offset, "ibm,vmx", 1)));
|
||||
}
|
||||
|
||||
/* Advertise DFP (Decimal Floating Point) if available
|
||||
* 0 / no property == no DFP
|
||||
* 1 == DFP available */
|
||||
if (env->insns_flags2 & PPC2_DFP) {
|
||||
if (spapr_get_cap(spapr, SPAPR_CAP_DFP) != 0) {
|
||||
_FDT((fdt_setprop_cell(fdt, offset, "ibm,dfp", 1)));
|
||||
}
|
||||
|
||||
@@ -579,7 +583,7 @@ static void spapr_populate_cpu_dt(CPUState *cs, void *fdt, int offset,
|
||||
page_sizes_prop, page_sizes_prop_size)));
|
||||
}
|
||||
|
||||
spapr_populate_pa_features(cpu, fdt, offset, false);
|
||||
spapr_populate_pa_features(spapr, cpu, fdt, offset, false);
|
||||
|
||||
_FDT((fdt_setprop_cell(fdt, offset, "ibm,chip-id",
|
||||
cs->cpu_index / vcpus_per_socket)));
|
||||
@@ -1440,7 +1444,12 @@ static void ppc_spapr_reset(void)
|
||||
/* Check for unknown sysbus devices */
|
||||
foreach_dynamic_sysbus_device(find_unknown_sysbus_device, NULL);
|
||||
|
||||
if (kvm_enabled() && kvmppc_has_cap_mmu_radix()) {
|
||||
spapr_caps_reset(spapr);
|
||||
|
||||
first_ppc_cpu = POWERPC_CPU(first_cpu);
|
||||
if (kvm_enabled() && kvmppc_has_cap_mmu_radix() &&
|
||||
ppc_check_compat(first_ppc_cpu, CPU_POWERPC_LOGICAL_3_00, 0,
|
||||
spapr->max_compat_pvr)) {
|
||||
/* If using KVM with radix mode available, VCPUs can be started
|
||||
* without a HPT because KVM will start them in radix mode.
|
||||
* Set the GR bit in PATB so that we know there is no HPT. */
|
||||
@@ -1449,6 +1458,15 @@ static void ppc_spapr_reset(void)
|
||||
spapr_setup_hpt_and_vrma(spapr);
|
||||
}
|
||||
|
||||
/* if this reset wasn't generated by CAS, we should reset our
|
||||
* negotiated options and start from scratch */
|
||||
if (!spapr->cas_reboot) {
|
||||
spapr_ovec_cleanup(spapr->ov5_cas);
|
||||
spapr->ov5_cas = spapr_ovec_new();
|
||||
|
||||
ppc_set_compat(first_ppc_cpu, spapr->max_compat_pvr, &error_fatal);
|
||||
}
|
||||
|
||||
qemu_devices_reset();
|
||||
|
||||
/* DRC reset may cause a device to be unplugged. This will cause troubles
|
||||
@@ -1469,15 +1487,6 @@ static void ppc_spapr_reset(void)
|
||||
rtas_addr = rtas_limit - RTAS_MAX_SIZE;
|
||||
fdt_addr = rtas_addr - FDT_MAX_SIZE;
|
||||
|
||||
/* if this reset wasn't generated by CAS, we should reset our
|
||||
* negotiated options and start from scratch */
|
||||
if (!spapr->cas_reboot) {
|
||||
spapr_ovec_cleanup(spapr->ov5_cas);
|
||||
spapr->ov5_cas = spapr_ovec_new();
|
||||
|
||||
ppc_set_compat_all(spapr->max_compat_pvr, &error_fatal);
|
||||
}
|
||||
|
||||
fdt = spapr_build_fdt(spapr, rtas_addr, spapr->rtas_size);
|
||||
|
||||
spapr_load_rtas(spapr, fdt, rtas_addr);
|
||||
@@ -1499,7 +1508,6 @@ static void ppc_spapr_reset(void)
|
||||
g_free(fdt);
|
||||
|
||||
/* Set up the entry state */
|
||||
first_ppc_cpu = POWERPC_CPU(first_cpu);
|
||||
first_ppc_cpu->env.gpr[3] = fdt_addr;
|
||||
first_ppc_cpu->env.gpr[5] = 0;
|
||||
first_cpu->halted = 0;
|
||||
@@ -1552,11 +1560,28 @@ static bool spapr_vga_init(PCIBus *pci_bus, Error **errp)
|
||||
}
|
||||
}
|
||||
|
||||
static int spapr_pre_load(void *opaque)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = spapr_caps_pre_load(opaque);
|
||||
if (rc) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int spapr_post_load(void *opaque, int version_id)
|
||||
{
|
||||
sPAPRMachineState *spapr = (sPAPRMachineState *)opaque;
|
||||
int err = 0;
|
||||
|
||||
err = spapr_caps_post_migration(spapr);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
if (!object_dynamic_cast(OBJECT(spapr->ics), TYPE_ICS_KVM)) {
|
||||
CPUState *cs;
|
||||
CPU_FOREACH(cs) {
|
||||
@@ -1588,6 +1613,18 @@ static int spapr_post_load(void *opaque, int version_id)
|
||||
return err;
|
||||
}
|
||||
|
||||
static int spapr_pre_save(void *opaque)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = spapr_caps_pre_save(opaque);
|
||||
if (rc) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool version_before_3(void *opaque, int version_id)
|
||||
{
|
||||
return version_id < 3;
|
||||
@@ -1708,7 +1745,9 @@ static const VMStateDescription vmstate_spapr = {
|
||||
.name = "spapr",
|
||||
.version_id = 3,
|
||||
.minimum_version_id = 1,
|
||||
.pre_load = spapr_pre_load,
|
||||
.post_load = spapr_post_load,
|
||||
.pre_save = spapr_pre_save,
|
||||
.fields = (VMStateField[]) {
|
||||
/* used to be @next_irq */
|
||||
VMSTATE_UNUSED_BUFFER(version_before_3, 0, 4),
|
||||
@@ -1723,6 +1762,12 @@ static const VMStateDescription vmstate_spapr = {
|
||||
&vmstate_spapr_ov5_cas,
|
||||
&vmstate_spapr_patb_entry,
|
||||
&vmstate_spapr_pending_events,
|
||||
&vmstate_spapr_cap_htm,
|
||||
&vmstate_spapr_cap_vsx,
|
||||
&vmstate_spapr_cap_dfp,
|
||||
&vmstate_spapr_cap_cfpc,
|
||||
&vmstate_spapr_cap_sbbc,
|
||||
&vmstate_spapr_cap_ibs,
|
||||
NULL
|
||||
}
|
||||
};
|
||||
@@ -3663,6 +3708,14 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data)
|
||||
* in which LMBs are represented and hot-added
|
||||
*/
|
||||
mc->numa_mem_align_shift = 28;
|
||||
|
||||
smc->default_caps.caps[SPAPR_CAP_HTM] = SPAPR_CAP_OFF;
|
||||
smc->default_caps.caps[SPAPR_CAP_VSX] = SPAPR_CAP_ON;
|
||||
smc->default_caps.caps[SPAPR_CAP_DFP] = SPAPR_CAP_ON;
|
||||
smc->default_caps.caps[SPAPR_CAP_CFPC] = SPAPR_CAP_BROKEN;
|
||||
smc->default_caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_BROKEN;
|
||||
smc->default_caps.caps[SPAPR_CAP_IBS] = SPAPR_CAP_BROKEN;
|
||||
spapr_caps_add_properties(smc, &error_abort);
|
||||
}
|
||||
|
||||
static const TypeInfo spapr_machine_info = {
|
||||
@@ -3714,27 +3767,50 @@ static const TypeInfo spapr_machine_info = {
|
||||
type_init(spapr_machine_register_##suffix)
|
||||
|
||||
/*
|
||||
* pseries-2.11
|
||||
* pseries-2.12
|
||||
*/
|
||||
static void spapr_machine_2_11_instance_options(MachineState *machine)
|
||||
static void spapr_machine_2_12_instance_options(MachineState *machine)
|
||||
{
|
||||
}
|
||||
|
||||
static void spapr_machine_2_11_class_options(MachineClass *mc)
|
||||
static void spapr_machine_2_12_class_options(MachineClass *mc)
|
||||
{
|
||||
/* Defaults for the latest behaviour inherited from the base class */
|
||||
}
|
||||
|
||||
DEFINE_SPAPR_MACHINE(2_11, "2.11", true);
|
||||
DEFINE_SPAPR_MACHINE(2_12, "2.12", true);
|
||||
|
||||
/*
|
||||
* pseries-2.11
|
||||
*/
|
||||
#define SPAPR_COMPAT_2_11 \
|
||||
HW_COMPAT_2_11
|
||||
|
||||
static void spapr_machine_2_11_instance_options(MachineState *machine)
|
||||
{
|
||||
spapr_machine_2_12_instance_options(machine);
|
||||
}
|
||||
|
||||
static void spapr_machine_2_11_class_options(MachineClass *mc)
|
||||
{
|
||||
sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
|
||||
|
||||
spapr_machine_2_12_class_options(mc);
|
||||
smc->default_caps.caps[SPAPR_CAP_HTM] = SPAPR_CAP_ON;
|
||||
SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_11);
|
||||
}
|
||||
|
||||
DEFINE_SPAPR_MACHINE(2_11, "2.11", false);
|
||||
|
||||
/*
|
||||
* pseries-2.10
|
||||
*/
|
||||
#define SPAPR_COMPAT_2_10 \
|
||||
HW_COMPAT_2_10 \
|
||||
HW_COMPAT_2_10
|
||||
|
||||
static void spapr_machine_2_10_instance_options(MachineState *machine)
|
||||
{
|
||||
spapr_machine_2_11_instance_options(machine);
|
||||
}
|
||||
|
||||
static void spapr_machine_2_10_class_options(MachineClass *mc)
|
||||
|
||||
@@ -0,0 +1,443 @@
|
||||
/*
|
||||
* QEMU PowerPC pSeries Logical Partition capabilities handling
|
||||
*
|
||||
* Copyright (c) 2017 David Gibson, Red Hat Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qapi/visitor.h"
|
||||
#include "sysemu/hw_accel.h"
|
||||
#include "target/ppc/cpu.h"
|
||||
#include "cpu-models.h"
|
||||
#include "kvm_ppc.h"
|
||||
|
||||
#include "hw/ppc/spapr.h"
|
||||
|
||||
typedef struct sPAPRCapabilityInfo {
|
||||
const char *name;
|
||||
const char *description;
|
||||
const char *options; /* valid capability values */
|
||||
int index;
|
||||
|
||||
/* Getter and Setter Function Pointers */
|
||||
ObjectPropertyAccessor *get;
|
||||
ObjectPropertyAccessor *set;
|
||||
const char *type;
|
||||
/* Make sure the virtual hardware can support this capability */
|
||||
void (*apply)(sPAPRMachineState *spapr, uint8_t val, Error **errp);
|
||||
} sPAPRCapabilityInfo;
|
||||
|
||||
static void spapr_cap_get_bool(Object *obj, Visitor *v, const char *name,
|
||||
void *opaque, Error **errp)
|
||||
{
|
||||
sPAPRCapabilityInfo *cap = opaque;
|
||||
sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
|
||||
bool value = spapr_get_cap(spapr, cap->index) == SPAPR_CAP_ON;
|
||||
|
||||
visit_type_bool(v, name, &value, errp);
|
||||
}
|
||||
|
||||
static void spapr_cap_set_bool(Object *obj, Visitor *v, const char *name,
|
||||
void *opaque, Error **errp)
|
||||
{
|
||||
sPAPRCapabilityInfo *cap = opaque;
|
||||
sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
|
||||
bool value;
|
||||
Error *local_err = NULL;
|
||||
|
||||
visit_type_bool(v, name, &value, &local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
return;
|
||||
}
|
||||
|
||||
spapr->cmd_line_caps[cap->index] = true;
|
||||
spapr->eff.caps[cap->index] = value ? SPAPR_CAP_ON : SPAPR_CAP_OFF;
|
||||
}
|
||||
|
||||
static void spapr_cap_get_tristate(Object *obj, Visitor *v, const char *name,
|
||||
void *opaque, Error **errp)
|
||||
{
|
||||
sPAPRCapabilityInfo *cap = opaque;
|
||||
sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
|
||||
char *val = NULL;
|
||||
uint8_t value = spapr_get_cap(spapr, cap->index);
|
||||
|
||||
switch (value) {
|
||||
case SPAPR_CAP_BROKEN:
|
||||
val = g_strdup("broken");
|
||||
break;
|
||||
case SPAPR_CAP_WORKAROUND:
|
||||
val = g_strdup("workaround");
|
||||
break;
|
||||
case SPAPR_CAP_FIXED:
|
||||
val = g_strdup("fixed");
|
||||
break;
|
||||
default:
|
||||
error_setg(errp, "Invalid value (%d) for cap-%s", value, cap->name);
|
||||
return;
|
||||
}
|
||||
|
||||
visit_type_str(v, name, &val, errp);
|
||||
g_free(val);
|
||||
}
|
||||
|
||||
static void spapr_cap_set_tristate(Object *obj, Visitor *v, const char *name,
|
||||
void *opaque, Error **errp)
|
||||
{
|
||||
sPAPRCapabilityInfo *cap = opaque;
|
||||
sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
|
||||
char *val;
|
||||
Error *local_err = NULL;
|
||||
uint8_t value;
|
||||
|
||||
visit_type_str(v, name, &val, &local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!strcasecmp(val, "broken")) {
|
||||
value = SPAPR_CAP_BROKEN;
|
||||
} else if (!strcasecmp(val, "workaround")) {
|
||||
value = SPAPR_CAP_WORKAROUND;
|
||||
} else if (!strcasecmp(val, "fixed")) {
|
||||
value = SPAPR_CAP_FIXED;
|
||||
} else {
|
||||
error_setg(errp, "Invalid capability mode \"%s\" for cap-%s", val,
|
||||
cap->name);
|
||||
goto out;
|
||||
}
|
||||
|
||||
spapr->cmd_line_caps[cap->index] = true;
|
||||
spapr->eff.caps[cap->index] = value;
|
||||
out:
|
||||
g_free(val);
|
||||
}
|
||||
|
||||
static void cap_htm_apply(sPAPRMachineState *spapr, uint8_t val, Error **errp)
|
||||
{
|
||||
if (!val) {
|
||||
/* TODO: We don't support disabling htm yet */
|
||||
return;
|
||||
}
|
||||
if (tcg_enabled()) {
|
||||
error_setg(errp,
|
||||
"No Transactional Memory support in TCG, try cap-htm=off");
|
||||
} else if (kvm_enabled() && !kvmppc_has_cap_htm()) {
|
||||
error_setg(errp,
|
||||
"KVM implementation does not support Transactional Memory, try cap-htm=off"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
static void cap_vsx_apply(sPAPRMachineState *spapr, uint8_t val, Error **errp)
|
||||
{
|
||||
PowerPCCPU *cpu = POWERPC_CPU(first_cpu);
|
||||
CPUPPCState *env = &cpu->env;
|
||||
|
||||
if (!val) {
|
||||
/* TODO: We don't support disabling vsx yet */
|
||||
return;
|
||||
}
|
||||
/* Allowable CPUs in spapr_cpu_core.c should already have gotten
|
||||
* rid of anything that doesn't do VMX */
|
||||
g_assert(env->insns_flags & PPC_ALTIVEC);
|
||||
if (!(env->insns_flags2 & PPC2_VSX)) {
|
||||
error_setg(errp, "VSX support not available, try cap-vsx=off");
|
||||
}
|
||||
}
|
||||
|
||||
static void cap_dfp_apply(sPAPRMachineState *spapr, uint8_t val, Error **errp)
|
||||
{
|
||||
PowerPCCPU *cpu = POWERPC_CPU(first_cpu);
|
||||
CPUPPCState *env = &cpu->env;
|
||||
|
||||
if (!val) {
|
||||
/* TODO: We don't support disabling dfp yet */
|
||||
return;
|
||||
}
|
||||
if (!(env->insns_flags2 & PPC2_DFP)) {
|
||||
error_setg(errp, "DFP support not available, try cap-dfp=off");
|
||||
}
|
||||
}
|
||||
|
||||
static void cap_safe_cache_apply(sPAPRMachineState *spapr, uint8_t val,
|
||||
Error **errp)
|
||||
{
|
||||
if (tcg_enabled() && val) {
|
||||
/* TODO - for now only allow broken for TCG */
|
||||
error_setg(errp, "Requested safe cache capability level not supported by tcg, try a different value for cap-cfpc");
|
||||
} else if (kvm_enabled() && (val > kvmppc_get_cap_safe_cache())) {
|
||||
error_setg(errp, "Requested safe cache capability level not supported by kvm, try a different value for cap-cfpc");
|
||||
}
|
||||
}
|
||||
|
||||
static void cap_safe_bounds_check_apply(sPAPRMachineState *spapr, uint8_t val,
|
||||
Error **errp)
|
||||
{
|
||||
if (tcg_enabled() && val) {
|
||||
/* TODO - for now only allow broken for TCG */
|
||||
error_setg(errp, "Requested safe bounds check capability level not supported by tcg, try a different value for cap-sbbc");
|
||||
} else if (kvm_enabled() && (val > kvmppc_get_cap_safe_bounds_check())) {
|
||||
error_setg(errp, "Requested safe bounds check capability level not supported by kvm, try a different value for cap-sbbc");
|
||||
}
|
||||
}
|
||||
|
||||
static void cap_safe_indirect_branch_apply(sPAPRMachineState *spapr,
|
||||
uint8_t val, Error **errp)
|
||||
{
|
||||
if (tcg_enabled() && val) {
|
||||
/* TODO - for now only allow broken for TCG */
|
||||
error_setg(errp, "Requested safe indirect branch capability level not supported by tcg, try a different value for cap-ibs");
|
||||
} else if (kvm_enabled() && (val > kvmppc_get_cap_safe_indirect_branch())) {
|
||||
error_setg(errp, "Requested safe indirect branch capability level not supported by kvm, try a different value for cap-ibs");
|
||||
}
|
||||
}
|
||||
|
||||
#define VALUE_DESC_TRISTATE " (broken, workaround, fixed)"
|
||||
|
||||
sPAPRCapabilityInfo capability_table[SPAPR_CAP_NUM] = {
|
||||
[SPAPR_CAP_HTM] = {
|
||||
.name = "htm",
|
||||
.description = "Allow Hardware Transactional Memory (HTM)",
|
||||
.options = "",
|
||||
.index = SPAPR_CAP_HTM,
|
||||
.get = spapr_cap_get_bool,
|
||||
.set = spapr_cap_set_bool,
|
||||
.type = "bool",
|
||||
.apply = cap_htm_apply,
|
||||
},
|
||||
[SPAPR_CAP_VSX] = {
|
||||
.name = "vsx",
|
||||
.description = "Allow Vector Scalar Extensions (VSX)",
|
||||
.options = "",
|
||||
.index = SPAPR_CAP_VSX,
|
||||
.get = spapr_cap_get_bool,
|
||||
.set = spapr_cap_set_bool,
|
||||
.type = "bool",
|
||||
.apply = cap_vsx_apply,
|
||||
},
|
||||
[SPAPR_CAP_DFP] = {
|
||||
.name = "dfp",
|
||||
.description = "Allow Decimal Floating Point (DFP)",
|
||||
.options = "",
|
||||
.index = SPAPR_CAP_DFP,
|
||||
.get = spapr_cap_get_bool,
|
||||
.set = spapr_cap_set_bool,
|
||||
.type = "bool",
|
||||
.apply = cap_dfp_apply,
|
||||
},
|
||||
[SPAPR_CAP_CFPC] = {
|
||||
.name = "cfpc",
|
||||
.description = "Cache Flush on Privilege Change" VALUE_DESC_TRISTATE,
|
||||
.index = SPAPR_CAP_CFPC,
|
||||
.get = spapr_cap_get_tristate,
|
||||
.set = spapr_cap_set_tristate,
|
||||
.type = "string",
|
||||
.apply = cap_safe_cache_apply,
|
||||
},
|
||||
[SPAPR_CAP_SBBC] = {
|
||||
.name = "sbbc",
|
||||
.description = "Speculation Barrier Bounds Checking" VALUE_DESC_TRISTATE,
|
||||
.index = SPAPR_CAP_SBBC,
|
||||
.get = spapr_cap_get_tristate,
|
||||
.set = spapr_cap_set_tristate,
|
||||
.type = "string",
|
||||
.apply = cap_safe_bounds_check_apply,
|
||||
},
|
||||
[SPAPR_CAP_IBS] = {
|
||||
.name = "ibs",
|
||||
.description = "Indirect Branch Serialisation" VALUE_DESC_TRISTATE,
|
||||
.index = SPAPR_CAP_IBS,
|
||||
.get = spapr_cap_get_tristate,
|
||||
.set = spapr_cap_set_tristate,
|
||||
.type = "string",
|
||||
.apply = cap_safe_indirect_branch_apply,
|
||||
},
|
||||
};
|
||||
|
||||
static sPAPRCapabilities default_caps_with_cpu(sPAPRMachineState *spapr,
|
||||
CPUState *cs)
|
||||
{
|
||||
sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
|
||||
PowerPCCPU *cpu = POWERPC_CPU(cs);
|
||||
sPAPRCapabilities caps;
|
||||
|
||||
caps = smc->default_caps;
|
||||
|
||||
if (!ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_2_07,
|
||||
0, spapr->max_compat_pvr)) {
|
||||
caps.caps[SPAPR_CAP_HTM] = SPAPR_CAP_OFF;
|
||||
}
|
||||
|
||||
if (!ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_2_06,
|
||||
0, spapr->max_compat_pvr)) {
|
||||
caps.caps[SPAPR_CAP_VSX] = SPAPR_CAP_OFF;
|
||||
caps.caps[SPAPR_CAP_DFP] = SPAPR_CAP_OFF;
|
||||
}
|
||||
|
||||
return caps;
|
||||
}
|
||||
|
||||
int spapr_caps_pre_load(void *opaque)
|
||||
{
|
||||
sPAPRMachineState *spapr = opaque;
|
||||
|
||||
/* Set to default so we can tell if this came in with the migration */
|
||||
spapr->mig = spapr->def;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int spapr_caps_pre_save(void *opaque)
|
||||
{
|
||||
sPAPRMachineState *spapr = opaque;
|
||||
|
||||
spapr->mig = spapr->eff;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This has to be called from the top-level spapr post_load, not the
|
||||
* caps specific one. Otherwise it wouldn't be called when the source
|
||||
* caps are all defaults, which could still conflict with overridden
|
||||
* caps on the destination */
|
||||
int spapr_caps_post_migration(sPAPRMachineState *spapr)
|
||||
{
|
||||
int i;
|
||||
bool ok = true;
|
||||
sPAPRCapabilities dstcaps = spapr->eff;
|
||||
sPAPRCapabilities srccaps;
|
||||
|
||||
srccaps = default_caps_with_cpu(spapr, first_cpu);
|
||||
for (i = 0; i < SPAPR_CAP_NUM; i++) {
|
||||
/* If not default value then assume came in with the migration */
|
||||
if (spapr->mig.caps[i] != spapr->def.caps[i]) {
|
||||
srccaps.caps[i] = spapr->mig.caps[i];
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < SPAPR_CAP_NUM; i++) {
|
||||
sPAPRCapabilityInfo *info = &capability_table[i];
|
||||
|
||||
if (srccaps.caps[i] > dstcaps.caps[i]) {
|
||||
error_report("cap-%s higher level (%d) in incoming stream than on destination (%d)",
|
||||
info->name, srccaps.caps[i], dstcaps.caps[i]);
|
||||
ok = false;
|
||||
}
|
||||
|
||||
if (srccaps.caps[i] < dstcaps.caps[i]) {
|
||||
warn_report("cap-%s lower level (%d) in incoming stream than on destination (%d)",
|
||||
info->name, srccaps.caps[i], dstcaps.caps[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return ok ? 0 : -EINVAL;
|
||||
}
|
||||
|
||||
/* Used to generate the migration field and needed function for a spapr cap */
|
||||
#define SPAPR_CAP_MIG_STATE(cap, ccap) \
|
||||
static bool spapr_cap_##cap##_needed(void *opaque) \
|
||||
{ \
|
||||
sPAPRMachineState *spapr = opaque; \
|
||||
\
|
||||
return spapr->cmd_line_caps[SPAPR_CAP_##ccap] && \
|
||||
(spapr->eff.caps[SPAPR_CAP_##ccap] != \
|
||||
spapr->def.caps[SPAPR_CAP_##ccap]); \
|
||||
} \
|
||||
\
|
||||
const VMStateDescription vmstate_spapr_cap_##cap = { \
|
||||
.name = "spapr/cap/" #cap, \
|
||||
.version_id = 1, \
|
||||
.minimum_version_id = 1, \
|
||||
.needed = spapr_cap_##cap##_needed, \
|
||||
.fields = (VMStateField[]) { \
|
||||
VMSTATE_UINT8(mig.caps[SPAPR_CAP_##ccap], \
|
||||
sPAPRMachineState), \
|
||||
VMSTATE_END_OF_LIST() \
|
||||
}, \
|
||||
}
|
||||
|
||||
SPAPR_CAP_MIG_STATE(htm, HTM);
|
||||
SPAPR_CAP_MIG_STATE(vsx, VSX);
|
||||
SPAPR_CAP_MIG_STATE(dfp, DFP);
|
||||
SPAPR_CAP_MIG_STATE(cfpc, CFPC);
|
||||
SPAPR_CAP_MIG_STATE(sbbc, SBBC);
|
||||
SPAPR_CAP_MIG_STATE(ibs, IBS);
|
||||
|
||||
void spapr_caps_reset(sPAPRMachineState *spapr)
|
||||
{
|
||||
sPAPRCapabilities default_caps;
|
||||
int i;
|
||||
|
||||
/* First compute the actual set of caps we're running with.. */
|
||||
default_caps = default_caps_with_cpu(spapr, first_cpu);
|
||||
|
||||
for (i = 0; i < SPAPR_CAP_NUM; i++) {
|
||||
/* Store the defaults */
|
||||
spapr->def.caps[i] = default_caps.caps[i];
|
||||
/* If not set on the command line then apply the default value */
|
||||
if (!spapr->cmd_line_caps[i]) {
|
||||
spapr->eff.caps[i] = default_caps.caps[i];
|
||||
}
|
||||
}
|
||||
|
||||
/* .. then apply those caps to the virtual hardware */
|
||||
|
||||
for (i = 0; i < SPAPR_CAP_NUM; i++) {
|
||||
sPAPRCapabilityInfo *info = &capability_table[i];
|
||||
|
||||
/*
|
||||
* If the apply function can't set the desired level and thinks it's
|
||||
* fatal, it should cause that.
|
||||
*/
|
||||
info->apply(spapr, spapr->eff.caps[i], &error_fatal);
|
||||
}
|
||||
}
|
||||
|
||||
void spapr_caps_add_properties(sPAPRMachineClass *smc, Error **errp)
|
||||
{
|
||||
Error *local_err = NULL;
|
||||
ObjectClass *klass = OBJECT_CLASS(smc);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(capability_table); i++) {
|
||||
sPAPRCapabilityInfo *cap = &capability_table[i];
|
||||
const char *name = g_strdup_printf("cap-%s", cap->name);
|
||||
char *desc;
|
||||
|
||||
object_class_property_add(klass, name, cap->type,
|
||||
cap->get, cap->set,
|
||||
NULL, cap, &local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
return;
|
||||
}
|
||||
|
||||
desc = g_strdup_printf("%s%s", cap->description, cap->options);
|
||||
object_class_property_set_description(klass, name, desc, &local_err);
|
||||
g_free(desc);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -35,6 +35,13 @@ static void spapr_cpu_reset(void *opaque)
|
||||
cs->halted = 1;
|
||||
|
||||
env->spr[SPR_HIOR] = 0;
|
||||
|
||||
/* Set compatibility mode to match the boot CPU, which was either set
|
||||
* by the machine reset code or by CAS. This should never fail.
|
||||
*/
|
||||
if (cs != first_cpu) {
|
||||
ppc_set_compat(cpu, POWERPC_CPU(first_cpu)->compat_pvr, &error_abort);
|
||||
}
|
||||
}
|
||||
|
||||
static void spapr_cpu_destroy(PowerPCCPU *cpu)
|
||||
|
||||
@@ -1655,6 +1655,61 @@ static target_ulong h_client_architecture_support(PowerPCCPU *cpu,
|
||||
return H_SUCCESS;
|
||||
}
|
||||
|
||||
static target_ulong h_get_cpu_characteristics(PowerPCCPU *cpu,
|
||||
sPAPRMachineState *spapr,
|
||||
target_ulong opcode,
|
||||
target_ulong *args)
|
||||
{
|
||||
uint64_t characteristics = H_CPU_CHAR_HON_BRANCH_HINTS &
|
||||
~H_CPU_CHAR_THR_RECONF_TRIG;
|
||||
uint64_t behaviour = H_CPU_BEHAV_FAVOUR_SECURITY;
|
||||
uint8_t safe_cache = spapr_get_cap(spapr, SPAPR_CAP_CFPC);
|
||||
uint8_t safe_bounds_check = spapr_get_cap(spapr, SPAPR_CAP_SBBC);
|
||||
uint8_t safe_indirect_branch = spapr_get_cap(spapr, SPAPR_CAP_IBS);
|
||||
|
||||
switch (safe_cache) {
|
||||
case SPAPR_CAP_WORKAROUND:
|
||||
characteristics |= H_CPU_CHAR_L1D_FLUSH_ORI30;
|
||||
characteristics |= H_CPU_CHAR_L1D_FLUSH_TRIG2;
|
||||
characteristics |= H_CPU_CHAR_L1D_THREAD_PRIV;
|
||||
behaviour |= H_CPU_BEHAV_L1D_FLUSH_PR;
|
||||
break;
|
||||
case SPAPR_CAP_FIXED:
|
||||
break;
|
||||
default: /* broken */
|
||||
assert(safe_cache == SPAPR_CAP_BROKEN);
|
||||
behaviour |= H_CPU_BEHAV_L1D_FLUSH_PR;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (safe_bounds_check) {
|
||||
case SPAPR_CAP_WORKAROUND:
|
||||
characteristics |= H_CPU_CHAR_SPEC_BAR_ORI31;
|
||||
behaviour |= H_CPU_BEHAV_BNDS_CHK_SPEC_BAR;
|
||||
break;
|
||||
case SPAPR_CAP_FIXED:
|
||||
break;
|
||||
default: /* broken */
|
||||
assert(safe_bounds_check == SPAPR_CAP_BROKEN);
|
||||
behaviour |= H_CPU_BEHAV_BNDS_CHK_SPEC_BAR;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (safe_indirect_branch) {
|
||||
case SPAPR_CAP_FIXED:
|
||||
characteristics |= H_CPU_CHAR_BCCTRL_SERIALISED;
|
||||
break;
|
||||
default: /* broken */
|
||||
assert(safe_indirect_branch == SPAPR_CAP_BROKEN);
|
||||
break;
|
||||
}
|
||||
|
||||
args[0] = characteristics;
|
||||
args[1] = behaviour;
|
||||
|
||||
return H_SUCCESS;
|
||||
}
|
||||
|
||||
static spapr_hcall_fn papr_hypercall_table[(MAX_HCALL_OPCODE / 4) + 1];
|
||||
static spapr_hcall_fn kvmppc_hypercall_table[KVMPPC_HCALL_MAX - KVMPPC_HCALL_BASE + 1];
|
||||
|
||||
@@ -1734,6 +1789,10 @@ static void hypercall_register_types(void)
|
||||
spapr_register_hypercall(H_INVALIDATE_PID, h_invalidate_pid);
|
||||
spapr_register_hypercall(H_REGISTER_PROC_TBL, h_register_process_table);
|
||||
|
||||
/* hcall-get-cpu-characteristics */
|
||||
spapr_register_hypercall(H_GET_CPU_CHARACTERISTICS,
|
||||
h_get_cpu_characteristics);
|
||||
|
||||
/* "debugger" hcalls (also used by SLOF). Note: We do -not- differenciate
|
||||
* here between the "CI" and the "CACHE" variants, they will use whatever
|
||||
* mapping attributes qemu is using. When using KVM, the kernel will
|
||||
|
||||
+43
-20
@@ -280,20 +280,6 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, sPAPRMachineState *spapr,
|
||||
int *config_addr_key;
|
||||
Error *err = NULL;
|
||||
|
||||
switch (func) {
|
||||
case RTAS_CHANGE_MSI_FN:
|
||||
case RTAS_CHANGE_FN:
|
||||
ret_intr_type = RTAS_TYPE_MSI;
|
||||
break;
|
||||
case RTAS_CHANGE_MSIX_FN:
|
||||
ret_intr_type = RTAS_TYPE_MSIX;
|
||||
break;
|
||||
default:
|
||||
error_report("rtas_ibm_change_msi(%u) is not implemented", func);
|
||||
rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Fins sPAPRPHBState */
|
||||
phb = spapr_pci_find_phb(spapr, buid);
|
||||
if (phb) {
|
||||
@@ -304,6 +290,39 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, sPAPRMachineState *spapr,
|
||||
return;
|
||||
}
|
||||
|
||||
switch (func) {
|
||||
case RTAS_CHANGE_FN:
|
||||
if (msi_present(pdev)) {
|
||||
ret_intr_type = RTAS_TYPE_MSI;
|
||||
} else if (msix_present(pdev)) {
|
||||
ret_intr_type = RTAS_TYPE_MSIX;
|
||||
} else {
|
||||
rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case RTAS_CHANGE_MSI_FN:
|
||||
if (msi_present(pdev)) {
|
||||
ret_intr_type = RTAS_TYPE_MSI;
|
||||
} else {
|
||||
rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case RTAS_CHANGE_MSIX_FN:
|
||||
if (msix_present(pdev)) {
|
||||
ret_intr_type = RTAS_TYPE_MSIX;
|
||||
} else {
|
||||
rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
error_report("rtas_ibm_change_msi(%u) is not implemented", func);
|
||||
rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
msi = (spapr_pci_msi *) g_hash_table_lookup(phb->msi, &config_addr);
|
||||
|
||||
/* Releasing MSIs */
|
||||
@@ -1286,13 +1305,17 @@ static void spapr_populate_pci_child_dt(PCIDevice *dev, void *fdt, int offset,
|
||||
_FDT(fdt_setprop_cell(fdt, offset, "#size-cells",
|
||||
RESOURCE_CELLS_SIZE));
|
||||
|
||||
max_msi = msi_nr_vectors_allocated(dev);
|
||||
if (max_msi) {
|
||||
_FDT(fdt_setprop_cell(fdt, offset, "ibm,req#msi", max_msi));
|
||||
if (msi_present(dev)) {
|
||||
max_msi = msi_nr_vectors_allocated(dev);
|
||||
if (max_msi) {
|
||||
_FDT(fdt_setprop_cell(fdt, offset, "ibm,req#msi", max_msi));
|
||||
}
|
||||
}
|
||||
max_msix = dev->msix_entries_nr;
|
||||
if (max_msix) {
|
||||
_FDT(fdt_setprop_cell(fdt, offset, "ibm,req#msi-x", max_msix));
|
||||
if (msix_present(dev)) {
|
||||
max_msix = dev->msix_entries_nr;
|
||||
if (max_msix) {
|
||||
_FDT(fdt_setprop_cell(fdt, offset, "ibm,req#msi-x", max_msix));
|
||||
}
|
||||
}
|
||||
|
||||
populate_resource_props(dev, &rp);
|
||||
|
||||
@@ -293,10 +293,10 @@ static void write_event_mask(SCLPEventFacility *ef, SCCB *sccb)
|
||||
ef->receive_mask = be32_to_cpu(tmp_mask);
|
||||
|
||||
/* return the SCLP's capability masks to the guest */
|
||||
tmp_mask = cpu_to_be32(get_host_send_mask(ef));
|
||||
tmp_mask = cpu_to_be32(get_host_receive_mask(ef));
|
||||
copy_mask(WEM_RECEIVE_MASK(we_mask, mask_length), (uint8_t *)&tmp_mask,
|
||||
mask_length, sizeof(tmp_mask));
|
||||
tmp_mask = cpu_to_be32(get_host_receive_mask(ef));
|
||||
tmp_mask = cpu_to_be32(get_host_send_mask(ef));
|
||||
copy_mask(WEM_SEND_MASK(we_mask, mask_length), (uint8_t *)&tmp_mask,
|
||||
mask_length, sizeof(tmp_mask));
|
||||
|
||||
|
||||
@@ -116,7 +116,7 @@ static void kvm_s390_stattrib_synchronize(S390StAttribState *sa)
|
||||
for (cx = 0; cx + len <= max; cx += len) {
|
||||
clog.start_gfn = cx;
|
||||
clog.count = len;
|
||||
clog.values = (uint64_t)(sas->incoming_buffer + cx * len);
|
||||
clog.values = (uint64_t)(sas->incoming_buffer + cx);
|
||||
r = kvm_vm_ioctl(kvm_state, KVM_S390_SET_CMMA_BITS, &clog);
|
||||
if (r) {
|
||||
error_report("KVM_S390_SET_CMMA_BITS failed: %s", strerror(-r));
|
||||
@@ -126,7 +126,7 @@ static void kvm_s390_stattrib_synchronize(S390StAttribState *sa)
|
||||
if (cx < max) {
|
||||
clog.start_gfn = cx;
|
||||
clog.count = max - cx;
|
||||
clog.values = (uint64_t)(sas->incoming_buffer + cx * len);
|
||||
clog.values = (uint64_t)(sas->incoming_buffer + cx);
|
||||
r = kvm_vm_ioctl(kvm_state, KVM_S390_SET_CMMA_BITS, &clog);
|
||||
if (r) {
|
||||
error_report("KVM_S390_SET_CMMA_BITS failed: %s", strerror(-r));
|
||||
|
||||
+8
-1
@@ -224,6 +224,7 @@ static void scsi_qdev_unrealize(DeviceState *qdev, Error **errp)
|
||||
/* handle legacy '-drive if=scsi,...' cmd line args */
|
||||
SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockBackend *blk,
|
||||
int unit, bool removable, int bootindex,
|
||||
bool share_rw,
|
||||
const char *serial, Error **errp)
|
||||
{
|
||||
const char *driver;
|
||||
@@ -254,6 +255,12 @@ SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockBackend *blk,
|
||||
object_unparent(OBJECT(dev));
|
||||
return NULL;
|
||||
}
|
||||
object_property_set_bool(OBJECT(dev), share_rw, "share-rw", &err);
|
||||
if (err != NULL) {
|
||||
error_propagate(errp, err);
|
||||
object_unparent(OBJECT(dev));
|
||||
return NULL;
|
||||
}
|
||||
object_property_set_bool(OBJECT(dev), true, "realized", &err);
|
||||
if (err != NULL) {
|
||||
error_propagate(errp, err);
|
||||
@@ -288,7 +295,7 @@ void scsi_bus_legacy_handle_cmdline(SCSIBus *bus, bool deprecated)
|
||||
}
|
||||
}
|
||||
scsi_bus_legacy_add_drive(bus, blk_by_legacy_dinfo(dinfo),
|
||||
unit, false, -1, NULL, &error_fatal);
|
||||
unit, false, -1, false, NULL, &error_fatal);
|
||||
}
|
||||
loc_pop(&loc);
|
||||
}
|
||||
|
||||
@@ -1755,6 +1755,7 @@ static void scsi_write_same_complete(void *opaque, int ret)
|
||||
data->sector << BDRV_SECTOR_BITS,
|
||||
&data->qiov, 0,
|
||||
scsi_write_same_complete, data);
|
||||
aio_context_release(blk_get_aio_context(s->qdev.conf.blk));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -248,6 +248,10 @@ static void milkymist_memcard_reset(DeviceState *d)
|
||||
for (i = 0; i < R_MAX; i++) {
|
||||
s->regs[i] = 0;
|
||||
}
|
||||
/* Since we're still using the legacy SD API the card is not plugged
|
||||
* into any bus, and we must reset it manually.
|
||||
*/
|
||||
device_reset(DEVICE(s->card));
|
||||
}
|
||||
|
||||
static int milkymist_memcard_init(SysBusDevice *dev)
|
||||
|
||||
@@ -480,6 +480,10 @@ static void pl181_reset(DeviceState *d)
|
||||
|
||||
/* We can assume our GPIO outputs have been wired up now */
|
||||
sd_set_cb(s->card, s->cardstatus[0], s->cardstatus[1]);
|
||||
/* Since we're still using the legacy SD API the card is not plugged
|
||||
* into any bus, and we must reset it manually.
|
||||
*/
|
||||
device_reset(DEVICE(s->card));
|
||||
}
|
||||
|
||||
static void pl181_init(Object *obj)
|
||||
|
||||
+23
-2
@@ -50,6 +50,9 @@ typedef struct {
|
||||
SDState *sd;
|
||||
} ssi_sd_state;
|
||||
|
||||
#define TYPE_SSI_SD "ssi-sd"
|
||||
#define SSI_SD(obj) OBJECT_CHECK(ssi_sd_state, (obj), TYPE_SSI_SD)
|
||||
|
||||
/* State word bits. */
|
||||
#define SSI_SDR_LOCKED 0x0001
|
||||
#define SSI_SDR_WP_ERASE 0x0002
|
||||
@@ -241,7 +244,6 @@ static void ssi_sd_realize(SSISlave *d, Error **errp)
|
||||
ssi_sd_state *s = FROM_SSI_SLAVE(ssi_sd_state, d);
|
||||
DriveInfo *dinfo;
|
||||
|
||||
s->mode = SSI_SD_CMD;
|
||||
/* FIXME use a qdev drive property instead of drive_get_next() */
|
||||
dinfo = drive_get_next(IF_SD);
|
||||
s->sd = sd_init(dinfo ? blk_by_legacy_dinfo(dinfo) : NULL, true);
|
||||
@@ -251,6 +253,24 @@ static void ssi_sd_realize(SSISlave *d, Error **errp)
|
||||
}
|
||||
}
|
||||
|
||||
static void ssi_sd_reset(DeviceState *dev)
|
||||
{
|
||||
ssi_sd_state *s = SSI_SD(dev);
|
||||
|
||||
s->mode = SSI_SD_CMD;
|
||||
s->cmd = 0;
|
||||
memset(s->cmdarg, 0, sizeof(s->cmdarg));
|
||||
memset(s->response, 0, sizeof(s->response));
|
||||
s->arglen = 0;
|
||||
s->response_pos = 0;
|
||||
s->stopping = 0;
|
||||
|
||||
/* Since we're still using the legacy SD API the card is not plugged
|
||||
* into any bus, and we must reset it manually.
|
||||
*/
|
||||
device_reset(DEVICE(s->sd));
|
||||
}
|
||||
|
||||
static void ssi_sd_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
@@ -260,10 +280,11 @@ static void ssi_sd_class_init(ObjectClass *klass, void *data)
|
||||
k->transfer = ssi_sd_transfer;
|
||||
k->cs_polarity = SSI_CS_LOW;
|
||||
dc->vmsd = &vmstate_ssi_sd;
|
||||
dc->reset = ssi_sd_reset;
|
||||
}
|
||||
|
||||
static const TypeInfo ssi_sd_info = {
|
||||
.name = "ssi-sd",
|
||||
.name = TYPE_SSI_SD,
|
||||
.parent = TYPE_SSI_SLAVE,
|
||||
.instance_size = sizeof(ssi_sd_state),
|
||||
.class_init = ssi_sd_class_init,
|
||||
|
||||
@@ -635,7 +635,8 @@ static void usb_msd_realize_storage(USBDevice *dev, Error **errp)
|
||||
scsi_bus_new(&s->bus, sizeof(s->bus), DEVICE(dev),
|
||||
&usb_msd_scsi_info_storage, NULL);
|
||||
scsi_dev = scsi_bus_legacy_add_drive(&s->bus, blk, 0, !!s->removable,
|
||||
s->conf.bootindex, dev->serial,
|
||||
s->conf.bootindex, s->conf.share_rw,
|
||||
dev->serial,
|
||||
&err);
|
||||
blk_unref(blk);
|
||||
if (!scsi_dev) {
|
||||
|
||||
@@ -968,6 +968,7 @@ static int vfio_connect_container(VFIOGroup *group, AddressSpace *as,
|
||||
if (!ioctl(group->fd, VFIO_GROUP_SET_CONTAINER, &container->fd)) {
|
||||
group->container = container;
|
||||
QLIST_INSERT_HEAD(&container->group_list, group, container_next);
|
||||
vfio_kvm_device_add_group(group);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -317,11 +317,14 @@ static int vhost_user_set_mem_table(struct vhost_dev *dev,
|
||||
&offset);
|
||||
fd = memory_region_get_fd(mr);
|
||||
if (fd > 0) {
|
||||
if (fd_num == VHOST_MEMORY_MAX_NREGIONS) {
|
||||
error_report("Failed preparing vhost-user memory table msg");
|
||||
return -1;
|
||||
}
|
||||
msg.payload.memory.regions[fd_num].userspace_addr = reg->userspace_addr;
|
||||
msg.payload.memory.regions[fd_num].memory_size = reg->memory_size;
|
||||
msg.payload.memory.regions[fd_num].guest_phys_addr = reg->guest_phys_addr;
|
||||
msg.payload.memory.regions[fd_num].mmap_offset = offset;
|
||||
assert(fd_num < VHOST_MEMORY_MAX_NREGIONS);
|
||||
fds[fd_num++] = fd;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -2469,7 +2469,7 @@ void GCC_FMT_ATTR(2, 3) virtio_error(VirtIODevice *vdev, const char *fmt, ...)
|
||||
va_end(ap);
|
||||
|
||||
if (virtio_vdev_has_feature(vdev, VIRTIO_F_VERSION_1)) {
|
||||
virtio_set_status(vdev, vdev->status | VIRTIO_CONFIG_S_NEEDS_RESET);
|
||||
vdev->status = vdev->status | VIRTIO_CONFIG_S_NEEDS_RESET;
|
||||
virtio_notify_config(vdev);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#ifndef HW_COMPAT_H
|
||||
#define HW_COMPAT_H
|
||||
|
||||
#define HW_COMPAT_2_11
|
||||
|
||||
#define HW_COMPAT_2_10 \
|
||||
{\
|
||||
.driver = "virtio-mouse-device",\
|
||||
|
||||
@@ -50,6 +50,41 @@ typedef enum {
|
||||
SPAPR_RESIZE_HPT_REQUIRED,
|
||||
} sPAPRResizeHPT;
|
||||
|
||||
/**
|
||||
* Capabilities
|
||||
*/
|
||||
|
||||
/* Hardware Transactional Memory */
|
||||
#define SPAPR_CAP_HTM 0x00
|
||||
/* Vector Scalar Extensions */
|
||||
#define SPAPR_CAP_VSX 0x01
|
||||
/* Decimal Floating Point */
|
||||
#define SPAPR_CAP_DFP 0x02
|
||||
/* Cache Flush on Privilege Change */
|
||||
#define SPAPR_CAP_CFPC 0x03
|
||||
/* Speculation Barrier Bounds Checking */
|
||||
#define SPAPR_CAP_SBBC 0x04
|
||||
/* Indirect Branch Serialisation */
|
||||
#define SPAPR_CAP_IBS 0x05
|
||||
/* Num Caps */
|
||||
#define SPAPR_CAP_NUM (SPAPR_CAP_IBS + 1)
|
||||
|
||||
/*
|
||||
* Capability Values
|
||||
*/
|
||||
/* Bool Caps */
|
||||
#define SPAPR_CAP_OFF 0x00
|
||||
#define SPAPR_CAP_ON 0x01
|
||||
/* Broken | Workaround | Fixed Caps */
|
||||
#define SPAPR_CAP_BROKEN 0x00
|
||||
#define SPAPR_CAP_WORKAROUND 0x01
|
||||
#define SPAPR_CAP_FIXED 0x02
|
||||
|
||||
typedef struct sPAPRCapabilities sPAPRCapabilities;
|
||||
struct sPAPRCapabilities {
|
||||
uint8_t caps[SPAPR_CAP_NUM];
|
||||
};
|
||||
|
||||
/**
|
||||
* sPAPRMachineClass:
|
||||
*/
|
||||
@@ -66,6 +101,7 @@ struct sPAPRMachineClass {
|
||||
hwaddr *mmio32, hwaddr *mmio64,
|
||||
unsigned n_dma, uint32_t *liobns, Error **errp);
|
||||
sPAPRResizeHPT resize_hpt_default;
|
||||
sPAPRCapabilities default_caps;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -127,6 +163,9 @@ struct sPAPRMachineState {
|
||||
MemoryHotplugState hotplug_memory;
|
||||
|
||||
const char *icp_type;
|
||||
|
||||
bool cmd_line_caps[SPAPR_CAP_NUM];
|
||||
sPAPRCapabilities def, eff, mig;
|
||||
};
|
||||
|
||||
#define H_SUCCESS 0
|
||||
@@ -266,6 +305,18 @@ struct sPAPRMachineState {
|
||||
#define H_DABRX_KERNEL (1ULL<<(63-62))
|
||||
#define H_DABRX_USER (1ULL<<(63-63))
|
||||
|
||||
/* Values for KVM_PPC_GET_CPU_CHAR & H_GET_CPU_CHARACTERISTICS */
|
||||
#define H_CPU_CHAR_SPEC_BAR_ORI31 PPC_BIT(0)
|
||||
#define H_CPU_CHAR_BCCTRL_SERIALISED PPC_BIT(1)
|
||||
#define H_CPU_CHAR_L1D_FLUSH_ORI30 PPC_BIT(2)
|
||||
#define H_CPU_CHAR_L1D_FLUSH_TRIG2 PPC_BIT(3)
|
||||
#define H_CPU_CHAR_L1D_THREAD_PRIV PPC_BIT(4)
|
||||
#define H_CPU_CHAR_HON_BRANCH_HINTS PPC_BIT(5)
|
||||
#define H_CPU_CHAR_THR_RECONF_TRIG PPC_BIT(6)
|
||||
#define H_CPU_BEHAV_FAVOUR_SECURITY PPC_BIT(0)
|
||||
#define H_CPU_BEHAV_L1D_FLUSH_PR PPC_BIT(1)
|
||||
#define H_CPU_BEHAV_BNDS_CHK_SPEC_BAR PPC_BIT(2)
|
||||
|
||||
/* Each control block has to be on a 4K boundary */
|
||||
#define H_CB_ALIGNMENT 4096
|
||||
|
||||
@@ -353,6 +404,7 @@ struct sPAPRMachineState {
|
||||
#define H_GET_HCA_INFO 0x1B8
|
||||
#define H_GET_PERF_COUNT 0x1BC
|
||||
#define H_MANAGE_TRACE 0x1C0
|
||||
#define H_GET_CPU_CHARACTERISTICS 0x1C8
|
||||
#define H_FREE_LOGICAL_LAN_BUFFER 0x1D4
|
||||
#define H_QUERY_INT_STATE 0x1E4
|
||||
#define H_POLL_PENDING 0x1D8
|
||||
@@ -707,4 +759,26 @@ void spapr_do_system_reset_on_cpu(CPUState *cs, run_on_cpu_data arg);
|
||||
int spapr_vcpu_id(PowerPCCPU *cpu);
|
||||
PowerPCCPU *spapr_find_cpu(int vcpu_id);
|
||||
|
||||
int spapr_caps_pre_load(void *opaque);
|
||||
int spapr_caps_pre_save(void *opaque);
|
||||
|
||||
/*
|
||||
* Handling of optional capabilities
|
||||
*/
|
||||
extern const VMStateDescription vmstate_spapr_cap_htm;
|
||||
extern const VMStateDescription vmstate_spapr_cap_vsx;
|
||||
extern const VMStateDescription vmstate_spapr_cap_dfp;
|
||||
extern const VMStateDescription vmstate_spapr_cap_cfpc;
|
||||
extern const VMStateDescription vmstate_spapr_cap_sbbc;
|
||||
extern const VMStateDescription vmstate_spapr_cap_ibs;
|
||||
|
||||
static inline uint8_t spapr_get_cap(sPAPRMachineState *spapr, int cap)
|
||||
{
|
||||
return spapr->eff.caps[cap];
|
||||
}
|
||||
|
||||
void spapr_caps_reset(sPAPRMachineState *spapr);
|
||||
void spapr_caps_add_properties(sPAPRMachineClass *smc, Error **errp);
|
||||
int spapr_caps_post_migration(sPAPRMachineState *spapr);
|
||||
|
||||
#endif /* HW_SPAPR_H */
|
||||
|
||||
@@ -151,6 +151,7 @@ static inline SCSIBus *scsi_bus_from_device(SCSIDevice *d)
|
||||
|
||||
SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockBackend *blk,
|
||||
int unit, bool removable, int bootindex,
|
||||
bool share_rw,
|
||||
const char *serial, Error **errp);
|
||||
void scsi_bus_legacy_handle_cmdline(SCSIBus *bus, bool deprecated);
|
||||
void scsi_legacy_handle_cmdline(void);
|
||||
|
||||
@@ -76,7 +76,11 @@ extern const struct SCSISense sense_code_LUN_FAILURE;
|
||||
extern const struct SCSISense sense_code_LUN_COMM_FAILURE;
|
||||
/* Command aborted, Overlapped Commands Attempted */
|
||||
extern const struct SCSISense sense_code_OVERLAPPED_COMMANDS;
|
||||
/* LUN not ready, Capacity data has changed */
|
||||
/* Medium error, Unrecovered read error */
|
||||
extern const struct SCSISense sense_code_READ_ERROR;
|
||||
/* LUN not ready, Cause not reportable */
|
||||
extern const struct SCSISense sense_code_NOT_READY;
|
||||
/* Unit attention, Capacity data has changed */
|
||||
extern const struct SCSISense sense_code_CAPACITY_CHANGED;
|
||||
/* Unit attention, SCSI bus reset */
|
||||
extern const struct SCSISense sense_code_SCSI_BUS_RESET;
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
|
||||
/*
|
||||
* Definitions for virtio-ccw devices.
|
||||
*
|
||||
* Copyright IBM Corp. 2013
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License (version 2 only)
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* Author(s): Cornelia Huck <cornelia.huck@de.ibm.com>
|
||||
*/
|
||||
#ifndef __KVM_VIRTIO_CCW_H
|
||||
|
||||
@@ -1,393 +1 @@
|
||||
#ifndef _ASM_X86_HYPERV_H
|
||||
#define _ASM_X86_HYPERV_H
|
||||
|
||||
#include "standard-headers/linux/types.h"
|
||||
|
||||
/*
|
||||
* The below CPUID leaves are present if VersionAndFeatures.HypervisorPresent
|
||||
* is set by CPUID(HvCpuIdFunctionVersionAndFeatures).
|
||||
*/
|
||||
#define HYPERV_CPUID_VENDOR_AND_MAX_FUNCTIONS 0x40000000
|
||||
#define HYPERV_CPUID_INTERFACE 0x40000001
|
||||
#define HYPERV_CPUID_VERSION 0x40000002
|
||||
#define HYPERV_CPUID_FEATURES 0x40000003
|
||||
#define HYPERV_CPUID_ENLIGHTMENT_INFO 0x40000004
|
||||
#define HYPERV_CPUID_IMPLEMENT_LIMITS 0x40000005
|
||||
|
||||
#define HYPERV_HYPERVISOR_PRESENT_BIT 0x80000000
|
||||
#define HYPERV_CPUID_MIN 0x40000005
|
||||
#define HYPERV_CPUID_MAX 0x4000ffff
|
||||
|
||||
/*
|
||||
* Feature identification. EAX indicates which features are available
|
||||
* to the partition based upon the current partition privileges.
|
||||
*/
|
||||
|
||||
/* VP Runtime (HV_X64_MSR_VP_RUNTIME) available */
|
||||
#define HV_X64_MSR_VP_RUNTIME_AVAILABLE (1 << 0)
|
||||
/* Partition Reference Counter (HV_X64_MSR_TIME_REF_COUNT) available*/
|
||||
#define HV_X64_MSR_TIME_REF_COUNT_AVAILABLE (1 << 1)
|
||||
/* Partition reference TSC MSR is available */
|
||||
#define HV_X64_MSR_REFERENCE_TSC_AVAILABLE (1 << 9)
|
||||
|
||||
/* A partition's reference time stamp counter (TSC) page */
|
||||
#define HV_X64_MSR_REFERENCE_TSC 0x40000021
|
||||
|
||||
/*
|
||||
* There is a single feature flag that signifies if the partition has access
|
||||
* to MSRs with local APIC and TSC frequencies.
|
||||
*/
|
||||
#define HV_X64_ACCESS_FREQUENCY_MSRS (1 << 11)
|
||||
|
||||
/*
|
||||
* Basic SynIC MSRs (HV_X64_MSR_SCONTROL through HV_X64_MSR_EOM
|
||||
* and HV_X64_MSR_SINT0 through HV_X64_MSR_SINT15) available
|
||||
*/
|
||||
#define HV_X64_MSR_SYNIC_AVAILABLE (1 << 2)
|
||||
/*
|
||||
* Synthetic Timer MSRs (HV_X64_MSR_STIMER0_CONFIG through
|
||||
* HV_X64_MSR_STIMER3_COUNT) available
|
||||
*/
|
||||
#define HV_X64_MSR_SYNTIMER_AVAILABLE (1 << 3)
|
||||
/*
|
||||
* APIC access MSRs (HV_X64_MSR_EOI, HV_X64_MSR_ICR and HV_X64_MSR_TPR)
|
||||
* are available
|
||||
*/
|
||||
#define HV_X64_MSR_APIC_ACCESS_AVAILABLE (1 << 4)
|
||||
/* Hypercall MSRs (HV_X64_MSR_GUEST_OS_ID and HV_X64_MSR_HYPERCALL) available*/
|
||||
#define HV_X64_MSR_HYPERCALL_AVAILABLE (1 << 5)
|
||||
/* Access virtual processor index MSR (HV_X64_MSR_VP_INDEX) available*/
|
||||
#define HV_X64_MSR_VP_INDEX_AVAILABLE (1 << 6)
|
||||
/* Virtual system reset MSR (HV_X64_MSR_RESET) is available*/
|
||||
#define HV_X64_MSR_RESET_AVAILABLE (1 << 7)
|
||||
/*
|
||||
* Access statistics pages MSRs (HV_X64_MSR_STATS_PARTITION_RETAIL_PAGE,
|
||||
* HV_X64_MSR_STATS_PARTITION_INTERNAL_PAGE, HV_X64_MSR_STATS_VP_RETAIL_PAGE,
|
||||
* HV_X64_MSR_STATS_VP_INTERNAL_PAGE) available
|
||||
*/
|
||||
#define HV_X64_MSR_STAT_PAGES_AVAILABLE (1 << 8)
|
||||
|
||||
/* Frequency MSRs available */
|
||||
#define HV_FEATURE_FREQUENCY_MSRS_AVAILABLE (1 << 8)
|
||||
|
||||
/* Crash MSR available */
|
||||
#define HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE (1 << 10)
|
||||
|
||||
/*
|
||||
* Feature identification: EBX indicates which flags were specified at
|
||||
* partition creation. The format is the same as the partition creation
|
||||
* flag structure defined in section Partition Creation Flags.
|
||||
*/
|
||||
#define HV_X64_CREATE_PARTITIONS (1 << 0)
|
||||
#define HV_X64_ACCESS_PARTITION_ID (1 << 1)
|
||||
#define HV_X64_ACCESS_MEMORY_POOL (1 << 2)
|
||||
#define HV_X64_ADJUST_MESSAGE_BUFFERS (1 << 3)
|
||||
#define HV_X64_POST_MESSAGES (1 << 4)
|
||||
#define HV_X64_SIGNAL_EVENTS (1 << 5)
|
||||
#define HV_X64_CREATE_PORT (1 << 6)
|
||||
#define HV_X64_CONNECT_PORT (1 << 7)
|
||||
#define HV_X64_ACCESS_STATS (1 << 8)
|
||||
#define HV_X64_DEBUGGING (1 << 11)
|
||||
#define HV_X64_CPU_POWER_MANAGEMENT (1 << 12)
|
||||
#define HV_X64_CONFIGURE_PROFILER (1 << 13)
|
||||
|
||||
/*
|
||||
* Feature identification. EDX indicates which miscellaneous features
|
||||
* are available to the partition.
|
||||
*/
|
||||
/* The MWAIT instruction is available (per section MONITOR / MWAIT) */
|
||||
#define HV_X64_MWAIT_AVAILABLE (1 << 0)
|
||||
/* Guest debugging support is available */
|
||||
#define HV_X64_GUEST_DEBUGGING_AVAILABLE (1 << 1)
|
||||
/* Performance Monitor support is available*/
|
||||
#define HV_X64_PERF_MONITOR_AVAILABLE (1 << 2)
|
||||
/* Support for physical CPU dynamic partitioning events is available*/
|
||||
#define HV_X64_CPU_DYNAMIC_PARTITIONING_AVAILABLE (1 << 3)
|
||||
/*
|
||||
* Support for passing hypercall input parameter block via XMM
|
||||
* registers is available
|
||||
*/
|
||||
#define HV_X64_HYPERCALL_PARAMS_XMM_AVAILABLE (1 << 4)
|
||||
/* Support for a virtual guest idle state is available */
|
||||
#define HV_X64_GUEST_IDLE_STATE_AVAILABLE (1 << 5)
|
||||
/* Guest crash data handler available */
|
||||
#define HV_X64_GUEST_CRASH_MSR_AVAILABLE (1 << 10)
|
||||
|
||||
/*
|
||||
* Implementation recommendations. Indicates which behaviors the hypervisor
|
||||
* recommends the OS implement for optimal performance.
|
||||
*/
|
||||
/*
|
||||
* Recommend using hypercall for address space switches rather
|
||||
* than MOV to CR3 instruction
|
||||
*/
|
||||
#define HV_X64_AS_SWITCH_RECOMMENDED (1 << 0)
|
||||
/* Recommend using hypercall for local TLB flushes rather
|
||||
* than INVLPG or MOV to CR3 instructions */
|
||||
#define HV_X64_LOCAL_TLB_FLUSH_RECOMMENDED (1 << 1)
|
||||
/*
|
||||
* Recommend using hypercall for remote TLB flushes rather
|
||||
* than inter-processor interrupts
|
||||
*/
|
||||
#define HV_X64_REMOTE_TLB_FLUSH_RECOMMENDED (1 << 2)
|
||||
/*
|
||||
* Recommend using MSRs for accessing APIC registers
|
||||
* EOI, ICR and TPR rather than their memory-mapped counterparts
|
||||
*/
|
||||
#define HV_X64_APIC_ACCESS_RECOMMENDED (1 << 3)
|
||||
/* Recommend using the hypervisor-provided MSR to initiate a system RESET */
|
||||
#define HV_X64_SYSTEM_RESET_RECOMMENDED (1 << 4)
|
||||
/*
|
||||
* Recommend using relaxed timing for this partition. If used,
|
||||
* the VM should disable any watchdog timeouts that rely on the
|
||||
* timely delivery of external interrupts
|
||||
*/
|
||||
#define HV_X64_RELAXED_TIMING_RECOMMENDED (1 << 5)
|
||||
|
||||
/*
|
||||
* Virtual APIC support
|
||||
*/
|
||||
#define HV_X64_DEPRECATING_AEOI_RECOMMENDED (1 << 9)
|
||||
|
||||
/* Recommend using the newer ExProcessorMasks interface */
|
||||
#define HV_X64_EX_PROCESSOR_MASKS_RECOMMENDED (1 << 11)
|
||||
|
||||
/*
|
||||
* Crash notification flag.
|
||||
*/
|
||||
#define HV_CRASH_CTL_CRASH_NOTIFY (1ULL << 63)
|
||||
|
||||
/* MSR used to identify the guest OS. */
|
||||
#define HV_X64_MSR_GUEST_OS_ID 0x40000000
|
||||
|
||||
/* MSR used to setup pages used to communicate with the hypervisor. */
|
||||
#define HV_X64_MSR_HYPERCALL 0x40000001
|
||||
|
||||
/* MSR used to provide vcpu index */
|
||||
#define HV_X64_MSR_VP_INDEX 0x40000002
|
||||
|
||||
/* MSR used to reset the guest OS. */
|
||||
#define HV_X64_MSR_RESET 0x40000003
|
||||
|
||||
/* MSR used to provide vcpu runtime in 100ns units */
|
||||
#define HV_X64_MSR_VP_RUNTIME 0x40000010
|
||||
|
||||
/* MSR used to read the per-partition time reference counter */
|
||||
#define HV_X64_MSR_TIME_REF_COUNT 0x40000020
|
||||
|
||||
/* MSR used to retrieve the TSC frequency */
|
||||
#define HV_X64_MSR_TSC_FREQUENCY 0x40000022
|
||||
|
||||
/* MSR used to retrieve the local APIC timer frequency */
|
||||
#define HV_X64_MSR_APIC_FREQUENCY 0x40000023
|
||||
|
||||
/* Define the virtual APIC registers */
|
||||
#define HV_X64_MSR_EOI 0x40000070
|
||||
#define HV_X64_MSR_ICR 0x40000071
|
||||
#define HV_X64_MSR_TPR 0x40000072
|
||||
#define HV_X64_MSR_APIC_ASSIST_PAGE 0x40000073
|
||||
|
||||
/* Define synthetic interrupt controller model specific registers. */
|
||||
#define HV_X64_MSR_SCONTROL 0x40000080
|
||||
#define HV_X64_MSR_SVERSION 0x40000081
|
||||
#define HV_X64_MSR_SIEFP 0x40000082
|
||||
#define HV_X64_MSR_SIMP 0x40000083
|
||||
#define HV_X64_MSR_EOM 0x40000084
|
||||
#define HV_X64_MSR_SINT0 0x40000090
|
||||
#define HV_X64_MSR_SINT1 0x40000091
|
||||
#define HV_X64_MSR_SINT2 0x40000092
|
||||
#define HV_X64_MSR_SINT3 0x40000093
|
||||
#define HV_X64_MSR_SINT4 0x40000094
|
||||
#define HV_X64_MSR_SINT5 0x40000095
|
||||
#define HV_X64_MSR_SINT6 0x40000096
|
||||
#define HV_X64_MSR_SINT7 0x40000097
|
||||
#define HV_X64_MSR_SINT8 0x40000098
|
||||
#define HV_X64_MSR_SINT9 0x40000099
|
||||
#define HV_X64_MSR_SINT10 0x4000009A
|
||||
#define HV_X64_MSR_SINT11 0x4000009B
|
||||
#define HV_X64_MSR_SINT12 0x4000009C
|
||||
#define HV_X64_MSR_SINT13 0x4000009D
|
||||
#define HV_X64_MSR_SINT14 0x4000009E
|
||||
#define HV_X64_MSR_SINT15 0x4000009F
|
||||
|
||||
/*
|
||||
* Synthetic Timer MSRs. Four timers per vcpu.
|
||||
*/
|
||||
#define HV_X64_MSR_STIMER0_CONFIG 0x400000B0
|
||||
#define HV_X64_MSR_STIMER0_COUNT 0x400000B1
|
||||
#define HV_X64_MSR_STIMER1_CONFIG 0x400000B2
|
||||
#define HV_X64_MSR_STIMER1_COUNT 0x400000B3
|
||||
#define HV_X64_MSR_STIMER2_CONFIG 0x400000B4
|
||||
#define HV_X64_MSR_STIMER2_COUNT 0x400000B5
|
||||
#define HV_X64_MSR_STIMER3_CONFIG 0x400000B6
|
||||
#define HV_X64_MSR_STIMER3_COUNT 0x400000B7
|
||||
|
||||
/* Hyper-V guest crash notification MSR's */
|
||||
#define HV_X64_MSR_CRASH_P0 0x40000100
|
||||
#define HV_X64_MSR_CRASH_P1 0x40000101
|
||||
#define HV_X64_MSR_CRASH_P2 0x40000102
|
||||
#define HV_X64_MSR_CRASH_P3 0x40000103
|
||||
#define HV_X64_MSR_CRASH_P4 0x40000104
|
||||
#define HV_X64_MSR_CRASH_CTL 0x40000105
|
||||
#define HV_X64_MSR_CRASH_CTL_NOTIFY (1ULL << 63)
|
||||
#define HV_X64_MSR_CRASH_PARAMS \
|
||||
(1 + (HV_X64_MSR_CRASH_P4 - HV_X64_MSR_CRASH_P0))
|
||||
|
||||
#define HV_X64_MSR_HYPERCALL_ENABLE 0x00000001
|
||||
#define HV_X64_MSR_HYPERCALL_PAGE_ADDRESS_SHIFT 12
|
||||
#define HV_X64_MSR_HYPERCALL_PAGE_ADDRESS_MASK \
|
||||
(~((1ull << HV_X64_MSR_HYPERCALL_PAGE_ADDRESS_SHIFT) - 1))
|
||||
|
||||
/* Declare the various hypercall operations. */
|
||||
#define HVCALL_FLUSH_VIRTUAL_ADDRESS_SPACE 0x0002
|
||||
#define HVCALL_FLUSH_VIRTUAL_ADDRESS_LIST 0x0003
|
||||
#define HVCALL_NOTIFY_LONG_SPIN_WAIT 0x0008
|
||||
#define HVCALL_FLUSH_VIRTUAL_ADDRESS_SPACE_EX 0x0013
|
||||
#define HVCALL_FLUSH_VIRTUAL_ADDRESS_LIST_EX 0x0014
|
||||
#define HVCALL_POST_MESSAGE 0x005c
|
||||
#define HVCALL_SIGNAL_EVENT 0x005d
|
||||
|
||||
#define HV_X64_MSR_APIC_ASSIST_PAGE_ENABLE 0x00000001
|
||||
#define HV_X64_MSR_APIC_ASSIST_PAGE_ADDRESS_SHIFT 12
|
||||
#define HV_X64_MSR_APIC_ASSIST_PAGE_ADDRESS_MASK \
|
||||
(~((1ull << HV_X64_MSR_APIC_ASSIST_PAGE_ADDRESS_SHIFT) - 1))
|
||||
|
||||
#define HV_X64_MSR_TSC_REFERENCE_ENABLE 0x00000001
|
||||
#define HV_X64_MSR_TSC_REFERENCE_ADDRESS_SHIFT 12
|
||||
|
||||
#define HV_PROCESSOR_POWER_STATE_C0 0
|
||||
#define HV_PROCESSOR_POWER_STATE_C1 1
|
||||
#define HV_PROCESSOR_POWER_STATE_C2 2
|
||||
#define HV_PROCESSOR_POWER_STATE_C3 3
|
||||
|
||||
#define HV_FLUSH_ALL_PROCESSORS BIT(0)
|
||||
#define HV_FLUSH_ALL_VIRTUAL_ADDRESS_SPACES BIT(1)
|
||||
#define HV_FLUSH_NON_GLOBAL_MAPPINGS_ONLY BIT(2)
|
||||
#define HV_FLUSH_USE_EXTENDED_RANGE_FORMAT BIT(3)
|
||||
|
||||
enum HV_GENERIC_SET_FORMAT {
|
||||
HV_GENERIC_SET_SPARCE_4K,
|
||||
HV_GENERIC_SET_ALL,
|
||||
};
|
||||
|
||||
/* hypercall status code */
|
||||
#define HV_STATUS_SUCCESS 0
|
||||
#define HV_STATUS_INVALID_HYPERCALL_CODE 2
|
||||
#define HV_STATUS_INVALID_HYPERCALL_INPUT 3
|
||||
#define HV_STATUS_INVALID_ALIGNMENT 4
|
||||
#define HV_STATUS_INSUFFICIENT_MEMORY 11
|
||||
#define HV_STATUS_INVALID_CONNECTION_ID 18
|
||||
#define HV_STATUS_INSUFFICIENT_BUFFERS 19
|
||||
|
||||
typedef struct _HV_REFERENCE_TSC_PAGE {
|
||||
uint32_t tsc_sequence;
|
||||
uint32_t res1;
|
||||
uint64_t tsc_scale;
|
||||
int64_t tsc_offset;
|
||||
} HV_REFERENCE_TSC_PAGE, *PHV_REFERENCE_TSC_PAGE;
|
||||
|
||||
/* Define the number of synthetic interrupt sources. */
|
||||
#define HV_SYNIC_SINT_COUNT (16)
|
||||
/* Define the expected SynIC version. */
|
||||
#define HV_SYNIC_VERSION_1 (0x1)
|
||||
|
||||
#define HV_SYNIC_CONTROL_ENABLE (1ULL << 0)
|
||||
#define HV_SYNIC_SIMP_ENABLE (1ULL << 0)
|
||||
#define HV_SYNIC_SIEFP_ENABLE (1ULL << 0)
|
||||
#define HV_SYNIC_SINT_MASKED (1ULL << 16)
|
||||
#define HV_SYNIC_SINT_AUTO_EOI (1ULL << 17)
|
||||
#define HV_SYNIC_SINT_VECTOR_MASK (0xFF)
|
||||
|
||||
#define HV_SYNIC_STIMER_COUNT (4)
|
||||
|
||||
/* Define synthetic interrupt controller message constants. */
|
||||
#define HV_MESSAGE_SIZE (256)
|
||||
#define HV_MESSAGE_PAYLOAD_BYTE_COUNT (240)
|
||||
#define HV_MESSAGE_PAYLOAD_QWORD_COUNT (30)
|
||||
|
||||
/* Define hypervisor message types. */
|
||||
enum hv_message_type {
|
||||
HVMSG_NONE = 0x00000000,
|
||||
|
||||
/* Memory access messages. */
|
||||
HVMSG_UNMAPPED_GPA = 0x80000000,
|
||||
HVMSG_GPA_INTERCEPT = 0x80000001,
|
||||
|
||||
/* Timer notification messages. */
|
||||
HVMSG_TIMER_EXPIRED = 0x80000010,
|
||||
|
||||
/* Error messages. */
|
||||
HVMSG_INVALID_VP_REGISTER_VALUE = 0x80000020,
|
||||
HVMSG_UNRECOVERABLE_EXCEPTION = 0x80000021,
|
||||
HVMSG_UNSUPPORTED_FEATURE = 0x80000022,
|
||||
|
||||
/* Trace buffer complete messages. */
|
||||
HVMSG_EVENTLOG_BUFFERCOMPLETE = 0x80000040,
|
||||
|
||||
/* Platform-specific processor intercept messages. */
|
||||
HVMSG_X64_IOPORT_INTERCEPT = 0x80010000,
|
||||
HVMSG_X64_MSR_INTERCEPT = 0x80010001,
|
||||
HVMSG_X64_CPUID_INTERCEPT = 0x80010002,
|
||||
HVMSG_X64_EXCEPTION_INTERCEPT = 0x80010003,
|
||||
HVMSG_X64_APIC_EOI = 0x80010004,
|
||||
HVMSG_X64_LEGACY_FP_ERROR = 0x80010005
|
||||
};
|
||||
|
||||
/* Define synthetic interrupt controller message flags. */
|
||||
union hv_message_flags {
|
||||
uint8_t asu8;
|
||||
struct {
|
||||
uint8_t msg_pending:1;
|
||||
uint8_t reserved:7;
|
||||
};
|
||||
};
|
||||
|
||||
/* Define port identifier type. */
|
||||
union hv_port_id {
|
||||
uint32_t asu32;
|
||||
struct {
|
||||
uint32_t id:24;
|
||||
uint32_t reserved:8;
|
||||
} u;
|
||||
};
|
||||
|
||||
/* Define synthetic interrupt controller message header. */
|
||||
struct hv_message_header {
|
||||
uint32_t message_type;
|
||||
uint8_t payload_size;
|
||||
union hv_message_flags message_flags;
|
||||
uint8_t reserved[2];
|
||||
union {
|
||||
uint64_t sender;
|
||||
union hv_port_id port;
|
||||
};
|
||||
};
|
||||
|
||||
/* Define synthetic interrupt controller message format. */
|
||||
struct hv_message {
|
||||
struct hv_message_header header;
|
||||
union {
|
||||
uint64_t payload[HV_MESSAGE_PAYLOAD_QWORD_COUNT];
|
||||
} u;
|
||||
};
|
||||
|
||||
/* Define the synthetic interrupt message page layout. */
|
||||
struct hv_message_page {
|
||||
struct hv_message sint_message[HV_SYNIC_SINT_COUNT];
|
||||
};
|
||||
|
||||
/* Define timer message payload structure. */
|
||||
struct hv_timer_message_payload {
|
||||
uint32_t timer_index;
|
||||
uint32_t reserved;
|
||||
uint64_t expiration_time; /* When the timer expired */
|
||||
uint64_t delivery_time; /* When the message was delivered */
|
||||
};
|
||||
|
||||
#define HV_STIMER_ENABLE (1ULL << 0)
|
||||
#define HV_STIMER_PERIODIC (1ULL << 1)
|
||||
#define HV_STIMER_LAZY (1ULL << 2)
|
||||
#define HV_STIMER_AUTOENABLE (1ULL << 3)
|
||||
#define HV_STIMER_SINT(config) (uint8_t)(((config) >> 16) & 0x0F)
|
||||
|
||||
#endif
|
||||
/* this is a temporary placeholder until kvm_para.h stops including it */
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||
/*
|
||||
* Input event codes
|
||||
*
|
||||
@@ -406,6 +407,7 @@
|
||||
#define BTN_TOOL_MOUSE 0x146
|
||||
#define BTN_TOOL_LENS 0x147
|
||||
#define BTN_TOOL_QUINTTAP 0x148 /* Five fingers on trackpad */
|
||||
#define BTN_STYLUS3 0x149
|
||||
#define BTN_TOUCH 0x14a
|
||||
#define BTN_STYLUS 0x14b
|
||||
#define BTN_STYLUS2 0x14c
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||
/*
|
||||
* Copyright (c) 1999-2002 Vojtech Pavlik
|
||||
*
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||
/*
|
||||
* pci_regs.h
|
||||
*
|
||||
@@ -746,6 +747,7 @@
|
||||
#define PCI_ERR_ROOT_FIRST_FATAL 0x00000010 /* First UNC is Fatal */
|
||||
#define PCI_ERR_ROOT_NONFATAL_RCV 0x00000020 /* Non-Fatal Received */
|
||||
#define PCI_ERR_ROOT_FATAL_RCV 0x00000040 /* Fatal Received */
|
||||
#define PCI_ERR_ROOT_AER_IRQ 0xf8000000 /* Advanced Error Interrupt Message Number */
|
||||
#define PCI_ERR_ROOT_ERR_SRC 52 /* Error Source Identification */
|
||||
|
||||
/* Virtual Channel */
|
||||
@@ -939,9 +941,13 @@
|
||||
#define PCI_SATA_SIZEOF_LONG 16
|
||||
|
||||
/* Resizable BARs */
|
||||
#define PCI_REBAR_CAP 4 /* capability register */
|
||||
#define PCI_REBAR_CAP_SIZES 0x00FFFFF0 /* supported BAR sizes */
|
||||
#define PCI_REBAR_CTRL 8 /* control register */
|
||||
#define PCI_REBAR_CTRL_NBAR_MASK (7 << 5) /* mask for # bars */
|
||||
#define PCI_REBAR_CTRL_NBAR_SHIFT 5 /* shift for # bars */
|
||||
#define PCI_REBAR_CTRL_BAR_IDX 0x00000007 /* BAR index */
|
||||
#define PCI_REBAR_CTRL_NBAR_MASK 0x000000E0 /* # of resizable BARs */
|
||||
#define PCI_REBAR_CTRL_NBAR_SHIFT 5 /* shift for # of BARs */
|
||||
#define PCI_REBAR_CTRL_BAR_SIZE 0x00001F00 /* BAR size */
|
||||
|
||||
/* Dynamic Power Allocation */
|
||||
#define PCI_DPA_CAP 4 /* capability register */
|
||||
@@ -960,6 +966,7 @@
|
||||
|
||||
/* Downstream Port Containment */
|
||||
#define PCI_EXP_DPC_CAP 4 /* DPC Capability */
|
||||
#define PCI_EXP_DPC_IRQ 0x1f /* DPC Interrupt Message Number */
|
||||
#define PCI_EXP_DPC_CAP_RP_EXT 0x20 /* Root Port Extensions for DPC */
|
||||
#define PCI_EXP_DPC_CAP_POISONED_TLP 0x40 /* Poisoned TLP Egress Blocking Supported */
|
||||
#define PCI_EXP_DPC_CAP_SW_TRIGGER 0x80 /* Software Triggering Supported */
|
||||
@@ -995,19 +1002,25 @@
|
||||
#define PCI_PTM_CTRL_ENABLE 0x00000001 /* PTM enable */
|
||||
#define PCI_PTM_CTRL_ROOT 0x00000002 /* Root select */
|
||||
|
||||
/* L1 PM Substates */
|
||||
#define PCI_L1SS_CAP 4 /* capability register */
|
||||
#define PCI_L1SS_CAP_PCIPM_L1_2 1 /* PCI PM L1.2 Support */
|
||||
#define PCI_L1SS_CAP_PCIPM_L1_1 2 /* PCI PM L1.1 Support */
|
||||
#define PCI_L1SS_CAP_ASPM_L1_2 4 /* ASPM L1.2 Support */
|
||||
#define PCI_L1SS_CAP_ASPM_L1_1 8 /* ASPM L1.1 Support */
|
||||
#define PCI_L1SS_CAP_L1_PM_SS 16 /* L1 PM Substates Support */
|
||||
#define PCI_L1SS_CTL1 8 /* Control Register 1 */
|
||||
#define PCI_L1SS_CTL1_PCIPM_L1_2 1 /* PCI PM L1.2 Enable */
|
||||
#define PCI_L1SS_CTL1_PCIPM_L1_1 2 /* PCI PM L1.1 Support */
|
||||
#define PCI_L1SS_CTL1_ASPM_L1_2 4 /* ASPM L1.2 Support */
|
||||
#define PCI_L1SS_CTL1_ASPM_L1_1 8 /* ASPM L1.1 Support */
|
||||
#define PCI_L1SS_CTL1_L1SS_MASK 0x0000000F
|
||||
#define PCI_L1SS_CTL2 0xC /* Control Register 2 */
|
||||
/* ASPM L1 PM Substates */
|
||||
#define PCI_L1SS_CAP 0x04 /* Capabilities Register */
|
||||
#define PCI_L1SS_CAP_PCIPM_L1_2 0x00000001 /* PCI-PM L1.2 Supported */
|
||||
#define PCI_L1SS_CAP_PCIPM_L1_1 0x00000002 /* PCI-PM L1.1 Supported */
|
||||
#define PCI_L1SS_CAP_ASPM_L1_2 0x00000004 /* ASPM L1.2 Supported */
|
||||
#define PCI_L1SS_CAP_ASPM_L1_1 0x00000008 /* ASPM L1.1 Supported */
|
||||
#define PCI_L1SS_CAP_L1_PM_SS 0x00000010 /* L1 PM Substates Supported */
|
||||
#define PCI_L1SS_CAP_CM_RESTORE_TIME 0x0000ff00 /* Port Common_Mode_Restore_Time */
|
||||
#define PCI_L1SS_CAP_P_PWR_ON_SCALE 0x00030000 /* Port T_POWER_ON scale */
|
||||
#define PCI_L1SS_CAP_P_PWR_ON_VALUE 0x00f80000 /* Port T_POWER_ON value */
|
||||
#define PCI_L1SS_CTL1 0x08 /* Control 1 Register */
|
||||
#define PCI_L1SS_CTL1_PCIPM_L1_2 0x00000001 /* PCI-PM L1.2 Enable */
|
||||
#define PCI_L1SS_CTL1_PCIPM_L1_1 0x00000002 /* PCI-PM L1.1 Enable */
|
||||
#define PCI_L1SS_CTL1_ASPM_L1_2 0x00000004 /* ASPM L1.2 Enable */
|
||||
#define PCI_L1SS_CTL1_ASPM_L1_1 0x00000008 /* ASPM L1.1 Enable */
|
||||
#define PCI_L1SS_CTL1_L1SS_MASK 0x0000000f
|
||||
#define PCI_L1SS_CTL1_CM_RESTORE_TIME 0x0000ff00 /* Common_Mode_Restore_Time */
|
||||
#define PCI_L1SS_CTL1_LTR_L12_TH_VALUE 0x03ff0000 /* LTR_L1.2_THRESHOLD_Value */
|
||||
#define PCI_L1SS_CTL1_LTR_L12_TH_SCALE 0xe0000000 /* LTR_L1.2_THRESHOLD_Scale */
|
||||
#define PCI_L1SS_CTL2 0x0c /* Control 2 Register */
|
||||
|
||||
#endif /* LINUX_PCI_REGS_H */
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||
/*
|
||||
* Copyright (C) 2012 - Virtual Open Systems and Columbia University
|
||||
* Author: Christoffer Dall <c.dall@virtualopensystems.com>
|
||||
@@ -151,6 +152,12 @@ struct kvm_arch_memory_slot {
|
||||
(__ARM_CP15_REG(op1, 0, crm, 0) | KVM_REG_SIZE_U64)
|
||||
#define ARM_CP15_REG64(...) __ARM_CP15_REG64(__VA_ARGS__)
|
||||
|
||||
/* PL1 Physical Timer Registers */
|
||||
#define KVM_REG_ARM_PTIMER_CTL ARM_CP15_REG32(0, 14, 2, 1)
|
||||
#define KVM_REG_ARM_PTIMER_CNT ARM_CP15_REG64(0, 14)
|
||||
#define KVM_REG_ARM_PTIMER_CVAL ARM_CP15_REG64(2, 14)
|
||||
|
||||
/* Virtual Timer Registers */
|
||||
#define KVM_REG_ARM_TIMER_CTL ARM_CP15_REG32(0, 14, 3, 1)
|
||||
#define KVM_REG_ARM_TIMER_CNT ARM_CP15_REG64(1, 14)
|
||||
#define KVM_REG_ARM_TIMER_CVAL ARM_CP15_REG64(3, 14)
|
||||
@@ -215,6 +222,7 @@ struct kvm_arch_memory_slot {
|
||||
#define KVM_DEV_ARM_ITS_SAVE_TABLES 1
|
||||
#define KVM_DEV_ARM_ITS_RESTORE_TABLES 2
|
||||
#define KVM_DEV_ARM_VGIC_SAVE_PENDING_TABLES 3
|
||||
#define KVM_DEV_ARM_ITS_CTRL_RESET 4
|
||||
|
||||
/* KVM_IRQ_LINE irq field index values */
|
||||
#define KVM_ARM_IRQ_TYPE_SHIFT 24
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||
#include <asm-generic/kvm_para.h>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||
/*
|
||||
* arch/arm/include/asm/unistd.h
|
||||
*
|
||||
@@ -35,5 +36,6 @@
|
||||
#define __ARM_NR_usr26 (__ARM_NR_BASE+3)
|
||||
#define __ARM_NR_usr32 (__ARM_NR_BASE+4)
|
||||
#define __ARM_NR_set_tls (__ARM_NR_BASE+5)
|
||||
#define __ARM_NR_get_tls (__ARM_NR_BASE+6)
|
||||
|
||||
#endif /* __ASM_ARM_UNISTD_H */
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||
/*
|
||||
* Copyright (C) 2012,2013 - ARM Ltd
|
||||
* Author: Marc Zyngier <marc.zyngier@arm.com>
|
||||
@@ -195,6 +196,12 @@ struct kvm_arch_memory_slot {
|
||||
|
||||
#define ARM64_SYS_REG(...) (__ARM64_SYS_REG(__VA_ARGS__) | KVM_REG_SIZE_U64)
|
||||
|
||||
/* Physical Timer EL0 Registers */
|
||||
#define KVM_REG_ARM_PTIMER_CTL ARM64_SYS_REG(3, 3, 14, 2, 1)
|
||||
#define KVM_REG_ARM_PTIMER_CVAL ARM64_SYS_REG(3, 3, 14, 2, 2)
|
||||
#define KVM_REG_ARM_PTIMER_CNT ARM64_SYS_REG(3, 3, 14, 0, 1)
|
||||
|
||||
/* EL0 Virtual Timer Registers */
|
||||
#define KVM_REG_ARM_TIMER_CTL ARM64_SYS_REG(3, 3, 14, 3, 1)
|
||||
#define KVM_REG_ARM_TIMER_CNT ARM64_SYS_REG(3, 3, 14, 3, 2)
|
||||
#define KVM_REG_ARM_TIMER_CVAL ARM64_SYS_REG(3, 3, 14, 0, 2)
|
||||
@@ -227,6 +234,7 @@ struct kvm_arch_memory_slot {
|
||||
#define KVM_DEV_ARM_ITS_SAVE_TABLES 1
|
||||
#define KVM_DEV_ARM_ITS_RESTORE_TABLES 2
|
||||
#define KVM_DEV_ARM_VGIC_SAVE_PENDING_TABLES 3
|
||||
#define KVM_DEV_ARM_ITS_CTRL_RESET 4
|
||||
|
||||
/* Device Control API on vcpu fd */
|
||||
#define KVM_ARM_VCPU_PMU_V3_CTRL 0
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||
/*
|
||||
* Copyright (C) 2012 ARM Ltd.
|
||||
*
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* SPDX-License-Identifier: ((GPL-2.0+ WITH Linux-syscall-note) OR BSD-3-Clause) */
|
||||
/*
|
||||
* ePAPR hcall interface
|
||||
*
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2, as
|
||||
@@ -442,6 +443,31 @@ struct kvm_ppc_rmmu_info {
|
||||
__u32 ap_encodings[8];
|
||||
};
|
||||
|
||||
/* For KVM_PPC_GET_CPU_CHAR */
|
||||
struct kvm_ppc_cpu_char {
|
||||
__u64 character; /* characteristics of the CPU */
|
||||
__u64 behaviour; /* recommended software behaviour */
|
||||
__u64 character_mask; /* valid bits in character */
|
||||
__u64 behaviour_mask; /* valid bits in behaviour */
|
||||
};
|
||||
|
||||
/*
|
||||
* Values for character and character_mask.
|
||||
* These are identical to the values used by H_GET_CPU_CHARACTERISTICS.
|
||||
*/
|
||||
#define KVM_PPC_CPU_CHAR_SPEC_BAR_ORI31 (1ULL << 63)
|
||||
#define KVM_PPC_CPU_CHAR_BCCTRL_SERIALISED (1ULL << 62)
|
||||
#define KVM_PPC_CPU_CHAR_L1D_FLUSH_ORI30 (1ULL << 61)
|
||||
#define KVM_PPC_CPU_CHAR_L1D_FLUSH_TRIG2 (1ULL << 60)
|
||||
#define KVM_PPC_CPU_CHAR_L1D_THREAD_PRIV (1ULL << 59)
|
||||
#define KVM_PPC_CPU_CHAR_BR_HINT_HONOURED (1ULL << 58)
|
||||
#define KVM_PPC_CPU_CHAR_MTTRIG_THR_RECONF (1ULL << 57)
|
||||
#define KVM_PPC_CPU_CHAR_COUNT_CACHE_DIS (1ULL << 56)
|
||||
|
||||
#define KVM_PPC_CPU_BEHAV_FAVOUR_SECURITY (1ULL << 63)
|
||||
#define KVM_PPC_CPU_BEHAV_L1D_FLUSH_PR (1ULL << 62)
|
||||
#define KVM_PPC_CPU_BEHAV_BNDS_CHK_SPEC_BAR (1ULL << 61)
|
||||
|
||||
/* Per-vcpu XICS interrupt controller state */
|
||||
#define KVM_REG_PPC_ICP_STATE (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x8c)
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2, as
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
|
||||
/*
|
||||
* This file contains the system call numbers.
|
||||
*
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||
#ifndef __LINUX_KVM_S390_H
|
||||
#define __LINUX_KVM_S390_H
|
||||
/*
|
||||
@@ -5,10 +6,6 @@
|
||||
*
|
||||
* Copyright IBM Corp. 2008
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License (version 2 only)
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* Author(s): Carsten Otte <cotte@de.ibm.com>
|
||||
* Christian Borntraeger <borntraeger@de.ibm.com>
|
||||
*/
|
||||
@@ -227,6 +224,7 @@ struct kvm_guest_debug_arch {
|
||||
#define KVM_SYNC_RICCB (1UL << 7)
|
||||
#define KVM_SYNC_FPRS (1UL << 8)
|
||||
#define KVM_SYNC_GSCB (1UL << 9)
|
||||
#define KVM_SYNC_BPBC (1UL << 10)
|
||||
/* length and alignment of the sdnx as a power of two */
|
||||
#define SDNXC 8
|
||||
#define SDNXL (1UL << SDNXC)
|
||||
@@ -250,7 +248,9 @@ struct kvm_sync_regs {
|
||||
};
|
||||
__u8 reserved[512]; /* for future vector expansion */
|
||||
__u32 fpc; /* valid on KVM_SYNC_VRS or KVM_SYNC_FPRS */
|
||||
__u8 padding1[52]; /* riccb needs to be 64byte aligned */
|
||||
__u8 bpbc : 1; /* bp mode */
|
||||
__u8 reserved2 : 7;
|
||||
__u8 padding1[51]; /* riccb needs to be 64byte aligned */
|
||||
__u8 riccb[64]; /* runtime instrumentation controls block */
|
||||
__u8 padding2[192]; /* sdnx needs to be 256byte aligned */
|
||||
union {
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||
/*
|
||||
* User API definitions for paravirtual devices on s390
|
||||
*
|
||||
* Copyright IBM Corp. 2008
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License (version 2 only)
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* Author(s): Christian Borntraeger <borntraeger@de.ibm.com>
|
||||
*/
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||
/*
|
||||
* S390 version
|
||||
*
|
||||
@@ -315,7 +316,8 @@
|
||||
#define __NR_pwritev2 377
|
||||
#define __NR_s390_guarded_storage 378
|
||||
#define __NR_statx 379
|
||||
#define NR_syscalls 380
|
||||
#define __NR_s390_sthyi 380
|
||||
#define NR_syscalls 381
|
||||
|
||||
/*
|
||||
* There are some system calls that are not present on 64 bit, some
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||
#ifndef _ASM_X86_KVM_H
|
||||
#define _ASM_X86_KVM_H
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||
#ifndef _ASM_X86_KVM_PARA_H
|
||||
#define _ASM_X86_KVM_PARA_H
|
||||
|
||||
@@ -109,5 +110,4 @@ struct kvm_vcpu_pv_apf_data {
|
||||
#define KVM_PV_EOI_ENABLED KVM_PV_EOI_MASK
|
||||
#define KVM_PV_EOI_DISABLED 0x0
|
||||
|
||||
|
||||
#endif /* _ASM_X86_KVM_PARA_H */
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||
#ifndef _ASM_X86_UNISTD_H
|
||||
#define _ASM_X86_UNISTD_H
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||
#ifndef __LINUX_KVM_H
|
||||
#define __LINUX_KVM_H
|
||||
|
||||
@@ -629,9 +630,9 @@ struct kvm_s390_irq {
|
||||
|
||||
struct kvm_s390_irq_state {
|
||||
__u64 buf;
|
||||
__u32 flags;
|
||||
__u32 flags; /* will stay unused for compatibility reasons */
|
||||
__u32 len;
|
||||
__u32 reserved[4];
|
||||
__u32 reserved[4]; /* will stay unused for compatibility reasons */
|
||||
};
|
||||
|
||||
/* for KVM_SET_GUEST_DEBUG */
|
||||
@@ -930,6 +931,9 @@ struct kvm_ppc_resize_hpt {
|
||||
#define KVM_CAP_PPC_SMT_POSSIBLE 147
|
||||
#define KVM_CAP_HYPERV_SYNIC2 148
|
||||
#define KVM_CAP_HYPERV_VP_INDEX 149
|
||||
#define KVM_CAP_S390_AIS_MIGRATION 150
|
||||
#define KVM_CAP_PPC_GET_CPU_CHAR 151
|
||||
#define KVM_CAP_S390_BPB 152
|
||||
|
||||
#ifdef KVM_CAP_IRQ_ROUTING
|
||||
|
||||
@@ -1259,6 +1263,8 @@ struct kvm_s390_ucas_mapping {
|
||||
#define KVM_PPC_CONFIGURE_V3_MMU _IOW(KVMIO, 0xaf, struct kvm_ppc_mmuv3_cfg)
|
||||
/* Available with KVM_CAP_PPC_RADIX_MMU */
|
||||
#define KVM_PPC_GET_RMMU_INFO _IOW(KVMIO, 0xb0, struct kvm_ppc_rmmu_info)
|
||||
/* Available with KVM_CAP_PPC_GET_CPU_CHAR */
|
||||
#define KVM_PPC_GET_CPU_CHAR _IOR(KVMIO, 0xb1, struct kvm_ppc_cpu_char)
|
||||
|
||||
/* ioctl for vm fd */
|
||||
#define KVM_CREATE_DEVICE _IOWR(KVMIO, 0xe0, struct kvm_create_device)
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||
#ifndef __LINUX_KVM_PARA_H
|
||||
#define __LINUX_KVM_PARA_H
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||
/*
|
||||
* ARM Power State and Coordination Interface (PSCI) header
|
||||
*
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||
/*
|
||||
* include/linux/userfaultfd.h
|
||||
*
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||
/*
|
||||
* VFIO API definition
|
||||
*
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||
/*
|
||||
* Interfaces for vfio-ccw
|
||||
*
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||
#ifndef _LINUX_VHOST_H
|
||||
#define _LINUX_VHOST_H
|
||||
/* Userspace interface for in-kernel virtio accelerators. */
|
||||
|
||||
+2
-2
@@ -128,9 +128,9 @@ int cpu_get_pic_interrupt(CPUX86State *env)
|
||||
/* Make sure everything is in a consistent state for calling fork(). */
|
||||
void fork_start(void)
|
||||
{
|
||||
cpu_list_lock();
|
||||
qemu_mutex_lock(&tb_ctx.tb_lock);
|
||||
mmap_fork_start();
|
||||
qemu_mutex_lock(&tb_ctx.tb_lock);
|
||||
cpu_list_lock();
|
||||
}
|
||||
|
||||
void fork_end(int child)
|
||||
|
||||
+59
-59
@@ -2758,29 +2758,29 @@ long do_rt_sigreturn(CPUSPARCState *env)
|
||||
}
|
||||
|
||||
#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
|
||||
#define MC_TSTATE 0
|
||||
#define MC_PC 1
|
||||
#define MC_NPC 2
|
||||
#define MC_Y 3
|
||||
#define MC_G1 4
|
||||
#define MC_G2 5
|
||||
#define MC_G3 6
|
||||
#define MC_G4 7
|
||||
#define MC_G5 8
|
||||
#define MC_G6 9
|
||||
#define MC_G7 10
|
||||
#define MC_O0 11
|
||||
#define MC_O1 12
|
||||
#define MC_O2 13
|
||||
#define MC_O3 14
|
||||
#define MC_O4 15
|
||||
#define MC_O5 16
|
||||
#define MC_O6 17
|
||||
#define MC_O7 18
|
||||
#define MC_NGREG 19
|
||||
#define SPARC_MC_TSTATE 0
|
||||
#define SPARC_MC_PC 1
|
||||
#define SPARC_MC_NPC 2
|
||||
#define SPARC_MC_Y 3
|
||||
#define SPARC_MC_G1 4
|
||||
#define SPARC_MC_G2 5
|
||||
#define SPARC_MC_G3 6
|
||||
#define SPARC_MC_G4 7
|
||||
#define SPARC_MC_G5 8
|
||||
#define SPARC_MC_G6 9
|
||||
#define SPARC_MC_G7 10
|
||||
#define SPARC_MC_O0 11
|
||||
#define SPARC_MC_O1 12
|
||||
#define SPARC_MC_O2 13
|
||||
#define SPARC_MC_O3 14
|
||||
#define SPARC_MC_O4 15
|
||||
#define SPARC_MC_O5 16
|
||||
#define SPARC_MC_O6 17
|
||||
#define SPARC_MC_O7 18
|
||||
#define SPARC_MC_NGREG 19
|
||||
|
||||
typedef abi_ulong target_mc_greg_t;
|
||||
typedef target_mc_greg_t target_mc_gregset_t[MC_NGREG];
|
||||
typedef target_mc_greg_t target_mc_gregset_t[SPARC_MC_NGREG];
|
||||
|
||||
struct target_mc_fq {
|
||||
abi_ulong *mcfq_addr;
|
||||
@@ -2840,8 +2840,8 @@ void sparc64_set_context(CPUSPARCState *env)
|
||||
goto do_sigsegv;
|
||||
}
|
||||
grp = &ucp->tuc_mcontext.mc_gregs;
|
||||
__get_user(pc, &((*grp)[MC_PC]));
|
||||
__get_user(npc, &((*grp)[MC_NPC]));
|
||||
__get_user(pc, &((*grp)[SPARC_MC_PC]));
|
||||
__get_user(npc, &((*grp)[SPARC_MC_NPC]));
|
||||
if ((pc | npc) & 3) {
|
||||
goto do_sigsegv;
|
||||
}
|
||||
@@ -2864,26 +2864,26 @@ void sparc64_set_context(CPUSPARCState *env)
|
||||
}
|
||||
env->pc = pc;
|
||||
env->npc = npc;
|
||||
__get_user(env->y, &((*grp)[MC_Y]));
|
||||
__get_user(tstate, &((*grp)[MC_TSTATE]));
|
||||
__get_user(env->y, &((*grp)[SPARC_MC_Y]));
|
||||
__get_user(tstate, &((*grp)[SPARC_MC_TSTATE]));
|
||||
env->asi = (tstate >> 24) & 0xff;
|
||||
cpu_put_ccr(env, tstate >> 32);
|
||||
cpu_put_cwp64(env, tstate & 0x1f);
|
||||
__get_user(env->gregs[1], (&(*grp)[MC_G1]));
|
||||
__get_user(env->gregs[2], (&(*grp)[MC_G2]));
|
||||
__get_user(env->gregs[3], (&(*grp)[MC_G3]));
|
||||
__get_user(env->gregs[4], (&(*grp)[MC_G4]));
|
||||
__get_user(env->gregs[5], (&(*grp)[MC_G5]));
|
||||
__get_user(env->gregs[6], (&(*grp)[MC_G6]));
|
||||
__get_user(env->gregs[7], (&(*grp)[MC_G7]));
|
||||
__get_user(env->regwptr[UREG_I0], (&(*grp)[MC_O0]));
|
||||
__get_user(env->regwptr[UREG_I1], (&(*grp)[MC_O1]));
|
||||
__get_user(env->regwptr[UREG_I2], (&(*grp)[MC_O2]));
|
||||
__get_user(env->regwptr[UREG_I3], (&(*grp)[MC_O3]));
|
||||
__get_user(env->regwptr[UREG_I4], (&(*grp)[MC_O4]));
|
||||
__get_user(env->regwptr[UREG_I5], (&(*grp)[MC_O5]));
|
||||
__get_user(env->regwptr[UREG_I6], (&(*grp)[MC_O6]));
|
||||
__get_user(env->regwptr[UREG_I7], (&(*grp)[MC_O7]));
|
||||
__get_user(env->gregs[1], (&(*grp)[SPARC_MC_G1]));
|
||||
__get_user(env->gregs[2], (&(*grp)[SPARC_MC_G2]));
|
||||
__get_user(env->gregs[3], (&(*grp)[SPARC_MC_G3]));
|
||||
__get_user(env->gregs[4], (&(*grp)[SPARC_MC_G4]));
|
||||
__get_user(env->gregs[5], (&(*grp)[SPARC_MC_G5]));
|
||||
__get_user(env->gregs[6], (&(*grp)[SPARC_MC_G6]));
|
||||
__get_user(env->gregs[7], (&(*grp)[SPARC_MC_G7]));
|
||||
__get_user(env->regwptr[UREG_I0], (&(*grp)[SPARC_MC_O0]));
|
||||
__get_user(env->regwptr[UREG_I1], (&(*grp)[SPARC_MC_O1]));
|
||||
__get_user(env->regwptr[UREG_I2], (&(*grp)[SPARC_MC_O2]));
|
||||
__get_user(env->regwptr[UREG_I3], (&(*grp)[SPARC_MC_O3]));
|
||||
__get_user(env->regwptr[UREG_I4], (&(*grp)[SPARC_MC_O4]));
|
||||
__get_user(env->regwptr[UREG_I5], (&(*grp)[SPARC_MC_O5]));
|
||||
__get_user(env->regwptr[UREG_I6], (&(*grp)[SPARC_MC_O6]));
|
||||
__get_user(env->regwptr[UREG_I7], (&(*grp)[SPARC_MC_O7]));
|
||||
|
||||
__get_user(fp, &(ucp->tuc_mcontext.mc_fp));
|
||||
__get_user(i7, &(ucp->tuc_mcontext.mc_i7));
|
||||
@@ -2971,25 +2971,25 @@ void sparc64_get_context(CPUSPARCState *env)
|
||||
}
|
||||
|
||||
/* XXX: tstate must be saved properly */
|
||||
// __put_user(env->tstate, &((*grp)[MC_TSTATE]));
|
||||
__put_user(env->pc, &((*grp)[MC_PC]));
|
||||
__put_user(env->npc, &((*grp)[MC_NPC]));
|
||||
__put_user(env->y, &((*grp)[MC_Y]));
|
||||
__put_user(env->gregs[1], &((*grp)[MC_G1]));
|
||||
__put_user(env->gregs[2], &((*grp)[MC_G2]));
|
||||
__put_user(env->gregs[3], &((*grp)[MC_G3]));
|
||||
__put_user(env->gregs[4], &((*grp)[MC_G4]));
|
||||
__put_user(env->gregs[5], &((*grp)[MC_G5]));
|
||||
__put_user(env->gregs[6], &((*grp)[MC_G6]));
|
||||
__put_user(env->gregs[7], &((*grp)[MC_G7]));
|
||||
__put_user(env->regwptr[UREG_I0], &((*grp)[MC_O0]));
|
||||
__put_user(env->regwptr[UREG_I1], &((*grp)[MC_O1]));
|
||||
__put_user(env->regwptr[UREG_I2], &((*grp)[MC_O2]));
|
||||
__put_user(env->regwptr[UREG_I3], &((*grp)[MC_O3]));
|
||||
__put_user(env->regwptr[UREG_I4], &((*grp)[MC_O4]));
|
||||
__put_user(env->regwptr[UREG_I5], &((*grp)[MC_O5]));
|
||||
__put_user(env->regwptr[UREG_I6], &((*grp)[MC_O6]));
|
||||
__put_user(env->regwptr[UREG_I7], &((*grp)[MC_O7]));
|
||||
// __put_user(env->tstate, &((*grp)[SPARC_MC_TSTATE]));
|
||||
__put_user(env->pc, &((*grp)[SPARC_MC_PC]));
|
||||
__put_user(env->npc, &((*grp)[SPARC_MC_NPC]));
|
||||
__put_user(env->y, &((*grp)[SPARC_MC_Y]));
|
||||
__put_user(env->gregs[1], &((*grp)[SPARC_MC_G1]));
|
||||
__put_user(env->gregs[2], &((*grp)[SPARC_MC_G2]));
|
||||
__put_user(env->gregs[3], &((*grp)[SPARC_MC_G3]));
|
||||
__put_user(env->gregs[4], &((*grp)[SPARC_MC_G4]));
|
||||
__put_user(env->gregs[5], &((*grp)[SPARC_MC_G5]));
|
||||
__put_user(env->gregs[6], &((*grp)[SPARC_MC_G6]));
|
||||
__put_user(env->gregs[7], &((*grp)[SPARC_MC_G7]));
|
||||
__put_user(env->regwptr[UREG_I0], &((*grp)[SPARC_MC_O0]));
|
||||
__put_user(env->regwptr[UREG_I1], &((*grp)[SPARC_MC_O1]));
|
||||
__put_user(env->regwptr[UREG_I2], &((*grp)[SPARC_MC_O2]));
|
||||
__put_user(env->regwptr[UREG_I3], &((*grp)[SPARC_MC_O3]));
|
||||
__put_user(env->regwptr[UREG_I4], &((*grp)[SPARC_MC_O4]));
|
||||
__put_user(env->regwptr[UREG_I5], &((*grp)[SPARC_MC_O5]));
|
||||
__put_user(env->regwptr[UREG_I6], &((*grp)[SPARC_MC_O6]));
|
||||
__put_user(env->regwptr[UREG_I7], &((*grp)[SPARC_MC_O7]));
|
||||
|
||||
w_addr = TARGET_STACK_BIAS+env->regwptr[UREG_I6];
|
||||
fp = i7 = 0;
|
||||
|
||||
@@ -1091,6 +1091,7 @@ void memory_region_transaction_commit(void)
|
||||
address_space_update_ioeventfds(as);
|
||||
}
|
||||
memory_region_update_pending = false;
|
||||
ioeventfd_update_pending = false;
|
||||
MEMORY_LISTENER_CALL_GLOBAL(commit, Forward);
|
||||
} else if (ioeventfd_update_pending) {
|
||||
QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) {
|
||||
|
||||
@@ -2128,7 +2128,8 @@ fail_invalidate:
|
||||
/* If not doing postcopy, vm_start() will be called: let's regain
|
||||
* control on images.
|
||||
*/
|
||||
if (s->state == MIGRATION_STATUS_ACTIVE) {
|
||||
if (s->state == MIGRATION_STATUS_ACTIVE ||
|
||||
s->state == MIGRATION_STATUS_DEVICE) {
|
||||
Error *local_err = NULL;
|
||||
|
||||
qemu_mutex_lock_iothread();
|
||||
|
||||
+21
-4
@@ -81,7 +81,7 @@ enum qemu_vm_cmd {
|
||||
MIG_CMD_MAX
|
||||
};
|
||||
|
||||
#define MAX_VM_CMD_PACKAGED_SIZE (1ul << 24)
|
||||
#define MAX_VM_CMD_PACKAGED_SIZE UINT32_MAX
|
||||
static struct mig_cmd_args {
|
||||
ssize_t len; /* -1 = variable */
|
||||
const char *name;
|
||||
@@ -1376,7 +1376,8 @@ static int qemu_loadvm_state_main(QEMUFile *f, MigrationIncomingState *mis);
|
||||
* *might* happen - it might be skipped if precopy transferred everything
|
||||
* quickly.
|
||||
*/
|
||||
static int loadvm_postcopy_handle_advise(MigrationIncomingState *mis)
|
||||
static int loadvm_postcopy_handle_advise(MigrationIncomingState *mis,
|
||||
uint16_t len)
|
||||
{
|
||||
PostcopyState ps = postcopy_state_set(POSTCOPY_INCOMING_ADVISE);
|
||||
uint64_t remote_pagesize_summary, local_pagesize_summary, remote_tps;
|
||||
@@ -1387,8 +1388,22 @@ static int loadvm_postcopy_handle_advise(MigrationIncomingState *mis)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!migrate_postcopy_ram()) {
|
||||
switch (len) {
|
||||
case 0:
|
||||
if (migrate_postcopy_ram()) {
|
||||
error_report("RAM postcopy is enabled but have 0 byte advise");
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
case 8 + 8:
|
||||
if (!migrate_postcopy_ram()) {
|
||||
error_report("RAM postcopy is disabled but have 16 byte advise");
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
error_report("CMD_POSTCOPY_ADVISE invalid length (%d)", len);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!postcopy_ram_supported_by_host(mis)) {
|
||||
@@ -1807,7 +1822,7 @@ static int loadvm_process_command(QEMUFile *f)
|
||||
return loadvm_handle_cmd_packaged(mis);
|
||||
|
||||
case MIG_CMD_POSTCOPY_ADVISE:
|
||||
return loadvm_postcopy_handle_advise(mis);
|
||||
return loadvm_postcopy_handle_advise(mis, len);
|
||||
|
||||
case MIG_CMD_POSTCOPY_LISTEN:
|
||||
return loadvm_postcopy_handle_listen(mis);
|
||||
@@ -2266,6 +2281,7 @@ void qmp_xen_save_devices_state(const char *filename, bool has_live, bool live,
|
||||
}
|
||||
qio_channel_set_name(QIO_CHANNEL(ioc), "migration-xen-save-state");
|
||||
f = qemu_fopen_channel_output(QIO_CHANNEL(ioc));
|
||||
object_unref(OBJECT(ioc));
|
||||
ret = qemu_save_device_state(f);
|
||||
qemu_fclose(f);
|
||||
if (ret < 0) {
|
||||
@@ -2313,6 +2329,7 @@ void qmp_xen_load_devices_state(const char *filename, Error **errp)
|
||||
}
|
||||
qio_channel_set_name(QIO_CHANNEL(ioc), "migration-xen-load-state");
|
||||
f = qemu_fopen_channel_input(QIO_CHANNEL(ioc));
|
||||
object_unref(OBJECT(ioc));
|
||||
|
||||
ret = qemu_loadvm_state(f);
|
||||
qemu_fclose(f);
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
#define ARCHHEADING(text, arch_mask) \
|
||||
if ((arch_mask) & arch_type) \
|
||||
puts(stringify(text) ":");
|
||||
puts(stringify(text));
|
||||
|
||||
#define DEFHEADING(text) ARCHHEADING(text, QEMU_ARCH_ALL)
|
||||
|
||||
|
||||
+14
-13
@@ -6,7 +6,7 @@ HXCOMM construct option structures, enums and help message for specified
|
||||
HXCOMM architectures.
|
||||
HXCOMM HXCOMM can be used for comments, discarded from both texi and C
|
||||
|
||||
DEFHEADING(Standard options)
|
||||
DEFHEADING(Standard options:)
|
||||
STEXI
|
||||
@table @option
|
||||
ETEXI
|
||||
@@ -578,7 +578,7 @@ STEXI
|
||||
ETEXI
|
||||
DEFHEADING()
|
||||
|
||||
DEFHEADING(Block device options)
|
||||
DEFHEADING(Block device options:)
|
||||
STEXI
|
||||
@table @option
|
||||
ETEXI
|
||||
@@ -1181,7 +1181,7 @@ STEXI
|
||||
ETEXI
|
||||
DEFHEADING()
|
||||
|
||||
DEFHEADING(USB options)
|
||||
DEFHEADING(USB options:)
|
||||
STEXI
|
||||
@table @option
|
||||
ETEXI
|
||||
@@ -1246,7 +1246,7 @@ STEXI
|
||||
ETEXI
|
||||
DEFHEADING()
|
||||
|
||||
DEFHEADING(Display options)
|
||||
DEFHEADING(Display options:)
|
||||
STEXI
|
||||
@table @option
|
||||
ETEXI
|
||||
@@ -1783,7 +1783,7 @@ STEXI
|
||||
ETEXI
|
||||
ARCHHEADING(, QEMU_ARCH_I386)
|
||||
|
||||
ARCHHEADING(i386 target only, QEMU_ARCH_I386)
|
||||
ARCHHEADING(i386 target only:, QEMU_ARCH_I386)
|
||||
STEXI
|
||||
@table @option
|
||||
ETEXI
|
||||
@@ -1899,7 +1899,7 @@ STEXI
|
||||
ETEXI
|
||||
DEFHEADING()
|
||||
|
||||
DEFHEADING(Network options)
|
||||
DEFHEADING(Network options:)
|
||||
STEXI
|
||||
@table @option
|
||||
ETEXI
|
||||
@@ -2480,7 +2480,7 @@ STEXI
|
||||
ETEXI
|
||||
DEFHEADING()
|
||||
|
||||
DEFHEADING(Character device options)
|
||||
DEFHEADING(Character device options:)
|
||||
STEXI
|
||||
|
||||
The general form of a character device option is:
|
||||
@@ -2813,7 +2813,7 @@ STEXI
|
||||
ETEXI
|
||||
DEFHEADING()
|
||||
|
||||
DEFHEADING(Device URL Syntax)
|
||||
DEFHEADING(Device URL Syntax:)
|
||||
STEXI
|
||||
|
||||
In addition to using normal file images for the emulated storage devices,
|
||||
@@ -3043,7 +3043,7 @@ STEXI
|
||||
@end table
|
||||
ETEXI
|
||||
|
||||
DEFHEADING(Bluetooth(R) options)
|
||||
DEFHEADING(Bluetooth(R) options:)
|
||||
STEXI
|
||||
@table @option
|
||||
ETEXI
|
||||
@@ -3119,7 +3119,7 @@ ETEXI
|
||||
DEFHEADING()
|
||||
|
||||
#ifdef CONFIG_TPM
|
||||
DEFHEADING(TPM device options)
|
||||
DEFHEADING(TPM device options:)
|
||||
|
||||
DEF("tpmdev", HAS_ARG, QEMU_OPTION_tpmdev, \
|
||||
"-tpmdev passthrough,id=id[,path=path][,cancel-path=path]\n"
|
||||
@@ -3209,7 +3209,7 @@ DEFHEADING()
|
||||
|
||||
#endif
|
||||
|
||||
DEFHEADING(Linux/Multiboot boot specific)
|
||||
DEFHEADING(Linux/Multiboot boot specific:)
|
||||
STEXI
|
||||
|
||||
When using these options, you can use a given Linux or Multiboot
|
||||
@@ -3265,7 +3265,7 @@ STEXI
|
||||
ETEXI
|
||||
DEFHEADING()
|
||||
|
||||
DEFHEADING(Debug/Expert options)
|
||||
DEFHEADING(Debug/Expert options:)
|
||||
STEXI
|
||||
@table @option
|
||||
ETEXI
|
||||
@@ -4171,7 +4171,8 @@ STEXI
|
||||
@end table
|
||||
ETEXI
|
||||
DEFHEADING()
|
||||
DEFHEADING(Generic object creation)
|
||||
|
||||
DEFHEADING(Generic object creation:)
|
||||
STEXI
|
||||
@table @option
|
||||
ETEXI
|
||||
|
||||
+2
-1
@@ -19,7 +19,8 @@ hxtoh()
|
||||
print_texi_heading()
|
||||
{
|
||||
if test "$*" != ""; then
|
||||
printf "@subsection %s\n" "$*"
|
||||
title="$*"
|
||||
printf "@subsection %s\n" "${title%:}"
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
+26
-4
@@ -314,6 +314,22 @@ static int is_mpath(int fd)
|
||||
return !strncmp(tgt->target_type, "multipath", DM_MAX_TYPE_NAME);
|
||||
}
|
||||
|
||||
static SCSISense mpath_generic_sense(int r)
|
||||
{
|
||||
switch (r) {
|
||||
case MPATH_PR_SENSE_NOT_READY:
|
||||
return SENSE_CODE(NOT_READY);
|
||||
case MPATH_PR_SENSE_MEDIUM_ERROR:
|
||||
return SENSE_CODE(READ_ERROR);
|
||||
case MPATH_PR_SENSE_HARDWARE_ERROR:
|
||||
return SENSE_CODE(TARGET_FAILURE);
|
||||
case MPATH_PR_SENSE_ABORTED_COMMAND:
|
||||
return SENSE_CODE(IO_ERROR);
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
static int mpath_reconstruct_sense(int fd, int r, uint8_t *sense)
|
||||
{
|
||||
switch (r) {
|
||||
@@ -329,7 +345,13 @@ static int mpath_reconstruct_sense(int fd, int r, uint8_t *sense)
|
||||
*/
|
||||
uint8_t cdb[6] = { TEST_UNIT_READY };
|
||||
int sz = 0;
|
||||
return do_sgio(fd, cdb, sense, NULL, &sz, SG_DXFER_NONE);
|
||||
int r = do_sgio(fd, cdb, sense, NULL, &sz, SG_DXFER_NONE);
|
||||
|
||||
if (r != GOOD) {
|
||||
return r;
|
||||
}
|
||||
scsi_build_sense(sense, mpath_generic_sense(r));
|
||||
return CHECK_CONDITION;
|
||||
}
|
||||
|
||||
case MPATH_PR_SENSE_UNIT_ATTENTION:
|
||||
@@ -449,7 +471,7 @@ static int multipath_pr_out(int fd, const uint8_t *cdb, uint8_t *sense,
|
||||
memset(¶mp, 0, sizeof(paramp));
|
||||
memcpy(¶mp.key, ¶m[0], 8);
|
||||
memcpy(¶mp.sa_key, ¶m[8], 8);
|
||||
paramp.sa_flags = param[10];
|
||||
paramp.sa_flags = param[20];
|
||||
if (sz > PR_OUT_FIXED_PARAM_SIZE) {
|
||||
size_t transportid_len;
|
||||
int i, j;
|
||||
@@ -478,8 +500,8 @@ static int multipath_pr_out(int fd, const uint8_t *cdb, uint8_t *sense,
|
||||
j += offsetof(struct transportid, n_port_name[8]);
|
||||
i += 24;
|
||||
break;
|
||||
case 3:
|
||||
case 0x43:
|
||||
case 5:
|
||||
case 0x45:
|
||||
/* iSCSI transport. */
|
||||
len = lduw_be_p(¶m[i + 2]);
|
||||
if (len > 252 || (len & 3) || i + len + 4 > transportid_len) {
|
||||
|
||||
@@ -211,6 +211,16 @@ const struct SCSISense sense_code_LUN_COMM_FAILURE = {
|
||||
.key = ABORTED_COMMAND, .asc = 0x08, .ascq = 0x00
|
||||
};
|
||||
|
||||
/* Medium Error, Unrecovered read error */
|
||||
const struct SCSISense sense_code_READ_ERROR = {
|
||||
.key = MEDIUM_ERROR, .asc = 0x11, .ascq = 0x00
|
||||
};
|
||||
|
||||
/* Not ready, Cause not reportable */
|
||||
const struct SCSISense sense_code_NOT_READY = {
|
||||
.key = NOT_READY, .asc = 0x04, .ascq = 0x00
|
||||
};
|
||||
|
||||
/* Unit attention, Capacity data has changed */
|
||||
const struct SCSISense sense_code_CAPACITY_CHANGED = {
|
||||
.key = UNIT_ATTENTION, .asc = 0x2a, .ascq = 0x09
|
||||
|
||||
+451
-4
@@ -458,7 +458,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
|
||||
NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, "spec-ctrl", NULL,
|
||||
NULL, NULL, NULL, NULL,
|
||||
},
|
||||
.cpuid_eax = 7,
|
||||
@@ -482,6 +482,22 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
|
||||
.tcg_features = TCG_APM_FEATURES,
|
||||
.unmigratable_flags = CPUID_APM_INVTSC,
|
||||
},
|
||||
[FEAT_8000_0008_EBX] = {
|
||||
.feat_names = {
|
||||
NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL,
|
||||
"ibpb", NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL,
|
||||
},
|
||||
.cpuid_eax = 0x80000008,
|
||||
.cpuid_reg = R_EBX,
|
||||
.tcg_features = 0,
|
||||
.unmigratable_flags = 0,
|
||||
},
|
||||
[FEAT_XSAVE] = {
|
||||
.feat_names = {
|
||||
"xsaveopt", "xsavec", "xgetbv1", "xsaves",
|
||||
@@ -748,7 +764,7 @@ struct X86CPUDefinition {
|
||||
int model;
|
||||
int stepping;
|
||||
FeatureWordArray features;
|
||||
char model_id[48];
|
||||
const char *model_id;
|
||||
};
|
||||
|
||||
static X86CPUDefinition builtin_x86_defs[] = {
|
||||
@@ -917,6 +933,7 @@ static X86CPUDefinition builtin_x86_defs[] = {
|
||||
.features[FEAT_1_EDX] =
|
||||
I486_FEATURES,
|
||||
.xlevel = 0,
|
||||
.model_id = "",
|
||||
},
|
||||
{
|
||||
.name = "pentium",
|
||||
@@ -928,6 +945,7 @@ static X86CPUDefinition builtin_x86_defs[] = {
|
||||
.features[FEAT_1_EDX] =
|
||||
PENTIUM_FEATURES,
|
||||
.xlevel = 0,
|
||||
.model_id = "",
|
||||
},
|
||||
{
|
||||
.name = "pentium2",
|
||||
@@ -939,6 +957,7 @@ static X86CPUDefinition builtin_x86_defs[] = {
|
||||
.features[FEAT_1_EDX] =
|
||||
PENTIUM2_FEATURES,
|
||||
.xlevel = 0,
|
||||
.model_id = "",
|
||||
},
|
||||
{
|
||||
.name = "pentium3",
|
||||
@@ -950,6 +969,7 @@ static X86CPUDefinition builtin_x86_defs[] = {
|
||||
.features[FEAT_1_EDX] =
|
||||
PENTIUM3_FEATURES,
|
||||
.xlevel = 0,
|
||||
.model_id = "",
|
||||
},
|
||||
{
|
||||
.name = "athlon",
|
||||
@@ -1059,6 +1079,31 @@ static X86CPUDefinition builtin_x86_defs[] = {
|
||||
.xlevel = 0x80000008,
|
||||
.model_id = "Intel Core i7 9xx (Nehalem Class Core i7)",
|
||||
},
|
||||
{
|
||||
.name = "Nehalem-IBRS",
|
||||
.level = 11,
|
||||
.vendor = CPUID_VENDOR_INTEL,
|
||||
.family = 6,
|
||||
.model = 26,
|
||||
.stepping = 3,
|
||||
.features[FEAT_1_EDX] =
|
||||
CPUID_VME | CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
|
||||
CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
|
||||
CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
|
||||
CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
|
||||
CPUID_DE | CPUID_FP87,
|
||||
.features[FEAT_1_ECX] =
|
||||
CPUID_EXT_POPCNT | CPUID_EXT_SSE42 | CPUID_EXT_SSE41 |
|
||||
CPUID_EXT_CX16 | CPUID_EXT_SSSE3 | CPUID_EXT_SSE3,
|
||||
.features[FEAT_7_0_EDX] =
|
||||
CPUID_7_0_EDX_SPEC_CTRL,
|
||||
.features[FEAT_8000_0001_EDX] =
|
||||
CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX,
|
||||
.features[FEAT_8000_0001_ECX] =
|
||||
CPUID_EXT3_LAHF_LM,
|
||||
.xlevel = 0x80000008,
|
||||
.model_id = "Intel Core i7 9xx (Nehalem Core i7, IBRS update)",
|
||||
},
|
||||
{
|
||||
.name = "Westmere",
|
||||
.level = 11,
|
||||
@@ -1085,6 +1130,34 @@ static X86CPUDefinition builtin_x86_defs[] = {
|
||||
.xlevel = 0x80000008,
|
||||
.model_id = "Westmere E56xx/L56xx/X56xx (Nehalem-C)",
|
||||
},
|
||||
{
|
||||
.name = "Westmere-IBRS",
|
||||
.level = 11,
|
||||
.vendor = CPUID_VENDOR_INTEL,
|
||||
.family = 6,
|
||||
.model = 44,
|
||||
.stepping = 1,
|
||||
.features[FEAT_1_EDX] =
|
||||
CPUID_VME | CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
|
||||
CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
|
||||
CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
|
||||
CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
|
||||
CPUID_DE | CPUID_FP87,
|
||||
.features[FEAT_1_ECX] =
|
||||
CPUID_EXT_AES | CPUID_EXT_POPCNT | CPUID_EXT_SSE42 |
|
||||
CPUID_EXT_SSE41 | CPUID_EXT_CX16 | CPUID_EXT_SSSE3 |
|
||||
CPUID_EXT_PCLMULQDQ | CPUID_EXT_SSE3,
|
||||
.features[FEAT_8000_0001_EDX] =
|
||||
CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX,
|
||||
.features[FEAT_8000_0001_ECX] =
|
||||
CPUID_EXT3_LAHF_LM,
|
||||
.features[FEAT_7_0_EDX] =
|
||||
CPUID_7_0_EDX_SPEC_CTRL,
|
||||
.features[FEAT_6_EAX] =
|
||||
CPUID_6_EAX_ARAT,
|
||||
.xlevel = 0x80000008,
|
||||
.model_id = "Westmere E56xx/L56xx/X56xx (IBRS update)",
|
||||
},
|
||||
{
|
||||
.name = "SandyBridge",
|
||||
.level = 0xd,
|
||||
@@ -1116,6 +1189,39 @@ static X86CPUDefinition builtin_x86_defs[] = {
|
||||
.xlevel = 0x80000008,
|
||||
.model_id = "Intel Xeon E312xx (Sandy Bridge)",
|
||||
},
|
||||
{
|
||||
.name = "SandyBridge-IBRS",
|
||||
.level = 0xd,
|
||||
.vendor = CPUID_VENDOR_INTEL,
|
||||
.family = 6,
|
||||
.model = 42,
|
||||
.stepping = 1,
|
||||
.features[FEAT_1_EDX] =
|
||||
CPUID_VME | CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
|
||||
CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
|
||||
CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
|
||||
CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
|
||||
CPUID_DE | CPUID_FP87,
|
||||
.features[FEAT_1_ECX] =
|
||||
CPUID_EXT_AVX | CPUID_EXT_XSAVE | CPUID_EXT_AES |
|
||||
CPUID_EXT_TSC_DEADLINE_TIMER | CPUID_EXT_POPCNT |
|
||||
CPUID_EXT_X2APIC | CPUID_EXT_SSE42 | CPUID_EXT_SSE41 |
|
||||
CPUID_EXT_CX16 | CPUID_EXT_SSSE3 | CPUID_EXT_PCLMULQDQ |
|
||||
CPUID_EXT_SSE3,
|
||||
.features[FEAT_8000_0001_EDX] =
|
||||
CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX |
|
||||
CPUID_EXT2_SYSCALL,
|
||||
.features[FEAT_8000_0001_ECX] =
|
||||
CPUID_EXT3_LAHF_LM,
|
||||
.features[FEAT_7_0_EDX] =
|
||||
CPUID_7_0_EDX_SPEC_CTRL,
|
||||
.features[FEAT_XSAVE] =
|
||||
CPUID_XSAVE_XSAVEOPT,
|
||||
.features[FEAT_6_EAX] =
|
||||
CPUID_6_EAX_ARAT,
|
||||
.xlevel = 0x80000008,
|
||||
.model_id = "Intel Xeon E312xx (Sandy Bridge, IBRS update)",
|
||||
},
|
||||
{
|
||||
.name = "IvyBridge",
|
||||
.level = 0xd,
|
||||
@@ -1150,6 +1256,42 @@ static X86CPUDefinition builtin_x86_defs[] = {
|
||||
.xlevel = 0x80000008,
|
||||
.model_id = "Intel Xeon E3-12xx v2 (Ivy Bridge)",
|
||||
},
|
||||
{
|
||||
.name = "IvyBridge-IBRS",
|
||||
.level = 0xd,
|
||||
.vendor = CPUID_VENDOR_INTEL,
|
||||
.family = 6,
|
||||
.model = 58,
|
||||
.stepping = 9,
|
||||
.features[FEAT_1_EDX] =
|
||||
CPUID_VME | CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
|
||||
CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
|
||||
CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
|
||||
CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
|
||||
CPUID_DE | CPUID_FP87,
|
||||
.features[FEAT_1_ECX] =
|
||||
CPUID_EXT_AVX | CPUID_EXT_XSAVE | CPUID_EXT_AES |
|
||||
CPUID_EXT_TSC_DEADLINE_TIMER | CPUID_EXT_POPCNT |
|
||||
CPUID_EXT_X2APIC | CPUID_EXT_SSE42 | CPUID_EXT_SSE41 |
|
||||
CPUID_EXT_CX16 | CPUID_EXT_SSSE3 | CPUID_EXT_PCLMULQDQ |
|
||||
CPUID_EXT_SSE3 | CPUID_EXT_F16C | CPUID_EXT_RDRAND,
|
||||
.features[FEAT_7_0_EBX] =
|
||||
CPUID_7_0_EBX_FSGSBASE | CPUID_7_0_EBX_SMEP |
|
||||
CPUID_7_0_EBX_ERMS,
|
||||
.features[FEAT_8000_0001_EDX] =
|
||||
CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX |
|
||||
CPUID_EXT2_SYSCALL,
|
||||
.features[FEAT_8000_0001_ECX] =
|
||||
CPUID_EXT3_LAHF_LM,
|
||||
.features[FEAT_7_0_EDX] =
|
||||
CPUID_7_0_EDX_SPEC_CTRL,
|
||||
.features[FEAT_XSAVE] =
|
||||
CPUID_XSAVE_XSAVEOPT,
|
||||
.features[FEAT_6_EAX] =
|
||||
CPUID_6_EAX_ARAT,
|
||||
.xlevel = 0x80000008,
|
||||
.model_id = "Intel Xeon E3-12xx v2 (Ivy Bridge, IBRS)",
|
||||
},
|
||||
{
|
||||
.name = "Haswell-noTSX",
|
||||
.level = 0xd,
|
||||
@@ -1185,7 +1327,46 @@ static X86CPUDefinition builtin_x86_defs[] = {
|
||||
CPUID_6_EAX_ARAT,
|
||||
.xlevel = 0x80000008,
|
||||
.model_id = "Intel Core Processor (Haswell, no TSX)",
|
||||
}, {
|
||||
},
|
||||
{
|
||||
.name = "Haswell-noTSX-IBRS",
|
||||
.level = 0xd,
|
||||
.vendor = CPUID_VENDOR_INTEL,
|
||||
.family = 6,
|
||||
.model = 60,
|
||||
.stepping = 1,
|
||||
.features[FEAT_1_EDX] =
|
||||
CPUID_VME | CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
|
||||
CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
|
||||
CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
|
||||
CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
|
||||
CPUID_DE | CPUID_FP87,
|
||||
.features[FEAT_1_ECX] =
|
||||
CPUID_EXT_AVX | CPUID_EXT_XSAVE | CPUID_EXT_AES |
|
||||
CPUID_EXT_POPCNT | CPUID_EXT_X2APIC | CPUID_EXT_SSE42 |
|
||||
CPUID_EXT_SSE41 | CPUID_EXT_CX16 | CPUID_EXT_SSSE3 |
|
||||
CPUID_EXT_PCLMULQDQ | CPUID_EXT_SSE3 |
|
||||
CPUID_EXT_TSC_DEADLINE_TIMER | CPUID_EXT_FMA | CPUID_EXT_MOVBE |
|
||||
CPUID_EXT_PCID | CPUID_EXT_F16C | CPUID_EXT_RDRAND,
|
||||
.features[FEAT_8000_0001_EDX] =
|
||||
CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX |
|
||||
CPUID_EXT2_SYSCALL,
|
||||
.features[FEAT_8000_0001_ECX] =
|
||||
CPUID_EXT3_ABM | CPUID_EXT3_LAHF_LM,
|
||||
.features[FEAT_7_0_EDX] =
|
||||
CPUID_7_0_EDX_SPEC_CTRL,
|
||||
.features[FEAT_7_0_EBX] =
|
||||
CPUID_7_0_EBX_FSGSBASE | CPUID_7_0_EBX_BMI1 |
|
||||
CPUID_7_0_EBX_AVX2 | CPUID_7_0_EBX_SMEP |
|
||||
CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ERMS | CPUID_7_0_EBX_INVPCID,
|
||||
.features[FEAT_XSAVE] =
|
||||
CPUID_XSAVE_XSAVEOPT,
|
||||
.features[FEAT_6_EAX] =
|
||||
CPUID_6_EAX_ARAT,
|
||||
.xlevel = 0x80000008,
|
||||
.model_id = "Intel Core Processor (Haswell, no TSX, IBRS)",
|
||||
},
|
||||
{
|
||||
.name = "Haswell",
|
||||
.level = 0xd,
|
||||
.vendor = CPUID_VENDOR_INTEL,
|
||||
@@ -1222,6 +1403,45 @@ static X86CPUDefinition builtin_x86_defs[] = {
|
||||
.xlevel = 0x80000008,
|
||||
.model_id = "Intel Core Processor (Haswell)",
|
||||
},
|
||||
{
|
||||
.name = "Haswell-IBRS",
|
||||
.level = 0xd,
|
||||
.vendor = CPUID_VENDOR_INTEL,
|
||||
.family = 6,
|
||||
.model = 60,
|
||||
.stepping = 4,
|
||||
.features[FEAT_1_EDX] =
|
||||
CPUID_VME | CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
|
||||
CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
|
||||
CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
|
||||
CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
|
||||
CPUID_DE | CPUID_FP87,
|
||||
.features[FEAT_1_ECX] =
|
||||
CPUID_EXT_AVX | CPUID_EXT_XSAVE | CPUID_EXT_AES |
|
||||
CPUID_EXT_POPCNT | CPUID_EXT_X2APIC | CPUID_EXT_SSE42 |
|
||||
CPUID_EXT_SSE41 | CPUID_EXT_CX16 | CPUID_EXT_SSSE3 |
|
||||
CPUID_EXT_PCLMULQDQ | CPUID_EXT_SSE3 |
|
||||
CPUID_EXT_TSC_DEADLINE_TIMER | CPUID_EXT_FMA | CPUID_EXT_MOVBE |
|
||||
CPUID_EXT_PCID | CPUID_EXT_F16C | CPUID_EXT_RDRAND,
|
||||
.features[FEAT_8000_0001_EDX] =
|
||||
CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX |
|
||||
CPUID_EXT2_SYSCALL,
|
||||
.features[FEAT_8000_0001_ECX] =
|
||||
CPUID_EXT3_ABM | CPUID_EXT3_LAHF_LM,
|
||||
.features[FEAT_7_0_EDX] =
|
||||
CPUID_7_0_EDX_SPEC_CTRL,
|
||||
.features[FEAT_7_0_EBX] =
|
||||
CPUID_7_0_EBX_FSGSBASE | CPUID_7_0_EBX_BMI1 |
|
||||
CPUID_7_0_EBX_HLE | CPUID_7_0_EBX_AVX2 | CPUID_7_0_EBX_SMEP |
|
||||
CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ERMS | CPUID_7_0_EBX_INVPCID |
|
||||
CPUID_7_0_EBX_RTM,
|
||||
.features[FEAT_XSAVE] =
|
||||
CPUID_XSAVE_XSAVEOPT,
|
||||
.features[FEAT_6_EAX] =
|
||||
CPUID_6_EAX_ARAT,
|
||||
.xlevel = 0x80000008,
|
||||
.model_id = "Intel Core Processor (Haswell, IBRS)",
|
||||
},
|
||||
{
|
||||
.name = "Broadwell-noTSX",
|
||||
.level = 0xd,
|
||||
@@ -1260,6 +1480,46 @@ static X86CPUDefinition builtin_x86_defs[] = {
|
||||
.xlevel = 0x80000008,
|
||||
.model_id = "Intel Core Processor (Broadwell, no TSX)",
|
||||
},
|
||||
{
|
||||
.name = "Broadwell-noTSX-IBRS",
|
||||
.level = 0xd,
|
||||
.vendor = CPUID_VENDOR_INTEL,
|
||||
.family = 6,
|
||||
.model = 61,
|
||||
.stepping = 2,
|
||||
.features[FEAT_1_EDX] =
|
||||
CPUID_VME | CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
|
||||
CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
|
||||
CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
|
||||
CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
|
||||
CPUID_DE | CPUID_FP87,
|
||||
.features[FEAT_1_ECX] =
|
||||
CPUID_EXT_AVX | CPUID_EXT_XSAVE | CPUID_EXT_AES |
|
||||
CPUID_EXT_POPCNT | CPUID_EXT_X2APIC | CPUID_EXT_SSE42 |
|
||||
CPUID_EXT_SSE41 | CPUID_EXT_CX16 | CPUID_EXT_SSSE3 |
|
||||
CPUID_EXT_PCLMULQDQ | CPUID_EXT_SSE3 |
|
||||
CPUID_EXT_TSC_DEADLINE_TIMER | CPUID_EXT_FMA | CPUID_EXT_MOVBE |
|
||||
CPUID_EXT_PCID | CPUID_EXT_F16C | CPUID_EXT_RDRAND,
|
||||
.features[FEAT_8000_0001_EDX] =
|
||||
CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX |
|
||||
CPUID_EXT2_SYSCALL,
|
||||
.features[FEAT_8000_0001_ECX] =
|
||||
CPUID_EXT3_ABM | CPUID_EXT3_LAHF_LM | CPUID_EXT3_3DNOWPREFETCH,
|
||||
.features[FEAT_7_0_EDX] =
|
||||
CPUID_7_0_EDX_SPEC_CTRL,
|
||||
.features[FEAT_7_0_EBX] =
|
||||
CPUID_7_0_EBX_FSGSBASE | CPUID_7_0_EBX_BMI1 |
|
||||
CPUID_7_0_EBX_AVX2 | CPUID_7_0_EBX_SMEP |
|
||||
CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ERMS | CPUID_7_0_EBX_INVPCID |
|
||||
CPUID_7_0_EBX_RDSEED | CPUID_7_0_EBX_ADX |
|
||||
CPUID_7_0_EBX_SMAP,
|
||||
.features[FEAT_XSAVE] =
|
||||
CPUID_XSAVE_XSAVEOPT,
|
||||
.features[FEAT_6_EAX] =
|
||||
CPUID_6_EAX_ARAT,
|
||||
.xlevel = 0x80000008,
|
||||
.model_id = "Intel Core Processor (Broadwell, no TSX, IBRS)",
|
||||
},
|
||||
{
|
||||
.name = "Broadwell",
|
||||
.level = 0xd,
|
||||
@@ -1298,6 +1558,46 @@ static X86CPUDefinition builtin_x86_defs[] = {
|
||||
.xlevel = 0x80000008,
|
||||
.model_id = "Intel Core Processor (Broadwell)",
|
||||
},
|
||||
{
|
||||
.name = "Broadwell-IBRS",
|
||||
.level = 0xd,
|
||||
.vendor = CPUID_VENDOR_INTEL,
|
||||
.family = 6,
|
||||
.model = 61,
|
||||
.stepping = 2,
|
||||
.features[FEAT_1_EDX] =
|
||||
CPUID_VME | CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
|
||||
CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
|
||||
CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
|
||||
CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
|
||||
CPUID_DE | CPUID_FP87,
|
||||
.features[FEAT_1_ECX] =
|
||||
CPUID_EXT_AVX | CPUID_EXT_XSAVE | CPUID_EXT_AES |
|
||||
CPUID_EXT_POPCNT | CPUID_EXT_X2APIC | CPUID_EXT_SSE42 |
|
||||
CPUID_EXT_SSE41 | CPUID_EXT_CX16 | CPUID_EXT_SSSE3 |
|
||||
CPUID_EXT_PCLMULQDQ | CPUID_EXT_SSE3 |
|
||||
CPUID_EXT_TSC_DEADLINE_TIMER | CPUID_EXT_FMA | CPUID_EXT_MOVBE |
|
||||
CPUID_EXT_PCID | CPUID_EXT_F16C | CPUID_EXT_RDRAND,
|
||||
.features[FEAT_8000_0001_EDX] =
|
||||
CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX |
|
||||
CPUID_EXT2_SYSCALL,
|
||||
.features[FEAT_8000_0001_ECX] =
|
||||
CPUID_EXT3_ABM | CPUID_EXT3_LAHF_LM | CPUID_EXT3_3DNOWPREFETCH,
|
||||
.features[FEAT_7_0_EDX] =
|
||||
CPUID_7_0_EDX_SPEC_CTRL,
|
||||
.features[FEAT_7_0_EBX] =
|
||||
CPUID_7_0_EBX_FSGSBASE | CPUID_7_0_EBX_BMI1 |
|
||||
CPUID_7_0_EBX_HLE | CPUID_7_0_EBX_AVX2 | CPUID_7_0_EBX_SMEP |
|
||||
CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ERMS | CPUID_7_0_EBX_INVPCID |
|
||||
CPUID_7_0_EBX_RTM | CPUID_7_0_EBX_RDSEED | CPUID_7_0_EBX_ADX |
|
||||
CPUID_7_0_EBX_SMAP,
|
||||
.features[FEAT_XSAVE] =
|
||||
CPUID_XSAVE_XSAVEOPT,
|
||||
.features[FEAT_6_EAX] =
|
||||
CPUID_6_EAX_ARAT,
|
||||
.xlevel = 0x80000008,
|
||||
.model_id = "Intel Core Processor (Broadwell, IBRS)",
|
||||
},
|
||||
{
|
||||
.name = "Skylake-Client",
|
||||
.level = 0xd,
|
||||
@@ -1343,6 +1643,53 @@ static X86CPUDefinition builtin_x86_defs[] = {
|
||||
.xlevel = 0x80000008,
|
||||
.model_id = "Intel Core Processor (Skylake)",
|
||||
},
|
||||
{
|
||||
.name = "Skylake-Client-IBRS",
|
||||
.level = 0xd,
|
||||
.vendor = CPUID_VENDOR_INTEL,
|
||||
.family = 6,
|
||||
.model = 94,
|
||||
.stepping = 3,
|
||||
.features[FEAT_1_EDX] =
|
||||
CPUID_VME | CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
|
||||
CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
|
||||
CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
|
||||
CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
|
||||
CPUID_DE | CPUID_FP87,
|
||||
.features[FEAT_1_ECX] =
|
||||
CPUID_EXT_AVX | CPUID_EXT_XSAVE | CPUID_EXT_AES |
|
||||
CPUID_EXT_POPCNT | CPUID_EXT_X2APIC | CPUID_EXT_SSE42 |
|
||||
CPUID_EXT_SSE41 | CPUID_EXT_CX16 | CPUID_EXT_SSSE3 |
|
||||
CPUID_EXT_PCLMULQDQ | CPUID_EXT_SSE3 |
|
||||
CPUID_EXT_TSC_DEADLINE_TIMER | CPUID_EXT_FMA | CPUID_EXT_MOVBE |
|
||||
CPUID_EXT_PCID | CPUID_EXT_F16C | CPUID_EXT_RDRAND,
|
||||
.features[FEAT_8000_0001_EDX] =
|
||||
CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX |
|
||||
CPUID_EXT2_SYSCALL,
|
||||
.features[FEAT_8000_0001_ECX] =
|
||||
CPUID_EXT3_ABM | CPUID_EXT3_LAHF_LM | CPUID_EXT3_3DNOWPREFETCH,
|
||||
.features[FEAT_7_0_EDX] =
|
||||
CPUID_7_0_EDX_SPEC_CTRL,
|
||||
.features[FEAT_7_0_EBX] =
|
||||
CPUID_7_0_EBX_FSGSBASE | CPUID_7_0_EBX_BMI1 |
|
||||
CPUID_7_0_EBX_HLE | CPUID_7_0_EBX_AVX2 | CPUID_7_0_EBX_SMEP |
|
||||
CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ERMS | CPUID_7_0_EBX_INVPCID |
|
||||
CPUID_7_0_EBX_RTM | CPUID_7_0_EBX_RDSEED | CPUID_7_0_EBX_ADX |
|
||||
CPUID_7_0_EBX_SMAP | CPUID_7_0_EBX_MPX,
|
||||
/* Missing: XSAVES (not supported by some Linux versions,
|
||||
* including v4.1 to v4.12).
|
||||
* KVM doesn't yet expose any XSAVES state save component,
|
||||
* and the only one defined in Skylake (processor tracing)
|
||||
* probably will block migration anyway.
|
||||
*/
|
||||
.features[FEAT_XSAVE] =
|
||||
CPUID_XSAVE_XSAVEOPT | CPUID_XSAVE_XSAVEC |
|
||||
CPUID_XSAVE_XGETBV1,
|
||||
.features[FEAT_6_EAX] =
|
||||
CPUID_6_EAX_ARAT,
|
||||
.xlevel = 0x80000008,
|
||||
.model_id = "Intel Core Processor (Skylake, IBRS)",
|
||||
},
|
||||
{
|
||||
.name = "Skylake-Server",
|
||||
.level = 0xd,
|
||||
@@ -1391,6 +1738,56 @@ static X86CPUDefinition builtin_x86_defs[] = {
|
||||
.xlevel = 0x80000008,
|
||||
.model_id = "Intel Xeon Processor (Skylake)",
|
||||
},
|
||||
{
|
||||
.name = "Skylake-Server-IBRS",
|
||||
.level = 0xd,
|
||||
.vendor = CPUID_VENDOR_INTEL,
|
||||
.family = 6,
|
||||
.model = 85,
|
||||
.stepping = 4,
|
||||
.features[FEAT_1_EDX] =
|
||||
CPUID_VME | CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
|
||||
CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
|
||||
CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
|
||||
CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
|
||||
CPUID_DE | CPUID_FP87,
|
||||
.features[FEAT_1_ECX] =
|
||||
CPUID_EXT_AVX | CPUID_EXT_XSAVE | CPUID_EXT_AES |
|
||||
CPUID_EXT_POPCNT | CPUID_EXT_X2APIC | CPUID_EXT_SSE42 |
|
||||
CPUID_EXT_SSE41 | CPUID_EXT_CX16 | CPUID_EXT_SSSE3 |
|
||||
CPUID_EXT_PCLMULQDQ | CPUID_EXT_SSE3 |
|
||||
CPUID_EXT_TSC_DEADLINE_TIMER | CPUID_EXT_FMA | CPUID_EXT_MOVBE |
|
||||
CPUID_EXT_PCID | CPUID_EXT_F16C | CPUID_EXT_RDRAND,
|
||||
.features[FEAT_8000_0001_EDX] =
|
||||
CPUID_EXT2_LM | CPUID_EXT2_PDPE1GB | CPUID_EXT2_RDTSCP |
|
||||
CPUID_EXT2_NX | CPUID_EXT2_SYSCALL,
|
||||
.features[FEAT_8000_0001_ECX] =
|
||||
CPUID_EXT3_ABM | CPUID_EXT3_LAHF_LM | CPUID_EXT3_3DNOWPREFETCH,
|
||||
.features[FEAT_7_0_EDX] =
|
||||
CPUID_7_0_EDX_SPEC_CTRL,
|
||||
.features[FEAT_7_0_EBX] =
|
||||
CPUID_7_0_EBX_FSGSBASE | CPUID_7_0_EBX_BMI1 |
|
||||
CPUID_7_0_EBX_HLE | CPUID_7_0_EBX_AVX2 | CPUID_7_0_EBX_SMEP |
|
||||
CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ERMS | CPUID_7_0_EBX_INVPCID |
|
||||
CPUID_7_0_EBX_RTM | CPUID_7_0_EBX_RDSEED | CPUID_7_0_EBX_ADX |
|
||||
CPUID_7_0_EBX_SMAP | CPUID_7_0_EBX_MPX | CPUID_7_0_EBX_CLWB |
|
||||
CPUID_7_0_EBX_AVX512F | CPUID_7_0_EBX_AVX512DQ |
|
||||
CPUID_7_0_EBX_AVX512BW | CPUID_7_0_EBX_AVX512CD |
|
||||
CPUID_7_0_EBX_AVX512VL,
|
||||
/* Missing: XSAVES (not supported by some Linux versions,
|
||||
* including v4.1 to v4.12).
|
||||
* KVM doesn't yet expose any XSAVES state save component,
|
||||
* and the only one defined in Skylake (processor tracing)
|
||||
* probably will block migration anyway.
|
||||
*/
|
||||
.features[FEAT_XSAVE] =
|
||||
CPUID_XSAVE_XSAVEOPT | CPUID_XSAVE_XSAVEC |
|
||||
CPUID_XSAVE_XGETBV1,
|
||||
.features[FEAT_6_EAX] =
|
||||
CPUID_6_EAX_ARAT,
|
||||
.xlevel = 0x80000008,
|
||||
.model_id = "Intel Xeon Processor (Skylake, IBRS)",
|
||||
},
|
||||
{
|
||||
.name = "Opteron_G1",
|
||||
.level = 5,
|
||||
@@ -1565,6 +1962,52 @@ static X86CPUDefinition builtin_x86_defs[] = {
|
||||
.xlevel = 0x8000000A,
|
||||
.model_id = "AMD EPYC Processor",
|
||||
},
|
||||
{
|
||||
.name = "EPYC-IBPB",
|
||||
.level = 0xd,
|
||||
.vendor = CPUID_VENDOR_AMD,
|
||||
.family = 23,
|
||||
.model = 1,
|
||||
.stepping = 2,
|
||||
.features[FEAT_1_EDX] =
|
||||
CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | CPUID_CLFLUSH |
|
||||
CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA | CPUID_PGE |
|
||||
CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 | CPUID_MCE |
|
||||
CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE | CPUID_DE |
|
||||
CPUID_VME | CPUID_FP87,
|
||||
.features[FEAT_1_ECX] =
|
||||
CPUID_EXT_RDRAND | CPUID_EXT_F16C | CPUID_EXT_AVX |
|
||||
CPUID_EXT_XSAVE | CPUID_EXT_AES | CPUID_EXT_POPCNT |
|
||||
CPUID_EXT_MOVBE | CPUID_EXT_SSE42 | CPUID_EXT_SSE41 |
|
||||
CPUID_EXT_CX16 | CPUID_EXT_FMA | CPUID_EXT_SSSE3 |
|
||||
CPUID_EXT_MONITOR | CPUID_EXT_PCLMULQDQ | CPUID_EXT_SSE3,
|
||||
.features[FEAT_8000_0001_EDX] =
|
||||
CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_PDPE1GB |
|
||||
CPUID_EXT2_FFXSR | CPUID_EXT2_MMXEXT | CPUID_EXT2_NX |
|
||||
CPUID_EXT2_SYSCALL,
|
||||
.features[FEAT_8000_0001_ECX] =
|
||||
CPUID_EXT3_OSVW | CPUID_EXT3_3DNOWPREFETCH |
|
||||
CPUID_EXT3_MISALIGNSSE | CPUID_EXT3_SSE4A | CPUID_EXT3_ABM |
|
||||
CPUID_EXT3_CR8LEG | CPUID_EXT3_SVM | CPUID_EXT3_LAHF_LM,
|
||||
.features[FEAT_8000_0008_EBX] =
|
||||
CPUID_8000_0008_EBX_IBPB,
|
||||
.features[FEAT_7_0_EBX] =
|
||||
CPUID_7_0_EBX_FSGSBASE | CPUID_7_0_EBX_BMI1 | CPUID_7_0_EBX_AVX2 |
|
||||
CPUID_7_0_EBX_SMEP | CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_RDSEED |
|
||||
CPUID_7_0_EBX_ADX | CPUID_7_0_EBX_SMAP | CPUID_7_0_EBX_CLFLUSHOPT |
|
||||
CPUID_7_0_EBX_SHA_NI,
|
||||
/* Missing: XSAVES (not supported by some Linux versions,
|
||||
* including v4.1 to v4.12).
|
||||
* KVM doesn't yet expose any XSAVES state save component.
|
||||
*/
|
||||
.features[FEAT_XSAVE] =
|
||||
CPUID_XSAVE_XSAVEOPT | CPUID_XSAVE_XSAVEC |
|
||||
CPUID_XSAVE_XGETBV1,
|
||||
.features[FEAT_6_EAX] =
|
||||
CPUID_6_EAX_ARAT,
|
||||
.xlevel = 0x8000000A,
|
||||
.model_id = "AMD EPYC Processor (with IBPB)",
|
||||
},
|
||||
};
|
||||
|
||||
typedef struct PropValue {
|
||||
@@ -2708,6 +3151,9 @@ static void x86_register_cpudef_type(X86CPUDefinition *def)
|
||||
* they shouldn't be set on the CPU model table.
|
||||
*/
|
||||
assert(!(def->features[FEAT_8000_0001_EDX] & CPUID_EXT2_AMD_ALIASES));
|
||||
/* catch mistakes instead of silently truncating model_id when too long */
|
||||
assert(def->model_id && strlen(def->model_id) <= 48);
|
||||
|
||||
|
||||
type_register(&ti);
|
||||
g_free(typename);
|
||||
@@ -3090,7 +3536,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
|
||||
} else {
|
||||
*eax = cpu->phys_bits;
|
||||
}
|
||||
*ebx = 0;
|
||||
*ebx = env->features[FEAT_8000_0008_EBX];
|
||||
*ecx = 0;
|
||||
*edx = 0;
|
||||
if (cs->nr_cores * cs->nr_threads > 1) {
|
||||
@@ -3546,6 +3992,7 @@ static void x86_cpu_expand_features(X86CPU *cpu, Error **errp)
|
||||
x86_cpu_adjust_feat_level(cpu, FEAT_8000_0001_EDX);
|
||||
x86_cpu_adjust_feat_level(cpu, FEAT_8000_0001_ECX);
|
||||
x86_cpu_adjust_feat_level(cpu, FEAT_8000_0007_EDX);
|
||||
x86_cpu_adjust_feat_level(cpu, FEAT_8000_0008_EBX);
|
||||
x86_cpu_adjust_feat_level(cpu, FEAT_C000_0001_EDX);
|
||||
x86_cpu_adjust_feat_level(cpu, FEAT_SVM);
|
||||
x86_cpu_adjust_feat_level(cpu, FEAT_XSAVE);
|
||||
|
||||
@@ -335,6 +335,7 @@
|
||||
#define MSR_IA32_APICBASE_BASE (0xfffffU<<12)
|
||||
#define MSR_IA32_FEATURE_CONTROL 0x0000003a
|
||||
#define MSR_TSC_ADJUST 0x0000003b
|
||||
#define MSR_IA32_SPEC_CTRL 0x48
|
||||
#define MSR_IA32_TSCDEADLINE 0x6e0
|
||||
|
||||
#define FEATURE_CONTROL_LOCKED (1<<0)
|
||||
@@ -453,6 +454,7 @@ typedef enum FeatureWord {
|
||||
FEAT_8000_0001_EDX, /* CPUID[8000_0001].EDX */
|
||||
FEAT_8000_0001_ECX, /* CPUID[8000_0001].ECX */
|
||||
FEAT_8000_0007_EDX, /* CPUID[8000_0007].EDX */
|
||||
FEAT_8000_0008_EBX, /* CPUID[8000_0008].EBX */
|
||||
FEAT_C000_0001_EDX, /* CPUID[C000_0001].EDX */
|
||||
FEAT_KVM, /* CPUID[4000_0001].EAX (KVM_CPUID_FEATURES) */
|
||||
FEAT_HYPERV_EAX, /* CPUID[4000_0003].EAX */
|
||||
@@ -641,6 +643,9 @@ typedef uint32_t FeatureWordArray[FEATURE_WORDS];
|
||||
|
||||
#define CPUID_7_0_EDX_AVX512_4VNNIW (1U << 2) /* AVX512 Neural Network Instructions */
|
||||
#define CPUID_7_0_EDX_AVX512_4FMAPS (1U << 3) /* AVX512 Multiply Accumulation Single Precision */
|
||||
#define CPUID_7_0_EDX_SPEC_CTRL (1U << 26) /* Speculation Control */
|
||||
|
||||
#define CPUID_8000_0008_EBX_IBPB (1U << 12) /* Indirect Branch Prediction Barrier */
|
||||
|
||||
#define CPUID_XSAVE_XSAVEOPT (1U << 0)
|
||||
#define CPUID_XSAVE_XSAVEC (1U << 1)
|
||||
@@ -1082,6 +1087,8 @@ typedef struct CPUX86State {
|
||||
|
||||
uint32_t pkru;
|
||||
|
||||
uint64_t spec_ctrl;
|
||||
|
||||
/* End of state preserved by INIT (dummy marker). */
|
||||
struct {} end_init_save;
|
||||
|
||||
|
||||
@@ -91,6 +91,7 @@ static bool has_msr_hv_synic;
|
||||
static bool has_msr_hv_stimer;
|
||||
static bool has_msr_hv_frequencies;
|
||||
static bool has_msr_xss;
|
||||
static bool has_msr_spec_ctrl;
|
||||
|
||||
static bool has_msr_architectural_pmu;
|
||||
static uint32_t num_architectural_pmu_counters;
|
||||
@@ -1144,6 +1145,9 @@ static int kvm_get_supported_msrs(KVMState *s)
|
||||
case HV_X64_MSR_TSC_FREQUENCY:
|
||||
has_msr_hv_frequencies = true;
|
||||
break;
|
||||
case MSR_IA32_SPEC_CTRL:
|
||||
has_msr_spec_ctrl = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1626,6 +1630,9 @@ static int kvm_put_msrs(X86CPU *cpu, int level)
|
||||
if (has_msr_xss) {
|
||||
kvm_msr_entry_add(cpu, MSR_IA32_XSS, env->xss);
|
||||
}
|
||||
if (has_msr_spec_ctrl) {
|
||||
kvm_msr_entry_add(cpu, MSR_IA32_SPEC_CTRL, env->spec_ctrl);
|
||||
}
|
||||
#ifdef TARGET_X86_64
|
||||
if (lm_capable_kernel) {
|
||||
kvm_msr_entry_add(cpu, MSR_CSTAR, env->cstar);
|
||||
@@ -1634,6 +1641,7 @@ static int kvm_put_msrs(X86CPU *cpu, int level)
|
||||
kvm_msr_entry_add(cpu, MSR_LSTAR, env->lstar);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The following MSRs have side effects on the guest or are too heavy
|
||||
* for normal writeback. Limit them to reset or full state updates.
|
||||
@@ -1998,6 +2006,9 @@ static int kvm_get_msrs(X86CPU *cpu)
|
||||
if (has_msr_xss) {
|
||||
kvm_msr_entry_add(cpu, MSR_IA32_XSS, 0);
|
||||
}
|
||||
if (has_msr_spec_ctrl) {
|
||||
kvm_msr_entry_add(cpu, MSR_IA32_SPEC_CTRL, 0);
|
||||
}
|
||||
|
||||
|
||||
if (!env->tsc_valid) {
|
||||
@@ -2347,6 +2358,9 @@ static int kvm_get_msrs(X86CPU *cpu)
|
||||
env->mtrr_var[MSR_MTRRphysIndex(index)].base = msrs[i].data;
|
||||
}
|
||||
break;
|
||||
case MSR_IA32_SPEC_CTRL:
|
||||
env->spec_ctrl = msrs[i].data;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -818,6 +818,25 @@ static const VMStateDescription vmstate_mcg_ext_ctl = {
|
||||
}
|
||||
};
|
||||
|
||||
static bool spec_ctrl_needed(void *opaque)
|
||||
{
|
||||
X86CPU *cpu = opaque;
|
||||
CPUX86State *env = &cpu->env;
|
||||
|
||||
return env->spec_ctrl != 0;
|
||||
}
|
||||
|
||||
static const VMStateDescription vmstate_spec_ctrl = {
|
||||
.name = "cpu/spec_ctrl",
|
||||
.version_id = 1,
|
||||
.minimum_version_id = 1,
|
||||
.needed = spec_ctrl_needed,
|
||||
.fields = (VMStateField[]){
|
||||
VMSTATE_UINT64(env.spec_ctrl, X86CPU),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
|
||||
VMStateDescription vmstate_x86_cpu = {
|
||||
.name = "cpu",
|
||||
.version_id = 12,
|
||||
@@ -936,6 +955,7 @@ VMStateDescription vmstate_x86_cpu = {
|
||||
#ifdef TARGET_X86_64
|
||||
&vmstate_pkru,
|
||||
#endif
|
||||
&vmstate_spec_ctrl,
|
||||
&vmstate_mcg_ext_ctl,
|
||||
NULL
|
||||
}
|
||||
|
||||
@@ -4547,9 +4547,9 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu)
|
||||
if (!CODE64(s) && (vex2 & 0xc0) != 0xc0) {
|
||||
/* 4.1.4.6: In 32-bit mode, bits [7:6] must be 11b,
|
||||
otherwise the instruction is LES or LDS. */
|
||||
s->pc--; /* rewind the advance_pc() x86_ldub_code() did */
|
||||
break;
|
||||
}
|
||||
s->pc++;
|
||||
|
||||
/* 4.1.1-4.1.3: No preceding lock, 66, f2, f3, or rex prefixes. */
|
||||
if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ
|
||||
|
||||
+8
-1
@@ -73,7 +73,14 @@ static const CompatInfo compat_table[] = {
|
||||
.pvr = CPU_POWERPC_LOGICAL_3_00,
|
||||
.pcr = PCR_COMPAT_3_00,
|
||||
.pcr_level = PCR_COMPAT_3_00,
|
||||
.max_threads = 4,
|
||||
/*
|
||||
* POWER9 hardware only supports 4 threads / core, but this
|
||||
* limit is for guests. We need to support 8 vthreads/vcore
|
||||
* on POWER9 for POWER8 compatibility guests, and it's very
|
||||
* confusing if half of the threads disappear from the guest
|
||||
* if it announces it's POWER9 aware at CAS time.
|
||||
*/
|
||||
.max_threads = 8,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
+56
-49
@@ -87,6 +87,13 @@
|
||||
#define PPC_ELF_MACHINE EM_PPC
|
||||
#endif
|
||||
|
||||
#define PPC_BIT(bit) (0x8000000000000000UL >> (bit))
|
||||
#define PPC_BIT32(bit) (0x80000000UL >> (bit))
|
||||
#define PPC_BIT8(bit) (0x80UL >> (bit))
|
||||
#define PPC_BITMASK(bs, be) ((PPC_BIT(bs) - PPC_BIT(be)) | PPC_BIT(bs))
|
||||
#define PPC_BITMASK32(bs, be) ((PPC_BIT32(bs) - PPC_BIT32(be)) | \
|
||||
PPC_BIT32(bs))
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Exception vectors definitions */
|
||||
enum {
|
||||
@@ -371,10 +378,10 @@ struct ppc_slb_t {
|
||||
#define MSR_LE 0 /* Little-endian mode 1 hflags */
|
||||
|
||||
/* LPCR bits */
|
||||
#define LPCR_VPM0 (1ull << (63 - 0))
|
||||
#define LPCR_VPM1 (1ull << (63 - 1))
|
||||
#define LPCR_ISL (1ull << (63 - 2))
|
||||
#define LPCR_KBV (1ull << (63 - 3))
|
||||
#define LPCR_VPM0 PPC_BIT(0)
|
||||
#define LPCR_VPM1 PPC_BIT(1)
|
||||
#define LPCR_ISL PPC_BIT(2)
|
||||
#define LPCR_KBV PPC_BIT(3)
|
||||
#define LPCR_DPFD_SHIFT (63 - 11)
|
||||
#define LPCR_DPFD (0x7ull << LPCR_DPFD_SHIFT)
|
||||
#define LPCR_VRMASD_SHIFT (63 - 16)
|
||||
@@ -382,41 +389,41 @@ struct ppc_slb_t {
|
||||
/* P9: Power-saving mode Exit Cause Enable (Upper Section) Mask */
|
||||
#define LPCR_PECE_U_SHIFT (63 - 19)
|
||||
#define LPCR_PECE_U_MASK (0x7ull << LPCR_PECE_U_SHIFT)
|
||||
#define LPCR_HVEE (1ull << (63 - 17)) /* Hypervisor Virt Exit Enable */
|
||||
#define LPCR_HVEE PPC_BIT(17) /* Hypervisor Virt Exit Enable */
|
||||
#define LPCR_RMLS_SHIFT (63 - 37)
|
||||
#define LPCR_RMLS (0xfull << LPCR_RMLS_SHIFT)
|
||||
#define LPCR_ILE (1ull << (63 - 38))
|
||||
#define LPCR_ILE PPC_BIT(38)
|
||||
#define LPCR_AIL_SHIFT (63 - 40) /* Alternate interrupt location */
|
||||
#define LPCR_AIL (3ull << LPCR_AIL_SHIFT)
|
||||
#define LPCR_UPRT (1ull << (63 - 41)) /* Use Process Table */
|
||||
#define LPCR_EVIRT (1ull << (63 - 42)) /* Enhanced Virtualisation */
|
||||
#define LPCR_ONL (1ull << (63 - 45))
|
||||
#define LPCR_LD (1ull << (63 - 46)) /* Large Decrementer */
|
||||
#define LPCR_P7_PECE0 (1ull << (63 - 49))
|
||||
#define LPCR_P7_PECE1 (1ull << (63 - 50))
|
||||
#define LPCR_P7_PECE2 (1ull << (63 - 51))
|
||||
#define LPCR_P8_PECE0 (1ull << (63 - 47))
|
||||
#define LPCR_P8_PECE1 (1ull << (63 - 48))
|
||||
#define LPCR_P8_PECE2 (1ull << (63 - 49))
|
||||
#define LPCR_P8_PECE3 (1ull << (63 - 50))
|
||||
#define LPCR_P8_PECE4 (1ull << (63 - 51))
|
||||
#define LPCR_UPRT PPC_BIT(41) /* Use Process Table */
|
||||
#define LPCR_EVIRT PPC_BIT(42) /* Enhanced Virtualisation */
|
||||
#define LPCR_ONL PPC_BIT(45)
|
||||
#define LPCR_LD PPC_BIT(46) /* Large Decrementer */
|
||||
#define LPCR_P7_PECE0 PPC_BIT(49)
|
||||
#define LPCR_P7_PECE1 PPC_BIT(50)
|
||||
#define LPCR_P7_PECE2 PPC_BIT(51)
|
||||
#define LPCR_P8_PECE0 PPC_BIT(47)
|
||||
#define LPCR_P8_PECE1 PPC_BIT(48)
|
||||
#define LPCR_P8_PECE2 PPC_BIT(49)
|
||||
#define LPCR_P8_PECE3 PPC_BIT(50)
|
||||
#define LPCR_P8_PECE4 PPC_BIT(51)
|
||||
/* P9: Power-saving mode Exit Cause Enable (Lower Section) Mask */
|
||||
#define LPCR_PECE_L_SHIFT (63 - 51)
|
||||
#define LPCR_PECE_L_MASK (0x1full << LPCR_PECE_L_SHIFT)
|
||||
#define LPCR_PDEE (1ull << (63 - 47)) /* Privileged Doorbell Exit EN */
|
||||
#define LPCR_HDEE (1ull << (63 - 48)) /* Hyperv Doorbell Exit Enable */
|
||||
#define LPCR_EEE (1ull << (63 - 49)) /* External Exit Enable */
|
||||
#define LPCR_DEE (1ull << (63 - 50)) /* Decrementer Exit Enable */
|
||||
#define LPCR_OEE (1ull << (63 - 51)) /* Other Exit Enable */
|
||||
#define LPCR_MER (1ull << (63 - 52))
|
||||
#define LPCR_GTSE (1ull << (63 - 53)) /* Guest Translation Shootdown */
|
||||
#define LPCR_TC (1ull << (63 - 54))
|
||||
#define LPCR_HEIC (1ull << (63 - 59)) /* HV Extern Interrupt Control */
|
||||
#define LPCR_LPES0 (1ull << (63 - 60))
|
||||
#define LPCR_LPES1 (1ull << (63 - 61))
|
||||
#define LPCR_RMI (1ull << (63 - 62))
|
||||
#define LPCR_HVICE (1ull << (63 - 62)) /* HV Virtualisation Int Enable */
|
||||
#define LPCR_HDICE (1ull << (63 - 63))
|
||||
#define LPCR_PDEE PPC_BIT(47) /* Privileged Doorbell Exit EN */
|
||||
#define LPCR_HDEE PPC_BIT(48) /* Hyperv Doorbell Exit Enable */
|
||||
#define LPCR_EEE PPC_BIT(49) /* External Exit Enable */
|
||||
#define LPCR_DEE PPC_BIT(50) /* Decrementer Exit Enable */
|
||||
#define LPCR_OEE PPC_BIT(51) /* Other Exit Enable */
|
||||
#define LPCR_MER PPC_BIT(52)
|
||||
#define LPCR_GTSE PPC_BIT(53) /* Guest Translation Shootdown */
|
||||
#define LPCR_TC PPC_BIT(54)
|
||||
#define LPCR_HEIC PPC_BIT(59) /* HV Extern Interrupt Control */
|
||||
#define LPCR_LPES0 PPC_BIT(60)
|
||||
#define LPCR_LPES1 PPC_BIT(61)
|
||||
#define LPCR_RMI PPC_BIT(62)
|
||||
#define LPCR_HVICE PPC_BIT(62) /* HV Virtualisation Int Enable */
|
||||
#define LPCR_HDICE PPC_BIT(63)
|
||||
|
||||
#define msr_sf ((env->msr >> MSR_SF) & 1)
|
||||
#define msr_isf ((env->msr >> MSR_ISF) & 1)
|
||||
@@ -507,22 +514,22 @@ struct ppc_slb_t {
|
||||
#define FSCR_IC_TAR 8
|
||||
|
||||
/* Exception state register bits definition */
|
||||
#define ESR_PIL (1 << (63 - 36)) /* Illegal Instruction */
|
||||
#define ESR_PPR (1 << (63 - 37)) /* Privileged Instruction */
|
||||
#define ESR_PTR (1 << (63 - 38)) /* Trap */
|
||||
#define ESR_FP (1 << (63 - 39)) /* Floating-Point Operation */
|
||||
#define ESR_ST (1 << (63 - 40)) /* Store Operation */
|
||||
#define ESR_AP (1 << (63 - 44)) /* Auxiliary Processor Operation */
|
||||
#define ESR_PUO (1 << (63 - 45)) /* Unimplemented Operation */
|
||||
#define ESR_BO (1 << (63 - 46)) /* Byte Ordering */
|
||||
#define ESR_PIE (1 << (63 - 47)) /* Imprecise exception */
|
||||
#define ESR_DATA (1 << (63 - 53)) /* Data Access (Embedded page table) */
|
||||
#define ESR_TLBI (1 << (63 - 54)) /* TLB Ineligible (Embedded page table) */
|
||||
#define ESR_PT (1 << (63 - 55)) /* Page Table (Embedded page table) */
|
||||
#define ESR_SPV (1 << (63 - 56)) /* SPE/VMX operation */
|
||||
#define ESR_EPID (1 << (63 - 57)) /* External Process ID operation */
|
||||
#define ESR_VLEMI (1 << (63 - 58)) /* VLE operation */
|
||||
#define ESR_MIF (1 << (63 - 62)) /* Misaligned instruction (VLE) */
|
||||
#define ESR_PIL PPC_BIT(36) /* Illegal Instruction */
|
||||
#define ESR_PPR PPC_BIT(37) /* Privileged Instruction */
|
||||
#define ESR_PTR PPC_BIT(38) /* Trap */
|
||||
#define ESR_FP PPC_BIT(39) /* Floating-Point Operation */
|
||||
#define ESR_ST PPC_BIT(40) /* Store Operation */
|
||||
#define ESR_AP PPC_BIT(44) /* Auxiliary Processor Operation */
|
||||
#define ESR_PUO PPC_BIT(45) /* Unimplemented Operation */
|
||||
#define ESR_BO PPC_BIT(46) /* Byte Ordering */
|
||||
#define ESR_PIE PPC_BIT(47) /* Imprecise exception */
|
||||
#define ESR_DATA PPC_BIT(53) /* Data Access (Embedded page table) */
|
||||
#define ESR_TLBI PPC_BIT(54) /* TLB Ineligible (Embedded page table) */
|
||||
#define ESR_PT PPC_BIT(55) /* Page Table (Embedded page table) */
|
||||
#define ESR_SPV PPC_BIT(56) /* SPE/VMX operation */
|
||||
#define ESR_EPID PPC_BIT(57) /* External Process ID operation */
|
||||
#define ESR_VLEMI PPC_BIT(58) /* VLE operation */
|
||||
#define ESR_MIF PPC_BIT(62) /* Misaligned instruction (VLE) */
|
||||
|
||||
/* Transaction EXception And Summary Register bits */
|
||||
#define TEXASR_FAILURE_PERSISTENT (63 - 7)
|
||||
@@ -1991,7 +1998,7 @@ void ppc_compat_add_property(Object *obj, const char *name,
|
||||
#define HID0_DEEPNAP (1 << 24) /* pre-2.06 */
|
||||
#define HID0_DOZE (1 << 23) /* pre-2.06 */
|
||||
#define HID0_NAP (1 << 22) /* pre-2.06 */
|
||||
#define HID0_HILE (1ull << (63 - 19)) /* POWER8 */
|
||||
#define HID0_HILE PPC_BIT(19) /* POWER8 */
|
||||
|
||||
/*****************************************************************************/
|
||||
/* PowerPC Instructions types definitions */
|
||||
|
||||
+64
-21
@@ -92,6 +92,9 @@ static int cap_mmu_radix;
|
||||
static int cap_mmu_hash_v3;
|
||||
static int cap_resize_hpt;
|
||||
static int cap_ppc_pvr_compat;
|
||||
static int cap_ppc_safe_cache;
|
||||
static int cap_ppc_safe_bounds_check;
|
||||
static int cap_ppc_safe_indirect_branch;
|
||||
|
||||
static uint32_t debug_inst_opcode;
|
||||
|
||||
@@ -124,6 +127,7 @@ static bool kvmppc_is_pr(KVMState *ks)
|
||||
}
|
||||
|
||||
static int kvm_ppc_register_host_cpu_type(MachineState *ms);
|
||||
static void kvmppc_get_cpu_characteristics(KVMState *s);
|
||||
|
||||
int kvm_arch_init(MachineState *ms, KVMState *s)
|
||||
{
|
||||
@@ -150,6 +154,7 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
|
||||
cap_mmu_radix = kvm_vm_check_extension(s, KVM_CAP_PPC_MMU_RADIX);
|
||||
cap_mmu_hash_v3 = kvm_vm_check_extension(s, KVM_CAP_PPC_MMU_HASH_V3);
|
||||
cap_resize_hpt = kvm_vm_check_extension(s, KVM_CAP_SPAPR_RESIZE_HPT);
|
||||
kvmppc_get_cpu_characteristics(s);
|
||||
/*
|
||||
* Note: setting it to false because there is not such capability
|
||||
* in KVM at this moment.
|
||||
@@ -2014,16 +2019,6 @@ uint64_t kvmppc_get_clockfreq(void)
|
||||
return kvmppc_read_int_cpu_dt("clock-frequency");
|
||||
}
|
||||
|
||||
uint32_t kvmppc_get_vmx(void)
|
||||
{
|
||||
return kvmppc_read_int_cpu_dt("ibm,vmx");
|
||||
}
|
||||
|
||||
uint32_t kvmppc_get_dfp(void)
|
||||
{
|
||||
return kvmppc_read_int_cpu_dt("ibm,dfp");
|
||||
}
|
||||
|
||||
static int kvmppc_get_pvinfo(CPUPPCState *env, struct kvm_ppc_pvinfo *pvinfo)
|
||||
{
|
||||
PowerPCCPU *cpu = ppc_env_get_cpu(env);
|
||||
@@ -2407,23 +2402,18 @@ static void alter_insns(uint64_t *word, uint64_t flags, bool on)
|
||||
static void kvmppc_host_cpu_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
|
||||
uint32_t vmx = kvmppc_get_vmx();
|
||||
uint32_t dfp = kvmppc_get_dfp();
|
||||
uint32_t dcache_size = kvmppc_read_int_cpu_dt("d-cache-size");
|
||||
uint32_t icache_size = kvmppc_read_int_cpu_dt("i-cache-size");
|
||||
|
||||
/* Now fix up the class with information we can query from the host */
|
||||
pcc->pvr = mfpvr();
|
||||
|
||||
if (vmx != -1) {
|
||||
/* Only override when we know what the host supports */
|
||||
alter_insns(&pcc->insns_flags, PPC_ALTIVEC, vmx > 0);
|
||||
alter_insns(&pcc->insns_flags2, PPC2_VSX, vmx > 1);
|
||||
}
|
||||
if (dfp != -1) {
|
||||
/* Only override when we know what the host supports */
|
||||
alter_insns(&pcc->insns_flags2, PPC2_DFP, dfp);
|
||||
}
|
||||
alter_insns(&pcc->insns_flags, PPC_ALTIVEC,
|
||||
qemu_getauxval(AT_HWCAP) & PPC_FEATURE_HAS_ALTIVEC);
|
||||
alter_insns(&pcc->insns_flags2, PPC2_VSX,
|
||||
qemu_getauxval(AT_HWCAP) & PPC_FEATURE_HAS_VSX);
|
||||
alter_insns(&pcc->insns_flags2, PPC2_DFP,
|
||||
qemu_getauxval(AT_HWCAP) & PPC_FEATURE_HAS_DFP);
|
||||
|
||||
if (dcache_size != -1) {
|
||||
pcc->l1_dcache_size = dcache_size;
|
||||
@@ -2474,6 +2464,59 @@ bool kvmppc_has_cap_mmu_hash_v3(void)
|
||||
return cap_mmu_hash_v3;
|
||||
}
|
||||
|
||||
static void kvmppc_get_cpu_characteristics(KVMState *s)
|
||||
{
|
||||
struct kvm_ppc_cpu_char c;
|
||||
int ret;
|
||||
|
||||
/* Assume broken */
|
||||
cap_ppc_safe_cache = 0;
|
||||
cap_ppc_safe_bounds_check = 0;
|
||||
cap_ppc_safe_indirect_branch = 0;
|
||||
|
||||
ret = kvm_vm_check_extension(s, KVM_CAP_PPC_GET_CPU_CHAR);
|
||||
if (!ret) {
|
||||
return;
|
||||
}
|
||||
ret = kvm_vm_ioctl(s, KVM_PPC_GET_CPU_CHAR, &c);
|
||||
if (ret < 0) {
|
||||
return;
|
||||
}
|
||||
/* Parse and set cap_ppc_safe_cache */
|
||||
if (~c.behaviour & c.behaviour_mask & H_CPU_BEHAV_L1D_FLUSH_PR) {
|
||||
cap_ppc_safe_cache = 2;
|
||||
} else if ((c.character & c.character_mask & H_CPU_CHAR_L1D_THREAD_PRIV) &&
|
||||
(c.character & c.character_mask
|
||||
& (H_CPU_CHAR_L1D_FLUSH_ORI30 | H_CPU_CHAR_L1D_FLUSH_TRIG2))) {
|
||||
cap_ppc_safe_cache = 1;
|
||||
}
|
||||
/* Parse and set cap_ppc_safe_bounds_check */
|
||||
if (~c.behaviour & c.behaviour_mask & H_CPU_BEHAV_BNDS_CHK_SPEC_BAR) {
|
||||
cap_ppc_safe_bounds_check = 2;
|
||||
} else if (c.character & c.character_mask & H_CPU_CHAR_SPEC_BAR_ORI31) {
|
||||
cap_ppc_safe_bounds_check = 1;
|
||||
}
|
||||
/* Parse and set cap_ppc_safe_indirect_branch */
|
||||
if (c.character & H_CPU_CHAR_BCCTRL_SERIALISED) {
|
||||
cap_ppc_safe_indirect_branch = 2;
|
||||
}
|
||||
}
|
||||
|
||||
int kvmppc_get_cap_safe_cache(void)
|
||||
{
|
||||
return cap_ppc_safe_cache;
|
||||
}
|
||||
|
||||
int kvmppc_get_cap_safe_bounds_check(void)
|
||||
{
|
||||
return cap_ppc_safe_bounds_check;
|
||||
}
|
||||
|
||||
int kvmppc_get_cap_safe_indirect_branch(void)
|
||||
{
|
||||
return cap_ppc_safe_indirect_branch;
|
||||
}
|
||||
|
||||
PowerPCCPUClass *kvm_ppc_get_host_cpu_class(void)
|
||||
{
|
||||
uint32_t host_pvr = mfpvr();
|
||||
|
||||
+18
-2
@@ -15,8 +15,6 @@
|
||||
|
||||
uint32_t kvmppc_get_tbfreq(void);
|
||||
uint64_t kvmppc_get_clockfreq(void);
|
||||
uint32_t kvmppc_get_vmx(void);
|
||||
uint32_t kvmppc_get_dfp(void);
|
||||
bool kvmppc_get_host_model(char **buf);
|
||||
bool kvmppc_get_host_serial(char **buf);
|
||||
int kvmppc_get_hasidle(CPUPPCState *env);
|
||||
@@ -61,6 +59,9 @@ bool kvmppc_has_cap_fixup_hcalls(void);
|
||||
bool kvmppc_has_cap_htm(void);
|
||||
bool kvmppc_has_cap_mmu_radix(void);
|
||||
bool kvmppc_has_cap_mmu_hash_v3(void);
|
||||
int kvmppc_get_cap_safe_cache(void);
|
||||
int kvmppc_get_cap_safe_bounds_check(void);
|
||||
int kvmppc_get_cap_safe_indirect_branch(void);
|
||||
int kvmppc_enable_hwrng(void);
|
||||
int kvmppc_put_books_sregs(PowerPCCPU *cpu);
|
||||
PowerPCCPUClass *kvm_ppc_get_host_cpu_class(void);
|
||||
@@ -292,6 +293,21 @@ static inline bool kvmppc_has_cap_mmu_hash_v3(void)
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline int kvmppc_get_cap_safe_cache(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int kvmppc_get_cap_safe_bounds_check(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int kvmppc_get_cap_safe_indirect_branch(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int kvmppc_enable_hwrng(void)
|
||||
{
|
||||
return -1;
|
||||
|
||||
@@ -89,6 +89,7 @@ static void s390_cpu_reset(CPUState *s)
|
||||
CPUS390XState *env = &cpu->env;
|
||||
|
||||
env->pfault_token = -1UL;
|
||||
env->bpbc = false;
|
||||
scc->parent_reset(s);
|
||||
cpu->env.sigp_order = 0;
|
||||
s390_cpu_set_state(CPU_STATE_STOPPED, cpu);
|
||||
|
||||
@@ -93,6 +93,7 @@ struct CPUS390XState {
|
||||
|
||||
uint32_t fpc; /* floating-point control register */
|
||||
uint32_t cc_op;
|
||||
bool bpbc; /* branch prediction blocking */
|
||||
|
||||
float_status fpu_status; /* passed to softfloat lib */
|
||||
|
||||
|
||||
@@ -89,6 +89,8 @@ static const S390FeatDef s390_features[] = {
|
||||
FEAT_INIT("msa4-base", S390_FEAT_TYPE_STFL, 77, "Message-security-assist-extension-4 facility (excluding subfunctions)"),
|
||||
FEAT_INIT("edat2", S390_FEAT_TYPE_STFL, 78, "Enhanced-DAT facility 2"),
|
||||
FEAT_INIT("dfppc", S390_FEAT_TYPE_STFL, 80, "Decimal-floating-point packed-conversion facility"),
|
||||
FEAT_INIT("ppa15", S390_FEAT_TYPE_STFL, 81, "PPA15 is installed"),
|
||||
FEAT_INIT("bpb", S390_FEAT_TYPE_STFL, 82, "Branch prediction blocking"),
|
||||
FEAT_INIT("vx", S390_FEAT_TYPE_STFL, 129, "Vector facility"),
|
||||
FEAT_INIT("iep", S390_FEAT_TYPE_STFL, 130, "Instruction-execution-protection facility"),
|
||||
FEAT_INIT("sea_esop2", S390_FEAT_TYPE_STFL, 131, "Side-effect-access facility and Enhanced-suppression-on-protection facility 2"),
|
||||
|
||||
@@ -80,6 +80,8 @@ typedef enum {
|
||||
S390_FEAT_MSA_EXT_4,
|
||||
S390_FEAT_EDAT_2,
|
||||
S390_FEAT_DFP_PACKED_CONVERSION,
|
||||
S390_FEAT_PPA15,
|
||||
S390_FEAT_BPB,
|
||||
S390_FEAT_VECTOR,
|
||||
S390_FEAT_INSTRUCTION_EXEC_PROT,
|
||||
S390_FEAT_SIDE_EFFECT_ACCESS_ESOP2,
|
||||
|
||||
@@ -352,6 +352,8 @@ static uint16_t base_GEN14_GA1[] = {
|
||||
* support these features yet.
|
||||
*/
|
||||
static uint16_t full_GEN7_GA1[] = {
|
||||
S390_FEAT_PPA15,
|
||||
S390_FEAT_BPB,
|
||||
S390_FEAT_SIE_F2,
|
||||
S390_FEAT_SIE_SKEY,
|
||||
S390_FEAT_SIE_GPERE,
|
||||
|
||||
@@ -490,6 +490,11 @@ int kvm_arch_put_registers(CPUState *cs, int level)
|
||||
cs->kvm_run->kvm_dirty_regs |= KVM_SYNC_GSCB;
|
||||
}
|
||||
|
||||
if (can_sync_regs(cs, KVM_SYNC_BPBC)) {
|
||||
cs->kvm_run->s.regs.bpbc = env->bpbc;
|
||||
cs->kvm_run->kvm_dirty_regs |= KVM_SYNC_BPBC;
|
||||
}
|
||||
|
||||
/* Finally the prefix */
|
||||
if (can_sync_regs(cs, KVM_SYNC_PREFIX)) {
|
||||
cs->kvm_run->s.regs.prefix = env->psa;
|
||||
@@ -600,6 +605,10 @@ int kvm_arch_get_registers(CPUState *cs)
|
||||
memcpy(env->gscb, cs->kvm_run->s.regs.gscb, 32);
|
||||
}
|
||||
|
||||
if (can_sync_regs(cs, KVM_SYNC_BPBC)) {
|
||||
env->bpbc = cs->kvm_run->s.regs.bpbc;
|
||||
}
|
||||
|
||||
/* pfault parameters */
|
||||
if (can_sync_regs(cs, KVM_SYNC_PFAULT)) {
|
||||
env->pfault_token = cs->kvm_run->s.regs.pft;
|
||||
@@ -2298,6 +2307,11 @@ void kvm_s390_get_host_cpu_model(S390CPUModel *model, Error **errp)
|
||||
clear_bit(S390_FEAT_CMM_NT, model->features);
|
||||
}
|
||||
|
||||
/* bpb needs kernel support for migration, VSIE and reset */
|
||||
if (!kvm_check_extension(kvm_state, KVM_CAP_S390_BPB)) {
|
||||
clear_bit(S390_FEAT_BPB, model->features);
|
||||
}
|
||||
|
||||
/* We emulate a zPCI bus and AEN, therefore we don't need HW support */
|
||||
if (pci_available) {
|
||||
set_bit(S390_FEAT_ZPCI, model->features);
|
||||
|
||||
@@ -194,6 +194,22 @@ const VMStateDescription vmstate_gscb = {
|
||||
}
|
||||
};
|
||||
|
||||
static bool bpbc_needed(void *opaque)
|
||||
{
|
||||
return s390_has_feat(S390_FEAT_BPB);
|
||||
}
|
||||
|
||||
const VMStateDescription vmstate_bpbc = {
|
||||
.name = "cpu/bpbc",
|
||||
.version_id = 1,
|
||||
.minimum_version_id = 1,
|
||||
.needed = bpbc_needed,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_BOOL(env.bpbc, S390CPU),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
|
||||
const VMStateDescription vmstate_s390_cpu = {
|
||||
.name = "cpu",
|
||||
.post_load = cpu_post_load,
|
||||
@@ -228,6 +244,7 @@ const VMStateDescription vmstate_s390_cpu = {
|
||||
&vmstate_riccb,
|
||||
&vmstate_exval,
|
||||
&vmstate_gscb,
|
||||
&vmstate_bpbc,
|
||||
NULL
|
||||
},
|
||||
};
|
||||
|
||||
@@ -601,6 +601,7 @@ static void _decode_opc(DisasContext * ctx)
|
||||
tcg_gen_subi_i32(addr, REG(B11_8), 4);
|
||||
tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx, MO_TEUL);
|
||||
tcg_gen_mov_i32(REG(B11_8), addr);
|
||||
tcg_temp_free(addr);
|
||||
}
|
||||
return;
|
||||
case 0x6004: /* mov.b @Rm+,Rn */
|
||||
@@ -1524,6 +1525,7 @@ static void _decode_opc(DisasContext * ctx)
|
||||
tcg_gen_qemu_ld_i32(val, REG(B11_8), ctx->memidx, MO_TEUL);
|
||||
gen_helper_movcal(cpu_env, REG(B11_8), val);
|
||||
tcg_gen_qemu_st_i32(REG(0), REG(B11_8), ctx->memidx, MO_TEUL);
|
||||
tcg_temp_free(val);
|
||||
}
|
||||
ctx->has_movcal = 1;
|
||||
return;
|
||||
@@ -2189,7 +2191,7 @@ static int decode_gusa(DisasContext *ctx, CPUSH4State *env, int *pmax_insns)
|
||||
}
|
||||
|
||||
/* If op_src is not a valid register, then op_arg was a constant. */
|
||||
if (op_src < 0) {
|
||||
if (op_src < 0 && !TCGV_IS_UNUSED(op_arg)) {
|
||||
tcg_temp_free_i32(op_arg);
|
||||
}
|
||||
|
||||
|
||||
@@ -421,6 +421,8 @@ void qemu_input_event_send_key(QemuConsole *src, KeyValue *key, bool down)
|
||||
} else if (queue_count < queue_limit) {
|
||||
qemu_input_queue_event(&kbd_queue, src, evt);
|
||||
qemu_input_queue_sync(&kbd_queue);
|
||||
} else {
|
||||
qapi_free_InputEvent(evt);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -35,6 +35,13 @@ vnc_client_connect(void *state, void *ioc) "VNC client connect state=%p ioc=%p"
|
||||
vnc_client_disconnect_start(void *state, void *ioc) "VNC client disconnect start state=%p ioc=%p"
|
||||
vnc_client_disconnect_finish(void *state, void *ioc) "VNC client disconnect finish state=%p ioc=%p"
|
||||
vnc_client_io_wrap(void *state, void *ioc, const char *type) "VNC client I/O wrap state=%p ioc=%p type=%s"
|
||||
vnc_client_throttle_threshold(void *state, void *ioc, size_t oldoffset, size_t offset, int client_width, int client_height, int bytes_per_pixel, void *audio_cap) "VNC client throttle threshold state=%p ioc=%p oldoffset=%zu newoffset=%zu width=%d height=%d bpp=%d audio=%p"
|
||||
vnc_client_throttle_incremental(void *state, void *ioc, int job_update, size_t offset) "VNC client throttle incremental state=%p ioc=%p job-update=%d offset=%zu"
|
||||
vnc_client_throttle_forced(void *state, void *ioc, int job_update, size_t offset) "VNC client throttle forced state=%p ioc=%p job-update=%d offset=%zu"
|
||||
vnc_client_throttle_audio(void *state, void *ioc, size_t offset) "VNC client throttle audio state=%p ioc=%p offset=%zu"
|
||||
vnc_client_unthrottle_forced(void *state, void *ioc) "VNC client unthrottle forced offset state=%p ioc=%p"
|
||||
vnc_client_unthrottle_incremental(void *state, void *ioc, size_t offset) "VNC client unthrottle incremental state=%p ioc=%p offset=%zu"
|
||||
vnc_client_output_limit(void *state, void *ioc, size_t offset, size_t threshold) "VNC client output limit state=%p ioc=%p offset=%zu threshold=%zu"
|
||||
vnc_auth_init(void *display, int websock, int auth, int subauth) "VNC auth init state=%p websock=%d auth=%d subauth=%d"
|
||||
vnc_auth_start(void *state, int method) "VNC client auth start state=%p method=%d"
|
||||
vnc_auth_pass(void *state, int method) "VNC client auth passed state=%p method=%d"
|
||||
|
||||
+11
-5
@@ -48,9 +48,9 @@ void vnc_sasl_client_cleanup(VncState *vs)
|
||||
}
|
||||
|
||||
|
||||
long vnc_client_write_sasl(VncState *vs)
|
||||
size_t vnc_client_write_sasl(VncState *vs)
|
||||
{
|
||||
long ret;
|
||||
size_t ret;
|
||||
|
||||
VNC_DEBUG("Write SASL: Pending output %p size %zd offset %zd "
|
||||
"Encoded: %p size %d offset %d\n",
|
||||
@@ -67,6 +67,7 @@ long vnc_client_write_sasl(VncState *vs)
|
||||
if (err != SASL_OK)
|
||||
return vnc_client_io_error(vs, -1, NULL);
|
||||
|
||||
vs->sasl.encodedRawLength = vs->output.offset;
|
||||
vs->sasl.encodedOffset = 0;
|
||||
}
|
||||
|
||||
@@ -78,7 +79,12 @@ long vnc_client_write_sasl(VncState *vs)
|
||||
|
||||
vs->sasl.encodedOffset += ret;
|
||||
if (vs->sasl.encodedOffset == vs->sasl.encodedLength) {
|
||||
vs->output.offset = 0;
|
||||
if (vs->sasl.encodedRawLength >= vs->force_update_offset) {
|
||||
vs->force_update_offset = 0;
|
||||
} else {
|
||||
vs->force_update_offset -= vs->sasl.encodedRawLength;
|
||||
}
|
||||
buffer_advance(&vs->output, vs->sasl.encodedRawLength);
|
||||
vs->sasl.encoded = NULL;
|
||||
vs->sasl.encodedOffset = vs->sasl.encodedLength = 0;
|
||||
}
|
||||
@@ -100,9 +106,9 @@ long vnc_client_write_sasl(VncState *vs)
|
||||
}
|
||||
|
||||
|
||||
long vnc_client_read_sasl(VncState *vs)
|
||||
size_t vnc_client_read_sasl(VncState *vs)
|
||||
{
|
||||
long ret;
|
||||
size_t ret;
|
||||
uint8_t encoded[4096];
|
||||
const char *decoded;
|
||||
unsigned int decodedLen;
|
||||
|
||||
+3
-2
@@ -53,6 +53,7 @@ struct VncStateSASL {
|
||||
*/
|
||||
const uint8_t *encoded;
|
||||
unsigned int encodedLength;
|
||||
unsigned int encodedRawLength;
|
||||
unsigned int encodedOffset;
|
||||
char *username;
|
||||
char *mechlist;
|
||||
@@ -64,8 +65,8 @@ struct VncDisplaySASL {
|
||||
|
||||
void vnc_sasl_client_cleanup(VncState *vs);
|
||||
|
||||
long vnc_client_read_sasl(VncState *vs);
|
||||
long vnc_client_write_sasl(VncState *vs);
|
||||
size_t vnc_client_read_sasl(VncState *vs);
|
||||
size_t vnc_client_write_sasl(VncState *vs);
|
||||
|
||||
void start_auth_sasl(VncState *vs);
|
||||
|
||||
|
||||
@@ -152,6 +152,11 @@ void vnc_jobs_consume_buffer(VncState *vs)
|
||||
vs->ioc, G_IO_IN | G_IO_OUT, vnc_client_io, vs, NULL);
|
||||
}
|
||||
buffer_move(&vs->output, &vs->jobs_buffer);
|
||||
|
||||
if (vs->job_update == VNC_STATE_UPDATE_FORCE) {
|
||||
vs->force_update_offset = vs->output.offset;
|
||||
}
|
||||
vs->job_update = VNC_STATE_UPDATE_NONE;
|
||||
}
|
||||
flush = vs->ioc != NULL && vs->abort != true;
|
||||
vnc_unlock_output(vs);
|
||||
|
||||
@@ -60,6 +60,7 @@ static QTAILQ_HEAD(, VncDisplay) vnc_displays =
|
||||
|
||||
static int vnc_cursor_define(VncState *vs);
|
||||
static void vnc_release_modifiers(VncState *vs);
|
||||
static void vnc_update_throttle_offset(VncState *vs);
|
||||
|
||||
static void vnc_set_share_mode(VncState *vs, VncShareMode mode)
|
||||
{
|
||||
@@ -596,7 +597,7 @@ VncInfo2List *qmp_query_vnc_servers(Error **errp)
|
||||
3) resolutions > 1024
|
||||
*/
|
||||
|
||||
static int vnc_update_client(VncState *vs, int has_dirty, bool sync);
|
||||
static int vnc_update_client(VncState *vs, int has_dirty);
|
||||
static void vnc_disconnect_start(VncState *vs);
|
||||
|
||||
static void vnc_colordepth(VncState *vs);
|
||||
@@ -671,6 +672,11 @@ static void vnc_desktop_resize(VncState *vs)
|
||||
vs->client_height == pixman_image_get_height(vs->vd->server)) {
|
||||
return;
|
||||
}
|
||||
|
||||
assert(pixman_image_get_width(vs->vd->server) < 65536 &&
|
||||
pixman_image_get_width(vs->vd->server) >= 0);
|
||||
assert(pixman_image_get_height(vs->vd->server) < 65536 &&
|
||||
pixman_image_get_height(vs->vd->server) >= 0);
|
||||
vs->client_width = pixman_image_get_width(vs->vd->server);
|
||||
vs->client_height = pixman_image_get_height(vs->vd->server);
|
||||
vnc_lock_output(vs);
|
||||
@@ -766,6 +772,7 @@ static void vnc_dpy_switch(DisplayChangeListener *dcl,
|
||||
vnc_set_area_dirty(vs->dirty, vd, 0, 0,
|
||||
vnc_width(vd),
|
||||
vnc_height(vd));
|
||||
vnc_update_throttle_offset(vs);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -961,85 +968,168 @@ static int find_and_clear_dirty_height(VncState *vs,
|
||||
return h;
|
||||
}
|
||||
|
||||
static int vnc_update_client(VncState *vs, int has_dirty, bool sync)
|
||||
/*
|
||||
* Figure out how much pending data we should allow in the output
|
||||
* buffer before we throttle incremental display updates, and/or
|
||||
* drop audio samples.
|
||||
*
|
||||
* We allow for equiv of 1 full display's worth of FB updates,
|
||||
* and 1 second of audio samples. If audio backlog was larger
|
||||
* than that the client would already suffering awful audio
|
||||
* glitches, so dropping samples is no worse really).
|
||||
*/
|
||||
static void vnc_update_throttle_offset(VncState *vs)
|
||||
{
|
||||
size_t offset =
|
||||
vs->client_width * vs->client_height * vs->client_pf.bytes_per_pixel;
|
||||
|
||||
if (vs->audio_cap) {
|
||||
int freq = vs->as.freq;
|
||||
/* We don't limit freq when reading settings from client, so
|
||||
* it could be upto MAX_INT in size. 48khz is a sensible
|
||||
* upper bound for trustworthy clients */
|
||||
int bps;
|
||||
if (freq > 48000) {
|
||||
freq = 48000;
|
||||
}
|
||||
switch (vs->as.fmt) {
|
||||
default:
|
||||
case AUD_FMT_U8:
|
||||
case AUD_FMT_S8:
|
||||
bps = 1;
|
||||
break;
|
||||
case AUD_FMT_U16:
|
||||
case AUD_FMT_S16:
|
||||
bps = 2;
|
||||
break;
|
||||
case AUD_FMT_U32:
|
||||
case AUD_FMT_S32:
|
||||
bps = 4;
|
||||
break;
|
||||
}
|
||||
offset += freq * bps * vs->as.nchannels;
|
||||
}
|
||||
|
||||
/* Put a floor of 1MB on offset, so that if we have a large pending
|
||||
* buffer and the display is resized to a small size & back again
|
||||
* we don't suddenly apply a tiny send limit
|
||||
*/
|
||||
offset = MAX(offset, 1024 * 1024);
|
||||
|
||||
if (vs->throttle_output_offset != offset) {
|
||||
trace_vnc_client_throttle_threshold(
|
||||
vs, vs->ioc, vs->throttle_output_offset, offset, vs->client_width,
|
||||
vs->client_height, vs->client_pf.bytes_per_pixel, vs->audio_cap);
|
||||
}
|
||||
|
||||
vs->throttle_output_offset = offset;
|
||||
}
|
||||
|
||||
static bool vnc_should_update(VncState *vs)
|
||||
{
|
||||
switch (vs->update) {
|
||||
case VNC_STATE_UPDATE_NONE:
|
||||
break;
|
||||
case VNC_STATE_UPDATE_INCREMENTAL:
|
||||
/* Only allow incremental updates if the pending send queue
|
||||
* is less than the permitted threshold, and the job worker
|
||||
* is completely idle.
|
||||
*/
|
||||
if (vs->output.offset < vs->throttle_output_offset &&
|
||||
vs->job_update == VNC_STATE_UPDATE_NONE) {
|
||||
return true;
|
||||
}
|
||||
trace_vnc_client_throttle_incremental(
|
||||
vs, vs->ioc, vs->job_update, vs->output.offset);
|
||||
break;
|
||||
case VNC_STATE_UPDATE_FORCE:
|
||||
/* Only allow forced updates if the pending send queue
|
||||
* does not contain a previous forced update, and the
|
||||
* job worker is completely idle.
|
||||
*
|
||||
* Note this means we'll queue a forced update, even if
|
||||
* the output buffer size is otherwise over the throttle
|
||||
* output limit.
|
||||
*/
|
||||
if (vs->force_update_offset == 0 &&
|
||||
vs->job_update == VNC_STATE_UPDATE_NONE) {
|
||||
return true;
|
||||
}
|
||||
trace_vnc_client_throttle_forced(
|
||||
vs, vs->ioc, vs->job_update, vs->force_update_offset);
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static int vnc_update_client(VncState *vs, int has_dirty)
|
||||
{
|
||||
VncDisplay *vd = vs->vd;
|
||||
VncJob *job;
|
||||
int y;
|
||||
int height, width;
|
||||
int n = 0;
|
||||
|
||||
if (vs->disconnecting) {
|
||||
vnc_disconnect_finish(vs);
|
||||
return 0;
|
||||
}
|
||||
|
||||
vs->has_dirty += has_dirty;
|
||||
if (vs->need_update && !vs->disconnecting) {
|
||||
VncDisplay *vd = vs->vd;
|
||||
VncJob *job;
|
||||
int y;
|
||||
int height, width;
|
||||
int n = 0;
|
||||
if (!vnc_should_update(vs)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (vs->output.offset && !vs->audio_cap && !vs->force_update)
|
||||
/* kernel send buffers are full -> drop frames to throttle */
|
||||
return 0;
|
||||
if (!vs->has_dirty && vs->update != VNC_STATE_UPDATE_FORCE) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!vs->has_dirty && !vs->audio_cap && !vs->force_update)
|
||||
return 0;
|
||||
/*
|
||||
* Send screen updates to the vnc client using the server
|
||||
* surface and server dirty map. guest surface updates
|
||||
* happening in parallel don't disturb us, the next pass will
|
||||
* send them to the client.
|
||||
*/
|
||||
job = vnc_job_new(vs);
|
||||
|
||||
/*
|
||||
* Send screen updates to the vnc client using the server
|
||||
* surface and server dirty map. guest surface updates
|
||||
* happening in parallel don't disturb us, the next pass will
|
||||
* send them to the client.
|
||||
*/
|
||||
job = vnc_job_new(vs);
|
||||
height = pixman_image_get_height(vd->server);
|
||||
width = pixman_image_get_width(vd->server);
|
||||
|
||||
height = pixman_image_get_height(vd->server);
|
||||
width = pixman_image_get_width(vd->server);
|
||||
|
||||
y = 0;
|
||||
for (;;) {
|
||||
int x, h;
|
||||
unsigned long x2;
|
||||
unsigned long offset = find_next_bit((unsigned long *) &vs->dirty,
|
||||
height * VNC_DIRTY_BPL(vs),
|
||||
y * VNC_DIRTY_BPL(vs));
|
||||
if (offset == height * VNC_DIRTY_BPL(vs)) {
|
||||
/* no more dirty bits */
|
||||
y = 0;
|
||||
for (;;) {
|
||||
int x, h;
|
||||
unsigned long x2;
|
||||
unsigned long offset = find_next_bit((unsigned long *) &vs->dirty,
|
||||
height * VNC_DIRTY_BPL(vs),
|
||||
y * VNC_DIRTY_BPL(vs));
|
||||
if (offset == height * VNC_DIRTY_BPL(vs)) {
|
||||
/* no more dirty bits */
|
||||
break;
|
||||
}
|
||||
y = offset / VNC_DIRTY_BPL(vs);
|
||||
x = offset % VNC_DIRTY_BPL(vs);
|
||||
x2 = find_next_zero_bit((unsigned long *) &vs->dirty[y],
|
||||
VNC_DIRTY_BPL(vs), x);
|
||||
bitmap_clear(vs->dirty[y], x, x2 - x);
|
||||
h = find_and_clear_dirty_height(vs, y, x, x2, height);
|
||||
x2 = MIN(x2, width / VNC_DIRTY_PIXELS_PER_BIT);
|
||||
if (x2 > x) {
|
||||
n += vnc_job_add_rect(job, x * VNC_DIRTY_PIXELS_PER_BIT, y,
|
||||
(x2 - x) * VNC_DIRTY_PIXELS_PER_BIT, h);
|
||||
}
|
||||
if (!x && x2 == width / VNC_DIRTY_PIXELS_PER_BIT) {
|
||||
y += h;
|
||||
if (y == height) {
|
||||
break;
|
||||
}
|
||||
y = offset / VNC_DIRTY_BPL(vs);
|
||||
x = offset % VNC_DIRTY_BPL(vs);
|
||||
x2 = find_next_zero_bit((unsigned long *) &vs->dirty[y],
|
||||
VNC_DIRTY_BPL(vs), x);
|
||||
bitmap_clear(vs->dirty[y], x, x2 - x);
|
||||
h = find_and_clear_dirty_height(vs, y, x, x2, height);
|
||||
x2 = MIN(x2, width / VNC_DIRTY_PIXELS_PER_BIT);
|
||||
if (x2 > x) {
|
||||
n += vnc_job_add_rect(job, x * VNC_DIRTY_PIXELS_PER_BIT, y,
|
||||
(x2 - x) * VNC_DIRTY_PIXELS_PER_BIT, h);
|
||||
}
|
||||
if (!x && x2 == width / VNC_DIRTY_PIXELS_PER_BIT) {
|
||||
y += h;
|
||||
if (y == height) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vnc_job_push(job);
|
||||
if (sync) {
|
||||
vnc_jobs_join(vs);
|
||||
}
|
||||
vs->force_update = 0;
|
||||
vs->has_dirty = 0;
|
||||
return n;
|
||||
}
|
||||
|
||||
if (vs->disconnecting) {
|
||||
vnc_disconnect_finish(vs);
|
||||
} else if (sync) {
|
||||
vnc_jobs_join(vs);
|
||||
}
|
||||
|
||||
return 0;
|
||||
vs->job_update = vs->update;
|
||||
vs->update = VNC_STATE_UPDATE_NONE;
|
||||
vnc_job_push(job);
|
||||
vs->has_dirty = 0;
|
||||
return n;
|
||||
}
|
||||
|
||||
/* audio */
|
||||
@@ -1077,11 +1167,15 @@ static void audio_capture(void *opaque, void *buf, int size)
|
||||
VncState *vs = opaque;
|
||||
|
||||
vnc_lock_output(vs);
|
||||
vnc_write_u8(vs, VNC_MSG_SERVER_QEMU);
|
||||
vnc_write_u8(vs, VNC_MSG_SERVER_QEMU_AUDIO);
|
||||
vnc_write_u16(vs, VNC_MSG_SERVER_QEMU_AUDIO_DATA);
|
||||
vnc_write_u32(vs, size);
|
||||
vnc_write(vs, buf, size);
|
||||
if (vs->output.offset < vs->throttle_output_offset) {
|
||||
vnc_write_u8(vs, VNC_MSG_SERVER_QEMU);
|
||||
vnc_write_u8(vs, VNC_MSG_SERVER_QEMU_AUDIO);
|
||||
vnc_write_u16(vs, VNC_MSG_SERVER_QEMU_AUDIO_DATA);
|
||||
vnc_write_u32(vs, size);
|
||||
vnc_write(vs, buf, size);
|
||||
} else {
|
||||
trace_vnc_client_throttle_audio(vs, vs->ioc, vs->output.offset);
|
||||
}
|
||||
vnc_unlock_output(vs);
|
||||
vnc_flush(vs);
|
||||
}
|
||||
@@ -1183,7 +1277,7 @@ void vnc_disconnect_finish(VncState *vs)
|
||||
g_free(vs);
|
||||
}
|
||||
|
||||
ssize_t vnc_client_io_error(VncState *vs, ssize_t ret, Error **errp)
|
||||
size_t vnc_client_io_error(VncState *vs, ssize_t ret, Error **errp)
|
||||
{
|
||||
if (ret <= 0) {
|
||||
if (ret == 0) {
|
||||
@@ -1226,9 +1320,9 @@ void vnc_client_error(VncState *vs)
|
||||
*
|
||||
* Returns the number of bytes written, which may be less than
|
||||
* the requested 'datalen' if the socket would block. Returns
|
||||
* -1 on error, and disconnects the client socket.
|
||||
* 0 on I/O error, and disconnects the client socket.
|
||||
*/
|
||||
ssize_t vnc_client_write_buf(VncState *vs, const uint8_t *data, size_t datalen)
|
||||
size_t vnc_client_write_buf(VncState *vs, const uint8_t *data, size_t datalen)
|
||||
{
|
||||
Error *err = NULL;
|
||||
ssize_t ret;
|
||||
@@ -1246,12 +1340,13 @@ ssize_t vnc_client_write_buf(VncState *vs, const uint8_t *data, size_t datalen)
|
||||
* will switch the FD poll() handler back to read monitoring.
|
||||
*
|
||||
* Returns the number of bytes written, which may be less than
|
||||
* the buffered output data if the socket would block. Returns
|
||||
* -1 on error, and disconnects the client socket.
|
||||
* the buffered output data if the socket would block. Returns
|
||||
* 0 on I/O error, and disconnects the client socket.
|
||||
*/
|
||||
static ssize_t vnc_client_write_plain(VncState *vs)
|
||||
static size_t vnc_client_write_plain(VncState *vs)
|
||||
{
|
||||
ssize_t ret;
|
||||
size_t offset;
|
||||
size_t ret;
|
||||
|
||||
#ifdef CONFIG_VNC_SASL
|
||||
VNC_DEBUG("Write Plain: Pending output %p size %zd offset %zd. Wait SSF %d\n",
|
||||
@@ -1270,7 +1365,20 @@ static ssize_t vnc_client_write_plain(VncState *vs)
|
||||
if (!ret)
|
||||
return 0;
|
||||
|
||||
if (ret >= vs->force_update_offset) {
|
||||
if (vs->force_update_offset != 0) {
|
||||
trace_vnc_client_unthrottle_forced(vs, vs->ioc);
|
||||
}
|
||||
vs->force_update_offset = 0;
|
||||
} else {
|
||||
vs->force_update_offset -= ret;
|
||||
}
|
||||
offset = vs->output.offset;
|
||||
buffer_advance(&vs->output, ret);
|
||||
if (offset >= vs->throttle_output_offset &&
|
||||
vs->output.offset < vs->throttle_output_offset) {
|
||||
trace_vnc_client_unthrottle_incremental(vs, vs->ioc, vs->output.offset);
|
||||
}
|
||||
|
||||
if (vs->output.offset == 0) {
|
||||
if (vs->ioc_tag) {
|
||||
@@ -1339,9 +1447,9 @@ void vnc_read_when(VncState *vs, VncReadEvent *func, size_t expecting)
|
||||
*
|
||||
* Returns the number of bytes read, which may be less than
|
||||
* the requested 'datalen' if the socket would block. Returns
|
||||
* -1 on error, and disconnects the client socket.
|
||||
* 0 on I/O error or EOF, and disconnects the client socket.
|
||||
*/
|
||||
ssize_t vnc_client_read_buf(VncState *vs, uint8_t *data, size_t datalen)
|
||||
size_t vnc_client_read_buf(VncState *vs, uint8_t *data, size_t datalen)
|
||||
{
|
||||
ssize_t ret;
|
||||
Error *err = NULL;
|
||||
@@ -1357,12 +1465,13 @@ ssize_t vnc_client_read_buf(VncState *vs, uint8_t *data, size_t datalen)
|
||||
* when not using any SASL SSF encryption layers. Will read as much
|
||||
* data as possible without blocking.
|
||||
*
|
||||
* Returns the number of bytes read. Returns -1 on error, and
|
||||
* disconnects the client socket.
|
||||
* Returns the number of bytes read, which may be less than
|
||||
* the requested 'datalen' if the socket would block. Returns
|
||||
* 0 on I/O error or EOF, and disconnects the client socket.
|
||||
*/
|
||||
static ssize_t vnc_client_read_plain(VncState *vs)
|
||||
static size_t vnc_client_read_plain(VncState *vs)
|
||||
{
|
||||
ssize_t ret;
|
||||
size_t ret;
|
||||
VNC_DEBUG("Read plain %p size %zd offset %zd\n",
|
||||
vs->input.buffer, vs->input.capacity, vs->input.offset);
|
||||
buffer_reserve(&vs->input, 4096);
|
||||
@@ -1388,7 +1497,7 @@ static void vnc_jobs_bh(void *opaque)
|
||||
*/
|
||||
static int vnc_client_read(VncState *vs)
|
||||
{
|
||||
ssize_t ret;
|
||||
size_t ret;
|
||||
|
||||
#ifdef CONFIG_VNC_SASL
|
||||
if (vs->sasl.conn && vs->sasl.runSSF)
|
||||
@@ -1439,8 +1548,39 @@ gboolean vnc_client_io(QIOChannel *ioc G_GNUC_UNUSED,
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Scale factor to apply to vs->throttle_output_offset when checking for
|
||||
* hard limit. Worst case normal usage could be x2, if we have a complete
|
||||
* incremental update and complete forced update in the output buffer.
|
||||
* So x3 should be good enough, but we pick x5 to be conservative and thus
|
||||
* (hopefully) never trigger incorrectly.
|
||||
*/
|
||||
#define VNC_THROTTLE_OUTPUT_LIMIT_SCALE 5
|
||||
|
||||
void vnc_write(VncState *vs, const void *data, size_t len)
|
||||
{
|
||||
if (vs->disconnecting) {
|
||||
return;
|
||||
}
|
||||
/* Protection against malicious client/guest to prevent our output
|
||||
* buffer growing without bound if client stops reading data. This
|
||||
* should rarely trigger, because we have earlier throttling code
|
||||
* which stops issuing framebuffer updates and drops audio data
|
||||
* if the throttle_output_offset value is exceeded. So we only reach
|
||||
* this higher level if a huge number of pseudo-encodings get
|
||||
* triggered while data can't be sent on the socket.
|
||||
*
|
||||
* NB throttle_output_offset can be zero during early protocol
|
||||
* handshake, or from the job thread's VncState clone
|
||||
*/
|
||||
if (vs->throttle_output_offset != 0 &&
|
||||
vs->output.offset > (vs->throttle_output_offset *
|
||||
VNC_THROTTLE_OUTPUT_LIMIT_SCALE)) {
|
||||
trace_vnc_client_output_limit(vs, vs->ioc, vs->output.offset,
|
||||
vs->throttle_output_offset);
|
||||
vnc_disconnect_start(vs);
|
||||
return;
|
||||
}
|
||||
buffer_reserve(&vs->output, len);
|
||||
|
||||
if (vs->ioc != NULL && buffer_empty(&vs->output)) {
|
||||
@@ -1876,14 +2016,14 @@ static void ext_key_event(VncState *vs, int down,
|
||||
static void framebuffer_update_request(VncState *vs, int incremental,
|
||||
int x, int y, int w, int h)
|
||||
{
|
||||
vs->need_update = 1;
|
||||
|
||||
if (incremental) {
|
||||
return;
|
||||
if (vs->update != VNC_STATE_UPDATE_FORCE) {
|
||||
vs->update = VNC_STATE_UPDATE_INCREMENTAL;
|
||||
}
|
||||
} else {
|
||||
vs->update = VNC_STATE_UPDATE_FORCE;
|
||||
vnc_set_area_dirty(vs->dirty, vs->vd, x, y, w, h);
|
||||
}
|
||||
|
||||
vs->force_update = 1;
|
||||
vnc_set_area_dirty(vs->dirty, vs->vd, x, y, w, h);
|
||||
}
|
||||
|
||||
static void send_ext_key_event_ack(VncState *vs)
|
||||
@@ -2281,6 +2421,7 @@ static int protocol_client_msg(VncState *vs, uint8_t *data, size_t len)
|
||||
break;
|
||||
}
|
||||
|
||||
vnc_update_throttle_offset(vs);
|
||||
vnc_read_when(vs, protocol_client_msg, 1);
|
||||
return 0;
|
||||
}
|
||||
@@ -2354,6 +2495,10 @@ static int protocol_client_init(VncState *vs, uint8_t *data, size_t len)
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(pixman_image_get_width(vs->vd->server) < 65536 &&
|
||||
pixman_image_get_width(vs->vd->server) >= 0);
|
||||
assert(pixman_image_get_height(vs->vd->server) < 65536 &&
|
||||
pixman_image_get_height(vs->vd->server) >= 0);
|
||||
vs->client_width = pixman_image_get_width(vs->vd->server);
|
||||
vs->client_height = pixman_image_get_height(vs->vd->server);
|
||||
vnc_write_u16(vs, vs->client_width);
|
||||
@@ -2863,7 +3008,7 @@ static void vnc_refresh(DisplayChangeListener *dcl)
|
||||
vnc_unlock_display(vd);
|
||||
|
||||
QTAILQ_FOREACH_SAFE(vs, &vd->clients, next, vn) {
|
||||
rects += vnc_update_client(vs, has_dirty, false);
|
||||
rects += vnc_update_client(vs, has_dirty);
|
||||
/* vs might be free()ed here */
|
||||
}
|
||||
|
||||
|
||||
@@ -252,6 +252,12 @@ struct VncJob
|
||||
QTAILQ_ENTRY(VncJob) next;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
VNC_STATE_UPDATE_NONE,
|
||||
VNC_STATE_UPDATE_INCREMENTAL,
|
||||
VNC_STATE_UPDATE_FORCE,
|
||||
} VncStateUpdate;
|
||||
|
||||
struct VncState
|
||||
{
|
||||
QIOChannelSocket *sioc; /* The underlying socket */
|
||||
@@ -264,16 +270,16 @@ struct VncState
|
||||
* vnc-jobs-async.c */
|
||||
|
||||
VncDisplay *vd;
|
||||
int need_update;
|
||||
int force_update;
|
||||
VncStateUpdate update; /* Most recent pending request from client */
|
||||
VncStateUpdate job_update; /* Currently processed by job thread */
|
||||
int has_dirty;
|
||||
uint32_t features;
|
||||
int absolute;
|
||||
int last_x;
|
||||
int last_y;
|
||||
uint32_t last_bmask;
|
||||
int client_width;
|
||||
int client_height;
|
||||
size_t client_width; /* limited to u16 by RFB proto */
|
||||
size_t client_height; /* limited to u16 by RFB proto */
|
||||
VncShareMode share_mode;
|
||||
|
||||
uint32_t vnc_encoding;
|
||||
@@ -293,6 +299,18 @@ struct VncState
|
||||
|
||||
VncClientInfo *info;
|
||||
|
||||
/* Job thread bottom half has put data for a forced update
|
||||
* into the output buffer. This offset points to the end of
|
||||
* the update data in the output buffer. This lets us determine
|
||||
* when a force update is fully sent to the client, allowing
|
||||
* us to process further forced updates. */
|
||||
size_t force_update_offset;
|
||||
/* We allow multiple incremental updates or audio capture
|
||||
* samples to be queued in output buffer, provided the
|
||||
* buffer size doesn't exceed this threshold. The value
|
||||
* is calculating dynamically based on framebuffer size
|
||||
* and audio sample settings in vnc_update_throttle_offset() */
|
||||
size_t throttle_output_offset;
|
||||
Buffer output;
|
||||
Buffer input;
|
||||
/* current output mode information */
|
||||
@@ -506,8 +524,8 @@ gboolean vnc_client_io(QIOChannel *ioc,
|
||||
GIOCondition condition,
|
||||
void *opaque);
|
||||
|
||||
ssize_t vnc_client_read_buf(VncState *vs, uint8_t *data, size_t datalen);
|
||||
ssize_t vnc_client_write_buf(VncState *vs, const uint8_t *data, size_t datalen);
|
||||
size_t vnc_client_read_buf(VncState *vs, uint8_t *data, size_t datalen);
|
||||
size_t vnc_client_write_buf(VncState *vs, const uint8_t *data, size_t datalen);
|
||||
|
||||
/* Protocol I/O functions */
|
||||
void vnc_write(VncState *vs, const void *data, size_t len);
|
||||
@@ -526,7 +544,7 @@ uint32_t read_u32(uint8_t *data, size_t offset);
|
||||
|
||||
/* Protocol stage functions */
|
||||
void vnc_client_error(VncState *vs);
|
||||
ssize_t vnc_client_io_error(VncState *vs, ssize_t ret, Error **errp);
|
||||
size_t vnc_client_io_error(VncState *vs, ssize_t ret, Error **errp);
|
||||
|
||||
void start_client_init(VncState *vs);
|
||||
void start_auth_vnc(VncState *vs);
|
||||
|
||||
+3
-1
@@ -244,7 +244,9 @@ static int qemu_lock_fcntl(int fd, int64_t start, int64_t len, int fl_type)
|
||||
.l_type = fl_type,
|
||||
};
|
||||
qemu_probe_lock_ops();
|
||||
ret = fcntl(fd, fcntl_op_setlk, &fl);
|
||||
do {
|
||||
ret = fcntl(fd, fcntl_op_setlk, &fl);
|
||||
} while (ret == -1 && errno == EINTR);
|
||||
return ret == -1 ? -errno : 0;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user