* Support multiple -d trace:PATTERN arguments (Daniel)

* SCSI cleanups/fixes for removable meia (Fam)
 * SCSI security fixes (Li Qiang, PJP)
 * qemu-char segfault fix (Lin Ma)
 * "make help" and qemu-socket cleanups (Marc-André)
 * end of the buffer_is_zero reword (Richard)
 * Fix target-i386 syscall segfault (Stanislav)
 * split irqchip fix/robustification (Wanpeng)
 * misc cleanups (me, Jiangang)
 * x86 vmstate fixes (Pavel)
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2
 
 iQExBAABCAAbBQJX2p4HFBxwYm9uemluaUByZWRoYXQuY29tAAoJEL/70l94x66D
 aPcIAJlBiq+SSLSTE3iWntjMQcOPWiclhSj+66BDYL4ck5zsj7vKJ1GaR0WHFZEW
 8PPe84uvX1ljTEYu1bs0uA+id8rUWhoJWnxRAYfECs7ymaViHk1n6RSEl7QJhC9X
 0Tahf/8W9q0ocqVurLGs6UzNn0HTr8O922y6IcM0/wlnixNaarGCT/skOJ91ZzwM
 OVtv1AltkdOQSF21dskltgj2gupkFOg1OqhO/EHOQHIbEDhyVxPFC5aAMPaxgWR/
 eyUxk5aXTXf1ZXRhsr23zZUOmAxHL6VKF17agNwNi+UNSk4DERU1+KOUbFowv+WV
 QO7tLKTTLrPcigrkRAZJ+xaUUoY=
 =HIc4
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/bonzini/tags/for-upstream' into staging

* Support multiple -d trace:PATTERN arguments (Daniel)
* SCSI cleanups/fixes for removable meia (Fam)
* SCSI security fixes (Li Qiang, PJP)
* qemu-char segfault fix (Lin Ma)
* "make help" and qemu-socket cleanups (Marc-André)
* end of the buffer_is_zero reword (Richard)
* Fix target-i386 syscall segfault (Stanislav)
* split irqchip fix/robustification (Wanpeng)
* misc cleanups (me, Jiangang)
* x86 vmstate fixes (Pavel)

# gpg: Signature made Thu 15 Sep 2016 14:11:35 BST
# 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:
  pcspk: adding vmstate for save/restore
  kvmvapic: fix state change handler
  pc: apic: introduce APIC macro
  target-i386: Fixed syscall posssible segfault
  log: fix parsing of multiple trace:PATTERN log args
  qemu-char: avoid segfault if user lacks of permisson of a given logfile
  build-sys: add make 'help' target
  linux-user: complete omission of removing uses of strdup
  target-i386: fix ordering of fields in CPUX86State
  pc: apic: fix touch LAPIC when irqchip is split
  scsi: pvscsi: limit process IO loop to ring size
  memory: remove memory_region_destructor_rom_device
  Change net/socket.c to use socket_*() functions
  cutils: Rewrite x86 buffer zero checking
  scsi: mptsas: use g_new0 to allocate MPTSASRequest object
  virtio-scsi: Don't abort when media is ejected
  scsi-disk: Cleaning up around tray open state

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2016-09-15 18:12:40 +01:00
commit 5f473241ac
18 changed files with 379 additions and 234 deletions

View File

@ -669,3 +669,40 @@ endif
-include $(wildcard *.d tests/*.d) -include $(wildcard *.d tests/*.d)
include $(SRC_PATH)/tests/docker/Makefile.include include $(SRC_PATH)/tests/docker/Makefile.include
.PHONY: help
help:
@echo 'Generic targets:'
@echo ' all - Build all'
@echo ' dir/file.o - Build specified target only'
@echo ' install - Install QEMU, documentation and tools'
@echo ' ctags/TAGS - Generate tags file for editors'
@echo ' cscope - Generate cscope index'
@echo ''
@$(if $(TARGET_DIRS), \
echo 'Architecture specific targets:'; \
$(foreach t, $(TARGET_DIRS), \
printf " %-30s - Build for %s\\n" $(patsubst %,subdir-%,$(t)) $(t);) \
echo '')
@echo 'Cleaning targets:'
@echo ' clean - Remove most generated files but keep the config'
@echo ' distclean - Remove all generated files'
@echo ' dist - Build a distributable tarball'
@echo ''
@echo 'Test targets:'
@echo ' check - Run all tests (check-help for details)'
@echo ' docker - Help about targets running tests inside Docker containers'
@echo ''
@echo 'Documentation targets:'
@echo ' dvi html info pdf'
@echo ' - Build documentation in specified format'
@echo ''
ifdef CONFIG_WIN32
@echo 'Windows targets:'
@echo ' installer - Build NSIS-based installer for qemu-ga'
ifdef QEMU_GA_MSI_ENABLED
@echo ' msi - Build MSI-based installer for qemu-ga'
endif
@echo ''
endif
@echo ' make V=0|1 [targets] 0 => quiet build (default), 1 => verbose build'

View File

@ -159,6 +159,9 @@ static CharDriverState *qemu_chr_open_msmouse(const char *id,
CharDriverState *chr; CharDriverState *chr;
chr = qemu_chr_alloc(common, errp); chr = qemu_chr_alloc(common, errp);
if (!chr) {
return NULL;
}
chr->chr_write = msmouse_chr_write; chr->chr_write = msmouse_chr_write;
chr->chr_close = msmouse_chr_close; chr->chr_close = msmouse_chr_close;
chr->chr_accept_input = msmouse_chr_accept_input; chr->chr_accept_input = msmouse_chr_accept_input;

View File

@ -52,8 +52,8 @@ typedef struct {
unsigned int pit_count; unsigned int pit_count;
unsigned int samples; unsigned int samples;
unsigned int play_pos; unsigned int play_pos;
int data_on; uint8_t data_on;
int dummy_refresh_clock; uint8_t dummy_refresh_clock;
} PCSpkState; } PCSpkState;
static const char *s_spk = "pcspk"; static const char *s_spk = "pcspk";
@ -187,6 +187,18 @@ static void pcspk_realizefn(DeviceState *dev, Error **errp)
pcspk_state = s; pcspk_state = s;
} }
static const VMStateDescription vmstate_spk = {
.name = "pcspk",
.version_id = 1,
.minimum_version_id = 1,
.minimum_version_id_old = 1,
.fields = (VMStateField[]) {
VMSTATE_UINT8(data_on, PCSpkState),
VMSTATE_UINT8(dummy_refresh_clock, PCSpkState),
VMSTATE_END_OF_LIST()
}
};
static Property pcspk_properties[] = { static Property pcspk_properties[] = {
DEFINE_PROP_UINT32("iobase", PCSpkState, iobase, -1), DEFINE_PROP_UINT32("iobase", PCSpkState, iobase, -1),
DEFINE_PROP_END_OF_LIST(), DEFINE_PROP_END_OF_LIST(),
@ -198,6 +210,7 @@ static void pcspk_class_initfn(ObjectClass *klass, void *data)
dc->realize = pcspk_realizefn; dc->realize = pcspk_realizefn;
set_bit(DEVICE_CATEGORY_SOUND, dc->categories); set_bit(DEVICE_CATEGORY_SOUND, dc->categories);
dc->vmsd = &vmstate_spk;
dc->props = pcspk_properties; dc->props = pcspk_properties;
/* Reason: realize sets global pcspk_state */ /* Reason: realize sets global pcspk_state */
dc->cannot_instantiate_with_device_add_yet = true; dc->cannot_instantiate_with_device_add_yet = true;

View File

@ -768,6 +768,7 @@ static void kvmvapic_vm_state_change(void *opaque, int running,
} }
qemu_del_vm_change_state_handler(s->vmsentry); qemu_del_vm_change_state_handler(s->vmsentry);
s->vmsentry = NULL;
} }
static int vapic_post_load(void *opaque, int version_id) static int vapic_post_load(void *opaque, int version_id)

View File

@ -161,6 +161,7 @@ int cpu_get_pic_interrupt(CPUX86State *env)
X86CPU *cpu = x86_env_get_cpu(env); X86CPU *cpu = x86_env_get_cpu(env);
int intno; int intno;
if (!kvm_irqchip_in_kernel()) {
intno = apic_get_interrupt(cpu->apic_state); intno = apic_get_interrupt(cpu->apic_state);
if (intno >= 0) { if (intno >= 0) {
return intno; return intno;
@ -169,6 +170,7 @@ int cpu_get_pic_interrupt(CPUX86State *env)
if (!apic_accept_pic_intr(cpu->apic_state)) { if (!apic_accept_pic_intr(cpu->apic_state)) {
return -1; return -1;
} }
}
intno = pic_read_irq(isa_pic); intno = pic_read_irq(isa_pic);
return intno; return intno;
@ -180,7 +182,7 @@ static void pic_irq_request(void *opaque, int irq, int level)
X86CPU *cpu = X86_CPU(cs); X86CPU *cpu = X86_CPU(cs);
DPRINTF("pic_irqs: %s irq %d\n", level? "raise" : "lower", irq); DPRINTF("pic_irqs: %s irq %d\n", level? "raise" : "lower", irq);
if (cpu->apic_state) { if (cpu->apic_state && !kvm_irqchip_in_kernel()) {
CPU_FOREACH(cs) { CPU_FOREACH(cs) {
cpu = X86_CPU(cs); cpu = X86_CPU(cs);
if (apic_accept_pic_intr(cpu->apic_state)) { if (apic_accept_pic_intr(cpu->apic_state)) {

View File

@ -39,6 +39,10 @@
static APICCommonState *local_apics[MAX_APICS + 1]; static APICCommonState *local_apics[MAX_APICS + 1];
#define TYPE_APIC "apic"
#define APIC(obj) \
OBJECT_CHECK(APICCommonState, (obj), TYPE_APIC)
static void apic_set_irq(APICCommonState *s, int vector_num, int trigger_mode); static void apic_set_irq(APICCommonState *s, int vector_num, int trigger_mode);
static void apic_update_irq(APICCommonState *s); static void apic_update_irq(APICCommonState *s);
static void apic_get_delivery_bitmask(uint32_t *deliver_bitmask, static void apic_get_delivery_bitmask(uint32_t *deliver_bitmask,
@ -163,7 +167,7 @@ static void apic_local_deliver(APICCommonState *s, int vector)
void apic_deliver_pic_intr(DeviceState *dev, int level) void apic_deliver_pic_intr(DeviceState *dev, int level)
{ {
APICCommonState *s = APIC_COMMON(dev); APICCommonState *s = APIC(dev);
if (level) { if (level) {
apic_local_deliver(s, APIC_LVT_LINT0); apic_local_deliver(s, APIC_LVT_LINT0);
@ -373,7 +377,7 @@ static void apic_update_irq(APICCommonState *s)
void apic_poll_irq(DeviceState *dev) void apic_poll_irq(DeviceState *dev)
{ {
APICCommonState *s = APIC_COMMON(dev); APICCommonState *s = APIC(dev);
apic_sync_vapic(s, SYNC_FROM_VAPIC); apic_sync_vapic(s, SYNC_FROM_VAPIC);
apic_update_irq(s); apic_update_irq(s);
@ -479,7 +483,7 @@ static void apic_startup(APICCommonState *s, int vector_num)
void apic_sipi(DeviceState *dev) void apic_sipi(DeviceState *dev)
{ {
APICCommonState *s = APIC_COMMON(dev); APICCommonState *s = APIC(dev);
cpu_reset_interrupt(CPU(s->cpu), CPU_INTERRUPT_SIPI); cpu_reset_interrupt(CPU(s->cpu), CPU_INTERRUPT_SIPI);
@ -493,7 +497,7 @@ static void apic_deliver(DeviceState *dev, uint8_t dest, uint8_t dest_mode,
uint8_t delivery_mode, uint8_t vector_num, uint8_t delivery_mode, uint8_t vector_num,
uint8_t trigger_mode) uint8_t trigger_mode)
{ {
APICCommonState *s = APIC_COMMON(dev); APICCommonState *s = APIC(dev);
uint32_t deliver_bitmask[MAX_APIC_WORDS]; uint32_t deliver_bitmask[MAX_APIC_WORDS];
int dest_shorthand = (s->icr[0] >> 18) & 3; int dest_shorthand = (s->icr[0] >> 18) & 3;
APICCommonState *apic_iter; APICCommonState *apic_iter;
@ -550,7 +554,7 @@ static bool apic_check_pic(APICCommonState *s)
int apic_get_interrupt(DeviceState *dev) int apic_get_interrupt(DeviceState *dev)
{ {
APICCommonState *s = APIC_COMMON(dev); APICCommonState *s = APIC(dev);
int intno; int intno;
/* if the APIC is installed or enabled, we let the 8259 handle the /* if the APIC is installed or enabled, we let the 8259 handle the
@ -584,7 +588,7 @@ int apic_get_interrupt(DeviceState *dev)
int apic_accept_pic_intr(DeviceState *dev) int apic_accept_pic_intr(DeviceState *dev)
{ {
APICCommonState *s = APIC_COMMON(dev); APICCommonState *s = APIC(dev);
uint32_t lvt0; uint32_t lvt0;
if (!s) if (!s)
@ -663,7 +667,7 @@ static uint32_t apic_mem_readl(void *opaque, hwaddr addr)
if (!dev) { if (!dev) {
return 0; return 0;
} }
s = APIC_COMMON(dev); s = APIC(dev);
index = (addr >> 4) & 0xff; index = (addr >> 4) & 0xff;
switch(index) { switch(index) {
@ -766,7 +770,7 @@ static void apic_mem_writel(void *opaque, hwaddr addr, uint32_t val)
if (!dev) { if (!dev) {
return; return;
} }
s = APIC_COMMON(dev); s = APIC(dev);
trace_apic_mem_writel(addr, val); trace_apic_mem_writel(addr, val);
@ -870,7 +874,7 @@ static const MemoryRegionOps apic_io_ops = {
static void apic_realize(DeviceState *dev, Error **errp) static void apic_realize(DeviceState *dev, Error **errp)
{ {
APICCommonState *s = APIC_COMMON(dev); APICCommonState *s = APIC(dev);
if (s->id >= MAX_APICS) { if (s->id >= MAX_APICS) {
error_setg(errp, "%s initialization failed. APIC ID %d is invalid", error_setg(errp, "%s initialization failed. APIC ID %d is invalid",
@ -889,7 +893,7 @@ static void apic_realize(DeviceState *dev, Error **errp)
static void apic_unrealize(DeviceState *dev, Error **errp) static void apic_unrealize(DeviceState *dev, Error **errp)
{ {
APICCommonState *s = APIC_COMMON(dev); APICCommonState *s = APIC(dev);
timer_del(s->timer); timer_del(s->timer);
timer_free(s->timer); timer_free(s->timer);
@ -912,7 +916,7 @@ static void apic_class_init(ObjectClass *klass, void *data)
} }
static const TypeInfo apic_info = { static const TypeInfo apic_info = {
.name = "apic", .name = TYPE_APIC,
.instance_size = sizeof(APICCommonState), .instance_size = sizeof(APICCommonState),
.parent = TYPE_APIC_COMMON, .parent = TYPE_APIC_COMMON,
.class_init = apic_class_init, .class_init = apic_class_init,

View File

@ -304,7 +304,7 @@ static int mptsas_process_scsi_io_request(MPTSASState *s,
goto bad; goto bad;
} }
req = g_new(MPTSASRequest, 1); req = g_new0(MPTSASRequest, 1);
QTAILQ_INSERT_TAIL(&s->pending, req, next); QTAILQ_INSERT_TAIL(&s->pending, req, next);
req->scsi_io = *scsi_io; req->scsi_io = *scsi_io;
req->dev = s; req->dev = s;

View File

@ -396,7 +396,7 @@ static void scsi_read_data(SCSIRequest *req)
return; return;
} }
if (s->tray_open) { if (!blk_is_available(req->dev->conf.blk)) {
scsi_read_complete(r, -ENOMEDIUM); scsi_read_complete(r, -ENOMEDIUM);
return; return;
} }
@ -519,7 +519,7 @@ static void scsi_write_data(SCSIRequest *req)
scsi_write_complete_noio(r, 0); scsi_write_complete_noio(r, 0);
return; return;
} }
if (s->tray_open) { if (!blk_is_available(req->dev->conf.blk)) {
scsi_write_complete_noio(r, -ENOMEDIUM); scsi_write_complete_noio(r, -ENOMEDIUM);
return; return;
} }
@ -792,10 +792,7 @@ static inline bool media_is_dvd(SCSIDiskState *s)
if (s->qdev.type != TYPE_ROM) { if (s->qdev.type != TYPE_ROM) {
return false; return false;
} }
if (!blk_is_inserted(s->qdev.conf.blk)) { if (!blk_is_available(s->qdev.conf.blk)) {
return false;
}
if (s->tray_open) {
return false; return false;
} }
blk_get_geometry(s->qdev.conf.blk, &nb_sectors); blk_get_geometry(s->qdev.conf.blk, &nb_sectors);
@ -808,10 +805,7 @@ static inline bool media_is_cd(SCSIDiskState *s)
if (s->qdev.type != TYPE_ROM) { if (s->qdev.type != TYPE_ROM) {
return false; return false;
} }
if (!blk_is_inserted(s->qdev.conf.blk)) { if (!blk_is_available(s->qdev.conf.blk)) {
return false;
}
if (s->tray_open) {
return false; return false;
} }
blk_get_geometry(s->qdev.conf.blk, &nb_sectors); blk_get_geometry(s->qdev.conf.blk, &nb_sectors);
@ -875,7 +869,7 @@ static int scsi_read_dvd_structure(SCSIDiskState *s, SCSIDiskReq *r,
} }
if (format != 0xff) { if (format != 0xff) {
if (s->tray_open || !blk_is_inserted(s->qdev.conf.blk)) { if (!blk_is_available(s->qdev.conf.blk)) {
scsi_check_condition(r, SENSE_CODE(NO_MEDIUM)); scsi_check_condition(r, SENSE_CODE(NO_MEDIUM));
return -1; return -1;
} }
@ -1857,7 +1851,7 @@ static int32_t scsi_disk_emulate_command(SCSIRequest *req, uint8_t *buf)
break; break;
default: default:
if (s->tray_open || !blk_is_inserted(s->qdev.conf.blk)) { if (!blk_is_available(s->qdev.conf.blk)) {
scsi_check_condition(r, SENSE_CODE(NO_MEDIUM)); scsi_check_condition(r, SENSE_CODE(NO_MEDIUM));
return 0; return 0;
} }
@ -1886,7 +1880,7 @@ static int32_t scsi_disk_emulate_command(SCSIRequest *req, uint8_t *buf)
memset(outbuf, 0, r->buflen); memset(outbuf, 0, r->buflen);
switch (req->cmd.buf[0]) { switch (req->cmd.buf[0]) {
case TEST_UNIT_READY: case TEST_UNIT_READY:
assert(!s->tray_open && blk_is_inserted(s->qdev.conf.blk)); assert(blk_is_available(s->qdev.conf.blk));
break; break;
case INQUIRY: case INQUIRY:
buflen = scsi_disk_emulate_inquiry(req, outbuf); buflen = scsi_disk_emulate_inquiry(req, outbuf);
@ -2126,7 +2120,7 @@ static int32_t scsi_disk_dma_command(SCSIRequest *req, uint8_t *buf)
command = buf[0]; command = buf[0];
if (s->tray_open || !blk_is_inserted(s->qdev.conf.blk)) { if (!blk_is_available(s->qdev.conf.blk)) {
scsi_check_condition(r, SENSE_CODE(NO_MEDIUM)); scsi_check_condition(r, SENSE_CODE(NO_MEDIUM));
return 0; return 0;
} }

View File

@ -236,6 +236,13 @@ static void virtio_scsi_cancel_notify(Notifier *notifier, void *data)
g_free(n); g_free(n);
} }
static inline void virtio_scsi_ctx_check(VirtIOSCSI *s, SCSIDevice *d)
{
if (s->dataplane_started && d && blk_is_available(d->conf.blk)) {
assert(blk_get_aio_context(d->conf.blk) == s->ctx);
}
}
/* Return 0 if the request is ready to be completed and return to guest; /* Return 0 if the request is ready to be completed and return to guest;
* -EINPROGRESS if the request is submitted and will be completed later, in the * -EINPROGRESS if the request is submitted and will be completed later, in the
* case of async cancellation. */ * case of async cancellation. */
@ -247,9 +254,7 @@ static int virtio_scsi_do_tmf(VirtIOSCSI *s, VirtIOSCSIReq *req)
int target; int target;
int ret = 0; int ret = 0;
if (s->dataplane_started && d) { virtio_scsi_ctx_check(s, d);
assert(blk_get_aio_context(d->conf.blk) == s->ctx);
}
/* Here VIRTIO_SCSI_S_OK means "FUNCTION COMPLETE". */ /* Here VIRTIO_SCSI_S_OK means "FUNCTION COMPLETE". */
req->resp.tmf.response = VIRTIO_SCSI_S_OK; req->resp.tmf.response = VIRTIO_SCSI_S_OK;
@ -539,9 +544,7 @@ static bool virtio_scsi_handle_cmd_req_prepare(VirtIOSCSI *s, VirtIOSCSIReq *req
virtio_scsi_complete_cmd_req(req); virtio_scsi_complete_cmd_req(req);
return false; return false;
} }
if (s->dataplane_started) { virtio_scsi_ctx_check(s, d);
assert(blk_get_aio_context(d->conf.blk) == s->ctx);
}
req->sreq = scsi_req_new(d, req->req.cmd.tag, req->sreq = scsi_req_new(d, req->req.cmd.tag,
virtio_scsi_get_lun(req->req.cmd.lun), virtio_scsi_get_lun(req->req.cmd.lun),
req->req.cmd.cdb, req); req->req.cmd.cdb, req);

View File

@ -247,8 +247,11 @@ static hwaddr
pvscsi_ring_pop_req_descr(PVSCSIRingInfo *mgr) pvscsi_ring_pop_req_descr(PVSCSIRingInfo *mgr)
{ {
uint32_t ready_ptr = RS_GET_FIELD(mgr, reqProdIdx); uint32_t ready_ptr = RS_GET_FIELD(mgr, reqProdIdx);
uint32_t ring_size = PVSCSI_MAX_NUM_PAGES_REQ_RING
* PVSCSI_MAX_NUM_REQ_ENTRIES_PER_PAGE;
if (ready_ptr != mgr->consumed_ptr) { if (ready_ptr != mgr->consumed_ptr
&& ready_ptr - mgr->consumed_ptr < ring_size) {
uint32_t next_ready_ptr = uint32_t next_ready_ptr =
mgr->consumed_ptr++ & mgr->txr_len_mask; mgr->consumed_ptr++ & mgr->txr_len_mask;
uint32_t next_ready_page = uint32_t next_ready_page =

View File

@ -2718,7 +2718,6 @@ static int core_dump_filename(const TaskState *ts, char *buf,
size_t bufsize) size_t bufsize)
{ {
char timestamp[64]; char timestamp[64];
char *filename = NULL;
char *base_filename = NULL; char *base_filename = NULL;
struct timeval tv; struct timeval tv;
struct tm tm; struct tm tm;
@ -2731,14 +2730,12 @@ static int core_dump_filename(const TaskState *ts, char *buf,
return (-1); return (-1);
} }
filename = strdup(ts->bprm->filename); base_filename = g_path_get_basename(ts->bprm->filename);
base_filename = strdup(basename(filename));
(void) strftime(timestamp, sizeof (timestamp), "%Y%m%d-%H%M%S", (void) strftime(timestamp, sizeof (timestamp), "%Y%m%d-%H%M%S",
localtime_r(&tv.tv_sec, &tm)); localtime_r(&tv.tv_sec, &tm));
(void) snprintf(buf, bufsize, "qemu_%s_%s_%d.core", (void) snprintf(buf, bufsize, "qemu_%s_%s_%d.core",
base_filename, timestamp, (int)getpid()); base_filename, timestamp, (int)getpid());
free(base_filename); g_free(base_filename);
free(filename);
return (0); return (0);
} }

View File

@ -944,11 +944,6 @@ static void memory_region_destructor_ram(MemoryRegion *mr)
qemu_ram_free(mr->ram_block); qemu_ram_free(mr->ram_block);
} }
static void memory_region_destructor_rom_device(MemoryRegion *mr)
{
qemu_ram_free(mr->ram_block);
}
static bool memory_region_need_escape(char c) static bool memory_region_need_escape(char c)
{ {
return c == '/' || c == '[' || c == '\\' || c == ']'; return c == '/' || c == '[' || c == '\\' || c == ']';
@ -1405,7 +1400,7 @@ void memory_region_init_rom_device(MemoryRegion *mr,
mr->opaque = opaque; mr->opaque = opaque;
mr->terminates = true; mr->terminates = true;
mr->rom_device = true; mr->rom_device = true;
mr->destructor = memory_region_destructor_rom_device; mr->destructor = memory_region_destructor_ram;
mr->ram_block = qemu_ram_alloc(size, mr, errp); mr->ram_block = qemu_ram_alloc(size, mr, errp);
} }

View File

@ -489,90 +489,105 @@ static int net_socket_listen_init(NetClientState *peer,
{ {
NetClientState *nc; NetClientState *nc;
NetSocketState *s; NetSocketState *s;
struct sockaddr_in saddr; SocketAddress *saddr;
int fd, ret; int ret;
Error *local_error = NULL;
if (parse_host_port(&saddr, host_str) < 0) saddr = socket_parse(host_str, &local_error);
return -1; if (saddr == NULL) {
error_report_err(local_error);
fd = qemu_socket(PF_INET, SOCK_STREAM, 0);
if (fd < 0) {
perror("socket");
return -1; return -1;
} }
qemu_set_nonblock(fd);
socket_set_fast_reuse(fd); ret = socket_listen(saddr, &local_error);
ret = bind(fd, (struct sockaddr *)&saddr, sizeof(saddr));
if (ret < 0) { if (ret < 0) {
perror("bind"); qapi_free_SocketAddress(saddr);
closesocket(fd); error_report_err(local_error);
return -1;
}
ret = listen(fd, 0);
if (ret < 0) {
perror("listen");
closesocket(fd);
return -1; return -1;
} }
nc = qemu_new_net_client(&net_socket_info, peer, model, name); nc = qemu_new_net_client(&net_socket_info, peer, model, name);
s = DO_UPCAST(NetSocketState, nc, nc); s = DO_UPCAST(NetSocketState, nc, nc);
s->fd = -1; s->fd = -1;
s->listen_fd = fd; s->listen_fd = ret;
s->nc.link_down = true; s->nc.link_down = true;
qemu_set_fd_handler(s->listen_fd, net_socket_accept, NULL, s); qemu_set_fd_handler(s->listen_fd, net_socket_accept, NULL, s);
qapi_free_SocketAddress(saddr);
return 0; return 0;
} }
typedef struct {
NetClientState *peer;
SocketAddress *saddr;
char *model;
char *name;
} socket_connect_data;
static void socket_connect_data_free(socket_connect_data *c)
{
qapi_free_SocketAddress(c->saddr);
g_free(c->model);
g_free(c->name);
g_free(c);
}
static void net_socket_connected(int fd, Error *err, void *opaque)
{
socket_connect_data *c = opaque;
NetSocketState *s;
char *addr_str = NULL;
Error *local_error = NULL;
addr_str = socket_address_to_string(c->saddr, &local_error);
if (addr_str == NULL) {
error_report_err(local_error);
closesocket(fd);
goto end;
}
s = net_socket_fd_init(c->peer, c->model, c->name, fd, true);
if (!s) {
closesocket(fd);
goto end;
}
snprintf(s->nc.info_str, sizeof(s->nc.info_str),
"socket: connect to %s", addr_str);
end:
g_free(addr_str);
socket_connect_data_free(c);
}
static int net_socket_connect_init(NetClientState *peer, static int net_socket_connect_init(NetClientState *peer,
const char *model, const char *model,
const char *name, const char *name,
const char *host_str) const char *host_str)
{ {
NetSocketState *s; socket_connect_data *c = g_new0(socket_connect_data, 1);
int fd, connected, ret; int fd = -1;
struct sockaddr_in saddr; Error *local_error = NULL;
if (parse_host_port(&saddr, host_str) < 0) c->peer = peer;
return -1; c->model = g_strdup(model);
c->name = g_strdup(name);
c->saddr = socket_parse(host_str, &local_error);
if (c->saddr == NULL) {
goto err;
}
fd = qemu_socket(PF_INET, SOCK_STREAM, 0); fd = socket_connect(c->saddr, &local_error, net_socket_connected, c);
if (fd < 0) { if (fd < 0) {
perror("socket"); goto err;
return -1;
} }
qemu_set_nonblock(fd);
connected = 0;
for(;;) {
ret = connect(fd, (struct sockaddr *)&saddr, sizeof(saddr));
if (ret < 0) {
if (errno == EINTR || errno == EWOULDBLOCK) {
/* continue */
} else if (errno == EINPROGRESS ||
errno == EALREADY ||
errno == EINVAL) {
break;
} else {
perror("connect");
closesocket(fd);
return -1;
}
} else {
connected = 1;
break;
}
}
s = net_socket_fd_init(peer, model, name, fd, connected);
if (!s)
return -1;
snprintf(s->nc.info_str, sizeof(s->nc.info_str),
"socket: connect to %s:%d",
inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
return 0; return 0;
err:
error_report_err(local_error);
socket_connect_data_free(c);
return -1;
} }
static int net_socket_mcast_init(NetClientState *peer, static int net_socket_mcast_init(NetClientState *peer,

View File

@ -1230,6 +1230,9 @@ static CharDriverState *qemu_chr_open_stdio(const char *id,
sigaction(SIGCONT, &act, NULL); sigaction(SIGCONT, &act, NULL);
chr = qemu_chr_open_fd(0, 1, common, errp); chr = qemu_chr_open_fd(0, 1, common, errp);
if (!chr) {
return NULL;
}
chr->chr_close = qemu_chr_close_stdio; chr->chr_close = qemu_chr_close_stdio;
chr->chr_set_echo = qemu_chr_set_echo_stdio; chr->chr_set_echo = qemu_chr_set_echo_stdio;
if (opts->has_signal) { if (opts->has_signal) {
@ -1686,6 +1689,9 @@ static CharDriverState *qemu_chr_open_tty_fd(int fd,
tty_serial_init(fd, 115200, 'N', 8, 1); tty_serial_init(fd, 115200, 'N', 8, 1);
chr = qemu_chr_open_fd(fd, fd, backend, errp); chr = qemu_chr_open_fd(fd, fd, backend, errp);
if (!chr) {
return NULL;
}
chr->chr_ioctl = tty_serial_ioctl; chr->chr_ioctl = tty_serial_ioctl;
chr->chr_close = qemu_chr_close_tty; chr->chr_close = qemu_chr_close_tty;
return chr; return chr;

View File

@ -1035,6 +1035,9 @@ typedef struct CPUX86State {
uint64_t tsc; uint64_t tsc;
uint64_t tsc_adjust; uint64_t tsc_adjust;
uint64_t tsc_deadline; uint64_t tsc_deadline;
uint64_t tsc_aux;
uint64_t xcr0;
uint64_t mcg_status; uint64_t mcg_status;
uint64_t msr_ia32_misc_enable; uint64_t msr_ia32_misc_enable;
@ -1051,6 +1054,8 @@ typedef struct CPUX86State {
uint64_t pat; uint64_t pat;
uint32_t smbase; uint32_t smbase;
uint32_t pkru;
/* End of state preserved by INIT (dummy marker). */ /* End of state preserved by INIT (dummy marker). */
struct {} end_init_save; struct {} end_init_save;
@ -1135,20 +1140,15 @@ typedef struct CPUX86State {
uint64_t mcg_ctl; uint64_t mcg_ctl;
uint64_t mcg_ext_ctl; uint64_t mcg_ext_ctl;
uint64_t mce_banks[MCE_BANKS_DEF*4]; uint64_t mce_banks[MCE_BANKS_DEF*4];
uint64_t xstate_bv;
uint64_t tsc_aux;
/* vmstate */ /* vmstate */
uint16_t fpus_vmstate; uint16_t fpus_vmstate;
uint16_t fptag_vmstate; uint16_t fptag_vmstate;
uint16_t fpregs_format_vmstate; uint16_t fpregs_format_vmstate;
uint64_t xstate_bv;
uint64_t xcr0;
uint64_t xss; uint64_t xss;
uint32_t pkru;
TPRAccess tpr_access_type; TPRAccess tpr_access_type;
} CPUX86State; } CPUX86State;

View File

@ -1137,6 +1137,7 @@ static void do_interrupt_real(CPUX86State *env, int intno, int is_int,
static void do_interrupt_user(CPUX86State *env, int intno, int is_int, static void do_interrupt_user(CPUX86State *env, int intno, int is_int,
int error_code, target_ulong next_eip) int error_code, target_ulong next_eip)
{ {
if (is_int) {
SegmentCache *dt; SegmentCache *dt;
target_ulong ptr; target_ulong ptr;
int dpl, cpl, shift; int dpl, cpl, shift;
@ -1154,9 +1155,10 @@ static void do_interrupt_user(CPUX86State *env, int intno, int is_int,
dpl = (e2 >> DESC_DPL_SHIFT) & 3; dpl = (e2 >> DESC_DPL_SHIFT) & 3;
cpl = env->hflags & HF_CPL_MASK; cpl = env->hflags & HF_CPL_MASK;
/* check privilege if software int */ /* check privilege if software int */
if (is_int && dpl < cpl) { if (dpl < cpl) {
raise_exception_err(env, EXCP0D_GPF, (intno << shift) + 2); raise_exception_err(env, EXCP0D_GPF, (intno << shift) + 2);
} }
}
/* Since we emulate only user space, we cannot do more than /* Since we emulate only user space, we cannot do more than
exiting the emulation with the suitable exception and error exiting the emulation with the suitable exception and error

View File

@ -26,38 +26,6 @@
#include "qemu/cutils.h" #include "qemu/cutils.h"
#include "qemu/bswap.h" #include "qemu/bswap.h"
/* vector definitions */
extern void link_error(void);
#define ACCEL_BUFFER_ZERO(NAME, SIZE, VECTYPE, NONZERO) \
static bool NAME(const void *buf, size_t len) \
{ \
const void *end = buf + len; \
do { \
const VECTYPE *p = buf; \
VECTYPE t; \
__builtin_prefetch(buf + SIZE); \
barrier(); \
if (SIZE == sizeof(VECTYPE) * 4) { \
t = (p[0] | p[1]) | (p[2] | p[3]); \
} else if (SIZE == sizeof(VECTYPE) * 8) { \
t = p[0] | p[1]; \
t |= p[2] | p[3]; \
t |= p[4] | p[5]; \
t |= p[6] | p[7]; \
} else { \
link_error(); \
} \
if (unlikely(NONZERO(t))) { \
return false; \
} \
buf += SIZE; \
} while (buf < end); \
return true; \
}
static bool static bool
buffer_zero_int(const void *buf, size_t len) buffer_zero_int(const void *buf, size_t len)
{ {
@ -96,47 +64,174 @@ buffer_zero_int(const void *buf, size_t len)
} }
} }
#if defined(CONFIG_AVX2_OPT) || (defined(CONFIG_CPUID_H) && defined(__SSE2__)) #if defined(CONFIG_AVX2_OPT) || defined(__SSE2__)
#include <cpuid.h>
/* Do not use push_options pragmas unnecessarily, because clang /* Do not use push_options pragmas unnecessarily, because clang
* does not support them. * does not support them.
*/ */
#ifndef __SSE2__ #ifdef CONFIG_AVX2_OPT
#pragma GCC push_options #pragma GCC push_options
#pragma GCC target("sse2") #pragma GCC target("sse2")
#endif #endif
#include <emmintrin.h> #include <emmintrin.h>
#define SSE2_NONZERO(X) \
(_mm_movemask_epi8(_mm_cmpeq_epi8((X), _mm_setzero_si128())) != 0xFFFF) /* Note that each of these vectorized functions require len >= 64. */
ACCEL_BUFFER_ZERO(buffer_zero_sse2, 64, __m128i, SSE2_NONZERO)
#ifndef __SSE2__ static bool
buffer_zero_sse2(const void *buf, size_t len)
{
__m128i t = _mm_loadu_si128(buf);
__m128i *p = (__m128i *)(((uintptr_t)buf + 5 * 16) & -16);
__m128i *e = (__m128i *)(((uintptr_t)buf + len) & -16);
__m128i zero = _mm_setzero_si128();
/* Loop over 16-byte aligned blocks of 64. */
while (likely(p <= e)) {
__builtin_prefetch(p);
t = _mm_cmpeq_epi8(t, zero);
if (unlikely(_mm_movemask_epi8(t) != 0xFFFF)) {
return false;
}
t = p[-4] | p[-3] | p[-2] | p[-1];
p += 4;
}
/* Finish the aligned tail. */
t |= e[-3];
t |= e[-2];
t |= e[-1];
/* Finish the unaligned tail. */
t |= _mm_loadu_si128(buf + len - 16);
return _mm_movemask_epi8(_mm_cmpeq_epi8(t, zero)) == 0xFFFF;
}
#ifdef CONFIG_AVX2_OPT
#pragma GCC pop_options #pragma GCC pop_options
#endif #endif
#ifdef CONFIG_AVX2_OPT #ifdef CONFIG_AVX2_OPT
/* Note that due to restrictions/bugs wrt __builtin functions in gcc <= 4.8,
* the includes have to be within the corresponding push_options region, and
* therefore the regions themselves have to be ordered with increasing ISA.
*/
#pragma GCC push_options #pragma GCC push_options
#pragma GCC target("sse4") #pragma GCC target("sse4")
#include <smmintrin.h> #include <smmintrin.h>
#define SSE4_NONZERO(X) !_mm_testz_si128((X), (X))
ACCEL_BUFFER_ZERO(buffer_zero_sse4, 64, __m128i, SSE4_NONZERO)
#pragma GCC pop_options
static bool
buffer_zero_sse4(const void *buf, size_t len)
{
__m128i t = _mm_loadu_si128(buf);
__m128i *p = (__m128i *)(((uintptr_t)buf + 5 * 16) & -16);
__m128i *e = (__m128i *)(((uintptr_t)buf + len) & -16);
/* Loop over 16-byte aligned blocks of 64. */
while (likely(p <= e)) {
__builtin_prefetch(p);
if (unlikely(!_mm_testz_si128(t, t))) {
return false;
}
t = p[-4] | p[-3] | p[-2] | p[-1];
p += 4;
}
/* Finish the aligned tail. */
t |= e[-3];
t |= e[-2];
t |= e[-1];
/* Finish the unaligned tail. */
t |= _mm_loadu_si128(buf + len - 16);
return _mm_testz_si128(t, t);
}
#pragma GCC pop_options
#pragma GCC push_options #pragma GCC push_options
#pragma GCC target("avx2") #pragma GCC target("avx2")
#include <immintrin.h> #include <immintrin.h>
#define AVX2_NONZERO(X) !_mm256_testz_si256((X), (X))
ACCEL_BUFFER_ZERO(buffer_zero_avx2, 128, __m256i, AVX2_NONZERO) static bool
buffer_zero_avx2(const void *buf, size_t len)
{
/* Begin with an unaligned head of 32 bytes. */
__m256i t = _mm256_loadu_si256(buf);
__m256i *p = (__m256i *)(((uintptr_t)buf + 5 * 32) & -32);
__m256i *e = (__m256i *)(((uintptr_t)buf + len) & -32);
if (likely(p <= e)) {
/* Loop over 32-byte aligned blocks of 128. */
do {
__builtin_prefetch(p);
if (unlikely(!_mm256_testz_si256(t, t))) {
return false;
}
t = p[-4] | p[-3] | p[-2] | p[-1];
p += 4;
} while (p <= e);
} else {
t |= _mm256_loadu_si256(buf + 32);
if (len <= 128) {
goto last2;
}
}
/* Finish the last block of 128 unaligned. */
t |= _mm256_loadu_si256(buf + len - 4 * 32);
t |= _mm256_loadu_si256(buf + len - 3 * 32);
last2:
t |= _mm256_loadu_si256(buf + len - 2 * 32);
t |= _mm256_loadu_si256(buf + len - 1 * 32);
return _mm256_testz_si256(t, t);
}
#pragma GCC pop_options #pragma GCC pop_options
#endif /* CONFIG_AVX2_OPT */
/* Note that for test_buffer_is_zero_next_accel, the most preferred
* ISA must have the least significant bit.
*/
#define CACHE_AVX2 1
#define CACHE_SSE4 2
#define CACHE_SSE2 4
/* Make sure that these variables are appropriately initialized when
* SSE2 is enabled on the compiler command-line, but the compiler is
* too old to support <cpuid.h>.
*/
#ifdef CONFIG_AVX2_OPT
# define INIT_CACHE 0
# define INIT_ACCEL buffer_zero_int
#else
# ifndef __SSE2__
# error "ISA selection confusion"
# endif
# define INIT_CACHE CACHE_SSE2
# define INIT_ACCEL buffer_zero_sse2
#endif #endif
#define CACHE_AVX2 2 static unsigned cpuid_cache = INIT_CACHE;
#define CACHE_AVX1 4 static bool (*buffer_accel)(const void *, size_t) = INIT_ACCEL;
#define CACHE_SSE4 8
#define CACHE_SSE2 16
static unsigned cpuid_cache; static void init_accel(unsigned cache)
{
bool (*fn)(const void *, size_t) = buffer_zero_int;
if (cache & CACHE_SSE2) {
fn = buffer_zero_sse2;
}
#ifdef CONFIG_AVX2_OPT
if (cache & CACHE_SSE4) {
fn = buffer_zero_sse4;
}
if (cache & CACHE_AVX2) {
fn = buffer_zero_avx2;
}
#endif
buffer_accel = fn;
}
#ifdef CONFIG_AVX2_OPT
#include <cpuid.h>
static void __attribute__((constructor)) init_cpuid_cache(void) static void __attribute__((constructor)) init_cpuid_cache(void)
{ {
int max = __get_cpuid_max(0, NULL); int max = __get_cpuid_max(0, NULL);
@ -154,24 +249,21 @@ static void __attribute__((constructor)) init_cpuid_cache(void)
} }
/* We must check that AVX is not just available, but usable. */ /* We must check that AVX is not just available, but usable. */
if ((c & bit_OSXSAVE) && (c & bit_AVX)) { if ((c & bit_OSXSAVE) && (c & bit_AVX) && max >= 7) {
__asm("xgetbv" : "=a"(a), "=d"(d) : "c"(0)); int bv;
if ((a & 6) == 6) { __asm("xgetbv" : "=a"(bv), "=d"(d) : "c"(0));
cache |= CACHE_AVX1;
if (max >= 7) {
__cpuid_count(7, 0, a, b, c, d); __cpuid_count(7, 0, a, b, c, d);
if (b & bit_AVX2) { if ((bv & 6) == 6 && (b & bit_AVX2)) {
cache |= CACHE_AVX2; cache |= CACHE_AVX2;
} }
} }
}
}
#endif #endif
} }
cpuid_cache = cache; cpuid_cache = cache;
init_accel(cache);
} }
#endif /* CONFIG_AVX2_OPT */
#define HAVE_NEXT_ACCEL
bool test_buffer_is_zero_next_accel(void) bool test_buffer_is_zero_next_accel(void)
{ {
/* If no bits set, we just tested buffer_zero_int, and there /* If no bits set, we just tested buffer_zero_int, and there
@ -181,31 +273,20 @@ bool test_buffer_is_zero_next_accel(void)
} }
/* Disable the accelerator we used before and select a new one. */ /* Disable the accelerator we used before and select a new one. */
cpuid_cache &= cpuid_cache - 1; cpuid_cache &= cpuid_cache - 1;
init_accel(cpuid_cache);
return true; return true;
} }
static bool select_accel_fn(const void *buf, size_t len) static bool select_accel_fn(const void *buf, size_t len)
{ {
uintptr_t ibuf = (uintptr_t)buf; if (likely(len >= 64)) {
#ifdef CONFIG_AVX2_OPT return buffer_accel(buf, len);
if (len % 128 == 0 && ibuf % 32 == 0 && (cpuid_cache & CACHE_AVX2)) {
return buffer_zero_avx2(buf, len);
}
if (len % 64 == 0 && ibuf % 16 == 0 && (cpuid_cache & CACHE_SSE4)) {
return buffer_zero_sse4(buf, len);
}
#endif
if (len % 64 == 0 && ibuf % 16 == 0 && (cpuid_cache & CACHE_SSE2)) {
return buffer_zero_sse2(buf, len);
} }
return buffer_zero_int(buf, len); return buffer_zero_int(buf, len);
} }
#else #else
#define select_accel_fn buffer_zero_int #define select_accel_fn buffer_zero_int
#endif
#ifndef HAVE_NEXT_ACCEL
bool test_buffer_is_zero_next_accel(void) bool test_buffer_is_zero_next_accel(void)
{ {
return false; return false;

View File

@ -275,53 +275,42 @@ const QEMULogItem qemu_log_items[] = {
{ 0, NULL, NULL }, { 0, NULL, NULL },
}; };
static int cmp1(const char *s1, int n, const char *s2)
{
if (strlen(s2) != n) {
return 0;
}
return memcmp(s1, s2, n) == 0;
}
/* takes a comma separated list of log masks. Return 0 if error. */ /* takes a comma separated list of log masks. Return 0 if error. */
int qemu_str_to_log_mask(const char *str) int qemu_str_to_log_mask(const char *str)
{ {
const QEMULogItem *item; const QEMULogItem *item;
int mask; int mask = 0;
const char *p, *p1; char **parts = g_strsplit(str, ",", 0);
char **tmp;
p = str; for (tmp = parts; tmp && *tmp; tmp++) {
mask = 0; if (g_str_equal(*tmp, "all")) {
for (;;) {
p1 = strchr(p, ',');
if (!p1) {
p1 = p + strlen(p);
}
if (cmp1(p,p1-p,"all")) {
for (item = qemu_log_items; item->mask != 0; item++) { for (item = qemu_log_items; item->mask != 0; item++) {
mask |= item->mask; mask |= item->mask;
} }
#ifdef CONFIG_TRACE_LOG #ifdef CONFIG_TRACE_LOG
} else if (strncmp(p, "trace:", 6) == 0 && p + 6 != p1) { } else if (g_str_has_prefix(*tmp, "trace:") && (*tmp)[6] != '\0') {
trace_enable_events(p + 6); trace_enable_events((*tmp) + 6);
mask |= LOG_TRACE; mask |= LOG_TRACE;
#endif #endif
} else { } else {
for (item = qemu_log_items; item->mask != 0; item++) { for (item = qemu_log_items; item->mask != 0; item++) {
if (cmp1(p, p1 - p, item->name)) { if (g_str_equal(*tmp, item->name)) {
goto found; goto found;
} }
} }
return 0; goto error;
found: found:
mask |= item->mask; mask |= item->mask;
} }
if (*p1 != ',') {
break;
}
p = p1 + 1;
} }
g_strfreev(parts);
return mask; return mask;
error:
g_strfreev(parts);
return 0;
} }
void qemu_print_log_usage(FILE *f) void qemu_print_log_usage(FILE *f)