aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--MAINTAINERS2
-rw-r--r--Makefile.target14
-rw-r--r--arm-semi.c5
-rw-r--r--audio/coreaudio.c6
-rw-r--r--block-migration.c2
-rw-r--r--block/qcow2.c2
-rw-r--r--block/sheepdog.c90
-rw-r--r--blockdev.c2
-rw-r--r--bsd-user/main.c4
-rw-r--r--cmd.c6
-rwxr-xr-xconfigure184
-rw-r--r--console.c9
-rw-r--r--cpu-all.h2
-rw-r--r--cpu-common.h1
-rw-r--r--cpu-exec.c150
-rw-r--r--cpus.c6
-rw-r--r--darwin-user/main.c2
-rw-r--r--disas.c1
-rw-r--r--error.c3
-rw-r--r--error.h3
-rw-r--r--exec-all.h3
-rw-r--r--exec.c138
-rw-r--r--gdbstub.c2
-rw-r--r--hppa-dis.c6
-rw-r--r--hw/9pfs/virtio-9p-device.c10
-rw-r--r--hw/ac97.c9
-rw-r--r--hw/acpi_piix4.c8
-rw-r--r--hw/apb_pci.c13
-rw-r--r--hw/armv7m.c4
-rw-r--r--hw/bonito.c9
-rw-r--r--hw/cirrus_vga.c15
-rw-r--r--hw/dec_pci.c26
-rw-r--r--hw/e1000.c8
-rw-r--r--hw/eepro100.c74
-rw-r--r--hw/es1370.c24
-rw-r--r--hw/etraxfs_ser.c24
-rw-r--r--hw/grackle_pci.c8
-rw-r--r--hw/gt64xxx.c8
-rw-r--r--hw/hw.h3
-rw-r--r--hw/ide/cmd646.c10
-rw-r--r--hw/ide/ich.c11
-rw-r--r--hw/ide/piix.c32
-rw-r--r--hw/ide/via.c8
-rw-r--r--hw/intel-hda.c8
-rw-r--r--hw/ioh3420.c7
-rw-r--r--hw/ivshmem.c8
-rw-r--r--hw/kvmclock.c9
-rw-r--r--hw/kvmclock.h10
-rw-r--r--hw/lm32_sys.c2
-rw-r--r--hw/lm32_timer.c4
-rw-r--r--hw/lm32_uart.c4
-rw-r--r--hw/lsi53c895a.c15
-rw-r--r--hw/milkymist-ac97.c4
-rw-r--r--hw/milkymist-memcard.c4
-rw-r--r--hw/milkymist-minimac2.c6
-rw-r--r--hw/milkymist-pfpu.c4
-rw-r--r--hw/milkymist-softusb.c8
-rw-r--r--hw/milkymist-sysctl.c4
-rw-r--r--hw/milkymist-tmu2.c8
-rw-r--r--hw/msi.c2
-rw-r--r--hw/msix.c40
-rw-r--r--hw/ne2000.c6
-rw-r--r--hw/pc.h1
-rw-r--r--hw/pc_piix.c58
-rw-r--r--hw/pci.c56
-rw-r--r--hw/pci.h7
-rw-r--r--hw/pci_ids.h2
-rw-r--r--hw/pci_regs.h60
-rw-r--r--hw/pcie_aer.c9
-rw-r--r--hw/pcnet-pci.c8
-rw-r--r--hw/piix4.c10
-rw-r--r--hw/piix_pci.c85
-rw-r--r--hw/ppce500_pci.c13
-rw-r--r--hw/qdev.c3
-rw-r--r--hw/qxl.c7
-rw-r--r--hw/rtl8139.c8
-rw-r--r--hw/sh7750.c1
-rw-r--r--hw/sh_pci.c4
-rw-r--r--hw/spapr_hcall.c1
-rw-r--r--hw/strongarm.c4
-rw-r--r--hw/sun4u.c8
-rw-r--r--hw/syborg_virtio.c4
-rw-r--r--hw/unin_pci.c33
-rw-r--r--hw/usb-bus.c31
-rw-r--r--hw/usb-ccid.c3
-rw-r--r--hw/usb-desc.c14
-rw-r--r--hw/usb-ehci.c52
-rw-r--r--hw/usb-msd.c19
-rw-r--r--hw/usb-ohci.c24
-rw-r--r--hw/usb-uhci.c46
-rw-r--r--hw/usb.h4
-rw-r--r--hw/versatile_pci.c8
-rw-r--r--hw/vga-pci.c11
-rw-r--r--hw/vga.c13
-rw-r--r--hw/vhost_net.c8
-rw-r--r--hw/virtio-pci.c66
-rw-r--r--hw/virtio-pci.h8
-rw-r--r--hw/virtio-serial-bus.c34
-rw-r--r--hw/virtio.c101
-rw-r--r--hw/virtio.h9
-rw-r--r--hw/vmware_vga.c13
-rw-r--r--hw/vt82c686.c35
-rw-r--r--hw/wdt_i6300esb.c9
-rw-r--r--hw/xen_common.h14
-rw-r--r--hw/xen_platform.c340
-rw-r--r--hw/xio3130_downstream.c6
-rw-r--r--hw/xio3130_upstream.c6
-rw-r--r--kvm-all.c13
-rw-r--r--kvm-stub.c20
-rw-r--r--kvm.h2
-rw-r--r--linux-headers/COPYING356
-rw-r--r--linux-headers/README2
-rw-r--r--linux-headers/asm-powerpc/kvm.h275
-rw-r--r--linux-headers/asm-powerpc/kvm_para.h53
-rw-r--r--linux-headers/asm-s390/kvm.h44
-rw-r--r--linux-headers/asm-s390/kvm_para.h17
-rw-r--r--linux-headers/asm-x86/hyperv.h193
-rw-r--r--linux-headers/asm-x86/kvm.h324
-rw-r--r--linux-headers/asm-x86/kvm_para.h79
-rw-r--r--linux-headers/linux/kvm.h804
-rw-r--r--linux-headers/linux/kvm_para.h28
-rw-r--r--linux-headers/linux/vhost.h130
-rw-r--r--linux-headers/linux/virtio_config.h54
-rw-r--r--linux-headers/linux/virtio_ring.h163
-rw-r--r--linux-user/elfload.c185
-rw-r--r--linux-user/flatload.c8
-rw-r--r--linux-user/linuxload.c25
-rw-r--r--linux-user/main.c42
-rw-r--r--linux-user/qemu.h3
-rw-r--r--linux-user/signal.c21
-rw-r--r--linux-user/syscall.c240
-rw-r--r--m68k-semi.c5
-rw-r--r--monitor.c2
-rw-r--r--net.c44
-rw-r--r--net.h3
-rw-r--r--net/socket.c6
-rw-r--r--qemu-common.h5
-rw-r--r--qemu-error.c2
-rw-r--r--qemu-img.c12
-rw-r--r--savevm.c1
-rwxr-xr-xscripts/get_maintainer.pl2149
-rwxr-xr-xscripts/update-linux-headers.sh55
-rw-r--r--sysemu.h5
-rw-r--r--target-alpha/cpu.h22
-rw-r--r--target-alpha/exec.h21
-rw-r--r--target-alpha/helper.c1
-rw-r--r--target-alpha/op_helper.c6
-rw-r--r--target-alpha/translate.c11
-rw-r--r--target-arm/cpu.h13
-rw-r--r--target-arm/exec.h13
-rw-r--r--target-arm/helper.c1
-rw-r--r--target-arm/op_helper.c6
-rw-r--r--target-arm/translate.c1
-rw-r--r--target-cris/cpu.h11
-rw-r--r--target-cris/exec.h12
-rw-r--r--target-cris/helper.c1
-rw-r--r--target-cris/mmu.c1
-rw-r--r--target-cris/op_helper.c4
-rw-r--r--target-cris/translate.c1
-rw-r--r--target-cris/translate_v10.c3
-rw-r--r--target-i386/cpu.h61
-rw-r--r--target-i386/cpuid.c20
-rw-r--r--target-i386/exec.h57
-rw-r--r--target-i386/helper.c1
-rw-r--r--target-i386/kvm.c148
-rw-r--r--target-i386/machine.c25
-rw-r--r--target-i386/op_helper.c106
-rw-r--r--target-i386/translate.c1
-rw-r--r--target-lm32/cpu.h13
-rw-r--r--target-lm32/exec.h12
-rw-r--r--target-lm32/helper.c1
-rw-r--r--target-lm32/op_helper.c6
-rw-r--r--target-lm32/translate.c1
-rw-r--r--target-m68k/cpu.h15
-rw-r--r--target-m68k/exec.h12
-rw-r--r--target-m68k/helper.c1
-rw-r--r--target-m68k/op_helper.c35
-rw-r--r--target-m68k/translate.c1
-rw-r--r--target-microblaze/cpu.h13
-rw-r--r--target-microblaze/exec.h12
-rw-r--r--target-microblaze/helper.c1
-rw-r--r--target-microblaze/mmu.c1
-rw-r--r--target-microblaze/op_helper.c4
-rw-r--r--target-microblaze/translate.c1
-rw-r--r--target-mips/cpu.h24
-rw-r--r--target-mips/exec.h23
-rw-r--r--target-mips/helper.c1
-rw-r--r--target-mips/machine.c2
-rw-r--r--target-mips/op_helper.c4
-rw-r--r--target-mips/translate.c1
-rw-r--r--target-ppc/cpu.h12
-rw-r--r--target-ppc/exec.h12
-rw-r--r--target-ppc/helper.c1
-rw-r--r--target-ppc/kvm.c23
-rw-r--r--target-ppc/op_helper.c2
-rw-r--r--target-ppc/translate.c1
-rw-r--r--target-s390x/cpu.h21
-rw-r--r--target-s390x/exec.h13
-rw-r--r--target-s390x/helper.c1
-rw-r--r--target-s390x/op_helper.c17
-rw-r--r--target-s390x/translate.c1
-rw-r--r--target-sh4/cpu.h13
-rw-r--r--target-sh4/exec.h12
-rw-r--r--target-sh4/helper.c1
-rw-r--r--target-sh4/op_helper.c10
-rw-r--r--target-sh4/translate.c1
-rw-r--r--target-sparc/cpu.h22
-rw-r--r--target-sparc/exec.h16
-rw-r--r--target-sparc/helper.c243
-rw-r--r--target-sparc/machine.c28
-rw-r--r--target-sparc/op_helper.c279
-rw-r--r--target-sparc/translate.c1
-rw-r--r--target-unicore32/cpu.h6
-rw-r--r--target-unicore32/exec.h7
-rw-r--r--target-unicore32/helper.c1
-rw-r--r--target-unicore32/op_helper.c2
-rw-r--r--target-unicore32/translate.c1
-rw-r--r--tcg/arm/tcg-target.c19
-rw-r--r--tcg/hppa/tcg-target.c67
-rw-r--r--tcg/hppa/tcg-target.h1
-rw-r--r--tcg/i386/tcg-target.c32
-rw-r--r--tcg/ia64/tcg-target.c7
-rw-r--r--tcg/mips/tcg-target.c10
-rw-r--r--tcg/ppc/tcg-target.c13
-rw-r--r--tcg/ppc64/tcg-target.c13
-rw-r--r--tcg/s390/tcg-target.c7
-rw-r--r--tcg/sparc/tcg-target.c9
-rw-r--r--tcg/tcg.c22
-rw-r--r--tcg/tcg.h7
-rw-r--r--trace-events4
-rw-r--r--translate-all.c3
-rw-r--r--ui/vnc-enc-tight.c10
-rw-r--r--usb-bsd.c2
-rw-r--r--usb-linux.c124
-rw-r--r--user-exec.c11
-rw-r--r--vl.c10
-rw-r--r--xen-all.c283
-rw-r--r--xen-mapcache-stub.c10
-rw-r--r--xen-mapcache.c141
-rw-r--r--xen-mapcache.h16
240 files changed, 7891 insertions, 2134 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index 35d4496186..6115e4ec08 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -480,7 +480,7 @@ S: Maintained
F: tcg/ia64/
MIPS target
-M: Aurelien Jarno <aurelien@aurel32.ne>
+M: Aurelien Jarno <aurelien@aurel32.net>
S: Maintained
F: tcg/mips/
diff --git a/Makefile.target b/Makefile.target
index d3ebe579eb..a53a2ff6ed 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -14,7 +14,10 @@ endif
TARGET_PATH=$(SRC_PATH)/target-$(TARGET_BASE_ARCH)
$(call set-vpath, $(SRC_PATH):$(TARGET_PATH):$(SRC_PATH)/hw)
-QEMU_CFLAGS+= -I.. -I$(TARGET_PATH) -DNEED_CPU_H
+ifdef CONFIG_LINUX
+QEMU_CFLAGS += -I../linux-headers
+endif
+QEMU_CFLAGS += -I.. -I$(TARGET_PATH) -DNEED_CPU_H
include $(SRC_PATH)/Makefile.objs
@@ -37,8 +40,6 @@ ifndef CONFIG_HAIKU
LIBS+=-lm
endif
-kvm.o kvm-all.o vhost.o vhost_net.o kvmclock.o: QEMU_CFLAGS+=$(KVM_CFLAGS)
-
config-target.h: config-target.h-timestamp
config-target.h-timestamp: config-target.mak
@@ -93,7 +94,7 @@ tcg/tcg.o: cpu.h
# HELPER_CFLAGS is used for all the code compiled with static register
# variables
-%_helper.o cpu-exec.o user-exec.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
+%_helper.o user-exec.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
# Note: this is a workaround. The real fix is to avoid compiling
# cpu_signal_handler() in user-exec.c.
@@ -218,6 +219,8 @@ obj-$(CONFIG_NO_XEN) += xen-stub.o
obj-i386-$(CONFIG_XEN_MAPCACHE) += xen-mapcache.o
obj-$(CONFIG_NO_XEN_MAPCACHE) += xen-mapcache-stub.o
+obj-i386-$(CONFIG_XEN) += xen_platform.o
+
# Inter-VM PCI shared memory
CONFIG_IVSHMEM =
ifeq ($(CONFIG_KVM), y)
@@ -234,7 +237,8 @@ obj-i386-y += cirrus_vga.o sga.o apic.o ioapic.o piix_pci.o
obj-i386-y += vmport.o
obj-i386-y += device-hotplug.o pci-hotplug.o smbios.o wdt_ib700.o
obj-i386-y += debugcon.o multiboot.o
-obj-i386-y += pc_piix.o kvmclock.o
+obj-i386-y += pc_piix.o
+obj-i386-$(CONFIG_KVM) += kvmclock.o
obj-i386-$(CONFIG_SPICE) += qxl.o qxl-logger.o qxl-render.o
# shared objects
diff --git a/arm-semi.c b/arm-semi.c
index e9e6f8993f..5a62d03b36 100644
--- a/arm-semi.c
+++ b/arm-semi.c
@@ -440,15 +440,16 @@ uint32_t do_arm_semihosting(CPUState *env)
/* Some C libraries assume the heap immediately follows .bss, so
allocate it using sbrk. */
if (!ts->heap_limit) {
- long ret;
+ abi_ulong ret;
ts->heap_base = do_brk(0);
limit = ts->heap_base + ARM_ANGEL_HEAP_SIZE;
/* Try a big heap, and reduce the size if that fails. */
for (;;) {
ret = do_brk(limit);
- if (ret != -1)
+ if (ret >= limit) {
break;
+ }
limit = (ts->heap_base >> 1) + (limit >> 1);
}
ts->heap_limit = limit;
diff --git a/audio/coreaudio.c b/audio/coreaudio.c
index 3bd75cdda4..5964c62eaf 100644
--- a/audio/coreaudio.c
+++ b/audio/coreaudio.c
@@ -104,7 +104,7 @@ static void coreaudio_logstatus (OSStatus status)
break;
default:
- AUD_log (AUDIO_CAP, "Reason: status code %ld\n", status);
+ AUD_log (AUDIO_CAP, "Reason: status code %" PRId32 "\n", (int32_t)status);
return;
}
@@ -360,8 +360,8 @@ static int coreaudio_init_out (HWVoiceOut *hw, struct audsettings *as)
&core->audioDevicePropertyBufferFrameSize);
if (status != kAudioHardwareNoError) {
coreaudio_logerr2 (status, typ,
- "Could not set device buffer frame size %ld\n",
- core->audioDevicePropertyBufferFrameSize);
+ "Could not set device buffer frame size %" PRIu32 "\n",
+ (uint32_t)core->audioDevicePropertyBufferFrameSize);
return -1;
}
diff --git a/block-migration.c b/block-migration.c
index 8d06a23649..0936c7d5ea 100644
--- a/block-migration.c
+++ b/block-migration.c
@@ -671,7 +671,7 @@ static int block_load(QEMUFile *f, void *opaque, int version_id)
bs_prev = bs;
total_sectors = bdrv_getlength(bs) >> BDRV_SECTOR_BITS;
if (total_sectors <= 0) {
- error_report("Error getting length of block device %s\n",
+ error_report("Error getting length of block device %s",
device_name);
return -EINVAL;
}
diff --git a/block/qcow2.c b/block/qcow2.c
index 2c51e7ccbd..48e1b95689 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -936,7 +936,7 @@ static int qcow2_create2(const char *filename, int64_t total_size,
(1 << cluster_bits) != cluster_size)
{
error_report(
- "Cluster size must be a power of two between %d and %dk\n",
+ "Cluster size must be a power of two between %d and %dk",
1 << MIN_CLUSTER_BITS, 1 << (MAX_CLUSTER_BITS - 10));
return -EINVAL;
}
diff --git a/block/sheepdog.c b/block/sheepdog.c
index 0392ca8c9c..80d106c2b2 100644
--- a/block/sheepdog.c
+++ b/block/sheepdog.c
@@ -444,18 +444,12 @@ static SheepdogAIOCB *sd_aio_setup(BlockDriverState *bs, QEMUIOVector *qiov,
static int sd_schedule_bh(QEMUBHFunc *cb, SheepdogAIOCB *acb)
{
if (acb->bh) {
- error_report("bug: %d %d\n", acb->aiocb_type, acb->aiocb_type);
+ error_report("bug: %d %d", acb->aiocb_type, acb->aiocb_type);
return -EIO;
}
acb->bh = qemu_bh_new(cb, acb);
- if (!acb->bh) {
- error_report("oom: %d %d\n", acb->aiocb_type, acb->aiocb_type);
- return -EIO;
- }
-
qemu_bh_schedule(acb->bh);
-
return 0;
}
@@ -598,7 +592,7 @@ static int connect_to_sdog(const char *addr, const char *port)
ret = getaddrinfo(addr, port, &hints, &res0);
if (ret) {
- error_report("unable to get address info %s, %s\n",
+ error_report("unable to get address info %s, %s",
addr, strerror(errno));
return -1;
}
@@ -628,7 +622,7 @@ static int connect_to_sdog(const char *addr, const char *port)
goto success;
}
fd = -1;
- error_report("failed connect to %s:%s\n", addr, port);
+ error_report("failed connect to %s:%s", addr, port);
success:
freeaddrinfo(res0);
return fd;
@@ -644,7 +638,7 @@ again:
if (errno == EINTR || errno == EAGAIN) {
goto again;
}
- error_report("failed to recv a rsp, %s\n", strerror(errno));
+ error_report("failed to recv a rsp, %s", strerror(errno));
return 1;
}
@@ -703,7 +697,7 @@ static int send_req(int sockfd, SheepdogReq *hdr, void *data,
ret = do_writev(sockfd, iov, sizeof(*hdr) + *wlen, 0);
if (ret) {
- error_report("failed to send a req, %s\n", strerror(errno));
+ error_report("failed to send a req, %s", strerror(errno));
ret = -1;
}
@@ -723,7 +717,7 @@ static int do_req(int sockfd, SheepdogReq *hdr, void *data,
ret = do_read(sockfd, hdr, sizeof(*hdr));
if (ret) {
- error_report("failed to get a rsp, %s\n", strerror(errno));
+ error_report("failed to get a rsp, %s", strerror(errno));
ret = -1;
goto out;
}
@@ -735,7 +729,7 @@ static int do_req(int sockfd, SheepdogReq *hdr, void *data,
if (*rlen) {
ret = do_read(sockfd, data, *rlen);
if (ret) {
- error_report("failed to get the data, %s\n", strerror(errno));
+ error_report("failed to get the data, %s", strerror(errno));
ret = -1;
goto out;
}
@@ -772,7 +766,7 @@ static void send_pending_req(BDRVSheepdogState *s, uint64_t oid, uint32_t id)
ret = add_aio_request(s, aio_req, acb->qiov->iov,
acb->qiov->niov, 0, acb->aiocb_type);
if (ret < 0) {
- error_report("add_aio_request is failed\n");
+ error_report("add_aio_request is failed");
free_aio_req(s, aio_req);
if (QLIST_EMPTY(&acb->aioreq_head)) {
sd_finish_aiocb(acb);
@@ -805,7 +799,7 @@ static void aio_read_response(void *opaque)
/* read a header */
ret = do_read(fd, &rsp, sizeof(rsp));
if (ret) {
- error_report("failed to get the header, %s\n", strerror(errno));
+ error_report("failed to get the header, %s", strerror(errno));
return;
}
@@ -816,7 +810,7 @@ static void aio_read_response(void *opaque)
}
}
if (!aio_req) {
- error_report("cannot find aio_req %x\n", rsp.id);
+ error_report("cannot find aio_req %x", rsp.id);
return;
}
@@ -852,7 +846,7 @@ static void aio_read_response(void *opaque)
ret = do_readv(fd, acb->qiov->iov, rsp.data_length,
aio_req->iov_offset);
if (ret) {
- error_report("failed to get the data, %s\n", strerror(errno));
+ error_report("failed to get the data, %s", strerror(errno));
return;
}
break;
@@ -860,7 +854,7 @@ static void aio_read_response(void *opaque)
if (rsp.result != SD_RES_SUCCESS) {
acb->ret = -EIO;
- error_report("%s\n", sd_strerror(rsp.result));
+ error_report("%s", sd_strerror(rsp.result));
}
rest = free_aio_req(s, aio_req);
@@ -917,7 +911,7 @@ static int get_sheep_fd(BDRVSheepdogState *s)
fd = connect_to_sdog(s->addr, s->port);
if (fd < 0) {
- error_report("%s\n", strerror(errno));
+ error_report("%s", strerror(errno));
return -1;
}
@@ -925,7 +919,7 @@ static int get_sheep_fd(BDRVSheepdogState *s)
ret = set_nodelay(fd);
if (ret) {
- error_report("%s\n", strerror(errno));
+ error_report("%s", strerror(errno));
closesocket(fd);
return -1;
}
@@ -1041,7 +1035,7 @@ static int find_vdi_name(BDRVSheepdogState *s, char *filename, uint32_t snapid,
}
if (rsp->result != SD_RES_SUCCESS) {
- error_report("cannot get vdi info, %s, %s %d %s\n",
+ error_report("cannot get vdi info, %s, %s %d %s",
sd_strerror(rsp->result), filename, snapid, tag);
ret = -1;
goto out;
@@ -1069,7 +1063,7 @@ static int add_aio_request(BDRVSheepdogState *s, AIOReq *aio_req,
uint64_t old_oid = aio_req->base_oid;
if (!nr_copies) {
- error_report("bug\n");
+ error_report("bug");
}
memset(&hdr, 0, sizeof(hdr));
@@ -1102,14 +1096,14 @@ static int add_aio_request(BDRVSheepdogState *s, AIOReq *aio_req,
/* send a header */
ret = do_write(s->fd, &hdr, sizeof(hdr));
if (ret) {
- error_report("failed to send a req, %s\n", strerror(errno));
+ error_report("failed to send a req, %s", strerror(errno));
return -EIO;
}
if (wlen) {
ret = do_writev(s->fd, iov, wlen, aio_req->iov_offset);
if (ret) {
- error_report("failed to send a data, %s\n", strerror(errno));
+ error_report("failed to send a data, %s", strerror(errno));
return -EIO;
}
}
@@ -1151,7 +1145,7 @@ static int read_write_object(int fd, char *buf, uint64_t oid, int copies,
ret = do_req(fd, (SheepdogReq *)&hdr, buf, &wlen, &rlen);
if (ret) {
- error_report("failed to send a request to the sheep\n");
+ error_report("failed to send a request to the sheep");
return -1;
}
@@ -1159,7 +1153,7 @@ static int read_write_object(int fd, char *buf, uint64_t oid, int copies,
case SD_RES_SUCCESS:
return 0;
default:
- error_report("%s\n", sd_strerror(rsp->result));
+ error_report("%s", sd_strerror(rsp->result));
return -1;
}
}
@@ -1212,7 +1206,7 @@ static int sd_open(BlockDriverState *bs, const char *filename, int flags)
fd = connect_to_sdog(s->addr, s->port);
if (fd < 0) {
- error_report("failed to connect\n");
+ error_report("failed to connect");
goto out;
}
@@ -1281,7 +1275,7 @@ static int do_sd_create(char *filename, int64_t vdi_size,
}
if (rsp->result != SD_RES_SUCCESS) {
- error_report("%s, %s\n", sd_strerror(rsp->result), filename);
+ error_report("%s, %s", sd_strerror(rsp->result), filename);
return -EIO;
}
@@ -1308,7 +1302,7 @@ static int sd_create(const char *filename, QEMUOptionParameter *options)
memset(vdi, 0, sizeof(vdi));
memset(tag, 0, sizeof(tag));
if (parse_vdiname(&s, filename, vdi, &snapid, tag) < 0) {
- error_report("invalid filename\n");
+ error_report("invalid filename");
return -EINVAL;
}
@@ -1322,7 +1316,7 @@ static int sd_create(const char *filename, QEMUOptionParameter *options)
}
if (vdi_size > SD_MAX_VDI_SIZE) {
- error_report("too big image size\n");
+ error_report("too big image size");
return -EINVAL;
}
@@ -1334,7 +1328,7 @@ static int sd_create(const char *filename, QEMUOptionParameter *options)
/* Currently, only Sheepdog backing image is supported. */
drv = bdrv_find_protocol(backing_file);
if (!drv || strcmp(drv->protocol_name, "sheepdog") != 0) {
- error_report("backing_file must be a sheepdog image\n");
+ error_report("backing_file must be a sheepdog image");
return -EINVAL;
}
@@ -1345,7 +1339,7 @@ static int sd_create(const char *filename, QEMUOptionParameter *options)
s = bs->opaque;
if (!is_snapshot(&s->inode)) {
- error_report("cannot clone from a non snapshot vdi\n");
+ error_report("cannot clone from a non snapshot vdi");
bdrv_delete(bs);
return -EINVAL;
}
@@ -1385,7 +1379,7 @@ static void sd_close(BlockDriverState *bs)
if (!ret && rsp->result != SD_RES_SUCCESS &&
rsp->result != SD_RES_VDI_NOT_LOCKED) {
- error_report("%s, %s\n", sd_strerror(rsp->result), s->name);
+ error_report("%s, %s", sd_strerror(rsp->result), s->name);
}
qemu_aio_set_fd_handler(s->fd, NULL, NULL, NULL, NULL, NULL);
@@ -1407,10 +1401,10 @@ static int sd_truncate(BlockDriverState *bs, int64_t offset)
unsigned int datalen;
if (offset < s->inode.vdi_size) {
- error_report("shrinking is not supported\n");
+ error_report("shrinking is not supported");
return -EINVAL;
} else if (offset > SD_MAX_VDI_SIZE) {
- error_report("too big image size\n");
+ error_report("too big image size");
return -EINVAL;
}
@@ -1427,7 +1421,7 @@ static int sd_truncate(BlockDriverState *bs, int64_t offset)
close(fd);
if (ret < 0) {
- error_report("failed to update an inode.\n");
+ error_report("failed to update an inode.");
return -EIO;
}
@@ -1500,7 +1494,7 @@ static int sd_create_branch(BDRVSheepdogState *s)
fd = connect_to_sdog(s->addr, s->port);
if (fd < 0) {
- error_report("failed to connect\n");
+ error_report("failed to connect");
goto out;
}
@@ -1618,7 +1612,7 @@ static void sd_readv_writev_bh_cb(void *p)
ret = add_aio_request(s, aio_req, acb->qiov->iov, acb->qiov->niov,
create, acb->aiocb_type);
if (ret < 0) {
- error_report("add_aio_request is failed\n");
+ error_report("add_aio_request is failed");
free_aio_req(s, aio_req);
acb->ret = -EIO;
goto out;
@@ -1695,7 +1689,7 @@ static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
if (s->is_snapshot) {
error_report("You can't create a snapshot of a snapshot VDI, "
- "%s (%" PRIu32 ").\n", s->name, s->inode.vdi_id);
+ "%s (%" PRIu32 ").", s->name, s->inode.vdi_id);
return -EINVAL;
}
@@ -1718,7 +1712,7 @@ static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
ret = write_object(fd, (char *)&s->inode, vid_to_vdi_oid(s->inode.vdi_id),
s->inode.nr_copies, datalen, 0, 0);
if (ret < 0) {
- error_report("failed to write snapshot's inode.\n");
+ error_report("failed to write snapshot's inode.");
ret = -EIO;
goto cleanup;
}
@@ -1726,7 +1720,7 @@ static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
ret = do_sd_create(s->name, s->inode.vdi_size, s->inode.vdi_id, &new_vid, 1,
s->addr, s->port);
if (ret < 0) {
- error_report("failed to create inode for snapshot. %s\n",
+ error_report("failed to create inode for snapshot. %s",
strerror(errno));
ret = -EIO;
goto cleanup;
@@ -1738,7 +1732,7 @@ static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
s->inode.nr_copies, datalen, 0);
if (ret < 0) {
- error_report("failed to read new inode info. %s\n", strerror(errno));
+ error_report("failed to read new inode info. %s", strerror(errno));
ret = -EIO;
goto cleanup;
}
@@ -1777,14 +1771,14 @@ static int sd_snapshot_goto(BlockDriverState *bs, const char *snapshot_id)
ret = find_vdi_name(s, vdi, snapid, tag, &vid, 1);
if (ret) {
- error_report("Failed to find_vdi_name\n");
+ error_report("Failed to find_vdi_name");
ret = -ENOENT;
goto out;
}
fd = connect_to_sdog(s->addr, s->port);
if (fd < 0) {
- error_report("failed to connect\n");
+ error_report("failed to connect");
goto out;
}
@@ -1802,7 +1796,7 @@ static int sd_snapshot_goto(BlockDriverState *bs, const char *snapshot_id)
memcpy(&s->inode, buf, sizeof(s->inode));
if (!s->inode.vm_state_size) {
- error_report("Invalid snapshot\n");
+ error_report("Invalid snapshot");
ret = -ENOENT;
goto out;
}
@@ -1819,7 +1813,7 @@ out:
qemu_free(buf);
qemu_free(old_s);
- error_report("failed to open. recover old bdrv_sd_state.\n");
+ error_report("failed to open. recover old bdrv_sd_state.");
return ret;
}
@@ -1874,7 +1868,7 @@ static int sd_snapshot_list(BlockDriverState *bs, QEMUSnapshotInfo **psn_tab)
fd = connect_to_sdog(s->addr, s->port);
if (fd < 0) {
- error_report("failed to connect\n");
+ error_report("failed to connect");
goto out;
}
@@ -1948,7 +1942,7 @@ static int do_load_save_vmstate(BDRVSheepdogState *s, uint8_t *data,
}
if (ret < 0) {
- error_report("failed to save vmstate %s\n", strerror(errno));
+ error_report("failed to save vmstate %s", strerror(errno));
ret = -EIO;
goto cleanup;
}
diff --git a/blockdev.c b/blockdev.c
index 1502575acb..7d579d6124 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -293,7 +293,7 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi)
if ((buf = qemu_opt_get(opts, "trans")) != NULL) {
if (!cyls) {
- error_report("'%s' trans must be used with cyls,heads and secs",
+ error_report("'%s' trans must be used with cyls, heads and secs",
buf);
return NULL;
}
diff --git a/bsd-user/main.c b/bsd-user/main.c
index 0af8a7e7f1..6018a419ed 100644
--- a/bsd-user/main.c
+++ b/bsd-user/main.c
@@ -29,7 +29,7 @@
#include "qemu.h"
#include "qemu-common.h"
/* For tb_lock */
-#include "exec-all.h"
+#include "cpu.h"
#include "tcg.h"
#include "qemu-timer.h"
#include "envlist.h"
@@ -866,7 +866,7 @@ int main(int argc, char **argv)
int mask;
const CPULogItem *item;
- mask = cpu_str_to_log_mask(r);
+ mask = cpu_str_to_log_mask(log_mask);
if (!mask) {
printf("Log items (comma separated):\n");
for (item = cpu_log_items; item->mask != 0; item++) {
diff --git a/cmd.c b/cmd.c
index db2c9c4c5e..ecca167399 100644
--- a/cmd.c
+++ b/cmd.c
@@ -486,7 +486,7 @@ timestr(
snprintf(ts, size, "%u:%02u.%02u",
(unsigned int) MINUTES(tv->tv_sec),
(unsigned int) SECONDS(tv->tv_sec),
- (unsigned int) usec * 100);
+ (unsigned int) (usec * 100));
return;
}
format |= VERBOSE_FIXED_TIME; /* fallback if hours needed */
@@ -497,9 +497,9 @@ timestr(
(unsigned int) HOURS(tv->tv_sec),
(unsigned int) MINUTES(tv->tv_sec),
(unsigned int) SECONDS(tv->tv_sec),
- (unsigned int) usec * 100);
+ (unsigned int) (usec * 100));
} else {
- snprintf(ts, size, "0.%04u sec", (unsigned int) usec * 10000);
+ snprintf(ts, size, "0.%04u sec", (unsigned int) (usec * 10000));
}
}
diff --git a/configure b/configure
index 44c092a292..88159acde2 100755
--- a/configure
+++ b/configure
@@ -114,7 +114,6 @@ curses=""
docs=""
fdt=""
kvm=""
-kvm_para=""
nptl=""
sdl=""
vnc="yes"
@@ -166,7 +165,6 @@ guest_base=""
uname_release=""
io_thread="no"
mixemu="no"
-kerneldir=""
aix="no"
blobs="yes"
pkgversion=""
@@ -459,6 +457,8 @@ Haiku)
linux="yes"
linux_user="yes"
usb="linux"
+ kvm="yes"
+ vhost_net="yes"
if [ "$cpu" = "i386" -o "$cpu" = "x86_64" ] ; then
audio_possible_drivers="$audio_possible_drivers fmod"
fi
@@ -715,8 +715,6 @@ for opt do
;;
--disable-blobs) blobs="no"
;;
- --kerneldir=*) kerneldir="$optarg"
- ;;
--with-pkgversion=*) pkgversion=" ($optarg)"
;;
--disable-docs) docs="no"
@@ -1005,7 +1003,6 @@ echo " --disable-attr disables attr and xattr support"
echo " --enable-attr enable attr and xattr support"
echo " --enable-io-thread enable IO thread"
echo " --disable-blobs disable installing provided firmware blobs"
-echo " --kerneldir=PATH look for kernel includes in PATH"
echo " --enable-docs enable documentation build"
echo " --disable-docs disable documentation build"
echo " --disable-vhost-net disable vhost-net acceleration support"
@@ -1210,6 +1207,7 @@ int main(void) {
xc = xc_interface_open(0, 0, 0);
xc_hvm_set_mem_type(0, 0, HVMMEM_ram_ro, 0, 0);
xc_gnttab_open(NULL, 0);
+ xc_domain_add_to_physmap(0, 0, XENMAPSPACE_gmfn, 0, 0);
return 0;
}
EOF
@@ -1228,10 +1226,14 @@ EOF
# error HVM_MAX_VCPUS not defined
#endif
int main(void) {
+ struct xen_add_to_physmap xatp = {
+ .domid = 0, .space = XENMAPSPACE_gmfn, .idx = 0, .gpfn = 0,
+ };
xs_daemon_open();
xc_interface_open();
xc_gnttab_open();
xc_hvm_set_mem_type(0, 0, HVMMEM_ram_ro, 0, 0);
+ xc_memory_op(0, XENMEM_add_to_physmap, &xatp);
return 0;
}
EOF
@@ -1240,7 +1242,29 @@ EOF
xen_ctrl_version=400
xen=yes
- # Xen 3.3.0, 3.4.0
+ # Xen 3.4.0
+ elif (
+ cat > $TMPC <<EOF
+#include <xenctrl.h>
+#include <xs.h>
+int main(void) {
+ struct xen_add_to_physmap xatp = {
+ .domid = 0, .space = XENMAPSPACE_gmfn, .idx = 0, .gpfn = 0,
+ };
+ xs_daemon_open();
+ xc_interface_open();
+ xc_gnttab_open();
+ xc_hvm_set_mem_type(0, 0, HVMMEM_ram_ro, 0, 0);
+ xc_memory_op(0, XENMEM_add_to_physmap, &xatp);
+ return 0;
+}
+EOF
+ compile_prog "" "$xen_libs"
+ ) ; then
+ xen_ctrl_version=340
+ xen=yes
+
+ # Xen 3.3.0
elif (
cat > $TMPC <<EOF
#include <xenctrl.h>
@@ -1616,7 +1640,7 @@ for drv in $audio_drv_list; do
pa)
audio_drv_probe $drv pulse/simple.h "-lpulse-simple -lpulse" \
- "pa_simple *s = NULL; pa_simple_free(s); return 0;"
+ "pa_simple *s = 0; pa_simple_free(s); return 0;"
libs_softmmu="-lpulse -lpulse-simple $libs_softmmu"
audio_pt_int="yes"
;;
@@ -1779,124 +1803,6 @@ EOF
fi
##########################################
-# kvm probe
-if test "$kvm" != "no" ; then
- cat > $TMPC <<EOF
-#include <linux/kvm.h>
-#if !defined(KVM_API_VERSION) || KVM_API_VERSION < 12 || KVM_API_VERSION > 12
-#error Invalid KVM version
-#endif
-EOF
- must_have_caps="KVM_CAP_USER_MEMORY \
- KVM_CAP_DESTROY_MEMORY_REGION_WORKS \
- KVM_CAP_COALESCED_MMIO \
- KVM_CAP_SYNC_MMU \
- "
- if test \( "$cpu" = "i386" -o "$cpu" = "x86_64" \) ; then
- must_have_caps="$caps \
- KVM_CAP_SET_TSS_ADDR \
- KVM_CAP_EXT_CPUID \
- KVM_CAP_CLOCKSOURCE \
- KVM_CAP_NOP_IO_DELAY \
- KVM_CAP_PV_MMU \
- KVM_CAP_MP_STATE \
- KVM_CAP_USER_NMI \
- "
- fi
- for c in $must_have_caps ; do
- cat >> $TMPC <<EOF
-#if !defined($c)
-#error Missing KVM capability $c
-#endif
-EOF
- done
- cat >> $TMPC <<EOF
-int main(void) { return 0; }
-EOF
- if test "$kerneldir" != "" ; then
- kvm_cflags=-I"$kerneldir"/include
- if test \( "$cpu" = "i386" -o "$cpu" = "x86_64" \) \
- -a -d "$kerneldir/arch/x86/include" ; then
- kvm_cflags="$kvm_cflags -I$kerneldir/arch/x86/include"
- elif test "$cpu" = "ppc" -a -d "$kerneldir/arch/powerpc/include" ; then
- kvm_cflags="$kvm_cflags -I$kerneldir/arch/powerpc/include"
- elif test "$cpu" = "s390x" -a -d "$kerneldir/arch/s390/include" ; then
- kvm_cflags="$kvm_cflags -I$kerneldir/arch/s390/include"
- elif test -d "$kerneldir/arch/$cpu/include" ; then
- kvm_cflags="$kvm_cflags -I$kerneldir/arch/$cpu/include"
- fi
- else
- kvm_cflags=`$pkg_config --cflags kvm-kmod 2>/dev/null`
- fi
- if compile_prog "$kvm_cflags" "" ; then
- kvm=yes
- cat > $TMPC <<EOF
-#include <linux/kvm_para.h>
-int main(void) { return 0; }
-EOF
- if compile_prog "$kvm_cflags" "" ; then
- kvm_para=yes
- fi
- else
- if test "$kvm" = "yes" ; then
- if has awk && has grep; then
- kvmerr=`LANG=C $cc $QEMU_CFLAGS -o $TMPE $kvm_cflags $TMPC 2>&1 \
- | grep "error: " \
- | awk -F "error: " '{if (NR>1) printf(", "); printf("%s",$2);}'`
- if test "$kvmerr" != "" ; then
- echo -e "${kvmerr}\n\
-NOTE: To enable KVM support, update your kernel to 2.6.29+ or install \
-recent kvm-kmod from http://sourceforge.net/projects/kvm."
- fi
- fi
- feature_not_found "kvm"
- fi
- kvm=no
- fi
-fi
-
-##########################################
-# test for ppc kvm pvr setting
-
-if test "$kvm" = "yes" && test "$cpu" = "ppc" -o "$cpu" = "ppc64"; then
- cat > $TMPC <<EOF
- #include <asm/kvm.h>
- int main(void) { struct kvm_sregs s; s.pvr = 0; return 0; }
-EOF
- if compile_prog "$kvm_cflags" "" ; then
- kvm_ppc_pvr=yes
- else
- kvm_ppc_pvr=no
- fi
-fi
-
-##########################################
-# test for vhost net
-
-if test "$vhost_net" != "no"; then
- if test "$kvm" != "no"; then
- cat > $TMPC <<EOF
- #include <linux/vhost.h>
- int main(void) { return 0; }
-EOF
- if compile_prog "$kvm_cflags" "" ; then
- vhost_net=yes
- else
- if test "$vhost_net" = "yes" ; then
- feature_not_found "vhost-net"
- fi
- vhost_net=no
- fi
- else
- if test "$vhost_net" = "yes" ; then
- echo "NOTE: vhost-net feature requires KVM (--enable-kvm)."
- feature_not_found "vhost-net"
- fi
- vhost_net=no
- fi
-fi
-
-##########################################
# pthread probe
PTHREADLIBS_LIST="-lpthread -lpthreadGC2"
@@ -3346,16 +3252,9 @@ case "$target_arch2" in
\( "$target_arch2" = "x86_64" -a "$cpu" = "i386" \) -o \
\( "$target_arch2" = "i386" -a "$cpu" = "x86_64" \) \) ; then
echo "CONFIG_KVM=y" >> $config_target_mak
- echo "KVM_CFLAGS=$kvm_cflags" >> $config_target_mak
- if test "$kvm_para" = "yes"; then
- echo "CONFIG_KVM_PARA=y" >> $config_target_mak
- fi
if test $vhost_net = "yes" ; then
echo "CONFIG_VHOST_NET=y" >> $config_target_mak
fi
- if test "$kvm_ppc_pvr" = "yes" ; then
- echo "CONFIG_KVM_PPC_PVR=y" >> $config_target_mak
- fi
fi
esac
if test "$target_bigendian" = "yes" ; then
@@ -3546,6 +3445,23 @@ if test "$target_linux_user" = "yes" -o "$target_bsd_user" = "yes" ; then
esac
fi
+# use included Linux headers
+if test "$linux" = "yes" ; then
+ includes="-I\$(SRC_PATH)/linux-headers $includes"
+ mkdir -p linux-headers
+ case "$cpu" in
+ i386|x86_64)
+ symlink $source_path/linux-headers/asm-x86 linux-headers/asm
+ ;;
+ ppcemb|ppc|ppc64)
+ symlink $source_path/linux-headers/asm-powerpc linux-headers/asm
+ ;;
+ s390x)
+ symlink $source_path/linux-headers/asm-s390 linux-headers/asm
+ ;;
+ esac
+fi
+
echo "LDFLAGS+=$ldflags" >> $config_target_mak
echo "QEMU_CFLAGS+=$cflags" >> $config_target_mak
echo "QEMU_INCLUDES+=$includes" >> $config_target_mak
@@ -3567,7 +3483,9 @@ for bios_file in $source_path/pc-bios/*.bin $source_path/pc-bios/*.rom $source_p
done
mkdir -p $DIRS
for f in $FILES ; do
- test -e $f || symlink $source_path/$f $f
+ if [ -e "$source_path/$f" ] && ! [ -e "$f" ]; then
+ symlink "$source_path/$f" "$f"
+ fi
done
# temporary config to build submodules
diff --git a/console.c b/console.c
index 9c6addf8e4..acd8ca162c 100644
--- a/console.c
+++ b/console.c
@@ -1349,8 +1349,15 @@ static struct DisplayAllocator default_allocator = {
static void dumb_display_init(void)
{
DisplayState *ds = qemu_mallocz(sizeof(DisplayState));
+ int width = 640;
+ int height = 480;
+
ds->allocator = &default_allocator;
- ds->surface = qemu_create_displaysurface(ds, 640, 480);
+ if (is_fixedsize_console()) {
+ width = active_console->g_width;
+ height = active_console->g_height;
+ }
+ ds->surface = qemu_create_displaysurface(ds, width, height);
register_displaystate(ds);
}
diff --git a/cpu-all.h b/cpu-all.h
index 880f570d56..e8391009a3 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -847,7 +847,7 @@ void cpu_reset_interrupt(CPUState *env, int mask);
void cpu_exit(CPUState *s);
-int qemu_cpu_has_work(CPUState *env);
+bool qemu_cpu_has_work(CPUState *env);
/* Breakpoint/watchpoint flags */
#define BP_MEM_READ 0x01
diff --git a/cpu-common.h b/cpu-common.h
index 9f5917224a..b027e43088 100644
--- a/cpu-common.h
+++ b/cpu-common.h
@@ -65,6 +65,7 @@ void qemu_ram_free_from_ptr(ram_addr_t addr);
void qemu_ram_remap(ram_addr_t addr, ram_addr_t length);
/* This should only be used for ram local to a device. */
void *qemu_get_ram_ptr(ram_addr_t addr);
+void *qemu_ram_ptr_length(target_phys_addr_t addr, target_phys_addr_t *size);
/* Same but slower, to use for migration, where the order of
* RAMBlocks must not change. */
void *qemu_safe_ram_ptr(ram_addr_t addr);
diff --git a/cpu-exec.c b/cpu-exec.c
index e1de56b397..20e3ec41d7 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -17,28 +17,21 @@
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
-#include "exec.h"
+#include "cpu.h"
#include "disas.h"
#include "tcg.h"
-#include "kvm.h"
#include "qemu-barrier.h"
-#if defined(__sparc__) && !defined(CONFIG_SOLARIS)
-// Work around ugly bugs in glibc that mangle global register contents
-#undef env
-#define env cpu_single_env
-#endif
-
int tb_invalidated_flag;
//#define CONFIG_DEBUG_EXEC
-int qemu_cpu_has_work(CPUState *env)
+bool qemu_cpu_has_work(CPUState *env)
{
return cpu_has_work(env);
}
-void cpu_loop_exit(void)
+void cpu_loop_exit(CPUState *env)
{
env->current_tb = NULL;
longjmp(env->jmp_env, 1);
@@ -48,10 +41,8 @@ void cpu_loop_exit(void)
restored in a state compatible with the CPU emulator
*/
#if defined(CONFIG_SOFTMMU)
-void cpu_resume_from_signal(CPUState *env1, void *puc)
+void cpu_resume_from_signal(CPUState *env, void *puc)
{
- env = env1;
-
/* XXX: restore cpu registers saved in host registers */
env->exception_index = -1;
@@ -61,7 +52,8 @@ void cpu_resume_from_signal(CPUState *env1, void *puc)
/* Execute the code without caching the generated code. An interpreter
could be used if available. */
-static void cpu_exec_nocache(int max_cycles, TranslationBlock *orig_tb)
+static void cpu_exec_nocache(CPUState *env, int max_cycles,
+ TranslationBlock *orig_tb)
{
unsigned long next_tb;
TranslationBlock *tb;
@@ -75,7 +67,7 @@ static void cpu_exec_nocache(int max_cycles, TranslationBlock *orig_tb)
max_cycles);
env->current_tb = tb;
/* execute the generated code */
- next_tb = tcg_qemu_tb_exec(tb->tc_ptr);
+ next_tb = tcg_qemu_tb_exec(env, tb->tc_ptr);
env->current_tb = NULL;
if ((next_tb & 3) == 2) {
@@ -87,7 +79,8 @@ static void cpu_exec_nocache(int max_cycles, TranslationBlock *orig_tb)
tb_free(tb);
}
-static TranslationBlock *tb_find_slow(target_ulong pc,
+static TranslationBlock *tb_find_slow(CPUState *env,
+ target_ulong pc,
target_ulong cs_base,
uint64_t flags)
{
@@ -141,7 +134,7 @@ static TranslationBlock *tb_find_slow(target_ulong pc,
return tb;
}
-static inline TranslationBlock *tb_find_fast(void)
+static inline TranslationBlock *tb_find_fast(CPUState *env)
{
TranslationBlock *tb;
target_ulong cs_base, pc;
@@ -154,7 +147,7 @@ static inline TranslationBlock *tb_find_fast(void)
tb = env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)];
if (unlikely(!tb || tb->pc != pc || tb->cs_base != cs_base ||
tb->flags != flags)) {
- tb = tb_find_slow(pc, cs_base, flags);
+ tb = tb_find_slow(env, pc, cs_base, flags);
}
return tb;
}
@@ -187,31 +180,22 @@ static void cpu_handle_debug_exception(CPUState *env)
volatile sig_atomic_t exit_request;
-int cpu_exec(CPUState *env1)
+int cpu_exec(CPUState *env)
{
- volatile host_reg_t saved_env_reg;
int ret, interrupt_request;
TranslationBlock *tb;
uint8_t *tc_ptr;
unsigned long next_tb;
- if (env1->halted) {
- if (!cpu_has_work(env1)) {
+ if (env->halted) {
+ if (!cpu_has_work(env)) {
return EXCP_HALTED;
}
- env1->halted = 0;
+ env->halted = 0;
}
- cpu_single_env = env1;
-
- /* the access to env below is actually saving the global register's
- value, so that files not including target-xyz/exec.h are free to
- use it. */
- QEMU_BUILD_BUG_ON (sizeof (saved_env_reg) != sizeof (env));
- saved_env_reg = (host_reg_t) env;
- barrier();
- env = env1;
+ cpu_single_env = env;
if (unlikely(exit_request)) {
env->exit_request = 1;
@@ -247,11 +231,6 @@ int cpu_exec(CPUState *env1)
/* prepare setjmp context for exception handling */
for(;;) {
if (setjmp(env->jmp_env) == 0) {
-#if defined(__sparc__) && !defined(CONFIG_SOLARIS)
-#undef env
- env = cpu_single_env;
-#define env cpu_single_env
-#endif
/* if an exception is pending, we execute it here */
if (env->exception_index >= 0) {
if (env->exception_index >= EXCP_INTERRUPT) {
@@ -267,51 +246,12 @@ int cpu_exec(CPUState *env1)
which will be handled outside the cpu execution
loop */
#if defined(TARGET_I386)
- do_interrupt_user(env->exception_index,
- env->exception_is_int,
- env->error_code,
- env->exception_next_eip);
- /* successfully delivered */
- env->old_exception = -1;
+ do_interrupt(env);
#endif
ret = env->exception_index;
break;
#else
-#if defined(TARGET_I386)
- /* simulate a real cpu exception. On i386, it can
- trigger new exceptions, but we do not handle
- double or triple faults yet. */
- do_interrupt(env->exception_index,
- env->exception_is_int,
- env->error_code,
- env->exception_next_eip, 0);
- /* successfully delivered */
- env->old_exception = -1;
-#elif defined(TARGET_PPC)
- do_interrupt(env);
-#elif defined(TARGET_LM32)
- do_interrupt(env);
-#elif defined(TARGET_MICROBLAZE)
- do_interrupt(env);
-#elif defined(TARGET_MIPS)
- do_interrupt(env);
-#elif defined(TARGET_SPARC)
do_interrupt(env);
-#elif defined(TARGET_ARM)
- do_interrupt(env);
-#elif defined(TARGET_UNICORE32)
- do_interrupt(env);
-#elif defined(TARGET_SH4)
- do_interrupt(env);
-#elif defined(TARGET_ALPHA)
- do_interrupt(env);
-#elif defined(TARGET_CRIS)
- do_interrupt(env);
-#elif defined(TARGET_M68K)
- do_interrupt(0);
-#elif defined(TARGET_S390X)
- do_interrupt(env);
-#endif
env->exception_index = -1;
#endif
}
@@ -328,7 +268,7 @@ int cpu_exec(CPUState *env1)
if (interrupt_request & CPU_INTERRUPT_DEBUG) {
env->interrupt_request &= ~CPU_INTERRUPT_DEBUG;
env->exception_index = EXCP_DEBUG;
- cpu_loop_exit();
+ cpu_loop_exit(env);
}
#if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_MIPS) || \
defined(TARGET_PPC) || defined(TARGET_ALPHA) || defined(TARGET_CRIS) || \
@@ -337,33 +277,33 @@ int cpu_exec(CPUState *env1)
env->interrupt_request &= ~CPU_INTERRUPT_HALT;
env->halted = 1;
env->exception_index = EXCP_HLT;
- cpu_loop_exit();
+ cpu_loop_exit(env);
}
#endif
#if defined(TARGET_I386)
if (interrupt_request & CPU_INTERRUPT_INIT) {
- svm_check_intercept(SVM_EXIT_INIT);
+ svm_check_intercept(env, SVM_EXIT_INIT);
do_cpu_init(env);
env->exception_index = EXCP_HALTED;
- cpu_loop_exit();
+ cpu_loop_exit(env);
} else if (interrupt_request & CPU_INTERRUPT_SIPI) {
do_cpu_sipi(env);
} else if (env->hflags2 & HF2_GIF_MASK) {
if ((interrupt_request & CPU_INTERRUPT_SMI) &&
!(env->hflags & HF_SMM_MASK)) {
- svm_check_intercept(SVM_EXIT_SMI);
+ svm_check_intercept(env, SVM_EXIT_SMI);
env->interrupt_request &= ~CPU_INTERRUPT_SMI;
- do_smm_enter();
+ do_smm_enter(env);
next_tb = 0;
} else if ((interrupt_request & CPU_INTERRUPT_NMI) &&
!(env->hflags2 & HF2_NMI_MASK)) {
env->interrupt_request &= ~CPU_INTERRUPT_NMI;
env->hflags2 |= HF2_NMI_MASK;
- do_interrupt(EXCP02_NMI, 0, 0, 0, 1);
+ do_interrupt_x86_hardirq(env, EXCP02_NMI, 1);
next_tb = 0;
} else if (interrupt_request & CPU_INTERRUPT_MCE) {
env->interrupt_request &= ~CPU_INTERRUPT_MCE;
- do_interrupt(EXCP12_MCHK, 0, 0, 0, 0);
+ do_interrupt_x86_hardirq(env, EXCP12_MCHK, 0);
next_tb = 0;
} else if ((interrupt_request & CPU_INTERRUPT_HARD) &&
(((env->hflags2 & HF2_VINTR_MASK) &&
@@ -372,16 +312,11 @@ int cpu_exec(CPUState *env1)
(env->eflags & IF_MASK &&
!(env->hflags & HF_INHIBIT_IRQ_MASK))))) {
int intno;
- svm_check_intercept(SVM_EXIT_INTR);
+ svm_check_intercept(env, SVM_EXIT_INTR);
env->interrupt_request &= ~(CPU_INTERRUPT_HARD | CPU_INTERRUPT_VIRQ);
intno = cpu_get_pic_interrupt(env);
qemu_log_mask(CPU_LOG_TB_IN_ASM, "Servicing hardware INT=0x%02x\n", intno);
-#if defined(__sparc__) && !defined(CONFIG_SOLARIS)
-#undef env
- env = cpu_single_env;
-#define env cpu_single_env
-#endif
- do_interrupt(intno, 0, 0, 0, 1);
+ do_interrupt_x86_hardirq(env, intno, 1);
/* ensure that no TB jump will be modified as
the program flow was changed */
next_tb = 0;
@@ -391,10 +326,10 @@ int cpu_exec(CPUState *env1)
!(env->hflags & HF_INHIBIT_IRQ_MASK)) {
int intno;
/* FIXME: this should respect TPR */
- svm_check_intercept(SVM_EXIT_VINTR);
+ svm_check_intercept(env, SVM_EXIT_VINTR);
intno = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_vector));
qemu_log_mask(CPU_LOG_TB_IN_ASM, "Servicing virtual hardware INT=0x%02x\n", intno);
- do_interrupt(intno, 0, 0, 0, 1);
+ do_interrupt_x86_hardirq(env, intno, 1);
env->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
next_tb = 0;
#endif
@@ -543,7 +478,7 @@ int cpu_exec(CPUState *env1)
provide/save the vector when the interrupt is
first signalled. */
env->exception_index = env->pending_vector;
- do_interrupt(1);
+ do_interrupt_m68k_hardirq(env);
next_tb = 0;
}
#elif defined(TARGET_S390X) && !defined(CONFIG_USER_ONLY)
@@ -565,13 +500,14 @@ int cpu_exec(CPUState *env1)
if (unlikely(env->exit_request)) {
env->exit_request = 0;
env->exception_index = EXCP_INTERRUPT;
- cpu_loop_exit();
+ cpu_loop_exit(env);
}
#if defined(DEBUG_DISAS) || defined(CONFIG_DEBUG_EXEC)
if (qemu_loglevel_mask(CPU_LOG_TB_CPU)) {
/* restore flags in standard format */
#if defined(TARGET_I386)
- env->eflags = env->eflags | helper_cc_compute_all(CC_OP) | (DF & DF_MASK);
+ env->eflags = env->eflags | cpu_cc_compute_all(env, CC_OP)
+ | (DF & DF_MASK);
log_cpu_state(env, X86_DUMP_CCOP);
env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
#elif defined(TARGET_M68K)
@@ -586,7 +522,7 @@ int cpu_exec(CPUState *env1)
}
#endif /* DEBUG_DISAS || CONFIG_DEBUG_EXEC */
spin_lock(&tb_lock);
- tb = tb_find_fast();
+ tb = tb_find_fast(env);
/* Note: we do it here to avoid a gcc bug on Mac OS X when
doing it in tb_find_slow */
if (tb_invalidated_flag) {
@@ -618,12 +554,7 @@ int cpu_exec(CPUState *env1)
if (likely(!env->exit_request)) {
tc_ptr = tb->tc_ptr;
/* execute the generated code */
-#if defined(__sparc__) && !defined(CONFIG_SOLARIS)
-#undef env
- env = cpu_single_env;
-#define env cpu_single_env
-#endif
- next_tb = tcg_qemu_tb_exec(tc_ptr);
+ next_tb = tcg_qemu_tb_exec(env, tc_ptr);
if ((next_tb & 3) == 2) {
/* Instruction counter expired. */
int insns_left;
@@ -644,11 +575,11 @@ int cpu_exec(CPUState *env1)
} else {
if (insns_left > 0) {
/* Execute remaining instructions. */
- cpu_exec_nocache(insns_left, tb);
+ cpu_exec_nocache(env, insns_left, tb);
}
env->exception_index = EXCP_INTERRUPT;
next_tb = 0;
- cpu_loop_exit();
+ cpu_loop_exit(env);
}
}
}
@@ -662,7 +593,8 @@ int cpu_exec(CPUState *env1)
#if defined(TARGET_I386)
/* restore flags in standard format */
- env->eflags = env->eflags | helper_cc_compute_all(CC_OP) | (DF & DF_MASK);
+ env->eflags = env->eflags | cpu_cc_compute_all(env, CC_OP)
+ | (DF & DF_MASK);
#elif defined(TARGET_ARM)
/* XXX: Save/restore host fpu exception state?. */
#elif defined(TARGET_UNICORE32)
@@ -685,10 +617,6 @@ int cpu_exec(CPUState *env1)
#error unsupported target CPU
#endif
- /* restore global registers */
- barrier();
- env = (void *) saved_env_reg;
-
/* fail safe : never use cpu_single_env outside cpu_exec() */
cpu_single_env = NULL;
return ret;
diff --git a/cpus.c b/cpus.c
index 17e96b56e0..abd24ab31c 100644
--- a/cpus.c
+++ b/cpus.c
@@ -30,11 +30,13 @@
#include "gdbstub.h"
#include "dma.h"
#include "kvm.h"
-#include "exec-all.h"
#include "qemu-thread.h"
#include "cpus.h"
+
+#ifndef _WIN32
#include "compatfd.h"
+#endif
#ifdef SIGRTMIN
#define SIG_IPI (SIGRTMIN+4)
@@ -297,7 +299,7 @@ static void qemu_event_increment(void)
/* EAGAIN is fine, a read must be pending. */
if (ret < 0 && errno != EAGAIN) {
- fprintf(stderr, "qemu_event_increment: write() filed: %s\n",
+ fprintf(stderr, "qemu_event_increment: write() failed: %s\n",
strerror(errno));
exit (1);
}
diff --git a/darwin-user/main.c b/darwin-user/main.c
index a6dc859219..35196a12cc 100644
--- a/darwin-user/main.c
+++ b/darwin-user/main.c
@@ -819,7 +819,7 @@ int main(int argc, char **argv)
int mask;
CPULogItem *item;
- mask = cpu_str_to_log_mask(r);
+ mask = cpu_str_to_log_mask(log_mask);
if (!mask) {
printf("Log items (comma separated):\n");
for (item = cpu_log_items; item->mask != 0; item++) {
diff --git a/disas.c b/disas.c
index d208c52402..1334b8e0f3 100644
--- a/disas.c
+++ b/disas.c
@@ -5,7 +5,6 @@
#include <errno.h>
#include "cpu.h"
-#include "exec-all.h"
#include "disas.h"
/* Filled in by elfload.c. Simplistic, but will do for now. */
diff --git a/error.c b/error.c
index 867eec2c1a..74d7398b58 100644
--- a/error.c
+++ b/error.c
@@ -9,11 +9,12 @@
* This work is licensed under the terms of the GNU LGPL, version 2. See
* the COPYING.LIB file in the top-level directory.
*/
+
+#include "qemu-common.h"
#include "error.h"
#include "error_int.h"
#include "qemu-objects.h"
#include "qerror.h"
-#include <assert.h>
struct Error
{
diff --git a/error.h b/error.h
index 003c855e65..0f92a6f570 100644
--- a/error.h
+++ b/error.h
@@ -25,8 +25,7 @@ typedef struct Error Error;
* Currently, qerror.h defines these error formats. This function is not
* meant to be used outside of QEMU.
*/
-void error_set(Error **err, const char *fmt, ...)
- __attribute__((format(printf, 2, 3)));
+void error_set(Error **err, const char *fmt, ...) GCC_FMT_ATTR(2, 3);
/**
* Returns true if an indirect pointer to an error is pointing to a valid
diff --git a/exec-all.h b/exec-all.h
index 2a13a9535e..21a69d68ad 100644
--- a/exec-all.h
+++ b/exec-all.h
@@ -40,6 +40,7 @@ typedef ram_addr_t tb_page_addr_t;
#define DISAS_UPDATE 2 /* cpu state was modified dynamically */
#define DISAS_TB_JUMP 3 /* only pc was modified statically */
+struct TranslationBlock;
typedef struct TranslationBlock TranslationBlock;
/* XXX: make safe guess about sizes */
@@ -95,7 +96,7 @@ TranslationBlock *tb_gen_code(CPUState *env,
target_ulong pc, target_ulong cs_base, int flags,
int cflags);
void cpu_exec_init(CPUState *env);
-void QEMU_NORETURN cpu_loop_exit(void);
+void QEMU_NORETURN cpu_loop_exit(CPUState *env1);
int page_unprotect(target_ulong address, unsigned long pc, void *puc);
void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end,
int is_cpu_write_access);
diff --git a/exec.c b/exec.c
index 09928a3b37..4c45299906 100644
--- a/exec.c
+++ b/exec.c
@@ -26,7 +26,6 @@
#include "qemu-common.h"
#include "cpu.h"
-#include "exec-all.h"
#include "tcg.h"
#include "hw/hw.h"
#include "hw/qdev.h"
@@ -53,6 +52,7 @@
#endif
#else /* !CONFIG_USER_ONLY */
#include "xen-mapcache.h"
+#include "trace.h"
#endif
//#define DEBUG_TB_INVALIDATE
@@ -1207,12 +1207,16 @@ static inline void tb_alloc_page(TranslationBlock *tb,
unsigned int n, tb_page_addr_t page_addr)
{
PageDesc *p;
- TranslationBlock *last_first_tb;
+#ifndef CONFIG_USER_ONLY
+ bool page_already_protected;
+#endif
tb->page_addr[n] = page_addr;
p = page_find_alloc(page_addr >> TARGET_PAGE_BITS, 1);
tb->page_next[n] = p->first_tb;
- last_first_tb = p->first_tb;
+#ifndef CONFIG_USER_ONLY
+ page_already_protected = p->first_tb != NULL;
+#endif
p->first_tb = (TranslationBlock *)((long)tb | n);
invalidate_page_bitmap(p);
@@ -1248,7 +1252,7 @@ static inline void tb_alloc_page(TranslationBlock *tb,
/* if some code is already present, then the pages are already
protected. So we handle the case where only the first TB is
allocated in a physical page */
- if (!last_first_tb) {
+ if (!page_already_protected) {
tlb_protect_code(page_addr);
}
#endif
@@ -1752,14 +1756,21 @@ static int cpu_notify_migration_log(int enable)
return 0;
}
+struct last_map {
+ target_phys_addr_t start_addr;
+ ram_addr_t size;
+ ram_addr_t phys_offset;
+};
+
/* The l1_phys_map provides the upper P_L1_BITs of the guest physical
* address. Each intermediate table provides the next L2_BITs of guest
* physical address space. The number of levels vary based on host and
* guest configuration, making it efficient to build the final guest
* physical address by seeding the L1 offset and shifting and adding in
* each L2 offset as we recurse through them. */
-static void phys_page_for_each_1(CPUPhysMemoryClient *client,
- int level, void **lp, target_phys_addr_t addr)
+static void phys_page_for_each_1(CPUPhysMemoryClient *client, int level,
+ void **lp, target_phys_addr_t addr,
+ struct last_map *map)
{
int i;
@@ -1771,15 +1782,29 @@ static void phys_page_for_each_1(CPUPhysMemoryClient *client,
addr <<= L2_BITS + TARGET_PAGE_BITS;
for (i = 0; i < L2_SIZE; ++i) {
if (pd[i].phys_offset != IO_MEM_UNASSIGNED) {
- client->set_memory(client, addr | i << TARGET_PAGE_BITS,
- TARGET_PAGE_SIZE, pd[i].phys_offset, false);
+ target_phys_addr_t start_addr = addr | i << TARGET_PAGE_BITS;
+
+ if (map->size &&
+ start_addr == map->start_addr + map->size &&
+ pd[i].phys_offset == map->phys_offset + map->size) {
+
+ map->size += TARGET_PAGE_SIZE;
+ continue;
+ } else if (map->size) {
+ client->set_memory(client, map->start_addr,
+ map->size, map->phys_offset, false);
+ }
+
+ map->start_addr = start_addr;
+ map->size = TARGET_PAGE_SIZE;
+ map->phys_offset = pd[i].phys_offset;
}
}
} else {
void **pp = *lp;
for (i = 0; i < L2_SIZE; ++i) {
phys_page_for_each_1(client, level - 1, pp + i,
- (addr << L2_BITS) | i);
+ (addr << L2_BITS) | i, map);
}
}
}
@@ -1787,9 +1812,15 @@ static void phys_page_for_each_1(CPUPhysMemoryClient *client,
static void phys_page_for_each(CPUPhysMemoryClient *client)
{
int i;
+ struct last_map map = { };
+
for (i = 0; i < P_L1_SIZE; ++i) {
phys_page_for_each_1(client, P_L1_SHIFT / L2_BITS - 1,
- l1_phys_map + i, i);
+ l1_phys_map + i, i, &map);
+ }
+ if (map.size) {
+ client->set_memory(client, map.start_addr, map.size, map.phys_offset,
+ false);
}
}
@@ -3084,11 +3115,12 @@ void *qemu_get_ram_ptr(ram_addr_t addr)
if (xen_mapcache_enabled()) {
/* We need to check if the requested address is in the RAM
* because we don't want to map the entire memory in QEMU.
+ * In that case just map until the end of the page.
*/
if (block->offset == 0) {
- return qemu_map_cache(addr, 0, 1);
+ return qemu_map_cache(addr, 0, 0);
} else if (block->host == NULL) {
- block->host = xen_map_block(block->offset, block->length);
+ block->host = qemu_map_cache(block->offset, block->length, 1);
}
}
return block->host + (addr - block->offset);
@@ -3113,11 +3145,12 @@ void *qemu_safe_ram_ptr(ram_addr_t addr)
if (xen_mapcache_enabled()) {
/* We need to check if the requested address is in the RAM
* because we don't want to map the entire memory in QEMU.
+ * In that case just map until the end of the page.
*/
if (block->offset == 0) {
- return qemu_map_cache(addr, 0, 1);
+ return qemu_map_cache(addr, 0, 0);
} else if (block->host == NULL) {
- block->host = xen_map_block(block->offset, block->length);
+ block->host = qemu_map_cache(block->offset, block->length, 1);
}
}
return block->host + (addr - block->offset);
@@ -3130,32 +3163,46 @@ void *qemu_safe_ram_ptr(ram_addr_t addr)
return NULL;
}
-void qemu_put_ram_ptr(void *addr)
+/* Return a host pointer to guest's ram. Similar to qemu_get_ram_ptr
+ * but takes a size argument */
+void *qemu_ram_ptr_length(target_phys_addr_t addr, target_phys_addr_t *size)
{
- trace_qemu_put_ram_ptr(addr);
-
- if (xen_mapcache_enabled()) {
+ if (xen_mapcache_enabled())
+ return qemu_map_cache(addr, *size, 1);
+ else {
RAMBlock *block;
QLIST_FOREACH(block, &ram_list.blocks, next) {
- if (addr == block->host) {
- break;
+ if (addr - block->offset < block->length) {
+ if (addr - block->offset + *size > block->length)
+ *size = block->length - addr + block->offset;
+ return block->host + (addr - block->offset);
}
}
- if (block && block->host) {
- xen_unmap_block(block->host, block->length);
- block->host = NULL;
- } else {
- qemu_map_cache_unlock(addr);
- }
+
+ fprintf(stderr, "Bad ram offset %" PRIx64 "\n", (uint64_t)addr);
+ abort();
+
+ *size = 0;
+ return NULL;
}
}
+void qemu_put_ram_ptr(void *addr)
+{
+ trace_qemu_put_ram_ptr(addr);
+}
+
int qemu_ram_addr_from_host(void *ptr, ram_addr_t *ram_addr)
{
RAMBlock *block;
uint8_t *host = ptr;
+ if (xen_mapcache_enabled()) {
+ *ram_addr = qemu_ram_addr_from_mapcache(ptr);
+ return 0;
+ }
+
QLIST_FOREACH(block, &ram_list.blocks, next) {
/* This case append when the block is not mapped. */
if (block->host == NULL) {
@@ -3167,11 +3214,6 @@ int qemu_ram_addr_from_host(void *ptr, ram_addr_t *ram_addr)
}
}
- if (xen_mapcache_enabled()) {
- *ram_addr = qemu_ram_addr_from_mapcache(ptr);
- return 0;
- }
-
return -1;
}
@@ -4003,14 +4045,12 @@ void *cpu_physical_memory_map(target_phys_addr_t addr,
int is_write)
{
target_phys_addr_t len = *plen;
- target_phys_addr_t done = 0;
+ target_phys_addr_t todo = 0;
int l;
- uint8_t *ret = NULL;
- uint8_t *ptr;
target_phys_addr_t page;
unsigned long pd;
PhysPageDesc *p;
- unsigned long addr1;
+ target_phys_addr_t addr1 = addr;
while (len > 0) {
page = addr & TARGET_PAGE_MASK;
@@ -4025,7 +4065,7 @@ void *cpu_physical_memory_map(target_phys_addr_t addr,
}
if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
- if (done || bounce.buffer) {
+ if (todo || bounce.buffer) {
break;
}
bounce.buffer = qemu_memalign(TARGET_PAGE_SIZE, TARGET_PAGE_SIZE);
@@ -4034,23 +4074,17 @@ void *cpu_physical_memory_map(target_phys_addr_t addr,
if (!is_write) {
cpu_physical_memory_read(addr, bounce.buffer, l);
}
- ptr = bounce.buffer;
- } else {
- addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
- ptr = qemu_get_ram_ptr(addr1);
- }
- if (!done) {
- ret = ptr;
- } else if (ret + done != ptr) {
- break;
+
+ *plen = l;
+ return bounce.buffer;
}
len -= l;
addr += l;
- done += l;
+ todo += l;
}
- *plen = done;
- return ret;
+ *plen = todo;
+ return qemu_ram_ptr_length(addr1, plen);
}
/* Unmaps a memory region previously mapped by cpu_physical_memory_map().
@@ -4080,13 +4114,7 @@ void cpu_physical_memory_unmap(void *buffer, target_phys_addr_t len,
}
}
if (xen_mapcache_enabled()) {
- uint8_t *buffer1 = buffer;
- uint8_t *end_buffer = buffer + len;
-
- while (buffer1 < end_buffer) {
- qemu_put_ram_ptr(buffer1);
- buffer1 += TARGET_PAGE_SIZE;
- }
+ qemu_invalidate_entry(buffer);
}
return;
}
diff --git a/gdbstub.c b/gdbstub.c
index b9ae30dd7d..c085a5afb3 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -37,7 +37,7 @@
#define MAX_PACKET_LENGTH 4096
-#include "exec-all.h"
+#include "cpu.h"
#include "qemu_socket.h"
#include "kvm.h"
diff --git a/hppa-dis.c b/hppa-dis.c
index a5760a9584..435da73553 100644
--- a/hppa-dis.c
+++ b/hppa-dis.c
@@ -1771,13 +1771,13 @@ static const char *const add_compl_names[] = { 0, "", ",l", ",tsv" };
static void
fput_reg (unsigned reg, disassemble_info *info)
{
- (*info->fprintf_func) (info->stream, reg ? reg_names[reg] : "r0");
+ (*info->fprintf_func) (info->stream, "%s", reg ? reg_names[reg] : "r0");
}
static void
fput_fp_reg (unsigned reg, disassemble_info *info)
{
- (*info->fprintf_func) (info->stream, reg ? fp_reg_names[reg] : "fr0");
+ (*info->fprintf_func) (info->stream, "%s", reg ? fp_reg_names[reg] : "fr0");
}
static void
@@ -1794,7 +1794,7 @@ fput_fp_reg_r (unsigned reg, disassemble_info *info)
static void
fput_creg (unsigned reg, disassemble_info *info)
{
- (*info->fprintf_func) (info->stream, control_reg[reg]);
+ (*info->fprintf_func) (info->stream, "%s", control_reg[reg]);
}
/* Print constants with sign. */
diff --git a/hw/9pfs/virtio-9p-device.c b/hw/9pfs/virtio-9p-device.c
index a2b6acc408..f235236ea0 100644
--- a/hw/9pfs/virtio-9p-device.c
+++ b/hw/9pfs/virtio-9p-device.c
@@ -142,11 +142,7 @@ static int virtio_9p_init_pci(PCIDevice *pci_dev)
vdev = virtio_9p_init(&pci_dev->qdev, &proxy->fsconf);
vdev->nvectors = proxy->nvectors;
- virtio_init_pci(proxy, vdev,
- PCI_VENDOR_ID_REDHAT_QUMRANET,
- 0x1009,
- 0x2,
- 0x00);
+ virtio_init_pci(proxy, vdev);
/* make the actual value visible */
proxy->nvectors = vdev->nvectors;
return 0;
@@ -156,6 +152,10 @@ static PCIDeviceInfo virtio_9p_info = {
.qdev.name = "virtio-9p-pci",
.qdev.size = sizeof(VirtIOPCIProxy),
.init = virtio_9p_init_pci,
+ .vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET,
+ .device_id = 0x1009,
+ .revision = VIRTIO_PCI_ABI_VERSION,
+ .class_id = 0x2,
.qdev.props = (Property[]) {
DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2),
DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
diff --git a/hw/ac97.c b/hw/ac97.c
index a946c1a56a..0b59896fbb 100644
--- a/hw/ac97.c
+++ b/hw/ac97.c
@@ -1277,9 +1277,6 @@ static int ac97_initfn (PCIDevice *dev)
AC97LinkState *s = DO_UPCAST (AC97LinkState, dev, dev);
uint8_t *c = s->dev.config;
- pci_config_set_vendor_id (c, PCI_VENDOR_ID_INTEL); /* ro */
- pci_config_set_device_id (c, PCI_DEVICE_ID_INTEL_82801AA_5); /* ro */
-
/* TODO: no need to override */
c[PCI_COMMAND] = 0x00; /* pcicmd pci command rw, ro */
c[PCI_COMMAND + 1] = 0x00;
@@ -1288,9 +1285,7 @@ static int ac97_initfn (PCIDevice *dev)
c[PCI_STATUS] = PCI_STATUS_FAST_BACK; /* pcists pci status rwc, ro */
c[PCI_STATUS + 1] = PCI_STATUS_DEVSEL_MEDIUM >> 8;
- c[PCI_REVISION_ID] = 0x01; /* rid revision ro */
c[PCI_CLASS_PROG] = 0x00; /* pi programming interface ro */
- pci_config_set_class (c, PCI_CLASS_MULTIMEDIA_AUDIO); /* ro */
/* TODO set when bar is registered. no need to override. */
/* nabmar native audio mixer base address rw */
@@ -1337,6 +1332,10 @@ static PCIDeviceInfo ac97_info = {
.qdev.size = sizeof (AC97LinkState),
.qdev.vmsd = &vmstate_ac97,
.init = ac97_initfn,
+ .vendor_id = PCI_VENDOR_ID_INTEL,
+ .device_id = PCI_DEVICE_ID_INTEL_82801AA_5,
+ .revision = 0x01,
+ .class_id = PCI_CLASS_MULTIMEDIA_AUDIO,
};
static void ac97_register (void)
diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
index 6c908ff00b..350558b859 100644
--- a/hw/acpi_piix4.c
+++ b/hw/acpi_piix4.c
@@ -317,13 +317,9 @@ static int piix4_pm_initfn(PCIDevice *dev)
uint8_t *pci_conf;
pci_conf = s->dev.config;
- pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_INTEL);
- pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_INTEL_82371AB_3);
pci_conf[0x06] = 0x80;
pci_conf[0x07] = 0x02;
- pci_conf[0x08] = 0x03; // revision number
pci_conf[0x09] = 0x00;
- pci_config_set_class(pci_conf, PCI_CLASS_BRIDGE_OTHER);
pci_conf[0x3d] = 0x01; // interrupt pin 1
pci_conf[0x40] = 0x01; /* PM io base read only bit */
@@ -394,6 +390,10 @@ static PCIDeviceInfo piix4_pm_info = {
.no_hotplug = 1,
.init = piix4_pm_initfn,
.config_write = pm_write_config,
+ .vendor_id = PCI_VENDOR_ID_INTEL,
+ .device_id = PCI_DEVICE_ID_INTEL_82371AB_3,
+ .revision = 0x03,
+ .class_id = PCI_CLASS_BRIDGE_OTHER,
.qdev.props = (Property[]) {
DEFINE_PROP_UINT32("smb_io_base", PIIX4PMState, smb_io_base, 0),
DEFINE_PROP_END_OF_LIST(),
diff --git a/hw/apb_pci.c b/hw/apb_pci.c
index 84e9af76a2..974c87a8ce 100644
--- a/hw/apb_pci.c
+++ b/hw/apb_pci.c
@@ -304,9 +304,6 @@ static int apb_pci_bridge_initfn(PCIDevice *dev)
return rc;
}
- pci_config_set_vendor_id(dev->config, PCI_VENDOR_ID_SUN);
- pci_config_set_device_id(dev->config, PCI_DEVICE_ID_SUN_SIMBA);
-
/*
* command register:
* According to PCI bridge spec, after reset
@@ -321,7 +318,6 @@ static int apb_pci_bridge_initfn(PCIDevice *dev)
pci_set_word(dev->config + PCI_STATUS,
PCI_STATUS_FAST_BACK | PCI_STATUS_66MHZ |
PCI_STATUS_DEVSEL_MEDIUM);
- pci_set_byte(dev->config + PCI_REVISION_ID, 0x11);
return 0;
}
@@ -436,14 +432,11 @@ static int pci_pbm_init_device(SysBusDevice *dev)
static int pbm_pci_host_init(PCIDevice *d)
{
- pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_SUN);
- pci_config_set_device_id(d->config, PCI_DEVICE_ID_SUN_SABRE);
pci_set_word(d->config + PCI_COMMAND,
PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
pci_set_word(d->config + PCI_STATUS,
PCI_STATUS_FAST_BACK | PCI_STATUS_66MHZ |
PCI_STATUS_DEVSEL_MEDIUM);
- pci_config_set_class(d->config, PCI_CLASS_BRIDGE_HOST);
return 0;
}
@@ -451,6 +444,9 @@ static PCIDeviceInfo pbm_pci_host_info = {
.qdev.name = "pbm",
.qdev.size = sizeof(PCIDevice),
.init = pbm_pci_host_init,
+ .vendor_id = PCI_VENDOR_ID_SUN,
+ .device_id = PCI_DEVICE_ID_SUN_SABRE,
+ .class_id = PCI_CLASS_BRIDGE_HOST,
.is_bridge = 1,
};
@@ -468,6 +464,9 @@ static PCIDeviceInfo pbm_pci_bridge_info = {
.qdev.reset = pci_bridge_reset,
.init = apb_pci_bridge_initfn,
.exit = pci_bridge_exitfn,
+ .vendor_id = PCI_VENDOR_ID_SUN,
+ .device_id = PCI_DEVICE_ID_SUN_SIMBA,
+ .revision = 0x11,
.config_write = pci_bridge_write_config,
.is_bridge = 1,
};
diff --git a/hw/armv7m.c b/hw/armv7m.c
index 72d010a63b..83f3393eab 100644
--- a/hw/armv7m.c
+++ b/hw/armv7m.c
@@ -4,7 +4,7 @@
* Copyright (c) 2006-2007 CodeSourcery.
* Written by Paul Brook
*
- * This code is licenced under the GPL.
+ * This code is licensed under the GPL.
*/
#include "sysbus.h"
@@ -14,7 +14,7 @@
/* Bitbanded IO. Each word corresponds to a single bit. */
-/* Get the byte address of the real memory for a bitband acess. */
+/* Get the byte address of the real memory for a bitband access. */
static inline uint32_t bitband_addr(void * opaque, uint32_t addr)
{
uint32_t res;
diff --git a/hw/bonito.c b/hw/bonito.c
index 65a4a637bf..e8c57a36ff 100644
--- a/hw/bonito.c
+++ b/hw/bonito.c
@@ -691,11 +691,7 @@ static int bonito_initfn(PCIDevice *dev)
PCIBonitoState *s = DO_UPCAST(PCIBonitoState, dev, dev);
/* Bonito North Bridge, built on FPGA, VENDOR_ID/DEVICE_ID are "undefined" */
- pci_config_set_vendor_id(dev->config, 0xdf53);
- pci_config_set_device_id(dev->config, 0x00d5);
- pci_config_set_class(dev->config, PCI_CLASS_BRIDGE_HOST);
pci_config_set_prog_interface(dev->config, 0x00);
- pci_config_set_revision(dev->config, 0x01);
/* set the north bridge register mapping */
s->bonito_reg_handle = cpu_register_io_memory(bonito_read, bonito_write, s,
@@ -796,6 +792,11 @@ static PCIDeviceInfo bonito_info = {
.qdev.vmsd = &vmstate_bonito,
.qdev.no_user = 1,
.init = bonito_initfn,
+ /*Bonito North Bridge, built on FPGA, VENDOR_ID/DEVICE_ID are "undefined"*/
+ .vendor_id = 0xdf53,
+ .device_id = 0x00d5,
+ .revision = 0x01,
+ .class_id = PCI_CLASS_BRIDGE_HOST,
};
static SysBusDeviceInfo bonito_pcihost_info = {
diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c
index 722cac7544..f39d1f82ff 100644
--- a/hw/cirrus_vga.c
+++ b/hw/cirrus_vga.c
@@ -3088,8 +3088,11 @@ static void pci_cirrus_write_config(PCIDevice *d,
CirrusVGAState *s = &pvs->cirrus_vga;
pci_default_write_config(d, address, val, len);
- if (s->vga.map_addr && d->io_regions[0].addr == PCI_BAR_UNMAPPED)
+ if (s->vga.map_addr && d->io_regions[0].addr == PCI_BAR_UNMAPPED) {
s->vga.map_addr = 0;
+ s->vga.lfb_addr = 0;
+ s->vga.lfb_end = 0;
+ }
cirrus_update_memory_access(s);
}
@@ -3097,8 +3100,8 @@ static int pci_cirrus_vga_initfn(PCIDevice *dev)
{
PCICirrusVGAState *d = DO_UPCAST(PCICirrusVGAState, dev, dev);
CirrusVGAState *s = &d->cirrus_vga;
- uint8_t *pci_conf = d->dev.config;
- int device_id = CIRRUS_ID_CLGD5446;
+ PCIDeviceInfo *info = DO_UPCAST(PCIDeviceInfo, qdev, dev->qdev.info);
+ int16_t device_id = info->device_id;
/* setup VGA */
vga_common_init(&s->vga, VGA_RAM_SIZE);
@@ -3108,9 +3111,6 @@ static int pci_cirrus_vga_initfn(PCIDevice *dev)
&s->vga);
/* setup PCI */
- pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_CIRRUS);
- pci_config_set_device_id(pci_conf, device_id);
- pci_config_set_class(pci_conf, PCI_CLASS_DISPLAY_VGA);
/* setup memory space */
/* memory #0 LFB */
@@ -3139,6 +3139,9 @@ static PCIDeviceInfo cirrus_vga_info = {
.init = pci_cirrus_vga_initfn,
.romfile = VGABIOS_CIRRUS_FILENAME,
.config_write = pci_cirrus_write_config,
+ .vendor_id = PCI_VENDOR_ID_CIRRUS,
+ .device_id = CIRRUS_ID_CLGD5446,
+ .class_id = PCI_CLASS_DISPLAY_VGA,
};
static void cirrus_vga_register(void)
diff --git a/hw/dec_pci.c b/hw/dec_pci.c
index bf88f2ac80..a35f382052 100644
--- a/hw/dec_pci.c
+++ b/hw/dec_pci.c
@@ -50,28 +50,16 @@ static int dec_map_irq(PCIDevice *pci_dev, int irq_num)
return irq_num;
}
-static int dec_21154_initfn(PCIDevice *dev)
-{
- int rc;
-
- rc = pci_bridge_initfn(dev);
- if (rc < 0) {
- return rc;
- }
-
- pci_config_set_vendor_id(dev->config, PCI_VENDOR_ID_DEC);
- pci_config_set_device_id(dev->config, PCI_DEVICE_ID_DEC_21154);
- return 0;
-}
-
static PCIDeviceInfo dec_21154_pci_bridge_info = {
.qdev.name = "dec-21154-p2p-bridge",
.qdev.desc = "DEC 21154 PCI-PCI bridge",
.qdev.size = sizeof(PCIBridge),
.qdev.vmsd = &vmstate_pci_device,
.qdev.reset = pci_bridge_reset,
- .init = dec_21154_initfn,
+ .init = pci_bridge_initfn,
.exit = pci_bridge_exitfn,
+ .vendor_id = PCI_VENDOR_ID_DEC,
+ .device_id = PCI_DEVICE_ID_DEC_21154,
.config_write = pci_bridge_write_config,
.is_bridge = 1,
};
@@ -108,10 +96,6 @@ static int pci_dec_21154_init_device(SysBusDevice *dev)
static int dec_21154_pci_host_init(PCIDevice *d)
{
/* PCI2PCI bridge same values as PearPC - check this */
- pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_DEC);
- pci_config_set_device_id(d->config, PCI_DEVICE_ID_DEC_21154);
- pci_set_byte(d->config + PCI_REVISION_ID, 0x02);
- pci_config_set_class(d->config, PCI_CLASS_BRIDGE_PCI);
return 0;
}
@@ -119,6 +103,10 @@ static PCIDeviceInfo dec_21154_pci_host_info = {
.qdev.name = "dec-21154",
.qdev.size = sizeof(PCIDevice),
.init = dec_21154_pci_host_init,
+ .vendor_id = PCI_VENDOR_ID_DEC,
+ .device_id = PCI_DEVICE_ID_DEC_21154,
+ .revision = 0x02,
+ .class_id = PCI_CLASS_BRIDGE_PCI,
.is_bridge = 1,
};
diff --git a/hw/e1000.c b/hw/e1000.c
index f160bfc2ab..96d84f91ae 100644
--- a/hw/e1000.c
+++ b/hw/e1000.c
@@ -1164,12 +1164,8 @@ static int pci_e1000_init(PCIDevice *pci_dev)
pci_conf = d->dev.config;
- pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_INTEL);
- pci_config_set_device_id(pci_conf, E1000_DEVID);
/* TODO: we have no capabilities, so why is this bit set? */
pci_set_word(pci_conf + PCI_STATUS, PCI_STATUS_CAP_LIST);
- pci_conf[PCI_REVISION_ID] = 0x03;
- pci_config_set_class(pci_conf, PCI_CLASS_NETWORK_ETHERNET);
/* TODO: RST# value should be 0, PCI spec 6.2.4 */
pci_conf[PCI_CACHE_LINE_SIZE] = 0x10;
@@ -1221,6 +1217,10 @@ static PCIDeviceInfo e1000_info = {
.init = pci_e1000_init,
.exit = pci_e1000_uninit,
.romfile = "pxe-e1000.rom",
+ .vendor_id = PCI_VENDOR_ID_INTEL,
+ .device_id = E1000_DEVID,
+ .revision = 0x03,
+ .class_id = PCI_CLASS_NETWORK_ETHERNET,
.qdev.props = (Property[]) {
DEFINE_NIC_PROPERTIES(E1000State, conf),
DEFINE_PROP_END_OF_LIST(),
diff --git a/hw/eepro100.c b/hw/eepro100.c
index 9f16efd365..9b6f4a5cd8 100644
--- a/hw/eepro100.c
+++ b/hw/eepro100.c
@@ -129,8 +129,6 @@
typedef struct {
PCIDeviceInfo pci;
uint32_t device;
- uint16_t device_id;
- uint8_t revision;
uint8_t stats_size;
bool has_extended_tcb_support;
bool power_management;
@@ -526,16 +524,9 @@ static void e100_pci_reset(EEPRO100State * s, E100PCIDeviceInfo *e100_device)
TRACE(OTHER, logout("%p\n", s));
- /* PCI Vendor ID */
- pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_INTEL);
- /* PCI Device ID */
- pci_config_set_device_id(pci_conf, e100_device->device_id);
/* PCI Status */
pci_set_word(pci_conf + PCI_STATUS, PCI_STATUS_DEVSEL_MEDIUM |
PCI_STATUS_FAST_BACK);
- /* PCI Revision ID */
- pci_config_set_revision(pci_conf, e100_device->revision);
- pci_config_set_class(pci_conf, PCI_CLASS_NETWORK_ETHERNET);
/* PCI Latency Timer */
pci_set_byte(pci_conf + PCI_LATENCY_TIMER, 0x20); /* latency timer = 32 clocks */
/* Capability Pointer is set by PCI framework. */
@@ -563,12 +554,7 @@ static void e100_pci_reset(EEPRO100State * s, E100PCIDeviceInfo *e100_device)
case i82559ER:
case i82562:
case i82801:
- break;
case i82559C:
-#if EEPROM_SIZE > 0
- pci_set_word(pci_conf + PCI_SUBSYSTEM_VENDOR_ID, PCI_VENDOR_ID_INTEL);
- pci_set_word(pci_conf + PCI_SUBSYSTEM_ID, 0x0040);
-#endif
break;
default:
logout("Device %X is undefined!\n", device);
@@ -2040,9 +2026,9 @@ static E100PCIDeviceInfo e100_devices[] = {
.pci.qdev.desc = "Intel i82550 Ethernet",
.device = i82550,
/* TODO: check device id. */
- .device_id = PCI_DEVICE_ID_INTEL_82551IT,
+ .pci.device_id = PCI_DEVICE_ID_INTEL_82551IT,
/* Revision ID: 0x0c, 0x0d, 0x0e. */
- .revision = 0x0e,
+ .pci.revision = 0x0e,
/* TODO: check size of statistical counters. */
.stats_size = 80,
/* TODO: check extended tcb support. */
@@ -2052,9 +2038,9 @@ static E100PCIDeviceInfo e100_devices[] = {
.pci.qdev.name = "i82551",
.pci.qdev.desc = "Intel i82551 Ethernet",
.device = i82551,
- .device_id = PCI_DEVICE_ID_INTEL_82551IT,
+ .pci.device_id = PCI_DEVICE_ID_INTEL_82551IT,
/* Revision ID: 0x0f, 0x10. */
- .revision = 0x0f,
+ .pci.revision = 0x0f,
/* TODO: check size of statistical counters. */
.stats_size = 80,
.has_extended_tcb_support = true,
@@ -2063,29 +2049,29 @@ static E100PCIDeviceInfo e100_devices[] = {
.pci.qdev.name = "i82557a",
.pci.qdev.desc = "Intel i82557A Ethernet",
.device = i82557A,
- .device_id = PCI_DEVICE_ID_INTEL_82557,
- .revision = 0x01,
+ .pci.device_id = PCI_DEVICE_ID_INTEL_82557,
+ .pci.revision = 0x01,
.power_management = false,
},{
.pci.qdev.name = "i82557b",
.pci.qdev.desc = "Intel i82557B Ethernet",
.device = i82557B,
- .device_id = PCI_DEVICE_ID_INTEL_82557,
- .revision = 0x02,
+ .pci.device_id = PCI_DEVICE_ID_INTEL_82557,
+ .pci.revision = 0x02,
.power_management = false,
},{
.pci.qdev.name = "i82557c",
.pci.qdev.desc = "Intel i82557C Ethernet",
.device = i82557C,
- .device_id = PCI_DEVICE_ID_INTEL_82557,
- .revision = 0x03,
+ .pci.device_id = PCI_DEVICE_ID_INTEL_82557,
+ .pci.revision = 0x03,
.power_management = false,
},{
.pci.qdev.name = "i82558a",
.pci.qdev.desc = "Intel i82558A Ethernet",
.device = i82558A,
- .device_id = PCI_DEVICE_ID_INTEL_82557,
- .revision = 0x04,
+ .pci.device_id = PCI_DEVICE_ID_INTEL_82557,
+ .pci.revision = 0x04,
.stats_size = 76,
.has_extended_tcb_support = true,
.power_management = true,
@@ -2093,8 +2079,8 @@ static E100PCIDeviceInfo e100_devices[] = {
.pci.qdev.name = "i82558b",
.pci.qdev.desc = "Intel i82558B Ethernet",
.device = i82558B,
- .device_id = PCI_DEVICE_ID_INTEL_82557,
- .revision = 0x05,
+ .pci.device_id = PCI_DEVICE_ID_INTEL_82557,
+ .pci.revision = 0x05,
.stats_size = 76,
.has_extended_tcb_support = true,
.power_management = true,
@@ -2102,8 +2088,8 @@ static E100PCIDeviceInfo e100_devices[] = {
.pci.qdev.name = "i82559a",
.pci.qdev.desc = "Intel i82559A Ethernet",
.device = i82559A,
- .device_id = PCI_DEVICE_ID_INTEL_82557,
- .revision = 0x06,
+ .pci.device_id = PCI_DEVICE_ID_INTEL_82557,
+ .pci.revision = 0x06,
.stats_size = 80,
.has_extended_tcb_support = true,
.power_management = true,
@@ -2111,8 +2097,8 @@ static E100PCIDeviceInfo e100_devices[] = {
.pci.qdev.name = "i82559b",
.pci.qdev.desc = "Intel i82559B Ethernet",
.device = i82559B,
- .device_id = PCI_DEVICE_ID_INTEL_82557,
- .revision = 0x07,
+ .pci.device_id = PCI_DEVICE_ID_INTEL_82557,
+ .pci.revision = 0x07,
.stats_size = 80,
.has_extended_tcb_support = true,
.power_management = true,
@@ -2120,12 +2106,16 @@ static E100PCIDeviceInfo e100_devices[] = {
.pci.qdev.name = "i82559c",
.pci.qdev.desc = "Intel i82559C Ethernet",
.device = i82559C,
- .device_id = PCI_DEVICE_ID_INTEL_82557,
+ .pci.device_id = PCI_DEVICE_ID_INTEL_82557,
#if 0
- .revision = 0x08,
+ .pci.revision = 0x08,
#endif
/* TODO: Windows wants revision id 0x0c. */
- .revision = 0x0c,
+ .pci.revision = 0x0c,
+#if EEPROM_SIZE > 0
+ .pci.subsystem_vendor_id = PCI_VENDOR_ID_INTEL,
+ .pci.subsystem_id = 0x0040,
+#endif
.stats_size = 80,
.has_extended_tcb_support = true,
.power_management = true,
@@ -2133,8 +2123,8 @@ static E100PCIDeviceInfo e100_devices[] = {
.pci.qdev.name = "i82559er",
.pci.qdev.desc = "Intel i82559ER Ethernet",
.device = i82559ER,
- .device_id = PCI_DEVICE_ID_INTEL_82551IT,
- .revision = 0x09,
+ .pci.device_id = PCI_DEVICE_ID_INTEL_82551IT,
+ .pci.revision = 0x09,
.stats_size = 80,
.has_extended_tcb_support = true,
.power_management = true,
@@ -2143,9 +2133,9 @@ static E100PCIDeviceInfo e100_devices[] = {
.pci.qdev.desc = "Intel i82562 Ethernet",
.device = i82562,
/* TODO: check device id. */
- .device_id = PCI_DEVICE_ID_INTEL_82551IT,
+ .pci.device_id = PCI_DEVICE_ID_INTEL_82551IT,
/* TODO: wrong revision id. */
- .revision = 0x0e,
+ .pci.revision = 0x0e,
.stats_size = 80,
.has_extended_tcb_support = true,
.power_management = true,
@@ -2154,8 +2144,8 @@ static E100PCIDeviceInfo e100_devices[] = {
.pci.qdev.name = "i82801",
.pci.qdev.desc = "Intel i82801 Ethernet",
.device = i82801,
- .device_id = 0x2449,
- .revision = 0x03,
+ .pci.device_id = 0x2449,
+ .pci.revision = 0x03,
.stats_size = 80,
.has_extended_tcb_support = true,
.power_management = true,
@@ -2174,6 +2164,8 @@ static void eepro100_register_devices(void)
PCIDeviceInfo *pci_dev = &e100_devices[i].pci;
/* We use the same rom file for all device ids.
QEMU fixes the device id during rom load. */
+ pci_dev->vendor_id = PCI_VENDOR_ID_INTEL;
+ pci_dev->class_id = PCI_CLASS_NETWORK_ETHERNET;
pci_dev->romfile = "pxe-eepro100.rom";
pci_dev->init = e100_nic_init;
pci_dev->exit = pci_nic_uninit;
diff --git a/hw/es1370.c b/hw/es1370.c
index 40cb48cbb8..1ed62b7da3 100644
--- a/hw/es1370.c
+++ b/hw/es1370.c
@@ -998,21 +998,9 @@ static int es1370_initfn (PCIDevice *dev)
ES1370State *s = DO_UPCAST (ES1370State, dev, dev);
uint8_t *c = s->dev.config;
- pci_config_set_vendor_id (c, PCI_VENDOR_ID_ENSONIQ);
- pci_config_set_device_id (c, PCI_DEVICE_ID_ENSONIQ_ES1370);
c[PCI_STATUS + 1] = PCI_STATUS_DEVSEL_SLOW >> 8;
- pci_config_set_class (c, PCI_CLASS_MULTIMEDIA_AUDIO);
-#if 1
- c[PCI_SUBSYSTEM_VENDOR_ID] = 0x42;
- c[PCI_SUBSYSTEM_VENDOR_ID + 1] = 0x49;
- c[PCI_SUBSYSTEM_ID] = 0x4c;
- c[PCI_SUBSYSTEM_ID + 1] = 0x4c;
-#else
- c[PCI_SUBSYSTEM_VENDOR_ID] = 0x74;
- c[PCI_SUBSYSTEM_VENDOR_ID + 1] = 0x12;
- c[PCI_SUBSYSTEM_ID] = 0x71;
- c[PCI_SUBSYSTEM_ID + 1] = 0x13;
+#if 0
c[PCI_CAPABILITY_LIST] = 0xdc;
c[PCI_INTERRUPT_LINE] = 10;
c[0xdc] = 0x00;
@@ -1043,6 +1031,16 @@ static PCIDeviceInfo es1370_info = {
.qdev.size = sizeof (ES1370State),
.qdev.vmsd = &vmstate_es1370,
.init = es1370_initfn,
+ .vendor_id = PCI_VENDOR_ID_ENSONIQ,
+ .device_id = PCI_DEVICE_ID_ENSONIQ_ES1370,
+ .class_id = PCI_CLASS_MULTIMEDIA_AUDIO,
+#if 1
+ .subsystem_vendor_id = 0x4942,
+ .subsystem_id = 0x4c4c,
+#else
+ .subsystem_vendor_id = 0x1274,
+ .subsystem_id = 0x1371,
+#endif
};
static void es1370_register (void)
diff --git a/hw/etraxfs_ser.c b/hw/etraxfs_ser.c
index 2787ebd5c8..b917d4db11 100644
--- a/hw/etraxfs_ser.c
+++ b/hw/etraxfs_ser.c
@@ -190,15 +190,23 @@ static void serial_event(void *opaque, int event)
}
-static int etraxfs_ser_init(SysBusDevice *dev)
+static void etraxfs_ser_reset(DeviceState *d)
{
- struct etrax_serial *s = FROM_SYSBUS(typeof (*s), dev);
- int ser_regs;
+ struct etrax_serial *s = container_of(d, typeof(*s), busdev.qdev);
/* transmitter begins ready and idle. */
s->regs[RS_STAT_DIN] |= (1 << STAT_TR_RDY);
s->regs[RS_STAT_DIN] |= (1 << STAT_TR_IDLE);
+ s->regs[RW_REC_CTRL] = 0x10000;
+
+}
+
+static int etraxfs_ser_init(SysBusDevice *dev)
+{
+ struct etrax_serial *s = FROM_SYSBUS(typeof (*s), dev);
+ int ser_regs;
+
sysbus_init_irq(dev, &s->irq);
ser_regs = cpu_register_io_memory(ser_read, ser_write, s,
DEVICE_NATIVE_ENDIAN);
@@ -211,10 +219,16 @@ static int etraxfs_ser_init(SysBusDevice *dev)
return 0;
}
+static SysBusDeviceInfo etraxfs_ser_info = {
+ .init = etraxfs_ser_init,
+ .qdev.name = "etraxfs,serial",
+ .qdev.size = sizeof(struct etrax_serial),
+ .qdev.reset = etraxfs_ser_reset,
+};
+
static void etraxfs_serial_register(void)
{
- sysbus_register_dev("etraxfs,serial", sizeof (struct etrax_serial),
- etraxfs_ser_init);
+ sysbus_register_withprop(&etraxfs_ser_info);
}
device_init(etraxfs_serial_register)
diff --git a/hw/grackle_pci.c b/hw/grackle_pci.c
index d35701f4a5..cee07e06c7 100644
--- a/hw/grackle_pci.c
+++ b/hw/grackle_pci.c
@@ -104,11 +104,7 @@ static int pci_grackle_init_device(SysBusDevice *dev)
static int grackle_pci_host_init(PCIDevice *d)
{
- pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_MOTOROLA);
- pci_config_set_device_id(d->config, PCI_DEVICE_ID_MOTOROLA_MPC106);
- d->config[0x08] = 0x00; // revision
d->config[0x09] = 0x01;
- pci_config_set_class(d->config, PCI_CLASS_BRIDGE_HOST);
return 0;
}
@@ -116,6 +112,10 @@ static PCIDeviceInfo grackle_pci_host_info = {
.qdev.name = "grackle",
.qdev.size = sizeof(PCIDevice),
.init = grackle_pci_host_init,
+ .vendor_id = PCI_VENDOR_ID_MOTOROLA,
+ .device_id = PCI_DEVICE_ID_MOTOROLA_MPC106,
+ .revision = 0x00,
+ .class_id = PCI_CLASS_BRIDGE_HOST,
};
static void grackle_register_devices(void)
diff --git a/hw/gt64xxx.c b/hw/gt64xxx.c
index c66188f40e..8e1f6a069d 100644
--- a/hw/gt64xxx.c
+++ b/hw/gt64xxx.c
@@ -1118,14 +1118,10 @@ static int gt64120_init(SysBusDevice *dev)
static int gt64120_pci_init(PCIDevice *d)
{
/* FIXME: Malta specific hw assumptions ahead */
- pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_MARVELL);
- pci_config_set_device_id(d->config, PCI_DEVICE_ID_MARVELL_GT6412X);
pci_set_word(d->config + PCI_COMMAND, 0);
pci_set_word(d->config + PCI_STATUS,
PCI_STATUS_FAST_BACK | PCI_STATUS_DEVSEL_MEDIUM);
- pci_set_byte(d->config + PCI_CLASS_REVISION, 0x10);
pci_config_set_prog_interface(d->config, 0);
- pci_config_set_class(d->config, PCI_CLASS_BRIDGE_HOST);
pci_set_long(d->config + PCI_BASE_ADDRESS_0, 0x00000008);
pci_set_long(d->config + PCI_BASE_ADDRESS_1, 0x01000008);
pci_set_long(d->config + PCI_BASE_ADDRESS_2, 0x1c000000);
@@ -1141,6 +1137,10 @@ static PCIDeviceInfo gt64120_pci_info = {
.qdev.name = "gt64120_pci",
.qdev.size = sizeof(PCIDevice),
.init = gt64120_pci_init,
+ .vendor_id = PCI_VENDOR_ID_MARVELL,
+ .device_id = PCI_DEVICE_ID_MARVELL_GT6412X,
+ .revision = 0x10,
+ .class_id = PCI_CLASS_BRIDGE_HOST,
};
static void gt64120_pci_register_devices(void)
diff --git a/hw/hw.h b/hw/hw.h
index 56447a735d..9dd7096fc2 100644
--- a/hw/hw.h
+++ b/hw/hw.h
@@ -780,6 +780,9 @@ extern const VMStateDescription vmstate_ptimer;
#define VMSTATE_INT32_LE(_f, _s) \
VMSTATE_SINGLE(_f, _s, 0, vmstate_info_int32_le, int32_t)
+#define VMSTATE_UINT8_TEST(_f, _s, _t) \
+ VMSTATE_SINGLE_TEST(_f, _s, _t, 0, vmstate_info_uint8, uint8_t)
+
#define VMSTATE_UINT16_TEST(_f, _s, _t) \
VMSTATE_SINGLE_TEST(_f, _s, _t, 0, vmstate_info_uint16, uint16_t)
diff --git a/hw/ide/cmd646.c b/hw/ide/cmd646.c
index 5d5464ae83..56302b5060 100644
--- a/hw/ide/cmd646.c
+++ b/hw/ide/cmd646.c
@@ -226,14 +226,8 @@ static int pci_cmd646_ide_initfn(PCIDevice *dev)
qemu_irq *irq;
int i;
- pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_CMD);
- pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_CMD_646);
-
- pci_conf[PCI_REVISION_ID] = 0x07; // IDE controller revision
pci_conf[PCI_CLASS_PROG] = 0x8f;
- pci_config_set_class(pci_conf, PCI_CLASS_STORAGE_IDE);
-
pci_conf[0x51] = 0x04; // enable IDE0
if (d->secondary) {
/* XXX: if not enabled, really disable the seconday IDE controller */
@@ -282,6 +276,10 @@ static PCIDeviceInfo cmd646_ide_info[] = {
.qdev.name = "cmd646-ide",
.qdev.size = sizeof(PCIIDEState),
.init = pci_cmd646_ide_initfn,
+ .vendor_id = PCI_VENDOR_ID_CMD,
+ .device_id = PCI_DEVICE_ID_CMD_646,
+ .revision = 0x07, // IDE controller revision
+ .class_id = PCI_CLASS_STORAGE_IDE,
.qdev.props = (Property[]) {
DEFINE_PROP_UINT32("secondary", PCIIDEState, secondary, 0),
DEFINE_PROP_END_OF_LIST(),
diff --git a/hw/ide/ich.c b/hw/ide/ich.c
index 6150ce3343..054e0734e4 100644
--- a/hw/ide/ich.c
+++ b/hw/ide/ich.c
@@ -77,11 +77,8 @@ static int pci_ich9_ahci_init(PCIDevice *dev)
struct AHCIPCIState *d;
d = DO_UPCAST(struct AHCIPCIState, card, dev);
- pci_config_set_vendor_id(d->card.config, PCI_VENDOR_ID_INTEL);
- pci_config_set_device_id(d->card.config, PCI_DEVICE_ID_INTEL_82801IR);
+ ahci_init(&d->ahci, &dev->qdev, 6);
- pci_config_set_class(d->card.config, PCI_CLASS_STORAGE_SATA);
- pci_config_set_revision(d->card.config, 0x02);
pci_config_set_prog_interface(d->card.config, AHCI_PROGMODE_MAJOR_REV_1);
d->card.config[PCI_CACHE_LINE_SIZE] = 0x08; /* Cache line size */
@@ -94,8 +91,6 @@ static int pci_ich9_ahci_init(PCIDevice *dev)
qemu_register_reset(ahci_reset, d);
msi_init(dev, 0x50, 1, true, false);
-
- ahci_init(&d->ahci, &dev->qdev, 6);
d->ahci.irq = d->card.irq[0];
/* XXX BAR size should be 1k, but that breaks, so bump it to 4k for now */
@@ -131,6 +126,10 @@ static PCIDeviceInfo ich_ahci_info[] = {
.init = pci_ich9_ahci_init,
.exit = pci_ich9_uninit,
.config_write = pci_ich9_write_config,
+ .vendor_id = PCI_VENDOR_ID_INTEL,
+ .device_id = PCI_DEVICE_ID_INTEL_82801IR,
+ .revision = 0x02,
+ .class_id = PCI_CLASS_STORAGE_SATA,
},{
/* end of list */
}
diff --git a/hw/ide/piix.c b/hw/ide/piix.c
index c3496448c3..84f72b0a66 100644
--- a/hw/ide/piix.c
+++ b/hw/ide/piix.c
@@ -131,12 +131,12 @@ static void pci_piix_init_ports(PCIIDEState *d) {
}
}
-static int pci_piix_ide_initfn(PCIIDEState *d)
+static int pci_piix_ide_initfn(PCIDevice *dev)
{
+ PCIIDEState *d = DO_UPCAST(PCIIDEState, dev, dev);
uint8_t *pci_conf = d->dev.config;
pci_conf[PCI_CLASS_PROG] = 0x80; // legacy ATA mode
- pci_config_set_class(pci_conf, PCI_CLASS_STORAGE_IDE);
qemu_register_reset(piix3_reset, d);
@@ -149,24 +149,6 @@ static int pci_piix_ide_initfn(PCIIDEState *d)
return 0;
}
-static int pci_piix3_ide_initfn(PCIDevice *dev)
-{
- PCIIDEState *d = DO_UPCAST(PCIIDEState, dev, dev);
-
- pci_config_set_vendor_id(d->dev.config, PCI_VENDOR_ID_INTEL);
- pci_config_set_device_id(d->dev.config, PCI_DEVICE_ID_INTEL_82371SB_1);
- return pci_piix_ide_initfn(d);
-}
-
-static int pci_piix4_ide_initfn(PCIDevice *dev)
-{
- PCIIDEState *d = DO_UPCAST(PCIIDEState, dev, dev);
-
- pci_config_set_vendor_id(d->dev.config, PCI_VENDOR_ID_INTEL);
- pci_config_set_device_id(d->dev.config, PCI_DEVICE_ID_INTEL_82371AB);
- return pci_piix_ide_initfn(d);
-}
-
/* hd_table must contain 4 block drivers */
/* NOTE: for the PIIX3, the IRQs and IOports are hardcoded */
PCIDevice *pci_piix3_ide_init(PCIBus *bus, DriveInfo **hd_table, int devfn)
@@ -195,13 +177,19 @@ static PCIDeviceInfo piix_ide_info[] = {
.qdev.size = sizeof(PCIIDEState),
.qdev.no_user = 1,
.no_hotplug = 1,
- .init = pci_piix3_ide_initfn,
+ .init = pci_piix_ide_initfn,
+ .vendor_id = PCI_VENDOR_ID_INTEL,
+ .device_id = PCI_DEVICE_ID_INTEL_82371SB_1,
+ .class_id = PCI_CLASS_STORAGE_IDE,
},{
.qdev.name = "piix4-ide",
.qdev.size = sizeof(PCIIDEState),
.qdev.no_user = 1,
.no_hotplug = 1,
- .init = pci_piix4_ide_initfn,
+ .init = pci_piix_ide_initfn,
+ .vendor_id = PCI_VENDOR_ID_INTEL,
+ .device_id = PCI_DEVICE_ID_INTEL_82371AB,
+ .class_id = PCI_CLASS_STORAGE_IDE,
},{
/* end of list */
}
diff --git a/hw/ide/via.c b/hw/ide/via.c
index 04f3290960..3474c37ff7 100644
--- a/hw/ide/via.c
+++ b/hw/ide/via.c
@@ -160,11 +160,7 @@ static int vt82c686b_ide_initfn(PCIDevice *dev)
PCIIDEState *d = DO_UPCAST(PCIIDEState, dev, dev);;
uint8_t *pci_conf = d->dev.config;
- pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_VIA);
- pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_VIA_IDE);
- pci_config_set_class(pci_conf, PCI_CLASS_STORAGE_IDE);
pci_config_set_prog_interface(pci_conf, 0x8a); /* legacy ATA mode */
- pci_config_set_revision(pci_conf,0x06); /* Revision 0.6 */
pci_set_long(pci_conf + PCI_CAPABILITY_LIST, 0x000000c0);
qemu_register_reset(via_reset, d);
@@ -191,6 +187,10 @@ static PCIDeviceInfo via_ide_info = {
.qdev.size = sizeof(PCIIDEState),
.qdev.no_user = 1,
.init = vt82c686b_ide_initfn,
+ .vendor_id = PCI_VENDOR_ID_VIA,
+ .device_id = PCI_DEVICE_ID_VIA_IDE,
+ .revision = 0x06,
+ .class_id = PCI_CLASS_STORAGE_IDE,
};
static void via_ide_register(void)
diff --git a/hw/intel-hda.c b/hw/intel-hda.c
index 5485745e85..0ffffce90e 100644
--- a/hw/intel-hda.c
+++ b/hw/intel-hda.c
@@ -1138,10 +1138,6 @@ static int intel_hda_init(PCIDevice *pci)
d->name = d->pci.qdev.info->name;
- pci_config_set_vendor_id(conf, PCI_VENDOR_ID_INTEL);
- pci_config_set_device_id(conf, 0x2668);
- pci_config_set_revision(conf, 1);
- pci_config_set_class(conf, PCI_CLASS_MULTIMEDIA_HD_AUDIO);
pci_config_set_interrupt_pin(conf, 1);
/* HDCTL off 0x40 bit 0 selects signaling mode (1-HDA, 0 - Ac97) 18.1.19 */
@@ -1265,6 +1261,10 @@ static PCIDeviceInfo intel_hda_info = {
.init = intel_hda_init,
.exit = intel_hda_exit,
.config_write = intel_hda_write_config,
+ .vendor_id = PCI_VENDOR_ID_INTEL,
+ .device_id = 0x2668,
+ .revision = 1,
+ .class_id = PCI_CLASS_MULTIMEDIA_HD_AUDIO,
.qdev.props = (Property[]) {
DEFINE_PROP_UINT32("debug", IntelHDAState, debug, 0),
DEFINE_PROP_UINT32("msi", IntelHDAState, msi, 1),
diff --git a/hw/ioh3420.c b/hw/ioh3420.c
index 95adf0978f..a6bfbb9173 100644
--- a/hw/ioh3420.c
+++ b/hw/ioh3420.c
@@ -104,12 +104,8 @@ static int ioh3420_initfn(PCIDevice *d)
return rc;
}
- d->config[PCI_REVISION_ID] = PCI_DEVICE_ID_IOH_REV;
pcie_port_init_reg(d);
- pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_INTEL);
- pci_config_set_device_id(d->config, PCI_DEVICE_ID_IOH_EPORT);
-
rc = pci_bridge_ssvid_init(d, IOH_EP_SSVID_OFFSET,
IOH_EP_SSVID_SVID, IOH_EP_SSVID_SSID);
if (rc < 0) {
@@ -217,6 +213,9 @@ static PCIDeviceInfo ioh3420_info = {
.config_write = ioh3420_write_config,
.init = ioh3420_initfn,
.exit = ioh3420_exitfn,
+ .vendor_id = PCI_VENDOR_ID_INTEL,
+ .device_id = PCI_DEVICE_ID_IOH_EPORT,
+ .revision = PCI_DEVICE_ID_IOH_REV,
.qdev.props = (Property[]) {
DEFINE_PROP_UINT8("port", PCIESlot, port.port, 0),
diff --git a/hw/ivshmem.c b/hw/ivshmem.c
index 7b19a81a47..3055dd2a50 100644
--- a/hw/ivshmem.c
+++ b/hw/ivshmem.c
@@ -706,12 +706,7 @@ static int pci_ivshmem_init(PCIDevice *dev)
}
pci_conf = s->dev.config;
- pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_REDHAT_QUMRANET);
- pci_conf[0x02] = 0x10;
- pci_conf[0x03] = 0x11;
pci_conf[PCI_COMMAND] = PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
- pci_config_set_class(pci_conf, PCI_CLASS_MEMORY_RAM);
- pci_conf[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL;
pci_config_set_interrupt_pin(pci_conf, 1);
@@ -809,6 +804,9 @@ static PCIDeviceInfo ivshmem_info = {
.qdev.reset = ivshmem_reset,
.init = pci_ivshmem_init,
.exit = pci_ivshmem_uninit,
+ .vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET,
+ .device_id = 0x1110,
+ .class_id = PCI_CLASS_MEMORY_RAM,
.qdev.props = (Property[]) {
DEFINE_PROP_CHR("chardev", IVShmemState, server_chr),
DEFINE_PROP_STRING("size", IVShmemState, sizearg),
diff --git a/hw/kvmclock.c b/hw/kvmclock.c
index 004c4add8c..692ad182f0 100644
--- a/hw/kvmclock.c
+++ b/hw/kvmclock.c
@@ -17,8 +17,6 @@
#include "kvm.h"
#include "kvmclock.h"
-#if defined(CONFIG_KVM_PARA) && defined(KVM_CAP_ADJUST_CLOCK)
-
#include <linux/kvm.h>
#include <linux/kvm_para.h>
@@ -120,10 +118,3 @@ static void kvmclock_register_device(void)
}
device_init(kvmclock_register_device);
-
-#else /* !(CONFIG_KVM_PARA && KVM_CAP_ADJUST_CLOCK) */
-
-void kvmclock_create(void)
-{
-}
-#endif /* !(CONFIG_KVM_PARA && KVM_CAP_ADJUST_CLOCK) */
diff --git a/hw/kvmclock.h b/hw/kvmclock.h
index 7a83cbe8f6..252ea13461 100644
--- a/hw/kvmclock.h
+++ b/hw/kvmclock.h
@@ -11,4 +11,14 @@
*
*/
+#ifdef CONFIG_KVM
+
void kvmclock_create(void);
+
+#else /* CONFIG_KVM */
+
+static inline void kvmclock_create(void)
+{
+}
+
+#endif /* !CONFIG_KVM */
diff --git a/hw/lm32_sys.c b/hw/lm32_sys.c
index 427b05fe1a..e5ff962f43 100644
--- a/hw/lm32_sys.c
+++ b/hw/lm32_sys.c
@@ -83,7 +83,7 @@ static void sys_write(void *opaque, target_phys_addr_t addr, uint32_t value)
break;
default:
- error_report("lm32_sys: write access to unkown register 0x"
+ error_report("lm32_sys: write access to unknown register 0x"
TARGET_FMT_plx, addr << 2);
break;
}
diff --git a/hw/lm32_timer.c b/hw/lm32_timer.c
index ed289847ac..49cbb22993 100644
--- a/hw/lm32_timer.c
+++ b/hw/lm32_timer.c
@@ -86,7 +86,7 @@ static uint32_t timer_read(void *opaque, target_phys_addr_t addr)
r = (uint32_t)ptimer_get_count(s->ptimer);
break;
default:
- error_report("lm32_timer: read access to unkown register 0x"
+ error_report("lm32_timer: read access to unknown register 0x"
TARGET_FMT_plx, addr << 2);
break;
}
@@ -124,7 +124,7 @@ static void timer_write(void *opaque, target_phys_addr_t addr, uint32_t value)
TARGET_FMT_plx, addr << 2);
break;
default:
- error_report("lm32_timer: write access to unkown register 0x"
+ error_report("lm32_timer: write access to unknown register 0x"
TARGET_FMT_plx, addr << 2);
break;
}
diff --git a/hw/lm32_uart.c b/hw/lm32_uart.c
index e225087b99..09090e93b2 100644
--- a/hw/lm32_uart.c
+++ b/hw/lm32_uart.c
@@ -149,7 +149,7 @@ static uint32_t uart_read(void *opaque, target_phys_addr_t addr)
TARGET_FMT_plx, addr << 2);
break;
default:
- error_report("lm32_uart: read access to unkown register 0x"
+ error_report("lm32_uart: read access to unknown register 0x"
TARGET_FMT_plx, addr << 2);
break;
}
@@ -185,7 +185,7 @@ static void uart_write(void *opaque, target_phys_addr_t addr, uint32_t value)
TARGET_FMT_plx, addr << 2);
break;
default:
- error_report("lm32_uart: write access to unkown register 0x"
+ error_report("lm32_uart: write access to unknown register 0x"
TARGET_FMT_plx, addr << 2);
break;
}
diff --git a/hw/lsi53c895a.c b/hw/lsi53c895a.c
index 83084b6b6a..940b43abfd 100644
--- a/hw/lsi53c895a.c
+++ b/hw/lsi53c895a.c
@@ -889,7 +889,6 @@ static void lsi_do_msgout(LSIState *s)
uint8_t msg;
int len;
uint32_t current_tag;
- SCSIDevice *current_dev;
lsi_request *current_req, *p, *p_next;
int id;
@@ -901,7 +900,6 @@ static void lsi_do_msgout(LSIState *s)
current_req = lsi_find_by_tag(s, current_tag);
}
id = (current_tag >> 8) & 0xf;
- current_dev = s->bus.devs[id];
DPRINTF("MSG out len=%d\n", s->dbc);
while (s->dbc) {
@@ -2258,15 +2256,6 @@ static int lsi_scsi_init(PCIDevice *dev)
pci_conf = s->dev.config;
- /* PCI Vendor ID (word) */
- pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_LSI_LOGIC);
- /* PCI device ID (word) */
- pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_LSI_53C895A);
- /* PCI base class code */
- pci_config_set_class(pci_conf, PCI_CLASS_STORAGE_SCSI);
- /* PCI subsystem ID */
- pci_conf[PCI_SUBSYSTEM_ID] = 0x00;
- pci_conf[PCI_SUBSYSTEM_ID + 1] = 0x10;
/* PCI latency timer = 255 */
pci_conf[PCI_LATENCY_TIMER] = 0xff;
/* TODO: RST# value should be 0 */
@@ -2302,6 +2291,10 @@ static PCIDeviceInfo lsi_info = {
.qdev.vmsd = &vmstate_lsi_scsi,
.init = lsi_scsi_init,
.exit = lsi_scsi_uninit,
+ .vendor_id = PCI_VENDOR_ID_LSI_LOGIC,
+ .device_id = PCI_DEVICE_ID_LSI_53C895A,
+ .class_id = PCI_CLASS_STORAGE_SCSI,
+ .subsystem_id = 0x1000,
};
static void lsi53c895a_register_devices(void)
diff --git a/hw/milkymist-ac97.c b/hw/milkymist-ac97.c
index 6c9e318aa2..6104732f7d 100644
--- a/hw/milkymist-ac97.c
+++ b/hw/milkymist-ac97.c
@@ -103,7 +103,7 @@ static uint32_t ac97_read(void *opaque, target_phys_addr_t addr)
break;
default:
- error_report("milkymist_ac97: read access to unkown register 0x"
+ error_report("milkymist_ac97: read access to unknown register 0x"
TARGET_FMT_plx, addr << 2);
break;
}
@@ -152,7 +152,7 @@ static void ac97_write(void *opaque, target_phys_addr_t addr, uint32_t value)
break;
default:
- error_report("milkymist_ac97: write access to unkown register 0x"
+ error_report("milkymist_ac97: write access to unknown register 0x"
TARGET_FMT_plx, addr);
break;
}
diff --git a/hw/milkymist-memcard.c b/hw/milkymist-memcard.c
index 06077af82a..22dc377d79 100644
--- a/hw/milkymist-memcard.c
+++ b/hw/milkymist-memcard.c
@@ -154,7 +154,7 @@ static uint32_t memcard_read(void *opaque, target_phys_addr_t addr)
break;
default:
- error_report("milkymist_memcard: read access to unkown register 0x"
+ error_report("milkymist_memcard: read access to unknown register 0x"
TARGET_FMT_plx, addr << 2);
break;
}
@@ -210,7 +210,7 @@ static void memcard_write(void *opaque, target_phys_addr_t addr, uint32_t value)
break;
default:
- error_report("milkymist_memcard: write access to unkown register 0x"
+ error_report("milkymist_memcard: write access to unknown register 0x"
TARGET_FMT_plx, addr << 2);
break;
}
diff --git a/hw/milkymist-minimac2.c b/hw/milkymist-minimac2.c
index c4e28187b3..cd360264c1 100644
--- a/hw/milkymist-minimac2.c
+++ b/hw/milkymist-minimac2.c
@@ -234,20 +234,20 @@ static void minimac2_tx(MilkymistMinimac2State *s)
uint8_t *buf = s->tx_buf;
if (txcount < 64) {
- error_report("milkymist_minimac2: ethernet frame too small (%u < %u)\n",
+ error_report("milkymist_minimac2: ethernet frame too small (%u < %u)",
txcount, 64);
goto err;
}
if (txcount > MINIMAC2_MTU) {
- error_report("milkymist_minimac2: MTU exceeded (%u > %u)\n",
+ error_report("milkymist_minimac2: MTU exceeded (%u > %u)",
txcount, MINIMAC2_MTU);
goto err;
}
if (memcmp(buf, preamble_sfd, 8) != 0) {
error_report("milkymist_minimac2: frame doesn't contain the preamble "
- "and/or the SFD (%02x %02x %02x %02x %02x %02x %02x %02x)\n",
+ "and/or the SFD (%02x %02x %02x %02x %02x %02x %02x %02x)",
buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]);
goto err;
}
diff --git a/hw/milkymist-pfpu.c b/hw/milkymist-pfpu.c
index 94e631510f..306d1ce287 100644
--- a/hw/milkymist-pfpu.c
+++ b/hw/milkymist-pfpu.c
@@ -301,7 +301,7 @@ static int pfpu_decode_insn(MilkymistPFPUState *s)
} break;
default:
- error_report("milkymist_pfpu: unknown opcode %d\n", op);
+ error_report("milkymist_pfpu: unknown opcode %d", op);
break;
}
@@ -358,7 +358,7 @@ static void pfpu_start(MilkymistPFPUState *s)
/* decode at most MICROCODE_WORDS instructions */
if (i++ >= MICROCODE_WORDS) {
error_report("milkymist_pfpu: too many instructions "
- "executed in microcode. No VECTOUT?\n");
+ "executed in microcode. No VECTOUT?");
break;
}
}
diff --git a/hw/milkymist-softusb.c b/hw/milkymist-softusb.c
index 028f3b79ac..5ab35c3827 100644
--- a/hw/milkymist-softusb.c
+++ b/hw/milkymist-softusb.c
@@ -131,7 +131,7 @@ static inline void softusb_read_dmem(MilkymistSoftUsbState *s,
{
if (offset + len >= s->dmem_size) {
error_report("milkymist_softusb: read dmem out of bounds "
- "at offset 0x%x, len %d\n", offset, len);
+ "at offset 0x%x, len %d", offset, len);
return;
}
@@ -143,7 +143,7 @@ static inline void softusb_write_dmem(MilkymistSoftUsbState *s,
{
if (offset + len >= s->dmem_size) {
error_report("milkymist_softusb: write dmem out of bounds "
- "at offset 0x%x, len %d\n", offset, len);
+ "at offset 0x%x, len %d", offset, len);
return;
}
@@ -155,7 +155,7 @@ static inline void softusb_read_pmem(MilkymistSoftUsbState *s,
{
if (offset + len >= s->pmem_size) {
error_report("milkymist_softusb: read pmem out of bounds "
- "at offset 0x%x, len %d\n", offset, len);
+ "at offset 0x%x, len %d", offset, len);
return;
}
@@ -167,7 +167,7 @@ static inline void softusb_write_pmem(MilkymistSoftUsbState *s,
{
if (offset + len >= s->pmem_size) {
error_report("milkymist_softusb: write pmem out of bounds "
- "at offset 0x%x, len %d\n", offset, len);
+ "at offset 0x%x, len %d", offset, len);
return;
}
diff --git a/hw/milkymist-sysctl.c b/hw/milkymist-sysctl.c
index 6bd0cb9740..7b2d544ac3 100644
--- a/hw/milkymist-sysctl.c
+++ b/hw/milkymist-sysctl.c
@@ -119,7 +119,7 @@ static uint32_t sysctl_read(void *opaque, target_phys_addr_t addr)
break;
default:
- error_report("milkymist_sysctl: read access to unkown register 0x"
+ error_report("milkymist_sysctl: read access to unknown register 0x"
TARGET_FMT_plx, addr << 2);
break;
}
@@ -189,7 +189,7 @@ static void sysctl_write(void *opaque, target_phys_addr_t addr, uint32_t value)
break;
default:
- error_report("milkymist_sysctl: write access to unkown register 0x"
+ error_report("milkymist_sysctl: write access to unknown register 0x"
TARGET_FMT_plx, addr << 2);
break;
}
diff --git a/hw/milkymist-tmu2.c b/hw/milkymist-tmu2.c
index 9cebe3173b..790cdcb41c 100644
--- a/hw/milkymist-tmu2.c
+++ b/hw/milkymist-tmu2.c
@@ -352,21 +352,21 @@ static uint32_t tmu2_read(void *opaque, target_phys_addr_t addr)
static void tmu2_check_registers(MilkymistTMU2State *s)
{
if (s->regs[R_BRIGHTNESS] > MAX_BRIGHTNESS) {
- error_report("milkymist_tmu2: max brightness is %d\n", MAX_BRIGHTNESS);
+ error_report("milkymist_tmu2: max brightness is %d", MAX_BRIGHTNESS);
}
if (s->regs[R_ALPHA] > MAX_ALPHA) {
- error_report("milkymist_tmu2: max alpha is %d\n", MAX_ALPHA);
+ error_report("milkymist_tmu2: max alpha is %d", MAX_ALPHA);
}
if (s->regs[R_VERTICESADDR] & 0x07) {
error_report("milkymist_tmu2: vertex mesh address has to be 64-bit "
- "aligned\n");
+ "aligned");
}
if (s->regs[R_TEXFBUF] & 0x01) {
error_report("milkymist_tmu2: texture buffer address has to be "
- "16-bit aligned\n");
+ "16-bit aligned");
}
}
diff --git a/hw/msi.c b/hw/msi.c
index b087fe52bb..e8c56079aa 100644
--- a/hw/msi.c
+++ b/hw/msi.c
@@ -172,7 +172,7 @@ void msi_uninit(struct PCIDevice *dev)
}
flags = pci_get_word(dev->config + msi_flags_off(dev));
cap_size = msi_cap_sizeof(flags);
- pci_del_capability(dev, PCI_CAP_ID_MSIX, cap_size);
+ pci_del_capability(dev, PCI_CAP_ID_MSI, cap_size);
dev->cap_present &= ~QEMU_PCI_CAP_MSI;
MSI_DEV_PRINTF(dev, "uninit\n");
diff --git a/hw/msix.c b/hw/msix.c
index af40e266fe..03d7becaaf 100644
--- a/hw/msix.c
+++ b/hw/msix.c
@@ -16,9 +16,6 @@
#include "pci.h"
#include "range.h"
-/* MSI-X capability structure */
-#define MSIX_TABLE_OFFSET 4
-#define MSIX_PBA_OFFSET 8
#define MSIX_CAP_LENGTH 12
/* MSI enable bit and maskall bit are in byte 1 in FLAGS register */
@@ -26,14 +23,6 @@
#define MSIX_ENABLE_MASK (PCI_MSIX_FLAGS_ENABLE >> 8)
#define MSIX_MASKALL_MASK (PCI_MSIX_FLAGS_MASKALL >> 8)
-/* MSI-X table format */
-#define MSIX_MSG_ADDR 0
-#define MSIX_MSG_UPPER_ADDR 4
-#define MSIX_MSG_DATA 8
-#define MSIX_VECTOR_CTRL 12
-#define MSIX_ENTRY_SIZE 16
-#define MSIX_VECTOR_MASK 0x1
-
/* How much space does an MSIX table need. */
/* The spec requires giving the table structure
* a 4K aligned region all by itself. */
@@ -82,9 +71,9 @@ static int msix_add_config(struct PCIDevice *pdev, unsigned short nentries,
pci_set_word(config + PCI_MSIX_FLAGS, nentries - 1);
/* Table on top of BAR */
- pci_set_long(config + MSIX_TABLE_OFFSET, bar_size | bar_nr);
+ pci_set_long(config + PCI_MSIX_TABLE, bar_size | bar_nr);
/* Pending bits on top of that */
- pci_set_long(config + MSIX_PBA_OFFSET, (bar_size + MSIX_PAGE_PENDING) |
+ pci_set_long(config + PCI_MSIX_PBA, (bar_size + MSIX_PAGE_PENDING) |
bar_nr);
pdev->msix_cap = config_offset;
/* Make flags bit writable. */
@@ -140,9 +129,10 @@ static int msix_function_masked(PCIDevice *dev)
static int msix_is_masked(PCIDevice *dev, int vector)
{
- unsigned offset = vector * MSIX_ENTRY_SIZE + MSIX_VECTOR_CTRL;
+ unsigned offset =
+ vector * PCI_MSIX_ENTRY_SIZE + PCI_MSIX_ENTRY_VECTOR_CTRL;
return msix_function_masked(dev) ||
- dev->msix_table_page[offset] & MSIX_VECTOR_MASK;
+ dev->msix_table_page[offset] & PCI_MSIX_ENTRY_CTRL_MASKBIT;
}
static void msix_handle_mask_update(PCIDevice *dev, int vector)
@@ -184,7 +174,7 @@ static void msix_mmio_writel(void *opaque, target_phys_addr_t addr,
{
PCIDevice *dev = opaque;
unsigned int offset = addr & (MSIX_PAGE_SIZE - 1) & ~0x3;
- int vector = offset / MSIX_ENTRY_SIZE;
+ int vector = offset / PCI_MSIX_ENTRY_SIZE;
pci_set_long(dev->msix_table_page + offset, val);
msix_handle_mask_update(dev, vector);
}
@@ -208,7 +198,7 @@ void msix_mmio_map(PCIDevice *d, int region_num,
pcibus_t addr, pcibus_t size, int type)
{
uint8_t *config = d->config + d->msix_cap;
- uint32_t table = pci_get_long(config + MSIX_TABLE_OFFSET);
+ uint32_t table = pci_get_long(config + PCI_MSIX_TABLE);
uint32_t offset = table & ~(MSIX_PAGE_SIZE - 1);
/* TODO: for assigned devices, we'll want to make it possible to map
* pending bits separately in case they are in a separate bar. */
@@ -226,8 +216,9 @@ static void msix_mask_all(struct PCIDevice *dev, unsigned nentries)
{
int vector;
for (vector = 0; vector < nentries; ++vector) {
- unsigned offset = vector * MSIX_ENTRY_SIZE + MSIX_VECTOR_CTRL;
- dev->msix_table_page[offset] |= MSIX_VECTOR_MASK;
+ unsigned offset =
+ vector * PCI_MSIX_ENTRY_SIZE + PCI_MSIX_ENTRY_VECTOR_CTRL;
+ dev->msix_table_page[offset] |= PCI_MSIX_ENTRY_CTRL_MASKBIT;
}
}
@@ -313,7 +304,7 @@ void msix_save(PCIDevice *dev, QEMUFile *f)
return;
}
- qemu_put_buffer(f, dev->msix_table_page, n * MSIX_ENTRY_SIZE);
+ qemu_put_buffer(f, dev->msix_table_page, n * PCI_MSIX_ENTRY_SIZE);
qemu_put_buffer(f, dev->msix_table_page + MSIX_PAGE_PENDING, (n + 7) / 8);
}
@@ -327,7 +318,7 @@ void msix_load(PCIDevice *dev, QEMUFile *f)
}
msix_free_irq_entries(dev);
- qemu_get_buffer(f, dev->msix_table_page, n * MSIX_ENTRY_SIZE);
+ qemu_get_buffer(f, dev->msix_table_page, n * PCI_MSIX_ENTRY_SIZE);
qemu_get_buffer(f, dev->msix_table_page + MSIX_PAGE_PENDING, (n + 7) / 8);
}
@@ -355,7 +346,7 @@ uint32_t msix_bar_size(PCIDevice *dev)
/* Send an MSI-X message */
void msix_notify(PCIDevice *dev, unsigned vector)
{
- uint8_t *table_entry = dev->msix_table_page + vector * MSIX_ENTRY_SIZE;
+ uint8_t *table_entry = dev->msix_table_page + vector * PCI_MSIX_ENTRY_SIZE;
uint64_t address;
uint32_t data;
@@ -366,9 +357,8 @@ void msix_notify(PCIDevice *dev, unsigned vector)
return;
}
- address = pci_get_long(table_entry + MSIX_MSG_UPPER_ADDR);
- address = (address << 32) | pci_get_long(table_entry + MSIX_MSG_ADDR);
- data = pci_get_long(table_entry + MSIX_MSG_DATA);
+ address = pci_get_quad(table_entry + PCI_MSIX_ENTRY_LOWER_ADDR);
+ data = pci_get_long(table_entry + PCI_MSIX_ENTRY_DATA);
stl_phys(address, data);
}
diff --git a/hw/ne2000.c b/hw/ne2000.c
index b668ad1070..f8acaaeeb6 100644
--- a/hw/ne2000.c
+++ b/hw/ne2000.c
@@ -721,9 +721,6 @@ static int pci_ne2000_init(PCIDevice *pci_dev)
uint8_t *pci_conf;
pci_conf = d->dev.config;
- pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_REALTEK);
- pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_REALTEK_8029);
- pci_config_set_class(pci_conf, PCI_CLASS_NETWORK_ETHERNET);
/* TODO: RST# value should be 0. PCI spec 6.2.4 */
pci_conf[PCI_INTERRUPT_PIN] = 1; // interrupt pin 0
@@ -767,6 +764,9 @@ static PCIDeviceInfo ne2000_info = {
.qdev.vmsd = &vmstate_pci_ne2000,
.init = pci_ne2000_init,
.exit = pci_ne2000_exit,
+ .vendor_id = PCI_VENDOR_ID_REALTEK,
+ .device_id = PCI_DEVICE_ID_REALTEK_8029,
+ .class_id = PCI_CLASS_NETWORK_ETHERNET,
.qdev.props = (Property[]) {
DEFINE_NIC_PROPERTIES(PCINE2000State, ne2000.c),
DEFINE_PROP_END_OF_LIST(),
diff --git a/hw/pc.h b/hw/pc.h
index 0dcbee7ca5..6d5730b26b 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -176,7 +176,6 @@ struct PCII440FXState;
typedef struct PCII440FXState PCII440FXState;
PCIBus *i440fx_init(PCII440FXState **pi440fx_state, int *piix_devfn, qemu_irq *pic, ram_addr_t ram_size);
-PCIBus *i440fx_xen_init(PCII440FXState **pi440fx_state, int *piix3_devfn, qemu_irq *pic, ram_addr_t ram_size);
void i440fx_init_memory_mappings(PCII440FXState *d);
/* piix4.c */
diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index 9a22a8afc8..c5c16b4571 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -124,11 +124,7 @@ static void pc_init1(ram_addr_t ram_size,
isa_irq = qemu_allocate_irqs(isa_irq_handler, isa_irq_state, 24);
if (pci_enabled) {
- if (!xen_enabled()) {
- pci_bus = i440fx_init(&i440fx_state, &piix3_devfn, isa_irq, ram_size);
- } else {
- pci_bus = i440fx_xen_init(&i440fx_state, &piix3_devfn, isa_irq, ram_size);
- }
+ pci_bus = i440fx_init(&i440fx_state, &piix3_devfn, isa_irq, ram_size);
} else {
pci_bus = NULL;
i440fx_state = NULL;
@@ -140,6 +136,10 @@ static void pc_init1(ram_addr_t ram_size,
pc_vga_init(pci_enabled? pci_bus: NULL);
+ if (xen_enabled()) {
+ pci_create_simple(pci_bus, -1, "xen-platform");
+ }
+
/* init basic PC hardware */
pc_basic_device_init(isa_irq, &rtc_state, xen_enabled());
@@ -288,6 +288,18 @@ static QEMUMachine pc_machine_v0_13 = {
.driver = "PCI",
.property = "command_serr_enable",
.value = "off",
+ },{
+ .driver = "virtio-blk-pci",
+ .property = "event_idx",
+ .value = "off",
+ },{
+ .driver = "virtio-serial-pci",
+ .property = "event_idx",
+ .value = "off",
+ },{
+ .driver = "virtio-net-pci",
+ .property = "event_idx",
+ .value = "off",
},
{ /* end of list */ }
},
@@ -319,6 +331,18 @@ static QEMUMachine pc_machine_v0_12 = {
.driver = "PCI",
.property = "command_serr_enable",
.value = "off",
+ },{
+ .driver = "virtio-blk-pci",
+ .property = "event_idx",
+ .value = "off",
+ },{
+ .driver = "virtio-serial-pci",
+ .property = "event_idx",
+ .value = "off",
+ },{
+ .driver = "virtio-net-pci",
+ .property = "event_idx",
+ .value = "off",
},
{ /* end of list */ }
}
@@ -358,6 +382,18 @@ static QEMUMachine pc_machine_v0_11 = {
.driver = "PCI",
.property = "command_serr_enable",
.value = "off",
+ },{
+ .driver = "virtio-blk-pci",
+ .property = "event_idx",
+ .value = "off",
+ },{
+ .driver = "virtio-serial-pci",
+ .property = "event_idx",
+ .value = "off",
+ },{
+ .driver = "virtio-net-pci",
+ .property = "event_idx",
+ .value = "off",
},
{ /* end of list */ }
}
@@ -409,6 +445,18 @@ static QEMUMachine pc_machine_v0_10 = {
.driver = "PCI",
.property = "command_serr_enable",
.value = "off",
+ },{
+ .driver = "virtio-blk-pci",
+ .property = "event_idx",
+ .value = "off",
+ },{
+ .driver = "virtio-serial-pci",
+ .property = "event_idx",
+ .value = "off",
+ },{
+ .driver = "virtio-net-pci",
+ .property = "event_idx",
+ .value = "off",
},
{ /* end of list */ }
},
diff --git a/hw/pci.c b/hw/pci.c
index 1d297d6c7c..b904a4ecb6 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -726,10 +726,11 @@ static void pci_config_free(PCIDevice *pci_dev)
/* -1 for devfn means auto assign */
static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
const char *name, int devfn,
- PCIConfigReadFunc *config_read,
- PCIConfigWriteFunc *config_write,
- bool is_bridge)
+ const PCIDeviceInfo *info)
{
+ PCIConfigReadFunc *config_read = info->config_read;
+ PCIConfigWriteFunc *config_write = info->config_write;
+
if (devfn < 0) {
for(devfn = bus->devfn_min ; devfn < ARRAY_SIZE(bus->devices);
devfn += PCI_FUNC_MAX) {
@@ -750,13 +751,29 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
pci_dev->irq_state = 0;
pci_config_alloc(pci_dev);
- if (!is_bridge) {
- pci_set_default_subsystem_id(pci_dev);
+ pci_config_set_vendor_id(pci_dev->config, info->vendor_id);
+ pci_config_set_device_id(pci_dev->config, info->device_id);
+ pci_config_set_revision(pci_dev->config, info->revision);
+ pci_config_set_class(pci_dev->config, info->class_id);
+
+ if (!info->is_bridge) {
+ if (info->subsystem_vendor_id || info->subsystem_id) {
+ pci_set_word(pci_dev->config + PCI_SUBSYSTEM_VENDOR_ID,
+ info->subsystem_vendor_id);
+ pci_set_word(pci_dev->config + PCI_SUBSYSTEM_ID,
+ info->subsystem_id);
+ } else {
+ pci_set_default_subsystem_id(pci_dev);
+ }
+ } else {
+ /* subsystem_vendor_id/subsystem_id are only for header type 0 */
+ assert(!info->subsystem_vendor_id);
+ assert(!info->subsystem_id);
}
pci_init_cmask(pci_dev);
pci_init_wmask(pci_dev);
pci_init_w1cmask(pci_dev);
- if (is_bridge) {
+ if (info->is_bridge) {
pci_init_wmask_bridge(pci_dev);
}
if (pci_init_multifunction(bus, pci_dev)) {
@@ -783,17 +800,20 @@ static void do_pci_unregister_device(PCIDevice *pci_dev)
pci_config_free(pci_dev);
}
+/* TODO: obsolete. eliminate this once all pci devices are qdevifed. */
PCIDevice *pci_register_device(PCIBus *bus, const char *name,
int instance_size, int devfn,
PCIConfigReadFunc *config_read,
PCIConfigWriteFunc *config_write)
{
PCIDevice *pci_dev;
+ PCIDeviceInfo info = {
+ .config_read = config_read,
+ .config_write = config_write,
+ };
pci_dev = qemu_mallocz(instance_size);
- pci_dev = do_pci_register_device(pci_dev, bus, name, devfn,
- config_read, config_write,
- PCI_HEADER_TYPE_NORMAL);
+ pci_dev = do_pci_register_device(pci_dev, bus, name, devfn, &info);
if (pci_dev == NULL) {
hw_error("PCI: can't register device\n");
}
@@ -1643,7 +1663,7 @@ static int pci_qdev_init(DeviceState *qdev, DeviceInfo *base)
PCIDevice *pci_dev = (PCIDevice *)qdev;
PCIDeviceInfo *info = container_of(base, PCIDeviceInfo, qdev);
PCIBus *bus;
- int devfn, rc;
+ int rc;
bool is_default_rom;
/* initialize cap_present for pci_is_express() and pci_config_size() */
@@ -1652,10 +1672,8 @@ static int pci_qdev_init(DeviceState *qdev, DeviceInfo *base)
}
bus = FROM_QBUS(PCIBus, qdev_get_parent_bus(qdev));
- devfn = pci_dev->devfn;
- pci_dev = do_pci_register_device(pci_dev, bus, base->name, devfn,
- info->config_read, info->config_write,
- info->is_bridge);
+ pci_dev = do_pci_register_device(pci_dev, bus, base->name,
+ pci_dev->devfn, info);
if (pci_dev == NULL)
return -1;
if (qdev->hotplugged && info->no_hotplug) {
@@ -1663,10 +1681,12 @@ static int pci_qdev_init(DeviceState *qdev, DeviceInfo *base)
do_pci_unregister_device(pci_dev);
return -1;
}
- rc = info->init(pci_dev);
- if (rc != 0) {
- do_pci_unregister_device(pci_dev);
- return rc;
+ if (info->init) {
+ rc = info->init(pci_dev);
+ if (rc != 0) {
+ do_pci_unregister_device(pci_dev);
+ return rc;
+ }
}
/* rom loading */
diff --git a/hw/pci.h b/hw/pci.h
index 0d288ce000..c220745c98 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -433,6 +433,13 @@ typedef struct {
PCIConfigReadFunc *config_read;
PCIConfigWriteFunc *config_write;
+ uint16_t vendor_id;
+ uint16_t device_id;
+ uint8_t revision;
+ uint16_t class_id;
+ uint16_t subsystem_vendor_id; /* only for header type = 0 */
+ uint16_t subsystem_id; /* only for header type = 0 */
+
/*
* pci-to-pci bridge or normal device.
* This doesn't mean pci host switch.
diff --git a/hw/pci_ids.h b/hw/pci_ids.h
index d9457ed3f4..d94578c87d 100644
--- a/hw/pci_ids.h
+++ b/hw/pci_ids.h
@@ -109,3 +109,5 @@
#define PCI_DEVICE_ID_INTEL_82371AB 0x7111
#define PCI_DEVICE_ID_INTEL_82371AB_2 0x7112
#define PCI_DEVICE_ID_INTEL_82371AB_3 0x7113
+
+#define PCI_VENDOR_ID_XENSOURCE 0x5853
diff --git a/hw/pci_regs.h b/hw/pci_regs.h
index 5a5ab89c7f..e8840964ac 100644
--- a/hw/pci_regs.h
+++ b/hw/pci_regs.h
@@ -300,12 +300,22 @@
#define PCI_MSI_DATA_64 12 /* 16 bits of data for 64-bit devices */
#define PCI_MSI_MASK_64 16 /* Mask bits register for 64-bit devices */
-/* MSI-X registers (these are at offset PCI_MSIX_FLAGS) */
+/* MSI-X registers */
#define PCI_MSIX_FLAGS 2
#define PCI_MSIX_FLAGS_QSIZE 0x7FF
#define PCI_MSIX_FLAGS_ENABLE (1 << 15)
#define PCI_MSIX_FLAGS_MASKALL (1 << 14)
-#define PCI_MSIX_FLAGS_BIRMASK (7 << 0)
+#define PCI_MSIX_TABLE 4
+#define PCI_MSIX_PBA 8
+#define PCI_MSIX_FLAGS_BIRMASK (7 << 0)
+
+/* MSI-X entry's format */
+#define PCI_MSIX_ENTRY_SIZE 16
+#define PCI_MSIX_ENTRY_LOWER_ADDR 0
+#define PCI_MSIX_ENTRY_UPPER_ADDR 4
+#define PCI_MSIX_ENTRY_DATA 8
+#define PCI_MSIX_ENTRY_VECTOR_CTRL 12
+#define PCI_MSIX_ENTRY_CTRL_MASKBIT 1
/* CompactPCI Hotswap Register */
@@ -365,6 +375,11 @@
#define PCI_X_STATUS_266MHZ 0x40000000 /* 266 MHz capable */
#define PCI_X_STATUS_533MHZ 0x80000000 /* 533 MHz capable */
+/* PCI Bridge Subsystem ID registers */
+
+#define PCI_SSVID_VENDOR_ID 4 /* PCI-Bridge subsystem vendor id register */
+#define PCI_SSVID_DEVICE_ID 6 /* PCI-Bridge subsystem device id register */
+
/* PCI Express capability registers */
#define PCI_EXP_FLAGS 2 /* Capabilities register */
@@ -420,7 +435,7 @@
#define PCI_EXP_LNKCAP_L0SEL 0x00007000 /* L0s Exit Latency */
#define PCI_EXP_LNKCAP_L1EL 0x00038000 /* L1 Exit Latency */
#define PCI_EXP_LNKCAP_CLKPM 0x00040000 /* L1 Clock Power Management */
-#define PCI_EXP_LNKCAP_SDERC 0x00080000 /* Suprise Down Error Reporting Capable */
+#define PCI_EXP_LNKCAP_SDERC 0x00080000 /* Surprise Down Error Reporting Capable */
#define PCI_EXP_LNKCAP_DLLLARC 0x00100000 /* Data Link Layer Link Active Reporting Capable */
#define PCI_EXP_LNKCAP_LBNC 0x00200000 /* Link Bandwidth Notification Capability */
#define PCI_EXP_LNKCAP_PN 0xff000000 /* Port Number */
@@ -437,7 +452,10 @@
#define PCI_EXP_LNKCTL_LABIE 0x0800 /* Lnk Autonomous Bandwidth Interrupt Enable */
#define PCI_EXP_LNKSTA 18 /* Link Status */
#define PCI_EXP_LNKSTA_CLS 0x000f /* Current Link Speed */
+#define PCI_EXP_LNKSTA_CLS_2_5GB 0x01 /* Current Link Speed 2.5GT/s */
+#define PCI_EXP_LNKSTA_CLS_5_0GB 0x02 /* Current Link Speed 5.0GT/s */
#define PCI_EXP_LNKSTA_NLW 0x03f0 /* Nogotiated Link Width */
+#define PCI_EXP_LNKSTA_NLW_SHIFT 4 /* start of NLW mask in link status */
#define PCI_EXP_LNKSTA_LT 0x0800 /* Link Training */
#define PCI_EXP_LNKSTA_SLC 0x1000 /* Slot Clock Configuration */
#define PCI_EXP_LNKSTA_DLLLA 0x2000 /* Data Link Layer Link Active */
@@ -486,10 +504,22 @@
#define PCI_EXP_RTCTL_CRSSVE 0x10 /* CRS Software Visibility Enable */
#define PCI_EXP_RTCAP 30 /* Root Capabilities */
#define PCI_EXP_RTSTA 32 /* Root Status */
+#define PCI_EXP_RTSTA_PME 0x10000 /* PME status */
+#define PCI_EXP_RTSTA_PENDING 0x20000 /* PME pending */
#define PCI_EXP_DEVCAP2 36 /* Device Capabilities 2 */
#define PCI_EXP_DEVCAP2_ARI 0x20 /* Alternative Routing-ID */
+#define PCI_EXP_DEVCAP2_LTR 0x800 /* Latency tolerance reporting */
+#define PCI_EXP_OBFF_MASK 0xc0000 /* OBFF support mechanism */
+#define PCI_EXP_OBFF_MSG 0x40000 /* New message signaling */
+#define PCI_EXP_OBFF_WAKE 0x80000 /* Re-use WAKE# for OBFF */
#define PCI_EXP_DEVCTL2 40 /* Device Control 2 */
#define PCI_EXP_DEVCTL2_ARI 0x20 /* Alternative Routing-ID */
+#define PCI_EXP_IDO_REQ_EN 0x100 /* ID-based ordering request enable */
+#define PCI_EXP_IDO_CMP_EN 0x200 /* ID-based ordering completion enable */
+#define PCI_EXP_LTR_EN 0x400 /* Latency tolerance reporting */
+#define PCI_EXP_OBFF_MSGA_EN 0x2000 /* OBFF enable with Message type A */
+#define PCI_EXP_OBFF_MSGB_EN 0x4000 /* OBFF enable with Message type B */
+#define PCI_EXP_OBFF_WAKE_EN 0x6000 /* OBFF using WAKE# signaling */
#define PCI_EXP_LNKCTL2 48 /* Link Control 2 */
#define PCI_EXP_SLTCTL2 56 /* Slot Control 2 */
@@ -502,9 +532,12 @@
#define PCI_EXT_CAP_ID_VC 2
#define PCI_EXT_CAP_ID_DSN 3
#define PCI_EXT_CAP_ID_PWR 4
+#define PCI_EXT_CAP_ID_VNDR 11
+#define PCI_EXT_CAP_ID_ACS 13
#define PCI_EXT_CAP_ID_ARI 14
#define PCI_EXT_CAP_ID_ATS 15
#define PCI_EXT_CAP_ID_SRIOV 16
+#define PCI_EXT_CAP_ID_LTR 24
/* Advanced Error Reporting */
#define PCI_ERR_UNCOR_STATUS 4 /* Uncorrectable Error Status */
@@ -556,8 +589,7 @@
#define PCI_ERR_ROOT_FIRST_FATAL 0x00000010 /* First Fatal */
#define PCI_ERR_ROOT_NONFATAL_RCV 0x00000020 /* Non-Fatal Received */
#define PCI_ERR_ROOT_FATAL_RCV 0x00000040 /* Fatal Received */
-#define PCI_ERR_ROOT_COR_SRC 52
-#define PCI_ERR_ROOT_SRC 54
+#define PCI_ERR_ROOT_ERR_SRC 52 /* Error Source Identification */
/* Virtual Channel */
#define PCI_VC_PORT_REG1 4
@@ -662,4 +694,22 @@
#define PCI_SRIOV_VFM_MO 0x2 /* Active.MigrateOut */
#define PCI_SRIOV_VFM_AV 0x3 /* Active.Available */
+#define PCI_LTR_MAX_SNOOP_LAT 0x4
+#define PCI_LTR_MAX_NOSNOOP_LAT 0x6
+#define PCI_LTR_VALUE_MASK 0x000003ff
+#define PCI_LTR_SCALE_MASK 0x00001c00
+#define PCI_LTR_SCALE_SHIFT 10
+
+/* Access Control Service */
+#define PCI_ACS_CAP 0x04 /* ACS Capability Register */
+#define PCI_ACS_SV 0x01 /* Source Validation */
+#define PCI_ACS_TB 0x02 /* Translation Blocking */
+#define PCI_ACS_RR 0x04 /* P2P Request Redirect */
+#define PCI_ACS_CR 0x08 /* P2P Completion Redirect */
+#define PCI_ACS_UF 0x10 /* Upstream Forwarding */
+#define PCI_ACS_EC 0x20 /* P2P Egress Control */
+#define PCI_ACS_DT 0x40 /* Direct Translated P2P */
+#define PCI_ACS_CTRL 0x06 /* ACS Control Register */
+#define PCI_ACS_EGRESS_CTL_V 0x08 /* ACS Egress Control Vector */
+
#endif /* LINUX_PCI_REGS_H */
diff --git a/hw/pcie_aer.c b/hw/pcie_aer.c
index f08d3c79f3..be019c7c0a 100644
--- a/hw/pcie_aer.c
+++ b/hw/pcie_aer.c
@@ -38,6 +38,9 @@
#define PCIE_DEV_PRINTF(dev, fmt, ...) \
PCIE_DPRINTF("%s:%x "fmt, (dev)->name, (dev)->devfn, ## __VA_ARGS__)
+#define PCI_ERR_SRC_COR_OFFS 0
+#define PCI_ERR_SRC_UNCOR_OFFS 2
+
/* From 6.2.7 Error Listing and Rules. Table 6-2, 6-3 and 6-4 */
static uint32_t pcie_aer_uncor_default_severity(uint32_t status)
{
@@ -320,7 +323,8 @@ static void pcie_aer_msg_root_port(PCIDevice *dev, const PCIEAERMsg *msg)
if (root_status & PCI_ERR_ROOT_COR_RCV) {
root_status |= PCI_ERR_ROOT_MULTI_COR_RCV;
} else {
- pci_set_word(aer_cap + PCI_ERR_ROOT_COR_SRC, msg->source_id);
+ pci_set_word(aer_cap + PCI_ERR_ROOT_ERR_SRC + PCI_ERR_SRC_COR_OFFS,
+ msg->source_id);
}
root_status |= PCI_ERR_ROOT_COR_RCV;
break;
@@ -341,7 +345,8 @@ static void pcie_aer_msg_root_port(PCIDevice *dev, const PCIEAERMsg *msg)
if (root_status & PCI_ERR_ROOT_UNCOR_RCV) {
root_status |= PCI_ERR_ROOT_MULTI_UNCOR_RCV;
} else {
- pci_set_word(aer_cap + PCI_ERR_ROOT_SRC, msg->source_id);
+ pci_set_word(aer_cap + PCI_ERR_ROOT_ERR_SRC +
+ PCI_ERR_SRC_UNCOR_OFFS, msg->source_id);
}
root_status |= PCI_ERR_ROOT_UNCOR_RCV;
}
diff --git a/hw/pcnet-pci.c b/hw/pcnet-pci.c
index 9415a1ecf5..216cf81492 100644
--- a/hw/pcnet-pci.c
+++ b/hw/pcnet-pci.c
@@ -265,12 +265,8 @@ static int pci_pcnet_init(PCIDevice *pci_dev)
pci_conf = pci_dev->config;
- pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_AMD);
- pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_AMD_LANCE);
pci_set_word(pci_conf + PCI_STATUS,
PCI_STATUS_FAST_BACK | PCI_STATUS_DEVSEL_MEDIUM);
- pci_conf[PCI_REVISION_ID] = 0x10;
- pci_config_set_class(pci_conf, PCI_CLASS_NETWORK_ETHERNET);
pci_set_word(pci_conf + PCI_SUBSYSTEM_VENDOR_ID, 0x0);
pci_set_word(pci_conf + PCI_SUBSYSTEM_ID, 0x0);
@@ -318,6 +314,10 @@ static PCIDeviceInfo pcnet_info = {
.qdev.vmsd = &vmstate_pci_pcnet,
.init = pci_pcnet_init,
.exit = pci_pcnet_uninit,
+ .vendor_id = PCI_VENDOR_ID_AMD,
+ .device_id = PCI_DEVICE_ID_AMD_LANCE,
+ .revision = 0x10,
+ .class_id = PCI_CLASS_NETWORK_ETHERNET,
.qdev.props = (Property[]) {
DEFINE_NIC_PROPERTIES(PCIPCNetState, state.conf),
DEFINE_PROP_END_OF_LIST(),
diff --git a/hw/piix4.c b/hw/piix4.c
index 71f1f84dc0..9590e7b140 100644
--- a/hw/piix4.c
+++ b/hw/piix4.c
@@ -86,15 +86,8 @@ static const VMStateDescription vmstate_piix4 = {
static int piix4_initfn(PCIDevice *dev)
{
PIIX4State *d = DO_UPCAST(PIIX4State, dev, dev);
- uint8_t *pci_conf;
isa_bus_new(&d->dev.qdev);
-
- pci_conf = d->dev.config;
- pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_INTEL);
- pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_INTEL_82371AB_0); // 82371AB/EB/MB PIIX4 PCI-to-ISA bridge
- pci_config_set_class(pci_conf, PCI_CLASS_BRIDGE_ISA);
-
piix4_dev = &d->dev;
qemu_register_reset(piix4_reset, d);
return 0;
@@ -117,6 +110,9 @@ static PCIDeviceInfo piix4_info[] = {
.qdev.no_user = 1,
.no_hotplug = 1,
.init = piix4_initfn,
+ .vendor_id = PCI_VENDOR_ID_INTEL,
+ .device_id = PCI_DEVICE_ID_INTEL_82371AB_0, // 82371AB/EB/MB PIIX4 PCI-to-ISA bridge
+ .class_id = PCI_CLASS_BRIDGE_ISA,
},{
/* end of list */
}
diff --git a/hw/piix_pci.c b/hw/piix_pci.c
index 85a320e729..26ce90451a 100644
--- a/hw/piix_pci.c
+++ b/hw/piix_pci.c
@@ -40,6 +40,7 @@ typedef PCIHostState I440FXState;
#define PIIX_NUM_PIC_IRQS 16 /* i8259 * 2 */
#define PIIX_NUM_PIRQS 4ULL /* PIRQ[A-D] */
+#define XEN_PIIX_NUM_PIRQS 128ULL
#define PIIX_PIRQC 0x60
typedef struct PIIX3State {
@@ -78,6 +79,8 @@ struct PCII440FXState {
#define I440FX_SMRAM 0x72
static void piix3_set_irq(void *opaque, int pirq, int level);
+static void piix3_write_config_xen(PCIDevice *dev,
+ uint32_t address, uint32_t val, int len);
/* return the global irq number corresponding to a given device irq
pin. We could also use the bus number to have a more precise
@@ -173,13 +176,6 @@ static void i440fx_write_config(PCIDevice *dev,
}
}
-static void i440fx_write_config_xen(PCIDevice *dev,
- uint32_t address, uint32_t val, int len)
-{
- xen_piix_pci_write_config_client(address, val, len);
- i440fx_write_config(dev, address, val, len);
-}
-
static int i440fx_load_old(QEMUFile* f, void *opaque, int version_id)
{
PCII440FXState *d = opaque;
@@ -236,11 +232,6 @@ static int i440fx_initfn(PCIDevice *dev)
{
PCII440FXState *d = DO_UPCAST(PCII440FXState, dev, dev);
- pci_config_set_vendor_id(d->dev.config, PCI_VENDOR_ID_INTEL);
- pci_config_set_device_id(d->dev.config, PCI_DEVICE_ID_INTEL_82441);
- d->dev.config[0x08] = 0x02; // revision
- pci_config_set_class(d->dev.config, PCI_CLASS_BRIDGE_HOST);
-
d->dev.config[I440FX_SMRAM] = 0x02;
cpu_smm_register(&i440fx_set_smm, d);
@@ -267,8 +258,21 @@ static PCIBus *i440fx_common_init(const char *device_name,
d = pci_create_simple(b, 0, device_name);
*pi440fx_state = DO_UPCAST(PCII440FXState, dev, d);
- piix3 = DO_UPCAST(PIIX3State, dev,
- pci_create_simple_multifunction(b, -1, true, "PIIX3"));
+ /* Xen supports additional interrupt routes from the PCI devices to
+ * the IOAPIC: the four pins of each PCI device on the bus are also
+ * connected to the IOAPIC directly.
+ * These additional routes can be discovered through ACPI. */
+ if (xen_enabled()) {
+ piix3 = DO_UPCAST(PIIX3State, dev,
+ pci_create_simple_multifunction(b, -1, true, "PIIX3-xen"));
+ pci_bus_irqs(b, xen_piix3_set_irq, xen_pci_slot_get_pirq,
+ piix3, XEN_PIIX_NUM_PIRQS);
+ } else {
+ piix3 = DO_UPCAST(PIIX3State, dev,
+ pci_create_simple_multifunction(b, -1, true, "PIIX3"));
+ pci_bus_irqs(b, piix3_set_irq, pci_slot_get_pirq, piix3,
+ PIIX_NUM_PIRQS);
+ }
piix3->pic = pic;
(*pi440fx_state)->piix3 = piix3;
@@ -289,21 +293,6 @@ PCIBus *i440fx_init(PCII440FXState **pi440fx_state, int *piix3_devfn,
PCIBus *b;
b = i440fx_common_init("i440FX", pi440fx_state, piix3_devfn, pic, ram_size);
- pci_bus_irqs(b, piix3_set_irq, pci_slot_get_pirq, (*pi440fx_state)->piix3,
- PIIX_NUM_PIRQS);
-
- return b;
-}
-
-PCIBus *i440fx_xen_init(PCII440FXState **pi440fx_state, int *piix3_devfn,
- qemu_irq *pic, ram_addr_t ram_size)
-{
- PCIBus *b;
-
- b = i440fx_common_init("i440FX-xen", pi440fx_state, piix3_devfn, pic, ram_size);
- pci_bus_irqs(b, xen_piix3_set_irq, xen_pci_slot_get_pirq,
- (*pi440fx_state)->piix3, PIIX_NUM_PIRQS);
-
return b;
}
@@ -365,6 +354,13 @@ static void piix3_write_config(PCIDevice *dev,
}
}
+static void piix3_write_config_xen(PCIDevice *dev,
+ uint32_t address, uint32_t val, int len)
+{
+ xen_piix_pci_write_config_client(address, val, len);
+ piix3_write_config(dev, address, val, len);
+}
+
static void piix3_reset(void *opaque)
{
PIIX3State *d = opaque;
@@ -441,15 +437,8 @@ static const VMStateDescription vmstate_piix3 = {
static int piix3_initfn(PCIDevice *dev)
{
PIIX3State *d = DO_UPCAST(PIIX3State, dev, dev);
- uint8_t *pci_conf;
isa_bus_new(&d->dev.qdev);
-
- pci_conf = d->dev.config;
- pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_INTEL);
- pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_INTEL_82371SB_0); // 82371SB PIIX3 PCI-to-ISA bridge (Step A1)
- pci_config_set_class(pci_conf, PCI_CLASS_BRIDGE_ISA);
-
qemu_register_reset(piix3_reset, d);
return 0;
}
@@ -464,14 +453,10 @@ static PCIDeviceInfo i440fx_info[] = {
.no_hotplug = 1,
.init = i440fx_initfn,
.config_write = i440fx_write_config,
- },{
- .qdev.name = "i440FX-xen",
- .qdev.desc = "Host bridge",
- .qdev.size = sizeof(PCII440FXState),
- .qdev.vmsd = &vmstate_i440fx,
- .qdev.no_user = 1,
- .init = i440fx_initfn,
- .config_write = i440fx_write_config_xen,
+ .vendor_id = PCI_VENDOR_ID_INTEL,
+ .device_id = PCI_DEVICE_ID_INTEL_82441,
+ .revision = 0x02,
+ .class_id = PCI_CLASS_BRIDGE_HOST,
},{
.qdev.name = "PIIX3",
.qdev.desc = "ISA bridge",
@@ -481,6 +466,18 @@ static PCIDeviceInfo i440fx_info[] = {
.no_hotplug = 1,
.init = piix3_initfn,
.config_write = piix3_write_config,
+ .vendor_id = PCI_VENDOR_ID_INTEL,
+ .device_id = PCI_DEVICE_ID_INTEL_82371SB_0, // 82371SB PIIX3 PCI-to-ISA bridge (Step A1)
+ .class_id = PCI_CLASS_BRIDGE_ISA,
+ },{
+ .qdev.name = "PIIX3-xen",
+ .qdev.desc = "ISA bridge",
+ .qdev.size = sizeof(PIIX3State),
+ .qdev.vmsd = &vmstate_piix3,
+ .qdev.no_user = 1,
+ .no_hotplug = 1,
+ .init = piix3_initfn,
+ .config_write = piix3_write_config_xen,
},{
/* end of list */
}
diff --git a/hw/ppce500_pci.c b/hw/ppce500_pci.c
index 069af9691a..fc11af4374 100644
--- a/hw/ppce500_pci.c
+++ b/hw/ppce500_pci.c
@@ -304,20 +304,13 @@ static int e500_pcihost_initfn(SysBusDevice *dev)
return 0;
}
-static int e500_host_bridge_initfn(PCIDevice *dev)
-{
- pci_config_set_vendor_id(dev->config, PCI_VENDOR_ID_FREESCALE);
- pci_config_set_device_id(dev->config, PCI_DEVICE_ID_MPC8533E);
- pci_config_set_class(dev->config, PCI_CLASS_PROCESSOR_POWERPC);
-
- return 0;
-}
-
static PCIDeviceInfo e500_host_bridge_info = {
.qdev.name = "e500-host-bridge",
.qdev.desc = "Host bridge",
.qdev.size = sizeof(PCIDevice),
- .init = e500_host_bridge_initfn,
+ .vendor_id = PCI_VENDOR_ID_FREESCALE,
+ .device_id = PCI_DEVICE_ID_MPC8533E,
+ .class_id = PCI_CLASS_PROCESSOR_POWERPC,
};
static SysBusDeviceInfo e500_pcihost_info = {
diff --git a/hw/qdev.c b/hw/qdev.c
index 9519f5dd57..292b52f8c5 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -371,7 +371,7 @@ void qdev_init_nofail(DeviceState *dev)
DeviceInfo *info = dev->info;
if (qdev_init(dev) < 0) {
- error_report("Initialization of device %s failed\n", info->name);
+ error_report("Initialization of device %s failed", info->name);
exit(1);
}
}
@@ -468,6 +468,7 @@ void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd)
qdev_prop_exists(dev, "vectors")) {
qdev_prop_set_uint32(dev, "vectors", nd->nvectors);
}
+ nd->instantiated = 1;
}
BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
diff --git a/hw/qxl.c b/hw/qxl.c
index 1906e84fab..16316f2bf5 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -1231,7 +1231,6 @@ static int qxl_init_common(PCIQXLDevice *qxl)
break;
}
- pci_config_set_vendor_id(config, REDHAT_PCI_VENDOR_ID);
pci_config_set_device_id(config, pci_device_id);
pci_set_byte(&config[PCI_REVISION_ID], pci_device_rev);
pci_set_byte(&config[PCI_INTERRUPT_PIN], 1);
@@ -1311,7 +1310,6 @@ static int qxl_init_primary(PCIDevice *dev)
qxl0 = qxl;
register_displaychangelistener(vga->ds, &display_listener);
- pci_config_set_class(dev->config, PCI_CLASS_DISPLAY_VGA);
return qxl_init_common(qxl);
}
@@ -1331,7 +1329,6 @@ static int qxl_init_secondary(PCIDevice *dev)
qxl->vga.vram_size);
qxl->vga.vram_ptr = qemu_get_ram_ptr(qxl->vga.vram_offset);
- pci_config_set_class(dev->config, PCI_CLASS_DISPLAY_OTHER);
return qxl_init_common(qxl);
}
@@ -1494,6 +1491,8 @@ static PCIDeviceInfo qxl_info_primary = {
.init = qxl_init_primary,
.config_write = qxl_write_config,
.romfile = "vgabios-qxl.bin",
+ .vendor_id = REDHAT_PCI_VENDOR_ID,
+ .class_id = PCI_CLASS_DISPLAY_VGA,
.qdev.props = (Property[]) {
DEFINE_PROP_UINT32("ram_size", PCIQXLDevice, vga.vram_size, 64 * 1024 * 1024),
DEFINE_PROP_UINT32("vram_size", PCIQXLDevice, vram_size, 64 * 1024 * 1024),
@@ -1512,6 +1511,8 @@ static PCIDeviceInfo qxl_info_secondary = {
.qdev.reset = qxl_reset_handler,
.qdev.vmsd = &qxl_vmstate,
.init = qxl_init_secondary,
+ .vendor_id = REDHAT_PCI_VENDOR_ID,
+ .class_id = PCI_CLASS_DISPLAY_OTHER,
.qdev.props = (Property[]) {
DEFINE_PROP_UINT32("ram_size", PCIQXLDevice, vga.vram_size, 64 * 1024 * 1024),
DEFINE_PROP_UINT32("vram_size", PCIQXLDevice, vram_size, 64 * 1024 * 1024),
diff --git a/hw/rtl8139.c b/hw/rtl8139.c
index 2f8db580d9..5214b8cb7c 100644
--- a/hw/rtl8139.c
+++ b/hw/rtl8139.c
@@ -3457,10 +3457,6 @@ static int pci_rtl8139_init(PCIDevice *dev)
uint8_t *pci_conf;
pci_conf = s->dev.config;
- pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_REALTEK);
- pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_REALTEK_8139);
- pci_conf[PCI_REVISION_ID] = RTL8139_PCI_REVID; /* >=0x20 is for 8139C+ */
- pci_config_set_class(pci_conf, PCI_CLASS_NETWORK_ETHERNET);
pci_conf[PCI_INTERRUPT_PIN] = 1; /* interrupt pin 0 */
/* TODO: start of capability list, but no capability
* list bit in status register, and offset 0xdc seems unused. */
@@ -3514,6 +3510,10 @@ static PCIDeviceInfo rtl8139_info = {
.init = pci_rtl8139_init,
.exit = pci_rtl8139_uninit,
.romfile = "pxe-rtl8139.rom",
+ .vendor_id = PCI_VENDOR_ID_REALTEK,
+ .device_id = PCI_DEVICE_ID_REALTEK_8139,
+ .revision = RTL8139_PCI_REVID, /* >=0x20 is for 8139C+ */
+ .class_id = PCI_CLASS_NETWORK_ETHERNET,
.qdev.props = (Property[]) {
DEFINE_NIC_PROPERTIES(RTL8139State, conf),
DEFINE_PROP_END_OF_LIST(),
diff --git a/hw/sh7750.c b/hw/sh7750.c
index 19d5bf8537..4f279e7e51 100644
--- a/hw/sh7750.c
+++ b/hw/sh7750.c
@@ -29,7 +29,6 @@
#include "sh7750_regs.h"
#include "sh7750_regnames.h"
#include "sh_intc.h"
-#include "exec-all.h"
#include "cpu.h"
#define NB_DEVICES 4
diff --git a/hw/sh_pci.c b/hw/sh_pci.c
index e99d8dbfb5..a076cf2ff0 100644
--- a/hw/sh_pci.c
+++ b/hw/sh_pci.c
@@ -137,8 +137,6 @@ static int sh_pci_init_device(SysBusDevice *dev)
static int sh_pci_host_init(PCIDevice *d)
{
- pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_HITACHI);
- pci_config_set_device_id(d->config, PCI_DEVICE_ID_HITACHI_SH7751R);
pci_set_word(d->config + PCI_COMMAND, PCI_COMMAND_WAIT);
pci_set_word(d->config + PCI_STATUS, PCI_STATUS_CAP_LIST |
PCI_STATUS_FAST_BACK | PCI_STATUS_DEVSEL_MEDIUM);
@@ -149,6 +147,8 @@ static PCIDeviceInfo sh_pci_host_info = {
.qdev.name = "sh_pci_host",
.qdev.size = sizeof(PCIDevice),
.init = sh_pci_host_init,
+ .vendor_id = PCI_VENDOR_ID_HITACHI,
+ .device_id = PCI_DEVICE_ID_HITACHI_SH7751R,
};
static void sh_pci_register_devices(void)
diff --git a/hw/spapr_hcall.c b/hw/spapr_hcall.c
index 43c441dc7d..84da8fc69c 100644
--- a/hw/spapr_hcall.c
+++ b/hw/spapr_hcall.c
@@ -3,7 +3,6 @@
#include "qemu-char.h"
#include "sysemu.h"
#include "qemu-char.h"
-#include "exec-all.h"
#include "exec.h"
#include "helper_regs.h"
#include "hw/spapr.h"
diff --git a/hw/strongarm.c b/hw/strongarm.c
index de08bdf674..0e03d61a1f 100644
--- a/hw/strongarm.c
+++ b/hw/strongarm.c
@@ -1536,14 +1536,14 @@ StrongARMState *sa1110_init(unsigned int sdram_size, const char *rev)
}
if (strncmp(rev, "sa1110", 6)) {
- error_report("Machine requires a SA1110 processor.\n");
+ error_report("Machine requires a SA1110 processor.");
exit(1);
}
s->env = cpu_init(rev);
if (!s->env) {
- error_report("Unable to find CPU definition\n");
+ error_report("Unable to find CPU definition");
exit(1);
}
diff --git a/hw/sun4u.c b/hw/sun4u.c
index 5eb38cf27d..d7dcaf007d 100644
--- a/hw/sun4u.c
+++ b/hw/sun4u.c
@@ -553,15 +553,11 @@ pci_ebus_init1(PCIDevice *s)
{
isa_bus_new(&s->qdev);
- pci_config_set_vendor_id(s->config, PCI_VENDOR_ID_SUN);
- pci_config_set_device_id(s->config, PCI_DEVICE_ID_SUN_EBUS);
s->config[0x04] = 0x06; // command = bus master, pci mem
s->config[0x05] = 0x00;
s->config[0x06] = 0xa0; // status = fast back-to-back, 66MHz, no error
s->config[0x07] = 0x03; // status = medium devsel
- s->config[0x08] = 0x01; // revision
s->config[0x09] = 0x00; // programming i/f
- pci_config_set_class(s->config, PCI_CLASS_BRIDGE_OTHER);
s->config[0x0D] = 0x0a; // latency_timer
pci_register_bar(s, 0, 0x1000000, PCI_BASE_ADDRESS_SPACE_MEMORY,
@@ -575,6 +571,10 @@ static PCIDeviceInfo ebus_info = {
.qdev.name = "ebus",
.qdev.size = sizeof(PCIDevice),
.init = pci_ebus_init1,
+ .vendor_id = PCI_VENDOR_ID_SUN,
+ .device_id = PCI_DEVICE_ID_SUN_EBUS,
+ .revision = 0x01,
+ .class_id = PCI_CLASS_BRIDGE_OTHER,
};
static void pci_ebus_register(void)
diff --git a/hw/syborg_virtio.c b/hw/syborg_virtio.c
index 2f3e6da4e2..00c7be8c8f 100644
--- a/hw/syborg_virtio.c
+++ b/hw/syborg_virtio.c
@@ -146,7 +146,9 @@ static void syborg_virtio_writel(void *opaque, target_phys_addr_t offset,
vdev->queue_sel = value;
break;
case SYBORG_VIRTIO_QUEUE_NOTIFY:
- virtio_queue_notify(vdev, value);
+ if (value < VIRTIO_PCI_QUEUE_MAX) {
+ virtio_queue_notify(vdev, value);
+ }
break;
case SYBORG_VIRTIO_STATUS:
virtio_set_status(vdev, value & 0xFF);
diff --git a/hw/unin_pci.c b/hw/unin_pci.c
index c57c0a1ce3..d364daa53a 100644
--- a/hw/unin_pci.c
+++ b/hw/unin_pci.c
@@ -279,10 +279,6 @@ PCIBus *pci_pmac_u3_init(qemu_irq *pic)
static int unin_main_pci_host_init(PCIDevice *d)
{
- pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_APPLE);
- pci_config_set_device_id(d->config, PCI_DEVICE_ID_APPLE_UNI_N_PCI);
- d->config[0x08] = 0x00; // revision
- pci_config_set_class(d->config, PCI_CLASS_BRIDGE_HOST);
d->config[0x0C] = 0x08; // cache_line_size
d->config[0x0D] = 0x10; // latency_timer
d->config[0x34] = 0x00; // capabilities_pointer
@@ -291,10 +287,6 @@ static int unin_main_pci_host_init(PCIDevice *d)
static int unin_agp_pci_host_init(PCIDevice *d)
{
- pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_APPLE);
- pci_config_set_device_id(d->config, PCI_DEVICE_ID_APPLE_UNI_N_AGP);
- d->config[0x08] = 0x00; // revision
- pci_config_set_class(d->config, PCI_CLASS_BRIDGE_HOST);
d->config[0x0C] = 0x08; // cache_line_size
d->config[0x0D] = 0x10; // latency_timer
// d->config[0x34] = 0x80; // capabilities_pointer
@@ -303,11 +295,6 @@ static int unin_agp_pci_host_init(PCIDevice *d)
static int u3_agp_pci_host_init(PCIDevice *d)
{
- pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_APPLE);
- pci_config_set_device_id(d->config, PCI_DEVICE_ID_APPLE_U3_AGP);
- /* revision */
- d->config[0x08] = 0x00;
- pci_config_set_class(d->config, PCI_CLASS_BRIDGE_HOST);
/* cache line size */
d->config[0x0C] = 0x08;
/* latency timer */
@@ -317,10 +304,6 @@ static int u3_agp_pci_host_init(PCIDevice *d)
static int unin_internal_pci_host_init(PCIDevice *d)
{
- pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_APPLE);
- pci_config_set_device_id(d->config, PCI_DEVICE_ID_APPLE_UNI_N_I_PCI);
- d->config[0x08] = 0x00; // revision
- pci_config_set_class(d->config, PCI_CLASS_BRIDGE_HOST);
d->config[0x0C] = 0x08; // cache_line_size
d->config[0x0D] = 0x10; // latency_timer
d->config[0x34] = 0x00; // capabilities_pointer
@@ -331,24 +314,40 @@ static PCIDeviceInfo unin_main_pci_host_info = {
.qdev.name = "uni-north",
.qdev.size = sizeof(PCIDevice),
.init = unin_main_pci_host_init,
+ .vendor_id = PCI_VENDOR_ID_APPLE,
+ .device_id = PCI_DEVICE_ID_APPLE_UNI_N_PCI,
+ .revision = 0x00,
+ .class_id = PCI_CLASS_BRIDGE_HOST,
};
static PCIDeviceInfo u3_agp_pci_host_info = {
.qdev.name = "u3-agp",
.qdev.size = sizeof(PCIDevice),
.init = u3_agp_pci_host_init,
+ .vendor_id = PCI_VENDOR_ID_APPLE,
+ .device_id = PCI_DEVICE_ID_APPLE_U3_AGP,
+ .revision = 0x00,
+ .class_id = PCI_CLASS_BRIDGE_HOST,
};
static PCIDeviceInfo unin_agp_pci_host_info = {
.qdev.name = "uni-north-agp",
.qdev.size = sizeof(PCIDevice),
.init = unin_agp_pci_host_init,
+ .vendor_id = PCI_VENDOR_ID_APPLE,
+ .device_id = PCI_DEVICE_ID_APPLE_UNI_N_AGP,
+ .revision = 0x00,
+ .class_id = PCI_CLASS_BRIDGE_HOST,
};
static PCIDeviceInfo unin_internal_pci_host_info = {
.qdev.name = "uni-north-pci",
.qdev.size = sizeof(PCIDevice),
.init = unin_internal_pci_host_init,
+ .vendor_id = PCI_VENDOR_ID_APPLE,
+ .device_id = PCI_DEVICE_ID_APPLE_UNI_N_I_PCI,
+ .revision = 0x00,
+ .class_id = PCI_CLASS_BRIDGE_HOST,
};
static void unin_register_devices(void)
diff --git a/hw/usb-bus.c b/hw/usb-bus.c
index 480956dfcf..2abce12de5 100644
--- a/hw/usb-bus.c
+++ b/hw/usb-bus.c
@@ -75,7 +75,7 @@ static int usb_qdev_init(DeviceState *qdev, DeviceInfo *base)
QLIST_INIT(&dev->strings);
rc = dev->info->init(dev);
if (rc == 0 && dev->auto_attach)
- usb_device_attach(dev);
+ rc = usb_device_attach(dev);
return rc;
}
@@ -121,7 +121,7 @@ USBDevice *usb_create(USBBus *bus, const char *name)
bus = usb_bus_find(-1);
if (!bus)
return NULL;
- fprintf(stderr, "%s: no bus specified, using \"%s\" for \"%s\"\n",
+ error_report("%s: no bus specified, using \"%s\" for \"%s\"\n",
__FUNCTION__, bus->qbus.name, name);
}
#endif
@@ -171,15 +171,20 @@ void usb_unregister_port(USBBus *bus, USBPort *port)
bus->nfree--;
}
-static void do_attach(USBDevice *dev)
+static int do_attach(USBDevice *dev)
{
USBBus *bus = usb_bus_from_device(dev);
USBPort *port;
if (dev->attached) {
- fprintf(stderr, "Warning: tried to attach usb device %s twice\n",
+ error_report("Error: tried to attach usb device %s twice\n",
dev->product_desc);
- return;
+ return -1;
+ }
+ if (bus->nfree == 0) {
+ error_report("Error: tried to attach usb device %s to a bus with no free ports\n",
+ dev->product_desc);
+ return -1;
}
if (dev->port_path) {
QTAILQ_FOREACH(port, &bus->free, next) {
@@ -188,13 +193,18 @@ static void do_attach(USBDevice *dev)
}
}
if (port == NULL) {
- fprintf(stderr, "Warning: usb port %s (bus %s) not found\n",
+ error_report("Error: usb port %s (bus %s) not found\n",
dev->port_path, bus->qbus.name);
- return;
+ return -1;
}
} else {
port = QTAILQ_FIRST(&bus->free);
}
+ if (!(port->speedmask & dev->speedmask)) {
+ error_report("Warning: speed mismatch trying to attach usb device %s to bus %s\n",
+ dev->product_desc, bus->qbus.name);
+ return -1;
+ }
dev->attached++;
QTAILQ_REMOVE(&bus->free, port, next);
@@ -204,6 +214,8 @@ static void do_attach(USBDevice *dev)
QTAILQ_INSERT_TAIL(&bus->used, port, next);
bus->nused++;
+
+ return 0;
}
int usb_device_attach(USBDevice *dev)
@@ -215,8 +227,7 @@ int usb_device_attach(USBDevice *dev)
(unless a physical port location is specified). */
usb_create_simple(bus, "usb-hub");
}
- do_attach(dev);
- return 0;
+ return do_attach(dev);
}
int usb_device_detach(USBDevice *dev)
@@ -225,7 +236,7 @@ int usb_device_detach(USBDevice *dev)
USBPort *port;
if (!dev->attached) {
- fprintf(stderr, "Warning: tried to detach unattached usb device %s\n",
+ error_report("Error: tried to detach unattached usb device %s\n",
dev->product_desc);
return -1;
}
diff --git a/hw/usb-ccid.c b/hw/usb-ccid.c
index 59c6431676..d3922998c5 100644
--- a/hw/usb-ccid.c
+++ b/hw/usb-ccid.c
@@ -1240,7 +1240,7 @@ static int ccid_card_init(DeviceState *qdev, DeviceInfo *base)
return -1;
}
if (s->card != NULL) {
- error_report("Warning: usb-ccid card already full, not adding\n");
+ error_report("Warning: usb-ccid card already full, not adding");
return -1;
}
ret = info->initfn ? info->initfn(card) : ret;
@@ -1271,6 +1271,7 @@ static int ccid_initfn(USBDevice *dev)
s->migration_target_ip = 0;
s->migration_target_port = 0;
s->dev.speed = USB_SPEED_FULL;
+ s->dev.speedmask = USB_SPEED_MASK_FULL;
s->notify_slot_change = false;
s->powered = true;
s->pending_answers_num = 0;
diff --git a/hw/usb-desc.c b/hw/usb-desc.c
index e4a4680fee..bc6858f62f 100644
--- a/hw/usb-desc.c
+++ b/hw/usb-desc.c
@@ -242,7 +242,17 @@ static void usb_desc_setdefaults(USBDevice *dev)
void usb_desc_init(USBDevice *dev)
{
+ const USBDesc *desc = dev->info->usb_desc;
+
+ assert(desc != NULL);
dev->speed = USB_SPEED_FULL;
+ dev->speedmask = 0;
+ if (desc->full) {
+ dev->speedmask |= USB_SPEED_MASK_FULL;
+ }
+ if (desc->high) {
+ dev->speedmask |= USB_SPEED_MASK_HIGH;
+ }
usb_desc_setdefaults(dev);
}
@@ -375,6 +385,10 @@ int usb_desc_get_descriptor(USBDevice *dev, int value, uint8_t *dest, size_t len
trace_usb_desc_other_speed_config(dev->addr, index, len, ret);
break;
+ case USB_DT_DEBUG:
+ /* ignore silently */
+ break;
+
default:
fprintf(stderr, "%s: %d unknown type %d (len %zd)\n", __FUNCTION__,
dev->addr, type, len);
diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
index c909127735..91fb7dea93 100644
--- a/hw/usb-ehci.c
+++ b/hw/usb-ehci.c
@@ -130,7 +130,7 @@
#define PORTSC_CONNECT (1 << 0) // Current Connect Status
#define FRAME_TIMER_FREQ 1000
-#define FRAME_TIMER_USEC (1000000 / FRAME_TIMER_FREQ)
+#define FRAME_TIMER_NS (1000000000 / FRAME_TIMER_FREQ)
#define NB_MAXINTRATE 8 // Max rate at which controller issues ints
#define NB_PORTS 4 // Number of downstream ports
@@ -348,7 +348,8 @@ struct EHCIQueue {
EHCIState *ehci;
QTAILQ_ENTRY(EHCIQueue) next;
bool async_schedule;
- uint32_t seen, ts;
+ uint32_t seen;
+ uint64_t ts;
/* cached data from guest - needs to be flushed
* when guest removes an entry (doorbell, handshake sequence)
@@ -373,6 +374,11 @@ struct EHCIState {
target_phys_addr_t mem_base;
int mem;
int num_ports;
+
+ /* properties */
+ uint32_t freq;
+ uint32_t maxframes;
+
/*
* EHCI spec version 1.0 Section 2.3
* Host Controller Operational Registers
@@ -413,12 +419,11 @@ struct EHCIState {
uint8_t ibuffer[BUFF_SIZE];
int isoch_pause;
- uint32_t last_run_usec;
- uint32_t frame_end_usec;
+ uint64_t last_run_ns;
};
#define SET_LAST_RUN_CLOCK(s) \
- (s)->last_run_usec = qemu_get_clock_ns(vm_clock) / 1000;
+ (s)->last_run_ns = qemu_get_clock_ns(vm_clock);
/* nifty macros from Arnon's EHCI version */
#define get_field(data, field) \
@@ -685,10 +690,10 @@ static void ehci_queues_rip_unused(EHCIState *ehci)
QTAILQ_FOREACH_SAFE(q, &ehci->queues, next, tmp) {
if (q->seen) {
q->seen = 0;
- q->ts = ehci->last_run_usec;
+ q->ts = ehci->last_run_ns;
continue;
}
- if (ehci->last_run_usec < q->ts + 250000) {
+ if (ehci->last_run_ns < q->ts + 250000000) {
/* allow 0.25 sec idle */
continue;
}
@@ -2040,23 +2045,16 @@ static void ehci_frame_timer(void *opaque)
{
EHCIState *ehci = opaque;
int64_t expire_time, t_now;
- int usec_elapsed;
+ uint64_t ns_elapsed;
int frames;
- int usec_now;
int i;
int skipped_frames = 0;
-
t_now = qemu_get_clock_ns(vm_clock);
- expire_time = t_now + (get_ticks_per_sec() / FRAME_TIMER_FREQ);
- if (expire_time == t_now) {
- expire_time++;
- }
+ expire_time = t_now + (get_ticks_per_sec() / ehci->freq);
- usec_now = t_now / 1000;
- usec_elapsed = usec_now - ehci->last_run_usec;
- frames = usec_elapsed / FRAME_TIMER_USEC;
- ehci->frame_end_usec = usec_now + FRAME_TIMER_USEC - 10;
+ ns_elapsed = t_now - ehci->last_run_ns;
+ frames = ns_elapsed / FRAME_TIMER_NS;
for (i = 0; i < frames; i++) {
if ( !(ehci->usbsts & USBSTS_HALT)) {
@@ -2073,13 +2071,13 @@ static void ehci_frame_timer(void *opaque)
ehci->sofv &= 0x000003ff;
}
- if (frames - i > 10) {
+ if (frames - i > ehci->maxframes) {
skipped_frames++;
} else {
ehci_advance_periodic_state(ehci);
}
- ehci->last_run_usec += FRAME_TIMER_USEC;
+ ehci->last_run_ns += FRAME_TIMER_NS;
}
#if 0
@@ -2142,6 +2140,15 @@ static PCIDeviceInfo ehci_info = {
.qdev.name = "usb-ehci",
.qdev.size = sizeof(EHCIState),
.init = usb_ehci_initfn,
+ .vendor_id = PCI_VENDOR_ID_INTEL,
+ .device_id = PCI_DEVICE_ID_INTEL_82801D,
+ .revision = 0x10,
+ .class_id = PCI_CLASS_SERIAL_USB,
+ .qdev.props = (Property[]) {
+ DEFINE_PROP_UINT32("freq", EHCIState, freq, FRAME_TIMER_FREQ),
+ DEFINE_PROP_UINT32("maxframes", EHCIState, maxframes, 128),
+ DEFINE_PROP_END_OF_LIST(),
+ },
};
static int usb_ehci_initfn(PCIDevice *dev)
@@ -2150,12 +2157,7 @@ static int usb_ehci_initfn(PCIDevice *dev)
uint8_t *pci_conf = s->dev.config;
int i;
- pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_INTEL);
- pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_INTEL_82801D);
- pci_set_byte(&pci_conf[PCI_REVISION_ID], 0x10);
pci_set_byte(&pci_conf[PCI_CLASS_PROG], 0x20);
- pci_config_set_class(pci_conf, PCI_CLASS_SERIAL_USB);
- pci_set_byte(&pci_conf[PCI_HEADER_TYPE], PCI_HEADER_TYPE_NORMAL);
/* capabilities pointer */
pci_set_byte(&pci_conf[PCI_CAPABILITY_LIST], 0x00);
diff --git a/hw/usb-msd.c b/hw/usb-msd.c
index c59797b27e..86582cc723 100644
--- a/hw/usb-msd.c
+++ b/hw/usb-msd.c
@@ -51,6 +51,7 @@ typedef struct {
SCSIRequest *req;
SCSIBus bus;
BlockConf conf;
+ char *serial;
SCSIDevice *scsi_dev;
uint32_t removable;
int result;
@@ -497,8 +498,9 @@ static void usb_msd_password_cb(void *opaque, int err)
MSDState *s = opaque;
if (!err)
- usb_device_attach(&s->dev);
- else
+ err = usb_device_attach(&s->dev);
+
+ if (err)
qdev_unplug(&s->dev.qdev);
}
@@ -531,9 +533,15 @@ static int usb_msd_initfn(USBDevice *dev)
bdrv_detach(bs, &s->dev.qdev);
s->conf.bs = NULL;
- dinfo = drive_get_by_blockdev(bs);
- if (dinfo && dinfo->serial) {
- usb_desc_set_string(dev, STR_SERIALNUMBER, dinfo->serial);
+ if (!s->serial) {
+ /* try to fall back to value set with legacy -drive serial=... */
+ dinfo = drive_get_by_blockdev(bs);
+ if (*dinfo->serial) {
+ s->serial = strdup(dinfo->serial);
+ }
+ }
+ if (s->serial) {
+ usb_desc_set_string(dev, STR_SERIALNUMBER, s->serial);
}
usb_desc_init(dev);
@@ -632,6 +640,7 @@ static struct USBDeviceInfo msd_info = {
.usbdevice_init = usb_msd_init,
.qdev.props = (Property[]) {
DEFINE_BLOCK_PROPERTIES(MSDState, conf),
+ DEFINE_PROP_STRING("serial", MSDState, serial),
DEFINE_PROP_BIT("removable", MSDState, removable, 0, false),
DEFINE_PROP_END_OF_LIST(),
},
diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c
index 832dcd688a..1c29b9fa6c 100644
--- a/hw/usb-ohci.c
+++ b/hw/usb-ohci.c
@@ -373,14 +373,25 @@ static void ohci_wakeup(USBDevice *dev)
OHCIState *s = container_of(bus, OHCIState, bus);
int portnum = dev->port->index;
OHCIPort *port = &s->rhport[portnum];
+ uint32_t intr = 0;
if (port->ctrl & OHCI_PORT_PSS) {
DPRINTF("usb-ohci: port %d: wakeup\n", portnum);
port->ctrl |= OHCI_PORT_PSSC;
port->ctrl &= ~OHCI_PORT_PSS;
- if ((s->ctl & OHCI_CTL_HCFS) == OHCI_USB_SUSPEND) {
- ohci_set_interrupt(s, OHCI_INTR_RD);
- }
+ intr = OHCI_INTR_RHSC;
+ }
+ /* Note that the controller can be suspended even if this port is not */
+ if ((s->ctl & OHCI_CTL_HCFS) == OHCI_USB_SUSPEND) {
+ DPRINTF("usb-ohci: remote-wakeup: SUSPEND->RESUME\n");
+ /* This is the one state transition the controller can do by itself */
+ s->ctl &= ~OHCI_CTL_HCFS;
+ s->ctl |= OHCI_USB_RESUME;
+ /* In suspend mode only ResumeDetected is possible, not RHSC:
+ * see the OHCI spec 5.1.2.3.
+ */
+ intr = OHCI_INTR_RD;
}
+ ohci_set_interrupt(s, intr);
}
/* Reset the controller */
@@ -1748,11 +1759,7 @@ static int usb_ohci_initfn_pci(struct PCIDevice *dev)
OHCIPCIState *ohci = DO_UPCAST(OHCIPCIState, pci_dev, dev);
int num_ports = 3;
- pci_config_set_vendor_id(ohci->pci_dev.config, PCI_VENDOR_ID_APPLE);
- pci_config_set_device_id(ohci->pci_dev.config,
- PCI_DEVICE_ID_APPLE_IPID_USB);
ohci->pci_dev.config[PCI_CLASS_PROG] = 0x10; /* OHCI */
- pci_config_set_class(ohci->pci_dev.config, PCI_CLASS_SERIAL_USB);
/* TODO: RST# value should be 0. */
ohci->pci_dev.config[PCI_INTERRUPT_PIN] = 0x01; /* interrupt pin 1 */
@@ -1792,6 +1799,9 @@ static PCIDeviceInfo ohci_pci_info = {
.qdev.desc = "Apple USB Controller",
.qdev.size = sizeof(OHCIPCIState),
.init = usb_ohci_initfn_pci,
+ .vendor_id = PCI_VENDOR_ID_APPLE,
+ .device_id = PCI_DEVICE_ID_APPLE_IPID_USB,
+ .class_id = PCI_CLASS_SERIAL_USB,
};
static SysBusDeviceInfo ohci_sysbus_info = {
diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c
index 75cd231f81..405fa7b65e 100644
--- a/hw/usb-uhci.c
+++ b/hw/usb-uhci.c
@@ -1114,14 +1114,13 @@ static USBBusOps uhci_bus_ops = {
.device_destroy = uhci_device_destroy,
};
-static int usb_uhci_common_initfn(UHCIState *s)
+static int usb_uhci_common_initfn(PCIDevice *dev)
{
+ UHCIState *s = DO_UPCAST(UHCIState, dev, dev);
uint8_t *pci_conf = s->dev.config;
int i;
- pci_conf[PCI_REVISION_ID] = 0x01; // revision number
pci_conf[PCI_CLASS_PROG] = 0x00;
- pci_config_set_class(pci_conf, PCI_CLASS_SERIAL_USB);
/* TODO: reset value should be 0. */
pci_conf[PCI_INTERRUPT_PIN] = 4; // interrupt pin 3
pci_conf[USB_SBRN] = USB_RELEASE_1; // release number
@@ -1146,34 +1145,11 @@ static int usb_uhci_common_initfn(UHCIState *s)
return 0;
}
-static int usb_uhci_piix3_initfn(PCIDevice *dev)
-{
- UHCIState *s = DO_UPCAST(UHCIState, dev, dev);
- uint8_t *pci_conf = s->dev.config;
-
- pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_INTEL);
- pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_INTEL_82371SB_2);
- return usb_uhci_common_initfn(s);
-}
-
-static int usb_uhci_piix4_initfn(PCIDevice *dev)
-{
- UHCIState *s = DO_UPCAST(UHCIState, dev, dev);
- uint8_t *pci_conf = s->dev.config;
-
- pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_INTEL);
- pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_INTEL_82371AB_2);
- return usb_uhci_common_initfn(s);
-}
-
static int usb_uhci_vt82c686b_initfn(PCIDevice *dev)
{
UHCIState *s = DO_UPCAST(UHCIState, dev, dev);
uint8_t *pci_conf = s->dev.config;
- pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_VIA);
- pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_VIA_UHCI);
-
/* USB misc control 1/2 */
pci_set_long(pci_conf + 0x40,0x00001000);
/* PM capability */
@@ -1181,7 +1157,7 @@ static int usb_uhci_vt82c686b_initfn(PCIDevice *dev)
/* USB legacy support */
pci_set_long(pci_conf + 0xc0,0x00002000);
- return usb_uhci_common_initfn(s);
+ return usb_uhci_common_initfn(dev);
}
static PCIDeviceInfo uhci_info[] = {
@@ -1189,17 +1165,29 @@ static PCIDeviceInfo uhci_info[] = {
.qdev.name = "piix3-usb-uhci",
.qdev.size = sizeof(UHCIState),
.qdev.vmsd = &vmstate_uhci,
- .init = usb_uhci_piix3_initfn,
+ .init = usb_uhci_common_initfn,
+ .vendor_id = PCI_VENDOR_ID_INTEL,
+ .device_id = PCI_DEVICE_ID_INTEL_82371SB_2,
+ .revision = 0x01,
+ .class_id = PCI_CLASS_SERIAL_USB,
},{
.qdev.name = "piix4-usb-uhci",
.qdev.size = sizeof(UHCIState),
.qdev.vmsd = &vmstate_uhci,
- .init = usb_uhci_piix4_initfn,
+ .init = usb_uhci_common_initfn,
+ .vendor_id = PCI_VENDOR_ID_INTEL,
+ .device_id = PCI_DEVICE_ID_INTEL_82371AB_2,
+ .revision = 0x01,
+ .class_id = PCI_CLASS_SERIAL_USB,
},{
.qdev.name = "vt82c686b-usb-uhci",
.qdev.size = sizeof(UHCIState),
.qdev.vmsd = &vmstate_uhci,
.init = usb_uhci_vt82c686b_initfn,
+ .vendor_id = PCI_VENDOR_ID_VIA,
+ .device_id = PCI_DEVICE_ID_VIA_UHCI,
+ .revision = 0x01,
+ .class_id = PCI_CLASS_SERIAL_USB,
},{
/* end of list */
}
diff --git a/hw/usb.h b/hw/usb.h
index 06ce05826a..076e2ffce4 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -130,6 +130,7 @@
#define USB_DT_ENDPOINT 0x05
#define USB_DT_DEVICE_QUALIFIER 0x06
#define USB_DT_OTHER_SPEED_CONFIG 0x07
+#define USB_DT_DEBUG 0x0A
#define USB_DT_INTERFACE_ASSOC 0x0B
#define USB_ENDPOINT_XFER_CONTROL 0
@@ -168,7 +169,10 @@ struct USBDevice {
char *port_path;
void *opaque;
+ /* Actual connected speed */
int speed;
+ /* Supported speeds, not in info because it may be variable (hostdevs) */
+ int speedmask;
uint8_t addr;
char product_desc[32];
int auto_attach;
diff --git a/hw/versatile_pci.c b/hw/versatile_pci.c
index 2fed8a00fd..8e75ffccfb 100644
--- a/hw/versatile_pci.c
+++ b/hw/versatile_pci.c
@@ -133,12 +133,8 @@ static int pci_realview_init(SysBusDevice *dev)
static int versatile_pci_host_init(PCIDevice *d)
{
- pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_XILINX);
- /* Both boards have the same device ID. Oh well. */
- pci_config_set_device_id(d->config, PCI_DEVICE_ID_XILINX_XC2VP30);
pci_set_word(d->config + PCI_STATUS,
PCI_STATUS_66MHZ | PCI_STATUS_DEVSEL_MEDIUM);
- pci_config_set_class(d->config, PCI_CLASS_PROCESSOR_CO);
pci_set_byte(d->config + PCI_LATENCY_TIMER, 0x10);
return 0;
}
@@ -147,6 +143,10 @@ static PCIDeviceInfo versatile_pci_host_info = {
.qdev.name = "versatile_pci_host",
.qdev.size = sizeof(PCIDevice),
.init = versatile_pci_host_init,
+ .vendor_id = PCI_VENDOR_ID_XILINX,
+ /* Both boards have the same device ID. Oh well. */
+ .device_id = PCI_DEVICE_ID_XILINX_XC2VP30,
+ .class_id = PCI_CLASS_PROCESSOR_CO,
};
static void versatile_pci_register_devices(void)
diff --git a/hw/vga-pci.c b/hw/vga-pci.c
index ce9ec45777..481f448e3f 100644
--- a/hw/vga-pci.c
+++ b/hw/vga-pci.c
@@ -74,7 +74,6 @@ static int pci_vga_initfn(PCIDevice *dev)
{
PCIVGAState *d = DO_UPCAST(PCIVGAState, dev, dev);
VGACommonState *s = &d->vga;
- uint8_t *pci_conf = d->dev.config;
// vga + console init
vga_common_init(s, VGA_RAM_SIZE);
@@ -83,11 +82,6 @@ static int pci_vga_initfn(PCIDevice *dev)
s->ds = graphic_console_init(s->update, s->invalidate,
s->screen_dump, s->text_update, s);
- // dummy VGA (same as Bochs ID)
- pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_QEMU);
- pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_QEMU_VGA);
- pci_config_set_class(pci_conf, PCI_CLASS_DISPLAY_VGA);
-
/* XXX: VGA_RAM_SIZE must be a power of two */
pci_register_bar(&d->dev, 0, VGA_RAM_SIZE,
PCI_BASE_ADDRESS_MEM_PREFETCH, vga_map);
@@ -114,6 +108,11 @@ static PCIDeviceInfo vga_info = {
.init = pci_vga_initfn,
.config_write = pci_vga_write_config,
.romfile = "vgabios-stdvga.bin",
+
+ /* dummy VGA (same as Bochs ID) */
+ .vendor_id = PCI_VENDOR_ID_QEMU,
+ .device_id = PCI_DEVICE_ID_QEMU_VGA,
+ .class_id = PCI_CLASS_DISPLAY_VGA,
};
static void vga_register(void)
diff --git a/hw/vga.c b/hw/vga.c
index 124295ae52..0f54734624 100644
--- a/hw/vga.c
+++ b/hw/vga.c
@@ -2346,15 +2346,19 @@ int ppm_save(const char *filename, struct DisplaySurface *ds)
uint32_t v;
int y, x;
uint8_t r, g, b;
+ int ret;
+ char *linebuf, *pbuf;
f = fopen(filename, "wb");
if (!f)
return -1;
fprintf(f, "P6\n%d %d\n%d\n",
ds->width, ds->height, 255);
+ linebuf = qemu_malloc(ds->width * 3);
d1 = ds->data;
for(y = 0; y < ds->height; y++) {
d = d1;
+ pbuf = linebuf;
for(x = 0; x < ds->width; x++) {
if (ds->pf.bits_per_pixel == 32)
v = *(uint32_t *)d;
@@ -2366,13 +2370,16 @@ int ppm_save(const char *filename, struct DisplaySurface *ds)
(ds->pf.gmax + 1);
b = ((v >> ds->pf.bshift) & ds->pf.bmax) * 256 /
(ds->pf.bmax + 1);
- fputc(r, f);
- fputc(g, f);
- fputc(b, f);
+ *pbuf++ = r;
+ *pbuf++ = g;
+ *pbuf++ = b;
d += ds->pf.bytes_per_pixel;
}
d1 += ds->linesize;
+ ret = fwrite(linebuf, 1, pbuf - linebuf, f);
+ (void)ret;
}
+ qemu_free(linebuf);
fclose(f);
return 0;
}
diff --git a/hw/vhost_net.c b/hw/vhost_net.c
index 420e05f112..b6dc592db0 100644
--- a/hw/vhost_net.c
+++ b/hw/vhost_net.c
@@ -15,6 +15,7 @@
#include "virtio-net.h"
#include "vhost_net.h"
+#include "qemu-error.h"
#include "config.h"
@@ -50,6 +51,9 @@ unsigned vhost_net_get_features(struct vhost_net *net, unsigned features)
if (!(net->dev.features & (1 << VIRTIO_RING_F_INDIRECT_DESC))) {
features &= ~(1 << VIRTIO_RING_F_INDIRECT_DESC);
}
+ if (!(net->dev.features & (1 << VIRTIO_RING_F_EVENT_IDX))) {
+ features &= ~(1 << VIRTIO_RING_F_EVENT_IDX);
+ }
if (!(net->dev.features & (1 << VIRTIO_NET_F_MRG_RXBUF))) {
features &= ~(1 << VIRTIO_NET_F_MRG_RXBUF);
}
@@ -65,6 +69,9 @@ void vhost_net_ack_features(struct vhost_net *net, unsigned features)
if (features & (1 << VIRTIO_RING_F_INDIRECT_DESC)) {
net->dev.acked_features |= (1 << VIRTIO_RING_F_INDIRECT_DESC);
}
+ if (features & (1 << VIRTIO_RING_F_EVENT_IDX)) {
+ net->dev.acked_features |= (1 << VIRTIO_RING_F_EVENT_IDX);
+ }
if (features & (1 << VIRTIO_NET_F_MRG_RXBUF)) {
net->dev.acked_features |= (1 << VIRTIO_NET_F_MRG_RXBUF);
}
@@ -197,6 +204,7 @@ void vhost_net_cleanup(struct vhost_net *net)
struct vhost_net *vhost_net_init(VLANClientState *backend, int devfd,
bool force)
{
+ error_report("vhost-net support is not compiled in");
return NULL;
}
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index c018351095..b3e7ba5d12 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -75,9 +75,6 @@
VIRTIO_PCI_CONFIG_MSI : \
VIRTIO_PCI_CONFIG_NOMSI)
-/* Virtio ABI version, if we increment this, we break the guest driver. */
-#define VIRTIO_PCI_ABI_VERSION 0
-
/* How many bits to shift physical queue address written to QUEUE_PFN.
* 12 is historical, and due to x86 page size. */
#define VIRTIO_PCI_QUEUE_ADDR_SHIFT 12
@@ -328,7 +325,9 @@ static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val)
vdev->queue_sel = val;
break;
case VIRTIO_PCI_QUEUE_NOTIFY:
- virtio_queue_notify(vdev, val);
+ if (val < VIRTIO_PCI_QUEUE_MAX) {
+ virtio_queue_notify(vdev, val);
+ }
break;
case VIRTIO_PCI_STATUS:
if (!(val & VIRTIO_CONFIG_S_DRIVER_OK)) {
@@ -649,9 +648,7 @@ static const VirtIOBindings virtio_pci_bindings = {
.vmstate_change = virtio_pci_vmstate_change,
};
-void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev,
- uint16_t vendor, uint16_t device,
- uint16_t class_code, uint8_t pif)
+void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev)
{
uint8_t *config;
uint32_t size;
@@ -659,19 +656,12 @@ void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev,
proxy->vdev = vdev;
config = proxy->pci_dev.config;
- pci_config_set_vendor_id(config, vendor);
- pci_config_set_device_id(config, device);
-
- config[0x08] = VIRTIO_PCI_ABI_VERSION;
-
- config[0x09] = pif;
- pci_config_set_class(config, class_code);
-
- config[0x2c] = vendor & 0xFF;
- config[0x2d] = (vendor >> 8) & 0xFF;
- config[0x2e] = vdev->device_id & 0xFF;
- config[0x2f] = (vdev->device_id >> 8) & 0xFF;
+ if (proxy->class_code) {
+ pci_config_set_class(config, proxy->class_code);
+ }
+ pci_set_word(config + 0x2c, pci_get_word(config + PCI_VENDOR_ID));
+ pci_set_word(config + 0x2e, vdev->device_id);
config[0x3d] = 1;
if (vdev->nvectors && !msix_init(&proxy->pci_dev, vdev->nvectors, 1, 0)) {
@@ -715,10 +705,7 @@ static int virtio_blk_init_pci(PCIDevice *pci_dev)
return -1;
}
vdev->nvectors = proxy->nvectors;
- virtio_init_pci(proxy, vdev,
- PCI_VENDOR_ID_REDHAT_QUMRANET,
- PCI_DEVICE_ID_VIRTIO_BLOCK,
- proxy->class_code, 0x00);
+ virtio_init_pci(proxy, vdev);
/* make the actual value visible */
proxy->nvectors = vdev->nvectors;
return 0;
@@ -756,10 +743,7 @@ static int virtio_serial_init_pci(PCIDevice *pci_dev)
vdev->nvectors = proxy->nvectors == DEV_NVECTORS_UNSPECIFIED
? proxy->serial.max_virtserial_ports + 1
: proxy->nvectors;
- virtio_init_pci(proxy, vdev,
- PCI_VENDOR_ID_REDHAT_QUMRANET,
- PCI_DEVICE_ID_VIRTIO_CONSOLE,
- proxy->class_code, 0x00);
+ virtio_init_pci(proxy, vdev);
proxy->nvectors = vdev->nvectors;
return 0;
}
@@ -781,11 +765,7 @@ static int virtio_net_init_pci(PCIDevice *pci_dev)
vdev = virtio_net_init(&pci_dev->qdev, &proxy->nic, &proxy->net);
vdev->nvectors = proxy->nvectors;
- virtio_init_pci(proxy, vdev,
- PCI_VENDOR_ID_REDHAT_QUMRANET,
- PCI_DEVICE_ID_VIRTIO_NET,
- PCI_CLASS_NETWORK_ETHERNET,
- 0x00);
+ virtio_init_pci(proxy, vdev);
/* make the actual value visible */
proxy->nvectors = vdev->nvectors;
@@ -807,11 +787,7 @@ static int virtio_balloon_init_pci(PCIDevice *pci_dev)
VirtIODevice *vdev;
vdev = virtio_balloon_init(&pci_dev->qdev);
- virtio_init_pci(proxy, vdev,
- PCI_VENDOR_ID_REDHAT_QUMRANET,
- PCI_DEVICE_ID_VIRTIO_BALLOON,
- PCI_CLASS_MEMORY_RAM,
- 0x00);
+ virtio_init_pci(proxy, vdev);
return 0;
}
@@ -822,6 +798,10 @@ static PCIDeviceInfo virtio_info[] = {
.qdev.size = sizeof(VirtIOPCIProxy),
.init = virtio_blk_init_pci,
.exit = virtio_blk_exit_pci,
+ .vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET,
+ .device_id = PCI_DEVICE_ID_VIRTIO_BLOCK,
+ .revision = VIRTIO_PCI_ABI_VERSION,
+ .class_id = PCI_CLASS_STORAGE_SCSI,
.qdev.props = (Property[]) {
DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0),
DEFINE_BLOCK_PROPERTIES(VirtIOPCIProxy, block),
@@ -839,6 +819,10 @@ static PCIDeviceInfo virtio_info[] = {
.init = virtio_net_init_pci,
.exit = virtio_net_exit_pci,
.romfile = "pxe-virtio.rom",
+ .vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET,
+ .device_id = PCI_DEVICE_ID_VIRTIO_NET,
+ .revision = VIRTIO_PCI_ABI_VERSION,
+ .class_id = PCI_CLASS_NETWORK_ETHERNET,
.qdev.props = (Property[]) {
DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags,
VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, false),
@@ -859,6 +843,10 @@ static PCIDeviceInfo virtio_info[] = {
.qdev.size = sizeof(VirtIOPCIProxy),
.init = virtio_serial_init_pci,
.exit = virtio_serial_exit_pci,
+ .vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET,
+ .device_id = PCI_DEVICE_ID_VIRTIO_CONSOLE,
+ .revision = VIRTIO_PCI_ABI_VERSION,
+ .class_id = PCI_CLASS_COMMUNICATION_OTHER,
.qdev.props = (Property[]) {
DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags,
VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true),
@@ -877,6 +865,10 @@ static PCIDeviceInfo virtio_info[] = {
.qdev.size = sizeof(VirtIOPCIProxy),
.init = virtio_balloon_init_pci,
.exit = virtio_exit_pci,
+ .vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET,
+ .device_id = PCI_DEVICE_ID_VIRTIO_BALLOON,
+ .revision = VIRTIO_PCI_ABI_VERSION,
+ .class_id = PCI_CLASS_MEMORY_RAM,
.qdev.props = (Property[]) {
DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
DEFINE_PROP_END_OF_LIST(),
diff --git a/hw/virtio-pci.h b/hw/virtio-pci.h
index a4b5fd30e1..b5189172de 100644
--- a/hw/virtio-pci.h
+++ b/hw/virtio-pci.h
@@ -37,7 +37,9 @@ typedef struct {
bool ioeventfd_started;
} VirtIOPCIProxy;
-extern void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev,
- uint16_t vendor, uint16_t device,
- uint16_t class_code, uint8_t pif);
+void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev);
+
+/* Virtio ABI version, if we increment this, we break the guest driver. */
+#define VIRTIO_PCI_ABI_VERSION 0
+
#endif
diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c
index 9a12104982..7f6db7bffe 100644
--- a/hw/virtio-serial-bus.c
+++ b/hw/virtio-serial-bus.c
@@ -328,18 +328,11 @@ static void handle_control_message(VirtIOSerial *vser, void *buf, size_t len)
cpkt.event = lduw_p(&gcpkt->event);
cpkt.value = lduw_p(&gcpkt->value);
- port = find_port_by_id(vser, ldl_p(&gcpkt->id));
- if (!port && cpkt.event != VIRTIO_CONSOLE_DEVICE_READY)
- return;
-
- info = DO_UPCAST(VirtIOSerialPortInfo, qdev, port->dev.info);
-
- switch(cpkt.event) {
- case VIRTIO_CONSOLE_DEVICE_READY:
+ if (cpkt.event == VIRTIO_CONSOLE_DEVICE_READY) {
if (!cpkt.value) {
- error_report("virtio-serial-bus: Guest failure in adding device %s\n",
+ error_report("virtio-serial-bus: Guest failure in adding device %s",
vser->bus.qbus.name);
- break;
+ return;
}
/*
* The device is up, we can now tell the device about all the
@@ -348,11 +341,22 @@ static void handle_control_message(VirtIOSerial *vser, void *buf, size_t len)
QTAILQ_FOREACH(port, &vser->ports, next) {
send_control_event(port, VIRTIO_CONSOLE_PORT_ADD, 1);
}
- break;
+ return;
+ }
+ port = find_port_by_id(vser, ldl_p(&gcpkt->id));
+ if (!port) {
+ error_report("virtio-serial-bus: Unexpected port id %u for device %s\n",
+ ldl_p(&gcpkt->id), vser->bus.qbus.name);
+ return;
+ }
+
+ info = DO_UPCAST(VirtIOSerialPortInfo, qdev, port->dev.info);
+
+ switch(cpkt.event) {
case VIRTIO_CONSOLE_PORT_READY:
if (!cpkt.value) {
- error_report("virtio-serial-bus: Guest failure in adding port %u for device %s\n",
+ error_report("virtio-serial-bus: Guest failure in adding port %u for device %s",
port->id, vser->bus.qbus.name);
break;
}
@@ -741,7 +745,7 @@ static int virtser_port_qdev_init(DeviceState *qdev, DeviceInfo *base)
plugging_port0 = info->is_console && !find_port_by_id(port->vser, 0);
if (find_port_by_id(port->vser, port->id)) {
- error_report("virtio-serial-bus: A port already exists at id %u\n",
+ error_report("virtio-serial-bus: A port already exists at id %u",
port->id);
return -1;
}
@@ -752,7 +756,7 @@ static int virtser_port_qdev_init(DeviceState *qdev, DeviceInfo *base)
} else {
port->id = find_free_port_id(port->vser);
if (port->id == VIRTIO_CONSOLE_BAD_ID) {
- error_report("virtio-serial-bus: Maximum port limit for this device reached\n");
+ error_report("virtio-serial-bus: Maximum port limit for this device reached");
return -1;
}
}
@@ -760,7 +764,7 @@ static int virtser_port_qdev_init(DeviceState *qdev, DeviceInfo *base)
max_nr_ports = tswap32(port->vser->config.max_nr_ports);
if (port->id >= max_nr_ports) {
- error_report("virtio-serial-bus: Out-of-range port id specified, max. allowed: %u\n",
+ error_report("virtio-serial-bus: Out-of-range port id specified, max. allowed: %u",
max_nr_ports - 1);
return -1;
}
diff --git a/hw/virtio.c b/hw/virtio.c
index 6e8814cb64..cc47a06a4e 100644
--- a/hw/virtio.c
+++ b/hw/virtio.c
@@ -71,7 +71,17 @@ struct VirtQueue
VRing vring;
target_phys_addr_t pa;
uint16_t last_avail_idx;
+ /* Last used index value we have signalled on */
+ uint16_t signalled_used;
+
+ /* Last used index value we have signalled on */
+ bool signalled_used_valid;
+
+ /* Notification enabled? */
+ bool notification;
+
int inuse;
+
uint16_t vector;
void (*handle_output)(VirtIODevice *vdev, VirtQueue *vq);
VirtIODevice *vdev;
@@ -140,6 +150,11 @@ static inline uint16_t vring_avail_ring(VirtQueue *vq, int i)
return lduw_phys(pa);
}
+static inline uint16_t vring_used_event(VirtQueue *vq)
+{
+ return vring_avail_ring(vq, vq->vring.num);
+}
+
static inline void vring_used_ring_id(VirtQueue *vq, int i, uint32_t val)
{
target_phys_addr_t pa;
@@ -161,11 +176,11 @@ static uint16_t vring_used_idx(VirtQueue *vq)
return lduw_phys(pa);
}
-static inline void vring_used_idx_increment(VirtQueue *vq, uint16_t val)
+static inline void vring_used_idx_set(VirtQueue *vq, uint16_t val)
{
target_phys_addr_t pa;
pa = vq->vring.used + offsetof(VRingUsed, idx);
- stw_phys(pa, vring_used_idx(vq) + val);
+ stw_phys(pa, val);
}
static inline void vring_used_flags_set_bit(VirtQueue *vq, int mask)
@@ -182,12 +197,26 @@ static inline void vring_used_flags_unset_bit(VirtQueue *vq, int mask)
stw_phys(pa, lduw_phys(pa) & ~mask);
}
+static inline void vring_avail_event(VirtQueue *vq, uint16_t val)
+{
+ target_phys_addr_t pa;
+ if (!vq->notification) {
+ return;
+ }
+ pa = vq->vring.used + offsetof(VRingUsed, ring[vq->vring.num]);
+ stw_phys(pa, val);
+}
+
void virtio_queue_set_notification(VirtQueue *vq, int enable)
{
- if (enable)
+ vq->notification = enable;
+ if (vq->vdev->guest_features & (1 << VIRTIO_RING_F_EVENT_IDX)) {
+ vring_avail_event(vq, vring_avail_idx(vq));
+ } else if (enable) {
vring_used_flags_unset_bit(vq, VRING_USED_F_NO_NOTIFY);
- else
+ } else {
vring_used_flags_set_bit(vq, VRING_USED_F_NO_NOTIFY);
+ }
}
int virtio_queue_ready(VirtQueue *vq)
@@ -233,11 +262,16 @@ void virtqueue_fill(VirtQueue *vq, const VirtQueueElement *elem,
void virtqueue_flush(VirtQueue *vq, unsigned int count)
{
+ uint16_t old, new;
/* Make sure buffer is written before we update index. */
wmb();
trace_virtqueue_flush(vq, count);
- vring_used_idx_increment(vq, count);
+ old = vring_used_idx(vq);
+ new = old + count;
+ vring_used_idx_set(vq, new);
vq->inuse -= count;
+ if (unlikely((int16_t)(new - vq->signalled_used) < (uint16_t)(new - old)))
+ vq->signalled_used_valid = false;
}
void virtqueue_push(VirtQueue *vq, const VirtQueueElement *elem,
@@ -394,6 +428,9 @@ int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem)
max = vq->vring.num;
i = head = virtqueue_get_head(vq, vq->last_avail_idx++);
+ if (vq->vdev->guest_features & (1 << VIRTIO_RING_F_EVENT_IDX)) {
+ vring_avail_event(vq, vring_avail_idx(vq));
+ }
if (vring_desc_flags(desc_pa, i) & VRING_DESC_F_INDIRECT) {
if (vring_desc_len(desc_pa, i) % sizeof(VRingDesc)) {
@@ -477,6 +514,9 @@ void virtio_reset(void *opaque)
vdev->vq[i].last_avail_idx = 0;
vdev->vq[i].pa = 0;
vdev->vq[i].vector = VIRTIO_NO_VECTOR;
+ vdev->vq[i].signalled_used = 0;
+ vdev->vq[i].signalled_used_valid = false;
+ vdev->vq[i].notification = true;
}
}
@@ -585,9 +625,7 @@ void virtio_queue_notify_vq(VirtQueue *vq)
void virtio_queue_notify(VirtIODevice *vdev, int n)
{
- if (n < VIRTIO_PCI_QUEUE_MAX) {
- virtio_queue_notify_vq(&vdev->vq[n]);
- }
+ virtio_queue_notify_vq(&vdev->vq[n]);
}
uint16_t virtio_queue_vector(VirtIODevice *vdev, int n)
@@ -628,13 +666,45 @@ void virtio_irq(VirtQueue *vq)
virtio_notify_vector(vq->vdev, vq->vector);
}
-void virtio_notify(VirtIODevice *vdev, VirtQueue *vq)
+/* Assuming a given event_idx value from the other size, if
+ * we have just incremented index from old to new_idx,
+ * should we trigger an event? */
+static inline int vring_need_event(uint16_t event, uint16_t new, uint16_t old)
+{
+ /* Note: Xen has similar logic for notification hold-off
+ * in include/xen/interface/io/ring.h with req_event and req_prod
+ * corresponding to event_idx + 1 and new respectively.
+ * Note also that req_event and req_prod in Xen start at 1,
+ * event indexes in virtio start at 0. */
+ return (uint16_t)(new - event - 1) < (uint16_t)(new - old);
+}
+
+static bool vring_notify(VirtIODevice *vdev, VirtQueue *vq)
{
+ uint16_t old, new;
+ bool v;
/* Always notify when queue is empty (when feature acknowledge) */
- if ((vring_avail_flags(vq) & VRING_AVAIL_F_NO_INTERRUPT) &&
- (!(vdev->guest_features & (1 << VIRTIO_F_NOTIFY_ON_EMPTY)) ||
- (vq->inuse || vring_avail_idx(vq) != vq->last_avail_idx)))
+ if (((vdev->guest_features & (1 << VIRTIO_F_NOTIFY_ON_EMPTY)) &&
+ !vq->inuse && vring_avail_idx(vq) == vq->last_avail_idx)) {
+ return true;
+ }
+
+ if (!(vdev->guest_features & (1 << VIRTIO_RING_F_EVENT_IDX))) {
+ return !(vring_avail_flags(vq) & VRING_AVAIL_F_NO_INTERRUPT);
+ }
+
+ v = vq->signalled_used_valid;
+ vq->signalled_used_valid = true;
+ old = vq->signalled_used;
+ new = vq->signalled_used = vring_used_idx(vq);
+ return !v || vring_need_event(vring_used_event(vq), new, old);
+}
+
+void virtio_notify(VirtIODevice *vdev, VirtQueue *vq)
+{
+ if (!vring_notify(vdev, vq)) {
return;
+ }
trace_virtio_notify(vdev, vq);
vdev->isr |= 0x01;
@@ -717,6 +787,8 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f)
vdev->vq[i].vring.num = qemu_get_be32(f);
vdev->vq[i].pa = qemu_get_be64(f);
qemu_get_be16s(f, &vdev->vq[i].last_avail_idx);
+ vdev->vq[i].signalled_used_valid = false;
+ vdev->vq[i].notification = true;
if (vdev->vq[i].pa) {
uint16_t nheads;
@@ -725,7 +797,7 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f)
/* Check it isn't doing very strange things with descriptor numbers. */
if (nheads > vdev->vq[i].vring.num) {
error_report("VQ %d size 0x%x Guest index 0x%x "
- "inconsistent with Host index 0x%x: delta 0x%x\n",
+ "inconsistent with Host index 0x%x: delta 0x%x",
i, vdev->vq[i].vring.num,
vring_avail_idx(&vdev->vq[i]),
vdev->vq[i].last_avail_idx, nheads);
@@ -733,7 +805,7 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f)
}
} else if (vdev->vq[i].last_avail_idx) {
error_report("VQ %d address 0x0 "
- "inconsistent with Host index 0x%x\n",
+ "inconsistent with Host index 0x%x",
i, vdev->vq[i].last_avail_idx);
return -1;
}
@@ -789,6 +861,7 @@ VirtIODevice *virtio_common_init(const char *name, uint16_t device_id,
vdev->queue_sel = 0;
vdev->config_vector = VIRTIO_NO_VECTOR;
vdev->vq = qemu_mallocz(sizeof(VirtQueue) * VIRTIO_PCI_QUEUE_MAX);
+ vdev->vm_running = vm_running;
for(i = 0; i < VIRTIO_PCI_QUEUE_MAX; i++) {
vdev->vq[i].vector = VIRTIO_NO_VECTOR;
vdev->vq[i].vdev = vdev;
diff --git a/hw/virtio.h b/hw/virtio.h
index bc722896c9..69e6bb1a4e 100644
--- a/hw/virtio.h
+++ b/hw/virtio.h
@@ -46,6 +46,11 @@
#define VIRTIO_F_NOTIFY_ON_EMPTY 24
/* We support indirect buffer descriptors */
#define VIRTIO_RING_F_INDIRECT_DESC 28
+/* The Guest publishes the used index for which it expects an interrupt
+ * at the end of the avail ring. Host should ignore the avail->flags field. */
+/* The Host publishes the avail index for which it expects a kick
+ * at the end of the used ring. Guest should ignore the used->flags field. */
+#define VIRTIO_RING_F_EVENT_IDX 29
/* A guest should never accept this. It implies negotiation is broken. */
#define VIRTIO_F_BAD_FEATURE 30
@@ -210,7 +215,9 @@ void virtio_serial_exit(VirtIODevice *vdev);
#define DEFINE_VIRTIO_COMMON_FEATURES(_state, _field) \
DEFINE_PROP_BIT("indirect_desc", _state, _field, \
- VIRTIO_RING_F_INDIRECT_DESC, true)
+ VIRTIO_RING_F_INDIRECT_DESC, true), \
+ DEFINE_PROP_BIT("event_idx", _state, _field, \
+ VIRTIO_RING_F_EVENT_IDX, true)
target_phys_addr_t virtio_queue_get_desc_addr(VirtIODevice *vdev, int n);
target_phys_addr_t virtio_queue_get_avail_addr(VirtIODevice *vdev, int n);
diff --git a/hw/vmware_vga.c b/hw/vmware_vga.c
index 4656767964..354c221720 100644
--- a/hw/vmware_vga.c
+++ b/hw/vmware_vga.c
@@ -1280,15 +1280,8 @@ static int pci_vmsvga_initfn(PCIDevice *dev)
struct pci_vmsvga_state_s *s =
DO_UPCAST(struct pci_vmsvga_state_s, card, dev);
- pci_config_set_vendor_id(s->card.config, PCI_VENDOR_ID_VMWARE);
- pci_config_set_device_id(s->card.config, SVGA_PCI_DEVICE_ID);
- pci_config_set_class(s->card.config, PCI_CLASS_DISPLAY_VGA);
s->card.config[PCI_CACHE_LINE_SIZE] = 0x08; /* Cache line size */
s->card.config[PCI_LATENCY_TIMER] = 0x40; /* Latency timer */
- s->card.config[PCI_SUBSYSTEM_VENDOR_ID] = PCI_VENDOR_ID_VMWARE & 0xff;
- s->card.config[PCI_SUBSYSTEM_VENDOR_ID + 1] = PCI_VENDOR_ID_VMWARE >> 8;
- s->card.config[PCI_SUBSYSTEM_ID] = SVGA_PCI_DEVICE_ID & 0xff;
- s->card.config[PCI_SUBSYSTEM_ID + 1] = SVGA_PCI_DEVICE_ID >> 8;
s->card.config[PCI_INTERRUPT_LINE] = 0xff; /* End */
pci_register_bar(&s->card, 0, 0x10,
@@ -1316,6 +1309,12 @@ static PCIDeviceInfo vmsvga_info = {
.no_hotplug = 1,
.init = pci_vmsvga_initfn,
.romfile = "vgabios-vmware.bin",
+
+ .vendor_id = PCI_VENDOR_ID_VMWARE,
+ .device_id = SVGA_PCI_DEVICE_ID,
+ .class_id = PCI_CLASS_DISPLAY_VGA,
+ .subsystem_vendor_id = PCI_VENDOR_ID_VMWARE,
+ .subsystem_id = SVGA_PCI_DEVICE_ID,
};
static void vmsvga_register(void)
diff --git a/hw/vt82c686.c b/hw/vt82c686.c
index ca8f826a07..5c973ed507 100644
--- a/hw/vt82c686.c
+++ b/hw/vt82c686.c
@@ -326,11 +326,6 @@ static int vt82c686b_ac97_initfn(PCIDevice *dev)
VT686AC97State *s = DO_UPCAST(VT686AC97State, dev, dev);
uint8_t *pci_conf = s->dev.config;
- pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_VIA);
- pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_VIA_AC97);
- pci_config_set_class(pci_conf, PCI_CLASS_MULTIMEDIA_AUDIO);
- pci_config_set_revision(pci_conf, 0x50);
-
pci_set_word(pci_conf + PCI_COMMAND, PCI_COMMAND_INVALIDATE |
PCI_COMMAND_PARITY);
pci_set_word(pci_conf + PCI_STATUS, PCI_STATUS_CAP_LIST |
@@ -353,6 +348,10 @@ static PCIDeviceInfo via_ac97_info = {
.qdev.desc = "AC97",
.qdev.size = sizeof(VT686AC97State),
.init = vt82c686b_ac97_initfn,
+ .vendor_id = PCI_VENDOR_ID_VIA,
+ .device_id = PCI_DEVICE_ID_VIA_AC97,
+ .revision = 0x50,
+ .class_id = PCI_CLASS_MULTIMEDIA_AUDIO,
};
static void vt82c686b_ac97_register(void)
@@ -367,11 +366,6 @@ static int vt82c686b_mc97_initfn(PCIDevice *dev)
VT686MC97State *s = DO_UPCAST(VT686MC97State, dev, dev);
uint8_t *pci_conf = s->dev.config;
- pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_VIA);
- pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_VIA_MC97);
- pci_config_set_class(pci_conf, PCI_CLASS_COMMUNICATION_OTHER);
- pci_config_set_revision(pci_conf, 0x30);
-
pci_set_word(pci_conf + PCI_COMMAND, PCI_COMMAND_INVALIDATE |
PCI_COMMAND_VGA_PALETTE);
pci_set_word(pci_conf + PCI_STATUS, PCI_STATUS_DEVSEL_MEDIUM);
@@ -393,6 +387,10 @@ static PCIDeviceInfo via_mc97_info = {
.qdev.desc = "MC97",
.qdev.size = sizeof(VT686MC97State),
.init = vt82c686b_mc97_initfn,
+ .vendor_id = PCI_VENDOR_ID_VIA,
+ .device_id = PCI_DEVICE_ID_VIA_MC97,
+ .class_id = PCI_CLASS_COMMUNICATION_OTHER,
+ .revision = 0x30,
};
static void vt82c686b_mc97_register(void)
@@ -409,11 +407,6 @@ static int vt82c686b_pm_initfn(PCIDevice *dev)
uint8_t *pci_conf;
pci_conf = s->dev.config;
- pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_VIA);
- pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_VIA_ACPI);
- pci_config_set_class(pci_conf, PCI_CLASS_BRIDGE_OTHER);
- pci_config_set_revision(pci_conf, 0x40);
-
pci_set_word(pci_conf + PCI_COMMAND, 0);
pci_set_word(pci_conf + PCI_STATUS, PCI_STATUS_FAST_BACK |
PCI_STATUS_DEVSEL_MEDIUM);
@@ -462,6 +455,10 @@ static PCIDeviceInfo via_pm_info = {
.qdev.vmsd = &vmstate_acpi,
.init = vt82c686b_pm_initfn,
.config_write = pm_write_config,
+ .vendor_id = PCI_VENDOR_ID_VIA,
+ .device_id = PCI_DEVICE_ID_VIA_ACPI,
+ .class_id = PCI_CLASS_BRIDGE_OTHER,
+ .revision = 0x40,
.qdev.props = (Property[]) {
DEFINE_PROP_UINT32("smb_io_base", VT686PMState, smb_io_base, 0),
DEFINE_PROP_END_OF_LIST(),
@@ -496,11 +493,7 @@ static int vt82c686b_initfn(PCIDevice *d)
isa_bus_new(&d->qdev);
pci_conf = d->config;
- pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_VIA);
- pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_VIA_ISA_BRIDGE);
- pci_config_set_class(pci_conf, PCI_CLASS_BRIDGE_ISA);
pci_config_set_prog_interface(pci_conf, 0x0);
- pci_config_set_revision(pci_conf,0x40); /* Revision 4.0 */
wmask = d->wmask;
for (i = 0x00; i < 0xff; i++) {
@@ -531,6 +524,10 @@ static PCIDeviceInfo via_info = {
.qdev.no_user = 1,
.init = vt82c686b_initfn,
.config_write = vt82c686b_write_config,
+ .vendor_id = PCI_VENDOR_ID_VIA,
+ .device_id = PCI_DEVICE_ID_VIA_ISA_BRIDGE,
+ .class_id = PCI_CLASS_BRIDGE_ISA,
+ .revision = 0x40,
};
static void vt82c686b_register(void)
diff --git a/hw/wdt_i6300esb.c b/hw/wdt_i6300esb.c
index 07917212c3..53786ce8fa 100644
--- a/hw/wdt_i6300esb.c
+++ b/hw/wdt_i6300esb.c
@@ -381,7 +381,6 @@ static const VMStateDescription vmstate_i6300esb = {
static int i6300esb_init(PCIDevice *dev)
{
I6300State *d = DO_UPCAST(I6300State, dev, dev);
- uint8_t *pci_conf;
int io_mem;
static CPUReadMemoryFunc * const mem_read[3] = {
i6300esb_mem_readb,
@@ -399,11 +398,6 @@ static int i6300esb_init(PCIDevice *dev)
d->timer = qemu_new_timer_ns(vm_clock, i6300esb_timer_expired, d);
d->previous_reboot_flag = 0;
- pci_conf = d->dev.config;
- pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_INTEL);
- pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_INTEL_ESB_9);
- pci_config_set_class(pci_conf, PCI_CLASS_SYSTEM_OTHER);
-
io_mem = cpu_register_io_memory(mem_read, mem_write, d,
DEVICE_NATIVE_ENDIAN);
pci_register_bar_simple(&d->dev, 0, 0x10, 0, io_mem);
@@ -425,6 +419,9 @@ static PCIDeviceInfo i6300esb_info = {
.config_read = i6300esb_config_read,
.config_write = i6300esb_config_write,
.init = i6300esb_init,
+ .vendor_id = PCI_VENDOR_ID_INTEL,
+ .device_id = PCI_DEVICE_ID_INTEL_ESB_9,
+ .class_id = PCI_CLASS_SYSTEM_OTHER,
};
static void i6300esb_register_devices(void)
diff --git a/hw/xen_common.h b/hw/xen_common.h
index a1958a0af1..2c79af64d0 100644
--- a/hw/xen_common.h
+++ b/hw/xen_common.h
@@ -71,6 +71,20 @@ static inline int xc_domain_populate_physmap_exact
(xc_handle, domid, nr_extents, extent_order, mem_flags, extent_start);
}
+static inline int xc_domain_add_to_physmap(int xc_handle, uint32_t domid,
+ unsigned int space, unsigned long idx,
+ xen_pfn_t gpfn)
+{
+ struct xen_add_to_physmap xatp = {
+ .domid = domid,
+ .space = space,
+ .idx = idx,
+ .gpfn = gpfn,
+ };
+
+ return xc_memory_op(xc_handle, XENMEM_add_to_physmap, &xatp);
+}
+
/* Xen 4.1 */
#else
diff --git a/hw/xen_platform.c b/hw/xen_platform.c
new file mode 100644
index 0000000000..b167eee1ff
--- /dev/null
+++ b/hw/xen_platform.c
@@ -0,0 +1,340 @@
+/*
+ * XEN platform pci device, formerly known as the event channel device
+ *
+ * Copyright (c) 2003-2004 Intel Corp.
+ * Copyright (c) 2006 XenSource
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <assert.h>
+
+#include "hw.h"
+#include "pc.h"
+#include "pci.h"
+#include "irq.h"
+#include "xen_common.h"
+#include "net.h"
+#include "xen_backend.h"
+#include "rwhandler.h"
+#include "trace.h"
+
+#include <xenguest.h>
+
+//#define DEBUG_PLATFORM
+
+#ifdef DEBUG_PLATFORM
+#define DPRINTF(fmt, ...) do { \
+ fprintf(stderr, "xen_platform: " fmt, ## __VA_ARGS__); \
+} while (0)
+#else
+#define DPRINTF(fmt, ...) do { } while (0)
+#endif
+
+#define PFFLAG_ROM_LOCK 1 /* Sets whether ROM memory area is RW or RO */
+
+typedef struct PCIXenPlatformState {
+ PCIDevice pci_dev;
+ uint8_t flags; /* used only for version_id == 2 */
+ int drivers_blacklisted;
+ uint16_t driver_product_version;
+
+ /* Log from guest drivers */
+ char log_buffer[4096];
+ int log_buffer_off;
+} PCIXenPlatformState;
+
+#define XEN_PLATFORM_IOPORT 0x10
+
+/* Send bytes to syslog */
+static void log_writeb(PCIXenPlatformState *s, char val)
+{
+ if (val == '\n' || s->log_buffer_off == sizeof(s->log_buffer) - 1) {
+ /* Flush buffer */
+ s->log_buffer[s->log_buffer_off] = 0;
+ trace_xen_platform_log(s->log_buffer);
+ s->log_buffer_off = 0;
+ } else {
+ s->log_buffer[s->log_buffer_off++] = val;
+ }
+}
+
+/* Xen Platform, Fixed IOPort */
+
+static void platform_fixed_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
+{
+ PCIXenPlatformState *s = opaque;
+
+ switch (addr - XEN_PLATFORM_IOPORT) {
+ case 0:
+ /* TODO: */
+ /* Unplug devices. Value is a bitmask of which devices to
+ unplug, with bit 0 the IDE devices, bit 1 the network
+ devices, and bit 2 the non-primary-master IDE devices. */
+ break;
+ case 2:
+ switch (val) {
+ case 1:
+ DPRINTF("Citrix Windows PV drivers loaded in guest\n");
+ break;
+ case 0:
+ DPRINTF("Guest claimed to be running PV product 0?\n");
+ break;
+ default:
+ DPRINTF("Unknown PV product %d loaded in guest\n", val);
+ break;
+ }
+ s->driver_product_version = val;
+ break;
+ }
+}
+
+static void platform_fixed_ioport_writel(void *opaque, uint32_t addr,
+ uint32_t val)
+{
+ switch (addr - XEN_PLATFORM_IOPORT) {
+ case 0:
+ /* PV driver version */
+ break;
+ }
+}
+
+static void platform_fixed_ioport_writeb(void *opaque, uint32_t addr, uint32_t val)
+{
+ PCIXenPlatformState *s = opaque;
+
+ switch (addr - XEN_PLATFORM_IOPORT) {
+ case 0: /* Platform flags */ {
+ hvmmem_type_t mem_type = (val & PFFLAG_ROM_LOCK) ?
+ HVMMEM_ram_ro : HVMMEM_ram_rw;
+ if (xc_hvm_set_mem_type(xen_xc, xen_domid, mem_type, 0xc0, 0x40)) {
+ DPRINTF("unable to change ro/rw state of ROM memory area!\n");
+ } else {
+ s->flags = val & PFFLAG_ROM_LOCK;
+ DPRINTF("changed ro/rw state of ROM memory area. now is %s state.\n",
+ (mem_type == HVMMEM_ram_ro ? "ro":"rw"));
+ }
+ break;
+ }
+ case 2:
+ log_writeb(s, val);
+ break;
+ }
+}
+
+static uint32_t platform_fixed_ioport_readw(void *opaque, uint32_t addr)
+{
+ PCIXenPlatformState *s = opaque;
+
+ switch (addr - XEN_PLATFORM_IOPORT) {
+ case 0:
+ if (s->drivers_blacklisted) {
+ /* The drivers will recognise this magic number and refuse
+ * to do anything. */
+ return 0xd249;
+ } else {
+ /* Magic value so that you can identify the interface. */
+ return 0x49d2;
+ }
+ default:
+ return 0xffff;
+ }
+}
+
+static uint32_t platform_fixed_ioport_readb(void *opaque, uint32_t addr)
+{
+ PCIXenPlatformState *s = opaque;
+
+ switch (addr - XEN_PLATFORM_IOPORT) {
+ case 0:
+ /* Platform flags */
+ return s->flags;
+ case 2:
+ /* Version number */
+ return 1;
+ default:
+ return 0xff;
+ }
+}
+
+static void platform_fixed_ioport_reset(void *opaque)
+{
+ PCIXenPlatformState *s = opaque;
+
+ platform_fixed_ioport_writeb(s, XEN_PLATFORM_IOPORT, 0);
+}
+
+static void platform_fixed_ioport_init(PCIXenPlatformState* s)
+{
+ register_ioport_write(XEN_PLATFORM_IOPORT, 16, 4, platform_fixed_ioport_writel, s);
+ register_ioport_write(XEN_PLATFORM_IOPORT, 16, 2, platform_fixed_ioport_writew, s);
+ register_ioport_write(XEN_PLATFORM_IOPORT, 16, 1, platform_fixed_ioport_writeb, s);
+ register_ioport_read(XEN_PLATFORM_IOPORT, 16, 2, platform_fixed_ioport_readw, s);
+ register_ioport_read(XEN_PLATFORM_IOPORT, 16, 1, platform_fixed_ioport_readb, s);
+}
+
+/* Xen Platform PCI Device */
+
+static uint32_t xen_platform_ioport_readb(void *opaque, uint32_t addr)
+{
+ addr &= 0xff;
+
+ if (addr == 0) {
+ return platform_fixed_ioport_readb(opaque, XEN_PLATFORM_IOPORT);
+ } else {
+ return ~0u;
+ }
+}
+
+static void xen_platform_ioport_writeb(void *opaque, uint32_t addr, uint32_t val)
+{
+ PCIXenPlatformState *s = opaque;
+
+ addr &= 0xff;
+ val &= 0xff;
+
+ switch (addr) {
+ case 0: /* Platform flags */
+ platform_fixed_ioport_writeb(opaque, XEN_PLATFORM_IOPORT, val);
+ break;
+ case 8:
+ log_writeb(s, val);
+ break;
+ default:
+ break;
+ }
+}
+
+static void platform_ioport_map(PCIDevice *pci_dev, int region_num, pcibus_t addr, pcibus_t size, int type)
+{
+ PCIXenPlatformState *d = DO_UPCAST(PCIXenPlatformState, pci_dev, pci_dev);
+
+ register_ioport_write(addr, size, 1, xen_platform_ioport_writeb, d);
+ register_ioport_read(addr, size, 1, xen_platform_ioport_readb, d);
+}
+
+static uint32_t platform_mmio_read(ReadWriteHandler *handler, pcibus_t addr, int len)
+{
+ DPRINTF("Warning: attempted read from physical address "
+ "0x" TARGET_FMT_plx " in xen platform mmio space\n", addr);
+
+ return 0;
+}
+
+static void platform_mmio_write(ReadWriteHandler *handler, pcibus_t addr,
+ uint32_t val, int len)
+{
+ DPRINTF("Warning: attempted write of 0x%x to physical "
+ "address 0x" TARGET_FMT_plx " in xen platform mmio space\n",
+ val, addr);
+}
+
+static ReadWriteHandler platform_mmio_handler = {
+ .read = &platform_mmio_read,
+ .write = &platform_mmio_write,
+};
+
+static void platform_mmio_map(PCIDevice *d, int region_num,
+ pcibus_t addr, pcibus_t size, int type)
+{
+ int mmio_io_addr;
+
+ mmio_io_addr = cpu_register_io_memory_simple(&platform_mmio_handler,
+ DEVICE_NATIVE_ENDIAN);
+
+ cpu_register_physical_memory(addr, size, mmio_io_addr);
+}
+
+static int xen_platform_post_load(void *opaque, int version_id)
+{
+ PCIXenPlatformState *s = opaque;
+
+ platform_fixed_ioport_writeb(s, XEN_PLATFORM_IOPORT, s->flags);
+
+ return 0;
+}
+
+static const VMStateDescription vmstate_xen_platform = {
+ .name = "platform",
+ .version_id = 4,
+ .minimum_version_id = 4,
+ .minimum_version_id_old = 4,
+ .post_load = xen_platform_post_load,
+ .fields = (VMStateField []) {
+ VMSTATE_PCI_DEVICE(pci_dev, PCIXenPlatformState),
+ VMSTATE_UINT8(flags, PCIXenPlatformState),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static int xen_platform_initfn(PCIDevice *dev)
+{
+ PCIXenPlatformState *d = DO_UPCAST(PCIXenPlatformState, pci_dev, dev);
+ uint8_t *pci_conf;
+
+ pci_conf = d->pci_dev.config;
+
+ pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_XENSOURCE);
+ pci_config_set_device_id(pci_conf, 0x0001);
+ pci_set_word(pci_conf + PCI_SUBSYSTEM_VENDOR_ID, PCI_VENDOR_ID_XENSOURCE);
+ pci_set_word(pci_conf + PCI_SUBSYSTEM_ID, 0x0001);
+
+ pci_set_word(pci_conf + PCI_COMMAND, PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
+
+ pci_config_set_revision(pci_conf, 1);
+ pci_config_set_prog_interface(pci_conf, 0);
+
+ pci_config_set_class(pci_conf, PCI_CLASS_OTHERS << 8 | 0x80);
+
+ pci_conf[PCI_INTERRUPT_PIN] = 1;
+
+ pci_register_bar(&d->pci_dev, 0, 0x100,
+ PCI_BASE_ADDRESS_SPACE_IO, platform_ioport_map);
+
+ /* reserve 16MB mmio address for share memory*/
+ pci_register_bar(&d->pci_dev, 1, 0x1000000,
+ PCI_BASE_ADDRESS_MEM_PREFETCH, platform_mmio_map);
+
+ platform_fixed_ioport_init(d);
+
+ return 0;
+}
+
+static void platform_reset(DeviceState *dev)
+{
+ PCIXenPlatformState *s = DO_UPCAST(PCIXenPlatformState, pci_dev.qdev, dev);
+
+ platform_fixed_ioport_reset(s);
+}
+
+static PCIDeviceInfo xen_platform_info = {
+ .init = xen_platform_initfn,
+ .qdev.name = "xen-platform",
+ .qdev.desc = "XEN platform pci device",
+ .qdev.size = sizeof(PCIXenPlatformState),
+ .qdev.vmsd = &vmstate_xen_platform,
+ .qdev.reset = platform_reset,
+};
+
+static void xen_platform_register(void)
+{
+ pci_qdev_register(&xen_platform_info);
+}
+
+device_init(xen_platform_register);
diff --git a/hw/xio3130_downstream.c b/hw/xio3130_downstream.c
index 5aa6a6b149..d3c387d6cb 100644
--- a/hw/xio3130_downstream.c
+++ b/hw/xio3130_downstream.c
@@ -69,9 +69,6 @@ static int xio3130_downstream_initfn(PCIDevice *d)
}
pcie_port_init_reg(d);
- pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_TI);
- pci_config_set_device_id(d->config, PCI_DEVICE_ID_TI_XIO3130D);
- d->config[PCI_REVISION_ID] = XIO3130_REVISION;
rc = msi_init(d, XIO3130_MSI_OFFSET, XIO3130_MSI_NR_VECTOR,
XIO3130_MSI_SUPPORTED_FLAGS & PCI_MSI_FLAGS_64BIT,
@@ -182,6 +179,9 @@ static PCIDeviceInfo xio3130_downstream_info = {
.config_write = xio3130_downstream_write_config,
.init = xio3130_downstream_initfn,
.exit = xio3130_downstream_exitfn,
+ .vendor_id = PCI_VENDOR_ID_TI,
+ .device_id = PCI_DEVICE_ID_TI_XIO3130D,
+ .revision = XIO3130_REVISION,
.qdev.props = (Property[]) {
DEFINE_PROP_UINT8("port", PCIESlot, port.port, 0),
diff --git a/hw/xio3130_upstream.c b/hw/xio3130_upstream.c
index a7640f518a..82836958a4 100644
--- a/hw/xio3130_upstream.c
+++ b/hw/xio3130_upstream.c
@@ -65,9 +65,6 @@ static int xio3130_upstream_initfn(PCIDevice *d)
}
pcie_port_init_reg(d);
- pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_TI);
- pci_config_set_device_id(d->config, PCI_DEVICE_ID_TI_XIO3130U);
- d->config[PCI_REVISION_ID] = XIO3130_REVISION;
rc = msi_init(d, XIO3130_MSI_OFFSET, XIO3130_MSI_NR_VECTOR,
XIO3130_MSI_SUPPORTED_FLAGS & PCI_MSI_FLAGS_64BIT,
@@ -159,6 +156,9 @@ static PCIDeviceInfo xio3130_upstream_info = {
.config_write = xio3130_upstream_write_config,
.init = xio3130_upstream_initfn,
.exit = xio3130_upstream_exitfn,
+ .vendor_id = PCI_VENDOR_ID_TI,
+ .device_id = PCI_DEVICE_ID_TI_XIO3130U,
+ .revision = XIO3130_REVISION,
.qdev.props = (Property[]) {
DEFINE_PROP_UINT8("port", PCIEPort, port, 0),
diff --git a/kvm-all.c b/kvm-all.c
index 106eb3adbd..cbc253235e 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -757,35 +757,26 @@ int kvm_init(void)
s->coalesced_mmio = kvm_check_extension(s, KVM_CAP_COALESCED_MMIO);
s->broken_set_mem_region = 1;
-#ifdef KVM_CAP_JOIN_MEMORY_REGIONS_WORKS
ret = kvm_check_extension(s, KVM_CAP_JOIN_MEMORY_REGIONS_WORKS);
if (ret > 0) {
s->broken_set_mem_region = 0;
}
-#endif
- s->vcpu_events = 0;
#ifdef KVM_CAP_VCPU_EVENTS
s->vcpu_events = kvm_check_extension(s, KVM_CAP_VCPU_EVENTS);
#endif
- s->robust_singlestep = 0;
-#ifdef KVM_CAP_X86_ROBUST_SINGLESTEP
s->robust_singlestep =
kvm_check_extension(s, KVM_CAP_X86_ROBUST_SINGLESTEP);
-#endif
- s->debugregs = 0;
#ifdef KVM_CAP_DEBUGREGS
s->debugregs = kvm_check_extension(s, KVM_CAP_DEBUGREGS);
#endif
- s->xsave = 0;
#ifdef KVM_CAP_XSAVE
s->xsave = kvm_check_extension(s, KVM_CAP_XSAVE);
#endif
- s->xcrs = 0;
#ifdef KVM_CAP_XCRS
s->xcrs = kvm_check_extension(s, KVM_CAP_XCRS);
#endif
@@ -855,7 +846,6 @@ static void kvm_handle_io(uint16_t port, void *data, int direction, int size,
}
}
-#ifdef KVM_CAP_INTERNAL_ERROR_DATA
static int kvm_handle_internal_error(CPUState *env, struct kvm_run *run)
{
fprintf(stderr, "KVM internal error.");
@@ -882,7 +872,6 @@ static int kvm_handle_internal_error(CPUState *env, struct kvm_run *run)
*/
return -1;
}
-#endif
void kvm_flush_coalesced_mmio_buffer(void)
{
@@ -1013,11 +1002,9 @@ int kvm_cpu_exec(CPUState *env)
(uint64_t)run->hw.hardware_exit_reason);
ret = -1;
break;
-#ifdef KVM_CAP_INTERNAL_ERROR_DATA
case KVM_EXIT_INTERNAL_ERROR:
ret = kvm_handle_internal_error(env, run);
break;
-#endif
default:
DPRINTF("kvm_arch_handle_exit\n");
ret = kvm_arch_handle_exit(env, run);
diff --git a/kvm-stub.c b/kvm-stub.c
index 1c95452140..06064b9a86 100644
--- a/kvm-stub.c
+++ b/kvm-stub.c
@@ -12,7 +12,7 @@
#include "qemu-common.h"
#include "hw/hw.h"
-#include "exec-all.h"
+#include "cpu.h"
#include "gdbstub.h"
#include "kvm.h"
@@ -42,11 +42,6 @@ int kvm_uncoalesce_mmio_region(target_phys_addr_t start, ram_addr_t size)
return -ENOSYS;
}
-int kvm_check_extension(KVMState *s, unsigned int extension)
-{
- return 0;
-}
-
int kvm_init(void)
{
return -ENOSYS;
@@ -78,16 +73,6 @@ int kvm_has_sync_mmu(void)
return 0;
}
-int kvm_has_vcpu_events(void)
-{
- return 0;
-}
-
-int kvm_has_robust_singlestep(void)
-{
- return 0;
-}
-
int kvm_has_many_ioeventfds(void)
{
return 0;
@@ -99,8 +84,7 @@ void kvm_setup_guest_memory(void *start, size_t size)
int kvm_update_guest_debug(CPUState *env, unsigned long reinject_trap)
{
- tb_flush(env);
- return 0;
+ return -ENOSYS;
}
int kvm_insert_breakpoint(CPUState *current_env, target_ulong addr,
diff --git a/kvm.h b/kvm.h
index d565dba1da..243b063f92 100644
--- a/kvm.h
+++ b/kvm.h
@@ -157,7 +157,7 @@ bool kvm_arch_stop_on_emulation_error(CPUState *env);
int kvm_check_extension(KVMState *s, unsigned int extension);
-uint32_t kvm_arch_get_supported_cpuid(CPUState *env, uint32_t function,
+uint32_t kvm_arch_get_supported_cpuid(KVMState *env, uint32_t function,
uint32_t index, int reg);
void kvm_cpu_synchronize_state(CPUState *env);
void kvm_cpu_synchronize_post_reset(CPUState *env);
diff --git a/linux-headers/COPYING b/linux-headers/COPYING
new file mode 100644
index 0000000000..ca442d313d
--- /dev/null
+++ b/linux-headers/COPYING
@@ -0,0 +1,356 @@
+
+ NOTE! This copyright does *not* cover user programs that use kernel
+ services by normal system calls - this is merely considered normal use
+ of the kernel, and does *not* fall under the heading of "derived work".
+ Also note that the GPL below is copyrighted by the Free Software
+ Foundation, but the instance of code that it refers to (the Linux
+ kernel) is copyrighted by me and others who actually wrote it.
+
+ Also note that the only valid version of the GPL as far as the kernel
+ is concerned is _this_ particular version of the license (ie v2, not
+ v2.2 or v3.x or whatever), unless explicitly otherwise stated.
+
+ Linus Torvalds
+
+----------------------------------------
+
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/linux-headers/README b/linux-headers/README
new file mode 100644
index 0000000000..5c9026b3da
--- /dev/null
+++ b/linux-headers/README
@@ -0,0 +1,2 @@
+Automatically imported Linux kernel headers.
+Only use scripts/update-linux-headers.sh to update!
diff --git a/linux-headers/asm-powerpc/kvm.h b/linux-headers/asm-powerpc/kvm.h
new file mode 100644
index 0000000000..777d307c71
--- /dev/null
+++ b/linux-headers/asm-powerpc/kvm.h
@@ -0,0 +1,275 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Copyright IBM Corp. 2007
+ *
+ * Authors: Hollis Blanchard <hollisb@us.ibm.com>
+ */
+
+#ifndef __LINUX_KVM_POWERPC_H
+#define __LINUX_KVM_POWERPC_H
+
+#include <linux/types.h>
+
+struct kvm_regs {
+ __u64 pc;
+ __u64 cr;
+ __u64 ctr;
+ __u64 lr;
+ __u64 xer;
+ __u64 msr;
+ __u64 srr0;
+ __u64 srr1;
+ __u64 pid;
+
+ __u64 sprg0;
+ __u64 sprg1;
+ __u64 sprg2;
+ __u64 sprg3;
+ __u64 sprg4;
+ __u64 sprg5;
+ __u64 sprg6;
+ __u64 sprg7;
+
+ __u64 gpr[32];
+};
+
+#define KVM_SREGS_E_IMPL_NONE 0
+#define KVM_SREGS_E_IMPL_FSL 1
+
+#define KVM_SREGS_E_FSL_PIDn (1 << 0) /* PID1/PID2 */
+
+/*
+ * Feature bits indicate which sections of the sregs struct are valid,
+ * both in KVM_GET_SREGS and KVM_SET_SREGS. On KVM_SET_SREGS, registers
+ * corresponding to unset feature bits will not be modified. This allows
+ * restoring a checkpoint made without that feature, while keeping the
+ * default values of the new registers.
+ *
+ * KVM_SREGS_E_BASE contains:
+ * CSRR0/1 (refers to SRR2/3 on 40x)
+ * ESR
+ * DEAR
+ * MCSR
+ * TSR
+ * TCR
+ * DEC
+ * TB
+ * VRSAVE (USPRG0)
+ */
+#define KVM_SREGS_E_BASE (1 << 0)
+
+/*
+ * KVM_SREGS_E_ARCH206 contains:
+ *
+ * PIR
+ * MCSRR0/1
+ * DECAR
+ * IVPR
+ */
+#define KVM_SREGS_E_ARCH206 (1 << 1)
+
+/*
+ * Contains EPCR, plus the upper half of 64-bit registers
+ * that are 32-bit on 32-bit implementations.
+ */
+#define KVM_SREGS_E_64 (1 << 2)
+
+#define KVM_SREGS_E_SPRG8 (1 << 3)
+#define KVM_SREGS_E_MCIVPR (1 << 4)
+
+/*
+ * IVORs are used -- contains IVOR0-15, plus additional IVORs
+ * in combination with an appropriate feature bit.
+ */
+#define KVM_SREGS_E_IVOR (1 << 5)
+
+/*
+ * Contains MAS0-4, MAS6-7, TLBnCFG, MMUCFG.
+ * Also TLBnPS if MMUCFG[MAVN] = 1.
+ */
+#define KVM_SREGS_E_ARCH206_MMU (1 << 6)
+
+/* DBSR, DBCR, IAC, DAC, DVC */
+#define KVM_SREGS_E_DEBUG (1 << 7)
+
+/* Enhanced debug -- DSRR0/1, SPRG9 */
+#define KVM_SREGS_E_ED (1 << 8)
+
+/* Embedded Floating Point (SPE) -- IVOR32-34 if KVM_SREGS_E_IVOR */
+#define KVM_SREGS_E_SPE (1 << 9)
+
+/* External Proxy (EXP) -- EPR */
+#define KVM_SREGS_EXP (1 << 10)
+
+/* External PID (E.PD) -- EPSC/EPLC */
+#define KVM_SREGS_E_PD (1 << 11)
+
+/* Processor Control (E.PC) -- IVOR36-37 if KVM_SREGS_E_IVOR */
+#define KVM_SREGS_E_PC (1 << 12)
+
+/* Page table (E.PT) -- EPTCFG */
+#define KVM_SREGS_E_PT (1 << 13)
+
+/* Embedded Performance Monitor (E.PM) -- IVOR35 if KVM_SREGS_E_IVOR */
+#define KVM_SREGS_E_PM (1 << 14)
+
+/*
+ * Special updates:
+ *
+ * Some registers may change even while a vcpu is not running.
+ * To avoid losing these changes, by default these registers are
+ * not updated by KVM_SET_SREGS. To force an update, set the bit
+ * in u.e.update_special corresponding to the register to be updated.
+ *
+ * The update_special field is zero on return from KVM_GET_SREGS.
+ *
+ * When restoring a checkpoint, the caller can set update_special
+ * to 0xffffffff to ensure that everything is restored, even new features
+ * that the caller doesn't know about.
+ */
+#define KVM_SREGS_E_UPDATE_MCSR (1 << 0)
+#define KVM_SREGS_E_UPDATE_TSR (1 << 1)
+#define KVM_SREGS_E_UPDATE_DEC (1 << 2)
+#define KVM_SREGS_E_UPDATE_DBSR (1 << 3)
+
+/*
+ * In KVM_SET_SREGS, reserved/pad fields must be left untouched from a
+ * previous KVM_GET_REGS.
+ *
+ * Unless otherwise indicated, setting any register with KVM_SET_SREGS
+ * directly sets its value. It does not trigger any special semantics such
+ * as write-one-to-clear. Calling KVM_SET_SREGS on an unmodified struct
+ * just received from KVM_GET_SREGS is always a no-op.
+ */
+struct kvm_sregs {
+ __u32 pvr;
+ union {
+ struct {
+ __u64 sdr1;
+ struct {
+ struct {
+ __u64 slbe;
+ __u64 slbv;
+ } slb[64];
+ } ppc64;
+ struct {
+ __u32 sr[16];
+ __u64 ibat[8];
+ __u64 dbat[8];
+ } ppc32;
+ } s;
+ struct {
+ union {
+ struct { /* KVM_SREGS_E_IMPL_FSL */
+ __u32 features; /* KVM_SREGS_E_FSL_ */
+ __u32 svr;
+ __u64 mcar;
+ __u32 hid0;
+
+ /* KVM_SREGS_E_FSL_PIDn */
+ __u32 pid1, pid2;
+ } fsl;
+ __u8 pad[256];
+ } impl;
+
+ __u32 features; /* KVM_SREGS_E_ */
+ __u32 impl_id; /* KVM_SREGS_E_IMPL_ */
+ __u32 update_special; /* KVM_SREGS_E_UPDATE_ */
+ __u32 pir; /* read-only */
+ __u64 sprg8;
+ __u64 sprg9; /* E.ED */
+ __u64 csrr0;
+ __u64 dsrr0; /* E.ED */
+ __u64 mcsrr0;
+ __u32 csrr1;
+ __u32 dsrr1; /* E.ED */
+ __u32 mcsrr1;
+ __u32 esr;
+ __u64 dear;
+ __u64 ivpr;
+ __u64 mcivpr;
+ __u64 mcsr; /* KVM_SREGS_E_UPDATE_MCSR */
+
+ __u32 tsr; /* KVM_SREGS_E_UPDATE_TSR */
+ __u32 tcr;
+ __u32 decar;
+ __u32 dec; /* KVM_SREGS_E_UPDATE_DEC */
+
+ /*
+ * Userspace can read TB directly, but the
+ * value reported here is consistent with "dec".
+ *
+ * Read-only.
+ */
+ __u64 tb;
+
+ __u32 dbsr; /* KVM_SREGS_E_UPDATE_DBSR */
+ __u32 dbcr[3];
+ __u32 iac[4];
+ __u32 dac[2];
+ __u32 dvc[2];
+ __u8 num_iac; /* read-only */
+ __u8 num_dac; /* read-only */
+ __u8 num_dvc; /* read-only */
+ __u8 pad;
+
+ __u32 epr; /* EXP */
+ __u32 vrsave; /* a.k.a. USPRG0 */
+ __u32 epcr; /* KVM_SREGS_E_64 */
+
+ __u32 mas0;
+ __u32 mas1;
+ __u64 mas2;
+ __u64 mas7_3;
+ __u32 mas4;
+ __u32 mas6;
+
+ __u32 ivor_low[16]; /* IVOR0-15 */
+ __u32 ivor_high[18]; /* IVOR32+, plus room to expand */
+
+ __u32 mmucfg; /* read-only */
+ __u32 eptcfg; /* E.PT, read-only */
+ __u32 tlbcfg[4];/* read-only */
+ __u32 tlbps[4]; /* read-only */
+
+ __u32 eplc, epsc; /* E.PD */
+ } e;
+ __u8 pad[1020];
+ } u;
+};
+
+struct kvm_fpu {
+ __u64 fpr[32];
+};
+
+struct kvm_debug_exit_arch {
+};
+
+/* for KVM_SET_GUEST_DEBUG */
+struct kvm_guest_debug_arch {
+};
+
+#define KVM_REG_MASK 0x001f
+#define KVM_REG_EXT_MASK 0xffe0
+#define KVM_REG_GPR 0x0000
+#define KVM_REG_FPR 0x0020
+#define KVM_REG_QPR 0x0040
+#define KVM_REG_FQPR 0x0060
+
+#define KVM_INTERRUPT_SET -1U
+#define KVM_INTERRUPT_UNSET -2U
+#define KVM_INTERRUPT_SET_LEVEL -3U
+
+#endif /* __LINUX_KVM_POWERPC_H */
diff --git a/linux-headers/asm-powerpc/kvm_para.h b/linux-headers/asm-powerpc/kvm_para.h
new file mode 100644
index 0000000000..ad58c90bf5
--- /dev/null
+++ b/linux-headers/asm-powerpc/kvm_para.h
@@ -0,0 +1,53 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Copyright IBM Corp. 2008
+ *
+ * Authors: Hollis Blanchard <hollisb@us.ibm.com>
+ */
+
+#ifndef __POWERPC_KVM_PARA_H__
+#define __POWERPC_KVM_PARA_H__
+
+#include <linux/types.h>
+
+struct kvm_vcpu_arch_shared {
+ __u64 scratch1;
+ __u64 scratch2;
+ __u64 scratch3;
+ __u64 critical; /* Guest may not get interrupts if == r1 */
+ __u64 sprg0;
+ __u64 sprg1;
+ __u64 sprg2;
+ __u64 sprg3;
+ __u64 srr0;
+ __u64 srr1;
+ __u64 dar;
+ __u64 msr;
+ __u32 dsisr;
+ __u32 int_pending; /* Tells the guest if we have an interrupt */
+ __u32 sr[16];
+};
+
+#define KVM_SC_MAGIC_R0 0x4b564d21 /* "KVM!" */
+#define HC_VENDOR_KVM (42 << 16)
+#define HC_EV_SUCCESS 0
+#define HC_EV_UNIMPLEMENTED 12
+
+#define KVM_FEATURE_MAGIC_PAGE 1
+
+#define KVM_MAGIC_FEAT_SR (1 << 0)
+
+
+#endif /* __POWERPC_KVM_PARA_H__ */
diff --git a/linux-headers/asm-s390/kvm.h b/linux-headers/asm-s390/kvm.h
new file mode 100644
index 0000000000..82b32a100c
--- /dev/null
+++ b/linux-headers/asm-s390/kvm.h
@@ -0,0 +1,44 @@
+#ifndef __LINUX_KVM_S390_H
+#define __LINUX_KVM_S390_H
+/*
+ * asm-s390/kvm.h - KVM s390 specific structures and definitions
+ *
+ * Copyright IBM Corp. 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License (version 2 only)
+ * as published by the Free Software Foundation.
+ *
+ * Author(s): Carsten Otte <cotte@de.ibm.com>
+ * Christian Borntraeger <borntraeger@de.ibm.com>
+ */
+#include <linux/types.h>
+
+#define __KVM_S390
+
+/* for KVM_GET_REGS and KVM_SET_REGS */
+struct kvm_regs {
+ /* general purpose regs for s390 */
+ __u64 gprs[16];
+};
+
+/* for KVM_GET_SREGS and KVM_SET_SREGS */
+struct kvm_sregs {
+ __u32 acrs[16];
+ __u64 crs[16];
+};
+
+/* for KVM_GET_FPU and KVM_SET_FPU */
+struct kvm_fpu {
+ __u32 fpc;
+ __u64 fprs[16];
+};
+
+struct kvm_debug_exit_arch {
+};
+
+/* for KVM_SET_GUEST_DEBUG */
+struct kvm_guest_debug_arch {
+};
+
+#endif
diff --git a/linux-headers/asm-s390/kvm_para.h b/linux-headers/asm-s390/kvm_para.h
new file mode 100644
index 0000000000..8e2dd6706b
--- /dev/null
+++ b/linux-headers/asm-s390/kvm_para.h
@@ -0,0 +1,17 @@
+/*
+ * asm-s390/kvm_para.h - definition for paravirtual devices on s390
+ *
+ * Copyright IBM Corp. 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License (version 2 only)
+ * as published by the Free Software Foundation.
+ *
+ * Author(s): Christian Borntraeger <borntraeger@de.ibm.com>
+ */
+
+#ifndef __S390_KVM_PARA_H
+#define __S390_KVM_PARA_H
+
+
+#endif /* __S390_KVM_PARA_H */
diff --git a/linux-headers/asm-x86/hyperv.h b/linux-headers/asm-x86/hyperv.h
new file mode 100644
index 0000000000..5df477ac3a
--- /dev/null
+++ b/linux-headers/asm-x86/hyperv.h
@@ -0,0 +1,193 @@
+#ifndef _ASM_X86_HYPERV_H
+#define _ASM_X86_HYPERV_H
+
+#include <linux/types.h>
+
+/*
+ * The below CPUID leaves are present if VersionAndFeatures.HypervisorPresent
+ * is set by CPUID(HvCpuIdFunctionVersionAndFeatures).
+ */
+#define HYPERV_CPUID_VENDOR_AND_MAX_FUNCTIONS 0x40000000
+#define HYPERV_CPUID_INTERFACE 0x40000001
+#define HYPERV_CPUID_VERSION 0x40000002
+#define HYPERV_CPUID_FEATURES 0x40000003
+#define HYPERV_CPUID_ENLIGHTMENT_INFO 0x40000004
+#define HYPERV_CPUID_IMPLEMENT_LIMITS 0x40000005
+
+#define HYPERV_HYPERVISOR_PRESENT_BIT 0x80000000
+#define HYPERV_CPUID_MIN 0x40000005
+#define HYPERV_CPUID_MAX 0x4000ffff
+
+/*
+ * Feature identification. EAX indicates which features are available
+ * to the partition based upon the current partition privileges.
+ */
+
+/* VP Runtime (HV_X64_MSR_VP_RUNTIME) available */
+#define HV_X64_MSR_VP_RUNTIME_AVAILABLE (1 << 0)
+/* Partition Reference Counter (HV_X64_MSR_TIME_REF_COUNT) available*/
+#define HV_X64_MSR_TIME_REF_COUNT_AVAILABLE (1 << 1)
+/*
+ * Basic SynIC MSRs (HV_X64_MSR_SCONTROL through HV_X64_MSR_EOM
+ * and HV_X64_MSR_SINT0 through HV_X64_MSR_SINT15) available
+ */
+#define HV_X64_MSR_SYNIC_AVAILABLE (1 << 2)
+/*
+ * Synthetic Timer MSRs (HV_X64_MSR_STIMER0_CONFIG through
+ * HV_X64_MSR_STIMER3_COUNT) available
+ */
+#define HV_X64_MSR_SYNTIMER_AVAILABLE (1 << 3)
+/*
+ * APIC access MSRs (HV_X64_MSR_EOI, HV_X64_MSR_ICR and HV_X64_MSR_TPR)
+ * are available
+ */
+#define HV_X64_MSR_APIC_ACCESS_AVAILABLE (1 << 4)
+/* Hypercall MSRs (HV_X64_MSR_GUEST_OS_ID and HV_X64_MSR_HYPERCALL) available*/
+#define HV_X64_MSR_HYPERCALL_AVAILABLE (1 << 5)
+/* Access virtual processor index MSR (HV_X64_MSR_VP_INDEX) available*/
+#define HV_X64_MSR_VP_INDEX_AVAILABLE (1 << 6)
+/* Virtual system reset MSR (HV_X64_MSR_RESET) is available*/
+#define HV_X64_MSR_RESET_AVAILABLE (1 << 7)
+ /*
+ * Access statistics pages MSRs (HV_X64_MSR_STATS_PARTITION_RETAIL_PAGE,
+ * HV_X64_MSR_STATS_PARTITION_INTERNAL_PAGE, HV_X64_MSR_STATS_VP_RETAIL_PAGE,
+ * HV_X64_MSR_STATS_VP_INTERNAL_PAGE) available
+ */
+#define HV_X64_MSR_STAT_PAGES_AVAILABLE (1 << 8)
+
+/*
+ * Feature identification: EBX indicates which flags were specified at
+ * partition creation. The format is the same as the partition creation
+ * flag structure defined in section Partition Creation Flags.
+ */
+#define HV_X64_CREATE_PARTITIONS (1 << 0)
+#define HV_X64_ACCESS_PARTITION_ID (1 << 1)
+#define HV_X64_ACCESS_MEMORY_POOL (1 << 2)
+#define HV_X64_ADJUST_MESSAGE_BUFFERS (1 << 3)
+#define HV_X64_POST_MESSAGES (1 << 4)
+#define HV_X64_SIGNAL_EVENTS (1 << 5)
+#define HV_X64_CREATE_PORT (1 << 6)
+#define HV_X64_CONNECT_PORT (1 << 7)
+#define HV_X64_ACCESS_STATS (1 << 8)
+#define HV_X64_DEBUGGING (1 << 11)
+#define HV_X64_CPU_POWER_MANAGEMENT (1 << 12)
+#define HV_X64_CONFIGURE_PROFILER (1 << 13)
+
+/*
+ * Feature identification. EDX indicates which miscellaneous features
+ * are available to the partition.
+ */
+/* The MWAIT instruction is available (per section MONITOR / MWAIT) */
+#define HV_X64_MWAIT_AVAILABLE (1 << 0)
+/* Guest debugging support is available */
+#define HV_X64_GUEST_DEBUGGING_AVAILABLE (1 << 1)
+/* Performance Monitor support is available*/
+#define HV_X64_PERF_MONITOR_AVAILABLE (1 << 2)
+/* Support for physical CPU dynamic partitioning events is available*/
+#define HV_X64_CPU_DYNAMIC_PARTITIONING_AVAILABLE (1 << 3)
+/*
+ * Support for passing hypercall input parameter block via XMM
+ * registers is available
+ */
+#define HV_X64_HYPERCALL_PARAMS_XMM_AVAILABLE (1 << 4)
+/* Support for a virtual guest idle state is available */
+#define HV_X64_GUEST_IDLE_STATE_AVAILABLE (1 << 5)
+
+/*
+ * Implementation recommendations. Indicates which behaviors the hypervisor
+ * recommends the OS implement for optimal performance.
+ */
+ /*
+ * Recommend using hypercall for address space switches rather
+ * than MOV to CR3 instruction
+ */
+#define HV_X64_MWAIT_RECOMMENDED (1 << 0)
+/* Recommend using hypercall for local TLB flushes rather
+ * than INVLPG or MOV to CR3 instructions */
+#define HV_X64_LOCAL_TLB_FLUSH_RECOMMENDED (1 << 1)
+/*
+ * Recommend using hypercall for remote TLB flushes rather
+ * than inter-processor interrupts
+ */
+#define HV_X64_REMOTE_TLB_FLUSH_RECOMMENDED (1 << 2)
+/*
+ * Recommend using MSRs for accessing APIC registers
+ * EOI, ICR and TPR rather than their memory-mapped counterparts
+ */
+#define HV_X64_APIC_ACCESS_RECOMMENDED (1 << 3)
+/* Recommend using the hypervisor-provided MSR to initiate a system RESET */
+#define HV_X64_SYSTEM_RESET_RECOMMENDED (1 << 4)
+/*
+ * Recommend using relaxed timing for this partition. If used,
+ * the VM should disable any watchdog timeouts that rely on the
+ * timely delivery of external interrupts
+ */
+#define HV_X64_RELAXED_TIMING_RECOMMENDED (1 << 5)
+
+/* MSR used to identify the guest OS. */
+#define HV_X64_MSR_GUEST_OS_ID 0x40000000
+
+/* MSR used to setup pages used to communicate with the hypervisor. */
+#define HV_X64_MSR_HYPERCALL 0x40000001
+
+/* MSR used to provide vcpu index */
+#define HV_X64_MSR_VP_INDEX 0x40000002
+
+/* MSR used to read the per-partition time reference counter */
+#define HV_X64_MSR_TIME_REF_COUNT 0x40000020
+
+/* Define the virtual APIC registers */
+#define HV_X64_MSR_EOI 0x40000070
+#define HV_X64_MSR_ICR 0x40000071
+#define HV_X64_MSR_TPR 0x40000072
+#define HV_X64_MSR_APIC_ASSIST_PAGE 0x40000073
+
+/* Define synthetic interrupt controller model specific registers. */
+#define HV_X64_MSR_SCONTROL 0x40000080
+#define HV_X64_MSR_SVERSION 0x40000081
+#define HV_X64_MSR_SIEFP 0x40000082
+#define HV_X64_MSR_SIMP 0x40000083
+#define HV_X64_MSR_EOM 0x40000084
+#define HV_X64_MSR_SINT0 0x40000090
+#define HV_X64_MSR_SINT1 0x40000091
+#define HV_X64_MSR_SINT2 0x40000092
+#define HV_X64_MSR_SINT3 0x40000093
+#define HV_X64_MSR_SINT4 0x40000094
+#define HV_X64_MSR_SINT5 0x40000095
+#define HV_X64_MSR_SINT6 0x40000096
+#define HV_X64_MSR_SINT7 0x40000097
+#define HV_X64_MSR_SINT8 0x40000098
+#define HV_X64_MSR_SINT9 0x40000099
+#define HV_X64_MSR_SINT10 0x4000009A
+#define HV_X64_MSR_SINT11 0x4000009B
+#define HV_X64_MSR_SINT12 0x4000009C
+#define HV_X64_MSR_SINT13 0x4000009D
+#define HV_X64_MSR_SINT14 0x4000009E
+#define HV_X64_MSR_SINT15 0x4000009F
+
+
+#define HV_X64_MSR_HYPERCALL_ENABLE 0x00000001
+#define HV_X64_MSR_HYPERCALL_PAGE_ADDRESS_SHIFT 12
+#define HV_X64_MSR_HYPERCALL_PAGE_ADDRESS_MASK \
+ (~((1ull << HV_X64_MSR_HYPERCALL_PAGE_ADDRESS_SHIFT) - 1))
+
+/* Declare the various hypercall operations. */
+#define HV_X64_HV_NOTIFY_LONG_SPIN_WAIT 0x0008
+
+#define HV_X64_MSR_APIC_ASSIST_PAGE_ENABLE 0x00000001
+#define HV_X64_MSR_APIC_ASSIST_PAGE_ADDRESS_SHIFT 12
+#define HV_X64_MSR_APIC_ASSIST_PAGE_ADDRESS_MASK \
+ (~((1ull << HV_X64_MSR_APIC_ASSIST_PAGE_ADDRESS_SHIFT) - 1))
+
+#define HV_PROCESSOR_POWER_STATE_C0 0
+#define HV_PROCESSOR_POWER_STATE_C1 1
+#define HV_PROCESSOR_POWER_STATE_C2 2
+#define HV_PROCESSOR_POWER_STATE_C3 3
+
+/* hypercall status code */
+#define HV_STATUS_SUCCESS 0
+#define HV_STATUS_INVALID_HYPERCALL_CODE 2
+#define HV_STATUS_INVALID_HYPERCALL_INPUT 3
+#define HV_STATUS_INVALID_ALIGNMENT 4
+
+#endif
diff --git a/linux-headers/asm-x86/kvm.h b/linux-headers/asm-x86/kvm.h
new file mode 100644
index 0000000000..4d8dcbdfc1
--- /dev/null
+++ b/linux-headers/asm-x86/kvm.h
@@ -0,0 +1,324 @@
+#ifndef _ASM_X86_KVM_H
+#define _ASM_X86_KVM_H
+
+/*
+ * KVM x86 specific structures and definitions
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/ioctl.h>
+
+/* Select x86 specific features in <linux/kvm.h> */
+#define __KVM_HAVE_PIT
+#define __KVM_HAVE_IOAPIC
+#define __KVM_HAVE_DEVICE_ASSIGNMENT
+#define __KVM_HAVE_MSI
+#define __KVM_HAVE_USER_NMI
+#define __KVM_HAVE_GUEST_DEBUG
+#define __KVM_HAVE_MSIX
+#define __KVM_HAVE_MCE
+#define __KVM_HAVE_PIT_STATE2
+#define __KVM_HAVE_XEN_HVM
+#define __KVM_HAVE_VCPU_EVENTS
+#define __KVM_HAVE_DEBUGREGS
+#define __KVM_HAVE_XSAVE
+#define __KVM_HAVE_XCRS
+
+/* Architectural interrupt line count. */
+#define KVM_NR_INTERRUPTS 256
+
+struct kvm_memory_alias {
+ __u32 slot; /* this has a different namespace than memory slots */
+ __u32 flags;
+ __u64 guest_phys_addr;
+ __u64 memory_size;
+ __u64 target_phys_addr;
+};
+
+/* for KVM_GET_IRQCHIP and KVM_SET_IRQCHIP */
+struct kvm_pic_state {
+ __u8 last_irr; /* edge detection */
+ __u8 irr; /* interrupt request register */
+ __u8 imr; /* interrupt mask register */
+ __u8 isr; /* interrupt service register */
+ __u8 priority_add; /* highest irq priority */
+ __u8 irq_base;
+ __u8 read_reg_select;
+ __u8 poll;
+ __u8 special_mask;
+ __u8 init_state;
+ __u8 auto_eoi;
+ __u8 rotate_on_auto_eoi;
+ __u8 special_fully_nested_mode;
+ __u8 init4; /* true if 4 byte init */
+ __u8 elcr; /* PIIX edge/trigger selection */
+ __u8 elcr_mask;
+};
+
+#define KVM_IOAPIC_NUM_PINS 24
+struct kvm_ioapic_state {
+ __u64 base_address;
+ __u32 ioregsel;
+ __u32 id;
+ __u32 irr;
+ __u32 pad;
+ union {
+ __u64 bits;
+ struct {
+ __u8 vector;
+ __u8 delivery_mode:3;
+ __u8 dest_mode:1;
+ __u8 delivery_status:1;
+ __u8 polarity:1;
+ __u8 remote_irr:1;
+ __u8 trig_mode:1;
+ __u8 mask:1;
+ __u8 reserve:7;
+ __u8 reserved[4];
+ __u8 dest_id;
+ } fields;
+ } redirtbl[KVM_IOAPIC_NUM_PINS];
+};
+
+#define KVM_IRQCHIP_PIC_MASTER 0
+#define KVM_IRQCHIP_PIC_SLAVE 1
+#define KVM_IRQCHIP_IOAPIC 2
+#define KVM_NR_IRQCHIPS 3
+
+/* for KVM_GET_REGS and KVM_SET_REGS */
+struct kvm_regs {
+ /* out (KVM_GET_REGS) / in (KVM_SET_REGS) */
+ __u64 rax, rbx, rcx, rdx;
+ __u64 rsi, rdi, rsp, rbp;
+ __u64 r8, r9, r10, r11;
+ __u64 r12, r13, r14, r15;
+ __u64 rip, rflags;
+};
+
+/* for KVM_GET_LAPIC and KVM_SET_LAPIC */
+#define KVM_APIC_REG_SIZE 0x400
+struct kvm_lapic_state {
+ char regs[KVM_APIC_REG_SIZE];
+};
+
+struct kvm_segment {
+ __u64 base;
+ __u32 limit;
+ __u16 selector;
+ __u8 type;
+ __u8 present, dpl, db, s, l, g, avl;
+ __u8 unusable;
+ __u8 padding;
+};
+
+struct kvm_dtable {
+ __u64 base;
+ __u16 limit;
+ __u16 padding[3];
+};
+
+
+/* for KVM_GET_SREGS and KVM_SET_SREGS */
+struct kvm_sregs {
+ /* out (KVM_GET_SREGS) / in (KVM_SET_SREGS) */
+ struct kvm_segment cs, ds, es, fs, gs, ss;
+ struct kvm_segment tr, ldt;
+ struct kvm_dtable gdt, idt;
+ __u64 cr0, cr2, cr3, cr4, cr8;
+ __u64 efer;
+ __u64 apic_base;
+ __u64 interrupt_bitmap[(KVM_NR_INTERRUPTS + 63) / 64];
+};
+
+/* for KVM_GET_FPU and KVM_SET_FPU */
+struct kvm_fpu {
+ __u8 fpr[8][16];
+ __u16 fcw;
+ __u16 fsw;
+ __u8 ftwx; /* in fxsave format */
+ __u8 pad1;
+ __u16 last_opcode;
+ __u64 last_ip;
+ __u64 last_dp;
+ __u8 xmm[16][16];
+ __u32 mxcsr;
+ __u32 pad2;
+};
+
+struct kvm_msr_entry {
+ __u32 index;
+ __u32 reserved;
+ __u64 data;
+};
+
+/* for KVM_GET_MSRS and KVM_SET_MSRS */
+struct kvm_msrs {
+ __u32 nmsrs; /* number of msrs in entries */
+ __u32 pad;
+
+ struct kvm_msr_entry entries[0];
+};
+
+/* for KVM_GET_MSR_INDEX_LIST */
+struct kvm_msr_list {
+ __u32 nmsrs; /* number of msrs in entries */
+ __u32 indices[0];
+};
+
+
+struct kvm_cpuid_entry {
+ __u32 function;
+ __u32 eax;
+ __u32 ebx;
+ __u32 ecx;
+ __u32 edx;
+ __u32 padding;
+};
+
+/* for KVM_SET_CPUID */
+struct kvm_cpuid {
+ __u32 nent;
+ __u32 padding;
+ struct kvm_cpuid_entry entries[0];
+};
+
+struct kvm_cpuid_entry2 {
+ __u32 function;
+ __u32 index;
+ __u32 flags;
+ __u32 eax;
+ __u32 ebx;
+ __u32 ecx;
+ __u32 edx;
+ __u32 padding[3];
+};
+
+#define KVM_CPUID_FLAG_SIGNIFCANT_INDEX 1
+#define KVM_CPUID_FLAG_STATEFUL_FUNC 2
+#define KVM_CPUID_FLAG_STATE_READ_NEXT 4
+
+/* for KVM_SET_CPUID2 */
+struct kvm_cpuid2 {
+ __u32 nent;
+ __u32 padding;
+ struct kvm_cpuid_entry2 entries[0];
+};
+
+/* for KVM_GET_PIT and KVM_SET_PIT */
+struct kvm_pit_channel_state {
+ __u32 count; /* can be 65536 */
+ __u16 latched_count;
+ __u8 count_latched;
+ __u8 status_latched;
+ __u8 status;
+ __u8 read_state;
+ __u8 write_state;
+ __u8 write_latch;
+ __u8 rw_mode;
+ __u8 mode;
+ __u8 bcd;
+ __u8 gate;
+ __s64 count_load_time;
+};
+
+struct kvm_debug_exit_arch {
+ __u32 exception;
+ __u32 pad;
+ __u64 pc;
+ __u64 dr6;
+ __u64 dr7;
+};
+
+#define KVM_GUESTDBG_USE_SW_BP 0x00010000
+#define KVM_GUESTDBG_USE_HW_BP 0x00020000
+#define KVM_GUESTDBG_INJECT_DB 0x00040000
+#define KVM_GUESTDBG_INJECT_BP 0x00080000
+
+/* for KVM_SET_GUEST_DEBUG */
+struct kvm_guest_debug_arch {
+ __u64 debugreg[8];
+};
+
+struct kvm_pit_state {
+ struct kvm_pit_channel_state channels[3];
+};
+
+#define KVM_PIT_FLAGS_HPET_LEGACY 0x00000001
+
+struct kvm_pit_state2 {
+ struct kvm_pit_channel_state channels[3];
+ __u32 flags;
+ __u32 reserved[9];
+};
+
+struct kvm_reinject_control {
+ __u8 pit_reinject;
+ __u8 reserved[31];
+};
+
+/* When set in flags, include corresponding fields on KVM_SET_VCPU_EVENTS */
+#define KVM_VCPUEVENT_VALID_NMI_PENDING 0x00000001
+#define KVM_VCPUEVENT_VALID_SIPI_VECTOR 0x00000002
+#define KVM_VCPUEVENT_VALID_SHADOW 0x00000004
+
+/* Interrupt shadow states */
+#define KVM_X86_SHADOW_INT_MOV_SS 0x01
+#define KVM_X86_SHADOW_INT_STI 0x02
+
+/* for KVM_GET/SET_VCPU_EVENTS */
+struct kvm_vcpu_events {
+ struct {
+ __u8 injected;
+ __u8 nr;
+ __u8 has_error_code;
+ __u8 pad;
+ __u32 error_code;
+ } exception;
+ struct {
+ __u8 injected;
+ __u8 nr;
+ __u8 soft;
+ __u8 shadow;
+ } interrupt;
+ struct {
+ __u8 injected;
+ __u8 pending;
+ __u8 masked;
+ __u8 pad;
+ } nmi;
+ __u32 sipi_vector;
+ __u32 flags;
+ __u32 reserved[10];
+};
+
+/* for KVM_GET/SET_DEBUGREGS */
+struct kvm_debugregs {
+ __u64 db[4];
+ __u64 dr6;
+ __u64 dr7;
+ __u64 flags;
+ __u64 reserved[9];
+};
+
+/* for KVM_CAP_XSAVE */
+struct kvm_xsave {
+ __u32 region[1024];
+};
+
+#define KVM_MAX_XCRS 16
+
+struct kvm_xcr {
+ __u32 xcr;
+ __u32 reserved;
+ __u64 value;
+};
+
+struct kvm_xcrs {
+ __u32 nr_xcrs;
+ __u32 flags;
+ struct kvm_xcr xcrs[KVM_MAX_XCRS];
+ __u64 padding[16];
+};
+
+#endif /* _ASM_X86_KVM_H */
diff --git a/linux-headers/asm-x86/kvm_para.h b/linux-headers/asm-x86/kvm_para.h
new file mode 100644
index 0000000000..834d71ea1f
--- /dev/null
+++ b/linux-headers/asm-x86/kvm_para.h
@@ -0,0 +1,79 @@
+#ifndef _ASM_X86_KVM_PARA_H
+#define _ASM_X86_KVM_PARA_H
+
+#include <linux/types.h>
+#include <asm/hyperv.h>
+
+/* This CPUID returns the signature 'KVMKVMKVM' in ebx, ecx, and edx. It
+ * should be used to determine that a VM is running under KVM.
+ */
+#define KVM_CPUID_SIGNATURE 0x40000000
+
+/* This CPUID returns a feature bitmap in eax. Before enabling a particular
+ * paravirtualization, the appropriate feature bit should be checked.
+ */
+#define KVM_CPUID_FEATURES 0x40000001
+#define KVM_FEATURE_CLOCKSOURCE 0
+#define KVM_FEATURE_NOP_IO_DELAY 1
+#define KVM_FEATURE_MMU_OP 2
+/* This indicates that the new set of kvmclock msrs
+ * are available. The use of 0x11 and 0x12 is deprecated
+ */
+#define KVM_FEATURE_CLOCKSOURCE2 3
+#define KVM_FEATURE_ASYNC_PF 4
+
+/* The last 8 bits are used to indicate how to interpret the flags field
+ * in pvclock structure. If no bits are set, all flags are ignored.
+ */
+#define KVM_FEATURE_CLOCKSOURCE_STABLE_BIT 24
+
+#define MSR_KVM_WALL_CLOCK 0x11
+#define MSR_KVM_SYSTEM_TIME 0x12
+
+/* Custom MSRs falls in the range 0x4b564d00-0x4b564dff */
+#define MSR_KVM_WALL_CLOCK_NEW 0x4b564d00
+#define MSR_KVM_SYSTEM_TIME_NEW 0x4b564d01
+#define MSR_KVM_ASYNC_PF_EN 0x4b564d02
+
+#define KVM_MAX_MMU_OP_BATCH 32
+
+#define KVM_ASYNC_PF_ENABLED (1 << 0)
+#define KVM_ASYNC_PF_SEND_ALWAYS (1 << 1)
+
+/* Operations for KVM_HC_MMU_OP */
+#define KVM_MMU_OP_WRITE_PTE 1
+#define KVM_MMU_OP_FLUSH_TLB 2
+#define KVM_MMU_OP_RELEASE_PT 3
+
+/* Payload for KVM_HC_MMU_OP */
+struct kvm_mmu_op_header {
+ __u32 op;
+ __u32 pad;
+};
+
+struct kvm_mmu_op_write_pte {
+ struct kvm_mmu_op_header header;
+ __u64 pte_phys;
+ __u64 pte_val;
+};
+
+struct kvm_mmu_op_flush_tlb {
+ struct kvm_mmu_op_header header;
+};
+
+struct kvm_mmu_op_release_pt {
+ struct kvm_mmu_op_header header;
+ __u64 pt_phys;
+};
+
+#define KVM_PV_REASON_PAGE_NOT_PRESENT 1
+#define KVM_PV_REASON_PAGE_READY 2
+
+struct kvm_vcpu_pv_apf_data {
+ __u32 reason;
+ __u8 pad[60];
+ __u32 enabled;
+};
+
+
+#endif /* _ASM_X86_KVM_PARA_H */
diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h
new file mode 100644
index 0000000000..fc63b73996
--- /dev/null
+++ b/linux-headers/linux/kvm.h
@@ -0,0 +1,804 @@
+#ifndef __LINUX_KVM_H
+#define __LINUX_KVM_H
+
+/*
+ * Userspace interface for /dev/kvm - kernel based virtual machine
+ *
+ * Note: you must update KVM_API_VERSION if you change this interface.
+ */
+
+#include <linux/types.h>
+
+#include <linux/ioctl.h>
+#include <asm/kvm.h>
+
+#define KVM_API_VERSION 12
+
+/* *** Deprecated interfaces *** */
+
+#define KVM_TRC_SHIFT 16
+
+#define KVM_TRC_ENTRYEXIT (1 << KVM_TRC_SHIFT)
+#define KVM_TRC_HANDLER (1 << (KVM_TRC_SHIFT + 1))
+
+#define KVM_TRC_VMENTRY (KVM_TRC_ENTRYEXIT + 0x01)
+#define KVM_TRC_VMEXIT (KVM_TRC_ENTRYEXIT + 0x02)
+#define KVM_TRC_PAGE_FAULT (KVM_TRC_HANDLER + 0x01)
+
+#define KVM_TRC_HEAD_SIZE 12
+#define KVM_TRC_CYCLE_SIZE 8
+#define KVM_TRC_EXTRA_MAX 7
+
+#define KVM_TRC_INJ_VIRQ (KVM_TRC_HANDLER + 0x02)
+#define KVM_TRC_REDELIVER_EVT (KVM_TRC_HANDLER + 0x03)
+#define KVM_TRC_PEND_INTR (KVM_TRC_HANDLER + 0x04)
+#define KVM_TRC_IO_READ (KVM_TRC_HANDLER + 0x05)
+#define KVM_TRC_IO_WRITE (KVM_TRC_HANDLER + 0x06)
+#define KVM_TRC_CR_READ (KVM_TRC_HANDLER + 0x07)
+#define KVM_TRC_CR_WRITE (KVM_TRC_HANDLER + 0x08)
+#define KVM_TRC_DR_READ (KVM_TRC_HANDLER + 0x09)
+#define KVM_TRC_DR_WRITE (KVM_TRC_HANDLER + 0x0A)
+#define KVM_TRC_MSR_READ (KVM_TRC_HANDLER + 0x0B)
+#define KVM_TRC_MSR_WRITE (KVM_TRC_HANDLER + 0x0C)
+#define KVM_TRC_CPUID (KVM_TRC_HANDLER + 0x0D)
+#define KVM_TRC_INTR (KVM_TRC_HANDLER + 0x0E)
+#define KVM_TRC_NMI (KVM_TRC_HANDLER + 0x0F)
+#define KVM_TRC_VMMCALL (KVM_TRC_HANDLER + 0x10)
+#define KVM_TRC_HLT (KVM_TRC_HANDLER + 0x11)
+#define KVM_TRC_CLTS (KVM_TRC_HANDLER + 0x12)
+#define KVM_TRC_LMSW (KVM_TRC_HANDLER + 0x13)
+#define KVM_TRC_APIC_ACCESS (KVM_TRC_HANDLER + 0x14)
+#define KVM_TRC_TDP_FAULT (KVM_TRC_HANDLER + 0x15)
+#define KVM_TRC_GTLB_WRITE (KVM_TRC_HANDLER + 0x16)
+#define KVM_TRC_STLB_WRITE (KVM_TRC_HANDLER + 0x17)
+#define KVM_TRC_STLB_INVAL (KVM_TRC_HANDLER + 0x18)
+#define KVM_TRC_PPC_INSTR (KVM_TRC_HANDLER + 0x19)
+
+struct kvm_user_trace_setup {
+ __u32 buf_size;
+ __u32 buf_nr;
+};
+
+#define __KVM_DEPRECATED_MAIN_W_0x06 \
+ _IOW(KVMIO, 0x06, struct kvm_user_trace_setup)
+#define __KVM_DEPRECATED_MAIN_0x07 _IO(KVMIO, 0x07)
+#define __KVM_DEPRECATED_MAIN_0x08 _IO(KVMIO, 0x08)
+
+#define __KVM_DEPRECATED_VM_R_0x70 _IOR(KVMIO, 0x70, struct kvm_assigned_irq)
+
+struct kvm_breakpoint {
+ __u32 enabled;
+ __u32 padding;
+ __u64 address;
+};
+
+struct kvm_debug_guest {
+ __u32 enabled;
+ __u32 pad;
+ struct kvm_breakpoint breakpoints[4];
+ __u32 singlestep;
+};
+
+#define __KVM_DEPRECATED_VCPU_W_0x87 _IOW(KVMIO, 0x87, struct kvm_debug_guest)
+
+/* *** End of deprecated interfaces *** */
+
+
+/* for KVM_CREATE_MEMORY_REGION */
+struct kvm_memory_region {
+ __u32 slot;
+ __u32 flags;
+ __u64 guest_phys_addr;
+ __u64 memory_size; /* bytes */
+};
+
+/* for KVM_SET_USER_MEMORY_REGION */
+struct kvm_userspace_memory_region {
+ __u32 slot;
+ __u32 flags;
+ __u64 guest_phys_addr;
+ __u64 memory_size; /* bytes */
+ __u64 userspace_addr; /* start of the userspace allocated memory */
+};
+
+/* for kvm_memory_region::flags */
+#define KVM_MEM_LOG_DIRTY_PAGES 1UL
+#define KVM_MEMSLOT_INVALID (1UL << 1)
+
+/* for KVM_IRQ_LINE */
+struct kvm_irq_level {
+ /*
+ * ACPI gsi notion of irq.
+ * For IA-64 (APIC model) IOAPIC0: irq 0-23; IOAPIC1: irq 24-47..
+ * For X86 (standard AT mode) PIC0/1: irq 0-15. IOAPIC0: 0-23..
+ */
+ union {
+ __u32 irq;
+ __s32 status;
+ };
+ __u32 level;
+};
+
+
+struct kvm_irqchip {
+ __u32 chip_id;
+ __u32 pad;
+ union {
+ char dummy[512]; /* reserving space */
+#ifdef __KVM_HAVE_PIT
+ struct kvm_pic_state pic;
+#endif
+#ifdef __KVM_HAVE_IOAPIC
+ struct kvm_ioapic_state ioapic;
+#endif
+ } chip;
+};
+
+/* for KVM_CREATE_PIT2 */
+struct kvm_pit_config {
+ __u32 flags;
+ __u32 pad[15];
+};
+
+#define KVM_PIT_SPEAKER_DUMMY 1
+
+#define KVM_EXIT_UNKNOWN 0
+#define KVM_EXIT_EXCEPTION 1
+#define KVM_EXIT_IO 2
+#define KVM_EXIT_HYPERCALL 3
+#define KVM_EXIT_DEBUG 4
+#define KVM_EXIT_HLT 5
+#define KVM_EXIT_MMIO 6
+#define KVM_EXIT_IRQ_WINDOW_OPEN 7
+#define KVM_EXIT_SHUTDOWN 8
+#define KVM_EXIT_FAIL_ENTRY 9
+#define KVM_EXIT_INTR 10
+#define KVM_EXIT_SET_TPR 11
+#define KVM_EXIT_TPR_ACCESS 12
+#define KVM_EXIT_S390_SIEIC 13
+#define KVM_EXIT_S390_RESET 14
+#define KVM_EXIT_DCR 15
+#define KVM_EXIT_NMI 16
+#define KVM_EXIT_INTERNAL_ERROR 17
+#define KVM_EXIT_OSI 18
+
+/* For KVM_EXIT_INTERNAL_ERROR */
+#define KVM_INTERNAL_ERROR_EMULATION 1
+#define KVM_INTERNAL_ERROR_SIMUL_EX 2
+
+/* for KVM_RUN, returned by mmap(vcpu_fd, offset=0) */
+struct kvm_run {
+ /* in */
+ __u8 request_interrupt_window;
+ __u8 padding1[7];
+
+ /* out */
+ __u32 exit_reason;
+ __u8 ready_for_interrupt_injection;
+ __u8 if_flag;
+ __u8 padding2[2];
+
+ /* in (pre_kvm_run), out (post_kvm_run) */
+ __u64 cr8;
+ __u64 apic_base;
+
+#ifdef __KVM_S390
+ /* the processor status word for s390 */
+ __u64 psw_mask; /* psw upper half */
+ __u64 psw_addr; /* psw lower half */
+#endif
+ union {
+ /* KVM_EXIT_UNKNOWN */
+ struct {
+ __u64 hardware_exit_reason;
+ } hw;
+ /* KVM_EXIT_FAIL_ENTRY */
+ struct {
+ __u64 hardware_entry_failure_reason;
+ } fail_entry;
+ /* KVM_EXIT_EXCEPTION */
+ struct {
+ __u32 exception;
+ __u32 error_code;
+ } ex;
+ /* KVM_EXIT_IO */
+ struct {
+#define KVM_EXIT_IO_IN 0
+#define KVM_EXIT_IO_OUT 1
+ __u8 direction;
+ __u8 size; /* bytes */
+ __u16 port;
+ __u32 count;
+ __u64 data_offset; /* relative to kvm_run start */
+ } io;
+ struct {
+ struct kvm_debug_exit_arch arch;
+ } debug;
+ /* KVM_EXIT_MMIO */
+ struct {
+ __u64 phys_addr;
+ __u8 data[8];
+ __u32 len;
+ __u8 is_write;
+ } mmio;
+ /* KVM_EXIT_HYPERCALL */
+ struct {
+ __u64 nr;
+ __u64 args[6];
+ __u64 ret;
+ __u32 longmode;
+ __u32 pad;
+ } hypercall;
+ /* KVM_EXIT_TPR_ACCESS */
+ struct {
+ __u64 rip;
+ __u32 is_write;
+ __u32 pad;
+ } tpr_access;
+ /* KVM_EXIT_S390_SIEIC */
+ struct {
+ __u8 icptcode;
+ __u16 ipa;
+ __u32 ipb;
+ } s390_sieic;
+ /* KVM_EXIT_S390_RESET */
+#define KVM_S390_RESET_POR 1
+#define KVM_S390_RESET_CLEAR 2
+#define KVM_S390_RESET_SUBSYSTEM 4
+#define KVM_S390_RESET_CPU_INIT 8
+#define KVM_S390_RESET_IPL 16
+ __u64 s390_reset_flags;
+ /* KVM_EXIT_DCR */
+ struct {
+ __u32 dcrn;
+ __u32 data;
+ __u8 is_write;
+ } dcr;
+ struct {
+ __u32 suberror;
+ /* Available with KVM_CAP_INTERNAL_ERROR_DATA: */
+ __u32 ndata;
+ __u64 data[16];
+ } internal;
+ /* KVM_EXIT_OSI */
+ struct {
+ __u64 gprs[32];
+ } osi;
+ /* Fix the size of the union. */
+ char padding[256];
+ };
+};
+
+/* for KVM_REGISTER_COALESCED_MMIO / KVM_UNREGISTER_COALESCED_MMIO */
+
+struct kvm_coalesced_mmio_zone {
+ __u64 addr;
+ __u32 size;
+ __u32 pad;
+};
+
+struct kvm_coalesced_mmio {
+ __u64 phys_addr;
+ __u32 len;
+ __u32 pad;
+ __u8 data[8];
+};
+
+struct kvm_coalesced_mmio_ring {
+ __u32 first, last;
+ struct kvm_coalesced_mmio coalesced_mmio[0];
+};
+
+#define KVM_COALESCED_MMIO_MAX \
+ ((PAGE_SIZE - sizeof(struct kvm_coalesced_mmio_ring)) / \
+ sizeof(struct kvm_coalesced_mmio))
+
+/* for KVM_TRANSLATE */
+struct kvm_translation {
+ /* in */
+ __u64 linear_address;
+
+ /* out */
+ __u64 physical_address;
+ __u8 valid;
+ __u8 writeable;
+ __u8 usermode;
+ __u8 pad[5];
+};
+
+/* for KVM_INTERRUPT */
+struct kvm_interrupt {
+ /* in */
+ __u32 irq;
+};
+
+/* for KVM_GET_DIRTY_LOG */
+struct kvm_dirty_log {
+ __u32 slot;
+ __u32 padding1;
+ union {
+ void *dirty_bitmap; /* one bit per page */
+ __u64 padding2;
+ };
+};
+
+/* for KVM_SET_SIGNAL_MASK */
+struct kvm_signal_mask {
+ __u32 len;
+ __u8 sigset[0];
+};
+
+/* for KVM_TPR_ACCESS_REPORTING */
+struct kvm_tpr_access_ctl {
+ __u32 enabled;
+ __u32 flags;
+ __u32 reserved[8];
+};
+
+/* for KVM_SET_VAPIC_ADDR */
+struct kvm_vapic_addr {
+ __u64 vapic_addr;
+};
+
+/* for KVM_SET_MPSTATE */
+
+#define KVM_MP_STATE_RUNNABLE 0
+#define KVM_MP_STATE_UNINITIALIZED 1
+#define KVM_MP_STATE_INIT_RECEIVED 2
+#define KVM_MP_STATE_HALTED 3
+#define KVM_MP_STATE_SIPI_RECEIVED 4
+
+struct kvm_mp_state {
+ __u32 mp_state;
+};
+
+struct kvm_s390_psw {
+ __u64 mask;
+ __u64 addr;
+};
+
+/* valid values for type in kvm_s390_interrupt */
+#define KVM_S390_SIGP_STOP 0xfffe0000u
+#define KVM_S390_PROGRAM_INT 0xfffe0001u
+#define KVM_S390_SIGP_SET_PREFIX 0xfffe0002u
+#define KVM_S390_RESTART 0xfffe0003u
+#define KVM_S390_INT_VIRTIO 0xffff2603u
+#define KVM_S390_INT_SERVICE 0xffff2401u
+#define KVM_S390_INT_EMERGENCY 0xffff1201u
+
+struct kvm_s390_interrupt {
+ __u32 type;
+ __u32 parm;
+ __u64 parm64;
+};
+
+/* for KVM_SET_GUEST_DEBUG */
+
+#define KVM_GUESTDBG_ENABLE 0x00000001
+#define KVM_GUESTDBG_SINGLESTEP 0x00000002
+
+struct kvm_guest_debug {
+ __u32 control;
+ __u32 pad;
+ struct kvm_guest_debug_arch arch;
+};
+
+enum {
+ kvm_ioeventfd_flag_nr_datamatch,
+ kvm_ioeventfd_flag_nr_pio,
+ kvm_ioeventfd_flag_nr_deassign,
+ kvm_ioeventfd_flag_nr_max,
+};
+
+#define KVM_IOEVENTFD_FLAG_DATAMATCH (1 << kvm_ioeventfd_flag_nr_datamatch)
+#define KVM_IOEVENTFD_FLAG_PIO (1 << kvm_ioeventfd_flag_nr_pio)
+#define KVM_IOEVENTFD_FLAG_DEASSIGN (1 << kvm_ioeventfd_flag_nr_deassign)
+
+#define KVM_IOEVENTFD_VALID_FLAG_MASK ((1 << kvm_ioeventfd_flag_nr_max) - 1)
+
+struct kvm_ioeventfd {
+ __u64 datamatch;
+ __u64 addr; /* legal pio/mmio address */
+ __u32 len; /* 1, 2, 4, or 8 bytes */
+ __s32 fd;
+ __u32 flags;
+ __u8 pad[36];
+};
+
+/* for KVM_ENABLE_CAP */
+struct kvm_enable_cap {
+ /* in */
+ __u32 cap;
+ __u32 flags;
+ __u64 args[4];
+ __u8 pad[64];
+};
+
+/* for KVM_PPC_GET_PVINFO */
+struct kvm_ppc_pvinfo {
+ /* out */
+ __u32 flags;
+ __u32 hcall[4];
+ __u8 pad[108];
+};
+
+#define KVMIO 0xAE
+
+/*
+ * ioctls for /dev/kvm fds:
+ */
+#define KVM_GET_API_VERSION _IO(KVMIO, 0x00)
+#define KVM_CREATE_VM _IO(KVMIO, 0x01) /* returns a VM fd */
+#define KVM_GET_MSR_INDEX_LIST _IOWR(KVMIO, 0x02, struct kvm_msr_list)
+
+#define KVM_S390_ENABLE_SIE _IO(KVMIO, 0x06)
+/*
+ * Check if a kvm extension is available. Argument is extension number,
+ * return is 1 (yes) or 0 (no, sorry).
+ */
+#define KVM_CHECK_EXTENSION _IO(KVMIO, 0x03)
+/*
+ * Get size for mmap(vcpu_fd)
+ */
+#define KVM_GET_VCPU_MMAP_SIZE _IO(KVMIO, 0x04) /* in bytes */
+#define KVM_GET_SUPPORTED_CPUID _IOWR(KVMIO, 0x05, struct kvm_cpuid2)
+#define KVM_TRACE_ENABLE __KVM_DEPRECATED_MAIN_W_0x06
+#define KVM_TRACE_PAUSE __KVM_DEPRECATED_MAIN_0x07
+#define KVM_TRACE_DISABLE __KVM_DEPRECATED_MAIN_0x08
+
+/*
+ * Extension capability list.
+ */
+#define KVM_CAP_IRQCHIP 0
+#define KVM_CAP_HLT 1
+#define KVM_CAP_MMU_SHADOW_CACHE_CONTROL 2
+#define KVM_CAP_USER_MEMORY 3
+#define KVM_CAP_SET_TSS_ADDR 4
+#define KVM_CAP_VAPIC 6
+#define KVM_CAP_EXT_CPUID 7
+#define KVM_CAP_CLOCKSOURCE 8
+#define KVM_CAP_NR_VCPUS 9 /* returns max vcpus per vm */
+#define KVM_CAP_NR_MEMSLOTS 10 /* returns max memory slots per vm */
+#define KVM_CAP_PIT 11
+#define KVM_CAP_NOP_IO_DELAY 12
+#define KVM_CAP_PV_MMU 13
+#define KVM_CAP_MP_STATE 14
+#define KVM_CAP_COALESCED_MMIO 15
+#define KVM_CAP_SYNC_MMU 16 /* Changes to host mmap are reflected in guest */
+#ifdef __KVM_HAVE_DEVICE_ASSIGNMENT
+#define KVM_CAP_DEVICE_ASSIGNMENT 17
+#endif
+#define KVM_CAP_IOMMU 18
+#ifdef __KVM_HAVE_MSI
+#define KVM_CAP_DEVICE_MSI 20
+#endif
+/* Bug in KVM_SET_USER_MEMORY_REGION fixed: */
+#define KVM_CAP_DESTROY_MEMORY_REGION_WORKS 21
+#ifdef __KVM_HAVE_USER_NMI
+#define KVM_CAP_USER_NMI 22
+#endif
+#ifdef __KVM_HAVE_GUEST_DEBUG
+#define KVM_CAP_SET_GUEST_DEBUG 23
+#endif
+#ifdef __KVM_HAVE_PIT
+#define KVM_CAP_REINJECT_CONTROL 24
+#endif
+#ifdef __KVM_HAVE_IOAPIC
+#define KVM_CAP_IRQ_ROUTING 25
+#endif
+#define KVM_CAP_IRQ_INJECT_STATUS 26
+#ifdef __KVM_HAVE_DEVICE_ASSIGNMENT
+#define KVM_CAP_DEVICE_DEASSIGNMENT 27
+#endif
+#ifdef __KVM_HAVE_MSIX
+#define KVM_CAP_DEVICE_MSIX 28
+#endif
+#define KVM_CAP_ASSIGN_DEV_IRQ 29
+/* Another bug in KVM_SET_USER_MEMORY_REGION fixed: */
+#define KVM_CAP_JOIN_MEMORY_REGIONS_WORKS 30
+#ifdef __KVM_HAVE_MCE
+#define KVM_CAP_MCE 31
+#endif
+#define KVM_CAP_IRQFD 32
+#ifdef __KVM_HAVE_PIT
+#define KVM_CAP_PIT2 33
+#endif
+#define KVM_CAP_SET_BOOT_CPU_ID 34
+#ifdef __KVM_HAVE_PIT_STATE2
+#define KVM_CAP_PIT_STATE2 35
+#endif
+#define KVM_CAP_IOEVENTFD 36
+#define KVM_CAP_SET_IDENTITY_MAP_ADDR 37
+#ifdef __KVM_HAVE_XEN_HVM
+#define KVM_CAP_XEN_HVM 38
+#endif
+#define KVM_CAP_ADJUST_CLOCK 39
+#define KVM_CAP_INTERNAL_ERROR_DATA 40
+#ifdef __KVM_HAVE_VCPU_EVENTS
+#define KVM_CAP_VCPU_EVENTS 41
+#endif
+#define KVM_CAP_S390_PSW 42
+#define KVM_CAP_PPC_SEGSTATE 43
+#define KVM_CAP_HYPERV 44
+#define KVM_CAP_HYPERV_VAPIC 45
+#define KVM_CAP_HYPERV_SPIN 46
+#define KVM_CAP_PCI_SEGMENT 47
+#define KVM_CAP_PPC_PAIRED_SINGLES 48
+#define KVM_CAP_INTR_SHADOW 49
+#ifdef __KVM_HAVE_DEBUGREGS
+#define KVM_CAP_DEBUGREGS 50
+#endif
+#define KVM_CAP_X86_ROBUST_SINGLESTEP 51
+#define KVM_CAP_PPC_OSI 52
+#define KVM_CAP_PPC_UNSET_IRQ 53
+#define KVM_CAP_ENABLE_CAP 54
+#ifdef __KVM_HAVE_XSAVE
+#define KVM_CAP_XSAVE 55
+#endif
+#ifdef __KVM_HAVE_XCRS
+#define KVM_CAP_XCRS 56
+#endif
+#define KVM_CAP_PPC_GET_PVINFO 57
+#define KVM_CAP_PPC_IRQ_LEVEL 58
+#define KVM_CAP_ASYNC_PF 59
+#define KVM_CAP_TSC_CONTROL 60
+#define KVM_CAP_GET_TSC_KHZ 61
+#define KVM_CAP_PPC_BOOKE_SREGS 62
+
+#ifdef KVM_CAP_IRQ_ROUTING
+
+struct kvm_irq_routing_irqchip {
+ __u32 irqchip;
+ __u32 pin;
+};
+
+struct kvm_irq_routing_msi {
+ __u32 address_lo;
+ __u32 address_hi;
+ __u32 data;
+ __u32 pad;
+};
+
+/* gsi routing entry types */
+#define KVM_IRQ_ROUTING_IRQCHIP 1
+#define KVM_IRQ_ROUTING_MSI 2
+
+struct kvm_irq_routing_entry {
+ __u32 gsi;
+ __u32 type;
+ __u32 flags;
+ __u32 pad;
+ union {
+ struct kvm_irq_routing_irqchip irqchip;
+ struct kvm_irq_routing_msi msi;
+ __u32 pad[8];
+ } u;
+};
+
+struct kvm_irq_routing {
+ __u32 nr;
+ __u32 flags;
+ struct kvm_irq_routing_entry entries[0];
+};
+
+#endif
+
+#ifdef KVM_CAP_MCE
+/* x86 MCE */
+struct kvm_x86_mce {
+ __u64 status;
+ __u64 addr;
+ __u64 misc;
+ __u64 mcg_status;
+ __u8 bank;
+ __u8 pad1[7];
+ __u64 pad2[3];
+};
+#endif
+
+#ifdef KVM_CAP_XEN_HVM
+struct kvm_xen_hvm_config {
+ __u32 flags;
+ __u32 msr;
+ __u64 blob_addr_32;
+ __u64 blob_addr_64;
+ __u8 blob_size_32;
+ __u8 blob_size_64;
+ __u8 pad2[30];
+};
+#endif
+
+#define KVM_IRQFD_FLAG_DEASSIGN (1 << 0)
+
+struct kvm_irqfd {
+ __u32 fd;
+ __u32 gsi;
+ __u32 flags;
+ __u8 pad[20];
+};
+
+struct kvm_clock_data {
+ __u64 clock;
+ __u32 flags;
+ __u32 pad[9];
+};
+
+/*
+ * ioctls for VM fds
+ */
+#define KVM_SET_MEMORY_REGION _IOW(KVMIO, 0x40, struct kvm_memory_region)
+/*
+ * KVM_CREATE_VCPU receives as a parameter the vcpu slot, and returns
+ * a vcpu fd.
+ */
+#define KVM_CREATE_VCPU _IO(KVMIO, 0x41)
+#define KVM_GET_DIRTY_LOG _IOW(KVMIO, 0x42, struct kvm_dirty_log)
+/* KVM_SET_MEMORY_ALIAS is obsolete: */
+#define KVM_SET_MEMORY_ALIAS _IOW(KVMIO, 0x43, struct kvm_memory_alias)
+#define KVM_SET_NR_MMU_PAGES _IO(KVMIO, 0x44)
+#define KVM_GET_NR_MMU_PAGES _IO(KVMIO, 0x45)
+#define KVM_SET_USER_MEMORY_REGION _IOW(KVMIO, 0x46, \
+ struct kvm_userspace_memory_region)
+#define KVM_SET_TSS_ADDR _IO(KVMIO, 0x47)
+#define KVM_SET_IDENTITY_MAP_ADDR _IOW(KVMIO, 0x48, __u64)
+/* Device model IOC */
+#define KVM_CREATE_IRQCHIP _IO(KVMIO, 0x60)
+#define KVM_IRQ_LINE _IOW(KVMIO, 0x61, struct kvm_irq_level)
+#define KVM_GET_IRQCHIP _IOWR(KVMIO, 0x62, struct kvm_irqchip)
+#define KVM_SET_IRQCHIP _IOR(KVMIO, 0x63, struct kvm_irqchip)
+#define KVM_CREATE_PIT _IO(KVMIO, 0x64)
+#define KVM_GET_PIT _IOWR(KVMIO, 0x65, struct kvm_pit_state)
+#define KVM_SET_PIT _IOR(KVMIO, 0x66, struct kvm_pit_state)
+#define KVM_IRQ_LINE_STATUS _IOWR(KVMIO, 0x67, struct kvm_irq_level)
+#define KVM_REGISTER_COALESCED_MMIO \
+ _IOW(KVMIO, 0x67, struct kvm_coalesced_mmio_zone)
+#define KVM_UNREGISTER_COALESCED_MMIO \
+ _IOW(KVMIO, 0x68, struct kvm_coalesced_mmio_zone)
+#define KVM_ASSIGN_PCI_DEVICE _IOR(KVMIO, 0x69, \
+ struct kvm_assigned_pci_dev)
+#define KVM_SET_GSI_ROUTING _IOW(KVMIO, 0x6a, struct kvm_irq_routing)
+/* deprecated, replaced by KVM_ASSIGN_DEV_IRQ */
+#define KVM_ASSIGN_IRQ __KVM_DEPRECATED_VM_R_0x70
+#define KVM_ASSIGN_DEV_IRQ _IOW(KVMIO, 0x70, struct kvm_assigned_irq)
+#define KVM_REINJECT_CONTROL _IO(KVMIO, 0x71)
+#define KVM_DEASSIGN_PCI_DEVICE _IOW(KVMIO, 0x72, \
+ struct kvm_assigned_pci_dev)
+#define KVM_ASSIGN_SET_MSIX_NR _IOW(KVMIO, 0x73, \
+ struct kvm_assigned_msix_nr)
+#define KVM_ASSIGN_SET_MSIX_ENTRY _IOW(KVMIO, 0x74, \
+ struct kvm_assigned_msix_entry)
+#define KVM_DEASSIGN_DEV_IRQ _IOW(KVMIO, 0x75, struct kvm_assigned_irq)
+#define KVM_IRQFD _IOW(KVMIO, 0x76, struct kvm_irqfd)
+#define KVM_CREATE_PIT2 _IOW(KVMIO, 0x77, struct kvm_pit_config)
+#define KVM_SET_BOOT_CPU_ID _IO(KVMIO, 0x78)
+#define KVM_IOEVENTFD _IOW(KVMIO, 0x79, struct kvm_ioeventfd)
+#define KVM_XEN_HVM_CONFIG _IOW(KVMIO, 0x7a, struct kvm_xen_hvm_config)
+#define KVM_SET_CLOCK _IOW(KVMIO, 0x7b, struct kvm_clock_data)
+#define KVM_GET_CLOCK _IOR(KVMIO, 0x7c, struct kvm_clock_data)
+/* Available with KVM_CAP_PIT_STATE2 */
+#define KVM_GET_PIT2 _IOR(KVMIO, 0x9f, struct kvm_pit_state2)
+#define KVM_SET_PIT2 _IOW(KVMIO, 0xa0, struct kvm_pit_state2)
+/* Available with KVM_CAP_PPC_GET_PVINFO */
+#define KVM_PPC_GET_PVINFO _IOW(KVMIO, 0xa1, struct kvm_ppc_pvinfo)
+/* Available with KVM_CAP_TSC_CONTROL */
+#define KVM_SET_TSC_KHZ _IO(KVMIO, 0xa2)
+#define KVM_GET_TSC_KHZ _IO(KVMIO, 0xa3)
+
+/*
+ * ioctls for vcpu fds
+ */
+#define KVM_RUN _IO(KVMIO, 0x80)
+#define KVM_GET_REGS _IOR(KVMIO, 0x81, struct kvm_regs)
+#define KVM_SET_REGS _IOW(KVMIO, 0x82, struct kvm_regs)
+#define KVM_GET_SREGS _IOR(KVMIO, 0x83, struct kvm_sregs)
+#define KVM_SET_SREGS _IOW(KVMIO, 0x84, struct kvm_sregs)
+#define KVM_TRANSLATE _IOWR(KVMIO, 0x85, struct kvm_translation)
+#define KVM_INTERRUPT _IOW(KVMIO, 0x86, struct kvm_interrupt)
+/* KVM_DEBUG_GUEST is no longer supported, use KVM_SET_GUEST_DEBUG instead */
+#define KVM_DEBUG_GUEST __KVM_DEPRECATED_VCPU_W_0x87
+#define KVM_GET_MSRS _IOWR(KVMIO, 0x88, struct kvm_msrs)
+#define KVM_SET_MSRS _IOW(KVMIO, 0x89, struct kvm_msrs)
+#define KVM_SET_CPUID _IOW(KVMIO, 0x8a, struct kvm_cpuid)
+#define KVM_SET_SIGNAL_MASK _IOW(KVMIO, 0x8b, struct kvm_signal_mask)
+#define KVM_GET_FPU _IOR(KVMIO, 0x8c, struct kvm_fpu)
+#define KVM_SET_FPU _IOW(KVMIO, 0x8d, struct kvm_fpu)
+#define KVM_GET_LAPIC _IOR(KVMIO, 0x8e, struct kvm_lapic_state)
+#define KVM_SET_LAPIC _IOW(KVMIO, 0x8f, struct kvm_lapic_state)
+#define KVM_SET_CPUID2 _IOW(KVMIO, 0x90, struct kvm_cpuid2)
+#define KVM_GET_CPUID2 _IOWR(KVMIO, 0x91, struct kvm_cpuid2)
+/* Available with KVM_CAP_VAPIC */
+#define KVM_TPR_ACCESS_REPORTING _IOWR(KVMIO, 0x92, struct kvm_tpr_access_ctl)
+/* Available with KVM_CAP_VAPIC */
+#define KVM_SET_VAPIC_ADDR _IOW(KVMIO, 0x93, struct kvm_vapic_addr)
+/* valid for virtual machine (for floating interrupt)_and_ vcpu */
+#define KVM_S390_INTERRUPT _IOW(KVMIO, 0x94, struct kvm_s390_interrupt)
+/* store status for s390 */
+#define KVM_S390_STORE_STATUS_NOADDR (-1ul)
+#define KVM_S390_STORE_STATUS_PREFIXED (-2ul)
+#define KVM_S390_STORE_STATUS _IOW(KVMIO, 0x95, unsigned long)
+/* initial ipl psw for s390 */
+#define KVM_S390_SET_INITIAL_PSW _IOW(KVMIO, 0x96, struct kvm_s390_psw)
+/* initial reset for s390 */
+#define KVM_S390_INITIAL_RESET _IO(KVMIO, 0x97)
+#define KVM_GET_MP_STATE _IOR(KVMIO, 0x98, struct kvm_mp_state)
+#define KVM_SET_MP_STATE _IOW(KVMIO, 0x99, struct kvm_mp_state)
+/* Available with KVM_CAP_NMI */
+#define KVM_NMI _IO(KVMIO, 0x9a)
+/* Available with KVM_CAP_SET_GUEST_DEBUG */
+#define KVM_SET_GUEST_DEBUG _IOW(KVMIO, 0x9b, struct kvm_guest_debug)
+/* MCE for x86 */
+#define KVM_X86_SETUP_MCE _IOW(KVMIO, 0x9c, __u64)
+#define KVM_X86_GET_MCE_CAP_SUPPORTED _IOR(KVMIO, 0x9d, __u64)
+#define KVM_X86_SET_MCE _IOW(KVMIO, 0x9e, struct kvm_x86_mce)
+/* IA64 stack access */
+#define KVM_IA64_VCPU_GET_STACK _IOR(KVMIO, 0x9a, void *)
+#define KVM_IA64_VCPU_SET_STACK _IOW(KVMIO, 0x9b, void *)
+/* Available with KVM_CAP_VCPU_EVENTS */
+#define KVM_GET_VCPU_EVENTS _IOR(KVMIO, 0x9f, struct kvm_vcpu_events)
+#define KVM_SET_VCPU_EVENTS _IOW(KVMIO, 0xa0, struct kvm_vcpu_events)
+/* Available with KVM_CAP_DEBUGREGS */
+#define KVM_GET_DEBUGREGS _IOR(KVMIO, 0xa1, struct kvm_debugregs)
+#define KVM_SET_DEBUGREGS _IOW(KVMIO, 0xa2, struct kvm_debugregs)
+#define KVM_ENABLE_CAP _IOW(KVMIO, 0xa3, struct kvm_enable_cap)
+/* Available with KVM_CAP_XSAVE */
+#define KVM_GET_XSAVE _IOR(KVMIO, 0xa4, struct kvm_xsave)
+#define KVM_SET_XSAVE _IOW(KVMIO, 0xa5, struct kvm_xsave)
+/* Available with KVM_CAP_XCRS */
+#define KVM_GET_XCRS _IOR(KVMIO, 0xa6, struct kvm_xcrs)
+#define KVM_SET_XCRS _IOW(KVMIO, 0xa7, struct kvm_xcrs)
+
+#define KVM_DEV_ASSIGN_ENABLE_IOMMU (1 << 0)
+
+struct kvm_assigned_pci_dev {
+ __u32 assigned_dev_id;
+ __u32 busnr;
+ __u32 devfn;
+ __u32 flags;
+ __u32 segnr;
+ union {
+ __u32 reserved[11];
+ };
+};
+
+#define KVM_DEV_IRQ_HOST_INTX (1 << 0)
+#define KVM_DEV_IRQ_HOST_MSI (1 << 1)
+#define KVM_DEV_IRQ_HOST_MSIX (1 << 2)
+
+#define KVM_DEV_IRQ_GUEST_INTX (1 << 8)
+#define KVM_DEV_IRQ_GUEST_MSI (1 << 9)
+#define KVM_DEV_IRQ_GUEST_MSIX (1 << 10)
+
+#define KVM_DEV_IRQ_HOST_MASK 0x00ff
+#define KVM_DEV_IRQ_GUEST_MASK 0xff00
+
+struct kvm_assigned_irq {
+ __u32 assigned_dev_id;
+ __u32 host_irq;
+ __u32 guest_irq;
+ __u32 flags;
+ union {
+ struct {
+ __u32 addr_lo;
+ __u32 addr_hi;
+ __u32 data;
+ } guest_msi;
+ __u32 reserved[12];
+ };
+};
+
+
+struct kvm_assigned_msix_nr {
+ __u32 assigned_dev_id;
+ __u16 entry_nr;
+ __u16 padding;
+};
+
+#define KVM_MAX_MSIX_PER_DEV 256
+struct kvm_assigned_msix_entry {
+ __u32 assigned_dev_id;
+ __u32 gsi;
+ __u16 entry; /* The index of entry in the MSI-X table */
+ __u16 padding[3];
+};
+
+#endif /* __LINUX_KVM_H */
diff --git a/linux-headers/linux/kvm_para.h b/linux-headers/linux/kvm_para.h
new file mode 100644
index 0000000000..7bdcf93c1d
--- /dev/null
+++ b/linux-headers/linux/kvm_para.h
@@ -0,0 +1,28 @@
+#ifndef __LINUX_KVM_PARA_H
+#define __LINUX_KVM_PARA_H
+
+/*
+ * This header file provides a method for making a hypercall to the host
+ * Architectures should define:
+ * - kvm_hypercall0, kvm_hypercall1...
+ * - kvm_arch_para_features
+ * - kvm_para_available
+ */
+
+/* Return values for hypercalls */
+#define KVM_ENOSYS 1000
+#define KVM_EFAULT EFAULT
+#define KVM_E2BIG E2BIG
+#define KVM_EPERM EPERM
+
+#define KVM_HC_VAPIC_POLL_IRQ 1
+#define KVM_HC_MMU_OP 2
+#define KVM_HC_FEATURES 3
+#define KVM_HC_PPC_MAP_MAGIC_PAGE 4
+
+/*
+ * hypercalls use architecture specific
+ */
+#include <asm/kvm_para.h>
+
+#endif /* __LINUX_KVM_PARA_H */
diff --git a/linux-headers/linux/vhost.h b/linux-headers/linux/vhost.h
new file mode 100644
index 0000000000..165a4848c6
--- /dev/null
+++ b/linux-headers/linux/vhost.h
@@ -0,0 +1,130 @@
+#ifndef _LINUX_VHOST_H
+#define _LINUX_VHOST_H
+/* Userspace interface for in-kernel virtio accelerators. */
+
+/* vhost is used to reduce the number of system calls involved in virtio.
+ *
+ * Existing virtio net code is used in the guest without modification.
+ *
+ * This header includes interface used by userspace hypervisor for
+ * device configuration.
+ */
+
+#include <linux/types.h>
+
+#include <linux/ioctl.h>
+#include <linux/virtio_config.h>
+#include <linux/virtio_ring.h>
+
+struct vhost_vring_state {
+ unsigned int index;
+ unsigned int num;
+};
+
+struct vhost_vring_file {
+ unsigned int index;
+ int fd; /* Pass -1 to unbind from file. */
+
+};
+
+struct vhost_vring_addr {
+ unsigned int index;
+ /* Option flags. */
+ unsigned int flags;
+ /* Flag values: */
+ /* Whether log address is valid. If set enables logging. */
+#define VHOST_VRING_F_LOG 0
+
+ /* Start of array of descriptors (virtually contiguous) */
+ __u64 desc_user_addr;
+ /* Used structure address. Must be 32 bit aligned */
+ __u64 used_user_addr;
+ /* Available structure address. Must be 16 bit aligned */
+ __u64 avail_user_addr;
+ /* Logging support. */
+ /* Log writes to used structure, at offset calculated from specified
+ * address. Address must be 32 bit aligned. */
+ __u64 log_guest_addr;
+};
+
+struct vhost_memory_region {
+ __u64 guest_phys_addr;
+ __u64 memory_size; /* bytes */
+ __u64 userspace_addr;
+ __u64 flags_padding; /* No flags are currently specified. */
+};
+
+/* All region addresses and sizes must be 4K aligned. */
+#define VHOST_PAGE_SIZE 0x1000
+
+struct vhost_memory {
+ __u32 nregions;
+ __u32 padding;
+ struct vhost_memory_region regions[0];
+};
+
+/* ioctls */
+
+#define VHOST_VIRTIO 0xAF
+
+/* Features bitmask for forward compatibility. Transport bits are used for
+ * vhost specific features. */
+#define VHOST_GET_FEATURES _IOR(VHOST_VIRTIO, 0x00, __u64)
+#define VHOST_SET_FEATURES _IOW(VHOST_VIRTIO, 0x00, __u64)
+
+/* Set current process as the (exclusive) owner of this file descriptor. This
+ * must be called before any other vhost command. Further calls to
+ * VHOST_OWNER_SET fail until VHOST_OWNER_RESET is called. */
+#define VHOST_SET_OWNER _IO(VHOST_VIRTIO, 0x01)
+/* Give up ownership, and reset the device to default values.
+ * Allows subsequent call to VHOST_OWNER_SET to succeed. */
+#define VHOST_RESET_OWNER _IO(VHOST_VIRTIO, 0x02)
+
+/* Set up/modify memory layout */
+#define VHOST_SET_MEM_TABLE _IOW(VHOST_VIRTIO, 0x03, struct vhost_memory)
+
+/* Write logging setup. */
+/* Memory writes can optionally be logged by setting bit at an offset
+ * (calculated from the physical address) from specified log base.
+ * The bit is set using an atomic 32 bit operation. */
+/* Set base address for logging. */
+#define VHOST_SET_LOG_BASE _IOW(VHOST_VIRTIO, 0x04, __u64)
+/* Specify an eventfd file descriptor to signal on log write. */
+#define VHOST_SET_LOG_FD _IOW(VHOST_VIRTIO, 0x07, int)
+
+/* Ring setup. */
+/* Set number of descriptors in ring. This parameter can not
+ * be modified while ring is running (bound to a device). */
+#define VHOST_SET_VRING_NUM _IOW(VHOST_VIRTIO, 0x10, struct vhost_vring_state)
+/* Set addresses for the ring. */
+#define VHOST_SET_VRING_ADDR _IOW(VHOST_VIRTIO, 0x11, struct vhost_vring_addr)
+/* Base value where queue looks for available descriptors */
+#define VHOST_SET_VRING_BASE _IOW(VHOST_VIRTIO, 0x12, struct vhost_vring_state)
+/* Get accessor: reads index, writes value in num */
+#define VHOST_GET_VRING_BASE _IOWR(VHOST_VIRTIO, 0x12, struct vhost_vring_state)
+
+/* The following ioctls use eventfd file descriptors to signal and poll
+ * for events. */
+
+/* Set eventfd to poll for added buffers */
+#define VHOST_SET_VRING_KICK _IOW(VHOST_VIRTIO, 0x20, struct vhost_vring_file)
+/* Set eventfd to signal when buffers have beed used */
+#define VHOST_SET_VRING_CALL _IOW(VHOST_VIRTIO, 0x21, struct vhost_vring_file)
+/* Set eventfd to signal an error */
+#define VHOST_SET_VRING_ERR _IOW(VHOST_VIRTIO, 0x22, struct vhost_vring_file)
+
+/* VHOST_NET specific defines */
+
+/* Attach virtio net ring to a raw socket, or tap device.
+ * The socket must be already bound to an ethernet device, this device will be
+ * used for transmit. Pass fd -1 to unbind from the socket and the transmit
+ * device. This can be used to stop the ring (e.g. for migration). */
+#define VHOST_NET_SET_BACKEND _IOW(VHOST_VIRTIO, 0x30, struct vhost_vring_file)
+
+/* Feature bits */
+/* Log all write descriptors. Can be changed while device is active. */
+#define VHOST_F_LOG_ALL 26
+/* vhost-net should add virtio_net_hdr for RX, and strip for TX packets. */
+#define VHOST_NET_F_VIRTIO_NET_HDR 27
+
+#endif
diff --git a/linux-headers/linux/virtio_config.h b/linux-headers/linux/virtio_config.h
new file mode 100644
index 0000000000..4f51d8f3af
--- /dev/null
+++ b/linux-headers/linux/virtio_config.h
@@ -0,0 +1,54 @@
+#ifndef _LINUX_VIRTIO_CONFIG_H
+#define _LINUX_VIRTIO_CONFIG_H
+/* This header, excluding the #ifdef __KERNEL__ part, is BSD licensed so
+ * anyone can use the definitions to implement compatible drivers/servers.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of IBM nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL IBM OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE. */
+
+/* Virtio devices use a standardized configuration space to define their
+ * features and pass configuration information, but each implementation can
+ * store and access that space differently. */
+#include <linux/types.h>
+
+/* Status byte for guest to report progress, and synchronize features. */
+/* We have seen device and processed generic fields (VIRTIO_CONFIG_F_VIRTIO) */
+#define VIRTIO_CONFIG_S_ACKNOWLEDGE 1
+/* We have found a driver for the device. */
+#define VIRTIO_CONFIG_S_DRIVER 2
+/* Driver has used its parts of the config, and is happy */
+#define VIRTIO_CONFIG_S_DRIVER_OK 4
+/* We've given up on this device. */
+#define VIRTIO_CONFIG_S_FAILED 0x80
+
+/* Some virtio feature bits (currently bits 28 through 31) are reserved for the
+ * transport being used (eg. virtio_ring), the rest are per-device feature
+ * bits. */
+#define VIRTIO_TRANSPORT_F_START 28
+#define VIRTIO_TRANSPORT_F_END 32
+
+/* Do we get callbacks when the ring is completely used, even if we've
+ * suppressed them? */
+#define VIRTIO_F_NOTIFY_ON_EMPTY 24
+
+#endif /* _LINUX_VIRTIO_CONFIG_H */
diff --git a/linux-headers/linux/virtio_ring.h b/linux-headers/linux/virtio_ring.h
new file mode 100644
index 0000000000..78289eedf2
--- /dev/null
+++ b/linux-headers/linux/virtio_ring.h
@@ -0,0 +1,163 @@
+#ifndef _LINUX_VIRTIO_RING_H
+#define _LINUX_VIRTIO_RING_H
+/* An interface for efficient virtio implementation, currently for use by KVM
+ * and lguest, but hopefully others soon. Do NOT change this since it will
+ * break existing servers and clients.
+ *
+ * This header is BSD licensed so anyone can use the definitions to implement
+ * compatible drivers/servers.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of IBM nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL IBM OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * Copyright Rusty Russell IBM Corporation 2007. */
+#include <linux/types.h>
+
+/* This marks a buffer as continuing via the next field. */
+#define VRING_DESC_F_NEXT 1
+/* This marks a buffer as write-only (otherwise read-only). */
+#define VRING_DESC_F_WRITE 2
+/* This means the buffer contains a list of buffer descriptors. */
+#define VRING_DESC_F_INDIRECT 4
+
+/* The Host uses this in used->flags to advise the Guest: don't kick me when
+ * you add a buffer. It's unreliable, so it's simply an optimization. Guest
+ * will still kick if it's out of buffers. */
+#define VRING_USED_F_NO_NOTIFY 1
+/* The Guest uses this in avail->flags to advise the Host: don't interrupt me
+ * when you consume a buffer. It's unreliable, so it's simply an
+ * optimization. */
+#define VRING_AVAIL_F_NO_INTERRUPT 1
+
+/* We support indirect buffer descriptors */
+#define VIRTIO_RING_F_INDIRECT_DESC 28
+
+/* The Guest publishes the used index for which it expects an interrupt
+ * at the end of the avail ring. Host should ignore the avail->flags field. */
+/* The Host publishes the avail index for which it expects a kick
+ * at the end of the used ring. Guest should ignore the used->flags field. */
+#define VIRTIO_RING_F_EVENT_IDX 29
+
+/* Virtio ring descriptors: 16 bytes. These can chain together via "next". */
+struct vring_desc {
+ /* Address (guest-physical). */
+ __u64 addr;
+ /* Length. */
+ __u32 len;
+ /* The flags as indicated above. */
+ __u16 flags;
+ /* We chain unused descriptors via this, too */
+ __u16 next;
+};
+
+struct vring_avail {
+ __u16 flags;
+ __u16 idx;
+ __u16 ring[];
+};
+
+/* u32 is used here for ids for padding reasons. */
+struct vring_used_elem {
+ /* Index of start of used descriptor chain. */
+ __u32 id;
+ /* Total length of the descriptor chain which was used (written to) */
+ __u32 len;
+};
+
+struct vring_used {
+ __u16 flags;
+ __u16 idx;
+ struct vring_used_elem ring[];
+};
+
+struct vring {
+ unsigned int num;
+
+ struct vring_desc *desc;
+
+ struct vring_avail *avail;
+
+ struct vring_used *used;
+};
+
+/* The standard layout for the ring is a continuous chunk of memory which looks
+ * like this. We assume num is a power of 2.
+ *
+ * struct vring
+ * {
+ * // The actual descriptors (16 bytes each)
+ * struct vring_desc desc[num];
+ *
+ * // A ring of available descriptor heads with free-running index.
+ * __u16 avail_flags;
+ * __u16 avail_idx;
+ * __u16 available[num];
+ * __u16 used_event_idx;
+ *
+ * // Padding to the next align boundary.
+ * char pad[];
+ *
+ * // A ring of used descriptor heads with free-running index.
+ * __u16 used_flags;
+ * __u16 used_idx;
+ * struct vring_used_elem used[num];
+ * __u16 avail_event_idx;
+ * };
+ */
+/* We publish the used event index at the end of the available ring, and vice
+ * versa. They are at the end for backwards compatibility. */
+#define vring_used_event(vr) ((vr)->avail->ring[(vr)->num])
+#define vring_avail_event(vr) (*(__u16 *)&(vr)->used->ring[(vr)->num])
+
+static __inline__ void vring_init(struct vring *vr, unsigned int num, void *p,
+ unsigned long align)
+{
+ vr->num = num;
+ vr->desc = p;
+ vr->avail = p + num*sizeof(struct vring_desc);
+ vr->used = (void *)(((unsigned long)&vr->avail->ring[num] + align-1)
+ & ~(align - 1));
+}
+
+static __inline__ unsigned vring_size(unsigned int num, unsigned long align)
+{
+ return ((sizeof(struct vring_desc) * num + sizeof(__u16) * (2 + num)
+ + align - 1) & ~(align - 1))
+ + sizeof(__u16) * 3 + sizeof(struct vring_used_elem) * num;
+}
+
+/* The following is used with USED_EVENT_IDX and AVAIL_EVENT_IDX */
+/* Assuming a given event_idx value from the other size, if
+ * we have just incremented index from old to new_idx,
+ * should we trigger an event? */
+static __inline__ int vring_need_event(__u16 event_idx, __u16 new_idx, __u16 old)
+{
+ /* Note: Xen has similar logic for notification hold-off
+ * in include/xen/interface/io/ring.h with req_event and req_prod
+ * corresponding to event_idx + 1 and new_idx respectively.
+ * Note also that req_event and req_prod in Xen start at 1,
+ * event indexes in virtio start at 0. */
+ return (__u16)(new_idx - event_idx - 1) < (__u16)(new_idx - old);
+}
+
+#endif /* _LINUX_VIRTIO_RING_H */
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index dcfeb7a286..b2746f2558 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -927,7 +927,7 @@ struct exec
#define TARGET_ELF_PAGESTART(_v) ((_v) & ~(unsigned long)(TARGET_ELF_EXEC_PAGESIZE-1))
#define TARGET_ELF_PAGEOFFSET(_v) ((_v) & (TARGET_ELF_EXEC_PAGESIZE-1))
-#define DLINFO_ITEMS 12
+#define DLINFO_ITEMS 13
static inline void memcpy_fromfs(void * to, const void * from, unsigned long n)
{
@@ -1202,6 +1202,9 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
{
abi_ulong sp;
int size;
+ int i;
+ abi_ulong u_rand_bytes;
+ uint8_t k_rand_bytes[16];
abi_ulong u_platform;
const char *k_platform;
const int n = sizeof(elf_addr_t);
@@ -1231,6 +1234,20 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
/* FIXME - check return value of memcpy_to_target() for failure */
memcpy_to_target(sp, k_platform, len);
}
+
+ /*
+ * Generate 16 random bytes for userspace PRNG seeding (not
+ * cryptically secure but it's not the aim of QEMU).
+ */
+ srand((unsigned int) time(NULL));
+ for (i = 0; i < 16; i++) {
+ k_rand_bytes[i] = rand();
+ }
+ sp -= 16;
+ u_rand_bytes = sp;
+ /* FIXME - check return value of memcpy_to_target() for failure */
+ memcpy_to_target(sp, k_rand_bytes, 16);
+
/*
* Force 16 byte _final_ alignment here for generality.
*/
@@ -1271,6 +1288,8 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
NEW_AUX_ENT(AT_EGID, (abi_ulong) getegid());
NEW_AUX_ENT(AT_HWCAP, (abi_ulong) ELF_HWCAP);
NEW_AUX_ENT(AT_CLKTCK, (abi_ulong) sysconf(_SC_CLK_TCK));
+ NEW_AUX_ENT(AT_RANDOM, (abi_ulong) u_rand_bytes);
+
if (k_platform)
NEW_AUX_ENT(AT_PLATFORM, u_platform);
#ifdef ARCH_DLINFO
@@ -1288,6 +1307,78 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
return sp;
}
+static void probe_guest_base(const char *image_name,
+ abi_ulong loaddr, abi_ulong hiaddr)
+{
+ /* Probe for a suitable guest base address, if the user has not set
+ * it explicitly, and set guest_base appropriately.
+ * In case of error we will print a suitable message and exit.
+ */
+#if defined(CONFIG_USE_GUEST_BASE)
+ const char *errmsg;
+ if (!have_guest_base && !reserved_va) {
+ unsigned long host_start, real_start, host_size;
+
+ /* Round addresses to page boundaries. */
+ loaddr &= qemu_host_page_mask;
+ hiaddr = HOST_PAGE_ALIGN(hiaddr);
+
+ if (loaddr < mmap_min_addr) {
+ host_start = HOST_PAGE_ALIGN(mmap_min_addr);
+ } else {
+ host_start = loaddr;
+ if (host_start != loaddr) {
+ errmsg = "Address overflow loading ELF binary";
+ goto exit_errmsg;
+ }
+ }
+ host_size = hiaddr - loaddr;
+ while (1) {
+ /* Do not use mmap_find_vma here because that is limited to the
+ guest address space. We are going to make the
+ guest address space fit whatever we're given. */
+ real_start = (unsigned long)
+ mmap((void *)host_start, host_size, PROT_NONE,
+ MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE, -1, 0);
+ if (real_start == (unsigned long)-1) {
+ goto exit_perror;
+ }
+ if (real_start == host_start) {
+ break;
+ }
+ /* That address didn't work. Unmap and try a different one.
+ The address the host picked because is typically right at
+ the top of the host address space and leaves the guest with
+ no usable address space. Resort to a linear search. We
+ already compensated for mmap_min_addr, so this should not
+ happen often. Probably means we got unlucky and host
+ address space randomization put a shared library somewhere
+ inconvenient. */
+ munmap((void *)real_start, host_size);
+ host_start += qemu_host_page_size;
+ if (host_start == loaddr) {
+ /* Theoretically possible if host doesn't have any suitably
+ aligned areas. Normally the first mmap will fail. */
+ errmsg = "Unable to find space for application";
+ goto exit_errmsg;
+ }
+ }
+ qemu_log("Relocating guest address space from 0x"
+ TARGET_ABI_FMT_lx " to 0x%lx\n",
+ loaddr, real_start);
+ guest_base = real_start - loaddr;
+ }
+ return;
+
+exit_perror:
+ errmsg = strerror(errno);
+exit_errmsg:
+ fprintf(stderr, "%s: %s\n", image_name, errmsg);
+ exit(-1);
+#endif
+}
+
+
/* Load an ELF image into the address space.
IMAGE_NAME is the filename of the image, to use in error messages.
@@ -1373,63 +1464,7 @@ static void load_elf_image(const char *image_name, int image_fd,
/* This is the main executable. Make sure that the low
address does not conflict with MMAP_MIN_ADDR or the
QEMU application itself. */
-#if defined(CONFIG_USE_GUEST_BASE)
- /*
- * In case where user has not explicitly set the guest_base, we
- * probe here that should we set it automatically.
- */
- if (!have_guest_base && !reserved_va) {
- unsigned long host_start, real_start, host_size;
-
- /* Round addresses to page boundaries. */
- loaddr &= qemu_host_page_mask;
- hiaddr = HOST_PAGE_ALIGN(hiaddr);
-
- if (loaddr < mmap_min_addr) {
- host_start = HOST_PAGE_ALIGN(mmap_min_addr);
- } else {
- host_start = loaddr;
- if (host_start != loaddr) {
- errmsg = "Address overflow loading ELF binary";
- goto exit_errmsg;
- }
- }
- host_size = hiaddr - loaddr;
- while (1) {
- /* Do not use mmap_find_vma here because that is limited to the
- guest address space. We are going to make the
- guest address space fit whatever we're given. */
- real_start = (unsigned long)
- mmap((void *)host_start, host_size, PROT_NONE,
- MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE, -1, 0);
- if (real_start == (unsigned long)-1) {
- goto exit_perror;
- }
- if (real_start == host_start) {
- break;
- }
- /* That address didn't work. Unmap and try a different one.
- The address the host picked because is typically right at
- the top of the host address space and leaves the guest with
- no usable address space. Resort to a linear search. We
- already compensated for mmap_min_addr, so this should not
- happen often. Probably means we got unlucky and host
- address space randomization put a shared library somewhere
- inconvenient. */
- munmap((void *)real_start, host_size);
- host_start += qemu_host_page_size;
- if (host_start == loaddr) {
- /* Theoretically possible if host doesn't have any suitably
- aligned areas. Normally the first mmap will fail. */
- errmsg = "Unable to find space for application";
- goto exit_errmsg;
- }
- }
- qemu_log("Relocating guest address space from 0x"
- TARGET_ABI_FMT_lx " to 0x%lx\n", loaddr, real_start);
- guest_base = real_start - loaddr;
- }
-#endif
+ probe_guest_base(image_name, loaddr, hiaddr);
}
load_bias = load_addr - loaddr;
@@ -1643,9 +1678,9 @@ static void load_symbols(struct elfhdr *hdr, int fd, abi_ulong load_bias)
{
int i, shnum, nsyms, sym_idx = 0, str_idx = 0;
struct elf_shdr *shdr;
- char *strings;
- struct syminfo *s;
- struct elf_sym *syms, *new_syms;
+ char *strings = NULL;
+ struct syminfo *s = NULL;
+ struct elf_sym *new_syms, *syms = NULL;
shnum = hdr->e_shnum;
i = shnum * sizeof(struct elf_shdr);
@@ -1670,24 +1705,19 @@ static void load_symbols(struct elfhdr *hdr, int fd, abi_ulong load_bias)
/* Now know where the strtab and symtab are. Snarf them. */
s = malloc(sizeof(*s));
if (!s) {
- return;
+ goto give_up;
}
i = shdr[str_idx].sh_size;
s->disas_strtab = strings = malloc(i);
if (!strings || pread(fd, strings, i, shdr[str_idx].sh_offset) != i) {
- free(s);
- free(strings);
- return;
+ goto give_up;
}
i = shdr[sym_idx].sh_size;
syms = malloc(i);
if (!syms || pread(fd, syms, i, shdr[sym_idx].sh_offset) != i) {
- free(s);
- free(strings);
- free(syms);
- return;
+ goto give_up;
}
nsyms = i / sizeof(struct elf_sym);
@@ -1710,16 +1740,18 @@ static void load_symbols(struct elfhdr *hdr, int fd, abi_ulong load_bias)
}
}
+ /* No "useful" symbol. */
+ if (nsyms == 0) {
+ goto give_up;
+ }
+
/* Attempt to free the storage associated with the local symbols
that we threw away. Whether or not this has any effect on the
memory allocation depends on the malloc implementation and how
many symbols we managed to discard. */
new_syms = realloc(syms, nsyms * sizeof(*syms));
if (new_syms == NULL) {
- free(s);
- free(syms);
- free(strings);
- return;
+ goto give_up;
}
syms = new_syms;
@@ -1734,6 +1766,13 @@ static void load_symbols(struct elfhdr *hdr, int fd, abi_ulong load_bias)
s->lookup_symbol = lookup_symbolxx;
s->next = syminfos;
syminfos = s;
+
+ return;
+
+give_up:
+ free(s);
+ free(strings);
+ free(syms);
}
int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
diff --git a/linux-user/flatload.c b/linux-user/flatload.c
index cd7af7cdff..1062da3852 100644
--- a/linux-user/flatload.c
+++ b/linux-user/flatload.c
@@ -379,12 +379,11 @@ static int load_flat_file(struct linux_binprm * bprm,
abi_long result;
abi_ulong realdatastart = 0;
abi_ulong text_len, data_len, bss_len, stack_len, flags;
- abi_ulong memp = 0; /* for finding the brk area */
abi_ulong extra;
abi_ulong reloc = 0, rp;
int i, rev, relocs = 0;
abi_ulong fpos;
- abi_ulong start_code, end_code;
+ abi_ulong start_code;
abi_ulong indx_len;
hdr = ((struct flat_hdr *) bprm->buf); /* exec-header */
@@ -491,7 +490,6 @@ static int load_flat_file(struct linux_binprm * bprm,
}
reloc = datapos + (ntohl(hdr->reloc_start) - text_len);
- memp = realdatastart;
} else {
@@ -506,7 +504,6 @@ static int load_flat_file(struct linux_binprm * bprm,
realdatastart = textpos + ntohl(hdr->data_start);
datapos = realdatastart + indx_len;
reloc = (textpos + ntohl(hdr->reloc_start) + indx_len);
- memp = textpos;
#ifdef CONFIG_BINFMT_ZFLAT
#error code needs checking
@@ -552,11 +549,10 @@ static int load_flat_file(struct linux_binprm * bprm,
/* The main program needs a little extra setup in the task structure */
start_code = textpos + sizeof (struct flat_hdr);
- end_code = textpos + text_len;
DBG_FLT("%s %s: TEXT=%x-%x DATA=%x-%x BSS=%x-%x\n",
id ? "Lib" : "Load", bprm->filename,
- (int) start_code, (int) end_code,
+ (int) start_code, (int) (textpos + text_len),
(int) datapos,
(int) (datapos + data_len),
(int) (datapos + data_len),
diff --git a/linux-user/linuxload.c b/linux-user/linuxload.c
index ac8c486c5f..62ebc7ed41 100644
--- a/linux-user/linuxload.c
+++ b/linux-user/linuxload.c
@@ -26,22 +26,6 @@ abi_long memcpy_to_target(abi_ulong dest, const void *src,
return 0;
}
-static int in_group_p(gid_t g)
-{
- /* return TRUE if we're in the specified group, FALSE otherwise */
- int ngroup;
- int i;
- gid_t grouplist[NGROUPS];
-
- ngroup = getgroups(NGROUPS, grouplist);
- for(i = 0; i < ngroup; i++) {
- if(grouplist[i] == g) {
- return 1;
- }
- }
- return 0;
-}
-
static int count(char ** vec)
{
int i;
@@ -57,7 +41,7 @@ static int prepare_binprm(struct linux_binprm *bprm)
{
struct stat st;
int mode;
- int retval, id_change;
+ int retval;
if(fstat(bprm->fd, &st) < 0) {
return(-errno);
@@ -73,14 +57,10 @@ static int prepare_binprm(struct linux_binprm *bprm)
bprm->e_uid = geteuid();
bprm->e_gid = getegid();
- id_change = 0;
/* Set-uid? */
if(mode & S_ISUID) {
bprm->e_uid = st.st_uid;
- if(bprm->e_uid != geteuid()) {
- id_change = 1;
- }
}
/* Set-gid? */
@@ -91,9 +71,6 @@ static int prepare_binprm(struct linux_binprm *bprm)
*/
if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) {
bprm->e_gid = st.st_gid;
- if (!in_group_p(bprm->e_gid)) {
- id_change = 1;
- }
}
retval = read(bprm->fd, bprm->buf, BPRM_BUF_SIZE);
diff --git a/linux-user/main.c b/linux-user/main.c
index 71dd253786..289054b0b7 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -29,8 +29,7 @@
#include "qemu.h"
#include "qemu-common.h"
#include "cache-utils.h"
-/* For tb_lock */
-#include "exec-all.h"
+#include "cpu.h"
#include "tcg.h"
#include "qemu-timer.h"
#include "envlist.h"
@@ -319,7 +318,8 @@ void cpu_loop(CPUX86State *env)
env->regs[R_EDX],
env->regs[R_ESI],
env->regs[R_EDI],
- env->regs[R_EBP]);
+ env->regs[R_EBP],
+ 0, 0);
break;
#ifndef TARGET_ABI32
case EXCP_SYSCALL:
@@ -331,7 +331,8 @@ void cpu_loop(CPUX86State *env)
env->regs[R_EDX],
env->regs[10],
env->regs[8],
- env->regs[9]);
+ env->regs[9],
+ 0, 0);
env->eip = env->exception_next_eip;
break;
#endif
@@ -735,7 +736,8 @@ void cpu_loop(CPUARMState *env)
env->regs[2],
env->regs[3],
env->regs[4],
- env->regs[5]);
+ env->regs[5],
+ 0, 0);
}
} else {
goto error;
@@ -831,7 +833,8 @@ void cpu_loop(CPUState *env)
env->regs[2],
env->regs[3],
env->regs[4],
- env->regs[5]);
+ env->regs[5],
+ 0, 0);
}
} else {
goto error;
@@ -1018,7 +1021,8 @@ void cpu_loop (CPUSPARCState *env)
ret = do_syscall (env, env->gregs[1],
env->regwptr[0], env->regwptr[1],
env->regwptr[2], env->regwptr[3],
- env->regwptr[4], env->regwptr[5]);
+ env->regwptr[4], env->regwptr[5],
+ 0, 0);
if ((abi_ulong)ret >= (abi_ulong)(-515)) {
#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
env->xcc |= PSR_CARRY;
@@ -1611,7 +1615,7 @@ void cpu_loop(CPUPPCState *env)
env->crf[0] &= ~0x1;
ret = do_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4],
env->gpr[5], env->gpr[6], env->gpr[7],
- env->gpr[8]);
+ env->gpr[8], 0, 0);
if (ret == (uint32_t)(-TARGET_QEMU_ESIGRETURN)) {
/* Returning from a successful sigreturn syscall.
Avoid corrupting register state. */
@@ -2072,7 +2076,7 @@ void cpu_loop(CPUMIPSState *env)
env->active_tc.gpr[5],
env->active_tc.gpr[6],
env->active_tc.gpr[7],
- arg5, arg6/*, arg7, arg8*/);
+ arg5, arg6, arg7, arg8);
}
if (ret == -TARGET_QEMU_ESIGRETURN) {
/* Returning from a successful sigreturn syscall.
@@ -2160,7 +2164,8 @@ void cpu_loop (CPUState *env)
env->gregs[6],
env->gregs[7],
env->gregs[0],
- env->gregs[1]);
+ env->gregs[1],
+ 0, 0);
env->gregs[0] = ret;
break;
case EXCP_INTERRUPT:
@@ -2229,7 +2234,8 @@ void cpu_loop (CPUState *env)
env->regs[12],
env->regs[13],
env->pregs[7],
- env->pregs[11]);
+ env->pregs[11],
+ 0, 0);
env->regs[10] = ret;
break;
case EXCP_DEBUG:
@@ -2288,7 +2294,8 @@ void cpu_loop (CPUState *env)
env->regs[7],
env->regs[8],
env->regs[9],
- env->regs[10]);
+ env->regs[10],
+ 0, 0);
env->regs[3] = ret;
env->sregs[SR_PC] = env->regs[14];
break;
@@ -2398,7 +2405,8 @@ void cpu_loop(CPUM68KState *env)
env->dregs[3],
env->dregs[4],
env->dregs[5],
- env->aregs[0]);
+ env->aregs[0],
+ 0, 0);
}
break;
case EXCP_INTERRUPT:
@@ -2576,7 +2584,8 @@ void cpu_loop (CPUState *env)
sysret = do_syscall(env, trapnr,
env->ir[IR_A0], env->ir[IR_A1],
env->ir[IR_A2], env->ir[IR_A3],
- env->ir[IR_A4], env->ir[IR_A5]);
+ env->ir[IR_A4], env->ir[IR_A5],
+ 0, 0);
if (trapnr == TARGET_NR_sigreturn
|| trapnr == TARGET_NR_rt_sigreturn) {
break;
@@ -2707,7 +2716,8 @@ void cpu_loop(CPUS390XState *env)
env->regs[4],
env->regs[5],
env->regs[6],
- env->regs[7]);
+ env->regs[7],
+ 0, 0);
}
break;
case EXCP_ADDR:
@@ -3020,7 +3030,7 @@ int main(int argc, char **argv, char **envp)
int mask;
const CPULogItem *item;
- mask = cpu_str_to_log_mask(r);
+ mask = cpu_str_to_log_mask(log_mask);
if (!mask) {
printf("Log items (comma separated):\n");
for (item = cpu_log_items; item->mask != 0; item++) {
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
index 237386caac..627c8b3423 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -192,7 +192,8 @@ abi_long do_brk(abi_ulong new_brk);
void syscall_init(void);
abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
abi_long arg2, abi_long arg3, abi_long arg4,
- abi_long arg5, abi_long arg6);
+ abi_long arg5, abi_long arg6, abi_long arg7,
+ abi_long arg8);
void gemu_log(const char *fmt, ...) GCC_FMT_ATTR(1, 2);
extern THREAD CPUState *thread_env;
void cpu_loop(CPUState *env);
diff --git a/linux-user/signal.c b/linux-user/signal.c
index 11b25be7b8..7d168e100f 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -981,8 +981,8 @@ restore_sigcontext(CPUX86State *env, struct target_sigcontext *sc, int *peax)
env->regs[R_ECX] = tswapl(sc->ecx);
env->eip = tswapl(sc->eip);
- cpu_x86_load_seg(env, R_CS, lduw(&sc->cs) | 3);
- cpu_x86_load_seg(env, R_SS, lduw(&sc->ss) | 3);
+ cpu_x86_load_seg(env, R_CS, lduw_p(&sc->cs) | 3);
+ cpu_x86_load_seg(env, R_SS, lduw_p(&sc->ss) | 3);
tmpflags = tswapl(sc->eflags);
env->eflags = (env->eflags & ~0x40DD5) | (tmpflags & 0x40DD5);
@@ -2080,7 +2080,6 @@ long do_sigreturn(CPUState *env)
uint32_t up_psr, pc, npc;
target_sigset_t set;
sigset_t host_set;
- abi_ulong fpu_save_addr;
int err, i;
sf_addr = env->regwptr[UREG_FP];
@@ -2120,10 +2119,11 @@ long do_sigreturn(CPUState *env)
err |= __get_user(env->regwptr[i + UREG_I0], &sf->info.si_regs.u_regs[i+8]);
}
- err |= __get_user(fpu_save_addr, &sf->fpu_save);
-
- //if (fpu_save)
- // err |= restore_fpu_state(env, fpu_save);
+ /* FIXME: implement FPU save/restore:
+ * __get_user(fpu_save, &sf->fpu_save);
+ * if (fpu_save)
+ * err |= restore_fpu_state(env, fpu_save);
+ */
/* This is pretty much atomic, no amount locking would prevent
* the races which exist anyways.
@@ -2228,7 +2228,6 @@ void sparc64_set_context(CPUSPARCState *env)
target_mc_gregset_t *grp;
abi_ulong pc, npc, tstate;
abi_ulong fp, i7, w_addr;
- unsigned char fenab;
int err;
unsigned int i;
@@ -2293,7 +2292,11 @@ void sparc64_set_context(CPUSPARCState *env)
if (put_user(i7, w_addr + offsetof(struct target_reg_window, ins[7]),
abi_ulong) != 0)
goto do_sigsegv;
- err |= __get_user(fenab, &(ucp->tuc_mcontext.mc_fpregs.mcfpu_enab));
+ /* FIXME this does not match how the kernel handles the FPU in
+ * its sparc64_set_context implementation. In particular the FPU
+ * is only restored if fenab is non-zero in:
+ * __get_user(fenab, &(ucp->tuc_mcontext.mc_fpregs.mcfpu_enab));
+ */
err |= __get_user(env->fprs, &(ucp->tuc_mcontext.mc_fpregs.mcfpu_fprs));
{
uint32_t *src, *dst;
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 5cb27c7f9f..fed7a8fe0f 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -550,6 +550,15 @@ _syscall5(int, sys_ppoll, struct pollfd *, fds, nfds_t, nfds,
size_t, sigsetsize)
#endif
+#if defined(TARGET_NR_pselect6)
+#ifndef __NR_pselect6
+# define __NR_pselect6 -1
+#endif
+#define __NR_sys_pselect6 __NR_pselect6
+_syscall6(int, sys_pselect6, int, nfds, fd_set *, readfds, fd_set *, writefds,
+ fd_set *, exceptfds, struct timespec *, timeout, void *, sig);
+#endif
+
extern int personality(int);
extern int flock(int, int);
extern int setfsuid(int);
@@ -709,49 +718,81 @@ char *target_strerror(int err)
static abi_ulong target_brk;
static abi_ulong target_original_brk;
+static abi_ulong brk_page;
void target_set_brk(abi_ulong new_brk)
{
target_original_brk = target_brk = HOST_PAGE_ALIGN(new_brk);
+ brk_page = HOST_PAGE_ALIGN(target_brk);
}
+//#define DEBUGF_BRK(message, args...) do { fprintf(stderr, (message), ## args); } while (0)
+#define DEBUGF_BRK(message, args...)
+
/* do_brk() must return target values and target errnos. */
abi_long do_brk(abi_ulong new_brk)
{
- abi_ulong brk_page;
abi_long mapped_addr;
int new_alloc_size;
- if (!new_brk)
+ DEBUGF_BRK("do_brk(%#010x) -> ", new_brk);
+
+ if (!new_brk) {
+ DEBUGF_BRK("%#010x (!new_brk)\n", target_brk);
return target_brk;
- if (new_brk < target_original_brk)
+ }
+ if (new_brk < target_original_brk) {
+ DEBUGF_BRK("%#010x (new_brk < target_original_brk)\n", target_brk);
return target_brk;
+ }
- brk_page = HOST_PAGE_ALIGN(target_brk);
-
- /* If the new brk is less than this, set it and we're done... */
- if (new_brk < brk_page) {
+ /* If the new brk is less than the highest page reserved to the
+ * target heap allocation, set it and we're almost done... */
+ if (new_brk <= brk_page) {
+ /* Heap contents are initialized to zero, as for anonymous
+ * mapped pages. */
+ if (new_brk > target_brk) {
+ memset(g2h(target_brk), 0, new_brk - target_brk);
+ }
target_brk = new_brk;
+ DEBUGF_BRK("%#010x (new_brk <= brk_page)\n", target_brk);
return target_brk;
}
- /* We need to allocate more memory after the brk... */
- new_alloc_size = HOST_PAGE_ALIGN(new_brk - brk_page + 1);
+ /* We need to allocate more memory after the brk... Note that
+ * we don't use MAP_FIXED because that will map over the top of
+ * any existing mapping (like the one with the host libc or qemu
+ * itself); instead we treat "mapped but at wrong address" as
+ * a failure and unmap again.
+ */
+ new_alloc_size = HOST_PAGE_ALIGN(new_brk - brk_page);
mapped_addr = get_errno(target_mmap(brk_page, new_alloc_size,
PROT_READ|PROT_WRITE,
- MAP_ANON|MAP_FIXED|MAP_PRIVATE, 0, 0));
+ MAP_ANON|MAP_PRIVATE, 0, 0));
+
+ if (mapped_addr == brk_page) {
+ target_brk = new_brk;
+ brk_page = HOST_PAGE_ALIGN(target_brk);
+ DEBUGF_BRK("%#010x (mapped_addr == brk_page)\n", target_brk);
+ return target_brk;
+ } else if (mapped_addr != -1) {
+ /* Mapped but at wrong address, meaning there wasn't actually
+ * enough space for this brk.
+ */
+ target_munmap(mapped_addr, new_alloc_size);
+ mapped_addr = -1;
+ DEBUGF_BRK("%#010x (mapped_addr != -1)\n", target_brk);
+ }
+ else {
+ DEBUGF_BRK("%#010x (otherwise)\n", target_brk);
+ }
#if defined(TARGET_ALPHA)
/* We (partially) emulate OSF/1 on Alpha, which requires we
return a proper errno, not an unchanged brk value. */
- if (is_error(mapped_addr)) {
- return -TARGET_ENOMEM;
- }
+ return -TARGET_ENOMEM;
#endif
-
- if (!is_error(mapped_addr)) {
- target_brk = new_brk;
- }
+ /* For everything else, return the previous break. */
return target_brk;
}
@@ -787,6 +828,20 @@ static inline abi_long copy_from_user_fdset(fd_set *fds,
return 0;
}
+static inline abi_ulong copy_from_user_fdset_ptr(fd_set *fds, fd_set **fds_ptr,
+ abi_ulong target_fds_addr,
+ int n)
+{
+ if (target_fds_addr) {
+ if (copy_from_user_fdset(fds, target_fds_addr, n))
+ return -TARGET_EFAULT;
+ *fds_ptr = fds;
+ } else {
+ *fds_ptr = NULL;
+ }
+ return 0;
+}
+
static inline abi_long copy_to_user_fdset(abi_ulong target_fds_addr,
const fd_set *fds,
int n)
@@ -952,6 +1007,7 @@ static inline abi_long copy_to_user_mq_attr(abi_ulong target_mq_attr_addr,
}
#endif
+#if defined(TARGET_NR_select) || defined(TARGET_NR__newselect)
/* do_select() must return target values and target errnos. */
static abi_long do_select(int n,
abi_ulong rfd_addr, abi_ulong wfd_addr,
@@ -962,26 +1018,17 @@ static abi_long do_select(int n,
struct timeval tv, *tv_ptr;
abi_long ret;
- if (rfd_addr) {
- if (copy_from_user_fdset(&rfds, rfd_addr, n))
- return -TARGET_EFAULT;
- rfds_ptr = &rfds;
- } else {
- rfds_ptr = NULL;
+ ret = copy_from_user_fdset_ptr(&rfds, &rfds_ptr, rfd_addr, n);
+ if (ret) {
+ return ret;
}
- if (wfd_addr) {
- if (copy_from_user_fdset(&wfds, wfd_addr, n))
- return -TARGET_EFAULT;
- wfds_ptr = &wfds;
- } else {
- wfds_ptr = NULL;
+ ret = copy_from_user_fdset_ptr(&wfds, &wfds_ptr, wfd_addr, n);
+ if (ret) {
+ return ret;
}
- if (efd_addr) {
- if (copy_from_user_fdset(&efds, efd_addr, n))
- return -TARGET_EFAULT;
- efds_ptr = &efds;
- } else {
- efds_ptr = NULL;
+ ret = copy_from_user_fdset_ptr(&efds, &efds_ptr, efd_addr, n);
+ if (ret) {
+ return ret;
}
if (target_tv_addr) {
@@ -1008,6 +1055,7 @@ static abi_long do_select(int n,
return ret;
}
+#endif
static abi_long do_pipe2(int host_pipe[], int flags)
{
@@ -3751,10 +3799,10 @@ static abi_long do_get_thread_area(CPUX86State *env, abi_ulong ptr)
#ifndef TARGET_ABI32
static abi_long do_arch_prctl(CPUX86State *env, int code, abi_ulong addr)
{
- abi_long ret;
+ abi_long ret = 0;
abi_ulong val;
int idx;
-
+
switch(code) {
case TARGET_ARCH_SET_GS:
case TARGET_ARCH_SET_FS:
@@ -3773,13 +3821,13 @@ static abi_long do_arch_prctl(CPUX86State *env, int code, abi_ulong addr)
idx = R_FS;
val = env->segs[idx].base;
if (put_user(val, addr, abi_ulong))
- return -TARGET_EFAULT;
+ ret = -TARGET_EFAULT;
break;
default:
ret = -TARGET_EINVAL;
break;
}
- return 0;
+ return ret;
}
#endif
@@ -4484,7 +4532,8 @@ int get_osversion(void)
All errnos that do_syscall() returns must be -TARGET_<errcode>. */
abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
abi_long arg2, abi_long arg3, abi_long arg4,
- abi_long arg5, abi_long arg6)
+ abi_long arg5, abi_long arg6, abi_long arg7,
+ abi_long arg8)
{
abi_long ret;
struct stat st;
@@ -5569,7 +5618,102 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
#endif
#ifdef TARGET_NR_pselect6
case TARGET_NR_pselect6:
- goto unimplemented_nowarn;
+ {
+ abi_long rfd_addr, wfd_addr, efd_addr, n, ts_addr;
+ fd_set rfds, wfds, efds;
+ fd_set *rfds_ptr, *wfds_ptr, *efds_ptr;
+ struct timespec ts, *ts_ptr;
+
+ /*
+ * The 6th arg is actually two args smashed together,
+ * so we cannot use the C library.
+ */
+ sigset_t set;
+ struct {
+ sigset_t *set;
+ size_t size;
+ } sig, *sig_ptr;
+
+ abi_ulong arg_sigset, arg_sigsize, *arg7;
+ target_sigset_t *target_sigset;
+
+ n = arg1;
+ rfd_addr = arg2;
+ wfd_addr = arg3;
+ efd_addr = arg4;
+ ts_addr = arg5;
+
+ ret = copy_from_user_fdset_ptr(&rfds, &rfds_ptr, rfd_addr, n);
+ if (ret) {
+ goto fail;
+ }
+ ret = copy_from_user_fdset_ptr(&wfds, &wfds_ptr, wfd_addr, n);
+ if (ret) {
+ goto fail;
+ }
+ ret = copy_from_user_fdset_ptr(&efds, &efds_ptr, efd_addr, n);
+ if (ret) {
+ goto fail;
+ }
+
+ /*
+ * This takes a timespec, and not a timeval, so we cannot
+ * use the do_select() helper ...
+ */
+ if (ts_addr) {
+ if (target_to_host_timespec(&ts, ts_addr)) {
+ goto efault;
+ }
+ ts_ptr = &ts;
+ } else {
+ ts_ptr = NULL;
+ }
+
+ /* Extract the two packed args for the sigset */
+ if (arg6) {
+ sig_ptr = &sig;
+ sig.size = _NSIG / 8;
+
+ arg7 = lock_user(VERIFY_READ, arg6, sizeof(*arg7) * 2, 1);
+ if (!arg7) {
+ goto efault;
+ }
+ arg_sigset = tswapl(arg7[0]);
+ arg_sigsize = tswapl(arg7[1]);
+ unlock_user(arg7, arg6, 0);
+
+ if (arg_sigset) {
+ sig.set = &set;
+ target_sigset = lock_user(VERIFY_READ, arg_sigset,
+ sizeof(*target_sigset), 1);
+ if (!target_sigset) {
+ goto efault;
+ }
+ target_to_host_sigset(&set, target_sigset);
+ unlock_user(target_sigset, arg_sigset, 0);
+ } else {
+ sig.set = NULL;
+ }
+ } else {
+ sig_ptr = NULL;
+ }
+
+ ret = get_errno(sys_pselect6(n, rfds_ptr, wfds_ptr, efds_ptr,
+ ts_ptr, sig_ptr));
+
+ if (!is_error(ret)) {
+ if (rfd_addr && copy_to_user_fdset(rfd_addr, &rfds, n))
+ goto efault;
+ if (wfd_addr && copy_to_user_fdset(wfd_addr, &wfds, n))
+ goto efault;
+ if (efd_addr && copy_to_user_fdset(efd_addr, &efds, n))
+ goto efault;
+
+ if (ts_addr && host_to_target_timespec(ts_addr, &ts))
+ goto efault;
+ }
+ }
+ break;
#endif
case TARGET_NR_symlink:
{
@@ -6029,8 +6173,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
#endif
#ifdef TARGET_NR_syscall
case TARGET_NR_syscall:
- ret = do_syscall(cpu_env,arg1 & 0xffff,arg2,arg3,arg4,arg5,arg6,0);
- break;
+ ret = do_syscall(cpu_env, arg1 & 0xffff, arg2, arg3, arg4, arg5,
+ arg6, arg7, arg8, 0);
+ break;
#endif
case TARGET_NR_wait4:
{
@@ -7058,7 +7203,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
case TARGET_NR_osf_sigprocmask:
{
abi_ulong mask;
- int how = arg1;
+ int how;
sigset_t set, oldset;
switch(arg1) {
@@ -7077,7 +7222,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
}
mask = arg2;
target_to_host_old_sigset(&set, &mask);
- sigprocmask(arg1, &set, &oldset);
+ sigprocmask(how, &set, &oldset);
host_to_target_old_sigset(&mask, &oldset);
ret = mask;
}
@@ -7717,8 +7862,13 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
#if defined(TARGET_NR_sync_file_range)
case TARGET_NR_sync_file_range:
#if TARGET_ABI_BITS == 32
+#if defined(TARGET_MIPS)
+ ret = get_errno(sync_file_range(arg1, target_offset64(arg3, arg4),
+ target_offset64(arg5, arg6), arg7));
+#else
ret = get_errno(sync_file_range(arg1, target_offset64(arg2, arg3),
target_offset64(arg4, arg5), arg6));
+#endif /* !TARGET_MIPS */
#else
ret = get_errno(sync_file_range(arg1, arg2, arg3, arg4));
#endif
diff --git a/m68k-semi.c b/m68k-semi.c
index 0371089b98..7fde10e8f3 100644
--- a/m68k-semi.c
+++ b/m68k-semi.c
@@ -370,7 +370,7 @@ void do_m68k_semihosting(CPUM68KState *env, int nr)
TaskState *ts = env->opaque;
/* Allocate the heap using sbrk. */
if (!ts->heap_limit) {
- long ret;
+ abi_ulong ret;
uint32_t size;
uint32_t base;
@@ -379,8 +379,9 @@ void do_m68k_semihosting(CPUM68KState *env, int nr)
/* Try a big heap, and reduce the size if that fails. */
for (;;) {
ret = do_brk(base + size);
- if (ret != -1)
+ if (ret >= (base + size)) {
break;
+ }
size >>= 1;
}
ts->heap_limit = base + size;
diff --git a/monitor.c b/monitor.c
index 6af6a4d999..67ceb46a62 100644
--- a/monitor.c
+++ b/monitor.c
@@ -56,7 +56,7 @@
#include "json-streamer.h"
#include "json-parser.h"
#include "osdep.h"
-#include "exec-all.h"
+#include "cpu.h"
#ifdef CONFIG_SIMPLE_TRACE
#include "trace.h"
#endif
diff --git a/net.c b/net.c
index 4f777c3dac..66123ad409 100644
--- a/net.c
+++ b/net.c
@@ -710,7 +710,7 @@ int qemu_find_nic_model(NICInfo *nd, const char * const *models,
return i;
}
- error_report("qemu: Unsupported NIC model: %s", nd->model);
+ error_report("Unsupported NIC model: %s", nd->model);
return -1;
}
@@ -1304,18 +1304,15 @@ void net_check_clients(void)
{
VLANState *vlan;
VLANClientState *vc;
- int seen_nics = 0;
+ int i;
/* Don't warn about the default network setup that you get if
- * no command line -net options are specified. There are two
- * cases that we would otherwise complain about:
+ * no command line -net or -netdev options are specified. There
+ * are two cases that we would otherwise complain about:
* (1) board doesn't support a NIC but the implicit "-net nic"
- * requested one; we'd otherwise complain about more NICs being
- * specified than we support, and also that the vlan set up by
- * the implicit "-net user" didn't have any NICs connected to it
- * (2) CONFIG_SLIRP not set: we'd otherwise complain about the
- * implicit "-net nic" setting up a nic that wasn't connected to
- * anything.
+ * requested one
+ * (2) CONFIG_SLIRP not set, in which case the implicit "-net nic"
+ * sets up a nic that isn't connected to anything.
*/
if (default_net) {
return;
@@ -1327,7 +1324,6 @@ void net_check_clients(void)
QTAILQ_FOREACH(vc, &vlan->clients, next) {
switch (vc->info->type) {
case NET_CLIENT_TYPE_NIC:
- seen_nics++;
has_nic = 1;
break;
case NET_CLIENT_TYPE_SLIRP:
@@ -1347,25 +1343,25 @@ void net_check_clients(void)
vlan->id);
}
QTAILQ_FOREACH(vc, &non_vlan_clients, next) {
- if (vc->info->type == NET_CLIENT_TYPE_NIC) {
- seen_nics++;
- }
if (!vc->peer) {
fprintf(stderr, "Warning: %s %s has no peer\n",
vc->info->type == NET_CLIENT_TYPE_NIC ? "nic" : "netdev",
vc->name);
}
}
- if (seen_nics != nb_nics) {
- /* Number of NICs requested by user on command line doesn't match
- * the number the model actually registered with us.
- * This will generally only happen for models of embedded boards
- * with no PCI bus or similar. PCI based machines can instantiate
- * all requested NICs as PCI devices but usually embedded boards
- * only have a single NIC.
- */
- fprintf(stderr, "Warning: more nics requested than this machine "
- "supports; some have been ignored\n");
+
+ /* Check that all NICs requested via -net nic actually got created.
+ * NICs created via -device don't need to be checked here because
+ * they are always instantiated.
+ */
+ for (i = 0; i < MAX_NICS; i++) {
+ NICInfo *nd = &nd_table[i];
+ if (nd->used && !nd->instantiated) {
+ fprintf(stderr, "Warning: requested NIC (%s, model %s) "
+ "was not created (not supported by this machine?)\n",
+ nd->name ? nd->name : "anonymous",
+ nd->model ? nd->model : "unspecified");
+ }
}
}
diff --git a/net.h b/net.h
index 6ceca50fc3..5b883a96ba 100644
--- a/net.h
+++ b/net.h
@@ -133,7 +133,8 @@ struct NICInfo {
char *devaddr;
VLANState *vlan;
VLANClientState *netdev;
- int used;
+ int used; /* is this slot in nd_table[] being used? */
+ int instantiated; /* does this NICInfo correspond to an instantiated NIC? */
int nvectors;
};
diff --git a/net/socket.c b/net/socket.c
index 7337f4fa10..bc1bf58894 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -530,7 +530,7 @@ int net_init_socket(QemuOpts *opts,
qemu_opt_get(opts, "connect") ||
qemu_opt_get(opts, "mcast") ||
qemu_opt_get(opts, "localaddr")) {
- error_report("listen=, connect=, mcast= and localaddr= is invalid with fd=\n");
+ error_report("listen=, connect=, mcast= and localaddr= is invalid with fd=");
return -1;
}
@@ -550,7 +550,7 @@ int net_init_socket(QemuOpts *opts,
qemu_opt_get(opts, "connect") ||
qemu_opt_get(opts, "mcast") ||
qemu_opt_get(opts, "localaddr")) {
- error_report("fd=, connect=, mcast= and localaddr= is invalid with listen=\n");
+ error_report("fd=, connect=, mcast= and localaddr= is invalid with listen=");
return -1;
}
@@ -566,7 +566,7 @@ int net_init_socket(QemuOpts *opts,
qemu_opt_get(opts, "listen") ||
qemu_opt_get(opts, "mcast") ||
qemu_opt_get(opts, "localaddr")) {
- error_report("fd=, listen=, mcast= and localaddr= is invalid with connect=\n");
+ error_report("fd=, listen=, mcast= and localaddr= is invalid with connect=");
return -1;
}
diff --git a/qemu-common.h b/qemu-common.h
index 109498dd4d..abd7a75b72 100644
--- a/qemu-common.h
+++ b/qemu-common.h
@@ -112,11 +112,6 @@ static inline char *realpath(const char *path, char *resolved_path)
_fullpath(resolved_path, path, _MAX_PATH);
return resolved_path;
}
-
-#define PRId64 "I64d"
-#define PRIx64 "I64x"
-#define PRIu64 "I64u"
-#define PRIo64 "I64o"
#endif
/* FIXME: Remove NEED_CPU_H. */
diff --git a/qemu-error.c b/qemu-error.c
index 41c191d528..4b20d283a2 100644
--- a/qemu-error.c
+++ b/qemu-error.c
@@ -193,6 +193,8 @@ void error_print_loc(void)
/*
* Print an error message to current monitor if we have one, else to stderr.
+ * Format arguments like sprintf(). The result should not contain
+ * newlines.
* Prepend the current location and append a newline.
* It's wrong to call this in a QMP monitor. Use qerror_report() there.
*/
diff --git a/qemu-img.c b/qemu-img.c
index 4f162d1abe..32628b3110 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -304,11 +304,11 @@ static int img_create(int argc, char **argv)
fmt = optarg;
break;
case 'e':
- error_report("qemu-img: option -e is deprecated, please use \'-o "
+ error_report("option -e is deprecated, please use \'-o "
"encryption\' instead!");
return 1;
case '6':
- error_report("qemu-img: option -6 is deprecated, please use \'-o "
+ error_report("option -6 is deprecated, please use \'-o "
"compat6\' instead!");
return 1;
case 'o':
@@ -633,11 +633,11 @@ static int img_convert(int argc, char **argv)
compress = 1;
break;
case 'e':
- error_report("qemu-img: option -e is deprecated, please use \'-o "
+ error_report("option -e is deprecated, please use \'-o "
"encryption\' instead!");
return 1;
case '6':
- error_report("qemu-img: option -6 is deprecated, please use \'-o "
+ error_report("option -6 is deprecated, please use \'-o "
"compat6\' instead!");
return 1;
case 'o':
@@ -690,12 +690,12 @@ static int img_convert(int argc, char **argv)
if (snapshot_name != NULL) {
if (bs_n > 1) {
- error_report("No support for concatenating multiple snapshot\n");
+ error_report("No support for concatenating multiple snapshot");
ret = -1;
goto out;
}
if (bdrv_snapshot_load_tmp(bs[0], snapshot_name) < 0) {
- error_report("Failed to load snapshot\n");
+ error_report("Failed to load snapshot");
ret = -1;
goto out;
}
diff --git a/savevm.c b/savevm.c
index 939845c825..8139bc7e29 100644
--- a/savevm.c
+++ b/savevm.c
@@ -2073,6 +2073,7 @@ int load_vmstate(const char *name)
return -EINVAL;
}
+ qemu_system_reset(VMRESET_SILENT);
ret = qemu_loadvm_state(f);
qemu_fclose(f);
diff --git a/scripts/get_maintainer.pl b/scripts/get_maintainer.pl
new file mode 100755
index 0000000000..d9c48e0982
--- /dev/null
+++ b/scripts/get_maintainer.pl
@@ -0,0 +1,2149 @@
+#!/usr/bin/perl -w
+# (c) 2007, Joe Perches <joe@perches.com>
+# created from checkpatch.pl
+#
+# Print selected MAINTAINERS information for
+# the files modified in a patch or for a file
+#
+# usage: perl scripts/get_maintainer.pl [OPTIONS] <patch>
+# perl scripts/get_maintainer.pl [OPTIONS] -f <file>
+#
+# Licensed under the terms of the GNU GPL License version 2
+
+use strict;
+
+my $P = $0;
+my $V = '0.26';
+
+use Getopt::Long qw(:config no_auto_abbrev);
+
+my $lk_path = "./";
+my $email = 1;
+my $email_usename = 1;
+my $email_maintainer = 1;
+my $email_list = 1;
+my $email_subscriber_list = 0;
+my $email_git_penguin_chiefs = 0;
+my $email_git = 0;
+my $email_git_all_signature_types = 0;
+my $email_git_blame = 0;
+my $email_git_blame_signatures = 1;
+my $email_git_fallback = 1;
+my $email_git_min_signatures = 1;
+my $email_git_max_maintainers = 5;
+my $email_git_min_percent = 5;
+my $email_git_since = "1-year-ago";
+my $email_hg_since = "-365";
+my $interactive = 0;
+my $email_remove_duplicates = 1;
+my $email_use_mailmap = 1;
+my $output_multiline = 1;
+my $output_separator = ", ";
+my $output_roles = 0;
+my $output_rolestats = 1;
+my $scm = 0;
+my $web = 0;
+my $subsystem = 0;
+my $status = 0;
+my $keywords = 1;
+my $sections = 0;
+my $file_emails = 0;
+my $from_filename = 0;
+my $pattern_depth = 0;
+my $version = 0;
+my $help = 0;
+
+my $vcs_used = 0;
+
+my $exit = 0;
+
+my %commit_author_hash;
+my %commit_signer_hash;
+
+my @penguin_chief = ();
+push(@penguin_chief, "Linus Torvalds:torvalds\@linux-foundation.org");
+#Andrew wants in on most everything - 2009/01/14
+#push(@penguin_chief, "Andrew Morton:akpm\@linux-foundation.org");
+
+my @penguin_chief_names = ();
+foreach my $chief (@penguin_chief) {
+ if ($chief =~ m/^(.*):(.*)/) {
+ my $chief_name = $1;
+ my $chief_addr = $2;
+ push(@penguin_chief_names, $chief_name);
+ }
+}
+my $penguin_chiefs = "\(" . join("|", @penguin_chief_names) . "\)";
+
+# Signature types of people who are either
+# a) responsible for the code in question, or
+# b) familiar enough with it to give relevant feedback
+my @signature_tags = ();
+push(@signature_tags, "Signed-off-by:");
+push(@signature_tags, "Reviewed-by:");
+push(@signature_tags, "Acked-by:");
+
+# rfc822 email address - preloaded methods go here.
+my $rfc822_lwsp = "(?:(?:\\r\\n)?[ \\t])";
+my $rfc822_char = '[\\000-\\377]';
+
+# VCS command support: class-like functions and strings
+
+my %VCS_cmds;
+
+my %VCS_cmds_git = (
+ "execute_cmd" => \&git_execute_cmd,
+ "available" => '(which("git") ne "") && (-d ".git")',
+ "find_signers_cmd" =>
+ "git log --no-color --since=\$email_git_since " .
+ '--format="GitCommit: %H%n' .
+ 'GitAuthor: %an <%ae>%n' .
+ 'GitDate: %aD%n' .
+ 'GitSubject: %s%n' .
+ '%b%n"' .
+ " -- \$file",
+ "find_commit_signers_cmd" =>
+ "git log --no-color " .
+ '--format="GitCommit: %H%n' .
+ 'GitAuthor: %an <%ae>%n' .
+ 'GitDate: %aD%n' .
+ 'GitSubject: %s%n' .
+ '%b%n"' .
+ " -1 \$commit",
+ "find_commit_author_cmd" =>
+ "git log --no-color " .
+ '--format="GitCommit: %H%n' .
+ 'GitAuthor: %an <%ae>%n' .
+ 'GitDate: %aD%n' .
+ 'GitSubject: %s%n"' .
+ " -1 \$commit",
+ "blame_range_cmd" => "git blame -l -L \$diff_start,+\$diff_length \$file",
+ "blame_file_cmd" => "git blame -l \$file",
+ "commit_pattern" => "^GitCommit: ([0-9a-f]{40,40})",
+ "blame_commit_pattern" => "^([0-9a-f]+) ",
+ "author_pattern" => "^GitAuthor: (.*)",
+ "subject_pattern" => "^GitSubject: (.*)",
+);
+
+my %VCS_cmds_hg = (
+ "execute_cmd" => \&hg_execute_cmd,
+ "available" => '(which("hg") ne "") && (-d ".hg")',
+ "find_signers_cmd" =>
+ "hg log --date=\$email_hg_since " .
+ "--template='HgCommit: {node}\\n" .
+ "HgAuthor: {author}\\n" .
+ "HgSubject: {desc}\\n'" .
+ " -- \$file",
+ "find_commit_signers_cmd" =>
+ "hg log " .
+ "--template='HgSubject: {desc}\\n'" .
+ " -r \$commit",
+ "find_commit_author_cmd" =>
+ "hg log " .
+ "--template='HgCommit: {node}\\n" .
+ "HgAuthor: {author}\\n" .
+ "HgSubject: {desc|firstline}\\n'" .
+ " -r \$commit",
+ "blame_range_cmd" => "", # not supported
+ "blame_file_cmd" => "hg blame -n \$file",
+ "commit_pattern" => "^HgCommit: ([0-9a-f]{40,40})",
+ "blame_commit_pattern" => "^([ 0-9a-f]+):",
+ "author_pattern" => "^HgAuthor: (.*)",
+ "subject_pattern" => "^HgSubject: (.*)",
+);
+
+my $conf = which_conf(".get_maintainer.conf");
+if (-f $conf) {
+ my @conf_args;
+ open(my $conffile, '<', "$conf")
+ or warn "$P: Can't find a readable .get_maintainer.conf file $!\n";
+
+ while (<$conffile>) {
+ my $line = $_;
+
+ $line =~ s/\s*\n?$//g;
+ $line =~ s/^\s*//g;
+ $line =~ s/\s+/ /g;
+
+ next if ($line =~ m/^\s*#/);
+ next if ($line =~ m/^\s*$/);
+
+ my @words = split(" ", $line);
+ foreach my $word (@words) {
+ last if ($word =~ m/^#/);
+ push (@conf_args, $word);
+ }
+ }
+ close($conffile);
+ unshift(@ARGV, @conf_args) if @conf_args;
+}
+
+if (!GetOptions(
+ 'email!' => \$email,
+ 'git!' => \$email_git,
+ 'git-all-signature-types!' => \$email_git_all_signature_types,
+ 'git-blame!' => \$email_git_blame,
+ 'git-blame-signatures!' => \$email_git_blame_signatures,
+ 'git-fallback!' => \$email_git_fallback,
+ 'git-chief-penguins!' => \$email_git_penguin_chiefs,
+ 'git-min-signatures=i' => \$email_git_min_signatures,
+ 'git-max-maintainers=i' => \$email_git_max_maintainers,
+ 'git-min-percent=i' => \$email_git_min_percent,
+ 'git-since=s' => \$email_git_since,
+ 'hg-since=s' => \$email_hg_since,
+ 'i|interactive!' => \$interactive,
+ 'remove-duplicates!' => \$email_remove_duplicates,
+ 'mailmap!' => \$email_use_mailmap,
+ 'm!' => \$email_maintainer,
+ 'n!' => \$email_usename,
+ 'l!' => \$email_list,
+ 's!' => \$email_subscriber_list,
+ 'multiline!' => \$output_multiline,
+ 'roles!' => \$output_roles,
+ 'rolestats!' => \$output_rolestats,
+ 'separator=s' => \$output_separator,
+ 'subsystem!' => \$subsystem,
+ 'status!' => \$status,
+ 'scm!' => \$scm,
+ 'web!' => \$web,
+ 'pattern-depth=i' => \$pattern_depth,
+ 'k|keywords!' => \$keywords,
+ 'sections!' => \$sections,
+ 'fe|file-emails!' => \$file_emails,
+ 'f|file' => \$from_filename,
+ 'v|version' => \$version,
+ 'h|help|usage' => \$help,
+ )) {
+ die "$P: invalid argument - use --help if necessary\n";
+}
+
+if ($help != 0) {
+ usage();
+ exit 0;
+}
+
+if ($version != 0) {
+ print("${P} ${V}\n");
+ exit 0;
+}
+
+if (-t STDIN && !@ARGV) {
+ # We're talking to a terminal, but have no command line arguments.
+ die "$P: missing patchfile or -f file - use --help if necessary\n";
+}
+
+$output_multiline = 0 if ($output_separator ne ", ");
+$output_rolestats = 1 if ($interactive);
+$output_roles = 1 if ($output_rolestats);
+
+if ($sections) {
+ $email = 0;
+ $email_list = 0;
+ $scm = 0;
+ $status = 0;
+ $subsystem = 0;
+ $web = 0;
+ $keywords = 0;
+ $interactive = 0;
+} else {
+ my $selections = $email + $scm + $status + $subsystem + $web;
+ if ($selections == 0) {
+ die "$P: Missing required option: email, scm, status, subsystem or web\n";
+ }
+}
+
+if ($email &&
+ ($email_maintainer + $email_list + $email_subscriber_list +
+ $email_git + $email_git_penguin_chiefs + $email_git_blame) == 0) {
+ die "$P: Please select at least 1 email option\n";
+}
+
+if (!top_of_tree($lk_path)) {
+ die "$P: The current directory does not appear to be "
+ . "a QEMU source tree.\n";
+}
+
+## Read MAINTAINERS for type/value pairs
+
+my @typevalue = ();
+my %keyword_hash;
+
+open (my $maint, '<', "${lk_path}MAINTAINERS")
+ or die "$P: Can't open MAINTAINERS: $!\n";
+while (<$maint>) {
+ my $line = $_;
+
+ if ($line =~ m/^(\C):\s*(.*)/) {
+ my $type = $1;
+ my $value = $2;
+
+ ##Filename pattern matching
+ if ($type eq "F" || $type eq "X") {
+ $value =~ s@\.@\\\.@g; ##Convert . to \.
+ $value =~ s/\*/\.\*/g; ##Convert * to .*
+ $value =~ s/\?/\./g; ##Convert ? to .
+ ##if pattern is a directory and it lacks a trailing slash, add one
+ if ((-d $value)) {
+ $value =~ s@([^/])$@$1/@;
+ }
+ } elsif ($type eq "K") {
+ $keyword_hash{@typevalue} = $value;
+ }
+ push(@typevalue, "$type:$value");
+ } elsif (!/^(\s)*$/) {
+ $line =~ s/\n$//g;
+ push(@typevalue, $line);
+ }
+}
+close($maint);
+
+
+#
+# Read mail address map
+#
+
+my $mailmap;
+
+read_mailmap();
+
+sub read_mailmap {
+ $mailmap = {
+ names => {},
+ addresses => {}
+ };
+
+ return if (!$email_use_mailmap || !(-f "${lk_path}.mailmap"));
+
+ open(my $mailmap_file, '<', "${lk_path}.mailmap")
+ or warn "$P: Can't open .mailmap: $!\n";
+
+ while (<$mailmap_file>) {
+ s/#.*$//; #strip comments
+ s/^\s+|\s+$//g; #trim
+
+ next if (/^\s*$/); #skip empty lines
+ #entries have one of the following formats:
+ # name1 <mail1>
+ # <mail1> <mail2>
+ # name1 <mail1> <mail2>
+ # name1 <mail1> name2 <mail2>
+ # (see man git-shortlog)
+ if (/^(.+)<(.+)>$/) {
+ my $real_name = $1;
+ my $address = $2;
+
+ $real_name =~ s/\s+$//;
+ ($real_name, $address) = parse_email("$real_name <$address>");
+ $mailmap->{names}->{$address} = $real_name;
+
+ } elsif (/^<([^\s]+)>\s*<([^\s]+)>$/) {
+ my $real_address = $1;
+ my $wrong_address = $2;
+
+ $mailmap->{addresses}->{$wrong_address} = $real_address;
+
+ } elsif (/^(.+)<([^\s]+)>\s*<([^\s]+)>$/) {
+ my $real_name = $1;
+ my $real_address = $2;
+ my $wrong_address = $3;
+
+ $real_name =~ s/\s+$//;
+ ($real_name, $real_address) =
+ parse_email("$real_name <$real_address>");
+ $mailmap->{names}->{$wrong_address} = $real_name;
+ $mailmap->{addresses}->{$wrong_address} = $real_address;
+
+ } elsif (/^(.+)<([^\s]+)>\s*([^\s].*)<([^\s]+)>$/) {
+ my $real_name = $1;
+ my $real_address = $2;
+ my $wrong_name = $3;
+ my $wrong_address = $4;
+
+ $real_name =~ s/\s+$//;
+ ($real_name, $real_address) =
+ parse_email("$real_name <$real_address>");
+
+ $wrong_name =~ s/\s+$//;
+ ($wrong_name, $wrong_address) =
+ parse_email("$wrong_name <$wrong_address>");
+
+ my $wrong_email = format_email($wrong_name, $wrong_address, 1);
+ $mailmap->{names}->{$wrong_email} = $real_name;
+ $mailmap->{addresses}->{$wrong_email} = $real_address;
+ }
+ }
+ close($mailmap_file);
+}
+
+## use the filenames on the command line or find the filenames in the patchfiles
+
+my @files = ();
+my @range = ();
+my @keyword_tvi = ();
+my @file_emails = ();
+
+if (!@ARGV) {
+ push(@ARGV, "&STDIN");
+}
+
+foreach my $file (@ARGV) {
+ if ($file ne "&STDIN") {
+ ##if $file is a directory and it lacks a trailing slash, add one
+ if ((-d $file)) {
+ $file =~ s@([^/])$@$1/@;
+ } elsif (!(-f $file)) {
+ die "$P: file '${file}' not found\n";
+ }
+ }
+ if ($from_filename) {
+ push(@files, $file);
+ if ($file ne "MAINTAINERS" && -f $file && ($keywords || $file_emails)) {
+ open(my $f, '<', $file)
+ or die "$P: Can't open $file: $!\n";
+ my $text = do { local($/) ; <$f> };
+ close($f);
+ if ($keywords) {
+ foreach my $line (keys %keyword_hash) {
+ if ($text =~ m/$keyword_hash{$line}/x) {
+ push(@keyword_tvi, $line);
+ }
+ }
+ }
+ if ($file_emails) {
+ my @poss_addr = $text =~ m$[A-Za-zÀ-ÿ\"\' \,\.\+-]*\s*[\,]*\s*[\(\<\{]{0,1}[A-Za-z0-9_\.\+-]+\@[A-Za-z0-9\.-]+\.[A-Za-z0-9]+[\)\>\}]{0,1}$g;
+ push(@file_emails, clean_file_emails(@poss_addr));
+ }
+ }
+ } else {
+ my $file_cnt = @files;
+ my $lastfile;
+
+ open(my $patch, "< $file")
+ or die "$P: Can't open $file: $!\n";
+
+ # We can check arbitrary information before the patch
+ # like the commit message, mail headers, etc...
+ # This allows us to match arbitrary keywords against any part
+ # of a git format-patch generated file (subject tags, etc...)
+
+ my $patch_prefix = ""; #Parsing the intro
+
+ while (<$patch>) {
+ my $patch_line = $_;
+ if (m/^\+\+\+\s+(\S+)/) {
+ my $filename = $1;
+ $filename =~ s@^[^/]*/@@;
+ $filename =~ s@\n@@;
+ $lastfile = $filename;
+ push(@files, $filename);
+ $patch_prefix = "^[+-].*"; #Now parsing the actual patch
+ } elsif (m/^\@\@ -(\d+),(\d+)/) {
+ if ($email_git_blame) {
+ push(@range, "$lastfile:$1:$2");
+ }
+ } elsif ($keywords) {
+ foreach my $line (keys %keyword_hash) {
+ if ($patch_line =~ m/${patch_prefix}$keyword_hash{$line}/x) {
+ push(@keyword_tvi, $line);
+ }
+ }
+ }
+ }
+ close($patch);
+
+ if ($file_cnt == @files) {
+ warn "$P: file '${file}' doesn't appear to be a patch. "
+ . "Add -f to options?\n";
+ }
+ @files = sort_and_uniq(@files);
+ }
+}
+
+@file_emails = uniq(@file_emails);
+
+my %email_hash_name;
+my %email_hash_address;
+my @email_to = ();
+my %hash_list_to;
+my @list_to = ();
+my @scm = ();
+my @web = ();
+my @subsystem = ();
+my @status = ();
+my %deduplicate_name_hash = ();
+my %deduplicate_address_hash = ();
+my $signature_pattern;
+
+my @maintainers = get_maintainers();
+
+if (@maintainers) {
+ @maintainers = merge_email(@maintainers);
+ output(@maintainers);
+}
+
+if ($scm) {
+ @scm = uniq(@scm);
+ output(@scm);
+}
+
+if ($status) {
+ @status = uniq(@status);
+ output(@status);
+}
+
+if ($subsystem) {
+ @subsystem = uniq(@subsystem);
+ output(@subsystem);
+}
+
+if ($web) {
+ @web = uniq(@web);
+ output(@web);
+}
+
+exit($exit);
+
+sub range_is_maintained {
+ my ($start, $end) = @_;
+
+ for (my $i = $start; $i < $end; $i++) {
+ my $line = $typevalue[$i];
+ if ($line =~ m/^(\C):\s*(.*)/) {
+ my $type = $1;
+ my $value = $2;
+ if ($type eq 'S') {
+ if ($value =~ /(maintain|support)/i) {
+ return 1;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+sub range_has_maintainer {
+ my ($start, $end) = @_;
+
+ for (my $i = $start; $i < $end; $i++) {
+ my $line = $typevalue[$i];
+ if ($line =~ m/^(\C):\s*(.*)/) {
+ my $type = $1;
+ my $value = $2;
+ if ($type eq 'M') {
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+sub get_maintainers {
+ %email_hash_name = ();
+ %email_hash_address = ();
+ %commit_author_hash = ();
+ %commit_signer_hash = ();
+ @email_to = ();
+ %hash_list_to = ();
+ @list_to = ();
+ @scm = ();
+ @web = ();
+ @subsystem = ();
+ @status = ();
+ %deduplicate_name_hash = ();
+ %deduplicate_address_hash = ();
+ if ($email_git_all_signature_types) {
+ $signature_pattern = "(.+?)[Bb][Yy]:";
+ } else {
+ $signature_pattern = "\(" . join("|", @signature_tags) . "\)";
+ }
+
+ # Find responsible parties
+
+ my %exact_pattern_match_hash = ();
+
+ foreach my $file (@files) {
+
+ my %hash;
+ my $tvi = find_first_section();
+ while ($tvi < @typevalue) {
+ my $start = find_starting_index($tvi);
+ my $end = find_ending_index($tvi);
+ my $exclude = 0;
+ my $i;
+
+ #Do not match excluded file patterns
+
+ for ($i = $start; $i < $end; $i++) {
+ my $line = $typevalue[$i];
+ if ($line =~ m/^(\C):\s*(.*)/) {
+ my $type = $1;
+ my $value = $2;
+ if ($type eq 'X') {
+ if (file_match_pattern($file, $value)) {
+ $exclude = 1;
+ last;
+ }
+ }
+ }
+ }
+
+ if (!$exclude) {
+ for ($i = $start; $i < $end; $i++) {
+ my $line = $typevalue[$i];
+ if ($line =~ m/^(\C):\s*(.*)/) {
+ my $type = $1;
+ my $value = $2;
+ if ($type eq 'F') {
+ if (file_match_pattern($file, $value)) {
+ my $value_pd = ($value =~ tr@/@@);
+ my $file_pd = ($file =~ tr@/@@);
+ $value_pd++ if (substr($value,-1,1) ne "/");
+ $value_pd = -1 if ($value =~ /^\.\*/);
+ if ($value_pd >= $file_pd &&
+ range_is_maintained($start, $end) &&
+ range_has_maintainer($start, $end)) {
+ $exact_pattern_match_hash{$file} = 1;
+ }
+ if ($pattern_depth == 0 ||
+ (($file_pd - $value_pd) < $pattern_depth)) {
+ $hash{$tvi} = $value_pd;
+ }
+ }
+ }
+ }
+ }
+ }
+ $tvi = $end + 1;
+ }
+
+ foreach my $line (sort {$hash{$b} <=> $hash{$a}} keys %hash) {
+ add_categories($line);
+ if ($sections) {
+ my $i;
+ my $start = find_starting_index($line);
+ my $end = find_ending_index($line);
+ for ($i = $start; $i < $end; $i++) {
+ my $line = $typevalue[$i];
+ if ($line =~ /^[FX]:/) { ##Restore file patterns
+ $line =~ s/([^\\])\.([^\*])/$1\?$2/g;
+ $line =~ s/([^\\])\.$/$1\?/g; ##Convert . back to ?
+ $line =~ s/\\\./\./g; ##Convert \. to .
+ $line =~ s/\.\*/\*/g; ##Convert .* to *
+ }
+ $line =~ s/^([A-Z]):/$1:\t/g;
+ print("$line\n");
+ }
+ print("\n");
+ }
+ }
+ }
+
+ if ($keywords) {
+ @keyword_tvi = sort_and_uniq(@keyword_tvi);
+ foreach my $line (@keyword_tvi) {
+ add_categories($line);
+ }
+ }
+
+ foreach my $email (@email_to, @list_to) {
+ $email->[0] = deduplicate_email($email->[0]);
+ }
+
+ foreach my $file (@files) {
+ if ($email &&
+ ($email_git || ($email_git_fallback &&
+ !$exact_pattern_match_hash{$file}))) {
+ vcs_file_signoffs($file);
+ }
+ if ($email && $email_git_blame) {
+ vcs_file_blame($file);
+ }
+ }
+
+ if ($email) {
+ foreach my $chief (@penguin_chief) {
+ if ($chief =~ m/^(.*):(.*)/) {
+ my $email_address;
+
+ $email_address = format_email($1, $2, $email_usename);
+ if ($email_git_penguin_chiefs) {
+ push(@email_to, [$email_address, 'chief penguin']);
+ } else {
+ @email_to = grep($_->[0] !~ /${email_address}/, @email_to);
+ }
+ }
+ }
+
+ foreach my $email (@file_emails) {
+ my ($name, $address) = parse_email($email);
+
+ my $tmp_email = format_email($name, $address, $email_usename);
+ push_email_address($tmp_email, '');
+ add_role($tmp_email, 'in file');
+ }
+ }
+
+ my @to = ();
+ if ($email || $email_list) {
+ if ($email) {
+ @to = (@to, @email_to);
+ }
+ if ($email_list) {
+ @to = (@to, @list_to);
+ }
+ }
+
+ if ($interactive) {
+ @to = interactive_get_maintainers(\@to);
+ }
+
+ return @to;
+}
+
+sub file_match_pattern {
+ my ($file, $pattern) = @_;
+ if (substr($pattern, -1) eq "/") {
+ if ($file =~ m@^$pattern@) {
+ return 1;
+ }
+ } else {
+ if ($file =~ m@^$pattern@) {
+ my $s1 = ($file =~ tr@/@@);
+ my $s2 = ($pattern =~ tr@/@@);
+ if ($s1 == $s2) {
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+sub usage {
+ print <<EOT;
+usage: $P [options] patchfile
+ $P [options] -f file|directory
+version: $V
+
+MAINTAINER field selection options:
+ --email => print email address(es) if any
+ --git => include recent git \*-by: signers
+ --git-all-signature-types => include signers regardless of signature type
+ or use only ${signature_pattern} signers (default: $email_git_all_signature_types)
+ --git-fallback => use git when no exact MAINTAINERS pattern (default: $email_git_fallback)
+ --git-chief-penguins => include ${penguin_chiefs}
+ --git-min-signatures => number of signatures required (default: $email_git_min_signatures)
+ --git-max-maintainers => maximum maintainers to add (default: $email_git_max_maintainers)
+ --git-min-percent => minimum percentage of commits required (default: $email_git_min_percent)
+ --git-blame => use git blame to find modified commits for patch or file
+ --git-since => git history to use (default: $email_git_since)
+ --hg-since => hg history to use (default: $email_hg_since)
+ --interactive => display a menu (mostly useful if used with the --git option)
+ --m => include maintainer(s) if any
+ --n => include name 'Full Name <addr\@domain.tld>'
+ --l => include list(s) if any
+ --s => include subscriber only list(s) if any
+ --remove-duplicates => minimize duplicate email names/addresses
+ --roles => show roles (status:subsystem, git-signer, list, etc...)
+ --rolestats => show roles and statistics (commits/total_commits, %)
+ --file-emails => add email addresses found in -f file (default: 0 (off))
+ --scm => print SCM tree(s) if any
+ --status => print status if any
+ --subsystem => print subsystem name if any
+ --web => print website(s) if any
+
+Output type options:
+ --separator [, ] => separator for multiple entries on 1 line
+ using --separator also sets --nomultiline if --separator is not [, ]
+ --multiline => print 1 entry per line
+
+Other options:
+ --pattern-depth => Number of pattern directory traversals (default: 0 (all))
+ --keywords => scan patch for keywords (default: $keywords)
+ --sections => print all of the subsystem sections with pattern matches
+ --mailmap => use .mailmap file (default: $email_use_mailmap)
+ --version => show version
+ --help => show this help information
+
+Default options:
+ [--email --nogit --git-fallback --m --n --l --multiline -pattern-depth=0
+ --remove-duplicates --rolestats]
+
+Notes:
+ Using "-f directory" may give unexpected results:
+ Used with "--git", git signators for _all_ files in and below
+ directory are examined as git recurses directories.
+ Any specified X: (exclude) pattern matches are _not_ ignored.
+ Used with "--nogit", directory is used as a pattern match,
+ no individual file within the directory or subdirectory
+ is matched.
+ Used with "--git-blame", does not iterate all files in directory
+ Using "--git-blame" is slow and may add old committers and authors
+ that are no longer active maintainers to the output.
+ Using "--roles" or "--rolestats" with git send-email --cc-cmd or any
+ other automated tools that expect only ["name"] <email address>
+ may not work because of additional output after <email address>.
+ Using "--rolestats" and "--git-blame" shows the #/total=% commits,
+ not the percentage of the entire file authored. # of commits is
+ not a good measure of amount of code authored. 1 major commit may
+ contain a thousand lines, 5 trivial commits may modify a single line.
+ If git is not installed, but mercurial (hg) is installed and an .hg
+ repository exists, the following options apply to mercurial:
+ --git,
+ --git-min-signatures, --git-max-maintainers, --git-min-percent, and
+ --git-blame
+ Use --hg-since not --git-since to control date selection
+ File ".get_maintainer.conf", if it exists in the QEMU source root
+ directory, can change whatever get_maintainer defaults are desired.
+ Entries in this file can be any command line argument.
+ This file is prepended to any additional command line arguments.
+ Multiple lines and # comments are allowed.
+EOT
+}
+
+sub top_of_tree {
+ my ($lk_path) = @_;
+
+ if ($lk_path ne "" && substr($lk_path,length($lk_path)-1,1) ne "/") {
+ $lk_path .= "/";
+ }
+ if ( (-f "${lk_path}COPYING")
+ && (-f "${lk_path}MAINTAINERS")
+ && (-f "${lk_path}Makefile")
+ && (-d "${lk_path}docs")
+ && (-f "${lk_path}VERSION")
+ && (-f "${lk_path}vl.c")) {
+ return 1;
+ }
+ return 0;
+}
+
+sub parse_email {
+ my ($formatted_email) = @_;
+
+ my $name = "";
+ my $address = "";
+
+ if ($formatted_email =~ /^([^<]+)<(.+\@.*)>.*$/) {
+ $name = $1;
+ $address = $2;
+ } elsif ($formatted_email =~ /^\s*<(.+\@\S*)>.*$/) {
+ $address = $1;
+ } elsif ($formatted_email =~ /^(.+\@\S*).*$/) {
+ $address = $1;
+ }
+
+ $name =~ s/^\s+|\s+$//g;
+ $name =~ s/^\"|\"$//g;
+ $address =~ s/^\s+|\s+$//g;
+
+ if ($name =~ /[^\w \-]/i) { ##has "must quote" chars
+ $name =~ s/(?<!\\)"/\\"/g; ##escape quotes
+ $name = "\"$name\"";
+ }
+
+ return ($name, $address);
+}
+
+sub format_email {
+ my ($name, $address, $usename) = @_;
+
+ my $formatted_email;
+
+ $name =~ s/^\s+|\s+$//g;
+ $name =~ s/^\"|\"$//g;
+ $address =~ s/^\s+|\s+$//g;
+
+ if ($name =~ /[^\w \-]/i) { ##has "must quote" chars
+ $name =~ s/(?<!\\)"/\\"/g; ##escape quotes
+ $name = "\"$name\"";
+ }
+
+ if ($usename) {
+ if ("$name" eq "") {
+ $formatted_email = "$address";
+ } else {
+ $formatted_email = "$name <$address>";
+ }
+ } else {
+ $formatted_email = $address;
+ }
+
+ return $formatted_email;
+}
+
+sub find_first_section {
+ my $index = 0;
+
+ while ($index < @typevalue) {
+ my $tv = $typevalue[$index];
+ if (($tv =~ m/^(\C):\s*(.*)/)) {
+ last;
+ }
+ $index++;
+ }
+
+ return $index;
+}
+
+sub find_starting_index {
+ my ($index) = @_;
+
+ while ($index > 0) {
+ my $tv = $typevalue[$index];
+ if (!($tv =~ m/^(\C):\s*(.*)/)) {
+ last;
+ }
+ $index--;
+ }
+
+ return $index;
+}
+
+sub find_ending_index {
+ my ($index) = @_;
+
+ while ($index < @typevalue) {
+ my $tv = $typevalue[$index];
+ if (!($tv =~ m/^(\C):\s*(.*)/)) {
+ last;
+ }
+ $index++;
+ }
+
+ return $index;
+}
+
+sub get_maintainer_role {
+ my ($index) = @_;
+
+ my $i;
+ my $start = find_starting_index($index);
+ my $end = find_ending_index($index);
+
+ my $role;
+ my $subsystem = $typevalue[$start];
+ if (length($subsystem) > 20) {
+ $subsystem = substr($subsystem, 0, 17);
+ $subsystem =~ s/\s*$//;
+ $subsystem = $subsystem . "...";
+ }
+
+ for ($i = $start + 1; $i < $end; $i++) {
+ my $tv = $typevalue[$i];
+ if ($tv =~ m/^(\C):\s*(.*)/) {
+ my $ptype = $1;
+ my $pvalue = $2;
+ if ($ptype eq "S") {
+ $role = $pvalue;
+ }
+ }
+ }
+
+ $role = lc($role);
+ if ($role eq "supported") {
+ $role = "supporter";
+ } elsif ($role eq "maintained") {
+ $role = "maintainer";
+ } elsif ($role eq "odd fixes") {
+ $role = "odd fixer";
+ } elsif ($role eq "orphan") {
+ $role = "orphan minder";
+ } elsif ($role eq "obsolete") {
+ $role = "obsolete minder";
+ } elsif ($role eq "buried alive in reporters") {
+ $role = "chief penguin";
+ }
+
+ return $role . ":" . $subsystem;
+}
+
+sub get_list_role {
+ my ($index) = @_;
+
+ my $i;
+ my $start = find_starting_index($index);
+ my $end = find_ending_index($index);
+
+ my $subsystem = $typevalue[$start];
+ if (length($subsystem) > 20) {
+ $subsystem = substr($subsystem, 0, 17);
+ $subsystem =~ s/\s*$//;
+ $subsystem = $subsystem . "...";
+ }
+
+ if ($subsystem eq "THE REST") {
+ $subsystem = "";
+ }
+
+ return $subsystem;
+}
+
+sub add_categories {
+ my ($index) = @_;
+
+ my $i;
+ my $start = find_starting_index($index);
+ my $end = find_ending_index($index);
+
+ push(@subsystem, $typevalue[$start]);
+
+ for ($i = $start + 1; $i < $end; $i++) {
+ my $tv = $typevalue[$i];
+ if ($tv =~ m/^(\C):\s*(.*)/) {
+ my $ptype = $1;
+ my $pvalue = $2;
+ if ($ptype eq "L") {
+ my $list_address = $pvalue;
+ my $list_additional = "";
+ my $list_role = get_list_role($i);
+
+ if ($list_role ne "") {
+ $list_role = ":" . $list_role;
+ }
+ if ($list_address =~ m/([^\s]+)\s+(.*)$/) {
+ $list_address = $1;
+ $list_additional = $2;
+ }
+ if ($list_additional =~ m/subscribers-only/) {
+ if ($email_subscriber_list) {
+ if (!$hash_list_to{lc($list_address)}) {
+ $hash_list_to{lc($list_address)} = 1;
+ push(@list_to, [$list_address,
+ "subscriber list${list_role}"]);
+ }
+ }
+ } else {
+ if ($email_list) {
+ if (!$hash_list_to{lc($list_address)}) {
+ $hash_list_to{lc($list_address)} = 1;
+ push(@list_to, [$list_address,
+ "open list${list_role}"]);
+ }
+ }
+ }
+ } elsif ($ptype eq "M") {
+ my ($name, $address) = parse_email($pvalue);
+ if ($name eq "") {
+ if ($i > 0) {
+ my $tv = $typevalue[$i - 1];
+ if ($tv =~ m/^(\C):\s*(.*)/) {
+ if ($1 eq "P") {
+ $name = $2;
+ $pvalue = format_email($name, $address, $email_usename);
+ }
+ }
+ }
+ }
+ if ($email_maintainer) {
+ my $role = get_maintainer_role($i);
+ push_email_addresses($pvalue, $role);
+ }
+ } elsif ($ptype eq "T") {
+ push(@scm, $pvalue);
+ } elsif ($ptype eq "W") {
+ push(@web, $pvalue);
+ } elsif ($ptype eq "S") {
+ push(@status, $pvalue);
+ }
+ }
+ }
+}
+
+sub email_inuse {
+ my ($name, $address) = @_;
+
+ return 1 if (($name eq "") && ($address eq ""));
+ return 1 if (($name ne "") && exists($email_hash_name{lc($name)}));
+ return 1 if (($address ne "") && exists($email_hash_address{lc($address)}));
+
+ return 0;
+}
+
+sub push_email_address {
+ my ($line, $role) = @_;
+
+ my ($name, $address) = parse_email($line);
+
+ if ($address eq "") {
+ return 0;
+ }
+
+ if (!$email_remove_duplicates) {
+ push(@email_to, [format_email($name, $address, $email_usename), $role]);
+ } elsif (!email_inuse($name, $address)) {
+ push(@email_to, [format_email($name, $address, $email_usename), $role]);
+ $email_hash_name{lc($name)}++ if ($name ne "");
+ $email_hash_address{lc($address)}++;
+ }
+
+ return 1;
+}
+
+sub push_email_addresses {
+ my ($address, $role) = @_;
+
+ my @address_list = ();
+
+ if (rfc822_valid($address)) {
+ push_email_address($address, $role);
+ } elsif (@address_list = rfc822_validlist($address)) {
+ my $array_count = shift(@address_list);
+ while (my $entry = shift(@address_list)) {
+ push_email_address($entry, $role);
+ }
+ } else {
+ if (!push_email_address($address, $role)) {
+ warn("Invalid MAINTAINERS address: '" . $address . "'\n");
+ }
+ }
+}
+
+sub add_role {
+ my ($line, $role) = @_;
+
+ my ($name, $address) = parse_email($line);
+ my $email = format_email($name, $address, $email_usename);
+
+ foreach my $entry (@email_to) {
+ if ($email_remove_duplicates) {
+ my ($entry_name, $entry_address) = parse_email($entry->[0]);
+ if (($name eq $entry_name || $address eq $entry_address)
+ && ($role eq "" || !($entry->[1] =~ m/$role/))
+ ) {
+ if ($entry->[1] eq "") {
+ $entry->[1] = "$role";
+ } else {
+ $entry->[1] = "$entry->[1],$role";
+ }
+ }
+ } else {
+ if ($email eq $entry->[0]
+ && ($role eq "" || !($entry->[1] =~ m/$role/))
+ ) {
+ if ($entry->[1] eq "") {
+ $entry->[1] = "$role";
+ } else {
+ $entry->[1] = "$entry->[1],$role";
+ }
+ }
+ }
+ }
+}
+
+sub which {
+ my ($bin) = @_;
+
+ foreach my $path (split(/:/, $ENV{PATH})) {
+ if (-e "$path/$bin") {
+ return "$path/$bin";
+ }
+ }
+
+ return "";
+}
+
+sub which_conf {
+ my ($conf) = @_;
+
+ foreach my $path (split(/:/, ".:$ENV{HOME}:.scripts")) {
+ if (-e "$path/$conf") {
+ return "$path/$conf";
+ }
+ }
+
+ return "";
+}
+
+sub mailmap_email {
+ my ($line) = @_;
+
+ my ($name, $address) = parse_email($line);
+ my $email = format_email($name, $address, 1);
+ my $real_name = $name;
+ my $real_address = $address;
+
+ if (exists $mailmap->{names}->{$email} ||
+ exists $mailmap->{addresses}->{$email}) {
+ if (exists $mailmap->{names}->{$email}) {
+ $real_name = $mailmap->{names}->{$email};
+ }
+ if (exists $mailmap->{addresses}->{$email}) {
+ $real_address = $mailmap->{addresses}->{$email};
+ }
+ } else {
+ if (exists $mailmap->{names}->{$address}) {
+ $real_name = $mailmap->{names}->{$address};
+ }
+ if (exists $mailmap->{addresses}->{$address}) {
+ $real_address = $mailmap->{addresses}->{$address};
+ }
+ }
+ return format_email($real_name, $real_address, 1);
+}
+
+sub mailmap {
+ my (@addresses) = @_;
+
+ my @mapped_emails = ();
+ foreach my $line (@addresses) {
+ push(@mapped_emails, mailmap_email($line));
+ }
+ merge_by_realname(@mapped_emails) if ($email_use_mailmap);
+ return @mapped_emails;
+}
+
+sub merge_by_realname {
+ my %address_map;
+ my (@emails) = @_;
+
+ foreach my $email (@emails) {
+ my ($name, $address) = parse_email($email);
+ if (exists $address_map{$name}) {
+ $address = $address_map{$name};
+ $email = format_email($name, $address, 1);
+ } else {
+ $address_map{$name} = $address;
+ }
+ }
+}
+
+sub git_execute_cmd {
+ my ($cmd) = @_;
+ my @lines = ();
+
+ my $output = `$cmd`;
+ $output =~ s/^\s*//gm;
+ @lines = split("\n", $output);
+
+ return @lines;
+}
+
+sub hg_execute_cmd {
+ my ($cmd) = @_;
+ my @lines = ();
+
+ my $output = `$cmd`;
+ @lines = split("\n", $output);
+
+ return @lines;
+}
+
+sub extract_formatted_signatures {
+ my (@signature_lines) = @_;
+
+ my @type = @signature_lines;
+
+ s/\s*(.*):.*/$1/ for (@type);
+
+ # cut -f2- -d":"
+ s/\s*.*:\s*(.+)\s*/$1/ for (@signature_lines);
+
+## Reformat email addresses (with names) to avoid badly written signatures
+
+ foreach my $signer (@signature_lines) {
+ $signer = deduplicate_email($signer);
+ }
+
+ return (\@type, \@signature_lines);
+}
+
+sub vcs_find_signers {
+ my ($cmd) = @_;
+ my $commits;
+ my @lines = ();
+ my @signatures = ();
+
+ @lines = &{$VCS_cmds{"execute_cmd"}}($cmd);
+
+ my $pattern = $VCS_cmds{"commit_pattern"};
+
+ $commits = grep(/$pattern/, @lines); # of commits
+
+ @signatures = grep(/^[ \t]*${signature_pattern}.*\@.*$/, @lines);
+
+ return (0, @signatures) if !@signatures;
+
+ save_commits_by_author(@lines) if ($interactive);
+ save_commits_by_signer(@lines) if ($interactive);
+
+ if (!$email_git_penguin_chiefs) {
+ @signatures = grep(!/${penguin_chiefs}/i, @signatures);
+ }
+
+ my ($types_ref, $signers_ref) = extract_formatted_signatures(@signatures);
+
+ return ($commits, @$signers_ref);
+}
+
+sub vcs_find_author {
+ my ($cmd) = @_;
+ my @lines = ();
+
+ @lines = &{$VCS_cmds{"execute_cmd"}}($cmd);
+
+ if (!$email_git_penguin_chiefs) {
+ @lines = grep(!/${penguin_chiefs}/i, @lines);
+ }
+
+ return @lines if !@lines;
+
+ my @authors = ();
+ foreach my $line (@lines) {
+ if ($line =~ m/$VCS_cmds{"author_pattern"}/) {
+ my $author = $1;
+ my ($name, $address) = parse_email($author);
+ $author = format_email($name, $address, 1);
+ push(@authors, $author);
+ }
+ }
+
+ save_commits_by_author(@lines) if ($interactive);
+ save_commits_by_signer(@lines) if ($interactive);
+
+ return @authors;
+}
+
+sub vcs_save_commits {
+ my ($cmd) = @_;
+ my @lines = ();
+ my @commits = ();
+
+ @lines = &{$VCS_cmds{"execute_cmd"}}($cmd);
+
+ foreach my $line (@lines) {
+ if ($line =~ m/$VCS_cmds{"blame_commit_pattern"}/) {
+ push(@commits, $1);
+ }
+ }
+
+ return @commits;
+}
+
+sub vcs_blame {
+ my ($file) = @_;
+ my $cmd;
+ my @commits = ();
+
+ return @commits if (!(-f $file));
+
+ if (@range && $VCS_cmds{"blame_range_cmd"} eq "") {
+ my @all_commits = ();
+
+ $cmd = $VCS_cmds{"blame_file_cmd"};
+ $cmd =~ s/(\$\w+)/$1/eeg; #interpolate $cmd
+ @all_commits = vcs_save_commits($cmd);
+
+ foreach my $file_range_diff (@range) {
+ next if (!($file_range_diff =~ m/(.+):(.+):(.+)/));
+ my $diff_file = $1;
+ my $diff_start = $2;
+ my $diff_length = $3;
+ next if ("$file" ne "$diff_file");
+ for (my $i = $diff_start; $i < $diff_start + $diff_length; $i++) {
+ push(@commits, $all_commits[$i]);
+ }
+ }
+ } elsif (@range) {
+ foreach my $file_range_diff (@range) {
+ next if (!($file_range_diff =~ m/(.+):(.+):(.+)/));
+ my $diff_file = $1;
+ my $diff_start = $2;
+ my $diff_length = $3;
+ next if ("$file" ne "$diff_file");
+ $cmd = $VCS_cmds{"blame_range_cmd"};
+ $cmd =~ s/(\$\w+)/$1/eeg; #interpolate $cmd
+ push(@commits, vcs_save_commits($cmd));
+ }
+ } else {
+ $cmd = $VCS_cmds{"blame_file_cmd"};
+ $cmd =~ s/(\$\w+)/$1/eeg; #interpolate $cmd
+ @commits = vcs_save_commits($cmd);
+ }
+
+ foreach my $commit (@commits) {
+ $commit =~ s/^\^//g;
+ }
+
+ return @commits;
+}
+
+my $printed_novcs = 0;
+sub vcs_exists {
+ %VCS_cmds = %VCS_cmds_git;
+ return 1 if eval $VCS_cmds{"available"};
+ %VCS_cmds = %VCS_cmds_hg;
+ return 2 if eval $VCS_cmds{"available"};
+ %VCS_cmds = ();
+ if (!$printed_novcs) {
+ warn("$P: No supported VCS found. Add --nogit to options?\n");
+ warn("Using a git repository produces better results.\n");
+ warn("Try latest git repository using:\n");
+ warn("git clone git://git.qemu.org/qemu.git\n");
+ $printed_novcs = 1;
+ }
+ return 0;
+}
+
+sub vcs_is_git {
+ vcs_exists();
+ return $vcs_used == 1;
+}
+
+sub vcs_is_hg {
+ return $vcs_used == 2;
+}
+
+sub interactive_get_maintainers {
+ my ($list_ref) = @_;
+ my @list = @$list_ref;
+
+ vcs_exists();
+
+ my %selected;
+ my %authored;
+ my %signed;
+ my $count = 0;
+ my $maintained = 0;
+ foreach my $entry (@list) {
+ $maintained = 1 if ($entry->[1] =~ /^(maintainer|supporter)/i);
+ $selected{$count} = 1;
+ $authored{$count} = 0;
+ $signed{$count} = 0;
+ $count++;
+ }
+
+ #menu loop
+ my $done = 0;
+ my $print_options = 0;
+ my $redraw = 1;
+ while (!$done) {
+ $count = 0;
+ if ($redraw) {
+ printf STDERR "\n%1s %2s %-65s",
+ "*", "#", "email/list and role:stats";
+ if ($email_git ||
+ ($email_git_fallback && !$maintained) ||
+ $email_git_blame) {
+ print STDERR "auth sign";
+ }
+ print STDERR "\n";
+ foreach my $entry (@list) {
+ my $email = $entry->[0];
+ my $role = $entry->[1];
+ my $sel = "";
+ $sel = "*" if ($selected{$count});
+ my $commit_author = $commit_author_hash{$email};
+ my $commit_signer = $commit_signer_hash{$email};
+ my $authored = 0;
+ my $signed = 0;
+ $authored++ for (@{$commit_author});
+ $signed++ for (@{$commit_signer});
+ printf STDERR "%1s %2d %-65s", $sel, $count + 1, $email;
+ printf STDERR "%4d %4d", $authored, $signed
+ if ($authored > 0 || $signed > 0);
+ printf STDERR "\n %s\n", $role;
+ if ($authored{$count}) {
+ my $commit_author = $commit_author_hash{$email};
+ foreach my $ref (@{$commit_author}) {
+ print STDERR " Author: @{$ref}[1]\n";
+ }
+ }
+ if ($signed{$count}) {
+ my $commit_signer = $commit_signer_hash{$email};
+ foreach my $ref (@{$commit_signer}) {
+ print STDERR " @{$ref}[2]: @{$ref}[1]\n";
+ }
+ }
+
+ $count++;
+ }
+ }
+ my $date_ref = \$email_git_since;
+ $date_ref = \$email_hg_since if (vcs_is_hg());
+ if ($print_options) {
+ $print_options = 0;
+ if (vcs_exists()) {
+ print STDERR <<EOT
+
+Version Control options:
+g use git history [$email_git]
+gf use git-fallback [$email_git_fallback]
+b use git blame [$email_git_blame]
+bs use blame signatures [$email_git_blame_signatures]
+c# minimum commits [$email_git_min_signatures]
+%# min percent [$email_git_min_percent]
+d# history to use [$$date_ref]
+x# max maintainers [$email_git_max_maintainers]
+t all signature types [$email_git_all_signature_types]
+m use .mailmap [$email_use_mailmap]
+EOT
+ }
+ print STDERR <<EOT
+
+Additional options:
+0 toggle all
+tm toggle maintainers
+tg toggle git entries
+tl toggle open list entries
+ts toggle subscriber list entries
+f emails in file [$file_emails]
+k keywords in file [$keywords]
+r remove duplicates [$email_remove_duplicates]
+p# pattern match depth [$pattern_depth]
+EOT
+ }
+ print STDERR
+"\n#(toggle), A#(author), S#(signed) *(all), ^(none), O(options), Y(approve): ";
+
+ my $input = <STDIN>;
+ chomp($input);
+
+ $redraw = 1;
+ my $rerun = 0;
+ my @wish = split(/[, ]+/, $input);
+ foreach my $nr (@wish) {
+ $nr = lc($nr);
+ my $sel = substr($nr, 0, 1);
+ my $str = substr($nr, 1);
+ my $val = 0;
+ $val = $1 if $str =~ /^(\d+)$/;
+
+ if ($sel eq "y") {
+ $interactive = 0;
+ $done = 1;
+ $output_rolestats = 0;
+ $output_roles = 0;
+ last;
+ } elsif ($nr =~ /^\d+$/ && $nr > 0 && $nr <= $count) {
+ $selected{$nr - 1} = !$selected{$nr - 1};
+ } elsif ($sel eq "*" || $sel eq '^') {
+ my $toggle = 0;
+ $toggle = 1 if ($sel eq '*');
+ for (my $i = 0; $i < $count; $i++) {
+ $selected{$i} = $toggle;
+ }
+ } elsif ($sel eq "0") {
+ for (my $i = 0; $i < $count; $i++) {
+ $selected{$i} = !$selected{$i};
+ }
+ } elsif ($sel eq "t") {
+ if (lc($str) eq "m") {
+ for (my $i = 0; $i < $count; $i++) {
+ $selected{$i} = !$selected{$i}
+ if ($list[$i]->[1] =~ /^(maintainer|supporter)/i);
+ }
+ } elsif (lc($str) eq "g") {
+ for (my $i = 0; $i < $count; $i++) {
+ $selected{$i} = !$selected{$i}
+ if ($list[$i]->[1] =~ /^(author|commit|signer)/i);
+ }
+ } elsif (lc($str) eq "l") {
+ for (my $i = 0; $i < $count; $i++) {
+ $selected{$i} = !$selected{$i}
+ if ($list[$i]->[1] =~ /^(open list)/i);
+ }
+ } elsif (lc($str) eq "s") {
+ for (my $i = 0; $i < $count; $i++) {
+ $selected{$i} = !$selected{$i}
+ if ($list[$i]->[1] =~ /^(subscriber list)/i);
+ }
+ }
+ } elsif ($sel eq "a") {
+ if ($val > 0 && $val <= $count) {
+ $authored{$val - 1} = !$authored{$val - 1};
+ } elsif ($str eq '*' || $str eq '^') {
+ my $toggle = 0;
+ $toggle = 1 if ($str eq '*');
+ for (my $i = 0; $i < $count; $i++) {
+ $authored{$i} = $toggle;
+ }
+ }
+ } elsif ($sel eq "s") {
+ if ($val > 0 && $val <= $count) {
+ $signed{$val - 1} = !$signed{$val - 1};
+ } elsif ($str eq '*' || $str eq '^') {
+ my $toggle = 0;
+ $toggle = 1 if ($str eq '*');
+ for (my $i = 0; $i < $count; $i++) {
+ $signed{$i} = $toggle;
+ }
+ }
+ } elsif ($sel eq "o") {
+ $print_options = 1;
+ $redraw = 1;
+ } elsif ($sel eq "g") {
+ if ($str eq "f") {
+ bool_invert(\$email_git_fallback);
+ } else {
+ bool_invert(\$email_git);
+ }
+ $rerun = 1;
+ } elsif ($sel eq "b") {
+ if ($str eq "s") {
+ bool_invert(\$email_git_blame_signatures);
+ } else {
+ bool_invert(\$email_git_blame);
+ }
+ $rerun = 1;
+ } elsif ($sel eq "c") {
+ if ($val > 0) {
+ $email_git_min_signatures = $val;
+ $rerun = 1;
+ }
+ } elsif ($sel eq "x") {
+ if ($val > 0) {
+ $email_git_max_maintainers = $val;
+ $rerun = 1;
+ }
+ } elsif ($sel eq "%") {
+ if ($str ne "" && $val >= 0) {
+ $email_git_min_percent = $val;
+ $rerun = 1;
+ }
+ } elsif ($sel eq "d") {
+ if (vcs_is_git()) {
+ $email_git_since = $str;
+ } elsif (vcs_is_hg()) {
+ $email_hg_since = $str;
+ }
+ $rerun = 1;
+ } elsif ($sel eq "t") {
+ bool_invert(\$email_git_all_signature_types);
+ $rerun = 1;
+ } elsif ($sel eq "f") {
+ bool_invert(\$file_emails);
+ $rerun = 1;
+ } elsif ($sel eq "r") {
+ bool_invert(\$email_remove_duplicates);
+ $rerun = 1;
+ } elsif ($sel eq "m") {
+ bool_invert(\$email_use_mailmap);
+ read_mailmap();
+ $rerun = 1;
+ } elsif ($sel eq "k") {
+ bool_invert(\$keywords);
+ $rerun = 1;
+ } elsif ($sel eq "p") {
+ if ($str ne "" && $val >= 0) {
+ $pattern_depth = $val;
+ $rerun = 1;
+ }
+ } elsif ($sel eq "h" || $sel eq "?") {
+ print STDERR <<EOT
+
+Interactive mode allows you to select the various maintainers, submitters,
+commit signers and mailing lists that could be CC'd on a patch.
+
+Any *'d entry is selected.
+
+If you have git or hg installed, you can choose to summarize the commit
+history of files in the patch. Also, each line of the current file can
+be matched to its commit author and that commits signers with blame.
+
+Various knobs exist to control the length of time for active commit
+tracking, the maximum number of commit authors and signers to add,
+and such.
+
+Enter selections at the prompt until you are satisfied that the selected
+maintainers are appropriate. You may enter multiple selections separated
+by either commas or spaces.
+
+EOT
+ } else {
+ print STDERR "invalid option: '$nr'\n";
+ $redraw = 0;
+ }
+ }
+ if ($rerun) {
+ print STDERR "git-blame can be very slow, please have patience..."
+ if ($email_git_blame);
+ goto &get_maintainers;
+ }
+ }
+
+ #drop not selected entries
+ $count = 0;
+ my @new_emailto = ();
+ foreach my $entry (@list) {
+ if ($selected{$count}) {
+ push(@new_emailto, $list[$count]);
+ }
+ $count++;
+ }
+ return @new_emailto;
+}
+
+sub bool_invert {
+ my ($bool_ref) = @_;
+
+ if ($$bool_ref) {
+ $$bool_ref = 0;
+ } else {
+ $$bool_ref = 1;
+ }
+}
+
+sub deduplicate_email {
+ my ($email) = @_;
+
+ my $matched = 0;
+ my ($name, $address) = parse_email($email);
+ $email = format_email($name, $address, 1);
+ $email = mailmap_email($email);
+
+ return $email if (!$email_remove_duplicates);
+
+ ($name, $address) = parse_email($email);
+
+ if ($name ne "" && $deduplicate_name_hash{lc($name)}) {
+ $name = $deduplicate_name_hash{lc($name)}->[0];
+ $address = $deduplicate_name_hash{lc($name)}->[1];
+ $matched = 1;
+ } elsif ($deduplicate_address_hash{lc($address)}) {
+ $name = $deduplicate_address_hash{lc($address)}->[0];
+ $address = $deduplicate_address_hash{lc($address)}->[1];
+ $matched = 1;
+ }
+ if (!$matched) {
+ $deduplicate_name_hash{lc($name)} = [ $name, $address ];
+ $deduplicate_address_hash{lc($address)} = [ $name, $address ];
+ }
+ $email = format_email($name, $address, 1);
+ $email = mailmap_email($email);
+ return $email;
+}
+
+sub save_commits_by_author {
+ my (@lines) = @_;
+
+ my @authors = ();
+ my @commits = ();
+ my @subjects = ();
+
+ foreach my $line (@lines) {
+ if ($line =~ m/$VCS_cmds{"author_pattern"}/) {
+ my $author = $1;
+ $author = deduplicate_email($author);
+ push(@authors, $author);
+ }
+ push(@commits, $1) if ($line =~ m/$VCS_cmds{"commit_pattern"}/);
+ push(@subjects, $1) if ($line =~ m/$VCS_cmds{"subject_pattern"}/);
+ }
+
+ for (my $i = 0; $i < @authors; $i++) {
+ my $exists = 0;
+ foreach my $ref(@{$commit_author_hash{$authors[$i]}}) {
+ if (@{$ref}[0] eq $commits[$i] &&
+ @{$ref}[1] eq $subjects[$i]) {
+ $exists = 1;
+ last;
+ }
+ }
+ if (!$exists) {
+ push(@{$commit_author_hash{$authors[$i]}},
+ [ ($commits[$i], $subjects[$i]) ]);
+ }
+ }
+}
+
+sub save_commits_by_signer {
+ my (@lines) = @_;
+
+ my $commit = "";
+ my $subject = "";
+
+ foreach my $line (@lines) {
+ $commit = $1 if ($line =~ m/$VCS_cmds{"commit_pattern"}/);
+ $subject = $1 if ($line =~ m/$VCS_cmds{"subject_pattern"}/);
+ if ($line =~ /^[ \t]*${signature_pattern}.*\@.*$/) {
+ my @signatures = ($line);
+ my ($types_ref, $signers_ref) = extract_formatted_signatures(@signatures);
+ my @types = @$types_ref;
+ my @signers = @$signers_ref;
+
+ my $type = $types[0];
+ my $signer = $signers[0];
+
+ $signer = deduplicate_email($signer);
+
+ my $exists = 0;
+ foreach my $ref(@{$commit_signer_hash{$signer}}) {
+ if (@{$ref}[0] eq $commit &&
+ @{$ref}[1] eq $subject &&
+ @{$ref}[2] eq $type) {
+ $exists = 1;
+ last;
+ }
+ }
+ if (!$exists) {
+ push(@{$commit_signer_hash{$signer}},
+ [ ($commit, $subject, $type) ]);
+ }
+ }
+ }
+}
+
+sub vcs_assign {
+ my ($role, $divisor, @lines) = @_;
+
+ my %hash;
+ my $count = 0;
+
+ return if (@lines <= 0);
+
+ if ($divisor <= 0) {
+ warn("Bad divisor in " . (caller(0))[3] . ": $divisor\n");
+ $divisor = 1;
+ }
+
+ @lines = mailmap(@lines);
+
+ return if (@lines <= 0);
+
+ @lines = sort(@lines);
+
+ # uniq -c
+ $hash{$_}++ for @lines;
+
+ # sort -rn
+ foreach my $line (sort {$hash{$b} <=> $hash{$a}} keys %hash) {
+ my $sign_offs = $hash{$line};
+ my $percent = $sign_offs * 100 / $divisor;
+
+ $percent = 100 if ($percent > 100);
+ $count++;
+ last if ($sign_offs < $email_git_min_signatures ||
+ $count > $email_git_max_maintainers ||
+ $percent < $email_git_min_percent);
+ push_email_address($line, '');
+ if ($output_rolestats) {
+ my $fmt_percent = sprintf("%.0f", $percent);
+ add_role($line, "$role:$sign_offs/$divisor=$fmt_percent%");
+ } else {
+ add_role($line, $role);
+ }
+ }
+}
+
+sub vcs_file_signoffs {
+ my ($file) = @_;
+
+ my @signers = ();
+ my $commits;
+
+ $vcs_used = vcs_exists();
+ return if (!$vcs_used);
+
+ my $cmd = $VCS_cmds{"find_signers_cmd"};
+ $cmd =~ s/(\$\w+)/$1/eeg; # interpolate $cmd
+
+ ($commits, @signers) = vcs_find_signers($cmd);
+
+ foreach my $signer (@signers) {
+ $signer = deduplicate_email($signer);
+ }
+
+ vcs_assign("commit_signer", $commits, @signers);
+}
+
+sub vcs_file_blame {
+ my ($file) = @_;
+
+ my @signers = ();
+ my @all_commits = ();
+ my @commits = ();
+ my $total_commits;
+ my $total_lines;
+
+ $vcs_used = vcs_exists();
+ return if (!$vcs_used);
+
+ @all_commits = vcs_blame($file);
+ @commits = uniq(@all_commits);
+ $total_commits = @commits;
+ $total_lines = @all_commits;
+
+ if ($email_git_blame_signatures) {
+ if (vcs_is_hg()) {
+ my $commit_count;
+ my @commit_signers = ();
+ my $commit = join(" -r ", @commits);
+ my $cmd;
+
+ $cmd = $VCS_cmds{"find_commit_signers_cmd"};
+ $cmd =~ s/(\$\w+)/$1/eeg; #substitute variables in $cmd
+
+ ($commit_count, @commit_signers) = vcs_find_signers($cmd);
+
+ push(@signers, @commit_signers);
+ } else {
+ foreach my $commit (@commits) {
+ my $commit_count;
+ my @commit_signers = ();
+ my $cmd;
+
+ $cmd = $VCS_cmds{"find_commit_signers_cmd"};
+ $cmd =~ s/(\$\w+)/$1/eeg; #substitute variables in $cmd
+
+ ($commit_count, @commit_signers) = vcs_find_signers($cmd);
+
+ push(@signers, @commit_signers);
+ }
+ }
+ }
+
+ if ($from_filename) {
+ if ($output_rolestats) {
+ my @blame_signers;
+ if (vcs_is_hg()) {{ # Double brace for last exit
+ my $commit_count;
+ my @commit_signers = ();
+ @commits = uniq(@commits);
+ @commits = sort(@commits);
+ my $commit = join(" -r ", @commits);
+ my $cmd;
+
+ $cmd = $VCS_cmds{"find_commit_author_cmd"};
+ $cmd =~ s/(\$\w+)/$1/eeg; #substitute variables in $cmd
+
+ my @lines = ();
+
+ @lines = &{$VCS_cmds{"execute_cmd"}}($cmd);
+
+ if (!$email_git_penguin_chiefs) {
+ @lines = grep(!/${penguin_chiefs}/i, @lines);
+ }
+
+ last if !@lines;
+
+ my @authors = ();
+ foreach my $line (@lines) {
+ if ($line =~ m/$VCS_cmds{"author_pattern"}/) {
+ my $author = $1;
+ $author = deduplicate_email($author);
+ push(@authors, $author);
+ }
+ }
+
+ save_commits_by_author(@lines) if ($interactive);
+ save_commits_by_signer(@lines) if ($interactive);
+
+ push(@signers, @authors);
+ }}
+ else {
+ foreach my $commit (@commits) {
+ my $i;
+ my $cmd = $VCS_cmds{"find_commit_author_cmd"};
+ $cmd =~ s/(\$\w+)/$1/eeg; #interpolate $cmd
+ my @author = vcs_find_author($cmd);
+ next if !@author;
+
+ my $formatted_author = deduplicate_email($author[0]);
+
+ my $count = grep(/$commit/, @all_commits);
+ for ($i = 0; $i < $count ; $i++) {
+ push(@blame_signers, $formatted_author);
+ }
+ }
+ }
+ if (@blame_signers) {
+ vcs_assign("authored lines", $total_lines, @blame_signers);
+ }
+ }
+ foreach my $signer (@signers) {
+ $signer = deduplicate_email($signer);
+ }
+ vcs_assign("commits", $total_commits, @signers);
+ } else {
+ foreach my $signer (@signers) {
+ $signer = deduplicate_email($signer);
+ }
+ vcs_assign("modified commits", $total_commits, @signers);
+ }
+}
+
+sub uniq {
+ my (@parms) = @_;
+
+ my %saw;
+ @parms = grep(!$saw{$_}++, @parms);
+ return @parms;
+}
+
+sub sort_and_uniq {
+ my (@parms) = @_;
+
+ my %saw;
+ @parms = sort @parms;
+ @parms = grep(!$saw{$_}++, @parms);
+ return @parms;
+}
+
+sub clean_file_emails {
+ my (@file_emails) = @_;
+ my @fmt_emails = ();
+
+ foreach my $email (@file_emails) {
+ $email =~ s/[\(\<\{]{0,1}([A-Za-z0-9_\.\+-]+\@[A-Za-z0-9\.-]+)[\)\>\}]{0,1}/\<$1\>/g;
+ my ($name, $address) = parse_email($email);
+ if ($name eq '"[,\.]"') {
+ $name = "";
+ }
+
+ my @nw = split(/[^A-Za-zÀ-ÿ\'\,\.\+-]/, $name);
+ if (@nw > 2) {
+ my $first = $nw[@nw - 3];
+ my $middle = $nw[@nw - 2];
+ my $last = $nw[@nw - 1];
+
+ if (((length($first) == 1 && $first =~ m/[A-Za-z]/) ||
+ (length($first) == 2 && substr($first, -1) eq ".")) ||
+ (length($middle) == 1 ||
+ (length($middle) == 2 && substr($middle, -1) eq "."))) {
+ $name = "$first $middle $last";
+ } else {
+ $name = "$middle $last";
+ }
+ }
+
+ if (substr($name, -1) =~ /[,\.]/) {
+ $name = substr($name, 0, length($name) - 1);
+ } elsif (substr($name, -2) =~ /[,\.]"/) {
+ $name = substr($name, 0, length($name) - 2) . '"';
+ }
+
+ if (substr($name, 0, 1) =~ /[,\.]/) {
+ $name = substr($name, 1, length($name) - 1);
+ } elsif (substr($name, 0, 2) =~ /"[,\.]/) {
+ $name = '"' . substr($name, 2, length($name) - 2);
+ }
+
+ my $fmt_email = format_email($name, $address, $email_usename);
+ push(@fmt_emails, $fmt_email);
+ }
+ return @fmt_emails;
+}
+
+sub merge_email {
+ my @lines;
+ my %saw;
+
+ for (@_) {
+ my ($address, $role) = @$_;
+ if (!$saw{$address}) {
+ if ($output_roles) {
+ push(@lines, "$address ($role)");
+ } else {
+ push(@lines, $address);
+ }
+ $saw{$address} = 1;
+ }
+ }
+
+ return @lines;
+}
+
+sub output {
+ my (@parms) = @_;
+
+ if ($output_multiline) {
+ foreach my $line (@parms) {
+ print("${line}\n");
+ }
+ } else {
+ print(join($output_separator, @parms));
+ print("\n");
+ }
+}
+
+my $rfc822re;
+
+sub make_rfc822re {
+# Basic lexical tokens are specials, domain_literal, quoted_string, atom, and
+# comment. We must allow for rfc822_lwsp (or comments) after each of these.
+# This regexp will only work on addresses which have had comments stripped
+# and replaced with rfc822_lwsp.
+
+ my $specials = '()<>@,;:\\\\".\\[\\]';
+ my $controls = '\\000-\\037\\177';
+
+ my $dtext = "[^\\[\\]\\r\\\\]";
+ my $domain_literal = "\\[(?:$dtext|\\\\.)*\\]$rfc822_lwsp*";
+
+ my $quoted_string = "\"(?:[^\\\"\\r\\\\]|\\\\.|$rfc822_lwsp)*\"$rfc822_lwsp*";
+
+# Use zero-width assertion to spot the limit of an atom. A simple
+# $rfc822_lwsp* causes the regexp engine to hang occasionally.
+ my $atom = "[^$specials $controls]+(?:$rfc822_lwsp+|\\Z|(?=[\\[\"$specials]))";
+ my $word = "(?:$atom|$quoted_string)";
+ my $localpart = "$word(?:\\.$rfc822_lwsp*$word)*";
+
+ my $sub_domain = "(?:$atom|$domain_literal)";
+ my $domain = "$sub_domain(?:\\.$rfc822_lwsp*$sub_domain)*";
+
+ my $addr_spec = "$localpart\@$rfc822_lwsp*$domain";
+
+ my $phrase = "$word*";
+ my $route = "(?:\@$domain(?:,\@$rfc822_lwsp*$domain)*:$rfc822_lwsp*)";
+ my $route_addr = "\\<$rfc822_lwsp*$route?$addr_spec\\>$rfc822_lwsp*";
+ my $mailbox = "(?:$addr_spec|$phrase$route_addr)";
+
+ my $group = "$phrase:$rfc822_lwsp*(?:$mailbox(?:,\\s*$mailbox)*)?;\\s*";
+ my $address = "(?:$mailbox|$group)";
+
+ return "$rfc822_lwsp*$address";
+}
+
+sub rfc822_strip_comments {
+ my $s = shift;
+# Recursively remove comments, and replace with a single space. The simpler
+# regexps in the Email Addressing FAQ are imperfect - they will miss escaped
+# chars in atoms, for example.
+
+ while ($s =~ s/^((?:[^"\\]|\\.)*
+ (?:"(?:[^"\\]|\\.)*"(?:[^"\\]|\\.)*)*)
+ \((?:[^()\\]|\\.)*\)/$1 /osx) {}
+ return $s;
+}
+
+# valid: returns true if the parameter is an RFC822 valid address
+#
+sub rfc822_valid {
+ my $s = rfc822_strip_comments(shift);
+
+ if (!$rfc822re) {
+ $rfc822re = make_rfc822re();
+ }
+
+ return $s =~ m/^$rfc822re$/so && $s =~ m/^$rfc822_char*$/;
+}
+
+# validlist: In scalar context, returns true if the parameter is an RFC822
+# valid list of addresses.
+#
+# In list context, returns an empty list on failure (an invalid
+# address was found); otherwise a list whose first element is the
+# number of addresses found and whose remaining elements are the
+# addresses. This is needed to disambiguate failure (invalid)
+# from success with no addresses found, because an empty string is
+# a valid list.
+
+sub rfc822_validlist {
+ my $s = rfc822_strip_comments(shift);
+
+ if (!$rfc822re) {
+ $rfc822re = make_rfc822re();
+ }
+ # * null list items are valid according to the RFC
+ # * the '1' business is to aid in distinguishing failure from no results
+
+ my @r;
+ if ($s =~ m/^(?:$rfc822re)?(?:,(?:$rfc822re)?)*$/so &&
+ $s =~ m/^$rfc822_char*$/) {
+ while ($s =~ m/(?:^|,$rfc822_lwsp*)($rfc822re)/gos) {
+ push(@r, $1);
+ }
+ return wantarray ? (scalar(@r), @r) : 1;
+ }
+ return wantarray ? () : 0;
+}
diff --git a/scripts/update-linux-headers.sh b/scripts/update-linux-headers.sh
new file mode 100755
index 0000000000..9d2a4bc4b4
--- /dev/null
+++ b/scripts/update-linux-headers.sh
@@ -0,0 +1,55 @@
+#!/bin/sh -e
+#
+# Update Linux kernel headers QEMU requires from a specified kernel tree.
+#
+# Copyright (C) 2011 Siemens AG
+#
+# Authors:
+# Jan Kiszka <jan.kiszka@siemens.com>
+#
+# This work is licensed under the terms of the GNU GPL version 2.
+# See the COPYING file in the top-level directory.
+
+tmpdir=`mktemp -d`
+linux="$1"
+output="$2"
+
+if [ -z "$linux" ] || ! [ -d "$linux" ]; then
+ cat << EOF
+usage: update-kernel-headers.sh LINUX_PATH [OUTPUT_PATH]
+
+LINUX_PATH Linux kernel directory to obtain the headers from
+OUTPUT_PATH output directory, usually the qemu source tree (default: $PWD)
+EOF
+ exit 1
+fi
+
+if [ -z "$output" ]; then
+ output="$PWD"
+fi
+
+for arch in x86 powerpc s390; do
+ make -C "$linux" INSTALL_HDR_PATH="$tmpdir" SRCARCH=$arch headers_install
+
+ rm -rf "$output/linux-headers/asm-$arch"
+ mkdir -p "$output/linux-headers/asm-$arch"
+ for header in kvm.h kvm_para.h; do
+ cp "$tmpdir/include/asm/$header" "$output/linux-headers/asm-$arch"
+ done
+ if [ $arch = x86 ]; then
+ cp "$tmpdir/include/asm/hyperv.h" "$output/linux-headers/asm-x86"
+ fi
+done
+
+rm -rf "$output/linux-headers/linux"
+mkdir -p "$output/linux-headers/linux"
+for header in kvm.h kvm_para.h vhost.h virtio_config.h virtio_ring.h; do
+ cp "$tmpdir/include/linux/$header" "$output/linux-headers/linux"
+done
+if [ -L "$linux/source" ]; then
+ cp "$linux/source/COPYING" "$output/linux-headers"
+else
+ cp "$linux/COPYING" "$output/linux-headers"
+fi
+
+rm -rf "$tmpdir"
diff --git a/sysemu.h b/sysemu.h
index 7e70daa3da..d3013f5cc4 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -34,6 +34,9 @@ void qemu_del_vm_change_state_handler(VMChangeStateEntry *e);
#define VMSTOP_LOADVM 7
#define VMSTOP_MIGRATE 8
+#define VMRESET_SILENT false
+#define VMRESET_REPORT true
+
void vm_start(void);
void vm_stop(int reason);
@@ -50,7 +53,7 @@ int qemu_powerdown_requested(void);
void qemu_system_killed(int signal, pid_t pid);
void qemu_kill_report(void);
extern qemu_irq qemu_system_powerdown;
-void qemu_system_reset(void);
+void qemu_system_reset(bool report);
void qemu_add_exit_notifier(Notifier *notify);
void qemu_remove_exit_notifier(Notifier *notify);
diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h
index e98b32513c..411bd55328 100644
--- a/target-alpha/cpu.h
+++ b/target-alpha/cpu.h
@@ -492,4 +492,26 @@ static inline void cpu_set_tls(CPUState *env, target_ulong newtls)
}
#endif
+static inline bool cpu_has_work(CPUState *env)
+{
+ /* Here we are checking to see if the CPU should wake up from HALT.
+ We will have gotten into this state only for WTINT from PALmode. */
+ /* ??? I'm not sure how the IPL state works with WTINT to keep a CPU
+ asleep even if (some) interrupts have been asserted. For now,
+ assume that if a CPU really wants to stay asleep, it will mask
+ interrupts at the chipset level, which will prevent these bits
+ from being set in the first place. */
+ return env->interrupt_request & (CPU_INTERRUPT_HARD
+ | CPU_INTERRUPT_TIMER
+ | CPU_INTERRUPT_SMP
+ | CPU_INTERRUPT_MCHK);
+}
+
+#include "exec-all.h"
+
+static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
+{
+ env->pc = tb->pc;
+}
+
#endif /* !defined (__CPU_ALPHA_H__) */
diff --git a/target-alpha/exec.h b/target-alpha/exec.h
index 7a325e7a75..afb01d3727 100644
--- a/target-alpha/exec.h
+++ b/target-alpha/exec.h
@@ -31,30 +31,9 @@ register struct CPUAlphaState *env asm(AREG0);
#define FP_STATUS (env->fp_status)
#include "cpu.h"
-#include "exec-all.h"
#if !defined(CONFIG_USER_ONLY)
#include "softmmu_exec.h"
#endif /* !defined(CONFIG_USER_ONLY) */
-static inline int cpu_has_work(CPUState *env)
-{
- /* Here we are checking to see if the CPU should wake up from HALT.
- We will have gotten into this state only for WTINT from PALmode. */
- /* ??? I'm not sure how the IPL state works with WTINT to keep a CPU
- asleep even if (some) interrupts have been asserted. For now,
- assume that if a CPU really wants to stay asleep, it will mask
- interrupts at the chipset level, which will prevent these bits
- from being set in the first place. */
- return env->interrupt_request & (CPU_INTERRUPT_HARD
- | CPU_INTERRUPT_TIMER
- | CPU_INTERRUPT_SMP
- | CPU_INTERRUPT_MCHK);
-}
-
-static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
-{
- env->pc = tb->pc;
-}
-
#endif /* !defined (__ALPHA_EXEC_H__) */
diff --git a/target-alpha/helper.c b/target-alpha/helper.c
index 32c2cf9db3..7049c80d5c 100644
--- a/target-alpha/helper.c
+++ b/target-alpha/helper.c
@@ -22,7 +22,6 @@
#include <stdio.h>
#include "cpu.h"
-#include "exec-all.h"
#include "softfloat.h"
uint64_t cpu_alpha_load_fpcr (CPUState *env)
diff --git a/target-alpha/op_helper.c b/target-alpha/op_helper.c
index d33271958f..51d1bd7099 100644
--- a/target-alpha/op_helper.c
+++ b/target-alpha/op_helper.c
@@ -32,7 +32,7 @@ void QEMU_NORETURN helper_excp(int excp, int error)
{
env->exception_index = excp;
env->error_code = error;
- cpu_loop_exit();
+ cpu_loop_exit(env);
}
static void do_restore_state(void *retaddr)
@@ -53,7 +53,7 @@ static void QEMU_NORETURN dynamic_excp(int excp, int error)
env->exception_index = excp;
env->error_code = error;
do_restore_state(GETPC());
- cpu_loop_exit();
+ cpu_loop_exit(env);
}
static void QEMU_NORETURN arith_excp(int exc, uint64_t mask)
@@ -1341,7 +1341,7 @@ void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
if (unlikely(ret != 0)) {
do_restore_state(retaddr);
/* Exception index and error code are already set */
- cpu_loop_exit();
+ cpu_loop_exit(env);
}
env = saved_env;
}
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index ad6c2ca448..c61906a8b3 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -22,7 +22,6 @@
#include <stdio.h>
#include "cpu.h"
-#include "exec-all.h"
#include "disas.h"
#include "host-utils.h"
#include "tcg-op.h"
@@ -1661,9 +1660,12 @@ static void gen_mtpr(int rb, int regno)
static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
{
uint32_t palcode;
- int32_t disp21, disp16, disp12;
+ int32_t disp21, disp16;
+#ifndef CONFIG_USER_ONLY
+ int32_t disp12;
+#endif
uint16_t fn11;
- uint8_t opc, ra, rb, rc, fpfn, fn7, fn2, islit, real_islit;
+ uint8_t opc, ra, rb, rc, fpfn, fn7, islit, real_islit;
uint8_t lit;
ExitStatus ret;
@@ -1681,11 +1683,12 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
palcode = insn & 0x03FFFFFF;
disp21 = ((int32_t)((insn & 0x001FFFFF) << 11)) >> 11;
disp16 = (int16_t)(insn & 0x0000FFFF);
+#ifndef CONFIG_USER_ONLY
disp12 = (int32_t)((insn & 0x00000FFF) << 20) >> 20;
+#endif
fn11 = (insn >> 5) & 0x000007FF;
fpfn = fn11 & 0x3F;
fn7 = (insn >> 5) & 0x0000007F;
- fn2 = (insn >> 5) & 0x00000003;
LOG_DISAS("opc %02x ra %2d rb %2d rc %2d disp16 %6d\n",
opc, ra, rb, rc, disp16);
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 01f5b57fbc..116131eef8 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -512,4 +512,17 @@ static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
}
}
+static inline bool cpu_has_work(CPUState *env)
+{
+ return env->interrupt_request &
+ (CPU_INTERRUPT_FIQ | CPU_INTERRUPT_HARD | CPU_INTERRUPT_EXITTB);
+}
+
+#include "exec-all.h"
+
+static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
+{
+ env->regs[15] = tb->pc;
+}
+
#endif
diff --git a/target-arm/exec.h b/target-arm/exec.h
index db6608ec8b..6793288d43 100644
--- a/target-arm/exec.h
+++ b/target-arm/exec.h
@@ -22,22 +22,9 @@
register struct CPUARMState *env asm(AREG0);
#include "cpu.h"
-#include "exec-all.h"
-
-static inline int cpu_has_work(CPUState *env)
-{
- return (env->interrupt_request &
- (CPU_INTERRUPT_FIQ | CPU_INTERRUPT_HARD | CPU_INTERRUPT_EXITTB));
-}
#if !defined(CONFIG_USER_ONLY)
#include "softmmu_exec.h"
#endif
void raise_exception(int);
-
-static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
-{
- env->regs[15] = tb->pc;
-}
-
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 12084167d6..f4d12aab55 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -3,7 +3,6 @@
#include <string.h>
#include "cpu.h"
-#include "exec-all.h"
#include "gdbstub.h"
#include "helper.h"
#include "qemu-common.h"
diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c
index 8334fbcf6d..46358844c5 100644
--- a/target-arm/op_helper.c
+++ b/target-arm/op_helper.c
@@ -25,7 +25,7 @@
void raise_exception(int tt)
{
env->exception_index = tt;
- cpu_loop_exit();
+ cpu_loop_exit(env);
}
uint32_t HELPER(neon_tbl)(uint32_t ireg, uint32_t def,
@@ -234,13 +234,13 @@ void HELPER(wfi)(void)
{
env->exception_index = EXCP_HLT;
env->halted = 1;
- cpu_loop_exit();
+ cpu_loop_exit(env);
}
void HELPER(exception)(uint32_t excp)
{
env->exception_index = excp;
- cpu_loop_exit();
+ cpu_loop_exit(env);
}
uint32_t HELPER(cpsr_read)(void)
diff --git a/target-arm/translate.c b/target-arm/translate.c
index f5507ec3b6..badbc5ff31 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -25,7 +25,6 @@
#include <inttypes.h>
#include "cpu.h"
-#include "exec-all.h"
#include "disas.h"
#include "tcg-op.h"
#include "qemu-log.h"
diff --git a/target-cris/cpu.h b/target-cris/cpu.h
index 2bc35e4975..ecb0df1d33 100644
--- a/target-cris/cpu.h
+++ b/target-cris/cpu.h
@@ -268,4 +268,15 @@ static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
#define cpu_list cris_cpu_list
void cris_cpu_list(FILE *f, fprintf_function cpu_fprintf);
+static inline bool cpu_has_work(CPUState *env)
+{
+ return env->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_NMI);
+}
+
+#include "exec-all.h"
+
+static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
+{
+ env->pc = tb->pc;
+}
#endif
diff --git a/target-cris/exec.h b/target-cris/exec.h
index 2d5d297e1b..3294abe393 100644
--- a/target-cris/exec.h
+++ b/target-cris/exec.h
@@ -22,19 +22,7 @@
register struct CPUCRISState *env asm(AREG0);
#include "cpu.h"
-#include "exec-all.h"
#if !defined(CONFIG_USER_ONLY)
#include "softmmu_exec.h"
#endif
-
-static inline int cpu_has_work(CPUState *env)
-{
- return (env->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_NMI));
-}
-
-static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
-{
- env->pc = tb->pc;
-}
-
diff --git a/target-cris/helper.c b/target-cris/helper.c
index 2a4403b847..962d214177 100644
--- a/target-cris/helper.c
+++ b/target-cris/helper.c
@@ -24,7 +24,6 @@
#include "config.h"
#include "cpu.h"
#include "mmu.h"
-#include "exec-all.h"
#include "host-utils.h"
diff --git a/target-cris/mmu.c b/target-cris/mmu.c
index 1243745598..d481e39352 100644
--- a/target-cris/mmu.c
+++ b/target-cris/mmu.c
@@ -27,7 +27,6 @@
#include "config.h"
#include "cpu.h"
#include "mmu.h"
-#include "exec-all.h"
#ifdef DEBUG
#define D(x) x
diff --git a/target-cris/op_helper.c b/target-cris/op_helper.c
index 34329e2a60..b3ddd33e02 100644
--- a/target-cris/op_helper.c
+++ b/target-cris/op_helper.c
@@ -83,7 +83,7 @@ void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
helper_top_evaluate_flags();
}
}
- cpu_loop_exit();
+ cpu_loop_exit(env);
}
env = saved_env;
}
@@ -93,7 +93,7 @@ void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
void helper_raise_exception(uint32_t index)
{
env->exception_index = index;
- cpu_loop_exit();
+ cpu_loop_exit(env);
}
void helper_tlb_flush_pid(uint32_t pid)
diff --git a/target-cris/translate.c b/target-cris/translate.c
index e2607d64c0..dd85859c0b 100644
--- a/target-cris/translate.c
+++ b/target-cris/translate.c
@@ -30,7 +30,6 @@
#include <inttypes.h>
#include "cpu.h"
-#include "exec-all.h"
#include "disas.h"
#include "tcg-op.h"
#include "helper.h"
diff --git a/target-cris/translate_v10.c b/target-cris/translate_v10.c
index 5b14157d1a..637ac2084a 100644
--- a/target-cris/translate_v10.c
+++ b/target-cris/translate_v10.c
@@ -262,9 +262,6 @@ static unsigned int dec10_quick_imm(DisasContext *dc)
break;
case CRISV10_QIMM_BCC_R0:
- if (!dc->ir) {
- cpu_abort(dc->env, "opcode zero\n");
- }
case CRISV10_QIMM_BCC_R1:
case CRISV10_QIMM_BCC_R2:
case CRISV10_QIMM_BCC_R3:
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index 9c3340da3f..9819b5fdb9 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -641,6 +641,10 @@ typedef struct CPUX86State {
uint16_t fpuc;
uint8_t fptags[8]; /* 0 = valid, 1 = empty */
FPReg fpregs[8];
+ /* KVM-only so far */
+ uint16_t fpop;
+ uint64_t fpip;
+ uint64_t fpdp;
/* emulator internal variables */
float_status fp_status;
@@ -953,6 +957,36 @@ static inline int cpu_mmu_index (CPUState *env)
return (env->hflags & HF_CPL_MASK) == 3 ? 1 : 0;
}
+#undef EAX
+#define EAX (env->regs[R_EAX])
+#undef ECX
+#define ECX (env->regs[R_ECX])
+#undef EDX
+#define EDX (env->regs[R_EDX])
+#undef EBX
+#define EBX (env->regs[R_EBX])
+#undef ESP
+#define ESP (env->regs[R_ESP])
+#undef EBP
+#define EBP (env->regs[R_EBP])
+#undef ESI
+#define ESI (env->regs[R_ESI])
+#undef EDI
+#define EDI (env->regs[R_EDI])
+#undef EIP
+#define EIP (env->eip)
+#define DF (env->df)
+
+#define CC_SRC (env->cc_src)
+#define CC_DST (env->cc_dst)
+#define CC_OP (env->cc_op)
+
+/* float macros */
+#define FT0 (env->ft0)
+#define ST0 (env->fpregs[env->fpstt].d)
+#define ST(n) (env->fpregs[(env->fpstt + (n)) & 7].d)
+#define ST1 ST(1)
+
/* translate.c */
void optimize_flags_init(void);
@@ -977,6 +1011,23 @@ static inline void cpu_clone_regs(CPUState *env, target_ulong newsp)
#include "hw/apic.h"
#endif
+static inline bool cpu_has_work(CPUState *env)
+{
+ return ((env->interrupt_request & CPU_INTERRUPT_HARD) &&
+ (env->eflags & IF_MASK)) ||
+ (env->interrupt_request & (CPU_INTERRUPT_NMI |
+ CPU_INTERRUPT_INIT |
+ CPU_INTERRUPT_SIPI |
+ CPU_INTERRUPT_MCE));
+}
+
+#include "exec-all.h"
+
+static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
+{
+ env->eip = tb->pc - tb->cs_base;
+}
+
static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
target_ulong *cs_base, int *flags)
{
@@ -996,4 +1047,14 @@ void cpu_x86_inject_mce(Monitor *mon, CPUState *cenv, int bank,
uint64_t status, uint64_t mcg_status, uint64_t addr,
uint64_t misc, int flags);
+/* op_helper.c */
+void do_interrupt(CPUState *env);
+void do_interrupt_x86_hardirq(CPUState *env, int intno, int is_hw);
+
+void do_smm_enter(CPUState *env1);
+
+void svm_check_intercept(CPUState *env1, uint32_t type);
+
+uint32_t cpu_cc_compute_all(CPUState *env1, int op);
+
#endif /* CPU_I386_H */
diff --git a/target-i386/cpuid.c b/target-i386/cpuid.c
index 79e7580c17..e1ae3af1e3 100644
--- a/target-i386/cpuid.c
+++ b/target-i386/cpuid.c
@@ -1144,10 +1144,12 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
break;
case 7:
if (kvm_enabled()) {
- *eax = kvm_arch_get_supported_cpuid(env, 0x7, count, R_EAX);
- *ebx = kvm_arch_get_supported_cpuid(env, 0x7, count, R_EBX);
- *ecx = kvm_arch_get_supported_cpuid(env, 0x7, count, R_ECX);
- *edx = kvm_arch_get_supported_cpuid(env, 0x7, count, R_EDX);
+ KVMState *s = env->kvm_state;
+
+ *eax = kvm_arch_get_supported_cpuid(s, 0x7, count, R_EAX);
+ *ebx = kvm_arch_get_supported_cpuid(s, 0x7, count, R_EBX);
+ *ecx = kvm_arch_get_supported_cpuid(s, 0x7, count, R_ECX);
+ *edx = kvm_arch_get_supported_cpuid(s, 0x7, count, R_EDX);
} else {
*eax = 0;
*ebx = 0;
@@ -1179,10 +1181,12 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
break;
}
if (kvm_enabled()) {
- *eax = kvm_arch_get_supported_cpuid(env, 0xd, count, R_EAX);
- *ebx = kvm_arch_get_supported_cpuid(env, 0xd, count, R_EBX);
- *ecx = kvm_arch_get_supported_cpuid(env, 0xd, count, R_ECX);
- *edx = kvm_arch_get_supported_cpuid(env, 0xd, count, R_EDX);
+ KVMState *s = env->kvm_state;
+
+ *eax = kvm_arch_get_supported_cpuid(s, 0xd, count, R_EAX);
+ *ebx = kvm_arch_get_supported_cpuid(s, 0xd, count, R_EBX);
+ *ecx = kvm_arch_get_supported_cpuid(s, 0xd, count, R_ECX);
+ *edx = kvm_arch_get_supported_cpuid(s, 0xd, count, R_EDX);
} else {
*eax = 0;
*ebx = 0;
diff --git a/target-i386/exec.h b/target-i386/exec.h
index 9bd080e3a8..dd9bce4eed 100644
--- a/target-i386/exec.h
+++ b/target-i386/exec.h
@@ -33,48 +33,12 @@ register struct CPUX86State *env asm(AREG0);
#include "qemu-common.h"
#include "qemu-log.h"
-#undef EAX
-#define EAX (env->regs[R_EAX])
-#undef ECX
-#define ECX (env->regs[R_ECX])
-#undef EDX
-#define EDX (env->regs[R_EDX])
-#undef EBX
-#define EBX (env->regs[R_EBX])
-#undef ESP
-#define ESP (env->regs[R_ESP])
-#undef EBP
-#define EBP (env->regs[R_EBP])
-#undef ESI
-#define ESI (env->regs[R_ESI])
-#undef EDI
-#define EDI (env->regs[R_EDI])
-#undef EIP
-#define EIP (env->eip)
-#define DF (env->df)
-
-#define CC_SRC (env->cc_src)
-#define CC_DST (env->cc_dst)
-#define CC_OP (env->cc_op)
-
-/* float macros */
-#define FT0 (env->ft0)
-#define ST0 (env->fpregs[env->fpstt].d)
-#define ST(n) (env->fpregs[(env->fpstt + (n)) & 7].d)
-#define ST1 ST(1)
-
#include "cpu.h"
-#include "exec-all.h"
/* op_helper.c */
-void do_interrupt(int intno, int is_int, int error_code,
- target_ulong next_eip, int is_hw);
-void do_interrupt_user(int intno, int is_int, int error_code,
- target_ulong next_eip);
void QEMU_NORETURN raise_exception_err(int exception_index, int error_code);
void QEMU_NORETURN raise_exception(int exception_index);
void QEMU_NORETURN raise_exception_env(int exception_index, CPUState *nenv);
-void do_smm_enter(void);
/* n must be a constant to be efficient */
static inline target_long lshift(target_long x, int n)
@@ -87,11 +51,6 @@ static inline target_long lshift(target_long x, int n)
#include "helper.h"
-static inline void svm_check_intercept(uint32_t type)
-{
- helper_svm_check_intercept_param(type, 0);
-}
-
#if !defined(CONFIG_USER_ONLY)
#include "softmmu_exec.h"
@@ -170,16 +129,6 @@ static inline void load_eflags(int eflags, int update_mask)
(eflags & update_mask) | 0x2;
}
-static inline int cpu_has_work(CPUState *env)
-{
- return ((env->interrupt_request & CPU_INTERRUPT_HARD) &&
- (env->eflags & IF_MASK)) ||
- (env->interrupt_request & (CPU_INTERRUPT_NMI |
- CPU_INTERRUPT_INIT |
- CPU_INTERRUPT_SIPI |
- CPU_INTERRUPT_MCE));
-}
-
/* load efer and update the corresponding hflags. XXX: do consistency
checks with cpuid bits ? */
static inline void cpu_load_efer(CPUState *env, uint64_t val)
@@ -191,9 +140,3 @@ static inline void cpu_load_efer(CPUState *env, uint64_t val)
if (env->efer & MSR_EFER_SVME)
env->hflags |= HF_SVME_MASK;
}
-
-static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
-{
- env->eip = tb->pc - tb->cs_base;
-}
-
diff --git a/target-i386/helper.c b/target-i386/helper.c
index 509d68ca0f..e9be104293 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -23,7 +23,6 @@
#include <inttypes.h>
#include "cpu.h"
-#include "exec-all.h"
#include "qemu-common.h"
#include "kvm.h"
#ifndef CONFIG_USER_ONLY
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 1ae2d61740..10fb2c4b07 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -18,6 +18,7 @@
#include <sys/utsname.h>
#include <linux/kvm.h>
+#include <linux/kvm_para.h>
#include "qemu-common.h"
#include "sysemu.h"
@@ -29,10 +30,6 @@
#include "hw/apic.h"
#include "ioport.h"
-#ifdef CONFIG_KVM_PARA
-#include <linux/kvm_para.h>
-#endif
-//
//#define DEBUG_KVM
#ifdef DEBUG_KVM
@@ -62,9 +59,7 @@ const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
static bool has_msr_star;
static bool has_msr_hsave_pa;
-#if defined(CONFIG_KVM_PARA) && defined(KVM_CAP_ASYNC_PF)
static bool has_msr_async_pf_en;
-#endif
static int lm_capable_kernel;
static struct kvm_cpuid2 *try_get_cpuid(KVMState *s, int max)
@@ -92,7 +87,6 @@ static struct kvm_cpuid2 *try_get_cpuid(KVMState *s, int max)
return cpuid;
}
-#ifdef CONFIG_KVM_PARA
struct kvm_para_features {
int cap;
int feature;
@@ -100,51 +94,44 @@ struct kvm_para_features {
{ KVM_CAP_CLOCKSOURCE, KVM_FEATURE_CLOCKSOURCE },
{ KVM_CAP_NOP_IO_DELAY, KVM_FEATURE_NOP_IO_DELAY },
{ KVM_CAP_PV_MMU, KVM_FEATURE_MMU_OP },
-#ifdef KVM_CAP_ASYNC_PF
{ KVM_CAP_ASYNC_PF, KVM_FEATURE_ASYNC_PF },
-#endif
{ -1, -1 }
};
-static int get_para_features(CPUState *env)
+static int get_para_features(KVMState *s)
{
int i, features = 0;
for (i = 0; i < ARRAY_SIZE(para_features) - 1; i++) {
- if (kvm_check_extension(env->kvm_state, para_features[i].cap)) {
+ if (kvm_check_extension(s, para_features[i].cap)) {
features |= (1 << para_features[i].feature);
}
}
return features;
}
-#endif
-uint32_t kvm_arch_get_supported_cpuid(CPUState *env, uint32_t function,
+uint32_t kvm_arch_get_supported_cpuid(KVMState *s, uint32_t function,
uint32_t index, int reg)
{
struct kvm_cpuid2 *cpuid;
int i, max;
uint32_t ret = 0;
uint32_t cpuid_1_edx;
-#ifdef CONFIG_KVM_PARA
int has_kvm_features = 0;
-#endif
max = 1;
- while ((cpuid = try_get_cpuid(env->kvm_state, max)) == NULL) {
+ while ((cpuid = try_get_cpuid(s, max)) == NULL) {
max *= 2;
}
for (i = 0; i < cpuid->nent; ++i) {
if (cpuid->entries[i].function == function &&
cpuid->entries[i].index == index) {
-#ifdef CONFIG_KVM_PARA
if (cpuid->entries[i].function == KVM_CPUID_FEATURES) {
has_kvm_features = 1;
}
-#endif
switch (reg) {
case R_EAX:
ret = cpuid->entries[i].eax;
@@ -166,7 +153,7 @@ uint32_t kvm_arch_get_supported_cpuid(CPUState *env, uint32_t function,
/* On Intel, kvm returns cpuid according to the Intel spec,
* so add missing bits according to the AMD spec:
*/
- cpuid_1_edx = kvm_arch_get_supported_cpuid(env, 1, 0, R_EDX);
+ cpuid_1_edx = kvm_arch_get_supported_cpuid(s, 1, 0, R_EDX);
ret |= cpuid_1_edx & 0x183f7ff;
break;
}
@@ -177,12 +164,10 @@ uint32_t kvm_arch_get_supported_cpuid(CPUState *env, uint32_t function,
qemu_free(cpuid);
-#ifdef CONFIG_KVM_PARA
/* fallback for older kernels */
if (!has_kvm_features && (function == KVM_CPUID_FEATURES)) {
- ret = get_para_features(env);
+ ret = get_para_features(s);
}
-#endif
return ret;
}
@@ -206,7 +191,6 @@ static void kvm_unpoison_all(void *param)
}
}
-#ifdef KVM_CAP_MCE
static void kvm_hwpoison_page_add(ram_addr_t ram_addr)
{
HWPoisonPage *page;
@@ -252,7 +236,6 @@ static void kvm_mce_inject(CPUState *env, target_phys_addr_t paddr, int code)
cpu_x86_support_mca_broadcast(env) ?
MCE_INJECT_BROADCAST : 0);
}
-#endif /* KVM_CAP_MCE */
static void hardware_memory_error(void)
{
@@ -262,7 +245,6 @@ static void hardware_memory_error(void)
int kvm_arch_on_sigbus_vcpu(CPUState *env, int code, void *addr)
{
-#ifdef KVM_CAP_MCE
ram_addr_t ram_addr;
target_phys_addr_t paddr;
@@ -282,9 +264,7 @@ int kvm_arch_on_sigbus_vcpu(CPUState *env, int code, void *addr)
}
kvm_hwpoison_page_add(ram_addr);
kvm_mce_inject(env, paddr, code);
- } else
-#endif /* KVM_CAP_MCE */
- {
+ } else {
if (code == BUS_MCEERR_AO) {
return 0;
} else if (code == BUS_MCEERR_AR) {
@@ -298,7 +278,6 @@ int kvm_arch_on_sigbus_vcpu(CPUState *env, int code, void *addr)
int kvm_arch_on_sigbus(int code, void *addr)
{
-#ifdef KVM_CAP_MCE
if ((first_cpu->mcg_cap & MCG_SER_P) && addr && code == BUS_MCEERR_AO) {
ram_addr_t ram_addr;
target_phys_addr_t paddr;
@@ -313,9 +292,7 @@ int kvm_arch_on_sigbus(int code, void *addr)
}
kvm_hwpoison_page_add(ram_addr);
kvm_mce_inject(first_cpu, paddr, code);
- } else
-#endif /* KVM_CAP_MCE */
- {
+ } else {
if (code == BUS_MCEERR_AO) {
return 0;
} else if (code == BUS_MCEERR_AR) {
@@ -329,7 +306,6 @@ int kvm_arch_on_sigbus(int code, void *addr)
static int kvm_inject_mce_oldstyle(CPUState *env)
{
-#ifdef KVM_CAP_MCE
if (!kvm_has_vcpu_events() && env->exception_injected == EXCP12_MCHK) {
unsigned int bank, bank_num = env->mcg_cap & 0xff;
struct kvm_x86_mce mce;
@@ -355,7 +331,6 @@ static int kvm_inject_mce_oldstyle(CPUState *env)
return kvm_vcpu_ioctl(env, KVM_X86_SET_MCE, &mce);
}
-#endif /* KVM_CAP_MCE */
return 0;
}
@@ -374,30 +349,27 @@ int kvm_arch_init_vcpu(CPUState *env)
struct kvm_cpuid2 cpuid;
struct kvm_cpuid_entry2 entries[100];
} __attribute__((packed)) cpuid_data;
+ KVMState *s = env->kvm_state;
uint32_t limit, i, j, cpuid_i;
uint32_t unused;
struct kvm_cpuid_entry2 *c;
-#ifdef CONFIG_KVM_PARA
uint32_t signature[3];
-#endif
- env->cpuid_features &= kvm_arch_get_supported_cpuid(env, 1, 0, R_EDX);
+ env->cpuid_features &= kvm_arch_get_supported_cpuid(s, 1, 0, R_EDX);
i = env->cpuid_ext_features & CPUID_EXT_HYPERVISOR;
- env->cpuid_ext_features &= kvm_arch_get_supported_cpuid(env, 1, 0, R_ECX);
+ env->cpuid_ext_features &= kvm_arch_get_supported_cpuid(s, 1, 0, R_ECX);
env->cpuid_ext_features |= i;
- env->cpuid_ext2_features &= kvm_arch_get_supported_cpuid(env, 0x80000001,
+ env->cpuid_ext2_features &= kvm_arch_get_supported_cpuid(s, 0x80000001,
0, R_EDX);
- env->cpuid_ext3_features &= kvm_arch_get_supported_cpuid(env, 0x80000001,
+ env->cpuid_ext3_features &= kvm_arch_get_supported_cpuid(s, 0x80000001,
0, R_ECX);
- env->cpuid_svm_features &= kvm_arch_get_supported_cpuid(env, 0x8000000A,
+ env->cpuid_svm_features &= kvm_arch_get_supported_cpuid(s, 0x8000000A,
0, R_EDX);
-
cpuid_i = 0;
-#ifdef CONFIG_KVM_PARA
/* Paravirtualization CPUIDs */
memcpy(signature, "KVMKVMKVM\0\0\0", 12);
c = &cpuid_data.entries[cpuid_i++];
@@ -411,14 +383,10 @@ int kvm_arch_init_vcpu(CPUState *env)
c = &cpuid_data.entries[cpuid_i++];
memset(c, 0, sizeof(*c));
c->function = KVM_CPUID_FEATURES;
- c->eax = env->cpuid_kvm_features & kvm_arch_get_supported_cpuid(env,
- KVM_CPUID_FEATURES, 0, R_EAX);
+ c->eax = env->cpuid_kvm_features &
+ kvm_arch_get_supported_cpuid(s, KVM_CPUID_FEATURES, 0, R_EAX);
-#ifdef KVM_CAP_ASYNC_PF
has_msr_async_pf_en = c->eax & (1 << KVM_FEATURE_ASYNC_PF);
-#endif
-
-#endif
cpu_x86_cpuid(env, 0, 0, &limit, &unused, &unused, &unused);
@@ -448,6 +416,9 @@ int kvm_arch_init_vcpu(CPUState *env)
case 0xb:
case 0xd:
for (j = 0; ; j++) {
+ if (i == 0xd && j == 64) {
+ break;
+ }
c->function = i;
c->flags = KVM_CPUID_FLAG_SIGNIFCANT_INDEX;
c->index = j;
@@ -460,7 +431,7 @@ int kvm_arch_init_vcpu(CPUState *env)
break;
}
if (i == 0xd && c->eax == 0) {
- break;
+ continue;
}
c = &cpuid_data.entries[cpuid_i++];
}
@@ -485,7 +456,7 @@ int kvm_arch_init_vcpu(CPUState *env)
/* Call Centaur's CPUID instructions they are supported. */
if (env->cpuid_xlevel2 > 0) {
env->cpuid_ext4_features &=
- kvm_arch_get_supported_cpuid(env, 0xC0000001, 0, R_EDX);
+ kvm_arch_get_supported_cpuid(s, 0xC0000001, 0, R_EDX);
cpu_x86_cpuid(env, 0xC0000000, 0, &limit, &unused, &unused, &unused);
for (i = 0xC0000000; i <= limit; i++) {
@@ -499,7 +470,6 @@ int kvm_arch_init_vcpu(CPUState *env)
cpuid_data.cpuid.nent = cpuid_i;
-#ifdef KVM_CAP_MCE
if (((env->cpuid_version >> 8)&0xF) >= 6
&& (env->cpuid_features&(CPUID_MCE|CPUID_MCA)) == (CPUID_MCE|CPUID_MCA)
&& kvm_check_extension(env->kvm_state, KVM_CAP_MCE) > 0) {
@@ -526,7 +496,6 @@ int kvm_arch_init_vcpu(CPUState *env)
env->mcg_cap = mcg_cap;
}
-#endif
qemu_add_vm_change_state_handler(cpu_update_state, env);
@@ -618,7 +587,6 @@ int kvm_arch_init(KVMState *s)
* that case we need to stick with the default, i.e. a 256K maximum BIOS
* size.
*/
-#ifdef KVM_CAP_SET_IDENTITY_MAP_ADDR
if (kvm_check_extension(s, KVM_CAP_SET_IDENTITY_MAP_ADDR)) {
/* Allows up to 16M BIOSes. */
identity_base = 0xfeffc000;
@@ -628,7 +596,7 @@ int kvm_arch_init(KVMState *s)
return ret;
}
}
-#endif
+
/* Set TSS base one page after EPT identity map. */
ret = kvm_vm_ioctl(s, KVM_SET_TSS_ADDR, identity_base + 0x1000);
if (ret < 0) {
@@ -753,6 +721,9 @@ static int kvm_put_fpu(CPUState *env)
fpu.fsw = env->fpus & ~(7 << 11);
fpu.fsw |= (env->fpstt & 7) << 11;
fpu.fcw = env->fpuc;
+ fpu.last_opcode = env->fpop;
+ fpu.last_ip = env->fpip;
+ fpu.last_dp = env->fpdp;
for (i = 0; i < 8; ++i) {
fpu.ftwx |= (!env->fptags[i]) << i;
}
@@ -763,7 +734,6 @@ static int kvm_put_fpu(CPUState *env)
return kvm_vcpu_ioctl(env, KVM_SET_FPU, &fpu);
}
-#ifdef KVM_CAP_XSAVE
#define XSAVE_CWD_RIP 2
#define XSAVE_CWD_RDP 4
#define XSAVE_MXCSR 6
@@ -771,14 +741,12 @@ static int kvm_put_fpu(CPUState *env)
#define XSAVE_XMM_SPACE 40
#define XSAVE_XSTATE_BV 128
#define XSAVE_YMMH_SPACE 144
-#endif
static int kvm_put_xsave(CPUState *env)
{
-#ifdef KVM_CAP_XSAVE
int i, r;
struct kvm_xsave* xsave;
- uint16_t cwd, swd, twd, fop;
+ uint16_t cwd, swd, twd;
if (!kvm_has_xsave()) {
return kvm_put_fpu(env);
@@ -786,7 +754,7 @@ static int kvm_put_xsave(CPUState *env)
xsave = qemu_memalign(4096, sizeof(struct kvm_xsave));
memset(xsave, 0, sizeof(struct kvm_xsave));
- cwd = swd = twd = fop = 0;
+ cwd = swd = twd = 0;
swd = env->fpus & ~(7 << 11);
swd |= (env->fpstt & 7) << 11;
cwd = env->fpuc;
@@ -794,7 +762,9 @@ static int kvm_put_xsave(CPUState *env)
twd |= (!env->fptags[i]) << i;
}
xsave->region[0] = (uint32_t)(swd << 16) + cwd;
- xsave->region[1] = (uint32_t)(fop << 16) + twd;
+ xsave->region[1] = (uint32_t)(env->fpop << 16) + twd;
+ memcpy(&xsave->region[XSAVE_CWD_RIP], &env->fpip, sizeof(env->fpip));
+ memcpy(&xsave->region[XSAVE_CWD_RDP], &env->fpdp, sizeof(env->fpdp));
memcpy(&xsave->region[XSAVE_ST_SPACE], env->fpregs,
sizeof env->fpregs);
memcpy(&xsave->region[XSAVE_XMM_SPACE], env->xmm_regs,
@@ -806,14 +776,10 @@ static int kvm_put_xsave(CPUState *env)
r = kvm_vcpu_ioctl(env, KVM_SET_XSAVE, xsave);
qemu_free(xsave);
return r;
-#else
- return kvm_put_fpu(env);
-#endif
}
static int kvm_put_xcrs(CPUState *env)
{
-#ifdef KVM_CAP_XCRS
struct kvm_xcrs xcrs;
if (!kvm_has_xcrs()) {
@@ -825,9 +791,6 @@ static int kvm_put_xcrs(CPUState *env)
xcrs.xcrs[0].xcr = 0;
xcrs.xcrs[0].value = env->xcr0;
return kvm_vcpu_ioctl(env, KVM_SET_XCRS, &xcrs);
-#else
- return 0;
-#endif
}
static int kvm_put_sregs(CPUState *env)
@@ -931,14 +894,11 @@ static int kvm_put_msrs(CPUState *env, int level)
kvm_msr_entry_set(&msrs[n++], MSR_KVM_SYSTEM_TIME,
env->system_time_msr);
kvm_msr_entry_set(&msrs[n++], MSR_KVM_WALL_CLOCK, env->wall_clock_msr);
-#if defined(CONFIG_KVM_PARA) && defined(KVM_CAP_ASYNC_PF)
if (has_msr_async_pf_en) {
kvm_msr_entry_set(&msrs[n++], MSR_KVM_ASYNC_PF_EN,
env->async_pf_en_msr);
}
-#endif
}
-#ifdef KVM_CAP_MCE
if (env->mcg_cap) {
int i;
@@ -948,7 +908,6 @@ static int kvm_put_msrs(CPUState *env, int level)
kvm_msr_entry_set(&msrs[n++], MSR_MC0_CTL + i, env->mce_banks[i]);
}
}
-#endif
msr_data.info.nmsrs = n;
@@ -970,6 +929,9 @@ static int kvm_get_fpu(CPUState *env)
env->fpstt = (fpu.fsw >> 11) & 7;
env->fpus = fpu.fsw;
env->fpuc = fpu.fcw;
+ env->fpop = fpu.last_opcode;
+ env->fpip = fpu.last_ip;
+ env->fpdp = fpu.last_dp;
for (i = 0; i < 8; ++i) {
env->fptags[i] = !((fpu.ftwx >> i) & 1);
}
@@ -982,10 +944,9 @@ static int kvm_get_fpu(CPUState *env)
static int kvm_get_xsave(CPUState *env)
{
-#ifdef KVM_CAP_XSAVE
struct kvm_xsave* xsave;
int ret, i;
- uint16_t cwd, swd, twd, fop;
+ uint16_t cwd, swd, twd;
if (!kvm_has_xsave()) {
return kvm_get_fpu(env);
@@ -1001,13 +962,15 @@ static int kvm_get_xsave(CPUState *env)
cwd = (uint16_t)xsave->region[0];
swd = (uint16_t)(xsave->region[0] >> 16);
twd = (uint16_t)xsave->region[1];
- fop = (uint16_t)(xsave->region[1] >> 16);
+ env->fpop = (uint16_t)(xsave->region[1] >> 16);
env->fpstt = (swd >> 11) & 7;
env->fpus = swd;
env->fpuc = cwd;
for (i = 0; i < 8; ++i) {
env->fptags[i] = !((twd >> i) & 1);
}
+ memcpy(&env->fpip, &xsave->region[XSAVE_CWD_RIP], sizeof(env->fpip));
+ memcpy(&env->fpdp, &xsave->region[XSAVE_CWD_RDP], sizeof(env->fpdp));
env->mxcsr = xsave->region[XSAVE_MXCSR];
memcpy(env->fpregs, &xsave->region[XSAVE_ST_SPACE],
sizeof env->fpregs);
@@ -1018,14 +981,10 @@ static int kvm_get_xsave(CPUState *env)
sizeof env->ymmh_regs);
qemu_free(xsave);
return 0;
-#else
- return kvm_get_fpu(env);
-#endif
}
static int kvm_get_xcrs(CPUState *env)
{
-#ifdef KVM_CAP_XCRS
int i, ret;
struct kvm_xcrs xcrs;
@@ -1046,9 +1005,6 @@ static int kvm_get_xcrs(CPUState *env)
}
}
return 0;
-#else
- return 0;
-#endif
}
static int kvm_get_sregs(CPUState *env)
@@ -1172,13 +1128,10 @@ static int kvm_get_msrs(CPUState *env)
#endif
msrs[n++].index = MSR_KVM_SYSTEM_TIME;
msrs[n++].index = MSR_KVM_WALL_CLOCK;
-#if defined(CONFIG_KVM_PARA) && defined(KVM_CAP_ASYNC_PF)
if (has_msr_async_pf_en) {
msrs[n++].index = MSR_KVM_ASYNC_PF_EN;
}
-#endif
-#ifdef KVM_CAP_MCE
if (env->mcg_cap) {
msrs[n++].index = MSR_MCG_STATUS;
msrs[n++].index = MSR_MCG_CTL;
@@ -1186,7 +1139,6 @@ static int kvm_get_msrs(CPUState *env)
msrs[n++].index = MSR_MC0_CTL + i;
}
}
-#endif
msr_data.info.nmsrs = n;
ret = kvm_vcpu_ioctl(env, KVM_GET_MSRS, &msr_data);
@@ -1237,27 +1189,21 @@ static int kvm_get_msrs(CPUState *env)
case MSR_KVM_WALL_CLOCK:
env->wall_clock_msr = msrs[i].data;
break;
-#ifdef KVM_CAP_MCE
case MSR_MCG_STATUS:
env->mcg_status = msrs[i].data;
break;
case MSR_MCG_CTL:
env->mcg_ctl = msrs[i].data;
break;
-#endif
default:
-#ifdef KVM_CAP_MCE
if (msrs[i].index >= MSR_MC0_CTL &&
msrs[i].index < MSR_MC0_CTL + (env->mcg_cap & 0xff) * 4) {
env->mce_banks[msrs[i].index - MSR_MC0_CTL] = msrs[i].data;
}
-#endif
break;
-#if defined(CONFIG_KVM_PARA) && defined(KVM_CAP_ASYNC_PF)
case MSR_KVM_ASYNC_PF_EN:
env->async_pf_en_msr = msrs[i].data;
break;
-#endif
}
}
@@ -1289,7 +1235,6 @@ static int kvm_get_mp_state(CPUState *env)
static int kvm_put_vcpu_events(CPUState *env, int level)
{
-#ifdef KVM_CAP_VCPU_EVENTS
struct kvm_vcpu_events events;
if (!kvm_has_vcpu_events()) {
@@ -1318,14 +1263,10 @@ static int kvm_put_vcpu_events(CPUState *env, int level)
}
return kvm_vcpu_ioctl(env, KVM_SET_VCPU_EVENTS, &events);
-#else
- return 0;
-#endif
}
static int kvm_get_vcpu_events(CPUState *env)
{
-#ifdef KVM_CAP_VCPU_EVENTS
struct kvm_vcpu_events events;
int ret;
@@ -1355,7 +1296,6 @@ static int kvm_get_vcpu_events(CPUState *env)
}
env->sipi_vector = events.sipi_vector;
-#endif
return 0;
}
@@ -1363,7 +1303,6 @@ static int kvm_get_vcpu_events(CPUState *env)
static int kvm_guest_debug_workarounds(CPUState *env)
{
int ret = 0;
-#ifdef KVM_CAP_SET_GUEST_DEBUG
unsigned long reinject_trap = 0;
if (!kvm_has_vcpu_events()) {
@@ -1387,13 +1326,11 @@ static int kvm_guest_debug_workarounds(CPUState *env)
(!kvm_has_robust_singlestep() && env->singlestep_enabled)) {
ret = kvm_update_guest_debug(env, reinject_trap);
}
-#endif /* KVM_CAP_SET_GUEST_DEBUG */
return ret;
}
static int kvm_put_debugregs(CPUState *env)
{
-#ifdef KVM_CAP_DEBUGREGS
struct kvm_debugregs dbgregs;
int i;
@@ -1409,14 +1346,10 @@ static int kvm_put_debugregs(CPUState *env)
dbgregs.flags = 0;
return kvm_vcpu_ioctl(env, KVM_SET_DEBUGREGS, &dbgregs);
-#else
- return 0;
-#endif
}
static int kvm_get_debugregs(CPUState *env)
{
-#ifdef KVM_CAP_DEBUGREGS
struct kvm_debugregs dbgregs;
int i, ret;
@@ -1433,7 +1366,6 @@ static int kvm_get_debugregs(CPUState *env)
}
env->dr[4] = env->dr[6] = dbgregs.dr6;
env->dr[5] = env->dr[7] = dbgregs.dr7;
-#endif
return 0;
}
@@ -1659,7 +1591,6 @@ static int kvm_handle_halt(CPUState *env)
return 0;
}
-#ifdef KVM_CAP_SET_GUEST_DEBUG
int kvm_arch_insert_sw_breakpoint(CPUState *env, struct kvm_sw_breakpoint *bp)
{
static const uint8_t int3 = 0xcc;
@@ -1840,7 +1771,6 @@ void kvm_arch_update_guest_debug(CPUState *env, struct kvm_guest_debug *dbg)
}
}
}
-#endif /* KVM_CAP_SET_GUEST_DEBUG */
static bool host_supports_vmx(void)
{
@@ -1887,12 +1817,10 @@ int kvm_arch_handle_exit(CPUState *env, struct kvm_run *run)
run->ex.exception, run->ex.error_code);
ret = -1;
break;
-#ifdef KVM_CAP_SET_GUEST_DEBUG
case KVM_EXIT_DEBUG:
DPRINTF("kvm_exit_debug\n");
ret = kvm_handle_debug(&run->debug.arch);
break;
-#endif /* KVM_CAP_SET_GUEST_DEBUG */
default:
fprintf(stderr, "KVM: unknown exit reason %d\n", run->exit_reason);
ret = -1;
diff --git a/target-i386/machine.c b/target-i386/machine.c
index bbeae8852c..9aca8e0523 100644
--- a/target-i386/machine.c
+++ b/target-i386/machine.c
@@ -3,7 +3,7 @@
#include "hw/pc.h"
#include "hw/isa.h"
-#include "exec-all.h"
+#include "cpu.h"
#include "kvm.h"
static const VMStateDescription vmstate_segment = {
@@ -290,6 +290,26 @@ static const VMStateDescription vmstate_async_pf_msr = {
}
};
+static bool fpop_ip_dp_needed(void *opaque)
+{
+ CPUState *env = opaque;
+
+ return env->fpop != 0 || env->fpip != 0 || env->fpdp != 0;
+}
+
+static const VMStateDescription vmstate_fpop_ip_dp = {
+ .name = "cpu/fpop_ip_dp",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField []) {
+ VMSTATE_UINT16(fpop, CPUState),
+ VMSTATE_UINT64(fpip, CPUState),
+ VMSTATE_UINT64(fpdp, CPUState),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
static const VMStateDescription vmstate_cpu = {
.name = "cpu",
.version_id = CPU_SAVE_VERSION,
@@ -398,6 +418,9 @@ static const VMStateDescription vmstate_cpu = {
.vmsd = &vmstate_async_pf_msr,
.needed = async_pf_msr_needed,
} , {
+ .vmsd = &vmstate_fpop_ip_dp,
+ .needed = fpop_ip_dp_needed,
+ } , {
/* empty */
}
}
diff --git a/target-i386/op_helper.c b/target-i386/op_helper.c
index cec0c7686f..315e18b9a4 100644
--- a/target-i386/op_helper.c
+++ b/target-i386/op_helper.c
@@ -19,7 +19,6 @@
#include <math.h>
#include "exec.h"
-#include "exec-all.h"
#include "host-utils.h"
#include "ioport.h"
@@ -1000,7 +999,7 @@ void helper_syscall(int next_eip_addend)
{
env->exception_index = EXCP_SYSCALL;
env->exception_next_eip = env->eip + next_eip_addend;
- cpu_loop_exit();
+ cpu_loop_exit(env);
}
#else
void helper_syscall(int next_eip_addend)
@@ -1150,9 +1149,10 @@ static void do_interrupt_real(int intno, int is_int, int error_code,
env->eflags &= ~(IF_MASK | TF_MASK | AC_MASK | RF_MASK);
}
+#if defined(CONFIG_USER_ONLY)
/* fake user mode interrupt */
-void do_interrupt_user(int intno, int is_int, int error_code,
- target_ulong next_eip)
+static void do_interrupt_user(int intno, int is_int, int error_code,
+ target_ulong next_eip)
{
SegmentCache *dt;
target_ulong ptr;
@@ -1181,7 +1181,8 @@ void do_interrupt_user(int intno, int is_int, int error_code,
EIP = next_eip;
}
-#if !defined(CONFIG_USER_ONLY)
+#else
+
static void handle_even_inj(int intno, int is_int, int error_code,
int is_hw, int rm)
{
@@ -1207,8 +1208,8 @@ static void handle_even_inj(int intno, int is_int, int error_code,
* the int instruction. next_eip is the EIP value AFTER the interrupt
* instruction. It is only relevant if is_int is TRUE.
*/
-void do_interrupt(int intno, int is_int, int error_code,
- target_ulong next_eip, int is_hw)
+static void do_interrupt_all(int intno, int is_int, int error_code,
+ target_ulong next_eip, int is_hw)
{
if (qemu_loglevel_mask(CPU_LOG_INT)) {
if ((env->cr[0] & CR0_PE_MASK)) {
@@ -1270,6 +1271,46 @@ void do_interrupt(int intno, int is_int, int error_code,
#endif
}
+void do_interrupt(CPUState *env1)
+{
+ CPUState *saved_env;
+
+ saved_env = env;
+ env = env1;
+#if defined(CONFIG_USER_ONLY)
+ /* if user mode only, we simulate a fake exception
+ which will be handled outside the cpu execution
+ loop */
+ do_interrupt_user(env->exception_index,
+ env->exception_is_int,
+ env->error_code,
+ env->exception_next_eip);
+ /* successfully delivered */
+ env->old_exception = -1;
+#else
+ /* simulate a real cpu exception. On i386, it can
+ trigger new exceptions, but we do not handle
+ double or triple faults yet. */
+ do_interrupt_all(env->exception_index,
+ env->exception_is_int,
+ env->error_code,
+ env->exception_next_eip, 0);
+ /* successfully delivered */
+ env->old_exception = -1;
+#endif
+ env = saved_env;
+}
+
+void do_interrupt_x86_hardirq(CPUState *env1, int intno, int is_hw)
+{
+ CPUState *saved_env;
+
+ saved_env = env;
+ env = env1;
+ do_interrupt_all(intno, 0, 0, 0, is_hw);
+ env = saved_env;
+}
+
/* This should come from sysemu.h - if we could include it here... */
void qemu_system_reset_request(void);
@@ -1335,7 +1376,7 @@ static void QEMU_NORETURN raise_interrupt(int intno, int is_int, int error_code,
env->error_code = error_code;
env->exception_is_int = is_int;
env->exception_next_eip = env->eip + next_eip_addend;
- cpu_loop_exit();
+ cpu_loop_exit(env);
}
/* shortcuts to generate exceptions */
@@ -1359,7 +1400,7 @@ void raise_exception_env(int exception_index, CPUState *nenv)
#if defined(CONFIG_USER_ONLY)
-void do_smm_enter(void)
+void do_smm_enter(CPUState *env1)
{
}
@@ -1375,11 +1416,15 @@ void helper_rsm(void)
#define SMM_REVISION_ID 0x00020000
#endif
-void do_smm_enter(void)
+void do_smm_enter(CPUState *env1)
{
target_ulong sm_state;
SegmentCache *dt;
int i, offset;
+ CPUState *saved_env;
+
+ saved_env = env;
+ env = env1;
qemu_log_mask(CPU_LOG_INT, "SMM: enter\n");
log_cpu_state_mask(CPU_LOG_INT, env, X86_DUMP_CCOP);
@@ -1506,6 +1551,7 @@ void do_smm_enter(void)
cpu_x86_update_cr4(env, 0);
env->dr[7] = 0x00000400;
CC_OP = CC_OP_EFLAGS;
+ env = saved_env;
}
void helper_rsm(void)
@@ -4658,7 +4704,7 @@ static void do_hlt(void)
env->hflags &= ~HF_INHIBIT_IRQ_MASK; /* needed if sti is just before */
env->halted = 1;
env->exception_index = EXCP_HLT;
- cpu_loop_exit();
+ cpu_loop_exit(env);
}
void helper_hlt(int next_eip_addend)
@@ -4696,7 +4742,7 @@ void helper_mwait(int next_eip_addend)
void helper_debug(void)
{
env->exception_index = EXCP_DEBUG;
- cpu_loop_exit();
+ cpu_loop_exit(env);
}
void helper_reset_rf(void)
@@ -4859,6 +4905,10 @@ void helper_svm_check_intercept_param(uint32_t type, uint64_t param)
{
}
+void svm_check_intercept(CPUState *env1, uint32_t type)
+{
+}
+
void helper_svm_check_io(uint32_t port, uint32_t param,
uint32_t next_eip_addend)
{
@@ -5040,7 +5090,7 @@ void helper_vmrun(int aflag, int next_eip_addend)
env->exception_next_eip = -1;
qemu_log_mask(CPU_LOG_TB_IN_ASM, "INTR");
/* XXX: is it always correct ? */
- do_interrupt(vector, 0, 0, 0, 1);
+ do_interrupt_all(vector, 0, 0, 0, 1);
break;
case SVM_EVTINJ_TYPE_NMI:
env->exception_index = EXCP02_NMI;
@@ -5048,7 +5098,7 @@ void helper_vmrun(int aflag, int next_eip_addend)
env->exception_is_int = 0;
env->exception_next_eip = EIP;
qemu_log_mask(CPU_LOG_TB_IN_ASM, "NMI");
- cpu_loop_exit();
+ cpu_loop_exit(env);
break;
case SVM_EVTINJ_TYPE_EXEPT:
env->exception_index = vector;
@@ -5056,7 +5106,7 @@ void helper_vmrun(int aflag, int next_eip_addend)
env->exception_is_int = 0;
env->exception_next_eip = -1;
qemu_log_mask(CPU_LOG_TB_IN_ASM, "EXEPT");
- cpu_loop_exit();
+ cpu_loop_exit(env);
break;
case SVM_EVTINJ_TYPE_SOFT:
env->exception_index = vector;
@@ -5064,7 +5114,7 @@ void helper_vmrun(int aflag, int next_eip_addend)
env->exception_is_int = 1;
env->exception_next_eip = EIP;
qemu_log_mask(CPU_LOG_TB_IN_ASM, "SOFT");
- cpu_loop_exit();
+ cpu_loop_exit(env);
break;
}
qemu_log_mask(CPU_LOG_TB_IN_ASM, " %#x %#x\n", env->exception_index, env->error_code);
@@ -5249,6 +5299,16 @@ void helper_svm_check_intercept_param(uint32_t type, uint64_t param)
}
}
+void svm_check_intercept(CPUState *env1, uint32_t type)
+{
+ CPUState *saved_env;
+
+ saved_env = env;
+ env = env1;
+ helper_svm_check_intercept_param(type, 0);
+ env = saved_env;
+}
+
void helper_svm_check_io(uint32_t port, uint32_t param,
uint32_t next_eip_addend)
{
@@ -5400,7 +5460,7 @@ void helper_vmexit(uint32_t exit_code, uint64_t exit_info_1)
env->error_code = 0;
env->old_exception = -1;
- cpu_loop_exit();
+ cpu_loop_exit(env);
}
#endif
@@ -5575,6 +5635,18 @@ uint32_t helper_cc_compute_all(int op)
}
}
+uint32_t cpu_cc_compute_all(CPUState *env1, int op)
+{
+ CPUState *saved_env;
+ uint32_t ret;
+
+ saved_env = env;
+ env = env1;
+ ret = helper_cc_compute_all(op);
+ env = saved_env;
+ return ret;
+}
+
uint32_t helper_cc_compute_c(int op)
{
switch (op) {
diff --git a/target-i386/translate.c b/target-i386/translate.c
index 10bd72a0e2..ccef381be8 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -24,7 +24,6 @@
#include <signal.h>
#include "cpu.h"
-#include "exec-all.h"
#include "disas.h"
#include "tcg-op.h"
diff --git a/target-lm32/cpu.h b/target-lm32/cpu.h
index 8e2d26b995..876b5be2bd 100644
--- a/target-lm32/cpu.h
+++ b/target-lm32/cpu.h
@@ -241,4 +241,17 @@ static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
*cs_base = 0;
*flags = 0;
}
+
+static inline bool cpu_has_work(CPUState *env)
+{
+ return env->interrupt_request & CPU_INTERRUPT_HARD;
+}
+
+#include "exec-all.h"
+
+static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
+{
+ env->pc = tb->pc;
+}
+
#endif
diff --git a/target-lm32/exec.h b/target-lm32/exec.h
index 348b723f29..2a227b2953 100644
--- a/target-lm32/exec.h
+++ b/target-lm32/exec.h
@@ -22,12 +22,6 @@
register struct CPULM32State *env asm(AREG0);
#include "cpu.h"
-#include "exec-all.h"
-
-static inline int cpu_has_work(CPUState *env)
-{
- return env->interrupt_request & CPU_INTERRUPT_HARD;
-}
static inline int cpu_halted(CPUState *env)
{
@@ -42,9 +36,3 @@ static inline int cpu_halted(CPUState *env)
}
return EXCP_HALTED;
}
-
-static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
-{
- env->pc = tb->pc;
-}
-
diff --git a/target-lm32/helper.c b/target-lm32/helper.c
index 4f3e7e0fcb..e79428d8e0 100644
--- a/target-lm32/helper.c
+++ b/target-lm32/helper.c
@@ -23,7 +23,6 @@
#include "config.h"
#include "cpu.h"
-#include "exec-all.h"
#include "host-utils.h"
int cpu_lm32_handle_mmu_fault(CPUState *env, target_ulong address, int rw,
diff --git a/target-lm32/op_helper.c b/target-lm32/op_helper.c
index c72b1df47b..a34cecd295 100644
--- a/target-lm32/op_helper.c
+++ b/target-lm32/op_helper.c
@@ -20,14 +20,14 @@
void helper_raise_exception(uint32_t index)
{
env->exception_index = index;
- cpu_loop_exit();
+ cpu_loop_exit(env);
}
void helper_hlt(void)
{
env->halted = 1;
env->exception_index = EXCP_HLT;
- cpu_loop_exit();
+ cpu_loop_exit(env);
}
void helper_wcsr_im(uint32_t im)
@@ -98,7 +98,7 @@ void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
cpu_restore_state(tb, env, pc);
}
}
- cpu_loop_exit();
+ cpu_loop_exit(env);
}
env = saved_env;
}
diff --git a/target-lm32/translate.c b/target-lm32/translate.c
index 5e197258eb..0be105d018 100644
--- a/target-lm32/translate.c
+++ b/target-lm32/translate.c
@@ -25,7 +25,6 @@
#include <assert.h>
#include "cpu.h"
-#include "exec-all.h"
#include "disas.h"
#include "helper.h"
#include "tcg-op.h"
diff --git a/target-m68k/cpu.h b/target-m68k/cpu.h
index b025b6689d..e0f9b32014 100644
--- a/target-m68k/cpu.h
+++ b/target-m68k/cpu.h
@@ -119,7 +119,8 @@ void m68k_tcg_init(void);
CPUM68KState *cpu_m68k_init(const char *cpu_model);
int cpu_m68k_exec(CPUM68KState *s);
void cpu_m68k_close(CPUM68KState *s);
-void do_interrupt(int is_hw);
+void do_interrupt(CPUState *env1);
+void do_interrupt_m68k_hardirq(CPUState *env1);
/* you can call this signal handler from your SIGBUS and SIGSEGV
signal handlers to inform the virtual CPU of exceptions. non zero
is returned if the signal was handled by the virtual CPU. */
@@ -254,4 +255,16 @@ static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
| ((env->macsr >> 4) & 0xf); /* Bits 0-3 */
}
+static inline bool cpu_has_work(CPUState *env)
+{
+ return env->interrupt_request & CPU_INTERRUPT_HARD;
+}
+
+#include "exec-all.h"
+
+static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
+{
+ env->pc = tb->pc;
+}
+
#endif
diff --git a/target-m68k/exec.h b/target-m68k/exec.h
index 91daa6bac4..93e7912148 100644
--- a/target-m68k/exec.h
+++ b/target-m68k/exec.h
@@ -22,19 +22,7 @@
register struct CPUM68KState *env asm(AREG0);
#include "cpu.h"
-#include "exec-all.h"
#if !defined(CONFIG_USER_ONLY)
#include "softmmu_exec.h"
#endif
-
-static inline int cpu_has_work(CPUState *env)
-{
- return (env->interrupt_request & (CPU_INTERRUPT_HARD));
-}
-
-static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
-{
- env->pc = tb->pc;
-}
-
diff --git a/target-m68k/helper.c b/target-m68k/helper.c
index faa8c42ae8..a936fe7b76 100644
--- a/target-m68k/helper.c
+++ b/target-m68k/helper.c
@@ -23,7 +23,6 @@
#include "config.h"
#include "cpu.h"
-#include "exec-all.h"
#include "qemu-common.h"
#include "gdbstub.h"
diff --git a/target-m68k/op_helper.c b/target-m68k/op_helper.c
index 9b13bdbcc2..237fc4cb54 100644
--- a/target-m68k/op_helper.c
+++ b/target-m68k/op_helper.c
@@ -21,9 +21,13 @@
#if defined(CONFIG_USER_ONLY)
-void do_interrupt(int is_hw)
+void do_interrupt(CPUState *env1)
+{
+ env1->exception_index = -1;
+}
+
+void do_interrupt_m68k_hardirq(CPUState *env1)
{
- env->exception_index = -1;
}
#else
@@ -71,7 +75,7 @@ void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
cpu_restore_state(tb, env, pc);
}
}
- cpu_loop_exit();
+ cpu_loop_exit(env);
}
env = saved_env;
}
@@ -90,7 +94,7 @@ static void do_rte(void)
env->aregs[7] = sp + 8;
}
-void do_interrupt(int is_hw)
+static void do_interrupt_all(int is_hw)
{
uint32_t sp;
uint32_t fmt;
@@ -118,7 +122,7 @@ void do_interrupt(int is_hw)
}
env->halted = 1;
env->exception_index = EXCP_HLT;
- cpu_loop_exit();
+ cpu_loop_exit(env);
return;
}
if (env->exception_index >= EXCP_TRAP0
@@ -155,12 +159,31 @@ void do_interrupt(int is_hw)
env->pc = ldl_kernel(env->vbr + vector);
}
+void do_interrupt(CPUState *env1)
+{
+ CPUState *saved_env;
+
+ saved_env = env;
+ env = env1;
+ do_interrupt_all(0);
+ env = saved_env;
+}
+
+void do_interrupt_m68k_hardirq(CPUState *env1)
+{
+ CPUState *saved_env;
+
+ saved_env = env;
+ env = env1;
+ do_interrupt_all(1);
+ env = saved_env;
+}
#endif
static void raise_exception(int tt)
{
env->exception_index = tt;
- cpu_loop_exit();
+ cpu_loop_exit(env);
}
void HELPER(raise_exception)(uint32_t tt)
diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index 26f0ee42e9..0e7f1fe2c7 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -25,7 +25,6 @@
#include "config.h"
#include "cpu.h"
-#include "exec-all.h"
#include "disas.h"
#include "tcg-op.h"
#include "qemu-log.h"
diff --git a/target-microblaze/cpu.h b/target-microblaze/cpu.h
index 78fe14ff35..51a13e38d1 100644
--- a/target-microblaze/cpu.h
+++ b/target-microblaze/cpu.h
@@ -350,4 +350,17 @@ static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
int is_asi, int size);
#endif
+
+static inline bool cpu_has_work(CPUState *env)
+{
+ return env->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_NMI);
+}
+
+#include "exec-all.h"
+
+static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
+{
+ env->sregs[SR_PC] = tb->pc;
+}
+
#endif
diff --git a/target-microblaze/exec.h b/target-microblaze/exec.h
index 1efff30620..71b4d397ed 100644
--- a/target-microblaze/exec.h
+++ b/target-microblaze/exec.h
@@ -21,19 +21,7 @@
register struct CPUMBState *env asm(AREG0);
#include "cpu.h"
-#include "exec-all.h"
#if !defined(CONFIG_USER_ONLY)
#include "softmmu_exec.h"
#endif
-
-static inline int cpu_has_work(CPUState *env)
-{
- return (env->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_NMI));
-}
-
-static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
-{
- env->sregs[SR_PC] = tb->pc;
-}
-
diff --git a/target-microblaze/helper.c b/target-microblaze/helper.c
index a623c7b04a..299259c3f0 100644
--- a/target-microblaze/helper.c
+++ b/target-microblaze/helper.c
@@ -23,7 +23,6 @@
#include "config.h"
#include "cpu.h"
-#include "exec-all.h"
#include "host-utils.h"
#define D(x)
diff --git a/target-microblaze/mmu.c b/target-microblaze/mmu.c
index b38f7d98b7..281fc8d8c4 100644
--- a/target-microblaze/mmu.c
+++ b/target-microblaze/mmu.c
@@ -22,7 +22,6 @@
#include "config.h"
#include "cpu.h"
-#include "exec-all.h"
#define D(x)
diff --git a/target-microblaze/op_helper.c b/target-microblaze/op_helper.c
index c7b2f97d96..1a0a476a62 100644
--- a/target-microblaze/op_helper.c
+++ b/target-microblaze/op_helper.c
@@ -63,7 +63,7 @@ void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
cpu_restore_state(tb, env, pc);
}
}
- cpu_loop_exit();
+ cpu_loop_exit(env);
}
env = saved_env;
}
@@ -107,7 +107,7 @@ uint32_t helper_get(uint32_t id, uint32_t ctrl)
void helper_raise_exception(uint32_t index)
{
env->exception_index = index;
- cpu_loop_exit();
+ cpu_loop_exit(env);
}
void helper_debug(void)
diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c
index b47b92e909..31e8306ef3 100644
--- a/target-microblaze/translate.c
+++ b/target-microblaze/translate.c
@@ -25,7 +25,6 @@
#include <assert.h>
#include "cpu.h"
-#include "exec-all.h"
#include "disas.h"
#include "tcg-op.h"
#include "helper.h"
diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index 0b98d10266..b0ac4da5a7 100644
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -656,4 +656,28 @@ static inline void cpu_set_tls(CPUState *env, target_ulong newtls)
env->tls_value = newtls;
}
+static inline int cpu_has_work(CPUState *env)
+{
+ int has_work = 0;
+
+ /* It is implementation dependent if non-enabled interrupts
+ wake-up the CPU, however most of the implementations only
+ check for interrupts that can be taken. */
+ if ((env->interrupt_request & CPU_INTERRUPT_HARD) &&
+ cpu_mips_hw_interrupts_pending(env)) {
+ has_work = 1;
+ }
+
+ return has_work;
+}
+
+#include "exec-all.h"
+
+static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
+{
+ env->active_tc.PC = tb->pc;
+ env->hflags &= ~MIPS_HFLAG_BMASK;
+ env->hflags |= tb->flags & MIPS_HFLAG_BMASK;
+}
+
#endif /* !defined (__MIPS_CPU_H__) */
diff --git a/target-mips/exec.h b/target-mips/exec.h
index 607edf12ca..e787e9a8ba 100644
--- a/target-mips/exec.h
+++ b/target-mips/exec.h
@@ -11,27 +11,11 @@
register struct CPUMIPSState *env asm(AREG0);
#include "cpu.h"
-#include "exec-all.h"
#if !defined(CONFIG_USER_ONLY)
#include "softmmu_exec.h"
#endif /* !defined(CONFIG_USER_ONLY) */
-static inline int cpu_has_work(CPUState *env)
-{
- int has_work = 0;
-
- /* It is implementation dependent if non-enabled interrupts
- wake-up the CPU, however most of the implementations only
- check for interrupts that can be taken. */
- if ((env->interrupt_request & CPU_INTERRUPT_HARD) &&
- cpu_mips_hw_interrupts_pending(env)) {
- has_work = 1;
- }
-
- return has_work;
-}
-
static inline void compute_hflags(CPUState *env)
{
env->hflags &= ~(MIPS_HFLAG_COP1X | MIPS_HFLAG_64 | MIPS_HFLAG_CP0 |
@@ -73,11 +57,4 @@ static inline void compute_hflags(CPUState *env)
}
}
-static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
-{
- env->active_tc.PC = tb->pc;
- env->hflags &= ~MIPS_HFLAG_BMASK;
- env->hflags |= tb->flags & MIPS_HFLAG_BMASK;
-}
-
#endif /* !defined(__QEMU_MIPS_EXEC_H__) */
diff --git a/target-mips/helper.c b/target-mips/helper.c
index 0f057c2171..ecf6182f56 100644
--- a/target-mips/helper.c
+++ b/target-mips/helper.c
@@ -24,7 +24,6 @@
#include <signal.h>
#include "cpu.h"
-#include "exec-all.h"
enum {
TLBRET_DIRTY = -4,
diff --git a/target-mips/machine.c b/target-mips/machine.c
index 9ffac711ce..be72b36de6 100644
--- a/target-mips/machine.c
+++ b/target-mips/machine.c
@@ -1,7 +1,7 @@
#include "hw/hw.h"
#include "hw/boards.h"
-#include "exec-all.h"
+#include "cpu.h"
static void save_tc(QEMUFile *f, TCState *tc)
{
diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
index b8e4991f32..6b966b1849 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -38,7 +38,7 @@ void helper_raise_exception_err (uint32_t exception, int error_code)
#endif
env->exception_index = exception;
env->error_code = error_code;
- cpu_loop_exit();
+ cpu_loop_exit(env);
}
void helper_raise_exception (uint32_t exception)
@@ -277,7 +277,7 @@ static inline target_phys_addr_t do_translate_address(target_ulong address, int
lladdr = cpu_mips_translate_address(env, address, rw);
if (lladdr == -1LL) {
- cpu_loop_exit();
+ cpu_loop_exit(env);
} else {
return lladdr;
}
diff --git a/target-mips/translate.c b/target-mips/translate.c
index 4eaa8261c3..2848c6a692 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -27,7 +27,6 @@
#include <inttypes.h>
#include "cpu.h"
-#include "exec-all.h"
#include "disas.h"
#include "tcg-op.h"
#include "qemu-common.h"
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index 46d86be4d7..84f8ff6748 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -2018,4 +2018,16 @@ static inline ppcmas_tlb_t *booke206_get_tlbm(CPUState *env, const int tlbn,
extern void (*cpu_ppc_hypercall)(CPUState *);
+static inline bool cpu_has_work(CPUState *env)
+{
+ return msr_ee && (env->interrupt_request & CPU_INTERRUPT_HARD);
+}
+
+#include "exec-all.h"
+
+static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
+{
+ env->nip = tb->pc;
+}
+
#endif /* !defined (__CPU_PPC_H__) */
diff --git a/target-ppc/exec.h b/target-ppc/exec.h
index f87847acb1..f4453e4965 100644
--- a/target-ppc/exec.h
+++ b/target-ppc/exec.h
@@ -24,7 +24,6 @@
#include "dyngen-exec.h"
#include "cpu.h"
-#include "exec-all.h"
register struct CPUPPCState *env asm(AREG0);
@@ -32,15 +31,4 @@ register struct CPUPPCState *env asm(AREG0);
#include "softmmu_exec.h"
#endif /* !defined(CONFIG_USER_ONLY) */
-static inline int cpu_has_work(CPUState *env)
-{
- return (msr_ee && (env->interrupt_request & CPU_INTERRUPT_HARD));
-}
-
-
-static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
-{
- env->nip = tb->pc;
-}
-
#endif /* !defined (__PPC_H__) */
diff --git a/target-ppc/helper.c b/target-ppc/helper.c
index 38849768c5..176128a3e2 100644
--- a/target-ppc/helper.c
+++ b/target-ppc/helper.c
@@ -23,7 +23,6 @@
#include <inttypes.h>
#include "cpu.h"
-#include "exec-all.h"
#include "helper_regs.h"
#include "qemu-common.h"
#include "kvm.h"
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index e7b1b10c69..21f35af762 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -65,18 +65,10 @@ static void kvm_kick_env(void *env)
int kvm_arch_init(KVMState *s)
{
-#ifdef KVM_CAP_PPC_UNSET_IRQ
cap_interrupt_unset = kvm_check_extension(s, KVM_CAP_PPC_UNSET_IRQ);
-#endif
-#ifdef KVM_CAP_PPC_IRQ_LEVEL
cap_interrupt_level = kvm_check_extension(s, KVM_CAP_PPC_IRQ_LEVEL);
-#endif
-#ifdef KVM_CAP_PPC_SEGSTATE
cap_segstate = kvm_check_extension(s, KVM_CAP_PPC_SEGSTATE);
-#endif
-#ifdef KVM_CAP_PPC_BOOKE_SREGS
cap_booke_sregs = kvm_check_extension(s, KVM_CAP_PPC_BOOKE_SREGS);
-#endif
if (!cap_interrupt_level) {
fprintf(stderr, "KVM: Couldn't find level irq capability. Expect the "
@@ -104,21 +96,12 @@ static int kvm_arch_sync_sregs(CPUState *cenv)
}
}
-#if !defined(CONFIG_KVM_PPC_PVR)
- if (1) {
- fprintf(stderr, "kvm error: missing PVR setting capability\n");
- return -ENOSYS;
- }
-#endif
-
ret = kvm_vcpu_ioctl(cenv, KVM_GET_SREGS, &sregs);
if (ret) {
return ret;
}
-#ifdef CONFIG_KVM_PPC_PVR
sregs.pvr = cenv->spr[SPR_PVR];
-#endif
return kvm_vcpu_ioctl(cenv, KVM_SET_SREGS, &sregs);
}
@@ -226,7 +209,6 @@ int kvm_arch_get_registers(CPUState *env)
return ret;
}
-#ifdef KVM_CAP_PPC_BOOKE_SREGS
if (sregs.u.e.features & KVM_SREGS_E_BASE) {
env->spr[SPR_BOOKE_CSRR0] = sregs.u.e.csrr0;
env->spr[SPR_BOOKE_CSRR1] = sregs.u.e.csrr1;
@@ -323,7 +305,6 @@ int kvm_arch_get_registers(CPUState *env)
env->spr[SPR_BOOKE_PID2] = sregs.u.e.impl.fsl.pid2;
}
}
-#endif
}
if (cap_segstate) {
@@ -332,7 +313,6 @@ int kvm_arch_get_registers(CPUState *env)
return ret;
}
-#ifdef KVM_CAP_PPC_SEGSTATE
ppc_store_sdr1(env, sregs.u.s.sdr1);
/* Sync SLB */
@@ -355,7 +335,6 @@ int kvm_arch_get_registers(CPUState *env)
env->IBAT[0][i] = sregs.u.s.ppc32.ibat[i] & 0xffffffff;
env->IBAT[1][i] = sregs.u.s.ppc32.ibat[i] >> 32;
}
-#endif
}
return 0;
@@ -534,7 +513,6 @@ int kvmppc_get_hypercall(CPUState *env, uint8_t *buf, int buf_len)
{
uint32_t *hc = (uint32_t*)buf;
-#ifdef KVM_CAP_PPC_GET_PVINFO
struct kvm_ppc_pvinfo pvinfo;
if (kvm_check_extension(env->kvm_state, KVM_CAP_PPC_GET_PVINFO) &&
@@ -543,7 +521,6 @@ int kvmppc_get_hypercall(CPUState *env, uint8_t *buf, int buf_len)
return 0;
}
-#endif
/*
* Fallback to always fail hypercalls:
diff --git a/target-ppc/op_helper.c b/target-ppc/op_helper.c
index 82b6651925..dde7595fda 100644
--- a/target-ppc/op_helper.c
+++ b/target-ppc/op_helper.c
@@ -44,7 +44,7 @@ void helper_raise_exception_err (uint32_t exception, uint32_t error_code)
#endif
env->exception_index = exception;
env->error_code = error_code;
- cpu_loop_exit();
+ cpu_loop_exit(env);
}
void helper_raise_exception (uint32_t exception)
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 7e318e397a..fd7c2087d7 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -24,7 +24,6 @@
#include <inttypes.h>
#include "cpu.h"
-#include "exec-all.h"
#include "disas.h"
#include "tcg-op.h"
#include "qemu-common.h"
diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index 4e5c3917d3..d48a9b7a0c 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -313,16 +313,6 @@ CPUState *s390_cpu_addr2state(uint16_t cpu_addr);
/* from s390-virtio-bus */
extern const target_phys_addr_t virtio_size;
-#ifndef KVM_S390_SIGP_STOP
-#define KVM_S390_SIGP_STOP 0
-#define KVM_S390_PROGRAM_INT 0
-#define KVM_S390_SIGP_SET_PREFIX 0
-#define KVM_S390_RESTART 0
-#define KVM_S390_INT_VIRTIO 0
-#define KVM_S390_INT_SERVICE 0
-#define KVM_S390_INT_EMERGENCY 0
-#endif
-
#endif
void cpu_lock(void);
void cpu_unlock(void);
@@ -972,4 +962,15 @@ static inline void cpu_inject_ext(CPUState *env, uint32_t code, uint32_t param,
cpu_interrupt(env, CPU_INTERRUPT_HARD);
}
+static inline bool cpu_has_work(CPUState *env)
+{
+ return (env->interrupt_request & CPU_INTERRUPT_HARD) &&
+ (env->psw.mask & PSW_MASK_EXT);
+}
+
+static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock* tb)
+{
+ env->psw.addr = tb->pc;
+}
+
#endif
diff --git a/target-s390x/exec.h b/target-s390x/exec.h
index 7a87fffca6..fb73f31804 100644
--- a/target-s390x/exec.h
+++ b/target-s390x/exec.h
@@ -23,18 +23,11 @@ register struct CPUS390XState *env asm(AREG0);
#include "config.h"
#include "cpu.h"
-#include "exec-all.h"
#if !defined(CONFIG_USER_ONLY)
#include "softmmu_exec.h"
#endif /* !defined(CONFIG_USER_ONLY) */
-static inline int cpu_has_work(CPUState *env)
-{
- return ((env->interrupt_request & CPU_INTERRUPT_HARD) &&
- (env->psw.mask & PSW_MASK_EXT));
-}
-
static inline void regs_to_env(void)
{
}
@@ -42,9 +35,3 @@ static inline void regs_to_env(void)
static inline void env_to_regs(void)
{
}
-
-static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock* tb)
-{
- env->psw.addr = tb->pc;
-}
-
diff --git a/target-s390x/helper.c b/target-s390x/helper.c
index 745d8c52bb..1ce7079af7 100644
--- a/target-s390x/helper.c
+++ b/target-s390x/helper.c
@@ -23,7 +23,6 @@
#include <string.h>
#include "cpu.h"
-#include "exec-all.h"
#include "gdbstub.h"
#include "qemu-common.h"
#include "qemu-timer.h"
diff --git a/target-s390x/op_helper.c b/target-s390x/op_helper.c
index db03a7971f..cd33f99d21 100644
--- a/target-s390x/op_helper.c
+++ b/target-s390x/op_helper.c
@@ -24,6 +24,9 @@
#include <string.h>
#include "kvm.h"
#include "qemu-timer.h"
+#ifdef CONFIG_KVM
+#include <linux/kvm.h>
+#endif
/*****************************************************************************/
/* Softmmu support */
@@ -70,7 +73,7 @@ void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
cpu_restore_state(tb, env, pc);
}
}
- cpu_loop_exit();
+ cpu_loop_exit(env);
}
env = saved_env;
}
@@ -89,7 +92,7 @@ void HELPER(exception)(uint32_t excp)
{
HELPER_LOG("%s: exception %d\n", __FUNCTION__, excp);
env->exception_index = excp;
- cpu_loop_exit();
+ cpu_loop_exit(env);
}
#ifndef CONFIG_USER_ONLY
@@ -2323,7 +2326,7 @@ void HELPER(tr)(uint32_t len, uint64_t array, uint64_t trans)
void HELPER(load_psw)(uint64_t mask, uint64_t addr)
{
load_psw(env, mask, addr);
- cpu_loop_exit();
+ cpu_loop_exit(env);
}
static void program_interrupt(CPUState *env, uint32_t code, int ilc)
@@ -2331,12 +2334,14 @@ static void program_interrupt(CPUState *env, uint32_t code, int ilc)
qemu_log("program interrupt at %#" PRIx64 "\n", env->psw.addr);
if (kvm_enabled()) {
+#ifdef CONFIG_KVM
kvm_s390_interrupt(env, KVM_S390_PROGRAM_INT, code);
+#endif
} else {
env->int_pgm_code = code;
env->int_pgm_ilc = ilc;
env->exception_index = EXCP_PGM;
- cpu_loop_exit();
+ cpu_loop_exit(env);
}
}
@@ -2823,12 +2828,12 @@ static uint32_t mvc_asc(int64_t l, uint64_t a1, uint64_t mode1, uint64_t a2,
}
if (mmu_translate(env, a1 & TARGET_PAGE_MASK, 1, mode1, &dest, &flags)) {
- cpu_loop_exit();
+ cpu_loop_exit(env);
}
dest |= a1 & ~TARGET_PAGE_MASK;
if (mmu_translate(env, a2 & TARGET_PAGE_MASK, 0, mode2, &src, &flags)) {
- cpu_loop_exit();
+ cpu_loop_exit(env);
}
src |= a2 & ~TARGET_PAGE_MASK;
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index eda4624d11..77fb4482aa 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -35,7 +35,6 @@
#endif
#include "cpu.h"
-#include "exec-all.h"
#include "disas.h"
#include "tcg-op.h"
#include "qemu-log.h"
diff --git a/target-sh4/cpu.h b/target-sh4/cpu.h
index 74ff97a908..00e32f2b10 100644
--- a/target-sh4/cpu.h
+++ b/target-sh4/cpu.h
@@ -361,4 +361,17 @@ static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
| (env->movcal_backup ? TB_FLAG_PENDING_MOVCA : 0); /* Bit 4 */
}
+static inline bool cpu_has_work(CPUState *env)
+{
+ return env->interrupt_request & CPU_INTERRUPT_HARD;
+}
+
+#include "exec-all.h"
+
+static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
+{
+ env->pc = tb->pc;
+ env->flags = tb->flags;
+}
+
#endif /* _CPU_SH4_H */
diff --git a/target-sh4/exec.h b/target-sh4/exec.h
index 9f1c1f6a00..4a6ae58898 100644
--- a/target-sh4/exec.h
+++ b/target-sh4/exec.h
@@ -25,21 +25,9 @@
register struct CPUSH4State *env asm(AREG0);
#include "cpu.h"
-#include "exec-all.h"
-
-static inline int cpu_has_work(CPUState *env)
-{
- return (env->interrupt_request & CPU_INTERRUPT_HARD);
-}
#ifndef CONFIG_USER_ONLY
#include "softmmu_exec.h"
#endif
-static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
-{
- env->pc = tb->pc;
- env->flags = tb->flags;
-}
-
#endif /* _EXEC_SH4_H */
diff --git a/target-sh4/helper.c b/target-sh4/helper.c
index 8f36d313cd..20e9b134d6 100644
--- a/target-sh4/helper.c
+++ b/target-sh4/helper.c
@@ -24,7 +24,6 @@
#include <signal.h>
#include "cpu.h"
-#include "exec-all.h"
#include "hw/sh_intc.h"
#if defined(CONFIG_USER_ONLY)
diff --git a/target-sh4/op_helper.c b/target-sh4/op_helper.c
index b909d18bc4..a932225880 100644
--- a/target-sh4/op_helper.c
+++ b/target-sh4/op_helper.c
@@ -66,7 +66,7 @@ void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
if (ret) {
/* now we have a real cpu fault */
cpu_restore_state_from_retaddr(retaddr);
- cpu_loop_exit();
+ cpu_loop_exit(env);
}
env = saved_env;
}
@@ -87,7 +87,7 @@ static inline void raise_exception(int index, void *retaddr)
{
env->exception_index = index;
cpu_restore_state_from_retaddr(retaddr);
- cpu_loop_exit();
+ cpu_loop_exit(env);
}
void helper_raise_illegal_instruction(void)
@@ -113,7 +113,7 @@ void helper_raise_slot_fpu_disable(void)
void helper_debug(void)
{
env->exception_index = EXCP_DEBUG;
- cpu_loop_exit();
+ cpu_loop_exit(env);
}
void helper_sleep(uint32_t next_pc)
@@ -122,7 +122,7 @@ void helper_sleep(uint32_t next_pc)
env->in_sleep = 1;
env->exception_index = EXCP_HLT;
env->pc = next_pc;
- cpu_loop_exit();
+ cpu_loop_exit(env);
}
void helper_trapa(uint32_t tra)
@@ -482,7 +482,7 @@ static void update_fpscr(void *retaddr)
if (cause & enable) {
cpu_restore_state_from_retaddr(retaddr);
env->exception_index = 0x120;
- cpu_loop_exit();
+ cpu_loop_exit(env);
}
}
}
diff --git a/target-sh4/translate.c b/target-sh4/translate.c
index 93c863650d..569bc738cb 100644
--- a/target-sh4/translate.c
+++ b/target-sh4/translate.c
@@ -27,7 +27,6 @@
//#define SH4_SINGLE_STEP
#include "cpu.h"
-#include "exec-all.h"
#include "disas.h"
#include "tcg-op.h"
#include "qemu-common.h"
diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h
index 320530ec9f..4edae78ca3 100644
--- a/target-sparc/cpu.h
+++ b/target-sparc/cpu.h
@@ -403,6 +403,8 @@ typedef struct CPUSPARCState {
uint32_t mmuregs[32];
uint64_t mxccdata[4];
uint64_t mxccregs[8];
+ uint32_t mmubpctrv, mmubpctrc, mmubpctrs;
+ uint64_t mmubpaction;
uint64_t mmubpregs[4];
uint64_t prom_addr;
#endif
@@ -474,6 +476,7 @@ target_ulong cpu_get_ccr(CPUState *env1);
void cpu_put_ccr(CPUState *env1, target_ulong val);
target_ulong cpu_get_cwp64(CPUState *env1);
void cpu_put_cwp64(CPUState *env1, int cwp);
+void cpu_change_pstate(CPUState *env1, uint32_t new_pstate);
#endif
int cpu_cwp_inc(CPUState *env1, int cwp);
int cpu_cwp_dec(CPUState *env1, int cwp);
@@ -521,7 +524,7 @@ int cpu_sparc_signal_handler(int host_signum, void *pinfo, void *puc);
#define cpu_signal_handler cpu_sparc_signal_handler
#define cpu_list sparc_cpu_list
-#define CPU_SAVE_VERSION 6
+#define CPU_SAVE_VERSION 7
/* MMU modes definitions */
#if defined (TARGET_SPARC64)
@@ -656,4 +659,21 @@ static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
#endif
}
+/* helper.c */
+void do_interrupt(CPUState *env);
+
+static inline bool cpu_has_work(CPUState *env1)
+{
+ return (env1->interrupt_request & CPU_INTERRUPT_HARD) &&
+ cpu_interrupts_enabled(env1);
+}
+
+#include "exec-all.h"
+
+static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
+{
+ env->pc = tb->pc;
+ env->npc = tb->cs_base;
+}
+
#endif
diff --git a/target-sparc/exec.h b/target-sparc/exec.h
index f5c221e48c..2395b0092f 100644
--- a/target-sparc/exec.h
+++ b/target-sparc/exec.h
@@ -12,20 +12,4 @@ register struct CPUSPARCState *env asm(AREG0);
#include "softmmu_exec.h"
#endif /* !defined(CONFIG_USER_ONLY) */
-/* op_helper.c */
-void do_interrupt(CPUState *env);
-
-static inline int cpu_has_work(CPUState *env1)
-{
- return (env1->interrupt_request & CPU_INTERRUPT_HARD) &&
- cpu_interrupts_enabled(env1);
-}
-
-
-static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
-{
- env->pc = tb->pc;
- env->npc = tb->cs_base;
-}
-
#endif
diff --git a/target-sparc/helper.c b/target-sparc/helper.c
index e9b42d03a9..7eea1acbd5 100644
--- a/target-sparc/helper.c
+++ b/target-sparc/helper.c
@@ -23,7 +23,6 @@
#include <inttypes.h>
#include "cpu.h"
-#include "exec-all.h"
#include "qemu-common.h"
//#define DEBUG_MMU
@@ -729,6 +728,248 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
}
#endif
+#ifdef TARGET_SPARC64
+#ifdef DEBUG_PCALL
+static const char * const excp_names[0x80] = {
+ [TT_TFAULT] = "Instruction Access Fault",
+ [TT_TMISS] = "Instruction Access MMU Miss",
+ [TT_CODE_ACCESS] = "Instruction Access Error",
+ [TT_ILL_INSN] = "Illegal Instruction",
+ [TT_PRIV_INSN] = "Privileged Instruction",
+ [TT_NFPU_INSN] = "FPU Disabled",
+ [TT_FP_EXCP] = "FPU Exception",
+ [TT_TOVF] = "Tag Overflow",
+ [TT_CLRWIN] = "Clean Windows",
+ [TT_DIV_ZERO] = "Division By Zero",
+ [TT_DFAULT] = "Data Access Fault",
+ [TT_DMISS] = "Data Access MMU Miss",
+ [TT_DATA_ACCESS] = "Data Access Error",
+ [TT_DPROT] = "Data Protection Error",
+ [TT_UNALIGNED] = "Unaligned Memory Access",
+ [TT_PRIV_ACT] = "Privileged Action",
+ [TT_EXTINT | 0x1] = "External Interrupt 1",
+ [TT_EXTINT | 0x2] = "External Interrupt 2",
+ [TT_EXTINT | 0x3] = "External Interrupt 3",
+ [TT_EXTINT | 0x4] = "External Interrupt 4",
+ [TT_EXTINT | 0x5] = "External Interrupt 5",
+ [TT_EXTINT | 0x6] = "External Interrupt 6",
+ [TT_EXTINT | 0x7] = "External Interrupt 7",
+ [TT_EXTINT | 0x8] = "External Interrupt 8",
+ [TT_EXTINT | 0x9] = "External Interrupt 9",
+ [TT_EXTINT | 0xa] = "External Interrupt 10",
+ [TT_EXTINT | 0xb] = "External Interrupt 11",
+ [TT_EXTINT | 0xc] = "External Interrupt 12",
+ [TT_EXTINT | 0xd] = "External Interrupt 13",
+ [TT_EXTINT | 0xe] = "External Interrupt 14",
+ [TT_EXTINT | 0xf] = "External Interrupt 15",
+};
+#endif
+
+void do_interrupt(CPUState *env)
+{
+ int intno = env->exception_index;
+ trap_state *tsptr;
+
+#ifdef DEBUG_PCALL
+ if (qemu_loglevel_mask(CPU_LOG_INT)) {
+ static int count;
+ const char *name;
+
+ if (intno < 0 || intno >= 0x180) {
+ name = "Unknown";
+ } else if (intno >= 0x100) {
+ name = "Trap Instruction";
+ } else if (intno >= 0xc0) {
+ name = "Window Fill";
+ } else if (intno >= 0x80) {
+ name = "Window Spill";
+ } else {
+ name = excp_names[intno];
+ if (!name) {
+ name = "Unknown";
+ }
+ }
+
+ qemu_log("%6d: %s (v=%04x) pc=%016" PRIx64 " npc=%016" PRIx64
+ " SP=%016" PRIx64 "\n",
+ count, name, intno,
+ env->pc,
+ env->npc, env->regwptr[6]);
+ log_cpu_state(env, 0);
+#if 0
+ {
+ int i;
+ uint8_t *ptr;
+
+ qemu_log(" code=");
+ ptr = (uint8_t *)env->pc;
+ for (i = 0; i < 16; i++) {
+ qemu_log(" %02x", ldub(ptr + i));
+ }
+ qemu_log("\n");
+ }
+#endif
+ count++;
+ }
+#endif
+#if !defined(CONFIG_USER_ONLY)
+ if (env->tl >= env->maxtl) {
+ cpu_abort(env, "Trap 0x%04x while trap level (%d) >= MAXTL (%d),"
+ " Error state", env->exception_index, env->tl, env->maxtl);
+ return;
+ }
+#endif
+ if (env->tl < env->maxtl - 1) {
+ env->tl++;
+ } else {
+ env->pstate |= PS_RED;
+ if (env->tl < env->maxtl) {
+ env->tl++;
+ }
+ }
+ tsptr = cpu_tsptr(env);
+
+ tsptr->tstate = (cpu_get_ccr(env) << 32) |
+ ((env->asi & 0xff) << 24) | ((env->pstate & 0xf3f) << 8) |
+ cpu_get_cwp64(env);
+ tsptr->tpc = env->pc;
+ tsptr->tnpc = env->npc;
+ tsptr->tt = intno;
+
+ switch (intno) {
+ case TT_IVEC:
+ cpu_change_pstate(env, PS_PEF | PS_PRIV | PS_IG);
+ break;
+ case TT_TFAULT:
+ case TT_DFAULT:
+ case TT_TMISS ... TT_TMISS + 3:
+ case TT_DMISS ... TT_DMISS + 3:
+ case TT_DPROT ... TT_DPROT + 3:
+ cpu_change_pstate(env, PS_PEF | PS_PRIV | PS_MG);
+ break;
+ default:
+ cpu_change_pstate(env, PS_PEF | PS_PRIV | PS_AG);
+ break;
+ }
+
+ if (intno == TT_CLRWIN) {
+ cpu_set_cwp(env, cpu_cwp_dec(env, env->cwp - 1));
+ } else if ((intno & 0x1c0) == TT_SPILL) {
+ cpu_set_cwp(env, cpu_cwp_dec(env, env->cwp - env->cansave - 2));
+ } else if ((intno & 0x1c0) == TT_FILL) {
+ cpu_set_cwp(env, cpu_cwp_inc(env, env->cwp + 1));
+ }
+ env->tbr &= ~0x7fffULL;
+ env->tbr |= ((env->tl > 1) ? 1 << 14 : 0) | (intno << 5);
+ env->pc = env->tbr;
+ env->npc = env->pc + 4;
+ env->exception_index = -1;
+}
+#else
+#ifdef DEBUG_PCALL
+static const char * const excp_names[0x80] = {
+ [TT_TFAULT] = "Instruction Access Fault",
+ [TT_ILL_INSN] = "Illegal Instruction",
+ [TT_PRIV_INSN] = "Privileged Instruction",
+ [TT_NFPU_INSN] = "FPU Disabled",
+ [TT_WIN_OVF] = "Window Overflow",
+ [TT_WIN_UNF] = "Window Underflow",
+ [TT_UNALIGNED] = "Unaligned Memory Access",
+ [TT_FP_EXCP] = "FPU Exception",
+ [TT_DFAULT] = "Data Access Fault",
+ [TT_TOVF] = "Tag Overflow",
+ [TT_EXTINT | 0x1] = "External Interrupt 1",
+ [TT_EXTINT | 0x2] = "External Interrupt 2",
+ [TT_EXTINT | 0x3] = "External Interrupt 3",
+ [TT_EXTINT | 0x4] = "External Interrupt 4",
+ [TT_EXTINT | 0x5] = "External Interrupt 5",
+ [TT_EXTINT | 0x6] = "External Interrupt 6",
+ [TT_EXTINT | 0x7] = "External Interrupt 7",
+ [TT_EXTINT | 0x8] = "External Interrupt 8",
+ [TT_EXTINT | 0x9] = "External Interrupt 9",
+ [TT_EXTINT | 0xa] = "External Interrupt 10",
+ [TT_EXTINT | 0xb] = "External Interrupt 11",
+ [TT_EXTINT | 0xc] = "External Interrupt 12",
+ [TT_EXTINT | 0xd] = "External Interrupt 13",
+ [TT_EXTINT | 0xe] = "External Interrupt 14",
+ [TT_EXTINT | 0xf] = "External Interrupt 15",
+ [TT_TOVF] = "Tag Overflow",
+ [TT_CODE_ACCESS] = "Instruction Access Error",
+ [TT_DATA_ACCESS] = "Data Access Error",
+ [TT_DIV_ZERO] = "Division By Zero",
+ [TT_NCP_INSN] = "Coprocessor Disabled",
+};
+#endif
+
+void do_interrupt(CPUState *env)
+{
+ int cwp, intno = env->exception_index;
+
+#ifdef DEBUG_PCALL
+ if (qemu_loglevel_mask(CPU_LOG_INT)) {
+ static int count;
+ const char *name;
+
+ if (intno < 0 || intno >= 0x100) {
+ name = "Unknown";
+ } else if (intno >= 0x80) {
+ name = "Trap Instruction";
+ } else {
+ name = excp_names[intno];
+ if (!name) {
+ name = "Unknown";
+ }
+ }
+
+ qemu_log("%6d: %s (v=%02x) pc=%08x npc=%08x SP=%08x\n",
+ count, name, intno,
+ env->pc,
+ env->npc, env->regwptr[6]);
+ log_cpu_state(env, 0);
+#if 0
+ {
+ int i;
+ uint8_t *ptr;
+
+ qemu_log(" code=");
+ ptr = (uint8_t *)env->pc;
+ for (i = 0; i < 16; i++) {
+ qemu_log(" %02x", ldub(ptr + i));
+ }
+ qemu_log("\n");
+ }
+#endif
+ count++;
+ }
+#endif
+#if !defined(CONFIG_USER_ONLY)
+ if (env->psret == 0) {
+ cpu_abort(env, "Trap 0x%02x while interrupts disabled, Error state",
+ env->exception_index);
+ return;
+ }
+#endif
+ env->psret = 0;
+ cwp = cpu_cwp_dec(env, env->cwp - 1);
+ cpu_set_cwp(env, cwp);
+ env->regwptr[9] = env->pc;
+ env->regwptr[10] = env->npc;
+ env->psrps = env->psrs;
+ env->psrs = 1;
+ env->tbr = (env->tbr & TBR_BASE_MASK) | (intno << 4);
+ env->pc = env->tbr;
+ env->npc = env->pc + 4;
+ env->exception_index = -1;
+
+#if !defined(CONFIG_USER_ONLY)
+ /* IRQ acknowledgment */
+ if ((intno & ~15) == TT_EXTINT && env->qemu_irq_ack != NULL) {
+ env->qemu_irq_ack(env->irq_manager, intno);
+ }
+#endif
+}
+#endif
+
void cpu_reset(CPUSPARCState *env)
{
if (qemu_loglevel_mask(CPU_LOG_RESET)) {
diff --git a/target-sparc/machine.c b/target-sparc/machine.c
index 752e431778..56ae0412cd 100644
--- a/target-sparc/machine.c
+++ b/target-sparc/machine.c
@@ -2,7 +2,7 @@
#include "hw/boards.h"
#include "qemu-timer.h"
-#include "exec-all.h"
+#include "cpu.h"
void cpu_save(QEMUFile *f, void *opaque)
{
@@ -45,6 +45,19 @@ void cpu_save(QEMUFile *f, void *opaque)
/* MMU */
for (i = 0; i < 32; i++)
qemu_put_be32s(f, &env->mmuregs[i]);
+ for (i = 0; i < 4; i++) {
+ qemu_put_be64s(f, &env->mxccdata[i]);
+ }
+ for (i = 0; i < 8; i++) {
+ qemu_put_be64s(f, &env->mxccregs[i]);
+ }
+ qemu_put_be32s(f, &env->mmubpctrv);
+ qemu_put_be32s(f, &env->mmubpctrc);
+ qemu_put_be32s(f, &env->mmubpctrs);
+ qemu_put_be64s(f, &env->mmubpaction);
+ for (i = 0; i < 4; i++) {
+ qemu_put_be64s(f, &env->mmubpregs[i]);
+ }
#else
qemu_put_be64s(f, &env->lsu);
for (i = 0; i < 16; i++) {
@@ -141,6 +154,19 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
/* MMU */
for (i = 0; i < 32; i++)
qemu_get_be32s(f, &env->mmuregs[i]);
+ for (i = 0; i < 4; i++) {
+ qemu_get_be64s(f, &env->mxccdata[i]);
+ }
+ for (i = 0; i < 8; i++) {
+ qemu_get_be64s(f, &env->mxccregs[i]);
+ }
+ qemu_get_be32s(f, &env->mmubpctrv);
+ qemu_get_be32s(f, &env->mmubpctrc);
+ qemu_get_be32s(f, &env->mmubpctrs);
+ qemu_get_be64s(f, &env->mmubpaction);
+ for (i = 0; i < 4; i++) {
+ qemu_get_be64s(f, &env->mmubpregs[i]);
+ }
#else
qemu_get_be64s(f, &env->lsu);
for (i = 0; i < 16; i++) {
diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c
index b38691e19d..fd0cfbdb73 100644
--- a/target-sparc/op_helper.c
+++ b/target-sparc/op_helper.c
@@ -316,7 +316,7 @@ static inline target_ulong asi_address_mask(CPUState *env1,
static void raise_exception(int tt)
{
env->exception_index = tt;
- cpu_loop_exit();
+ cpu_loop_exit(env);
}
void HELPER(raise_exception)(int tt)
@@ -1940,7 +1940,6 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
case 0x31: // Turbosparc RAM snoop
case 0x32: // Turbosparc page table descriptor diagnostic
case 0x39: /* data cache diagnostic register */
- case 0x4c: /* SuperSPARC MMU Breakpoint Action register */
ret = 0;
break;
case 0x38: /* SuperSPARC MMU Breakpoint Control Registers */
@@ -1966,6 +1965,18 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
ret);
}
break;
+ case 0x49: /* SuperSPARC MMU Counter Breakpoint Value */
+ ret = env->mmubpctrv;
+ break;
+ case 0x4a: /* SuperSPARC MMU Counter Breakpoint Control */
+ ret = env->mmubpctrc;
+ break;
+ case 0x4b: /* SuperSPARC MMU Counter Breakpoint Status */
+ ret = env->mmubpctrs;
+ break;
+ case 0x4c: /* SuperSPARC MMU Breakpoint Action */
+ ret = env->mmubpaction;
+ break;
case 8: /* User code access, XXX */
default:
do_unassigned_access(addr, 0, 0, asi, size);
@@ -2304,7 +2315,6 @@ void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size)
// descriptor diagnostic
case 0x36: /* I-cache flash clear */
case 0x37: /* D-cache flash clear */
- case 0x4c: /* breakpoint action */
break;
case 0x38: /* SuperSPARC MMU Breakpoint Control Registers*/
{
@@ -2328,6 +2338,18 @@ void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size)
env->mmuregs[reg]);
}
break;
+ case 0x49: /* SuperSPARC MMU Counter Breakpoint Value */
+ env->mmubpctrv = val & 0xffffffff;
+ break;
+ case 0x4a: /* SuperSPARC MMU Counter Breakpoint Control */
+ env->mmubpctrc = val & 0x3;
+ break;
+ case 0x4b: /* SuperSPARC MMU Counter Breakpoint Status */
+ env->mmubpctrs = val & 0x3;
+ break;
+ case 0x4c: /* SuperSPARC MMU Breakpoint Action */
+ env->mmubpaction = val & 0x1fff;
+ break;
case 8: /* User code access, XXX */
case 9: /* Supervisor code access, XXX */
default:
@@ -3702,7 +3724,7 @@ void helper_ldxfsr(uint64_t new_fsr)
void helper_debug(void)
{
env->exception_index = EXCP_DEBUG;
- cpu_loop_exit();
+ cpu_loop_exit(env);
}
#ifndef TARGET_SPARC64
@@ -4007,6 +4029,16 @@ void helper_wrpstate(target_ulong new_state)
#endif
}
+void cpu_change_pstate(CPUState *env1, uint32_t new_pstate)
+{
+ CPUState *saved_env;
+
+ saved_env = env;
+ env = env1;
+ change_pstate(new_pstate);
+ env = saved_env;
+}
+
void helper_wrpil(target_ulong new_pil)
{
#if !defined(CONFIG_USER_ONLY)
@@ -4093,247 +4125,10 @@ void helper_write_softint(uint64_t value)
#endif
#ifdef TARGET_SPARC64
-#ifdef DEBUG_PCALL
-static const char * const excp_names[0x80] = {
- [TT_TFAULT] = "Instruction Access Fault",
- [TT_TMISS] = "Instruction Access MMU Miss",
- [TT_CODE_ACCESS] = "Instruction Access Error",
- [TT_ILL_INSN] = "Illegal Instruction",
- [TT_PRIV_INSN] = "Privileged Instruction",
- [TT_NFPU_INSN] = "FPU Disabled",
- [TT_FP_EXCP] = "FPU Exception",
- [TT_TOVF] = "Tag Overflow",
- [TT_CLRWIN] = "Clean Windows",
- [TT_DIV_ZERO] = "Division By Zero",
- [TT_DFAULT] = "Data Access Fault",
- [TT_DMISS] = "Data Access MMU Miss",
- [TT_DATA_ACCESS] = "Data Access Error",
- [TT_DPROT] = "Data Protection Error",
- [TT_UNALIGNED] = "Unaligned Memory Access",
- [TT_PRIV_ACT] = "Privileged Action",
- [TT_EXTINT | 0x1] = "External Interrupt 1",
- [TT_EXTINT | 0x2] = "External Interrupt 2",
- [TT_EXTINT | 0x3] = "External Interrupt 3",
- [TT_EXTINT | 0x4] = "External Interrupt 4",
- [TT_EXTINT | 0x5] = "External Interrupt 5",
- [TT_EXTINT | 0x6] = "External Interrupt 6",
- [TT_EXTINT | 0x7] = "External Interrupt 7",
- [TT_EXTINT | 0x8] = "External Interrupt 8",
- [TT_EXTINT | 0x9] = "External Interrupt 9",
- [TT_EXTINT | 0xa] = "External Interrupt 10",
- [TT_EXTINT | 0xb] = "External Interrupt 11",
- [TT_EXTINT | 0xc] = "External Interrupt 12",
- [TT_EXTINT | 0xd] = "External Interrupt 13",
- [TT_EXTINT | 0xe] = "External Interrupt 14",
- [TT_EXTINT | 0xf] = "External Interrupt 15",
-};
-#endif
-
trap_state* cpu_tsptr(CPUState* env)
{
return &env->ts[env->tl & MAXTL_MASK];
}
-
-void do_interrupt(CPUState *env)
-{
- int intno = env->exception_index;
- trap_state* tsptr;
-
-#ifdef DEBUG_PCALL
- if (qemu_loglevel_mask(CPU_LOG_INT)) {
- static int count;
- const char *name;
-
- if (intno < 0 || intno >= 0x180)
- name = "Unknown";
- else if (intno >= 0x100)
- name = "Trap Instruction";
- else if (intno >= 0xc0)
- name = "Window Fill";
- else if (intno >= 0x80)
- name = "Window Spill";
- else {
- name = excp_names[intno];
- if (!name)
- name = "Unknown";
- }
-
- qemu_log("%6d: %s (v=%04x) pc=%016" PRIx64 " npc=%016" PRIx64
- " SP=%016" PRIx64 "\n",
- count, name, intno,
- env->pc,
- env->npc, env->regwptr[6]);
- log_cpu_state(env, 0);
-#if 0
- {
- int i;
- uint8_t *ptr;
-
- qemu_log(" code=");
- ptr = (uint8_t *)env->pc;
- for(i = 0; i < 16; i++) {
- qemu_log(" %02x", ldub(ptr + i));
- }
- qemu_log("\n");
- }
-#endif
- count++;
- }
-#endif
-#if !defined(CONFIG_USER_ONLY)
- if (env->tl >= env->maxtl) {
- cpu_abort(env, "Trap 0x%04x while trap level (%d) >= MAXTL (%d),"
- " Error state", env->exception_index, env->tl, env->maxtl);
- return;
- }
-#endif
- if (env->tl < env->maxtl - 1) {
- env->tl++;
- } else {
- env->pstate |= PS_RED;
- if (env->tl < env->maxtl)
- env->tl++;
- }
- tsptr = cpu_tsptr(env);
-
- tsptr->tstate = (get_ccr() << 32) |
- ((env->asi & 0xff) << 24) | ((env->pstate & 0xf3f) << 8) |
- get_cwp64();
- tsptr->tpc = env->pc;
- tsptr->tnpc = env->npc;
- tsptr->tt = intno;
-
- switch (intno) {
- case TT_IVEC:
- change_pstate(PS_PEF | PS_PRIV | PS_IG);
- break;
- case TT_TFAULT:
- case TT_DFAULT:
- case TT_TMISS ... TT_TMISS + 3:
- case TT_DMISS ... TT_DMISS + 3:
- case TT_DPROT ... TT_DPROT + 3:
- change_pstate(PS_PEF | PS_PRIV | PS_MG);
- break;
- default:
- change_pstate(PS_PEF | PS_PRIV | PS_AG);
- break;
- }
-
- if (intno == TT_CLRWIN) {
- set_cwp(cwp_dec(env->cwp - 1));
- } else if ((intno & 0x1c0) == TT_SPILL) {
- set_cwp(cwp_dec(env->cwp - env->cansave - 2));
- } else if ((intno & 0x1c0) == TT_FILL) {
- set_cwp(cwp_inc(env->cwp + 1));
- }
- env->tbr &= ~0x7fffULL;
- env->tbr |= ((env->tl > 1) ? 1 << 14 : 0) | (intno << 5);
- env->pc = env->tbr;
- env->npc = env->pc + 4;
- env->exception_index = -1;
-}
-#else
-#ifdef DEBUG_PCALL
-static const char * const excp_names[0x80] = {
- [TT_TFAULT] = "Instruction Access Fault",
- [TT_ILL_INSN] = "Illegal Instruction",
- [TT_PRIV_INSN] = "Privileged Instruction",
- [TT_NFPU_INSN] = "FPU Disabled",
- [TT_WIN_OVF] = "Window Overflow",
- [TT_WIN_UNF] = "Window Underflow",
- [TT_UNALIGNED] = "Unaligned Memory Access",
- [TT_FP_EXCP] = "FPU Exception",
- [TT_DFAULT] = "Data Access Fault",
- [TT_TOVF] = "Tag Overflow",
- [TT_EXTINT | 0x1] = "External Interrupt 1",
- [TT_EXTINT | 0x2] = "External Interrupt 2",
- [TT_EXTINT | 0x3] = "External Interrupt 3",
- [TT_EXTINT | 0x4] = "External Interrupt 4",
- [TT_EXTINT | 0x5] = "External Interrupt 5",
- [TT_EXTINT | 0x6] = "External Interrupt 6",
- [TT_EXTINT | 0x7] = "External Interrupt 7",
- [TT_EXTINT | 0x8] = "External Interrupt 8",
- [TT_EXTINT | 0x9] = "External Interrupt 9",
- [TT_EXTINT | 0xa] = "External Interrupt 10",
- [TT_EXTINT | 0xb] = "External Interrupt 11",
- [TT_EXTINT | 0xc] = "External Interrupt 12",
- [TT_EXTINT | 0xd] = "External Interrupt 13",
- [TT_EXTINT | 0xe] = "External Interrupt 14",
- [TT_EXTINT | 0xf] = "External Interrupt 15",
- [TT_TOVF] = "Tag Overflow",
- [TT_CODE_ACCESS] = "Instruction Access Error",
- [TT_DATA_ACCESS] = "Data Access Error",
- [TT_DIV_ZERO] = "Division By Zero",
- [TT_NCP_INSN] = "Coprocessor Disabled",
-};
-#endif
-
-void do_interrupt(CPUState *env)
-{
- int cwp, intno = env->exception_index;
-
-#ifdef DEBUG_PCALL
- if (qemu_loglevel_mask(CPU_LOG_INT)) {
- static int count;
- const char *name;
-
- if (intno < 0 || intno >= 0x100)
- name = "Unknown";
- else if (intno >= 0x80)
- name = "Trap Instruction";
- else {
- name = excp_names[intno];
- if (!name)
- name = "Unknown";
- }
-
- qemu_log("%6d: %s (v=%02x) pc=%08x npc=%08x SP=%08x\n",
- count, name, intno,
- env->pc,
- env->npc, env->regwptr[6]);
- log_cpu_state(env, 0);
-#if 0
- {
- int i;
- uint8_t *ptr;
-
- qemu_log(" code=");
- ptr = (uint8_t *)env->pc;
- for(i = 0; i < 16; i++) {
- qemu_log(" %02x", ldub(ptr + i));
- }
- qemu_log("\n");
- }
-#endif
- count++;
- }
-#endif
-#if !defined(CONFIG_USER_ONLY)
- if (env->psret == 0) {
- cpu_abort(env, "Trap 0x%02x while interrupts disabled, Error state",
- env->exception_index);
- return;
- }
-#endif
- env->psret = 0;
- cwp = cwp_dec(env->cwp - 1);
- set_cwp(cwp);
- env->regwptr[9] = env->pc;
- env->regwptr[10] = env->npc;
- env->psrps = env->psrs;
- env->psrs = 1;
- env->tbr = (env->tbr & TBR_BASE_MASK) | (intno << 4);
- env->pc = env->tbr;
- env->npc = env->pc + 4;
- env->exception_index = -1;
-
-#if !defined(CONFIG_USER_ONLY)
- /* IRQ acknowledgment */
- if ((intno & ~15) == TT_EXTINT && env->qemu_irq_ack != NULL) {
- env->qemu_irq_ack(env->irq_manager, intno);
- }
-#endif
-}
#endif
#if !defined(CONFIG_USER_ONLY)
@@ -4402,7 +4197,7 @@ void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
ret = cpu_sparc_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
if (ret) {
cpu_restore_state2(retaddr);
- cpu_loop_exit();
+ cpu_loop_exit(env);
}
env = saved_env;
}
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index 0cc47e9ff3..992cd77e72 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -25,7 +25,6 @@
#include <inttypes.h>
#include "cpu.h"
-#include "exec-all.h"
#include "disas.h"
#include "helper.h"
#include "tcg-op.h"
diff --git a/target-unicore32/cpu.h b/target-unicore32/cpu.h
index 1e10049f89..981760734f 100644
--- a/target-unicore32/cpu.h
+++ b/target-unicore32/cpu.h
@@ -179,4 +179,10 @@ void uc32_translate_init(void);
void do_interrupt(CPUState *);
void switch_mode(CPUState_UniCore32 *, int);
+static inline bool cpu_has_work(CPUState *env)
+{
+ return env->interrupt_request &
+ (CPU_INTERRUPT_HARD | CPU_INTERRUPT_EXITTB);
+}
+
#endif /* __CPU_UC32_H__ */
diff --git a/target-unicore32/exec.h b/target-unicore32/exec.h
index 4ab55f42cf..7912105e32 100644
--- a/target-unicore32/exec.h
+++ b/target-unicore32/exec.h
@@ -16,7 +16,6 @@
register struct CPUState_UniCore32 *env asm(AREG0);
#include "cpu.h"
-#include "exec-all.h"
static inline void env_to_regs(void)
{
@@ -26,12 +25,6 @@ static inline void regs_to_env(void)
{
}
-static inline int cpu_has_work(CPUState *env)
-{
- return env->interrupt_request &
- (CPU_INTERRUPT_HARD | CPU_INTERRUPT_EXITTB);
-}
-
static inline int cpu_halted(CPUState *env)
{
if (!env->halted) {
diff --git a/target-unicore32/helper.c b/target-unicore32/helper.c
index 483aeaeb14..02707d5857 100644
--- a/target-unicore32/helper.c
+++ b/target-unicore32/helper.c
@@ -10,7 +10,6 @@
#include <string.h>
#include "cpu.h"
-#include "exec-all.h"
#include "gdbstub.h"
#include "helper.h"
#include "qemu-common.h"
diff --git a/target-unicore32/op_helper.c b/target-unicore32/op_helper.c
index 31e4b11e43..541e6f099d 100644
--- a/target-unicore32/op_helper.c
+++ b/target-unicore32/op_helper.c
@@ -16,7 +16,7 @@
void HELPER(exception)(uint32_t excp)
{
env->exception_index = excp;
- cpu_loop_exit();
+ cpu_loop_exit(env);
}
static target_ulong asr_read(void)
diff --git a/target-unicore32/translate.c b/target-unicore32/translate.c
index 98eaeb3d43..a15e42d663 100644
--- a/target-unicore32/translate.c
+++ b/target-unicore32/translate.c
@@ -14,7 +14,6 @@
#include <inttypes.h>
#include "cpu.h"
-#include "exec-all.h"
#include "disas.h"
#include "tcg-op.h"
#include "qemu-log.h"
diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
index fb858d8634..93eb0f1a45 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -1804,6 +1804,8 @@ static void tcg_target_init(TCGContext *s)
tcg_regset_set_reg(s->reserved_regs, TCG_REG_PC);
tcg_add_target_add_op_defs(arm_op_defs);
+ tcg_set_frame(s, TCG_AREG0, offsetof(CPUState, temp_buf),
+ CPU_TEMP_BUF_NLONGS * sizeof(long));
}
static inline void tcg_out_ld(TCGContext *s, TCGType type, int arg,
@@ -1846,15 +1848,18 @@ static inline void tcg_out_movi(TCGContext *s, TCGType type,
static void tcg_target_qemu_prologue(TCGContext *s)
{
- /* There is no need to save r7, it is used to store the address
- of the env structure and is not modified by GCC. */
+ /* Calling convention requires us to save r4-r11 and lr;
+ * save also r12 to maintain stack 8-alignment.
+ */
+
+ /* stmdb sp!, { r4 - r12, lr } */
+ tcg_out32(s, (COND_AL << 28) | 0x092d5ff0);
- /* stmdb sp!, { r4 - r6, r8 - r11, lr } */
- tcg_out32(s, (COND_AL << 28) | 0x092d4f70);
+ tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
- tcg_out_bx(s, COND_AL, TCG_REG_R0);
+ tcg_out_bx(s, COND_AL, tcg_target_call_iarg_regs[1]);
tb_ret_addr = s->code_ptr;
- /* ldmia sp!, { r4 - r6, r8 - r11, pc } */
- tcg_out32(s, (COND_AL << 28) | 0x08bd8f70);
+ /* ldmia sp!, { r4 - r12, pc } */
+ tcg_out32(s, (COND_AL << 28) | 0x08bd9ff0);
}
diff --git a/tcg/hppa/tcg-target.c b/tcg/hppa/tcg-target.c
index 7f4653e342..222f33eb6d 100644
--- a/tcg/hppa/tcg-target.c
+++ b/tcg/hppa/tcg-target.c
@@ -467,6 +467,14 @@ static inline void tcg_out_dep(TCGContext *s, int ret, int arg,
| INSN_SHDEP_CP(31 - ofs) | INSN_DEP_LEN(len));
}
+static inline void tcg_out_depi(TCGContext *s, int ret, int arg,
+ unsigned ofs, unsigned len)
+{
+ assert(ofs < 32 && len <= 32 - ofs);
+ tcg_out32(s, INSN_DEPI | INSN_R2(ret) | INSN_IM5(arg)
+ | INSN_SHDEP_CP(31 - ofs) | INSN_DEP_LEN(len));
+}
+
static inline void tcg_out_shd(TCGContext *s, int ret, int hi, int lo,
unsigned count)
{
@@ -499,8 +507,7 @@ static void tcg_out_ori(TCGContext *s, int ret, int arg, tcg_target_ulong m)
assert(bs1 == 32 || (1ul << bs1) > m);
tcg_out_mov(s, TCG_TYPE_I32, ret, arg);
- tcg_out32(s, INSN_DEPI | INSN_R2(ret) | INSN_IM5(-1)
- | INSN_SHDEP_CP(31 - bs0) | INSN_DEP_LEN(bs1 - bs0));
+ tcg_out_depi(s, ret, -1, bs0, bs1 - bs0);
}
static void tcg_out_andi(TCGContext *s, int ret, int arg, tcg_target_ulong m)
@@ -529,8 +536,7 @@ static void tcg_out_andi(TCGContext *s, int ret, int arg, tcg_target_ulong m)
tcg_out_extr(s, ret, arg, 0, ls0, 0);
} else {
tcg_out_mov(s, TCG_TYPE_I32, ret, arg);
- tcg_out32(s, INSN_DEPI | INSN_R2(ret) | INSN_IM5(0)
- | INSN_SHDEP_CP(31 - ls0) | INSN_DEP_LEN(ls1 - ls0));
+ tcg_out_depi(s, ret, 0, ls0, ls1 - ls0);
}
}
@@ -646,14 +652,14 @@ static void tcg_out_xmpyu(TCGContext *s, int retl, int reth,
int arg1, int arg2)
{
/* Store both words into the stack for copy to the FPU. */
- tcg_out_ldst(s, arg1, TCG_REG_SP, STACK_TEMP_OFS, INSN_STW);
- tcg_out_ldst(s, arg2, TCG_REG_SP, STACK_TEMP_OFS + 4, INSN_STW);
+ tcg_out_ldst(s, arg1, TCG_REG_CALL_STACK, STACK_TEMP_OFS, INSN_STW);
+ tcg_out_ldst(s, arg2, TCG_REG_CALL_STACK, STACK_TEMP_OFS + 4, INSN_STW);
/* Load both words into the FPU at the same time. We get away
with this because we can address the left and right half of the
FPU registers individually once loaded. */
/* fldds stack_temp(sp),fr22 */
- tcg_out32(s, INSN_FLDDS | INSN_R2(TCG_REG_SP)
+ tcg_out32(s, INSN_FLDDS | INSN_R2(TCG_REG_CALL_STACK)
| INSN_IM5(STACK_TEMP_OFS) | INSN_T(22));
/* xmpyu fr22r,fr22,fr22 */
@@ -661,15 +667,16 @@ static void tcg_out_xmpyu(TCGContext *s, int retl, int reth,
/* Store the 64-bit result back into the stack. */
/* fstds stack_temp(sp),fr22 */
- tcg_out32(s, INSN_FSTDS | INSN_R2(TCG_REG_SP)
+ tcg_out32(s, INSN_FSTDS | INSN_R2(TCG_REG_CALL_STACK)
| INSN_IM5(STACK_TEMP_OFS) | INSN_T(22));
/* Load the pieces of the result that the caller requested. */
if (reth) {
- tcg_out_ldst(s, reth, TCG_REG_SP, STACK_TEMP_OFS, INSN_LDW);
+ tcg_out_ldst(s, reth, TCG_REG_CALL_STACK, STACK_TEMP_OFS, INSN_LDW);
}
if (retl) {
- tcg_out_ldst(s, retl, TCG_REG_SP, STACK_TEMP_OFS + 4, INSN_LDW);
+ tcg_out_ldst(s, retl, TCG_REG_CALL_STACK, STACK_TEMP_OFS + 4,
+ INSN_LDW);
}
}
@@ -1198,7 +1205,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
}
tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_R23, datahi_reg);
tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_R24, datalo_reg);
- tcg_out_st(s, TCG_TYPE_I32, argreg, TCG_REG_SP,
+ tcg_out_st(s, TCG_TYPE_I32, argreg, TCG_REG_CALL_STACK,
TCG_TARGET_CALL_STACK_OFFSET - 4);
break;
default:
@@ -1458,6 +1465,14 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
args[4], args[5], const_args[2], const_args[4]);
break;
+ case INDEX_op_deposit_i32:
+ if (const_args[2]) {
+ tcg_out_depi(s, args[0], args[2], args[3], args[4]);
+ } else {
+ tcg_out_dep(s, args[0], args[2], args[3], args[4]);
+ }
+ break;
+
case INDEX_op_qemu_ld8u:
tcg_out_qemu_ld(s, args, 0);
break;
@@ -1551,6 +1566,8 @@ static const TCGTargetOpDef hppa_op_defs[] = {
{ INDEX_op_add2_i32, { "r", "r", "rZ", "rZ", "rI", "rZ" } },
{ INDEX_op_sub2_i32, { "r", "r", "rI", "rZ", "rK", "rZ" } },
+ { INDEX_op_deposit_i32, { "r", "0", "rJ" } },
+
#if TARGET_LONG_BITS == 32
{ INDEX_op_qemu_ld8u, { "r", "L" } },
{ INDEX_op_qemu_ld8s, { "r", "L" } },
@@ -1596,7 +1613,7 @@ static int tcg_target_callee_save_regs[] = {
TCG_REG_R14,
TCG_REG_R15,
TCG_REG_R16,
- /* R17 is the global env, so no need to save. */
+ TCG_REG_R17, /* R17 is the global env. */
TCG_REG_R18
};
@@ -1611,23 +1628,30 @@ static void tcg_target_qemu_prologue(TCGContext *s)
/* Allocate space for the saved registers. */
frame_size += ARRAY_SIZE(tcg_target_callee_save_regs) * 4;
+ /* Allocate space for the TCG temps. */
+ frame_size += CPU_TEMP_BUF_NLONGS * sizeof(long);
+
/* Align the allocated space. */
frame_size = ((frame_size + TCG_TARGET_STACK_ALIGN - 1)
& -TCG_TARGET_STACK_ALIGN);
/* The return address is stored in the caller's frame. */
- tcg_out_st(s, TCG_TYPE_PTR, TCG_REG_RP, TCG_REG_SP, -20);
+ tcg_out_st(s, TCG_TYPE_PTR, TCG_REG_RP, TCG_REG_CALL_STACK, -20);
/* Allocate stack frame, saving the first register at the same time. */
tcg_out_ldst(s, tcg_target_callee_save_regs[0],
- TCG_REG_SP, frame_size, INSN_STWM);
+ TCG_REG_CALL_STACK, frame_size, INSN_STWM);
/* Save all callee saved registers. */
for (i = 1; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) {
tcg_out_st(s, TCG_TYPE_PTR, tcg_target_callee_save_regs[i],
- TCG_REG_SP, -frame_size + i * 4);
+ TCG_REG_CALL_STACK, -frame_size + i * 4);
}
+ /* Record the location of the TCG temps. */
+ tcg_set_frame(s, TCG_REG_CALL_STACK, -frame_size + i * 4,
+ TCG_TEMP_BUF_NLONGS * sizeof(long));
+
#ifdef CONFIG_USE_GUEST_BASE
if (GUEST_BASE != 0) {
tcg_out_movi(s, TCG_TYPE_PTR, TCG_GUEST_BASE_REG, GUEST_BASE);
@@ -1635,21 +1659,24 @@ static void tcg_target_qemu_prologue(TCGContext *s)
}
#endif
+ tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
+
/* Jump to TB, and adjust R18 to be the return address. */
- tcg_out32(s, INSN_BLE_SR4 | INSN_R2(TCG_REG_R26));
+ tcg_out32(s, INSN_BLE_SR4 | INSN_R2(tcg_target_call_iarg_regs[1]));
tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_R18, TCG_REG_R31);
/* Restore callee saved registers. */
- tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_RP, TCG_REG_SP, -frame_size - 20);
+ tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_RP, TCG_REG_CALL_STACK,
+ -frame_size - 20);
for (i = 1; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) {
tcg_out_ld(s, TCG_TYPE_PTR, tcg_target_callee_save_regs[i],
- TCG_REG_SP, -frame_size + i * 4);
+ TCG_REG_CALL_STACK, -frame_size + i * 4);
}
/* Deallocate stack frame and return. */
tcg_out32(s, INSN_BV | INSN_R2(TCG_REG_RP));
tcg_out_ldst(s, tcg_target_callee_save_regs[0],
- TCG_REG_SP, -frame_size, INSN_LDWM);
+ TCG_REG_CALL_STACK, -frame_size, INSN_LDWM);
}
static void tcg_target_init(TCGContext *s)
@@ -1676,7 +1703,7 @@ static void tcg_target_init(TCGContext *s)
tcg_regset_set_reg(s->reserved_regs, TCG_REG_R19); /* clobbered w/o pic */
tcg_regset_set_reg(s->reserved_regs, TCG_REG_R20); /* reserved */
tcg_regset_set_reg(s->reserved_regs, TCG_REG_DP); /* data pointer */
- tcg_regset_set_reg(s->reserved_regs, TCG_REG_SP); /* stack pointer */
+ tcg_regset_set_reg(s->reserved_regs, TCG_REG_CALL_STACK); /* stack pointer */
tcg_regset_set_reg(s->reserved_regs, TCG_REG_R31); /* ble link reg */
tcg_add_target_add_op_defs(hppa_op_defs);
diff --git a/tcg/hppa/tcg-target.h b/tcg/hppa/tcg-target.h
index a5cc440d49..f7919ceef7 100644
--- a/tcg/hppa/tcg-target.h
+++ b/tcg/hppa/tcg-target.h
@@ -94,6 +94,7 @@ enum {
#define TCG_TARGET_HAS_not_i32
#define TCG_TARGET_HAS_andc_i32
// #define TCG_TARGET_HAS_orc_i32
+#define TCG_TARGET_HAS_deposit_i32
/* optional instructions automatically implemented */
#undef TCG_TARGET_HAS_neg_i32 /* sub rd, 0, rs */
diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index bb19a950bf..7529677fe2 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -1398,7 +1398,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
/* Pop and discard. This is 2 bytes smaller than the add. */
tcg_out_pop(s, TCG_REG_ECX);
} else if (stack_adjust != 0) {
- tcg_out_addi(s, TCG_REG_ESP, stack_adjust);
+ tcg_out_addi(s, TCG_REG_CALL_STACK, stack_adjust);
}
/* label2: */
@@ -1901,10 +1901,10 @@ static int tcg_target_callee_save_regs[] = {
TCG_REG_RBX,
TCG_REG_R12,
TCG_REG_R13,
- /* TCG_REG_R14, */ /* Currently used for the global env. */
+ TCG_REG_R14, /* Currently used for the global env. */
TCG_REG_R15,
#else
- /* TCG_REG_EBP, */ /* Currently used for the global env. */
+ TCG_REG_EBP, /* Currently used for the global env. */
TCG_REG_EBX,
TCG_REG_ESI,
TCG_REG_EDI,
@@ -1918,28 +1918,34 @@ static void tcg_target_qemu_prologue(TCGContext *s)
/* TB prologue */
- /* Save all callee saved registers. */
- for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) {
- tcg_out_push(s, tcg_target_callee_save_regs[i]);
- }
-
- /* Reserve some stack space. */
+ /* Reserve some stack space, also for TCG temps. */
push_size = 1 + ARRAY_SIZE(tcg_target_callee_save_regs);
push_size *= TCG_TARGET_REG_BITS / 8;
- frame_size = push_size + TCG_STATIC_CALL_ARGS_SIZE;
+ frame_size = push_size + TCG_STATIC_CALL_ARGS_SIZE +
+ CPU_TEMP_BUF_NLONGS * sizeof(long);
frame_size = (frame_size + TCG_TARGET_STACK_ALIGN - 1) &
~(TCG_TARGET_STACK_ALIGN - 1);
stack_addend = frame_size - push_size;
+ tcg_set_frame(s, TCG_REG_CALL_STACK, TCG_STATIC_CALL_ARGS_SIZE,
+ CPU_TEMP_BUF_NLONGS * sizeof(long));
+
+ /* Save all callee saved registers. */
+ for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) {
+ tcg_out_push(s, tcg_target_callee_save_regs[i]);
+ }
+
tcg_out_addi(s, TCG_REG_ESP, -stack_addend);
+ tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
+
/* jmp *tb. */
- tcg_out_modrm(s, OPC_GRP5, EXT5_JMPN_Ev, tcg_target_call_iarg_regs[0]);
+ tcg_out_modrm(s, OPC_GRP5, EXT5_JMPN_Ev, tcg_target_call_iarg_regs[1]);
/* TB epilogue */
tb_ret_addr = s->code_ptr;
- tcg_out_addi(s, TCG_REG_ESP, stack_addend);
+ tcg_out_addi(s, TCG_REG_CALL_STACK, stack_addend);
for (i = ARRAY_SIZE(tcg_target_callee_save_regs) - 1; i >= 0; i--) {
tcg_out_pop(s, tcg_target_callee_save_regs[i]);
@@ -1976,7 +1982,7 @@ static void tcg_target_init(TCGContext *s)
}
tcg_regset_clear(s->reserved_regs);
- tcg_regset_set_reg(s->reserved_regs, TCG_REG_ESP);
+ tcg_regset_set_reg(s->reserved_regs, TCG_REG_CALL_STACK);
tcg_add_target_add_op_defs(x86_op_defs);
}
diff --git a/tcg/ia64/tcg-target.c b/tcg/ia64/tcg-target.c
index 8dac7f72fd..6386a5bf27 100644
--- a/tcg/ia64/tcg-target.c
+++ b/tcg/ia64/tcg-target.c
@@ -2292,7 +2292,7 @@ static void tcg_target_qemu_prologue(TCGContext *s)
tcg_opc_m34(TCG_REG_P0, OPC_ALLOC_M34,
TCG_REG_R33, 32, 24, 0),
tcg_opc_i21(TCG_REG_P0, OPC_MOV_I21,
- TCG_REG_B6, TCG_REG_R32, 0),
+ TCG_REG_B6, TCG_REG_R33, 0),
tcg_opc_i22(TCG_REG_P0, OPC_MOV_I22,
TCG_REG_R32, TCG_REG_B0));
@@ -2308,7 +2308,8 @@ static void tcg_target_qemu_prologue(TCGContext *s)
}
tcg_out_bundle(s, miB,
- tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
+ tcg_opc_m48(TCG_REG_P0, OPC_MOV_I21,
+ TCG_REG_AREG0, TCG_REG_R32, 0),
tcg_opc_a4 (TCG_REG_P0, OPC_ADDS_A4,
TCG_REG_R12, -frame_size, TCG_REG_R12),
tcg_opc_b4 (TCG_REG_P0, OPC_BR_SPTK_MANY_B4, TCG_REG_B6));
@@ -2387,4 +2388,6 @@ static void tcg_target_init(TCGContext *s)
tcg_regset_set_reg(s->reserved_regs, TCG_REG_R6);
tcg_add_target_add_op_defs(ia64_op_defs);
+ tcg_set_frame(s, TCG_AREG0, offsetof(CPUState, temp_buf),
+ CPU_TEMP_BUF_NLONGS * sizeof(long));
}
diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c
index e04b0dc32f..12ff9d5259 100644
--- a/tcg/mips/tcg-target.c
+++ b/tcg/mips/tcg-target.c
@@ -1452,9 +1452,7 @@ static const TCGTargetOpDef mips_op_defs[] = {
};
static int tcg_target_callee_save_regs[] = {
-#if 0 /* used for the global env (TCG_AREG0), so no need to save */
- TCG_REG_S0,
-#endif
+ TCG_REG_S0, /* used for the global env (TCG_AREG0) */
TCG_REG_S1,
TCG_REG_S2,
TCG_REG_S3,
@@ -1486,8 +1484,8 @@ static void tcg_target_qemu_prologue(TCGContext *s)
}
/* Call generated code */
- tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_A0, 0);
- tcg_out_nop(s);
+ tcg_out_opc_reg(s, OPC_JR, 0, tcg_target_call_iarg_regs[1]), 0);
+ tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
tb_ret_addr = s->code_ptr;
/* TB epilogue */
@@ -1530,4 +1528,6 @@ static void tcg_target_init(TCGContext *s)
tcg_regset_set_reg(s->reserved_regs, TCG_REG_SP); /* stack pointer */
tcg_add_target_add_op_defs(mips_op_defs);
+ tcg_set_frame(s, TCG_AREG0, offsetof(CPUState, temp_buf),
+ CPU_TEMP_BUF_NLONGS * sizeof(long));
}
diff --git a/tcg/ppc/tcg-target.c b/tcg/ppc/tcg-target.c
index 7970268e5a..0cd887383d 100644
--- a/tcg/ppc/tcg-target.c
+++ b/tcg/ppc/tcg-target.c
@@ -160,8 +160,7 @@ static const int tcg_target_callee_save_regs[] = {
TCG_REG_R24,
TCG_REG_R25,
TCG_REG_R26,
- /* TCG_REG_R27, */ /* currently used for the global env, so no
- need to save */
+ TCG_REG_R27, /* currently used for the global env */
TCG_REG_R28,
TCG_REG_R29,
TCG_REG_R30,
@@ -939,7 +938,8 @@ static void tcg_target_qemu_prologue (TCGContext *s)
}
#endif
- tcg_out32 (s, MTSPR | RS (3) | CTR);
+ tcg_out_mov (s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
+ tcg_out32 (s, MTSPR | RS (tcg_target_call_iarg_regs[1]) | CTR);
tcg_out32 (s, BCCTR | BO_ALWAYS);
tb_ret_addr = s->code_ptr;
@@ -982,11 +982,6 @@ static void ppc_addi (TCGContext *s, int rt, int ra, tcg_target_long si)
}
}
-static void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val)
-{
- ppc_addi (s, reg, reg, val);
-}
-
static void tcg_out_cmp (TCGContext *s, int cond, TCGArg arg1, TCGArg arg2,
int const_arg2, int cr)
{
@@ -1919,4 +1914,6 @@ static void tcg_target_init(TCGContext *s)
#endif
tcg_add_target_add_op_defs(ppc_op_defs);
+ tcg_set_frame(s, TCG_AREG0, offsetof(CPUState, temp_buf),
+ CPU_TEMP_BUF_NLONGS * sizeof(long));
}
diff --git a/tcg/ppc64/tcg-target.c b/tcg/ppc64/tcg-target.c
index ebbee343fd..065c710f33 100644
--- a/tcg/ppc64/tcg-target.c
+++ b/tcg/ppc64/tcg-target.c
@@ -151,8 +151,7 @@ static const int tcg_target_callee_save_regs[] = {
TCG_REG_R24,
TCG_REG_R25,
TCG_REG_R26,
- /* TCG_REG_R27, */ /* currently used for the global env, so no
- need to save */
+ TCG_REG_R27, /* currently used for the global env */
TCG_REG_R28,
TCG_REG_R29,
TCG_REG_R30,
@@ -905,7 +904,8 @@ static void tcg_target_qemu_prologue (TCGContext *s)
}
#endif
- tcg_out32 (s, MTSPR | RS (3) | CTR);
+ tcg_out_mov (s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
+ tcg_out32 (s, MTSPR | RS (tcg_target_call_iarg_regs[1]) | CTR);
tcg_out32 (s, BCCTR | BO_ALWAYS);
/* Epilogue */
@@ -968,11 +968,6 @@ static void ppc_addi64 (TCGContext *s, int rt, int ra, tcg_target_long si)
}
}
-static void tcg_out_addi (TCGContext *s, int reg, tcg_target_long val)
-{
- ppc_addi64 (s, reg, reg, val);
-}
-
static void tcg_out_cmp (TCGContext *s, int cond, TCGArg arg1, TCGArg arg2,
int const_arg2, int cr, int arch64)
{
@@ -1696,4 +1691,6 @@ static void tcg_target_init (TCGContext *s)
tcg_regset_set_reg (s->reserved_regs, TCG_REG_R13);
tcg_add_target_add_op_defs (ppc_op_defs);
+ tcg_set_frame(s, TCG_AREG0, offsetof(CPUState, temp_buf),
+ CPU_TEMP_BUF_NLONGS * sizeof(long));
}
diff --git a/tcg/s390/tcg-target.c b/tcg/s390/tcg-target.c
index 450fcabd70..2fc5646400 100644
--- a/tcg/s390/tcg-target.c
+++ b/tcg/s390/tcg-target.c
@@ -2291,6 +2291,8 @@ static void tcg_target_init(TCGContext *s)
tcg_regset_set_reg(s->reserved_regs, TCG_REG_CALL_STACK);
tcg_add_target_add_op_defs(s390_op_defs);
+ tcg_set_frame(s, TCG_AREG0, offsetof(CPUState, temp_buf),
+ CPU_TEMP_BUF_NLONGS * sizeof(long));
}
static void tcg_target_qemu_prologue(TCGContext *s)
@@ -2306,8 +2308,9 @@ static void tcg_target_qemu_prologue(TCGContext *s)
tcg_regset_set_reg(s->reserved_regs, TCG_GUEST_BASE_REG);
}
- /* br %r2 (go to TB) */
- tcg_out_insn(s, RR, BCR, S390_CC_ALWAYS, TCG_REG_R2);
+ tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
+ /* br %r3 (go to TB) */
+ tcg_out_insn(s, RR, BCR, S390_CC_ALWAYS, tcg_target_call_iarg_regs[1]);
tb_ret_addr = s->code_ptr;
diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c
index 5f1353adf8..ac76e1198d 100644
--- a/tcg/sparc/tcg-target.c
+++ b/tcg/sparc/tcg-target.c
@@ -693,11 +693,14 @@ static void tcg_out_setcond2_i32(TCGContext *s, TCGCond cond, TCGArg ret,
/* Generate global QEMU prologue and epilogue code */
static void tcg_target_qemu_prologue(TCGContext *s)
{
+ tcg_set_frame(s, TCG_REG_I6, TCG_TARGET_CALL_STACK_OFFSET,
+ CPU_TEMP_BUF_NLONGS * (int)sizeof(long));
tcg_out32(s, SAVE | INSN_RD(TCG_REG_O6) | INSN_RS1(TCG_REG_O6) |
- INSN_IMM13(-TCG_TARGET_STACK_MINFRAME));
- tcg_out32(s, JMPL | INSN_RD(TCG_REG_G0) | INSN_RS1(TCG_REG_I0) |
+ INSN_IMM13(-(TCG_TARGET_STACK_MINFRAME +
+ CPU_TEMP_BUF_NLONGS * (int)sizeof(long))));
+ tcg_out32(s, JMPL | INSN_RD(TCG_REG_G0) | INSN_RS1(TCG_REG_I1) |
INSN_RS2(TCG_REG_G0));
- tcg_out_nop(s);
+ tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, TCG_REG_I0);
}
#if defined(CONFIG_SOFTMMU)
diff --git a/tcg/tcg.c b/tcg/tcg.c
index 184c208980..c05413baa4 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -54,7 +54,6 @@
instructions */
#define NO_CPU_IO_DEFS
#include "cpu.h"
-#include "exec-all.h"
#include "tcg-op.h"
#include "elf.h"
@@ -1440,13 +1439,19 @@ static void temp_allocate_frame(TCGContext *s, int temp)
{
TCGTemp *ts;
ts = &s->temps[temp];
- s->current_frame_offset = (s->current_frame_offset + sizeof(tcg_target_long) - 1) & ~(sizeof(tcg_target_long) - 1);
- if (s->current_frame_offset + sizeof(tcg_target_long) > s->frame_end)
+#ifndef __sparc_v9__ /* Sparc64 stack is accessed with offset of 2047 */
+ s->current_frame_offset = (s->current_frame_offset +
+ (tcg_target_long)sizeof(tcg_target_long) - 1) &
+ ~(sizeof(tcg_target_long) - 1);
+#endif
+ if (s->current_frame_offset + (tcg_target_long)sizeof(tcg_target_long) >
+ s->frame_end) {
tcg_abort();
+ }
ts->mem_offset = s->current_frame_offset;
ts->mem_reg = s->frame_reg;
ts->mem_allocated = 1;
- s->current_frame_offset += sizeof(tcg_target_long);
+ s->current_frame_offset += (tcg_target_long)sizeof(tcg_target_long);
}
/* free register 'reg' by spilling the corresponding temporary if necessary */
@@ -1842,13 +1847,14 @@ static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
nb_regs = nb_params;
/* assign stack slots first */
- /* XXX: preallocate call stack */
call_stack_size = (nb_params - nb_regs) * sizeof(tcg_target_long);
call_stack_size = (call_stack_size + TCG_TARGET_STACK_ALIGN - 1) &
~(TCG_TARGET_STACK_ALIGN - 1);
allocate_args = (call_stack_size > TCG_STATIC_CALL_ARGS_SIZE);
if (allocate_args) {
- tcg_out_addi(s, TCG_REG_CALL_STACK, -STACK_DIR(call_stack_size));
+ /* XXX: if more than TCG_STATIC_CALL_ARGS_SIZE is needed,
+ preallocate call stack */
+ tcg_abort();
}
stack_offset = TCG_TARGET_CALL_STACK_OFFSET;
@@ -1967,10 +1973,6 @@ static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
}
tcg_out_op(s, opc, &func_arg, &const_func_arg);
-
- if (allocate_args) {
- tcg_out_addi(s, TCG_REG_CALL_STACK, STACK_DIR(call_stack_size));
- }
/* assign output registers and emit moves if needed */
for(i = 0; i < nb_oargs; i++) {
diff --git a/tcg/tcg.h b/tcg/tcg.h
index 3647390c5f..a2dd8b892a 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -515,8 +515,9 @@ TCGv_i64 tcg_const_local_i64(int64_t val);
extern uint8_t code_gen_prologue[];
#if defined(_ARCH_PPC) && !defined(_ARCH_PPC64)
-#define tcg_qemu_tb_exec(tb_ptr) \
- ((long REGPARM __attribute__ ((longcall)) (*)(void *))code_gen_prologue)(tb_ptr)
+#define tcg_qemu_tb_exec(env, tb_ptr) \
+ ((long REGPARM __attribute__ ((longcall)) (*)(void *, void *))code_gen_prologue)(env, tb_ptr)
#else
-#define tcg_qemu_tb_exec(tb_ptr) ((long REGPARM (*)(void *))code_gen_prologue)(tb_ptr)
+#define tcg_qemu_tb_exec(env, tb_ptr) \
+ ((long REGPARM (*)(void *, void *))code_gen_prologue)(env, tb_ptr)
#endif
diff --git a/trace-events b/trace-events
index f1230f1e33..bebf612fe9 100644
--- a/trace-events
+++ b/trace-events
@@ -396,6 +396,7 @@ disable milkymist_vgafb_memory_write(uint32_t addr, uint32_t value) "addr %08x v
# xen-all.c
disable xen_ram_alloc(unsigned long ram_addr, unsigned long size) "requested: %#lx, size %#lx"
+disable xen_client_set_memory(uint64_t start_addr, unsigned long size, unsigned long phys_offset, bool log_dirty) "%#"PRIx64" size %#lx, offset %#lx, log_dirty %i"
# xen-mapcache.c
disable qemu_map_cache(uint64_t phys_addr) "want %#"PRIx64""
@@ -406,3 +407,6 @@ disable xen_unmap_block(void* addr, unsigned long size) "%p, size %#lx"
# exec.c
disable qemu_put_ram_ptr(void* addr) "%p"
+
+# hw/xen_platform.c
+disable xen_platform_log(char *s) "xen platform: %s"
diff --git a/translate-all.c b/translate-all.c
index 2ca190ca8f..041c108948 100644
--- a/translate-all.c
+++ b/translate-all.c
@@ -26,7 +26,6 @@
#define NO_CPU_IO_DEFS
#include "cpu.h"
-#include "exec-all.h"
#include "disas.h"
#include "tcg.h"
#include "qemu-timer.h"
@@ -44,8 +43,6 @@ uint8_t gen_opc_instr_start[OPC_BUF_SIZE];
void cpu_gen_init(void)
{
tcg_context_init(&tcg_ctx);
- tcg_set_frame(&tcg_ctx, TCG_AREG0, offsetof(CPUState, temp_buf),
- CPU_TEMP_BUF_NLONGS * sizeof(long));
}
/* return non zero if the very first instruction is invalid so that
diff --git a/ui/vnc-enc-tight.c b/ui/vnc-enc-tight.c
index 87fdf35d3e..5c02803411 100644
--- a/ui/vnc-enc-tight.c
+++ b/ui/vnc-enc-tight.c
@@ -28,7 +28,15 @@
#include "config-host.h"
+/* This needs to be before jpeglib.h line because of conflict with
+ INT32 definitions between jmorecfg.h (included by jpeglib.h) and
+ Win32 basetsd.h (included by windows.h). */
+#include "qemu-common.h"
+
#ifdef CONFIG_VNC_PNG
+/* The following define is needed by pngconf.h. Otherwise it won't compile,
+ because setjmp.h was already included by qemu-common.h. */
+#define PNG_SKIP_SETJMP_CHECK
#include <png.h>
#endif
#ifdef CONFIG_VNC_JPEG
@@ -36,8 +44,6 @@
#include <jpeglib.h>
#endif
-#include "qemu-common.h"
-
#include "bswap.h"
#include "qint.h"
#include "vnc.h"
diff --git a/usb-bsd.c b/usb-bsd.c
index c1bcc4a1da..3b97eb491b 100644
--- a/usb-bsd.c
+++ b/usb-bsd.c
@@ -367,8 +367,10 @@ USBDevice *usb_host_device_open(const char *devname)
if (dev_info.udi_speed == 1) {
dev->dev.speed = USB_SPEED_LOW - 1;
+ dev->dev.speedmask = USB_SPEED_MASK_LOW;
} else {
dev->dev.speed = USB_SPEED_FULL - 1;
+ dev->dev.speedmask = USB_SPEED_MASK_FULL;
}
if (strncmp(dev_info.udi_product, "product", 7) != 0) {
diff --git a/usb-linux.c b/usb-linux.c
index 5d2ec5c5c7..1a2deb35c9 100644
--- a/usb-linux.c
+++ b/usb-linux.c
@@ -85,7 +85,6 @@ static int usb_fs_type;
/* endpoint association data */
#define ISO_FRAME_DESC_PER_URB 32
-#define ISO_URB_COUNT 3
#define INVALID_EP_TYPE 255
/* devio.c limits single requests to 16k */
@@ -101,6 +100,7 @@ struct endp_data {
int iso_urb_idx;
int iso_buffer_used;
int max_packet_size;
+ int inflight;
};
struct USBAutoFilter {
@@ -120,6 +120,7 @@ typedef struct USBHostDevice {
int configuration;
int ninterfaces;
int closing;
+ uint32_t iso_urb_count;
Notifier exit;
struct endp_data endp_table[MAX_ENDPOINTS];
@@ -142,74 +143,91 @@ static void usb_host_auto_check(void *unused);
static int usb_host_read_file(char *line, size_t line_size,
const char *device_file, const char *device_name);
+static struct endp_data *get_endp(USBHostDevice *s, int ep)
+{
+ return s->endp_table + ep - 1;
+}
+
static int is_isoc(USBHostDevice *s, int ep)
{
- return s->endp_table[ep - 1].type == USBDEVFS_URB_TYPE_ISO;
+ return get_endp(s, ep)->type == USBDEVFS_URB_TYPE_ISO;
}
static int is_valid(USBHostDevice *s, int ep)
{
- return s->endp_table[ep - 1].type != INVALID_EP_TYPE;
+ return get_endp(s, ep)->type != INVALID_EP_TYPE;
}
static int is_halted(USBHostDevice *s, int ep)
{
- return s->endp_table[ep - 1].halted;
+ return get_endp(s, ep)->halted;
}
static void clear_halt(USBHostDevice *s, int ep)
{
- s->endp_table[ep - 1].halted = 0;
+ get_endp(s, ep)->halted = 0;
}
static void set_halt(USBHostDevice *s, int ep)
{
- s->endp_table[ep - 1].halted = 1;
+ get_endp(s, ep)->halted = 1;
}
static int is_iso_started(USBHostDevice *s, int ep)
{
- return s->endp_table[ep - 1].iso_started;
+ return get_endp(s, ep)->iso_started;
}
static void clear_iso_started(USBHostDevice *s, int ep)
{
- s->endp_table[ep - 1].iso_started = 0;
+ get_endp(s, ep)->iso_started = 0;
}
static void set_iso_started(USBHostDevice *s, int ep)
{
- s->endp_table[ep - 1].iso_started = 1;
+ struct endp_data *e = get_endp(s, ep);
+ if (!e->iso_started) {
+ e->iso_started = 1;
+ e->inflight = 0;
+ }
+}
+
+static int change_iso_inflight(USBHostDevice *s, int ep, int value)
+{
+ struct endp_data *e = get_endp(s, ep);
+
+ e->inflight += value;
+ return e->inflight;
}
static void set_iso_urb(USBHostDevice *s, int ep, AsyncURB *iso_urb)
{
- s->endp_table[ep - 1].iso_urb = iso_urb;
+ get_endp(s, ep)->iso_urb = iso_urb;
}
static AsyncURB *get_iso_urb(USBHostDevice *s, int ep)
{
- return s->endp_table[ep - 1].iso_urb;
+ return get_endp(s, ep)->iso_urb;
}
static void set_iso_urb_idx(USBHostDevice *s, int ep, int i)
{
- s->endp_table[ep - 1].iso_urb_idx = i;
+ get_endp(s, ep)->iso_urb_idx = i;
}
static int get_iso_urb_idx(USBHostDevice *s, int ep)
{
- return s->endp_table[ep - 1].iso_urb_idx;
+ return get_endp(s, ep)->iso_urb_idx;
}
static void set_iso_buffer_used(USBHostDevice *s, int ep, int i)
{
- s->endp_table[ep - 1].iso_buffer_used = i;
+ get_endp(s, ep)->iso_buffer_used = i;
}
static int get_iso_buffer_used(USBHostDevice *s, int ep)
{
- return s->endp_table[ep - 1].iso_buffer_used;
+ return get_endp(s, ep)->iso_buffer_used;
}
static void set_max_packet_size(USBHostDevice *s, int ep, uint8_t *descriptor)
@@ -223,14 +241,12 @@ static void set_max_packet_size(USBHostDevice *s, int ep, uint8_t *descriptor)
case 2: microframes = 3; break;
default: microframes = 1; break;
}
- DPRINTF("husb: max packet size: 0x%x -> %d x %d\n",
- raw, microframes, size);
- s->endp_table[ep - 1].max_packet_size = size * microframes;
+ get_endp(s, ep)->max_packet_size = size * microframes;
}
static int get_max_packet_size(USBHostDevice *s, int ep)
{
- return s->endp_table[ep - 1].max_packet_size;
+ return get_endp(s, ep)->max_packet_size;
}
/*
@@ -279,6 +295,7 @@ static void async_complete(void *opaque)
{
USBHostDevice *s = opaque;
AsyncURB *aurb;
+ int urbs = 0;
while (1) {
USBPacket *p;
@@ -286,6 +303,9 @@ static void async_complete(void *opaque)
int r = ioctl(s->fd, USBDEVFS_REAPURBNDELAY, &aurb);
if (r < 0) {
if (errno == EAGAIN) {
+ if (urbs > 2) {
+ fprintf(stderr, "husb: %d iso urbs finished at once\n", urbs);
+ }
return;
}
if (errno == ENODEV && !s->closing) {
@@ -303,10 +323,16 @@ static void async_complete(void *opaque)
/* If this is a buffered iso urb mark it as complete and don't do
anything else (it is handled further in usb_host_handle_iso_data) */
if (aurb->iso_frame_idx == -1) {
+ int inflight;
if (aurb->urb.status == -EPIPE) {
set_halt(s, aurb->urb.endpoint & 0xf);
}
aurb->iso_frame_idx = 0;
+ urbs++;
+ inflight = change_iso_inflight(s, aurb->urb.endpoint & 0xf, -1);
+ if (inflight == 0 && is_iso_started(s, aurb->urb.endpoint & 0xf)) {
+ fprintf(stderr, "husb: out of buffers for iso stream\n");
+ }
continue;
}
@@ -502,8 +528,8 @@ static AsyncURB *usb_host_alloc_iso(USBHostDevice *s, uint8_t ep, int in)
AsyncURB *aurb;
int i, j, len = get_max_packet_size(s, ep);
- aurb = qemu_mallocz(ISO_URB_COUNT * sizeof(*aurb));
- for (i = 0; i < ISO_URB_COUNT; i++) {
+ aurb = qemu_mallocz(s->iso_urb_count * sizeof(*aurb));
+ for (i = 0; i < s->iso_urb_count; i++) {
aurb[i].urb.endpoint = ep;
aurb[i].urb.buffer_length = ISO_FRAME_DESC_PER_URB * len;
aurb[i].urb.buffer = qemu_malloc(aurb[i].urb.buffer_length);
@@ -533,7 +559,7 @@ static void usb_host_stop_n_free_iso(USBHostDevice *s, uint8_t ep)
return;
}
- for (i = 0; i < ISO_URB_COUNT; i++) {
+ for (i = 0; i < s->iso_urb_count; i++) {
/* in flight? */
if (aurb[i].iso_frame_idx == -1) {
ret = ioctl(s->fd, USBDEVFS_DISCARDURB, &aurb[i]);
@@ -551,7 +577,7 @@ static void usb_host_stop_n_free_iso(USBHostDevice *s, uint8_t ep)
async_complete(s);
}
- for (i = 0; i < ISO_URB_COUNT; i++) {
+ for (i = 0; i < s->iso_urb_count; i++) {
qemu_free(aurb[i].urb.buffer);
}
@@ -636,7 +662,7 @@ static int usb_host_handle_iso_data(USBHostDevice *s, USBPacket *p, int in)
}
aurb[i].iso_frame_idx++;
if (aurb[i].iso_frame_idx == ISO_FRAME_DESC_PER_URB) {
- i = (i + 1) % ISO_URB_COUNT;
+ i = (i + 1) % s->iso_urb_count;
set_iso_urb_idx(s, p->devep, i);
}
} else {
@@ -649,7 +675,7 @@ static int usb_host_handle_iso_data(USBHostDevice *s, USBPacket *p, int in)
if (is_iso_started(s, p->devep)) {
/* (Re)-submit all fully consumed / filled urbs */
- for (i = 0; i < ISO_URB_COUNT; i++) {
+ for (i = 0; i < s->iso_urb_count; i++) {
if (aurb[i].iso_frame_idx == ISO_FRAME_DESC_PER_URB) {
ret = ioctl(s->fd, USBDEVFS_SUBMITURB, &aurb[i]);
if (ret < 0) {
@@ -667,6 +693,7 @@ static int usb_host_handle_iso_data(USBHostDevice *s, USBPacket *p, int in)
break;
}
aurb[i].iso_frame_idx = -1;
+ change_iso_inflight(s, p->devep, +1);
}
}
}
@@ -1061,6 +1088,42 @@ static int usb_linux_update_endp_table(USBHostDevice *s)
return 0;
}
+/*
+ * Check if we can safely redirect a usb2 device to a usb1 virtual controller,
+ * this function assumes this is safe, if:
+ * 1) There are no isoc endpoints
+ * 2) There are no interrupt endpoints with a max_packet_size > 64
+ * Note bulk endpoints with a max_packet_size > 64 in theory also are not
+ * usb1 compatible, but in practice this seems to work fine.
+ */
+static int usb_linux_full_speed_compat(USBHostDevice *dev)
+{
+ int i, packet_size;
+
+ /*
+ * usb_linux_update_endp_table only registers info about ep in the current
+ * interface altsettings, so we need to parse the descriptors again.
+ */
+ for (i = 0; (i + 5) < dev->descr_len; i += dev->descr[i]) {
+ if (dev->descr[i + 1] == USB_DT_ENDPOINT) {
+ switch (dev->descr[i + 3] & 0x3) {
+ case 0x00: /* CONTROL */
+ break;
+ case 0x01: /* ISO */
+ return 0;
+ case 0x02: /* BULK */
+ break;
+ case 0x03: /* INTERRUPT */
+ packet_size = dev->descr[i + 4] + (dev->descr[i + 5] << 8);
+ if (packet_size > 64)
+ return 0;
+ break;
+ }
+ }
+ }
+ return 1;
+}
+
static int usb_host_open(USBHostDevice *dev, int bus_num,
int addr, char *port, const char *prod_name, int speed)
{
@@ -1140,6 +1203,10 @@ static int usb_host_open(USBHostDevice *dev, int bus_num,
}
}
dev->dev.speed = speed;
+ dev->dev.speedmask = (1 << speed);
+ if (dev->dev.speed == USB_SPEED_HIGH && usb_linux_full_speed_compat(dev)) {
+ dev->dev.speedmask |= USB_SPEED_MASK_FULL;
+ }
printf("husb: grabbed usb device %d.%d\n", bus_num, addr);
@@ -1151,10 +1218,14 @@ static int usb_host_open(USBHostDevice *dev, int bus_num,
prod_name);
}
+ ret = usb_device_attach(&dev->dev);
+ if (ret) {
+ goto fail;
+ }
+
/* USB devio uses 'write' flag to check for async completions */
qemu_set_fd_handler(dev->fd, NULL, async_complete, dev);
- usb_device_attach(&dev->dev);
return 0;
fail:
@@ -1230,6 +1301,7 @@ static struct USBDeviceInfo usb_host_dev_info = {
DEFINE_PROP_STRING("hostport", USBHostDevice, match.port),
DEFINE_PROP_HEX32("vendorid", USBHostDevice, match.vendor_id, 0),
DEFINE_PROP_HEX32("productid", USBHostDevice, match.product_id, 0),
+ DEFINE_PROP_UINT32("isobufs", USBHostDevice, iso_urb_count, 4),
DEFINE_PROP_END_OF_LIST(),
},
};
diff --git a/user-exec.c b/user-exec.c
index d4a6abb8f5..02c2f8ba43 100644
--- a/user-exec.c
+++ b/user-exec.c
@@ -37,13 +37,14 @@
//#define DEBUG_SIGNAL
+static void exception_action(CPUState *env1)
+{
#if defined(TARGET_I386)
-#define EXCEPTION_ACTION \
- raise_exception_err(env->exception_index, env->error_code)
+ raise_exception_err(env1->exception_index, env1->error_code);
#else
-#define EXCEPTION_ACTION \
- cpu_loop_exit()
+ cpu_loop_exit(env1);
#endif
+}
/* exit the current TB from a signal handler. The host registers are
restored in a state compatible with the CPU emulator
@@ -118,7 +119,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
/* we restore the process signal mask as the sigreturn should
do it (XXX: use sigsetjmp) */
sigprocmask(SIG_SETMASK, old_set, NULL);
- EXCEPTION_ACTION;
+ exception_action(env);
/* never comes here */
return 1;
diff --git a/vl.c b/vl.c
index dbdec7199a..52402a2b73 100644
--- a/vl.c
+++ b/vl.c
@@ -1253,7 +1253,7 @@ void qemu_unregister_reset(QEMUResetHandler *func, void *opaque)
}
}
-void qemu_system_reset(void)
+void qemu_system_reset(bool report)
{
QEMUResetEntry *re, *nre;
@@ -1261,7 +1261,9 @@ void qemu_system_reset(void)
QTAILQ_FOREACH_SAFE(re, &reset_handlers, entry, nre) {
re->func(re->opaque);
}
- monitor_protocol_event(QEVENT_RESET, NULL);
+ if (report) {
+ monitor_protocol_event(QEVENT_RESET, NULL);
+ }
cpu_synchronize_all_post_reset();
}
@@ -1403,7 +1405,7 @@ static void main_loop(void)
if (qemu_reset_requested()) {
pause_all_vcpus();
cpu_synchronize_all_states();
- qemu_system_reset();
+ qemu_system_reset(VMRESET_REPORT);
resume_all_vcpus();
}
if (qemu_powerdown_requested()) {
@@ -3293,7 +3295,7 @@ int main(int argc, char **argv, char **envp)
qemu_register_reset(qbus_reset_all_fn, sysbus_get_default());
qemu_run_machine_init_done_notifiers();
- qemu_system_reset();
+ qemu_system_reset(VMRESET_SILENT);
if (loadvm) {
if (load_vmstate(loadvm) < 0) {
autostart = 0;
diff --git a/xen-all.c b/xen-all.c
index 0eac202d4e..fcb106f815 100644
--- a/xen-all.c
+++ b/xen-all.c
@@ -13,6 +13,7 @@
#include "hw/xen_common.h"
#include "hw/xen_backend.h"
+#include "range.h"
#include "xen-mapcache.h"
#include "trace.h"
@@ -54,6 +55,14 @@ static inline ioreq_t *xen_vcpu_ioreq(shared_iopage_t *shared_page, int vcpu)
#define BUFFER_IO_MAX_DELAY 100
+typedef struct XenPhysmap {
+ target_phys_addr_t start_addr;
+ ram_addr_t size;
+ target_phys_addr_t phys_offset;
+
+ QLIST_ENTRY(XenPhysmap) list;
+} XenPhysmap;
+
typedef struct XenIOState {
shared_iopage_t *shared_page;
buffered_iopage_t *buffered_io_page;
@@ -66,6 +75,9 @@ typedef struct XenIOState {
int send_vcpu;
struct xs_handle *xenstore;
+ CPUPhysMemoryClient client;
+ QLIST_HEAD(, XenPhysmap) physmap;
+ const XenPhysmap *log_for_dirtybit;
Notifier exit;
} XenIOState;
@@ -178,6 +190,270 @@ void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size)
qemu_free(pfn_list);
}
+static XenPhysmap *get_physmapping(XenIOState *state,
+ target_phys_addr_t start_addr, ram_addr_t size)
+{
+ XenPhysmap *physmap = NULL;
+
+ start_addr &= TARGET_PAGE_MASK;
+
+ QLIST_FOREACH(physmap, &state->physmap, list) {
+ if (range_covers_byte(physmap->start_addr, physmap->size, start_addr)) {
+ return physmap;
+ }
+ }
+ return NULL;
+}
+
+#if CONFIG_XEN_CTRL_INTERFACE_VERSION >= 340
+static int xen_add_to_physmap(XenIOState *state,
+ target_phys_addr_t start_addr,
+ ram_addr_t size,
+ target_phys_addr_t phys_offset)
+{
+ unsigned long i = 0;
+ int rc = 0;
+ XenPhysmap *physmap = NULL;
+ target_phys_addr_t pfn, start_gpfn;
+ RAMBlock *block;
+
+ if (get_physmapping(state, start_addr, size)) {
+ return 0;
+ }
+ if (size <= 0) {
+ return -1;
+ }
+
+ /* Xen can only handle a single dirty log region for now and we want
+ * the linear framebuffer to be that region.
+ * Avoid tracking any regions that is not videoram and avoid tracking
+ * the legacy vga region. */
+ QLIST_FOREACH(block, &ram_list.blocks, next) {
+ if (!strcmp(block->idstr, "vga.vram") && block->offset == phys_offset
+ && start_addr > 0xbffff) {
+ goto go_physmap;
+ }
+ }
+ return -1;
+
+go_physmap:
+ DPRINTF("mapping vram to %llx - %llx, from %llx\n",
+ start_addr, start_addr + size, phys_offset);
+
+ pfn = phys_offset >> TARGET_PAGE_BITS;
+ start_gpfn = start_addr >> TARGET_PAGE_BITS;
+ for (i = 0; i < size >> TARGET_PAGE_BITS; i++) {
+ unsigned long idx = pfn + i;
+ xen_pfn_t gpfn = start_gpfn + i;
+
+ rc = xc_domain_add_to_physmap(xen_xc, xen_domid, XENMAPSPACE_gmfn, idx, gpfn);
+ if (rc) {
+ DPRINTF("add_to_physmap MFN %"PRI_xen_pfn" to PFN %"
+ PRI_xen_pfn" failed: %d\n", idx, gpfn, rc);
+ return -rc;
+ }
+ }
+
+ physmap = qemu_malloc(sizeof (XenPhysmap));
+
+ physmap->start_addr = start_addr;
+ physmap->size = size;
+ physmap->phys_offset = phys_offset;
+
+ QLIST_INSERT_HEAD(&state->physmap, physmap, list);
+
+ xc_domain_pin_memory_cacheattr(xen_xc, xen_domid,
+ start_addr >> TARGET_PAGE_BITS,
+ (start_addr + size) >> TARGET_PAGE_BITS,
+ XEN_DOMCTL_MEM_CACHEATTR_WB);
+ return 0;
+}
+
+static int xen_remove_from_physmap(XenIOState *state,
+ target_phys_addr_t start_addr,
+ ram_addr_t size)
+{
+ unsigned long i = 0;
+ int rc = 0;
+ XenPhysmap *physmap = NULL;
+ target_phys_addr_t phys_offset = 0;
+
+ physmap = get_physmapping(state, start_addr, size);
+ if (physmap == NULL) {
+ return -1;
+ }
+
+ phys_offset = physmap->phys_offset;
+ size = physmap->size;
+
+ DPRINTF("unmapping vram to %llx - %llx, from %llx\n",
+ phys_offset, phys_offset + size, start_addr);
+
+ size >>= TARGET_PAGE_BITS;
+ start_addr >>= TARGET_PAGE_BITS;
+ phys_offset >>= TARGET_PAGE_BITS;
+ for (i = 0; i < size; i++) {
+ unsigned long idx = start_addr + i;
+ xen_pfn_t gpfn = phys_offset + i;
+
+ rc = xc_domain_add_to_physmap(xen_xc, xen_domid, XENMAPSPACE_gmfn, idx, gpfn);
+ if (rc) {
+ fprintf(stderr, "add_to_physmap MFN %"PRI_xen_pfn" to PFN %"
+ PRI_xen_pfn" failed: %d\n", idx, gpfn, rc);
+ return -rc;
+ }
+ }
+
+ QLIST_REMOVE(physmap, list);
+ if (state->log_for_dirtybit == physmap) {
+ state->log_for_dirtybit = NULL;
+ }
+ free(physmap);
+
+ return 0;
+}
+
+#else
+static int xen_add_to_physmap(XenIOState *state,
+ target_phys_addr_t start_addr,
+ ram_addr_t size,
+ target_phys_addr_t phys_offset)
+{
+ return -ENOSYS;
+}
+
+static int xen_remove_from_physmap(XenIOState *state,
+ target_phys_addr_t start_addr,
+ ram_addr_t size)
+{
+ return -ENOSYS;
+}
+#endif
+
+static void xen_client_set_memory(struct CPUPhysMemoryClient *client,
+ target_phys_addr_t start_addr,
+ ram_addr_t size,
+ ram_addr_t phys_offset,
+ bool log_dirty)
+{
+ XenIOState *state = container_of(client, XenIOState, client);
+ ram_addr_t flags = phys_offset & ~TARGET_PAGE_MASK;
+ hvmmem_type_t mem_type;
+
+ if (!(start_addr != phys_offset
+ && ( (log_dirty && flags < IO_MEM_UNASSIGNED)
+ || (!log_dirty && flags == IO_MEM_UNASSIGNED)))) {
+ return;
+ }
+
+ trace_xen_client_set_memory(start_addr, size, phys_offset, log_dirty);
+
+ start_addr &= TARGET_PAGE_MASK;
+ size = TARGET_PAGE_ALIGN(size);
+ phys_offset &= TARGET_PAGE_MASK;
+
+ switch (flags) {
+ case IO_MEM_RAM:
+ xen_add_to_physmap(state, start_addr, size, phys_offset);
+ break;
+ case IO_MEM_ROM:
+ mem_type = HVMMEM_ram_ro;
+ if (xc_hvm_set_mem_type(xen_xc, xen_domid, mem_type,
+ start_addr >> TARGET_PAGE_BITS,
+ size >> TARGET_PAGE_BITS)) {
+ DPRINTF("xc_hvm_set_mem_type error, addr: "TARGET_FMT_plx"\n",
+ start_addr);
+ }
+ break;
+ case IO_MEM_UNASSIGNED:
+ if (xen_remove_from_physmap(state, start_addr, size) < 0) {
+ DPRINTF("physmapping does not exist at "TARGET_FMT_plx"\n", start_addr);
+ }
+ break;
+ }
+}
+
+static int xen_sync_dirty_bitmap(XenIOState *state,
+ target_phys_addr_t start_addr,
+ ram_addr_t size)
+{
+ target_phys_addr_t npages = size >> TARGET_PAGE_BITS;
+ target_phys_addr_t vram_offset = 0;
+ const int width = sizeof(unsigned long) * 8;
+ unsigned long bitmap[(npages + width - 1) / width];
+ int rc, i, j;
+ const XenPhysmap *physmap = NULL;
+
+ physmap = get_physmapping(state, start_addr, size);
+ if (physmap == NULL) {
+ /* not handled */
+ return -1;
+ }
+
+ if (state->log_for_dirtybit == NULL) {
+ state->log_for_dirtybit = physmap;
+ } else if (state->log_for_dirtybit != physmap) {
+ return -1;
+ }
+ vram_offset = physmap->phys_offset;
+
+ rc = xc_hvm_track_dirty_vram(xen_xc, xen_domid,
+ start_addr >> TARGET_PAGE_BITS, npages,
+ bitmap);
+ if (rc) {
+ return rc;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(bitmap); i++) {
+ unsigned long map = bitmap[i];
+ while (map != 0) {
+ j = ffsl(map) - 1;
+ map &= ~(1ul << j);
+ cpu_physical_memory_set_dirty(vram_offset + (i * width + j) * TARGET_PAGE_SIZE);
+ };
+ }
+
+ return 0;
+}
+
+static int xen_log_start(CPUPhysMemoryClient *client, target_phys_addr_t phys_addr, ram_addr_t size)
+{
+ XenIOState *state = container_of(client, XenIOState, client);
+
+ return xen_sync_dirty_bitmap(state, phys_addr, size);
+}
+
+static int xen_log_stop(CPUPhysMemoryClient *client, target_phys_addr_t phys_addr, ram_addr_t size)
+{
+ XenIOState *state = container_of(client, XenIOState, client);
+
+ state->log_for_dirtybit = NULL;
+ /* Disable dirty bit tracking */
+ return xc_hvm_track_dirty_vram(xen_xc, xen_domid, 0, 0, NULL);
+}
+
+static int xen_client_sync_dirty_bitmap(struct CPUPhysMemoryClient *client,
+ target_phys_addr_t start_addr,
+ target_phys_addr_t end_addr)
+{
+ XenIOState *state = container_of(client, XenIOState, client);
+
+ return xen_sync_dirty_bitmap(state, start_addr, end_addr - start_addr);
+}
+
+static int xen_client_migration_log(struct CPUPhysMemoryClient *client,
+ int enable)
+{
+ return 0;
+}
+
+static CPUPhysMemoryClient xen_cpu_phys_memory_client = {
+ .set_memory = xen_client_set_memory,
+ .sync_dirty_bitmap = xen_client_sync_dirty_bitmap,
+ .migration_log = xen_client_migration_log,
+ .log_start = xen_log_start,
+ .log_stop = xen_log_stop,
+};
/* VCPU Operations, MMIO, IO ring ... */
@@ -452,7 +728,7 @@ static void cpu_handle_ioreq(void *opaque)
destroy_hvm_domain();
}
if (qemu_reset_requested_get()) {
- qemu_system_reset();
+ qemu_system_reset(VMRESET_REPORT);
}
}
@@ -581,6 +857,11 @@ int xen_hvm_init(void)
qemu_add_vm_change_state_handler(xen_vm_change_state_handler, state);
+ state->client = xen_cpu_phys_memory_client;
+ QLIST_INIT(&state->physmap);
+ cpu_register_phys_memory_client(&state->client);
+ state->log_for_dirtybit = NULL;
+
return 0;
}
diff --git a/xen-mapcache-stub.c b/xen-mapcache-stub.c
index 7c14b3d141..90a994dc2c 100644
--- a/xen-mapcache-stub.c
+++ b/xen-mapcache-stub.c
@@ -8,7 +8,7 @@
#include "config.h"
-#include "exec-all.h"
+#include "cpu.h"
#include "qemu-common.h"
#include "cpu-common.h"
#include "xen-mapcache.h"
@@ -22,10 +22,6 @@ uint8_t *qemu_map_cache(target_phys_addr_t phys_addr, target_phys_addr_t size, u
return qemu_get_ram_ptr(phys_addr);
}
-void qemu_map_cache_unlock(void *buffer)
-{
-}
-
ram_addr_t qemu_ram_addr_from_mapcache(void *ptr)
{
return -1;
@@ -38,7 +34,3 @@ void qemu_invalidate_map_cache(void)
void qemu_invalidate_entry(uint8_t *buffer)
{
}
-uint8_t *xen_map_block(target_phys_addr_t phys_addr, target_phys_addr_t size)
-{
- return NULL;
-}
diff --git a/xen-mapcache.c b/xen-mapcache.c
index 349cc6221d..fac47cd9be 100644
--- a/xen-mapcache.c
+++ b/xen-mapcache.c
@@ -43,14 +43,16 @@
typedef struct MapCacheEntry {
target_phys_addr_t paddr_index;
uint8_t *vaddr_base;
- DECLARE_BITMAP(valid_mapping, MCACHE_BUCKET_SIZE >> XC_PAGE_SHIFT);
+ unsigned long *valid_mapping;
uint8_t lock;
+ target_phys_addr_t size;
struct MapCacheEntry *next;
} MapCacheEntry;
typedef struct MapCacheRev {
uint8_t *vaddr_req;
target_phys_addr_t paddr_index;
+ target_phys_addr_t size;
QTAILQ_ENTRY(MapCacheRev) next;
} MapCacheRev;
@@ -68,6 +70,15 @@ typedef struct MapCache {
static MapCache *mapcache;
+static inline int test_bits(int nr, int size, const unsigned long *addr)
+{
+ unsigned long res = find_next_zero_bit(addr, size + nr, nr);
+ if (res >= nr + size)
+ return 1;
+ else
+ return 0;
+}
+
void qemu_map_cache_init(void)
{
unsigned long size;
@@ -115,11 +126,15 @@ static void qemu_remap_bucket(MapCacheEntry *entry,
err = qemu_mallocz(nb_pfn * sizeof (int));
if (entry->vaddr_base != NULL) {
- if (munmap(entry->vaddr_base, size) != 0) {
+ if (munmap(entry->vaddr_base, entry->size) != 0) {
perror("unmap fails");
exit(-1);
}
}
+ if (entry->valid_mapping != NULL) {
+ qemu_free(entry->valid_mapping);
+ entry->valid_mapping = NULL;
+ }
for (i = 0; i < nb_pfn; i++) {
pfns[i] = (address_index << (MCACHE_BUCKET_SHIFT-XC_PAGE_SHIFT)) + i;
@@ -134,6 +149,9 @@ static void qemu_remap_bucket(MapCacheEntry *entry,
entry->vaddr_base = vaddr_base;
entry->paddr_index = address_index;
+ entry->size = size;
+ entry->valid_mapping = (unsigned long *) qemu_mallocz(sizeof(unsigned long) *
+ BITS_TO_LONGS(size >> XC_PAGE_SHIFT));
bitmap_zero(entry->valid_mapping, nb_pfn);
for (i = 0; i < nb_pfn; i++) {
@@ -151,32 +169,47 @@ uint8_t *qemu_map_cache(target_phys_addr_t phys_addr, target_phys_addr_t size, u
MapCacheEntry *entry, *pentry = NULL;
target_phys_addr_t address_index = phys_addr >> MCACHE_BUCKET_SHIFT;
target_phys_addr_t address_offset = phys_addr & (MCACHE_BUCKET_SIZE - 1);
+ target_phys_addr_t __size = size;
trace_qemu_map_cache(phys_addr);
- if (address_index == mapcache->last_address_index && !lock) {
+ if (address_index == mapcache->last_address_index && !lock && !__size) {
trace_qemu_map_cache_return(mapcache->last_address_vaddr + address_offset);
return mapcache->last_address_vaddr + address_offset;
}
+ /* size is always a multiple of MCACHE_BUCKET_SIZE */
+ if ((address_offset + (__size % MCACHE_BUCKET_SIZE)) > MCACHE_BUCKET_SIZE)
+ __size += MCACHE_BUCKET_SIZE;
+ if (__size % MCACHE_BUCKET_SIZE)
+ __size += MCACHE_BUCKET_SIZE - (__size % MCACHE_BUCKET_SIZE);
+ if (!__size)
+ __size = MCACHE_BUCKET_SIZE;
+
entry = &mapcache->entry[address_index % mapcache->nr_buckets];
- while (entry && entry->lock && entry->paddr_index != address_index && entry->vaddr_base) {
+ while (entry && entry->lock && entry->vaddr_base &&
+ (entry->paddr_index != address_index || entry->size != __size ||
+ !test_bits(address_offset >> XC_PAGE_SHIFT, size >> XC_PAGE_SHIFT,
+ entry->valid_mapping))) {
pentry = entry;
entry = entry->next;
}
if (!entry) {
entry = qemu_mallocz(sizeof (MapCacheEntry));
pentry->next = entry;
- qemu_remap_bucket(entry, size ? : MCACHE_BUCKET_SIZE, address_index);
+ qemu_remap_bucket(entry, __size, address_index);
} else if (!entry->lock) {
if (!entry->vaddr_base || entry->paddr_index != address_index ||
- !test_bit(address_offset >> XC_PAGE_SHIFT, entry->valid_mapping)) {
- qemu_remap_bucket(entry, size ? : MCACHE_BUCKET_SIZE, address_index);
+ entry->size != __size ||
+ !test_bits(address_offset >> XC_PAGE_SHIFT, size >> XC_PAGE_SHIFT,
+ entry->valid_mapping)) {
+ qemu_remap_bucket(entry, __size, address_index);
}
}
- if (!test_bit(address_offset >> XC_PAGE_SHIFT, entry->valid_mapping)) {
+ if(!test_bits(address_offset >> XC_PAGE_SHIFT, size >> XC_PAGE_SHIFT,
+ entry->valid_mapping)) {
mapcache->last_address_index = -1;
trace_qemu_map_cache_return(NULL);
return NULL;
@@ -189,6 +222,7 @@ uint8_t *qemu_map_cache(target_phys_addr_t phys_addr, target_phys_addr_t size, u
entry->lock++;
reventry->vaddr_req = mapcache->last_address_vaddr + address_offset;
reventry->paddr_index = mapcache->last_address_index;
+ reventry->size = entry->size;
QTAILQ_INSERT_HEAD(&mapcache->locked_entries, reventry, next);
}
@@ -196,48 +230,18 @@ uint8_t *qemu_map_cache(target_phys_addr_t phys_addr, target_phys_addr_t size, u
return mapcache->last_address_vaddr + address_offset;
}
-void qemu_map_cache_unlock(void *buffer)
-{
- MapCacheEntry *entry = NULL, *pentry = NULL;
- MapCacheRev *reventry;
- target_phys_addr_t paddr_index;
- int found = 0;
-
- QTAILQ_FOREACH(reventry, &mapcache->locked_entries, next) {
- if (reventry->vaddr_req == buffer) {
- paddr_index = reventry->paddr_index;
- found = 1;
- break;
- }
- }
- if (!found) {
- return;
- }
- QTAILQ_REMOVE(&mapcache->locked_entries, reventry, next);
- qemu_free(reventry);
-
- entry = &mapcache->entry[paddr_index % mapcache->nr_buckets];
- while (entry && entry->paddr_index != paddr_index) {
- pentry = entry;
- entry = entry->next;
- }
- if (!entry) {
- return;
- }
- if (entry->lock > 0) {
- entry->lock--;
- }
-}
-
ram_addr_t qemu_ram_addr_from_mapcache(void *ptr)
{
+ MapCacheEntry *entry = NULL, *pentry = NULL;
MapCacheRev *reventry;
target_phys_addr_t paddr_index;
+ target_phys_addr_t size;
int found = 0;
QTAILQ_FOREACH(reventry, &mapcache->locked_entries, next) {
if (reventry->vaddr_req == ptr) {
paddr_index = reventry->paddr_index;
+ size = reventry->size;
found = 1;
break;
}
@@ -252,7 +256,17 @@ ram_addr_t qemu_ram_addr_from_mapcache(void *ptr)
return 0;
}
- return paddr_index << MCACHE_BUCKET_SHIFT;
+ entry = &mapcache->entry[paddr_index % mapcache->nr_buckets];
+ while (entry && (entry->paddr_index != paddr_index || entry->size != size)) {
+ pentry = entry;
+ entry = entry->next;
+ }
+ if (!entry) {
+ DPRINTF("Trying to find address %p that is not in the mapcache!\n", ptr);
+ return 0;
+ }
+ return (reventry->paddr_index << MCACHE_BUCKET_SHIFT) +
+ ((unsigned long) ptr - (unsigned long) entry->vaddr_base);
}
void qemu_invalidate_entry(uint8_t *buffer)
@@ -260,6 +274,7 @@ void qemu_invalidate_entry(uint8_t *buffer)
MapCacheEntry *entry = NULL, *pentry = NULL;
MapCacheRev *reventry;
target_phys_addr_t paddr_index;
+ target_phys_addr_t size;
int found = 0;
if (mapcache->last_address_vaddr == buffer) {
@@ -269,6 +284,7 @@ void qemu_invalidate_entry(uint8_t *buffer)
QTAILQ_FOREACH(reventry, &mapcache->locked_entries, next) {
if (reventry->vaddr_req == buffer) {
paddr_index = reventry->paddr_index;
+ size = reventry->size;
found = 1;
break;
}
@@ -284,7 +300,7 @@ void qemu_invalidate_entry(uint8_t *buffer)
qemu_free(reventry);
entry = &mapcache->entry[paddr_index % mapcache->nr_buckets];
- while (entry && entry->paddr_index != paddr_index) {
+ while (entry && (entry->paddr_index != paddr_index || entry->size != size)) {
pentry = entry;
entry = entry->next;
}
@@ -298,10 +314,11 @@ void qemu_invalidate_entry(uint8_t *buffer)
}
pentry->next = entry->next;
- if (munmap(entry->vaddr_base, MCACHE_BUCKET_SIZE) != 0) {
+ if (munmap(entry->vaddr_base, entry->size) != 0) {
perror("unmap fails");
exit(-1);
}
+ qemu_free(entry->valid_mapping);
qemu_free(entry);
}
@@ -328,13 +345,16 @@ void qemu_invalidate_map_cache(void)
continue;
}
- if (munmap(entry->vaddr_base, MCACHE_BUCKET_SIZE) != 0) {
+ if (munmap(entry->vaddr_base, entry->size) != 0) {
perror("unmap fails");
exit(-1);
}
entry->paddr_index = 0;
entry->vaddr_base = NULL;
+ entry->size = 0;
+ qemu_free(entry->valid_mapping);
+ entry->valid_mapping = NULL;
}
mapcache->last_address_index = -1;
@@ -342,34 +362,3 @@ void qemu_invalidate_map_cache(void)
mapcache_unlock();
}
-
-uint8_t *xen_map_block(target_phys_addr_t phys_addr, target_phys_addr_t size)
-{
- uint8_t *vaddr_base;
- xen_pfn_t *pfns;
- int *err;
- unsigned int i;
- target_phys_addr_t nb_pfn = size >> XC_PAGE_SHIFT;
-
- trace_xen_map_block(phys_addr, size);
- phys_addr >>= XC_PAGE_SHIFT;
-
- pfns = qemu_mallocz(nb_pfn * sizeof (xen_pfn_t));
- err = qemu_mallocz(nb_pfn * sizeof (int));
-
- for (i = 0; i < nb_pfn; i++) {
- pfns[i] = phys_addr + i;
- }
-
- vaddr_base = xc_map_foreign_bulk(xen_xc, xen_domid, PROT_READ|PROT_WRITE,
- pfns, err, nb_pfn);
- if (vaddr_base == NULL) {
- perror("xc_map_foreign_bulk");
- exit(-1);
- }
-
- qemu_free(pfns);
- qemu_free(err);
-
- return vaddr_base;
-}
diff --git a/xen-mapcache.h b/xen-mapcache.h
index 339444c94e..6216cc3be7 100644
--- a/xen-mapcache.h
+++ b/xen-mapcache.h
@@ -9,28 +9,12 @@
#ifndef XEN_MAPCACHE_H
#define XEN_MAPCACHE_H
-#include <sys/mman.h>
-#include "trace.h"
-
void qemu_map_cache_init(void);
uint8_t *qemu_map_cache(target_phys_addr_t phys_addr, target_phys_addr_t size, uint8_t lock);
-void qemu_map_cache_unlock(void *phys_addr);
ram_addr_t qemu_ram_addr_from_mapcache(void *ptr);
void qemu_invalidate_entry(uint8_t *buffer);
void qemu_invalidate_map_cache(void);
-uint8_t *xen_map_block(target_phys_addr_t phys_addr, target_phys_addr_t size);
-
-static inline void xen_unmap_block(void *addr, ram_addr_t size)
-{
- trace_xen_unmap_block(addr, size);
-
- if (munmap(addr, size) != 0) {
- hw_error("xen_unmap_block: %s", strerror(errno));
- }
-}
-
-
#define mapcache_lock() ((void)0)
#define mapcache_unlock() ((void)0)