aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.target16
-rw-r--r--arch_init.c7
-rw-r--r--default-configs/mips64-linux-user.mak1
-rw-r--r--default-configs/mips64el-linux-user.mak1
-rw-r--r--default-configs/mipsn32-linux-user.mak1
-rw-r--r--default-configs/mipsn32el-linux-user.mak1
-rw-r--r--exec-obsolete.h15
-rw-r--r--fsdev/file-op-9p.h12
-rw-r--r--fsdev/virtfs-proxy-helper.c10
-rw-r--r--hw/9pfs/cofile.c14
-rw-r--r--hw/9pfs/virtio-9p-device.c9
-rw-r--r--hw/9pfs/virtio-9p-handle.c4
-rw-r--r--hw/9pfs/virtio-9p-local.c357
-rw-r--r--hw/9pfs/virtio-9p.c3
-rw-r--r--hw/ac97.c56
-rw-r--r--hw/adlib.c2
-rw-r--r--hw/cirrus_vga.c9
-rw-r--r--hw/cirrus_vga_template.h102
-rw-r--r--hw/cs4231a.c22
-rw-r--r--hw/es1370.c42
-rw-r--r--hw/framebuffer.c9
-rw-r--r--hw/g364fb.c3
-rw-r--r--hw/gus.c28
-rw-r--r--hw/kvm/apic.c1
-rw-r--r--hw/kvm/i8259.c1
-rw-r--r--hw/s390-virtio-bus.c1
-rw-r--r--hw/sb16.c108
-rw-r--r--hw/sm501.c11
-rw-r--r--hw/tcx.c19
-rw-r--r--hw/vga.c391
-rw-r--r--hw/vga.h159
-rw-r--r--hw/vga_int.h16
-rw-r--r--hw/vga_template.h74
-rw-r--r--kvm-all.c4
-rw-r--r--linux-headers/asm-powerpc/kvm.h11
-rw-r--r--linux-headers/asm-powerpc/kvm_para.h41
-rw-r--r--linux-headers/asm-s390/kvm.h9
-rw-r--r--linux-headers/asm-x86/hyperv.h1
-rw-r--r--linux-headers/asm-x86/kvm.h4
-rw-r--r--linux-headers/linux/kvm.h78
-rw-r--r--linux-headers/linux/kvm_para.h1
-rw-r--r--linux-headers/linux/virtio_ring.h6
-rw-r--r--linux-user/elfload.c15
-rw-r--r--linux-user/main.c7
-rw-r--r--linux-user/mips64/syscall.h3
-rw-r--r--linux-user/mipsn32/syscall.h3
-rw-r--r--linux-user/qemu.h3
-rw-r--r--linux-user/signal.c8
-rw-r--r--linux-user/strace.c19
-rw-r--r--linux-user/syscall.c303
-rw-r--r--linux-user/syscall_defs.h6
-rw-r--r--memory.c5
-rw-r--r--memory.h9
-rw-r--r--net.c19
-rw-r--r--qemu-options.hx18
-rw-r--r--qemu-thread-win32.c9
-rw-r--r--target-ppc/cpu.h59
-rw-r--r--target-ppc/helper.c32
-rw-r--r--target-ppc/helper.h5
-rw-r--r--target-ppc/kvm.c10
-rw-r--r--target-ppc/op_helper.c159
-rw-r--r--target-ppc/translate.c75
-rw-r--r--target-ppc/translate_init.c48
-rw-r--r--usb-bsd.c11
-rw-r--r--usb-redir.c24
-rw-r--r--vl.c6
66 files changed, 1908 insertions, 608 deletions
diff --git a/Makefile.target b/Makefile.target
index 68481a3a6c..7ed497942a 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -29,10 +29,17 @@ ifdef CONFIG_USER_ONLY
QEMU_PROG=qemu-$(TARGET_ARCH2)
else
# system emulator name
+ifneq (,$(findstring -mwindows,$(LIBS)))
+# Terminate program name with a 'w' because the linker builds a windows executable.
+QEMU_PROGW=qemu-system-$(TARGET_ARCH2)w$(EXESUF)
+endif # windows executable
QEMU_PROG=qemu-system-$(TARGET_ARCH2)$(EXESUF)
endif
PROGS=$(QEMU_PROG)
+ifdef QEMU_PROGW
+PROGS+=$(QEMU_PROGW)
+endif
STPFILES=
ifndef CONFIG_HAIKU
@@ -407,9 +414,16 @@ endif # CONFIG_LINUX_USER
obj-$(CONFIG_GDBSTUB_XML) += gdbstub-xml.o
+ifdef QEMU_PROGW
+# The linker builds a windows executable. Make also a console executable.
+$(QEMU_PROGW): $(obj-y) $(obj-$(TARGET_BASE_ARCH)-y)
+ $(call LINK,$^)
+$(QEMU_PROG): $(QEMU_PROGW)
+ $(call quiet-command,$(OBJCOPY) --subsystem console $(QEMU_PROGW) $(QEMU_PROG)," GEN $(TARGET_DIR)$(QEMU_PROG)")
+else
$(QEMU_PROG): $(obj-y) $(obj-$(TARGET_BASE_ARCH)-y)
$(call LINK,$^)
-
+endif
gdbstub-xml.c: $(TARGET_XML_FILES) $(SRC_PATH)/scripts/feature_to_c.sh
$(call quiet-command,rm -f $@ && $(SHELL) $(SRC_PATH)/scripts/feature_to_c.sh $@ $(TARGET_XML_FILES)," GEN $(TARGET_DIR)$@")
diff --git a/arch_init.c b/arch_init.c
index 2366511a6f..699bdd1051 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -141,7 +141,8 @@ static int ram_save_block(QEMUFile *f)
do {
mr = block->mr;
- if (memory_region_get_dirty(mr, offset, DIRTY_MEMORY_MIGRATION)) {
+ if (memory_region_get_dirty(mr, offset, TARGET_PAGE_SIZE,
+ DIRTY_MEMORY_MIGRATION)) {
uint8_t *p;
int cont = (block == last_block) ? RAM_SAVE_FLAG_CONTINUE : 0;
@@ -198,7 +199,7 @@ static ram_addr_t ram_save_remaining(void)
QLIST_FOREACH(block, &ram_list.blocks, next) {
ram_addr_t addr;
for (addr = 0; addr < block->length; addr += TARGET_PAGE_SIZE) {
- if (memory_region_get_dirty(block->mr, addr,
+ if (memory_region_get_dirty(block->mr, addr, TARGET_PAGE_SIZE,
DIRTY_MEMORY_MIGRATION)) {
count++;
}
@@ -283,7 +284,7 @@ int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
/* Make sure all dirty bits are set */
QLIST_FOREACH(block, &ram_list.blocks, next) {
for (addr = 0; addr < block->length; addr += TARGET_PAGE_SIZE) {
- if (!memory_region_get_dirty(block->mr, addr,
+ if (!memory_region_get_dirty(block->mr, addr, TARGET_PAGE_SIZE,
DIRTY_MEMORY_MIGRATION)) {
memory_region_set_dirty(block->mr, addr, TARGET_PAGE_SIZE);
}
diff --git a/default-configs/mips64-linux-user.mak b/default-configs/mips64-linux-user.mak
new file mode 100644
index 0000000000..1598bfcf7d
--- /dev/null
+++ b/default-configs/mips64-linux-user.mak
@@ -0,0 +1 @@
+# Default configuration for mips64-linux-user
diff --git a/default-configs/mips64el-linux-user.mak b/default-configs/mips64el-linux-user.mak
new file mode 100644
index 0000000000..629f084086
--- /dev/null
+++ b/default-configs/mips64el-linux-user.mak
@@ -0,0 +1 @@
+# Default configuration for mips64el-linux-user
diff --git a/default-configs/mipsn32-linux-user.mak b/default-configs/mipsn32-linux-user.mak
new file mode 100644
index 0000000000..5b97919794
--- /dev/null
+++ b/default-configs/mipsn32-linux-user.mak
@@ -0,0 +1 @@
+# Default configuration for mipsn32-linux-user
diff --git a/default-configs/mipsn32el-linux-user.mak b/default-configs/mipsn32el-linux-user.mak
new file mode 100644
index 0000000000..d6367ff987
--- /dev/null
+++ b/default-configs/mipsn32el-linux-user.mak
@@ -0,0 +1 @@
+# Default configuration for mipsn32el-linux-user
diff --git a/exec-obsolete.h b/exec-obsolete.h
index d2749d36fa..94c23d0951 100644
--- a/exec-obsolete.h
+++ b/exec-obsolete.h
@@ -59,10 +59,21 @@ static inline int cpu_physical_memory_get_dirty_flags(ram_addr_t addr)
return ram_list.phys_dirty[addr >> TARGET_PAGE_BITS];
}
-static inline int cpu_physical_memory_get_dirty(ram_addr_t addr,
+static inline int cpu_physical_memory_get_dirty(ram_addr_t start,
+ ram_addr_t length,
int dirty_flags)
{
- return ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] & dirty_flags;
+ int ret = 0;
+ uint8_t *p;
+ ram_addr_t addr, end;
+
+ end = TARGET_PAGE_ALIGN(start + length);
+ start &= TARGET_PAGE_MASK;
+ p = ram_list.phys_dirty + (start >> TARGET_PAGE_BITS);
+ for (addr = start; addr < end; addr += TARGET_PAGE_SIZE) {
+ ret |= *p++ & dirty_flags;
+ }
+ return ret;
}
static inline void cpu_physical_memory_set_dirty(ram_addr_t addr)
diff --git a/fsdev/file-op-9p.h b/fsdev/file-op-9p.h
index 1e96c8bed9..956fda0919 100644
--- a/fsdev/file-op-9p.h
+++ b/fsdev/file-op-9p.h
@@ -56,11 +56,15 @@ typedef struct extended_ops {
* On failure ignore the error.
*/
#define V9FS_SM_NONE 0x00000010
-#define V9FS_RDONLY 0x00000020
-#define V9FS_PROXY_SOCK_FD 0x00000040
-#define V9FS_PROXY_SOCK_NAME 0x00000080
+/*
+ * uid/gid part of .virtfs_meatadata namespace
+ */
+#define V9FS_SM_MAPPED_FILE 0x00000020
+#define V9FS_RDONLY 0x00000040
+#define V9FS_PROXY_SOCK_FD 0x00000080
+#define V9FS_PROXY_SOCK_NAME 0x00000100
-#define V9FS_SEC_MASK 0x0000001C
+#define V9FS_SEC_MASK 0x0000003C
typedef struct FileOperations FileOperations;
diff --git a/fsdev/virtfs-proxy-helper.c b/fsdev/virtfs-proxy-helper.c
index 4a507d860e..f9a8270ee9 100644
--- a/fsdev/virtfs-proxy-helper.c
+++ b/fsdev/virtfs-proxy-helper.c
@@ -1036,7 +1036,13 @@ int main(int argc, char **argv)
return -1;
}
- if (*sock_name && (own_u == -1 || own_g == -1)) {
+ if (sock_name && sock != -1) {
+ fprintf(stderr, "both named socket and socket descriptor specified\n");
+ usage(argv[0]);
+ exit(EXIT_FAILURE);
+ }
+
+ if (sock_name && (own_u == -1 || own_g == -1)) {
fprintf(stderr, "owner uid:gid not specified, ");
fprintf(stderr,
"owner uid:gid specifies who can access the socket file\n");
@@ -1064,7 +1070,7 @@ int main(int argc, char **argv)
}
do_log(LOG_INFO, "Started\n");
- if (*sock_name) {
+ if (sock_name) {
sock = proxy_socket(sock_name, own_u, own_g);
if (sock < 0) {
goto error;
diff --git a/hw/9pfs/cofile.c b/hw/9pfs/cofile.c
index b15838c1e6..9345aaeb2e 100644
--- a/hw/9pfs/cofile.c
+++ b/hw/9pfs/cofile.c
@@ -76,6 +76,20 @@ int v9fs_co_fstat(V9fsPDU *pdu, V9fsFidState *fidp, struct stat *stbuf)
err = -errno;
}
});
+ /*
+ * Some FS driver (local:mapped-file) can't support fetching attributes
+ * using file descriptor. Use Path name in that case.
+ */
+ if (err == -EOPNOTSUPP) {
+ err = v9fs_co_lstat(pdu, &fidp->path, stbuf);
+ if (err == -ENOENT) {
+ /*
+ * fstat on an unlinked file. Work with partial results
+ * returned from s->ops->fstat
+ */
+ err = 0;
+ }
+ }
return err;
}
diff --git a/hw/9pfs/virtio-9p-device.c b/hw/9pfs/virtio-9p-device.c
index 3f15540c5f..791a5572bb 100644
--- a/hw/9pfs/virtio-9p-device.c
+++ b/hw/9pfs/virtio-9p-device.c
@@ -91,15 +91,6 @@ VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf *conf)
s->ctx.fs_root = NULL;
}
s->ctx.exops.get_st_gen = NULL;
-
- if (fse->export_flags & V9FS_SM_PASSTHROUGH) {
- s->ctx.xops = passthrough_xattr_ops;
- } else if (fse->export_flags & V9FS_SM_MAPPED) {
- s->ctx.xops = mapped_xattr_ops;
- } else if (fse->export_flags & V9FS_SM_NONE) {
- s->ctx.xops = none_xattr_ops;
- }
-
len = strlen(conf->tag);
if (len > MAX_TAG_LEN - 1) {
fprintf(stderr, "mount tag '%s' (%d bytes) is longer than "
diff --git a/hw/9pfs/virtio-9p-handle.c b/hw/9pfs/virtio-9p-handle.c
index cb012c0510..f96d17a974 100644
--- a/hw/9pfs/virtio-9p-handle.c
+++ b/hw/9pfs/virtio-9p-handle.c
@@ -63,11 +63,11 @@ static int handle_update_file_cred(int dirfd, const char *name, FsCred *credp)
if (fd < 0) {
return fd;
}
- ret = fchmod(fd, credp->fc_mode & 07777);
+ ret = fchownat(fd, "", credp->fc_uid, credp->fc_gid, AT_EMPTY_PATH);
if (ret < 0) {
goto err_out;
}
- ret = fchownat(fd, "", credp->fc_uid, credp->fc_gid, AT_EMPTY_PATH);
+ ret = fchmod(fd, credp->fc_mode & 07777);
err_out:
close(fd);
return ret;
diff --git a/hw/9pfs/virtio-9p-local.c b/hw/9pfs/virtio-9p-local.c
index 3ae6ef2e39..33a41d2e18 100644
--- a/hw/9pfs/virtio-9p-local.c
+++ b/hw/9pfs/virtio-9p-local.c
@@ -20,6 +20,7 @@
#include <sys/socket.h>
#include <sys/un.h>
#include "qemu-xattr.h"
+#include <libgen.h>
#include <linux/fs.h>
#ifdef CONFIG_LINUX_MAGIC_H
#include <linux/magic.h>
@@ -39,6 +40,54 @@
#define BTRFS_SUPER_MAGIC 0x9123683E
#endif
+#define VIRTFS_META_DIR ".virtfs_metadata"
+
+static const char *local_mapped_attr_path(FsContext *ctx,
+ const char *path, char *buffer)
+{
+ char *dir_name;
+ char *tmp_path = strdup(path);
+ char *base_name = basename(tmp_path);
+
+ /* NULL terminate the directory */
+ dir_name = tmp_path;
+ *(base_name - 1) = '\0';
+
+ snprintf(buffer, PATH_MAX, "%s/%s/%s/%s",
+ ctx->fs_root, dir_name, VIRTFS_META_DIR, base_name);
+ free(tmp_path);
+ return buffer;
+}
+
+#define ATTR_MAX 100
+static void local_mapped_file_attr(FsContext *ctx, const char *path,
+ struct stat *stbuf)
+{
+ FILE *fp;
+ char buf[ATTR_MAX];
+ char attr_path[PATH_MAX];
+
+ local_mapped_attr_path(ctx, path, attr_path);
+ fp = fopen(attr_path, "r");
+ if (!fp) {
+ return;
+ }
+ memset(buf, 0, ATTR_MAX);
+ while (fgets(buf, ATTR_MAX, fp)) {
+ if (!strncmp(buf, "virtfs.uid", 10)) {
+ stbuf->st_uid = atoi(buf+11);
+ } else if (!strncmp(buf, "virtfs.gid", 10)) {
+ stbuf->st_gid = atoi(buf+11);
+ } else if (!strncmp(buf, "virtfs.mode", 11)) {
+ stbuf->st_mode = atoi(buf+12);
+ } else if (!strncmp(buf, "virtfs.rdev", 11)) {
+ stbuf->st_rdev = atoi(buf+12);
+ }
+ memset(buf, 0, ATTR_MAX);
+ }
+ fclose(fp);
+}
+
static int local_lstat(FsContext *fs_ctx, V9fsPath *fs_path, struct stat *stbuf)
{
int err;
@@ -71,10 +120,103 @@ static int local_lstat(FsContext *fs_ctx, V9fsPath *fs_path, struct stat *stbuf)
sizeof(dev_t)) > 0) {
stbuf->st_rdev = tmp_dev;
}
+ } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
+ local_mapped_file_attr(fs_ctx, path, stbuf);
}
return err;
}
+static int local_create_mapped_attr_dir(FsContext *ctx, const char *path)
+{
+ int err;
+ char attr_dir[PATH_MAX];
+ char *tmp_path = strdup(path);
+
+ snprintf(attr_dir, PATH_MAX, "%s/%s/%s",
+ ctx->fs_root, dirname(tmp_path), VIRTFS_META_DIR);
+
+ err = mkdir(attr_dir, 0700);
+ if (err < 0 && errno == EEXIST) {
+ err = 0;
+ }
+ free(tmp_path);
+ return err;
+}
+
+static int local_set_mapped_file_attr(FsContext *ctx,
+ const char *path, FsCred *credp)
+{
+ FILE *fp;
+ int ret = 0;
+ char buf[ATTR_MAX];
+ char attr_path[PATH_MAX];
+ int uid = -1, gid = -1, mode = -1, rdev = -1;
+
+ fp = fopen(local_mapped_attr_path(ctx, path, attr_path), "r");
+ if (!fp) {
+ goto create_map_file;
+ }
+ memset(buf, 0, ATTR_MAX);
+ while (fgets(buf, ATTR_MAX, fp)) {
+ if (!strncmp(buf, "virtfs.uid", 10)) {
+ uid = atoi(buf+11);
+ } else if (!strncmp(buf, "virtfs.gid", 10)) {
+ gid = atoi(buf+11);
+ } else if (!strncmp(buf, "virtfs.mode", 11)) {
+ mode = atoi(buf+12);
+ } else if (!strncmp(buf, "virtfs.rdev", 11)) {
+ rdev = atoi(buf+12);
+ }
+ memset(buf, 0, ATTR_MAX);
+ }
+ fclose(fp);
+ goto update_map_file;
+
+create_map_file:
+ ret = local_create_mapped_attr_dir(ctx, path);
+ if (ret < 0) {
+ goto err_out;
+ }
+
+update_map_file:
+ fp = fopen(attr_path, "w");
+ if (!fp) {
+ ret = -1;
+ goto err_out;
+ }
+
+ if (credp->fc_uid != -1) {
+ uid = credp->fc_uid;
+ }
+ if (credp->fc_gid != -1) {
+ gid = credp->fc_gid;
+ }
+ if (credp->fc_mode != -1) {
+ mode = credp->fc_mode;
+ }
+ if (credp->fc_rdev != -1) {
+ rdev = credp->fc_rdev;
+ }
+
+
+ if (uid != -1) {
+ fprintf(fp, "virtfs.uid=%d\n", uid);
+ }
+ if (gid != -1) {
+ fprintf(fp, "virtfs.gid=%d\n", gid);
+ }
+ if (mode != -1) {
+ fprintf(fp, "virtfs.mode=%d\n", mode);
+ }
+ if (rdev != -1) {
+ fprintf(fp, "virtfs.rdev=%d\n", rdev);
+ }
+ fclose(fp);
+
+err_out:
+ return ret;
+}
+
static int local_set_xattr(const char *path, FsCred *credp)
{
int err;
@@ -115,9 +257,6 @@ static int local_post_create_passthrough(FsContext *fs_ctx, const char *path,
{
char buffer[PATH_MAX];
- if (chmod(rpath(fs_ctx, path, buffer), credp->fc_mode & 07777) < 0) {
- return -1;
- }
if (lchown(rpath(fs_ctx, path, buffer), credp->fc_uid,
credp->fc_gid) < 0) {
/*
@@ -128,6 +267,10 @@ static int local_post_create_passthrough(FsContext *fs_ctx, const char *path,
return -1;
}
}
+
+ if (chmod(rpath(fs_ctx, path, buffer), credp->fc_mode & 07777) < 0) {
+ return -1;
+ }
return 0;
}
@@ -138,7 +281,8 @@ static ssize_t local_readlink(FsContext *fs_ctx, V9fsPath *fs_path,
char buffer[PATH_MAX];
char *path = fs_path->data;
- if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
+ if ((fs_ctx->export_flags & V9FS_SM_MAPPED) ||
+ (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE)) {
int fd;
fd = open(rpath(fs_ctx, path, buffer), O_RDONLY);
if (fd == -1) {
@@ -203,7 +347,18 @@ static int local_readdir_r(FsContext *ctx, V9fsFidOpenState *fs,
struct dirent *entry,
struct dirent **result)
{
- return readdir_r(fs->dir, entry, result);
+ int ret;
+
+again:
+ ret = readdir_r(fs->dir, entry, result);
+ if (ctx->export_flags & V9FS_SM_MAPPED_FILE) {
+ if (!ret && *result != NULL &&
+ !strcmp(entry->d_name, VIRTFS_META_DIR)) {
+ /* skp the meta data directory */
+ goto again;
+ }
+ }
+ return ret;
}
static void local_seekdir(FsContext *ctx, V9fsFidOpenState *fs, off_t off)
@@ -264,6 +419,8 @@ static int local_chmod(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp)
if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
return local_set_xattr(rpath(fs_ctx, path, buffer), credp);
+ } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
+ return local_set_mapped_file_attr(fs_ctx, path, credp);
} else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
(fs_ctx->export_flags & V9FS_SM_NONE)) {
return chmod(rpath(fs_ctx, path, buffer), credp->fc_mode);
@@ -296,6 +453,18 @@ static int local_mknod(FsContext *fs_ctx, V9fsPath *dir_path,
serrno = errno;
goto err_end;
}
+ } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
+
+ err = mknod(rpath(fs_ctx, path, buffer),
+ SM_LOCAL_MODE_BITS|S_IFREG, 0);
+ if (err == -1) {
+ goto out;
+ }
+ err = local_set_mapped_file_attr(fs_ctx, path, credp);
+ if (err == -1) {
+ serrno = errno;
+ goto err_end;
+ }
} else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
(fs_ctx->export_flags & V9FS_SM_NONE)) {
err = mknod(rpath(fs_ctx, path, buffer), credp->fc_mode,
@@ -344,6 +513,17 @@ static int local_mkdir(FsContext *fs_ctx, V9fsPath *dir_path,
serrno = errno;
goto err_end;
}
+ } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
+ err = mkdir(rpath(fs_ctx, path, buffer), SM_LOCAL_DIR_MODE_BITS);
+ if (err == -1) {
+ goto out;
+ }
+ credp->fc_mode = credp->fc_mode|S_IFDIR;
+ err = local_set_mapped_file_attr(fs_ctx, path, credp);
+ if (err == -1) {
+ serrno = errno;
+ goto err_end;
+ }
} else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
(fs_ctx->export_flags & V9FS_SM_NONE)) {
err = mkdir(rpath(fs_ctx, path, buffer), credp->fc_mode);
@@ -404,6 +584,9 @@ static int local_fstat(FsContext *fs_ctx, int fid_type,
&tmp_dev, sizeof(dev_t)) > 0) {
stbuf->st_rdev = tmp_dev;
}
+ } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
+ errno = EOPNOTSUPP;
+ return -1;
}
return err;
}
@@ -436,6 +619,19 @@ static int local_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name,
serrno = errno;
goto err_end;
}
+ } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
+ fd = open(rpath(fs_ctx, path, buffer), flags, SM_LOCAL_MODE_BITS);
+ if (fd == -1) {
+ err = fd;
+ goto out;
+ }
+ credp->fc_mode = credp->fc_mode|S_IFREG;
+ /* Set client credentials in .virtfs_metadata directory files */
+ err = local_set_mapped_file_attr(fs_ctx, path, credp);
+ if (err == -1) {
+ serrno = errno;
+ goto err_end;
+ }
} else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
(fs_ctx->export_flags & V9FS_SM_NONE)) {
fd = open(rpath(fs_ctx, path, buffer), flags, credp->fc_mode);
@@ -506,6 +702,35 @@ static int local_symlink(FsContext *fs_ctx, const char *oldpath,
serrno = errno;
goto err_end;
}
+ } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
+ int fd;
+ ssize_t oldpath_size, write_size;
+ fd = open(rpath(fs_ctx, newpath, buffer), O_CREAT|O_EXCL|O_RDWR,
+ SM_LOCAL_MODE_BITS);
+ if (fd == -1) {
+ err = fd;
+ goto out;
+ }
+ /* Write the oldpath (target) to the file. */
+ oldpath_size = strlen(oldpath);
+ do {
+ write_size = write(fd, (void *)oldpath, oldpath_size);
+ } while (write_size == -1 && errno == EINTR);
+
+ if (write_size != oldpath_size) {
+ serrno = errno;
+ close(fd);
+ err = -1;
+ goto err_end;
+ }
+ close(fd);
+ /* Set cleint credentials in symlink's xattr */
+ credp->fc_mode = credp->fc_mode|S_IFLNK;
+ err = local_set_mapped_file_attr(fs_ctx, newpath, credp);
+ if (err == -1) {
+ serrno = errno;
+ goto err_end;
+ }
} else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
(fs_ctx->export_flags & V9FS_SM_NONE)) {
err = symlink(oldpath, rpath(fs_ctx, newpath, buffer));
@@ -548,6 +773,21 @@ static int local_link(FsContext *ctx, V9fsPath *oldpath,
ret = link(rpath(ctx, oldpath->data, buffer),
rpath(ctx, newpath.data, buffer1));
+
+ /* now link the virtfs_metadata files */
+ if (!ret && (ctx->export_flags & V9FS_SM_MAPPED_FILE)) {
+ /* Link the .virtfs_metadata files. Create the metada directory */
+ ret = local_create_mapped_attr_dir(ctx, newpath.data);
+ if (ret < 0) {
+ goto err_out;
+ }
+ ret = link(local_mapped_attr_path(ctx, oldpath->data, buffer),
+ local_mapped_attr_path(ctx, newpath.data, buffer1));
+ if (ret < 0 && errno != ENOENT) {
+ goto err_out;
+ }
+ }
+err_out:
v9fs_string_free(&newpath);
return ret;
}
@@ -563,8 +803,21 @@ static int local_truncate(FsContext *ctx, V9fsPath *fs_path, off_t size)
static int local_rename(FsContext *ctx, const char *oldpath,
const char *newpath)
{
+ int err;
char buffer[PATH_MAX], buffer1[PATH_MAX];
+ if (ctx->export_flags & V9FS_SM_MAPPED_FILE) {
+ err = local_create_mapped_attr_dir(ctx, newpath);
+ if (err < 0) {
+ return err;
+ }
+ /* rename the .virtfs_metadata files */
+ err = rename(local_mapped_attr_path(ctx, oldpath, buffer),
+ local_mapped_attr_path(ctx, newpath, buffer1));
+ if (err < 0 && errno != ENOENT) {
+ return err;
+ }
+ }
return rename(rpath(ctx, oldpath, buffer), rpath(ctx, newpath, buffer1));
}
@@ -580,6 +833,8 @@ static int local_chown(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp)
credp->fc_uid, credp->fc_gid);
} else if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
return local_set_xattr(rpath(fs_ctx, path, buffer), credp);
+ } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
+ return local_set_mapped_file_attr(fs_ctx, path, credp);
}
return -1;
}
@@ -595,8 +850,46 @@ static int local_utimensat(FsContext *s, V9fsPath *fs_path,
static int local_remove(FsContext *ctx, const char *path)
{
+ int err;
+ struct stat stbuf;
char buffer[PATH_MAX];
+
+ if (ctx->export_flags & V9FS_SM_MAPPED_FILE) {
+ err = lstat(rpath(ctx, path, buffer), &stbuf);
+ if (err) {
+ goto err_out;
+ }
+ /*
+ * If directory remove .virtfs_metadata contained in the
+ * directory
+ */
+ if (S_ISDIR(stbuf.st_mode)) {
+ sprintf(buffer, "%s/%s/%s", ctx->fs_root, path, VIRTFS_META_DIR);
+ err = remove(buffer);
+ if (err < 0 && errno != ENOENT) {
+ /*
+ * We didn't had the .virtfs_metadata file. May be file created
+ * in non-mapped mode ?. Ignore ENOENT.
+ */
+ goto err_out;
+ }
+ }
+ /*
+ * Now remove the name from parent directory
+ * .virtfs_metadata directory
+ */
+ err = remove(local_mapped_attr_path(ctx, path, buffer));;
+ if (err < 0 && errno != ENOENT) {
+ /*
+ * We didn't had the .virtfs_metadata file. May be file created
+ * in non-mapped mode ?. Ignore ENOENT.
+ */
+ goto err_out;
+ }
+ }
return remove(rpath(ctx, path, buffer));
+err_out:
+ return err;
}
static int local_fsync(FsContext *ctx, int fid_type,
@@ -696,12 +989,45 @@ static int local_unlinkat(FsContext *ctx, V9fsPath *dir,
int ret;
V9fsString fullname;
char buffer[PATH_MAX];
+
v9fs_string_init(&fullname);
v9fs_string_sprintf(&fullname, "%s/%s", dir->data, name);
+ if (ctx->export_flags & V9FS_SM_MAPPED_FILE) {
+ if (flags == AT_REMOVEDIR) {
+ /*
+ * If directory remove .virtfs_metadata contained in the
+ * directory
+ */
+ sprintf(buffer, "%s/%s/%s", ctx->fs_root,
+ fullname.data, VIRTFS_META_DIR);
+ ret = remove(buffer);
+ if (ret < 0 && errno != ENOENT) {
+ /*
+ * We didn't had the .virtfs_metadata file. May be file created
+ * in non-mapped mode ?. Ignore ENOENT.
+ */
+ goto err_out;
+ }
+ }
+ /*
+ * Now remove the name from parent directory
+ * .virtfs_metadata directory.
+ */
+ ret = remove(local_mapped_attr_path(ctx, fullname.data, buffer));
+ if (ret < 0 && errno != ENOENT) {
+ /*
+ * We didn't had the .virtfs_metadata file. May be file created
+ * in non-mapped mode ?. Ignore ENOENT.
+ */
+ goto err_out;
+ }
+ }
+ /* Remove the name finally */
ret = remove(rpath(ctx, fullname.data, buffer));
v9fs_string_free(&fullname);
+err_out:
return ret;
}
@@ -736,6 +1062,19 @@ static int local_init(FsContext *ctx)
int err = 0;
struct statfs stbuf;
+ if (ctx->export_flags & V9FS_SM_PASSTHROUGH) {
+ ctx->xops = passthrough_xattr_ops;
+ } else if (ctx->export_flags & V9FS_SM_MAPPED) {
+ ctx->xops = mapped_xattr_ops;
+ } else if (ctx->export_flags & V9FS_SM_NONE) {
+ ctx->xops = none_xattr_ops;
+ } else if (ctx->export_flags & V9FS_SM_MAPPED_FILE) {
+ /*
+ * xattr operation for mapped-file and passthrough
+ * remain same.
+ */
+ ctx->xops = passthrough_xattr_ops;
+ }
ctx->export_flags |= V9FS_PATHNAME_FSCONTEXT;
#ifdef FS_IOC_GETVERSION
/*
@@ -770,13 +1109,17 @@ static int local_parse_opts(QemuOpts *opts, struct FsDriverEntry *fse)
if (!strcmp(sec_model, "passthrough")) {
fse->export_flags |= V9FS_SM_PASSTHROUGH;
- } else if (!strcmp(sec_model, "mapped")) {
+ } else if (!strcmp(sec_model, "mapped") ||
+ !strcmp(sec_model, "mapped-xattr")) {
fse->export_flags |= V9FS_SM_MAPPED;
} else if (!strcmp(sec_model, "none")) {
fse->export_flags |= V9FS_SM_NONE;
+ } else if (!strcmp(sec_model, "mapped-file")) {
+ fse->export_flags |= V9FS_SM_MAPPED_FILE;
} else {
fprintf(stderr, "Invalid security model %s specified, valid options are"
- "\n\t [passthrough|mapped|none]\n", sec_model);
+ "\n\t [passthrough|mapped-xattr|mapped-file|none]\n",
+ sec_model);
return -1;
}
diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c
index e6ba6ba30b..a72ffc3390 100644
--- a/hw/9pfs/virtio-9p.c
+++ b/hw/9pfs/virtio-9p.c
@@ -986,7 +986,7 @@ static void v9fs_attach(void *opaque)
s->root_fid = fid;
/* disable migration */
error_set(&s->migration_blocker, QERR_VIRTFS_FEATURE_BLOCKS_MIGRATION,
- s->ctx.fs_root, s->tag);
+ s->ctx.fs_root ? s->ctx.fs_root : "NULL", s->tag);
migrate_add_blocker(s->migration_blocker);
out:
put_fid(pdu, fidp);
@@ -1391,7 +1391,6 @@ static void v9fs_open(void *opaque)
err = -EROFS;
goto out;
}
- flags |= O_NOATIME;
}
err = v9fs_co_open(pdu, fidp, flags);
if (err < 0) {
diff --git a/hw/ac97.c b/hw/ac97.c
index ed2e4cd9ab..7bf9171487 100644
--- a/hw/ac97.c
+++ b/hw/ac97.c
@@ -1175,17 +1175,17 @@ static const VMStateDescription vmstate_ac97_bm_regs = {
.minimum_version_id = 1,
.minimum_version_id_old = 1,
.fields = (VMStateField []) {
- VMSTATE_UINT32(bdbar, AC97BusMasterRegs),
- VMSTATE_UINT8(civ, AC97BusMasterRegs),
- VMSTATE_UINT8(lvi, AC97BusMasterRegs),
- VMSTATE_UINT16(sr, AC97BusMasterRegs),
- VMSTATE_UINT16(picb, AC97BusMasterRegs),
- VMSTATE_UINT8(piv, AC97BusMasterRegs),
- VMSTATE_UINT8(cr, AC97BusMasterRegs),
- VMSTATE_UINT32(bd_valid, AC97BusMasterRegs),
- VMSTATE_UINT32(bd.addr, AC97BusMasterRegs),
- VMSTATE_UINT32(bd.ctl_len, AC97BusMasterRegs),
- VMSTATE_END_OF_LIST()
+ VMSTATE_UINT32 (bdbar, AC97BusMasterRegs),
+ VMSTATE_UINT8 (civ, AC97BusMasterRegs),
+ VMSTATE_UINT8 (lvi, AC97BusMasterRegs),
+ VMSTATE_UINT16 (sr, AC97BusMasterRegs),
+ VMSTATE_UINT16 (picb, AC97BusMasterRegs),
+ VMSTATE_UINT8 (piv, AC97BusMasterRegs),
+ VMSTATE_UINT8 (cr, AC97BusMasterRegs),
+ VMSTATE_UINT32 (bd_valid, AC97BusMasterRegs),
+ VMSTATE_UINT32 (bd.addr, AC97BusMasterRegs),
+ VMSTATE_UINT32 (bd.ctl_len, AC97BusMasterRegs),
+ VMSTATE_END_OF_LIST ()
}
};
@@ -1224,15 +1224,15 @@ static const VMStateDescription vmstate_ac97 = {
.minimum_version_id_old = 2,
.post_load = ac97_post_load,
.fields = (VMStateField []) {
- VMSTATE_PCI_DEVICE(dev, AC97LinkState),
- VMSTATE_UINT32(glob_cnt, AC97LinkState),
- VMSTATE_UINT32(glob_sta, AC97LinkState),
- VMSTATE_UINT32(cas, AC97LinkState),
- VMSTATE_STRUCT_ARRAY(bm_regs, AC97LinkState, 3, 1,
- vmstate_ac97_bm_regs, AC97BusMasterRegs),
- VMSTATE_BUFFER(mixer_data, AC97LinkState),
- VMSTATE_UNUSED_TEST(is_version_2, 3),
- VMSTATE_END_OF_LIST()
+ VMSTATE_PCI_DEVICE (dev, AC97LinkState),
+ VMSTATE_UINT32 (glob_cnt, AC97LinkState),
+ VMSTATE_UINT32 (glob_sta, AC97LinkState),
+ VMSTATE_UINT32 (cas, AC97LinkState),
+ VMSTATE_STRUCT_ARRAY (bm_regs, AC97LinkState, 3, 1,
+ vmstate_ac97_bm_regs, AC97BusMasterRegs),
+ VMSTATE_BUFFER (mixer_data, AC97LinkState),
+ VMSTATE_UNUSED_TEST (is_version_2, 3),
+ VMSTATE_END_OF_LIST ()
}
};
@@ -1243,7 +1243,7 @@ static const MemoryRegionPortio nam_portio[] = {
{ 0, 256 * 1, 1, .write = nam_writeb, },
{ 0, 256 * 2, 2, .write = nam_writew, },
{ 0, 256 * 4, 4, .write = nam_writel, },
- PORTIO_END_OF_LIST(),
+ PORTIO_END_OF_LIST (),
};
static const MemoryRegionOps ac97_io_nam_ops = {
@@ -1257,7 +1257,7 @@ static const MemoryRegionPortio nabm_portio[] = {
{ 0, 64 * 1, 1, .write = nabm_writeb, },
{ 0, 64 * 2, 2, .write = nabm_writew, },
{ 0, 64 * 4, 4, .write = nabm_writel, },
- PORTIO_END_OF_LIST()
+ PORTIO_END_OF_LIST ()
};
static const MemoryRegionOps ac97_io_nabm_ops = {
@@ -1345,14 +1345,14 @@ int ac97_init (PCIBus *bus)
}
static Property ac97_properties[] = {
- DEFINE_PROP_UINT32("use_broken_id", AC97LinkState, use_broken_id, 0),
- DEFINE_PROP_END_OF_LIST(),
+ DEFINE_PROP_UINT32 ("use_broken_id", AC97LinkState, use_broken_id, 0),
+ DEFINE_PROP_END_OF_LIST (),
};
-static void ac97_class_init(ObjectClass *klass, void *data)
+static void ac97_class_init (ObjectClass *klass, void *data)
{
- DeviceClass *dc = DEVICE_CLASS(klass);
- PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+ DeviceClass *dc = DEVICE_CLASS (klass);
+ PCIDeviceClass *k = PCI_DEVICE_CLASS (klass);
k->init = ac97_initfn;
k->exit = ac97_exitfn;
@@ -1374,7 +1374,7 @@ static TypeInfo ac97_info = {
static void ac97_register (void)
{
- type_register_static(&ac97_info);
+ type_register_static (&ac97_info);
}
device_init (ac97_register);
diff --git a/hw/adlib.c b/hw/adlib.c
index dd8b1888cf..d39cd97384 100644
--- a/hw/adlib.c
+++ b/hw/adlib.c
@@ -164,7 +164,7 @@ static void timer_handler (int c, double interval_Sec)
s->ticking[n] = 1;
#ifdef DEBUG
- interval = get_ticks_per_sec() * interval_Sec;
+ interval = get_ticks_per_sec () * interval_Sec;
exp = qemu_get_clock_ns (vm_clock) + interval;
s->exp[n] = exp;
#endif
diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c
index 116e2b10c5..a8e8ab7660 100644
--- a/hw/cirrus_vga.c
+++ b/hw/cirrus_vga.c
@@ -2164,6 +2164,15 @@ static void cirrus_cursor_invalidate(VGACommonState *s1)
}
}
+#define DEPTH 8
+#include "cirrus_vga_template.h"
+
+#define DEPTH 16
+#include "cirrus_vga_template.h"
+
+#define DEPTH 32
+#include "cirrus_vga_template.h"
+
static void cirrus_cursor_draw_line(VGACommonState *s1, uint8_t *d1, int scr_y)
{
CirrusVGAState *s = container_of(s1, CirrusVGAState, vga);
diff --git a/hw/cirrus_vga_template.h b/hw/cirrus_vga_template.h
new file mode 100644
index 0000000000..3b28280588
--- /dev/null
+++ b/hw/cirrus_vga_template.h
@@ -0,0 +1,102 @@
+/*
+ * QEMU Cirrus VGA Emulator templates
+ *
+ * Copyright (c) 2003 Fabrice Bellard
+ *
+ * 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.
+ */
+
+#if DEPTH == 8
+#define BPP 1
+#elif DEPTH == 15 || DEPTH == 16
+#define BPP 2
+#elif DEPTH == 32
+#define BPP 4
+#else
+#error unsupported depth
+#endif
+
+static void glue(vga_draw_cursor_line_, DEPTH)(uint8_t *d1,
+ const uint8_t *src1,
+ int poffset, int w,
+ unsigned int color0,
+ unsigned int color1,
+ unsigned int color_xor)
+{
+ const uint8_t *plane0, *plane1;
+ int x, b0, b1;
+ uint8_t *d;
+
+ d = d1;
+ plane0 = src1;
+ plane1 = src1 + poffset;
+ for (x = 0; x < w; x++) {
+ b0 = (plane0[x >> 3] >> (7 - (x & 7))) & 1;
+ b1 = (plane1[x >> 3] >> (7 - (x & 7))) & 1;
+#if DEPTH == 8
+ switch (b0 | (b1 << 1)) {
+ case 0:
+ break;
+ case 1:
+ d[0] ^= color_xor;
+ break;
+ case 2:
+ d[0] = color0;
+ break;
+ case 3:
+ d[0] = color1;
+ break;
+ }
+#elif DEPTH == 16
+ switch (b0 | (b1 << 1)) {
+ case 0:
+ break;
+ case 1:
+ ((uint16_t *)d)[0] ^= color_xor;
+ break;
+ case 2:
+ ((uint16_t *)d)[0] = color0;
+ break;
+ case 3:
+ ((uint16_t *)d)[0] = color1;
+ break;
+ }
+#elif DEPTH == 32
+ switch (b0 | (b1 << 1)) {
+ case 0:
+ break;
+ case 1:
+ ((uint32_t *)d)[0] ^= color_xor;
+ break;
+ case 2:
+ ((uint32_t *)d)[0] = color0;
+ break;
+ case 3:
+ ((uint32_t *)d)[0] = color1;
+ break;
+ }
+#else
+#error unsupported depth
+#endif
+ d += BPP;
+ }
+}
+
+#undef DEPTH
+#undef BPP
diff --git a/hw/cs4231a.c b/hw/cs4231a.c
index 811dda6516..ad04ad667c 100644
--- a/hw/cs4231a.c
+++ b/hw/cs4231a.c
@@ -622,13 +622,13 @@ static const VMStateDescription vmstate_cs4231a = {
.pre_load = cs4231a_pre_load,
.post_load = cs4231a_post_load,
.fields = (VMStateField []) {
- VMSTATE_UINT32_ARRAY(regs, CSState, CS_REGS),
- VMSTATE_BUFFER(dregs, CSState),
- VMSTATE_INT32(dma_running, CSState),
- VMSTATE_INT32(audio_free, CSState),
- VMSTATE_INT32(transferred, CSState),
- VMSTATE_INT32(aci_counter, CSState),
- VMSTATE_END_OF_LIST()
+ VMSTATE_UINT32_ARRAY (regs, CSState, CS_REGS),
+ VMSTATE_BUFFER (dregs, CSState),
+ VMSTATE_INT32 (dma_running, CSState),
+ VMSTATE_INT32 (audio_free, CSState),
+ VMSTATE_INT32 (transferred, CSState),
+ VMSTATE_INT32 (aci_counter, CSState),
+ VMSTATE_END_OF_LIST ()
}
};
@@ -672,10 +672,10 @@ static Property cs4231a_properties[] = {
DEFINE_PROP_END_OF_LIST (),
};
-static void cs4231a_class_initfn(ObjectClass *klass, void *data)
+static void cs4231a_class_initfn (ObjectClass *klass, void *data)
{
- DeviceClass *dc = DEVICE_CLASS(klass);
- ISADeviceClass *ic = ISA_DEVICE_CLASS(klass);
+ DeviceClass *dc = DEVICE_CLASS (klass);
+ ISADeviceClass *ic = ISA_DEVICE_CLASS (klass);
ic->init = cs4231a_initfn;
dc->desc = "Crystal Semiconductor CS4231A";
dc->vmsd = &vmstate_cs4231a;
@@ -691,6 +691,6 @@ static TypeInfo cs4231a_info = {
static void cs4231a_register (void)
{
- type_register_static(&cs4231a_info);
+ type_register_static (&cs4231a_info);
}
device_init (cs4231a_register)
diff --git a/hw/es1370.c b/hw/es1370.c
index 95e88b96ed..e377c48e49 100644
--- a/hw/es1370.c
+++ b/hw/es1370.c
@@ -914,7 +914,7 @@ static const MemoryRegionPortio es1370_portio[] = {
{ 0, 0x40 * 4, 1, .read = es1370_readb, },
{ 0, 0x40 * 2, 2, .read = es1370_readw, },
{ 0, 0x40, 4, .read = es1370_readl, },
- PORTIO_END_OF_LIST()
+ PORTIO_END_OF_LIST ()
};
static const MemoryRegionOps es1370_io_ops = {
@@ -928,12 +928,12 @@ static const VMStateDescription vmstate_es1370_channel = {
.minimum_version_id = 2,
.minimum_version_id_old = 2,
.fields = (VMStateField []) {
- VMSTATE_UINT32(shift, struct chan),
- VMSTATE_UINT32(leftover, struct chan),
- VMSTATE_UINT32(scount, struct chan),
- VMSTATE_UINT32(frame_addr, struct chan),
- VMSTATE_UINT32(frame_cnt, struct chan),
- VMSTATE_END_OF_LIST()
+ VMSTATE_UINT32 (shift, struct chan),
+ VMSTATE_UINT32 (leftover, struct chan),
+ VMSTATE_UINT32 (scount, struct chan),
+ VMSTATE_UINT32 (frame_addr, struct chan),
+ VMSTATE_UINT32 (frame_cnt, struct chan),
+ VMSTATE_END_OF_LIST ()
}
};
@@ -973,15 +973,15 @@ static const VMStateDescription vmstate_es1370 = {
.minimum_version_id_old = 2,
.post_load = es1370_post_load,
.fields = (VMStateField []) {
- VMSTATE_PCI_DEVICE(dev, ES1370State),
- VMSTATE_STRUCT_ARRAY(chan, ES1370State, NB_CHANNELS, 2,
- vmstate_es1370_channel, struct chan),
- VMSTATE_UINT32(ctl, ES1370State),
- VMSTATE_UINT32(status, ES1370State),
- VMSTATE_UINT32(mempage, ES1370State),
- VMSTATE_UINT32(codec, ES1370State),
- VMSTATE_UINT32(sctl, ES1370State),
- VMSTATE_END_OF_LIST()
+ VMSTATE_PCI_DEVICE (dev, ES1370State),
+ VMSTATE_STRUCT_ARRAY (chan, ES1370State, NB_CHANNELS, 2,
+ vmstate_es1370_channel, struct chan),
+ VMSTATE_UINT32 (ctl, ES1370State),
+ VMSTATE_UINT32 (status, ES1370State),
+ VMSTATE_UINT32 (mempage, ES1370State),
+ VMSTATE_UINT32 (codec, ES1370State),
+ VMSTATE_UINT32 (sctl, ES1370State),
+ VMSTATE_END_OF_LIST ()
}
};
@@ -1017,7 +1017,7 @@ static int es1370_initfn (PCIDevice *dev)
return 0;
}
-static int es1370_exitfn(PCIDevice *dev)
+static int es1370_exitfn (PCIDevice *dev)
{
ES1370State *s = DO_UPCAST (ES1370State, dev, dev);
@@ -1031,10 +1031,10 @@ int es1370_init (PCIBus *bus)
return 0;
}
-static void es1370_class_init(ObjectClass *klass, void *data)
+static void es1370_class_init (ObjectClass *klass, void *data)
{
- DeviceClass *dc = DEVICE_CLASS(klass);
- PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+ DeviceClass *dc = DEVICE_CLASS (klass);
+ PCIDeviceClass *k = PCI_DEVICE_CLASS (klass);
k->init = es1370_initfn;
k->exit = es1370_exitfn;
@@ -1056,7 +1056,7 @@ static TypeInfo es1370_info = {
static void es1370_register (void)
{
- type_register_static(&es1370_info);
+ type_register_static (&es1370_info);
}
device_init (es1370_register);
diff --git a/hw/framebuffer.c b/hw/framebuffer.c
index 6bf48dc046..ea122fb266 100644
--- a/hw/framebuffer.c
+++ b/hw/framebuffer.c
@@ -87,15 +87,8 @@ void framebuffer_update_display(
dest += i * dest_row_pitch;
for (; i < rows; i++) {
- target_phys_addr_t dirty_offset;
- dirty = 0;
- dirty_offset = 0;
- while (addr + dirty_offset < TARGET_PAGE_ALIGN(addr + src_width)) {
- dirty |= memory_region_get_dirty(mem, addr + dirty_offset,
+ dirty = memory_region_get_dirty(mem, addr, addr + src_width,
DIRTY_MEMORY_VGA);
- dirty_offset += TARGET_PAGE_SIZE;
- }
-
if (dirty || invalidate) {
fn(opaque, dest, src, cols, dest_col_pitch);
if (first == -1)
diff --git a/hw/g364fb.c b/hw/g364fb.c
index f47acc51c2..66d0044c06 100644
--- a/hw/g364fb.c
+++ b/hw/g364fb.c
@@ -62,7 +62,8 @@ typedef struct G364State {
static inline int check_dirty(G364State *s, ram_addr_t page)
{
- return memory_region_get_dirty(&s->mem_vram, page, DIRTY_MEMORY_VGA);
+ return memory_region_get_dirty(&s->mem_vram, page, G364_PAGE_SIZE,
+ DIRTY_MEMORY_VGA);
}
static inline void reset_dirty(G364State *s,
diff --git a/hw/gus.c b/hw/gus.c
index 49e5dbfbbb..20547075ec 100644
--- a/hw/gus.c
+++ b/hw/gus.c
@@ -221,14 +221,14 @@ static const VMStateDescription vmstate_gus = {
.minimum_version_id = 2,
.minimum_version_id_old = 2,
.fields = (VMStateField []) {
- VMSTATE_INT32(pos, GUSState),
- VMSTATE_INT32(left, GUSState),
- VMSTATE_INT32(shift, GUSState),
- VMSTATE_INT32(irqs, GUSState),
- VMSTATE_INT32(samples, GUSState),
- VMSTATE_INT64(last_ticks, GUSState),
- VMSTATE_BUFFER(himem, GUSState),
- VMSTATE_END_OF_LIST()
+ VMSTATE_INT32 (pos, GUSState),
+ VMSTATE_INT32 (left, GUSState),
+ VMSTATE_INT32 (shift, GUSState),
+ VMSTATE_INT32 (irqs, GUSState),
+ VMSTATE_INT32 (samples, GUSState),
+ VMSTATE_INT64 (last_ticks, GUSState),
+ VMSTATE_BUFFER (himem, GUSState),
+ VMSTATE_END_OF_LIST ()
}
};
@@ -239,13 +239,13 @@ static const MemoryRegionPortio gus_portio_list1[] = {
{0x006, 10, 2, .read = gus_readw, .write = gus_writew },
{0x100, 8, 1, .read = gus_readb, .write = gus_writeb },
{0x100, 8, 2, .read = gus_readw, .write = gus_writew },
- PORTIO_END_OF_LIST(),
+ PORTIO_END_OF_LIST (),
};
static const MemoryRegionPortio gus_portio_list2[] = {
{0, 1, 1, .read = gus_readb },
{0, 1, 2, .read = gus_readw },
- PORTIO_END_OF_LIST(),
+ PORTIO_END_OF_LIST (),
};
static int gus_initfn (ISADevice *dev)
@@ -307,10 +307,10 @@ static Property gus_properties[] = {
DEFINE_PROP_END_OF_LIST (),
};
-static void gus_class_initfn(ObjectClass *klass, void *data)
+static void gus_class_initfn (ObjectClass *klass, void *data)
{
- DeviceClass *dc = DEVICE_CLASS(klass);
- ISADeviceClass *ic = ISA_DEVICE_CLASS(klass);
+ DeviceClass *dc = DEVICE_CLASS (klass);
+ ISADeviceClass *ic = ISA_DEVICE_CLASS (klass);
ic->init = gus_initfn;
dc->desc = "Gravis Ultrasound GF1";
dc->vmsd = &vmstate_gus;
@@ -326,6 +326,6 @@ static TypeInfo gus_info = {
static void gus_register (void)
{
- type_register_static(&gus_info);
+ type_register_static (&gus_info);
}
device_init (gus_register)
diff --git a/hw/kvm/apic.c b/hw/kvm/apic.c
index 89e33b0ac8..dfc2ab3b03 100644
--- a/hw/kvm/apic.c
+++ b/hw/kvm/apic.c
@@ -135,6 +135,7 @@ static void kvm_apic_class_init(ObjectClass *klass, void *data)
static TypeInfo kvm_apic_info = {
.name = "kvm-apic",
.parent = TYPE_APIC_COMMON,
+ .instance_size = sizeof(APICCommonState),
.class_init = kvm_apic_class_init,
};
diff --git a/hw/kvm/i8259.c b/hw/kvm/i8259.c
index 297d64e11f..14bd427518 100644
--- a/hw/kvm/i8259.c
+++ b/hw/kvm/i8259.c
@@ -126,6 +126,7 @@ static void kvm_i8259_class_init(ObjectClass *klass, void *data)
static TypeInfo kvm_i8259_info = {
.name = "kvm-i8259",
.parent = TYPE_PIC_COMMON,
+ .instance_size = sizeof(PICCommonState),
.class_init = kvm_i8259_class_init,
};
diff --git a/hw/s390-virtio-bus.c b/hw/s390-virtio-bus.c
index b66ef68bc2..49140f8a9e 100644
--- a/hw/s390-virtio-bus.c
+++ b/hw/s390-virtio-bus.c
@@ -429,6 +429,7 @@ static TypeInfo virtio_s390_device_info = {
.parent = TYPE_DEVICE,
.instance_size = sizeof(VirtIOS390Device),
.class_init = virtio_s390_device_class_init,
+ .class_size = sizeof(VirtIOS390DeviceClass),
.abstract = true,
};
diff --git a/hw/sb16.c b/hw/sb16.c
index ae2545068a..db8929b98e 100644
--- a/hw/sb16.c
+++ b/hw/sb16.c
@@ -1289,55 +1289,55 @@ static const VMStateDescription vmstate_sb16 = {
.minimum_version_id_old = 1,
.post_load = sb16_post_load,
.fields = (VMStateField []) {
- VMSTATE_UINT32(irq, SB16State),
- VMSTATE_UINT32(dma, SB16State),
- VMSTATE_UINT32(hdma, SB16State),
- VMSTATE_UINT32(port, SB16State),
- VMSTATE_UINT32(ver, SB16State),
- VMSTATE_INT32(in_index, SB16State),
- VMSTATE_INT32(out_data_len, SB16State),
- VMSTATE_INT32(fmt_stereo, SB16State),
- VMSTATE_INT32(fmt_signed, SB16State),
- VMSTATE_INT32(fmt_bits, SB16State),
- VMSTATE_UINT32(fmt, SB16State),
- VMSTATE_INT32(dma_auto, SB16State),
- VMSTATE_INT32(block_size, SB16State),
- VMSTATE_INT32(fifo, SB16State),
- VMSTATE_INT32(freq, SB16State),
- VMSTATE_INT32(time_const, SB16State),
- VMSTATE_INT32(speaker, SB16State),
- VMSTATE_INT32(needed_bytes, SB16State),
- VMSTATE_INT32(cmd, SB16State),
- VMSTATE_INT32(use_hdma, SB16State),
- VMSTATE_INT32(highspeed, SB16State),
- VMSTATE_INT32(can_write, SB16State),
- VMSTATE_INT32(v2x6, SB16State),
-
- VMSTATE_UINT8(csp_param, SB16State),
- VMSTATE_UINT8(csp_value, SB16State),
- VMSTATE_UINT8(csp_mode, SB16State),
- VMSTATE_UINT8(csp_param, SB16State),
- VMSTATE_BUFFER(csp_regs, SB16State),
- VMSTATE_UINT8(csp_index, SB16State),
- VMSTATE_BUFFER(csp_reg83, SB16State),
- VMSTATE_INT32(csp_reg83r, SB16State),
- VMSTATE_INT32(csp_reg83w, SB16State),
-
- VMSTATE_BUFFER(in2_data, SB16State),
- VMSTATE_BUFFER(out_data, SB16State),
- VMSTATE_UINT8(test_reg, SB16State),
- VMSTATE_UINT8(last_read_byte, SB16State),
-
- VMSTATE_INT32(nzero, SB16State),
- VMSTATE_INT32(left_till_irq, SB16State),
- VMSTATE_INT32(dma_running, SB16State),
- VMSTATE_INT32(bytes_per_second, SB16State),
- VMSTATE_INT32(align, SB16State),
-
- VMSTATE_INT32(mixer_nreg, SB16State),
- VMSTATE_BUFFER(mixer_regs, SB16State),
-
- VMSTATE_END_OF_LIST()
+ VMSTATE_UINT32 (irq, SB16State),
+ VMSTATE_UINT32 (dma, SB16State),
+ VMSTATE_UINT32 (hdma, SB16State),
+ VMSTATE_UINT32 (port, SB16State),
+ VMSTATE_UINT32 (ver, SB16State),
+ VMSTATE_INT32 (in_index, SB16State),
+ VMSTATE_INT32 (out_data_len, SB16State),
+ VMSTATE_INT32 (fmt_stereo, SB16State),
+ VMSTATE_INT32 (fmt_signed, SB16State),
+ VMSTATE_INT32 (fmt_bits, SB16State),
+ VMSTATE_UINT32 (fmt, SB16State),
+ VMSTATE_INT32 (dma_auto, SB16State),
+ VMSTATE_INT32 (block_size, SB16State),
+ VMSTATE_INT32 (fifo, SB16State),
+ VMSTATE_INT32 (freq, SB16State),
+ VMSTATE_INT32 (time_const, SB16State),
+ VMSTATE_INT32 (speaker, SB16State),
+ VMSTATE_INT32 (needed_bytes, SB16State),
+ VMSTATE_INT32 (cmd, SB16State),
+ VMSTATE_INT32 (use_hdma, SB16State),
+ VMSTATE_INT32 (highspeed, SB16State),
+ VMSTATE_INT32 (can_write, SB16State),
+ VMSTATE_INT32 (v2x6, SB16State),
+
+ VMSTATE_UINT8 (csp_param, SB16State),
+ VMSTATE_UINT8 (csp_value, SB16State),
+ VMSTATE_UINT8 (csp_mode, SB16State),
+ VMSTATE_UINT8 (csp_param, SB16State),
+ VMSTATE_BUFFER (csp_regs, SB16State),
+ VMSTATE_UINT8 (csp_index, SB16State),
+ VMSTATE_BUFFER (csp_reg83, SB16State),
+ VMSTATE_INT32 (csp_reg83r, SB16State),
+ VMSTATE_INT32 (csp_reg83w, SB16State),
+
+ VMSTATE_BUFFER (in2_data, SB16State),
+ VMSTATE_BUFFER (out_data, SB16State),
+ VMSTATE_UINT8 (test_reg, SB16State),
+ VMSTATE_UINT8 (last_read_byte, SB16State),
+
+ VMSTATE_INT32 (nzero, SB16State),
+ VMSTATE_INT32 (left_till_irq, SB16State),
+ VMSTATE_INT32 (dma_running, SB16State),
+ VMSTATE_INT32 (bytes_per_second, SB16State),
+ VMSTATE_INT32 (align, SB16State),
+
+ VMSTATE_INT32 (mixer_nreg, SB16State),
+ VMSTATE_BUFFER (mixer_regs, SB16State),
+
+ VMSTATE_END_OF_LIST ()
}
};
@@ -1349,7 +1349,7 @@ static const MemoryRegionPortio sb16_ioport_list[] = {
{ 10, 1, 1, .read = dsp_read },
{ 12, 1, 1, .write = dsp_write },
{ 12, 4, 1, .read = dsp_read },
- PORTIO_END_OF_LIST(),
+ PORTIO_END_OF_LIST (),
};
@@ -1400,10 +1400,10 @@ static Property sb16_properties[] = {
DEFINE_PROP_END_OF_LIST (),
};
-static void sb16_class_initfn(ObjectClass *klass, void *data)
+static void sb16_class_initfn (ObjectClass *klass, void *data)
{
- DeviceClass *dc = DEVICE_CLASS(klass);
- ISADeviceClass *ic = ISA_DEVICE_CLASS(klass);
+ DeviceClass *dc = DEVICE_CLASS (klass);
+ ISADeviceClass *ic = ISA_DEVICE_CLASS (klass);
ic->init = sb16_initfn;
dc->desc = "Creative Sound Blaster 16";
dc->vmsd = &vmstate_sb16;
@@ -1419,6 +1419,6 @@ static TypeInfo sb16_info = {
static void sb16_register (void)
{
- type_register_static(&sb16_info);
+ type_register_static (&sb16_info);
}
device_init (sb16_register)
diff --git a/hw/sm501.c b/hw/sm501.c
index 09c5894cf9..94c0abf4cb 100644
--- a/hw/sm501.c
+++ b/hw/sm501.c
@@ -1323,15 +1323,12 @@ static void sm501_draw_crt(SM501State * s)
for (y = 0; y < height; y++) {
int update_hwc = draw_hwc_line ? within_hwc_y_range(s, y, 1) : 0;
int update = full_update || update_hwc;
- ram_addr_t page0 = offset & TARGET_PAGE_MASK;
- ram_addr_t page1 = (offset + width * src_bpp - 1) & TARGET_PAGE_MASK;
- ram_addr_t page;
+ ram_addr_t page0 = offset;
+ ram_addr_t page1 = offset + width * src_bpp - 1;
/* check dirty flags for each line */
- for (page = page0; page <= page1; page += TARGET_PAGE_SIZE)
- if (memory_region_get_dirty(&s->local_mem_region, page,
- DIRTY_MEMORY_VGA))
- update = 1;
+ update = memory_region_get_dirty(&s->local_mem_region, page0, page1,
+ DIRTY_MEMORY_VGA);
/* draw line and change status */
if (update) {
diff --git a/hw/tcx.c b/hw/tcx.c
index f400f92307..ceb94c74a7 100644
--- a/hw/tcx.c
+++ b/hw/tcx.c
@@ -178,15 +178,13 @@ static inline int check_dirty(TCXState *s, ram_addr_t page, ram_addr_t page24,
ram_addr_t cpage)
{
int ret;
- unsigned int off;
-
- ret = memory_region_get_dirty(&s->vram_mem, page, DIRTY_MEMORY_VGA);
- for (off = 0; off < TARGET_PAGE_SIZE * 4; off += TARGET_PAGE_SIZE) {
- ret |= memory_region_get_dirty(&s->vram_mem, page24 + off,
- DIRTY_MEMORY_VGA);
- ret |= memory_region_get_dirty(&s->vram_mem, cpage + off,
- DIRTY_MEMORY_VGA);
- }
+
+ ret = memory_region_get_dirty(&s->vram_mem, page, TARGET_PAGE_SIZE,
+ DIRTY_MEMORY_VGA);
+ ret |= memory_region_get_dirty(&s->vram_mem, page24, TARGET_PAGE_SIZE * 4,
+ DIRTY_MEMORY_VGA);
+ ret |= memory_region_get_dirty(&s->vram_mem, cpage, TARGET_PAGE_SIZE * 4,
+ DIRTY_MEMORY_VGA);
return ret;
}
@@ -245,7 +243,8 @@ static void tcx_update_display(void *opaque)
}
for(y = 0; y < ts->height; y += 4, page += TARGET_PAGE_SIZE) {
- if (memory_region_get_dirty(&ts->vram_mem, page, DIRTY_MEMORY_VGA)) {
+ if (memory_region_get_dirty(&ts->vram_mem, page, TARGET_PAGE_SIZE,
+ DIRTY_MEMORY_VGA)) {
if (y_start < 0)
y_start = y;
if (page < page_min)
diff --git a/hw/vga.c b/hw/vga.c
index 4dc2610314..d87c4f9f5b 100644
--- a/hw/vga.c
+++ b/hw/vga.c
@@ -22,6 +22,7 @@
* THE SOFTWARE.
*/
#include "hw.h"
+#include "vga.h"
#include "console.h"
#include "pc.h"
#include "pci.h"
@@ -36,6 +37,18 @@
//#define DEBUG_BOCHS_VBE
+/*
+ * Video Graphics Array (VGA)
+ *
+ * Chipset docs for original IBM VGA:
+ * http://www.mcamafia.de/pdf/ibm_vgaxga_trm2.pdf
+ *
+ * FreeVGA site:
+ * http://www.osdever.net/FreeVGA/home.htm
+ *
+ * Standard VGA features and Bochs VBE extensions are implemented.
+ */
+
/* force some bits to zero */
const uint8_t sr_mask[8] = {
0x03,
@@ -160,9 +173,10 @@ static void vga_update_memory_access(VGACommonState *s)
s->chain4_alias = NULL;
- if ((s->sr[0x02] & 0xf) == 0xf && s->sr[0x04] & 0x08) {
+ if ((s->sr[VGA_SEQ_PLANE_WRITE] & VGA_SR02_ALL_PLANES) ==
+ VGA_SR02_ALL_PLANES && s->sr[VGA_SEQ_MEMORY_MODE] & VGA_SR04_CHN_4M) {
offset = 0;
- switch ((s->gr[6] >> 2) & 3) {
+ switch ((s->gr[VGA_GFX_MISC] >> 2) & 3) {
case 0:
base = 0xa0000;
size = 0x20000;
@@ -223,22 +237,20 @@ static void vga_precise_update_retrace_info(VGACommonState *s)
int64_t chars_per_sec;
struct vga_precise_retrace *r = &s->retrace_info.precise;
- htotal_chars = s->cr[0x00] + 5;
- hretr_start_char = s->cr[0x04];
- hretr_skew_chars = (s->cr[0x05] >> 5) & 3;
- hretr_end_char = s->cr[0x05] & 0x1f;
+ htotal_chars = s->cr[VGA_CRTC_H_TOTAL] + 5;
+ hretr_start_char = s->cr[VGA_CRTC_H_SYNC_START];
+ hretr_skew_chars = (s->cr[VGA_CRTC_H_SYNC_END] >> 5) & 3;
+ hretr_end_char = s->cr[VGA_CRTC_H_SYNC_END] & 0x1f;
- vtotal_lines = (s->cr[0x06]
- | (((s->cr[0x07] & 1) | ((s->cr[0x07] >> 4) & 2)) << 8)) + 2
- ;
- vretr_start_line = s->cr[0x10]
- | ((((s->cr[0x07] >> 2) & 1) | ((s->cr[0x07] >> 6) & 2)) << 8)
- ;
- vretr_end_line = s->cr[0x11] & 0xf;
+ vtotal_lines = (s->cr[VGA_CRTC_V_TOTAL] |
+ (((s->cr[VGA_CRTC_OVERFLOW] & 1) |
+ ((s->cr[VGA_CRTC_OVERFLOW] >> 4) & 2)) << 8)) + 2;
+ vretr_start_line = s->cr[VGA_CRTC_V_SYNC_START] |
+ ((((s->cr[VGA_CRTC_OVERFLOW] >> 2) & 1) |
+ ((s->cr[VGA_CRTC_OVERFLOW] >> 6) & 2)) << 8);
+ vretr_end_line = s->cr[VGA_CRTC_V_SYNC_END] & 0xf;
-
-
- clocking_mode = (s->sr[0x01] >> 3) & 1;
+ clocking_mode = (s->sr[VGA_SEQ_CLOCK_MODE] >> 3) & 1;
clock_sel = (s->msr >> 2) & 3;
dots = (s->msr & 1) ? 8 : 9;
@@ -261,8 +273,8 @@ static void vga_precise_update_retrace_info(VGACommonState *s)
r->htotal = htotal_chars;
#if 0
- div2 = (s->cr[0x17] >> 2) & 1;
- sldiv2 = (s->cr[0x17] >> 3) & 1;
+ div2 = (s->cr[VGA_CRTC_MODE] >> 2) & 1;
+ sldiv2 = (s->cr[VGA_CRTC_MODE] >> 3) & 1;
printf (
"hz=%f\n"
"htotal = %d\n"
@@ -332,7 +344,7 @@ static uint8_t vga_dumb_retrace(VGACommonState *s)
int vga_ioport_invalid(VGACommonState *s, uint32_t addr)
{
- if (s->msr & MSR_COLOR_EMULATION) {
+ if (s->msr & VGA_MIS_COLOR) {
/* Color */
return (addr >= 0x3b0 && addr <= 0x3bf);
} else {
@@ -350,73 +362,74 @@ uint32_t vga_ioport_read(void *opaque, uint32_t addr)
val = 0xff;
} else {
switch(addr) {
- case 0x3c0:
+ case VGA_ATT_W:
if (s->ar_flip_flop == 0) {
val = s->ar_index;
} else {
val = 0;
}
break;
- case 0x3c1:
+ case VGA_ATT_R:
index = s->ar_index & 0x1f;
- if (index < 21)
+ if (index < VGA_ATT_C) {
val = s->ar[index];
- else
+ } else {
val = 0;
+ }
break;
- case 0x3c2:
+ case VGA_MIS_W:
val = s->st00;
break;
- case 0x3c4:
+ case VGA_SEQ_I:
val = s->sr_index;
break;
- case 0x3c5:
+ case VGA_SEQ_D:
val = s->sr[s->sr_index];
#ifdef DEBUG_VGA_REG
printf("vga: read SR%x = 0x%02x\n", s->sr_index, val);
#endif
break;
- case 0x3c7:
+ case VGA_PEL_IR:
val = s->dac_state;
break;
- case 0x3c8:
+ case VGA_PEL_IW:
val = s->dac_write_index;
break;
- case 0x3c9:
+ case VGA_PEL_D:
val = s->palette[s->dac_read_index * 3 + s->dac_sub_index];
if (++s->dac_sub_index == 3) {
s->dac_sub_index = 0;
s->dac_read_index++;
}
break;
- case 0x3ca:
+ case VGA_FTC_R:
val = s->fcr;
break;
- case 0x3cc:
+ case VGA_MIS_R:
val = s->msr;
break;
- case 0x3ce:
+ case VGA_GFX_I:
val = s->gr_index;
break;
- case 0x3cf:
+ case VGA_GFX_D:
val = s->gr[s->gr_index];
#ifdef DEBUG_VGA_REG
printf("vga: read GR%x = 0x%02x\n", s->gr_index, val);
#endif
break;
- case 0x3b4:
- case 0x3d4:
+ case VGA_CRT_IM:
+ case VGA_CRT_IC:
val = s->cr_index;
break;
- case 0x3b5:
- case 0x3d5:
+ case VGA_CRT_DM:
+ case VGA_CRT_DC:
val = s->cr[s->cr_index];
#ifdef DEBUG_VGA_REG
printf("vga: read CR%x = 0x%02x\n", s->cr_index, val);
#endif
break;
- case 0x3ba:
- case 0x3da:
+ case VGA_IS1_RM:
+ case VGA_IS1_RC:
/* just toggle to fool polling */
val = s->st01 = s->retrace(s);
s->ar_flip_flop = 0;
@@ -446,29 +459,29 @@ void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
#endif
switch(addr) {
- case 0x3c0:
+ case VGA_ATT_W:
if (s->ar_flip_flop == 0) {
val &= 0x3f;
s->ar_index = val;
} else {
index = s->ar_index & 0x1f;
switch(index) {
- case 0x00 ... 0x0f:
+ case VGA_ATC_PALETTE0 ... VGA_ATC_PALETTEF:
s->ar[index] = val & 0x3f;
break;
- case 0x10:
+ case VGA_ATC_MODE:
s->ar[index] = val & ~0x10;
break;
- case 0x11:
+ case VGA_ATC_OVERSCAN:
s->ar[index] = val;
break;
- case 0x12:
+ case VGA_ATC_PLANE_ENABLE:
s->ar[index] = val & ~0xc0;
break;
- case 0x13:
+ case VGA_ATC_PEL:
s->ar[index] = val & ~0xf0;
break;
- case 0x14:
+ case VGA_ATC_COLOR_PAGE:
s->ar[index] = val & ~0xf0;
break;
default:
@@ -477,32 +490,34 @@ void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
}
s->ar_flip_flop ^= 1;
break;
- case 0x3c2:
+ case VGA_MIS_W:
s->msr = val & ~0x10;
s->update_retrace_info(s);
break;
- case 0x3c4:
+ case VGA_SEQ_I:
s->sr_index = val & 7;
break;
- case 0x3c5:
+ case VGA_SEQ_D:
#ifdef DEBUG_VGA_REG
printf("vga: write SR%x = 0x%02x\n", s->sr_index, val);
#endif
s->sr[s->sr_index] = val & sr_mask[s->sr_index];
- if (s->sr_index == 1) s->update_retrace_info(s);
+ if (s->sr_index == VGA_SEQ_CLOCK_MODE) {
+ s->update_retrace_info(s);
+ }
vga_update_memory_access(s);
break;
- case 0x3c7:
+ case VGA_PEL_IR:
s->dac_read_index = val;
s->dac_sub_index = 0;
s->dac_state = 3;
break;
- case 0x3c8:
+ case VGA_PEL_IW:
s->dac_write_index = val;
s->dac_sub_index = 0;
s->dac_state = 0;
break;
- case 0x3c9:
+ case VGA_PEL_D:
s->dac_cache[s->dac_sub_index] = val;
if (++s->dac_sub_index == 3) {
memcpy(&s->palette[s->dac_write_index * 3], s->dac_cache, 3);
@@ -510,48 +525,51 @@ void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
s->dac_write_index++;
}
break;
- case 0x3ce:
+ case VGA_GFX_I:
s->gr_index = val & 0x0f;
break;
- case 0x3cf:
+ case VGA_GFX_D:
#ifdef DEBUG_VGA_REG
printf("vga: write GR%x = 0x%02x\n", s->gr_index, val);
#endif
s->gr[s->gr_index] = val & gr_mask[s->gr_index];
vga_update_memory_access(s);
break;
- case 0x3b4:
- case 0x3d4:
+ case VGA_CRT_IM:
+ case VGA_CRT_IC:
s->cr_index = val;
break;
- case 0x3b5:
- case 0x3d5:
+ case VGA_CRT_DM:
+ case VGA_CRT_DC:
#ifdef DEBUG_VGA_REG
printf("vga: write CR%x = 0x%02x\n", s->cr_index, val);
#endif
/* handle CR0-7 protection */
- if ((s->cr[0x11] & 0x80) && s->cr_index <= 7) {
+ if ((s->cr[VGA_CRTC_V_SYNC_END] & VGA_CR11_LOCK_CR0_CR7) &&
+ s->cr_index <= VGA_CRTC_OVERFLOW) {
/* can always write bit 4 of CR7 */
- if (s->cr_index == 7)
- s->cr[7] = (s->cr[7] & ~0x10) | (val & 0x10);
+ if (s->cr_index == VGA_CRTC_OVERFLOW) {
+ s->cr[VGA_CRTC_OVERFLOW] = (s->cr[VGA_CRTC_OVERFLOW] & ~0x10) |
+ (val & 0x10);
+ }
return;
}
s->cr[s->cr_index] = val;
switch(s->cr_index) {
- case 0x00:
- case 0x04:
- case 0x05:
- case 0x06:
- case 0x07:
- case 0x11:
- case 0x17:
+ case VGA_CRTC_H_TOTAL:
+ case VGA_CRTC_H_SYNC_START:
+ case VGA_CRTC_H_SYNC_END:
+ case VGA_CRTC_V_TOTAL:
+ case VGA_CRTC_OVERFLOW:
+ case VGA_CRTC_V_SYNC_END:
+ case VGA_CRTC_MODE:
s->update_retrace_info(s);
break;
}
break;
- case 0x3ba:
- case 0x3da:
+ case VGA_IS1_RM:
+ case VGA_IS1_RC:
s->fcr = val & 0x10;
break;
}
@@ -681,31 +699,37 @@ static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
/* we initialize the VGA graphic mode (should be done
in BIOS) */
- s->gr[0x06] = (s->gr[0x06] & ~0x0c) | 0x05; /* graphic mode + memory map 1 */
- s->cr[0x17] |= 3; /* no CGA modes */
- s->cr[0x13] = s->vbe_line_offset >> 3;
+ /* graphic mode + memory map 1 */
+ s->gr[VGA_GFX_MISC] = (s->gr[VGA_GFX_MISC] & ~0x0c) | 0x04 |
+ VGA_GR06_GRAPHICS_MODE;
+ s->cr[VGA_CRTC_MODE] |= 3; /* no CGA modes */
+ s->cr[VGA_CRTC_OFFSET] = s->vbe_line_offset >> 3;
/* width */
- s->cr[0x01] = (s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 3) - 1;
+ s->cr[VGA_CRTC_H_DISP] =
+ (s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 3) - 1;
/* height (only meaningful if < 1024) */
h = s->vbe_regs[VBE_DISPI_INDEX_YRES] - 1;
- s->cr[0x12] = h;
- s->cr[0x07] = (s->cr[0x07] & ~0x42) |
+ s->cr[VGA_CRTC_V_DISP_END] = h;
+ s->cr[VGA_CRTC_OVERFLOW] = (s->cr[VGA_CRTC_OVERFLOW] & ~0x42) |
((h >> 7) & 0x02) | ((h >> 3) & 0x40);
/* line compare to 1023 */
- s->cr[0x18] = 0xff;
- s->cr[0x07] |= 0x10;
- s->cr[0x09] |= 0x40;
+ s->cr[VGA_CRTC_LINE_COMPARE] = 0xff;
+ s->cr[VGA_CRTC_OVERFLOW] |= 0x10;
+ s->cr[VGA_CRTC_MAX_SCAN] |= 0x40;
if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) {
shift_control = 0;
- s->sr[0x01] &= ~8; /* no double line */
+ s->sr[VGA_SEQ_CLOCK_MODE] &= ~8; /* no double line */
} else {
shift_control = 2;
- s->sr[4] |= 0x08; /* set chain 4 mode */
- s->sr[2] |= 0x0f; /* activate all planes */
+ /* set chain 4 mode */
+ s->sr[VGA_SEQ_MEMORY_MODE] |= VGA_SR04_CHN_4M;
+ /* activate all planes */
+ s->sr[VGA_SEQ_PLANE_WRITE] |= VGA_SR02_ALL_PLANES;
}
- s->gr[0x05] = (s->gr[0x05] & ~0x60) | (shift_control << 5);
- s->cr[0x09] &= ~0x9f; /* no double scan */
+ s->gr[VGA_GFX_MODE] = (s->gr[VGA_GFX_MODE] & ~0x60) |
+ (shift_control << 5);
+ s->cr[VGA_CRTC_MAX_SCAN] &= ~0x9f; /* no double scan */
} else {
/* XXX: the bios should do that */
s->bank_offset = 0;
@@ -762,7 +786,7 @@ uint32_t vga_mem_readb(VGACommonState *s, target_phys_addr_t addr)
uint32_t ret;
/* convert to VGA memory offset */
- memory_map_mode = (s->gr[6] >> 2) & 3;
+ memory_map_mode = (s->gr[VGA_GFX_MISC] >> 2) & 3;
addr &= 0x1ffff;
switch(memory_map_mode) {
case 0:
@@ -785,24 +809,25 @@ uint32_t vga_mem_readb(VGACommonState *s, target_phys_addr_t addr)
break;
}
- if (s->sr[4] & 0x08) {
+ if (s->sr[VGA_SEQ_MEMORY_MODE] & VGA_SR04_CHN_4M) {
/* chain 4 mode : simplest access */
ret = s->vram_ptr[addr];
- } else if (s->gr[5] & 0x10) {
+ } else if (s->gr[VGA_GFX_MODE] & 0x10) {
/* odd/even mode (aka text mode mapping) */
- plane = (s->gr[4] & 2) | (addr & 1);
+ plane = (s->gr[VGA_GFX_PLANE_READ] & 2) | (addr & 1);
ret = s->vram_ptr[((addr & ~1) << 1) | plane];
} else {
/* standard VGA latched access */
s->latch = ((uint32_t *)s->vram_ptr)[addr];
- if (!(s->gr[5] & 0x08)) {
+ if (!(s->gr[VGA_GFX_MODE] & 0x08)) {
/* read mode 0 */
- plane = s->gr[4];
+ plane = s->gr[VGA_GFX_PLANE_READ];
ret = GET_PLANE(s->latch, plane);
} else {
/* read mode 1 */
- ret = (s->latch ^ mask16[s->gr[2]]) & mask16[s->gr[7]];
+ ret = (s->latch ^ mask16[s->gr[VGA_GFX_COMPARE_VALUE]]) &
+ mask16[s->gr[VGA_GFX_COMPARE_MASK]];
ret |= ret >> 16;
ret |= ret >> 8;
ret = (~ret) & 0xff;
@@ -821,7 +846,7 @@ void vga_mem_writeb(VGACommonState *s, target_phys_addr_t addr, uint32_t val)
printf("vga: [0x" TARGET_FMT_plx "] = 0x%02x\n", addr, val);
#endif
/* convert to VGA memory offset */
- memory_map_mode = (s->gr[6] >> 2) & 3;
+ memory_map_mode = (s->gr[VGA_GFX_MISC] >> 2) & 3;
addr &= 0x1ffff;
switch(memory_map_mode) {
case 0:
@@ -844,11 +869,11 @@ void vga_mem_writeb(VGACommonState *s, target_phys_addr_t addr, uint32_t val)
break;
}
- if (s->sr[4] & 0x08) {
+ if (s->sr[VGA_SEQ_MEMORY_MODE] & VGA_SR04_CHN_4M) {
/* chain 4 mode : simplest access */
plane = addr & 3;
mask = (1 << plane);
- if (s->sr[2] & mask) {
+ if (s->sr[VGA_SEQ_PLANE_WRITE] & mask) {
s->vram_ptr[addr] = val;
#ifdef DEBUG_VGA_MEM
printf("vga: chain4: [0x" TARGET_FMT_plx "]\n", addr);
@@ -856,11 +881,11 @@ void vga_mem_writeb(VGACommonState *s, target_phys_addr_t addr, uint32_t val)
s->plane_updated |= mask; /* only used to detect font change */
memory_region_set_dirty(&s->vram, addr, 1);
}
- } else if (s->gr[5] & 0x10) {
+ } else if (s->gr[VGA_GFX_MODE] & 0x10) {
/* odd/even mode (aka text mode mapping) */
- plane = (s->gr[4] & 2) | (addr & 1);
+ plane = (s->gr[VGA_GFX_PLANE_READ] & 2) | (addr & 1);
mask = (1 << plane);
- if (s->sr[2] & mask) {
+ if (s->sr[VGA_SEQ_PLANE_WRITE] & mask) {
addr = ((addr & ~1) << 1) | plane;
s->vram_ptr[addr] = val;
#ifdef DEBUG_VGA_MEM
@@ -871,40 +896,41 @@ void vga_mem_writeb(VGACommonState *s, target_phys_addr_t addr, uint32_t val)
}
} else {
/* standard VGA latched access */
- write_mode = s->gr[5] & 3;
+ write_mode = s->gr[VGA_GFX_MODE] & 3;
switch(write_mode) {
default:
case 0:
/* rotate */
- b = s->gr[3] & 7;
+ b = s->gr[VGA_GFX_DATA_ROTATE] & 7;
val = ((val >> b) | (val << (8 - b))) & 0xff;
val |= val << 8;
val |= val << 16;
/* apply set/reset mask */
- set_mask = mask16[s->gr[1]];
- val = (val & ~set_mask) | (mask16[s->gr[0]] & set_mask);
- bit_mask = s->gr[8];
+ set_mask = mask16[s->gr[VGA_GFX_SR_ENABLE]];
+ val = (val & ~set_mask) |
+ (mask16[s->gr[VGA_GFX_SR_VALUE]] & set_mask);
+ bit_mask = s->gr[VGA_GFX_BIT_MASK];
break;
case 1:
val = s->latch;
goto do_write;
case 2:
val = mask16[val & 0x0f];
- bit_mask = s->gr[8];
+ bit_mask = s->gr[VGA_GFX_BIT_MASK];
break;
case 3:
/* rotate */
- b = s->gr[3] & 7;
+ b = s->gr[VGA_GFX_DATA_ROTATE] & 7;
val = (val >> b) | (val << (8 - b));
- bit_mask = s->gr[8] & val;
- val = mask16[s->gr[0]];
+ bit_mask = s->gr[VGA_GFX_BIT_MASK] & val;
+ val = mask16[s->gr[VGA_GFX_SR_VALUE]];
break;
}
/* apply logical operation */
- func_select = s->gr[3] >> 3;
+ func_select = s->gr[VGA_GFX_DATA_ROTATE] >> 3;
switch(func_select) {
case 0:
default:
@@ -931,7 +957,7 @@ void vga_mem_writeb(VGACommonState *s, target_phys_addr_t addr, uint32_t val)
do_write:
/* mask data according to sr[2] */
- mask = s->sr[2];
+ mask = s->sr[VGA_SEQ_PLANE_WRITE];
s->plane_updated |= mask; /* only used to detect font change */
write_mask = mask16[mask];
((uint32_t *)s->vram_ptr)[addr] =
@@ -1045,10 +1071,11 @@ static int update_palette16(VGACommonState *s)
palette = s->last_palette;
for(i = 0; i < 16; i++) {
v = s->ar[i];
- if (s->ar[0x10] & 0x80)
- v = ((s->ar[0x14] & 0xf) << 4) | (v & 0xf);
- else
- v = ((s->ar[0x14] & 0xc) << 4) | (v & 0x3f);
+ if (s->ar[VGA_ATC_MODE] & 0x80) {
+ v = ((s->ar[VGA_ATC_COLOR_PAGE] & 0xf) << 4) | (v & 0xf);
+ } else {
+ v = ((s->ar[VGA_ATC_COLOR_PAGE] & 0xc) << 4) | (v & 0x3f);
+ }
v = v * 3;
col = s->rgb_to_pixel(c6_to_8(s->palette[v]),
c6_to_8(s->palette[v + 1]),
@@ -1104,16 +1131,17 @@ static void vga_get_offsets(VGACommonState *s,
#endif
{
/* compute line_offset in bytes */
- line_offset = s->cr[0x13];
+ line_offset = s->cr[VGA_CRTC_OFFSET];
line_offset <<= 3;
/* starting address */
- start_addr = s->cr[0x0d] | (s->cr[0x0c] << 8);
+ start_addr = s->cr[VGA_CRTC_START_LO] |
+ (s->cr[VGA_CRTC_START_HI] << 8);
/* line compare */
- line_compare = s->cr[0x18] |
- ((s->cr[0x07] & 0x10) << 4) |
- ((s->cr[0x09] & 0x40) << 3);
+ line_compare = s->cr[VGA_CRTC_LINE_COMPARE] |
+ ((s->cr[VGA_CRTC_OVERFLOW] & 0x10) << 4) |
+ ((s->cr[VGA_CRTC_MAX_SCAN] & 0x40) << 3);
}
*pline_offset = line_offset;
*pstart_addr = start_addr;
@@ -1216,20 +1244,22 @@ static void vga_get_text_resolution(VGACommonState *s, int *pwidth, int *pheight
int width, cwidth, height, cheight;
/* total width & height */
- cheight = (s->cr[9] & 0x1f) + 1;
+ cheight = (s->cr[VGA_CRTC_MAX_SCAN] & 0x1f) + 1;
cwidth = 8;
- if (!(s->sr[1] & 0x01))
+ if (!(s->sr[VGA_SEQ_CLOCK_MODE] & VGA_SR01_CHAR_CLK_8DOTS)) {
cwidth = 9;
- if (s->sr[1] & 0x08)
+ }
+ if (s->sr[VGA_SEQ_CLOCK_MODE] & 0x08) {
cwidth = 16; /* NOTE: no 18 pixel wide */
- width = (s->cr[0x01] + 1);
- if (s->cr[0x06] == 100) {
+ }
+ width = (s->cr[VGA_CRTC_H_DISP] + 1);
+ if (s->cr[VGA_CRTC_V_TOTAL] == 100) {
/* ugly hack for CGA 160x100x16 - explain me the logic */
height = 100;
} else {
- height = s->cr[0x12] |
- ((s->cr[0x07] & 0x02) << 7) |
- ((s->cr[0x07] & 0x40) << 3);
+ height = s->cr[VGA_CRTC_V_DISP_END] |
+ ((s->cr[VGA_CRTC_OVERFLOW] & 0x02) << 7) |
+ ((s->cr[VGA_CRTC_OVERFLOW] & 0x40) << 3);
height = (height + 1) / cheight;
}
@@ -1273,7 +1303,7 @@ static void vga_draw_text(VGACommonState *s, int full_update)
vga_draw_glyph9_func *vga_draw_glyph9;
/* compute font data address (in plane 2) */
- v = s->sr[3];
+ v = s->sr[VGA_SEQ_CHARACTER_MAP];
offset = (((v >> 4) & 1) | ((v << 1) & 6)) * 8192 * 4 + 2;
if (offset != s->font_offsets[0]) {
s->font_offsets[0] = offset;
@@ -1321,10 +1351,11 @@ static void vga_draw_text(VGACommonState *s, int full_update)
palette = s->last_palette;
x_incr = cw * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3);
- cursor_offset = ((s->cr[0x0e] << 8) | s->cr[0x0f]) - s->start_addr;
+ cursor_offset = ((s->cr[VGA_CRTC_CURSOR_HI] << 8) |
+ s->cr[VGA_CRTC_CURSOR_LO]) - s->start_addr;
if (cursor_offset != s->cursor_offset ||
- s->cr[0xa] != s->cursor_start ||
- s->cr[0xb] != s->cursor_end) {
+ s->cr[VGA_CRTC_CURSOR_START] != s->cursor_start ||
+ s->cr[VGA_CRTC_CURSOR_END] != s->cursor_end) {
/* if the cursor position changed, we update the old and new
chars */
if (s->cursor_offset < CH_ATTR_SIZE)
@@ -1332,8 +1363,8 @@ static void vga_draw_text(VGACommonState *s, int full_update)
if (cursor_offset < CH_ATTR_SIZE)
s->last_ch_attr[cursor_offset] = -1;
s->cursor_offset = cursor_offset;
- s->cursor_start = s->cr[0xa];
- s->cursor_end = s->cr[0xb];
+ s->cursor_start = s->cr[VGA_CRTC_CURSOR_START];
+ s->cursor_end = s->cr[VGA_CRTC_CURSOR_END];
}
cursor_ptr = s->vram_ptr + (s->start_addr + cursor_offset) * 4;
@@ -1378,17 +1409,19 @@ static void vga_draw_text(VGACommonState *s, int full_update)
font_ptr, cheight, fgcol, bgcol);
} else {
dup9 = 0;
- if (ch >= 0xb0 && ch <= 0xdf && (s->ar[0x10] & 0x04))
+ if (ch >= 0xb0 && ch <= 0xdf &&
+ (s->ar[VGA_ATC_MODE] & 0x04)) {
dup9 = 1;
+ }
vga_draw_glyph9(d1, linesize,
font_ptr, cheight, fgcol, bgcol, dup9);
}
if (src == cursor_ptr &&
- !(s->cr[0x0a] & 0x20)) {
+ !(s->cr[VGA_CRTC_CURSOR_START] & 0x20)) {
int line_start, line_last, h;
/* draw the cursor */
- line_start = s->cr[0x0a] & 0x1f;
- line_last = s->cr[0x0b] & 0x1f;
+ line_start = s->cr[VGA_CRTC_CURSOR_START] & 0x1f;
+ line_last = s->cr[VGA_CRTC_CURSOR_END] & 0x1f;
/* XXX: check that */
if (line_last > cheight - 1)
line_last = cheight - 1;
@@ -1544,10 +1577,10 @@ static void vga_get_resolution(VGACommonState *s, int *pwidth, int *pheight)
} else
#endif
{
- width = (s->cr[0x01] + 1) * 8;
- height = s->cr[0x12] |
- ((s->cr[0x07] & 0x02) << 7) |
- ((s->cr[0x07] & 0x40) << 3);
+ width = (s->cr[VGA_CRTC_H_DISP] + 1) * 8;
+ height = s->cr[VGA_CRTC_V_DISP_END] |
+ ((s->cr[VGA_CRTC_OVERFLOW] & 0x02) << 7) |
+ ((s->cr[VGA_CRTC_OVERFLOW] & 0x40) << 3);
height = (height + 1);
}
*pwidth = width;
@@ -1602,10 +1635,11 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
s->get_resolution(s, &width, &height);
disp_width = width;
- shift_control = (s->gr[0x05] >> 5) & 3;
- double_scan = (s->cr[0x09] >> 7);
+ shift_control = (s->gr[VGA_GFX_MODE] >> 5) & 3;
+ double_scan = (s->cr[VGA_CRTC_MAX_SCAN] >> 7);
if (shift_control != 1) {
- multi_scan = (((s->cr[0x09] & 0x1f) + 1) << double_scan) - 1;
+ multi_scan = (((s->cr[VGA_CRTC_MAX_SCAN] & 0x1f) + 1) << double_scan)
+ - 1;
} else {
/* in CGA modes, multi_scan is ignored */
/* XXX: is it correct ? */
@@ -1620,11 +1654,11 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
}
if (shift_control == 0) {
- if (s->sr[0x01] & 8) {
+ if (s->sr[VGA_SEQ_CLOCK_MODE] & 8) {
disp_width <<= 1;
}
} else if (shift_control == 1) {
- if (s->sr[0x01] & 8) {
+ if (s->sr[VGA_SEQ_CLOCK_MODE] & 8) {
disp_width <<= 1;
}
}
@@ -1668,7 +1702,7 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
if (shift_control == 0) {
full_update |= update_palette16(s);
- if (s->sr[0x01] & 8) {
+ if (s->sr[VGA_SEQ_CLOCK_MODE] & 8) {
v = VGA_DRAW_LINE4D2;
} else {
v = VGA_DRAW_LINE4;
@@ -1676,7 +1710,7 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
bits = 4;
} else if (shift_control == 1) {
full_update |= update_palette16(s);
- if (s->sr[0x01] & 8) {
+ if (s->sr[VGA_SEQ_CLOCK_MODE] & 8) {
v = VGA_DRAW_LINE2D2;
} else {
v = VGA_DRAW_LINE2;
@@ -1721,7 +1755,8 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
line_offset = s->line_offset;
#if 0
printf("w=%d h=%d v=%d line_offset=%d cr[0x09]=0x%02x cr[0x17]=0x%02x linecmp=%d sr[0x01]=0x%02x\n",
- width, height, v, line_offset, s->cr[9], s->cr[0x17], s->line_compare, s->sr[0x01]);
+ width, height, v, line_offset, s->cr[9], s->cr[VGA_CRTC_MODE],
+ s->line_compare, s->sr[VGA_SEQ_CLOCK_MODE]);
#endif
addr1 = (s->start_addr * 4);
bwidth = (width * bits + 7) / 8;
@@ -1733,26 +1768,19 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
y1 = 0;
for(y = 0; y < height; y++) {
addr = addr1;
- if (!(s->cr[0x17] & 1)) {
+ if (!(s->cr[VGA_CRTC_MODE] & 1)) {
int shift;
/* CGA compatibility handling */
- shift = 14 + ((s->cr[0x17] >> 6) & 1);
+ shift = 14 + ((s->cr[VGA_CRTC_MODE] >> 6) & 1);
addr = (addr & ~(1 << shift)) | ((y1 & 1) << shift);
}
- if (!(s->cr[0x17] & 2)) {
+ if (!(s->cr[VGA_CRTC_MODE] & 2)) {
addr = (addr & ~0x8000) | ((y1 & 2) << 14);
}
- page0 = addr & TARGET_PAGE_MASK;
- page1 = (addr + bwidth - 1) & TARGET_PAGE_MASK;
- update = full_update |
- memory_region_get_dirty(&s->vram, page0, DIRTY_MEMORY_VGA) |
- memory_region_get_dirty(&s->vram, page1, DIRTY_MEMORY_VGA);
- if ((page1 - page0) > TARGET_PAGE_SIZE) {
- /* if wide line, can use another page */
- update |= memory_region_get_dirty(&s->vram,
- page0 + TARGET_PAGE_SIZE,
- DIRTY_MEMORY_VGA);
- }
+ page0 = addr;
+ page1 = addr + bwidth - 1;
+ update = memory_region_get_dirty(&s->vram, page0, page1,
+ DIRTY_MEMORY_VGA);
/* explicit invalidation for the hardware cursor */
update |= (s->invalidated_y_table[y >> 5] >> (y & 0x1f)) & 1;
if (update) {
@@ -1776,7 +1804,7 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
}
}
if (!multi_run) {
- mask = (s->cr[0x17] & 3) ^ 3;
+ mask = (s->cr[VGA_CRTC_MODE] & 3) ^ 3;
if ((y1 & mask) == mask)
addr1 += line_offset;
y1++;
@@ -1798,7 +1826,7 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
if (page_max >= page_min) {
memory_region_reset_dirty(&s->vram,
page_min,
- page_max + TARGET_PAGE_SIZE - page_min,
+ page_max - page_min,
DIRTY_MEMORY_VGA);
}
memset(s->invalidated_y_table, 0, ((height + 31) >> 5) * 4);
@@ -1848,7 +1876,7 @@ static void vga_update_display(void *opaque)
if (!(s->ar_index & 0x20)) {
graphic_mode = GMODE_BLANK;
} else {
- graphic_mode = s->gr[6] & 1;
+ graphic_mode = s->gr[VGA_GFX_MISC] & VGA_GR06_GRAPHICS_MODE;
}
if (graphic_mode != s->graphic_mode) {
s->graphic_mode = graphic_mode;
@@ -1966,7 +1994,7 @@ static void vga_update_text(void *opaque, console_ch_t *chardata)
if (!(s->ar_index & 0x20)) {
graphic_mode = GMODE_BLANK;
} else {
- graphic_mode = s->gr[6] & 1;
+ graphic_mode = s->gr[VGA_GFX_MISC] & VGA_GR06_GRAPHICS_MODE;
}
if (graphic_mode != s->graphic_mode) {
s->graphic_mode = graphic_mode;
@@ -1983,20 +2011,22 @@ static void vga_update_text(void *opaque, console_ch_t *chardata)
full_update |= update_basic_params(s);
/* total width & height */
- cheight = (s->cr[9] & 0x1f) + 1;
+ cheight = (s->cr[VGA_CRTC_MAX_SCAN] & 0x1f) + 1;
cw = 8;
- if (!(s->sr[1] & 0x01))
+ if (!(s->sr[VGA_SEQ_CLOCK_MODE] & VGA_SR01_CHAR_CLK_8DOTS)) {
cw = 9;
- if (s->sr[1] & 0x08)
+ }
+ if (s->sr[VGA_SEQ_CLOCK_MODE] & 0x08) {
cw = 16; /* NOTE: no 18 pixel wide */
- width = (s->cr[0x01] + 1);
- if (s->cr[0x06] == 100) {
+ }
+ width = (s->cr[VGA_CRTC_H_DISP] + 1);
+ if (s->cr[VGA_CRTC_V_TOTAL] == 100) {
/* ugly hack for CGA 160x100x16 - explain me the logic */
height = 100;
} else {
- height = s->cr[0x12] |
- ((s->cr[0x07] & 0x02) << 7) |
- ((s->cr[0x07] & 0x40) << 3);
+ height = s->cr[VGA_CRTC_V_DISP_END] |
+ ((s->cr[VGA_CRTC_OVERFLOW] & 0x02) << 7) |
+ ((s->cr[VGA_CRTC_OVERFLOW] & 0x40) << 3);
height = (height + 1) / cheight;
}
@@ -2025,11 +2055,12 @@ static void vga_update_text(void *opaque, console_ch_t *chardata)
}
/* Update "hardware" cursor */
- cursor_offset = ((s->cr[0x0e] << 8) | s->cr[0x0f]) - s->start_addr;
+ cursor_offset = ((s->cr[VGA_CRTC_CURSOR_HI] << 8) |
+ s->cr[VGA_CRTC_CURSOR_LO]) - s->start_addr;
if (cursor_offset != s->cursor_offset ||
- s->cr[0xa] != s->cursor_start ||
- s->cr[0xb] != s->cursor_end || full_update) {
- cursor_visible = !(s->cr[0xa] & 0x20);
+ s->cr[VGA_CRTC_CURSOR_START] != s->cursor_start ||
+ s->cr[VGA_CRTC_CURSOR_END] != s->cursor_end || full_update) {
+ cursor_visible = !(s->cr[VGA_CRTC_CURSOR_START] & 0x20);
if (cursor_visible && cursor_offset < size && cursor_offset >= 0)
dpy_cursor(s->ds,
TEXTMODE_X(cursor_offset),
@@ -2037,8 +2068,8 @@ static void vga_update_text(void *opaque, console_ch_t *chardata)
else
dpy_cursor(s->ds, -1, -1);
s->cursor_offset = cursor_offset;
- s->cursor_start = s->cr[0xa];
- s->cursor_end = s->cr[0xb];
+ s->cursor_start = s->cr[VGA_CRTC_CURSOR_START];
+ s->cursor_end = s->cr[VGA_CRTC_CURSOR_END];
}
src = (uint32_t *) s->vram_ptr + s->start_addr;
diff --git a/hw/vga.h b/hw/vga.h
new file mode 100644
index 0000000000..d917046da6
--- /dev/null
+++ b/hw/vga.h
@@ -0,0 +1,159 @@
+/*
+ * linux/include/video/vga.h -- standard VGA chipset interaction
+ *
+ * Copyright 1999 Jeff Garzik <jgarzik@pobox.com>
+ *
+ * Copyright history from vga16fb.c:
+ * Copyright 1999 Ben Pfaff and Petr Vandrovec
+ * Based on VGA info at http://www.osdever.net/FreeVGA/home.htm
+ * Based on VESA framebuffer (c) 1998 Gerd Knorr
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License. See the file COPYING in the main directory of this
+ * archive for more details.
+ *
+ */
+
+#ifndef __linux_video_vga_h__
+#define __linux_video_vga_h__
+
+/* Some of the code below is taken from SVGAlib. The original,
+ unmodified copyright notice for that code is below. */
+/* VGAlib version 1.2 - (c) 1993 Tommy Frandsen */
+/* */
+/* This library is free software; you can redistribute it and/or */
+/* modify it without any restrictions. This library is distributed */
+/* in the hope that it will be useful, but without any warranty. */
+
+/* Multi-chipset support Copyright 1993 Harm Hanemaayer */
+/* partially copyrighted (C) 1993 by Hartmut Schirmer */
+
+/* VGA data register ports */
+#define VGA_CRT_DC 0x3D5 /* CRT Controller Data Register - color emulation */
+#define VGA_CRT_DM 0x3B5 /* CRT Controller Data Register - mono emulation */
+#define VGA_ATT_R 0x3C1 /* Attribute Controller Data Read Register */
+#define VGA_ATT_W 0x3C0 /* Attribute Controller Data Write Register */
+#define VGA_GFX_D 0x3CF /* Graphics Controller Data Register */
+#define VGA_SEQ_D 0x3C5 /* Sequencer Data Register */
+#define VGA_MIS_R 0x3CC /* Misc Output Read Register */
+#define VGA_MIS_W 0x3C2 /* Misc Output Write Register */
+#define VGA_FTC_R 0x3CA /* Feature Control Read Register */
+#define VGA_IS1_RC 0x3DA /* Input Status Register 1 - color emulation */
+#define VGA_IS1_RM 0x3BA /* Input Status Register 1 - mono emulation */
+#define VGA_PEL_D 0x3C9 /* PEL Data Register */
+#define VGA_PEL_MSK 0x3C6 /* PEL mask register */
+
+/* EGA-specific registers */
+#define EGA_GFX_E0 0x3CC /* Graphics enable processor 0 */
+#define EGA_GFX_E1 0x3CA /* Graphics enable processor 1 */
+
+/* VGA index register ports */
+#define VGA_CRT_IC 0x3D4 /* CRT Controller Index - color emulation */
+#define VGA_CRT_IM 0x3B4 /* CRT Controller Index - mono emulation */
+#define VGA_ATT_IW 0x3C0 /* Attribute Controller Index & Data Write Register */
+#define VGA_GFX_I 0x3CE /* Graphics Controller Index */
+#define VGA_SEQ_I 0x3C4 /* Sequencer Index */
+#define VGA_PEL_IW 0x3C8 /* PEL Write Index */
+#define VGA_PEL_IR 0x3C7 /* PEL Read Index */
+
+/* standard VGA indexes max counts */
+#define VGA_CRT_C 0x19 /* Number of CRT Controller Registers */
+#define VGA_ATT_C 0x15 /* Number of Attribute Controller Registers */
+#define VGA_GFX_C 0x09 /* Number of Graphics Controller Registers */
+#define VGA_SEQ_C 0x05 /* Number of Sequencer Registers */
+#define VGA_MIS_C 0x01 /* Number of Misc Output Register */
+
+/* VGA misc register bit masks */
+#define VGA_MIS_COLOR 0x01
+#define VGA_MIS_ENB_MEM_ACCESS 0x02
+#define VGA_MIS_DCLK_28322_720 0x04
+#define VGA_MIS_ENB_PLL_LOAD (0x04 | 0x08)
+#define VGA_MIS_SEL_HIGH_PAGE 0x20
+
+/* VGA CRT controller register indices */
+#define VGA_CRTC_H_TOTAL 0
+#define VGA_CRTC_H_DISP 1
+#define VGA_CRTC_H_BLANK_START 2
+#define VGA_CRTC_H_BLANK_END 3
+#define VGA_CRTC_H_SYNC_START 4
+#define VGA_CRTC_H_SYNC_END 5
+#define VGA_CRTC_V_TOTAL 6
+#define VGA_CRTC_OVERFLOW 7
+#define VGA_CRTC_PRESET_ROW 8
+#define VGA_CRTC_MAX_SCAN 9
+#define VGA_CRTC_CURSOR_START 0x0A
+#define VGA_CRTC_CURSOR_END 0x0B
+#define VGA_CRTC_START_HI 0x0C
+#define VGA_CRTC_START_LO 0x0D
+#define VGA_CRTC_CURSOR_HI 0x0E
+#define VGA_CRTC_CURSOR_LO 0x0F
+#define VGA_CRTC_V_SYNC_START 0x10
+#define VGA_CRTC_V_SYNC_END 0x11
+#define VGA_CRTC_V_DISP_END 0x12
+#define VGA_CRTC_OFFSET 0x13
+#define VGA_CRTC_UNDERLINE 0x14
+#define VGA_CRTC_V_BLANK_START 0x15
+#define VGA_CRTC_V_BLANK_END 0x16
+#define VGA_CRTC_MODE 0x17
+#define VGA_CRTC_LINE_COMPARE 0x18
+#define VGA_CRTC_REGS VGA_CRT_C
+
+/* VGA CRT controller bit masks */
+#define VGA_CR11_LOCK_CR0_CR7 0x80 /* lock writes to CR0 - CR7 */
+#define VGA_CR17_H_V_SIGNALS_ENABLED 0x80
+
+/* VGA attribute controller register indices */
+#define VGA_ATC_PALETTE0 0x00
+#define VGA_ATC_PALETTE1 0x01
+#define VGA_ATC_PALETTE2 0x02
+#define VGA_ATC_PALETTE3 0x03
+#define VGA_ATC_PALETTE4 0x04
+#define VGA_ATC_PALETTE5 0x05
+#define VGA_ATC_PALETTE6 0x06
+#define VGA_ATC_PALETTE7 0x07
+#define VGA_ATC_PALETTE8 0x08
+#define VGA_ATC_PALETTE9 0x09
+#define VGA_ATC_PALETTEA 0x0A
+#define VGA_ATC_PALETTEB 0x0B
+#define VGA_ATC_PALETTEC 0x0C
+#define VGA_ATC_PALETTED 0x0D
+#define VGA_ATC_PALETTEE 0x0E
+#define VGA_ATC_PALETTEF 0x0F
+#define VGA_ATC_MODE 0x10
+#define VGA_ATC_OVERSCAN 0x11
+#define VGA_ATC_PLANE_ENABLE 0x12
+#define VGA_ATC_PEL 0x13
+#define VGA_ATC_COLOR_PAGE 0x14
+
+#define VGA_AR_ENABLE_DISPLAY 0x20
+
+/* VGA sequencer register indices */
+#define VGA_SEQ_RESET 0x00
+#define VGA_SEQ_CLOCK_MODE 0x01
+#define VGA_SEQ_PLANE_WRITE 0x02
+#define VGA_SEQ_CHARACTER_MAP 0x03
+#define VGA_SEQ_MEMORY_MODE 0x04
+
+/* VGA sequencer register bit masks */
+#define VGA_SR01_CHAR_CLK_8DOTS 0x01 /* bit 0: character clocks 8 dots wide are generated */
+#define VGA_SR01_SCREEN_OFF 0x20 /* bit 5: Screen is off */
+#define VGA_SR02_ALL_PLANES 0x0F /* bits 3-0: enable access to all planes */
+#define VGA_SR04_EXT_MEM 0x02 /* bit 1: allows complete mem access to 256K */
+#define VGA_SR04_SEQ_MODE 0x04 /* bit 2: directs system to use a sequential addressing mode */
+#define VGA_SR04_CHN_4M 0x08 /* bit 3: selects modulo 4 addressing for CPU access to display memory */
+
+/* VGA graphics controller register indices */
+#define VGA_GFX_SR_VALUE 0x00
+#define VGA_GFX_SR_ENABLE 0x01
+#define VGA_GFX_COMPARE_VALUE 0x02
+#define VGA_GFX_DATA_ROTATE 0x03
+#define VGA_GFX_PLANE_READ 0x04
+#define VGA_GFX_MODE 0x05
+#define VGA_GFX_MISC 0x06
+#define VGA_GFX_COMPARE_MASK 0x07
+#define VGA_GFX_BIT_MASK 0x08
+
+/* VGA graphics controller bit masks */
+#define VGA_GR06_GRAPHICS_MODE 0x01
+
+#endif /* __linux_video_vga_h__ */
diff --git a/hw/vga_int.h b/hw/vga_int.h
index c1e700fa0b..7685b2b167 100644
--- a/hw/vga_int.h
+++ b/hw/vga_int.h
@@ -25,9 +25,6 @@
#include <hw/hw.h>
#include "memory.h"
-#define MSR_COLOR_EMULATION 0x01
-#define MSR_PAGE_SELECT 0x20
-
#define ST01_V_RETRACE 0x08
#define ST01_DISP_ENABLE 0x01
@@ -205,19 +202,6 @@ void vga_mem_writeb(VGACommonState *s, target_phys_addr_t addr, uint32_t val);
void vga_invalidate_scanlines(VGACommonState *s, int y1, int y2);
int ppm_save(const char *filename, struct DisplaySurface *ds);
-void vga_draw_cursor_line_8(uint8_t *d1, const uint8_t *src1,
- int poffset, int w,
- unsigned int color0, unsigned int color1,
- unsigned int color_xor);
-void vga_draw_cursor_line_16(uint8_t *d1, const uint8_t *src1,
- int poffset, int w,
- unsigned int color0, unsigned int color1,
- unsigned int color_xor);
-void vga_draw_cursor_line_32(uint8_t *d1, const uint8_t *src1,
- int poffset, int w,
- unsigned int color0, unsigned int color1,
- unsigned int color_xor);
-
int vga_ioport_invalid(VGACommonState *s, uint32_t addr);
void vga_init_vbe(VGACommonState *s, MemoryRegion *address_space);
diff --git a/hw/vga_template.h b/hw/vga_template.h
index 681425f9a2..f6f6a01d84 100644
--- a/hw/vga_template.h
+++ b/hw/vga_template.h
@@ -161,7 +161,7 @@ static void glue(vga_draw_line2_, DEPTH)(VGACommonState *s1, uint8_t *d,
int x;
palette = s1->last_palette;
- plane_mask = mask16[s1->ar[0x12] & 0xf];
+ plane_mask = mask16[s1->ar[VGA_ATC_PLANE_ENABLE] & 0xf];
width >>= 3;
for(x = 0; x < width; x++) {
data = ((uint32_t *)s)[0];
@@ -203,7 +203,7 @@ static void glue(vga_draw_line2d2_, DEPTH)(VGACommonState *s1, uint8_t *d,
int x;
palette = s1->last_palette;
- plane_mask = mask16[s1->ar[0x12] & 0xf];
+ plane_mask = mask16[s1->ar[VGA_ATC_PLANE_ENABLE] & 0xf];
width >>= 3;
for(x = 0; x < width; x++) {
data = ((uint32_t *)s)[0];
@@ -236,7 +236,7 @@ static void glue(vga_draw_line4_, DEPTH)(VGACommonState *s1, uint8_t *d,
int x;
palette = s1->last_palette;
- plane_mask = mask16[s1->ar[0x12] & 0xf];
+ plane_mask = mask16[s1->ar[VGA_ATC_PLANE_ENABLE] & 0xf];
width >>= 3;
for(x = 0; x < width; x++) {
data = ((uint32_t *)s)[0];
@@ -268,7 +268,7 @@ static void glue(vga_draw_line4d2_, DEPTH)(VGACommonState *s1, uint8_t *d,
int x;
palette = s1->last_palette;
- plane_mask = mask16[s1->ar[0x12] & 0xf];
+ plane_mask = mask16[s1->ar[VGA_ATC_PLANE_ENABLE] & 0xf];
width >>= 3;
for(x = 0; x < width; x++) {
data = ((uint32_t *)s)[0];
@@ -340,72 +340,6 @@ static void glue(vga_draw_line8_, DEPTH)(VGACommonState *s1, uint8_t *d,
}
}
-void glue(vga_draw_cursor_line_, DEPTH)(uint8_t *d1,
- const uint8_t *src1,
- int poffset, int w,
- unsigned int color0,
- unsigned int color1,
- unsigned int color_xor)
-{
- const uint8_t *plane0, *plane1;
- int x, b0, b1;
- uint8_t *d;
-
- d = d1;
- plane0 = src1;
- plane1 = src1 + poffset;
- for(x = 0; x < w; x++) {
- b0 = (plane0[x >> 3] >> (7 - (x & 7))) & 1;
- b1 = (plane1[x >> 3] >> (7 - (x & 7))) & 1;
-#if DEPTH == 8
- switch(b0 | (b1 << 1)) {
- case 0:
- break;
- case 1:
- d[0] ^= color_xor;
- break;
- case 2:
- d[0] = color0;
- break;
- case 3:
- d[0] = color1;
- break;
- }
-#elif DEPTH == 16
- switch(b0 | (b1 << 1)) {
- case 0:
- break;
- case 1:
- ((uint16_t *)d)[0] ^= color_xor;
- break;
- case 2:
- ((uint16_t *)d)[0] = color0;
- break;
- case 3:
- ((uint16_t *)d)[0] = color1;
- break;
- }
-#elif DEPTH == 32
- switch(b0 | (b1 << 1)) {
- case 0:
- break;
- case 1:
- ((uint32_t *)d)[0] ^= color_xor;
- break;
- case 2:
- ((uint32_t *)d)[0] = color0;
- break;
- case 3:
- ((uint32_t *)d)[0] = color1;
- break;
- }
-#else
-#error unsupported depth
-#endif
- d += BPP;
- }
-}
-
#endif /* DEPTH != 15 */
diff --git a/kvm-all.c b/kvm-all.c
index 7d4e544c52..0b87658f6a 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -1306,7 +1306,11 @@ int kvm_has_many_ioeventfds(void)
int kvm_has_gsi_routing(void)
{
+#ifdef KVM_CAP_IRQ_ROUTING
return kvm_check_extension(kvm_state, KVM_CAP_IRQ_ROUTING);
+#else
+ return false;
+#endif
}
int kvm_allows_irq0_override(void)
diff --git a/linux-headers/asm-powerpc/kvm.h b/linux-headers/asm-powerpc/kvm.h
index fb3fddcd87..b921c3f489 100644
--- a/linux-headers/asm-powerpc/kvm.h
+++ b/linux-headers/asm-powerpc/kvm.h
@@ -265,12 +265,9 @@ struct kvm_debug_exit_arch {
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
+/* definition of registers in kvm_run */
+struct kvm_sync_regs {
+};
#define KVM_INTERRUPT_SET -1U
#define KVM_INTERRUPT_UNSET -2U
@@ -327,6 +324,6 @@ struct kvm_book3e_206_tlb_params {
__u32 reserved[8];
};
-#define KVM_ONE_REG_PPC_HIOR KVM_ONE_REG_PPC | 0x100
+#define KVM_REG_PPC_HIOR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x1)
#endif /* __LINUX_KVM_POWERPC_H */
diff --git a/linux-headers/asm-powerpc/kvm_para.h b/linux-headers/asm-powerpc/kvm_para.h
index ad58c90bf5..c047a84000 100644
--- a/linux-headers/asm-powerpc/kvm_para.h
+++ b/linux-headers/asm-powerpc/kvm_para.h
@@ -22,6 +22,16 @@
#include <linux/types.h>
+/*
+ * Additions to this struct must only occur at the end, and should be
+ * accompanied by a KVM_MAGIC_FEAT flag to advertise that they are present
+ * (albeit not necessarily relevant to the current target hardware platform).
+ *
+ * Struct fields are always 32 or 64 bit aligned, depending on them being 32
+ * or 64 bit wide respectively.
+ *
+ * See Documentation/virtual/kvm/ppc-pv.txt
+ */
struct kvm_vcpu_arch_shared {
__u64 scratch1;
__u64 scratch2;
@@ -33,11 +43,35 @@ struct kvm_vcpu_arch_shared {
__u64 sprg3;
__u64 srr0;
__u64 srr1;
- __u64 dar;
+ __u64 dar; /* dear on BookE */
__u64 msr;
__u32 dsisr;
__u32 int_pending; /* Tells the guest if we have an interrupt */
__u32 sr[16];
+ __u32 mas0;
+ __u32 mas1;
+ __u64 mas7_3;
+ __u64 mas2;
+ __u32 mas4;
+ __u32 mas6;
+ __u32 esr;
+ __u32 pir;
+
+ /*
+ * SPRG4-7 are user-readable, so we can only keep these consistent
+ * between the shared area and the real registers when there's an
+ * intervening exit to KVM. This also applies to SPRG3 on some
+ * chips.
+ *
+ * This suffices for access by guest userspace, since in PR-mode
+ * KVM, an exit must occur when changing the guest's MSR[PR].
+ * If the guest kernel writes to SPRG3-7 via the shared area, it
+ * must also use the shared area for reading while in kernel space.
+ */
+ __u64 sprg4;
+ __u64 sprg5;
+ __u64 sprg6;
+ __u64 sprg7;
};
#define KVM_SC_MAGIC_R0 0x4b564d21 /* "KVM!" */
@@ -47,7 +81,10 @@ struct kvm_vcpu_arch_shared {
#define KVM_FEATURE_MAGIC_PAGE 1
-#define KVM_MAGIC_FEAT_SR (1 << 0)
+#define KVM_MAGIC_FEAT_SR (1 << 0)
+
+/* MASn, ESR, PIR, and high SPRGs */
+#define KVM_MAGIC_FEAT_MAS0_TO_SPRG7 (1 << 1)
#endif /* __POWERPC_KVM_PARA_H__ */
diff --git a/linux-headers/asm-s390/kvm.h b/linux-headers/asm-s390/kvm.h
index 82b32a100c..9acbde4af2 100644
--- a/linux-headers/asm-s390/kvm.h
+++ b/linux-headers/asm-s390/kvm.h
@@ -41,4 +41,13 @@ struct kvm_debug_exit_arch {
struct kvm_guest_debug_arch {
};
+#define KVM_SYNC_PREFIX (1UL << 0)
+#define KVM_SYNC_GPRS (1UL << 1)
+#define KVM_SYNC_ACRS (1UL << 2)
+/* definition of registers in kvm_run */
+struct kvm_sync_regs {
+ __u64 prefix; /* prefix register */
+ __u64 gprs[16]; /* general purpose registers */
+ __u32 acrs[16]; /* access registers */
+};
#endif
diff --git a/linux-headers/asm-x86/hyperv.h b/linux-headers/asm-x86/hyperv.h
index 5df477ac3a..b80420bcd0 100644
--- a/linux-headers/asm-x86/hyperv.h
+++ b/linux-headers/asm-x86/hyperv.h
@@ -189,5 +189,6 @@
#define HV_STATUS_INVALID_HYPERCALL_CODE 2
#define HV_STATUS_INVALID_HYPERCALL_INPUT 3
#define HV_STATUS_INVALID_ALIGNMENT 4
+#define HV_STATUS_INSUFFICIENT_BUFFERS 19
#endif
diff --git a/linux-headers/asm-x86/kvm.h b/linux-headers/asm-x86/kvm.h
index 4d8dcbdfc1..e7d1c194d2 100644
--- a/linux-headers/asm-x86/kvm.h
+++ b/linux-headers/asm-x86/kvm.h
@@ -321,4 +321,8 @@ struct kvm_xcrs {
__u64 padding[16];
};
+/* definition of registers in kvm_run */
+struct kvm_sync_regs {
+};
+
#endif /* _ASM_X86_KVM_H */
diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h
index a8761d3be6..f6b53432db 100644
--- a/linux-headers/linux/kvm.h
+++ b/linux-headers/linux/kvm.h
@@ -162,6 +162,7 @@ struct kvm_pit_config {
#define KVM_EXIT_INTERNAL_ERROR 17
#define KVM_EXIT_OSI 18
#define KVM_EXIT_PAPR_HCALL 19
+#define KVM_EXIT_S390_UCONTROL 20
/* For KVM_EXIT_INTERNAL_ERROR */
#define KVM_INTERNAL_ERROR_EMULATION 1
@@ -249,6 +250,11 @@ struct kvm_run {
#define KVM_S390_RESET_CPU_INIT 8
#define KVM_S390_RESET_IPL 16
__u64 s390_reset_flags;
+ /* KVM_EXIT_S390_UCONTROL */
+ struct {
+ __u64 trans_exc_code;
+ __u32 pgm_code;
+ } s390_ucontrol;
/* KVM_EXIT_DCR */
struct {
__u32 dcrn;
@@ -273,6 +279,20 @@ struct kvm_run {
/* Fix the size of the union. */
char padding[256];
};
+
+ /*
+ * shared registers between kvm and userspace.
+ * kvm_valid_regs specifies the register classes set by the host
+ * kvm_dirty_regs specified the register classes dirtied by userspace
+ * struct kvm_sync_regs is architecture specific, as well as the
+ * bits for kvm_valid_regs and kvm_dirty_regs
+ */
+ __u64 kvm_valid_regs;
+ __u64 kvm_dirty_regs;
+ union {
+ struct kvm_sync_regs regs;
+ char padding[1024];
+ } s;
};
/* for KVM_REGISTER_COALESCED_MMIO / KVM_UNREGISTER_COALESCED_MMIO */
@@ -371,6 +391,7 @@ struct kvm_s390_psw {
#define KVM_S390_INT_VIRTIO 0xffff2603u
#define KVM_S390_INT_SERVICE 0xffff2401u
#define KVM_S390_INT_EMERGENCY 0xffff1201u
+#define KVM_S390_INT_EXTERNAL_CALL 0xffff1202u
struct kvm_s390_interrupt {
__u32 type;
@@ -430,6 +451,11 @@ struct kvm_ppc_pvinfo {
#define KVMIO 0xAE
+/* machine type bits, to be used as argument to KVM_CREATE_VM */
+#define KVM_VM_S390_UCONTROL 1
+
+#define KVM_S390_SIE_PAGE_OFFSET 1
+
/*
* ioctls for /dev/kvm fds:
*/
@@ -558,6 +584,10 @@ struct kvm_ppc_pvinfo {
#define KVM_CAP_PPC_PAPR 68
#define KVM_CAP_SW_TLB 69
#define KVM_CAP_ONE_REG 70
+#define KVM_CAP_S390_GMAP 71
+#define KVM_CAP_TSC_DEADLINE_TIMER 72
+#define KVM_CAP_S390_UCONTROL 73
+#define KVM_CAP_SYNC_REGS 74
#ifdef KVM_CAP_IRQ_ROUTING
@@ -654,30 +684,33 @@ struct kvm_dirty_tlb {
/* Available with KVM_CAP_ONE_REG */
-#define KVM_ONE_REG_GENERIC 0x0000000000000000ULL
+#define KVM_REG_ARCH_MASK 0xff00000000000000ULL
+#define KVM_REG_GENERIC 0x0000000000000000ULL
/*
* Architecture specific registers are to be defined in arch headers and
* ORed with the arch identifier.
*/
-#define KVM_ONE_REG_PPC 0x1000000000000000ULL
-#define KVM_ONE_REG_X86 0x2000000000000000ULL
-#define KVM_ONE_REG_IA64 0x3000000000000000ULL
-#define KVM_ONE_REG_ARM 0x4000000000000000ULL
-#define KVM_ONE_REG_S390 0x5000000000000000ULL
+#define KVM_REG_PPC 0x1000000000000000ULL
+#define KVM_REG_X86 0x2000000000000000ULL
+#define KVM_REG_IA64 0x3000000000000000ULL
+#define KVM_REG_ARM 0x4000000000000000ULL
+#define KVM_REG_S390 0x5000000000000000ULL
+
+#define KVM_REG_SIZE_SHIFT 52
+#define KVM_REG_SIZE_MASK 0x00f0000000000000ULL
+#define KVM_REG_SIZE_U8 0x0000000000000000ULL
+#define KVM_REG_SIZE_U16 0x0010000000000000ULL
+#define KVM_REG_SIZE_U32 0x0020000000000000ULL
+#define KVM_REG_SIZE_U64 0x0030000000000000ULL
+#define KVM_REG_SIZE_U128 0x0040000000000000ULL
+#define KVM_REG_SIZE_U256 0x0050000000000000ULL
+#define KVM_REG_SIZE_U512 0x0060000000000000ULL
+#define KVM_REG_SIZE_U1024 0x0070000000000000ULL
struct kvm_one_reg {
__u64 id;
- union {
- __u8 reg8;
- __u16 reg16;
- __u32 reg32;
- __u64 reg64;
- __u8 reg128[16];
- __u8 reg256[32];
- __u8 reg512[64];
- __u8 reg1024[128];
- } u;
+ __u64 addr;
};
/*
@@ -698,6 +731,17 @@ struct kvm_one_reg {
struct kvm_userspace_memory_region)
#define KVM_SET_TSS_ADDR _IO(KVMIO, 0x47)
#define KVM_SET_IDENTITY_MAP_ADDR _IOW(KVMIO, 0x48, __u64)
+
+/* enable ucontrol for s390 */
+struct kvm_s390_ucas_mapping {
+ __u64 user_addr;
+ __u64 vcpu_addr;
+ __u64 length;
+};
+#define KVM_S390_UCAS_MAP _IOW(KVMIO, 0x50, struct kvm_s390_ucas_mapping)
+#define KVM_S390_UCAS_UNMAP _IOW(KVMIO, 0x51, struct kvm_s390_ucas_mapping)
+#define KVM_S390_VCPU_FAULT _IOW(KVMIO, 0x52, unsigned long)
+
/* Device model IOC */
#define KVM_CREATE_IRQCHIP _IO(KVMIO, 0x60)
#define KVM_IRQ_LINE _IOW(KVMIO, 0x61, struct kvm_irq_level)
@@ -809,7 +853,7 @@ struct kvm_one_reg {
/* Available with KVM_CAP_SW_TLB */
#define KVM_DIRTY_TLB _IOW(KVMIO, 0xaa, struct kvm_dirty_tlb)
/* Available with KVM_CAP_ONE_REG */
-#define KVM_GET_ONE_REG _IOWR(KVMIO, 0xab, struct kvm_one_reg)
+#define KVM_GET_ONE_REG _IOW(KVMIO, 0xab, struct kvm_one_reg)
#define KVM_SET_ONE_REG _IOW(KVMIO, 0xac, struct kvm_one_reg)
#define KVM_DEV_ASSIGN_ENABLE_IOMMU (1 << 0)
diff --git a/linux-headers/linux/kvm_para.h b/linux-headers/linux/kvm_para.h
index b315e27a9c..7bdcf93c1d 100644
--- a/linux-headers/linux/kvm_para.h
+++ b/linux-headers/linux/kvm_para.h
@@ -26,4 +26,3 @@
#include <asm/kvm_para.h>
#endif /* __LINUX_KVM_PARA_H */
-
diff --git a/linux-headers/linux/virtio_ring.h b/linux-headers/linux/virtio_ring.h
index 78289eedf2..1b333e2536 100644
--- a/linux-headers/linux/virtio_ring.h
+++ b/linux-headers/linux/virtio_ring.h
@@ -135,13 +135,13 @@ static __inline__ void vring_init(struct vring *vr, unsigned int num, void *p,
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));
+ vr->used = (void *)(((unsigned long)&vr->avail->ring[num] + sizeof(__u16)
+ + 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)
+ return ((sizeof(struct vring_desc) * num + sizeof(__u16) * (3 + num)
+ align - 1) & ~(align - 1))
+ sizeof(__u16) * 3 + sizeof(struct vring_used_elem) * num;
}
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 845be8be3b..2fd4a93f8a 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -1245,6 +1245,7 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
struct image_info *interp_info)
{
abi_ulong sp;
+ abi_ulong sp_auxv;
int size;
int i;
abi_ulong u_rand_bytes;
@@ -1316,6 +1317,7 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
sp -= n; put_user_ual(id, sp); \
} while(0)
+ sp_auxv = sp;
NEW_AUX_ENT (AT_NULL, 0);
/* There must be exactly DLINFO_ITEMS entries here. */
@@ -1346,6 +1348,7 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
#undef NEW_AUX_ENT
info->saved_auxv = sp;
+ info->auxv_len = sp_auxv - sp;
sp = loader_build_argptr(envc, argc, sp, p, 0);
return sp;
@@ -2326,9 +2329,8 @@ static void fill_auxv_note(struct memelfnote *note, const TaskState *ts)
{
elf_addr_t auxv = (elf_addr_t)ts->info->saved_auxv;
elf_addr_t orig_auxv = auxv;
- abi_ulong val;
void *ptr;
- int i, len;
+ int len = ts->info->auxv_len;
/*
* Auxiliary vector is stored in target process stack. It contains
@@ -2336,15 +2338,6 @@ static void fill_auxv_note(struct memelfnote *note, const TaskState *ts)
* strictly necessary but we do it here for sake of completeness.
*/
- /* find out length of the vector, AT_NULL is terminator */
- i = len = 0;
- do {
- get_user_ual(val, auxv);
- i += 2;
- auxv += 2 * sizeof (elf_addr_t);
- } while (val != AT_NULL);
- len = i * sizeof (elf_addr_t);
-
/* read in whole auxv vector and copy it to memelfnote */
ptr = lock_user(VERIFY_READ, orig_auxv, len, 0);
if (ptr != NULL) {
diff --git a/linux-user/main.c b/linux-user/main.c
index 64d2208a08..14bf5f0bc7 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -2945,6 +2945,11 @@ static void handle_arg_log(const char *arg)
cpu_set_log(mask);
}
+static void handle_arg_log_filename(const char *arg)
+{
+ cpu_set_log_filename(arg);
+}
+
static void handle_arg_set_env(const char *arg)
{
char *r, *p, *token;
@@ -3125,6 +3130,8 @@ struct qemu_argument arg_table[] = {
#endif
{"d", "QEMU_LOG", true, handle_arg_log,
"options", "activate log"},
+ {"D", "QEMU_LOG_FILENAME", true, handle_arg_log_filename,
+ "logfile", "override default logfile location"},
{"p", "QEMU_PAGESIZE", true, handle_arg_pagesize,
"pagesize", "set the host page size to 'pagesize'"},
{"singlestep", "QEMU_SINGLESTEP", false, handle_arg_singlestep,
diff --git a/linux-user/mips64/syscall.h b/linux-user/mips64/syscall.h
index 668a2b95d4..e436ea57dc 100644
--- a/linux-user/mips64/syscall.h
+++ b/linux-user/mips64/syscall.h
@@ -218,4 +218,7 @@ struct target_pt_regs {
+/* Nasty hack: define a fake errno value for use by sigreturn. */
+#define TARGET_QEMU_ESIGRETURN 255
+
#define UNAME_MACHINE "mips64"
diff --git a/linux-user/mipsn32/syscall.h b/linux-user/mipsn32/syscall.h
index 4ec506cb02..ebe98f2070 100644
--- a/linux-user/mipsn32/syscall.h
+++ b/linux-user/mipsn32/syscall.h
@@ -218,4 +218,7 @@ struct target_pt_regs {
+/* Nasty hack: define a fake errno value for use by sigreturn. */
+#define TARGET_QEMU_ESIGRETURN 255
+
#define UNAME_MACHINE "mips64"
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
index 55ad9d8586..308dbc025b 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -48,6 +48,7 @@ struct image_info {
abi_ulong code_offset;
abi_ulong data_offset;
abi_ulong saved_auxv;
+ abi_ulong auxv_len;
abi_ulong arg_start;
abi_ulong arg_end;
int personality;
@@ -123,10 +124,10 @@ typedef struct TaskState {
#endif
#if defined(TARGET_ARM) || defined(TARGET_M68K) || defined(TARGET_UNICORE32)
/* Extra fields for semihosted binaries. */
- uint32_t stack_base;
uint32_t heap_base;
uint32_t heap_limit;
#endif
+ uint32_t stack_base;
int used; /* non zero if used */
struct image_info *info;
struct linux_binprm *bprm;
diff --git a/linux-user/signal.c b/linux-user/signal.c
index ded12caa18..79a39dcd7f 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -587,7 +587,11 @@ int do_sigaction(int sig, const struct target_sigaction *act,
#endif
if (oact) {
oact->_sa_handler = tswapal(k->_sa_handler);
+#if defined(TARGET_MIPS) || defined (TARGET_ALPHA)
+ oact->sa_flags = bswap32(k->sa_flags);
+#else
oact->sa_flags = tswapal(k->sa_flags);
+#endif
#if !defined(TARGET_MIPS)
oact->sa_restorer = tswapal(k->sa_restorer);
#endif
@@ -596,7 +600,11 @@ int do_sigaction(int sig, const struct target_sigaction *act,
if (act) {
/* FIXME: This is not threadsafe. */
k->_sa_handler = tswapal(act->_sa_handler);
+#if defined(TARGET_MIPS) || defined (TARGET_ALPHA)
+ k->sa_flags = bswap32(act->sa_flags);
+#else
k->sa_flags = tswapal(act->sa_flags);
+#endif
#if !defined(TARGET_MIPS)
k->sa_restorer = tswapal(act->sa_restorer);
#endif
diff --git a/linux-user/strace.c b/linux-user/strace.c
index 90027a1106..05a0d3e9d7 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -1,5 +1,4 @@
#include <stdio.h>
-#include <errno.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/sem.h>
@@ -284,8 +283,13 @@ print_ipc(const struct syscallname *name,
static void
print_syscall_ret_addr(const struct syscallname *name, abi_long ret)
{
-if( ret == -1 ) {
- gemu_log(" = -1 errno=%d (%s)\n", errno, target_strerror(errno));
+ char *errstr = NULL;
+
+ if (ret < 0) {
+ errstr = target_strerror(-ret);
+ }
+ if (errstr) {
+ gemu_log(" = -1 errno=%d (%s)\n", (int)-ret, errstr);
} else {
gemu_log(" = 0x" TARGET_ABI_FMT_lx "\n", ret);
}
@@ -1515,14 +1519,19 @@ void
print_syscall_ret(int num, abi_long ret)
{
int i;
+ char *errstr = NULL;
for(i=0;i<nsyscalls;i++)
if( scnames[i].nr == num ) {
if( scnames[i].result != NULL ) {
scnames[i].result(&scnames[i],ret);
} else {
- if( ret < 0 ) {
- gemu_log(" = -1 errno=" TARGET_ABI_FMT_ld " (%s)\n", -ret, target_strerror(-ret));
+ if (ret < 0) {
+ errstr = target_strerror(-ret);
+ }
+ if (errstr) {
+ gemu_log(" = -1 errno=" TARGET_ABI_FMT_ld " (%s)\n",
+ -ret, errstr);
} else {
gemu_log(" = " TARGET_ABI_FMT_ld "\n", ret);
}
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 2bf9e7ec44..ee8899ef3d 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -731,6 +731,9 @@ static inline int is_error(abi_long ret)
char *target_strerror(int err)
{
+ if ((err >= ERRNO_TABLE_SIZE) || (err < 0)) {
+ return NULL;
+ }
return strerror(target_to_host_errno(err));
}
@@ -1530,9 +1533,41 @@ static abi_long do_getsockopt(int sockfd, int level, int optname,
case TARGET_SO_LINGER:
case TARGET_SO_RCVTIMEO:
case TARGET_SO_SNDTIMEO:
- case TARGET_SO_PEERCRED:
case TARGET_SO_PEERNAME:
goto unimplemented;
+ case TARGET_SO_PEERCRED: {
+ struct ucred cr;
+ socklen_t crlen;
+ struct target_ucred *tcr;
+
+ if (get_user_u32(len, optlen)) {
+ return -TARGET_EFAULT;
+ }
+ if (len < 0) {
+ return -TARGET_EINVAL;
+ }
+
+ crlen = sizeof(cr);
+ ret = get_errno(getsockopt(sockfd, level, SO_PEERCRED,
+ &cr, &crlen));
+ if (ret < 0) {
+ return ret;
+ }
+ if (len > crlen) {
+ len = crlen;
+ }
+ if (!lock_user_struct(VERIFY_WRITE, tcr, optval_addr, 0)) {
+ return -TARGET_EFAULT;
+ }
+ __put_user(cr.pid, &tcr->pid);
+ __put_user(cr.uid, &tcr->uid);
+ __put_user(cr.gid, &tcr->gid);
+ unlock_user_struct(tcr, optval_addr, 1);
+ if (put_user_u32(len, optlen)) {
+ return -TARGET_EFAULT;
+ }
+ break;
+ }
/* Options with 'int' argument. */
case TARGET_SO_DEBUG:
optname = SO_DEBUG;
@@ -4600,6 +4635,123 @@ int get_osversion(void)
return osversion;
}
+
+static int open_self_maps(void *cpu_env, int fd)
+{
+ TaskState *ts = ((CPUState *)cpu_env)->opaque;
+
+ dprintf(fd, "%08llx-%08llx rw-p %08llx 00:00 0 [stack]\n",
+ (unsigned long long)ts->info->stack_limit,
+ (unsigned long long)(ts->stack_base + (TARGET_PAGE_SIZE - 1))
+ & TARGET_PAGE_MASK,
+ (unsigned long long)ts->stack_base);
+
+ return 0;
+}
+
+static int open_self_stat(void *cpu_env, int fd)
+{
+ TaskState *ts = ((CPUState *)cpu_env)->opaque;
+ abi_ulong start_stack = ts->info->start_stack;
+ int i;
+
+ for (i = 0; i < 44; i++) {
+ char buf[128];
+ int len;
+ uint64_t val = 0;
+
+ if (i == 27) {
+ /* stack bottom */
+ val = start_stack;
+ }
+ snprintf(buf, sizeof(buf), "%"PRId64 "%c", val, i == 43 ? '\n' : ' ');
+ len = strlen(buf);
+ if (write(fd, buf, len) != len) {
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static int open_self_auxv(void *cpu_env, int fd)
+{
+ TaskState *ts = ((CPUState *)cpu_env)->opaque;
+ abi_ulong auxv = ts->info->saved_auxv;
+ abi_ulong len = ts->info->auxv_len;
+ char *ptr;
+
+ /*
+ * Auxiliary vector is stored in target process stack.
+ * read in whole auxv vector and copy it to file
+ */
+ ptr = lock_user(VERIFY_READ, auxv, len, 0);
+ if (ptr != NULL) {
+ while (len > 0) {
+ ssize_t r;
+ r = write(fd, ptr, len);
+ if (r <= 0) {
+ break;
+ }
+ len -= r;
+ ptr += r;
+ }
+ lseek(fd, 0, SEEK_SET);
+ unlock_user(ptr, auxv, len);
+ }
+
+ return 0;
+}
+
+static int do_open(void *cpu_env, const char *pathname, int flags, mode_t mode)
+{
+ struct fake_open {
+ const char *filename;
+ int (*fill)(void *cpu_env, int fd);
+ };
+ const struct fake_open *fake_open;
+ static const struct fake_open fakes[] = {
+ { "/proc/self/maps", open_self_maps },
+ { "/proc/self/stat", open_self_stat },
+ { "/proc/self/auxv", open_self_auxv },
+ { NULL, NULL }
+ };
+
+ for (fake_open = fakes; fake_open->filename; fake_open++) {
+ if (!strncmp(pathname, fake_open->filename,
+ strlen(fake_open->filename))) {
+ break;
+ }
+ }
+
+ if (fake_open->filename) {
+ const char *tmpdir;
+ char filename[PATH_MAX];
+ int fd, r;
+
+ /* create temporary file to map stat to */
+ tmpdir = getenv("TMPDIR");
+ if (!tmpdir)
+ tmpdir = "/tmp";
+ snprintf(filename, sizeof(filename), "%s/qemu-open.XXXXXX", tmpdir);
+ fd = mkstemp(filename);
+ if (fd < 0) {
+ return fd;
+ }
+ unlink(filename);
+
+ if ((r = fake_open->fill(cpu_env, fd))) {
+ close(fd);
+ return r;
+ }
+ lseek(fd, 0, SEEK_SET);
+
+ return fd;
+ }
+
+ return get_errno(open(path(pathname), flags, mode));
+}
+
/* do_syscall() should always have a single exit point at the end so
that actions, such as logging of syscall results, can be performed.
All errnos that do_syscall() returns must be -TARGET_<errcode>. */
@@ -4685,9 +4837,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
case TARGET_NR_open:
if (!(p = lock_user_string(arg1)))
goto efault;
- ret = get_errno(open(path(p),
- target_to_host_bitmask(arg2, fcntl_flags_tbl),
- arg3));
+ ret = get_errno(do_open(cpu_env, p,
+ target_to_host_bitmask(arg2, fcntl_flags_tbl),
+ arg3));
unlock_user(p, arg1, 0);
break;
#if defined(TARGET_NR_openat) && defined(__NR_openat)
@@ -4715,7 +4867,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
{
int status;
ret = get_errno(waitpid(arg1, &status, arg3));
- if (!is_error(ret) && arg2
+ if (!is_error(ret) && arg2 && ret
&& put_user_s32(host_to_target_waitstatus(status), arg2))
goto efault;
}
@@ -6271,7 +6423,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
rusage_ptr = NULL;
ret = get_errno(wait4(arg1, &status, arg3, rusage_ptr));
if (!is_error(ret)) {
- if (status_ptr) {
+ if (status_ptr && ret) {
status = host_to_target_waitstatus(status);
if (put_user_s32(status, status_ptr))
goto efault;
@@ -7644,25 +7796,64 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
#endif
#ifdef CONFIG_ATTR
#ifdef TARGET_NR_setxattr
- case TARGET_NR_lsetxattr:
- case TARGET_NR_fsetxattr:
- case TARGET_NR_lgetxattr:
- case TARGET_NR_fgetxattr:
case TARGET_NR_listxattr:
case TARGET_NR_llistxattr:
+ {
+ void *p, *b = 0;
+ if (arg2) {
+ b = lock_user(VERIFY_WRITE, arg2, arg3, 0);
+ if (!b) {
+ ret = -TARGET_EFAULT;
+ break;
+ }
+ }
+ p = lock_user_string(arg1);
+ if (p) {
+ if (num == TARGET_NR_listxattr) {
+ ret = get_errno(listxattr(p, b, arg3));
+ } else {
+ ret = get_errno(llistxattr(p, b, arg3));
+ }
+ } else {
+ ret = -TARGET_EFAULT;
+ }
+ unlock_user(p, arg1, 0);
+ unlock_user(b, arg2, arg3);
+ break;
+ }
case TARGET_NR_flistxattr:
- case TARGET_NR_lremovexattr:
- case TARGET_NR_fremovexattr:
- ret = -TARGET_EOPNOTSUPP;
+ {
+ void *b = 0;
+ if (arg2) {
+ b = lock_user(VERIFY_WRITE, arg2, arg3, 0);
+ if (!b) {
+ ret = -TARGET_EFAULT;
+ break;
+ }
+ }
+ ret = get_errno(flistxattr(arg1, b, arg3));
+ unlock_user(b, arg2, arg3);
break;
+ }
case TARGET_NR_setxattr:
+ case TARGET_NR_lsetxattr:
{
- void *p, *n, *v;
+ void *p, *n, *v = 0;
+ if (arg3) {
+ v = lock_user(VERIFY_READ, arg3, arg4, 1);
+ if (!v) {
+ ret = -TARGET_EFAULT;
+ break;
+ }
+ }
p = lock_user_string(arg1);
n = lock_user_string(arg2);
- v = lock_user(VERIFY_READ, arg3, arg4, 1);
- if (p && n && v) {
- ret = get_errno(setxattr(p, n, v, arg4, arg5));
+ if (p && n) {
+ if (num == TARGET_NR_setxattr) {
+ ret = get_errno(setxattr(p, n, v, arg4, arg5));
+ } else {
+ ret = get_errno(lsetxattr(p, n, v, arg4, arg5));
+ }
} else {
ret = -TARGET_EFAULT;
}
@@ -7671,14 +7862,45 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
unlock_user(v, arg3, 0);
}
break;
+ case TARGET_NR_fsetxattr:
+ {
+ void *n, *v = 0;
+ if (arg3) {
+ v = lock_user(VERIFY_READ, arg3, arg4, 1);
+ if (!v) {
+ ret = -TARGET_EFAULT;
+ break;
+ }
+ }
+ n = lock_user_string(arg2);
+ if (n) {
+ ret = get_errno(fsetxattr(arg1, n, v, arg4, arg5));
+ } else {
+ ret = -TARGET_EFAULT;
+ }
+ unlock_user(n, arg2, 0);
+ unlock_user(v, arg3, 0);
+ }
+ break;
case TARGET_NR_getxattr:
+ case TARGET_NR_lgetxattr:
{
- void *p, *n, *v;
+ void *p, *n, *v = 0;
+ if (arg3) {
+ v = lock_user(VERIFY_WRITE, arg3, arg4, 0);
+ if (!v) {
+ ret = -TARGET_EFAULT;
+ break;
+ }
+ }
p = lock_user_string(arg1);
n = lock_user_string(arg2);
- v = lock_user(VERIFY_WRITE, arg3, arg4, 0);
- if (p && n && v) {
- ret = get_errno(getxattr(p, n, v, arg4));
+ if (p && n) {
+ if (num == TARGET_NR_getxattr) {
+ ret = get_errno(getxattr(p, n, v, arg4));
+ } else {
+ ret = get_errno(lgetxattr(p, n, v, arg4));
+ }
} else {
ret = -TARGET_EFAULT;
}
@@ -7687,13 +7909,38 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
unlock_user(v, arg3, arg4);
}
break;
+ case TARGET_NR_fgetxattr:
+ {
+ void *n, *v = 0;
+ if (arg3) {
+ v = lock_user(VERIFY_WRITE, arg3, arg4, 0);
+ if (!v) {
+ ret = -TARGET_EFAULT;
+ break;
+ }
+ }
+ n = lock_user_string(arg2);
+ if (n) {
+ ret = get_errno(fgetxattr(arg1, n, v, arg4));
+ } else {
+ ret = -TARGET_EFAULT;
+ }
+ unlock_user(n, arg2, 0);
+ unlock_user(v, arg3, arg4);
+ }
+ break;
case TARGET_NR_removexattr:
+ case TARGET_NR_lremovexattr:
{
void *p, *n;
p = lock_user_string(arg1);
n = lock_user_string(arg2);
if (p && n) {
- ret = get_errno(removexattr(p, n));
+ if (num == TARGET_NR_removexattr) {
+ ret = get_errno(removexattr(p, n));
+ } else {
+ ret = get_errno(lremovexattr(p, n));
+ }
} else {
ret = -TARGET_EFAULT;
}
@@ -7701,6 +7948,18 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
unlock_user(n, arg2, 0);
}
break;
+ case TARGET_NR_fremovexattr:
+ {
+ void *n;
+ n = lock_user_string(arg2);
+ if (n) {
+ ret = get_errno(fremovexattr(arg1, n));
+ } else {
+ ret = -TARGET_EFAULT;
+ }
+ unlock_user(n, arg2, 0);
+ }
+ break;
#endif
#endif /* CONFIG_ATTR */
#ifdef TARGET_NR_set_thread_area
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index 2857805e16..41f0ff8c7d 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -2336,3 +2336,9 @@ struct target_rlimit64 {
uint64_t rlim_cur;
uint64_t rlim_max;
};
+
+struct target_ucred {
+ uint32_t pid;
+ uint32_t uid;
+ uint32_t gid;
+};
diff --git a/memory.c b/memory.c
index ee4c98af8c..5e77d8a2f4 100644
--- a/memory.c
+++ b/memory.c
@@ -1136,10 +1136,11 @@ void memory_region_set_log(MemoryRegion *mr, bool log, unsigned client)
}
bool memory_region_get_dirty(MemoryRegion *mr, target_phys_addr_t addr,
- unsigned client)
+ target_phys_addr_t size, unsigned client)
{
assert(mr->terminates);
- return cpu_physical_memory_get_dirty(mr->ram_addr + addr, 1 << client);
+ return cpu_physical_memory_get_dirty(mr->ram_addr + addr, size,
+ 1 << client);
}
void memory_region_set_dirty(MemoryRegion *mr, target_phys_addr_t addr,
diff --git a/memory.h b/memory.h
index fa45b99135..4cf8d2f27a 100644
--- a/memory.h
+++ b/memory.h
@@ -380,20 +380,21 @@ void memory_region_set_offset(MemoryRegion *mr, target_phys_addr_t offset);
void memory_region_set_log(MemoryRegion *mr, bool log, unsigned client);
/**
- * memory_region_get_dirty: Check whether a page is dirty for a specified
- * client.
+ * memory_region_get_dirty: Check whether a range of bytes is dirty
+ * for a specified client.
*
- * Checks whether a page has been written to since the last
+ * Checks whether a range of bytes has been written to since the last
* call to memory_region_reset_dirty() with the same @client. Dirty logging
* must be enabled.
*
* @mr: the memory region being queried.
* @addr: the address (relative to the start of the region) being queried.
+ * @size: the size of the range being queried.
* @client: the user of the logging information; %DIRTY_MEMORY_MIGRATION or
* %DIRTY_MEMORY_VGA.
*/
bool memory_region_get_dirty(MemoryRegion *mr, target_phys_addr_t addr,
- unsigned client);
+ target_phys_addr_t size, unsigned client);
/**
* memory_region_set_dirty: Mark a range of bytes as dirty in a memory region.
diff --git a/net.c b/net.c
index 1944539050..c34474fe5f 100644
--- a/net.c
+++ b/net.c
@@ -38,6 +38,11 @@
#include "hw/qdev.h"
#include "iov.h"
+/* Net bridge is currently not supported for W32. */
+#if !defined(_WIN32)
+# define CONFIG_NET_BRIDGE
+#endif
+
static QTAILQ_HEAD(, VLANState) vlans;
static QTAILQ_HEAD(, VLANClientState) non_vlan_clients;
@@ -952,10 +957,12 @@ static const struct {
.type = QEMU_OPT_STRING,
.help = "script to shut down the interface",
}, {
+#ifdef CONFIG_NET_BRIDGE
.name = "helper",
.type = QEMU_OPT_STRING,
.help = "command to execute to configure bridge",
}, {
+#endif
.name = "sndbuf",
.type = QEMU_OPT_SIZE,
.help = "send buffer limit"
@@ -1057,6 +1064,7 @@ static const struct {
{ /* end of list */ }
},
},
+#ifdef CONFIG_NET_BRIDGE
[NET_CLIENT_TYPE_BRIDGE] = {
.type = "bridge",
.init = net_init_bridge,
@@ -1074,6 +1082,7 @@ static const struct {
{ /* end of list */ }
},
},
+#endif /* CONFIG_NET_BRIDGE */
};
int net_client_init(Monitor *mon, QemuOpts *opts, int is_netdev)
@@ -1090,14 +1099,16 @@ int net_client_init(Monitor *mon, QemuOpts *opts, int is_netdev)
if (is_netdev) {
if (strcmp(type, "tap") != 0 &&
+#ifdef CONFIG_NET_BRIDGE
+ strcmp(type, "bridge") != 0 &&
+#endif
#ifdef CONFIG_SLIRP
strcmp(type, "user") != 0 &&
#endif
#ifdef CONFIG_VDE
strcmp(type, "vde") != 0 &&
#endif
- strcmp(type, "socket") != 0 &&
- strcmp(type, "bridge") != 0) {
+ strcmp(type, "socket") != 0) {
qerror_report(QERR_INVALID_PARAMETER_VALUE, "type",
"a netdev backend type");
return -1;
@@ -1161,13 +1172,15 @@ static int net_host_check_device(const char *device)
{
int i;
const char *valid_param_list[] = { "tap", "socket", "dump"
+#ifdef CONFIG_NET_BRIDGE
+ , "bridge"
+#endif
#ifdef CONFIG_SLIRP
,"user"
#endif
#ifdef CONFIG_VDE
,"vde"
#endif
- , "bridge"
};
for (i = 0; i < sizeof(valid_param_list) / sizeof(char *); i++) {
if (!strncmp(valid_param_list[i], device,
diff --git a/qemu-options.hx b/qemu-options.hx
index 19906e57e1..f577cc8470 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -554,7 +554,7 @@ DEFHEADING()
DEFHEADING(File system options:)
DEF("fsdev", HAS_ARG, QEMU_OPTION_fsdev,
- "-fsdev fsdriver,id=id[,path=path,][security_model={mapped|passthrough|none}]\n"
+ "-fsdev fsdriver,id=id[,path=path,][security_model={mapped-xattr|mapped-file|passthrough|none}]\n"
" [,writeout=immediate][,readonly][,socket=socket|sock_fd=sock_fd]\n",
QEMU_ARCH_ALL)
@@ -574,12 +574,13 @@ Specifies the export path for the file system device. Files under
this path will be available to the 9p client on the guest.
@item security_model=@var{security_model}
Specifies the security model to be used for this export path.
-Supported security models are "passthrough", "mapped" and "none".
+Supported security models are "passthrough", "mapped-xattr", "mapped-file" and "none".
In "passthrough" security model, files are stored using the same
credentials as they are created on the guest. This requires qemu
-to run as root. In "mapped" security model, some of the file
+to run as root. In "mapped-xattr" security model, some of the file
attributes like uid, gid, mode bits and link target are stored as
-file attributes. Directories exported by this security model cannot
+file attributes. For "mapped-file" these attributes are stored in the
+hidden .virtfs_metadata directory. Directories exported by this security model cannot
interact with other unix tools. "none" security model is same as
passthrough except the sever won't report failures if it fails to
set file attributes like ownership. Security model is mandatory
@@ -619,7 +620,7 @@ DEFHEADING()
DEFHEADING(Virtual File system pass-through options:)
DEF("virtfs", HAS_ARG, QEMU_OPTION_virtfs,
- "-virtfs local,path=path,mount_tag=tag,security_model=[mapped|passthrough|none]\n"
+ "-virtfs local,path=path,mount_tag=tag,security_model=[mapped-xattr|mapped-file|passthrough|none]\n"
" [,writeout=immediate][,readonly][,socket=socket|sock_fd=sock_fd]\n",
QEMU_ARCH_ALL)
@@ -640,12 +641,13 @@ Specifies the export path for the file system device. Files under
this path will be available to the 9p client on the guest.
@item security_model=@var{security_model}
Specifies the security model to be used for this export path.
-Supported security models are "passthrough", "mapped" and "none".
+Supported security models are "passthrough", "mapped-xattr", "mapped-file" and "none".
In "passthrough" security model, files are stored using the same
credentials as they are created on the guest. This requires qemu
-to run as root. In "mapped" security model, some of the file
+to run as root. In "mapped-xattr" security model, some of the file
attributes like uid, gid, mode bits and link target are stored as
-file attributes. Directories exported by this security model cannot
+file attributes. For "mapped-file" these attributes are stored in the
+hidden .virtfs_metadata directory. Directories exported by this security model cannot
interact with other unix tools. "none" security model is same as
passthrough except the sever won't report failures if it fails to
set file attributes like ownership. Security model is mandatory only
diff --git a/qemu-thread-win32.c b/qemu-thread-win32.c
index fe9b931863..3524c8b785 100644
--- a/qemu-thread-win32.c
+++ b/qemu-thread-win32.c
@@ -215,8 +215,6 @@ static unsigned __stdcall win32_start_routine(void *arg)
if (data->mode == QEMU_THREAD_DETACHED) {
g_free(data);
data = NULL;
- } else {
- InitializeCriticalSection(&data->cs);
}
TlsSetValue(qemu_thread_tls_index, data);
qemu_thread_exit(start_routine(thread_arg));
@@ -227,6 +225,7 @@ void qemu_thread_exit(void *arg)
{
QemuThreadData *data = TlsGetValue(qemu_thread_tls_index);
if (data) {
+ assert(data->mode != QEMU_THREAD_DETACHED);
data->ret = arg;
EnterCriticalSection(&data->cs);
data->exited = true;
@@ -258,6 +257,7 @@ void *qemu_thread_join(QemuThread *thread)
CloseHandle(handle);
}
ret = data->ret;
+ assert(data->mode != QEMU_THREAD_DETACHED);
DeleteCriticalSection(&data->cs);
g_free(data);
return ret;
@@ -288,6 +288,10 @@ void qemu_thread_create(QemuThread *thread,
data->mode = mode;
data->exited = false;
+ if (data->mode != QEMU_THREAD_DETACHED) {
+ InitializeCriticalSection(&data->cs);
+ }
+
hThread = (HANDLE) _beginthreadex(NULL, 0, win32_start_routine,
data, 0, &thread->tid);
if (!hThread) {
@@ -314,6 +318,7 @@ HANDLE qemu_thread_get_handle(QemuThread *thread)
return NULL;
}
+ assert(data->mode != QEMU_THREAD_DETACHED);
EnterCriticalSection(&data->cs);
if (!data->exited) {
handle = OpenThread(SYNCHRONIZE | THREAD_SUSPEND_RESUME, FALSE,
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index 2d67d1f4b8..fbcf4881a8 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -187,7 +187,10 @@ enum {
POWERPC_EXCP_EPERFM = 35, /* Embedded performance monitor interrupt */
POWERPC_EXCP_DOORI = 36, /* Embedded doorbell interrupt */
POWERPC_EXCP_DOORCI = 37, /* Embedded doorbell critical interrupt */
- /* Vectors 38 to 63 are reserved */
+ POWERPC_EXCP_GDOORI = 38, /* Embedded guest doorbell interrupt */
+ POWERPC_EXCP_GDOORCI = 39, /* Embedded guest doorbell critical interrupt*/
+ POWERPC_EXCP_HYPPRIV = 41, /* Embedded hypervisor priv instruction */
+ /* Vectors 42 to 63 are reserved */
/* Exceptions defined in the PowerPC server specification */
POWERPC_EXCP_RESET = 64, /* System reset exception */
POWERPC_EXCP_DSEG = 65, /* Data segment exception */
@@ -855,6 +858,22 @@ enum {
#define BOOKE206_MAX_TLBN 4
/*****************************************************************************/
+/* Embedded.Processor Control */
+
+#define DBELL_TYPE_SHIFT 27
+#define DBELL_TYPE_MASK (0x1f << DBELL_TYPE_SHIFT)
+#define DBELL_TYPE_DBELL (0x00 << DBELL_TYPE_SHIFT)
+#define DBELL_TYPE_DBELL_CRIT (0x01 << DBELL_TYPE_SHIFT)
+#define DBELL_TYPE_G_DBELL (0x02 << DBELL_TYPE_SHIFT)
+#define DBELL_TYPE_G_DBELL_CRIT (0x03 << DBELL_TYPE_SHIFT)
+#define DBELL_TYPE_G_DBELL_MC (0x04 << DBELL_TYPE_SHIFT)
+
+#define DBELL_BRDCAST (1 << 26)
+#define DBELL_LPIDTAG_SHIFT 14
+#define DBELL_LPIDTAG_MASK (0xfff << DBELL_LPIDTAG_SHIFT)
+#define DBELL_PIRTAG_MASK 0x3fff
+
+/*****************************************************************************/
/* The whole PowerPC CPU context */
#define NB_MMU_MODES 3
@@ -1355,6 +1374,10 @@ static inline void cpu_clone_regs(CPUState *env, target_ulong newsp)
#define SPR_BOOKE_DVC2 (0x13F)
#define SPR_BOOKE_TSR (0x150)
#define SPR_BOOKE_TCR (0x154)
+#define SPR_BOOKE_TLB0PS (0x158)
+#define SPR_BOOKE_TLB1PS (0x159)
+#define SPR_BOOKE_TLB2PS (0x15A)
+#define SPR_BOOKE_TLB3PS (0x15B)
#define SPR_BOOKE_IVOR0 (0x190)
#define SPR_BOOKE_IVOR1 (0x191)
#define SPR_BOOKE_IVOR2 (0x192)
@@ -1371,6 +1394,11 @@ static inline void cpu_clone_regs(CPUState *env, target_ulong newsp)
#define SPR_BOOKE_IVOR13 (0x19D)
#define SPR_BOOKE_IVOR14 (0x19E)
#define SPR_BOOKE_IVOR15 (0x19F)
+#define SPR_BOOKE_IVOR38 (0x1B0)
+#define SPR_BOOKE_IVOR39 (0x1B1)
+#define SPR_BOOKE_IVOR40 (0x1B2)
+#define SPR_BOOKE_IVOR41 (0x1B3)
+#define SPR_BOOKE_IVOR42 (0x1B4)
#define SPR_BOOKE_SPEFSCR (0x200)
#define SPR_Exxx_BBEAR (0x201)
#define SPR_Exxx_BBTAR (0x202)
@@ -1888,8 +1916,10 @@ enum {
PPC2_VSX = 0x0000000000000002ULL,
/* Decimal Floating Point (DFP) */
PPC2_DFP = 0x0000000000000004ULL,
+ /* Embedded.Processor Control */
+ PPC2_PRCNTL = 0x0000000000000008ULL,
-#define PPC_TCG_INSNS2 (PPC2_BOOKE206)
+#define PPC_TCG_INSNS2 (PPC2_BOOKE206 | PPC2_PRCNTL)
};
/*****************************************************************************/
@@ -2103,6 +2133,10 @@ static inline ppcmas_tlb_t *booke206_get_tlbm(CPUState *env, const int tlbn,
ea &= (1 << (tlb_bits - ways_bits)) - 1;
r = (ea << ways_bits) | way;
+ if (r >= booke206_tlb_size(env, tlbn)) {
+ return NULL;
+ }
+
/* bump up to tlbn index */
for (i = 0; i < tlbn; i++) {
r += booke206_tlb_size(env, i);
@@ -2111,6 +2145,27 @@ static inline ppcmas_tlb_t *booke206_get_tlbm(CPUState *env, const int tlbn,
return &env->tlb.tlbm[r];
}
+/* returns bitmap of supported page sizes for a given TLB */
+static inline uint32_t booke206_tlbnps(CPUState *env, const int tlbn)
+{
+ bool mav2 = false;
+ uint32_t ret = 0;
+
+ if (mav2) {
+ ret = env->spr[SPR_BOOKE_TLB0PS + tlbn];
+ } else {
+ uint32_t tlbncfg = env->spr[SPR_BOOKE_TLB0CFG + tlbn];
+ uint32_t min = (tlbncfg & TLBnCFG_MINSIZE) >> TLBnCFG_MINSIZE_SHIFT;
+ uint32_t max = (tlbncfg & TLBnCFG_MAXSIZE) >> TLBnCFG_MAXSIZE_SHIFT;
+ int i;
+ for (i = min; i <= max; i++) {
+ ret |= (1 << (i << 1));
+ }
+ }
+
+ return ret;
+}
+
#endif
extern void (*cpu_ppc_hypercall)(CPUState *);
diff --git a/target-ppc/helper.c b/target-ppc/helper.c
index 58474536c0..e56fac8684 100644
--- a/target-ppc/helper.c
+++ b/target-ppc/helper.c
@@ -1298,13 +1298,7 @@ target_phys_addr_t booke206_tlb_to_page_size(CPUState *env, ppcmas_tlb_t *tlb)
int tlbm_size;
tlbncfg = env->spr[SPR_BOOKE_TLB0CFG + tlbn];
-
- if (tlbncfg & TLBnCFG_AVAIL) {
- tlbm_size = (tlb->mas1 & MAS1_TSIZE_MASK) >> MAS1_TSIZE_SHIFT;
- } else {
- tlbm_size = (tlbncfg & TLBnCFG_MINSIZE) >> TLBnCFG_MINSIZE_SHIFT;
- tlbm_size <<= 1;
- }
+ tlbm_size = (tlb->mas1 & MAS1_TSIZE_MASK) >> MAS1_TSIZE_SHIFT;
return 1024ULL << tlbm_size;
}
@@ -1338,7 +1332,10 @@ int ppcmas_tlb_check(CPUState *env, ppcmas_tlb_t *tlb,
if ((address & mask) != (tlb->mas2 & MAS2_EPN_MASK)) {
return -1;
}
- *raddrp = (tlb->mas7_3 & mask) | (address & ~mask);
+
+ if (raddrp) {
+ *raddrp = (tlb->mas7_3 & mask) | (address & ~mask);
+ }
return 0;
}
@@ -1445,6 +1442,9 @@ static int mmubooke206_get_physical_address(CPUState *env, mmu_ctx_t *ctx,
for (j = 0; j < ways; j++) {
tlb = booke206_get_tlbm(env, i, address, j);
+ if (!tlb) {
+ continue;
+ }
ret = mmubooke206_check_tlb(env, tlb, &raddr, &ctx->prot, address,
rw, access_type);
if (ret != -1) {
@@ -2698,22 +2698,10 @@ static inline void powerpc_excp(CPUState *env, int excp_model, int excp)
"Performance counter exception is not implemented yet !\n");
goto store_next;
case POWERPC_EXCP_DOORI: /* Embedded doorbell interrupt */
- /* XXX: TODO */
- cpu_abort(env,
- "Embedded doorbell interrupt is not implemented yet !\n");
goto store_next;
case POWERPC_EXCP_DOORCI: /* Embedded doorbell critical interrupt */
- switch (excp_model) {
- case POWERPC_EXCP_BOOKE:
- srr0 = SPR_BOOKE_CSRR0;
- srr1 = SPR_BOOKE_CSRR1;
- break;
- default:
- break;
- }
- /* XXX: TODO */
- cpu_abort(env, "Embedded doorbell critical interrupt "
- "is not implemented yet !\n");
+ srr0 = SPR_BOOKE_CSRR0;
+ srr1 = SPR_BOOKE_CSRR1;
goto store_next;
case POWERPC_EXCP_RESET: /* System reset exception */
if (msr_pow) {
diff --git a/target-ppc/helper.h b/target-ppc/helper.h
index 470e42f676..148543a8a1 100644
--- a/target-ppc/helper.h
+++ b/target-ppc/helper.h
@@ -336,6 +336,9 @@ DEF_HELPER_0(booke206_tlbre, void)
DEF_HELPER_0(booke206_tlbwe, void)
DEF_HELPER_1(booke206_tlbsx, void, tl)
DEF_HELPER_1(booke206_tlbivax, void, tl)
+DEF_HELPER_1(booke206_tlbilx0, void, tl)
+DEF_HELPER_1(booke206_tlbilx1, void, tl)
+DEF_HELPER_1(booke206_tlbilx3, void, tl)
DEF_HELPER_1(booke206_tlbflush, void, i32)
DEF_HELPER_2(booke_setpid, void, i32, tl)
DEF_HELPER_1(6xx_tlbd, void, tl)
@@ -355,6 +358,8 @@ DEF_HELPER_FLAGS_1(load_sr, TCG_CALL_CONST, tl, tl);
DEF_HELPER_FLAGS_2(store_sr, TCG_CALL_CONST, void, tl, tl)
DEF_HELPER_FLAGS_1(602_mfrom, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
+DEF_HELPER_1(msgsnd, void, tl)
+DEF_HELPER_1(msgclr, void, tl)
#endif
DEF_HELPER_3(dlmzb, tl, tl, tl, i32)
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index ce8ac5b4de..50cfa02f78 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -740,6 +740,7 @@ void kvmppc_set_papr(CPUState *env)
struct kvm_one_reg reg = {};
struct kvm_sregs sregs = {};
int ret;
+ uint64_t hior = env->spr[SPR_HIOR];
cap.cap = KVM_CAP_PPC_PAPR;
ret = kvm_vcpu_ioctl(env, KVM_ENABLE_CAP, &cap);
@@ -755,11 +756,14 @@ void kvmppc_set_papr(CPUState *env)
* Once we have qdev CPUs, move HIOR to a qdev property and
* remove this chunk.
*/
- reg.id = KVM_ONE_REG_PPC_HIOR;
- reg.u.reg64 = env->spr[SPR_HIOR];
+ reg.id = KVM_REG_PPC_HIOR;
+ reg.addr = (uintptr_t)&hior;
ret = kvm_vcpu_ioctl(env, KVM_SET_ONE_REG, &reg);
if (ret) {
- goto fail;
+ fprintf(stderr, "Couldn't set HIOR. Maybe you're running an old \n"
+ "kernel with support for HV KVM but no PAPR PR \n"
+ "KVM in which case things will work. If they don't \n"
+ "please update your host kernel!\n");
}
/* Set SDR1 so kernel space finds the HTAB */
diff --git a/target-ppc/op_helper.c b/target-ppc/op_helper.c
index 6339c9559f..3f4e06789f 100644
--- a/target-ppc/op_helper.c
+++ b/target-ppc/op_helper.c
@@ -4228,6 +4228,7 @@ void helper_booke206_tlbwe(void)
{
uint32_t tlbncfg, tlbn;
ppcmas_tlb_t *tlb;
+ uint32_t size_tlb, size_ps;
switch (env->spr[SPR_BOOKE_MAS0] & MAS0_WQ_MASK) {
case MAS0_WQ_ALWAYS:
@@ -4259,12 +4260,37 @@ void helper_booke206_tlbwe(void)
tlb = booke206_cur_tlb(env);
+ if (!tlb) {
+ helper_raise_exception_err(POWERPC_EXCP_PROGRAM,
+ POWERPC_EXCP_INVAL |
+ POWERPC_EXCP_INVAL_INVAL);
+ }
+
+ /* check that we support the targeted size */
+ size_tlb = (env->spr[SPR_BOOKE_MAS1] & MAS1_TSIZE_MASK) >> MAS1_TSIZE_SHIFT;
+ size_ps = booke206_tlbnps(env, tlbn);
+ if ((env->spr[SPR_BOOKE_MAS1] & MAS1_VALID) && (tlbncfg & TLBnCFG_AVAIL) &&
+ !(size_ps & (1 << size_tlb))) {
+ helper_raise_exception_err(POWERPC_EXCP_PROGRAM,
+ POWERPC_EXCP_INVAL |
+ POWERPC_EXCP_INVAL_INVAL);
+ }
+
if (msr_gs) {
cpu_abort(env, "missing HV implementation\n");
}
tlb->mas7_3 = ((uint64_t)env->spr[SPR_BOOKE_MAS7] << 32) |
env->spr[SPR_BOOKE_MAS3];
tlb->mas1 = env->spr[SPR_BOOKE_MAS1];
+
+ /* MAV 1.0 only */
+ if (!(tlbncfg & TLBnCFG_AVAIL)) {
+ /* force !AVAIL TLB entries to correct page size */
+ tlb->mas1 &= ~MAS1_TSIZE_MASK;
+ /* XXX can be configured in MMUCSR0 */
+ tlb->mas1 |= (tlbncfg & TLBnCFG_MINSIZE) >> 12;
+ }
+
/* XXX needs to change when supporting 64-bit e500 */
tlb->mas2 = env->spr[SPR_BOOKE_MAS2] & 0xffffffff;
@@ -4300,7 +4326,11 @@ void helper_booke206_tlbre(void)
ppcmas_tlb_t *tlb = NULL;
tlb = booke206_cur_tlb(env);
- booke206_tlb_to_mas(env, tlb);
+ if (!tlb) {
+ env->spr[SPR_BOOKE_MAS1] = 0;
+ } else {
+ booke206_tlb_to_mas(env, tlb);
+ }
}
void helper_booke206_tlbsx(target_ulong address)
@@ -4319,6 +4349,10 @@ void helper_booke206_tlbsx(target_ulong address)
for (j = 0; j < ways; j++) {
tlb = booke206_get_tlbm(env, i, address, j);
+ if (!tlb) {
+ continue;
+ }
+
if (ppcmas_tlb_check(env, tlb, &raddr, address, spid)) {
continue;
}
@@ -4362,6 +4396,9 @@ static inline void booke206_invalidate_ea_tlb(CPUState *env, int tlbn,
for (i = 0; i < ways; i++) {
ppcmas_tlb_t *tlb = booke206_get_tlbm(env, tlbn, ea, i);
+ if (!tlb) {
+ continue;
+ }
mask = ~(booke206_tlb_to_page_size(env, tlb) - 1);
if (((tlb->mas2 & MAS2_EPN_MASK) == (ea & mask)) &&
!(tlb->mas1 & MAS1_IPROT)) {
@@ -4395,6 +4432,73 @@ void helper_booke206_tlbivax(target_ulong address)
}
}
+void helper_booke206_tlbilx0(target_ulong address)
+{
+ /* XXX missing LPID handling */
+ booke206_flush_tlb(env, -1, 1);
+}
+
+void helper_booke206_tlbilx1(target_ulong address)
+{
+ int i, j;
+ int tid = (env->spr[SPR_BOOKE_MAS6] & MAS6_SPID);
+ ppcmas_tlb_t *tlb = env->tlb.tlbm;
+ int tlb_size;
+
+ /* XXX missing LPID handling */
+ for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
+ tlb_size = booke206_tlb_size(env, i);
+ for (j = 0; j < tlb_size; j++) {
+ if (!(tlb[j].mas1 & MAS1_IPROT) &&
+ ((tlb[j].mas1 & MAS1_TID_MASK) == tid)) {
+ tlb[j].mas1 &= ~MAS1_VALID;
+ }
+ }
+ tlb += booke206_tlb_size(env, i);
+ }
+ tlb_flush(env, 1);
+}
+
+void helper_booke206_tlbilx3(target_ulong address)
+{
+ int i, j;
+ ppcmas_tlb_t *tlb;
+ int tid = (env->spr[SPR_BOOKE_MAS6] & MAS6_SPID);
+ int pid = tid >> MAS6_SPID_SHIFT;
+ int sgs = env->spr[SPR_BOOKE_MAS5] & MAS5_SGS;
+ int ind = (env->spr[SPR_BOOKE_MAS6] & MAS6_SIND) ? MAS1_IND : 0;
+ /* XXX check for unsupported isize and raise an invalid opcode then */
+ int size = env->spr[SPR_BOOKE_MAS6] & MAS6_ISIZE_MASK;
+ /* XXX implement MAV2 handling */
+ bool mav2 = false;
+
+ /* XXX missing LPID handling */
+ /* flush by pid and ea */
+ for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
+ int ways = booke206_tlb_ways(env, i);
+
+ for (j = 0; j < ways; j++) {
+ tlb = booke206_get_tlbm(env, i, address, j);
+ if (!tlb) {
+ continue;
+ }
+ if ((ppcmas_tlb_check(env, tlb, NULL, address, pid) != 0) ||
+ (tlb->mas1 & MAS1_IPROT) ||
+ ((tlb->mas1 & MAS1_IND) != ind) ||
+ ((tlb->mas8 & MAS8_TGS) != sgs)) {
+ continue;
+ }
+ if (mav2 && ((tlb->mas1 & MAS1_TSIZE_MASK) != size)) {
+ /* XXX only check when MMUCFG[TWC] || TLBnCFG[HES] */
+ continue;
+ }
+ /* XXX e500mc doesn't match SAS, but other cores might */
+ tlb->mas1 &= ~MAS1_VALID;
+ }
+ }
+ tlb_flush(env, 1);
+}
+
void helper_booke206_tlbflush(uint32_t type)
{
int flags = 0;
@@ -4410,4 +4514,57 @@ void helper_booke206_tlbflush(uint32_t type)
booke206_flush_tlb(env, flags, 1);
}
+/* Embedded.Processor Control */
+static int dbell2irq(target_ulong rb)
+{
+ int msg = rb & DBELL_TYPE_MASK;
+ int irq = -1;
+
+ switch (msg) {
+ case DBELL_TYPE_DBELL:
+ irq = PPC_INTERRUPT_DOORBELL;
+ break;
+ case DBELL_TYPE_DBELL_CRIT:
+ irq = PPC_INTERRUPT_CDOORBELL;
+ break;
+ case DBELL_TYPE_G_DBELL:
+ case DBELL_TYPE_G_DBELL_CRIT:
+ case DBELL_TYPE_G_DBELL_MC:
+ /* XXX implement */
+ default:
+ break;
+ }
+
+ return irq;
+}
+
+void helper_msgclr(target_ulong rb)
+{
+ int irq = dbell2irq(rb);
+
+ if (irq < 0) {
+ return;
+ }
+
+ env->pending_interrupts &= ~(1 << irq);
+}
+
+void helper_msgsnd(target_ulong rb)
+{
+ int irq = dbell2irq(rb);
+ int pir = rb & DBELL_PIRTAG_MASK;
+ CPUState *cenv;
+
+ if (irq < 0) {
+ return;
+ }
+
+ for (cenv = first_cpu; cenv != NULL; cenv = cenv->next_cpu) {
+ if ((rb & DBELL_BRDCAST) || (cenv->spr[SPR_BOOKE_PIR] == pir)) {
+ cenv->pending_interrupts |= 1 << irq;
+ cpu_interrupt(cenv, CPU_INTERRUPT_HARD);
+ }
+ }
+}
+
#endif /* !CONFIG_USER_ONLY */
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 66eae30209..b2780dbe55 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -6088,6 +6088,7 @@ static void gen_tlbwe_booke206(DisasContext *ctx)
gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
return;
}
+ gen_update_nip(ctx, ctx->nip - 4);
gen_helper_booke206_tlbwe();
#endif
}
@@ -6110,6 +6111,39 @@ static void gen_tlbivax_booke206(DisasContext *ctx)
#endif
}
+static void gen_tlbilx_booke206(DisasContext *ctx)
+{
+#if defined(CONFIG_USER_ONLY)
+ gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
+#else
+ TCGv t0;
+ if (unlikely(!ctx->mem_idx)) {
+ gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
+ return;
+ }
+
+ t0 = tcg_temp_new();
+ gen_addr_reg_index(ctx, t0);
+
+ switch((ctx->opcode >> 21) & 0x3) {
+ case 0:
+ gen_helper_booke206_tlbilx0(t0);
+ break;
+ case 1:
+ gen_helper_booke206_tlbilx1(t0);
+ break;
+ case 3:
+ gen_helper_booke206_tlbilx3(t0);
+ break;
+ default:
+ gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
+ break;
+ }
+
+ tcg_temp_free(t0);
+#endif
+}
+
/* wrtee */
static void gen_wrtee(DisasContext *ctx)
@@ -6172,7 +6206,7 @@ static void gen_mbar(DisasContext *ctx)
}
/* msync replaces sync on 440 */
-static void gen_msync(DisasContext *ctx)
+static void gen_msync_4xx(DisasContext *ctx)
{
/* interpreted as no-op */
}
@@ -6186,6 +6220,36 @@ static void gen_icbt_440(DisasContext *ctx)
*/
}
+/* Embedded.Processor Control */
+
+static void gen_msgclr(DisasContext *ctx)
+{
+#if defined(CONFIG_USER_ONLY)
+ gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
+#else
+ if (unlikely(ctx->mem_idx == 0)) {
+ gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
+ return;
+ }
+
+ gen_helper_msgclr(cpu_gpr[rB(ctx->opcode)]);
+#endif
+}
+
+static void gen_msgsnd(DisasContext *ctx)
+{
+#if defined(CONFIG_USER_ONLY)
+ gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
+#else
+ if (unlikely(ctx->mem_idx == 0)) {
+ gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
+ return;
+ }
+
+ gen_helper_msgsnd(cpu_gpr[rB(ctx->opcode)]);
+#endif
+}
+
/*** Altivec vector extension ***/
/* Altivec registers moves */
@@ -8574,13 +8638,18 @@ GEN_HANDLER2_E(tlbwe_booke206, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001,
PPC_NONE, PPC2_BOOKE206),
GEN_HANDLER2_E(tlbivax_booke206, "tlbivax", 0x1F, 0x12, 0x18, 0x00000001,
PPC_NONE, PPC2_BOOKE206),
+GEN_HANDLER2_E(tlbilx_booke206, "tlbilx", 0x1F, 0x12, 0x00, 0x03800001,
+ PPC_NONE, PPC2_BOOKE206),
+GEN_HANDLER2_E(msgsnd, "msgsnd", 0x1F, 0x0E, 0x06, 0x03ff0001,
+ PPC_NONE, PPC2_PRCNTL),
+GEN_HANDLER2_E(msgclr, "msgclr", 0x1F, 0x0E, 0x07, 0x03ff0001,
+ PPC_NONE, PPC2_PRCNTL),
GEN_HANDLER(wrtee, 0x1F, 0x03, 0x04, 0x000FFC01, PPC_WRTEE),
GEN_HANDLER(wrteei, 0x1F, 0x03, 0x05, 0x000E7C01, PPC_WRTEE),
GEN_HANDLER(dlmzb, 0x1F, 0x0E, 0x02, 0x00000000, PPC_440_SPEC),
GEN_HANDLER_E(mbar, 0x1F, 0x16, 0x1a, 0x001FF801,
PPC_BOOKE, PPC2_BOOKE206),
-GEN_HANDLER_E(msync, 0x1F, 0x16, 0x12, 0x03FFF801,
- PPC_BOOKE, PPC2_BOOKE206),
+GEN_HANDLER(msync_4xx, 0x1F, 0x16, 0x12, 0x03FFF801, PPC_BOOKE),
GEN_HANDLER2_E(icbt_440, "icbt", 0x1F, 0x16, 0x00, 0x03E00001,
PPC_BOOKE, PPC2_BOOKE206),
GEN_HANDLER(lvsl, 0x1f, 0x06, 0x00, 0x00000001, PPC_ALTIVEC),
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 4d692d0dd3..6253076f68 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -526,26 +526,27 @@ static void spr_write_excp_prefix (void *opaque, int sprn, int gprn)
static void spr_write_excp_vector (void *opaque, int sprn, int gprn)
{
DisasContext *ctx = opaque;
+ int sprn_offs;
if (sprn >= SPR_BOOKE_IVOR0 && sprn <= SPR_BOOKE_IVOR15) {
- TCGv t0 = tcg_temp_new();
- tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, ivor_mask));
- tcg_gen_and_tl(t0, t0, cpu_gpr[gprn]);
- tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, excp_vectors[sprn - SPR_BOOKE_IVOR0]));
- gen_store_spr(sprn, t0);
- tcg_temp_free(t0);
+ sprn_offs = sprn - SPR_BOOKE_IVOR0;
} else if (sprn >= SPR_BOOKE_IVOR32 && sprn <= SPR_BOOKE_IVOR37) {
- TCGv t0 = tcg_temp_new();
- tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, ivor_mask));
- tcg_gen_and_tl(t0, t0, cpu_gpr[gprn]);
- tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, excp_vectors[sprn - SPR_BOOKE_IVOR32 + 32]));
- gen_store_spr(sprn, t0);
- tcg_temp_free(t0);
+ sprn_offs = sprn - SPR_BOOKE_IVOR32 + 32;
+ } else if (sprn >= SPR_BOOKE_IVOR38 && sprn <= SPR_BOOKE_IVOR42) {
+ sprn_offs = sprn - SPR_BOOKE_IVOR38 + 38;
} else {
printf("Trying to write an unknown exception vector %d %03x\n",
sprn, sprn);
gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
+ return;
}
+
+ TCGv t0 = tcg_temp_new();
+ tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, ivor_mask));
+ tcg_gen_and_tl(t0, t0, cpu_gpr[gprn]);
+ tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, excp_vectors[sprn_offs]));
+ gen_store_spr(sprn, t0);
+ tcg_temp_free(t0);
}
#endif
@@ -1434,8 +1435,8 @@ static void gen_spr_BookE (CPUPPCState *env, uint64_t ivor_mask)
SPR_BOOKE_IVORxx, SPR_BOOKE_IVORxx, SPR_BOOKE_IVORxx, SPR_BOOKE_IVORxx,
SPR_BOOKE_IVORxx, SPR_BOOKE_IVORxx, SPR_BOOKE_IVORxx, SPR_BOOKE_IVORxx,
SPR_BOOKE_IVOR32, SPR_BOOKE_IVOR33, SPR_BOOKE_IVOR34, SPR_BOOKE_IVOR35,
- SPR_BOOKE_IVOR36, SPR_BOOKE_IVOR37, SPR_BOOKE_IVORxx, SPR_BOOKE_IVORxx,
- SPR_BOOKE_IVORxx, SPR_BOOKE_IVORxx, SPR_BOOKE_IVORxx, SPR_BOOKE_IVORxx,
+ SPR_BOOKE_IVOR36, SPR_BOOKE_IVOR37, SPR_BOOKE_IVOR38, SPR_BOOKE_IVOR39,
+ SPR_BOOKE_IVOR40, SPR_BOOKE_IVOR41, SPR_BOOKE_IVOR42, SPR_BOOKE_IVORxx,
SPR_BOOKE_IVORxx, SPR_BOOKE_IVORxx, SPR_BOOKE_IVORxx, SPR_BOOKE_IVORxx,
SPR_BOOKE_IVORxx, SPR_BOOKE_IVORxx, SPR_BOOKE_IVORxx, SPR_BOOKE_IVORxx,
SPR_BOOKE_IVORxx, SPR_BOOKE_IVORxx, SPR_BOOKE_IVORxx, SPR_BOOKE_IVORxx,
@@ -4370,7 +4371,7 @@ static void init_proc_e300 (CPUPPCState *env)
PPC_WRTEE | PPC_RFDI | \
PPC_CACHE | PPC_CACHE_LOCK | PPC_CACHE_ICBI | \
PPC_CACHE_DCBZ | PPC_CACHE_DCBA | \
- PPC_MEM_TLBSYNC | PPC_TLBIVAX)
+ PPC_MEM_TLBSYNC | PPC_TLBIVAX | PPC_MEM_SYNC)
#define POWERPC_INSNS2_e500v1 (PPC2_BOOKE206)
#define POWERPC_MSRM_e500v1 (0x000000000606FF30ULL)
#define POWERPC_MMU_e500v1 (POWERPC_MMU_BOOKE206)
@@ -4389,7 +4390,7 @@ static void init_proc_e300 (CPUPPCState *env)
PPC_WRTEE | PPC_RFDI | \
PPC_CACHE | PPC_CACHE_LOCK | PPC_CACHE_ICBI | \
PPC_CACHE_DCBZ | PPC_CACHE_DCBA | \
- PPC_MEM_TLBSYNC | PPC_TLBIVAX)
+ PPC_MEM_TLBSYNC | PPC_TLBIVAX | PPC_MEM_SYNC)
#define POWERPC_INSNS2_e500v2 (PPC2_BOOKE206)
#define POWERPC_MSRM_e500v2 (0x000000000606FF30ULL)
#define POWERPC_MMU_e500v2 (POWERPC_MMU_BOOKE206)
@@ -4410,8 +4411,8 @@ static void init_proc_e300 (CPUPPCState *env)
PPC_FLOAT | PPC_FLOAT_FRES | \
PPC_FLOAT_FRSQRTE | PPC_FLOAT_FSEL | \
PPC_FLOAT_STFIWX | PPC_WAIT | \
- PPC_MEM_TLBSYNC | PPC_TLBIVAX)
-#define POWERPC_INSNS2_e500mc (PPC2_BOOKE206)
+ PPC_MEM_TLBSYNC | PPC_TLBIVAX | PPC_MEM_SYNC)
+#define POWERPC_INSNS2_e500mc (PPC2_BOOKE206 | PPC2_PRCNTL)
#define POWERPC_MSRM_e500mc (0x000000001402FB36ULL)
#define POWERPC_MMU_e500mc (POWERPC_MMU_BOOKE206)
#define POWERPC_EXCP_e500mc (POWERPC_EXCP_BOOKE)
@@ -4432,6 +4433,9 @@ enum fsl_e500_version {
static void init_proc_e500 (CPUPPCState *env, int version)
{
uint32_t tlbncfg[2];
+ uint64_t ivor_mask = 0x0000000F0000FFFFULL;
+ uint32_t l1cfg0 = 0x3800 /* 8 ways */
+ | 0x0020; /* 32 kb */
#if !defined(CONFIG_USER_ONLY)
int i;
#endif
@@ -4443,7 +4447,10 @@ static void init_proc_e500 (CPUPPCState *env, int version)
* complain when accessing them.
* gen_spr_BookE(env, 0x0000000F0000FD7FULL);
*/
- gen_spr_BookE(env, 0x0000000F0000FFFFULL);
+ if (version == fsl_e500mc) {
+ ivor_mask = 0x000003FE0000FFFFULL;
+ }
+ gen_spr_BookE(env, ivor_mask);
/* Processor identification */
spr_register(env, SPR_BOOKE_PIR, "PIR",
SPR_NOACCESS, SPR_NOACCESS,
@@ -4480,6 +4487,7 @@ static void init_proc_e500 (CPUPPCState *env, int version)
tlbncfg[1] = gen_tlbncfg(64, 1, 12, TLBnCFG_AVAIL | TLBnCFG_IPROT, 64);
env->dcache_line_size = 64;
env->icache_line_size = 64;
+ l1cfg0 |= 0x1000000; /* 64 byte cache block size */
break;
default:
cpu_abort(env, "Unknown CPU: " TARGET_FMT_lx "\n", env->spr[SPR_PVR]);
@@ -4530,7 +4538,7 @@ static void init_proc_e500 (CPUPPCState *env, int version)
spr_register(env, SPR_Exxx_L1CFG0, "L1CFG0",
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
- 0x00000000);
+ l1cfg0);
/* XXX : not implemented */
spr_register(env, SPR_Exxx_L1CSR0, "L1CSR0",
SPR_NOACCESS, SPR_NOACCESS,
diff --git a/usb-bsd.c b/usb-bsd.c
index 2c6afc8f32..fc722b3cfa 100644
--- a/usb-bsd.c
+++ b/usb-bsd.c
@@ -410,15 +410,16 @@ static void usb_host_class_initfn(ObjectClass *klass, void *data)
uc->handle_destroy = usb_host_handle_destroy;
}
-static struct DeviceInfo usb_host_dev_info = {
- .name = "usb-host",
- .size = sizeof(USBHostDevice),
- .class_init= usb_host_initfn,
+static TypeInfo usb_host_dev_info = {
+ .name = "usb-host",
+ .parent = TYPE_USB_DEVICE,
+ .instance_size = sizeof(USBHostDevice),
+ .class_init = usb_host_class_initfn,
};
static void usb_host_register_devices(void)
{
- usb_qdev_register(&usb_host_dev_info, NULL, NULL);
+ type_register_static(&usb_host_dev_info);
}
device_init(usb_host_register_devices)
diff --git a/usb-redir.c b/usb-redir.c
index 8f4a29a218..303292acd6 100644
--- a/usb-redir.c
+++ b/usb-redir.c
@@ -1315,9 +1315,16 @@ static void usbredir_interrupt_packet(void *priv, uint32_t id,
}
}
+static Property usbredir_properties[] = {
+ DEFINE_PROP_CHR("chardev", USBRedirDevice, cs),
+ DEFINE_PROP_UINT8("debug", USBRedirDevice, debug, 0),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
static void usbredir_class_initfn(ObjectClass *klass, void *data)
{
USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
+ DeviceClass *dc = DEVICE_CLASS(klass);
uc->init = usbredir_initfn;
uc->product_desc = "USB Redirection Device";
@@ -1327,21 +1334,18 @@ static void usbredir_class_initfn(ObjectClass *klass, void *data)
uc->handle_reset = usbredir_handle_reset;
uc->handle_data = usbredir_handle_data;
uc->handle_control = usbredir_handle_control;
+ dc->props = usbredir_properties;
}
-static struct DeviceInfo usbredir_dev_info = {
- .name = "usb-redir",
- .size = sizeof(USBRedirDevice),
- .class_init= usbredir_class_initfn,
- .props = (Property[]) {
- DEFINE_PROP_CHR("chardev", USBRedirDevice, cs),
- DEFINE_PROP_UINT8("debug", USBRedirDevice, debug, 0),
- DEFINE_PROP_END_OF_LIST(),
- },
+static TypeInfo usbredir_dev_info = {
+ .name = "usb-redir",
+ .parent = TYPE_USB_DEVICE,
+ .instance_size = sizeof(USBRedirDevice),
+ .class_init = usbredir_class_initfn,
};
static void usbredir_register_devices(void)
{
- usb_qdev_register(&usbredir_dev_info, NULL, NULL);
+ type_register_static(&usbredir_dev_info);
}
device_init(usbredir_register_devices);
diff --git a/vl.c b/vl.c
index 2d464cf65c..63dd725216 100644
--- a/vl.c
+++ b/vl.c
@@ -1947,7 +1947,11 @@ static int virtcon_parse(const char *devname)
}
bus_opts = qemu_opts_create(device, NULL, 0);
- qemu_opt_set(bus_opts, "driver", "virtio-serial");
+ if (arch_type == QEMU_ARCH_S390X) {
+ qemu_opt_set(bus_opts, "driver", "virtio-serial-s390");
+ } else {
+ qemu_opt_set(bus_opts, "driver", "virtio-serial-pci");
+ }
dev_opts = qemu_opts_create(device, NULL, 0);
qemu_opt_set(dev_opts, "driver", "virtconsole");