Compare commits
58 Commits
pull-input
...
v1.4.1
Author | SHA1 | Date | |
---|---|---|---|
|
57105f7480 | ||
|
6e8865313f | ||
|
6d0b135a98 | ||
|
d89f9ba43b | ||
|
46f9071a23 | ||
|
f85e082a36 | ||
|
da78a1bc7a | ||
|
2b92aa36d1 | ||
|
e4cce2d3e9 | ||
|
d15b1aa30c | ||
|
65fe29ec00 | ||
|
888e036eb4 | ||
|
d019dd928c | ||
|
dac077f0e6 | ||
|
b09a673164 | ||
|
79a4dd4085 | ||
|
57e929c19c | ||
|
27c71355fb | ||
|
283b7de6a5 | ||
|
a1cb89f3fe | ||
|
68f9df5990 | ||
|
0135796271 | ||
|
799a34a48b | ||
|
8378910554 | ||
|
7a238b9fbd | ||
|
02493ee490 | ||
|
7d47b243d6 | ||
|
02ea844746 | ||
|
0fcf00b55c | ||
|
5610ef5863 | ||
|
7a687aed28 | ||
|
b91aee5810 | ||
|
e09b99b54f | ||
|
611c7f2c3a | ||
|
4e4566ce78 | ||
|
43e00611bc | ||
|
3c3de7c6b4 | ||
|
b0da310a69 | ||
|
d26efd2d39 | ||
|
f305d504ab | ||
|
d3652a1b28 | ||
|
51943504d5 | ||
|
4d1cdb9efd | ||
|
c3b81e01b8 | ||
|
99b1f39bd2 | ||
|
f23ab037c7 | ||
|
0c918dd600 | ||
|
a8b090ef08 | ||
|
4a38944326 | ||
|
b7ff1a7a00 | ||
|
d49fed4c55 | ||
|
cebb8ebe41 | ||
|
3b39a11cde | ||
|
ec9f828341 | ||
|
332e93417a | ||
|
e6b795f34e | ||
|
51968b8503 | ||
|
80d8b5da48 |
@@ -350,7 +350,7 @@ static int nbd_establish_connection(BlockDriverState *bs)
|
||||
|
||||
/* Now that we're connected, set the socket to be non-blocking and
|
||||
* kick the reply mechanism. */
|
||||
socket_set_nonblock(sock);
|
||||
qemu_set_nonblock(sock);
|
||||
qemu_aio_set_fd_handler(sock, nbd_reply_ready, NULL,
|
||||
nbd_have_request, s);
|
||||
|
||||
|
@@ -454,6 +454,9 @@ int qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset,
|
||||
*cluster_offset &= L2E_COMPRESSED_OFFSET_SIZE_MASK;
|
||||
break;
|
||||
case QCOW2_CLUSTER_ZERO:
|
||||
if (s->qcow_version < 3) {
|
||||
return -EIO;
|
||||
}
|
||||
c = count_contiguous_clusters(nb_clusters, s->cluster_size,
|
||||
&l2_table[l2_index], 0,
|
||||
QCOW_OFLAG_COMPRESSED | QCOW_OFLAG_ZERO);
|
||||
|
@@ -201,7 +201,10 @@ static int alloc_refcount_block(BlockDriverState *bs,
|
||||
*refcount_block = NULL;
|
||||
|
||||
/* We write to the refcount table, so we might depend on L2 tables */
|
||||
qcow2_cache_flush(bs, s->l2_table_cache);
|
||||
ret = qcow2_cache_flush(bs, s->l2_table_cache);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Allocate the refcount block itself and mark it as used */
|
||||
int64_t new_block = alloc_clusters_noref(bs, s->cluster_size);
|
||||
@@ -237,7 +240,10 @@ static int alloc_refcount_block(BlockDriverState *bs,
|
||||
goto fail_block;
|
||||
}
|
||||
|
||||
bdrv_flush(bs->file);
|
||||
ret = qcow2_cache_flush(bs, s->refcount_block_cache);
|
||||
if (ret < 0) {
|
||||
goto fail_block;
|
||||
}
|
||||
|
||||
/* Initialize the new refcount block only after updating its refcount,
|
||||
* update_refcount uses the refcount cache itself */
|
||||
|
@@ -180,11 +180,14 @@ static int qcow2_write_snapshots(BlockDriverState *bs)
|
||||
|
||||
/* Allocate space for the new snapshot list */
|
||||
snapshots_offset = qcow2_alloc_clusters(bs, snapshots_size);
|
||||
bdrv_flush(bs->file);
|
||||
offset = snapshots_offset;
|
||||
if (offset < 0) {
|
||||
return offset;
|
||||
}
|
||||
ret = bdrv_flush(bs);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Write all snapshots to the new list */
|
||||
for(i = 0; i < s->nb_snapshots; i++) {
|
||||
|
@@ -584,7 +584,7 @@ static int coroutine_fn qcow2_co_is_allocated(BlockDriverState *bs,
|
||||
*pnum = 0;
|
||||
}
|
||||
|
||||
return (cluster_offset != 0);
|
||||
return (cluster_offset != 0) || (ret == QCOW2_CLUSTER_ZERO);
|
||||
}
|
||||
|
||||
/* handle reading after the end of the backing file */
|
||||
@@ -665,10 +665,6 @@ static coroutine_fn int qcow2_co_readv(BlockDriverState *bs, int64_t sector_num,
|
||||
break;
|
||||
|
||||
case QCOW2_CLUSTER_ZERO:
|
||||
if (s->qcow_version < 3) {
|
||||
ret = -EIO;
|
||||
goto fail;
|
||||
}
|
||||
qemu_iovec_memset(&hd_qiov, 0, 0, 512 * cur_nr_sectors);
|
||||
break;
|
||||
|
||||
|
@@ -549,7 +549,7 @@ static coroutine_fn void do_co_req(void *opaque)
|
||||
co = qemu_coroutine_self();
|
||||
qemu_aio_set_fd_handler(sockfd, NULL, restart_co_req, NULL, co);
|
||||
|
||||
socket_set_block(sockfd);
|
||||
qemu_set_block(sockfd);
|
||||
ret = send_co_req(sockfd, hdr, data, wlen);
|
||||
if (ret < 0) {
|
||||
goto out;
|
||||
@@ -579,7 +579,7 @@ static coroutine_fn void do_co_req(void *opaque)
|
||||
ret = 0;
|
||||
out:
|
||||
qemu_aio_set_fd_handler(sockfd, NULL, NULL, NULL, NULL);
|
||||
socket_set_nonblock(sockfd);
|
||||
qemu_set_nonblock(sockfd);
|
||||
|
||||
srco->ret = ret;
|
||||
srco->finished = true;
|
||||
@@ -812,7 +812,7 @@ static int get_sheep_fd(BDRVSheepdogState *s)
|
||||
return fd;
|
||||
}
|
||||
|
||||
socket_set_nonblock(fd);
|
||||
qemu_set_nonblock(fd);
|
||||
|
||||
ret = set_nodelay(fd);
|
||||
if (ret) {
|
||||
|
@@ -1043,6 +1043,9 @@ void qmp_block_resize(const char *device, int64_t size, Error **errp)
|
||||
return;
|
||||
}
|
||||
|
||||
/* complete all in-flight operations before resizing the device */
|
||||
bdrv_drain_all();
|
||||
|
||||
switch (bdrv_truncate(bs, size)) {
|
||||
case 0:
|
||||
break;
|
||||
|
10
configure
vendored
10
configure
vendored
@@ -2759,7 +2759,13 @@ if test "$libiscsi" != "no" ; then
|
||||
#include <iscsi/iscsi.h>
|
||||
int main(void) { iscsi_unmap_sync(NULL,0,0,0,NULL,0); return 0; }
|
||||
EOF
|
||||
if compile_prog "" "-liscsi" ; then
|
||||
if $pkg_config --atleast-version=1.7.0 libiscsi --modversion >/dev/null 2>&1; then
|
||||
libiscsi="yes"
|
||||
libiscsi_cflags=$($pkg_config --cflags libiscsi 2>/dev/null)
|
||||
libiscsi_libs=$($pkg_config --libs libiscsi 2>/dev/null)
|
||||
CFLAGS="$CFLAGS $libiscsi_cflags"
|
||||
LIBS="$LIBS $libiscsi_libs"
|
||||
elif compile_prog "" "-liscsi" ; then
|
||||
libiscsi="yes"
|
||||
LIBS="$LIBS -liscsi"
|
||||
else
|
||||
@@ -2827,7 +2833,7 @@ EOF
|
||||
spice_cflags=$($pkg_config --cflags spice-protocol spice-server 2>/dev/null)
|
||||
spice_libs=$($pkg_config --libs spice-protocol spice-server 2>/dev/null)
|
||||
if $pkg_config --atleast-version=0.12.0 spice-server >/dev/null 2>&1 && \
|
||||
$pkg_config --atleast-version=0.12.2 spice-protocol > /dev/null 2>&1 && \
|
||||
$pkg_config --atleast-version=0.12.3 spice-protocol > /dev/null 2>&1 && \
|
||||
compile_prog "$spice_cflags" "$spice_libs" ; then
|
||||
spice="yes"
|
||||
libs_softmmu="$libs_softmmu $spice_libs"
|
||||
|
@@ -472,8 +472,9 @@ static const MemoryRegionOps acpi_pm_cnt_ops = {
|
||||
.endianness = DEVICE_LITTLE_ENDIAN,
|
||||
};
|
||||
|
||||
void acpi_pm1_cnt_init(ACPIREGS *ar, MemoryRegion *parent)
|
||||
void acpi_pm1_cnt_init(ACPIREGS *ar, MemoryRegion *parent, uint8_t s4_val)
|
||||
{
|
||||
ar->pm1.cnt.s4_val = s4_val;
|
||||
ar->wakeup.notify = acpi_notify_wakeup;
|
||||
qemu_register_wakeup_notifier(&ar->wakeup);
|
||||
memory_region_init_io(&ar->pm1.cnt.io, &acpi_pm_cnt_ops, ar, "acpi-cnt", 2);
|
||||
|
@@ -142,7 +142,7 @@ void acpi_pm1_evt_init(ACPIREGS *ar, acpi_update_sci_fn update_sci,
|
||||
MemoryRegion *parent);
|
||||
|
||||
/* PM1a_CNT: piix and ich9 don't implement PM1b CNT. */
|
||||
void acpi_pm1_cnt_init(ACPIREGS *ar, MemoryRegion *parent);
|
||||
void acpi_pm1_cnt_init(ACPIREGS *ar, MemoryRegion *parent, uint8_t s4_val);
|
||||
void acpi_pm1_cnt_update(ACPIREGS *ar,
|
||||
bool sci_enable, bool sci_disable);
|
||||
void acpi_pm1_cnt_reset(ACPIREGS *ar);
|
||||
|
@@ -212,7 +212,7 @@ void ich9_pm_init(PCIDevice *lpc_pci, ICH9LPCPMRegs *pm,
|
||||
|
||||
acpi_pm_tmr_init(&pm->acpi_regs, ich9_pm_update_sci_fn, &pm->io);
|
||||
acpi_pm1_evt_init(&pm->acpi_regs, ich9_pm_update_sci_fn, &pm->io);
|
||||
acpi_pm1_cnt_init(&pm->acpi_regs, &pm->io);
|
||||
acpi_pm1_cnt_init(&pm->acpi_regs, &pm->io, 2);
|
||||
|
||||
acpi_gpe_init(&pm->acpi_regs, ICH9_PMIO_GPE0_LEN);
|
||||
memory_region_init_io(&pm->io_gpe, &ich9_gpe_ops, pm, "apci-gpe0",
|
||||
|
@@ -418,7 +418,7 @@ static int piix4_pm_initfn(PCIDevice *dev)
|
||||
|
||||
acpi_pm_tmr_init(&s->ar, pm_tmr_timer, &s->io);
|
||||
acpi_pm1_evt_init(&s->ar, pm_tmr_timer, &s->io);
|
||||
acpi_pm1_cnt_init(&s->ar, &s->io);
|
||||
acpi_pm1_cnt_init(&s->ar, &s->io, s->s4_val);
|
||||
acpi_gpe_init(&s->ar, GPE_LEN);
|
||||
|
||||
s->powerdown_notifier.notify = piix4_pm_powerdown_req;
|
||||
|
@@ -188,7 +188,7 @@ static int macio_newworld_initfn(PCIDevice *d)
|
||||
sysbus_dev = SYS_BUS_DEVICE(&ns->ide[1]);
|
||||
sysbus_connect_irq(sysbus_dev, 0, ns->irqs[3]);
|
||||
sysbus_connect_irq(sysbus_dev, 1, ns->irqs[4]);
|
||||
macio_ide_register_dma(&ns->ide[0], s->dbdma, 0x1a);
|
||||
macio_ide_register_dma(&ns->ide[1], s->dbdma, 0x1a);
|
||||
ret = qdev_init(DEVICE(&ns->ide[1]));
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
|
@@ -118,7 +118,8 @@ static void qxl_render_update_area_unlocked(PCIQXLDevice *qxl)
|
||||
qxl->guest_primary.surface.height,
|
||||
qxl->guest_primary.bits_pp,
|
||||
qxl->guest_primary.abs_stride,
|
||||
qxl->guest_primary.data);
|
||||
qxl->guest_primary.data,
|
||||
false);
|
||||
} else {
|
||||
qemu_resize_displaysurface(vga->ds,
|
||||
qxl->guest_primary.surface.width,
|
||||
|
2
hw/qxl.c
2
hw/qxl.c
@@ -1075,8 +1075,8 @@ static void qxl_enter_vga_mode(PCIQXLDevice *d)
|
||||
trace_qxl_enter_vga_mode(d->id);
|
||||
qemu_spice_create_host_primary(&d->ssd);
|
||||
d->mode = QXL_MODE_VGA;
|
||||
dpy_gfx_resize(d->ssd.ds);
|
||||
vga_dirty_log_start(&d->vga);
|
||||
vga_hw_update();
|
||||
}
|
||||
|
||||
static void qxl_exit_vga_mode(PCIQXLDevice *d)
|
||||
|
@@ -402,6 +402,7 @@ static const VirtIOBindings virtio_s390_bindings = {
|
||||
|
||||
static Property s390_virtio_net_properties[] = {
|
||||
DEFINE_NIC_PROPERTIES(VirtIOS390Device, nic),
|
||||
DEFINE_VIRTIO_NET_FEATURES(VirtIOS390Device, host_features),
|
||||
DEFINE_PROP_UINT32("x-txtimer", VirtIOS390Device,
|
||||
net.txtimer, TX_TIMER_INTERVAL),
|
||||
DEFINE_PROP_INT32("x-txburst", VirtIOS390Device,
|
||||
|
@@ -31,6 +31,9 @@ static int virtio_ccw_hcall_notify(const uint64_t *args)
|
||||
if (!sch || !css_subch_visible(sch)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
if (queue >= VIRTIO_PCI_QUEUE_MAX) {
|
||||
return -EINVAL;
|
||||
}
|
||||
virtio_queue_notify(virtio_ccw_get_vdev(sch), queue);
|
||||
return 0;
|
||||
|
||||
|
@@ -1508,6 +1508,10 @@ void scsi_req_unref(SCSIRequest *req)
|
||||
will start the next chunk or complete the command. */
|
||||
void scsi_req_continue(SCSIRequest *req)
|
||||
{
|
||||
if (req->io_canceled) {
|
||||
trace_scsi_req_continue_canceled(req->dev->id, req->lun, req->tag);
|
||||
return;
|
||||
}
|
||||
trace_scsi_req_continue(req->dev->id, req->lun, req->tag);
|
||||
if (req->cmd.mode == SCSI_XFER_TO_DEV) {
|
||||
req->ops->write_data(req);
|
||||
|
@@ -176,6 +176,9 @@ static void scsi_aio_complete(void *opaque, int ret)
|
||||
assert(r->req.aiocb != NULL);
|
||||
r->req.aiocb = NULL;
|
||||
bdrv_acct_done(s->qdev.conf.bs, &r->acct);
|
||||
if (r->req.io_canceled) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
if (scsi_handle_rw_error(r, -ret)) {
|
||||
@@ -221,6 +224,10 @@ static void scsi_write_do_fua(SCSIDiskReq *r)
|
||||
{
|
||||
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
|
||||
|
||||
if (r->req.io_canceled) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (scsi_is_cmd_fua(&r->req.cmd)) {
|
||||
bdrv_acct_start(s->qdev.conf.bs, &r->acct, 0, BDRV_ACCT_FLUSH);
|
||||
r->req.aiocb = bdrv_aio_flush(s->qdev.conf.bs, scsi_aio_complete, r);
|
||||
@@ -228,6 +235,8 @@ static void scsi_write_do_fua(SCSIDiskReq *r)
|
||||
}
|
||||
|
||||
scsi_req_complete(&r->req, GOOD);
|
||||
|
||||
done:
|
||||
if (!r->req.io_canceled) {
|
||||
scsi_req_unref(&r->req);
|
||||
}
|
||||
@@ -241,6 +250,9 @@ static void scsi_dma_complete(void *opaque, int ret)
|
||||
assert(r->req.aiocb != NULL);
|
||||
r->req.aiocb = NULL;
|
||||
bdrv_acct_done(s->qdev.conf.bs, &r->acct);
|
||||
if (r->req.io_canceled) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
if (scsi_handle_rw_error(r, -ret)) {
|
||||
@@ -272,6 +284,9 @@ static void scsi_read_complete(void * opaque, int ret)
|
||||
assert(r->req.aiocb != NULL);
|
||||
r->req.aiocb = NULL;
|
||||
bdrv_acct_done(s->qdev.conf.bs, &r->acct);
|
||||
if (r->req.io_canceled) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
if (scsi_handle_rw_error(r, -ret)) {
|
||||
@@ -303,6 +318,9 @@ static void scsi_do_read(void *opaque, int ret)
|
||||
r->req.aiocb = NULL;
|
||||
bdrv_acct_done(s->qdev.conf.bs, &r->acct);
|
||||
}
|
||||
if (r->req.io_canceled) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
if (scsi_handle_rw_error(r, -ret)) {
|
||||
@@ -310,10 +328,6 @@ static void scsi_do_read(void *opaque, int ret)
|
||||
}
|
||||
}
|
||||
|
||||
if (r->req.io_canceled) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* The request is used as the AIO opaque value, so add a ref. */
|
||||
scsi_req_ref(&r->req);
|
||||
|
||||
@@ -421,6 +435,9 @@ static void scsi_write_complete(void * opaque, int ret)
|
||||
r->req.aiocb = NULL;
|
||||
bdrv_acct_done(s->qdev.conf.bs, &r->acct);
|
||||
}
|
||||
if (r->req.io_canceled) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
if (scsi_handle_rw_error(r, -ret)) {
|
||||
@@ -1476,13 +1493,17 @@ static void scsi_unmap_complete(void *opaque, int ret)
|
||||
uint32_t nb_sectors;
|
||||
|
||||
r->req.aiocb = NULL;
|
||||
if (r->req.io_canceled) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
if (scsi_handle_rw_error(r, -ret)) {
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
if (data->count > 0 && !r->req.io_canceled) {
|
||||
if (data->count > 0) {
|
||||
sector_num = ldq_be_p(&data->inbuf[0]);
|
||||
nb_sectors = ldl_be_p(&data->inbuf[8]) & 0xffffffffULL;
|
||||
if (!check_lba_range(s, sector_num, nb_sectors)) {
|
||||
@@ -1499,10 +1520,9 @@ static void scsi_unmap_complete(void *opaque, int ret)
|
||||
return;
|
||||
}
|
||||
|
||||
scsi_req_complete(&r->req, GOOD);
|
||||
|
||||
done:
|
||||
if (data->count == 0) {
|
||||
scsi_req_complete(&r->req, GOOD);
|
||||
}
|
||||
if (!r->req.io_canceled) {
|
||||
scsi_req_unref(&r->req);
|
||||
}
|
||||
|
@@ -260,6 +260,7 @@ static void *spapr_create_fdt_skel(const char *cpu_model,
|
||||
_FDT((fdt_begin_node(fdt, "")));
|
||||
_FDT((fdt_property_string(fdt, "device_type", "chrp")));
|
||||
_FDT((fdt_property_string(fdt, "model", "IBM pSeries (emulated by qemu)")));
|
||||
_FDT((fdt_property_string(fdt, "compatible", "qemu,pseries")));
|
||||
|
||||
_FDT((fdt_property_cell(fdt, "#address-cells", 0x2)));
|
||||
_FDT((fdt_property_cell(fdt, "#size-cells", 0x2)));
|
||||
|
@@ -175,11 +175,19 @@ static ssize_t spapr_vlan_receive(NetClientState *nc, const uint8_t *buf,
|
||||
return size;
|
||||
}
|
||||
|
||||
static void spapr_vlan_cleanup(NetClientState *nc)
|
||||
{
|
||||
VIOsPAPRVLANDevice *dev = qemu_get_nic_opaque(nc);
|
||||
|
||||
dev->nic = NULL;
|
||||
}
|
||||
|
||||
static NetClientInfo net_spapr_vlan_info = {
|
||||
.type = NET_CLIENT_OPTIONS_KIND_NIC,
|
||||
.size = sizeof(NICState),
|
||||
.can_receive = spapr_vlan_can_receive,
|
||||
.receive = spapr_vlan_receive,
|
||||
.cleanup = spapr_vlan_cleanup,
|
||||
};
|
||||
|
||||
static void spapr_vlan_reset(VIOsPAPRDevice *sdev)
|
||||
|
@@ -236,7 +236,7 @@ static const USBDescDevice desc_device_tablet2 = {
|
||||
.bNumInterfaces = 1,
|
||||
.bConfigurationValue = 1,
|
||||
.iConfiguration = STR_CONFIG_TABLET,
|
||||
.bmAttributes = 0xa0,
|
||||
.bmAttributes = 0x80,
|
||||
.bMaxPower = 50,
|
||||
.nif = 1,
|
||||
.ifs = &desc_iface_tablet2,
|
||||
|
18
hw/vga.c
18
hw/vga.c
@@ -1643,6 +1643,11 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
|
||||
uint8_t *d;
|
||||
uint32_t v, addr1, addr;
|
||||
vga_draw_line_func *vga_draw_line;
|
||||
#if defined(HOST_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
|
||||
static const bool byteswap = false;
|
||||
#else
|
||||
static const bool byteswap = true;
|
||||
#endif
|
||||
|
||||
full_update |= update_basic_params(s);
|
||||
|
||||
@@ -1685,18 +1690,11 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
|
||||
disp_width != s->last_width ||
|
||||
height != s->last_height ||
|
||||
s->last_depth != depth) {
|
||||
#if defined(HOST_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
|
||||
if (depth == 16 || depth == 32) {
|
||||
#else
|
||||
if (depth == 32) {
|
||||
#endif
|
||||
if (depth == 32 || (depth == 16 && !byteswap)) {
|
||||
qemu_free_displaysurface(s->ds);
|
||||
s->ds->surface = qemu_create_displaysurface_from(disp_width, height, depth,
|
||||
s->line_offset,
|
||||
s->vram_ptr + (s->start_addr * 4));
|
||||
#if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
|
||||
s->ds->surface->pf = qemu_different_endianness_pixelformat(depth);
|
||||
#endif
|
||||
s->vram_ptr + (s->start_addr * 4), byteswap);
|
||||
dpy_gfx_resize(s->ds);
|
||||
} else {
|
||||
qemu_console_resize(s->ds, disp_width, height);
|
||||
@@ -1715,7 +1713,7 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
|
||||
s->ds->surface = qemu_create_displaysurface_from(disp_width,
|
||||
height, depth,
|
||||
s->line_offset,
|
||||
s->vram_ptr + (s->start_addr * 4));
|
||||
s->vram_ptr + (s->start_addr * 4), byteswap);
|
||||
dpy_gfx_setdata(s->ds);
|
||||
}
|
||||
|
||||
|
@@ -36,6 +36,7 @@ typedef struct VirtIOBlock
|
||||
VirtIOBlkConf *blk;
|
||||
unsigned short sector_mask;
|
||||
DeviceState *qdev;
|
||||
VMChangeStateEntry *change;
|
||||
#ifdef CONFIG_VIRTIO_BLK_DATA_PLANE
|
||||
VirtIOBlockDataPlane *dataplane;
|
||||
#endif
|
||||
@@ -681,7 +682,7 @@ VirtIODevice *virtio_blk_init(DeviceState *dev, VirtIOBlkConf *blk)
|
||||
}
|
||||
#endif
|
||||
|
||||
qemu_add_vm_change_state_handler(virtio_blk_dma_restart_cb, s);
|
||||
s->change = qemu_add_vm_change_state_handler(virtio_blk_dma_restart_cb, s);
|
||||
s->qdev = dev;
|
||||
register_savevm(dev, "virtio-blk", virtio_blk_id++, 2,
|
||||
virtio_blk_save, virtio_blk_load, s);
|
||||
@@ -702,6 +703,7 @@ void virtio_blk_exit(VirtIODevice *vdev)
|
||||
virtio_blk_data_plane_destroy(s->dataplane);
|
||||
s->dataplane = NULL;
|
||||
#endif
|
||||
qemu_del_vm_change_state_handler(s->change);
|
||||
unregister_savevm(s->qdev, "virtio-blk", s);
|
||||
blockdev_mark_auto_del(s->bs);
|
||||
virtio_cleanup(vdev);
|
||||
|
@@ -44,7 +44,7 @@ typedef struct VirtIONet
|
||||
VirtIODevice vdev;
|
||||
uint8_t mac[ETH_ALEN];
|
||||
uint16_t status;
|
||||
VirtIONetQueue vqs[MAX_QUEUE_NUM];
|
||||
VirtIONetQueue *vqs;
|
||||
VirtQueue *ctrl_vq;
|
||||
NICState *nic;
|
||||
uint32_t tx_timeout;
|
||||
@@ -1326,8 +1326,9 @@ VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf,
|
||||
n->vdev.set_status = virtio_net_set_status;
|
||||
n->vdev.guest_notifier_mask = virtio_net_guest_notifier_mask;
|
||||
n->vdev.guest_notifier_pending = virtio_net_guest_notifier_pending;
|
||||
n->max_queues = MAX(conf->queues, 1);
|
||||
n->vqs = g_malloc0(sizeof(VirtIONetQueue) * n->max_queues);
|
||||
n->vqs[0].rx_vq = virtio_add_queue(&n->vdev, 256, virtio_net_handle_rx);
|
||||
n->max_queues = conf->queues;
|
||||
n->curr_queues = 1;
|
||||
n->vqs[0].n = n;
|
||||
n->tx_timeout = net->txtimer;
|
||||
@@ -1412,6 +1413,7 @@ void virtio_net_exit(VirtIODevice *vdev)
|
||||
}
|
||||
}
|
||||
|
||||
g_free(n->vqs);
|
||||
qemu_del_nic(n->nic);
|
||||
virtio_cleanup(&n->vdev);
|
||||
}
|
||||
|
@@ -1074,7 +1074,7 @@ static void vmsvga_screen_dump(void *opaque, const char *filename, bool cswitch,
|
||||
ds_get_height(s->vga.ds),
|
||||
32,
|
||||
ds_get_linesize(s->vga.ds),
|
||||
s->vga.vram_ptr);
|
||||
s->vga.vram_ptr, false);
|
||||
ppm_save(filename, ds, errp);
|
||||
g_free(ds);
|
||||
}
|
||||
|
@@ -362,7 +362,7 @@ static int vt82c686b_pm_initfn(PCIDevice *dev)
|
||||
|
||||
acpi_pm_tmr_init(&s->ar, pm_tmr_timer, &s->io);
|
||||
acpi_pm1_evt_init(&s->ar, pm_tmr_timer, &s->io);
|
||||
acpi_pm1_cnt_init(&s->ar, &s->io);
|
||||
acpi_pm1_cnt_init(&s->ar, &s->io, 2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@@ -756,7 +756,8 @@ static void xenfb_update(void *opaque)
|
||||
qemu_free_displaysurface(xenfb->c.ds);
|
||||
xenfb->c.ds->surface = qemu_create_displaysurface_from
|
||||
(xenfb->width, xenfb->height, xenfb->depth,
|
||||
xenfb->row_stride, xenfb->pixels + xenfb->offset);
|
||||
xenfb->row_stride, xenfb->pixels + xenfb->offset,
|
||||
false);
|
||||
break;
|
||||
default:
|
||||
/* we must convert stuff */
|
||||
|
@@ -72,7 +72,7 @@ struct NetClientState {
|
||||
};
|
||||
|
||||
typedef struct NICState {
|
||||
NetClientState ncs[MAX_QUEUE_NUM];
|
||||
NetClientState *ncs;
|
||||
NICConf *conf;
|
||||
void *opaque;
|
||||
bool peer_deleted;
|
||||
|
@@ -33,7 +33,7 @@
|
||||
#define cat(x,y) x ## y
|
||||
#define cat2(x,y) cat(x,y)
|
||||
#define QEMU_BUILD_BUG_ON(x) \
|
||||
typedef char cat2(qemu_build_bug_on__,__LINE__)[(x)?-1:1];
|
||||
typedef char cat2(qemu_build_bug_on__,__LINE__)[(x)?-1:1] __attribute__((unused));
|
||||
|
||||
#if defined __GNUC__
|
||||
# if !QEMU_GNUC_PREREQ(4, 4)
|
||||
|
@@ -34,8 +34,8 @@ int inet_aton(const char *cp, struct in_addr *ia);
|
||||
int qemu_socket(int domain, int type, int protocol);
|
||||
int qemu_accept(int s, struct sockaddr *addr, socklen_t *addrlen);
|
||||
int socket_set_cork(int fd, int v);
|
||||
void socket_set_block(int fd);
|
||||
void socket_set_nonblock(int fd);
|
||||
void qemu_set_block(int fd);
|
||||
void qemu_set_nonblock(int fd);
|
||||
int send_all(int fd, const void *buf, int len1);
|
||||
|
||||
/* callback function for nonblocking connect
|
||||
|
@@ -117,8 +117,7 @@ extern int use_rt_clock;
|
||||
|
||||
static inline int64_t get_clock(void)
|
||||
{
|
||||
#if defined(__linux__) || (defined(__FreeBSD__) && __FreeBSD_version >= 500000) \
|
||||
|| defined(__DragonFly__) || defined(__FreeBSD_kernel__)
|
||||
#ifdef CLOCK_MONOTONIC
|
||||
if (use_rt_clock) {
|
||||
struct timespec ts;
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
|
@@ -184,7 +184,8 @@ struct DisplayState {
|
||||
void register_displaystate(DisplayState *ds);
|
||||
DisplayState *get_displaystate(void);
|
||||
DisplaySurface* qemu_create_displaysurface_from(int width, int height, int bpp,
|
||||
int linesize, uint8_t *data);
|
||||
int linesize, uint8_t *data,
|
||||
bool byteswap);
|
||||
PixelFormat qemu_different_endianness_pixelformat(int bpp);
|
||||
PixelFormat qemu_default_pixelformat(int bpp);
|
||||
|
||||
|
@@ -1436,6 +1436,12 @@ if( cmd == val ) { \
|
||||
gemu_log("FUTEX_PRIVATE_FLAG|");
|
||||
cmd &= ~FUTEX_PRIVATE_FLAG;
|
||||
}
|
||||
#endif
|
||||
#ifdef FUTEX_CLOCK_REALTIME
|
||||
if (cmd & FUTEX_CLOCK_REALTIME) {
|
||||
gemu_log("FUTEX_CLOCK_REALTIME|");
|
||||
cmd &= ~FUTEX_CLOCK_REALTIME;
|
||||
}
|
||||
#endif
|
||||
print_op(FUTEX_WAIT)
|
||||
print_op(FUTEX_WAKE)
|
||||
|
@@ -1776,7 +1776,7 @@ static struct iovec *lock_iovec(int type, abi_ulong target_addr,
|
||||
errno = 0;
|
||||
return NULL;
|
||||
}
|
||||
if (count > IOV_MAX) {
|
||||
if (count < 0 || count > IOV_MAX) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
@@ -4920,6 +4920,7 @@ static int do_futex(target_ulong uaddr, int op, int val, target_ulong timeout,
|
||||
#endif
|
||||
switch (base_op) {
|
||||
case FUTEX_WAIT:
|
||||
case FUTEX_WAIT_BITSET:
|
||||
if (timeout) {
|
||||
pts = &ts;
|
||||
target_to_host_timespec(pts, timeout);
|
||||
@@ -4927,7 +4928,7 @@ static int do_futex(target_ulong uaddr, int op, int val, target_ulong timeout,
|
||||
pts = NULL;
|
||||
}
|
||||
return get_errno(sys_futex(g2h(uaddr), op, tswap32(val),
|
||||
pts, NULL, 0));
|
||||
pts, NULL, val3));
|
||||
case FUTEX_WAKE:
|
||||
return get_errno(sys_futex(g2h(uaddr), op, val, NULL, NULL, 0));
|
||||
case FUTEX_FD:
|
||||
@@ -8550,7 +8551,20 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
||||
|
||||
#ifdef TARGET_NR_set_robust_list
|
||||
case TARGET_NR_set_robust_list:
|
||||
goto unimplemented_nowarn;
|
||||
case TARGET_NR_get_robust_list:
|
||||
/* The ABI for supporting robust futexes has userspace pass
|
||||
* the kernel a pointer to a linked list which is updated by
|
||||
* userspace after the syscall; the list is walked by the kernel
|
||||
* when the thread exits. Since the linked list in QEMU guest
|
||||
* memory isn't a valid linked list for the host and we have
|
||||
* no way to reliably intercept the thread-death event, we can't
|
||||
* support these. Silently return ENOSYS so that guest userspace
|
||||
* falls back to a non-robust futex implementation (which should
|
||||
* be OK except in the corner case of the guest crashing while
|
||||
* holding a mutex that is shared with another process via
|
||||
* shared memory).
|
||||
*/
|
||||
goto unimplemented_nowarn;
|
||||
#endif
|
||||
|
||||
#if defined(TARGET_NR_utimensat) && defined(__NR_utimensat)
|
||||
|
@@ -60,7 +60,7 @@ static void tcp_wait_for_connect(int fd, void *opaque)
|
||||
} else {
|
||||
DPRINTF("migrate connect success\n");
|
||||
s->fd = fd;
|
||||
socket_set_block(s->fd);
|
||||
qemu_set_block(s->fd);
|
||||
migrate_fd_connect(s);
|
||||
}
|
||||
}
|
||||
|
@@ -60,7 +60,7 @@ static void unix_wait_for_connect(int fd, void *opaque)
|
||||
} else {
|
||||
DPRINTF("migrate connect success\n");
|
||||
s->fd = fd;
|
||||
socket_set_block(s->fd);
|
||||
qemu_set_block(s->fd);
|
||||
migrate_fd_connect(s);
|
||||
}
|
||||
}
|
||||
|
@@ -120,7 +120,7 @@ void process_incoming_migration(QEMUFile *f)
|
||||
int fd = qemu_get_fd(f);
|
||||
|
||||
assert(fd != -1);
|
||||
socket_set_nonblock(fd);
|
||||
qemu_set_nonblock(fd);
|
||||
qemu_coroutine_enter(co, f);
|
||||
}
|
||||
|
||||
|
8
nbd.c
8
nbd.c
@@ -393,7 +393,7 @@ static int nbd_send_negotiate(NBDClient *client)
|
||||
[28 .. 151] reserved (0)
|
||||
*/
|
||||
|
||||
socket_set_block(csock);
|
||||
qemu_set_block(csock);
|
||||
rc = -EINVAL;
|
||||
|
||||
TRACE("Beginning negotiation.");
|
||||
@@ -436,7 +436,7 @@ static int nbd_send_negotiate(NBDClient *client)
|
||||
TRACE("Negotiation succeeded.");
|
||||
rc = 0;
|
||||
fail:
|
||||
socket_set_nonblock(csock);
|
||||
qemu_set_nonblock(csock);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -450,7 +450,7 @@ int nbd_receive_negotiate(int csock, const char *name, uint32_t *flags,
|
||||
|
||||
TRACE("Receiving negotiation.");
|
||||
|
||||
socket_set_block(csock);
|
||||
qemu_set_block(csock);
|
||||
rc = -EINVAL;
|
||||
|
||||
if (read_sync(csock, buf, 8) != 8) {
|
||||
@@ -565,7 +565,7 @@ int nbd_receive_negotiate(int csock, const char *name, uint32_t *flags,
|
||||
rc = 0;
|
||||
|
||||
fail:
|
||||
socket_set_nonblock(csock);
|
||||
qemu_set_nonblock(csock);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
19
net/net.c
19
net/net.c
@@ -235,23 +235,20 @@ NICState *qemu_new_nic(NetClientInfo *info,
|
||||
const char *name,
|
||||
void *opaque)
|
||||
{
|
||||
NetClientState *nc;
|
||||
NetClientState **peers = conf->peers.ncs;
|
||||
NICState *nic;
|
||||
int i;
|
||||
int i, queues = MAX(1, conf->queues);
|
||||
|
||||
assert(info->type == NET_CLIENT_OPTIONS_KIND_NIC);
|
||||
assert(info->size >= sizeof(NICState));
|
||||
|
||||
nc = qemu_new_net_client(info, peers[0], model, name);
|
||||
nc->queue_index = 0;
|
||||
|
||||
nic = qemu_get_nic(nc);
|
||||
nic = g_malloc0(info->size + sizeof(NetClientState) * queues);
|
||||
nic->ncs = (void *)nic + info->size;
|
||||
nic->conf = conf;
|
||||
nic->opaque = opaque;
|
||||
|
||||
for (i = 1; i < conf->queues; i++) {
|
||||
qemu_net_client_setup(&nic->ncs[i], info, peers[i], model, nc->name,
|
||||
for (i = 0; i < queues; i++) {
|
||||
qemu_net_client_setup(&nic->ncs[i], info, peers[i], model, name,
|
||||
NULL);
|
||||
nic->ncs[i].queue_index = i;
|
||||
}
|
||||
@@ -261,7 +258,7 @@ NICState *qemu_new_nic(NetClientInfo *info,
|
||||
|
||||
NetClientState *qemu_get_subqueue(NICState *nic, int queue_index)
|
||||
{
|
||||
return &nic->ncs[queue_index];
|
||||
return nic->ncs + queue_index;
|
||||
}
|
||||
|
||||
NetClientState *qemu_get_queue(NICState *nic)
|
||||
@@ -273,7 +270,7 @@ NICState *qemu_get_nic(NetClientState *nc)
|
||||
{
|
||||
NetClientState *nc0 = nc - nc->queue_index;
|
||||
|
||||
return DO_UPCAST(NICState, ncs[0], nc0);
|
||||
return (NICState *)((void *)nc0 - nc->info->size);
|
||||
}
|
||||
|
||||
void *qemu_get_nic_opaque(NetClientState *nc)
|
||||
@@ -368,6 +365,8 @@ void qemu_del_nic(NICState *nic)
|
||||
qemu_cleanup_net_client(nc);
|
||||
qemu_free_net_client(nc);
|
||||
}
|
||||
|
||||
g_free(nic);
|
||||
}
|
||||
|
||||
void qemu_foreach_nic(qemu_nic_foreach func, void *opaque)
|
||||
|
13
net/socket.c
13
net/socket.c
@@ -309,7 +309,7 @@ static int net_socket_mcast_create(struct sockaddr_in *mcastaddr, struct in_addr
|
||||
}
|
||||
}
|
||||
|
||||
socket_set_nonblock(fd);
|
||||
qemu_set_nonblock(fd);
|
||||
return fd;
|
||||
fail:
|
||||
if (fd >= 0)
|
||||
@@ -517,7 +517,7 @@ static int net_socket_listen_init(NetClientState *peer,
|
||||
perror("socket");
|
||||
return -1;
|
||||
}
|
||||
socket_set_nonblock(fd);
|
||||
qemu_set_nonblock(fd);
|
||||
|
||||
/* allow fast reuse */
|
||||
val = 1;
|
||||
@@ -563,7 +563,7 @@ static int net_socket_connect_init(NetClientState *peer,
|
||||
perror("socket");
|
||||
return -1;
|
||||
}
|
||||
socket_set_nonblock(fd);
|
||||
qemu_set_nonblock(fd);
|
||||
|
||||
connected = 0;
|
||||
for(;;) {
|
||||
@@ -672,6 +672,7 @@ static int net_socket_udp_init(NetClientState *peer,
|
||||
closesocket(fd);
|
||||
return -1;
|
||||
}
|
||||
qemu_set_nonblock(fd);
|
||||
|
||||
s = net_socket_fd_init(peer, model, name, fd, 0);
|
||||
if (!s) {
|
||||
@@ -710,7 +711,11 @@ int net_init_socket(const NetClientOptions *opts, const char *name,
|
||||
int fd;
|
||||
|
||||
fd = monitor_handle_fd_param(cur_mon, sock->fd);
|
||||
if (fd == -1 || !net_socket_fd_init(peer, "socket", name, fd, 1)) {
|
||||
if (fd == -1) {
|
||||
return -1;
|
||||
}
|
||||
qemu_set_nonblock(fd);
|
||||
if (!net_socket_fd_init(peer, "socket", name, fd, 1)) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
|
@@ -693,6 +693,13 @@ int net_init_tap(const NetClientOptions *opts, const char *name,
|
||||
queues = tap->has_queues ? tap->queues : 1;
|
||||
vhostfdname = tap->has_vhostfd ? tap->vhostfd : NULL;
|
||||
|
||||
/* QEMU vlans does not support multiqueue tap, in this case peer is set.
|
||||
* For -netdev, peer is always NULL. */
|
||||
if (peer && (tap->has_queues || tap->has_fds || tap->has_vhostfds)) {
|
||||
error_report("Multiqueue tap cannnot be used with QEMU vlans");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (tap->has_fd) {
|
||||
if (tap->has_ifname || tap->has_script || tap->has_downscript ||
|
||||
tap->has_vnet_hdr || tap->has_helper || tap->has_queues ||
|
||||
|
@@ -152,6 +152,9 @@ void cache_insert(PageCache *cache, uint64_t addr, uint8_t *pdata)
|
||||
/* actual update of entry */
|
||||
it = cache_get_by_addr(cache, addr);
|
||||
|
||||
/* free old cached data if any */
|
||||
g_free(it->it_data);
|
||||
|
||||
if (!it->it_data) {
|
||||
cache->num_items++;
|
||||
}
|
||||
@@ -208,6 +211,7 @@ int64_t cache_resize(PageCache *cache, int64_t new_num_pages)
|
||||
}
|
||||
}
|
||||
|
||||
g_free(cache->page_cache);
|
||||
cache->page_cache = new_cache->page_cache;
|
||||
cache->max_num_items = new_cache->max_num_items;
|
||||
cache->num_items = new_cache->num_items;
|
||||
|
BIN
pc-bios/bios.bin
BIN
pc-bios/bios.bin
Binary file not shown.
@@ -2504,6 +2504,9 @@
|
||||
#
|
||||
# @fd: #optional file descriptor of an already opened tap
|
||||
#
|
||||
# @fds: #optional multiple file descriptors of already opened multiqueue capable
|
||||
# tap
|
||||
#
|
||||
# @script: #optional script to initialize the interface
|
||||
#
|
||||
# @downscript: #optional script to shut down the interface
|
||||
@@ -2518,8 +2521,13 @@
|
||||
#
|
||||
# @vhostfd: #optional file descriptor of an already opened vhost net device
|
||||
#
|
||||
# @vhostfds: #optional file descriptors of multiple already opened vhost net
|
||||
# devices
|
||||
#
|
||||
# @vhostforce: #optional vhost on for non-MSIX virtio guests
|
||||
#
|
||||
# @queues: #optional number of queues to be created for multiqueue capable tap
|
||||
#
|
||||
# Since 1.2
|
||||
##
|
||||
{ 'type': 'NetdevTapOptions',
|
||||
|
@@ -367,6 +367,24 @@ int main(int argc, char **argv)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Linux uses the lowest enslaved MAC address as the MAC address of
|
||||
* the bridge. Set MAC address to a high value so that it doesn't
|
||||
* affect the MAC address of the bridge.
|
||||
*/
|
||||
if (ioctl(ctlfd, SIOCGIFHWADDR, &ifr) < 0) {
|
||||
fprintf(stderr, "failed to get MAC address of device `%s': %s\n",
|
||||
iface, strerror(errno));
|
||||
ret = EXIT_FAILURE;
|
||||
goto cleanup;
|
||||
}
|
||||
ifr.ifr_hwaddr.sa_data[0] = 0xFE;
|
||||
if (ioctl(ctlfd, SIOCSIFHWADDR, &ifr) < 0) {
|
||||
fprintf(stderr, "failed to set MAC address of device `%s': %s\n",
|
||||
iface, strerror(errno));
|
||||
ret = EXIT_FAILURE;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* add the interface to the bridge */
|
||||
prep_ifreq(&ifr, bridge);
|
||||
ifindex = if_nametoindex(iface);
|
||||
|
13
qemu-char.c
13
qemu-char.c
@@ -2252,6 +2252,9 @@ static void unix_process_msgfd(CharDriverState *chr, struct msghdr *msg)
|
||||
if (fd < 0)
|
||||
continue;
|
||||
|
||||
/* O_NONBLOCK is preserved across SCM_RIGHTS so reset it */
|
||||
qemu_set_block(fd);
|
||||
|
||||
#ifndef MSG_CMSG_CLOEXEC
|
||||
qemu_set_cloexec(fd);
|
||||
#endif
|
||||
@@ -2377,7 +2380,7 @@ static int tcp_chr_add_client(CharDriverState *chr, int fd)
|
||||
if (s->fd != -1)
|
||||
return -1;
|
||||
|
||||
socket_set_nonblock(fd);
|
||||
qemu_set_nonblock(fd);
|
||||
if (s->do_nodelay)
|
||||
socket_set_nodelay(fd);
|
||||
s->fd = fd;
|
||||
@@ -2482,7 +2485,7 @@ static CharDriverState *qemu_chr_open_socket_fd(int fd, bool do_nodelay,
|
||||
s->do_nodelay = do_nodelay;
|
||||
getnameinfo((struct sockaddr *) &ss, ss_len, host, sizeof(host),
|
||||
serv, sizeof(serv), NI_NUMERICHOST | NI_NUMERICSERV);
|
||||
snprintf(chr->filename, 256, "%s:%s:%s%s%s%s",
|
||||
snprintf(chr->filename, 256, "%s:%s%s%s:%s%s",
|
||||
is_telnet ? "telnet" : "tcp",
|
||||
left, host, right, serv,
|
||||
is_listen ? ",server" : "");
|
||||
@@ -2512,7 +2515,7 @@ static CharDriverState *qemu_chr_open_socket_fd(int fd, bool do_nodelay,
|
||||
printf("QEMU waiting for connection on: %s\n",
|
||||
chr->filename);
|
||||
tcp_chr_accept(chr);
|
||||
socket_set_nonblock(s->listen_fd);
|
||||
qemu_set_nonblock(s->listen_fd);
|
||||
}
|
||||
return chr;
|
||||
}
|
||||
@@ -2554,7 +2557,7 @@ static CharDriverState *qemu_chr_open_socket(QemuOpts *opts)
|
||||
}
|
||||
|
||||
if (!is_waitconnect)
|
||||
socket_set_nonblock(fd);
|
||||
qemu_set_nonblock(fd);
|
||||
|
||||
chr = qemu_chr_open_socket_fd(fd, do_nodelay, is_listen, is_telnet,
|
||||
is_waitconnect, &local_err);
|
||||
@@ -3328,7 +3331,7 @@ static CharDriverState *qmp_chardev_open_serial(ChardevHostdev *serial,
|
||||
if (error_is_set(errp)) {
|
||||
return NULL;
|
||||
}
|
||||
socket_set_nonblock(fd);
|
||||
qemu_set_nonblock(fd);
|
||||
return qemu_chr_open_tty_fd(fd);
|
||||
#else
|
||||
error_setg(errp, "character device backend type 'serial' not supported");
|
||||
|
20
qemu-nbd.c
20
qemu-nbd.c
@@ -305,6 +305,7 @@ static void nbd_accept(void *opaque)
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
BlockDriverState *bs;
|
||||
BlockDriver *drv;
|
||||
off_t dev_offset = 0;
|
||||
uint32_t nbdflags = 0;
|
||||
bool disconnect = false;
|
||||
@@ -312,7 +313,7 @@ int main(int argc, char **argv)
|
||||
char *device = NULL;
|
||||
int port = NBD_DEFAULT_PORT;
|
||||
off_t fd_size;
|
||||
const char *sopt = "hVb:o:p:rsnP:c:dvk:e:t";
|
||||
const char *sopt = "hVb:o:p:rsnP:c:dvk:e:f:t";
|
||||
struct option lopt[] = {
|
||||
{ "help", 0, NULL, 'h' },
|
||||
{ "version", 0, NULL, 'V' },
|
||||
@@ -331,6 +332,7 @@ int main(int argc, char **argv)
|
||||
{ "aio", 1, NULL, QEMU_NBD_OPT_AIO },
|
||||
#endif
|
||||
{ "shared", 1, NULL, 'e' },
|
||||
{ "format", 1, NULL, 'f' },
|
||||
{ "persistent", 0, NULL, 't' },
|
||||
{ "verbose", 0, NULL, 'v' },
|
||||
{ NULL, 0, NULL, 0 }
|
||||
@@ -348,6 +350,7 @@ int main(int argc, char **argv)
|
||||
bool seen_aio = false;
|
||||
#endif
|
||||
pthread_t client_thread;
|
||||
const char *fmt = NULL;
|
||||
|
||||
/* The client thread uses SIGTERM to interrupt the server. A signal
|
||||
* handler ensures that "qemu-nbd -v -c" exits with a nice status code.
|
||||
@@ -442,6 +445,9 @@ int main(int argc, char **argv)
|
||||
errx(EXIT_FAILURE, "Shared device number must be greater than 0\n");
|
||||
}
|
||||
break;
|
||||
case 'f':
|
||||
fmt = optarg;
|
||||
break;
|
||||
case 't':
|
||||
persistent = 1;
|
||||
break;
|
||||
@@ -543,9 +549,19 @@ int main(int argc, char **argv)
|
||||
bdrv_init();
|
||||
atexit(bdrv_close_all);
|
||||
|
||||
if (fmt) {
|
||||
drv = bdrv_find_format(fmt);
|
||||
if (!drv) {
|
||||
errx(EXIT_FAILURE, "Unknown file format '%s'", fmt);
|
||||
}
|
||||
} else {
|
||||
drv = NULL;
|
||||
}
|
||||
|
||||
bs = bdrv_new("hda");
|
||||
srcpath = argv[optind];
|
||||
if ((ret = bdrv_open(bs, srcpath, flags, NULL)) < 0) {
|
||||
ret = bdrv_open(bs, srcpath, flags, drv);
|
||||
if (ret < 0) {
|
||||
errno = -ret;
|
||||
err(EXIT_FAILURE, "Failed to bdrv_open '%s'", argv[optind]);
|
||||
}
|
||||
|
@@ -41,6 +41,8 @@ Export QEMU disk image using NBD protocol.
|
||||
disconnect the specified device
|
||||
@item -e, --shared=@var{num}
|
||||
device can be shared by @var{num} clients (default @samp{1})
|
||||
@item -f, --format=@var{fmt}
|
||||
force block driver for format @var{fmt} instead of auto-detecting
|
||||
@item -t, --persistent
|
||||
don't exit on the last connection
|
||||
@item -v, --verbose
|
||||
|
@@ -537,13 +537,15 @@ STEXI
|
||||
@end table
|
||||
ETEXI
|
||||
|
||||
STEXI
|
||||
USB options:
|
||||
@table @option
|
||||
ETEXI
|
||||
|
||||
DEF("usb", 0, QEMU_OPTION_usb,
|
||||
"-usb enable the USB driver (will be the default soon)\n",
|
||||
QEMU_ARCH_ALL)
|
||||
STEXI
|
||||
USB options:
|
||||
@table @option
|
||||
|
||||
@item -usb
|
||||
@findex -usb
|
||||
Enable the USB driver (will be the default soon)
|
||||
@@ -610,9 +612,15 @@ possible drivers and properties, use @code{-device help} and
|
||||
@code{-device @var{driver},help}.
|
||||
ETEXI
|
||||
|
||||
STEXI
|
||||
@end table
|
||||
ETEXI
|
||||
DEFHEADING()
|
||||
|
||||
DEFHEADING(File system options:)
|
||||
STEXI
|
||||
@table @option
|
||||
ETEXI
|
||||
|
||||
DEF("fsdev", HAS_ARG, QEMU_OPTION_fsdev,
|
||||
"-fsdev fsdriver,id=id[,path=path,][security_model={mapped-xattr|mapped-file|passthrough|none}]\n"
|
||||
@@ -676,9 +684,15 @@ Specifies the tag name to be used by the guest to mount this export point
|
||||
|
||||
ETEXI
|
||||
|
||||
STEXI
|
||||
@end table
|
||||
ETEXI
|
||||
DEFHEADING()
|
||||
|
||||
DEFHEADING(Virtual File system pass-through options:)
|
||||
STEXI
|
||||
@table @option
|
||||
ETEXI
|
||||
|
||||
DEF("virtfs", HAS_ARG, QEMU_OPTION_virtfs,
|
||||
"-virtfs local,path=path,mount_tag=tag,security_model=[mapped-xattr|mapped-file|passthrough|none]\n"
|
||||
@@ -769,11 +783,9 @@ ETEXI
|
||||
STEXI
|
||||
@end table
|
||||
ETEXI
|
||||
|
||||
DEFHEADING()
|
||||
|
||||
DEFHEADING(Display options:)
|
||||
|
||||
STEXI
|
||||
@table @option
|
||||
ETEXI
|
||||
@@ -1215,7 +1227,6 @@ ETEXI
|
||||
STEXI
|
||||
@end table
|
||||
ETEXI
|
||||
|
||||
ARCHHEADING(, QEMU_ARCH_I386)
|
||||
|
||||
ARCHHEADING(i386 target only:, QEMU_ARCH_I386)
|
||||
@@ -1301,10 +1312,10 @@ Specify SMBIOS type 0 fields
|
||||
Specify SMBIOS type 1 fields
|
||||
ETEXI
|
||||
|
||||
DEFHEADING()
|
||||
STEXI
|
||||
@end table
|
||||
ETEXI
|
||||
DEFHEADING()
|
||||
|
||||
DEFHEADING(Network options:)
|
||||
STEXI
|
||||
@@ -1338,7 +1349,7 @@ DEF("net", HAS_ARG, QEMU_OPTION_net,
|
||||
"-net tap[,vlan=n][,name=str],ifname=name\n"
|
||||
" connect the host TAP network interface to VLAN 'n'\n"
|
||||
#else
|
||||
"-net tap[,vlan=n][,name=str][,fd=h][,ifname=name][,script=file][,downscript=dfile][,helper=helper][,sndbuf=nbytes][,vnet_hdr=on|off][,vhost=on|off][,vhostfd=h][,vhostforce=on|off]\n"
|
||||
"-net tap[,vlan=n][,name=str][,fd=h][,fds=x:y:...:z][,ifname=name][,script=file][,downscript=dfile][,helper=helper][,sndbuf=nbytes][,vnet_hdr=on|off][,vhost=on|off][,vhostfd=h][,vhostfds=x:y:...:z][,vhostforce=on|off][,queues=n]\n"
|
||||
" connect the host TAP network interface to VLAN 'n'\n"
|
||||
" use network scripts 'file' (default=" DEFAULT_NETWORK_SCRIPT ")\n"
|
||||
" to configure it and 'dfile' (default=" DEFAULT_NETWORK_DOWN_SCRIPT ")\n"
|
||||
@@ -1347,6 +1358,7 @@ DEF("net", HAS_ARG, QEMU_OPTION_net,
|
||||
" use network helper 'helper' (default=" DEFAULT_BRIDGE_HELPER ") to\n"
|
||||
" configure it\n"
|
||||
" use 'fd=h' to connect to an already opened TAP interface\n"
|
||||
" use 'fds=x:y:...:z' to connect to already opened multiqueue capable TAP interfaces\n"
|
||||
" use 'sndbuf=nbytes' to limit the size of the send buffer (the\n"
|
||||
" default is disabled 'sndbuf=0' to enable flow control set 'sndbuf=1048576')\n"
|
||||
" use vnet_hdr=off to avoid enabling the IFF_VNET_HDR tap flag\n"
|
||||
@@ -1355,6 +1367,8 @@ DEF("net", HAS_ARG, QEMU_OPTION_net,
|
||||
" (only has effect for virtio guests which use MSIX)\n"
|
||||
" use vhostforce=on to force vhost on for non-MSIX virtio guests\n"
|
||||
" use 'vhostfd=h' to connect to an already opened vhost net device\n"
|
||||
" use 'vhostfds=x:y:...:z to connect to multiple already opened vhost net devices\n"
|
||||
" use 'queues=n' to specify the number of queues to be created for multiqueue TAP\n"
|
||||
"-net bridge[,vlan=n][,name=str][,br=bridge][,helper=helper]\n"
|
||||
" connects a host TAP network interface to a host bridge device 'br'\n"
|
||||
" (default=" DEFAULT_BRIDGE_INTERFACE ") using the program 'helper'\n"
|
||||
@@ -1718,13 +1732,19 @@ libpcap, so it can be analyzed with tools such as tcpdump or Wireshark.
|
||||
Indicate that no network devices should be configured. It is used to
|
||||
override the default configuration (@option{-net nic -net user}) which
|
||||
is activated if no @option{-net} options are provided.
|
||||
|
||||
@end table
|
||||
ETEXI
|
||||
|
||||
STEXI
|
||||
@end table
|
||||
ETEXI
|
||||
DEFHEADING()
|
||||
|
||||
DEFHEADING(Character device options:)
|
||||
STEXI
|
||||
|
||||
The general form of a character device option is:
|
||||
@table @option
|
||||
ETEXI
|
||||
|
||||
DEF("chardev", HAS_ARG, QEMU_OPTION_chardev,
|
||||
"-chardev null,id=id[,mux=on|off]\n"
|
||||
@@ -1766,10 +1786,6 @@ DEF("chardev", HAS_ARG, QEMU_OPTION_chardev,
|
||||
)
|
||||
|
||||
STEXI
|
||||
|
||||
The general form of a character device option is:
|
||||
@table @option
|
||||
|
||||
@item -chardev @var{backend} ,id=@var{id} [,mux=on|off] [,@var{options}]
|
||||
@findex -chardev
|
||||
Backend is one of:
|
||||
@@ -1990,14 +2006,15 @@ Connect to a spice virtual machine channel, such as vdiport.
|
||||
|
||||
Connect to a spice port, allowing a Spice client to handle the traffic
|
||||
identified by a name (preferably a fqdn).
|
||||
|
||||
@end table
|
||||
ETEXI
|
||||
|
||||
STEXI
|
||||
@end table
|
||||
ETEXI
|
||||
DEFHEADING()
|
||||
|
||||
STEXI
|
||||
DEFHEADING(Device URL Syntax:)
|
||||
STEXI
|
||||
|
||||
In addition to using normal file images for the emulated storage devices,
|
||||
QEMU can also use networked resources such as iSCSI devices. These are
|
||||
@@ -2113,10 +2130,16 @@ qemu-system-x86_84 --drive file=gluster://192.0.2.1/testvol/a.img
|
||||
@end example
|
||||
|
||||
See also @url{http://www.gluster.org}.
|
||||
ETEXI
|
||||
|
||||
STEXI
|
||||
@end table
|
||||
ETEXI
|
||||
|
||||
DEFHEADING(Bluetooth(R) options:)
|
||||
STEXI
|
||||
@table @option
|
||||
ETEXI
|
||||
|
||||
DEF("bt", HAS_ARG, QEMU_OPTION_bt, \
|
||||
"-bt hci,null dumb bluetooth HCI - doesn't respond to commands\n" \
|
||||
@@ -2130,8 +2153,6 @@ DEF("bt", HAS_ARG, QEMU_OPTION_bt, \
|
||||
" emulate a bluetooth device 'dev' in scatternet 'n'\n",
|
||||
QEMU_ARCH_ALL)
|
||||
STEXI
|
||||
@table @option
|
||||
|
||||
@item -bt hci[...]
|
||||
@findex -bt
|
||||
Defines the function of the corresponding Bluetooth HCI. -bt options
|
||||
@@ -2183,9 +2204,11 @@ currently:
|
||||
@item keyboard
|
||||
Virtual wireless keyboard implementing the HIDP bluetooth profile.
|
||||
@end table
|
||||
@end table
|
||||
ETEXI
|
||||
|
||||
STEXI
|
||||
@end table
|
||||
ETEXI
|
||||
DEFHEADING()
|
||||
|
||||
DEFHEADING(Linux/Multiboot boot specific:)
|
||||
@@ -2242,11 +2265,9 @@ ETEXI
|
||||
STEXI
|
||||
@end table
|
||||
ETEXI
|
||||
|
||||
DEFHEADING()
|
||||
|
||||
DEFHEADING(Debug/Expert options:)
|
||||
|
||||
STEXI
|
||||
@table @option
|
||||
ETEXI
|
||||
|
@@ -129,14 +129,22 @@ static struct {
|
||||
QTAILQ_HEAD(, GuestFileHandle) filehandles;
|
||||
} guest_file_state;
|
||||
|
||||
static void guest_file_handle_add(FILE *fh)
|
||||
static int64_t guest_file_handle_add(FILE *fh, Error **errp)
|
||||
{
|
||||
GuestFileHandle *gfh;
|
||||
int64_t handle;
|
||||
|
||||
handle = ga_get_fd_handle(ga_state, errp);
|
||||
if (error_is_set(errp)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
gfh = g_malloc0(sizeof(GuestFileHandle));
|
||||
gfh->id = fileno(fh);
|
||||
gfh->id = handle;
|
||||
gfh->fh = fh;
|
||||
QTAILQ_INSERT_TAIL(&guest_file_state.filehandles, gfh, next);
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
static GuestFileHandle *guest_file_handle_find(int64_t id, Error **err)
|
||||
@@ -158,7 +166,7 @@ int64_t qmp_guest_file_open(const char *path, bool has_mode, const char *mode, E
|
||||
{
|
||||
FILE *fh;
|
||||
int fd;
|
||||
int64_t ret = -1;
|
||||
int64_t ret = -1, handle;
|
||||
|
||||
if (!has_mode) {
|
||||
mode = "r";
|
||||
@@ -184,9 +192,14 @@ int64_t qmp_guest_file_open(const char *path, bool has_mode, const char *mode, E
|
||||
return -1;
|
||||
}
|
||||
|
||||
guest_file_handle_add(fh);
|
||||
slog("guest-file-open, handle: %d", fd);
|
||||
return fd;
|
||||
handle = guest_file_handle_add(fh, err);
|
||||
if (error_is_set(err)) {
|
||||
fclose(fh);
|
||||
return -1;
|
||||
}
|
||||
|
||||
slog("guest-file-open, handle: %d", handle);
|
||||
return handle;
|
||||
}
|
||||
|
||||
void qmp_guest_file_close(int64_t handle, Error **err)
|
||||
|
@@ -35,6 +35,7 @@ bool ga_is_frozen(GAState *s);
|
||||
void ga_set_frozen(GAState *s);
|
||||
void ga_unset_frozen(GAState *s);
|
||||
const char *ga_fsfreeze_hook(GAState *s);
|
||||
int64_t ga_get_fd_handle(GAState *s, Error **errp);
|
||||
|
||||
#ifndef _WIN32
|
||||
void reopen_fd_to_null(int fd);
|
||||
|
185
qga/main.c
185
qga/main.c
@@ -15,6 +15,7 @@
|
||||
#include <stdbool.h>
|
||||
#include <glib.h>
|
||||
#include <getopt.h>
|
||||
#include <glib/gstdio.h>
|
||||
#ifndef _WIN32
|
||||
#include <syslog.h>
|
||||
#include <sys/wait.h>
|
||||
@@ -30,6 +31,7 @@
|
||||
#include "qapi/qmp/qerror.h"
|
||||
#include "qapi/qmp/dispatch.h"
|
||||
#include "qga/channel.h"
|
||||
#include "qemu/bswap.h"
|
||||
#ifdef _WIN32
|
||||
#include "qga/service-win32.h"
|
||||
#include <windows.h>
|
||||
@@ -53,6 +55,11 @@
|
||||
#endif
|
||||
#define QGA_SENTINEL_BYTE 0xFF
|
||||
|
||||
typedef struct GAPersistentState {
|
||||
#define QGA_PSTATE_DEFAULT_FD_COUNTER 1000
|
||||
int64_t fd_counter;
|
||||
} GAPersistentState;
|
||||
|
||||
struct GAState {
|
||||
JSONMessageParser parser;
|
||||
GMainLoop *main_loop;
|
||||
@@ -76,6 +83,8 @@ struct GAState {
|
||||
#ifdef CONFIG_FSFREEZE
|
||||
const char *fsfreeze_hook;
|
||||
#endif
|
||||
const gchar *pstate_filepath;
|
||||
GAPersistentState pstate;
|
||||
};
|
||||
|
||||
struct GAState *ga_state;
|
||||
@@ -85,6 +94,7 @@ static const char *ga_freeze_whitelist[] = {
|
||||
"guest-ping",
|
||||
"guest-info",
|
||||
"guest-sync",
|
||||
"guest-sync-delimited",
|
||||
"guest-fsfreeze-status",
|
||||
"guest-fsfreeze-thaw",
|
||||
NULL
|
||||
@@ -724,6 +734,171 @@ VOID WINAPI service_main(DWORD argc, TCHAR *argv[])
|
||||
}
|
||||
#endif
|
||||
|
||||
static void set_persistent_state_defaults(GAPersistentState *pstate)
|
||||
{
|
||||
g_assert(pstate);
|
||||
pstate->fd_counter = QGA_PSTATE_DEFAULT_FD_COUNTER;
|
||||
}
|
||||
|
||||
static void persistent_state_from_keyfile(GAPersistentState *pstate,
|
||||
GKeyFile *keyfile)
|
||||
{
|
||||
g_assert(pstate);
|
||||
g_assert(keyfile);
|
||||
/* if any fields are missing, either because the file was tampered with
|
||||
* by agents of chaos, or because the field wasn't present at the time the
|
||||
* file was created, the best we can ever do is start over with the default
|
||||
* values. so load them now, and ignore any errors in accessing key-value
|
||||
* pairs
|
||||
*/
|
||||
set_persistent_state_defaults(pstate);
|
||||
|
||||
if (g_key_file_has_key(keyfile, "global", "fd_counter", NULL)) {
|
||||
pstate->fd_counter =
|
||||
g_key_file_get_integer(keyfile, "global", "fd_counter", NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void persistent_state_to_keyfile(const GAPersistentState *pstate,
|
||||
GKeyFile *keyfile)
|
||||
{
|
||||
g_assert(pstate);
|
||||
g_assert(keyfile);
|
||||
|
||||
g_key_file_set_integer(keyfile, "global", "fd_counter", pstate->fd_counter);
|
||||
}
|
||||
|
||||
static gboolean write_persistent_state(const GAPersistentState *pstate,
|
||||
const gchar *path)
|
||||
{
|
||||
GKeyFile *keyfile = g_key_file_new();
|
||||
GError *gerr = NULL;
|
||||
gboolean ret = true;
|
||||
gchar *data = NULL;
|
||||
gsize data_len;
|
||||
|
||||
g_assert(pstate);
|
||||
|
||||
persistent_state_to_keyfile(pstate, keyfile);
|
||||
data = g_key_file_to_data(keyfile, &data_len, &gerr);
|
||||
if (gerr) {
|
||||
g_critical("failed to convert persistent state to string: %s",
|
||||
gerr->message);
|
||||
ret = false;
|
||||
goto out;
|
||||
}
|
||||
|
||||
g_file_set_contents(path, data, data_len, &gerr);
|
||||
if (gerr) {
|
||||
g_critical("failed to write persistent state to %s: %s",
|
||||
path, gerr->message);
|
||||
ret = false;
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
if (gerr) {
|
||||
g_error_free(gerr);
|
||||
}
|
||||
if (keyfile) {
|
||||
g_key_file_free(keyfile);
|
||||
}
|
||||
g_free(data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static gboolean read_persistent_state(GAPersistentState *pstate,
|
||||
const gchar *path, gboolean frozen)
|
||||
{
|
||||
GKeyFile *keyfile = NULL;
|
||||
GError *gerr = NULL;
|
||||
struct stat st;
|
||||
gboolean ret = true;
|
||||
|
||||
g_assert(pstate);
|
||||
|
||||
if (stat(path, &st) == -1) {
|
||||
/* it's okay if state file doesn't exist, but any other error
|
||||
* indicates a permissions issue or some other misconfiguration
|
||||
* that we likely won't be able to recover from.
|
||||
*/
|
||||
if (errno != ENOENT) {
|
||||
g_critical("unable to access state file at path %s: %s",
|
||||
path, strerror(errno));
|
||||
ret = false;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* file doesn't exist. initialize state to default values and
|
||||
* attempt to save now. (we could wait till later when we have
|
||||
* modified state we need to commit, but if there's a problem,
|
||||
* such as a missing parent directory, we want to catch it now)
|
||||
*
|
||||
* there is a potential scenario where someone either managed to
|
||||
* update the agent from a version that didn't use a key store
|
||||
* while qemu-ga thought the filesystem was frozen, or
|
||||
* deleted the key store prior to issuing a fsfreeze, prior
|
||||
* to restarting the agent. in this case we go ahead and defer
|
||||
* initial creation till we actually have modified state to
|
||||
* write, otherwise fail to recover from freeze.
|
||||
*/
|
||||
set_persistent_state_defaults(pstate);
|
||||
if (!frozen) {
|
||||
ret = write_persistent_state(pstate, path);
|
||||
if (!ret) {
|
||||
g_critical("unable to create state file at path %s", path);
|
||||
ret = false;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
ret = true;
|
||||
goto out;
|
||||
}
|
||||
|
||||
keyfile = g_key_file_new();
|
||||
g_key_file_load_from_file(keyfile, path, 0, &gerr);
|
||||
if (gerr) {
|
||||
g_critical("error loading persistent state from path: %s, %s",
|
||||
path, gerr->message);
|
||||
ret = false;
|
||||
goto out;
|
||||
}
|
||||
|
||||
persistent_state_from_keyfile(pstate, keyfile);
|
||||
|
||||
out:
|
||||
if (keyfile) {
|
||||
g_key_file_free(keyfile);
|
||||
}
|
||||
if (gerr) {
|
||||
g_error_free(gerr);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int64_t ga_get_fd_handle(GAState *s, Error **errp)
|
||||
{
|
||||
int64_t handle;
|
||||
|
||||
g_assert(s->pstate_filepath);
|
||||
/* we blacklist commands and avoid operations that potentially require
|
||||
* writing to disk when we're in a frozen state. this includes opening
|
||||
* new files, so we should never get here in that situation
|
||||
*/
|
||||
g_assert(!ga_is_frozen(s));
|
||||
|
||||
handle = s->pstate.fd_counter++;
|
||||
if (s->pstate.fd_counter < 0) {
|
||||
s->pstate.fd_counter = 0;
|
||||
}
|
||||
if (!write_persistent_state(&s->pstate, s->pstate_filepath)) {
|
||||
error_setg(errp, "failed to commit persistent state to disk");
|
||||
}
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
const char *sopt = "hVvdm:p:l:f:F::b:s:t:";
|
||||
@@ -853,7 +1028,9 @@ int main(int argc, char **argv)
|
||||
ga_enable_logging(s);
|
||||
s->state_filepath_isfrozen = g_strdup_printf("%s/qga.state.isfrozen",
|
||||
state_dir);
|
||||
s->pstate_filepath = g_strdup_printf("%s/qga.state", state_dir);
|
||||
s->frozen = false;
|
||||
|
||||
#ifndef _WIN32
|
||||
/* check if a previous instance of qemu-ga exited with filesystems' state
|
||||
* marked as frozen. this could be a stale value (a non-qemu-ga process
|
||||
@@ -910,6 +1087,14 @@ int main(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
|
||||
/* load persistent state from disk */
|
||||
if (!read_persistent_state(&s->pstate,
|
||||
s->pstate_filepath,
|
||||
ga_is_frozen(s))) {
|
||||
g_critical("failed to load persistent state");
|
||||
goto out_bad;
|
||||
}
|
||||
|
||||
if (blacklist) {
|
||||
s->blacklist = blacklist;
|
||||
do {
|
||||
|
@@ -822,7 +822,7 @@ Example:
|
||||
-> { "execute": "netdev_add", "arguments": { "type": "user", "id": "netdev1" } }
|
||||
<- { "return": {} }
|
||||
|
||||
Note: The supported device options are the same ones supported by the '-net'
|
||||
Note: The supported device options are the same ones supported by the '-netdev'
|
||||
command-line argument, which are listed in the '-help' output or QEMU's
|
||||
manual
|
||||
|
||||
|
Submodule roms/seabios updated: 4bd8aebf35...88cb66ea54
@@ -215,7 +215,7 @@ fork_exec(struct socket *so, const char *ex, int do_pty)
|
||||
setsockopt(so->s, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(int));
|
||||
opt = 1;
|
||||
setsockopt(so->s, SOL_SOCKET, SO_OOBINLINE, (char *)&opt, sizeof(int));
|
||||
socket_set_nonblock(so->s);
|
||||
qemu_set_nonblock(so->s);
|
||||
|
||||
/* Append the telnet options now */
|
||||
if (so->so_m != NULL && do_pty == 1) {
|
||||
|
@@ -336,7 +336,7 @@ int tcp_fconnect(struct socket *so)
|
||||
int opt, s=so->s;
|
||||
struct sockaddr_in addr;
|
||||
|
||||
socket_set_nonblock(s);
|
||||
qemu_set_nonblock(s);
|
||||
opt = 1;
|
||||
setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(opt ));
|
||||
opt = 1;
|
||||
@@ -424,7 +424,7 @@ tcp_connect(struct socket *inso)
|
||||
tcp_close(sototcpcb(so)); /* This will sofree() as well */
|
||||
return;
|
||||
}
|
||||
socket_set_nonblock(s);
|
||||
qemu_set_nonblock(s);
|
||||
opt = 1;
|
||||
setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int));
|
||||
opt = 1;
|
||||
|
@@ -2091,14 +2091,14 @@ void x86_cpu_realize(Object *obj, Error **errp)
|
||||
env->cpuid_ext3_features &= TCG_EXT3_FEATURES;
|
||||
env->cpuid_svm_features &= TCG_SVM_FEATURES;
|
||||
} else {
|
||||
#ifdef CONFIG_KVM
|
||||
filter_features_for_kvm(cpu);
|
||||
#endif
|
||||
if (check_cpuid && kvm_check_features_against_host(cpu)
|
||||
&& enforce_cpuid) {
|
||||
error_setg(errp, "Host's CPU doesn't support requested features");
|
||||
return;
|
||||
}
|
||||
#ifdef CONFIG_KVM
|
||||
filter_features_for_kvm(cpu);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
|
@@ -44,7 +44,8 @@ typedef union {
|
||||
|
||||
/*** MIPS DSP internal functions begin ***/
|
||||
#define MIPSDSP_ABS(x) (((x) >= 0) ? x : -x)
|
||||
#define MIPSDSP_OVERFLOW(a, b, c, d) (!(!((a ^ b ^ -1) & (a ^ c) & d)))
|
||||
#define MIPSDSP_OVERFLOW_ADD(a, b, c, d) (~(a ^ b) & (a ^ c) & d)
|
||||
#define MIPSDSP_OVERFLOW_SUB(a, b, c, d) ((a ^ b) & (a ^ c) & d)
|
||||
|
||||
static inline void set_DSPControl_overflow_flag(uint32_t flag, int position,
|
||||
CPUMIPSState *env)
|
||||
@@ -142,7 +143,7 @@ static inline int16_t mipsdsp_add_i16(int16_t a, int16_t b, CPUMIPSState *env)
|
||||
|
||||
tempI = a + b;
|
||||
|
||||
if (MIPSDSP_OVERFLOW(a, b, tempI, 0x8000)) {
|
||||
if (MIPSDSP_OVERFLOW_ADD(a, b, tempI, 0x8000)) {
|
||||
set_DSPControl_overflow_flag(1, 20, env);
|
||||
}
|
||||
|
||||
@@ -156,7 +157,7 @@ static inline int16_t mipsdsp_sat_add_i16(int16_t a, int16_t b,
|
||||
|
||||
tempS = a + b;
|
||||
|
||||
if (MIPSDSP_OVERFLOW(a, b, tempS, 0x8000)) {
|
||||
if (MIPSDSP_OVERFLOW_ADD(a, b, tempS, 0x8000)) {
|
||||
if (a > 0) {
|
||||
tempS = 0x7FFF;
|
||||
} else {
|
||||
@@ -175,7 +176,7 @@ static inline int32_t mipsdsp_sat_add_i32(int32_t a, int32_t b,
|
||||
|
||||
tempI = a + b;
|
||||
|
||||
if (MIPSDSP_OVERFLOW(a, b, tempI, 0x80000000)) {
|
||||
if (MIPSDSP_OVERFLOW_ADD(a, b, tempI, 0x80000000)) {
|
||||
if (a > 0) {
|
||||
tempI = 0x7FFFFFFF;
|
||||
} else {
|
||||
@@ -516,13 +517,8 @@ static inline void mipsdsp_rndrashift_short_acc(int64_t *p,
|
||||
|
||||
acc = ((int64_t)env->active_tc.HI[ac] << 32) |
|
||||
((int64_t)env->active_tc.LO[ac] & 0xFFFFFFFF);
|
||||
if (shift == 0) {
|
||||
p[0] = acc << 1;
|
||||
p[1] = (acc >> 63) & 0x01;
|
||||
} else {
|
||||
p[0] = acc >> (shift - 1);
|
||||
p[1] = 0;
|
||||
}
|
||||
p[0] = (shift == 0) ? (acc << 1) : (acc >> (shift - 1));
|
||||
p[1] = (acc >> 63) & 0x01;
|
||||
}
|
||||
|
||||
/* 128 bits long. p[0] is LO, p[1] is HI */
|
||||
@@ -652,7 +648,7 @@ static inline int32_t mipsdsp_sat16_mul_q15_q15(uint16_t a, uint16_t b,
|
||||
temp = 0x7FFF0000;
|
||||
set_DSPControl_overflow_flag(1, 21, env);
|
||||
} else {
|
||||
temp = ((uint32_t)a * (uint32_t)b);
|
||||
temp = (int16_t)a * (int16_t)b;
|
||||
temp = temp << 1;
|
||||
}
|
||||
|
||||
@@ -858,7 +854,7 @@ static inline uint16_t mipsdsp_sub_i16(int16_t a, int16_t b, CPUMIPSState *env)
|
||||
int16_t temp;
|
||||
|
||||
temp = a - b;
|
||||
if (MIPSDSP_OVERFLOW(a, -b, temp, 0x8000)) {
|
||||
if (MIPSDSP_OVERFLOW_SUB(a, b, temp, 0x8000)) {
|
||||
set_DSPControl_overflow_flag(1, 20, env);
|
||||
}
|
||||
|
||||
@@ -871,8 +867,8 @@ static inline uint16_t mipsdsp_sat16_sub(int16_t a, int16_t b,
|
||||
int16_t temp;
|
||||
|
||||
temp = a - b;
|
||||
if (MIPSDSP_OVERFLOW(a, -b, temp, 0x8000)) {
|
||||
if (a > 0) {
|
||||
if (MIPSDSP_OVERFLOW_SUB(a, b, temp, 0x8000)) {
|
||||
if (a >= 0) {
|
||||
temp = 0x7FFF;
|
||||
} else {
|
||||
temp = 0x8000;
|
||||
@@ -889,8 +885,8 @@ static inline uint32_t mipsdsp_sat32_sub(int32_t a, int32_t b,
|
||||
int32_t temp;
|
||||
|
||||
temp = a - b;
|
||||
if (MIPSDSP_OVERFLOW(a, -b, temp, 0x80000000)) {
|
||||
if (a > 0) {
|
||||
if (MIPSDSP_OVERFLOW_SUB(a, b, temp, 0x80000000)) {
|
||||
if (a >= 0) {
|
||||
temp = 0x7FFFFFFF;
|
||||
} else {
|
||||
temp = 0x80000000;
|
||||
@@ -1004,7 +1000,7 @@ static inline uint32_t mipsdsp_sub32(int32_t a, int32_t b, CPUMIPSState *env)
|
||||
int32_t temp;
|
||||
|
||||
temp = a - b;
|
||||
if (MIPSDSP_OVERFLOW(a, -b, temp, 0x80000000)) {
|
||||
if (MIPSDSP_OVERFLOW_SUB(a, b, temp, 0x80000000)) {
|
||||
set_DSPControl_overflow_flag(1, 20, env);
|
||||
}
|
||||
|
||||
@@ -1017,7 +1013,7 @@ static inline int32_t mipsdsp_add_i32(int32_t a, int32_t b, CPUMIPSState *env)
|
||||
|
||||
temp = a + b;
|
||||
|
||||
if (MIPSDSP_OVERFLOW(a, b, temp, 0x80000000)) {
|
||||
if (MIPSDSP_OVERFLOW_ADD(a, b, temp, 0x80000000)) {
|
||||
set_DSPControl_overflow_flag(1, 20, env);
|
||||
}
|
||||
|
||||
@@ -2488,37 +2484,42 @@ DP_QH(dpsq_s_w_qh, 0, 1);
|
||||
#endif
|
||||
|
||||
#define DP_L_W(name, is_add) \
|
||||
void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt, \
|
||||
CPUMIPSState *env) \
|
||||
{ \
|
||||
int32_t temp63; \
|
||||
int64_t dotp, acc; \
|
||||
uint64_t temp; \
|
||||
\
|
||||
dotp = mipsdsp_mul_q31_q31(ac, rs, rt, env); \
|
||||
acc = ((uint64_t)env->active_tc.HI[ac] << 32) | \
|
||||
((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO); \
|
||||
if (!is_add) { \
|
||||
dotp = -dotp; \
|
||||
} \
|
||||
\
|
||||
temp = acc + dotp; \
|
||||
if (MIPSDSP_OVERFLOW((uint64_t)acc, (uint64_t)dotp, temp, \
|
||||
(0x01ull << 63))) { \
|
||||
temp63 = (temp >> 63) & 0x01; \
|
||||
if (temp63 == 1) { \
|
||||
temp = (0x01ull << 63) - 1; \
|
||||
} else { \
|
||||
temp = 0x01ull << 63; \
|
||||
} \
|
||||
\
|
||||
set_DSPControl_overflow_flag(1, 16 + ac, env); \
|
||||
} \
|
||||
\
|
||||
env->active_tc.HI[ac] = (target_long)(int32_t) \
|
||||
((temp & MIPSDSP_LHI) >> 32); \
|
||||
env->active_tc.LO[ac] = (target_long)(int32_t) \
|
||||
(temp & MIPSDSP_LLO); \
|
||||
void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt, \
|
||||
CPUMIPSState *env) \
|
||||
{ \
|
||||
int32_t temp63; \
|
||||
int64_t dotp, acc; \
|
||||
uint64_t temp; \
|
||||
bool overflow; \
|
||||
\
|
||||
dotp = mipsdsp_mul_q31_q31(ac, rs, rt, env); \
|
||||
acc = ((uint64_t)env->active_tc.HI[ac] << 32) | \
|
||||
((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO); \
|
||||
if (is_add) { \
|
||||
temp = acc + dotp; \
|
||||
overflow = MIPSDSP_OVERFLOW_ADD((uint64_t)acc, (uint64_t)dotp, \
|
||||
temp, (0x01ull << 63)); \
|
||||
} else { \
|
||||
temp = acc - dotp; \
|
||||
overflow = MIPSDSP_OVERFLOW_SUB((uint64_t)acc, (uint64_t)dotp, \
|
||||
temp, (0x01ull << 63)); \
|
||||
} \
|
||||
\
|
||||
if (overflow) { \
|
||||
temp63 = (temp >> 63) & 0x01; \
|
||||
if (temp63 == 1) { \
|
||||
temp = (0x01ull << 63) - 1; \
|
||||
} else { \
|
||||
temp = 0x01ull << 63; \
|
||||
} \
|
||||
\
|
||||
set_DSPControl_overflow_flag(1, 16 + ac, env); \
|
||||
} \
|
||||
\
|
||||
env->active_tc.HI[ac] = (target_long)(int32_t) \
|
||||
((temp & MIPSDSP_LHI) >> 32); \
|
||||
env->active_tc.LO[ac] = (target_long)(int32_t) \
|
||||
(temp & MIPSDSP_LLO); \
|
||||
}
|
||||
|
||||
DP_L_W(dpaq_sa_l_w, 1);
|
||||
@@ -2689,7 +2690,7 @@ MAQ_SA_W(maq_sa_w_phr, 0);
|
||||
target_ulong helper_##name(target_ulong rs, target_ulong rt, \
|
||||
CPUMIPSState *env) \
|
||||
{ \
|
||||
uint32_t rs_t, rt_t; \
|
||||
int32_t rs_t, rt_t; \
|
||||
int32_t tempI; \
|
||||
int64_t tempL; \
|
||||
\
|
||||
@@ -3155,8 +3156,8 @@ target_ulong helper_extr_w(target_ulong ac, target_ulong shift,
|
||||
tempDL[1] += 1;
|
||||
}
|
||||
|
||||
if ((!(tempDL[1] == 0 && (tempDL[0] & MIPSDSP_LHI) == 0x00)) &&
|
||||
(!(tempDL[1] == 1 && (tempDL[0] & MIPSDSP_LHI) == MIPSDSP_LHI))) {
|
||||
if (((tempDL[1] & 0x01) != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
|
||||
((tempDL[1] & 0x01) != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
|
||||
set_DSPControl_overflow_flag(1, 23, env);
|
||||
}
|
||||
|
||||
@@ -3181,8 +3182,8 @@ target_ulong helper_extr_r_w(target_ulong ac, target_ulong shift,
|
||||
tempDL[1] += 1;
|
||||
}
|
||||
|
||||
if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
|
||||
(tempDL[1] != 1 && (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
|
||||
if (((tempDL[1] & 0x01) != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
|
||||
((tempDL[1] & 0x01) != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
|
||||
set_DSPControl_overflow_flag(1, 23, env);
|
||||
}
|
||||
|
||||
@@ -3208,9 +3209,9 @@ target_ulong helper_extr_rs_w(target_ulong ac, target_ulong shift,
|
||||
}
|
||||
tempI = tempDL[0] >> 1;
|
||||
|
||||
if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
|
||||
(tempDL[1] != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
|
||||
temp64 = tempDL[1];
|
||||
if (((tempDL[1] & 0x01) != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
|
||||
((tempDL[1] & 0x01) != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
|
||||
temp64 = tempDL[1] & 0x01;
|
||||
if (temp64 == 0) {
|
||||
tempI = 0x7FFFFFFF;
|
||||
} else {
|
||||
|
@@ -24,8 +24,8 @@ DEF_HELPER_FLAGS_1(clz, TCG_CALL_NO_RWG_SE, tl, tl)
|
||||
#ifdef TARGET_MIPS64
|
||||
DEF_HELPER_FLAGS_1(dclo, TCG_CALL_NO_RWG_SE, tl, tl)
|
||||
DEF_HELPER_FLAGS_1(dclz, TCG_CALL_NO_RWG_SE, tl, tl)
|
||||
DEF_HELPER_3(dmult, void, env, tl, tl)
|
||||
DEF_HELPER_3(dmultu, void, env, tl, tl)
|
||||
DEF_HELPER_4(dmult, void, env, int, tl, tl)
|
||||
DEF_HELPER_4(dmultu, void, env, int, tl, tl)
|
||||
#endif
|
||||
|
||||
DEF_HELPER_3(muls, tl, env, tl, tl)
|
||||
|
@@ -268,14 +268,16 @@ target_ulong helper_mulshiu(CPUMIPSState *env, target_ulong arg1,
|
||||
}
|
||||
|
||||
#ifdef TARGET_MIPS64
|
||||
void helper_dmult(CPUMIPSState *env, target_ulong arg1, target_ulong arg2)
|
||||
void helper_dmult(CPUMIPSState *env, int acc, target_ulong arg1,
|
||||
target_ulong arg2)
|
||||
{
|
||||
muls64(&(env->active_tc.LO[0]), &(env->active_tc.HI[0]), arg1, arg2);
|
||||
muls64(&(env->active_tc.LO[acc]), &(env->active_tc.HI[acc]), arg1, arg2);
|
||||
}
|
||||
|
||||
void helper_dmultu(CPUMIPSState *env, target_ulong arg1, target_ulong arg2)
|
||||
void helper_dmultu(CPUMIPSState *env, int acc, target_ulong arg1,
|
||||
target_ulong arg2)
|
||||
{
|
||||
mulu64(&(env->active_tc.LO[0]), &(env->active_tc.HI[0]), arg1, arg2);
|
||||
mulu64(&(env->active_tc.LO[acc]), &(env->active_tc.HI[acc]), arg1, arg2);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@@ -2582,10 +2582,9 @@ static void gen_shift(DisasContext *ctx, uint32_t opc,
|
||||
}
|
||||
|
||||
/* Arithmetic on HI/LO registers */
|
||||
static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg)
|
||||
static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg)
|
||||
{
|
||||
const char *opn = "hilo";
|
||||
unsigned int acc;
|
||||
|
||||
if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
|
||||
/* Treat as NOP. */
|
||||
@@ -2593,12 +2592,6 @@ static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg)
|
||||
return;
|
||||
}
|
||||
|
||||
if (opc == OPC_MFHI || opc == OPC_MFLO) {
|
||||
acc = ((ctx->opcode) >> 21) & 0x03;
|
||||
} else {
|
||||
acc = ((ctx->opcode) >> 11) & 0x03;
|
||||
}
|
||||
|
||||
if (acc != 0) {
|
||||
check_dsp(ctx);
|
||||
}
|
||||
@@ -2661,12 +2654,11 @@ static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg)
|
||||
MIPS_DEBUG("%s %s", opn, regnames[reg]);
|
||||
}
|
||||
|
||||
static void gen_muldiv (DisasContext *ctx, uint32_t opc,
|
||||
int rs, int rt)
|
||||
static void gen_muldiv(DisasContext *ctx, uint32_t opc,
|
||||
int acc, int rs, int rt)
|
||||
{
|
||||
const char *opn = "mul/div";
|
||||
TCGv t0, t1;
|
||||
unsigned int acc;
|
||||
|
||||
t0 = tcg_temp_new();
|
||||
t1 = tcg_temp_new();
|
||||
@@ -2674,6 +2666,10 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
|
||||
gen_load_gpr(t0, rs);
|
||||
gen_load_gpr(t1, rt);
|
||||
|
||||
if (acc != 0) {
|
||||
check_dsp(ctx);
|
||||
}
|
||||
|
||||
switch (opc) {
|
||||
case OPC_DIV:
|
||||
{
|
||||
@@ -2688,10 +2684,10 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
|
||||
tcg_gen_or_tl(t2, t2, t3);
|
||||
tcg_gen_movi_tl(t3, 0);
|
||||
tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
|
||||
tcg_gen_div_tl(cpu_LO[0], t0, t1);
|
||||
tcg_gen_rem_tl(cpu_HI[0], t0, t1);
|
||||
tcg_gen_ext32s_tl(cpu_LO[0], cpu_LO[0]);
|
||||
tcg_gen_ext32s_tl(cpu_HI[0], cpu_HI[0]);
|
||||
tcg_gen_div_tl(cpu_LO[acc], t0, t1);
|
||||
tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
|
||||
tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
|
||||
tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
|
||||
tcg_temp_free(t3);
|
||||
tcg_temp_free(t2);
|
||||
}
|
||||
@@ -2704,10 +2700,10 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
|
||||
tcg_gen_ext32u_tl(t0, t0);
|
||||
tcg_gen_ext32u_tl(t1, t1);
|
||||
tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
|
||||
tcg_gen_divu_tl(cpu_LO[0], t0, t1);
|
||||
tcg_gen_remu_tl(cpu_HI[0], t0, t1);
|
||||
tcg_gen_ext32s_tl(cpu_LO[0], cpu_LO[0]);
|
||||
tcg_gen_ext32s_tl(cpu_HI[0], cpu_HI[0]);
|
||||
tcg_gen_divu_tl(cpu_LO[acc], t0, t1);
|
||||
tcg_gen_remu_tl(cpu_HI[acc], t0, t1);
|
||||
tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
|
||||
tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
|
||||
tcg_temp_free(t3);
|
||||
tcg_temp_free(t2);
|
||||
}
|
||||
@@ -2717,11 +2713,6 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
|
||||
{
|
||||
TCGv_i64 t2 = tcg_temp_new_i64();
|
||||
TCGv_i64 t3 = tcg_temp_new_i64();
|
||||
acc = ((ctx->opcode) >> 11) & 0x03;
|
||||
if (acc != 0) {
|
||||
check_dsp(ctx);
|
||||
}
|
||||
|
||||
tcg_gen_ext_tl_i64(t2, t0);
|
||||
tcg_gen_ext_tl_i64(t3, t1);
|
||||
tcg_gen_mul_i64(t2, t2, t3);
|
||||
@@ -2739,11 +2730,6 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
|
||||
{
|
||||
TCGv_i64 t2 = tcg_temp_new_i64();
|
||||
TCGv_i64 t3 = tcg_temp_new_i64();
|
||||
acc = ((ctx->opcode) >> 11) & 0x03;
|
||||
if (acc != 0) {
|
||||
check_dsp(ctx);
|
||||
}
|
||||
|
||||
tcg_gen_ext32u_tl(t0, t0);
|
||||
tcg_gen_ext32u_tl(t1, t1);
|
||||
tcg_gen_extu_tl_i64(t2, t0);
|
||||
@@ -2771,8 +2757,8 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
|
||||
tcg_gen_or_tl(t2, t2, t3);
|
||||
tcg_gen_movi_tl(t3, 0);
|
||||
tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
|
||||
tcg_gen_div_tl(cpu_LO[0], t0, t1);
|
||||
tcg_gen_rem_tl(cpu_HI[0], t0, t1);
|
||||
tcg_gen_div_tl(cpu_LO[acc], t0, t1);
|
||||
tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
|
||||
tcg_temp_free(t3);
|
||||
tcg_temp_free(t2);
|
||||
}
|
||||
@@ -2783,19 +2769,19 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
|
||||
TCGv t2 = tcg_const_tl(0);
|
||||
TCGv t3 = tcg_const_tl(1);
|
||||
tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
|
||||
tcg_gen_divu_i64(cpu_LO[0], t0, t1);
|
||||
tcg_gen_remu_i64(cpu_HI[0], t0, t1);
|
||||
tcg_gen_divu_i64(cpu_LO[acc], t0, t1);
|
||||
tcg_gen_remu_i64(cpu_HI[acc], t0, t1);
|
||||
tcg_temp_free(t3);
|
||||
tcg_temp_free(t2);
|
||||
}
|
||||
opn = "ddivu";
|
||||
break;
|
||||
case OPC_DMULT:
|
||||
gen_helper_dmult(cpu_env, t0, t1);
|
||||
gen_helper_dmult(cpu_env, acc, t0, t1);
|
||||
opn = "dmult";
|
||||
break;
|
||||
case OPC_DMULTU:
|
||||
gen_helper_dmultu(cpu_env, t0, t1);
|
||||
gen_helper_dmultu(cpu_env, acc, t0, t1);
|
||||
opn = "dmultu";
|
||||
break;
|
||||
#endif
|
||||
@@ -2803,10 +2789,6 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
|
||||
{
|
||||
TCGv_i64 t2 = tcg_temp_new_i64();
|
||||
TCGv_i64 t3 = tcg_temp_new_i64();
|
||||
acc = ((ctx->opcode) >> 11) & 0x03;
|
||||
if (acc != 0) {
|
||||
check_dsp(ctx);
|
||||
}
|
||||
|
||||
tcg_gen_ext_tl_i64(t2, t0);
|
||||
tcg_gen_ext_tl_i64(t3, t1);
|
||||
@@ -2827,10 +2809,6 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
|
||||
{
|
||||
TCGv_i64 t2 = tcg_temp_new_i64();
|
||||
TCGv_i64 t3 = tcg_temp_new_i64();
|
||||
acc = ((ctx->opcode) >> 11) & 0x03;
|
||||
if (acc != 0) {
|
||||
check_dsp(ctx);
|
||||
}
|
||||
|
||||
tcg_gen_ext32u_tl(t0, t0);
|
||||
tcg_gen_ext32u_tl(t1, t1);
|
||||
@@ -2853,10 +2831,6 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
|
||||
{
|
||||
TCGv_i64 t2 = tcg_temp_new_i64();
|
||||
TCGv_i64 t3 = tcg_temp_new_i64();
|
||||
acc = ((ctx->opcode) >> 11) & 0x03;
|
||||
if (acc != 0) {
|
||||
check_dsp(ctx);
|
||||
}
|
||||
|
||||
tcg_gen_ext_tl_i64(t2, t0);
|
||||
tcg_gen_ext_tl_i64(t3, t1);
|
||||
@@ -2877,10 +2851,6 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
|
||||
{
|
||||
TCGv_i64 t2 = tcg_temp_new_i64();
|
||||
TCGv_i64 t3 = tcg_temp_new_i64();
|
||||
acc = ((ctx->opcode) >> 11) & 0x03;
|
||||
if (acc != 0) {
|
||||
check_dsp(ctx);
|
||||
}
|
||||
|
||||
tcg_gen_ext32u_tl(t0, t0);
|
||||
tcg_gen_ext32u_tl(t1, t1);
|
||||
@@ -10143,7 +10113,7 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx,
|
||||
gen_logic(ctx, OPC_NOR, rx, ry, 0);
|
||||
break;
|
||||
case RR_MFHI:
|
||||
gen_HILO(ctx, OPC_MFHI, rx);
|
||||
gen_HILO(ctx, OPC_MFHI, 0, rx);
|
||||
break;
|
||||
case RR_CNVT:
|
||||
switch (cnvt_op) {
|
||||
@@ -10175,7 +10145,7 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx,
|
||||
}
|
||||
break;
|
||||
case RR_MFLO:
|
||||
gen_HILO(ctx, OPC_MFLO, rx);
|
||||
gen_HILO(ctx, OPC_MFLO, 0, rx);
|
||||
break;
|
||||
#if defined (TARGET_MIPS64)
|
||||
case RR_DSRA:
|
||||
@@ -10196,33 +10166,33 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx,
|
||||
break;
|
||||
#endif
|
||||
case RR_MULT:
|
||||
gen_muldiv(ctx, OPC_MULT, rx, ry);
|
||||
gen_muldiv(ctx, OPC_MULT, 0, rx, ry);
|
||||
break;
|
||||
case RR_MULTU:
|
||||
gen_muldiv(ctx, OPC_MULTU, rx, ry);
|
||||
gen_muldiv(ctx, OPC_MULTU, 0, rx, ry);
|
||||
break;
|
||||
case RR_DIV:
|
||||
gen_muldiv(ctx, OPC_DIV, rx, ry);
|
||||
gen_muldiv(ctx, OPC_DIV, 0, rx, ry);
|
||||
break;
|
||||
case RR_DIVU:
|
||||
gen_muldiv(ctx, OPC_DIVU, rx, ry);
|
||||
gen_muldiv(ctx, OPC_DIVU, 0, rx, ry);
|
||||
break;
|
||||
#if defined (TARGET_MIPS64)
|
||||
case RR_DMULT:
|
||||
check_mips_64(ctx);
|
||||
gen_muldiv(ctx, OPC_DMULT, rx, ry);
|
||||
gen_muldiv(ctx, OPC_DMULT, 0, rx, ry);
|
||||
break;
|
||||
case RR_DMULTU:
|
||||
check_mips_64(ctx);
|
||||
gen_muldiv(ctx, OPC_DMULTU, rx, ry);
|
||||
gen_muldiv(ctx, OPC_DMULTU, 0, rx, ry);
|
||||
break;
|
||||
case RR_DDIV:
|
||||
check_mips_64(ctx);
|
||||
gen_muldiv(ctx, OPC_DDIV, rx, ry);
|
||||
gen_muldiv(ctx, OPC_DDIV, 0, rx, ry);
|
||||
break;
|
||||
case RR_DDIVU:
|
||||
check_mips_64(ctx);
|
||||
gen_muldiv(ctx, OPC_DDIVU, rx, ry);
|
||||
gen_muldiv(ctx, OPC_DDIVU, 0, rx, ry);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
@@ -10931,11 +10901,11 @@ static void gen_pool16c_insn(DisasContext *ctx, int *is_branch)
|
||||
break;
|
||||
case MFHI16 + 0:
|
||||
case MFHI16 + 1:
|
||||
gen_HILO(ctx, OPC_MFHI, uMIPS_RS5(ctx->opcode));
|
||||
gen_HILO(ctx, OPC_MFHI, 0, uMIPS_RS5(ctx->opcode));
|
||||
break;
|
||||
case MFLO16 + 0:
|
||||
case MFLO16 + 1:
|
||||
gen_HILO(ctx, OPC_MFLO, uMIPS_RS5(ctx->opcode));
|
||||
gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode));
|
||||
break;
|
||||
case BREAK16:
|
||||
generate_exception(ctx, EXCP_BREAK);
|
||||
@@ -11133,30 +11103,34 @@ static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs,
|
||||
break;
|
||||
case MULT:
|
||||
mips32_op = OPC_MULT;
|
||||
goto do_muldiv;
|
||||
goto do_mul;
|
||||
case MULTU:
|
||||
mips32_op = OPC_MULTU;
|
||||
goto do_muldiv;
|
||||
goto do_mul;
|
||||
case DIV:
|
||||
mips32_op = OPC_DIV;
|
||||
goto do_muldiv;
|
||||
goto do_div;
|
||||
case DIVU:
|
||||
mips32_op = OPC_DIVU;
|
||||
goto do_muldiv;
|
||||
goto do_div;
|
||||
do_div:
|
||||
check_insn(ctx, ISA_MIPS32);
|
||||
gen_muldiv(ctx, mips32_op, 0, rs, rt);
|
||||
break;
|
||||
case MADD:
|
||||
mips32_op = OPC_MADD;
|
||||
goto do_muldiv;
|
||||
goto do_mul;
|
||||
case MADDU:
|
||||
mips32_op = OPC_MADDU;
|
||||
goto do_muldiv;
|
||||
goto do_mul;
|
||||
case MSUB:
|
||||
mips32_op = OPC_MSUB;
|
||||
goto do_muldiv;
|
||||
goto do_mul;
|
||||
case MSUBU:
|
||||
mips32_op = OPC_MSUBU;
|
||||
do_muldiv:
|
||||
do_mul:
|
||||
check_insn(ctx, ISA_MIPS32);
|
||||
gen_muldiv(ctx, mips32_op, rs, rt);
|
||||
gen_muldiv(ctx, mips32_op, (ctx->opcode >> 14) & 3, rs, rt);
|
||||
break;
|
||||
default:
|
||||
goto pool32axf_invalid;
|
||||
@@ -11293,18 +11267,18 @@ static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs,
|
||||
}
|
||||
break;
|
||||
case 0x35:
|
||||
switch (minor) {
|
||||
switch (minor & 3) {
|
||||
case MFHI32:
|
||||
gen_HILO(ctx, OPC_MFHI, rs);
|
||||
gen_HILO(ctx, OPC_MFHI, minor >> 2, rs);
|
||||
break;
|
||||
case MFLO32:
|
||||
gen_HILO(ctx, OPC_MFLO, rs);
|
||||
gen_HILO(ctx, OPC_MFLO, minor >> 2, rs);
|
||||
break;
|
||||
case MTHI32:
|
||||
gen_HILO(ctx, OPC_MTHI, rs);
|
||||
gen_HILO(ctx, OPC_MTHI, minor >> 2, rs);
|
||||
break;
|
||||
case MTLO32:
|
||||
gen_HILO(ctx, OPC_MTLO, rs);
|
||||
gen_HILO(ctx, OPC_MTLO, minor >> 2, rs);
|
||||
break;
|
||||
default:
|
||||
goto pool32axf_invalid;
|
||||
@@ -14477,13 +14451,19 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
|
||||
case OPC_XOR:
|
||||
gen_logic(ctx, op1, rd, rs, rt);
|
||||
break;
|
||||
case OPC_MULT ... OPC_DIVU:
|
||||
case OPC_MULT:
|
||||
case OPC_MULTU:
|
||||
if (sa) {
|
||||
check_insn(ctx, INSN_VR54XX);
|
||||
op1 = MASK_MUL_VR54XX(ctx->opcode);
|
||||
gen_mul_vr54xx(ctx, op1, rd, rs, rt);
|
||||
} else
|
||||
gen_muldiv(ctx, op1, rs, rt);
|
||||
} else {
|
||||
gen_muldiv(ctx, op1, rd & 3, rs, rt);
|
||||
}
|
||||
break;
|
||||
case OPC_DIV:
|
||||
case OPC_DIVU:
|
||||
gen_muldiv(ctx, op1, 0, rs, rt);
|
||||
break;
|
||||
case OPC_JR ... OPC_JALR:
|
||||
gen_compute_branch(ctx, op1, 4, rs, rd, sa);
|
||||
@@ -14495,11 +14475,11 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
|
||||
break;
|
||||
case OPC_MFHI: /* Move from HI/LO */
|
||||
case OPC_MFLO:
|
||||
gen_HILO(ctx, op1, rd);
|
||||
gen_HILO(ctx, op1, rs & 3, rd);
|
||||
break;
|
||||
case OPC_MTHI:
|
||||
case OPC_MTLO: /* Move to HI/LO */
|
||||
gen_HILO(ctx, op1, rs);
|
||||
gen_HILO(ctx, op1, rd & 3, rs);
|
||||
break;
|
||||
case OPC_PMON: /* Pmon entry point, also R4010 selsl */
|
||||
#ifdef MIPS_STRICT_STANDARD
|
||||
@@ -14619,7 +14599,7 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
|
||||
case OPC_DMULT ... OPC_DDIVU:
|
||||
check_insn(ctx, ISA_MIPS3);
|
||||
check_mips_64(ctx);
|
||||
gen_muldiv(ctx, op1, rs, rt);
|
||||
gen_muldiv(ctx, op1, 0, rs, rt);
|
||||
break;
|
||||
#endif
|
||||
default: /* Invalid */
|
||||
@@ -14634,7 +14614,7 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
|
||||
case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
|
||||
case OPC_MSUB ... OPC_MSUBU:
|
||||
check_insn(ctx, ISA_MIPS32);
|
||||
gen_muldiv(ctx, op1, rs, rt);
|
||||
gen_muldiv(ctx, op1, rd & 3, rs, rt);
|
||||
break;
|
||||
case OPC_MUL:
|
||||
gen_arith(ctx, op1, rd, rs, rt);
|
||||
|
@@ -7282,7 +7282,7 @@ enum {
|
||||
#define CPU_POWERPC_MPC8545E_v10 CPU_POWERPC_e500v2_v10
|
||||
#define CPU_POWERPC_MPC8545E_v20 CPU_POWERPC_e500v2_v20
|
||||
#define CPU_POWERPC_MPC8545E_v21 CPU_POWERPC_e500v2_v21
|
||||
#define CPU_POWERPC_MPC8547E CPU_POWERPC_MPC8545E_v21
|
||||
#define CPU_POWERPC_MPC8547E CPU_POWERPC_MPC8547E_v21
|
||||
#define CPU_POWERPC_MPC8547E_v10 CPU_POWERPC_e500v2_v10
|
||||
#define CPU_POWERPC_MPC8547E_v20 CPU_POWERPC_e500v2_v20
|
||||
#define CPU_POWERPC_MPC8547E_v21 CPU_POWERPC_e500v2_v21
|
||||
@@ -8243,7 +8243,7 @@ static const ppc_def_t ppc_defs[] = {
|
||||
/* PowerPC G2LE GP1 core */
|
||||
POWERPC_DEF("G2leGP1", CPU_POWERPC_G2LEgp1, G2LE),
|
||||
/* PowerPC G2LE GP3 core */
|
||||
POWERPC_DEF("G2leGP3", CPU_POWERPC_G2LEgp1, G2LE),
|
||||
POWERPC_DEF("G2leGP3", CPU_POWERPC_G2LEgp3, G2LE),
|
||||
/* PowerPC MPC603 microcontrollers */
|
||||
/* MPC8240 */
|
||||
POWERPC_DEF("MPC8240", CPU_POWERPC_MPC8240, 603E),
|
||||
|
@@ -387,8 +387,8 @@ int main(int argc, char **argv)
|
||||
qtest_add_func("/rtc/alarm-time", alarm_time);
|
||||
qtest_add_func("/rtc/set-year/20xx", set_year_20xx);
|
||||
qtest_add_func("/rtc/set-year/1980", set_year_1980);
|
||||
qtest_add_func("/rtc/register_b_set_flag", register_b_set_flag);
|
||||
qtest_add_func("/rtc/fuzz-registers", fuzz_registers);
|
||||
qtest_add_func("/rtc/misc/register_b_set_flag", register_b_set_flag);
|
||||
qtest_add_func("/rtc/misc/fuzz-registers", fuzz_registers);
|
||||
ret = g_test_run();
|
||||
|
||||
if (s) {
|
||||
|
@@ -67,5 +67,28 @@ int main()
|
||||
assert(dsp == 0);
|
||||
assert(result == rt);
|
||||
|
||||
/* Clear dspcontrol */
|
||||
dsp = 0;
|
||||
__asm
|
||||
("wrdsp %0\n\t"
|
||||
:
|
||||
: "r"(dsp)
|
||||
);
|
||||
|
||||
ach = 0xFFFFFFFF;
|
||||
acl = 0xFFFFFFFF;
|
||||
result = 0;
|
||||
__asm
|
||||
("mthi %2, $ac1\n\t"
|
||||
"mtlo %3, $ac1\n\t"
|
||||
"extr_r.w %0, $ac1, 0x1F\n\t"
|
||||
"rddsp %1\n\t"
|
||||
: "=r"(rt), "=r"(dsp)
|
||||
: "r"(ach), "r"(acl)
|
||||
);
|
||||
dsp = (dsp >> 23) & 0x01;
|
||||
assert(dsp == 0);
|
||||
assert(result == rt);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@@ -67,5 +67,51 @@ int main()
|
||||
assert(dsp == 0);
|
||||
assert(result == rt);
|
||||
|
||||
/* Clear dspcontrol */
|
||||
dsp = 0;
|
||||
__asm
|
||||
("wrdsp %0\n\t"
|
||||
:
|
||||
: "r"(dsp)
|
||||
);
|
||||
|
||||
ach = 0x80000000;
|
||||
acl = 0x00000000;
|
||||
result = 0x80000000;
|
||||
__asm
|
||||
("mthi %2, $ac1\n\t"
|
||||
"mtlo %3, $ac1\n\t"
|
||||
"extr_rs.w %0, $ac1, 0x1F\n\t"
|
||||
"rddsp %1\n\t"
|
||||
: "=r"(rt), "=r"(dsp)
|
||||
: "r"(ach), "r"(acl)
|
||||
);
|
||||
dsp = (dsp >> 23) & 0x01;
|
||||
assert(dsp == 1);
|
||||
assert(result == rt);
|
||||
|
||||
/* Clear dspcontrol */
|
||||
dsp = 0;
|
||||
__asm
|
||||
("wrdsp %0\n\t"
|
||||
:
|
||||
: "r"(dsp)
|
||||
);
|
||||
|
||||
ach = 0xFFFFFFFF;
|
||||
acl = 0xFFFFFFFF;
|
||||
result = 0;
|
||||
__asm
|
||||
("mthi %2, $ac1\n\t"
|
||||
"mtlo %3, $ac1\n\t"
|
||||
"extr_rs.w %0, $ac1, 0x1F\n\t"
|
||||
"rddsp %1\n\t"
|
||||
: "=r"(rt), "=r"(dsp)
|
||||
: "r"(ach), "r"(acl)
|
||||
);
|
||||
dsp = (dsp >> 23) & 0x01;
|
||||
assert(dsp == 0);
|
||||
assert(result == rt);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@@ -67,5 +67,28 @@ int main()
|
||||
assert(dsp == 0);
|
||||
assert(result == rt);
|
||||
|
||||
/* Clear dspcontrol */
|
||||
dsp = 0;
|
||||
__asm
|
||||
("wrdsp %0\n\t"
|
||||
:
|
||||
: "r"(dsp)
|
||||
);
|
||||
|
||||
ach = 0xFFFFFFFF;
|
||||
acl = 0xFFFFFFFF;
|
||||
result = 0xFFFFFFFF;
|
||||
__asm
|
||||
("mthi %2, $ac1\n\t"
|
||||
"mtlo %3, $ac1\n\t"
|
||||
"extr.w %0, $ac1, 0x1F\n\t"
|
||||
"rddsp %1\n\t"
|
||||
: "=r"(rt), "=r"(dsp)
|
||||
: "r"(ach), "r"(acl)
|
||||
);
|
||||
dsp = (dsp >> 23) & 0x01;
|
||||
assert(dsp == 0);
|
||||
assert(result == rt);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@@ -12,7 +12,8 @@ int main()
|
||||
resultdsp = 0x01;
|
||||
|
||||
__asm
|
||||
("subq_s.ph %0, %2, %3\n\t"
|
||||
("wrdsp $0\n\t"
|
||||
"subq_s.ph %0, %2, %3\n\t"
|
||||
"rddsp %1\n\t"
|
||||
: "=r"(rd), "=r"(dsp)
|
||||
: "r"(rs), "r"(rt)
|
||||
@@ -27,7 +28,24 @@ int main()
|
||||
resultdsp = 0x01;
|
||||
|
||||
__asm
|
||||
("subq_s.ph %0, %2, %3\n\t"
|
||||
("wrdsp $0\n\t"
|
||||
"subq_s.ph %0, %2, %3\n\t"
|
||||
"rddsp %1\n\t"
|
||||
: "=r"(rd), "=r"(dsp)
|
||||
: "r"(rs), "r"(rt)
|
||||
);
|
||||
dsp = (dsp >> 20) & 0x01;
|
||||
assert(dsp == resultdsp);
|
||||
assert(rd == result);
|
||||
|
||||
rs = 0x12340000;
|
||||
rt = 0x87658000;
|
||||
result = 0x7FFF7FFF;
|
||||
resultdsp = 0x01;
|
||||
|
||||
__asm
|
||||
("wrdsp $0\n\t"
|
||||
"subq_s.ph %0, %2, %3\n\t"
|
||||
"rddsp %1\n\t"
|
||||
: "=r"(rd), "=r"(dsp)
|
||||
: "r"(rs), "r"(rt)
|
||||
|
@@ -12,7 +12,8 @@ int main()
|
||||
resultdsp = 0x01;
|
||||
|
||||
__asm
|
||||
("subq_s.w %0, %2, %3\n\t"
|
||||
("wrdsp $0\n\t"
|
||||
"subq_s.w %0, %2, %3\n\t"
|
||||
"rddsp %1\n\t"
|
||||
: "=r"(rd), "=r"(dsp)
|
||||
: "r"(rs), "r"(rt)
|
||||
@@ -24,10 +25,11 @@ int main()
|
||||
rs = 0x66666;
|
||||
rt = 0x55555;
|
||||
result = 0x11111;
|
||||
resultdsp = 0x01;
|
||||
resultdsp = 0x0;
|
||||
|
||||
__asm
|
||||
("subq_s.w %0, %2, %3\n\t"
|
||||
("wrdsp $0\n\t"
|
||||
"subq_s.w %0, %2, %3\n\t"
|
||||
"rddsp %1\n\t"
|
||||
: "=r"(rd), "=r"(dsp)
|
||||
: "r"(rs), "r"(rt)
|
||||
@@ -36,23 +38,37 @@ int main()
|
||||
assert(dsp == resultdsp);
|
||||
assert(rd == result);
|
||||
|
||||
|
||||
#if 0
|
||||
rs = 0x35555555;
|
||||
rt = 0xf5555555;
|
||||
result = 0x80000000;
|
||||
rs = 0x0;
|
||||
rt = 0x80000000;
|
||||
result = 0x7FFFFFFF;
|
||||
resultdsp = 0x01;
|
||||
|
||||
__asm
|
||||
("subq_s.w %0, %2, %3\n\t"
|
||||
("wrdsp $0\n\t"
|
||||
"subq_s.w %0, %2, %3\n\t"
|
||||
"rddsp %1\n\t"
|
||||
: "=r"(rd), "=r"(dsp)
|
||||
: "r"(rs), "r"(rt)
|
||||
);
|
||||
|
||||
dsp = (dsp >> 20) & 0x01;
|
||||
assert(dsp == resultdsp);
|
||||
assert(rd == result);
|
||||
#endif
|
||||
|
||||
rs = 0x80000000;
|
||||
rt = 0x80000000;
|
||||
result = 0;
|
||||
resultdsp = 0x00;
|
||||
|
||||
__asm
|
||||
("wrdsp $0\n\t"
|
||||
"subq_s.w %0, %2, %3\n\t"
|
||||
"rddsp %1\n\t"
|
||||
: "=r"(rd), "=r"(dsp)
|
||||
: "r"(rs), "r"(rt)
|
||||
);
|
||||
dsp = (dsp >> 20) & 0x01;
|
||||
assert(dsp == resultdsp);
|
||||
assert(rd == result);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@@ -8,7 +8,7 @@ int main()
|
||||
|
||||
rs = 0x80001234;
|
||||
rt = 0x80004321;
|
||||
result = 0x80005555;
|
||||
result = 0x7FFFAAAB;
|
||||
|
||||
__asm
|
||||
("mulq_rs.w %0, %1, %2\n\t"
|
||||
|
@@ -6,6 +6,21 @@ int main()
|
||||
int rd, rs, rt, dsp;
|
||||
int result, resultdsp;
|
||||
|
||||
rs = 0x80000000;
|
||||
rt = 0x0ffc0000;
|
||||
result = 0xF0040000;
|
||||
resultdsp = 0;
|
||||
|
||||
__asm
|
||||
("mulq_s.ph %0, %2, %3\n\t"
|
||||
"rddsp %1\n\t"
|
||||
: "=r"(rd), "=r"(dsp)
|
||||
: "r"(rs), "r"(rt)
|
||||
);
|
||||
dsp = (dsp >> 21) & 0x01;
|
||||
assert(rd == result);
|
||||
assert(dsp == resultdsp);
|
||||
|
||||
rs = 0x80001234;
|
||||
rt = 0x80004321;
|
||||
result = 0x7FFF098B;
|
||||
|
@@ -8,7 +8,7 @@ int main()
|
||||
|
||||
rs = 0x80001234;
|
||||
rt = 0x80004321;
|
||||
result = 0x80005555;
|
||||
result = 0x7FFFAAAB;
|
||||
|
||||
__asm
|
||||
("mulq_s.w %0, %1, %2\n\t"
|
||||
|
@@ -183,7 +183,7 @@ static void perf_nesting(void)
|
||||
double duration;
|
||||
|
||||
maxcycles = 100000000;
|
||||
maxnesting = 20000;
|
||||
maxnesting = 1000;
|
||||
Coroutine *root;
|
||||
NestData nd = {
|
||||
.n_enter = 0,
|
||||
|
@@ -460,6 +460,7 @@ scsi_req_data(int target, int lun, int tag, int len) "target %d lun %d tag %d le
|
||||
scsi_req_data_canceled(int target, int lun, int tag, int len) "target %d lun %d tag %d len %d"
|
||||
scsi_req_dequeue(int target, int lun, int tag) "target %d lun %d tag %d"
|
||||
scsi_req_continue(int target, int lun, int tag) "target %d lun %d tag %d"
|
||||
scsi_req_continue_canceled(int target, int lun, int tag) "target %d lun %d tag %d"
|
||||
scsi_req_parsed(int target, int lun, int tag, int cmd, int mode, int xfer) "target %d lun %d tag %d command %d dir %d length %d"
|
||||
scsi_req_parsed_lba(int target, int lun, int tag, int cmd, uint64_t lba) "target %d lun %d tag %d command %d lba %"PRIu64
|
||||
scsi_req_parse_bad(int target, int lun, int tag, int cmd) "target %d lun %d tag %d command %d"
|
||||
|
@@ -1310,10 +1310,10 @@ static void tb_link_page(TranslationBlock *tb, tb_page_addr_t phys_pc,
|
||||
/* check whether the given addr is in TCG generated code buffer or not */
|
||||
bool is_tcg_gen_code(uintptr_t tc_ptr)
|
||||
{
|
||||
/* This can be called during code generation, code_gen_buffer_max_size
|
||||
/* This can be called during code generation, code_gen_buffer_size
|
||||
is used instead of code_gen_ptr for upper boundary checking */
|
||||
return (tc_ptr >= (uintptr_t)code_gen_buffer &&
|
||||
tc_ptr < (uintptr_t)(code_gen_buffer + code_gen_buffer_max_size));
|
||||
tc_ptr < (uintptr_t)(code_gen_buffer + code_gen_buffer_size));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@@ -1339,11 +1339,16 @@ DisplaySurface *qemu_resize_displaysurface(DisplayState *ds,
|
||||
}
|
||||
|
||||
DisplaySurface *qemu_create_displaysurface_from(int width, int height, int bpp,
|
||||
int linesize, uint8_t *data)
|
||||
int linesize, uint8_t *data,
|
||||
bool byteswap)
|
||||
{
|
||||
DisplaySurface *surface = g_new0(DisplaySurface, 1);
|
||||
|
||||
surface->pf = qemu_default_pixelformat(bpp);
|
||||
if (byteswap) {
|
||||
surface->pf = qemu_different_endianness_pixelformat(bpp);
|
||||
} else {
|
||||
surface->pf = qemu_default_pixelformat(bpp);
|
||||
}
|
||||
|
||||
surface->format = qemu_pixman_get_format(&surface->pf);
|
||||
assert(surface->format != 0);
|
||||
|
2
ui/vnc.c
2
ui/vnc.c
@@ -2726,7 +2726,7 @@ static void vnc_connect(VncDisplay *vd, int csock, int skipauth, bool websocket)
|
||||
|
||||
VNC_DEBUG("New client on socket %d\n", csock);
|
||||
dcl->idle = 0;
|
||||
socket_set_nonblock(vs->csock);
|
||||
qemu_set_nonblock(vs->csock);
|
||||
#ifdef CONFIG_VNC_WS
|
||||
if (websocket) {
|
||||
vs->websocket = 1;
|
||||
|
@@ -134,14 +134,14 @@ void qemu_vfree(void *ptr)
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
void socket_set_block(int fd)
|
||||
void qemu_set_block(int fd)
|
||||
{
|
||||
int f;
|
||||
f = fcntl(fd, F_GETFL);
|
||||
fcntl(fd, F_SETFL, f & ~O_NONBLOCK);
|
||||
}
|
||||
|
||||
void socket_set_nonblock(int fd)
|
||||
void qemu_set_nonblock(int fd)
|
||||
{
|
||||
int f;
|
||||
f = fcntl(fd, F_GETFL);
|
||||
|
@@ -100,14 +100,14 @@ struct tm *localtime_r(const time_t *timep, struct tm *result)
|
||||
return p;
|
||||
}
|
||||
|
||||
void socket_set_block(int fd)
|
||||
void qemu_set_block(int fd)
|
||||
{
|
||||
unsigned long opt = 0;
|
||||
WSAEventSelect(fd, NULL, 0);
|
||||
ioctlsocket(fd, FIONBIO, &opt);
|
||||
}
|
||||
|
||||
void socket_set_nonblock(int fd)
|
||||
void qemu_set_nonblock(int fd)
|
||||
{
|
||||
unsigned long opt = 1;
|
||||
ioctlsocket(fd, FIONBIO, &opt);
|
||||
|
@@ -277,7 +277,7 @@ static int inet_connect_addr(struct addrinfo *addr, bool *in_progress,
|
||||
}
|
||||
qemu_setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
|
||||
if (connect_state != NULL) {
|
||||
socket_set_nonblock(sock);
|
||||
qemu_set_nonblock(sock);
|
||||
}
|
||||
/* connect to peer */
|
||||
do {
|
||||
@@ -733,7 +733,7 @@ int unix_connect_opts(QemuOpts *opts, Error **errp,
|
||||
connect_state = g_malloc0(sizeof(*connect_state));
|
||||
connect_state->callback = callback;
|
||||
connect_state->opaque = opaque;
|
||||
socket_set_nonblock(sock);
|
||||
qemu_set_nonblock(sock);
|
||||
}
|
||||
|
||||
memset(&un, 0, sizeof(un));
|
||||
@@ -906,6 +906,7 @@ int socket_connect(SocketAddress *addr, Error **errp,
|
||||
case SOCKET_ADDRESS_KIND_FD:
|
||||
fd = monitor_get_fd(cur_mon, addr->fd->str, errp);
|
||||
if (callback) {
|
||||
qemu_set_nonblock(fd);
|
||||
callback(fd, opaque);
|
||||
}
|
||||
break;
|
||||
|
@@ -49,9 +49,7 @@ int use_rt_clock;
|
||||
static void __attribute__((constructor)) init_get_clock(void)
|
||||
{
|
||||
use_rt_clock = 0;
|
||||
#if defined(__linux__) || (defined(__FreeBSD__) && __FreeBSD_version >= 500000) \
|
||||
|| defined(__DragonFly__) || defined(__FreeBSD_kernel__) \
|
||||
|| defined(__OpenBSD__)
|
||||
#ifdef CLOCK_MONOTONIC
|
||||
{
|
||||
struct timespec ts;
|
||||
if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) {
|
||||
|
Reference in New Issue
Block a user