diff options
-rw-r--r-- | MAINTAINERS | 6 | ||||
-rw-r--r-- | Makefile | 1 | ||||
-rw-r--r-- | arch_init.c | 1 | ||||
-rw-r--r-- | block/iscsi.c | 23 | ||||
-rw-r--r-- | compiler.h | 5 | ||||
-rw-r--r-- | console.c | 7 | ||||
-rw-r--r-- | cpus.c | 6 | ||||
-rw-r--r-- | hw/cadence_uart.c | 2 | ||||
-rw-r--r-- | hw/ioh3420.c | 1 | ||||
-rw-r--r-- | hw/lm4549.c | 2 | ||||
-rw-r--r-- | hw/pflash_cfi01.c | 8 | ||||
-rw-r--r-- | hw/scsi-bus.c | 23 | ||||
-rw-r--r-- | hw/scsi-disk.c | 44 | ||||
-rw-r--r-- | hw/scsi.h | 2 | ||||
-rw-r--r-- | linux-user/main.c | 6 | ||||
-rw-r--r-- | linux-user/syscall.c | 4 | ||||
-rw-r--r-- | nbd.c | 396 | ||||
-rw-r--r-- | nbd.h | 15 | ||||
-rw-r--r-- | net/socket.c | 6 | ||||
-rw-r--r-- | os-posix.c | 5 | ||||
-rw-r--r-- | qemu-common.h | 5 | ||||
-rw-r--r-- | qemu-ga.c | 2 | ||||
-rw-r--r-- | qemu-nbd.c | 36 | ||||
-rw-r--r-- | qemu-os-posix.h | 2 | ||||
-rw-r--r-- | qemu-os-win32.h | 5 | ||||
-rw-r--r-- | qemu-sockets.c | 2 | ||||
-rw-r--r-- | qemu-timer.c | 7 | ||||
-rw-r--r-- | scripts/tracetool/backend/dtrace.py | 2 | ||||
-rw-r--r-- | sysconfigs/target/cpus-x86_64.conf | 128 | ||||
-rw-r--r-- | target-alpha/translate.c | 1 | ||||
-rw-r--r-- | target-i386/cpu.c | 413 | ||||
-rw-r--r-- | target-i386/cpu.h | 26 | ||||
-rw-r--r-- | vl.c | 4 |
33 files changed, 752 insertions, 444 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 61f8b45cb5..25733fc864 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -531,6 +531,12 @@ M: Anthony Liguori <aliguori@us.ibm.com> S: Maintained F: qemu-char.c +CPU +M: Andreas Färber <afaerber@suse.de> +S: Supported +F: qom/cpu.c +F: include/qemu/cpu.h + Device Tree M: Peter Crosthwaite <peter.crosthwaite@petalogix.com> M: Alexander Graf <agraf@suse.de> @@ -298,7 +298,6 @@ install-confdir: install-sysconfig: install-datadir install-confdir $(INSTALL_DATA) $(SRC_PATH)/sysconfigs/target/target-x86_64.conf "$(DESTDIR)$(qemu_confdir)" - $(INSTALL_DATA) $(SRC_PATH)/sysconfigs/target/cpus-x86_64.conf "$(DESTDIR)$(qemu_datadir)" install: all $(if $(BUILD_DOCS),install-doc) install-sysconfig install-datadir $(INSTALL_DIR) "$(DESTDIR)$(bindir)" diff --git a/arch_init.c b/arch_init.c index f849f9b872..9904f95478 100644 --- a/arch_init.c +++ b/arch_init.c @@ -136,7 +136,6 @@ static struct defconfig_file { /* Indicates it is an user config file (disabled by -no-user-config) */ bool userconfig; } default_config_files[] = { - { CONFIG_QEMU_DATADIR "/cpus-" TARGET_ARCH ".conf", false }, { CONFIG_QEMU_CONFDIR "/qemu.conf", true }, { CONFIG_QEMU_CONFDIR "/target-" TARGET_ARCH ".conf", true }, { NULL }, /* end of list */ diff --git a/block/iscsi.c b/block/iscsi.c index 70cf700e53..d0b1a10ee4 100644 --- a/block/iscsi.c +++ b/block/iscsi.c @@ -167,12 +167,6 @@ iscsi_set_events(IscsiLun *iscsilun) } - /* If we just added an event, the callback might be delayed - * unless we call qemu_notify_event(). - */ - if (ev & ~iscsilun->events) { - qemu_notify_event(); - } iscsilun->events = ev; } @@ -624,9 +618,17 @@ static BlockDriverAIOCB *iscsi_aio_ioctl(BlockDriverState *bs, return &acb->common; } + +static void ioctl_cb(void *opaque, int status) +{ + int *p_status = opaque; + *p_status = status; +} + static int iscsi_ioctl(BlockDriverState *bs, unsigned long int req, void *buf) { IscsiLun *iscsilun = bs->opaque; + int status; switch (req) { case SG_GET_VERSION_NUM: @@ -635,6 +637,15 @@ static int iscsi_ioctl(BlockDriverState *bs, unsigned long int req, void *buf) case SG_GET_SCSI_ID: ((struct sg_scsi_id *)buf)->scsi_type = iscsilun->type; break; + case SG_IO: + status = -EINPROGRESS; + iscsi_aio_ioctl(bs, req, buf, ioctl_cb, &status); + + while (status == -EINPROGRESS) { + qemu_aio_wait(); + } + + return 0; default: return -1; } diff --git a/compiler.h b/compiler.h index 07ba1f8113..c734a71c67 100644 --- a/compiler.h +++ b/compiler.h @@ -44,6 +44,11 @@ /* Use gnu_printf when supported (qemu uses standard format strings). */ # define GCC_ATTR __attribute__((__unused__, format(gnu_printf, 1, 2))) # define GCC_FMT_ATTR(n, m) __attribute__((format(gnu_printf, n, m))) +# if defined(_WIN32) + /* Map __printf__ to __gnu_printf__ because we want standard format strings + * even when MinGW or GLib include files use __printf__. */ +# define __printf__ __gnu_printf__ +# endif # endif #if defined(_WIN32) #define GCC_WEAK __attribute__((weak)) @@ -938,8 +938,11 @@ static void console_putchar(TextConsole *s, int ch) case TTY_STATE_CSI: /* handle escape sequence parameters */ if (ch >= '0' && ch <= '9') { if (s->nb_esc_params < MAX_ESC_PARAMS) { - s->esc_params[s->nb_esc_params] = - s->esc_params[s->nb_esc_params] * 10 + ch - '0'; + int *param = &s->esc_params[s->nb_esc_params]; + int digit = (ch - '0'); + + *param = (*param <= (INT_MAX - digit) / 10) ? + *param * 10 + digit : INT_MAX; } } else { if (s->nb_esc_params < MAX_ESC_PARAMS) @@ -1192,10 +1192,8 @@ void set_cpu_log_filename(const char *optarg) void list_cpus(FILE *f, fprintf_function cpu_fprintf, const char *optarg) { /* XXX: implement xxx_cpu_list for targets that still miss it */ -#if defined(cpu_list_id) - cpu_list_id(f, cpu_fprintf, optarg); -#elif defined(cpu_list) - cpu_list(f, cpu_fprintf); /* deprecated */ +#if defined(cpu_list) + cpu_list(f, cpu_fprintf); #endif } diff --git a/hw/cadence_uart.c b/hw/cadence_uart.c index d98e531372..f8afc4ed26 100644 --- a/hw/cadence_uart.c +++ b/hw/cadence_uart.c @@ -404,7 +404,7 @@ static uint64_t uart_read(void *opaque, target_phys_addr_t offset, uint32_t c = 0; offset >>= 2; - if (offset > R_MAX) { + if (offset >= R_MAX) { return 0; } else if (offset == R_TX_RX) { uart_read_rx_fifo(s, &c); diff --git a/hw/ioh3420.c b/hw/ioh3420.c index 94a537c9b3..4d314733b9 100644 --- a/hw/ioh3420.c +++ b/hw/ioh3420.c @@ -125,7 +125,6 @@ static int ioh3420_initfn(PCIDevice *d) rc = pcie_chassis_add_slot(s); if (rc < 0) { goto err_pcie_cap; - return rc; } pcie_cap_root_init(d); rc = pcie_aer_init(d, IOH_EP_AER_OFFSET); diff --git a/hw/lm4549.c b/hw/lm4549.c index 80b3ec4a5d..e0137d54b6 100644 --- a/hw/lm4549.c +++ b/hw/lm4549.c @@ -224,7 +224,7 @@ uint32_t lm4549_write_samples(lm4549_state *s, uint32_t left, uint32_t right) This model supports 16-bit playback. */ - if (s->buffer_level >= LM4549_BUFFER_SIZE) { + if (s->buffer_level > LM4549_BUFFER_SIZE - 2) { DPRINTF("write_sample Buffer full\n"); return 0; } diff --git a/hw/pflash_cfi01.c b/hw/pflash_cfi01.c index 9c42d3105c..855890d1f1 100644 --- a/hw/pflash_cfi01.c +++ b/hw/pflash_cfi01.c @@ -321,7 +321,7 @@ static void pflash_write(pflash_t *pfl, target_phys_addr_t offset, } pfl->wcycle++; pfl->cmd = cmd; - return; + break; case 1: switch (pfl->cmd) { case 0x10: /* Single Byte Program */ @@ -376,7 +376,7 @@ static void pflash_write(pflash_t *pfl, target_phys_addr_t offset, default: goto error_flash; } - return; + break; case 2: switch (pfl->cmd) { case 0xe8: /* Block write */ @@ -407,7 +407,7 @@ static void pflash_write(pflash_t *pfl, target_phys_addr_t offset, default: goto error_flash; } - return; + break; case 3: /* Confirm mode */ switch (pfl->cmd) { case 0xe8: /* Block write */ @@ -423,7 +423,7 @@ static void pflash_write(pflash_t *pfl, target_phys_addr_t offset, default: goto error_flash; } - return; + break; default: /* Should never happen */ DPRINTF("%s: invalid write state\n", __func__); diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c index 4981a02436..058d3b237f 100644 --- a/hw/scsi-bus.c +++ b/hw/scsi-bus.c @@ -801,26 +801,39 @@ static int ata_passthrough_16_xfer_size(SCSIDevice *dev, uint8_t *buf) return xfer * unit; } -static int scsi_req_length(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf) +uint32_t scsi_data_cdb_length(uint8_t *buf) +{ + if ((buf[0] >> 5) == 0 && buf[4] == 0) { + return 256; + } else { + return scsi_cdb_length(buf); + } +} + +uint32_t scsi_cdb_length(uint8_t *buf) { switch (buf[0] >> 5) { case 0: - cmd->xfer = buf[4]; + return buf[4]; break; case 1: case 2: - cmd->xfer = lduw_be_p(&buf[7]); + return lduw_be_p(&buf[7]); break; case 4: - cmd->xfer = ldl_be_p(&buf[10]) & 0xffffffffULL; + return ldl_be_p(&buf[10]) & 0xffffffffULL; break; case 5: - cmd->xfer = ldl_be_p(&buf[6]) & 0xffffffffULL; + return ldl_be_p(&buf[6]) & 0xffffffffULL; break; default: return -1; } +} +static int scsi_req_length(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf) +{ + cmd->xfer = scsi_cdb_length(buf); switch (buf[0]) { case TEST_UNIT_READY: case REWIND: diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c index 1585683bce..95e91585e6 100644 --- a/hw/scsi-disk.c +++ b/hw/scsi-disk.c @@ -678,7 +678,7 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf) * is actually implemented, but we're good enough. */ outbuf[2] = 5; - outbuf[3] = 2; /* Format 2 */ + outbuf[3] = 2 | 0x10; /* Format 2, HiSup */ if (buflen > 36) { outbuf[4] = buflen - 5; /* Additional Length = (Len - 1) - 4 */ @@ -1449,6 +1449,22 @@ invalid_field: return; } +static inline bool check_lba_range(SCSIDiskState *s, + uint64_t sector_num, uint32_t nb_sectors) +{ + /* + * The first line tests that no overflow happens when computing the last + * sector. The second line tests that the last accessed sector is in + * range. + * + * Careful, the computations should not underflow for nb_sectors == 0, + * and a 0-block read to the first LBA beyond the end of device is + * valid. + */ + return (sector_num <= sector_num + nb_sectors && + sector_num + nb_sectors <= s->qdev.max_lba + 1); +} + typedef struct UnmapCBData { SCSIDiskReq *r; uint8_t *inbuf; @@ -1473,8 +1489,7 @@ static void scsi_unmap_complete(void *opaque, int ret) if (data->count > 0 && !r->req.io_canceled) { sector_num = ldq_be_p(&data->inbuf[0]); nb_sectors = ldl_be_p(&data->inbuf[8]) & 0xffffffffULL; - if (sector_num > sector_num + nb_sectors || - sector_num + nb_sectors - 1 > s->qdev.max_lba) { + if (!check_lba_range(s, sector_num, nb_sectors)) { scsi_check_condition(r, SENSE_CODE(LBA_OUT_OF_RANGE)); goto done; } @@ -1793,17 +1808,13 @@ static int32_t scsi_disk_emulate_command(SCSIRequest *req, uint8_t *buf) DPRINTF("Unmap (len %lu)\n", (long)r->req.cmd.xfer); break; case WRITE_SAME_10: - nb_sectors = lduw_be_p(&req->cmd.buf[7]); - goto write_same; case WRITE_SAME_16: - nb_sectors = ldl_be_p(&req->cmd.buf[10]) & 0xffffffffULL; - write_same: + nb_sectors = scsi_data_cdb_length(r->req.cmd.buf); if (bdrv_is_read_only(s->qdev.conf.bs)) { scsi_check_condition(r, SENSE_CODE(WRITE_PROTECTED)); return 0; } - if (r->req.cmd.lba > r->req.cmd.lba + nb_sectors || - r->req.cmd.lba + nb_sectors - 1 > s->qdev.max_lba) { + if (!check_lba_range(s, r->req.cmd.lba, nb_sectors)) { goto illegal_lba; } @@ -1858,7 +1869,7 @@ static int32_t scsi_disk_dma_command(SCSIRequest *req, uint8_t *buf) { SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req); SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev); - int32_t len; + uint32_t len; uint8_t command; command = buf[0]; @@ -1868,18 +1879,17 @@ static int32_t scsi_disk_dma_command(SCSIRequest *req, uint8_t *buf) return 0; } + len = scsi_data_cdb_length(r->req.cmd.buf); switch (command) { case READ_6: case READ_10: case READ_12: case READ_16: - len = r->req.cmd.xfer / s->qdev.blocksize; - DPRINTF("Read (sector %" PRId64 ", count %d)\n", r->req.cmd.lba, len); + DPRINTF("Read (sector %" PRId64 ", count %u)\n", r->req.cmd.lba, len); if (r->req.cmd.buf[1] & 0xe0) { goto illegal_request; } - if (r->req.cmd.lba > r->req.cmd.lba + len || - r->req.cmd.lba + len - 1 > s->qdev.max_lba) { + if (!check_lba_range(s, r->req.cmd.lba, len)) { goto illegal_lba; } r->sector = r->req.cmd.lba * (s->qdev.blocksize / 512); @@ -1900,15 +1910,13 @@ static int32_t scsi_disk_dma_command(SCSIRequest *req, uint8_t *buf) case VERIFY_10: case VERIFY_12: case VERIFY_16: - len = r->req.cmd.xfer / s->qdev.blocksize; - DPRINTF("Write %s(sector %" PRId64 ", count %d)\n", + DPRINTF("Write %s(sector %" PRId64 ", count %u)\n", (command & 0xe) == 0xe ? "And Verify " : "", r->req.cmd.lba, len); if (r->req.cmd.buf[1] & 0xe0) { goto illegal_request; } - if (r->req.cmd.lba > r->req.cmd.lba + len || - r->req.cmd.lba + len - 1 > s->qdev.max_lba) { + if (!check_lba_range(s, r->req.cmd.lba, len)) { goto illegal_lba; } r->sector = r->req.cmd.lba * (s->qdev.blocksize / 512); @@ -218,6 +218,8 @@ extern const struct SCSISense sense_code_WRITE_PROTECTED; #define SENSE_CODE(x) sense_code_ ## x +uint32_t scsi_data_cdb_length(uint8_t *buf); +uint32_t scsi_cdb_length(uint8_t *buf); int scsi_sense_valid(SCSISense sense); int scsi_build_sense(uint8_t *in_buf, int in_len, uint8_t *buf, int len, bool fixed); diff --git a/linux-user/main.c b/linux-user/main.c index e84a18c33c..9f3476ba57 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -3130,10 +3130,8 @@ static void handle_arg_cpu(const char *arg) cpu_model = strdup(arg); if (cpu_model == NULL || is_help_option(cpu_model)) { /* XXX: implement xxx_cpu_list for targets that still miss it */ -#if defined(cpu_list_id) - cpu_list_id(stdout, &fprintf, ""); -#elif defined(cpu_list) - cpu_list(stdout, &fprintf); /* deprecated */ +#if defined(cpu_list) + cpu_list(stdout, &fprintf); #endif exit(1); } diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 6257a04d0a..471d0605f7 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -3628,9 +3628,7 @@ static abi_long do_ioctl_dm(const IOCTLEntry *ie, uint8_t *buf_temp, int fd, unlock_user(argptr, arg, target_size); } out: - if (big_buf) { - free(big_buf); - } + g_free(big_buf); return ret; } @@ -57,9 +57,12 @@ /* This is all part of the "official" NBD API */ +#define NBD_REQUEST_SIZE (4 + 4 + 8 + 8 + 4) #define NBD_REPLY_SIZE (4 + 4 + 8) #define NBD_REQUEST_MAGIC 0x25609513 #define NBD_REPLY_MAGIC 0x67446698 +#define NBD_OPTS_MAGIC 0x49484156454F5054LL +#define NBD_CLIENT_MAGIC 0x0000420281861253LL #define NBD_SET_SOCK _IO(0xab, 0) #define NBD_SET_BLKSIZE _IO(0xab, 1) @@ -75,6 +78,49 @@ #define NBD_OPT_EXPORT_NAME (1 << 0) +/* Definitions for opaque data types */ + +typedef struct NBDRequest NBDRequest; + +struct NBDRequest { + QSIMPLEQ_ENTRY(NBDRequest) entry; + NBDClient *client; + uint8_t *data; +}; + +struct NBDExport { + int refcount; + void (*close)(NBDExport *exp); + + BlockDriverState *bs; + char *name; + off_t dev_offset; + off_t size; + uint32_t nbdflags; + QTAILQ_HEAD(, NBDClient) clients; + QSIMPLEQ_HEAD(, NBDRequest) requests; + QTAILQ_ENTRY(NBDExport) next; +}; + +static QTAILQ_HEAD(, NBDExport) exports = QTAILQ_HEAD_INITIALIZER(exports); + +struct NBDClient { + int refcount; + void (*close)(NBDClient *client); + + NBDExport *exp; + int sock; + + Coroutine *recv_coroutine; + + CoMutex send_lock; + Coroutine *send_coroutine; + + QTAILQ_ENTRY(NBDClient) next; + int nb_requests; + bool closing; +}; + /* That's all folks */ ssize_t nbd_wr_sync(int fd, void *buffer, size_t size, bool do_read) @@ -192,11 +238,23 @@ int unix_socket_outgoing(const char *path) return unix_connect(path); } -/* Basic flow +/* Basic flow for negotiation Server Client - Negotiate + + or + + Server Client + Negotiate #1 + Option + Negotiate #2 + + ---- + + followed by + + Server Client Request Response Request @@ -204,19 +262,112 @@ int unix_socket_outgoing(const char *path) ... ... Request (type == 2) + */ -static int nbd_send_negotiate(int csock, off_t size, uint32_t flags) +static int nbd_receive_options(NBDClient *client) +{ + int csock = client->sock; + char name[256]; + uint32_t tmp, length; + uint64_t magic; + int rc; + + /* Client sends: + [ 0 .. 3] reserved (0) + [ 4 .. 11] NBD_OPTS_MAGIC + [12 .. 15] NBD_OPT_EXPORT_NAME + [16 .. 19] length + [20 .. xx] export name (length bytes) + */ + + rc = -EINVAL; + if (read_sync(csock, &tmp, sizeof(tmp)) != sizeof(tmp)) { + LOG("read failed"); + goto fail; + } + TRACE("Checking reserved"); + if (tmp != 0) { + LOG("Bad reserved received"); + goto fail; + } + + if (read_sync(csock, &magic, sizeof(magic)) != sizeof(magic)) { + LOG("read failed"); + goto fail; + } + TRACE("Checking reserved"); + if (magic != be64_to_cpu(NBD_OPTS_MAGIC)) { + LOG("Bad magic received"); + goto fail; + } + + if (read_sync(csock, &tmp, sizeof(tmp)) != sizeof(tmp)) { + LOG("read failed"); + goto fail; + } + TRACE("Checking option"); + if (tmp != be32_to_cpu(NBD_OPT_EXPORT_NAME)) { + LOG("Bad option received"); + goto fail; + } + + if (read_sync(csock, &length, sizeof(length)) != sizeof(length)) { + LOG("read failed"); + goto fail; + } + TRACE("Checking length"); + length = be32_to_cpu(length); + if (length > 255) { + LOG("Bad length received"); + goto fail; + } + if (read_sync(csock, name, length) != length) { + LOG("read failed"); + goto fail; + } + name[length] = '\0'; + + client->exp = nbd_export_find(name); + if (!client->exp) { + LOG("export not found"); + goto fail; + } + + QTAILQ_INSERT_TAIL(&client->exp->clients, client, next); + nbd_export_get(client->exp); + + TRACE("Option negotiation succeeded."); + rc = 0; +fail: + return rc; +} + +static int nbd_send_negotiate(NBDClient *client) { + int csock = client->sock; char buf[8 + 8 + 8 + 128]; int rc; + const int myflags = (NBD_FLAG_HAS_FLAGS | NBD_FLAG_SEND_TRIM | + NBD_FLAG_SEND_FLUSH | NBD_FLAG_SEND_FUA); - /* Negotiate - [ 0 .. 7] passwd ("NBDMAGIC") - [ 8 .. 15] magic (0x00420281861253) + /* Negotiation header without options: + [ 0 .. 7] passwd ("NBDMAGIC") + [ 8 .. 15] magic (NBD_CLIENT_MAGIC) [16 .. 23] size - [24 .. 27] flags - [28 .. 151] reserved (0) + [24 .. 25] server flags (0) + [24 .. 27] export flags + [28 .. 151] reserved (0) + + Negotiation header with options, part 1: + [ 0 .. 7] passwd ("NBDMAGIC") + [ 8 .. 15] magic (NBD_OPTS_MAGIC) + [16 .. 17] server flags (0) + + part 2 (after options are sent): + [18 .. 25] size + [26 .. 27] export flags + [28 .. 151] reserved (0) */ socket_set_block(csock); @@ -224,16 +375,39 @@ static int nbd_send_negotiate(int csock, off_t size, uint32_t flags) TRACE("Beginning negotiation."); memcpy(buf, "NBDMAGIC", 8); - cpu_to_be64w((uint64_t*)(buf + 8), 0x00420281861253LL); - cpu_to_be64w((uint64_t*)(buf + 16), size); - cpu_to_be32w((uint32_t*)(buf + 24), - flags | NBD_FLAG_HAS_FLAGS | NBD_FLAG_SEND_TRIM | - NBD_FLAG_SEND_FLUSH | NBD_FLAG_SEND_FUA); + if (client->exp) { + assert ((client->exp->nbdflags & ~65535) == 0); + cpu_to_be64w((uint64_t*)(buf + 8), NBD_CLIENT_MAGIC); + cpu_to_be64w((uint64_t*)(buf + 16), client->exp->size); + cpu_to_be16w((uint16_t*)(buf + 26), client->exp->nbdflags | myflags); + } else { + cpu_to_be64w((uint64_t*)(buf + 8), NBD_OPTS_MAGIC); + } memset(buf + 28, 0, 124); - if (write_sync(csock, buf, sizeof(buf)) != sizeof(buf)) { - LOG("write failed"); - goto fail; + if (client->exp) { + if (write_sync(csock, buf, sizeof(buf)) != sizeof(buf)) { + LOG("write failed"); + goto fail; + } + } else { + if (write_sync(csock, buf, 18) != 18) { + LOG("write failed"); + goto fail; + } + rc = nbd_receive_options(client); + if (rc < 0) { + LOG("option negotiation failed"); + goto fail; + } + + assert ((client->exp->nbdflags & ~65535) == 0); + cpu_to_be64w((uint64_t*)(buf + 18), client->exp->size); + cpu_to_be16w((uint16_t*)(buf + 26), client->exp->nbdflags | myflags); + if (write_sync(csock, buf + 18, sizeof(buf) - 18) != sizeof(buf) - 18) { + LOG("write failed"); + goto fail; + } } TRACE("Negotiation succeeded."); @@ -295,7 +469,7 @@ int nbd_receive_negotiate(int csock, const char *name, uint32_t *flags, uint32_t namesize; TRACE("Checking magic (opts_magic)"); - if (magic != 0x49484156454F5054LL) { + if (magic != NBD_OPTS_MAGIC) { LOG("Bad magic received"); goto fail; } @@ -334,7 +508,7 @@ int nbd_receive_negotiate(int csock, const char *name, uint32_t *flags, } else { TRACE("Checking magic (cli_magic)"); - if (magic != 0x00420281861253LL) { + if (magic != NBD_CLIENT_MAGIC) { LOG("Bad magic received"); goto fail; } @@ -477,7 +651,7 @@ int nbd_client(int fd) ssize_t nbd_send_request(int csock, struct nbd_request *request) { - uint8_t buf[4 + 4 + 8 + 8 + 4]; + uint8_t buf[NBD_REQUEST_SIZE]; ssize_t ret; cpu_to_be32w((uint32_t*)buf, NBD_REQUEST_MAGIC); @@ -504,7 +678,7 @@ ssize_t nbd_send_request(int csock, struct nbd_request *request) static ssize_t nbd_receive_request(int csock, struct nbd_request *request) { - uint8_t buf[4 + 4 + 8 + 8 + 4]; + uint8_t buf[NBD_REQUEST_SIZE]; uint32_t magic; ssize_t ret; @@ -582,7 +756,7 @@ ssize_t nbd_receive_reply(int csock, struct nbd_reply *reply) static ssize_t nbd_send_reply(int csock, struct nbd_reply *reply) { - uint8_t buf[4 + 4 + 8]; + uint8_t buf[NBD_REPLY_SIZE]; ssize_t ret; /* Reply @@ -610,58 +784,47 @@ static ssize_t nbd_send_reply(int csock, struct nbd_reply *reply) #define MAX_NBD_REQUESTS 16 -typedef struct NBDRequest NBDRequest; - -struct NBDRequest { - QSIMPLEQ_ENTRY(NBDRequest) entry; - NBDClient *client; - uint8_t *data; -}; - -struct NBDExport { - BlockDriverState *bs; - off_t dev_offset; - off_t size; - uint32_t nbdflags; - QSIMPLEQ_HEAD(, NBDRequest) requests; -}; - -struct NBDClient { - int refcount; - void (*close)(NBDClient *client); - - NBDExport *exp; - int sock; - - Coroutine *recv_coroutine; - - CoMutex send_lock; - Coroutine *send_coroutine; - - int nb_requests; -}; - -static void nbd_client_get(NBDClient *client) +void nbd_client_get(NBDClient *client) { client->refcount++; } -static void nbd_client_put(NBDClient *client) +void nbd_client_put(NBDClient *client) { if (--client->refcount == 0) { + /* The last reference should be dropped by client->close, + * which is called by nbd_client_close. + */ + assert(client->closing); + + qemu_set_fd_handler2(client->sock, NULL, NULL, NULL, NULL); + close(client->sock); + client->sock = -1; + if (client->exp) { + QTAILQ_REMOVE(&client->exp->clients, client, next); + nbd_export_put(client->exp); + } g_free(client); } } -static void nbd_client_close(NBDClient *client) +void nbd_client_close(NBDClient *client) { - qemu_set_fd_handler2(client->sock, NULL, NULL, NULL, NULL); - close(client->sock); - client->sock = -1; + if (client->closing) { + return; + } + + client->closing = true; + + /* Force requests to finish. They will drop their own references, + * then we'll close the socket and free the NBDClient. + */ + shutdown(client->sock, 2); + + /* Also tell the client, so that they release their reference. */ if (client->close) { client->close(client); } - nbd_client_put(client); } static NBDRequest *nbd_request_get(NBDClient *client) @@ -695,28 +858,109 @@ static void nbd_request_put(NBDRequest *req) } NBDExport *nbd_export_new(BlockDriverState *bs, off_t dev_offset, - off_t size, uint32_t nbdflags) + off_t size, uint32_t nbdflags, + void (*close)(NBDExport *)) { NBDExport *exp = g_malloc0(sizeof(NBDExport)); QSIMPLEQ_INIT(&exp->requests); + exp->refcount = 1; + QTAILQ_INIT(&exp->clients); exp->bs = bs; exp->dev_offset = dev_offset; exp->nbdflags = nbdflags; exp->size = size == -1 ? bdrv_getlength(bs) : size; + exp->close = close; return exp; } +NBDExport *nbd_export_find(const char *name) +{ + NBDExport *exp; + QTAILQ_FOREACH(exp, &exports, next) { + if (strcmp(name, exp->name) == 0) { + return exp; + } + } + + return NULL; +} + +void nbd_export_set_name(NBDExport *exp, const char *name) +{ + if (exp->name == name) { + return; + } + + nbd_export_get(exp); + if (exp->name != NULL) { + g_free(exp->name); + exp->name = NULL; + QTAILQ_REMOVE(&exports, exp, next); + nbd_export_put(exp); + } + if (name != NULL) { + nbd_export_get(exp); + exp->name = g_strdup(name); + QTAILQ_INSERT_TAIL(&exports, exp, next); + } + nbd_export_put(exp); +} + void nbd_export_close(NBDExport *exp) { - while (!QSIMPLEQ_EMPTY(&exp->requests)) { - NBDRequest *first = QSIMPLEQ_FIRST(&exp->requests); - QSIMPLEQ_REMOVE_HEAD(&exp->requests, entry); - qemu_vfree(first->data); - g_free(first); + NBDClient *client, *next; + + nbd_export_get(exp); + QTAILQ_FOREACH_SAFE(client, &exp->clients, next, next) { + nbd_client_close(client); } + nbd_export_set_name(exp, NULL); + nbd_export_put(exp); +} - bdrv_close(exp->bs); - g_free(exp); +void nbd_export_get(NBDExport *exp) +{ + assert(exp->refcount > 0); + exp->refcount++; +} + +void nbd_export_put(NBDExport *exp) +{ + assert(exp->refcount > 0); + if (exp->refcount == 1) { + nbd_export_close(exp); + } + + if (--exp->refcount == 0) { + assert(exp->name == NULL); + + if (exp->close) { + exp->close(exp); + } + + while (!QSIMPLEQ_EMPTY(&exp->requests)) { + NBDRequest *first = QSIMPLEQ_FIRST(&exp->requests); + QSIMPLEQ_REMOVE_HEAD(&exp->requests, entry); + qemu_vfree(first->data); + g_free(first); + } + + g_free(exp); + } +} + +BlockDriverState *nbd_export_get_blockdev(NBDExport *exp) +{ + return exp->bs; +} + +void nbd_export_close_all(void) +{ + NBDExport *exp, *next; + + QTAILQ_FOREACH_SAFE(exp, &exports, next, next) { + nbd_export_close(exp); + } } static int nbd_can_read(void *opaque); @@ -805,14 +1049,18 @@ out: static void nbd_trip(void *opaque) { NBDClient *client = opaque; - NBDRequest *req = nbd_request_get(client); NBDExport *exp = client->exp; + NBDRequest *req; struct nbd_request request; struct nbd_reply reply; ssize_t ret; TRACE("Reading request."); + if (client->closing) { + return; + } + req = nbd_request_get(client); ret = nbd_co_receive_request(req, &request); if (ret == -EAGAIN) { goto done; @@ -974,15 +1222,21 @@ NBDClient *nbd_client_new(NBDExport *exp, int csock, void (*close)(NBDClient *)) { NBDClient *client; - if (nbd_send_negotiate(csock, exp->size, exp->nbdflags) < 0) { - return NULL; - } client = g_malloc0(sizeof(NBDClient)); client->refcount = 1; client->exp = exp; client->sock = csock; + if (nbd_send_negotiate(client) < 0) { + g_free(client); + return NULL; + } client->close = close; qemu_co_mutex_init(&client->send_lock); qemu_set_fd_handler2(csock, nbd_can_read, nbd_read, NULL, client); + + if (exp) { + QTAILQ_INSERT_TAIL(&exp->clients, client, next); + nbd_export_get(exp); + } return client; } @@ -79,9 +79,22 @@ typedef struct NBDExport NBDExport; typedef struct NBDClient NBDClient; NBDExport *nbd_export_new(BlockDriverState *bs, off_t dev_offset, - off_t size, uint32_t nbdflags); + off_t size, uint32_t nbdflags, + void (*close)(NBDExport *)); void nbd_export_close(NBDExport *exp); +void nbd_export_get(NBDExport *exp); +void nbd_export_put(NBDExport *exp); + +BlockDriverState *nbd_export_get_blockdev(NBDExport *exp); + +NBDExport *nbd_export_find(const char *name); +void nbd_export_set_name(NBDExport *exp, const char *name); +void nbd_export_close_all(void); + NBDClient *nbd_client_new(NBDExport *exp, int csock, void (*close)(NBDClient *)); +void nbd_client_close(NBDClient *client); +void nbd_client_get(NBDClient *client); +void nbd_client_put(NBDClient *client); #endif diff --git a/net/socket.c b/net/socket.c index 5e0c92e062..f3d7878264 100644 --- a/net/socket.c +++ b/net/socket.c @@ -131,9 +131,9 @@ static ssize_t net_socket_receive_dgram(NetClientState *nc, const uint8_t *buf, ssize_t ret; do { - ret = sendto(s->fd, buf, size, 0, - (struct sockaddr *)&s->dgram_dst, - sizeof(s->dgram_dst)); + ret = qemu_sendto(s->fd, buf, size, 0, + (struct sockaddr *)&s->dgram_dst, + sizeof(s->dgram_dst)); } while (ret == -1 && errno == EINTR); if (ret == -1 && errno == EAGAIN) { diff --git a/os-posix.c b/os-posix.c index 79fa2288e4..eabccb8fe0 100644 --- a/os-posix.c +++ b/os-posix.c @@ -360,3 +360,8 @@ int qemu_create_pidfile(const char *filename) /* keep pidfile open & locked forever */ return 0; } + +bool is_daemonized(void) +{ + return daemonize; +} diff --git a/qemu-common.h b/qemu-common.h index e5c2bcd204..15d9e4ed71 100644 --- a/qemu-common.h +++ b/qemu-common.h @@ -223,9 +223,14 @@ int qemu_pipe(int pipefd[2]); #endif #ifdef _WIN32 +/* MinGW needs a type cast for the 'buf' argument. */ #define qemu_recv(sockfd, buf, len, flags) recv(sockfd, (void *)buf, len, flags) +#define qemu_sendto(sockfd, buf, len, flags, destaddr, addrlen) \ + sendto(sockfd, (const void *)buf, len, flags, destaddr, addrlen) #else #define qemu_recv(sockfd, buf, len, flags) recv(sockfd, buf, len, flags) +#define qemu_sendto(sockfd, buf, len, flags, destaddr, addrlen) \ + sendto(sockfd, buf, len, flags, destaddr, addrlen) #endif /* Error handling. */ @@ -114,12 +114,10 @@ static gboolean register_signal_handlers(void) ret = sigaction(SIGINT, &sigact, NULL); if (ret == -1) { g_error("error configuring signal handler: %s", strerror(errno)); - return false; } ret = sigaction(SIGTERM, &sigact, NULL); if (ret == -1) { g_error("error configuring signal handler: %s", strerror(errno)); - return false; } return true; diff --git a/qemu-nbd.c b/qemu-nbd.c index 1c1cf6a463..15bcd08123 100644 --- a/qemu-nbd.c +++ b/qemu-nbd.c @@ -41,8 +41,8 @@ static NBDExport *exp; static int verbose; static char *srcpath; static char *sockpath; -static bool sigterm_reported; -static bool nbd_started; +static int persistent = 0; +static enum { RUNNING, TERMINATE, TERMINATING, TERMINATED } state; static int shared = 1; static int nb_fds; @@ -186,7 +186,7 @@ static int find_partition(BlockDriverState *bs, int partition, static void termsig_handler(int signum) { - sigterm_reported = true; + state = TERMINATE; qemu_notify_event(); } @@ -269,10 +269,20 @@ static int nbd_can_accept(void *opaque) return nb_fds < shared; } +static void nbd_export_closed(NBDExport *exp) +{ + assert(state == TERMINATING); + state = TERMINATED; +} + static void nbd_client_closed(NBDClient *client) { nb_fds--; + if (nb_fds == 0 && !persistent && state == RUNNING) { + state = TERMINATE; + } qemu_notify_event(); + nbd_client_put(client); } static void nbd_accept(void *opaque) @@ -282,7 +292,11 @@ static void nbd_accept(void *opaque) socklen_t addr_len = sizeof(addr); int fd = accept(server_fd, (struct sockaddr *)&addr, &addr_len); - nbd_started = true; + if (state >= TERMINATE) { + close(fd); + return; + } + if (fd >= 0 && nbd_client_new(exp, fd, nbd_client_closed)) { nb_fds++; } @@ -329,7 +343,6 @@ int main(int argc, char **argv) int partition = -1; int ret; int fd; - int persistent = 0; bool seen_cache = false; #ifdef CONFIG_LINUX_AIO bool seen_aio = false; @@ -546,7 +559,7 @@ int main(int argc, char **argv) } } - exp = nbd_export_new(bs, dev_offset, fd_size, nbdflags); + exp = nbd_export_new(bs, dev_offset, fd_size, nbdflags, nbd_export_closed); if (sockpath) { fd = unix_socket_incoming(sockpath); @@ -581,11 +594,18 @@ int main(int argc, char **argv) err(EXIT_FAILURE, "Could not chdir to root directory"); } + state = RUNNING; do { main_loop_wait(false); - } while (!sigterm_reported && (persistent || !nbd_started || nb_fds > 0)); + if (state == TERMINATE) { + state = TERMINATING; + nbd_export_close(exp); + nbd_export_put(exp); + exp = NULL; + } + } while (state != TERMINATED); - nbd_export_close(exp); + bdrv_close(bs); if (sockpath) { unlink(sockpath); } diff --git a/qemu-os-posix.h b/qemu-os-posix.h index 8e1149d964..7f198e475c 100644 --- a/qemu-os-posix.h +++ b/qemu-os-posix.h @@ -46,4 +46,6 @@ typedef struct timeval qemu_timeval; typedef struct timespec qemu_timespec; int qemu_utimens(const char *path, const qemu_timespec *times); +bool is_daemonized(void); + #endif diff --git a/qemu-os-win32.h b/qemu-os-win32.h index 3b5a35b6c2..8ba466dbfb 100644 --- a/qemu-os-win32.h +++ b/qemu-os-win32.h @@ -92,4 +92,9 @@ typedef struct { } qemu_timeval; int qemu_gettimeofday(qemu_timeval *tp); +static inline bool is_daemonized(void) +{ + return false; +} + #endif diff --git a/qemu-sockets.c b/qemu-sockets.c index 361d890da3..037775b86b 100644 --- a/qemu-sockets.c +++ b/qemu-sockets.c @@ -353,7 +353,7 @@ int inet_dgram_opts(QemuOpts *opts) if (0 != (rc = getaddrinfo(addr, port, &ai, &local))) { fprintf(stderr,"getaddrinfo(%s,%s): %s\n", addr, port, gai_strerror(rc)); - return -1; + goto err; } /* create socket */ diff --git a/qemu-timer.c b/qemu-timer.c index c7a1551a36..908a1030b6 100644 --- a/qemu-timer.c +++ b/qemu-timer.c @@ -372,21 +372,20 @@ bool qemu_timer_expired(QEMUTimer *timer_head, int64_t current_time) void qemu_run_timers(QEMUClock *clock) { - QEMUTimer **ptimer_head, *ts; + QEMUTimer *ts; int64_t current_time; if (!clock->enabled) return; current_time = qemu_get_clock_ns(clock); - ptimer_head = &clock->active_timers; for(;;) { - ts = *ptimer_head; + ts = clock->active_timers; if (!qemu_timer_expired_ns(ts, current_time)) { break; } /* remove timer from the list before calling the callback */ - *ptimer_head = ts->next; + clock->active_timers = ts->next; ts->next = NULL; /* run the callback (the timer list can be modified) */ diff --git a/scripts/tracetool/backend/dtrace.py b/scripts/tracetool/backend/dtrace.py index 9cab75cde8..6be7047018 100644 --- a/scripts/tracetool/backend/dtrace.py +++ b/scripts/tracetool/backend/dtrace.py @@ -87,7 +87,7 @@ def stap(events): if len(e.args) > 0: for name in e.args.names(): # Append underscore to reserved keywords - if name in ('limit', 'in', 'next', 'self'): + if name in ('limit', 'in', 'next', 'self', 'function'): name += '_' out(' %s = $arg%d;' % (name, i)) i += 1 diff --git a/sysconfigs/target/cpus-x86_64.conf b/sysconfigs/target/cpus-x86_64.conf deleted file mode 100644 index cee0ea9e55..0000000000 --- a/sysconfigs/target/cpus-x86_64.conf +++ /dev/null @@ -1,128 +0,0 @@ -# x86 CPU MODELS - -[cpudef] - name = "Conroe" - level = "2" - vendor = "GenuineIntel" - family = "6" - model = "2" - stepping = "3" - feature_edx = "sse2 sse fxsr mmx clflush pse36 pat cmov mca pge mtrr sep apic cx8 mce pae msr tsc pse de fpu" - feature_ecx = "ssse3 sse3" - extfeature_edx = "i64 xd syscall" - extfeature_ecx = "lahf_lm" - xlevel = "0x8000000A" - model_id = "Intel Celeron_4x0 (Conroe/Merom Class Core 2)" - -[cpudef] - name = "Penryn" - level = "2" - vendor = "GenuineIntel" - family = "6" - model = "2" - stepping = "3" - feature_edx = "sse2 sse fxsr mmx clflush pse36 pat cmov mca pge mtrr sep apic cx8 mce pae msr tsc pse de fpu" - feature_ecx = "sse4.1 cx16 ssse3 sse3" - extfeature_edx = "i64 xd syscall" - extfeature_ecx = "lahf_lm" - xlevel = "0x8000000A" - model_id = "Intel Core 2 Duo P9xxx (Penryn Class Core 2)" - -[cpudef] - name = "Nehalem" - level = "2" - vendor = "GenuineIntel" - family = "6" - model = "2" - stepping = "3" - feature_edx = "sse2 sse fxsr mmx clflush pse36 pat cmov mca pge mtrr sep apic cx8 mce pae msr tsc pse de fpu" - feature_ecx = "popcnt sse4.2 sse4.1 cx16 ssse3 sse3" - extfeature_edx = "i64 syscall xd" - extfeature_ecx = "lahf_lm" - xlevel = "0x8000000A" - model_id = "Intel Core i7 9xx (Nehalem Class Core i7)" - -[cpudef] - name = "Westmere" - level = "11" - vendor = "GenuineIntel" - family = "6" - model = "44" - stepping = "1" - feature_edx = "sse2 sse fxsr mmx clflush pse36 pat cmov mca pge mtrr sep apic cx8 mce pae msr tsc pse de fpu" - feature_ecx = "aes popcnt sse4.2 sse4.1 cx16 ssse3 sse3" - extfeature_edx = "i64 syscall xd" - extfeature_ecx = "lahf_lm" - xlevel = "0x8000000A" - model_id = "Westmere E56xx/L56xx/X56xx (Nehalem-C)" - -[cpudef] - name = "SandyBridge" - level = "0xd" - vendor = "GenuineIntel" - family = "6" - model = "42" - stepping = "1" - feature_edx = " sse2 sse fxsr mmx clflush pse36 pat cmov mca pge mtrr sep apic cx8 mce pae msr tsc pse de fpu" - feature_ecx = "avx xsave aes tsc-deadline popcnt x2apic sse4.2 sse4.1 cx16 ssse3 pclmulqdq sse3" - extfeature_edx = "i64 rdtscp nx syscall " - extfeature_ecx = "lahf_lm" - xlevel = "0x8000000A" - model_id = "Intel Xeon E312xx (Sandy Bridge)" - -[cpudef] - name = "Opteron_G1" - level = "5" - vendor = "AuthenticAMD" - family = "15" - model = "6" - stepping = "1" - feature_edx = "sse2 sse fxsr mmx clflush pse36 pat cmov mca pge mtrr sep apic cx8 mce pae msr tsc pse de fpu" - feature_ecx = "sse3" - extfeature_edx = "lm fxsr mmx nx pse36 pat cmov mca pge mtrr syscall apic cx8 mce pae msr tsc pse de fpu" - extfeature_ecx = " " - xlevel = "0x80000008" - model_id = "AMD Opteron 240 (Gen 1 Class Opteron)" - -[cpudef] - name = "Opteron_G2" - level = "5" - vendor = "AuthenticAMD" - family = "15" - model = "6" - stepping = "1" - feature_edx = "sse2 sse fxsr mmx clflush pse36 pat cmov mca pge mtrr sep apic cx8 mce pae msr tsc pse de fpu" - feature_ecx = "cx16 sse3" - extfeature_edx = "lm rdtscp fxsr mmx nx pse36 pat cmov mca pge mtrr syscall apic cx8 mce pae msr tsc pse de fpu" - extfeature_ecx = "svm lahf_lm" - xlevel = "0x80000008" - model_id = "AMD Opteron 22xx (Gen 2 Class Opteron)" - -[cpudef] - name = "Opteron_G3" - level = "5" - vendor = "AuthenticAMD" - family = "15" - model = "6" - stepping = "1" - feature_edx = "sse2 sse fxsr mmx clflush pse36 pat cmov mca pge mtrr sep apic cx8 mce pae msr tsc pse de fpu" - feature_ecx = "popcnt cx16 monitor sse3" - extfeature_edx = "lm rdtscp fxsr mmx nx pse36 pat cmov mca pge mtrr syscall apic cx8 mce pae msr tsc pse de fpu" - extfeature_ecx = "misalignsse sse4a abm svm lahf_lm" - xlevel = "0x80000008" - model_id = "AMD Opteron 23xx (Gen 3 Class Opteron)" - -[cpudef] - name = "Opteron_G4" - level = "0xd" - vendor = "AuthenticAMD" - family = "21" - model = "1" - stepping = "2" - feature_edx = "sse2 sse fxsr mmx clflush pse36 pat cmov mca pge mtrr sep apic cx8 mce pae msr tsc pse de fpu" - feature_ecx = "avx xsave aes popcnt sse4.2 sse4.1 cx16 ssse3 pclmulqdq sse3" - extfeature_edx = "lm rdtscp pdpe1gb fxsr mmx nx pse36 pat cmov mca pge mtrr syscall apic cx8 mce pae msr tsc pse de fpu" - extfeature_ecx = " fma4 xop 3dnowprefetch misalignsse sse4a abm svm lahf_lm" - xlevel = "0x8000001A" - model_id = "AMD Opteron 62xx class CPU" - diff --git a/target-alpha/translate.c b/target-alpha/translate.c index 4a9011a2b6..3f9aee12d4 100644 --- a/target-alpha/translate.c +++ b/target-alpha/translate.c @@ -3543,6 +3543,7 @@ CPUAlphaState * cpu_alpha_init (const char *cpu_model) } env->implver = implver; env->amask = amask; + env->cpu_model_str = cpu_model; qemu_init_vcpu(env); return env; diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 423e00905d..fd4fe2898b 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -240,7 +240,6 @@ typedef struct x86_def_t { uint32_t xlevel; char model_id[48]; int vendor_override; - uint32_t flags; /* Store the results of Centaur's CPUID instructions */ uint32_t ext4_features; uint32_t xlevel2; @@ -490,6 +489,225 @@ static x86_def_t builtin_x86_defs[] = { .xlevel = 0x8000000A, .model_id = "Intel(R) Atom(TM) CPU N270 @ 1.60GHz", }, + { + .name = "Conroe", + .level = 2, + .vendor1 = CPUID_VENDOR_INTEL_1, + .vendor2 = CPUID_VENDOR_INTEL_2, + .vendor3 = CPUID_VENDOR_INTEL_3, + .family = 6, + .model = 2, + .stepping = 3, + .features = CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | + CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA | + CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 | + CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE | + CPUID_DE | CPUID_FP87, + .ext_features = CPUID_EXT_SSSE3 | CPUID_EXT_SSE3, + .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_NX | CPUID_EXT2_SYSCALL, + .ext3_features = CPUID_EXT3_LAHF_LM, + .xlevel = 0x8000000A, + .model_id = "Intel Celeron_4x0 (Conroe/Merom Class Core 2)", + }, + { + .name = "Penryn", + .level = 2, + .vendor1 = CPUID_VENDOR_INTEL_1, + .vendor2 = CPUID_VENDOR_INTEL_2, + .vendor3 = CPUID_VENDOR_INTEL_3, + .family = 6, + .model = 2, + .stepping = 3, + .features = CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | + CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA | + CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 | + CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE | + CPUID_DE | CPUID_FP87, + .ext_features = CPUID_EXT_SSE41 | CPUID_EXT_CX16 | CPUID_EXT_SSSE3 | + CPUID_EXT_SSE3, + .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_NX | CPUID_EXT2_SYSCALL, + .ext3_features = CPUID_EXT3_LAHF_LM, + .xlevel = 0x8000000A, + .model_id = "Intel Core 2 Duo P9xxx (Penryn Class Core 2)", + }, + { + .name = "Nehalem", + .level = 2, + .vendor1 = CPUID_VENDOR_INTEL_1, + .vendor2 = CPUID_VENDOR_INTEL_2, + .vendor3 = CPUID_VENDOR_INTEL_3, + .family = 6, + .model = 2, + .stepping = 3, + .features = CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | + CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA | + CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 | + CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE | + CPUID_DE | CPUID_FP87, + .ext_features = CPUID_EXT_POPCNT | CPUID_EXT_SSE42 | CPUID_EXT_SSE41 | + CPUID_EXT_CX16 | CPUID_EXT_SSSE3 | CPUID_EXT_SSE3, + .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX, + .ext3_features = CPUID_EXT3_LAHF_LM, + .xlevel = 0x8000000A, + .model_id = "Intel Core i7 9xx (Nehalem Class Core i7)", + }, + { + .name = "Westmere", + .level = 11, + .vendor1 = CPUID_VENDOR_INTEL_1, + .vendor2 = CPUID_VENDOR_INTEL_2, + .vendor3 = CPUID_VENDOR_INTEL_3, + .family = 6, + .model = 44, + .stepping = 1, + .features = CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | + CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA | + CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 | + CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE | + CPUID_DE | CPUID_FP87, + .ext_features = CPUID_EXT_AES | CPUID_EXT_POPCNT | CPUID_EXT_SSE42 | + CPUID_EXT_SSE41 | CPUID_EXT_CX16 | CPUID_EXT_SSSE3 | + CPUID_EXT_SSE3, + .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX, + .ext3_features = CPUID_EXT3_LAHF_LM, + .xlevel = 0x8000000A, + .model_id = "Westmere E56xx/L56xx/X56xx (Nehalem-C)", + }, + { + .name = "SandyBridge", + .level = 0xd, + .vendor1 = CPUID_VENDOR_INTEL_1, + .vendor2 = CPUID_VENDOR_INTEL_2, + .vendor3 = CPUID_VENDOR_INTEL_3, + .family = 6, + .model = 42, + .stepping = 1, + .features = CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | + CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA | + CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 | + CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE | + CPUID_DE | CPUID_FP87, + .ext_features = CPUID_EXT_AVX | CPUID_EXT_XSAVE | CPUID_EXT_AES | + CPUID_EXT_TSC_DEADLINE_TIMER | CPUID_EXT_POPCNT | + CPUID_EXT_X2APIC | CPUID_EXT_SSE42 | CPUID_EXT_SSE41 | + CPUID_EXT_CX16 | CPUID_EXT_SSSE3 | CPUID_EXT_PCLMULQDQ | + CPUID_EXT_SSE3, + .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX | + CPUID_EXT2_SYSCALL, + .ext3_features = CPUID_EXT3_LAHF_LM, + .xlevel = 0x8000000A, + .model_id = "Intel Xeon E312xx (Sandy Bridge)", + }, + { + .name = "Opteron_G1", + .level = 5, + .vendor1 = CPUID_VENDOR_AMD_1, + .vendor2 = CPUID_VENDOR_AMD_2, + .vendor3 = CPUID_VENDOR_AMD_3, + .family = 15, + .model = 6, + .stepping = 1, + .features = CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | + CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA | + CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 | + CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE | + CPUID_DE | CPUID_FP87, + .ext_features = CPUID_EXT_SSE3, + .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_FXSR | CPUID_EXT2_MMX | + CPUID_EXT2_NX | CPUID_EXT2_PSE36 | CPUID_EXT2_PAT | + CPUID_EXT2_CMOV | CPUID_EXT2_MCA | CPUID_EXT2_PGE | + CPUID_EXT2_MTRR | CPUID_EXT2_SYSCALL | CPUID_EXT2_APIC | + CPUID_EXT2_CX8 | CPUID_EXT2_MCE | CPUID_EXT2_PAE | CPUID_EXT2_MSR | + CPUID_EXT2_TSC | CPUID_EXT2_PSE | CPUID_EXT2_DE | CPUID_EXT2_FPU, + .xlevel = 0x80000008, + .model_id = "AMD Opteron 240 (Gen 1 Class Opteron)", + }, + { + .name = "Opteron_G2", + .level = 5, + .vendor1 = CPUID_VENDOR_AMD_1, + .vendor2 = CPUID_VENDOR_AMD_2, + .vendor3 = CPUID_VENDOR_AMD_3, + .family = 15, + .model = 6, + .stepping = 1, + .features = CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | + CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA | + CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 | + CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE | + CPUID_DE | CPUID_FP87, + .ext_features = CPUID_EXT_CX16 | CPUID_EXT_SSE3, + .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_FXSR | + CPUID_EXT2_MMX | CPUID_EXT2_NX | CPUID_EXT2_PSE36 | + CPUID_EXT2_PAT | CPUID_EXT2_CMOV | CPUID_EXT2_MCA | + CPUID_EXT2_PGE | CPUID_EXT2_MTRR | CPUID_EXT2_SYSCALL | + CPUID_EXT2_APIC | CPUID_EXT2_CX8 | CPUID_EXT2_MCE | + CPUID_EXT2_PAE | CPUID_EXT2_MSR | CPUID_EXT2_TSC | CPUID_EXT2_PSE | + CPUID_EXT2_DE | CPUID_EXT2_FPU, + .ext3_features = CPUID_EXT3_SVM | CPUID_EXT3_LAHF_LM, + .xlevel = 0x80000008, + .model_id = "AMD Opteron 22xx (Gen 2 Class Opteron)", + }, + { + .name = "Opteron_G3", + .level = 5, + .vendor1 = CPUID_VENDOR_AMD_1, + .vendor2 = CPUID_VENDOR_AMD_2, + .vendor3 = CPUID_VENDOR_AMD_3, + .family = 15, + .model = 6, + .stepping = 1, + .features = CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | + CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA | + CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 | + CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE | + CPUID_DE | CPUID_FP87, + .ext_features = CPUID_EXT_POPCNT | CPUID_EXT_CX16 | CPUID_EXT_MONITOR | + CPUID_EXT_SSE3, + .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_FXSR | + CPUID_EXT2_MMX | CPUID_EXT2_NX | CPUID_EXT2_PSE36 | + CPUID_EXT2_PAT | CPUID_EXT2_CMOV | CPUID_EXT2_MCA | + CPUID_EXT2_PGE | CPUID_EXT2_MTRR | CPUID_EXT2_SYSCALL | + CPUID_EXT2_APIC | CPUID_EXT2_CX8 | CPUID_EXT2_MCE | + CPUID_EXT2_PAE | CPUID_EXT2_MSR | CPUID_EXT2_TSC | CPUID_EXT2_PSE | + CPUID_EXT2_DE | CPUID_EXT2_FPU, + .ext3_features = CPUID_EXT3_MISALIGNSSE | CPUID_EXT3_SSE4A | + CPUID_EXT3_ABM | CPUID_EXT3_SVM | CPUID_EXT3_LAHF_LM, + .xlevel = 0x80000008, + .model_id = "AMD Opteron 23xx (Gen 3 Class Opteron)", + }, + { + .name = "Opteron_G4", + .level = 0xd, + .vendor1 = CPUID_VENDOR_AMD_1, + .vendor2 = CPUID_VENDOR_AMD_2, + .vendor3 = CPUID_VENDOR_AMD_3, + .family = 21, + .model = 1, + .stepping = 2, + .features = CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | + CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA | + CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 | + CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE | + CPUID_DE | CPUID_FP87, + .ext_features = CPUID_EXT_AVX | CPUID_EXT_XSAVE | CPUID_EXT_AES | + CPUID_EXT_POPCNT | CPUID_EXT_SSE42 | CPUID_EXT_SSE41 | + CPUID_EXT_CX16 | CPUID_EXT_SSSE3 | CPUID_EXT_PCLMULQDQ | + CPUID_EXT_SSE3, + .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | + CPUID_EXT2_PDPE1GB | CPUID_EXT2_FXSR | CPUID_EXT2_MMX | + CPUID_EXT2_NX | CPUID_EXT2_PSE36 | CPUID_EXT2_PAT | + CPUID_EXT2_CMOV | CPUID_EXT2_MCA | CPUID_EXT2_PGE | + CPUID_EXT2_MTRR | CPUID_EXT2_SYSCALL | CPUID_EXT2_APIC | + CPUID_EXT2_CX8 | CPUID_EXT2_MCE | CPUID_EXT2_PAE | CPUID_EXT2_MSR | + CPUID_EXT2_TSC | CPUID_EXT2_PSE | CPUID_EXT2_DE | CPUID_EXT2_FPU, + .ext3_features = CPUID_EXT3_FMA4 | CPUID_EXT3_XOP | + CPUID_EXT3_3DNOWPREFETCH | CPUID_EXT3_MISALIGNSSE | + CPUID_EXT3_SSE4A | CPUID_EXT3_ABM | CPUID_EXT3_SVM | + CPUID_EXT3_LAHF_LM, + .xlevel = 0x8000001A, + .model_id = "AMD Opteron 62xx class CPU", + }, }; static int cpu_x86_fill_model_id(char *str) @@ -846,7 +1064,7 @@ static void x86_cpuid_set_tsc_freq(Object *obj, Visitor *v, void *opaque, { X86CPU *cpu = X86_CPU(obj); const int64_t min = 0; - const int64_t max = INT_MAX; + const int64_t max = INT64_MAX; int64_t value; visit_type_int(v, &value, name, errp); @@ -1073,70 +1291,28 @@ static void listflags(char *buf, int bufsize, uint32_t fbits, } } -/* generate CPU information: - * -? list model names - * -?model list model names/IDs - * -?dump output all model (x86_def_t) data - * -?cpuid list all recognized cpuid flag names - */ -void x86_cpu_list(FILE *f, fprintf_function cpu_fprintf, const char *optarg) +/* generate CPU information. */ +void x86_cpu_list(FILE *f, fprintf_function cpu_fprintf) { - unsigned char model = !strcmp("?model", optarg); - unsigned char dump = !strcmp("?dump", optarg); - unsigned char cpuid = !strcmp("?cpuid", optarg); x86_def_t *def; char buf[256]; - if (cpuid) { - (*cpu_fprintf)(f, "Recognized CPUID flags:\n"); - listflags(buf, sizeof (buf), (uint32_t)~0, feature_name, 1); - (*cpu_fprintf)(f, " f_edx: %s\n", buf); - listflags(buf, sizeof (buf), (uint32_t)~0, ext_feature_name, 1); - (*cpu_fprintf)(f, " f_ecx: %s\n", buf); - listflags(buf, sizeof (buf), (uint32_t)~0, ext2_feature_name, 1); - (*cpu_fprintf)(f, " extf_edx: %s\n", buf); - listflags(buf, sizeof (buf), (uint32_t)~0, ext3_feature_name, 1); - (*cpu_fprintf)(f, " extf_ecx: %s\n", buf); - return; - } for (def = x86_defs; def; def = def->next) { - snprintf(buf, sizeof (buf), def->flags ? "[%s]": "%s", def->name); - if (model || dump) { - (*cpu_fprintf)(f, "x86 %16s %-48s\n", buf, def->model_id); - } else { - (*cpu_fprintf)(f, "x86 %16s\n", buf); - } - if (dump) { - memcpy(buf, &def->vendor1, sizeof (def->vendor1)); - memcpy(buf + 4, &def->vendor2, sizeof (def->vendor2)); - memcpy(buf + 8, &def->vendor3, sizeof (def->vendor3)); - buf[12] = '\0'; - (*cpu_fprintf)(f, - " family %d model %d stepping %d level %d xlevel 0x%x" - " vendor \"%s\"\n", - def->family, def->model, def->stepping, def->level, - def->xlevel, buf); - listflags(buf, sizeof (buf), def->features, feature_name, 0); - (*cpu_fprintf)(f, " feature_edx %08x (%s)\n", def->features, - buf); - listflags(buf, sizeof (buf), def->ext_features, ext_feature_name, - 0); - (*cpu_fprintf)(f, " feature_ecx %08x (%s)\n", def->ext_features, - buf); - listflags(buf, sizeof (buf), def->ext2_features, ext2_feature_name, - 0); - (*cpu_fprintf)(f, " extfeature_edx %08x (%s)\n", - def->ext2_features, buf); - listflags(buf, sizeof (buf), def->ext3_features, ext3_feature_name, - 0); - (*cpu_fprintf)(f, " extfeature_ecx %08x (%s)\n", - def->ext3_features, buf); - (*cpu_fprintf)(f, "\n"); - } + snprintf(buf, sizeof(buf), "%s", def->name); + (*cpu_fprintf)(f, "x86 %16s %-48s\n", buf, def->model_id); } if (kvm_enabled()) { (*cpu_fprintf)(f, "x86 %16s\n", "[host]"); } + (*cpu_fprintf)(f, "\nRecognized CPUID flags:\n"); + listflags(buf, sizeof(buf), (uint32_t)~0, feature_name, 1); + (*cpu_fprintf)(f, " f_edx: %s\n", buf); + listflags(buf, sizeof(buf), (uint32_t)~0, ext_feature_name, 1); + (*cpu_fprintf)(f, " f_ecx: %s\n", buf); + listflags(buf, sizeof(buf), (uint32_t)~0, ext2_feature_name, 1); + (*cpu_fprintf)(f, " extf_edx: %s\n", buf); + listflags(buf, sizeof(buf), (uint32_t)~0, ext3_feature_name, 1); + (*cpu_fprintf)(f, " extf_ecx: %s\n", buf); } CpuDefinitionInfoList *arch_query_cpu_definitions(Error **errp) @@ -1216,109 +1392,6 @@ int cpu_x86_register(X86CPU *cpu, const char *cpu_model) } #if !defined(CONFIG_USER_ONLY) -/* copy vendor id string to 32 bit register, nul pad as needed - */ -static void cpyid(const char *s, uint32_t *id) -{ - char *d = (char *)id; - char i; - - for (i = sizeof (*id); i--; ) - *d++ = *s ? *s++ : '\0'; -} - -/* interpret radix and convert from string to arbitrary scalar, - * otherwise flag failure - */ -#define setscalar(pval, str, perr) \ -{ \ - char *pend; \ - unsigned long ul; \ - \ - ul = strtoul(str, &pend, 0); \ - *str && !*pend ? (*pval = ul) : (*perr = 1); \ -} - -/* map cpuid options to feature bits, otherwise return failure - * (option tags in *str are delimited by whitespace) - */ -static void setfeatures(uint32_t *pval, const char *str, - const char **featureset, int *perr) -{ - const char *p, *q; - - for (q = p = str; *p || *q; q = p) { - while (iswhite(*p)) - q = ++p; - while (*p && !iswhite(*p)) - ++p; - if (!*q && !*p) - return; - if (!lookup_feature(pval, q, p, featureset)) { - fprintf(stderr, "error: feature \"%.*s\" not available in set\n", - (int)(p - q), q); - *perr = 1; - return; - } - } -} - -/* map config file options to x86_def_t form - */ -static int cpudef_setfield(const char *name, const char *str, void *opaque) -{ - x86_def_t *def = opaque; - int err = 0; - - if (!strcmp(name, "name")) { - g_free((void *)def->name); - def->name = g_strdup(str); - } else if (!strcmp(name, "model_id")) { - strncpy(def->model_id, str, sizeof (def->model_id)); - } else if (!strcmp(name, "level")) { - setscalar(&def->level, str, &err) - } else if (!strcmp(name, "vendor")) { - cpyid(&str[0], &def->vendor1); - cpyid(&str[4], &def->vendor2); - cpyid(&str[8], &def->vendor3); - } else if (!strcmp(name, "family")) { - setscalar(&def->family, str, &err) - } else if (!strcmp(name, "model")) { - setscalar(&def->model, str, &err) - } else if (!strcmp(name, "stepping")) { - setscalar(&def->stepping, str, &err) - } else if (!strcmp(name, "feature_edx")) { - setfeatures(&def->features, str, feature_name, &err); - } else if (!strcmp(name, "feature_ecx")) { - setfeatures(&def->ext_features, str, ext_feature_name, &err); - } else if (!strcmp(name, "extfeature_edx")) { - setfeatures(&def->ext2_features, str, ext2_feature_name, &err); - } else if (!strcmp(name, "extfeature_ecx")) { - setfeatures(&def->ext3_features, str, ext3_feature_name, &err); - } else if (!strcmp(name, "xlevel")) { - setscalar(&def->xlevel, str, &err) - } else { - fprintf(stderr, "error: unknown option [%s = %s]\n", name, str); - return (1); - } - if (err) { - fprintf(stderr, "error: bad option value [%s = %s]\n", name, str); - return (1); - } - return (0); -} - -/* register config file entry as x86_def_t - */ -static int cpudef_register(QemuOpts *opts, void *opaque) -{ - x86_def_t *def = g_malloc0(sizeof (x86_def_t)); - - qemu_opt_foreach(opts, cpudef_setfield, def, 1); - def->next = x86_defs; - x86_defs = def; - return (0); -} void cpu_clear_apic_feature(CPUX86State *env) { @@ -1327,8 +1400,7 @@ void cpu_clear_apic_feature(CPUX86State *env) #endif /* !CONFIG_USER_ONLY */ -/* register "cpudef" models defined in configuration file. Here we first - * preload any built-in definitions +/* Initialize list of CPU models, filling some non-static fields if necessary */ void x86_cpudef_setup(void) { @@ -1336,24 +1408,23 @@ void x86_cpudef_setup(void) static const char *model_with_versions[] = { "qemu32", "qemu64", "athlon" }; for (i = 0; i < ARRAY_SIZE(builtin_x86_defs); ++i) { - builtin_x86_defs[i].next = x86_defs; - builtin_x86_defs[i].flags = 1; + x86_def_t *def = &builtin_x86_defs[i]; + def->next = x86_defs; /* Look for specific "cpudef" models that */ /* have the QEMU version in .model_id */ for (j = 0; j < ARRAY_SIZE(model_with_versions); j++) { - if (strcmp(model_with_versions[j], builtin_x86_defs[i].name) == 0) { - pstrcpy(builtin_x86_defs[i].model_id, sizeof(builtin_x86_defs[i].model_id), "QEMU Virtual CPU version "); - pstrcat(builtin_x86_defs[i].model_id, sizeof(builtin_x86_defs[i].model_id), qemu_get_version()); + if (strcmp(model_with_versions[j], def->name) == 0) { + pstrcpy(def->model_id, sizeof(def->model_id), + "QEMU Virtual CPU version "); + pstrcat(def->model_id, sizeof(def->model_id), + qemu_get_version()); break; } } - x86_defs = &builtin_x86_defs[i]; + x86_defs = def; } -#if !defined(CONFIG_USER_ONLY) - qemu_opts_foreach(qemu_find_opts("cpudef"), cpudef_register, NULL, 0); -#endif } static void get_cpuid_vendor(CPUX86State *env, uint32_t *ebx, diff --git a/target-i386/cpu.h b/target-i386/cpu.h index 0677502dcc..d7ea2f92a8 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -382,6 +382,7 @@ #define CPUID_PBE (1 << 31) #define CPUID_EXT_SSE3 (1 << 0) +#define CPUID_EXT_PCLMULQDQ (1 << 1) #define CPUID_EXT_DTES64 (1 << 2) #define CPUID_EXT_MONITOR (1 << 3) #define CPUID_EXT_DSCPL (1 << 4) @@ -401,14 +402,33 @@ #define CPUID_EXT_MOVBE (1 << 22) #define CPUID_EXT_POPCNT (1 << 23) #define CPUID_EXT_TSC_DEADLINE_TIMER (1 << 24) +#define CPUID_EXT_AES (1 << 25) #define CPUID_EXT_XSAVE (1 << 26) #define CPUID_EXT_OSXSAVE (1 << 27) +#define CPUID_EXT_AVX (1 << 28) #define CPUID_EXT_HYPERVISOR (1 << 31) +#define CPUID_EXT2_FPU (1 << 0) +#define CPUID_EXT2_DE (1 << 2) +#define CPUID_EXT2_PSE (1 << 3) +#define CPUID_EXT2_TSC (1 << 4) +#define CPUID_EXT2_MSR (1 << 5) +#define CPUID_EXT2_PAE (1 << 6) +#define CPUID_EXT2_MCE (1 << 7) +#define CPUID_EXT2_CX8 (1 << 8) +#define CPUID_EXT2_APIC (1 << 9) #define CPUID_EXT2_SYSCALL (1 << 11) +#define CPUID_EXT2_MTRR (1 << 12) +#define CPUID_EXT2_PGE (1 << 13) +#define CPUID_EXT2_MCA (1 << 14) +#define CPUID_EXT2_CMOV (1 << 15) +#define CPUID_EXT2_PAT (1 << 16) +#define CPUID_EXT2_PSE36 (1 << 17) #define CPUID_EXT2_MP (1 << 19) #define CPUID_EXT2_NX (1 << 20) #define CPUID_EXT2_MMXEXT (1 << 22) +#define CPUID_EXT2_MMX (1 << 23) +#define CPUID_EXT2_FXSR (1 << 24) #define CPUID_EXT2_FFXSR (1 << 25) #define CPUID_EXT2_PDPE1GB (1 << 26) #define CPUID_EXT2_RDTSCP (1 << 27) @@ -427,7 +447,9 @@ #define CPUID_EXT3_3DNOWPREFETCH (1 << 8) #define CPUID_EXT3_OSVW (1 << 9) #define CPUID_EXT3_IBS (1 << 10) +#define CPUID_EXT3_XOP (1 << 11) #define CPUID_EXT3_SKINIT (1 << 12) +#define CPUID_EXT3_FMA4 (1 << 16) #define CPUID_SVM_NPT (1 << 0) #define CPUID_SVM_LBRV (1 << 1) @@ -792,7 +814,7 @@ typedef struct CPUX86State { X86CPU *cpu_x86_init(const char *cpu_model); int cpu_x86_exec(CPUX86State *s); -void x86_cpu_list (FILE *f, fprintf_function cpu_fprintf, const char *optarg); +void x86_cpu_list(FILE *f, fprintf_function cpu_fprintf); void x86_cpudef_setup(void); int cpu_x86_support_mca_broadcast(CPUX86State *env); @@ -976,7 +998,7 @@ static inline CPUX86State *cpu_init(const char *cpu_model) #define cpu_exec cpu_x86_exec #define cpu_gen_code cpu_x86_gen_code #define cpu_signal_handler cpu_x86_signal_handler -#define cpu_list_id x86_cpu_list +#define cpu_list x86_cpu_list #define cpudef_setup x86_cpudef_setup #define CPU_SAVE_VERSION 12 @@ -3657,7 +3657,9 @@ int main(int argc, char **argv, char **envp) break; #if defined(CONFIG_CURSES) case DT_CURSES: - curses_display_init(ds, full_screen); + if (!is_daemonized()) { + curses_display_init(ds, full_screen); + } break; #endif #if defined(CONFIG_SDL) |