Merge branch 'ppc-next' of git://repo.or.cz/qemu/agraf
* 'ppc-next' of git://repo.or.cz/qemu/agraf:
PPC: move TLBs to their own arrays
PPC: 440: Use 440 style MMU as default, so Qemu knows the MMU type
PPC: E500: Use MAS registers instead of internal TLB representation
PPC: Only set lower 32bits with mtmsr
PPC: update openbios firmware
PPC: mpc8544ds: Add hypervisor node
PPC: calculate kernel,initrd,cmdline locations dynamically
target-ppc: Handle memory-forced I/O controller access
PPC: E500: Implement reboot controller
diff --git a/MAINTAINERS b/MAINTAINERS
index 35d4496..6115e4e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -480,7 +480,7 @@
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 d3ebe57..a53a2ff 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -14,7 +14,10 @@
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 @@
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 @@
# 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-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 += 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 e9e6f89..5a62d03 100644
--- a/arm-semi.c
+++ b/arm-semi.c
@@ -440,15 +440,16 @@
/* 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 3bd75cd..5964c62 100644
--- a/audio/coreaudio.c
+++ b/audio/coreaudio.c
@@ -104,7 +104,7 @@
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 @@
&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 8d06a23..0936c7d 100644
--- a/block-migration.c
+++ b/block-migration.c
@@ -671,7 +671,7 @@
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 2c51e7c..48e1b95 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -936,7 +936,7 @@
(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 0392ca8..80d106c 100644
--- a/block/sheepdog.c
+++ b/block/sheepdog.c
@@ -444,18 +444,12 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
/* 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 @@
}
}
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 @@
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 @@
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 @@
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 @@
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 @@
}
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 @@
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 @@
/* 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 @@
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 @@
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 @@
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 @@
}
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 @@
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 @@
}
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 @@
/* 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
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 1502575..7d579d6 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -293,7 +293,7 @@
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 0af8a7e..6018a41 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 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 db2c9c4..ecca167 100644
--- a/cmd.c
+++ b/cmd.c
@@ -486,7 +486,7 @@
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 @@
(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 44c092a..88159ac 100755
--- a/configure
+++ b/configure
@@ -114,7 +114,6 @@
docs=""
fdt=""
kvm=""
-kvm_para=""
nptl=""
sdl=""
vnc="yes"
@@ -166,7 +165,6 @@
uname_release=""
io_thread="no"
mixemu="no"
-kerneldir=""
aix="no"
blobs="yes"
pkgversion=""
@@ -459,6 +457,8 @@
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 @@
;;
--disable-blobs) blobs="no"
;;
- --kerneldir=*) kerneldir="$optarg"
- ;;
--with-pkgversion=*) pkgversion=" ($optarg)"
;;
--disable-docs) docs="no"
@@ -1005,7 +1003,6 @@
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 @@
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 @@
# 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 @@
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 @@
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 @@
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 @@
\( "$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 @@
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 @@
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 9c6addf..acd8ca1 100644
--- a/console.c
+++ b/console.c
@@ -1349,8 +1349,15 @@
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 880f570..e839100 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -847,7 +847,7 @@
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 9f59172..b027e43 100644
--- a/cpu-common.h
+++ b/cpu-common.h
@@ -65,6 +65,7 @@
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 e1de56b..20e3ec4 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 @@
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 @@
/* 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
/* 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 @@
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 @@
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 @@
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 @@
(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 @@
!(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 @@
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 @@
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 @@
}
#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 @@
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 @@
} 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 @@
#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 @@
#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 17e96b5..abd24ab 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 @@
/* 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 a6dc859..35196a1 100644
--- a/darwin-user/main.c
+++ b/darwin-user/main.c
@@ -819,7 +819,7 @@
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 d208c52..1334b8e 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 867eec2..74d7398 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 003c855..0f92a6f 100644
--- a/error.h
+++ b/error.h
@@ -25,8 +25,7 @@
* 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 2a13a95..21a69d6 100644
--- a/exec-all.h
+++ b/exec-all.h
@@ -40,6 +40,7 @@
#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 @@
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 09928a3..4c45299 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 @@
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 @@
/* 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 @@
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 @@
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(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 @@
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 @@
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 @@
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 @@
}
}
- if (xen_mapcache_enabled()) {
- *ram_addr = qemu_ram_addr_from_mapcache(ptr);
- return 0;
- }
-
return -1;
}
@@ -4003,14 +4045,12 @@
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 @@
}
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 @@
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 @@
}
}
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 b9ae30d..c085a5a 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 a5760a9..435da73 100644
--- a/hppa-dis.c
+++ b/hppa-dis.c
@@ -1771,13 +1771,13 @@
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 @@
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 a2b6acc..f235236 100644
--- a/hw/9pfs/virtio-9p-device.c
+++ b/hw/9pfs/virtio-9p-device.c
@@ -142,11 +142,7 @@
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 @@
.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 a946c1a..0b59896 100644
--- a/hw/ac97.c
+++ b/hw/ac97.c
@@ -1277,9 +1277,6 @@
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 @@
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 @@
.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 6c908ff..350558b 100644
--- a/hw/acpi_piix4.c
+++ b/hw/acpi_piix4.c
@@ -317,13 +317,9 @@
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 @@
.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 84e9af7..974c87a 100644
--- a/hw/apb_pci.c
+++ b/hw/apb_pci.c
@@ -304,9 +304,6 @@
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 @@
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 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 @@
.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 @@
.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 72d010a..83f3393 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 65a4a63..e8c57a3 100644
--- a/hw/bonito.c
+++ b/hw/bonito.c
@@ -691,11 +691,7 @@
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 @@
.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 722cac7..f39d1f8 100644
--- a/hw/cirrus_vga.c
+++ b/hw/cirrus_vga.c
@@ -3088,8 +3088,11 @@
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 @@
{
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 @@
&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 @@
.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 bf88f2a..a35f382 100644
--- a/hw/dec_pci.c
+++ b/hw/dec_pci.c
@@ -50,28 +50,16 @@
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 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 @@
.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 f160bfc..96d84f9 100644
--- a/hw/e1000.c
+++ b/hw/e1000.c
@@ -1164,12 +1164,8 @@
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 @@
.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 9f16efd..9b6f4a5 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 @@
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 @@
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 @@
.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 @@
.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 @@
.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 @@
.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 @@
.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 @@
.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 @@
.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 @@
.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 @@
.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 @@
.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 @@
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 40cb48c..1ed62b7 100644
--- a/hw/es1370.c
+++ b/hw/es1370.c
@@ -998,21 +998,9 @@
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 @@
.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 2787ebd..b917d4d 100644
--- a/hw/etraxfs_ser.c
+++ b/hw/etraxfs_ser.c
@@ -190,15 +190,23 @@
}
-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 @@
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 d35701f..cee07e0 100644
--- a/hw/grackle_pci.c
+++ b/hw/grackle_pci.c
@@ -104,11 +104,7 @@
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 @@
.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 c66188f..8e1f6a0 100644
--- a/hw/gt64xxx.c
+++ b/hw/gt64xxx.c
@@ -1118,14 +1118,10 @@
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 @@
.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 56447a7..9dd7096 100644
--- a/hw/hw.h
+++ b/hw/hw.h
@@ -780,6 +780,9 @@
#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 5d5464a..56302b5 100644
--- a/hw/ide/cmd646.c
+++ b/hw/ide/cmd646.c
@@ -226,14 +226,8 @@
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 @@
.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 6150ce3..054e073 100644
--- a/hw/ide/ich.c
+++ b/hw/ide/ich.c
@@ -77,11 +77,8 @@
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 @@
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 @@
.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 c349644..84f72b0 100644
--- a/hw/ide/piix.c
+++ b/hw/ide/piix.c
@@ -131,12 +131,12 @@
}
}
-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 @@
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 @@
.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 04f3290..3474c37 100644
--- a/hw/ide/via.c
+++ b/hw/ide/via.c
@@ -160,11 +160,7 @@
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 @@
.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 5485745..0ffffce 100644
--- a/hw/intel-hda.c
+++ b/hw/intel-hda.c
@@ -1138,10 +1138,6 @@
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 @@
.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 95adf09..a6bfbb9 100644
--- a/hw/ioh3420.c
+++ b/hw/ioh3420.c
@@ -104,12 +104,8 @@
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 @@
.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 7b19a81..3055dd2 100644
--- a/hw/ivshmem.c
+++ b/hw/ivshmem.c
@@ -706,12 +706,7 @@
}
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 @@
.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 004c4ad..692ad18 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 @@
}
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 7a83cbe..252ea13 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 427b05f..e5ff962 100644
--- a/hw/lm32_sys.c
+++ b/hw/lm32_sys.c
@@ -83,7 +83,7 @@
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 ed28984..49cbb22 100644
--- a/hw/lm32_timer.c
+++ b/hw/lm32_timer.c
@@ -86,7 +86,7 @@
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 @@
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 e225087..09090e9 100644
--- a/hw/lm32_uart.c
+++ b/hw/lm32_uart.c
@@ -149,7 +149,7 @@
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 @@
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 83084b6..940b43a 100644
--- a/hw/lsi53c895a.c
+++ b/hw/lsi53c895a.c
@@ -889,7 +889,6 @@
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 @@
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 @@
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 @@
.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 6c9e318..6104732 100644
--- a/hw/milkymist-ac97.c
+++ b/hw/milkymist-ac97.c
@@ -103,7 +103,7 @@
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 @@
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 06077af..22dc377 100644
--- a/hw/milkymist-memcard.c
+++ b/hw/milkymist-memcard.c
@@ -154,7 +154,7 @@
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 @@
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 c4e2818..cd36026 100644
--- a/hw/milkymist-minimac2.c
+++ b/hw/milkymist-minimac2.c
@@ -234,20 +234,20 @@
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 94e6315..306d1ce 100644
--- a/hw/milkymist-pfpu.c
+++ b/hw/milkymist-pfpu.c
@@ -301,7 +301,7 @@
} break;
default:
- error_report("milkymist_pfpu: unknown opcode %d\n", op);
+ error_report("milkymist_pfpu: unknown opcode %d", op);
break;
}
@@ -358,7 +358,7 @@
/* 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 028f3b7..5ab35c3 100644
--- a/hw/milkymist-softusb.c
+++ b/hw/milkymist-softusb.c
@@ -131,7 +131,7 @@
{
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 @@
{
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 @@
{
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 @@
{
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 6bd0cb9..7b2d544 100644
--- a/hw/milkymist-sysctl.c
+++ b/hw/milkymist-sysctl.c
@@ -119,7 +119,7 @@
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 @@
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 9cebe31..790cdcb 100644
--- a/hw/milkymist-tmu2.c
+++ b/hw/milkymist-tmu2.c
@@ -352,21 +352,21 @@
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 b087fe5..e8c5607 100644
--- a/hw/msi.c
+++ b/hw/msi.c
@@ -172,7 +172,7 @@
}
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 af40e26..03d7bec 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 @@
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_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 @@
{
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 @@
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 @@
{
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 @@
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 @@
}
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 @@
/* 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 @@
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 b668ad1..f8acaae 100644
--- a/hw/ne2000.c
+++ b/hw/ne2000.c
@@ -721,9 +721,6 @@
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 @@
.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 0dcbee7..6d5730b 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -176,7 +176,6 @@
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 9a22a8a..c5c16b4 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -124,11 +124,7 @@
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 @@
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 @@
.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 @@
.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 @@
.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 @@
.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 1d297d6..b904a4e 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -726,10 +726,11 @@
/* -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 @@
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 @@
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 @@
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 @@
}
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 @@
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 0d288ce..c220745 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -433,6 +433,13 @@
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 d9457ed..d94578c 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 5a5ab89..e884096 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 f08d3c7..be019c7 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 @@
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 @@
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 9415a1e..216cf81 100644
--- a/hw/pcnet-pci.c
+++ b/hw/pcnet-pci.c
@@ -265,12 +265,8 @@
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 @@
.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 71f1f84..9590e7b 100644
--- a/hw/piix4.c
+++ b/hw/piix4.c
@@ -86,15 +86,8 @@
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 @@
.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 85a320e..26ce904 100644
--- a/hw/piix_pci.c
+++ b/hw/piix_pci.c
@@ -40,6 +40,7 @@
#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 @@
#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_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 @@
{
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 @@
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 *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_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 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 @@
.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 @@
.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 069af96..fc11af4 100644
--- a/hw/ppce500_pci.c
+++ b/hw/ppce500_pci.c
@@ -304,20 +304,13 @@
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 9519f5d..292b52f 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -371,7 +371,7 @@
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 @@
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 1906e84..16316f2 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -1231,7 +1231,6 @@
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 @@
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 @@
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 @@
.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 @@
.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 2f8db58..5214b8c 100644
--- a/hw/rtl8139.c
+++ b/hw/rtl8139.c
@@ -3457,10 +3457,6 @@
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 @@
.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 19d5bf8..4f279e7 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 e99d8db..a076cf2 100644
--- a/hw/sh_pci.c
+++ b/hw/sh_pci.c
@@ -137,8 +137,6 @@
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 @@
.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 43c441d..84da8fc 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 de08bdf..0e03d61 100644
--- a/hw/strongarm.c
+++ b/hw/strongarm.c
@@ -1536,14 +1536,14 @@
}
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 5eb38cf..d7dcaf0 100644
--- a/hw/sun4u.c
+++ b/hw/sun4u.c
@@ -553,15 +553,11 @@
{
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 @@
.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 2f3e6da..00c7be8 100644
--- a/hw/syborg_virtio.c
+++ b/hw/syborg_virtio.c
@@ -146,7 +146,9 @@
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 c57c0a1..d364daa 100644
--- a/hw/unin_pci.c
+++ b/hw/unin_pci.c
@@ -279,10 +279,6 @@
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_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 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 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 @@
.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 480956d..2abce12 100644
--- a/hw/usb-bus.c
+++ b/hw/usb-bus.c
@@ -75,7 +75,7 @@
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 @@
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 @@
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 @@
}
}
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 @@
QTAILQ_INSERT_TAIL(&bus->used, port, next);
bus->nused++;
+
+ return 0;
}
int usb_device_attach(USBDevice *dev)
@@ -215,8 +227,7 @@
(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 @@
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 59c6431..d392299 100644
--- a/hw/usb-ccid.c
+++ b/hw/usb-ccid.c
@@ -1240,7 +1240,7 @@
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 @@
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 e4a4680..bc6858f 100644
--- a/hw/usb-desc.c
+++ b/hw/usb-desc.c
@@ -242,7 +242,17 @@
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 @@
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 c909127..91fb7de 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 @@
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 @@
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 @@
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 @@
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 @@
{
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 @@
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 @@
.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 @@
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 c59797b..86582cc 100644
--- a/hw/usb-msd.c
+++ b/hw/usb-msd.c
@@ -51,6 +51,7 @@
SCSIRequest *req;
SCSIBus bus;
BlockConf conf;
+ char *serial;
SCSIDevice *scsi_dev;
uint32_t removable;
int result;
@@ -497,8 +498,9 @@
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 @@
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 @@
.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 832dcd6..1c29b9f 100644
--- a/hw/usb-ohci.c
+++ b/hw/usb-ohci.c
@@ -373,14 +373,25 @@
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 @@
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 @@
.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 75cd231..405fa7b 100644
--- a/hw/usb-uhci.c
+++ b/hw/usb-uhci.c
@@ -1114,14 +1114,13 @@
.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 @@
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 @@
/* 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 @@
.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 06ce058..076e2ff 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 @@
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 2fed8a0..8e75ffc 100644
--- a/hw/versatile_pci.c
+++ b/hw/versatile_pci.c
@@ -133,12 +133,8 @@
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 @@
.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 ce9ec45..481f448 100644
--- a/hw/vga-pci.c
+++ b/hw/vga-pci.c
@@ -74,7 +74,6 @@
{
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 @@
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 @@
.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 124295a..0f54734 100644
--- a/hw/vga.c
+++ b/hw/vga.c
@@ -2346,15 +2346,19 @@
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 @@
(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 420e05f..b6dc592 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 @@
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 @@
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 @@
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 c018351..b3e7ba5 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 @@
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 @@
.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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
.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 @@
.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 @@
.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 @@
.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 a4b5fd3..b518917 100644
--- a/hw/virtio-pci.h
+++ b/hw/virtio-pci.h
@@ -37,7 +37,9 @@
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 9a12104..7f6db7b 100644
--- a/hw/virtio-serial-bus.c
+++ b/hw/virtio-serial-bus.c
@@ -328,18 +328,11 @@
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 @@
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 @@
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 @@
} 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 @@
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 6e8814c..cc47a06 100644
--- a/hw/virtio.c
+++ b/hw/virtio.c
@@ -71,7 +71,17 @@
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 @@
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 @@
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 @@
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_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 @@
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 @@
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(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 @@
virtio_notify_vector(vq->vdev, vq->vector);
}
+/* 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 (((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)
{
- /* 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 (!vring_notify(vdev, vq)) {
return;
+ }
trace_virtio_notify(vdev, vq);
vdev->isr |= 0x01;
@@ -717,6 +787,8 @@
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 @@
/* 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 @@
}
} 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 @@
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 bc72289..69e6bb1 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 @@
#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 4656767..354c221 100644
--- a/hw/vmware_vga.c
+++ b/hw/vmware_vga.c
@@ -1280,15 +1280,8 @@
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 @@
.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 ca8f826..5c973ed 100644
--- a/hw/vt82c686.c
+++ b/hw/vt82c686.c
@@ -326,11 +326,6 @@
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 @@
.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 @@
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 @@
.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 @@
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 @@
.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 @@
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 @@
.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 0791721..53786ce 100644
--- a/hw/wdt_i6300esb.c
+++ b/hw/wdt_i6300esb.c
@@ -381,7 +381,6 @@
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 @@
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 @@
.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 a1958a0..2c79af6 100644
--- a/hw/xen_common.h
+++ b/hw/xen_common.h
@@ -71,6 +71,20 @@
(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 0000000..b167eee
--- /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 5aa6a6b..d3c387d 100644
--- a/hw/xio3130_downstream.c
+++ b/hw/xio3130_downstream.c
@@ -69,9 +69,6 @@
}
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 @@
.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 a7640f5..8283695 100644
--- a/hw/xio3130_upstream.c
+++ b/hw/xio3130_upstream.c
@@ -65,9 +65,6 @@
}
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 @@
.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 106eb3a..cbc2532 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -757,35 +757,26 @@
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 @@
}
}
-#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 @@
*/
return -1;
}
-#endif
void kvm_flush_coalesced_mmio_buffer(void)
{
@@ -1013,11 +1002,9 @@
(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 1c95452..06064b9 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 @@
return -ENOSYS;
}
-int kvm_check_extension(KVMState *s, unsigned int extension)
-{
- return 0;
-}
-
int kvm_init(void)
{
return -ENOSYS;
@@ -78,16 +73,6 @@
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 @@
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 d565dba..243b063 100644
--- a/kvm.h
+++ b/kvm.h
@@ -157,7 +157,7 @@
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 0000000..ca442d3
--- /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 0000000..5c9026b
--- /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 0000000..777d307
--- /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 0000000..ad58c90
--- /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 0000000..82b32a1
--- /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 0000000..8e2dd67
--- /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 0000000..5df477a
--- /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 0000000..4d8dcbd
--- /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 0000000..834d71e
--- /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 0000000..fc63b73
--- /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 0000000..7bdcf93
--- /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 0000000..165a484
--- /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 0000000..4f51d8f
--- /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 0000000..78289ee
--- /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 dcfeb7a..b2746f2 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -927,7 +927,7 @@
#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 @@
{
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 @@
/* 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 @@
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 @@
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 @@
/* 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 @@
{
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 @@
/* 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 @@
}
}
+ /* 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 @@
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 cd7af7c..1062da3 100644
--- a/linux-user/flatload.c
+++ b/linux-user/flatload.c
@@ -379,12 +379,11 @@
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 @@
}
reloc = datapos + (ntohl(hdr->reloc_start) - text_len);
- memp = realdatastart;
} else {
@@ -506,7 +504,6 @@
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 @@
/* 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 ac8c486..62ebc7e 100644
--- a/linux-user/linuxload.c
+++ b/linux-user/linuxload.c
@@ -26,22 +26,6 @@
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 @@
{
struct stat st;
int mode;
- int retval, id_change;
+ int retval;
if(fstat(bprm->fd, &st) < 0) {
return(-errno);
@@ -73,14 +57,10 @@
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 @@
*/
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 71dd253..289054b 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 @@
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 @@
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 @@
env->regs[2],
env->regs[3],
env->regs[4],
- env->regs[5]);
+ env->regs[5],
+ 0, 0);
}
} else {
goto error;
@@ -831,7 +833,8 @@
env->regs[2],
env->regs[3],
env->regs[4],
- env->regs[5]);
+ env->regs[5],
+ 0, 0);
}
} else {
goto error;
@@ -1018,7 +1021,8 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 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 237386c..627c8b3 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -192,7 +192,8 @@
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 11b25be..7d168e1 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -981,8 +981,8 @@
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 @@
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 @@
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 @@
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 @@
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 5cb27c7..fed7a8f 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -550,6 +550,15 @@
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 @@
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)
- return target_brk;
- if (new_brk < target_original_brk)
- return target_brk;
+ DEBUGF_BRK("do_brk(%#010x) -> ", new_brk);
- brk_page = HOST_PAGE_ALIGN(target_brk);
+ if (!new_brk) {
+ DEBUGF_BRK("%#010x (!new_brk)\n", target_brk);
+ return target_brk;
+ }
+ if (new_brk < target_original_brk) {
+ DEBUGF_BRK("%#010x (new_brk < target_original_brk)\n", target_brk);
+ return 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 @@
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 @@
}
#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 @@
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 @@
return ret;
}
+#endif
static abi_long do_pipe2(int host_pipe[], int flags)
{
@@ -3751,10 +3799,10 @@
#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 @@
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 @@
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 @@
#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 @@
#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 @@
case TARGET_NR_osf_sigprocmask:
{
abi_ulong mask;
- int how = arg1;
+ int how;
sigset_t set, oldset;
switch(arg1) {
@@ -7077,7 +7222,7 @@
}
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 @@
#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 0371089..7fde10e 100644
--- a/m68k-semi.c
+++ b/m68k-semi.c
@@ -370,7 +370,7 @@
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 @@
/* 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 6af6a4d..67ceb46 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 4f777c3..66123ad 100644
--- a/net.c
+++ b/net.c
@@ -710,7 +710,7 @@
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 @@
{
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 @@
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 @@
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 6ceca50..5b883a9 100644
--- a/net.h
+++ b/net.h
@@ -133,7 +133,8 @@
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 7337f4f..bc1bf58 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -530,7 +530,7 @@
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 @@
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 @@
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 109498d..abd7a75 100644
--- a/qemu-common.h
+++ b/qemu-common.h
@@ -112,11 +112,6 @@
_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 41c191d..4b20d28 100644
--- a/qemu-error.c
+++ b/qemu-error.c
@@ -193,6 +193,8 @@
/*
* 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 4f162d1..32628b3 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -304,11 +304,11 @@
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 @@
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 @@
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 939845c..8139bc7 100644
--- a/savevm.c
+++ b/savevm.c
@@ -2073,6 +2073,7 @@
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 0000000..d9c48e0
--- /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 0000000..9d2a4bc
--- /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 7e70daa..d3013f5 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -34,6 +34,9 @@
#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 @@
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 e98b325..411bd55 100644
--- a/target-alpha/cpu.h
+++ b/target-alpha/cpu.h
@@ -492,4 +492,26 @@
}
#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 7a325e7..afb01d3 100644
--- a/target-alpha/exec.h
+++ b/target-alpha/exec.h
@@ -31,30 +31,9 @@
#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 32c2cf9..7049c80 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 d332719..51d1bd7 100644
--- a/target-alpha/op_helper.c
+++ b/target-alpha/op_helper.c
@@ -32,7 +32,7 @@
{
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 @@
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 @@
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 ad6c2ca..c61906a 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 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 @@
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 01f5b57..116131e 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -512,4 +512,17 @@
}
}
+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 db6608e..6793288 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 1208416..f4d12aa 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 8334fbc..4635884 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 @@
{
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 f5507ec..badbc5f 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 2bc35e4..ecb0df1 100644
--- a/target-cris/cpu.h
+++ b/target-cris/cpu.h
@@ -268,4 +268,15 @@
#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 2d5d297..3294abe 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 2a4403b..962d214 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 1243745..d481e39 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 34329e2..b3ddd33 100644
--- a/target-cris/op_helper.c
+++ b/target-cris/op_helper.c
@@ -83,7 +83,7 @@
helper_top_evaluate_flags();
}
}
- cpu_loop_exit();
+ cpu_loop_exit(env);
}
env = saved_env;
}
@@ -93,7 +93,7 @@
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 e2607d6..dd85859 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 5b14157..637ac20 100644
--- a/target-cris/translate_v10.c
+++ b/target-cris/translate_v10.c
@@ -262,9 +262,6 @@
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 9c3340d..9819b5f 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -641,6 +641,10 @@
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 @@
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 @@
#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 @@
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 79e7580..e1ae3af 100644
--- a/target-i386/cpuid.c
+++ b/target-i386/cpuid.c
@@ -1144,10 +1144,12 @@
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 @@
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 9bd080e..dd9bce4 100644
--- a/target-i386/exec.h
+++ b/target-i386/exec.h
@@ -33,48 +33,12 @@
#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 @@
#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 @@
(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 @@
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 509d68c..e9be104 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 1ae2d61..10fb2c4 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 @@
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 @@
return cpuid;
}
-#ifdef CONFIG_KVM_PARA
struct kvm_para_features {
int cap;
int feature;
@@ -100,51 +94,44 @@
{ 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 @@
/* 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 @@
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 @@
}
}
-#ifdef KVM_CAP_MCE
static void kvm_hwpoison_page_add(ram_addr_t ram_addr)
{
HWPoisonPage *page;
@@ -252,7 +236,6 @@
cpu_x86_support_mca_broadcast(env) ?
MCE_INJECT_BROADCAST : 0);
}
-#endif /* KVM_CAP_MCE */
static void hardware_memory_error(void)
{
@@ -262,7 +245,6 @@
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 @@
}
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(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 @@
}
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 @@
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 @@
return kvm_vcpu_ioctl(env, KVM_X86_SET_MCE, &mce);
}
-#endif /* KVM_CAP_MCE */
return 0;
}
@@ -374,30 +349,27 @@
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 @@
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 @@
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 @@
break;
}
if (i == 0xd && c->eax == 0) {
- break;
+ continue;
}
c = &cpuid_data.entries[cpuid_i++];
}
@@ -485,7 +456,7 @@
/* 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 @@
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 @@
env->mcg_cap = mcg_cap;
}
-#endif
qemu_add_vm_change_state_handler(cpu_update_state, env);
@@ -618,7 +587,6 @@
* 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 @@
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 @@
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 @@
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 @@
#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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
kvm_msr_entry_set(&msrs[n++], MSR_MC0_CTL + i, env->mce_banks[i]);
}
}
-#endif
msr_data.info.nmsrs = n;
@@ -970,6 +929,9 @@
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_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 @@
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 @@
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 @@
}
}
return 0;
-#else
- return 0;
-#endif
}
static int kvm_get_sregs(CPUState *env)
@@ -1172,13 +1128,10 @@
#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 @@
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 @@
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_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 @@
}
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 @@
}
env->sipi_vector = events.sipi_vector;
-#endif
return 0;
}
@@ -1363,7 +1303,6 @@
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 @@
(!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 @@
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 @@
}
env->dr[4] = env->dr[6] = dbgregs.dr6;
env->dr[5] = env->dr[7] = dbgregs.dr7;
-#endif
return 0;
}
@@ -1659,7 +1591,6 @@
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 @@
}
}
}
-#endif /* KVM_CAP_SET_GUEST_DEBUG */
static bool host_supports_vmx(void)
{
@@ -1887,12 +1817,10 @@
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 bbeae88..9aca8e0 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 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 @@
.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 cec0c76..315e18b 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 @@
{
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 @@
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 @@
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 @@
* 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 @@
#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 @@
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 @@
#if defined(CONFIG_USER_ONLY)
-void do_smm_enter(void)
+void do_smm_enter(CPUState *env1)
{
}
@@ -1375,11 +1416,15 @@
#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 @@
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 @@
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_debug(void)
{
env->exception_index = EXCP_DEBUG;
- cpu_loop_exit();
+ cpu_loop_exit(env);
}
void helper_reset_rf(void)
@@ -4859,6 +4905,10 @@
{
}
+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 @@
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 @@
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 @@
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 @@
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 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 @@
env->error_code = 0;
env->old_exception = -1;
- cpu_loop_exit();
+ cpu_loop_exit(env);
}
#endif
@@ -5575,6 +5635,18 @@
}
}
+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 10bd72a..ccef381 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 8e2d26b..876b5be 100644
--- a/target-lm32/cpu.h
+++ b/target-lm32/cpu.h
@@ -241,4 +241,17 @@
*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 348b723..2a227b2 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 @@
}
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 4f3e7e0..e79428d 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 c72b1df..a34cecd 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 @@
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 5e19725..0be105d 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 b025b66..e0f9b32 100644
--- a/target-m68k/cpu.h
+++ b/target-m68k/cpu.h
@@ -119,7 +119,8 @@
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 @@
| ((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 91daa6b..93e7912 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 faa8c42..a936fe7 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 9b13bdb..237fc4c 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)
{
- env->exception_index = -1;
+ env1->exception_index = -1;
+}
+
+void do_interrupt_m68k_hardirq(CPUState *env1)
+{
}
#else
@@ -71,7 +75,7 @@
cpu_restore_state(tb, env, pc);
}
}
- cpu_loop_exit();
+ cpu_loop_exit(env);
}
env = saved_env;
}
@@ -90,7 +94,7 @@
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 @@
}
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 @@
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 26f0ee4..0e7f1fe 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 78fe14ff..51a13e3 100644
--- a/target-microblaze/cpu.h
+++ b/target-microblaze/cpu.h
@@ -350,4 +350,17 @@
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 1efff30..71b4d39 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 a623c7b..299259c 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 b38f7d9..281fc8d 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 c7b2f97..1a0a476 100644
--- a/target-microblaze/op_helper.c
+++ b/target-microblaze/op_helper.c
@@ -63,7 +63,7 @@
cpu_restore_state(tb, env, pc);
}
}
- cpu_loop_exit();
+ cpu_loop_exit(env);
}
env = saved_env;
}
@@ -107,7 +107,7 @@
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 b47b92e..31e8306 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 0b98d10..b0ac4da 100644
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -656,4 +656,28 @@
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 607edf1..e787e9a 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 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 0f057c2..ecf6182 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 9ffac71..be72b36 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 b8e4991..6b966b1 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -38,7 +38,7 @@
#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 @@
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 4eaa826..2848c6a 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 46d86be..84f8ff6 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -2018,4 +2018,16 @@
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 f87847a..f4453e4 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 @@
#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 3884976..176128a 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 e7b1b10..21f35af7 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -65,18 +65,10 @@
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 @@
}
}
-#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 @@
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 @@
env->spr[SPR_BOOKE_PID2] = sregs.u.e.impl.fsl.pid2;
}
}
-#endif
}
if (cap_segstate) {
@@ -332,7 +313,6 @@
return ret;
}
-#ifdef KVM_CAP_PPC_SEGSTATE
ppc_store_sdr1(env, sregs.u.s.sdr1);
/* Sync SLB */
@@ -355,7 +335,6 @@
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 @@
{
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 @@
return 0;
}
-#endif
/*
* Fallback to always fail hypercalls:
diff --git a/target-ppc/op_helper.c b/target-ppc/op_helper.c
index 82b6651..dde7595 100644
--- a/target-ppc/op_helper.c
+++ b/target-ppc/op_helper.c
@@ -44,7 +44,7 @@
#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 7e318e3..fd7c208 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 4e5c391..d48a9b7 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -313,16 +313,6 @@
/* 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 @@
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 7a87fff..fb73f31 100644
--- a/target-s390x/exec.h
+++ b/target-s390x/exec.h
@@ -23,18 +23,11 @@
#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 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 745d8c5..1ce7079 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 db03a79..cd33f99 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 @@
cpu_restore_state(tb, env, pc);
}
}
- cpu_loop_exit();
+ cpu_loop_exit(env);
}
env = saved_env;
}
@@ -89,7 +92,7 @@
{
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(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 @@
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 @@
}
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 eda4624..77fb448 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 74ff97a..00e32f2 100644
--- a/target-sh4/cpu.h
+++ b/target-sh4/cpu.h
@@ -361,4 +361,17 @@
| (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 9f1c1f6..4a6ae58 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 8f36d31..20e9b13 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 b909d18..a932225 100644
--- a/target-sh4/op_helper.c
+++ b/target-sh4/op_helper.c
@@ -66,7 +66,7 @@
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 @@
{
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_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 @@
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 @@
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 93c8636..569bc73 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 320530e..4edae78 100644
--- a/target-sparc/cpu.h
+++ b/target-sparc/cpu.h
@@ -403,6 +403,8 @@
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 @@
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 @@
#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 @@
#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 f5c221e..2395b00 100644
--- a/target-sparc/exec.h
+++ b/target-sparc/exec.h
@@ -12,20 +12,4 @@
#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 e9b42d0..7eea1ac 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 @@
}
#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 752e431..56ae041 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 @@
/* 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 @@
/* 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 b38691e..fd0cfbd 100644
--- a/target-sparc/op_helper.c
+++ b/target-sparc/op_helper.c
@@ -316,7 +316,7 @@
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 @@
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 @@
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 @@
// 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 @@
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_debug(void)
{
env->exception_index = EXCP_DEBUG;
- cpu_loop_exit();
+ cpu_loop_exit(env);
}
#ifndef TARGET_SPARC64
@@ -4007,6 +4029,16 @@
#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 @@
#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 @@
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 0cc47e9..992cd77 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 1e10049..9817607 100644
--- a/target-unicore32/cpu.h
+++ b/target-unicore32/cpu.h
@@ -179,4 +179,10 @@
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 4ab55f4..7912105 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 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 483aeae..02707d5 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 31e4b11..541e6f0 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 98eaeb3..a15e42d 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 fb858d8..93eb0f1 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -1804,6 +1804,8 @@
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 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 - r6, r8 - r11, lr } */
- tcg_out32(s, (COND_AL << 28) | 0x092d4f70);
+ /* stmdb sp!, { r4 - r12, lr } */
+ tcg_out32(s, (COND_AL << 28) | 0x092d5ff0);
- tcg_out_bx(s, COND_AL, TCG_REG_R0);
+ tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
+
+ 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 7f4653e..222f33e 100644
--- a/tcg/hppa/tcg-target.c
+++ b/tcg/hppa/tcg-target.c
@@ -467,6 +467,14 @@
| 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 @@
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 @@
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 @@
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 @@
/* 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 @@
}
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 @@
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 @@
{ 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 @@
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 @@
/* 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 @@
}
#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 @@
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 a5cc440..f7919ce 100644
--- a/tcg/hppa/tcg-target.h
+++ b/tcg/hppa/tcg-target.h
@@ -94,6 +94,7 @@
#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 bb19a95..7529677 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -1398,7 +1398,7 @@
/* 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 @@
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 @@
/* TB prologue */
+ /* 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 +
+ 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]);
}
- /* Reserve some stack space. */
- 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 = (frame_size + TCG_TARGET_STACK_ALIGN - 1) &
- ~(TCG_TARGET_STACK_ALIGN - 1);
- stack_addend = frame_size - push_size;
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 @@
}
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 8dac7f7..6386a5b 100644
--- a/tcg/ia64/tcg-target.c
+++ b/tcg/ia64/tcg-target.c
@@ -2292,7 +2292,7 @@
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 @@
}
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 @@
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 e04b0dc..12ff9d5 100644
--- a/tcg/mips/tcg-target.c
+++ b/tcg/mips/tcg-target.c
@@ -1452,9 +1452,7 @@
};
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 @@
}
/* 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 @@
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 7970268..0cd8873 100644
--- a/tcg/ppc/tcg-target.c
+++ b/tcg/ppc/tcg-target.c
@@ -160,8 +160,7 @@
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 @@
}
#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 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 @@
#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 ebbee34..065c710 100644
--- a/tcg/ppc64/tcg-target.c
+++ b/tcg/ppc64/tcg-target.c
@@ -151,8 +151,7 @@
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 @@
}
#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 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 @@
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 450fcab..2fc5646 100644
--- a/tcg/s390/tcg-target.c
+++ b/tcg/s390/tcg-target.c
@@ -2291,6 +2291,8 @@
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 @@
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 5f1353a..ac76e11 100644
--- a/tcg/sparc/tcg-target.c
+++ b/tcg/sparc/tcg-target.c
@@ -693,11 +693,14 @@
/* 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 184c208..c05413b 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 @@
{
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 @@
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 @@
}
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 3647390..a2dd8b8 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -515,8 +515,9 @@
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 f1230f1..bebf612f 100644
--- a/trace-events
+++ b/trace-events
@@ -396,6 +396,7 @@
# 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 @@
# 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 2ca190c..041c108 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 @@
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 87fdf35..5c02803 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 c1bcc4a..3b97eb4 100644
--- a/usb-bsd.c
+++ b/usb-bsd.c
@@ -367,8 +367,10 @@
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 5d2ec5c..1a2deb3 100644
--- a/usb-linux.c
+++ b/usb-linux.c
@@ -85,7 +85,6 @@
/* 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 @@
int iso_urb_idx;
int iso_buffer_used;
int max_packet_size;
+ int inflight;
};
struct USBAutoFilter {
@@ -120,6 +120,7 @@
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 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 @@
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 @@
{
USBHostDevice *s = opaque;
AsyncURB *aurb;
+ int urbs = 0;
while (1) {
USBPacket *p;
@@ -286,6 +303,9 @@
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 @@
/* 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 @@
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 @@
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 @@
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 @@
}
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 @@
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 @@
break;
}
aurb[i].iso_frame_idx = -1;
+ change_iso_inflight(s, p->devep, +1);
}
}
}
@@ -1061,6 +1088,42 @@
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 @@
}
}
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 @@
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 @@
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 d4a6abb..02c2f8b 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 @@
/* 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 dbdec71..52402a2 100644
--- a/vl.c
+++ b/vl.c
@@ -1253,7 +1253,7 @@
}
}
-void qemu_system_reset(void)
+void qemu_system_reset(bool report)
{
QEMUResetEntry *re, *nre;
@@ -1261,7 +1261,9 @@
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 @@
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 @@
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 0eac202..fcb106f 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 @@
#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 @@
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 @@
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 @@
destroy_hvm_domain();
}
if (qemu_reset_requested_get()) {
- qemu_system_reset();
+ qemu_system_reset(VMRESET_REPORT);
}
}
@@ -581,6 +857,11 @@
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 7c14b3d..90a994d 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 @@
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_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 349cc62..fac47cd 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
return mapcache->last_address_vaddr + address_offset;
}
-void qemu_map_cache_unlock(void *buffer)
+ram_addr_t qemu_ram_addr_from_mapcache(void *ptr)
{
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)
-{
- 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 @@
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 @@
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 @@
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 @@
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 @@
}
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 @@
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 @@
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 339444c..6216cc3 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)