mirror of https://gitee.com/openkylin/qemu.git
* NBD and chardev conversion to QIONetListener (Daniel)
* MTTCG fixes (David) * Hyper-V fixes (Roman, Evgeny) * share-rw option (Fam) * Mux chardev event bugfix (Marc-André) * Add systemd unit files in contrib/ (me) * SCSI and block/iscsi.c bugfixes (me, Peter L.) * unassigned_mem_ops fixes (Peter M.) * VEX decoding fix (Peter M.) * "info pic" and "info irq" improvements (Peter Xu) * vmport trace events (Philippe) * Braille chardev bugfix (Samuel) * Compiler warnings fix (Stefan) * initial support for TCG smoke test of more boards (Thomas) * New CPU features (Yang) * Reduce startup memory usage (Yang) * QemuThread race fix (linhecheng) -----BEGIN PGP SIGNATURE----- iQFIBAABCAAyFiEE8TM4V0tmI4mGbHaCv/vSX3jHroMFAlo7cTkUHHBib256aW5p QHJlZGhhdC5jb20ACgkQv/vSX3jHroPTsQf+IlIjTWnwBKaoECDo3t5Nulj84+O5 KLLwW7Yhy6vtu1U8N2kxzGickGf+wF1OEw0916Ku6b/P2jpKNogjDxXBQuO+uerG fPdc17gpSLcIXFzcfhiEH7pKJsdtcW+TTWPoF/RNK0KLP/tmJ+SBNNn0Ly0KRxQ9 t4YoMkFiybMZ+bpuixy/2TN2ZRwyuGdjXSiFLjium6ioPF262f4DqXV8PA7kfV8b FCANCql/p0HvAtURgzsJt0lfqAatKLOUELE4ClHBjUfGCLXAwMw8LQ0F/9jBAcaz fJov/RKjh5y2Av9mjCaTPEu+E550+4qdDcfpk2kuV8xH+CUspUpqGGm3jw== =y+Yl -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/bonzini/tags/for-upstream' into staging * NBD and chardev conversion to QIONetListener (Daniel) * MTTCG fixes (David) * Hyper-V fixes (Roman, Evgeny) * share-rw option (Fam) * Mux chardev event bugfix (Marc-André) * Add systemd unit files in contrib/ (me) * SCSI and block/iscsi.c bugfixes (me, Peter L.) * unassigned_mem_ops fixes (Peter M.) * VEX decoding fix (Peter M.) * "info pic" and "info irq" improvements (Peter Xu) * vmport trace events (Philippe) * Braille chardev bugfix (Samuel) * Compiler warnings fix (Stefan) * initial support for TCG smoke test of more boards (Thomas) * New CPU features (Yang) * Reduce startup memory usage (Yang) * QemuThread race fix (linhecheng) # gpg: Signature made Thu 21 Dec 2017 08:30:49 GMT # gpg: using RSA key 0xBFFBD25F78C7AE83 # gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>" # gpg: aka "Paolo Bonzini <pbonzini@redhat.com>" # Primary key fingerprint: 46F5 9FBD 57D6 12E7 BFD4 E2F7 7E15 100C CD36 69B1 # Subkey fingerprint: F133 3857 4B66 2389 866C 7682 BFFB D25F 78C7 AE83 * remotes/bonzini/tags/for-upstream: (41 commits) chardev: convert the socket server to QIONetListener blockdev: convert qemu-nbd server to QIONetListener blockdev: convert internal NBD server to QIONetListener test: add some chardev mux event tests chardev: fix backend events regression with mux chardev rcu: reduce more than 7MB heap memory by malloc_trim() checkpatch: volatile with a comment or sig_atomic_t is okay i8259: move TYPE_INTERRUPT_STATS_PROVIDER upper kvm-i8259: support "info pic" and "info irq" i8259: generalize statistics into common code i8259: use DEBUG_IRQ_COUNT always i8259: convert DPRINTFs into trace Remove legacy -no-kvm-pit option scsi: replace hex constants with #defines scsi: provide general-purpose functions to manage sense data hw/i386/vmport: replace fprintf() by trace events or LOG_UNIMP hw/mips/boston: Remove workaround for writes to ROM aborting exec: Don't reuse unassigned_mem_ops for io_mem_rom block/iscsi: only report an iSCSI Failure if we don't handle it gracefully block/iscsi: dont leave allocmap in an invalid state on UNMAP failure ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
23bafd75cd
|
@ -1011,6 +1011,7 @@ T: git git://github.com/jasowang/qemu.git net
|
|||
|
||||
SCSI
|
||||
M: Paolo Bonzini <pbonzini@redhat.com>
|
||||
R: Fam Zheng <famz@redhat.com>
|
||||
S: Supported
|
||||
F: include/hw/scsi/*
|
||||
F: hw/scsi/*
|
||||
|
@ -1271,6 +1272,7 @@ T: git git://github.com/stefanha/qemu.git block
|
|||
|
||||
Block SCSI subsystem
|
||||
M: Paolo Bonzini <pbonzini@redhat.com>
|
||||
R: Fam Zheng <famz@redhat.com>
|
||||
L: qemu-block@nongnu.org
|
||||
S: Supported
|
||||
F: include/scsi/*
|
||||
|
|
|
@ -525,19 +525,13 @@ static inline bool cpu_handle_interrupt(CPUState *cpu,
|
|||
TranslationBlock **last_tb)
|
||||
{
|
||||
CPUClass *cc = CPU_GET_CLASS(cpu);
|
||||
int32_t insns_left;
|
||||
|
||||
/* Clear the interrupt flag now since we're processing
|
||||
* cpu->interrupt_request and cpu->exit_request.
|
||||
* Ensure zeroing happens before reading cpu->exit_request or
|
||||
* cpu->interrupt_request (see also smp_wmb in cpu_exit())
|
||||
*/
|
||||
insns_left = atomic_read(&cpu->icount_decr.u32);
|
||||
atomic_set(&cpu->icount_decr.u16.high, 0);
|
||||
if (unlikely(insns_left < 0)) {
|
||||
/* Ensure the zeroing of icount_decr comes before the next read
|
||||
* of cpu->exit_request or cpu->interrupt_request.
|
||||
*/
|
||||
smp_mb();
|
||||
}
|
||||
atomic_mb_set(&cpu->icount_decr.u16.high, 0);
|
||||
|
||||
if (unlikely(atomic_read(&cpu->interrupt_request))) {
|
||||
int interrupt_request;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* QEMU Block driver for iSCSI images
|
||||
*
|
||||
* Copyright (c) 2010-2011 Ronnie Sahlberg <ronniesahlberg@gmail.com>
|
||||
* Copyright (c) 2012-2016 Peter Lieven <pl@kamp.de>
|
||||
* Copyright (c) 2012-2017 Peter Lieven <pl@kamp.de>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -104,6 +104,7 @@ typedef struct IscsiTask {
|
|||
IscsiLun *iscsilun;
|
||||
QEMUTimer retry_timer;
|
||||
int err_code;
|
||||
char *err_str;
|
||||
} IscsiTask;
|
||||
|
||||
typedef struct IscsiAIOCB {
|
||||
|
@ -265,7 +266,7 @@ iscsi_co_generic_cb(struct iscsi_context *iscsi, int status,
|
|||
}
|
||||
}
|
||||
iTask->err_code = iscsi_translate_sense(&task->sense);
|
||||
error_report("iSCSI Failure: %s", iscsi_get_error(iscsi));
|
||||
iTask->err_str = g_strdup(iscsi_get_error(iscsi));
|
||||
}
|
||||
|
||||
out:
|
||||
|
@ -629,6 +630,8 @@ retry:
|
|||
|
||||
if (iTask.status != SCSI_STATUS_GOOD) {
|
||||
iscsi_allocmap_set_invalid(iscsilun, sector_num, nb_sectors);
|
||||
error_report("iSCSI WRITE10/16 failed at lba %" PRIu64 ": %s", lba,
|
||||
iTask.err_str);
|
||||
r = iTask.err_code;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
@ -637,6 +640,7 @@ retry:
|
|||
|
||||
out_unlock:
|
||||
qemu_mutex_unlock(&iscsilun->mutex);
|
||||
g_free(iTask.err_str);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -651,10 +655,9 @@ static int64_t coroutine_fn iscsi_co_get_block_status(BlockDriverState *bs,
|
|||
struct scsi_get_lba_status *lbas = NULL;
|
||||
struct scsi_lba_status_descriptor *lbasd = NULL;
|
||||
struct IscsiTask iTask;
|
||||
uint64_t lba;
|
||||
int64_t ret;
|
||||
|
||||
iscsi_co_init_iscsitask(iscsilun, &iTask);
|
||||
|
||||
if (!is_sector_request_lun_aligned(sector_num, nb_sectors, iscsilun)) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
|
@ -670,11 +673,13 @@ static int64_t coroutine_fn iscsi_co_get_block_status(BlockDriverState *bs,
|
|||
goto out;
|
||||
}
|
||||
|
||||
lba = sector_qemu2lun(sector_num, iscsilun);
|
||||
|
||||
iscsi_co_init_iscsitask(iscsilun, &iTask);
|
||||
qemu_mutex_lock(&iscsilun->mutex);
|
||||
retry:
|
||||
if (iscsi_get_lba_status_task(iscsilun->iscsi, iscsilun->lun,
|
||||
sector_qemu2lun(sector_num, iscsilun),
|
||||
8 + 16, iscsi_co_generic_cb,
|
||||
lba, 8 + 16, iscsi_co_generic_cb,
|
||||
&iTask) == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto out_unlock;
|
||||
|
@ -701,6 +706,8 @@ retry:
|
|||
* because the device is busy or the cmd is not
|
||||
* supported) we pretend all blocks are allocated
|
||||
* for backwards compatibility */
|
||||
error_report("iSCSI GET_LBA_STATUS failed at lba %" PRIu64 ": %s",
|
||||
lba, iTask.err_str);
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
|
@ -738,6 +745,7 @@ retry:
|
|||
}
|
||||
out_unlock:
|
||||
qemu_mutex_unlock(&iscsilun->mutex);
|
||||
g_free(iTask.err_str);
|
||||
out:
|
||||
if (iTask.task != NULL) {
|
||||
scsi_free_scsi_task(iTask.task);
|
||||
|
@ -756,6 +764,7 @@ static int coroutine_fn iscsi_co_readv(BlockDriverState *bs,
|
|||
struct IscsiTask iTask;
|
||||
uint64_t lba;
|
||||
uint32_t num_sectors;
|
||||
int r = 0;
|
||||
|
||||
if (!is_sector_request_lun_aligned(sector_num, nb_sectors, iscsilun)) {
|
||||
return -EINVAL;
|
||||
|
@ -853,19 +862,23 @@ retry:
|
|||
iTask.complete = 0;
|
||||
goto retry;
|
||||
}
|
||||
qemu_mutex_unlock(&iscsilun->mutex);
|
||||
|
||||
if (iTask.status != SCSI_STATUS_GOOD) {
|
||||
return iTask.err_code;
|
||||
error_report("iSCSI READ10/16 failed at lba %" PRIu64 ": %s",
|
||||
lba, iTask.err_str);
|
||||
r = iTask.err_code;
|
||||
}
|
||||
|
||||
return 0;
|
||||
qemu_mutex_unlock(&iscsilun->mutex);
|
||||
g_free(iTask.err_str);
|
||||
return r;
|
||||
}
|
||||
|
||||
static int coroutine_fn iscsi_co_flush(BlockDriverState *bs)
|
||||
{
|
||||
IscsiLun *iscsilun = bs->opaque;
|
||||
struct IscsiTask iTask;
|
||||
int r = 0;
|
||||
|
||||
iscsi_co_init_iscsitask(iscsilun, &iTask);
|
||||
qemu_mutex_lock(&iscsilun->mutex);
|
||||
|
@ -892,13 +905,15 @@ retry:
|
|||
iTask.complete = 0;
|
||||
goto retry;
|
||||
}
|
||||
qemu_mutex_unlock(&iscsilun->mutex);
|
||||
|
||||
if (iTask.status != SCSI_STATUS_GOOD) {
|
||||
return iTask.err_code;
|
||||
error_report("iSCSI SYNCHRONIZECACHE10 failed: %s", iTask.err_str);
|
||||
r = iTask.err_code;
|
||||
}
|
||||
|
||||
return 0;
|
||||
qemu_mutex_unlock(&iscsilun->mutex);
|
||||
g_free(iTask.err_str);
|
||||
return r;
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
|
@ -1128,6 +1143,9 @@ retry:
|
|||
goto retry;
|
||||
}
|
||||
|
||||
iscsi_allocmap_set_invalid(iscsilun, offset >> BDRV_SECTOR_BITS,
|
||||
bytes >> BDRV_SECTOR_BITS);
|
||||
|
||||
if (iTask.status == SCSI_STATUS_CHECK_CONDITION) {
|
||||
/* the target might fail with a check condition if it
|
||||
is not happy with the alignment of the UNMAP request
|
||||
|
@ -1136,15 +1154,15 @@ retry:
|
|||
}
|
||||
|
||||
if (iTask.status != SCSI_STATUS_GOOD) {
|
||||
error_report("iSCSI UNMAP failed at lba %" PRIu64 ": %s",
|
||||
list.lba, iTask.err_str);
|
||||
r = iTask.err_code;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
iscsi_allocmap_set_invalid(iscsilun, offset >> BDRV_SECTOR_BITS,
|
||||
bytes >> BDRV_SECTOR_BITS);
|
||||
|
||||
out_unlock:
|
||||
qemu_mutex_unlock(&iscsilun->mutex);
|
||||
g_free(iTask.err_str);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -1241,6 +1259,8 @@ retry:
|
|||
if (iTask.status != SCSI_STATUS_GOOD) {
|
||||
iscsi_allocmap_set_invalid(iscsilun, offset >> BDRV_SECTOR_BITS,
|
||||
bytes >> BDRV_SECTOR_BITS);
|
||||
error_report("iSCSI WRITESAME10/16 failed at lba %" PRIu64 ": %s",
|
||||
lba, iTask.err_str);
|
||||
r = iTask.err_code;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
@ -1255,6 +1275,7 @@ retry:
|
|||
|
||||
out_unlock:
|
||||
qemu_mutex_unlock(&iscsilun->mutex);
|
||||
g_free(iTask.err_str);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
|
|
@ -18,10 +18,10 @@
|
|||
#include "qmp-commands.h"
|
||||
#include "block/nbd.h"
|
||||
#include "io/channel-socket.h"
|
||||
#include "io/net-listener.h"
|
||||
|
||||
typedef struct NBDServerData {
|
||||
QIOChannelSocket *listen_ioc;
|
||||
int watch;
|
||||
QIONetListener *listener;
|
||||
QCryptoTLSCreds *tlscreds;
|
||||
} NBDServerData;
|
||||
|
||||
|
@ -32,27 +32,13 @@ static void nbd_blockdev_client_closed(NBDClient *client, bool ignored)
|
|||
nbd_client_put(client);
|
||||
}
|
||||
|
||||
static gboolean nbd_accept(QIOChannel *ioc, GIOCondition condition,
|
||||
gpointer opaque)
|
||||
static void nbd_accept(QIONetListener *listener, QIOChannelSocket *cioc,
|
||||
gpointer opaque)
|
||||
{
|
||||
QIOChannelSocket *cioc;
|
||||
|
||||
if (!nbd_server) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
cioc = qio_channel_socket_accept(QIO_CHANNEL_SOCKET(ioc),
|
||||
NULL);
|
||||
if (!cioc) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
qio_channel_set_name(QIO_CHANNEL(cioc), "nbd-server");
|
||||
nbd_client_new(NULL, cioc,
|
||||
nbd_server->tlscreds, NULL,
|
||||
nbd_blockdev_client_closed);
|
||||
object_unref(OBJECT(cioc));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
@ -62,10 +48,8 @@ static void nbd_server_free(NBDServerData *server)
|
|||
return;
|
||||
}
|
||||
|
||||
if (server->watch != -1) {
|
||||
g_source_remove(server->watch);
|
||||
}
|
||||
object_unref(OBJECT(server->listen_ioc));
|
||||
qio_net_listener_disconnect(server->listener);
|
||||
object_unref(OBJECT(server->listener));
|
||||
if (server->tlscreds) {
|
||||
object_unref(OBJECT(server->tlscreds));
|
||||
}
|
||||
|
@ -112,12 +96,12 @@ void nbd_server_start(SocketAddress *addr, const char *tls_creds,
|
|||
}
|
||||
|
||||
nbd_server = g_new0(NBDServerData, 1);
|
||||
nbd_server->watch = -1;
|
||||
nbd_server->listen_ioc = qio_channel_socket_new();
|
||||
qio_channel_set_name(QIO_CHANNEL(nbd_server->listen_ioc),
|
||||
"nbd-listener");
|
||||
if (qio_channel_socket_listen_sync(
|
||||
nbd_server->listen_ioc, addr, errp) < 0) {
|
||||
nbd_server->listener = qio_net_listener_new();
|
||||
|
||||
qio_net_listener_set_name(nbd_server->listener,
|
||||
"nbd-listener");
|
||||
|
||||
if (qio_net_listener_open_sync(nbd_server->listener, addr, errp) < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
@ -134,12 +118,10 @@ void nbd_server_start(SocketAddress *addr, const char *tls_creds,
|
|||
}
|
||||
}
|
||||
|
||||
nbd_server->watch = qio_channel_add_watch(
|
||||
QIO_CHANNEL(nbd_server->listen_ioc),
|
||||
G_IO_IN,
|
||||
nbd_accept,
|
||||
NULL,
|
||||
NULL);
|
||||
qio_net_listener_set_client_func(nbd_server->listener,
|
||||
nbd_accept,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
return;
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* QEMU Baum Braille Device
|
||||
*
|
||||
* Copyright (c) 2008, 2010-2011, 2016 Samuel Thibault
|
||||
* Copyright (c) 2008, 2010-2011, 2016-2017 Samuel Thibault
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -239,6 +239,12 @@ static int baum_deferred_init(BaumChardev *baum)
|
|||
brlapi_perror("baum: brlapi__getDisplaySize");
|
||||
return 0;
|
||||
}
|
||||
if (baum->y > 1) {
|
||||
baum->y = 1;
|
||||
}
|
||||
if (baum->x > 84) {
|
||||
baum->x = 84;
|
||||
}
|
||||
|
||||
con = qemu_console_lookup_by_index(0);
|
||||
if (con && qemu_console_is_graphic(con)) {
|
||||
|
|
|
@ -123,6 +123,15 @@ static void mux_chr_send_event(MuxChardev *d, int mux_nr, int event)
|
|||
}
|
||||
}
|
||||
|
||||
static void mux_chr_be_event(Chardev *chr, int event)
|
||||
{
|
||||
MuxChardev *d = MUX_CHARDEV(chr);
|
||||
|
||||
if (d->focus != -1) {
|
||||
mux_chr_send_event(d, d->focus, event);
|
||||
}
|
||||
}
|
||||
|
||||
static int mux_proc_byte(Chardev *chr, MuxChardev *d, int ch)
|
||||
{
|
||||
if (d->term_got_escape) {
|
||||
|
@ -346,6 +355,7 @@ static void char_mux_class_init(ObjectClass *oc, void *data)
|
|||
cc->chr_write = mux_chr_write;
|
||||
cc->chr_accept_input = mux_chr_accept_input;
|
||||
cc->chr_add_watch = mux_chr_add_watch;
|
||||
cc->chr_be_event = mux_chr_be_event;
|
||||
}
|
||||
|
||||
static const TypeInfo char_mux_type_info = {
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "chardev/char.h"
|
||||
#include "io/channel-socket.h"
|
||||
#include "io/channel-tls.h"
|
||||
#include "io/net-listener.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qapi/clone-visitor.h"
|
||||
|
@ -40,8 +41,7 @@ typedef struct {
|
|||
Chardev parent;
|
||||
QIOChannel *ioc; /* Client I/O channel */
|
||||
QIOChannelSocket *sioc; /* Client master channel */
|
||||
QIOChannelSocket *listen_ioc;
|
||||
guint listen_tag;
|
||||
QIONetListener *listener;
|
||||
QCryptoTLSCreds *tls_creds;
|
||||
int connected;
|
||||
int max_size;
|
||||
|
@ -93,9 +93,9 @@ static void check_report_connect_error(Chardev *chr,
|
|||
qemu_chr_socket_restart_timer(chr);
|
||||
}
|
||||
|
||||
static gboolean tcp_chr_accept(QIOChannel *chan,
|
||||
GIOCondition cond,
|
||||
void *opaque);
|
||||
static void tcp_chr_accept(QIONetListener *listener,
|
||||
QIOChannelSocket *cioc,
|
||||
void *opaque);
|
||||
|
||||
static int tcp_chr_read_poll(void *opaque);
|
||||
static void tcp_chr_disconnect(Chardev *chr);
|
||||
|
@ -401,9 +401,9 @@ static void tcp_chr_disconnect(Chardev *chr)
|
|||
|
||||
tcp_chr_free_connection(chr);
|
||||
|
||||
if (s->listen_ioc && s->listen_tag == 0) {
|
||||
s->listen_tag = qio_channel_add_watch(
|
||||
QIO_CHANNEL(s->listen_ioc), G_IO_IN, tcp_chr_accept, chr, NULL);
|
||||
if (s->listener) {
|
||||
qio_net_listener_set_client_func(s->listener, tcp_chr_accept,
|
||||
chr, NULL);
|
||||
}
|
||||
update_disconnected_filename(s);
|
||||
if (emit_close) {
|
||||
|
@ -702,9 +702,8 @@ static int tcp_chr_new_client(Chardev *chr, QIOChannelSocket *sioc)
|
|||
if (s->do_nodelay) {
|
||||
qio_channel_set_delay(s->ioc, false);
|
||||
}
|
||||
if (s->listen_tag) {
|
||||
g_source_remove(s->listen_tag);
|
||||
s->listen_tag = 0;
|
||||
if (s->listener) {
|
||||
qio_net_listener_set_client_func(s->listener, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
if (s->tls_creds) {
|
||||
|
@ -736,24 +735,14 @@ static int tcp_chr_add_client(Chardev *chr, int fd)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static gboolean tcp_chr_accept(QIOChannel *channel,
|
||||
GIOCondition cond,
|
||||
void *opaque)
|
||||
static void tcp_chr_accept(QIONetListener *listener,
|
||||
QIOChannelSocket *cioc,
|
||||
void *opaque)
|
||||
{
|
||||
Chardev *chr = CHARDEV(opaque);
|
||||
QIOChannelSocket *sioc;
|
||||
|
||||
sioc = qio_channel_socket_accept(QIO_CHANNEL_SOCKET(channel),
|
||||
NULL);
|
||||
if (!sioc) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
tcp_chr_new_client(chr, sioc);
|
||||
|
||||
object_unref(OBJECT(sioc));
|
||||
|
||||
return TRUE;
|
||||
tcp_chr_set_client_ioc_name(chr, cioc);
|
||||
tcp_chr_new_client(chr, cioc);
|
||||
}
|
||||
|
||||
static int tcp_chr_wait_connected(Chardev *chr, Error **errp)
|
||||
|
@ -767,9 +756,10 @@ static int tcp_chr_wait_connected(Chardev *chr, Error **errp)
|
|||
if (s->is_listen) {
|
||||
info_report("QEMU waiting for connection on: %s",
|
||||
chr->filename);
|
||||
qio_channel_set_blocking(QIO_CHANNEL(s->listen_ioc), true, NULL);
|
||||
tcp_chr_accept(QIO_CHANNEL(s->listen_ioc), G_IO_IN, chr);
|
||||
qio_channel_set_blocking(QIO_CHANNEL(s->listen_ioc), false, NULL);
|
||||
sioc = qio_net_listener_wait_client(s->listener);
|
||||
tcp_chr_set_client_ioc_name(chr, sioc);
|
||||
tcp_chr_new_client(chr, sioc);
|
||||
object_unref(OBJECT(sioc));
|
||||
} else {
|
||||
sioc = qio_channel_socket_new();
|
||||
tcp_chr_set_client_ioc_name(chr, sioc);
|
||||
|
@ -797,12 +787,9 @@ static void char_socket_finalize(Object *obj)
|
|||
s->reconnect_timer = 0;
|
||||
}
|
||||
qapi_free_SocketAddress(s->addr);
|
||||
if (s->listen_tag) {
|
||||
g_source_remove(s->listen_tag);
|
||||
s->listen_tag = 0;
|
||||
}
|
||||
if (s->listen_ioc) {
|
||||
object_unref(OBJECT(s->listen_ioc));
|
||||
if (s->listener) {
|
||||
qio_net_listener_set_client_func(s->listener, NULL, NULL, NULL);
|
||||
object_unref(OBJECT(s->listener));
|
||||
}
|
||||
if (s->tls_creds) {
|
||||
object_unref(OBJECT(s->tls_creds));
|
||||
|
@ -935,29 +922,29 @@ static void qmp_chardev_open_socket(Chardev *chr,
|
|||
} else {
|
||||
if (s->is_listen) {
|
||||
char *name;
|
||||
sioc = qio_channel_socket_new();
|
||||
s->listener = qio_net_listener_new();
|
||||
|
||||
name = g_strdup_printf("chardev-tcp-listener-%s", chr->label);
|
||||
qio_channel_set_name(QIO_CHANNEL(sioc), name);
|
||||
qio_net_listener_set_name(s->listener, name);
|
||||
g_free(name);
|
||||
|
||||
if (qio_channel_socket_listen_sync(sioc, s->addr, errp) < 0) {
|
||||
if (qio_net_listener_open_sync(s->listener, s->addr, errp) < 0) {
|
||||
object_unref(OBJECT(s->listener));
|
||||
s->listener = NULL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
qapi_free_SocketAddress(s->addr);
|
||||
s->addr = socket_local_address(sioc->fd, errp);
|
||||
s->addr = socket_local_address(s->listener->sioc[0]->fd, errp);
|
||||
update_disconnected_filename(s);
|
||||
|
||||
s->listen_ioc = sioc;
|
||||
if (is_waitconnect &&
|
||||
qemu_chr_wait_connected(chr, errp) < 0) {
|
||||
return;
|
||||
}
|
||||
if (!s->ioc) {
|
||||
s->listen_tag = qio_channel_add_watch(
|
||||
QIO_CHANNEL(s->listen_ioc), G_IO_IN,
|
||||
tcp_chr_accept, chr, NULL);
|
||||
qio_net_listener_set_client_func(s->listener, tcp_chr_accept,
|
||||
chr, NULL);
|
||||
}
|
||||
} else if (qemu_chr_wait_connected(chr, errp) < 0) {
|
||||
goto error;
|
||||
|
|
|
@ -43,10 +43,19 @@ static Object *get_chardevs_root(void)
|
|||
return container_get(object_get_root(), "/chardevs");
|
||||
}
|
||||
|
||||
void qemu_chr_be_event(Chardev *s, int event)
|
||||
static void chr_be_event(Chardev *s, int event)
|
||||
{
|
||||
CharBackend *be = s->be;
|
||||
|
||||
if (!be || !be->chr_event) {
|
||||
return;
|
||||
}
|
||||
|
||||
be->chr_event(be->opaque, event);
|
||||
}
|
||||
|
||||
void qemu_chr_be_event(Chardev *s, int event)
|
||||
{
|
||||
/* Keep track if the char device is open */
|
||||
switch (event) {
|
||||
case CHR_EVENT_OPENED:
|
||||
|
@ -57,11 +66,7 @@ void qemu_chr_be_event(Chardev *s, int event)
|
|||
break;
|
||||
}
|
||||
|
||||
if (!be || !be->chr_event) {
|
||||
return;
|
||||
}
|
||||
|
||||
be->chr_event(be->opaque, event);
|
||||
CHARDEV_GET_CLASS(s)->chr_be_event(s, event);
|
||||
}
|
||||
|
||||
/* Not reporting errors from writing to logfile, as logs are
|
||||
|
@ -244,6 +249,7 @@ static void char_class_init(ObjectClass *oc, void *data)
|
|||
ChardevClass *cc = CHARDEV_CLASS(oc);
|
||||
|
||||
cc->chr_write = null_chr_write;
|
||||
cc->chr_be_event = chr_be_event;
|
||||
}
|
||||
|
||||
static void char_finalize(Object *obj)
|
||||
|
|
|
@ -426,6 +426,7 @@ vxhs=""
|
|||
supported_cpu="no"
|
||||
supported_os="no"
|
||||
bogus_os="no"
|
||||
malloc_trim=""
|
||||
|
||||
# parse CC options first
|
||||
for opt do
|
||||
|
@ -1047,6 +1048,10 @@ for opt do
|
|||
;;
|
||||
--enable-tcg) tcg="yes"
|
||||
;;
|
||||
--disable-malloc-trim) malloc_trim="no"
|
||||
;;
|
||||
--enable-malloc-trim) malloc_trim="yes"
|
||||
;;
|
||||
--disable-spice) spice="no"
|
||||
;;
|
||||
--enable-spice) spice="yes"
|
||||
|
@ -1466,6 +1471,7 @@ Advanced options (experts only):
|
|||
Default:trace-<pid>
|
||||
--disable-slirp disable SLIRP userspace network connectivity
|
||||
--enable-tcg-interpreter enable TCG with bytecode interpreter (TCI)
|
||||
--enable-malloc-trim enable libc malloc_trim() for memory optimization
|
||||
--oss-lib path to OSS library
|
||||
--cpu=CPU Build for host CPU [$cpu]
|
||||
--with-coroutine=BACKEND coroutine backend. Supported options:
|
||||
|
@ -3860,6 +3866,30 @@ if test "$tcmalloc" = "yes" && test "$jemalloc" = "yes" ; then
|
|||
exit 1
|
||||
fi
|
||||
|
||||
# Even if malloc_trim() is available, these non-libc memory allocators
|
||||
# do not support it.
|
||||
if test "$tcmalloc" = "yes" || test "$jemalloc" = "yes" ; then
|
||||
if test "$malloc_trim" = "yes" ; then
|
||||
echo "Disabling malloc_trim with non-libc memory allocator"
|
||||
fi
|
||||
malloc_trim="no"
|
||||
fi
|
||||
|
||||
#######################################
|
||||
# malloc_trim
|
||||
|
||||
if test "$malloc_trim" != "no" ; then
|
||||
cat > $TMPC << EOF
|
||||
#include <malloc.h>
|
||||
int main(void) { malloc_trim(0); return 0; }
|
||||
EOF
|
||||
if compile_prog "" "" ; then
|
||||
malloc_trim="yes"
|
||||
else
|
||||
malloc_trim="no"
|
||||
fi
|
||||
fi
|
||||
|
||||
##########################################
|
||||
# tcmalloc probe
|
||||
|
||||
|
@ -3923,7 +3953,7 @@ fi
|
|||
# check if memfd is supported
|
||||
memfd=no
|
||||
cat > $TMPC << EOF
|
||||
#include <sys/memfd.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
|
@ -5505,6 +5535,7 @@ if test "$tcg" = "yes" ; then
|
|||
echo "TCG debug enabled $debug_tcg"
|
||||
echo "TCG interpreter $tcg_interpreter"
|
||||
fi
|
||||
echo "malloc trim support $malloc_trim"
|
||||
echo "RDMA support $rdma"
|
||||
echo "fdt support $fdt"
|
||||
echo "preadv support $preadv"
|
||||
|
@ -6015,6 +6046,10 @@ if test "$opengl" = "yes" ; then
|
|||
fi
|
||||
fi
|
||||
|
||||
if test "$malloc_trim" = "yes" ; then
|
||||
echo "CONFIG_MALLOC_TRIM=y" >> $config_host_mak
|
||||
fi
|
||||
|
||||
if test "$avx2_opt" = "yes" ; then
|
||||
echo "CONFIG_AVX2_OPT=y" >> $config_host_mak
|
||||
fi
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
[Unit]
|
||||
Description=QEMU Guest Agent
|
||||
BindTo=dev-virtio\x2dports-org.qemu.guest_agent.0.device
|
||||
After=dev-virtio\x2dports-org.qemu.guest_agent.0.device
|
||||
|
||||
[Service]
|
||||
ExecStart=-/usr/bin/qemu-ga
|
||||
Restart=always
|
||||
RestartSec=0
|
||||
|
||||
[Install]
|
|
@ -0,0 +1,15 @@
|
|||
[Unit]
|
||||
Description=Persistent Reservation Daemon for QEMU
|
||||
|
||||
[Service]
|
||||
WorkingDirectory=/tmp
|
||||
Type=simple
|
||||
ExecStart=/usr/bin/qemu-pr-helper
|
||||
PrivateTmp=yes
|
||||
ProtectSystem=strict
|
||||
ReadWritePaths=/var/run
|
||||
RestrictAddressFamilies=AF_UNIX
|
||||
Restart=always
|
||||
RestartSec=0
|
||||
|
||||
[Install]
|
|
@ -0,0 +1,9 @@
|
|||
[Unit]
|
||||
Description=Persistent Reservation Daemon for QEMU
|
||||
|
||||
[Socket]
|
||||
ListenStream=/run/qemu-pr-helper.sock
|
||||
SocketMode=0600
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
37
cpus.c
37
cpus.c
|
@ -1057,13 +1057,22 @@ static void qemu_tcg_destroy_vcpu(CPUState *cpu)
|
|||
{
|
||||
}
|
||||
|
||||
static void qemu_cpu_stop(CPUState *cpu, bool exit)
|
||||
{
|
||||
g_assert(qemu_cpu_is_self(cpu));
|
||||
cpu->stop = false;
|
||||
cpu->stopped = true;
|
||||
if (exit) {
|
||||
cpu_exit(cpu);
|
||||
}
|
||||
qemu_cond_broadcast(&qemu_pause_cond);
|
||||
}
|
||||
|
||||
static void qemu_wait_io_event_common(CPUState *cpu)
|
||||
{
|
||||
atomic_mb_set(&cpu->thread_kicked, false);
|
||||
if (cpu->stop) {
|
||||
cpu->stop = false;
|
||||
cpu->stopped = true;
|
||||
qemu_cond_broadcast(&qemu_pause_cond);
|
||||
qemu_cpu_stop(cpu, false);
|
||||
}
|
||||
process_queued_cpu_work(cpu);
|
||||
}
|
||||
|
@ -1610,12 +1619,12 @@ void pause_all_vcpus(void)
|
|||
|
||||
qemu_clock_enable(QEMU_CLOCK_VIRTUAL, false);
|
||||
CPU_FOREACH(cpu) {
|
||||
cpu->stop = true;
|
||||
qemu_cpu_kick(cpu);
|
||||
}
|
||||
|
||||
if (qemu_in_vcpu_thread()) {
|
||||
cpu_stop_current();
|
||||
if (qemu_cpu_is_self(cpu)) {
|
||||
qemu_cpu_stop(cpu, true);
|
||||
} else {
|
||||
cpu->stop = true;
|
||||
qemu_cpu_kick(cpu);
|
||||
}
|
||||
}
|
||||
|
||||
while (!all_vcpus_paused()) {
|
||||
|
@ -1778,11 +1787,8 @@ void qemu_init_vcpu(CPUState *cpu)
|
|||
/* If the target cpu hasn't set up any address spaces itself,
|
||||
* give it the default one.
|
||||
*/
|
||||
AddressSpace *as = g_new0(AddressSpace, 1);
|
||||
|
||||
address_space_init(as, cpu->memory, "cpu-memory");
|
||||
cpu->num_ases = 1;
|
||||
cpu_address_space_init(cpu, as, 0);
|
||||
cpu_address_space_init(cpu, 0, "cpu-memory", cpu->memory);
|
||||
}
|
||||
|
||||
if (kvm_enabled()) {
|
||||
|
@ -1799,10 +1805,7 @@ void qemu_init_vcpu(CPUState *cpu)
|
|||
void cpu_stop_current(void)
|
||||
{
|
||||
if (current_cpu) {
|
||||
current_cpu->stop = false;
|
||||
current_cpu->stopped = true;
|
||||
cpu_exit(current_cpu);
|
||||
qemu_cond_broadcast(&qemu_pause_cond);
|
||||
qemu_cpu_stop(current_cpu, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
44
exec.c
44
exec.c
|
@ -705,9 +705,17 @@ CPUState *qemu_get_cpu(int index)
|
|||
}
|
||||
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
void cpu_address_space_init(CPUState *cpu, AddressSpace *as, int asidx)
|
||||
void cpu_address_space_init(CPUState *cpu, int asidx,
|
||||
const char *prefix, MemoryRegion *mr)
|
||||
{
|
||||
CPUAddressSpace *newas;
|
||||
AddressSpace *as = g_new0(AddressSpace, 1);
|
||||
char *as_name;
|
||||
|
||||
assert(mr);
|
||||
as_name = g_strdup_printf("%s-%d", prefix, cpu->cpu_index);
|
||||
address_space_init(as, mr, as_name);
|
||||
g_free(as_name);
|
||||
|
||||
/* Target code should have set num_ases before calling us */
|
||||
assert(asidx < cpu->num_ases);
|
||||
|
@ -2717,6 +2725,37 @@ static uint16_t dummy_section(PhysPageMap *map, FlatView *fv, MemoryRegion *mr)
|
|||
return phys_section_add(map, §ion);
|
||||
}
|
||||
|
||||
static void readonly_mem_write(void *opaque, hwaddr addr,
|
||||
uint64_t val, unsigned size)
|
||||
{
|
||||
/* Ignore any write to ROM. */
|
||||
}
|
||||
|
||||
static bool readonly_mem_accepts(void *opaque, hwaddr addr,
|
||||
unsigned size, bool is_write)
|
||||
{
|
||||
return is_write;
|
||||
}
|
||||
|
||||
/* This will only be used for writes, because reads are special cased
|
||||
* to directly access the underlying host ram.
|
||||
*/
|
||||
static const MemoryRegionOps readonly_mem_ops = {
|
||||
.write = readonly_mem_write,
|
||||
.valid.accepts = readonly_mem_accepts,
|
||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||
.valid = {
|
||||
.min_access_size = 1,
|
||||
.max_access_size = 8,
|
||||
.unaligned = false,
|
||||
},
|
||||
.impl = {
|
||||
.min_access_size = 1,
|
||||
.max_access_size = 8,
|
||||
.unaligned = false,
|
||||
},
|
||||
};
|
||||
|
||||
MemoryRegion *iotlb_to_region(CPUState *cpu, hwaddr index, MemTxAttrs attrs)
|
||||
{
|
||||
int asidx = cpu_asidx_from_attrs(cpu, attrs);
|
||||
|
@ -2729,7 +2768,8 @@ MemoryRegion *iotlb_to_region(CPUState *cpu, hwaddr index, MemTxAttrs attrs)
|
|||
|
||||
static void io_mem_init(void)
|
||||
{
|
||||
memory_region_init_io(&io_mem_rom, NULL, &unassigned_mem_ops, NULL, NULL, UINT64_MAX);
|
||||
memory_region_init_io(&io_mem_rom, NULL, &readonly_mem_ops,
|
||||
NULL, NULL, UINT64_MAX);
|
||||
memory_region_init_io(&io_mem_unassigned, NULL, &unassigned_mem_ops, NULL,
|
||||
NULL, UINT64_MAX);
|
||||
|
||||
|
|
|
@ -111,6 +111,7 @@ static void kvm_pic_set_irq(void *opaque, int irq, int level)
|
|||
{
|
||||
int delivered;
|
||||
|
||||
pic_stat_update_irq(irq, level);
|
||||
delivered = kvm_set_irq(kvm_state, irq, level);
|
||||
apic_report_irq_delivered(delivered);
|
||||
}
|
||||
|
|
|
@ -113,3 +113,7 @@ amdvi_mode_invalid(uint8_t level, uint64_t addr)"error: translation level 0x%"PR
|
|||
amdvi_page_fault(uint64_t addr) "error: page fault accessing guest physical address 0x%"PRIx64
|
||||
amdvi_iotlb_hit(uint8_t bus, uint8_t slot, uint8_t func, uint64_t addr, uint64_t txaddr) "hit iotlb devid %02x:%02x.%x gpa 0x%"PRIx64" hpa 0x%"PRIx64
|
||||
amdvi_translation_result(uint8_t bus, uint8_t slot, uint8_t func, uint64_t addr, uint64_t txaddr) "devid: %02x:%02x.%x gpa 0x%"PRIx64" hpa 0x%"PRIx64
|
||||
|
||||
# hw/i386/vmport.c
|
||||
vmport_register(unsigned char command, void *func, void *opaque) "command: 0x%02x func: %p opaque: %p"
|
||||
vmport_command(unsigned char command) "command: 0x%02x"
|
||||
|
|
|
@ -27,8 +27,7 @@
|
|||
#include "hw/i386/pc.h"
|
||||
#include "sysemu/hw_accel.h"
|
||||
#include "hw/qdev.h"
|
||||
|
||||
/* #define VMPORT_DEBUG */
|
||||
#include "trace.h"
|
||||
|
||||
#define VMPORT_CMD_GETVERSION 0x0a
|
||||
#define VMPORT_CMD_GETRAMSIZE 0x14
|
||||
|
@ -54,6 +53,7 @@ void vmport_register(unsigned char command, VMPortReadFunc *func, void *opaque)
|
|||
return;
|
||||
}
|
||||
|
||||
trace_vmport_register(command, func, opaque);
|
||||
port_state->func[command] = func;
|
||||
port_state->opaque[command] = opaque;
|
||||
}
|
||||
|
@ -76,13 +76,9 @@ static uint64_t vmport_ioport_read(void *opaque, hwaddr addr,
|
|||
}
|
||||
|
||||
command = env->regs[R_ECX];
|
||||
if (command >= VMPORT_ENTRIES) {
|
||||
return eax;
|
||||
}
|
||||
if (!s->func[command]) {
|
||||
#ifdef VMPORT_DEBUG
|
||||
fprintf(stderr, "vmport: unknown command %x\n", command);
|
||||
#endif
|
||||
trace_vmport_command(command);
|
||||
if (command >= VMPORT_ENTRIES || !s->func[command]) {
|
||||
qemu_log_mask(LOG_UNIMP, "vmport: unknown command %x\n", command);
|
||||
return eax;
|
||||
}
|
||||
|
||||
|
|
|
@ -25,24 +25,15 @@
|
|||
#include "hw/hw.h"
|
||||
#include "hw/i386/pc.h"
|
||||
#include "hw/isa/isa.h"
|
||||
#include "monitor/monitor.h"
|
||||
#include "qemu/timer.h"
|
||||
#include "qemu/log.h"
|
||||
#include "hw/isa/i8259_internal.h"
|
||||
#include "hw/intc/intc.h"
|
||||
#include "trace.h"
|
||||
|
||||
/* debug PIC */
|
||||
//#define DEBUG_PIC
|
||||
|
||||
#ifdef DEBUG_PIC
|
||||
#define DPRINTF(fmt, ...) \
|
||||
do { printf("pic: " fmt , ## __VA_ARGS__); } while (0)
|
||||
#else
|
||||
#define DPRINTF(fmt, ...)
|
||||
#endif
|
||||
|
||||
//#define DEBUG_IRQ_LATENCY
|
||||
//#define DEBUG_IRQ_COUNT
|
||||
|
||||
#define TYPE_I8259 "isa-i8259"
|
||||
#define PIC_CLASS(class) OBJECT_CLASS_CHECK(PICClass, (class), TYPE_I8259)
|
||||
|
@ -58,12 +49,6 @@ typedef struct PICClass {
|
|||
DeviceRealize parent_realize;
|
||||
} PICClass;
|
||||
|
||||
#if defined(DEBUG_PIC) || defined(DEBUG_IRQ_COUNT)
|
||||
static int irq_level[16];
|
||||
#endif
|
||||
#ifdef DEBUG_IRQ_COUNT
|
||||
static uint64_t irq_count[16];
|
||||
#endif
|
||||
#ifdef DEBUG_IRQ_LATENCY
|
||||
static int64_t irq_time[16];
|
||||
#endif
|
||||
|
@ -122,8 +107,7 @@ static void pic_update_irq(PICCommonState *s)
|
|||
|
||||
irq = pic_get_irq(s);
|
||||
if (irq >= 0) {
|
||||
DPRINTF("pic%d: imr=%x irr=%x padd=%d\n",
|
||||
s->master ? 0 : 1, s->imr, s->irr, s->priority_add);
|
||||
trace_pic_update_irq(s->master, s->imr, s->irr, s->priority_add);
|
||||
qemu_irq_raise(s->int_out[0]);
|
||||
} else {
|
||||
qemu_irq_lower(s->int_out[0]);
|
||||
|
@ -135,22 +119,11 @@ static void pic_set_irq(void *opaque, int irq, int level)
|
|||
{
|
||||
PICCommonState *s = opaque;
|
||||
int mask = 1 << irq;
|
||||
|
||||
#if defined(DEBUG_PIC) || defined(DEBUG_IRQ_COUNT) || \
|
||||
defined(DEBUG_IRQ_LATENCY)
|
||||
int irq_index = s->master ? irq : irq + 8;
|
||||
#endif
|
||||
#if defined(DEBUG_PIC) || defined(DEBUG_IRQ_COUNT)
|
||||
if (level != irq_level[irq_index]) {
|
||||
DPRINTF("pic_set_irq: irq=%d level=%d\n", irq_index, level);
|
||||
irq_level[irq_index] = level;
|
||||
#ifdef DEBUG_IRQ_COUNT
|
||||
if (level == 1) {
|
||||
irq_count[irq_index]++;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
trace_pic_set_irq(s->master, irq, level);
|
||||
pic_stat_update_irq(irq_index, level);
|
||||
|
||||
#ifdef DEBUG_IRQ_LATENCY
|
||||
if (level) {
|
||||
irq_time[irq_index] = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
|
||||
|
@ -223,18 +196,18 @@ int pic_read_irq(DeviceState *d)
|
|||
intno = s->irq_base + irq;
|
||||
}
|
||||
|
||||
#if defined(DEBUG_PIC) || defined(DEBUG_IRQ_LATENCY)
|
||||
if (irq == 2) {
|
||||
irq = irq2 + 8;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_IRQ_LATENCY
|
||||
printf("IRQ%d latency=%0.3fus\n",
|
||||
irq,
|
||||
(double)(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) -
|
||||
irq_time[irq]) * 1000000.0 / NANOSECONDS_PER_SECOND);
|
||||
#endif
|
||||
DPRINTF("pic_interrupt: irq=%d\n", irq);
|
||||
|
||||
trace_pic_interrupt(irq, intno);
|
||||
return intno;
|
||||
}
|
||||
|
||||
|
@ -252,35 +225,6 @@ static void pic_reset(DeviceState *dev)
|
|||
pic_init_reset(s);
|
||||
}
|
||||
|
||||
static bool pic_get_statistics(InterruptStatsProvider *obj,
|
||||
uint64_t **irq_counts, unsigned int *nb_irqs)
|
||||
{
|
||||
PICCommonState *s = PIC_COMMON(obj);
|
||||
|
||||
if (s->master) {
|
||||
#ifdef DEBUG_IRQ_COUNT
|
||||
*irq_counts = irq_count;
|
||||
*nb_irqs = ARRAY_SIZE(irq_count);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
} else {
|
||||
*irq_counts = NULL;
|
||||
*nb_irqs = 0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void pic_print_info(InterruptStatsProvider *obj, Monitor *mon)
|
||||
{
|
||||
PICCommonState *s = PIC_COMMON(obj);
|
||||
monitor_printf(mon, "pic%d: irr=%02x imr=%02x isr=%02x hprio=%d "
|
||||
"irq_base=%02x rr_sel=%d elcr=%02x fnm=%d\n",
|
||||
s->master ? 0 : 1, s->irr, s->imr, s->isr, s->priority_add,
|
||||
s->irq_base, s->read_reg_select, s->elcr,
|
||||
s->special_fully_nested_mode);
|
||||
}
|
||||
|
||||
static void pic_ioport_write(void *opaque, hwaddr addr64,
|
||||
uint64_t val64, unsigned size)
|
||||
{
|
||||
|
@ -289,7 +233,8 @@ static void pic_ioport_write(void *opaque, hwaddr addr64,
|
|||
uint32_t val = val64;
|
||||
int priority, cmd, irq;
|
||||
|
||||
DPRINTF("write: addr=0x%02x val=0x%02x\n", addr, val);
|
||||
trace_pic_ioport_write(s->master, addr, val);
|
||||
|
||||
if (addr == 0) {
|
||||
if (val & 0x10) {
|
||||
pic_init_reset(s);
|
||||
|
@ -402,7 +347,7 @@ static uint64_t pic_ioport_read(void *opaque, hwaddr addr,
|
|||
ret = s->imr;
|
||||
}
|
||||
}
|
||||
DPRINTF("read: addr=0x%02" HWADDR_PRIx " val=0x%02x\n", addr, ret);
|
||||
trace_pic_ioport_read(s->master, addr, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -497,13 +442,10 @@ static void i8259_class_init(ObjectClass *klass, void *data)
|
|||
{
|
||||
PICClass *k = PIC_CLASS(klass);
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
InterruptStatsProviderClass *ic = INTERRUPT_STATS_PROVIDER_CLASS(klass);
|
||||
|
||||
k->parent_realize = dc->realize;
|
||||
dc->realize = pic_realize;
|
||||
dc->reset = pic_reset;
|
||||
ic->get_statistics = pic_get_statistics;
|
||||
ic->print_info = pic_print_info;
|
||||
}
|
||||
|
||||
static const TypeInfo i8259_info = {
|
||||
|
@ -512,10 +454,6 @@ static const TypeInfo i8259_info = {
|
|||
.parent = TYPE_PIC_COMMON,
|
||||
.class_init = i8259_class_init,
|
||||
.class_size = sizeof(PICClass),
|
||||
.interfaces = (InterfaceInfo[]) {
|
||||
{ TYPE_INTERRUPT_STATS_PROVIDER },
|
||||
{ }
|
||||
},
|
||||
};
|
||||
|
||||
static void pic_register_types(void)
|
||||
|
|
|
@ -25,6 +25,10 @@
|
|||
#include "qemu/osdep.h"
|
||||
#include "hw/i386/pc.h"
|
||||
#include "hw/isa/i8259_internal.h"
|
||||
#include "monitor/monitor.h"
|
||||
|
||||
static int irq_level[16];
|
||||
static uint64_t irq_count[16];
|
||||
|
||||
void pic_reset_common(PICCommonState *s)
|
||||
{
|
||||
|
@ -98,6 +102,44 @@ ISADevice *i8259_init_chip(const char *name, ISABus *bus, bool master)
|
|||
return isadev;
|
||||
}
|
||||
|
||||
void pic_stat_update_irq(int irq, int level)
|
||||
{
|
||||
if (level != irq_level[irq]) {
|
||||
irq_level[irq] = level;
|
||||
if (level == 1) {
|
||||
irq_count[irq]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool pic_get_statistics(InterruptStatsProvider *obj,
|
||||
uint64_t **irq_counts, unsigned int *nb_irqs)
|
||||
{
|
||||
PICCommonState *s = PIC_COMMON(obj);
|
||||
|
||||
if (s->master) {
|
||||
*irq_counts = irq_count;
|
||||
*nb_irqs = ARRAY_SIZE(irq_count);
|
||||
} else {
|
||||
*irq_counts = NULL;
|
||||
*nb_irqs = 0;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void pic_print_info(InterruptStatsProvider *obj, Monitor *mon)
|
||||
{
|
||||
PICCommonState *s = PIC_COMMON(obj);
|
||||
|
||||
pic_dispatch_pre_save(s);
|
||||
monitor_printf(mon, "pic%d: irr=%02x imr=%02x isr=%02x hprio=%d "
|
||||
"irq_base=%02x rr_sel=%d elcr=%02x fnm=%d\n",
|
||||
s->master ? 0 : 1, s->irr, s->imr, s->isr, s->priority_add,
|
||||
s->irq_base, s->read_reg_select, s->elcr,
|
||||
s->special_fully_nested_mode);
|
||||
}
|
||||
|
||||
static const VMStateDescription vmstate_pic_common = {
|
||||
.name = "i8259",
|
||||
.version_id = 1,
|
||||
|
@ -136,6 +178,7 @@ static Property pic_properties_common[] = {
|
|||
static void pic_common_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
InterruptStatsProviderClass *ic = INTERRUPT_STATS_PROVIDER_CLASS(klass);
|
||||
|
||||
dc->vmsd = &vmstate_pic_common;
|
||||
dc->props = pic_properties_common;
|
||||
|
@ -147,6 +190,8 @@ static void pic_common_class_init(ObjectClass *klass, void *data)
|
|||
* code.
|
||||
*/
|
||||
dc->user_creatable = false;
|
||||
ic->get_statistics = pic_get_statistics;
|
||||
ic->print_info = pic_print_info;
|
||||
}
|
||||
|
||||
static const TypeInfo pic_common_type = {
|
||||
|
@ -156,6 +201,10 @@ static const TypeInfo pic_common_type = {
|
|||
.class_size = sizeof(PICCommonClass),
|
||||
.class_init = pic_common_class_init,
|
||||
.abstract = true,
|
||||
.interfaces = (InterfaceInfo[]) {
|
||||
{ TYPE_INTERRUPT_STATS_PROVIDER },
|
||||
{ }
|
||||
},
|
||||
};
|
||||
|
||||
static void pic_common_register_types(void)
|
||||
|
|
|
@ -1,5 +1,12 @@
|
|||
# See docs/devel/tracing.txt for syntax documentation.
|
||||
|
||||
# hw/intc/i8259.c
|
||||
pic_update_irq(bool master, uint8_t imr, uint8_t irr, uint8_t padd) "master %d imr %"PRIu8" irr %"PRIu8" padd %"PRIu8
|
||||
pic_set_irq(bool master, int irq, int level) "master %d irq %d level %d"
|
||||
pic_interrupt(int irq, int intno) "irq %d intno %d"
|
||||
pic_ioport_write(bool master, uint64_t addr, uint64_t val) "master %d addr 0x%"PRIx64" val 0x%"PRIx64
|
||||
pic_ioport_read(bool master, uint64_t addr, int val) "master %d addr 0x%"PRIx64" val 0x%x"
|
||||
|
||||
# hw/intc/apic_common.c
|
||||
cpu_set_apic_base(uint64_t val) "0x%016"PRIx64
|
||||
cpu_get_apic_base(uint64_t val) "0x%016"PRIx64
|
||||
|
|
|
@ -248,16 +248,6 @@ static const MemoryRegionOps boston_platreg_ops = {
|
|||
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||
};
|
||||
|
||||
static void boston_flash_write(void *opaque, hwaddr addr,
|
||||
uint64_t val, unsigned size)
|
||||
{
|
||||
}
|
||||
|
||||
static const MemoryRegionOps boston_flash_ops = {
|
||||
.write = boston_flash_write,
|
||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||
};
|
||||
|
||||
static const TypeInfo boston_device = {
|
||||
.name = TYPE_MIPS_BOSTON,
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
|
@ -481,8 +471,8 @@ static void boston_mach_init(MachineState *machine)
|
|||
sysbus_mmio_map_overlap(SYS_BUS_DEVICE(s->cps), 0, 0, 1);
|
||||
|
||||
flash = g_new(MemoryRegion, 1);
|
||||
memory_region_init_rom_device_nomigrate(flash, NULL, &boston_flash_ops, s,
|
||||
"boston.flash", 128 * M_BYTE, &err);
|
||||
memory_region_init_rom_nomigrate(flash, NULL,
|
||||
"boston.flash", 128 * M_BYTE, &err);
|
||||
memory_region_add_subregion_overlap(sys_mem, 0x18000000, flash, 0);
|
||||
|
||||
ddr = g_new(MemoryRegion, 1);
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
* THE SOFTWARE.
|
||||
*/
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qemu-common.h"
|
||||
#include "cpu.h"
|
||||
|
@ -40,6 +41,8 @@
|
|||
#include "elf.h"
|
||||
|
||||
#define PHYS_MEM_BASE 0x80000000
|
||||
#define FIRMWARE_BASE 0x1000
|
||||
#define FIRMWARE_SIZE (128 * 0x1000)
|
||||
|
||||
typedef struct {
|
||||
uint64_t ram_size;
|
||||
|
@ -122,8 +125,8 @@ static void moxiesim_init(MachineState *machine)
|
|||
memory_region_init_ram(ram, NULL, "moxiesim.ram", ram_size, &error_fatal);
|
||||
memory_region_add_subregion(address_space_mem, ram_base, ram);
|
||||
|
||||
memory_region_init_ram(rom, NULL, "moxie.rom", 128 * 0x1000, &error_fatal);
|
||||
memory_region_add_subregion(get_system_memory(), 0x1000, rom);
|
||||
memory_region_init_ram(rom, NULL, "moxie.rom", FIRMWARE_SIZE, &error_fatal);
|
||||
memory_region_add_subregion(get_system_memory(), FIRMWARE_BASE, rom);
|
||||
|
||||
if (kernel_filename) {
|
||||
loader_params.ram_size = ram_size;
|
||||
|
@ -132,6 +135,11 @@ static void moxiesim_init(MachineState *machine)
|
|||
loader_params.initrd_filename = initrd_filename;
|
||||
load_kernel(cpu, &loader_params);
|
||||
}
|
||||
if (bios_name) {
|
||||
if (load_image_targphys(bios_name, FIRMWARE_BASE, FIRMWARE_SIZE) < 0) {
|
||||
error_report("Failed to load firmware '%s'", bios_name);
|
||||
}
|
||||
}
|
||||
|
||||
/* A single 16450 sits at offset 0x3f8. */
|
||||
if (serial_hds[0]) {
|
||||
|
|
|
@ -540,20 +540,8 @@ static int32_t scsi_target_send_command(SCSIRequest *req, uint8_t *buf)
|
|||
if (req->lun != 0) {
|
||||
const struct SCSISense sense = SENSE_CODE(LUN_NOT_SUPPORTED);
|
||||
|
||||
if (fixed_sense) {
|
||||
r->buf[0] = 0x70;
|
||||
r->buf[2] = sense.key;
|
||||
r->buf[10] = 10;
|
||||
r->buf[12] = sense.asc;
|
||||
r->buf[13] = sense.ascq;
|
||||
r->len = MIN(req->cmd.xfer, SCSI_SENSE_LEN);
|
||||
} else {
|
||||
r->buf[0] = 0x72;
|
||||
r->buf[1] = sense.key;
|
||||
r->buf[2] = sense.asc;
|
||||
r->buf[3] = sense.ascq;
|
||||
r->len = 8;
|
||||
}
|
||||
r->len = scsi_build_sense_buf(r->buf, req->cmd.xfer,
|
||||
sense, fixed_sense);
|
||||
} else {
|
||||
r->len = scsi_device_get_sense(r->req.dev, r->buf,
|
||||
MIN(req->cmd.xfer, r->buf_len),
|
||||
|
|
|
@ -3004,6 +3004,7 @@ static const TypeInfo scsi_cd_info = {
|
|||
static Property scsi_block_properties[] = {
|
||||
DEFINE_BLOCK_ERROR_PROPERTIES(SCSIDiskState, qdev.conf), \
|
||||
DEFINE_PROP_DRIVE("drive", SCSIDiskState, qdev.conf.blk),
|
||||
DEFINE_PROP_BOOL("share-rw", SCSIDiskState, qdev.conf.share_rw, false),
|
||||
DEFINE_PROP_UINT16("rotation_rate", SCSIDiskState, rotation_rate, 0),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
|
|
@ -248,6 +248,7 @@ typedef struct ChardevClass {
|
|||
void (*chr_accept_input)(Chardev *chr);
|
||||
void (*chr_set_echo)(Chardev *chr, bool echo);
|
||||
void (*chr_set_fe_open)(Chardev *chr, int fe_open);
|
||||
void (*chr_be_event)(Chardev *s, int event);
|
||||
} ChardevClass;
|
||||
|
||||
Chardev *qemu_chardev_new(const char *id, const char *typename,
|
||||
|
|
|
@ -74,8 +74,9 @@ void cpu_reloading_memory_map(void);
|
|||
/**
|
||||
* cpu_address_space_init:
|
||||
* @cpu: CPU to add this address space to
|
||||
* @as: address space to add
|
||||
* @asidx: integer index of this address space
|
||||
* @prefix: prefix to be used as name of address space
|
||||
* @mr: the root memory region of address space
|
||||
*
|
||||
* Add the specified address space to the CPU's cpu_ases list.
|
||||
* The address space added with @asidx 0 is the one used for the
|
||||
|
@ -89,7 +90,8 @@ void cpu_reloading_memory_map(void);
|
|||
*
|
||||
* Note that with KVM only one address space is supported.
|
||||
*/
|
||||
void cpu_address_space_init(CPUState *cpu, AddressSpace *as, int asidx);
|
||||
void cpu_address_space_init(CPUState *cpu, int asidx,
|
||||
const char *prefix, MemoryRegion *mr);
|
||||
#endif
|
||||
|
||||
#if !defined(CONFIG_USER_ONLY) && defined(CONFIG_TCG)
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "hw/hw.h"
|
||||
#include "hw/i386/pc.h"
|
||||
#include "hw/isa/isa.h"
|
||||
#include "hw/intc/intc.h"
|
||||
|
||||
typedef struct PICCommonState PICCommonState;
|
||||
|
||||
|
@ -76,8 +77,10 @@ struct PICCommonState {
|
|||
};
|
||||
|
||||
void pic_reset_common(PICCommonState *s);
|
||||
|
||||
ISADevice *i8259_init_chip(const char *name, ISABus *bus, bool master);
|
||||
|
||||
void pic_stat_update_irq(int irq, int level);
|
||||
bool pic_get_statistics(InterruptStatsProvider *obj,
|
||||
uint64_t **irq_counts, unsigned int *nb_irqs);
|
||||
void pic_print_info(InterruptStatsProvider *obj, Monitor *mon);
|
||||
|
||||
#endif /* QEMU_I8259_INTERNAL_H */
|
||||
|
|
|
@ -35,7 +35,7 @@ int inet_connect_saddr(InetSocketAddress *saddr, Error **errp);
|
|||
|
||||
NetworkAddressFamily inet_netfamily(int family);
|
||||
|
||||
int unix_listen(const char *path, char *ostr, int olen, Error **errp);
|
||||
int unix_listen(const char *path, Error **errp);
|
||||
int unix_connect(const char *path, Error **errp);
|
||||
|
||||
SocketAddress *socket_parse(const char *str, Error **errp);
|
||||
|
|
|
@ -31,6 +31,9 @@ typedef struct SCSISense {
|
|||
} SCSISense;
|
||||
|
||||
int scsi_build_sense(uint8_t *buf, SCSISense sense);
|
||||
SCSISense scsi_parse_sense_buf(const uint8_t *in_buf, int in_len);
|
||||
int scsi_build_sense_buf(uint8_t *buf, size_t max_size, SCSISense sense,
|
||||
bool fixed_sense);
|
||||
|
||||
/*
|
||||
* Predefined sense codes
|
||||
|
@ -76,7 +79,11 @@ extern const struct SCSISense sense_code_LUN_FAILURE;
|
|||
extern const struct SCSISense sense_code_LUN_COMM_FAILURE;
|
||||
/* Command aborted, Overlapped Commands Attempted */
|
||||
extern const struct SCSISense sense_code_OVERLAPPED_COMMANDS;
|
||||
/* LUN not ready, Capacity data has changed */
|
||||
/* Medium error, Unrecovered read error */
|
||||
extern const struct SCSISense sense_code_READ_ERROR;
|
||||
/* LUN not ready, Cause not reportable */
|
||||
extern const struct SCSISense sense_code_NOT_READY;
|
||||
/* Unit attention, Capacity data has changed */
|
||||
extern const struct SCSISense sense_code_CAPACITY_CHANGED;
|
||||
/* Unit attention, SCSI bus reset */
|
||||
extern const struct SCSISense sense_code_SCSI_BUS_RESET;
|
||||
|
|
|
@ -2612,11 +2612,6 @@ synonym for setting ``-global kvm-pit.lost_tick_policy=discard''.
|
|||
The ``-no-kvm-irqchip'' argument is now a synonym for
|
||||
setting ``-machine kernel_irqchip=off''.
|
||||
|
||||
@subsection -no-kvm-pit (since 1.3.0)
|
||||
|
||||
The ``-no-kvm-pit'' argument is ignored. It is no longer
|
||||
possible to disable the KVM PIT directly.
|
||||
|
||||
@subsection -no-kvm (since 1.3.0)
|
||||
|
||||
The ``-no-kvm'' argument is now a synonym for setting
|
||||
|
|
61
qemu-nbd.c
61
qemu-nbd.c
|
@ -37,6 +37,7 @@
|
|||
#include "qapi/qmp/qstring.h"
|
||||
#include "qom/object_interfaces.h"
|
||||
#include "io/channel-socket.h"
|
||||
#include "io/net-listener.h"
|
||||
#include "crypto/init.h"
|
||||
#include "trace/control.h"
|
||||
#include "qemu-version.h"
|
||||
|
@ -62,8 +63,7 @@ static int persistent = 0;
|
|||
static enum { RUNNING, TERMINATE, TERMINATING, TERMINATED } state;
|
||||
static int shared = 1;
|
||||
static int nb_fds;
|
||||
static QIOChannelSocket *server_ioc;
|
||||
static int server_watch = -1;
|
||||
static QIONetListener *server;
|
||||
static QCryptoTLSCreds *tlscreds;
|
||||
|
||||
static void usage(const char *name)
|
||||
|
@ -344,44 +344,25 @@ static void nbd_client_closed(NBDClient *client, bool negotiated)
|
|||
nbd_client_put(client);
|
||||
}
|
||||
|
||||
static gboolean nbd_accept(QIOChannel *ioc, GIOCondition cond, gpointer opaque)
|
||||
static void nbd_accept(QIONetListener *listener, QIOChannelSocket *cioc,
|
||||
gpointer opaque)
|
||||
{
|
||||
QIOChannelSocket *cioc;
|
||||
|
||||
cioc = qio_channel_socket_accept(QIO_CHANNEL_SOCKET(ioc),
|
||||
NULL);
|
||||
if (!cioc) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (state >= TERMINATE) {
|
||||
object_unref(OBJECT(cioc));
|
||||
return TRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
nb_fds++;
|
||||
nbd_update_server_watch();
|
||||
nbd_client_new(newproto ? NULL : exp, cioc,
|
||||
tlscreds, NULL, nbd_client_closed);
|
||||
object_unref(OBJECT(cioc));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void nbd_update_server_watch(void)
|
||||
{
|
||||
if (nbd_can_accept()) {
|
||||
if (server_watch == -1) {
|
||||
server_watch = qio_channel_add_watch(QIO_CHANNEL(server_ioc),
|
||||
G_IO_IN,
|
||||
nbd_accept,
|
||||
NULL, NULL);
|
||||
}
|
||||
qio_net_listener_set_client_func(server, nbd_accept, NULL, NULL);
|
||||
} else {
|
||||
if (server_watch != -1) {
|
||||
g_source_remove(server_watch);
|
||||
server_watch = -1;
|
||||
}
|
||||
qio_net_listener_set_client_func(server, NULL, NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -915,23 +896,29 @@ int main(int argc, char **argv)
|
|||
snprintf(sockpath, 128, SOCKET_PATH, basename(device));
|
||||
}
|
||||
|
||||
server = qio_net_listener_new();
|
||||
if (socket_activation == 0) {
|
||||
server_ioc = qio_channel_socket_new();
|
||||
saddr = nbd_build_socket_address(sockpath, bindto, port);
|
||||
if (qio_channel_socket_listen_sync(server_ioc, saddr, &local_err) < 0) {
|
||||
object_unref(OBJECT(server_ioc));
|
||||
if (qio_net_listener_open_sync(server, saddr, &local_err) < 0) {
|
||||
object_unref(OBJECT(server));
|
||||
error_report_err(local_err);
|
||||
return 1;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
} else {
|
||||
size_t i;
|
||||
/* See comment in check_socket_activation above. */
|
||||
assert(socket_activation == 1);
|
||||
server_ioc = qio_channel_socket_new_fd(FIRST_SOCKET_ACTIVATION_FD,
|
||||
&local_err);
|
||||
if (server_ioc == NULL) {
|
||||
error_report("Failed to use socket activation: %s",
|
||||
error_get_pretty(local_err));
|
||||
exit(EXIT_FAILURE);
|
||||
for (i = 0; i < socket_activation; i++) {
|
||||
QIOChannelSocket *sioc;
|
||||
sioc = qio_channel_socket_new_fd(FIRST_SOCKET_ACTIVATION_FD + i,
|
||||
&local_err);
|
||||
if (sioc == NULL) {
|
||||
object_unref(OBJECT(server));
|
||||
error_report("Failed to use socket activation: %s",
|
||||
error_get_pretty(local_err));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
qio_net_listener_add(server, sioc);
|
||||
object_unref(OBJECT(sioc));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3927,9 +3927,6 @@ HXCOMM Deprecated by kvm-pit driver properties
|
|||
DEF("no-kvm-pit-reinjection", 0, QEMU_OPTION_no_kvm_pit_reinjection,
|
||||
"", QEMU_ARCH_I386)
|
||||
|
||||
HXCOMM Deprecated (ignored)
|
||||
DEF("no-kvm-pit", 0, QEMU_OPTION_no_kvm_pit, "", QEMU_ARCH_I386)
|
||||
|
||||
HXCOMM Deprecated by -machine kernel_irqchip=on|off property
|
||||
DEF("no-kvm-irqchip", 0, QEMU_OPTION_no_kvm_irqchip, "", QEMU_ARCH_I386)
|
||||
|
||||
|
|
|
@ -190,7 +190,7 @@ static gboolean ga_channel_open(GAChannel *c, const gchar *path,
|
|||
if (fd < 0) {
|
||||
Error *local_err = NULL;
|
||||
|
||||
fd = unix_listen(path, NULL, strlen(path), &local_err);
|
||||
fd = unix_listen(path, &local_err);
|
||||
if (local_err != NULL) {
|
||||
g_critical("%s", error_get_pretty(local_err));
|
||||
error_free(local_err);
|
||||
|
|
|
@ -2475,8 +2475,11 @@ sub process {
|
|||
|
||||
# no volatiles please
|
||||
my $asm_volatile = qr{\b(__asm__|asm)\s+(__volatile__|volatile)\b};
|
||||
if ($line =~ /\bvolatile\b/ && $line !~ /$asm_volatile/) {
|
||||
ERROR("Use of volatile is usually wrong: see Documentation/volatile-considered-harmful.txt\n" . $herecurr);
|
||||
if ($line =~ /\bvolatile\b/ && $line !~ /$asm_volatile/ &&
|
||||
$line !~ /sig_atomic_t/ &&
|
||||
!ctx_has_comment($first_line, $linenr)) {
|
||||
my $msg = "Use of volatile is usually wrong, please add a comment\n" . $herecurr;
|
||||
ERROR($msg);
|
||||
}
|
||||
|
||||
# warn about #if 0
|
||||
|
|
|
@ -314,6 +314,22 @@ static int is_mpath(int fd)
|
|||
return !strncmp(tgt->target_type, "multipath", DM_MAX_TYPE_NAME);
|
||||
}
|
||||
|
||||
static SCSISense mpath_generic_sense(int r)
|
||||
{
|
||||
switch (r) {
|
||||
case MPATH_PR_SENSE_NOT_READY:
|
||||
return SENSE_CODE(NOT_READY);
|
||||
case MPATH_PR_SENSE_MEDIUM_ERROR:
|
||||
return SENSE_CODE(READ_ERROR);
|
||||
case MPATH_PR_SENSE_HARDWARE_ERROR:
|
||||
return SENSE_CODE(TARGET_FAILURE);
|
||||
case MPATH_PR_SENSE_ABORTED_COMMAND:
|
||||
return SENSE_CODE(IO_ERROR);
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
static int mpath_reconstruct_sense(int fd, int r, uint8_t *sense)
|
||||
{
|
||||
switch (r) {
|
||||
|
@ -329,7 +345,13 @@ static int mpath_reconstruct_sense(int fd, int r, uint8_t *sense)
|
|||
*/
|
||||
uint8_t cdb[6] = { TEST_UNIT_READY };
|
||||
int sz = 0;
|
||||
return do_sgio(fd, cdb, sense, NULL, &sz, SG_DXFER_NONE);
|
||||
int r = do_sgio(fd, cdb, sense, NULL, &sz, SG_DXFER_NONE);
|
||||
|
||||
if (r != GOOD) {
|
||||
return r;
|
||||
}
|
||||
scsi_build_sense(sense, mpath_generic_sense(r));
|
||||
return CHECK_CONDITION;
|
||||
}
|
||||
|
||||
case MPATH_PR_SENSE_UNIT_ATTENTION:
|
||||
|
@ -449,7 +471,7 @@ static int multipath_pr_out(int fd, const uint8_t *cdb, uint8_t *sense,
|
|||
memset(¶mp, 0, sizeof(paramp));
|
||||
memcpy(¶mp.key, ¶m[0], 8);
|
||||
memcpy(¶mp.sa_key, ¶m[8], 8);
|
||||
paramp.sa_flags = param[10];
|
||||
paramp.sa_flags = param[20];
|
||||
if (sz > PR_OUT_FIXED_PARAM_SIZE) {
|
||||
size_t transportid_len;
|
||||
int i, j;
|
||||
|
@ -478,8 +500,8 @@ static int multipath_pr_out(int fd, const uint8_t *cdb, uint8_t *sense,
|
|||
j += offsetof(struct transportid, n_port_name[8]);
|
||||
i += 24;
|
||||
break;
|
||||
case 3:
|
||||
case 0x43:
|
||||
case 5:
|
||||
case 0x45:
|
||||
/* iSCSI transport. */
|
||||
len = lduw_be_p(¶m[i + 2]);
|
||||
if (len > 252 || (len & 3) || i + len + 4 > transportid_len) {
|
||||
|
|
163
scsi/utils.c
163
scsi/utils.c
|
@ -96,15 +96,60 @@ int scsi_cdb_length(uint8_t *buf)
|
|||
return cdb_len;
|
||||
}
|
||||
|
||||
SCSISense scsi_parse_sense_buf(const uint8_t *in_buf, int in_len)
|
||||
{
|
||||
bool fixed_in;
|
||||
SCSISense sense;
|
||||
|
||||
assert(in_len > 0);
|
||||
fixed_in = (in_buf[0] & 2) == 0;
|
||||
if (fixed_in) {
|
||||
if (in_len < 14) {
|
||||
return SENSE_CODE(IO_ERROR);
|
||||
}
|
||||
sense.key = in_buf[2];
|
||||
sense.asc = in_buf[12];
|
||||
sense.ascq = in_buf[13];
|
||||
} else {
|
||||
if (in_len < 4) {
|
||||
return SENSE_CODE(IO_ERROR);
|
||||
}
|
||||
sense.key = in_buf[1];
|
||||
sense.asc = in_buf[2];
|
||||
sense.ascq = in_buf[3];
|
||||
}
|
||||
|
||||
return sense;
|
||||
}
|
||||
|
||||
int scsi_build_sense_buf(uint8_t *out_buf, size_t size, SCSISense sense,
|
||||
bool fixed_sense)
|
||||
{
|
||||
int len;
|
||||
uint8_t buf[SCSI_SENSE_LEN] = { 0 };
|
||||
|
||||
if (fixed_sense) {
|
||||
buf[0] = 0x70;
|
||||
buf[2] = sense.key;
|
||||
buf[7] = 10;
|
||||
buf[12] = sense.asc;
|
||||
buf[13] = sense.ascq;
|
||||
len = 18;
|
||||
} else {
|
||||
buf[0] = 0x72;
|
||||
buf[1] = sense.key;
|
||||
buf[2] = sense.asc;
|
||||
buf[3] = sense.ascq;
|
||||
len = 8;
|
||||
}
|
||||
len = MIN(len, size);
|
||||
memcpy(out_buf, buf, len);
|
||||
return len;
|
||||
}
|
||||
|
||||
int scsi_build_sense(uint8_t *buf, SCSISense sense)
|
||||
{
|
||||
memset(buf, 0, 18);
|
||||
buf[0] = 0x70;
|
||||
buf[2] = sense.key;
|
||||
buf[7] = 10;
|
||||
buf[12] = sense.asc;
|
||||
buf[13] = sense.ascq;
|
||||
return 18;
|
||||
return scsi_build_sense_buf(buf, SCSI_SENSE_LEN, sense, true);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -211,6 +256,16 @@ const struct SCSISense sense_code_LUN_COMM_FAILURE = {
|
|||
.key = ABORTED_COMMAND, .asc = 0x08, .ascq = 0x00
|
||||
};
|
||||
|
||||
/* Medium Error, Unrecovered read error */
|
||||
const struct SCSISense sense_code_READ_ERROR = {
|
||||
.key = MEDIUM_ERROR, .asc = 0x11, .ascq = 0x00
|
||||
};
|
||||
|
||||
/* Not ready, Cause not reportable */
|
||||
const struct SCSISense sense_code_NOT_READY = {
|
||||
.key = NOT_READY, .asc = 0x04, .ascq = 0x00
|
||||
};
|
||||
|
||||
/* Unit attention, Capacity data has changed */
|
||||
const struct SCSISense sense_code_CAPACITY_CHANGED = {
|
||||
.key = UNIT_ATTENTION, .asc = 0x2a, .ascq = 0x09
|
||||
|
@ -264,67 +319,36 @@ const struct SCSISense sense_code_SPACE_ALLOC_FAILED = {
|
|||
int scsi_convert_sense(uint8_t *in_buf, int in_len,
|
||||
uint8_t *buf, int len, bool fixed)
|
||||
{
|
||||
bool fixed_in;
|
||||
SCSISense sense;
|
||||
if (!fixed && len < 8) {
|
||||
return 0;
|
||||
bool fixed_in;
|
||||
|
||||
fixed_in = (in_buf[0] & 2) == 0;
|
||||
if (in_len && fixed == fixed_in) {
|
||||
memcpy(buf, in_buf, MIN(len, in_len));
|
||||
return MIN(len, in_len);
|
||||
}
|
||||
|
||||
if (in_len == 0) {
|
||||
sense.key = NO_SENSE;
|
||||
sense.asc = 0;
|
||||
sense.ascq = 0;
|
||||
sense = SENSE_CODE(NO_SENSE);
|
||||
} else {
|
||||
fixed_in = (in_buf[0] & 2) == 0;
|
||||
|
||||
if (fixed == fixed_in) {
|
||||
memcpy(buf, in_buf, MIN(len, in_len));
|
||||
return MIN(len, in_len);
|
||||
}
|
||||
|
||||
if (fixed_in) {
|
||||
sense.key = in_buf[2];
|
||||
sense.asc = in_buf[12];
|
||||
sense.ascq = in_buf[13];
|
||||
} else {
|
||||
sense.key = in_buf[1];
|
||||
sense.asc = in_buf[2];
|
||||
sense.ascq = in_buf[3];
|
||||
}
|
||||
}
|
||||
|
||||
memset(buf, 0, len);
|
||||
if (fixed) {
|
||||
/* Return fixed format sense buffer */
|
||||
buf[0] = 0x70;
|
||||
buf[2] = sense.key;
|
||||
buf[7] = 10;
|
||||
buf[12] = sense.asc;
|
||||
buf[13] = sense.ascq;
|
||||
return MIN(len, SCSI_SENSE_LEN);
|
||||
} else {
|
||||
/* Return descriptor format sense buffer */
|
||||
buf[0] = 0x72;
|
||||
buf[1] = sense.key;
|
||||
buf[2] = sense.asc;
|
||||
buf[3] = sense.ascq;
|
||||
return 8;
|
||||
sense = scsi_parse_sense_buf(in_buf, in_len);
|
||||
}
|
||||
return scsi_build_sense_buf(buf, len, sense, fixed);
|
||||
}
|
||||
|
||||
int scsi_sense_to_errno(int key, int asc, int ascq)
|
||||
{
|
||||
switch (key) {
|
||||
case 0x00: /* NO SENSE */
|
||||
case 0x01: /* RECOVERED ERROR */
|
||||
case 0x06: /* UNIT ATTENTION */
|
||||
case NO_SENSE:
|
||||
case RECOVERED_ERROR:
|
||||
case UNIT_ATTENTION:
|
||||
/* These sense keys are not errors */
|
||||
return 0;
|
||||
case 0x0b: /* COMMAND ABORTED */
|
||||
case ABORTED_COMMAND: /* COMMAND ABORTED */
|
||||
return ECANCELED;
|
||||
case 0x02: /* NOT READY */
|
||||
case 0x05: /* ILLEGAL REQUEST */
|
||||
case 0x07: /* DATA PROTECTION */
|
||||
case NOT_READY:
|
||||
case ILLEGAL_REQUEST:
|
||||
case DATA_PROTECT:
|
||||
/* Parse ASCQ */
|
||||
break;
|
||||
default:
|
||||
|
@ -356,34 +380,15 @@ int scsi_sense_to_errno(int key, int asc, int ascq)
|
|||
}
|
||||
}
|
||||
|
||||
int scsi_sense_buf_to_errno(const uint8_t *sense, size_t sense_size)
|
||||
int scsi_sense_buf_to_errno(const uint8_t *in_buf, size_t in_len)
|
||||
{
|
||||
int key, asc, ascq;
|
||||
if (sense_size < 1) {
|
||||
SCSISense sense;
|
||||
if (in_len < 1) {
|
||||
return EIO;
|
||||
}
|
||||
switch (sense[0]) {
|
||||
case 0x70: /* Fixed format sense data. */
|
||||
if (sense_size < 14) {
|
||||
return EIO;
|
||||
}
|
||||
key = sense[2] & 0xF;
|
||||
asc = sense[12];
|
||||
ascq = sense[13];
|
||||
break;
|
||||
case 0x72: /* Descriptor format sense data. */
|
||||
if (sense_size < 4) {
|
||||
return EIO;
|
||||
}
|
||||
key = sense[1] & 0xF;
|
||||
asc = sense[2];
|
||||
ascq = sense[3];
|
||||
break;
|
||||
default:
|
||||
return EIO;
|
||||
break;
|
||||
}
|
||||
return scsi_sense_to_errno(key, asc, ascq);
|
||||
|
||||
sense = scsi_parse_sense_buf(in_buf, in_len);
|
||||
return scsi_sense_to_errno(sense.key, sense.asc, sense.ascq);
|
||||
}
|
||||
|
||||
const char *scsi_command_name(uint8_t cmd)
|
||||
|
|
|
@ -705,9 +705,6 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
|
|||
CPUARMState *env = &cpu->env;
|
||||
int pagebits;
|
||||
Error *local_err = NULL;
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
AddressSpace *as;
|
||||
#endif
|
||||
|
||||
cpu_exec_realizefn(cs, &local_err);
|
||||
if (local_err != NULL) {
|
||||
|
@ -912,21 +909,17 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
|
|||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
if (cpu->has_el3 || arm_feature(env, ARM_FEATURE_M_SECURITY)) {
|
||||
as = g_new0(AddressSpace, 1);
|
||||
|
||||
cs->num_ases = 2;
|
||||
|
||||
if (!cpu->secure_memory) {
|
||||
cpu->secure_memory = cs->memory;
|
||||
}
|
||||
address_space_init(as, cpu->secure_memory, "cpu-secure-memory");
|
||||
cpu_address_space_init(cs, as, ARMASIdx_S);
|
||||
cpu_address_space_init(cs, ARMASIdx_S, "cpu-secure-memory",
|
||||
cpu->secure_memory);
|
||||
} else {
|
||||
cs->num_ases = 1;
|
||||
}
|
||||
as = g_new0(AddressSpace, 1);
|
||||
address_space_init(as, cs->memory, "cpu-memory");
|
||||
cpu_address_space_init(cs, as, ARMASIdx_NS);
|
||||
cpu_address_space_init(cs, ARMASIdx_NS, "cpu-memory", cs->memory);
|
||||
#endif
|
||||
|
||||
qemu_init_vcpu(cs);
|
||||
|
|
|
@ -437,9 +437,9 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
|
|||
[FEAT_7_0_ECX] = {
|
||||
.feat_names = {
|
||||
NULL, "avx512vbmi", "umip", "pku",
|
||||
"ospke", NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, "avx512-vpopcntdq", NULL,
|
||||
"ospke", NULL, "avx512vbmi2", NULL,
|
||||
"gfni", "vaes", "vpclmulqdq", "avx512vnni",
|
||||
"avx512bitalg", NULL, "avx512-vpopcntdq", NULL,
|
||||
"la57", NULL, NULL, NULL,
|
||||
NULL, NULL, "rdpid", NULL,
|
||||
NULL, NULL, NULL, NULL,
|
||||
|
@ -3736,11 +3736,6 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp)
|
|||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
if (tcg_enabled()) {
|
||||
AddressSpace *as_normal = g_new0(AddressSpace, 1);
|
||||
AddressSpace *as_smm = g_new(AddressSpace, 1);
|
||||
|
||||
address_space_init(as_normal, cs->memory, "cpu-memory");
|
||||
|
||||
cpu->cpu_as_mem = g_new(MemoryRegion, 1);
|
||||
cpu->cpu_as_root = g_new(MemoryRegion, 1);
|
||||
|
||||
|
@ -3755,11 +3750,10 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp)
|
|||
get_system_memory(), 0, ~0ull);
|
||||
memory_region_add_subregion_overlap(cpu->cpu_as_root, 0, cpu->cpu_as_mem, 0);
|
||||
memory_region_set_enabled(cpu->cpu_as_mem, true);
|
||||
address_space_init(as_smm, cpu->cpu_as_root, "CPU");
|
||||
|
||||
cs->num_ases = 2;
|
||||
cpu_address_space_init(cs, as_normal, 0);
|
||||
cpu_address_space_init(cs, as_smm, 1);
|
||||
cpu_address_space_init(cs, 0, "cpu-memory", cs->memory);
|
||||
cpu_address_space_init(cs, 1, "cpu-smm", cpu->cpu_as_root);
|
||||
|
||||
/* ... SMRAM with higher priority, linked from /machine/smram. */
|
||||
cpu->machine_done.notify = x86_cpu_machine_done;
|
||||
|
|
|
@ -635,6 +635,12 @@ typedef uint32_t FeatureWordArray[FEATURE_WORDS];
|
|||
#define CPUID_7_0_ECX_UMIP (1U << 2)
|
||||
#define CPUID_7_0_ECX_PKU (1U << 3)
|
||||
#define CPUID_7_0_ECX_OSPKE (1U << 4)
|
||||
#define CPUID_7_0_ECX_VBMI2 (1U << 6) /* Additional VBMI Instrs */
|
||||
#define CPUID_7_0_ECX_GFNI (1U << 8)
|
||||
#define CPUID_7_0_ECX_VAES (1U << 9)
|
||||
#define CPUID_7_0_ECX_VPCLMULQDQ (1U << 10)
|
||||
#define CPUID_7_0_ECX_AVX512VNNI (1U << 11)
|
||||
#define CPUID_7_0_ECX_AVX512BITALG (1U << 12)
|
||||
#define CPUID_7_0_ECX_AVX512_VPOPCNTDQ (1U << 14) /* POPCNT for vectors of DW/QW */
|
||||
#define CPUID_7_0_ECX_LA57 (1U << 16)
|
||||
#define CPUID_7_0_ECX_RDPID (1U << 22)
|
||||
|
@ -1091,14 +1097,16 @@ typedef struct CPUX86State {
|
|||
uint64_t async_pf_en_msr;
|
||||
uint64_t pv_eoi_en_msr;
|
||||
|
||||
/* Partition-wide HV MSRs, will be updated only on the first vcpu */
|
||||
uint64_t msr_hv_hypercall;
|
||||
uint64_t msr_hv_guest_os_id;
|
||||
uint64_t msr_hv_vapic;
|
||||
uint64_t msr_hv_tsc;
|
||||
|
||||
/* Per-VCPU HV MSRs */
|
||||
uint64_t msr_hv_vapic;
|
||||
uint64_t msr_hv_crash_params[HV_CRASH_PARAMS];
|
||||
uint64_t msr_hv_runtime;
|
||||
uint64_t msr_hv_synic_control;
|
||||
uint64_t msr_hv_synic_version;
|
||||
uint64_t msr_hv_synic_evt_page;
|
||||
uint64_t msr_hv_synic_msg_page;
|
||||
uint64_t msr_hv_synic_sint[HV_SINT_COUNT];
|
||||
|
|
|
@ -662,8 +662,6 @@ static int hyperv_handle_properties(CPUState *cs)
|
|||
env->features[FEAT_HYPERV_EAX] |= HV_VP_RUNTIME_AVAILABLE;
|
||||
}
|
||||
if (cpu->hyperv_synic) {
|
||||
int sint;
|
||||
|
||||
if (!has_msr_hv_synic ||
|
||||
kvm_vcpu_enable_cap(cs, KVM_CAP_HYPERV_SYNIC, 0)) {
|
||||
fprintf(stderr, "Hyper-V SynIC is not supported by kernel\n");
|
||||
|
@ -671,10 +669,6 @@ static int hyperv_handle_properties(CPUState *cs)
|
|||
}
|
||||
|
||||
env->features[FEAT_HYPERV_EAX] |= HV_SYNIC_AVAILABLE;
|
||||
env->msr_hv_synic_version = HV_SYNIC_VERSION;
|
||||
for (sint = 0; sint < ARRAY_SIZE(env->msr_hv_synic_sint); sint++) {
|
||||
env->msr_hv_synic_sint[sint] = HV_SINT_MASKED;
|
||||
}
|
||||
}
|
||||
if (cpu->hyperv_stimer) {
|
||||
if (!has_msr_hv_stimer) {
|
||||
|
@ -1053,6 +1047,13 @@ void kvm_arch_reset_vcpu(X86CPU *cpu)
|
|||
} else {
|
||||
env->mp_state = KVM_MP_STATE_RUNNABLE;
|
||||
}
|
||||
|
||||
if (cpu->hyperv_synic) {
|
||||
int i;
|
||||
for (i = 0; i < ARRAY_SIZE(env->msr_hv_synic_sint); i++) {
|
||||
env->msr_hv_synic_sint[i] = HV_SINT_MASKED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void kvm_arch_do_init_vcpu(X86CPU *cpu)
|
||||
|
@ -1678,19 +1679,26 @@ static int kvm_put_msrs(X86CPU *cpu, int level)
|
|||
kvm_msr_entry_add(cpu, MSR_CORE_PERF_GLOBAL_CTRL,
|
||||
env->msr_global_ctrl);
|
||||
}
|
||||
if (has_msr_hv_hypercall) {
|
||||
kvm_msr_entry_add(cpu, HV_X64_MSR_GUEST_OS_ID,
|
||||
env->msr_hv_guest_os_id);
|
||||
kvm_msr_entry_add(cpu, HV_X64_MSR_HYPERCALL,
|
||||
env->msr_hv_hypercall);
|
||||
/*
|
||||
* Hyper-V partition-wide MSRs: to avoid clearing them on cpu hot-add,
|
||||
* only sync them to KVM on the first cpu
|
||||
*/
|
||||
if (current_cpu == first_cpu) {
|
||||
if (has_msr_hv_hypercall) {
|
||||
kvm_msr_entry_add(cpu, HV_X64_MSR_GUEST_OS_ID,
|
||||
env->msr_hv_guest_os_id);
|
||||
kvm_msr_entry_add(cpu, HV_X64_MSR_HYPERCALL,
|
||||
env->msr_hv_hypercall);
|
||||
}
|
||||
if (cpu->hyperv_time) {
|
||||
kvm_msr_entry_add(cpu, HV_X64_MSR_REFERENCE_TSC,
|
||||
env->msr_hv_tsc);
|
||||
}
|
||||
}
|
||||
if (cpu->hyperv_vapic) {
|
||||
kvm_msr_entry_add(cpu, HV_X64_MSR_APIC_ASSIST_PAGE,
|
||||
env->msr_hv_vapic);
|
||||
}
|
||||
if (cpu->hyperv_time) {
|
||||
kvm_msr_entry_add(cpu, HV_X64_MSR_REFERENCE_TSC, env->msr_hv_tsc);
|
||||
}
|
||||
if (has_msr_hv_crash) {
|
||||
int j;
|
||||
|
||||
|
@ -1706,10 +1714,10 @@ static int kvm_put_msrs(X86CPU *cpu, int level)
|
|||
if (cpu->hyperv_synic) {
|
||||
int j;
|
||||
|
||||
kvm_msr_entry_add(cpu, HV_X64_MSR_SVERSION, HV_SYNIC_VERSION);
|
||||
|
||||
kvm_msr_entry_add(cpu, HV_X64_MSR_SCONTROL,
|
||||
env->msr_hv_synic_control);
|
||||
kvm_msr_entry_add(cpu, HV_X64_MSR_SVERSION,
|
||||
env->msr_hv_synic_version);
|
||||
kvm_msr_entry_add(cpu, HV_X64_MSR_SIEFP,
|
||||
env->msr_hv_synic_evt_page);
|
||||
kvm_msr_entry_add(cpu, HV_X64_MSR_SIMP,
|
||||
|
@ -2073,7 +2081,6 @@ static int kvm_get_msrs(X86CPU *cpu)
|
|||
uint32_t msr;
|
||||
|
||||
kvm_msr_entry_add(cpu, HV_X64_MSR_SCONTROL, 0);
|
||||
kvm_msr_entry_add(cpu, HV_X64_MSR_SVERSION, 0);
|
||||
kvm_msr_entry_add(cpu, HV_X64_MSR_SIEFP, 0);
|
||||
kvm_msr_entry_add(cpu, HV_X64_MSR_SIMP, 0);
|
||||
for (msr = HV_X64_MSR_SINT0; msr <= HV_X64_MSR_SINT15; msr++) {
|
||||
|
@ -2277,9 +2284,6 @@ static int kvm_get_msrs(X86CPU *cpu)
|
|||
case HV_X64_MSR_SCONTROL:
|
||||
env->msr_hv_synic_control = msrs[i].data;
|
||||
break;
|
||||
case HV_X64_MSR_SVERSION:
|
||||
env->msr_hv_synic_version = msrs[i].data;
|
||||
break;
|
||||
case HV_X64_MSR_SIEFP:
|
||||
env->msr_hv_synic_evt_page = msrs[i].data;
|
||||
break;
|
||||
|
|
|
@ -4467,10 +4467,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu)
|
|||
target_ulong pc_start = s->base.pc_next;
|
||||
|
||||
s->pc_start = s->pc = pc_start;
|
||||
prefixes = 0;
|
||||
s->override = -1;
|
||||
rex_w = -1;
|
||||
rex_r = 0;
|
||||
#ifdef TARGET_X86_64
|
||||
s->rex_x = 0;
|
||||
s->rex_b = 0;
|
||||
|
@ -4484,6 +4481,10 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu)
|
|||
return s->pc;
|
||||
}
|
||||
|
||||
prefixes = 0;
|
||||
rex_w = -1;
|
||||
rex_r = 0;
|
||||
|
||||
next_byte:
|
||||
b = x86_ldub_code(env, s);
|
||||
/* Collect prefixes. */
|
||||
|
@ -4547,9 +4548,9 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu)
|
|||
if (!CODE64(s) && (vex2 & 0xc0) != 0xc0) {
|
||||
/* 4.1.4.6: In 32-bit mode, bits [7:6] must be 11b,
|
||||
otherwise the instruction is LES or LDS. */
|
||||
s->pc--; /* rewind the advance_pc() x86_ldub_code() did */
|
||||
break;
|
||||
}
|
||||
s->pc++;
|
||||
|
||||
/* 4.1.1-4.1.3: No preceding lock, 66, f2, f3, or rex prefixes. */
|
||||
if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ
|
||||
|
|
|
@ -7,9 +7,10 @@
|
|||
* or later. See the COPYING file in the top-level directory.
|
||||
*
|
||||
* This test is used to check that the serial output of the firmware
|
||||
* (that we provide for some machines) contains an expected string.
|
||||
* Thus we check that the firmware still boots at least to a certain
|
||||
* point and so we know that the machine is not completely broken.
|
||||
* (that we provide for some machines) or some small mini-kernels that
|
||||
* we provide here contains an expected string. Thus we check that the
|
||||
* firmware/kernel still boots at least to a certain point and so we
|
||||
* know that the machine is not completely broken.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
|
@ -20,6 +21,9 @@ typedef struct testdef {
|
|||
const char *machine; /* Name of the machine */
|
||||
const char *extra; /* Additional parameters */
|
||||
const char *expect; /* Expected string in the serial output */
|
||||
size_t codesize; /* Size of the kernel or bios data */
|
||||
const uint8_t *kernel; /* Set in case we use our own mini kernel */
|
||||
const uint8_t *bios; /* Set in case we use our own mini bios */
|
||||
} testdef_t;
|
||||
|
||||
static testdef_t tests[] = {
|
||||
|
@ -43,12 +47,13 @@ static testdef_t tests[] = {
|
|||
static void check_guest_output(const testdef_t *test, int fd)
|
||||
{
|
||||
bool output_ok = false;
|
||||
int i, nbr, pos = 0;
|
||||
int i, nbr, pos = 0, ccnt;
|
||||
char ch;
|
||||
|
||||
/* Poll serial output... Wait at most 60 seconds */
|
||||
for (i = 0; i < 6000; ++i) {
|
||||
while ((nbr = read(fd, &ch, 1)) == 1) {
|
||||
ccnt = 0;
|
||||
while ((nbr = read(fd, &ch, 1)) == 1 && ccnt++ < 512) {
|
||||
if (ch == test->expect[pos]) {
|
||||
pos += 1;
|
||||
if (test->expect[pos] == '\0') {
|
||||
|
@ -71,26 +76,52 @@ done:
|
|||
static void test_machine(const void *data)
|
||||
{
|
||||
const testdef_t *test = data;
|
||||
char tmpname[] = "/tmp/qtest-boot-serial-XXXXXX";
|
||||
int fd;
|
||||
char serialtmp[] = "/tmp/qtest-boot-serial-sXXXXXX";
|
||||
char codetmp[] = "/tmp/qtest-boot-serial-cXXXXXX";
|
||||
const char *codeparam = "";
|
||||
const uint8_t *code = NULL;
|
||||
int ser_fd;
|
||||
|
||||
fd = mkstemp(tmpname);
|
||||
g_assert(fd != -1);
|
||||
ser_fd = mkstemp(serialtmp);
|
||||
g_assert(ser_fd != -1);
|
||||
|
||||
if (test->kernel) {
|
||||
code = test->kernel;
|
||||
codeparam = "-kernel";
|
||||
} else if (test->bios) {
|
||||
code = test->bios;
|
||||
codeparam = "-bios";
|
||||
}
|
||||
|
||||
if (code) {
|
||||
ssize_t wlen;
|
||||
int code_fd;
|
||||
|
||||
code_fd = mkstemp(codetmp);
|
||||
g_assert(code_fd != -1);
|
||||
wlen = write(code_fd, code, test->codesize);
|
||||
g_assert(wlen == test->codesize);
|
||||
close(code_fd);
|
||||
}
|
||||
|
||||
/*
|
||||
* Make sure that this test uses tcg if available: It is used as a
|
||||
* fast-enough smoketest for that.
|
||||
*/
|
||||
global_qtest = qtest_startf("-M %s,accel=tcg:kvm "
|
||||
global_qtest = qtest_startf("%s %s -M %s,accel=tcg:kvm "
|
||||
"-chardev file,id=serial0,path=%s "
|
||||
"-no-shutdown -serial chardev:serial0 %s",
|
||||
test->machine, tmpname, test->extra);
|
||||
unlink(tmpname);
|
||||
codeparam, code ? codetmp : "",
|
||||
test->machine, serialtmp, test->extra);
|
||||
unlink(serialtmp);
|
||||
if (code) {
|
||||
unlink(codetmp);
|
||||
}
|
||||
|
||||
check_guest_output(test, fd);
|
||||
check_guest_output(test, ser_fd);
|
||||
qtest_quit(global_qtest);
|
||||
|
||||
close(fd);
|
||||
close(ser_fd);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "qemu/config-file.h"
|
||||
#include "qemu/sockets.h"
|
||||
#include "chardev/char-fe.h"
|
||||
#include "chardev/char-mux.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qom/qom-qobject.h"
|
||||
|
@ -164,6 +165,7 @@ static void char_mux_test(void)
|
|||
FeHandler h1 = { 0, }, h2 = { 0, };
|
||||
CharBackend chr_be1, chr_be2;
|
||||
|
||||
muxes_realized = true; /* done after machine init */
|
||||
opts = qemu_opts_create(qemu_find_opts("chardev"), "mux-label",
|
||||
1, &error_abort);
|
||||
qemu_opt_set(opts, "backend", "ringbuf", &error_abort);
|
||||
|
@ -201,8 +203,23 @@ static void char_mux_test(void)
|
|||
g_assert_cmpstr(h2.read_buf, ==, "hello");
|
||||
h2.read_count = 0;
|
||||
|
||||
g_assert_cmpint(h1.last_event, !=, 42); /* should be MUX_OUT or OPENED */
|
||||
g_assert_cmpint(h2.last_event, !=, 42); /* should be MUX_IN or OPENED */
|
||||
/* sending event on the base broadcast to all fe, historical reasons? */
|
||||
qemu_chr_be_event(base, 42);
|
||||
g_assert_cmpint(h1.last_event, ==, 42);
|
||||
g_assert_cmpint(h2.last_event, ==, 42);
|
||||
qemu_chr_be_event(chr, -1);
|
||||
g_assert_cmpint(h1.last_event, ==, 42);
|
||||
g_assert_cmpint(h2.last_event, ==, -1);
|
||||
|
||||
/* switch focus */
|
||||
qemu_chr_be_write(base, (void *)"\1c", 2);
|
||||
g_assert_cmpint(h1.last_event, ==, CHR_EVENT_MUX_IN);
|
||||
g_assert_cmpint(h2.last_event, ==, CHR_EVENT_MUX_OUT);
|
||||
qemu_chr_be_event(chr, -1);
|
||||
g_assert_cmpint(h1.last_event, ==, -1);
|
||||
g_assert_cmpint(h2.last_event, ==, CHR_EVENT_MUX_OUT);
|
||||
|
||||
qemu_chr_be_write(base, (void *)"hello", 6);
|
||||
g_assert_cmpint(h2.read_count, ==, 0);
|
||||
|
|
|
@ -31,9 +31,7 @@
|
|||
|
||||
#include "qemu/memfd.h"
|
||||
|
||||
#ifdef CONFIG_MEMFD
|
||||
#include <sys/memfd.h>
|
||||
#elif defined CONFIG_LINUX
|
||||
#if defined CONFIG_LINUX && !defined CONFIG_MEMFD
|
||||
#include <sys/syscall.h>
|
||||
#include <asm/unistd.h>
|
||||
|
||||
|
|
|
@ -198,7 +198,6 @@ static int try_bind(int socket, InetSocketAddress *saddr, struct addrinfo *e)
|
|||
|
||||
static int inet_listen_saddr(InetSocketAddress *saddr,
|
||||
int port_offset,
|
||||
bool update_addr,
|
||||
Error **errp)
|
||||
{
|
||||
struct addrinfo ai,*res,*e;
|
||||
|
@ -326,15 +325,6 @@ listen_failed:
|
|||
return -1;
|
||||
|
||||
listen_ok:
|
||||
if (update_addr) {
|
||||
g_free(saddr->host);
|
||||
saddr->host = g_strdup(uaddr);
|
||||
g_free(saddr->port);
|
||||
saddr->port = g_strdup_printf("%d",
|
||||
inet_getport(e) - port_offset);
|
||||
saddr->has_ipv6 = saddr->ipv6 = e->ai_family == PF_INET6;
|
||||
saddr->has_ipv4 = saddr->ipv4 = e->ai_family != PF_INET6;
|
||||
}
|
||||
freeaddrinfo(res);
|
||||
return slisten;
|
||||
}
|
||||
|
@ -790,7 +780,6 @@ static int vsock_parse(VsockSocketAddress *addr, const char *str,
|
|||
#ifndef _WIN32
|
||||
|
||||
static int unix_listen_saddr(UnixSocketAddress *saddr,
|
||||
bool update_addr,
|
||||
Error **errp)
|
||||
{
|
||||
struct sockaddr_un un;
|
||||
|
@ -855,12 +844,7 @@ static int unix_listen_saddr(UnixSocketAddress *saddr,
|
|||
goto err;
|
||||
}
|
||||
|
||||
if (update_addr && pathbuf) {
|
||||
g_free(saddr->path);
|
||||
saddr->path = pathbuf;
|
||||
} else {
|
||||
g_free(pathbuf);
|
||||
}
|
||||
g_free(pathbuf);
|
||||
return sock;
|
||||
|
||||
err:
|
||||
|
@ -920,7 +904,6 @@ static int unix_connect_saddr(UnixSocketAddress *saddr, Error **errp)
|
|||
#else
|
||||
|
||||
static int unix_listen_saddr(UnixSocketAddress *saddr,
|
||||
bool update_addr,
|
||||
Error **errp)
|
||||
{
|
||||
error_setg(errp, "unix sockets are not available on windows");
|
||||
|
@ -937,7 +920,7 @@ static int unix_connect_saddr(UnixSocketAddress *saddr, Error **errp)
|
|||
#endif
|
||||
|
||||
/* compatibility wrapper */
|
||||
int unix_listen(const char *str, char *ostr, int olen, Error **errp)
|
||||
int unix_listen(const char *str, Error **errp)
|
||||
{
|
||||
char *path, *optstr;
|
||||
int sock, len;
|
||||
|
@ -957,11 +940,7 @@ int unix_listen(const char *str, char *ostr, int olen, Error **errp)
|
|||
saddr->path = g_strdup(str);
|
||||
}
|
||||
|
||||
sock = unix_listen_saddr(saddr, true, errp);
|
||||
|
||||
if (sock != -1 && ostr) {
|
||||
snprintf(ostr, olen, "%s%s", saddr->path, optstr ? optstr : "");
|
||||
}
|
||||
sock = unix_listen_saddr(saddr, errp);
|
||||
|
||||
qapi_free_UnixSocketAddress(saddr);
|
||||
return sock;
|
||||
|
@ -1052,11 +1031,11 @@ int socket_listen(SocketAddress *addr, Error **errp)
|
|||
|
||||
switch (addr->type) {
|
||||
case SOCKET_ADDRESS_TYPE_INET:
|
||||
fd = inet_listen_saddr(&addr->u.inet, 0, false, errp);
|
||||
fd = inet_listen_saddr(&addr->u.inet, 0, errp);
|
||||
break;
|
||||
|
||||
case SOCKET_ADDRESS_TYPE_UNIX:
|
||||
fd = unix_listen_saddr(&addr->u.q_unix, false, errp);
|
||||
fd = unix_listen_saddr(&addr->u.q_unix, errp);
|
||||
break;
|
||||
|
||||
case SOCKET_ADDRESS_TYPE_FD:
|
||||
|
|
|
@ -479,15 +479,29 @@ static void __attribute__((constructor)) qemu_thread_atexit_init(void)
|
|||
}
|
||||
|
||||
|
||||
/* Attempt to set the threads name; note that this is for debug, so
|
||||
* we're not going to fail if we can't set it.
|
||||
*/
|
||||
static void qemu_thread_set_name(QemuThread *thread, const char *name)
|
||||
{
|
||||
#ifdef CONFIG_PTHREAD_SETNAME_NP
|
||||
pthread_setname_np(thread->thread, name);
|
||||
#endif
|
||||
typedef struct {
|
||||
void *(*start_routine)(void *);
|
||||
void *arg;
|
||||
char *name;
|
||||
} QemuThreadArgs;
|
||||
|
||||
static void *qemu_thread_start(void *args)
|
||||
{
|
||||
QemuThreadArgs *qemu_thread_args = args;
|
||||
void *(*start_routine)(void *) = qemu_thread_args->start_routine;
|
||||
void *arg = qemu_thread_args->arg;
|
||||
|
||||
/* Attempt to set the threads name; note that this is for debug, so
|
||||
* we're not going to fail if we can't set it.
|
||||
*/
|
||||
pthread_setname_np(pthread_self(), qemu_thread_args->name);
|
||||
g_free(qemu_thread_args->name);
|
||||
g_free(qemu_thread_args);
|
||||
return start_routine(arg);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void qemu_thread_create(QemuThread *thread, const char *name,
|
||||
void *(*start_routine)(void*),
|
||||
|
@ -502,23 +516,34 @@ void qemu_thread_create(QemuThread *thread, const char *name,
|
|||
error_exit(err, __func__);
|
||||
}
|
||||
|
||||
if (mode == QEMU_THREAD_DETACHED) {
|
||||
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
||||
}
|
||||
|
||||
/* Leave signal handling to the iothread. */
|
||||
sigfillset(&set);
|
||||
pthread_sigmask(SIG_SETMASK, &set, &oldset);
|
||||
err = pthread_create(&thread->thread, &attr, start_routine, arg);
|
||||
|
||||
#ifdef CONFIG_PTHREAD_SETNAME_NP
|
||||
if (name_threads) {
|
||||
QemuThreadArgs *qemu_thread_args;
|
||||
qemu_thread_args = g_new0(QemuThreadArgs, 1);
|
||||
qemu_thread_args->name = g_strdup(name);
|
||||
qemu_thread_args->start_routine = start_routine;
|
||||
qemu_thread_args->arg = arg;
|
||||
|
||||
err = pthread_create(&thread->thread, &attr,
|
||||
qemu_thread_start, qemu_thread_args);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
err = pthread_create(&thread->thread, &attr,
|
||||
start_routine, arg);
|
||||
}
|
||||
|
||||
if (err)
|
||||
error_exit(err, __func__);
|
||||
|
||||
if (name_threads) {
|
||||
qemu_thread_set_name(thread, name);
|
||||
}
|
||||
|
||||
if (mode == QEMU_THREAD_DETACHED) {
|
||||
err = pthread_detach(thread->thread);
|
||||
if (err) {
|
||||
error_exit(err, __func__);
|
||||
}
|
||||
}
|
||||
pthread_sigmask(SIG_SETMASK, &oldset, NULL);
|
||||
|
||||
pthread_attr_destroy(&attr);
|
||||
|
|
|
@ -32,6 +32,9 @@
|
|||
#include "qemu/atomic.h"
|
||||
#include "qemu/thread.h"
|
||||
#include "qemu/main-loop.h"
|
||||
#if defined(CONFIG_MALLOC_TRIM)
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Global grace period counter. Bit 0 is always one in rcu_gp_ctr.
|
||||
|
@ -246,6 +249,9 @@ static void *call_rcu_thread(void *opaque)
|
|||
qemu_event_reset(&rcu_call_ready_event);
|
||||
n = atomic_read(&rcu_call_count);
|
||||
if (n == 0) {
|
||||
#if defined(CONFIG_MALLOC_TRIM)
|
||||
malloc_trim(4 * 1024 * 1024);
|
||||
#endif
|
||||
qemu_event_wait(&rcu_call_ready_event);
|
||||
}
|
||||
}
|
||||
|
|
4
vl.c
4
vl.c
|
@ -3817,10 +3817,6 @@ int main(int argc, char **argv, char **envp)
|
|||
olist = qemu_find_opts("machine");
|
||||
qemu_opts_parse_noisily(olist, "accel=tcg", false);
|
||||
break;
|
||||
case QEMU_OPTION_no_kvm_pit: {
|
||||
warn_report("ignoring deprecated option");
|
||||
break;
|
||||
}
|
||||
case QEMU_OPTION_no_kvm_pit_reinjection: {
|
||||
static GlobalProperty kvm_pit_lost_tick_policy = {
|
||||
.driver = "kvm-pit",
|
||||
|
|
Loading…
Reference in New Issue