vhost, pc: fixes for 2.5
Minor vhost fixes. HW version tweak for PC. Documentation and test updates. Signed-off-by: Michael S. Tsirkin <mst@redhat.com> -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQEcBAABAgAGBQJWVzX5AAoJECgfDbjSjVRp3UUH/jmankS57MaFIfB2plhrFlk0 BAjMLhJ6GCLrDEAaMaes9wJXJJMQHfoZnwAqkfkvjabKbiq6yPZz2FIfjSKuV86Z F6XNuMxiM2qwt/HJ5IaBX0c0Bm9bsF3zQpVAs082KfLvTrmOf8SHk4b8OFOCJMvu asSl9J8DTo3LZwC1TNpbxvTj5k3OFhB8i16WT3lvdLv9QUxBwdUaG6WxUCZD/35C CJnjut7n09ZbG4dfVxAVl7KubX1llpNBopbTQEyoHaaVfOvFDL5R2Gf7/YG9G0+x aI4+rMmRt0KCTii7xjN63j88+YpGlTgrAZETzwxVolZGMOe74jGtCNQqlIBwPZI= =I1ki -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging vhost, pc: fixes for 2.5 Minor vhost fixes. HW version tweak for PC. Documentation and test updates. Signed-off-by: Michael S. Tsirkin <mst@redhat.com> # gpg: Signature made Thu 26 Nov 2015 16:40:25 GMT using RSA key ID D28D5469 # gpg: Good signature from "Michael S. Tsirkin <mst@kernel.org>" # gpg: aka "Michael S. Tsirkin <mst@redhat.com>" * remotes/mst/tags/for_upstream: vhost-user-test: fix migration overlap test Fix memory leak on error Revert "vhost: send SET_VRING_ENABLE at start/stop" tests/vhost-user-bridge: read command line arguments tests/vhost-user-bridge: propose GUEST_ANNOUNCE feature vhost-user: clarify start and enable vhost-user: set link down when the char device is closed pc: Don't set hw_version on pc-*-2.5 osdep: Change default value of qemu_hw_version() to "2.5+" Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
72f75c76d8
@ -148,13 +148,23 @@ a feature bit was dedicated for this purpose:
|
|||||||
|
|
||||||
Starting and stopping rings
|
Starting and stopping rings
|
||||||
----------------------
|
----------------------
|
||||||
Client must only process each ring when it is both started and enabled.
|
Client must only process each ring when it is started.
|
||||||
|
|
||||||
|
Client must only pass data between the ring and the
|
||||||
|
backend, when the ring is enabled.
|
||||||
|
|
||||||
|
If ring is started but disabled, client must process the
|
||||||
|
ring without talking to the backend.
|
||||||
|
|
||||||
|
For example, for a networking device, in the disabled state
|
||||||
|
client must not supply any new RX packets, but must process
|
||||||
|
and discard any TX packets.
|
||||||
|
|
||||||
If VHOST_USER_F_PROTOCOL_FEATURES has not been negotiated, the ring is initialized
|
If VHOST_USER_F_PROTOCOL_FEATURES has not been negotiated, the ring is initialized
|
||||||
in an enabled state.
|
in an enabled state.
|
||||||
|
|
||||||
If VHOST_USER_F_PROTOCOL_FEATURES has been negotiated, the ring is initialized
|
If VHOST_USER_F_PROTOCOL_FEATURES has been negotiated, the ring is initialized
|
||||||
in a disabled state. Client must not process it until ring is enabled by
|
in a disabled state. Client must not pass data to/from the backend until ring is enabled by
|
||||||
VHOST_USER_SET_VRING_ENABLE with parameter 1, or after it has been disabled by
|
VHOST_USER_SET_VRING_ENABLE with parameter 1, or after it has been disabled by
|
||||||
VHOST_USER_SET_VRING_ENABLE with parameter 0.
|
VHOST_USER_SET_VRING_ENABLE with parameter 0.
|
||||||
|
|
||||||
@ -166,7 +176,7 @@ descriptor is readable) on the descriptor specified by
|
|||||||
VHOST_USER_SET_VRING_KICK, and stop ring upon receiving
|
VHOST_USER_SET_VRING_KICK, and stop ring upon receiving
|
||||||
VHOST_USER_GET_VRING_BASE.
|
VHOST_USER_GET_VRING_BASE.
|
||||||
|
|
||||||
While processing the rings (when they are started and enabled), client must
|
While processing the rings (whether they are enabled or not), client must
|
||||||
support changing some configuration aspects on the fly.
|
support changing some configuration aspects on the fly.
|
||||||
|
|
||||||
Multiple queue support
|
Multiple queue support
|
||||||
@ -309,11 +319,11 @@ Message types
|
|||||||
Id: 4
|
Id: 4
|
||||||
Master payload: N/A
|
Master payload: N/A
|
||||||
|
|
||||||
This is no longer used. Used to be sent to request stopping
|
This is no longer used. Used to be sent to request disabling
|
||||||
all rings, but some clients interpreted it to also discard
|
all rings, but some clients interpreted it to also discard
|
||||||
connection state (this interpretation would lead to bugs).
|
connection state (this interpretation would lead to bugs).
|
||||||
It is recommended that clients either ignore this message,
|
It is recommended that clients either ignore this message,
|
||||||
or use it to stop all rings.
|
or use it to disable all rings.
|
||||||
|
|
||||||
* VHOST_USER_SET_MEM_TABLE
|
* VHOST_USER_SET_MEM_TABLE
|
||||||
|
|
||||||
|
@ -155,6 +155,7 @@ static void acpi_memory_hotplug_write(void *opaque, hwaddr addr, uint64_t data,
|
|||||||
qapi_event_send_mem_unplug_error(dev->id,
|
qapi_event_send_mem_unplug_error(dev->id,
|
||||||
error_get_pretty(local_err),
|
error_get_pretty(local_err),
|
||||||
&error_abort);
|
&error_abort);
|
||||||
|
error_free(local_err);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
trace_mhp_acpi_pc_dimm_deleted(mem_st->selector);
|
trace_mhp_acpi_pc_dimm_deleted(mem_st->selector);
|
||||||
|
@ -472,7 +472,6 @@ static void pc_i440fx_machine_options(MachineClass *m)
|
|||||||
static void pc_i440fx_2_5_machine_options(MachineClass *m)
|
static void pc_i440fx_2_5_machine_options(MachineClass *m)
|
||||||
{
|
{
|
||||||
pc_i440fx_machine_options(m);
|
pc_i440fx_machine_options(m);
|
||||||
m->hw_version = QEMU_VERSION;
|
|
||||||
m->alias = "pc";
|
m->alias = "pc";
|
||||||
m->is_default = 1;
|
m->is_default = 1;
|
||||||
}
|
}
|
||||||
|
@ -373,7 +373,6 @@ static void pc_q35_machine_options(MachineClass *m)
|
|||||||
static void pc_q35_2_5_machine_options(MachineClass *m)
|
static void pc_q35_2_5_machine_options(MachineClass *m)
|
||||||
{
|
{
|
||||||
pc_q35_machine_options(m);
|
pc_q35_machine_options(m);
|
||||||
m->hw_version = QEMU_VERSION;
|
|
||||||
m->alias = "q35";
|
m->alias = "q35";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,6 +125,7 @@ static XICSState *xics_system_init(MachineState *machine,
|
|||||||
error_report("kernel_irqchip requested but unavailable: %s",
|
error_report("kernel_irqchip requested but unavailable: %s",
|
||||||
error_get_pretty(err));
|
error_get_pretty(err));
|
||||||
}
|
}
|
||||||
|
error_free(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!icp) {
|
if (!icp) {
|
||||||
|
@ -1226,11 +1226,6 @@ int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hdev->vhost_ops->vhost_set_vring_enable) {
|
|
||||||
/* only enable first vq pair by default */
|
|
||||||
hdev->vhost_ops->vhost_set_vring_enable(hdev, hdev->vq_index == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
fail_log:
|
fail_log:
|
||||||
vhost_log_put(hdev, false);
|
vhost_log_put(hdev, false);
|
||||||
@ -1261,10 +1256,6 @@ void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev)
|
|||||||
hdev->vq_index + i);
|
hdev->vq_index + i);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hdev->vhost_ops->vhost_set_vring_enable) {
|
|
||||||
hdev->vhost_ops->vhost_set_vring_enable(hdev, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
vhost_log_put(hdev, true);
|
vhost_log_put(hdev, true);
|
||||||
hdev->started = false;
|
hdev->started = false;
|
||||||
hdev->log = NULL;
|
hdev->log = NULL;
|
||||||
|
@ -51,6 +51,11 @@ bool machine_mem_merge(MachineState *machine);
|
|||||||
* used to provide @cpu_index to socket number mapping, allowing
|
* used to provide @cpu_index to socket number mapping, allowing
|
||||||
* a machine to group CPU threads belonging to the same socket/package
|
* a machine to group CPU threads belonging to the same socket/package
|
||||||
* Returns: socket number given cpu_index belongs to.
|
* Returns: socket number given cpu_index belongs to.
|
||||||
|
* @hw_version:
|
||||||
|
* Value of QEMU_VERSION when the machine was added to QEMU.
|
||||||
|
* Set only by old machines because they need to keep
|
||||||
|
* compatibility on code that exposed QEMU_VERSION to guests in
|
||||||
|
* the past (and now use qemu_hw_version()).
|
||||||
*/
|
*/
|
||||||
struct MachineClass {
|
struct MachineClass {
|
||||||
/*< private >*/
|
/*< private >*/
|
||||||
|
@ -256,6 +256,10 @@ static inline void qemu_timersub(const struct timeval *val1,
|
|||||||
|
|
||||||
void qemu_set_cloexec(int fd);
|
void qemu_set_cloexec(int fd);
|
||||||
|
|
||||||
|
/* QEMU "hardware version" setting. Used to replace code that exposed
|
||||||
|
* QEMU_VERSION to guests in the past and need to keep compatibilty.
|
||||||
|
* Do not use qemu_hw_version() in new code.
|
||||||
|
*/
|
||||||
void qemu_set_hw_version(const char *);
|
void qemu_set_hw_version(const char *);
|
||||||
const char *qemu_hw_version(void);
|
const char *qemu_hw_version(void);
|
||||||
|
|
||||||
|
@ -188,7 +188,7 @@ static void net_vhost_user_event(void *opaque, int event)
|
|||||||
qmp_set_link(name, true, &err);
|
qmp_set_link(name, true, &err);
|
||||||
break;
|
break;
|
||||||
case CHR_EVENT_CLOSED:
|
case CHR_EVENT_CLOSED:
|
||||||
qmp_set_link(name, true, &err);
|
qmp_set_link(name, false, &err);
|
||||||
vhost_user_stop(queues, ncs);
|
vhost_user_stop(queues, ncs);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -45,6 +45,8 @@
|
|||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <sys/eventfd.h>
|
#include <sys/eventfd.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
|
||||||
#include <linux/vhost.h>
|
#include <linux/vhost.h>
|
||||||
|
|
||||||
@ -747,6 +749,7 @@ vubr_get_features_exec(VubrDev *dev, VhostUserMsg *vmsg)
|
|||||||
vmsg->payload.u64 =
|
vmsg->payload.u64 =
|
||||||
((1ULL << VIRTIO_NET_F_MRG_RXBUF) |
|
((1ULL << VIRTIO_NET_F_MRG_RXBUF) |
|
||||||
(1ULL << VHOST_F_LOG_ALL) |
|
(1ULL << VHOST_F_LOG_ALL) |
|
||||||
|
(1ULL << VIRTIO_NET_F_GUEST_ANNOUNCE) |
|
||||||
(1ULL << VHOST_USER_F_PROTOCOL_FEATURES));
|
(1ULL << VHOST_USER_F_PROTOCOL_FEATURES));
|
||||||
|
|
||||||
vmsg->size = sizeof(vmsg->payload.u64);
|
vmsg->size = sizeof(vmsg->payload.u64);
|
||||||
@ -1209,33 +1212,62 @@ vubr_new(const char *path)
|
|||||||
return dev;
|
return dev;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
vubr_set_host(struct sockaddr_in *saddr, const char *host)
|
||||||
|
{
|
||||||
|
if (isdigit(host[0])) {
|
||||||
|
if (!inet_aton(host, &saddr->sin_addr)) {
|
||||||
|
fprintf(stderr, "inet_aton() failed.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
struct hostent *he = gethostbyname(host);
|
||||||
|
|
||||||
|
if (!he) {
|
||||||
|
fprintf(stderr, "gethostbyname() failed.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
saddr->sin_addr = *(struct in_addr *)he->h_addr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
vubr_backend_udp_setup(VubrDev *dev,
|
vubr_backend_udp_setup(VubrDev *dev,
|
||||||
const char *local_host,
|
const char *local_host,
|
||||||
uint16_t local_port,
|
const char *local_port,
|
||||||
const char *dest_host,
|
const char *remote_host,
|
||||||
uint16_t dest_port)
|
const char *remote_port)
|
||||||
{
|
{
|
||||||
int sock;
|
int sock;
|
||||||
struct sockaddr_in si_local = {
|
const char *r;
|
||||||
.sin_family = AF_INET,
|
|
||||||
.sin_port = htons(local_port),
|
|
||||||
};
|
|
||||||
|
|
||||||
if (inet_aton(local_host, &si_local.sin_addr) == 0) {
|
int lport, rport;
|
||||||
fprintf(stderr, "inet_aton() failed.\n");
|
|
||||||
|
lport = strtol(local_port, (char **)&r, 0);
|
||||||
|
if (r == local_port) {
|
||||||
|
fprintf(stderr, "lport parsing failed.\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rport = strtol(remote_port, (char **)&r, 0);
|
||||||
|
if (r == remote_port) {
|
||||||
|
fprintf(stderr, "rport parsing failed.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sockaddr_in si_local = {
|
||||||
|
.sin_family = AF_INET,
|
||||||
|
.sin_port = htons(lport),
|
||||||
|
};
|
||||||
|
|
||||||
|
vubr_set_host(&si_local, local_host);
|
||||||
|
|
||||||
/* setup destination for sends */
|
/* setup destination for sends */
|
||||||
dev->backend_udp_dest = (struct sockaddr_in) {
|
dev->backend_udp_dest = (struct sockaddr_in) {
|
||||||
.sin_family = AF_INET,
|
.sin_family = AF_INET,
|
||||||
.sin_port = htons(dest_port),
|
.sin_port = htons(rport),
|
||||||
};
|
};
|
||||||
if (inet_aton(dest_host, &dev->backend_udp_dest.sin_addr) == 0) {
|
vubr_set_host(&dev->backend_udp_dest, remote_host);
|
||||||
fprintf(stderr, "inet_aton() failed.\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||||
if (sock == -1) {
|
if (sock == -1) {
|
||||||
@ -1249,7 +1281,7 @@ vubr_backend_udp_setup(VubrDev *dev,
|
|||||||
dev->backend_udp_sock = sock;
|
dev->backend_udp_sock = sock;
|
||||||
dispatcher_add(&dev->dispatcher, sock, dev, vubr_backend_recv_cb);
|
dispatcher_add(&dev->dispatcher, sock, dev, vubr_backend_recv_cb);
|
||||||
DPRINT("Waiting for data from udp backend on %s:%d...\n",
|
DPRINT("Waiting for data from udp backend on %s:%d...\n",
|
||||||
local_host, local_port);
|
local_host, lport);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -1262,19 +1294,81 @@ vubr_run(VubrDev *dev)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
vubr_parse_host_port(const char **host, const char **port, const char *buf)
|
||||||
|
{
|
||||||
|
char *p = strchr(buf, ':');
|
||||||
|
|
||||||
|
if (!p) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
*p = '\0';
|
||||||
|
*host = strdup(buf);
|
||||||
|
*port = strdup(p + 1);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define DEFAULT_UD_SOCKET "/tmp/vubr.sock"
|
||||||
|
#define DEFAULT_LHOST "127.0.0.1"
|
||||||
|
#define DEFAULT_LPORT "4444"
|
||||||
|
#define DEFAULT_RHOST "127.0.0.1"
|
||||||
|
#define DEFAULT_RPORT "5555"
|
||||||
|
|
||||||
|
static const char *ud_socket_path = DEFAULT_UD_SOCKET;
|
||||||
|
static const char *lhost = DEFAULT_LHOST;
|
||||||
|
static const char *lport = DEFAULT_LPORT;
|
||||||
|
static const char *rhost = DEFAULT_RHOST;
|
||||||
|
static const char *rport = DEFAULT_RPORT;
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char *argv[])
|
main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
VubrDev *dev;
|
VubrDev *dev;
|
||||||
|
int opt;
|
||||||
|
|
||||||
dev = vubr_new("/tmp/vubr.sock");
|
while ((opt = getopt(argc, argv, "l:r:u:")) != -1) {
|
||||||
|
|
||||||
|
switch (opt) {
|
||||||
|
case 'l':
|
||||||
|
if (vubr_parse_host_port(&lhost, &lport, optarg) < 0) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
if (vubr_parse_host_port(&rhost, &rport, optarg) < 0) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'u':
|
||||||
|
ud_socket_path = strdup(optarg);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DPRINT("ud socket: %s\n", ud_socket_path);
|
||||||
|
DPRINT("local: %s:%s\n", lhost, lport);
|
||||||
|
DPRINT("remote: %s:%s\n", rhost, rport);
|
||||||
|
|
||||||
|
dev = vubr_new(ud_socket_path);
|
||||||
if (!dev) {
|
if (!dev) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
vubr_backend_udp_setup(dev,
|
vubr_backend_udp_setup(dev, lhost, lport, rhost, rport);
|
||||||
"127.0.0.1", 4444,
|
|
||||||
"127.0.0.1", 5555);
|
|
||||||
vubr_run(dev);
|
vubr_run(dev);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
out:
|
||||||
|
fprintf(stderr, "Usage: %s ", argv[0]);
|
||||||
|
fprintf(stderr, "[-u ud_socket_path] [-l lhost:lport] [-r rhost:rport]\n");
|
||||||
|
fprintf(stderr, "\t-u path to unix doman socket. default: %s\n",
|
||||||
|
DEFAULT_UD_SOCKET);
|
||||||
|
fprintf(stderr, "\t-l local host and port. default: %s:%s\n",
|
||||||
|
DEFAULT_LHOST, DEFAULT_LPORT);
|
||||||
|
fprintf(stderr, "\t-r remote host and port. default: %s:%s\n",
|
||||||
|
DEFAULT_RHOST, DEFAULT_RPORT);
|
||||||
|
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -131,6 +131,7 @@ typedef struct TestServer {
|
|||||||
GMutex data_mutex;
|
GMutex data_mutex;
|
||||||
GCond data_cond;
|
GCond data_cond;
|
||||||
int log_fd;
|
int log_fd;
|
||||||
|
uint64_t rings;
|
||||||
} TestServer;
|
} TestServer;
|
||||||
|
|
||||||
#if !GLIB_CHECK_VERSION(2, 32, 0)
|
#if !GLIB_CHECK_VERSION(2, 32, 0)
|
||||||
@ -279,6 +280,9 @@ static void chr_read(void *opaque, const uint8_t *buf, int size)
|
|||||||
msg.payload.state.num = 0;
|
msg.payload.state.num = 0;
|
||||||
p = (uint8_t *) &msg;
|
p = (uint8_t *) &msg;
|
||||||
qemu_chr_fe_write_all(chr, p, VHOST_USER_HDR_SIZE + msg.size);
|
qemu_chr_fe_write_all(chr, p, VHOST_USER_HDR_SIZE + msg.size);
|
||||||
|
|
||||||
|
assert(msg.payload.state.index < 2);
|
||||||
|
s->rings &= ~(0x1ULL << msg.payload.state.index);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VHOST_USER_SET_MEM_TABLE:
|
case VHOST_USER_SET_MEM_TABLE:
|
||||||
@ -316,10 +320,9 @@ static void chr_read(void *opaque, const uint8_t *buf, int size)
|
|||||||
g_cond_signal(&s->data_cond);
|
g_cond_signal(&s->data_cond);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VHOST_USER_SET_VRING_ENABLE:
|
case VHOST_USER_SET_VRING_BASE:
|
||||||
if (!msg.payload.state.num) {
|
assert(msg.payload.state.index < 2);
|
||||||
s->fds_num = 0;
|
s->rings |= 0x1ULL << msg.payload.state.index;
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -486,7 +489,7 @@ static gboolean
|
|||||||
test_migrate_source_check(GSource *source)
|
test_migrate_source_check(GSource *source)
|
||||||
{
|
{
|
||||||
TestMigrateSource *t = (TestMigrateSource *)source;
|
TestMigrateSource *t = (TestMigrateSource *)source;
|
||||||
gboolean overlap = t->src->fds_num > 0 && t->dest->fds_num > 0;
|
gboolean overlap = t->src->rings && t->dest->rings;
|
||||||
|
|
||||||
g_assert(!overlap);
|
g_assert(!overlap);
|
||||||
|
|
||||||
|
@ -52,7 +52,14 @@ extern int madvise(caddr_t, size_t, int);
|
|||||||
|
|
||||||
static bool fips_enabled = false;
|
static bool fips_enabled = false;
|
||||||
|
|
||||||
static const char *hw_version = QEMU_VERSION;
|
/* Starting on QEMU 2.5, qemu_hw_version() returns "2.5+" by default
|
||||||
|
* instead of QEMU_VERSION, so setting hw_version on MachineClass
|
||||||
|
* is no longer mandatory.
|
||||||
|
*
|
||||||
|
* Do NOT change this string, or it will break compatibility on all
|
||||||
|
* machine classes that don't set hw_version.
|
||||||
|
*/
|
||||||
|
static const char *hw_version = "2.5+";
|
||||||
|
|
||||||
int socket_set_cork(int fd, int v)
|
int socket_set_cork(int fd, int v)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user