Compare commits
64
Commits
v4.0.0-rc2
...
v4.0.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
131b9a0570 | ||
|
|
eeba63fc7f | ||
|
|
375cb86d9f | ||
|
|
dbfc49b69a | ||
|
|
93e32b3e20 | ||
|
|
a9b305ba29 | ||
|
|
677746b39f | ||
|
|
6fabae61a9 | ||
|
|
afccfc0c4c | ||
|
|
9749636b00 | ||
|
|
23e1d05411 | ||
|
|
13c24edaa7 | ||
|
|
e1be98540e | ||
|
|
9e4a484b4a | ||
|
|
4560116e42 | ||
|
|
532cc6da74 | ||
|
|
6523516f32 | ||
|
|
065e6298a7 | ||
|
|
f151f8aca5 | ||
|
|
4b9a21c344 | ||
|
|
3e20c81ed8 | ||
|
|
ae909496e9 | ||
|
|
77b1757090 | ||
|
|
1cab464136 | ||
|
|
d912e795e0 | ||
|
|
8cb2ca3d74 | ||
|
|
120cba7ff1 | ||
|
|
248987f92c | ||
|
|
5cf0d326a0 | ||
|
|
1c685a9026 | ||
|
|
7fe1427b57 | ||
|
|
e53f88df77 | ||
|
|
099fbcd65c | ||
|
|
6e280648d2 | ||
|
|
2178a569be | ||
|
|
5263724b78 | ||
|
|
ab63817119 | ||
|
|
71ba74f67e | ||
|
|
184943d827 | ||
|
|
3f48686fac | ||
|
|
2c57310627 | ||
|
|
c19f2b711e | ||
|
|
c098aac7dc | ||
|
|
08f7ad1b00 | ||
|
|
f55a585d10 | ||
|
|
90fb864a7d | ||
|
|
d013283a46 | ||
|
|
c6e5bafb6f | ||
|
|
10546e09e1 | ||
|
|
bc939abe00 | ||
|
|
79bcac250f | ||
|
|
0feb4a7129 | ||
|
|
2bcd05cf24 | ||
|
|
15f084505a | ||
|
|
f4b3717137 | ||
|
|
7357b22159 | ||
|
|
5d45a33292 | ||
|
|
bea0279b72 | ||
|
|
e1d0b37261 | ||
|
|
81fb1e646e | ||
|
|
2811af3b49 | ||
|
|
20f86a75a7 | ||
|
|
75c5626c88 | ||
|
|
22132828d1 |
No files matched your search
@@ -950,8 +950,9 @@ static void bdrv_temp_snapshot_options(int *child_flags, QDict *child_options,
|
||||
qdict_set_default_str(child_options, BDRV_OPT_CACHE_DIRECT, "off");
|
||||
qdict_set_default_str(child_options, BDRV_OPT_CACHE_NO_FLUSH, "on");
|
||||
|
||||
/* Copy the read-only option from the parent */
|
||||
/* Copy the read-only and discard options from the parent */
|
||||
qdict_copy_default(child_options, parent_options, BDRV_OPT_READ_ONLY);
|
||||
qdict_copy_default(child_options, parent_options, BDRV_OPT_DISCARD);
|
||||
|
||||
/* aio=native doesn't work for cache.direct=off, so disable it for the
|
||||
* temporary snapshot */
|
||||
|
||||
+2
-1
@@ -2723,6 +2723,7 @@ static int qcow2_set_up_encryption(BlockDriverState *bs,
|
||||
static int coroutine_fn preallocate_co(BlockDriverState *bs, uint64_t offset,
|
||||
uint64_t new_length)
|
||||
{
|
||||
BDRVQcow2State *s = bs->opaque;
|
||||
uint64_t bytes;
|
||||
uint64_t host_offset = 0;
|
||||
unsigned int cur_bytes;
|
||||
@@ -2771,7 +2772,7 @@ static int coroutine_fn preallocate_co(BlockDriverState *bs, uint64_t offset,
|
||||
*/
|
||||
if (host_offset != 0) {
|
||||
uint8_t data = 0;
|
||||
ret = bdrv_pwrite(bs->file, (host_offset + cur_bytes) - 1,
|
||||
ret = bdrv_pwrite(s->data_file, (host_offset + cur_bytes) - 1,
|
||||
&data, 1);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
|
||||
@@ -1263,10 +1263,14 @@ static bool qmp_chardev_validate_socket(ChardevSocket *sock,
|
||||
return false;
|
||||
}
|
||||
if (sock->has_wait) {
|
||||
error_setg(errp, "%s",
|
||||
"'wait' option is incompatible with "
|
||||
"socket in client connect mode");
|
||||
return false;
|
||||
warn_report("'wait' option is deprecated with "
|
||||
"socket in client connect mode");
|
||||
if (sock->wait) {
|
||||
error_setg(errp, "%s",
|
||||
"'wait' option is incompatible with "
|
||||
"socket in client connect mode");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -48,7 +48,7 @@ static DriveInfo *add_init_drive(const char *optstr)
|
||||
|
||||
mc = MACHINE_GET_CLASS(current_machine);
|
||||
dinfo = drive_new(opts, mc->block_default_type, &err);
|
||||
if (!dinfo) {
|
||||
if (err) {
|
||||
error_report_err(err);
|
||||
qemu_opts_del(opts);
|
||||
return NULL;
|
||||
|
||||
@@ -84,6 +84,10 @@ void *load_device_tree(const char *filename_path, int *sizep)
|
||||
filename_path);
|
||||
goto fail;
|
||||
}
|
||||
if (dt_size > INT_MAX / 2 - 10000) {
|
||||
error_report("Device tree file '%s' is too large", filename_path);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Expand to 2x size to give enough room for manipulation. */
|
||||
dt_size += 10000;
|
||||
|
||||
@@ -1825,8 +1825,10 @@ void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict)
|
||||
case MIGRATION_PARAMETER_XBZRLE_CACHE_SIZE:
|
||||
p->has_xbzrle_cache_size = true;
|
||||
visit_type_size(v, param, &cache_size, &err);
|
||||
if (err || cache_size > INT64_MAX
|
||||
|| (size_t)cache_size != cache_size) {
|
||||
if (err) {
|
||||
break;
|
||||
}
|
||||
if (cache_size > INT64_MAX || (size_t)cache_size != cache_size) {
|
||||
error_setg(&err, "Invalid size %s", valuestr);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -283,6 +283,8 @@ void bios_linker_loader_add_pointer(BIOSLinker *linker,
|
||||
const BiosLinkerFileEntry *source_file =
|
||||
bios_linker_find_file(linker, src_file);
|
||||
|
||||
assert(dst_file);
|
||||
assert(source_file);
|
||||
assert(dst_patched_offset < dst_file->blob->len);
|
||||
assert(dst_patched_offset + dst_patched_size <= dst_file->blob->len);
|
||||
assert(src_offset < source_file->blob->len);
|
||||
|
||||
@@ -49,7 +49,6 @@ struct XenBlockDataPlane {
|
||||
unsigned int *ring_ref;
|
||||
unsigned int nr_ring_ref;
|
||||
void *sring;
|
||||
int64_t file_blk;
|
||||
int protocol;
|
||||
blkif_back_rings_t rings;
|
||||
int more_work;
|
||||
@@ -168,7 +167,7 @@ static int xen_block_parse_request(XenBlockRequest *request)
|
||||
goto err;
|
||||
}
|
||||
|
||||
request->start = request->req.sector_number * dataplane->file_blk;
|
||||
request->start = request->req.sector_number * XEN_BLKIF_SECTOR_SIZE;
|
||||
for (i = 0; i < request->req.nr_segments; i++) {
|
||||
if (i == BLKIF_MAX_SEGMENTS_PER_REQUEST) {
|
||||
error_report("error: nr_segments too big");
|
||||
@@ -178,14 +177,14 @@ static int xen_block_parse_request(XenBlockRequest *request)
|
||||
error_report("error: first > last sector");
|
||||
goto err;
|
||||
}
|
||||
if (request->req.seg[i].last_sect * dataplane->file_blk >=
|
||||
if (request->req.seg[i].last_sect * XEN_BLKIF_SECTOR_SIZE >=
|
||||
XC_PAGE_SIZE) {
|
||||
error_report("error: page crossing");
|
||||
goto err;
|
||||
}
|
||||
|
||||
len = (request->req.seg[i].last_sect -
|
||||
request->req.seg[i].first_sect + 1) * dataplane->file_blk;
|
||||
request->req.seg[i].first_sect + 1) * XEN_BLKIF_SECTOR_SIZE;
|
||||
request->size += len;
|
||||
}
|
||||
if (request->start + request->size > blk_getlength(dataplane->blk)) {
|
||||
@@ -205,7 +204,6 @@ static int xen_block_copy_request(XenBlockRequest *request)
|
||||
XenDevice *xendev = dataplane->xendev;
|
||||
XenDeviceGrantCopySegment segs[BLKIF_MAX_SEGMENTS_PER_REQUEST];
|
||||
int i, count;
|
||||
int64_t file_blk = dataplane->file_blk;
|
||||
bool to_domain = (request->req.operation == BLKIF_OP_READ);
|
||||
void *virt = request->buf;
|
||||
Error *local_err = NULL;
|
||||
@@ -220,16 +218,17 @@ static int xen_block_copy_request(XenBlockRequest *request)
|
||||
if (to_domain) {
|
||||
segs[i].dest.foreign.ref = request->req.seg[i].gref;
|
||||
segs[i].dest.foreign.offset = request->req.seg[i].first_sect *
|
||||
file_blk;
|
||||
XEN_BLKIF_SECTOR_SIZE;
|
||||
segs[i].source.virt = virt;
|
||||
} else {
|
||||
segs[i].source.foreign.ref = request->req.seg[i].gref;
|
||||
segs[i].source.foreign.offset = request->req.seg[i].first_sect *
|
||||
file_blk;
|
||||
XEN_BLKIF_SECTOR_SIZE;
|
||||
segs[i].dest.virt = virt;
|
||||
}
|
||||
segs[i].len = (request->req.seg[i].last_sect -
|
||||
request->req.seg[i].first_sect + 1) * file_blk;
|
||||
request->req.seg[i].first_sect + 1) *
|
||||
XEN_BLKIF_SECTOR_SIZE;
|
||||
virt += segs[i].len;
|
||||
}
|
||||
|
||||
@@ -331,22 +330,22 @@ static bool xen_block_split_discard(XenBlockRequest *request,
|
||||
XenBlockDataPlane *dataplane = request->dataplane;
|
||||
int64_t byte_offset;
|
||||
int byte_chunk;
|
||||
uint64_t byte_remaining, limit;
|
||||
uint64_t byte_remaining;
|
||||
uint64_t sec_start = sector_number;
|
||||
uint64_t sec_count = nr_sectors;
|
||||
|
||||
/* Wrap around, or overflowing byte limit? */
|
||||
if (sec_start + sec_count < sec_count ||
|
||||
sec_start + sec_count > INT64_MAX / dataplane->file_blk) {
|
||||
sec_start + sec_count > INT64_MAX / XEN_BLKIF_SECTOR_SIZE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
limit = BDRV_REQUEST_MAX_SECTORS * dataplane->file_blk;
|
||||
byte_offset = sec_start * dataplane->file_blk;
|
||||
byte_remaining = sec_count * dataplane->file_blk;
|
||||
byte_offset = sec_start * XEN_BLKIF_SECTOR_SIZE;
|
||||
byte_remaining = sec_count * XEN_BLKIF_SECTOR_SIZE;
|
||||
|
||||
do {
|
||||
byte_chunk = byte_remaining > limit ? limit : byte_remaining;
|
||||
byte_chunk = byte_remaining > BDRV_REQUEST_MAX_BYTES ?
|
||||
BDRV_REQUEST_MAX_BYTES : byte_remaining;
|
||||
request->aio_inflight++;
|
||||
blk_aio_pdiscard(dataplane->blk, byte_offset, byte_chunk,
|
||||
xen_block_complete_aio, request);
|
||||
@@ -632,7 +631,6 @@ XenBlockDataPlane *xen_block_dataplane_create(XenDevice *xendev,
|
||||
XenBlockDataPlane *dataplane = g_new0(XenBlockDataPlane, 1);
|
||||
|
||||
dataplane->xendev = xendev;
|
||||
dataplane->file_blk = conf->logical_block_size;
|
||||
dataplane->blk = conf->blk;
|
||||
|
||||
QLIST_INIT(&dataplane->inflight);
|
||||
|
||||
+17
-5
@@ -149,7 +149,7 @@ static void xen_block_set_size(XenBlockDevice *blockdev)
|
||||
const char *type = object_get_typename(OBJECT(blockdev));
|
||||
XenBlockVdev *vdev = &blockdev->props.vdev;
|
||||
BlockConf *conf = &blockdev->props.conf;
|
||||
int64_t sectors = blk_getlength(conf->blk) / conf->logical_block_size;
|
||||
int64_t sectors = blk_getlength(conf->blk) / XEN_BLKIF_SECTOR_SIZE;
|
||||
XenDevice *xendev = XEN_DEVICE(blockdev);
|
||||
|
||||
trace_xen_block_size(type, vdev->disk, vdev->partition, sectors);
|
||||
@@ -223,6 +223,12 @@ static void xen_block_realize(XenDevice *xendev, Error **errp)
|
||||
|
||||
blkconf_blocksizes(conf);
|
||||
|
||||
if (conf->logical_block_size != XEN_BLKIF_SECTOR_SIZE) {
|
||||
error_setg(errp, "logical_block_size != %u not supported",
|
||||
XEN_BLKIF_SECTOR_SIZE);
|
||||
return;
|
||||
}
|
||||
|
||||
if (conf->logical_block_size > conf->physical_block_size) {
|
||||
error_setg(
|
||||
errp, "logical_block_size > physical_block_size not supported");
|
||||
@@ -232,8 +238,14 @@ static void xen_block_realize(XenDevice *xendev, Error **errp)
|
||||
blk_set_dev_ops(conf->blk, &xen_block_dev_ops, blockdev);
|
||||
blk_set_guest_block_size(conf->blk, conf->logical_block_size);
|
||||
|
||||
if (conf->discard_granularity > 0) {
|
||||
if (conf->discard_granularity == -1) {
|
||||
conf->discard_granularity = conf->physical_block_size;
|
||||
}
|
||||
|
||||
if (blk_get_flags(conf->blk) & BDRV_O_UNMAP) {
|
||||
xen_device_backend_printf(xendev, "feature-discard", "%u", 1);
|
||||
xen_device_backend_printf(xendev, "discard-granularity", "%u",
|
||||
conf->discard_granularity);
|
||||
}
|
||||
|
||||
xen_device_backend_printf(xendev, "feature-flush-cache", "%u", 1);
|
||||
@@ -247,7 +259,7 @@ static void xen_block_realize(XenDevice *xendev, Error **errp)
|
||||
blockdev->device_type);
|
||||
|
||||
xen_device_backend_printf(xendev, "sector-size", "%u",
|
||||
conf->logical_block_size);
|
||||
XEN_BLKIF_SECTOR_SIZE);
|
||||
|
||||
xen_block_set_size(blockdev);
|
||||
|
||||
@@ -755,6 +767,7 @@ static XenBlockDrive *xen_block_drive_create(const char *id,
|
||||
drive->id = g_strdup(id);
|
||||
|
||||
file_layer = qdict_new();
|
||||
driver_layer = qdict_new();
|
||||
|
||||
qdict_put_str(file_layer, "driver", "file");
|
||||
qdict_put_str(file_layer, "filename", filename);
|
||||
@@ -782,6 +795,7 @@ static XenBlockDrive *xen_block_drive_create(const char *id,
|
||||
|
||||
if (!qemu_strtoul(discard_enable, NULL, 2, &value) && !!value) {
|
||||
qdict_put_str(file_layer, "discard", "unmap");
|
||||
qdict_put_str(driver_layer, "discard", "unmap");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -791,8 +805,6 @@ static XenBlockDrive *xen_block_drive_create(const char *id,
|
||||
*/
|
||||
qdict_put_str(file_layer, "locking", "off");
|
||||
|
||||
driver_layer = qdict_new();
|
||||
|
||||
qdict_put_str(driver_layer, "driver", driver);
|
||||
g_free(driver);
|
||||
|
||||
|
||||
@@ -143,4 +143,6 @@ static inline void blkif_get_x86_64_req(blkif_request_t *dst,
|
||||
}
|
||||
}
|
||||
|
||||
#define XEN_BLKIF_SECTOR_SIZE 512
|
||||
|
||||
#endif /* XEN_BLKIF_H */
|
||||
+23
-9
@@ -162,6 +162,15 @@ static inline void vtd_iommu_unlock(IntelIOMMUState *s)
|
||||
qemu_mutex_unlock(&s->iommu_lock);
|
||||
}
|
||||
|
||||
static void vtd_update_scalable_state(IntelIOMMUState *s)
|
||||
{
|
||||
uint64_t val = vtd_get_quad_raw(s, DMAR_RTADDR_REG);
|
||||
|
||||
if (s->scalable_mode) {
|
||||
s->root_scalable = val & VTD_RTADDR_SMT;
|
||||
}
|
||||
}
|
||||
|
||||
/* Whether the address space needs to notify new mappings */
|
||||
static inline gboolean vtd_as_has_map_notifier(VTDAddressSpace *as)
|
||||
{
|
||||
@@ -1709,13 +1718,11 @@ error:
|
||||
static void vtd_root_table_setup(IntelIOMMUState *s)
|
||||
{
|
||||
s->root = vtd_get_quad_raw(s, DMAR_RTADDR_REG);
|
||||
s->root_extended = s->root & VTD_RTADDR_RTT;
|
||||
if (s->scalable_mode) {
|
||||
s->root_scalable = s->root & VTD_RTADDR_SMT;
|
||||
}
|
||||
s->root &= VTD_RTADDR_ADDR_MASK(s->aw_bits);
|
||||
|
||||
trace_vtd_reg_dmar_root(s->root, s->root_extended);
|
||||
vtd_update_scalable_state(s);
|
||||
|
||||
trace_vtd_reg_dmar_root(s->root, s->root_scalable);
|
||||
}
|
||||
|
||||
static void vtd_iec_notify_all(IntelIOMMUState *s, bool global,
|
||||
@@ -2919,7 +2926,7 @@ static void vtd_iommu_notify_flag_changed(IOMMUMemoryRegion *iommu,
|
||||
IntelIOMMUState *s = vtd_as->iommu_state;
|
||||
|
||||
if (!s->caching_mode && new & IOMMU_NOTIFIER_MAP) {
|
||||
error_report("We need to set caching-mode=1 for intel-iommu to enable "
|
||||
error_report("We need to set caching-mode=on for intel-iommu to enable "
|
||||
"device assignment with IOMMU protection.");
|
||||
exit(1);
|
||||
}
|
||||
@@ -2945,6 +2952,15 @@ static int vtd_post_load(void *opaque, int version_id)
|
||||
*/
|
||||
vtd_switch_address_space_all(iommu);
|
||||
|
||||
/*
|
||||
* We don't need to migrate the root_scalable because we can
|
||||
* simply do the calculation after the loading is complete. We
|
||||
* can actually do similar things with root, dmar_enabled, etc.
|
||||
* however since we've had them already so we'd better keep them
|
||||
* for compatibility of migration.
|
||||
*/
|
||||
vtd_update_scalable_state(iommu);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2965,8 +2981,7 @@ static const VMStateDescription vtd_vmstate = {
|
||||
VMSTATE_UINT16(next_frcd_reg, IntelIOMMUState),
|
||||
VMSTATE_UINT8_ARRAY(csr, IntelIOMMUState, DMAR_REG_SIZE),
|
||||
VMSTATE_UINT8(iq_last_desc_type, IntelIOMMUState),
|
||||
VMSTATE_BOOL(root_extended, IntelIOMMUState),
|
||||
VMSTATE_BOOL(root_scalable, IntelIOMMUState),
|
||||
VMSTATE_UNUSED(1), /* bool root_extended is obsolete by VT-d */
|
||||
VMSTATE_BOOL(dmar_enabled, IntelIOMMUState),
|
||||
VMSTATE_BOOL(qi_enabled, IntelIOMMUState),
|
||||
VMSTATE_BOOL(intr_enabled, IntelIOMMUState),
|
||||
@@ -3487,7 +3502,6 @@ static void vtd_init(IntelIOMMUState *s)
|
||||
memset(s->womask, 0, DMAR_REG_SIZE);
|
||||
|
||||
s->root = 0;
|
||||
s->root_extended = false;
|
||||
s->root_scalable = false;
|
||||
s->dmar_enabled = false;
|
||||
s->intr_enabled = false;
|
||||
|
||||
@@ -171,7 +171,6 @@
|
||||
#define VTD_CCMD_FM(val) (((val) >> 32) & 3ULL)
|
||||
|
||||
/* RTADDR_REG */
|
||||
#define VTD_RTADDR_RTT (1ULL << 11)
|
||||
#define VTD_RTADDR_SMT (1ULL << 10)
|
||||
#define VTD_RTADDR_ADDR_MASK(aw) (VTD_HAW_MASK(aw) ^ 0xfffULL)
|
||||
|
||||
|
||||
+7
-2
@@ -2078,6 +2078,7 @@ static void pc_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
|
||||
const MachineState *ms = MACHINE(hotplug_dev);
|
||||
const bool is_nvdimm = object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM);
|
||||
const uint64_t legacy_align = TARGET_PAGE_SIZE;
|
||||
Error *local_err = NULL;
|
||||
|
||||
/*
|
||||
* When -no-acpi is used with Q35 machine type, no ACPI is built,
|
||||
@@ -2090,13 +2091,17 @@ static void pc_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
|
||||
return;
|
||||
}
|
||||
|
||||
hotplug_handler_pre_plug(pcms->acpi_dev, dev, errp);
|
||||
|
||||
if (is_nvdimm && !ms->nvdimms_state->is_enabled) {
|
||||
error_setg(errp, "nvdimm is not enabled: missing 'nvdimm' in '-M'");
|
||||
return;
|
||||
}
|
||||
|
||||
hotplug_handler_pre_plug(pcms->acpi_dev, dev, &local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
return;
|
||||
}
|
||||
|
||||
pc_dimm_pre_plug(PC_DIMM(dev), MACHINE(hotplug_dev),
|
||||
pcmc->enforce_aligned_dimm ? NULL : &legacy_align, errp);
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ vtd_pt_enable_fast_path(uint16_t sid, bool success) "sid 0x%"PRIu16" %d"
|
||||
vtd_irq_generate(uint64_t addr, uint64_t data) "addr 0x%"PRIx64" data 0x%"PRIx64
|
||||
vtd_reg_read(uint64_t addr, uint64_t size) "addr 0x%"PRIx64" size 0x%"PRIx64
|
||||
vtd_reg_write(uint64_t addr, uint64_t size, uint64_t val) "addr 0x%"PRIx64" size 0x%"PRIx64" value 0x%"PRIx64
|
||||
vtd_reg_dmar_root(uint64_t addr, bool extended) "addr 0x%"PRIx64" extended %d"
|
||||
vtd_reg_dmar_root(uint64_t addr, bool scalable) "addr 0x%"PRIx64" scalable %d"
|
||||
vtd_reg_ir_root(uint64_t addr, uint32_t size) "addr 0x%"PRIx64" size 0x%"PRIx32
|
||||
vtd_reg_write_gcmd(uint32_t status, uint32_t val) "status 0x%"PRIx32" value 0x%"PRIx32
|
||||
vtd_reg_write_fectl(uint32_t value) "value 0x%"PRIx32
|
||||
|
||||
+1
-1
@@ -2281,7 +2281,7 @@ static void virtio_net_change_num_queues(VirtIONet *n, int new_max_queues)
|
||||
/*
|
||||
* We always need to remove and add ctrl vq if
|
||||
* old_num_queues != new_num_queues. Remove ctrl_vq first,
|
||||
* and then we only enter one of the following too loops.
|
||||
* and then we only enter one of the following two loops.
|
||||
*/
|
||||
virtio_del_queue(vdev, old_num_queues - 1);
|
||||
|
||||
|
||||
@@ -147,6 +147,11 @@ static uint16_t pcibus_numa_node(PCIBus *bus)
|
||||
return NUMA_NODE_UNASSIGNED;
|
||||
}
|
||||
|
||||
static bool pcibus_allows_extended_config_space(PCIBus *bus)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static void pci_bus_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
BusClass *k = BUS_CLASS(klass);
|
||||
@@ -162,6 +167,7 @@ static void pci_bus_class_init(ObjectClass *klass, void *data)
|
||||
pbc->is_root = pcibus_is_root;
|
||||
pbc->bus_num = pcibus_num;
|
||||
pbc->numa_node = pcibus_numa_node;
|
||||
pbc->allows_extended_config_space = pcibus_allows_extended_config_space;
|
||||
}
|
||||
|
||||
static const TypeInfo pci_bus_info = {
|
||||
@@ -182,9 +188,22 @@ static const TypeInfo conventional_pci_interface_info = {
|
||||
.parent = TYPE_INTERFACE,
|
||||
};
|
||||
|
||||
static bool pciebus_allows_extended_config_space(PCIBus *bus)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static void pcie_bus_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
PCIBusClass *pbc = PCI_BUS_CLASS(klass);
|
||||
|
||||
pbc->allows_extended_config_space = pciebus_allows_extended_config_space;
|
||||
}
|
||||
|
||||
static const TypeInfo pcie_bus_info = {
|
||||
.name = TYPE_PCIE_BUS,
|
||||
.parent = TYPE_PCI_BUS,
|
||||
.class_init = pcie_bus_class_init,
|
||||
};
|
||||
|
||||
static PCIBus *pci_find_bus_nr(PCIBus *bus, int bus_num);
|
||||
@@ -401,6 +420,11 @@ bool pci_bus_is_root(PCIBus *bus)
|
||||
return PCI_BUS_GET_CLASS(bus)->is_root(bus);
|
||||
}
|
||||
|
||||
bool pci_bus_allows_extended_config_space(PCIBus *bus)
|
||||
{
|
||||
return PCI_BUS_GET_CLASS(bus)->allows_extended_config_space(bus);
|
||||
}
|
||||
|
||||
void pci_root_bus_new_inplace(PCIBus *bus, size_t bus_size, DeviceState *parent,
|
||||
const char *name,
|
||||
MemoryRegion *address_space_mem,
|
||||
|
||||
+1
-1
@@ -54,7 +54,7 @@ static inline PCIDevice *pci_dev_find_by_addr(PCIBus *bus, uint32_t addr)
|
||||
static void pci_adjust_config_limit(PCIBus *bus, uint32_t *limit)
|
||||
{
|
||||
if (*limit > PCI_CONFIG_SPACE_SIZE) {
|
||||
if (!pci_bus_is_express(bus)) {
|
||||
if (!pci_bus_allows_extended_config_space(bus)) {
|
||||
*limit = PCI_CONFIG_SPACE_SIZE;
|
||||
return;
|
||||
}
|
||||
|
||||
+25
-1
@@ -1638,6 +1638,28 @@ static void spapr_phb_unrealize(DeviceState *dev, Error **errp)
|
||||
memory_region_del_subregion(get_system_memory(), &sphb->mem32window);
|
||||
}
|
||||
|
||||
static bool spapr_phb_allows_extended_config_space(PCIBus *bus)
|
||||
{
|
||||
SpaprPhbState *sphb = SPAPR_PCI_HOST_BRIDGE(BUS(bus)->parent);
|
||||
|
||||
return sphb->pcie_ecs;
|
||||
}
|
||||
|
||||
static void spapr_phb_root_bus_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
PCIBusClass *pbc = PCI_BUS_CLASS(klass);
|
||||
|
||||
pbc->allows_extended_config_space = spapr_phb_allows_extended_config_space;
|
||||
}
|
||||
|
||||
#define TYPE_SPAPR_PHB_ROOT_BUS "pci"
|
||||
|
||||
static const TypeInfo spapr_phb_root_bus_info = {
|
||||
.name = TYPE_SPAPR_PHB_ROOT_BUS,
|
||||
.parent = TYPE_PCI_BUS,
|
||||
.class_init = spapr_phb_root_bus_class_init,
|
||||
};
|
||||
|
||||
static void spapr_phb_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
/* We don't use SPAPR_MACHINE() in order to exit gracefully if the user
|
||||
@@ -1742,7 +1764,8 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp)
|
||||
bus = pci_register_root_bus(dev, NULL,
|
||||
pci_spapr_set_irq, pci_spapr_map_irq, sphb,
|
||||
&sphb->memspace, &sphb->iospace,
|
||||
PCI_DEVFN(0, 0), PCI_NUM_PINS, TYPE_PCI_BUS);
|
||||
PCI_DEVFN(0, 0), PCI_NUM_PINS,
|
||||
TYPE_SPAPR_PHB_ROOT_BUS);
|
||||
phb->bus = bus;
|
||||
qbus_set_hotplug_handler(BUS(phb->bus), OBJECT(sphb), NULL);
|
||||
|
||||
@@ -2325,6 +2348,7 @@ void spapr_pci_rtas_init(void)
|
||||
static void spapr_pci_register_types(void)
|
||||
{
|
||||
type_register_static(&spapr_phb_info);
|
||||
type_register_static(&spapr_phb_root_bus_info);
|
||||
}
|
||||
|
||||
type_init(spapr_pci_register_types)
|
||||
|
||||
+11
-5
@@ -207,7 +207,7 @@ static uint64_t sifive_plic_read(void *opaque, hwaddr addr, unsigned size)
|
||||
if (addr >= plic->priority_base && /* 4 bytes per source */
|
||||
addr < plic->priority_base + (plic->num_sources << 2))
|
||||
{
|
||||
uint32_t irq = (addr - plic->priority_base) >> 2;
|
||||
uint32_t irq = ((addr - plic->priority_base) >> 2) + 1;
|
||||
if (RISCV_DEBUG_PLIC) {
|
||||
qemu_log("plic: read priority: irq=%d priority=%d\n",
|
||||
irq, plic->source_priority[irq]);
|
||||
@@ -263,7 +263,9 @@ static uint64_t sifive_plic_read(void *opaque, hwaddr addr, unsigned size)
|
||||
}
|
||||
|
||||
err:
|
||||
error_report("plic: invalid register read: %08x", (uint32_t)addr);
|
||||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
"%s: Invalid register read 0x%" HWADDR_PRIx "\n",
|
||||
__func__, addr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -280,7 +282,7 @@ static void sifive_plic_write(void *opaque, hwaddr addr, uint64_t value,
|
||||
if (addr >= plic->priority_base && /* 4 bytes per source */
|
||||
addr < plic->priority_base + (plic->num_sources << 2))
|
||||
{
|
||||
uint32_t irq = (addr - plic->priority_base) >> 2;
|
||||
uint32_t irq = ((addr - plic->priority_base) >> 2) + 1;
|
||||
plic->source_priority[irq] = value & 7;
|
||||
if (RISCV_DEBUG_PLIC) {
|
||||
qemu_log("plic: write priority: irq=%d priority=%d\n",
|
||||
@@ -290,7 +292,9 @@ static void sifive_plic_write(void *opaque, hwaddr addr, uint64_t value,
|
||||
} else if (addr >= plic->pending_base && /* 1 bit per source */
|
||||
addr < plic->pending_base + (plic->num_sources >> 3))
|
||||
{
|
||||
error_report("plic: invalid pending write: %08x", (uint32_t)addr);
|
||||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
"%s: invalid pending write: 0x%" HWADDR_PRIx "",
|
||||
__func__, addr);
|
||||
return;
|
||||
} else if (addr >= plic->enable_base && /* 1 bit per source */
|
||||
addr < plic->enable_base + plic->num_addrs * plic->enable_stride)
|
||||
@@ -340,7 +344,9 @@ static void sifive_plic_write(void *opaque, hwaddr addr, uint64_t value,
|
||||
}
|
||||
|
||||
err:
|
||||
error_report("plic: invalid register write: %08x", (uint32_t)addr);
|
||||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
"%s: Invalid register write 0x%" HWADDR_PRIx "\n",
|
||||
__func__, addr);
|
||||
}
|
||||
|
||||
static const MemoryRegionOps sifive_plic_ops = {
|
||||
|
||||
+4
-4
@@ -78,13 +78,13 @@ static int emulated_ccw_3270_cb(SubchDev *sch, CCW1 ccw)
|
||||
|
||||
if (rc == -EIO) {
|
||||
/* I/O error, specific devices generate specific conditions */
|
||||
SCSW *s = &sch->curr_status.scsw;
|
||||
SCHIB *schib = &sch->curr_status;
|
||||
|
||||
sch->curr_status.scsw.dstat = SCSW_DSTAT_UNIT_CHECK;
|
||||
sch->sense_data[0] = 0x40; /* intervention-req */
|
||||
s->ctrl &= ~SCSW_ACTL_START_PEND;
|
||||
s->ctrl &= ~SCSW_CTRL_MASK_STCTL;
|
||||
s->ctrl |= SCSW_STCTL_PRIMARY | SCSW_STCTL_SECONDARY |
|
||||
schib->scsw.ctrl &= ~SCSW_ACTL_START_PEND;
|
||||
schib->scsw.ctrl &= ~SCSW_CTRL_MASK_STCTL;
|
||||
schib->scsw.ctrl |= SCSW_STCTL_PRIMARY | SCSW_STCTL_SECONDARY |
|
||||
SCSW_STCTL_ALERT | SCSW_STCTL_STATUS_PEND;
|
||||
}
|
||||
|
||||
|
||||
+187
-201
@@ -695,35 +695,32 @@ void css_adapter_interrupt(CssIoAdapterType type, uint8_t isc)
|
||||
|
||||
static void sch_handle_clear_func(SubchDev *sch)
|
||||
{
|
||||
PMCW *p = &sch->curr_status.pmcw;
|
||||
SCSW *s = &sch->curr_status.scsw;
|
||||
SCHIB *schib = &sch->curr_status;
|
||||
int path;
|
||||
|
||||
/* Path management: In our simple css, we always choose the only path. */
|
||||
path = 0x80;
|
||||
|
||||
/* Reset values prior to 'issuing the clear signal'. */
|
||||
p->lpum = 0;
|
||||
p->pom = 0xff;
|
||||
s->flags &= ~SCSW_FLAGS_MASK_PNO;
|
||||
schib->pmcw.lpum = 0;
|
||||
schib->pmcw.pom = 0xff;
|
||||
schib->scsw.flags &= ~SCSW_FLAGS_MASK_PNO;
|
||||
|
||||
/* We always 'attempt to issue the clear signal', and we always succeed. */
|
||||
sch->channel_prog = 0x0;
|
||||
sch->last_cmd_valid = false;
|
||||
s->ctrl &= ~SCSW_ACTL_CLEAR_PEND;
|
||||
s->ctrl |= SCSW_STCTL_STATUS_PEND;
|
||||
schib->scsw.ctrl &= ~SCSW_ACTL_CLEAR_PEND;
|
||||
schib->scsw.ctrl |= SCSW_STCTL_STATUS_PEND;
|
||||
|
||||
s->dstat = 0;
|
||||
s->cstat = 0;
|
||||
p->lpum = path;
|
||||
schib->scsw.dstat = 0;
|
||||
schib->scsw.cstat = 0;
|
||||
schib->pmcw.lpum = path;
|
||||
|
||||
}
|
||||
|
||||
static void sch_handle_halt_func(SubchDev *sch)
|
||||
{
|
||||
|
||||
PMCW *p = &sch->curr_status.pmcw;
|
||||
SCSW *s = &sch->curr_status.scsw;
|
||||
SCHIB *schib = &sch->curr_status;
|
||||
hwaddr curr_ccw = sch->channel_prog;
|
||||
int path;
|
||||
|
||||
@@ -733,20 +730,22 @@ static void sch_handle_halt_func(SubchDev *sch)
|
||||
/* We always 'attempt to issue the halt signal', and we always succeed. */
|
||||
sch->channel_prog = 0x0;
|
||||
sch->last_cmd_valid = false;
|
||||
s->ctrl &= ~SCSW_ACTL_HALT_PEND;
|
||||
s->ctrl |= SCSW_STCTL_STATUS_PEND;
|
||||
schib->scsw.ctrl &= ~SCSW_ACTL_HALT_PEND;
|
||||
schib->scsw.ctrl |= SCSW_STCTL_STATUS_PEND;
|
||||
|
||||
if ((s->ctrl & (SCSW_ACTL_SUBCH_ACTIVE | SCSW_ACTL_DEVICE_ACTIVE)) ||
|
||||
!((s->ctrl & SCSW_ACTL_START_PEND) ||
|
||||
(s->ctrl & SCSW_ACTL_SUSP))) {
|
||||
s->dstat = SCSW_DSTAT_DEVICE_END;
|
||||
if ((schib->scsw.ctrl & (SCSW_ACTL_SUBCH_ACTIVE |
|
||||
SCSW_ACTL_DEVICE_ACTIVE)) ||
|
||||
!((schib->scsw.ctrl & SCSW_ACTL_START_PEND) ||
|
||||
(schib->scsw.ctrl & SCSW_ACTL_SUSP))) {
|
||||
schib->scsw.dstat = SCSW_DSTAT_DEVICE_END;
|
||||
}
|
||||
if ((s->ctrl & (SCSW_ACTL_SUBCH_ACTIVE | SCSW_ACTL_DEVICE_ACTIVE)) ||
|
||||
(s->ctrl & SCSW_ACTL_SUSP)) {
|
||||
s->cpa = curr_ccw + 8;
|
||||
if ((schib->scsw.ctrl & (SCSW_ACTL_SUBCH_ACTIVE |
|
||||
SCSW_ACTL_DEVICE_ACTIVE)) ||
|
||||
(schib->scsw.ctrl & SCSW_ACTL_SUSP)) {
|
||||
schib->scsw.cpa = curr_ccw + 8;
|
||||
}
|
||||
s->cstat = 0;
|
||||
p->lpum = path;
|
||||
schib->scsw.cstat = 0;
|
||||
schib->pmcw.lpum = path;
|
||||
|
||||
}
|
||||
|
||||
@@ -1111,9 +1110,7 @@ static int css_interpret_ccw(SubchDev *sch, hwaddr ccw_addr,
|
||||
|
||||
static void sch_handle_start_func_virtual(SubchDev *sch)
|
||||
{
|
||||
|
||||
PMCW *p = &sch->curr_status.pmcw;
|
||||
SCSW *s = &sch->curr_status.scsw;
|
||||
SCHIB *schib = &sch->curr_status;
|
||||
int path;
|
||||
int ret;
|
||||
bool suspend_allowed;
|
||||
@@ -1121,27 +1118,27 @@ static void sch_handle_start_func_virtual(SubchDev *sch)
|
||||
/* Path management: In our simple css, we always choose the only path. */
|
||||
path = 0x80;
|
||||
|
||||
if (!(s->ctrl & SCSW_ACTL_SUSP)) {
|
||||
if (!(schib->scsw.ctrl & SCSW_ACTL_SUSP)) {
|
||||
/* Start Function triggered via ssch, i.e. we have an ORB */
|
||||
ORB *orb = &sch->orb;
|
||||
s->cstat = 0;
|
||||
s->dstat = 0;
|
||||
schib->scsw.cstat = 0;
|
||||
schib->scsw.dstat = 0;
|
||||
/* Look at the orb and try to execute the channel program. */
|
||||
p->intparm = orb->intparm;
|
||||
schib->pmcw.intparm = orb->intparm;
|
||||
if (!(orb->lpm & path)) {
|
||||
/* Generate a deferred cc 3 condition. */
|
||||
s->flags |= SCSW_FLAGS_MASK_CC;
|
||||
s->ctrl &= ~SCSW_CTRL_MASK_STCTL;
|
||||
s->ctrl |= (SCSW_STCTL_ALERT | SCSW_STCTL_STATUS_PEND);
|
||||
schib->scsw.flags |= SCSW_FLAGS_MASK_CC;
|
||||
schib->scsw.ctrl &= ~SCSW_CTRL_MASK_STCTL;
|
||||
schib->scsw.ctrl |= (SCSW_STCTL_ALERT | SCSW_STCTL_STATUS_PEND);
|
||||
return;
|
||||
}
|
||||
sch->ccw_fmt_1 = !!(orb->ctrl0 & ORB_CTRL0_MASK_FMT);
|
||||
s->flags |= (sch->ccw_fmt_1) ? SCSW_FLAGS_MASK_FMT : 0;
|
||||
schib->scsw.flags |= (sch->ccw_fmt_1) ? SCSW_FLAGS_MASK_FMT : 0;
|
||||
sch->ccw_no_data_cnt = 0;
|
||||
suspend_allowed = !!(orb->ctrl0 & ORB_CTRL0_MASK_SPND);
|
||||
} else {
|
||||
/* Start Function resumed via rsch */
|
||||
s->ctrl &= ~(SCSW_ACTL_SUSP | SCSW_ACTL_RESUME_PEND);
|
||||
schib->scsw.ctrl &= ~(SCSW_ACTL_SUSP | SCSW_ACTL_RESUME_PEND);
|
||||
/* The channel program had been suspended before. */
|
||||
suspend_allowed = true;
|
||||
}
|
||||
@@ -1154,40 +1151,40 @@ static void sch_handle_start_func_virtual(SubchDev *sch)
|
||||
break;
|
||||
case 0:
|
||||
/* success */
|
||||
s->ctrl &= ~SCSW_ACTL_START_PEND;
|
||||
s->ctrl &= ~SCSW_CTRL_MASK_STCTL;
|
||||
s->ctrl |= SCSW_STCTL_PRIMARY | SCSW_STCTL_SECONDARY |
|
||||
schib->scsw.ctrl &= ~SCSW_ACTL_START_PEND;
|
||||
schib->scsw.ctrl &= ~SCSW_CTRL_MASK_STCTL;
|
||||
schib->scsw.ctrl |= SCSW_STCTL_PRIMARY | SCSW_STCTL_SECONDARY |
|
||||
SCSW_STCTL_STATUS_PEND;
|
||||
s->dstat = SCSW_DSTAT_CHANNEL_END | SCSW_DSTAT_DEVICE_END;
|
||||
s->cpa = sch->channel_prog + 8;
|
||||
schib->scsw.dstat = SCSW_DSTAT_CHANNEL_END | SCSW_DSTAT_DEVICE_END;
|
||||
schib->scsw.cpa = sch->channel_prog + 8;
|
||||
break;
|
||||
case -EIO:
|
||||
/* I/O errors, status depends on specific devices */
|
||||
break;
|
||||
case -ENOSYS:
|
||||
/* unsupported command, generate unit check (command reject) */
|
||||
s->ctrl &= ~SCSW_ACTL_START_PEND;
|
||||
s->dstat = SCSW_DSTAT_UNIT_CHECK;
|
||||
schib->scsw.ctrl &= ~SCSW_ACTL_START_PEND;
|
||||
schib->scsw.dstat = SCSW_DSTAT_UNIT_CHECK;
|
||||
/* Set sense bit 0 in ecw0. */
|
||||
sch->sense_data[0] = 0x80;
|
||||
s->ctrl &= ~SCSW_CTRL_MASK_STCTL;
|
||||
s->ctrl |= SCSW_STCTL_PRIMARY | SCSW_STCTL_SECONDARY |
|
||||
schib->scsw.ctrl &= ~SCSW_CTRL_MASK_STCTL;
|
||||
schib->scsw.ctrl |= SCSW_STCTL_PRIMARY | SCSW_STCTL_SECONDARY |
|
||||
SCSW_STCTL_ALERT | SCSW_STCTL_STATUS_PEND;
|
||||
s->cpa = sch->channel_prog + 8;
|
||||
schib->scsw.cpa = sch->channel_prog + 8;
|
||||
break;
|
||||
case -EINPROGRESS:
|
||||
/* channel program has been suspended */
|
||||
s->ctrl &= ~SCSW_ACTL_START_PEND;
|
||||
s->ctrl |= SCSW_ACTL_SUSP;
|
||||
schib->scsw.ctrl &= ~SCSW_ACTL_START_PEND;
|
||||
schib->scsw.ctrl |= SCSW_ACTL_SUSP;
|
||||
break;
|
||||
default:
|
||||
/* error, generate channel program check */
|
||||
s->ctrl &= ~SCSW_ACTL_START_PEND;
|
||||
s->cstat = SCSW_CSTAT_PROG_CHECK;
|
||||
s->ctrl &= ~SCSW_CTRL_MASK_STCTL;
|
||||
s->ctrl |= SCSW_STCTL_PRIMARY | SCSW_STCTL_SECONDARY |
|
||||
schib->scsw.ctrl &= ~SCSW_ACTL_START_PEND;
|
||||
schib->scsw.cstat = SCSW_CSTAT_PROG_CHECK;
|
||||
schib->scsw.ctrl &= ~SCSW_CTRL_MASK_STCTL;
|
||||
schib->scsw.ctrl |= SCSW_STCTL_PRIMARY | SCSW_STCTL_SECONDARY |
|
||||
SCSW_STCTL_ALERT | SCSW_STCTL_STATUS_PEND;
|
||||
s->cpa = sch->channel_prog + 8;
|
||||
schib->scsw.cpa = sch->channel_prog + 8;
|
||||
break;
|
||||
}
|
||||
} while (ret == -EAGAIN);
|
||||
@@ -1196,14 +1193,11 @@ static void sch_handle_start_func_virtual(SubchDev *sch)
|
||||
|
||||
static IOInstEnding sch_handle_start_func_passthrough(SubchDev *sch)
|
||||
{
|
||||
|
||||
PMCW *p = &sch->curr_status.pmcw;
|
||||
SCSW *s = &sch->curr_status.scsw;
|
||||
|
||||
SCHIB *schib = &sch->curr_status;
|
||||
ORB *orb = &sch->orb;
|
||||
if (!(s->ctrl & SCSW_ACTL_SUSP)) {
|
||||
if (!(schib->scsw.ctrl & SCSW_ACTL_SUSP)) {
|
||||
assert(orb != NULL);
|
||||
p->intparm = orb->intparm;
|
||||
schib->pmcw.intparm = orb->intparm;
|
||||
}
|
||||
return s390_ccw_cmd_request(sch);
|
||||
}
|
||||
@@ -1216,14 +1210,13 @@ static IOInstEnding sch_handle_start_func_passthrough(SubchDev *sch)
|
||||
*/
|
||||
IOInstEnding do_subchannel_work_virtual(SubchDev *sch)
|
||||
{
|
||||
SCHIB *schib = &sch->curr_status;
|
||||
|
||||
SCSW *s = &sch->curr_status.scsw;
|
||||
|
||||
if (s->ctrl & SCSW_FCTL_CLEAR_FUNC) {
|
||||
if (schib->scsw.ctrl & SCSW_FCTL_CLEAR_FUNC) {
|
||||
sch_handle_clear_func(sch);
|
||||
} else if (s->ctrl & SCSW_FCTL_HALT_FUNC) {
|
||||
} else if (schib->scsw.ctrl & SCSW_FCTL_HALT_FUNC) {
|
||||
sch_handle_halt_func(sch);
|
||||
} else if (s->ctrl & SCSW_FCTL_START_FUNC) {
|
||||
} else if (schib->scsw.ctrl & SCSW_FCTL_START_FUNC) {
|
||||
/* Triggered by both ssch and rsch. */
|
||||
sch_handle_start_func_virtual(sch);
|
||||
}
|
||||
@@ -1234,15 +1227,15 @@ IOInstEnding do_subchannel_work_virtual(SubchDev *sch)
|
||||
|
||||
IOInstEnding do_subchannel_work_passthrough(SubchDev *sch)
|
||||
{
|
||||
SCSW *s = &sch->curr_status.scsw;
|
||||
SCHIB *schib = &sch->curr_status;
|
||||
|
||||
if (s->ctrl & SCSW_FCTL_CLEAR_FUNC) {
|
||||
if (schib->scsw.ctrl & SCSW_FCTL_CLEAR_FUNC) {
|
||||
/* TODO: Clear handling */
|
||||
sch_handle_clear_func(sch);
|
||||
} else if (s->ctrl & SCSW_FCTL_HALT_FUNC) {
|
||||
} else if (schib->scsw.ctrl & SCSW_FCTL_HALT_FUNC) {
|
||||
/* TODO: Halt handling */
|
||||
sch_handle_halt_func(sch);
|
||||
} else if (s->ctrl & SCSW_FCTL_START_FUNC) {
|
||||
} else if (schib->scsw.ctrl & SCSW_FCTL_START_FUNC) {
|
||||
return sch_handle_start_func_passthrough(sch);
|
||||
}
|
||||
return IOINST_CC_EXPECTED;
|
||||
@@ -1370,46 +1363,45 @@ static void copy_schib_from_guest(SCHIB *dest, const SCHIB *src)
|
||||
|
||||
IOInstEnding css_do_msch(SubchDev *sch, const SCHIB *orig_schib)
|
||||
{
|
||||
SCSW *s = &sch->curr_status.scsw;
|
||||
PMCW *p = &sch->curr_status.pmcw;
|
||||
SCHIB *schib = &sch->curr_status;
|
||||
uint16_t oldflags;
|
||||
SCHIB schib;
|
||||
SCHIB schib_copy;
|
||||
|
||||
if (!(sch->curr_status.pmcw.flags & PMCW_FLAGS_MASK_DNV)) {
|
||||
if (!(schib->pmcw.flags & PMCW_FLAGS_MASK_DNV)) {
|
||||
return IOINST_CC_EXPECTED;
|
||||
}
|
||||
|
||||
if (s->ctrl & SCSW_STCTL_STATUS_PEND) {
|
||||
if (schib->scsw.ctrl & SCSW_STCTL_STATUS_PEND) {
|
||||
return IOINST_CC_STATUS_PRESENT;
|
||||
}
|
||||
|
||||
if (s->ctrl &
|
||||
if (schib->scsw.ctrl &
|
||||
(SCSW_FCTL_START_FUNC|SCSW_FCTL_HALT_FUNC|SCSW_FCTL_CLEAR_FUNC)) {
|
||||
return IOINST_CC_BUSY;
|
||||
}
|
||||
|
||||
copy_schib_from_guest(&schib, orig_schib);
|
||||
copy_schib_from_guest(&schib_copy, orig_schib);
|
||||
/* Only update the program-modifiable fields. */
|
||||
p->intparm = schib.pmcw.intparm;
|
||||
oldflags = p->flags;
|
||||
p->flags &= ~(PMCW_FLAGS_MASK_ISC | PMCW_FLAGS_MASK_ENA |
|
||||
schib->pmcw.intparm = schib_copy.pmcw.intparm;
|
||||
oldflags = schib->pmcw.flags;
|
||||
schib->pmcw.flags &= ~(PMCW_FLAGS_MASK_ISC | PMCW_FLAGS_MASK_ENA |
|
||||
PMCW_FLAGS_MASK_LM | PMCW_FLAGS_MASK_MME |
|
||||
PMCW_FLAGS_MASK_MP);
|
||||
p->flags |= schib.pmcw.flags &
|
||||
schib->pmcw.flags |= schib_copy.pmcw.flags &
|
||||
(PMCW_FLAGS_MASK_ISC | PMCW_FLAGS_MASK_ENA |
|
||||
PMCW_FLAGS_MASK_LM | PMCW_FLAGS_MASK_MME |
|
||||
PMCW_FLAGS_MASK_MP);
|
||||
p->lpm = schib.pmcw.lpm;
|
||||
p->mbi = schib.pmcw.mbi;
|
||||
p->pom = schib.pmcw.pom;
|
||||
p->chars &= ~(PMCW_CHARS_MASK_MBFC | PMCW_CHARS_MASK_CSENSE);
|
||||
p->chars |= schib.pmcw.chars &
|
||||
schib->pmcw.lpm = schib_copy.pmcw.lpm;
|
||||
schib->pmcw.mbi = schib_copy.pmcw.mbi;
|
||||
schib->pmcw.pom = schib_copy.pmcw.pom;
|
||||
schib->pmcw.chars &= ~(PMCW_CHARS_MASK_MBFC | PMCW_CHARS_MASK_CSENSE);
|
||||
schib->pmcw.chars |= schib_copy.pmcw.chars &
|
||||
(PMCW_CHARS_MASK_MBFC | PMCW_CHARS_MASK_CSENSE);
|
||||
sch->curr_status.mba = schib.mba;
|
||||
schib->mba = schib_copy.mba;
|
||||
|
||||
/* Has the channel been disabled? */
|
||||
if (sch->disable_cb && (oldflags & PMCW_FLAGS_MASK_ENA) != 0
|
||||
&& (p->flags & PMCW_FLAGS_MASK_ENA) == 0) {
|
||||
&& (schib->pmcw.flags & PMCW_FLAGS_MASK_ENA) == 0) {
|
||||
sch->disable_cb(sch);
|
||||
}
|
||||
return IOINST_CC_EXPECTED;
|
||||
@@ -1417,82 +1409,80 @@ IOInstEnding css_do_msch(SubchDev *sch, const SCHIB *orig_schib)
|
||||
|
||||
IOInstEnding css_do_xsch(SubchDev *sch)
|
||||
{
|
||||
SCSW *s = &sch->curr_status.scsw;
|
||||
PMCW *p = &sch->curr_status.pmcw;
|
||||
SCHIB *schib = &sch->curr_status;
|
||||
|
||||
if (~(p->flags) & (PMCW_FLAGS_MASK_DNV | PMCW_FLAGS_MASK_ENA)) {
|
||||
if (~(schib->pmcw.flags) & (PMCW_FLAGS_MASK_DNV | PMCW_FLAGS_MASK_ENA)) {
|
||||
return IOINST_CC_NOT_OPERATIONAL;
|
||||
}
|
||||
|
||||
if (s->ctrl & SCSW_CTRL_MASK_STCTL) {
|
||||
if (schib->scsw.ctrl & SCSW_CTRL_MASK_STCTL) {
|
||||
return IOINST_CC_STATUS_PRESENT;
|
||||
}
|
||||
|
||||
if (!(s->ctrl & SCSW_CTRL_MASK_FCTL) ||
|
||||
((s->ctrl & SCSW_CTRL_MASK_FCTL) != SCSW_FCTL_START_FUNC) ||
|
||||
(!(s->ctrl &
|
||||
if (!(schib->scsw.ctrl & SCSW_CTRL_MASK_FCTL) ||
|
||||
((schib->scsw.ctrl & SCSW_CTRL_MASK_FCTL) != SCSW_FCTL_START_FUNC) ||
|
||||
(!(schib->scsw.ctrl &
|
||||
(SCSW_ACTL_RESUME_PEND | SCSW_ACTL_START_PEND | SCSW_ACTL_SUSP))) ||
|
||||
(s->ctrl & SCSW_ACTL_SUBCH_ACTIVE)) {
|
||||
(schib->scsw.ctrl & SCSW_ACTL_SUBCH_ACTIVE)) {
|
||||
return IOINST_CC_BUSY;
|
||||
}
|
||||
|
||||
/* Cancel the current operation. */
|
||||
s->ctrl &= ~(SCSW_FCTL_START_FUNC |
|
||||
schib->scsw.ctrl &= ~(SCSW_FCTL_START_FUNC |
|
||||
SCSW_ACTL_RESUME_PEND |
|
||||
SCSW_ACTL_START_PEND |
|
||||
SCSW_ACTL_SUSP);
|
||||
sch->channel_prog = 0x0;
|
||||
sch->last_cmd_valid = false;
|
||||
s->dstat = 0;
|
||||
s->cstat = 0;
|
||||
schib->scsw.dstat = 0;
|
||||
schib->scsw.cstat = 0;
|
||||
return IOINST_CC_EXPECTED;
|
||||
}
|
||||
|
||||
IOInstEnding css_do_csch(SubchDev *sch)
|
||||
{
|
||||
SCSW *s = &sch->curr_status.scsw;
|
||||
PMCW *p = &sch->curr_status.pmcw;
|
||||
SCHIB *schib = &sch->curr_status;
|
||||
|
||||
if (~(p->flags) & (PMCW_FLAGS_MASK_DNV | PMCW_FLAGS_MASK_ENA)) {
|
||||
if (~(schib->pmcw.flags) & (PMCW_FLAGS_MASK_DNV | PMCW_FLAGS_MASK_ENA)) {
|
||||
return IOINST_CC_NOT_OPERATIONAL;
|
||||
}
|
||||
|
||||
/* Trigger the clear function. */
|
||||
s->ctrl &= ~(SCSW_CTRL_MASK_FCTL | SCSW_CTRL_MASK_ACTL);
|
||||
s->ctrl |= SCSW_FCTL_CLEAR_FUNC | SCSW_ACTL_CLEAR_PEND;
|
||||
schib->scsw.ctrl &= ~(SCSW_CTRL_MASK_FCTL | SCSW_CTRL_MASK_ACTL);
|
||||
schib->scsw.ctrl |= SCSW_FCTL_CLEAR_FUNC | SCSW_ACTL_CLEAR_PEND;
|
||||
|
||||
return do_subchannel_work(sch);
|
||||
}
|
||||
|
||||
IOInstEnding css_do_hsch(SubchDev *sch)
|
||||
{
|
||||
SCSW *s = &sch->curr_status.scsw;
|
||||
PMCW *p = &sch->curr_status.pmcw;
|
||||
SCHIB *schib = &sch->curr_status;
|
||||
|
||||
if (~(p->flags) & (PMCW_FLAGS_MASK_DNV | PMCW_FLAGS_MASK_ENA)) {
|
||||
if (~(schib->pmcw.flags) & (PMCW_FLAGS_MASK_DNV | PMCW_FLAGS_MASK_ENA)) {
|
||||
return IOINST_CC_NOT_OPERATIONAL;
|
||||
}
|
||||
|
||||
if (((s->ctrl & SCSW_CTRL_MASK_STCTL) == SCSW_STCTL_STATUS_PEND) ||
|
||||
(s->ctrl & (SCSW_STCTL_PRIMARY |
|
||||
if (((schib->scsw.ctrl & SCSW_CTRL_MASK_STCTL) == SCSW_STCTL_STATUS_PEND) ||
|
||||
(schib->scsw.ctrl & (SCSW_STCTL_PRIMARY |
|
||||
SCSW_STCTL_SECONDARY |
|
||||
SCSW_STCTL_ALERT))) {
|
||||
return IOINST_CC_STATUS_PRESENT;
|
||||
}
|
||||
|
||||
if (s->ctrl & (SCSW_FCTL_HALT_FUNC | SCSW_FCTL_CLEAR_FUNC)) {
|
||||
if (schib->scsw.ctrl & (SCSW_FCTL_HALT_FUNC | SCSW_FCTL_CLEAR_FUNC)) {
|
||||
return IOINST_CC_BUSY;
|
||||
}
|
||||
|
||||
/* Trigger the halt function. */
|
||||
s->ctrl |= SCSW_FCTL_HALT_FUNC;
|
||||
s->ctrl &= ~SCSW_FCTL_START_FUNC;
|
||||
if (((s->ctrl & SCSW_CTRL_MASK_ACTL) ==
|
||||
schib->scsw.ctrl |= SCSW_FCTL_HALT_FUNC;
|
||||
schib->scsw.ctrl &= ~SCSW_FCTL_START_FUNC;
|
||||
if (((schib->scsw.ctrl & SCSW_CTRL_MASK_ACTL) ==
|
||||
(SCSW_ACTL_SUBCH_ACTIVE | SCSW_ACTL_DEVICE_ACTIVE)) &&
|
||||
((s->ctrl & SCSW_CTRL_MASK_STCTL) == SCSW_STCTL_INTERMEDIATE)) {
|
||||
s->ctrl &= ~SCSW_STCTL_STATUS_PEND;
|
||||
((schib->scsw.ctrl & SCSW_CTRL_MASK_STCTL) ==
|
||||
SCSW_STCTL_INTERMEDIATE)) {
|
||||
schib->scsw.ctrl &= ~SCSW_STCTL_STATUS_PEND;
|
||||
}
|
||||
s->ctrl |= SCSW_ACTL_HALT_PEND;
|
||||
schib->scsw.ctrl |= SCSW_ACTL_HALT_PEND;
|
||||
|
||||
return do_subchannel_work(sch);
|
||||
}
|
||||
@@ -1534,18 +1524,17 @@ static void css_update_chnmon(SubchDev *sch)
|
||||
|
||||
IOInstEnding css_do_ssch(SubchDev *sch, ORB *orb)
|
||||
{
|
||||
SCSW *s = &sch->curr_status.scsw;
|
||||
PMCW *p = &sch->curr_status.pmcw;
|
||||
SCHIB *schib = &sch->curr_status;
|
||||
|
||||
if (~(p->flags) & (PMCW_FLAGS_MASK_DNV | PMCW_FLAGS_MASK_ENA)) {
|
||||
if (~(schib->pmcw.flags) & (PMCW_FLAGS_MASK_DNV | PMCW_FLAGS_MASK_ENA)) {
|
||||
return IOINST_CC_NOT_OPERATIONAL;
|
||||
}
|
||||
|
||||
if (s->ctrl & SCSW_STCTL_STATUS_PEND) {
|
||||
if (schib->scsw.ctrl & SCSW_STCTL_STATUS_PEND) {
|
||||
return IOINST_CC_STATUS_PRESENT;
|
||||
}
|
||||
|
||||
if (s->ctrl & (SCSW_FCTL_START_FUNC |
|
||||
if (schib->scsw.ctrl & (SCSW_FCTL_START_FUNC |
|
||||
SCSW_FCTL_HALT_FUNC |
|
||||
SCSW_FCTL_CLEAR_FUNC)) {
|
||||
return IOINST_CC_BUSY;
|
||||
@@ -1558,13 +1547,13 @@ IOInstEnding css_do_ssch(SubchDev *sch, ORB *orb)
|
||||
sch->orb = *orb;
|
||||
sch->channel_prog = orb->cpa;
|
||||
/* Trigger the start function. */
|
||||
s->ctrl |= (SCSW_FCTL_START_FUNC | SCSW_ACTL_START_PEND);
|
||||
s->flags &= ~SCSW_FLAGS_MASK_PNO;
|
||||
schib->scsw.ctrl |= (SCSW_FCTL_START_FUNC | SCSW_ACTL_START_PEND);
|
||||
schib->scsw.flags &= ~SCSW_FLAGS_MASK_PNO;
|
||||
|
||||
return do_subchannel_work(sch);
|
||||
}
|
||||
|
||||
static void copy_irb_to_guest(IRB *dest, const IRB *src, PMCW *pmcw,
|
||||
static void copy_irb_to_guest(IRB *dest, const IRB *src, const PMCW *pmcw,
|
||||
int *irb_len)
|
||||
{
|
||||
int i;
|
||||
@@ -1603,24 +1592,24 @@ static void copy_irb_to_guest(IRB *dest, const IRB *src, PMCW *pmcw,
|
||||
|
||||
int css_do_tsch_get_irb(SubchDev *sch, IRB *target_irb, int *irb_len)
|
||||
{
|
||||
SCSW *s = &sch->curr_status.scsw;
|
||||
PMCW *p = &sch->curr_status.pmcw;
|
||||
SCHIB *schib = &sch->curr_status;
|
||||
PMCW p;
|
||||
uint16_t stctl;
|
||||
IRB irb;
|
||||
|
||||
if (~(p->flags) & (PMCW_FLAGS_MASK_DNV | PMCW_FLAGS_MASK_ENA)) {
|
||||
if (~(schib->pmcw.flags) & (PMCW_FLAGS_MASK_DNV | PMCW_FLAGS_MASK_ENA)) {
|
||||
return 3;
|
||||
}
|
||||
|
||||
stctl = s->ctrl & SCSW_CTRL_MASK_STCTL;
|
||||
stctl = schib->scsw.ctrl & SCSW_CTRL_MASK_STCTL;
|
||||
|
||||
/* Prepare the irb for the guest. */
|
||||
memset(&irb, 0, sizeof(IRB));
|
||||
|
||||
/* Copy scsw from current status. */
|
||||
memcpy(&irb.scsw, s, sizeof(SCSW));
|
||||
irb.scsw = schib->scsw;
|
||||
if (stctl & SCSW_STCTL_STATUS_PEND) {
|
||||
if (s->cstat & (SCSW_CSTAT_DATA_CHECK |
|
||||
if (schib->scsw.cstat & (SCSW_CSTAT_DATA_CHECK |
|
||||
SCSW_CSTAT_CHN_CTRL_CHK |
|
||||
SCSW_CSTAT_INTF_CTRL_CHK)) {
|
||||
irb.scsw.flags |= SCSW_FLAGS_MASK_ESWF;
|
||||
@@ -1629,8 +1618,8 @@ int css_do_tsch_get_irb(SubchDev *sch, IRB *target_irb, int *irb_len)
|
||||
irb.esw[0] = 0x00800000;
|
||||
}
|
||||
/* If a unit check is pending, copy sense data. */
|
||||
if ((s->dstat & SCSW_DSTAT_UNIT_CHECK) &&
|
||||
(p->chars & PMCW_CHARS_MASK_CSENSE)) {
|
||||
if ((schib->scsw.dstat & SCSW_DSTAT_UNIT_CHECK) &&
|
||||
(schib->pmcw.chars & PMCW_CHARS_MASK_CSENSE)) {
|
||||
int i;
|
||||
|
||||
irb.scsw.flags |= SCSW_FLAGS_MASK_ESWF | SCSW_FLAGS_MASK_ECTL;
|
||||
@@ -1643,34 +1632,34 @@ int css_do_tsch_get_irb(SubchDev *sch, IRB *target_irb, int *irb_len)
|
||||
}
|
||||
}
|
||||
/* Store the irb to the guest. */
|
||||
copy_irb_to_guest(target_irb, &irb, p, irb_len);
|
||||
p = schib->pmcw;
|
||||
copy_irb_to_guest(target_irb, &irb, &p, irb_len);
|
||||
|
||||
return ((stctl & SCSW_STCTL_STATUS_PEND) == 0);
|
||||
}
|
||||
|
||||
void css_do_tsch_update_subch(SubchDev *sch)
|
||||
{
|
||||
SCSW *s = &sch->curr_status.scsw;
|
||||
PMCW *p = &sch->curr_status.pmcw;
|
||||
SCHIB *schib = &sch->curr_status;
|
||||
uint16_t stctl;
|
||||
uint16_t fctl;
|
||||
uint16_t actl;
|
||||
|
||||
stctl = s->ctrl & SCSW_CTRL_MASK_STCTL;
|
||||
fctl = s->ctrl & SCSW_CTRL_MASK_FCTL;
|
||||
actl = s->ctrl & SCSW_CTRL_MASK_ACTL;
|
||||
stctl = schib->scsw.ctrl & SCSW_CTRL_MASK_STCTL;
|
||||
fctl = schib->scsw.ctrl & SCSW_CTRL_MASK_FCTL;
|
||||
actl = schib->scsw.ctrl & SCSW_CTRL_MASK_ACTL;
|
||||
|
||||
/* Clear conditions on subchannel, if applicable. */
|
||||
if (stctl & SCSW_STCTL_STATUS_PEND) {
|
||||
s->ctrl &= ~SCSW_CTRL_MASK_STCTL;
|
||||
schib->scsw.ctrl &= ~SCSW_CTRL_MASK_STCTL;
|
||||
if ((stctl != (SCSW_STCTL_INTERMEDIATE | SCSW_STCTL_STATUS_PEND)) ||
|
||||
((fctl & SCSW_FCTL_HALT_FUNC) &&
|
||||
(actl & SCSW_ACTL_SUSP))) {
|
||||
s->ctrl &= ~SCSW_CTRL_MASK_FCTL;
|
||||
schib->scsw.ctrl &= ~SCSW_CTRL_MASK_FCTL;
|
||||
}
|
||||
if (stctl != (SCSW_STCTL_INTERMEDIATE | SCSW_STCTL_STATUS_PEND)) {
|
||||
s->flags &= ~SCSW_FLAGS_MASK_PNO;
|
||||
s->ctrl &= ~(SCSW_ACTL_RESUME_PEND |
|
||||
schib->scsw.flags &= ~SCSW_FLAGS_MASK_PNO;
|
||||
schib->scsw.ctrl &= ~(SCSW_ACTL_RESUME_PEND |
|
||||
SCSW_ACTL_START_PEND |
|
||||
SCSW_ACTL_HALT_PEND |
|
||||
SCSW_ACTL_CLEAR_PEND |
|
||||
@@ -1678,20 +1667,20 @@ void css_do_tsch_update_subch(SubchDev *sch)
|
||||
} else {
|
||||
if ((actl & SCSW_ACTL_SUSP) &&
|
||||
(fctl & SCSW_FCTL_START_FUNC)) {
|
||||
s->flags &= ~SCSW_FLAGS_MASK_PNO;
|
||||
schib->scsw.flags &= ~SCSW_FLAGS_MASK_PNO;
|
||||
if (fctl & SCSW_FCTL_HALT_FUNC) {
|
||||
s->ctrl &= ~(SCSW_ACTL_RESUME_PEND |
|
||||
schib->scsw.ctrl &= ~(SCSW_ACTL_RESUME_PEND |
|
||||
SCSW_ACTL_START_PEND |
|
||||
SCSW_ACTL_HALT_PEND |
|
||||
SCSW_ACTL_CLEAR_PEND |
|
||||
SCSW_ACTL_SUSP);
|
||||
} else {
|
||||
s->ctrl &= ~SCSW_ACTL_RESUME_PEND;
|
||||
schib->scsw.ctrl &= ~SCSW_ACTL_RESUME_PEND;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Clear pending sense data. */
|
||||
if (p->chars & PMCW_CHARS_MASK_CSENSE) {
|
||||
if (schib->pmcw.chars & PMCW_CHARS_MASK_CSENSE) {
|
||||
memset(sch->sense_data, 0 , sizeof(sch->sense_data));
|
||||
}
|
||||
}
|
||||
@@ -1804,20 +1793,19 @@ void css_do_schm(uint8_t mbk, int update, int dct, uint64_t mbo)
|
||||
|
||||
IOInstEnding css_do_rsch(SubchDev *sch)
|
||||
{
|
||||
SCSW *s = &sch->curr_status.scsw;
|
||||
PMCW *p = &sch->curr_status.pmcw;
|
||||
SCHIB *schib = &sch->curr_status;
|
||||
|
||||
if (~(p->flags) & (PMCW_FLAGS_MASK_DNV | PMCW_FLAGS_MASK_ENA)) {
|
||||
if (~(schib->pmcw.flags) & (PMCW_FLAGS_MASK_DNV | PMCW_FLAGS_MASK_ENA)) {
|
||||
return IOINST_CC_NOT_OPERATIONAL;
|
||||
}
|
||||
|
||||
if (s->ctrl & SCSW_STCTL_STATUS_PEND) {
|
||||
if (schib->scsw.ctrl & SCSW_STCTL_STATUS_PEND) {
|
||||
return IOINST_CC_STATUS_PRESENT;
|
||||
}
|
||||
|
||||
if (((s->ctrl & SCSW_CTRL_MASK_FCTL) != SCSW_FCTL_START_FUNC) ||
|
||||
(s->ctrl & SCSW_ACTL_RESUME_PEND) ||
|
||||
(!(s->ctrl & SCSW_ACTL_SUSP))) {
|
||||
if (((schib->scsw.ctrl & SCSW_CTRL_MASK_FCTL) != SCSW_FCTL_START_FUNC) ||
|
||||
(schib->scsw.ctrl & SCSW_ACTL_RESUME_PEND) ||
|
||||
(!(schib->scsw.ctrl & SCSW_ACTL_SUSP))) {
|
||||
return IOINST_CC_BUSY;
|
||||
}
|
||||
|
||||
@@ -1826,7 +1814,7 @@ IOInstEnding css_do_rsch(SubchDev *sch)
|
||||
css_update_chnmon(sch);
|
||||
}
|
||||
|
||||
s->ctrl |= SCSW_ACTL_RESUME_PEND;
|
||||
schib->scsw.ctrl |= SCSW_ACTL_RESUME_PEND;
|
||||
return do_subchannel_work(sch);
|
||||
}
|
||||
|
||||
@@ -1927,28 +1915,27 @@ static int css_add_chpid(uint8_t cssid, uint8_t chpid, uint8_t type,
|
||||
|
||||
void css_sch_build_virtual_schib(SubchDev *sch, uint8_t chpid, uint8_t type)
|
||||
{
|
||||
PMCW *p = &sch->curr_status.pmcw;
|
||||
SCSW *s = &sch->curr_status.scsw;
|
||||
SCHIB *schib = &sch->curr_status;
|
||||
int i;
|
||||
CssImage *css = channel_subsys.css[sch->cssid];
|
||||
|
||||
assert(css != NULL);
|
||||
memset(p, 0, sizeof(PMCW));
|
||||
p->flags |= PMCW_FLAGS_MASK_DNV;
|
||||
p->devno = sch->devno;
|
||||
memset(&schib->pmcw, 0, sizeof(PMCW));
|
||||
schib->pmcw.flags |= PMCW_FLAGS_MASK_DNV;
|
||||
schib->pmcw.devno = sch->devno;
|
||||
/* single path */
|
||||
p->pim = 0x80;
|
||||
p->pom = 0xff;
|
||||
p->pam = 0x80;
|
||||
p->chpid[0] = chpid;
|
||||
schib->pmcw.pim = 0x80;
|
||||
schib->pmcw.pom = 0xff;
|
||||
schib->pmcw.pam = 0x80;
|
||||
schib->pmcw.chpid[0] = chpid;
|
||||
if (!css->chpids[chpid].in_use) {
|
||||
css_add_chpid(sch->cssid, chpid, type, true);
|
||||
}
|
||||
|
||||
memset(s, 0, sizeof(SCSW));
|
||||
sch->curr_status.mba = 0;
|
||||
for (i = 0; i < ARRAY_SIZE(sch->curr_status.mda); i++) {
|
||||
sch->curr_status.mda[i] = 0;
|
||||
memset(&schib->scsw, 0, sizeof(SCSW));
|
||||
schib->mba = 0;
|
||||
for (i = 0; i < ARRAY_SIZE(schib->mda); i++) {
|
||||
schib->mda[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2246,30 +2233,30 @@ int css_enable_mss(void)
|
||||
|
||||
void css_reset_sch(SubchDev *sch)
|
||||
{
|
||||
PMCW *p = &sch->curr_status.pmcw;
|
||||
SCHIB *schib = &sch->curr_status;
|
||||
|
||||
if ((p->flags & PMCW_FLAGS_MASK_ENA) != 0 && sch->disable_cb) {
|
||||
if ((schib->pmcw.flags & PMCW_FLAGS_MASK_ENA) != 0 && sch->disable_cb) {
|
||||
sch->disable_cb(sch);
|
||||
}
|
||||
|
||||
p->intparm = 0;
|
||||
p->flags &= ~(PMCW_FLAGS_MASK_ISC | PMCW_FLAGS_MASK_ENA |
|
||||
schib->pmcw.intparm = 0;
|
||||
schib->pmcw.flags &= ~(PMCW_FLAGS_MASK_ISC | PMCW_FLAGS_MASK_ENA |
|
||||
PMCW_FLAGS_MASK_LM | PMCW_FLAGS_MASK_MME |
|
||||
PMCW_FLAGS_MASK_MP | PMCW_FLAGS_MASK_TF);
|
||||
p->flags |= PMCW_FLAGS_MASK_DNV;
|
||||
p->devno = sch->devno;
|
||||
p->pim = 0x80;
|
||||
p->lpm = p->pim;
|
||||
p->pnom = 0;
|
||||
p->lpum = 0;
|
||||
p->mbi = 0;
|
||||
p->pom = 0xff;
|
||||
p->pam = 0x80;
|
||||
p->chars &= ~(PMCW_CHARS_MASK_MBFC | PMCW_CHARS_MASK_XMWME |
|
||||
schib->pmcw.flags |= PMCW_FLAGS_MASK_DNV;
|
||||
schib->pmcw.devno = sch->devno;
|
||||
schib->pmcw.pim = 0x80;
|
||||
schib->pmcw.lpm = schib->pmcw.pim;
|
||||
schib->pmcw.pnom = 0;
|
||||
schib->pmcw.lpum = 0;
|
||||
schib->pmcw.mbi = 0;
|
||||
schib->pmcw.pom = 0xff;
|
||||
schib->pmcw.pam = 0x80;
|
||||
schib->pmcw.chars &= ~(PMCW_CHARS_MASK_MBFC | PMCW_CHARS_MASK_XMWME |
|
||||
PMCW_CHARS_MASK_CSENSE);
|
||||
|
||||
memset(&sch->curr_status.scsw, 0, sizeof(sch->curr_status.scsw));
|
||||
sch->curr_status.mba = 0;
|
||||
memset(&schib->scsw, 0, sizeof(schib->scsw));
|
||||
schib->mba = 0;
|
||||
|
||||
sch->channel_prog = 0x0;
|
||||
sch->last_cmd_valid = false;
|
||||
@@ -2433,7 +2420,7 @@ static int css_sch_get_chpids(SubchDev *sch, CssDevId *dev_id)
|
||||
FILE *fd;
|
||||
uint32_t chpid[8];
|
||||
int i;
|
||||
PMCW *p = &sch->curr_status.pmcw;
|
||||
SCHIB *schib = &sch->curr_status;
|
||||
|
||||
fid_path = g_strdup_printf("/sys/bus/css/devices/%x.%x.%04x/chpids",
|
||||
dev_id->cssid, dev_id->ssid, dev_id->devid);
|
||||
@@ -2452,8 +2439,8 @@ static int css_sch_get_chpids(SubchDev *sch, CssDevId *dev_id)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(p->chpid); i++) {
|
||||
p->chpid[i] = chpid[i];
|
||||
for (i = 0; i < ARRAY_SIZE(schib->pmcw.chpid); i++) {
|
||||
schib->pmcw.chpid[i] = chpid[i];
|
||||
}
|
||||
|
||||
fclose(fd);
|
||||
@@ -2467,7 +2454,7 @@ static int css_sch_get_path_masks(SubchDev *sch, CssDevId *dev_id)
|
||||
char *fid_path;
|
||||
FILE *fd;
|
||||
uint32_t pim, pam, pom;
|
||||
PMCW *p = &sch->curr_status.pmcw;
|
||||
SCHIB *schib = &sch->curr_status;
|
||||
|
||||
fid_path = g_strdup_printf("/sys/bus/css/devices/%x.%x.%04x/pimpampom",
|
||||
dev_id->cssid, dev_id->ssid, dev_id->devid);
|
||||
@@ -2484,9 +2471,9 @@ static int css_sch_get_path_masks(SubchDev *sch, CssDevId *dev_id)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
p->pim = pim;
|
||||
p->pam = pam;
|
||||
p->pom = pom;
|
||||
schib->pmcw.pim = pim;
|
||||
schib->pmcw.pam = pam;
|
||||
schib->pmcw.pom = pom;
|
||||
fclose(fd);
|
||||
g_free(fid_path);
|
||||
|
||||
@@ -2528,16 +2515,15 @@ static int css_sch_get_chpid_type(uint8_t chpid, uint32_t *type,
|
||||
int css_sch_build_schib(SubchDev *sch, CssDevId *dev_id)
|
||||
{
|
||||
CssImage *css = channel_subsys.css[sch->cssid];
|
||||
PMCW *p = &sch->curr_status.pmcw;
|
||||
SCSW *s = &sch->curr_status.scsw;
|
||||
SCHIB *schib = &sch->curr_status;
|
||||
uint32_t type;
|
||||
int i, ret;
|
||||
|
||||
assert(css != NULL);
|
||||
memset(p, 0, sizeof(PMCW));
|
||||
p->flags |= PMCW_FLAGS_MASK_DNV;
|
||||
memset(&schib->pmcw, 0, sizeof(PMCW));
|
||||
schib->pmcw.flags |= PMCW_FLAGS_MASK_DNV;
|
||||
/* We are dealing with I/O subchannels only. */
|
||||
p->devno = sch->devno;
|
||||
schib->pmcw.devno = sch->devno;
|
||||
|
||||
/* Grab path mask from sysfs. */
|
||||
ret = css_sch_get_path_masks(sch, dev_id);
|
||||
@@ -2552,20 +2538,20 @@ int css_sch_build_schib(SubchDev *sch, CssDevId *dev_id)
|
||||
}
|
||||
|
||||
/* Build chpid type. */
|
||||
for (i = 0; i < ARRAY_SIZE(p->chpid); i++) {
|
||||
if (p->chpid[i] && !css->chpids[p->chpid[i]].in_use) {
|
||||
ret = css_sch_get_chpid_type(p->chpid[i], &type, dev_id);
|
||||
for (i = 0; i < ARRAY_SIZE(schib->pmcw.chpid); i++) {
|
||||
if (schib->pmcw.chpid[i] && !css->chpids[schib->pmcw.chpid[i]].in_use) {
|
||||
ret = css_sch_get_chpid_type(schib->pmcw.chpid[i], &type, dev_id);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
css_add_chpid(sch->cssid, p->chpid[i], type, false);
|
||||
css_add_chpid(sch->cssid, schib->pmcw.chpid[i], type, false);
|
||||
}
|
||||
}
|
||||
|
||||
memset(s, 0, sizeof(SCSW));
|
||||
sch->curr_status.mba = 0;
|
||||
for (i = 0; i < ARRAY_SIZE(sch->curr_status.mda); i++) {
|
||||
sch->curr_status.mda[i] = 0;
|
||||
memset(&schib->scsw, 0, sizeof(SCSW));
|
||||
schib->mba = 0;
|
||||
for (i = 0; i < ARRAY_SIZE(schib->mda); i++) {
|
||||
schib->mda[i] = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
+5
-7
@@ -252,8 +252,6 @@ static void s390_ipl_set_boot_menu(S390IPLState *ipl)
|
||||
{
|
||||
QemuOptsList *plist = qemu_find_opts("boot-opts");
|
||||
QemuOpts *opts = QTAILQ_FIRST(&plist->head);
|
||||
uint8_t *flags = &ipl->qipl.qipl_flags;
|
||||
uint32_t *timeout = &ipl->qipl.boot_menu_timeout;
|
||||
const char *tmp;
|
||||
unsigned long splash_time = 0;
|
||||
|
||||
@@ -269,7 +267,7 @@ static void s390_ipl_set_boot_menu(S390IPLState *ipl)
|
||||
case S390_IPL_TYPE_CCW:
|
||||
/* In the absence of -boot menu, use zipl parameters */
|
||||
if (!qemu_opt_get(opts, "menu")) {
|
||||
*flags |= QIPL_FLAG_BM_OPTS_ZIPL;
|
||||
ipl->qipl.qipl_flags |= QIPL_FLAG_BM_OPTS_ZIPL;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
@@ -286,23 +284,23 @@ static void s390_ipl_set_boot_menu(S390IPLState *ipl)
|
||||
return;
|
||||
}
|
||||
|
||||
*flags |= QIPL_FLAG_BM_OPTS_CMD;
|
||||
ipl->qipl.qipl_flags |= QIPL_FLAG_BM_OPTS_CMD;
|
||||
|
||||
tmp = qemu_opt_get(opts, "splash-time");
|
||||
|
||||
if (tmp && qemu_strtoul(tmp, NULL, 10, &splash_time)) {
|
||||
error_report("splash-time is invalid, forcing it to 0");
|
||||
*timeout = 0;
|
||||
ipl->qipl.boot_menu_timeout = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (splash_time > 0xffffffff) {
|
||||
error_report("splash-time is too large, forcing it to max value");
|
||||
*timeout = 0xffffffff;
|
||||
ipl->qipl.boot_menu_timeout = 0xffffffff;
|
||||
return;
|
||||
}
|
||||
|
||||
*timeout = cpu_to_be32(splash_time);
|
||||
ipl->qipl.boot_menu_timeout = cpu_to_be32(splash_time);
|
||||
}
|
||||
|
||||
static CcwDevice *s390_get_ccw_device(DeviceState *dev_st)
|
||||
|
||||
+9
-2
@@ -1699,12 +1699,19 @@ static void usb_mtp_write_metadata(MTPState *s, uint64_t dlen)
|
||||
MTPObject *o;
|
||||
MTPObject *p = usb_mtp_object_lookup(s, s->dataset.parent_handle);
|
||||
uint32_t next_handle = s->next_handle;
|
||||
size_t filename_chars = dlen - offsetof(ObjectInfo, filename);
|
||||
|
||||
/*
|
||||
* filename is utf-16. We're intentionally doing
|
||||
* integer division to truncate if malicious guest
|
||||
* sent an odd number of bytes.
|
||||
*/
|
||||
filename_chars /= 2;
|
||||
|
||||
assert(!s->write_pending);
|
||||
assert(p != NULL);
|
||||
|
||||
filename = utf16_to_str(MIN(dataset->length,
|
||||
dlen - offsetof(ObjectInfo, filename)),
|
||||
filename = utf16_to_str(MIN(dataset->length, filename_chars),
|
||||
dataset->filename);
|
||||
|
||||
if (strchr(filename, '/')) {
|
||||
|
||||
+22
-20
@@ -130,8 +130,8 @@ static void vfio_ccw_io_notifier_handler(void *opaque)
|
||||
S390CCWDevice *cdev = S390_CCW_DEVICE(vcdev);
|
||||
CcwDevice *ccw_dev = CCW_DEVICE(cdev);
|
||||
SubchDev *sch = ccw_dev->sch;
|
||||
SCSW *s = &sch->curr_status.scsw;
|
||||
PMCW *p = &sch->curr_status.pmcw;
|
||||
SCHIB *schib = &sch->curr_status;
|
||||
SCSW s;
|
||||
IRB irb;
|
||||
int size;
|
||||
|
||||
@@ -145,33 +145,33 @@ static void vfio_ccw_io_notifier_handler(void *opaque)
|
||||
switch (errno) {
|
||||
case ENODEV:
|
||||
/* Generate a deferred cc 3 condition. */
|
||||
s->flags |= SCSW_FLAGS_MASK_CC;
|
||||
s->ctrl &= ~SCSW_CTRL_MASK_STCTL;
|
||||
s->ctrl |= (SCSW_STCTL_ALERT | SCSW_STCTL_STATUS_PEND);
|
||||
schib->scsw.flags |= SCSW_FLAGS_MASK_CC;
|
||||
schib->scsw.ctrl &= ~SCSW_CTRL_MASK_STCTL;
|
||||
schib->scsw.ctrl |= (SCSW_STCTL_ALERT | SCSW_STCTL_STATUS_PEND);
|
||||
goto read_err;
|
||||
case EFAULT:
|
||||
/* Memory problem, generate channel data check. */
|
||||
s->ctrl &= ~SCSW_ACTL_START_PEND;
|
||||
s->cstat = SCSW_CSTAT_DATA_CHECK;
|
||||
s->ctrl &= ~SCSW_CTRL_MASK_STCTL;
|
||||
s->ctrl |= SCSW_STCTL_PRIMARY | SCSW_STCTL_SECONDARY |
|
||||
schib->scsw.ctrl &= ~SCSW_ACTL_START_PEND;
|
||||
schib->scsw.cstat = SCSW_CSTAT_DATA_CHECK;
|
||||
schib->scsw.ctrl &= ~SCSW_CTRL_MASK_STCTL;
|
||||
schib->scsw.ctrl |= SCSW_STCTL_PRIMARY | SCSW_STCTL_SECONDARY |
|
||||
SCSW_STCTL_ALERT | SCSW_STCTL_STATUS_PEND;
|
||||
goto read_err;
|
||||
default:
|
||||
/* Error, generate channel program check. */
|
||||
s->ctrl &= ~SCSW_ACTL_START_PEND;
|
||||
s->cstat = SCSW_CSTAT_PROG_CHECK;
|
||||
s->ctrl &= ~SCSW_CTRL_MASK_STCTL;
|
||||
s->ctrl |= SCSW_STCTL_PRIMARY | SCSW_STCTL_SECONDARY |
|
||||
schib->scsw.ctrl &= ~SCSW_ACTL_START_PEND;
|
||||
schib->scsw.cstat = SCSW_CSTAT_PROG_CHECK;
|
||||
schib->scsw.ctrl &= ~SCSW_CTRL_MASK_STCTL;
|
||||
schib->scsw.ctrl |= SCSW_STCTL_PRIMARY | SCSW_STCTL_SECONDARY |
|
||||
SCSW_STCTL_ALERT | SCSW_STCTL_STATUS_PEND;
|
||||
goto read_err;
|
||||
}
|
||||
} else if (size != vcdev->io_region_size) {
|
||||
/* Information transfer error, generate channel-control check. */
|
||||
s->ctrl &= ~SCSW_ACTL_START_PEND;
|
||||
s->cstat = SCSW_CSTAT_CHN_CTRL_CHK;
|
||||
s->ctrl &= ~SCSW_CTRL_MASK_STCTL;
|
||||
s->ctrl |= SCSW_STCTL_PRIMARY | SCSW_STCTL_SECONDARY |
|
||||
schib->scsw.ctrl &= ~SCSW_ACTL_START_PEND;
|
||||
schib->scsw.cstat = SCSW_CSTAT_CHN_CTRL_CHK;
|
||||
schib->scsw.ctrl &= ~SCSW_CTRL_MASK_STCTL;
|
||||
schib->scsw.ctrl |= SCSW_STCTL_PRIMARY | SCSW_STCTL_SECONDARY |
|
||||
SCSW_STCTL_ALERT | SCSW_STCTL_STATUS_PEND;
|
||||
goto read_err;
|
||||
}
|
||||
@@ -179,11 +179,13 @@ static void vfio_ccw_io_notifier_handler(void *opaque)
|
||||
memcpy(&irb, region->irb_area, sizeof(IRB));
|
||||
|
||||
/* Update control block via irb. */
|
||||
copy_scsw_to_guest(s, &irb.scsw);
|
||||
s = schib->scsw;
|
||||
copy_scsw_to_guest(&s, &irb.scsw);
|
||||
schib->scsw = s;
|
||||
|
||||
/* If a uint check is pending, copy sense data. */
|
||||
if ((s->dstat & SCSW_DSTAT_UNIT_CHECK) &&
|
||||
(p->chars & PMCW_CHARS_MASK_CSENSE)) {
|
||||
if ((schib->scsw.dstat & SCSW_DSTAT_UNIT_CHECK) &&
|
||||
(schib->pmcw.chars & PMCW_CHARS_MASK_CSENSE)) {
|
||||
memcpy(sch->sense_data, irb.ecw, sizeof(irb.ecw));
|
||||
}
|
||||
|
||||
|
||||
@@ -234,7 +234,6 @@ struct IntelIOMMUState {
|
||||
bool scalable_mode; /* RO - is Scalable Mode supported? */
|
||||
|
||||
dma_addr_t root; /* Current root table pointer */
|
||||
bool root_extended; /* Type of root table (extended or not) */
|
||||
bool root_scalable; /* Type of root table (scalable or not) */
|
||||
bool dmar_enabled; /* Set if DMA remapping is enabled */
|
||||
|
||||
|
||||
@@ -396,6 +396,8 @@ typedef PCIINTxRoute (*pci_route_irq_fn)(void *opaque, int pin);
|
||||
|
||||
bool pci_bus_is_express(PCIBus *bus);
|
||||
bool pci_bus_is_root(PCIBus *bus);
|
||||
bool pci_bus_allows_extended_config_space(PCIBus *bus);
|
||||
|
||||
void pci_root_bus_new_inplace(PCIBus *bus, size_t bus_size, DeviceState *parent,
|
||||
const char *name,
|
||||
MemoryRegion *address_space_mem,
|
||||
|
||||
@@ -18,6 +18,7 @@ typedef struct PCIBusClass {
|
||||
bool (*is_root)(PCIBus *bus);
|
||||
int (*bus_num)(PCIBus *bus);
|
||||
uint16_t (*numa_node)(PCIBus *bus);
|
||||
bool (*allows_extended_config_space)(PCIBus *bus);
|
||||
} PCIBusClass;
|
||||
|
||||
struct PCIBus {
|
||||
|
||||
@@ -70,7 +70,7 @@ enum {
|
||||
#define SIFIVE_E_PLIC_HART_CONFIG "M"
|
||||
#define SIFIVE_E_PLIC_NUM_SOURCES 127
|
||||
#define SIFIVE_E_PLIC_NUM_PRIORITIES 7
|
||||
#define SIFIVE_E_PLIC_PRIORITY_BASE 0x0
|
||||
#define SIFIVE_E_PLIC_PRIORITY_BASE 0x04
|
||||
#define SIFIVE_E_PLIC_PENDING_BASE 0x1000
|
||||
#define SIFIVE_E_PLIC_ENABLE_BASE 0x2000
|
||||
#define SIFIVE_E_PLIC_ENABLE_STRIDE 0x80
|
||||
|
||||
@@ -68,9 +68,9 @@ enum {
|
||||
};
|
||||
|
||||
#define SIFIVE_U_PLIC_HART_CONFIG "MS"
|
||||
#define SIFIVE_U_PLIC_NUM_SOURCES 127
|
||||
#define SIFIVE_U_PLIC_NUM_SOURCES 54
|
||||
#define SIFIVE_U_PLIC_NUM_PRIORITIES 7
|
||||
#define SIFIVE_U_PLIC_PRIORITY_BASE 0x0
|
||||
#define SIFIVE_U_PLIC_PRIORITY_BASE 0x04
|
||||
#define SIFIVE_U_PLIC_PENDING_BASE 0x1000
|
||||
#define SIFIVE_U_PLIC_ENABLE_BASE 0x2000
|
||||
#define SIFIVE_U_PLIC_ENABLE_STRIDE 0x80
|
||||
|
||||
@@ -59,7 +59,7 @@ enum {
|
||||
#define VIRT_PLIC_HART_CONFIG "MS"
|
||||
#define VIRT_PLIC_NUM_SOURCES 127
|
||||
#define VIRT_PLIC_NUM_PRIORITIES 7
|
||||
#define VIRT_PLIC_PRIORITY_BASE 0x0
|
||||
#define VIRT_PLIC_PRIORITY_BASE 0x04
|
||||
#define VIRT_PLIC_PENDING_BASE 0x1000
|
||||
#define VIRT_PLIC_ENABLE_BASE 0x2000
|
||||
#define VIRT_PLIC_ENABLE_STRIDE 0x80
|
||||
|
||||
+16
-10
@@ -316,51 +316,57 @@ static inline void stb_p(void *ptr, uint8_t v)
|
||||
*(uint8_t *)ptr = v;
|
||||
}
|
||||
|
||||
/* Any compiler worth its salt will turn these memcpy into native unaligned
|
||||
operations. Thus we don't need to play games with packed attributes, or
|
||||
inline byte-by-byte stores. */
|
||||
/*
|
||||
* Any compiler worth its salt will turn these memcpy into native unaligned
|
||||
* operations. Thus we don't need to play games with packed attributes, or
|
||||
* inline byte-by-byte stores.
|
||||
* Some compilation environments (eg some fortify-source implementations)
|
||||
* may intercept memcpy() in a way that defeats the compiler optimization,
|
||||
* though, so we use __builtin_memcpy() to give ourselves the best chance
|
||||
* of good performance.
|
||||
*/
|
||||
|
||||
static inline int lduw_he_p(const void *ptr)
|
||||
{
|
||||
uint16_t r;
|
||||
memcpy(&r, ptr, sizeof(r));
|
||||
__builtin_memcpy(&r, ptr, sizeof(r));
|
||||
return r;
|
||||
}
|
||||
|
||||
static inline int ldsw_he_p(const void *ptr)
|
||||
{
|
||||
int16_t r;
|
||||
memcpy(&r, ptr, sizeof(r));
|
||||
__builtin_memcpy(&r, ptr, sizeof(r));
|
||||
return r;
|
||||
}
|
||||
|
||||
static inline void stw_he_p(void *ptr, uint16_t v)
|
||||
{
|
||||
memcpy(ptr, &v, sizeof(v));
|
||||
__builtin_memcpy(ptr, &v, sizeof(v));
|
||||
}
|
||||
|
||||
static inline int ldl_he_p(const void *ptr)
|
||||
{
|
||||
int32_t r;
|
||||
memcpy(&r, ptr, sizeof(r));
|
||||
__builtin_memcpy(&r, ptr, sizeof(r));
|
||||
return r;
|
||||
}
|
||||
|
||||
static inline void stl_he_p(void *ptr, uint32_t v)
|
||||
{
|
||||
memcpy(ptr, &v, sizeof(v));
|
||||
__builtin_memcpy(ptr, &v, sizeof(v));
|
||||
}
|
||||
|
||||
static inline uint64_t ldq_he_p(const void *ptr)
|
||||
{
|
||||
uint64_t r;
|
||||
memcpy(&r, ptr, sizeof(r));
|
||||
__builtin_memcpy(&r, ptr, sizeof(r));
|
||||
return r;
|
||||
}
|
||||
|
||||
static inline void stq_he_p(void *ptr, uint64_t v)
|
||||
{
|
||||
memcpy(ptr, &v, sizeof(v));
|
||||
__builtin_memcpy(ptr, &v, sizeof(v));
|
||||
}
|
||||
|
||||
static inline int lduw_le_p(const void *ptr)
|
||||
|
||||
+6
-13
@@ -249,15 +249,8 @@ static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5, \
|
||||
#define TARGET_NR__llseek TARGET_NR_llseek
|
||||
#endif
|
||||
|
||||
#ifdef __NR_gettid
|
||||
_syscall0(int, gettid)
|
||||
#else
|
||||
/* This is a replacement for the host gettid() and must return a host
|
||||
errno. */
|
||||
static int gettid(void) {
|
||||
return -ENOSYS;
|
||||
}
|
||||
#endif
|
||||
#define __NR_sys_gettid __NR_gettid
|
||||
_syscall0(int, sys_gettid)
|
||||
|
||||
/* For the 64-bit guest on 32-bit host case we must emulate
|
||||
* getdents using getdents64, because otherwise the host
|
||||
@@ -5442,7 +5435,7 @@ static void *clone_func(void *arg)
|
||||
cpu = ENV_GET_CPU(env);
|
||||
thread_cpu = cpu;
|
||||
ts = (TaskState *)cpu->opaque;
|
||||
info->tid = gettid();
|
||||
info->tid = sys_gettid();
|
||||
task_settid(ts);
|
||||
if (info->child_tidptr)
|
||||
put_user_u32(info->tid, info->child_tidptr);
|
||||
@@ -5587,9 +5580,9 @@ static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp,
|
||||
mapping. We can't repeat the spinlock hack used above because
|
||||
the child process gets its own copy of the lock. */
|
||||
if (flags & CLONE_CHILD_SETTID)
|
||||
put_user_u32(gettid(), child_tidptr);
|
||||
put_user_u32(sys_gettid(), child_tidptr);
|
||||
if (flags & CLONE_PARENT_SETTID)
|
||||
put_user_u32(gettid(), parent_tidptr);
|
||||
put_user_u32(sys_gettid(), parent_tidptr);
|
||||
ts = (TaskState *)cpu->opaque;
|
||||
if (flags & CLONE_SETTLS)
|
||||
cpu_set_tls (env, newtls);
|
||||
@@ -10629,7 +10622,7 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
|
||||
return TARGET_PAGE_SIZE;
|
||||
#endif
|
||||
case TARGET_NR_gettid:
|
||||
return get_errno(gettid());
|
||||
return get_errno(sys_gettid());
|
||||
#ifdef TARGET_NR_readahead
|
||||
case TARGET_NR_readahead:
|
||||
#if TARGET_ABI_BITS == 32
|
||||
|
||||
+3
-1
@@ -851,7 +851,7 @@ static int multifd_recv_unfill_packet(MultiFDRecvParams *p, Error **errp)
|
||||
*/
|
||||
if (packet->pages_alloc > p->pages->allocated) {
|
||||
multifd_pages_clear(p->pages);
|
||||
multifd_pages_init(packet->pages_alloc);
|
||||
p->pages = multifd_pages_init(packet->pages_alloc);
|
||||
}
|
||||
|
||||
p->pages->used = be32_to_cpu(packet->pages_used);
|
||||
@@ -3918,6 +3918,7 @@ int colo_init_ram_cache(void)
|
||||
}
|
||||
ram_state = g_new0(RAMState, 1);
|
||||
ram_state->migration_dirty_pages = 0;
|
||||
qemu_mutex_init(&ram_state->bitmap_mutex);
|
||||
memory_global_dirty_log_start();
|
||||
|
||||
return 0;
|
||||
@@ -3956,6 +3957,7 @@ void colo_release_ram_cache(void)
|
||||
}
|
||||
|
||||
rcu_read_unlock();
|
||||
qemu_mutex_destroy(&ram_state->bitmap_mutex);
|
||||
g_free(ram_state);
|
||||
ram_state = NULL;
|
||||
}
|
||||
|
||||
+1
-1
@@ -428,7 +428,7 @@ static int nbd_opt_info_or_go(QIOChannel *ioc, uint32_t opt,
|
||||
}
|
||||
if (info->min_block &&
|
||||
!QEMU_IS_ALIGNED(info->size, info->min_block)) {
|
||||
error_setg(errp, "export size %" PRIu64 "is not multiple of "
|
||||
error_setg(errp, "export size %" PRIu64 " is not multiple of "
|
||||
"minimum block size %" PRIu32, info->size,
|
||||
info->min_block);
|
||||
nbd_send_opt_abort(ioc);
|
||||
|
||||
+27
-12
@@ -124,6 +124,8 @@ struct NBDClient {
|
||||
int nb_requests;
|
||||
bool closing;
|
||||
|
||||
uint32_t check_align; /* If non-zero, check for aligned client requests */
|
||||
|
||||
bool structured_reply;
|
||||
NBDExportMetaContexts export_meta;
|
||||
|
||||
@@ -533,6 +535,7 @@ static int nbd_negotiate_handle_info(NBDClient *client, uint16_t myflags,
|
||||
bool blocksize = false;
|
||||
uint32_t sizes[3];
|
||||
char buf[sizeof(uint64_t) + sizeof(uint16_t)];
|
||||
uint32_t check_align = 0;
|
||||
|
||||
/* Client sends:
|
||||
4 bytes: L, name length (can be 0)
|
||||
@@ -609,7 +612,7 @@ static int nbd_negotiate_handle_info(NBDClient *client, uint16_t myflags,
|
||||
* whether this is OPT_INFO or OPT_GO. */
|
||||
/* minimum - 1 for back-compat, or actual if client will obey it. */
|
||||
if (client->opt == NBD_OPT_INFO || blocksize) {
|
||||
sizes[0] = blk_get_request_alignment(exp->blk);
|
||||
check_align = sizes[0] = blk_get_request_alignment(exp->blk);
|
||||
} else {
|
||||
sizes[0] = 1;
|
||||
}
|
||||
@@ -640,11 +643,14 @@ static int nbd_negotiate_handle_info(NBDClient *client, uint16_t myflags,
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* If the client is just asking for NBD_OPT_INFO, but forgot to
|
||||
* request block sizes, return an error.
|
||||
* TODO: consult blk_bs(blk)->request_align, and only error if it
|
||||
* is not 1? */
|
||||
if (client->opt == NBD_OPT_INFO && !blocksize) {
|
||||
/*
|
||||
* If the client is just asking for NBD_OPT_INFO, but forgot to
|
||||
* request block sizes in a situation that would impact
|
||||
* performance, then return an error. But for NBD_OPT_GO, we
|
||||
* tolerate all clients, regardless of alignments.
|
||||
*/
|
||||
if (client->opt == NBD_OPT_INFO && !blocksize &&
|
||||
blk_get_request_alignment(exp->blk) > 1) {
|
||||
return nbd_negotiate_send_rep_err(client,
|
||||
NBD_REP_ERR_BLOCK_SIZE_REQD,
|
||||
errp,
|
||||
@@ -660,6 +666,7 @@ static int nbd_negotiate_handle_info(NBDClient *client, uint16_t myflags,
|
||||
|
||||
if (client->opt == NBD_OPT_GO) {
|
||||
client->exp = exp;
|
||||
client->check_align = check_align;
|
||||
QTAILQ_INSERT_TAIL(&client->exp->clients, client, next);
|
||||
nbd_export_get(client->exp);
|
||||
nbd_check_meta_export(client);
|
||||
@@ -1880,17 +1887,12 @@ static int blockstatus_to_extents(BlockDriverState *bs, uint64_t offset,
|
||||
|
||||
flags = (ret & BDRV_BLOCK_ALLOCATED ? 0 : NBD_STATE_HOLE) |
|
||||
(ret & BDRV_BLOCK_ZERO ? NBD_STATE_ZERO : 0);
|
||||
offset += num;
|
||||
remaining_bytes -= num;
|
||||
|
||||
if (first_extent) {
|
||||
extent->flags = flags;
|
||||
extent->length = num;
|
||||
first_extent = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (flags == extent->flags) {
|
||||
} else if (flags == extent->flags) {
|
||||
/* extend current extent */
|
||||
extent->length += num;
|
||||
} else {
|
||||
@@ -1903,6 +1905,8 @@ static int blockstatus_to_extents(BlockDriverState *bs, uint64_t offset,
|
||||
extent->flags = flags;
|
||||
extent->length = num;
|
||||
}
|
||||
offset += num;
|
||||
remaining_bytes -= num;
|
||||
}
|
||||
|
||||
extents_end = extent + 1;
|
||||
@@ -2129,6 +2133,17 @@ static int nbd_co_receive_request(NBDRequestData *req, NBDRequest *request,
|
||||
return (request->type == NBD_CMD_WRITE ||
|
||||
request->type == NBD_CMD_WRITE_ZEROES) ? -ENOSPC : -EINVAL;
|
||||
}
|
||||
if (client->check_align && !QEMU_IS_ALIGNED(request->from | request->len,
|
||||
client->check_align)) {
|
||||
/*
|
||||
* The block layer gracefully handles unaligned requests, but
|
||||
* it's still worth tracing client non-compliance
|
||||
*/
|
||||
trace_nbd_co_receive_align_compliance(nbd_cmd_lookup(request->type),
|
||||
request->from,
|
||||
request->len,
|
||||
client->check_align);
|
||||
}
|
||||
valid_flags = NBD_CMD_FLAG_FUA;
|
||||
if (request->type == NBD_CMD_READ && client->structured_reply) {
|
||||
valid_flags |= NBD_CMD_FLAG_DF;
|
||||
|
||||
@@ -71,4 +71,5 @@ nbd_co_send_extents(uint64_t handle, unsigned int extents, uint32_t id, uint64_t
|
||||
nbd_co_send_structured_error(uint64_t handle, int err, const char *errname, const char *msg) "Send structured error reply: handle = %" PRIu64 ", error = %d (%s), msg = '%s'"
|
||||
nbd_co_receive_request_decode_type(uint64_t handle, uint16_t type, const char *name) "Decoding type: handle = %" PRIu64 ", type = %" PRIu16 " (%s)"
|
||||
nbd_co_receive_request_payload_received(uint64_t handle, uint32_t len) "Payload received: handle = %" PRIu64 ", len = %" PRIu32
|
||||
nbd_co_receive_align_compliance(const char *op, uint64_t from, uint32_t len, uint32_t align) "client sent non-compliant unaligned %s request: from=0x%" PRIx64 ", len=0x%" PRIx32 ", align=0x%" PRIx32
|
||||
nbd_trip(void) "Reading request"
|
||||
@@ -105,6 +105,11 @@ details.
|
||||
The ``query-events'' command has been superseded by the more powerful
|
||||
and accurate ``query-qmp-schema'' command.
|
||||
|
||||
@subsection chardev client socket with 'wait' option (since 4.0)
|
||||
|
||||
Character devices creating sockets in client mode should not specify
|
||||
the 'wait' field, which is only applicable to sockets in server mode
|
||||
|
||||
@section Human Monitor Protocol (HMP) commands
|
||||
|
||||
@subsection The hub_id parameter of 'hostfwd_add' / 'hostfwd_remove' (since 3.1)
|
||||
|
||||
+1
-1
@@ -46,7 +46,7 @@ ETEXI
|
||||
DEF("convert", img_convert,
|
||||
"convert [--object objectdef] [--image-opts] [--target-image-opts] [-U] [-C] [-c] [-p] [-q] [-n] [-f fmt] [-t cache] [-T src_cache] [-O output_fmt] [-B backing_file] [-o options] [-l snapshot_param] [-S sparse_size] [-m num_coroutines] [-W] filename [filename2 [...]] output_filename")
|
||||
STEXI
|
||||
@item convert [--object @var{objectdef}] [--image-opts] [--target-image-opts] [-U] [-c] [-p] [-q] [-n] [-f @var{fmt}] [-t @var{cache}] [-T @var{src_cache}] [-O @var{output_fmt}] [-B @var{backing_file}] [-o @var{options}] [-l @var{snapshot_param}] [-S @var{sparse_size}] [-m @var{num_coroutines}] [-W] @var{filename} [@var{filename2} [...]] @var{output_filename}
|
||||
@item convert [--object @var{objectdef}] [--image-opts] [--target-image-opts] [-U] [-C] [-c] [-p] [-q] [-n] [-f @var{fmt}] [-t @var{cache}] [-T @var{src_cache}] [-O @var{output_fmt}] [-B @var{backing_file}] [-o @var{options}] [-l @var{snapshot_param}] [-S @var{sparse_size}] [-m @var{num_coroutines}] [-W] @var{filename} [@var{filename2} [...]] @var{output_filename}
|
||||
ETEXI
|
||||
|
||||
DEF("create", img_create,
|
||||
|
||||
+2
-2
@@ -197,7 +197,7 @@ Command description:
|
||||
|
||||
@table @option
|
||||
|
||||
@item amend [--object @var{objectdef}] [--image-opts] [-p] [-p] [-f @var{fmt}] [-t @var{cache}] -o @var{options} @var{filename}
|
||||
@item amend [--object @var{objectdef}] [--image-opts] [-p] [-q] [-f @var{fmt}] [-t @var{cache}] -o @var{options} @var{filename}
|
||||
|
||||
Amends the image format specific @var{options} for the image file
|
||||
@var{filename}. Not all file formats support this operation.
|
||||
@@ -424,7 +424,7 @@ To enumerate information about each disk image in the above chain, starting from
|
||||
qemu-img info --backing-chain snap2.qcow2
|
||||
@end example
|
||||
|
||||
@item map [-f @var{fmt}] [--output=@var{ofmt}] @var{filename}
|
||||
@item map [--object @var{objectdef}] [--image-opts] [-f @var{fmt}] [--output=@var{ofmt}] [-U] @var{filename}
|
||||
|
||||
Dump the metadata of image @var{filename} and its backing file chain.
|
||||
In particular, this commands dumps the allocation state of every sector
|
||||
|
||||
+18
-5
@@ -47,7 +47,7 @@ SEABIOS_EXTRAVERSION="-prebuilt.qemu.org"
|
||||
# We need that to combine multiple images (legacy bios,
|
||||
# efi ia32, efi x64) into a single rom binary.
|
||||
#
|
||||
EFIROM = edk2/BaseTools/Source/C/bin/EfiRom
|
||||
EDK2_EFIROM = edk2/BaseTools/Source/C/bin/EfiRom
|
||||
|
||||
default:
|
||||
@echo "nothing is build by default"
|
||||
@@ -102,8 +102,8 @@ pxe-rom-%: build-pxe-roms
|
||||
|
||||
efirom: $(patsubst %,efi-rom-%,$(pxerom_variants))
|
||||
|
||||
efi-rom-%: build-pxe-roms build-efi-roms $(EFIROM)
|
||||
$(EFIROM) -f "0x$(VID)" -i "0x$(DID)" -l 0x02 \
|
||||
efi-rom-%: build-pxe-roms build-efi-roms $(EDK2_EFIROM)
|
||||
$(EDK2_EFIROM) -f "0x$(VID)" -i "0x$(DID)" -l 0x02 \
|
||||
-b ipxe/src/bin/$(VID)$(DID).rom \
|
||||
-ec ipxe/src/bin-i386-efi/$(VID)$(DID).efidrv \
|
||||
-ec ipxe/src/bin-x86_64-efi/$(VID)$(DID).efidrv \
|
||||
@@ -120,8 +120,21 @@ build-efi-roms: build-pxe-roms
|
||||
$(patsubst %,bin-i386-efi/%.efidrv,$(pxerom_targets)) \
|
||||
$(patsubst %,bin-x86_64-efi/%.efidrv,$(pxerom_targets))
|
||||
|
||||
$(EFIROM):
|
||||
$(MAKE) -C edk2/BaseTools
|
||||
# Build scripts can pass compiler/linker flags to the EDK2 build tools
|
||||
# via the EDK2_BASETOOLS_OPTFLAGS (CPPFLAGS and CFLAGS) and
|
||||
# EDK2_BASETOOLS_LDFLAGS (LDFLAGS) environment variables.
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# make -C roms \
|
||||
# EDK2_BASETOOLS_OPTFLAGS='...' \
|
||||
# EDK2_BASETOOLS_LDFLAGS='...' \
|
||||
# efirom
|
||||
#
|
||||
$(EDK2_EFIROM):
|
||||
$(MAKE) -C edk2/BaseTools \
|
||||
EXTRA_OPTFLAGS='$(EDK2_BASETOOLS_OPTFLAGS)' \
|
||||
EXTRA_LDFLAGS='$(EDK2_BASETOOLS_LDFLAGS)'
|
||||
|
||||
slof:
|
||||
$(MAKE) -C SLOF CROSS=$(powerpc64_cross_prefix) qemu
|
||||
|
||||
+4
-1
@@ -171,6 +171,7 @@ int
|
||||
soread(struct socket *so)
|
||||
{
|
||||
int n, nn;
|
||||
size_t buf_len;
|
||||
struct sbuf *sb = &so->so_snd;
|
||||
struct iovec iov[2];
|
||||
|
||||
@@ -181,7 +182,8 @@ soread(struct socket *so)
|
||||
* No need to check if there's enough room to read.
|
||||
* soread wouldn't have been called if there weren't
|
||||
*/
|
||||
sopreprbuf(so, iov, &n);
|
||||
buf_len = sopreprbuf(so, iov, &n);
|
||||
assert(buf_len != 0);
|
||||
|
||||
nn = recv(so->s, iov[0].iov_base, iov[0].iov_len,0);
|
||||
if (nn <= 0) {
|
||||
@@ -257,6 +259,7 @@ int soreadbuf(struct socket *so, const char *buf, int size)
|
||||
* No need to check if there's enough room to read.
|
||||
* soread wouldn't have been called if there weren't
|
||||
*/
|
||||
assert(size > 0);
|
||||
if (sopreprbuf(so, iov, &n) < size)
|
||||
goto err;
|
||||
|
||||
|
||||
@@ -1398,6 +1398,11 @@ static void gen_op(DisasContext *s1, int op, TCGMemOp ot, int d)
|
||||
static void gen_inc(DisasContext *s1, TCGMemOp ot, int d, int c)
|
||||
{
|
||||
if (s1->prefix & PREFIX_LOCK) {
|
||||
if (d != OR_TMP0) {
|
||||
/* Lock prefix when destination is not memory */
|
||||
gen_illegal_opcode(s1);
|
||||
return;
|
||||
}
|
||||
tcg_gen_movi_tl(s1->T0, c > 0 ? 1 : -1);
|
||||
tcg_gen_atomic_add_fetch_tl(s1->T0, s1->A0, s1->T0,
|
||||
s1->mem_index, ot | MO_LE);
|
||||
|
||||
@@ -1164,7 +1164,7 @@ check-acceptance: check-venv $(TESTS_RESULTS_DIR)
|
||||
|
||||
# Consolidated targets
|
||||
|
||||
.PHONY: check-qapi-schema check-qtest check-unit check check-clean
|
||||
.PHONY: check-block check-qapi-schema check-qtest check-unit check check-clean
|
||||
check-qapi-schema: $(patsubst %,check-%, $(check-qapi-schema-y)) check-tests/qapi-schema/doc-good.texi
|
||||
check-qtest: $(patsubst %,check-qtest-%, $(QTEST_TARGETS))
|
||||
check-block: $(patsubst %,check-%, $(check-block-y))
|
||||
|
||||
@@ -125,7 +125,7 @@ void qpci_init_pc(QPCIBusPC *qpci, QTestState *qts, QGuestAllocator *alloc)
|
||||
assert(qts);
|
||||
|
||||
/* tests can use pci-bus */
|
||||
qpci->bus.has_buggy_msi = FALSE;
|
||||
qpci->bus.has_buggy_msi = false;
|
||||
|
||||
qpci->bus.pio_readb = qpci_pc_pio_readb;
|
||||
qpci->bus.pio_readw = qpci_pc_pio_readw;
|
||||
|
||||
@@ -156,7 +156,7 @@ void qpci_init_spapr(QPCIBusSPAPR *qpci, QTestState *qts,
|
||||
assert(qts);
|
||||
|
||||
/* tests cannot use spapr, needs to be fixed first */
|
||||
qpci->bus.has_buggy_msi = TRUE;
|
||||
qpci->bus.has_buggy_msi = true;
|
||||
|
||||
qpci->alloc = alloc;
|
||||
|
||||
|
||||
@@ -77,6 +77,7 @@ static void add_edge(const char *source, const char *dest,
|
||||
{
|
||||
char *key;
|
||||
QOSGraphEdgeList *list = g_hash_table_lookup(edge_table, source);
|
||||
QOSGraphEdgeOptions def_opts = { };
|
||||
|
||||
if (!list) {
|
||||
list = g_new0(QOSGraphEdgeList, 1);
|
||||
@@ -85,7 +86,7 @@ static void add_edge(const char *source, const char *dest,
|
||||
}
|
||||
|
||||
if (!opts) {
|
||||
opts = &(QOSGraphEdgeOptions) { };
|
||||
opts = &def_opts;
|
||||
}
|
||||
|
||||
QOSGraphEdge *edge = g_new0(QOSGraphEdge, 1);
|
||||
@@ -590,9 +591,10 @@ void qos_add_test(const char *name, const char *interface,
|
||||
{
|
||||
QOSGraphNode *node;
|
||||
char *test_name = g_strdup_printf("%s-tests/%s", interface, name);;
|
||||
QOSGraphTestOptions def_opts = { };
|
||||
|
||||
if (!opts) {
|
||||
opts = &(QOSGraphTestOptions) { };
|
||||
opts = &def_opts;
|
||||
}
|
||||
node = create_node(test_name, QNODE_TEST);
|
||||
node->u.test.function = test_func;
|
||||
|
||||
@@ -28,6 +28,7 @@ nbd_unix_socket=$TEST_DIR/test_qemu_nbd_socket
|
||||
_cleanup()
|
||||
{
|
||||
_cleanup_test_img
|
||||
rm -f "$TEST_DIR/server.log"
|
||||
nbd_server_stop
|
||||
}
|
||||
trap "_cleanup; exit \$status" 0 1 2 3 15
|
||||
@@ -69,12 +70,13 @@ echo
|
||||
|
||||
# Intentionally omit '-f' to force image probing, which in turn forces
|
||||
# sector alignment, here at the server.
|
||||
nbd_server_start_unix_socket "$TEST_IMG_FILE"
|
||||
nbd_server_start_unix_socket "$TEST_IMG_FILE" 2> "$TEST_DIR/server.log"
|
||||
|
||||
$QEMU_NBD_PROG --list -k $nbd_unix_socket | grep '\(size\|min\)'
|
||||
$QEMU_IMG map -f raw --output=json "$TEST_IMG" | _filter_qemu_img_map
|
||||
$QEMU_IO -f raw -c map "$TEST_IMG"
|
||||
nbd_server_stop
|
||||
cat "$TEST_DIR/server.log" | _filter_testdir
|
||||
|
||||
echo
|
||||
echo "=== Exporting unaligned raw image, forced client sector alignment ==="
|
||||
|
||||
@@ -10,13 +10,13 @@ QA output created by 241
|
||||
|
||||
=== Exporting unaligned raw image, forced server sector alignment ===
|
||||
|
||||
WARNING: Image format was not specified for '/home/eblake/qemu/tests/qemu-iotests/scratch/t.raw' and probing guessed raw.
|
||||
Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
|
||||
Specify the 'raw' format explicitly to remove the restrictions.
|
||||
size: 1024
|
||||
min block: 512
|
||||
[{ "start": 0, "length": 1024, "depth": 0, "zero": false, "data": true, "offset": OFFSET}]
|
||||
1 KiB (0x400) bytes allocated at offset 0 bytes (0x0)
|
||||
WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw.
|
||||
Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
|
||||
Specify the 'raw' format explicitly to remove the restrictions.
|
||||
|
||||
=== Exporting unaligned raw image, forced client sector alignment ===
|
||||
|
||||
|
||||
@@ -209,6 +209,12 @@ class TestBlockdevReopen(iotests.QMPTestCase):
|
||||
|
||||
# Reopen an image several times changing some of its options
|
||||
def test_reopen(self):
|
||||
# Check whether the filesystem supports O_DIRECT
|
||||
if 'O_DIRECT' in qemu_io('-f', 'raw', '-t', 'none', '-c', 'quit', hd_path[0]):
|
||||
supports_direct = False
|
||||
else:
|
||||
supports_direct = True
|
||||
|
||||
# Open the hd1 image passing all backing options
|
||||
opts = hd_opts(1)
|
||||
opts['backing'] = hd_opts(0)
|
||||
@@ -231,9 +237,9 @@ class TestBlockdevReopen(iotests.QMPTestCase):
|
||||
self.assert_qmp(self.get_node('hd1'), 'cache/writeback', True)
|
||||
self.assert_qmp(self.get_node('hd1'), 'cache/direct', False)
|
||||
self.assert_qmp(self.get_node('hd1'), 'cache/no-flush', False)
|
||||
self.reopen(opts, {'cache': { 'direct': True, 'no-flush': True }})
|
||||
self.reopen(opts, {'cache': { 'direct': supports_direct, 'no-flush': True }})
|
||||
self.assert_qmp(self.get_node('hd1'), 'cache/writeback', True)
|
||||
self.assert_qmp(self.get_node('hd1'), 'cache/direct', True)
|
||||
self.assert_qmp(self.get_node('hd1'), 'cache/direct', supports_direct)
|
||||
self.assert_qmp(self.get_node('hd1'), 'cache/no-flush', True)
|
||||
|
||||
# Reopen again with the original options
|
||||
|
||||
@@ -31,6 +31,7 @@ static const char *hmp_cmds[] = {
|
||||
"cpu 0",
|
||||
"device_add ?",
|
||||
"device_add usb-mouse,id=mouse1",
|
||||
"drive_add ignored format=help",
|
||||
"mouse_button 7",
|
||||
"mouse_move 10 10",
|
||||
"mouse_button 0",
|
||||
|
||||
+2
-2
@@ -453,8 +453,8 @@ static uint16_t get_ucs(wchar_t wch, iconv_t conv)
|
||||
swch = sizeof(wch);
|
||||
|
||||
if (iconv(conv, &pwch, &swch, &pch, &sch) == (size_t) -1) {
|
||||
fprintf(stderr, "Could not convert 0x%02x from WCHAR_T to UCS-2: %s\n",
|
||||
wch, strerror(errno));
|
||||
fprintf(stderr, "Could not convert 0x%02lx from WCHAR_T to UCS-2: %s\n",
|
||||
(unsigned long)wch, strerror(errno));
|
||||
return 0xFFFD;
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user