diff options
56 files changed, 1408 insertions, 1784 deletions
diff --git a/Makefile.target b/Makefile.target index e280bf6bf4..07af4d47c7 100644 --- a/Makefile.target +++ b/Makefile.target @@ -387,9 +387,11 @@ obj-y += $(addprefix $(HWDIR)/, $(hw-obj-y)) endif # CONFIG_SOFTMMU ifndef CONFIG_LINUX_USER +ifndef CONFIG_BSD_USER # libcacard needs qemu-thread support, and besides is only needed by devices -# so not requires with linux-user targets +# so not requires with linux-user / bsd-user targets obj-$(CONFIG_SMARTCARD_NSS) += $(addprefix ../libcacard/, $(libcacard-y)) +endif # CONFIG_BSD_USER endif # CONFIG_LINUX_USER obj-y += $(addprefix ../, $(trace-obj-y)) @@ -71,23 +71,23 @@ SECTIONS .data1 : { *(.data1) } .preinit_array : { - PROVIDE_HIDDEN (__preinit_array_start = .); + PROVIDE (__preinit_array_start = .); KEEP (*(.preinit_array)) - PROVIDE_HIDDEN (__preinit_array_end = .); + PROVIDE (__preinit_array_end = .); } .init_array : { - PROVIDE_HIDDEN (__init_array_start = .); + PROVIDE (__init_array_start = .); KEEP (*(SORT(.init_array.*))) KEEP (*(.init_array)) - PROVIDE_HIDDEN (__init_array_end = .); + PROVIDE (__init_array_end = .); } .fini_array : { - PROVIDE_HIDDEN (__fini_array_start = .); + PROVIDE (__fini_array_start = .); KEEP (*(.fini_array)) KEEP (*(SORT(.fini_array.*))) - PROVIDE_HIDDEN (__fini_array_end = .); + PROVIDE (__fini_array_end = .); } .ctors : { @@ -408,7 +408,7 @@ fail: int64_t strtosz_suffix(const char *nptr, char **end, const char default_suffix) { - return strtosz_suffix_unit(nptr, end, default_suffix, 1024); + return strtosz_suffix_unit(nptr, end, default_suffix, 1024); } int64_t strtosz(const char *nptr, char **end) @@ -137,7 +137,7 @@ print_insn_thumb1(bfd_vma pc, disassemble_info *info) /* Disassemble this for me please... (debugging). 'flags' has the following values: - i386 - nonzero means 16 bit code + i386 - 1 means 16 bit code, 2 means 64 bit code arm - nonzero means thumb code ppc - nonzero means little endian other targets - unused diff --git a/dyngen-exec.h b/dyngen-exec.h index cc1e4fb09d..8beb7f3344 100644 --- a/dyngen-exec.h +++ b/dyngen-exec.h @@ -19,15 +19,6 @@ #if !defined(__DYNGEN_EXEC_H__) #define __DYNGEN_EXEC_H__ -#include "qemu-common.h" - -#ifdef __OpenBSD__ -#include <sys/types.h> -#endif - -/* XXX: This may be wrong for 64-bit ILP32 hosts. */ -typedef void * host_reg_t; - #if defined(__i386__) #define AREG0 "ebp" #elif defined(__x86_64__) @@ -66,11 +57,6 @@ typedef void * host_reg_t; register CPUState *env asm(AREG0); -#define xglue(x, y) x ## y -#define glue(x, y) xglue(x, y) -#define stringify(s) tostring(s) -#define tostring(s) #s - /* The return address may point to the start of the next instruction. Subtracting one gets us the call instruction itself. */ #if defined(__s390__) && !defined(__s390x__) diff --git a/fsdev/file-op-9p.h b/fsdev/file-op-9p.h index af9daf797f..1eda342f69 100644 --- a/fsdev/file-op-9p.h +++ b/fsdev/file-op-9p.h @@ -78,7 +78,7 @@ typedef struct FileOperations int (*open2)(FsContext *, const char *, int, FsCred *); void (*rewinddir)(FsContext *, DIR *); off_t (*telldir)(FsContext *, DIR *); - struct dirent *(*readdir)(FsContext *, DIR *); + int (*readdir_r)(FsContext *, DIR *, struct dirent *, struct dirent **); void (*seekdir)(FsContext *, DIR *, off_t); ssize_t (*preadv)(FsContext *, int, const struct iovec *, int, off_t); ssize_t (*pwritev)(FsContext *, int, const struct iovec *, int, off_t); @@ -75,36 +75,34 @@ SECTIONS .sbss2 : { *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) } .PARISC.unwind : { *(.PARISC.unwind) } .eh_frame_hdr : { *(.eh_frame_hdr) } - .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) } - .gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) } /* Adjust the address for the data segment. We want to adjust up to the same address within the page on the next page up. */ . = ALIGN(0x10000) + (. & (0x10000 - 1)); /* Exception handling */ - .eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) } - .gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) } + .eh_frame : { KEEP (*(.eh_frame)) } + .gcc_except_table : { *(.gcc_except_table .gcc_except_table.*) } /* Thread Local Storage sections */ .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) } .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } .preinit_array : { - PROVIDE_HIDDEN (__preinit_array_start = .); + PROVIDE (__preinit_array_start = .); KEEP (*(.preinit_array)) - PROVIDE_HIDDEN (__preinit_array_end = .); + PROVIDE (__preinit_array_end = .); } .init_array : { - PROVIDE_HIDDEN (__init_array_start = .); + PROVIDE (__init_array_start = .); KEEP (*(SORT(.init_array.*))) KEEP (*(.init_array)) - PROVIDE_HIDDEN (__init_array_end = .); + PROVIDE (__init_array_end = .); } .fini_array : { - PROVIDE_HIDDEN (__fini_array_start = .); + PROVIDE (__fini_array_start = .); KEEP (*(.fini_array)) KEEP (*(SORT(.fini_array.*))) - PROVIDE_HIDDEN (__fini_array_end = .); + PROVIDE (__fini_array_end = .); } .ctors : { diff --git a/hw/9pfs/codir.c b/hw/9pfs/codir.c index 28f2ad7320..3a257b9027 100644 --- a/hw/9pfs/codir.c +++ b/hw/9pfs/codir.c @@ -17,16 +17,16 @@ #include "qemu-coroutine.h" #include "virtio-9p-coth.h" -int v9fs_co_readdir(V9fsState *s, V9fsFidState *fidp, struct dirent **dent) +int v9fs_co_readdir_r(V9fsState *s, V9fsFidState *fidp, struct dirent *dent, + struct dirent **result) { int err; v9fs_co_run_in_worker( { errno = 0; - /*FIXME!! need to switch to readdir_r */ - *dent = s->ops->readdir(&s->ctx, fidp->fs.dir); - if (!*dent && errno) { + err = s->ops->readdir_r(&s->ctx, fidp->fs.dir, dent, result); + if (!*result && errno) { err = -errno; } else { err = 0; @@ -83,3 +83,35 @@ int v9fs_co_mkdir(V9fsState *s, char *name, mode_t mode, uid_t uid, gid_t gid) }); return err; } + +int v9fs_co_opendir(V9fsState *s, V9fsFidState *fidp) +{ + int err; + + v9fs_co_run_in_worker( + { + fidp->fs.dir = s->ops->opendir(&s->ctx, fidp->path.data); + if (!fidp->fs.dir) { + err = -errno; + } else { + err = 0; + } + }); + return err; +} + +int v9fs_co_closedir(V9fsState *s, V9fsFidState *fidp) +{ + int err; + DIR *dir; + + dir = fidp->fs.dir; + v9fs_co_run_in_worker( + { + err = s->ops->closedir(&s->ctx, dir); + if (err < 0) { + err = -errno; + } + }); + return err; +} diff --git a/hw/9pfs/cofile.c b/hw/9pfs/cofile.c index a4c0ae75cc..e388146422 100644 --- a/hw/9pfs/cofile.c +++ b/hw/9pfs/cofile.c @@ -30,3 +30,134 @@ int v9fs_co_lstat(V9fsState *s, V9fsString *path, struct stat *stbuf) }); return err; } + +int v9fs_co_fstat(V9fsState *s, int fd, struct stat *stbuf) +{ + int err; + + v9fs_co_run_in_worker( + { + err = s->ops->fstat(&s->ctx, fd, stbuf); + if (err < 0) { + err = -errno; + } + }); + return err; +} + +int v9fs_co_open(V9fsState *s, V9fsFidState *fidp, int flags) +{ + int err; + + v9fs_co_run_in_worker( + { + fidp->fs.fd = s->ops->open(&s->ctx, fidp->path.data, flags); + if (fidp->fs.fd == -1) { + err = -errno; + } else { + err = 0; + } + }); + return err; +} + +int v9fs_co_open2(V9fsState *s, V9fsFidState *fidp, char *fullname, gid_t gid, + int flags, int mode) +{ + int err; + FsCred cred; + + cred_init(&cred); + cred.fc_mode = mode & 07777; + cred.fc_uid = fidp->uid; + cred.fc_gid = gid; + v9fs_co_run_in_worker( + { + fidp->fs.fd = s->ops->open2(&s->ctx, fullname, flags, &cred); + err = 0; + if (fidp->fs.fd == -1) { + err = -errno; + } + }); + return err; +} + +int v9fs_co_close(V9fsState *s, V9fsFidState *fidp) +{ + int fd; + int err; + + fd = fidp->fs.fd; + v9fs_co_run_in_worker( + { + err = s->ops->close(&s->ctx, fd); + if (err < 0) { + err = -errno; + } + }); + return err; +} + +int v9fs_co_fsync(V9fsState *s, V9fsFidState *fidp, int datasync) +{ + int fd; + int err; + + fd = fidp->fs.fd; + v9fs_co_run_in_worker( + { + err = s->ops->fsync(&s->ctx, fd, datasync); + if (err < 0) { + err = -errno; + } + }); + return err; +} + +int v9fs_co_link(V9fsState *s, V9fsString *oldpath, V9fsString *newpath) +{ + int err; + + v9fs_co_run_in_worker( + { + err = s->ops->link(&s->ctx, oldpath->data, newpath->data); + if (err < 0) { + err = -errno; + } + }); + return err; +} + +int v9fs_co_pwritev(V9fsState *s, V9fsFidState *fidp, + struct iovec *iov, int iovcnt, int64_t offset) +{ + int fd; + int err; + + fd = fidp->fs.fd; + v9fs_co_run_in_worker( + { + err = s->ops->pwritev(&s->ctx, fd, iov, iovcnt, offset); + if (err < 0) { + err = -errno; + } + }); + return err; +} + +int v9fs_co_preadv(V9fsState *s, V9fsFidState *fidp, + struct iovec *iov, int iovcnt, int64_t offset) +{ + int fd; + int err; + + fd = fidp->fs.fd; + v9fs_co_run_in_worker( + { + err = s->ops->preadv(&s->ctx, fd, iov, iovcnt, offset); + if (err < 0) { + err = -errno; + } + }); + return err; +} diff --git a/hw/9pfs/cofs.c b/hw/9pfs/cofs.c index 1f10632540..a78fccbe23 100644 --- a/hw/9pfs/cofs.c +++ b/hw/9pfs/cofs.c @@ -169,3 +169,23 @@ int v9fs_co_rename(V9fsState *s, V9fsString *oldpath, V9fsString *newpath) }); return err; } + +int v9fs_co_symlink(V9fsState *s, V9fsFidState *fidp, + const char *oldpath, const char *newpath, gid_t gid) +{ + int err; + FsCred cred; + + cred_init(&cred); + cred.fc_uid = fidp->uid; + cred.fc_gid = gid; + cred.fc_mode = 0777; + v9fs_co_run_in_worker( + { + err = s->ops->symlink(&s->ctx, oldpath, newpath, &cred); + if (err < 0) { + err = -errno; + } + }); + return err; +} diff --git a/hw/9pfs/coxattr.c b/hw/9pfs/coxattr.c index 2fba2c98c2..a289389e49 100644 --- a/hw/9pfs/coxattr.c +++ b/hw/9pfs/coxattr.c @@ -48,3 +48,37 @@ int v9fs_co_lgetxattr(V9fsState *s, V9fsString *path, }); return err; } + +int v9fs_co_lsetxattr(V9fsState *s, V9fsString *path, + V9fsString *xattr_name, void *value, + size_t size, int flags) +{ + int err; + + v9fs_co_run_in_worker( + { + err = s->ops->lsetxattr(&s->ctx, path->data, + xattr_name->data, value, + size, flags); + if (err < 0) { + err = -errno; + } + }); + return err; +} + +int v9fs_co_lremovexattr(V9fsState *s, V9fsString *path, + V9fsString *xattr_name) +{ + int err; + + v9fs_co_run_in_worker( + { + err = s->ops->lremovexattr(&s->ctx, path->data, + xattr_name->data); + if (err < 0) { + err = -errno; + } + }); + return err; +} diff --git a/hw/9pfs/virtio-9p-coth.h b/hw/9pfs/virtio-9p-coth.h index 11272d3357..48defb72ff 100644 --- a/hw/9pfs/virtio-9p-coth.h +++ b/hw/9pfs/virtio-9p-coth.h @@ -57,8 +57,8 @@ typedef struct V9fsThPool { extern void co_run_in_worker_bh(void *); extern int v9fs_init_worker_threads(void); extern int v9fs_co_readlink(V9fsState *, V9fsString *, V9fsString *); -extern int v9fs_co_readdir(V9fsState *, V9fsFidState *, - struct dirent **); +extern int v9fs_co_readdir_r(V9fsState *, V9fsFidState *, + struct dirent *, struct dirent **result); extern off_t v9fs_co_telldir(V9fsState *, V9fsFidState *); extern void v9fs_co_seekdir(V9fsState *, V9fsFidState *, off_t); extern void v9fs_co_rewinddir(V9fsState *, V9fsFidState *); @@ -76,4 +76,21 @@ extern int v9fs_co_mknod(V9fsState *, V9fsString *, uid_t, extern int v9fs_co_mkdir(V9fsState *, char *, mode_t, uid_t, gid_t); extern int v9fs_co_remove(V9fsState *, V9fsString *); extern int v9fs_co_rename(V9fsState *, V9fsString *, V9fsString *); +extern int v9fs_co_fstat(V9fsState *, int, struct stat *); +extern int v9fs_co_opendir(V9fsState *, V9fsFidState *); +extern int v9fs_co_open(V9fsState *, V9fsFidState *, int); +extern int v9fs_co_open2(V9fsState *, V9fsFidState *, char *, gid_t, int, int); +extern int v9fs_co_lsetxattr(V9fsState *, V9fsString *, V9fsString *, + void *, size_t, int); +extern int v9fs_co_lremovexattr(V9fsState *, V9fsString *, V9fsString *); +extern int v9fs_co_closedir(V9fsState *, V9fsFidState *); +extern int v9fs_co_close(V9fsState *, V9fsFidState *); +extern int v9fs_co_fsync(V9fsState *, V9fsFidState *, int); +extern int v9fs_co_symlink(V9fsState *, V9fsFidState *, const char *, + const char *, gid_t); +extern int v9fs_co_link(V9fsState *, V9fsString *, V9fsString *); +extern int v9fs_co_pwritev(V9fsState *, V9fsFidState *, + struct iovec *, int, int64_t); +extern int v9fs_co_preadv(V9fsState *, V9fsFidState *, + struct iovec *, int, int64_t); #endif diff --git a/hw/9pfs/virtio-9p-local.c b/hw/9pfs/virtio-9p-local.c index 77904c37bd..61cbf8db14 100644 --- a/hw/9pfs/virtio-9p-local.c +++ b/hw/9pfs/virtio-9p-local.c @@ -165,9 +165,10 @@ static off_t local_telldir(FsContext *ctx, DIR *dir) return telldir(dir); } -static struct dirent *local_readdir(FsContext *ctx, DIR *dir) +static int local_readdir_r(FsContext *ctx, DIR *dir, struct dirent *entry, + struct dirent **result) { - return readdir(dir); + return readdir_r(dir, entry, result); } static void local_seekdir(FsContext *ctx, DIR *dir, off_t off) @@ -532,7 +533,7 @@ FileOperations local_ops = { .opendir = local_opendir, .rewinddir = local_rewinddir, .telldir = local_telldir, - .readdir = local_readdir, + .readdir_r = local_readdir_r, .seekdir = local_seekdir, .preadv = local_preadv, .pwritev = local_pwritev, diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c index eb33636565..ad70768dce 100644 --- a/hw/9pfs/virtio-9p.c +++ b/hw/9pfs/virtio-9p.c @@ -77,160 +77,6 @@ void cred_init(FsCred *credp) credp->fc_rdev = -1; } -static int v9fs_do_lstat(V9fsState *s, V9fsString *path, struct stat *stbuf) -{ - return s->ops->lstat(&s->ctx, path->data, stbuf); -} - -static int v9fs_do_close(V9fsState *s, int fd) -{ - return s->ops->close(&s->ctx, fd); -} - -static int v9fs_do_closedir(V9fsState *s, DIR *dir) -{ - return s->ops->closedir(&s->ctx, dir); -} - -static int v9fs_do_open(V9fsState *s, V9fsString *path, int flags) -{ - return s->ops->open(&s->ctx, path->data, flags); -} - -static DIR *v9fs_do_opendir(V9fsState *s, V9fsString *path) -{ - return s->ops->opendir(&s->ctx, path->data); -} - -static void v9fs_do_rewinddir(V9fsState *s, DIR *dir) -{ - return s->ops->rewinddir(&s->ctx, dir); -} - -static off_t v9fs_do_telldir(V9fsState *s, DIR *dir) -{ - return s->ops->telldir(&s->ctx, dir); -} - -static void v9fs_do_seekdir(V9fsState *s, DIR *dir, off_t off) -{ - return s->ops->seekdir(&s->ctx, dir, off); -} - -static int v9fs_do_preadv(V9fsState *s, int fd, const struct iovec *iov, - int iovcnt, int64_t offset) -{ - return s->ops->preadv(&s->ctx, fd, iov, iovcnt, offset); -} - -static int v9fs_do_pwritev(V9fsState *s, int fd, const struct iovec *iov, - int iovcnt, int64_t offset) -{ - return s->ops->pwritev(&s->ctx, fd, iov, iovcnt, offset); -} - -static int v9fs_do_chmod(V9fsState *s, V9fsString *path, mode_t mode) -{ - FsCred cred; - cred_init(&cred); - cred.fc_mode = mode; - return s->ops->chmod(&s->ctx, path->data, &cred); -} - -static int v9fs_do_mknod(V9fsState *s, char *name, - mode_t mode, dev_t dev, uid_t uid, gid_t gid) -{ - FsCred cred; - cred_init(&cred); - cred.fc_uid = uid; - cred.fc_gid = gid; - cred.fc_mode = mode; - cred.fc_rdev = dev; - return s->ops->mknod(&s->ctx, name, &cred); -} - -static int v9fs_do_fstat(V9fsState *s, int fd, struct stat *stbuf) -{ - return s->ops->fstat(&s->ctx, fd, stbuf); -} - -static int v9fs_do_open2(V9fsState *s, char *fullname, uid_t uid, gid_t gid, - int flags, int mode) -{ - FsCred cred; - - cred_init(&cred); - cred.fc_uid = uid; - cred.fc_gid = gid; - cred.fc_mode = mode & 07777; - - return s->ops->open2(&s->ctx, fullname, flags, &cred); -} - -static int v9fs_do_symlink(V9fsState *s, V9fsFidState *fidp, - const char *oldpath, const char *newpath, gid_t gid) -{ - FsCred cred; - cred_init(&cred); - cred.fc_uid = fidp->uid; - cred.fc_gid = gid; - cred.fc_mode = 0777; - - return s->ops->symlink(&s->ctx, oldpath, newpath, &cred); -} - -static int v9fs_do_link(V9fsState *s, V9fsString *oldpath, V9fsString *newpath) -{ - return s->ops->link(&s->ctx, oldpath->data, newpath->data); -} - -static int v9fs_do_truncate(V9fsState *s, V9fsString *path, off_t size) -{ - return s->ops->truncate(&s->ctx, path->data, size); -} - -static int v9fs_do_chown(V9fsState *s, V9fsString *path, uid_t uid, gid_t gid) -{ - FsCred cred; - cred_init(&cred); - cred.fc_uid = uid; - cred.fc_gid = gid; - - return s->ops->chown(&s->ctx, path->data, &cred); -} - -static int v9fs_do_utimensat(V9fsState *s, V9fsString *path, - const struct timespec times[2]) -{ - return s->ops->utimensat(&s->ctx, path->data, times); -} - -static int v9fs_do_fsync(V9fsState *s, int fd, int datasync) -{ - return s->ops->fsync(&s->ctx, fd, datasync); -} - -static int v9fs_do_statfs(V9fsState *s, V9fsString *path, struct statfs *stbuf) -{ - return s->ops->statfs(&s->ctx, path->data, stbuf); -} - -static int v9fs_do_lsetxattr(V9fsState *s, V9fsString *path, - V9fsString *xattr_name, - void *value, size_t size, int flags) -{ - return s->ops->lsetxattr(&s->ctx, path->data, - xattr_name->data, value, size, flags); -} - -static int v9fs_do_lremovexattr(V9fsState *s, V9fsString *path, - V9fsString *xattr_name) -{ - return s->ops->lremovexattr(&s->ctx, path->data, - xattr_name->data); -} - - static void v9fs_string_init(V9fsString *str) { str->data = NULL; @@ -437,12 +283,12 @@ static int v9fs_xattr_fid_clunk(V9fsState *s, V9fsFidState *fidp) goto free_out; } if (fidp->fs.xattr.len) { - retval = v9fs_do_lsetxattr(s, &fidp->path, &fidp->fs.xattr.name, + retval = v9fs_co_lsetxattr(s, &fidp->path, &fidp->fs.xattr.name, fidp->fs.xattr.value, fidp->fs.xattr.len, fidp->fs.xattr.flags); } else { - retval = v9fs_do_lremovexattr(s, &fidp->path, &fidp->fs.xattr.name); + retval = v9fs_co_lremovexattr(s, &fidp->path, &fidp->fs.xattr.name); } free_out: v9fs_string_free(&fidp->fs.xattr.name); @@ -472,15 +318,14 @@ static int free_fid(V9fsState *s, int32_t fid) *fidpp = fidp->next; if (fidp->fid_type == P9_FID_FILE) { - v9fs_do_close(s, fidp->fs.fd); + retval = v9fs_co_close(s, fidp); } else if (fidp->fid_type == P9_FID_DIR) { - v9fs_do_closedir(s, fidp->fs.dir); + retval = v9fs_co_closedir(s, fidp); } else if (fidp->fid_type == P9_FID_XATTR) { retval = v9fs_xattr_fid_clunk(s, fidp); } v9fs_string_free(&fidp->path); g_free(fidp); - return retval; } @@ -531,11 +376,10 @@ static int fid_to_qid(V9fsState *s, V9fsFidState *fidp, V9fsQID *qidp) struct stat stbuf; int err; - err = v9fs_do_lstat(s, &fidp->path, &stbuf); - if (err) { + err = v9fs_co_lstat(s, &fidp->path, &stbuf); + if (err < 0) { return err; } - stat_to_qid(&stbuf, qidp); return 0; } @@ -1161,8 +1005,8 @@ static void v9fs_attach(void *opaque) int32_t fid, afid, n_uname; V9fsString uname, aname; V9fsFidState *fidp; - V9fsQID qid; size_t offset = 7; + V9fsQID qid; ssize_t err; pdu_unmarshal(pdu, offset, "ddssd", &fid, &afid, &uname, &aname, &n_uname); @@ -1172,19 +1016,15 @@ static void v9fs_attach(void *opaque) err = -EINVAL; goto out; } - fidp->uid = n_uname; - v9fs_string_sprintf(&fidp->path, "%s", "/"); err = fid_to_qid(s, fidp, &qid); - if (err) { + if (err < 0) { err = -EINVAL; free_fid(s, fid); goto out; } - offset += pdu_marshal(pdu, offset, "Q", &qid); - err = offset; out: complete_pdu(s, pdu, err); @@ -1192,56 +1032,36 @@ out: v9fs_string_free(&aname); } -static void v9fs_stat_post_lstat(V9fsState *s, V9fsStatState *vs, int err) -{ - if (err == -1) { - err = -errno; - goto out; - } - - err = stat_to_v9stat(s, &vs->fidp->path, &vs->stbuf, &vs->v9stat); - if (err) { - goto out; - } - vs->offset += pdu_marshal(vs->pdu, vs->offset, "wS", 0, &vs->v9stat); - err = vs->offset; - -out: - complete_pdu(s, vs->pdu, err); - v9fs_stat_free(&vs->v9stat); - g_free(vs); -} - static void v9fs_stat(void *opaque) { - V9fsPDU *pdu = opaque; - V9fsState *s = pdu->s; int32_t fid; - V9fsStatState *vs; + V9fsStat v9stat; ssize_t err = 0; + size_t offset = 7; + struct stat stbuf; + V9fsFidState *fidp; + V9fsPDU *pdu = opaque; + V9fsState *s = pdu->s; - vs = g_malloc(sizeof(*vs)); - vs->pdu = pdu; - vs->offset = 7; - - memset(&vs->v9stat, 0, sizeof(vs->v9stat)); - - pdu_unmarshal(vs->pdu, vs->offset, "d", &fid); - - vs->fidp = lookup_fid(s, fid); - if (vs->fidp == NULL) { + pdu_unmarshal(pdu, offset, "d", &fid); + fidp = lookup_fid(s, fid); + if (fidp == NULL) { err = -ENOENT; goto out; } - - err = v9fs_do_lstat(s, &vs->fidp->path, &vs->stbuf); - v9fs_stat_post_lstat(s, vs, err); - return; - + err = v9fs_co_lstat(s, &fidp->path, &stbuf); + if (err < 0) { + goto out; + } + err = stat_to_v9stat(s, &fidp->path, &stbuf, &v9stat); + if (err < 0) { + goto out; + } + offset += pdu_marshal(pdu, offset, "wS", 0, &v9stat); + err = offset; + v9fs_stat_free(&v9stat); out: - complete_pdu(s, vs->pdu, err); - v9fs_stat_free(&vs->v9stat); - g_free(vs); + complete_pdu(s, pdu, err); } static void v9fs_getattr(void *opaque) @@ -1370,171 +1190,101 @@ out: complete_pdu(s, pdu, err); } -static void v9fs_walk_complete(V9fsState *s, V9fsWalkState *vs, int err) -{ - complete_pdu(s, vs->pdu, err); - - if (vs->nwnames && vs->nwnames <= P9_MAXWELEM) { - for (vs->name_idx = 0; vs->name_idx < vs->nwnames; vs->name_idx++) { - v9fs_string_free(&vs->wnames[vs->name_idx]); - } - - g_free(vs->wnames); - g_free(vs->qids); - } -} - -static void v9fs_walk_marshal(V9fsWalkState *vs) +static int v9fs_walk_marshal(V9fsPDU *pdu, uint16_t nwnames, V9fsQID *qids) { int i; - vs->offset = 7; - vs->offset += pdu_marshal(vs->pdu, vs->offset, "w", vs->nwnames); - - for (i = 0; i < vs->nwnames; i++) { - vs->offset += pdu_marshal(vs->pdu, vs->offset, "Q", &vs->qids[i]); + size_t offset = 7; + offset += pdu_marshal(pdu, offset, "w", nwnames); + for (i = 0; i < nwnames; i++) { + offset += pdu_marshal(pdu, offset, "Q", &qids[i]); } -} - -static void v9fs_walk_post_newfid_lstat(V9fsState *s, V9fsWalkState *vs, - int err) -{ - if (err == -1) { - free_fid(s, vs->newfidp->fid); - v9fs_string_free(&vs->path); - err = -ENOENT; - goto out; - } - - stat_to_qid(&vs->stbuf, &vs->qids[vs->name_idx]); - - vs->name_idx++; - if (vs->name_idx < vs->nwnames) { - v9fs_string_sprintf(&vs->path, "%s/%s", vs->newfidp->path.data, - vs->wnames[vs->name_idx].data); - v9fs_string_copy(&vs->newfidp->path, &vs->path); - - err = v9fs_do_lstat(s, &vs->newfidp->path, &vs->stbuf); - v9fs_walk_post_newfid_lstat(s, vs, err); - return; - } - - v9fs_string_free(&vs->path); - v9fs_walk_marshal(vs); - err = vs->offset; -out: - v9fs_walk_complete(s, vs, err); -} - -static void v9fs_walk_post_oldfid_lstat(V9fsState *s, V9fsWalkState *vs, - int err) -{ - if (err == -1) { - v9fs_string_free(&vs->path); - err = -ENOENT; - goto out; - } - - stat_to_qid(&vs->stbuf, &vs->qids[vs->name_idx]); - vs->name_idx++; - if (vs->name_idx < vs->nwnames) { - - v9fs_string_sprintf(&vs->path, "%s/%s", - vs->fidp->path.data, vs->wnames[vs->name_idx].data); - v9fs_string_copy(&vs->fidp->path, &vs->path); - - err = v9fs_do_lstat(s, &vs->fidp->path, &vs->stbuf); - v9fs_walk_post_oldfid_lstat(s, vs, err); - return; - } - - v9fs_string_free(&vs->path); - v9fs_walk_marshal(vs); - err = vs->offset; -out: - v9fs_walk_complete(s, vs, err); + return offset; } static void v9fs_walk(void *opaque) { + int name_idx; + V9fsQID *qids = NULL; + int i, err = 0; + V9fsString path; + uint16_t nwnames; + struct stat stbuf; + size_t offset = 7; + int32_t fid, newfid; + V9fsString *wnames = NULL; + V9fsFidState *fidp; + V9fsFidState *newfidp; V9fsPDU *pdu = opaque; V9fsState *s = pdu->s; - int32_t fid, newfid; - V9fsWalkState *vs; - int err = 0; - int i; - - vs = g_malloc(sizeof(*vs)); - vs->pdu = pdu; - vs->wnames = NULL; - vs->qids = NULL; - vs->offset = 7; - vs->offset += pdu_unmarshal(vs->pdu, vs->offset, "ddw", &fid, - &newfid, &vs->nwnames); + offset += pdu_unmarshal(pdu, offset, "ddw", &fid, + &newfid, &nwnames); - if (vs->nwnames && vs->nwnames <= P9_MAXWELEM) { - vs->wnames = g_malloc0(sizeof(vs->wnames[0]) * vs->nwnames); - - vs->qids = g_malloc0(sizeof(vs->qids[0]) * vs->nwnames); - - for (i = 0; i < vs->nwnames; i++) { - vs->offset += pdu_unmarshal(vs->pdu, vs->offset, "s", - &vs->wnames[i]); + if (nwnames && nwnames <= P9_MAXWELEM) { + wnames = g_malloc0(sizeof(wnames[0]) * nwnames); + qids = g_malloc0(sizeof(qids[0]) * nwnames); + for (i = 0; i < nwnames; i++) { + offset += pdu_unmarshal(pdu, offset, "s", &wnames[i]); } - } else if (vs->nwnames > P9_MAXWELEM) { + + } else if (nwnames > P9_MAXWELEM) { err = -EINVAL; goto out; } - - vs->fidp = lookup_fid(s, fid); - if (vs->fidp == NULL) { + fidp = lookup_fid(s, fid); + if (fidp == NULL) { err = -ENOENT; goto out; } - - /* FIXME: is this really valid? */ if (fid == newfid) { - - BUG_ON(vs->fidp->fid_type != P9_FID_NONE); - v9fs_string_init(&vs->path); - vs->name_idx = 0; - - if (vs->name_idx < vs->nwnames) { - v9fs_string_sprintf(&vs->path, "%s/%s", - vs->fidp->path.data, vs->wnames[vs->name_idx].data); - v9fs_string_copy(&vs->fidp->path, &vs->path); - - err = v9fs_do_lstat(s, &vs->fidp->path, &vs->stbuf); - v9fs_walk_post_oldfid_lstat(s, vs, err); - return; + BUG_ON(fidp->fid_type != P9_FID_NONE); + v9fs_string_init(&path); + for (name_idx = 0; name_idx < nwnames; name_idx++) { + v9fs_string_sprintf(&path, "%s/%s", + fidp->path.data, wnames[name_idx].data); + v9fs_string_copy(&fidp->path, &path); + + err = v9fs_co_lstat(s, &fidp->path, &stbuf); + if (err < 0) { + v9fs_string_free(&path); + goto out; + } + stat_to_qid(&stbuf, &qids[name_idx]); } + v9fs_string_free(&path); } else { - vs->newfidp = alloc_fid(s, newfid); - if (vs->newfidp == NULL) { + newfidp = alloc_fid(s, newfid); + if (newfidp == NULL) { err = -EINVAL; goto out; } - - vs->newfidp->uid = vs->fidp->uid; - v9fs_string_init(&vs->path); - vs->name_idx = 0; - v9fs_string_copy(&vs->newfidp->path, &vs->fidp->path); - - if (vs->name_idx < vs->nwnames) { - v9fs_string_sprintf(&vs->path, "%s/%s", vs->newfidp->path.data, - vs->wnames[vs->name_idx].data); - v9fs_string_copy(&vs->newfidp->path, &vs->path); - - err = v9fs_do_lstat(s, &vs->newfidp->path, &vs->stbuf); - v9fs_walk_post_newfid_lstat(s, vs, err); - return; + newfidp->uid = fidp->uid; + v9fs_string_init(&path); + v9fs_string_copy(&newfidp->path, &fidp->path); + for (name_idx = 0; name_idx < nwnames; name_idx++) { + v9fs_string_sprintf(&path, "%s/%s", newfidp->path.data, + wnames[name_idx].data); + v9fs_string_copy(&newfidp->path, &path); + err = v9fs_co_lstat(s, &newfidp->path, &stbuf); + if (err < 0) { + free_fid(s, newfidp->fid); + v9fs_string_free(&path); + goto out; + } + stat_to_qid(&stbuf, &qids[name_idx]); } + v9fs_string_free(&path); } - - v9fs_walk_marshal(vs); - err = vs->offset; + err = v9fs_walk_marshal(pdu, nwnames, qids); out: - v9fs_walk_complete(s, vs, err); + complete_pdu(s, pdu, err); + if (nwnames && nwnames <= P9_MAXWELEM) { + for (name_idx = 0; name_idx < nwnames; name_idx++) { + v9fs_string_free(&wnames[name_idx]); + } + g_free(wnames); + g_free(qids); + } } static int32_t get_iounit(V9fsState *s, V9fsString *name) @@ -1546,467 +1296,323 @@ static int32_t get_iounit(V9fsState *s, V9fsString *name) * iounit should be multiples of f_bsize (host filesystem block size * and as well as less than (client msize - P9_IOHDRSZ)) */ - if (!v9fs_do_statfs(s, name, &stbuf)) { + if (!v9fs_co_statfs(s, name, &stbuf)) { iounit = stbuf.f_bsize; iounit *= (s->msize - P9_IOHDRSZ)/stbuf.f_bsize; } - if (!iounit) { iounit = s->msize - P9_IOHDRSZ; } return iounit; } -static void v9fs_open_post_opendir(V9fsState *s, V9fsOpenState *vs, int err) -{ - if (vs->fidp->fs.dir == NULL) { - err = -errno; - goto out; - } - vs->fidp->fid_type = P9_FID_DIR; - vs->offset += pdu_marshal(vs->pdu, vs->offset, "Qd", &vs->qid, 0); - err = vs->offset; -out: - complete_pdu(s, vs->pdu, err); - g_free(vs); - -} - -static void v9fs_open_post_getiounit(V9fsState *s, V9fsOpenState *vs) +static void v9fs_open(void *opaque) { - int err; - vs->offset += pdu_marshal(vs->pdu, vs->offset, "Qd", &vs->qid, vs->iounit); - err = vs->offset; - complete_pdu(s, vs->pdu, err); - g_free(vs); -} + int flags; + int iounit; + int32_t fid; + int32_t mode; + V9fsQID qid; + ssize_t err = 0; + size_t offset = 7; + struct stat stbuf; + V9fsFidState *fidp; + V9fsPDU *pdu = opaque; + V9fsState *s = pdu->s; -static void v9fs_open_post_open(V9fsState *s, V9fsOpenState *vs, int err) -{ - if (vs->fidp->fs.fd == -1) { - err = -errno; + if (s->proto_version == V9FS_PROTO_2000L) { + pdu_unmarshal(pdu, offset, "dd", &fid, &mode); + } else { + pdu_unmarshal(pdu, offset, "db", &fid, &mode); + } + fidp = lookup_fid(s, fid); + if (fidp == NULL) { + err = -ENOENT; goto out; } - vs->fidp->fid_type = P9_FID_FILE; - vs->iounit = get_iounit(s, &vs->fidp->path); - v9fs_open_post_getiounit(s, vs); - return; -out: - complete_pdu(s, vs->pdu, err); - g_free(vs); -} - -static void v9fs_open_post_lstat(V9fsState *s, V9fsOpenState *vs, int err) -{ - int flags; + BUG_ON(fidp->fid_type != P9_FID_NONE); - if (err) { - err = -errno; + err = v9fs_co_lstat(s, &fidp->path, &stbuf); + if (err < 0) { goto out; } - - stat_to_qid(&vs->stbuf, &vs->qid); - - if (S_ISDIR(vs->stbuf.st_mode)) { - vs->fidp->fs.dir = v9fs_do_opendir(s, &vs->fidp->path); - v9fs_open_post_opendir(s, vs, err); + stat_to_qid(&stbuf, &qid); + if (S_ISDIR(stbuf.st_mode)) { + err = v9fs_co_opendir(s, fidp); + if (err < 0) { + goto out; + } + fidp->fid_type = P9_FID_DIR; + offset += pdu_marshal(pdu, offset, "Qd", &qid, 0); + err = offset; } else { if (s->proto_version == V9FS_PROTO_2000L) { - flags = vs->mode; + flags = mode; flags &= ~(O_NOCTTY | O_ASYNC | O_CREAT); /* Ignore direct disk access hint until the server supports it. */ flags &= ~O_DIRECT; } else { - flags = omode_to_uflags(vs->mode); + flags = omode_to_uflags(mode); } - vs->fidp->fs.fd = v9fs_do_open(s, &vs->fidp->path, flags); - v9fs_open_post_open(s, vs, err); - } - return; -out: - complete_pdu(s, vs->pdu, err); - g_free(vs); -} - -static void v9fs_open(void *opaque) -{ - V9fsPDU *pdu = opaque; - V9fsState *s = pdu->s; - int32_t fid; - V9fsOpenState *vs; - ssize_t err = 0; - - vs = g_malloc(sizeof(*vs)); - vs->pdu = pdu; - vs->offset = 7; - vs->mode = 0; - - if (s->proto_version == V9FS_PROTO_2000L) { - pdu_unmarshal(vs->pdu, vs->offset, "dd", &fid, &vs->mode); - } else { - pdu_unmarshal(vs->pdu, vs->offset, "db", &fid, &vs->mode); - } - - vs->fidp = lookup_fid(s, fid); - if (vs->fidp == NULL) { - err = -ENOENT; - goto out; - } - - BUG_ON(vs->fidp->fid_type != P9_FID_NONE); - - err = v9fs_do_lstat(s, &vs->fidp->path, &vs->stbuf); - - v9fs_open_post_lstat(s, vs, err); - return; -out: - complete_pdu(s, pdu, err); - g_free(vs); -} - -static void v9fs_post_lcreate(V9fsState *s, V9fsLcreateState *vs, int err) -{ - if (err == 0) { - v9fs_string_copy(&vs->fidp->path, &vs->fullname); - stat_to_qid(&vs->stbuf, &vs->qid); - vs->offset += pdu_marshal(vs->pdu, vs->offset, "Qd", &vs->qid, - vs->iounit); - err = vs->offset; - } else { - vs->fidp->fid_type = P9_FID_NONE; - err = -errno; - if (vs->fidp->fs.fd > 0) { - close(vs->fidp->fs.fd); + err = v9fs_co_open(s, fidp, flags); + if (err < 0) { + goto out; } + fidp->fid_type = P9_FID_FILE; + iounit = get_iounit(s, &fidp->path); + offset += pdu_marshal(pdu, offset, "Qd", &qid, iounit); + err = offset; } - - complete_pdu(s, vs->pdu, err); - v9fs_string_free(&vs->name); - v9fs_string_free(&vs->fullname); - g_free(vs); -} - -static void v9fs_lcreate_post_get_iounit(V9fsState *s, V9fsLcreateState *vs, - int err) -{ - if (err) { - err = -errno; - goto out; - } - err = v9fs_do_lstat(s, &vs->fullname, &vs->stbuf); - -out: - v9fs_post_lcreate(s, vs, err); -} - -static void v9fs_lcreate_post_do_open2(V9fsState *s, V9fsLcreateState *vs, - int err) -{ - if (vs->fidp->fs.fd == -1) { - err = -errno; - goto out; - } - vs->fidp->fid_type = P9_FID_FILE; - vs->iounit = get_iounit(s, &vs->fullname); - v9fs_lcreate_post_get_iounit(s, vs, err); - return; - out: - v9fs_post_lcreate(s, vs, err); + complete_pdu(s, pdu, err); } static void v9fs_lcreate(void *opaque) { - V9fsPDU *pdu = opaque; - V9fsState *s = pdu->s; int32_t dfid, flags, mode; gid_t gid; - V9fsLcreateState *vs; ssize_t err = 0; + ssize_t offset = 7; + V9fsString fullname; + V9fsString name; + V9fsFidState *fidp; + struct stat stbuf; + V9fsQID qid; + int32_t iounit; + V9fsPDU *pdu = opaque; - vs = g_malloc(sizeof(*vs)); - vs->pdu = pdu; - vs->offset = 7; - - v9fs_string_init(&vs->fullname); - - pdu_unmarshal(vs->pdu, vs->offset, "dsddd", &dfid, &vs->name, &flags, - &mode, &gid); + v9fs_string_init(&fullname); + pdu_unmarshal(pdu, offset, "dsddd", &dfid, &name, &flags, + &mode, &gid); - vs->fidp = lookup_fid(s, dfid); - if (vs->fidp == NULL) { + fidp = lookup_fid(pdu->s, dfid); + if (fidp == NULL) { err = -ENOENT; goto out; } - - v9fs_string_sprintf(&vs->fullname, "%s/%s", vs->fidp->path.data, - vs->name.data); + v9fs_string_sprintf(&fullname, "%s/%s", fidp->path.data, name.data); /* Ignore direct disk access hint until the server supports it. */ flags &= ~O_DIRECT; - vs->fidp->fs.fd = v9fs_do_open2(s, vs->fullname.data, vs->fidp->uid, - gid, flags, mode); - v9fs_lcreate_post_do_open2(s, vs, err); - return; - -out: - complete_pdu(s, vs->pdu, err); - v9fs_string_free(&vs->name); - g_free(vs); -} + err = v9fs_co_open2(pdu->s, fidp, fullname.data, gid, flags, mode); + if (err < 0) { + goto out; + } + fidp->fid_type = P9_FID_FILE; + iounit = get_iounit(pdu->s, &fullname); -static void v9fs_post_do_fsync(V9fsState *s, V9fsPDU *pdu, int err) -{ - if (err == -1) { - err = -errno; + err = v9fs_co_lstat(pdu->s, &fullname, &stbuf); + if (err < 0) { + fidp->fid_type = P9_FID_NONE; + if (fidp->fs.fd > 0) { + close(fidp->fs.fd); + } + goto out; } - complete_pdu(s, pdu, err); + v9fs_string_copy(&fidp->path, &fullname); + stat_to_qid(&stbuf, &qid); + offset += pdu_marshal(pdu, offset, "Qd", &qid, iounit); + err = offset; +out: + complete_pdu(pdu->s, pdu, err); + v9fs_string_free(&name); + v9fs_string_free(&fullname); } static void v9fs_fsync(void *opaque) { - V9fsPDU *pdu = opaque; - V9fsState *s = pdu->s; + int err; int32_t fid; + int datasync; size_t offset = 7; V9fsFidState *fidp; - int datasync; - int err; + V9fsPDU *pdu = opaque; + V9fsState *s = pdu->s; pdu_unmarshal(pdu, offset, "dd", &fid, &datasync); fidp = lookup_fid(s, fid); if (fidp == NULL) { err = -ENOENT; - v9fs_post_do_fsync(s, pdu, err); - return; + goto out; + } + err = v9fs_co_fsync(s, fidp, datasync); + if (!err) { + err = offset; } - err = v9fs_do_fsync(s, fidp->fs.fd, datasync); - v9fs_post_do_fsync(s, pdu, err); +out: + complete_pdu(s, pdu, err); } static void v9fs_clunk(void *opaque) { - V9fsPDU *pdu = opaque; - V9fsState *s = pdu->s; + int err; int32_t fid; size_t offset = 7; - int err; + V9fsPDU *pdu = opaque; + V9fsState *s = pdu->s; pdu_unmarshal(pdu, offset, "d", &fid); - err = free_fid(s, fid); if (err < 0) { goto out; } - - offset = 7; err = offset; out: complete_pdu(s, pdu, err); } -static void v9fs_read_post_readdir(V9fsState *, V9fsReadState *, ssize_t); - -static void v9fs_read_post_seekdir(V9fsState *s, V9fsReadState *vs, ssize_t err) +static int v9fs_xattr_read(V9fsState *s, V9fsPDU *pdu, + V9fsFidState *fidp, int64_t off, int32_t max_count) { - if (err) { - goto out; - } - vs->offset += pdu_marshal(vs->pdu, vs->offset, "d", vs->count); - vs->offset += vs->count; - err = vs->offset; -out: - complete_pdu(s, vs->pdu, err); - v9fs_stat_free(&vs->v9stat); - v9fs_string_free(&vs->name); - g_free(vs); - return; -} + size_t offset = 7; + int read_count; + int64_t xattr_len; -static void v9fs_read_post_dir_lstat(V9fsState *s, V9fsReadState *vs, - ssize_t err) -{ - if (err) { - err = -errno; - goto out; - } - err = stat_to_v9stat(s, &vs->name, &vs->stbuf, &vs->v9stat); - if (err) { - goto out; + xattr_len = fidp->fs.xattr.len; + read_count = xattr_len - off; + if (read_count > max_count) { + read_count = max_count; + } else if (read_count < 0) { + /* + * read beyond XATTR value + */ + read_count = 0; } - - vs->len = pdu_marshal(vs->pdu, vs->offset + 4 + vs->count, "S", - &vs->v9stat); - if ((vs->len != (vs->v9stat.size + 2)) || - ((vs->count + vs->len) > vs->max_count)) { - v9fs_do_seekdir(s, vs->fidp->fs.dir, vs->dir_pos); - v9fs_read_post_seekdir(s, vs, err); - return; - } - vs->count += vs->len; - v9fs_stat_free(&vs->v9stat); - v9fs_string_free(&vs->name); - vs->dir_pos = vs->dent->d_off; - v9fs_co_readdir(s, vs->fidp, &vs->dent); - v9fs_read_post_readdir(s, vs, err); - return; -out: - v9fs_do_seekdir(s, vs->fidp->fs.dir, vs->dir_pos); - v9fs_read_post_seekdir(s, vs, err); - return; - + offset += pdu_marshal(pdu, offset, "d", read_count); + offset += pdu_pack(pdu, offset, + ((char *)fidp->fs.xattr.value) + off, + read_count); + return offset; } -static void v9fs_read_post_readdir(V9fsState *s, V9fsReadState *vs, ssize_t err) +static int v9fs_do_readdir_with_stat(V9fsState *s, V9fsPDU *pdu, + V9fsFidState *fidp, int32_t max_count) { - if (vs->dent) { - memset(&vs->v9stat, 0, sizeof(vs->v9stat)); - v9fs_string_init(&vs->name); - v9fs_string_sprintf(&vs->name, "%s/%s", vs->fidp->path.data, - vs->dent->d_name); - err = v9fs_do_lstat(s, &vs->name, &vs->stbuf); - v9fs_read_post_dir_lstat(s, vs, err); - return; - } - - vs->offset += pdu_marshal(vs->pdu, vs->offset, "d", vs->count); - vs->offset += vs->count; - err = vs->offset; - complete_pdu(s, vs->pdu, err); - g_free(vs); - return; -} + V9fsString name; + V9fsStat v9stat; + int len, err = 0; + int32_t count = 0; + struct stat stbuf; + off_t saved_dir_pos; + struct dirent *dent, *result; -static void v9fs_read_post_telldir(V9fsState *s, V9fsReadState *vs, ssize_t err) -{ - v9fs_co_readdir(s, vs->fidp, &vs->dent); - v9fs_read_post_readdir(s, vs, err); - return; -} + /* save the directory position */ + saved_dir_pos = v9fs_co_telldir(s, fidp); + if (saved_dir_pos < 0) { + return saved_dir_pos; + } -static void v9fs_read_post_rewinddir(V9fsState *s, V9fsReadState *vs, - ssize_t err) -{ - vs->dir_pos = v9fs_do_telldir(s, vs->fidp->fs.dir); - v9fs_read_post_telldir(s, vs, err); - return; -} + dent = g_malloc(sizeof(struct dirent)); -static void v9fs_read_post_preadv(V9fsState *s, V9fsReadState *vs, ssize_t err) -{ - if (err < 0) { - /* IO error return the error */ - err = -errno; - goto out; - } - vs->total += vs->len; - vs->sg = adjust_sg(vs->sg, vs->len, &vs->cnt); - if (vs->total < vs->count && vs->len > 0) { - do { - if (0) { - print_sg(vs->sg, vs->cnt); - } - vs->len = v9fs_do_preadv(s, vs->fidp->fs.fd, vs->sg, vs->cnt, - vs->off); - if (vs->len > 0) { - vs->off += vs->len; - } - } while (vs->len == -1 && errno == EINTR); - if (vs->len == -1) { - err = -errno; + while (1) { + v9fs_string_init(&name); + err = v9fs_co_readdir_r(s, fidp, dent, &result); + if (err || !result) { + break; + } + v9fs_string_sprintf(&name, "%s/%s", fidp->path.data, dent->d_name); + err = v9fs_co_lstat(s, &name, &stbuf); + if (err < 0) { + goto out; } - v9fs_read_post_preadv(s, vs, err); - return; + err = stat_to_v9stat(s, &name, &stbuf, &v9stat); + if (err < 0) { + goto out; + } + /* 11 = 7 + 4 (7 = start offset, 4 = space for storing count) */ + len = pdu_marshal(pdu, 11 + count, "S", &v9stat); + if ((len != (v9stat.size + 2)) || ((count + len) > max_count)) { + /* Ran out of buffer. Set dir back to old position and return */ + v9fs_co_seekdir(s, fidp, saved_dir_pos); + v9fs_stat_free(&v9stat); + v9fs_string_free(&name); + g_free(dent); + return count; + } + count += len; + v9fs_stat_free(&v9stat); + v9fs_string_free(&name); + saved_dir_pos = dent->d_off; } - vs->offset += pdu_marshal(vs->pdu, vs->offset, "d", vs->total); - vs->offset += vs->count; - err = vs->offset; - out: - complete_pdu(s, vs->pdu, err); - g_free(vs); -} - -static void v9fs_xattr_read(V9fsState *s, V9fsReadState *vs) -{ - ssize_t err = 0; - int read_count; - int64_t xattr_len; - - xattr_len = vs->fidp->fs.xattr.len; - read_count = xattr_len - vs->off; - if (read_count > vs->count) { - read_count = vs->count; - } else if (read_count < 0) { - /* - * read beyond XATTR value - */ - read_count = 0; + g_free(dent); + v9fs_string_free(&name); + if (err < 0) { + return err; } - vs->offset += pdu_marshal(vs->pdu, vs->offset, "d", read_count); - vs->offset += pdu_pack(vs->pdu, vs->offset, - ((char *)vs->fidp->fs.xattr.value) + vs->off, - read_count); - err = vs->offset; - complete_pdu(s, vs->pdu, err); - g_free(vs); + return count; } static void v9fs_read(void *opaque) { - V9fsPDU *pdu = opaque; - V9fsState *s = pdu->s; int32_t fid; - V9fsReadState *vs; + int64_t off; ssize_t err = 0; + int32_t count = 0; + size_t offset = 7; + int32_t max_count; + V9fsFidState *fidp; + V9fsPDU *pdu = opaque; + V9fsState *s = pdu->s; - vs = g_malloc(sizeof(*vs)); - vs->pdu = pdu; - vs->offset = 7; - vs->total = 0; - vs->len = 0; - vs->count = 0; - - pdu_unmarshal(vs->pdu, vs->offset, "dqd", &fid, &vs->off, &vs->count); - - vs->fidp = lookup_fid(s, fid); - if (vs->fidp == NULL) { + pdu_unmarshal(pdu, offset, "dqd", &fid, &off, &max_count); + fidp = lookup_fid(s, fid); + if (fidp == NULL) { err = -EINVAL; goto out; } + if (fidp->fid_type == P9_FID_DIR) { - if (vs->fidp->fid_type == P9_FID_DIR) { - vs->max_count = vs->count; - vs->count = 0; - if (vs->off == 0) { - v9fs_do_rewinddir(s, vs->fidp->fs.dir); - } - v9fs_read_post_rewinddir(s, vs, err); - return; - } else if (vs->fidp->fid_type == P9_FID_FILE) { - vs->sg = vs->iov; - pdu_marshal(vs->pdu, vs->offset + 4, "v", vs->sg, &vs->cnt); - vs->sg = cap_sg(vs->sg, vs->count, &vs->cnt); - if (vs->total <= vs->count) { - vs->len = v9fs_do_preadv(s, vs->fidp->fs.fd, vs->sg, vs->cnt, - vs->off); - if (vs->len > 0) { - vs->off += vs->len; - } - err = vs->len; - v9fs_read_post_preadv(s, vs, err); + if (off == 0) { + v9fs_co_rewinddir(s, fidp); } - return; - } else if (vs->fidp->fid_type == P9_FID_XATTR) { - v9fs_xattr_read(s, vs); - return; + count = v9fs_do_readdir_with_stat(s, pdu, fidp, max_count); + if (count < 0) { + err = count; + goto out; + } + err = offset; + err += pdu_marshal(pdu, offset, "d", count); + err += count; + } else if (fidp->fid_type == P9_FID_FILE) { + int32_t cnt; + int32_t len; + struct iovec *sg; + struct iovec iov[128]; /* FIXME: bad, bad, bad */ + + sg = iov; + pdu_marshal(pdu, offset + 4, "v", sg, &cnt); + sg = cap_sg(sg, max_count, &cnt); + do { + if (0) { + print_sg(sg, cnt); + } + /* Loop in case of EINTR */ + do { + len = v9fs_co_preadv(s, fidp, sg, cnt, off); + if (len >= 0) { + off += len; + count += len; + } + } while (len == -EINTR); + if (len < 0) { + /* IO error return the error */ + err = len; + goto out; + } + sg = adjust_sg(sg, len, &cnt); + } while (count < max_count && len > 0); + err = offset; + err += pdu_marshal(pdu, offset, "d", count); + err += count; + } else if (fidp->fid_type == P9_FID_XATTR) { + err = v9fs_xattr_read(s, pdu, fidp, off, max_count); } else { err = -EINVAL; } out: complete_pdu(s, pdu, err); - g_free(vs); } static size_t v9fs_readdir_data_size(V9fsString *name) @@ -2027,16 +1633,19 @@ static int v9fs_do_readdir(V9fsState *s, V9fsPDU *pdu, int len, err = 0; int32_t count = 0; off_t saved_dir_pos; - struct dirent *dent; + struct dirent *dent, *result; /* save the directory position */ saved_dir_pos = v9fs_co_telldir(s, fidp); if (saved_dir_pos < 0) { return saved_dir_pos; } + + dent = g_malloc(sizeof(struct dirent)); + while (1) { - err = v9fs_co_readdir(s, fidp, &dent); - if (err || !dent) { + err = v9fs_co_readdir_r(s, fidp, dent, &result); + if (err || !result) { break; } v9fs_string_init(&name); @@ -2045,6 +1654,7 @@ static int v9fs_do_readdir(V9fsState *s, V9fsPDU *pdu, /* Ran out of buffer. Set dir back to old position and return */ v9fs_co_seekdir(s, fidp, saved_dir_pos); v9fs_string_free(&name); + g_free(dent); return count; } /* @@ -2066,6 +1676,7 @@ static int v9fs_do_readdir(V9fsState *s, V9fsPDU *pdu, v9fs_string_free(&name); saved_dir_pos = dent->d_off; } + g_free(dent); if (err < 0) { return err; } @@ -2107,51 +1718,21 @@ out: complete_pdu(s, pdu, retval); } -static void v9fs_write_post_pwritev(V9fsState *s, V9fsWriteState *vs, - ssize_t err) -{ - if (err < 0) { - /* IO error return the error */ - err = -errno; - goto out; - } - vs->total += vs->len; - vs->sg = adjust_sg(vs->sg, vs->len, &vs->cnt); - if (vs->total < vs->count && vs->len > 0) { - do { - if (0) { - print_sg(vs->sg, vs->cnt); - } - vs->len = v9fs_do_pwritev(s, vs->fidp->fs.fd, vs->sg, vs->cnt, - vs->off); - if (vs->len > 0) { - vs->off += vs->len; - } - } while (vs->len == -1 && errno == EINTR); - if (vs->len == -1) { - err = -errno; - } - v9fs_write_post_pwritev(s, vs, err); - return; - } - vs->offset += pdu_marshal(vs->pdu, vs->offset, "d", vs->total); - err = vs->offset; -out: - complete_pdu(s, vs->pdu, err); - g_free(vs); -} - -static void v9fs_xattr_write(V9fsState *s, V9fsWriteState *vs) +static int v9fs_xattr_write(V9fsState *s, V9fsPDU *pdu, V9fsFidState *fidp, + int64_t off, int32_t count, + struct iovec *sg, int cnt) { int i, to_copy; ssize_t err = 0; int write_count; int64_t xattr_len; + size_t offset = 7; - xattr_len = vs->fidp->fs.xattr.len; - write_count = xattr_len - vs->off; - if (write_count > vs->count) { - write_count = vs->count; + + xattr_len = fidp->fs.xattr.len; + write_count = xattr_len - off; + if (write_count > count) { + write_count = count; } else if (write_count < 0) { /* * write beyond XATTR value len specified in @@ -2160,225 +1741,161 @@ static void v9fs_xattr_write(V9fsState *s, V9fsWriteState *vs) err = -ENOSPC; goto out; } - vs->offset += pdu_marshal(vs->pdu, vs->offset, "d", write_count); - err = vs->offset; - vs->fidp->fs.xattr.copied_len += write_count; + offset += pdu_marshal(pdu, offset, "d", write_count); + err = offset; + fidp->fs.xattr.copied_len += write_count; /* * Now copy the content from sg list */ - for (i = 0; i < vs->cnt; i++) { - if (write_count > vs->sg[i].iov_len) { - to_copy = vs->sg[i].iov_len; + for (i = 0; i < cnt; i++) { + if (write_count > sg[i].iov_len) { + to_copy = sg[i].iov_len; } else { to_copy = write_count; } - memcpy((char *)vs->fidp->fs.xattr.value + vs->off, - vs->sg[i].iov_base, to_copy); + memcpy((char *)fidp->fs.xattr.value + off, sg[i].iov_base, to_copy); /* updating vs->off since we are not using below */ - vs->off += to_copy; + off += to_copy; write_count -= to_copy; } out: - complete_pdu(s, vs->pdu, err); - g_free(vs); + return err; } static void v9fs_write(void *opaque) { + int cnt; + ssize_t err; + int32_t fid; + int64_t off; + int32_t count; + int32_t len = 0; + int32_t total = 0; + size_t offset = 7; + V9fsFidState *fidp; + struct iovec iov[128]; /* FIXME: bad, bad, bad */ + struct iovec *sg = iov; V9fsPDU *pdu = opaque; V9fsState *s = pdu->s; - int32_t fid; - V9fsWriteState *vs; - ssize_t err; - - vs = g_malloc(sizeof(*vs)); - - vs->pdu = pdu; - vs->offset = 7; - vs->sg = vs->iov; - vs->total = 0; - vs->len = 0; - pdu_unmarshal(vs->pdu, vs->offset, "dqdv", &fid, &vs->off, &vs->count, - vs->sg, &vs->cnt); - - vs->fidp = lookup_fid(s, fid); - if (vs->fidp == NULL) { + pdu_unmarshal(pdu, offset, "dqdv", &fid, &off, &count, sg, &cnt); + fidp = lookup_fid(s, fid); + if (fidp == NULL) { err = -EINVAL; goto out; } - - if (vs->fidp->fid_type == P9_FID_FILE) { - if (vs->fidp->fs.fd == -1) { + if (fidp->fid_type == P9_FID_FILE) { + if (fidp->fs.fd == -1) { err = -EINVAL; goto out; } - } else if (vs->fidp->fid_type == P9_FID_XATTR) { + } else if (fidp->fid_type == P9_FID_XATTR) { /* * setxattr operation */ - v9fs_xattr_write(s, vs); - return; + err = v9fs_xattr_write(s, pdu, fidp, off, count, sg, cnt); + goto out; } else { err = -EINVAL; goto out; } - vs->sg = cap_sg(vs->sg, vs->count, &vs->cnt); - if (vs->total <= vs->count) { - vs->len = v9fs_do_pwritev(s, vs->fidp->fs.fd, vs->sg, vs->cnt, vs->off); - if (vs->len > 0) { - vs->off += vs->len; + sg = cap_sg(sg, count, &cnt); + do { + if (0) { + print_sg(sg, cnt); } - err = vs->len; - v9fs_write_post_pwritev(s, vs, err); - } - return; + /* Loop in case of EINTR */ + do { + len = v9fs_co_pwritev(s, fidp, sg, cnt, off); + if (len >= 0) { + off += len; + total += len; + } + } while (len == -EINTR); + if (len < 0) { + /* IO error return the error */ + err = len; + goto out; + } + sg = adjust_sg(sg, len, &cnt); + } while (total < count && len > 0); + offset += pdu_marshal(pdu, offset, "d", total); + err = offset; out: - complete_pdu(s, vs->pdu, err); - g_free(vs); -} - -static void v9fs_create_post_getiounit(V9fsState *s, V9fsCreateState *vs) -{ - int err; - v9fs_string_copy(&vs->fidp->path, &vs->fullname); - stat_to_qid(&vs->stbuf, &vs->qid); - - vs->offset += pdu_marshal(vs->pdu, vs->offset, "Qd", &vs->qid, vs->iounit); - err = vs->offset; - - complete_pdu(s, vs->pdu, err); - v9fs_string_free(&vs->name); - v9fs_string_free(&vs->extension); - v9fs_string_free(&vs->fullname); - g_free(vs); -} - -static void v9fs_post_create(V9fsState *s, V9fsCreateState *vs, int err) -{ - if (err == 0) { - vs->iounit = get_iounit(s, &vs->fidp->path); - v9fs_create_post_getiounit(s, vs); - return; - } - - complete_pdu(s, vs->pdu, err); - v9fs_string_free(&vs->name); - v9fs_string_free(&vs->extension); - v9fs_string_free(&vs->fullname); - g_free(vs); -} - -static void v9fs_create_post_perms(V9fsState *s, V9fsCreateState *vs, int err) -{ - if (err) { - err = -errno; - } - v9fs_post_create(s, vs, err); -} - -static void v9fs_create_post_opendir(V9fsState *s, V9fsCreateState *vs, - int err) -{ - if (!vs->fidp->fs.dir) { - err = -errno; - } - vs->fidp->fid_type = P9_FID_DIR; - v9fs_post_create(s, vs, err); + complete_pdu(s, pdu, err); } -static void v9fs_create_post_dir_lstat(V9fsState *s, V9fsCreateState *vs, - int err) +static void v9fs_create(void *opaque) { - if (err) { - err = -errno; - goto out; - } + int32_t fid; + int err = 0; + size_t offset = 7; + V9fsFidState *fidp; + V9fsQID qid; + int32_t perm; + int8_t mode; + struct stat stbuf; + V9fsString name; + V9fsString extension; + V9fsString fullname; + int iounit; + V9fsPDU *pdu = opaque; - vs->fidp->fs.dir = v9fs_do_opendir(s, &vs->fullname); - v9fs_create_post_opendir(s, vs, err); - return; + v9fs_string_init(&fullname); -out: - v9fs_post_create(s, vs, err); -} + pdu_unmarshal(pdu, offset, "dsdbs", &fid, &name, + &perm, &mode, &extension); -static void v9fs_create_post_mkdir(V9fsState *s, V9fsCreateState *vs, int err) -{ - if (err < 0) { + fidp = lookup_fid(pdu->s, fid); + if (fidp == NULL) { + err = -EINVAL; goto out; } - err = v9fs_do_lstat(s, &vs->fullname, &vs->stbuf); - v9fs_create_post_dir_lstat(s, vs, err); - return; - -out: - v9fs_post_create(s, vs, err); -} - -static void v9fs_create_post_fstat(V9fsState *s, V9fsCreateState *vs, int err) -{ - if (err) { - vs->fidp->fid_type = P9_FID_NONE; - close(vs->fidp->fs.fd); - err = -errno; - } - v9fs_post_create(s, vs, err); - return; -} - -static void v9fs_create_post_open2(V9fsState *s, V9fsCreateState *vs, int err) -{ - if (vs->fidp->fs.fd == -1) { - err = -errno; + v9fs_string_sprintf(&fullname, "%s/%s", fidp->path.data, name.data); + err = v9fs_co_lstat(pdu->s, &fullname, &stbuf); + if (!err) { + err = -EEXIST; goto out; - } - vs->fidp->fid_type = P9_FID_FILE; - err = v9fs_do_fstat(s, vs->fidp->fs.fd, &vs->stbuf); - v9fs_create_post_fstat(s, vs, err); - - return; - -out: - v9fs_post_create(s, vs, err); - -} - -static void v9fs_create_post_lstat(V9fsState *s, V9fsCreateState *vs, int err) -{ - - if (err == 0 || errno != ENOENT) { - err = -errno; + } else if (err != -ENOENT) { goto out; } - - if (vs->perm & P9_STAT_MODE_DIR) { - err = v9fs_co_mkdir(s, vs->fullname.data, vs->perm & 0777, - vs->fidp->uid, -1); - v9fs_create_post_mkdir(s, vs, err); - } else if (vs->perm & P9_STAT_MODE_SYMLINK) { - err = v9fs_do_symlink(s, vs->fidp, vs->extension.data, - vs->fullname.data, -1); - v9fs_create_post_perms(s, vs, err); - } else if (vs->perm & P9_STAT_MODE_LINK) { - int32_t nfid = atoi(vs->extension.data); - V9fsFidState *nfidp = lookup_fid(s, nfid); + if (perm & P9_STAT_MODE_DIR) { + err = v9fs_co_mkdir(pdu->s, fullname.data, perm & 0777, + fidp->uid, -1); + if (err < 0) { + goto out; + } + err = v9fs_co_opendir(pdu->s, fidp); + if (err < 0) { + goto out; + } + fidp->fid_type = P9_FID_DIR; + } else if (perm & P9_STAT_MODE_SYMLINK) { + err = v9fs_co_symlink(pdu->s, fidp, extension.data, + fullname.data, -1); + if (err < 0) { + goto out; + } + } else if (perm & P9_STAT_MODE_LINK) { + int32_t nfid = atoi(extension.data); + V9fsFidState *nfidp = lookup_fid(pdu->s, nfid); if (nfidp == NULL) { - err = -errno; - v9fs_post_create(s, vs, err); + err = -EINVAL; + goto out; + } + err = v9fs_co_link(pdu->s, &nfidp->path, &fullname); + if (err < 0) { + goto out; } - err = v9fs_do_link(s, &nfidp->path, &vs->fullname); - v9fs_create_post_perms(s, vs, err); - } else if (vs->perm & P9_STAT_MODE_DEVICE) { + } else if (perm & P9_STAT_MODE_DEVICE) { char ctype; uint32_t major, minor; mode_t nmode = 0; - if (sscanf(vs->extension.data, "%c %u %u", &ctype, &major, - &minor) != 3) { + if (sscanf(extension.data, "%c %u %u", &ctype, &major, &minor) != 3) { err = -errno; - v9fs_post_create(s, vs, err); + goto out; } switch (ctype) { @@ -2390,134 +1907,95 @@ static void v9fs_create_post_lstat(V9fsState *s, V9fsCreateState *vs, int err) break; default: err = -EIO; - v9fs_post_create(s, vs, err); - } - - nmode |= vs->perm & 0777; - err = v9fs_do_mknod(s, vs->fullname.data, nmode, - makedev(major, minor), vs->fidp->uid, -1); - v9fs_create_post_perms(s, vs, err); - } else if (vs->perm & P9_STAT_MODE_NAMED_PIPE) { - err = v9fs_do_mknod(s, vs->fullname.data, S_IFIFO | (vs->perm & 0777), - 0, vs->fidp->uid, -1); - v9fs_post_create(s, vs, err); - } else if (vs->perm & P9_STAT_MODE_SOCKET) { - err = v9fs_do_mknod(s, vs->fullname.data, S_IFSOCK | (vs->perm & 0777), - 0, vs->fidp->uid, -1); - v9fs_post_create(s, vs, err); - } else { - vs->fidp->fs.fd = v9fs_do_open2(s, vs->fullname.data, vs->fidp->uid, - -1, omode_to_uflags(vs->mode)|O_CREAT, vs->perm); - - v9fs_create_post_open2(s, vs, err); - } - - return; - -out: - v9fs_post_create(s, vs, err); -} - -static void v9fs_create(void *opaque) -{ - V9fsPDU *pdu = opaque; - V9fsState *s = pdu->s; - int32_t fid; - V9fsCreateState *vs; - int err = 0; - - vs = g_malloc(sizeof(*vs)); - vs->pdu = pdu; - vs->offset = 7; - - v9fs_string_init(&vs->fullname); - - pdu_unmarshal(vs->pdu, vs->offset, "dsdbs", &fid, &vs->name, - &vs->perm, &vs->mode, &vs->extension); - - vs->fidp = lookup_fid(s, fid); - if (vs->fidp == NULL) { - err = -EINVAL; - goto out; - } - - v9fs_string_sprintf(&vs->fullname, "%s/%s", vs->fidp->path.data, - vs->name.data); - - err = v9fs_do_lstat(s, &vs->fullname, &vs->stbuf); - v9fs_create_post_lstat(s, vs, err); - return; - -out: - complete_pdu(s, vs->pdu, err); - v9fs_string_free(&vs->name); - v9fs_string_free(&vs->extension); - g_free(vs); -} + goto out; + } -static void v9fs_post_symlink(V9fsState *s, V9fsSymlinkState *vs, int err) -{ - if (err == 0) { - stat_to_qid(&vs->stbuf, &vs->qid); - vs->offset += pdu_marshal(vs->pdu, vs->offset, "Q", &vs->qid); - err = vs->offset; + nmode |= perm & 0777; + err = v9fs_co_mknod(pdu->s, &fullname, fidp->uid, -1, + makedev(major, minor), nmode); + if (err < 0) { + goto out; + } + } else if (perm & P9_STAT_MODE_NAMED_PIPE) { + err = v9fs_co_mknod(pdu->s, &fullname, fidp->uid, -1, + 0, S_IFIFO | (perm & 0777)); + if (err < 0) { + goto out; + } + } else if (perm & P9_STAT_MODE_SOCKET) { + err = v9fs_co_mknod(pdu->s, &fullname, fidp->uid, -1, + 0, S_IFSOCK | (perm & 0777)); + if (err < 0) { + goto out; + } } else { - err = -errno; + err = v9fs_co_open2(pdu->s, fidp, fullname.data, -1, + omode_to_uflags(mode)|O_CREAT, perm); + if (err < 0) { + goto out; + } + fidp->fid_type = P9_FID_FILE; } - complete_pdu(s, vs->pdu, err); - v9fs_string_free(&vs->name); - v9fs_string_free(&vs->symname); - v9fs_string_free(&vs->fullname); - g_free(vs); -} - -static void v9fs_symlink_post_do_symlink(V9fsState *s, V9fsSymlinkState *vs, - int err) -{ - if (err) { + err = v9fs_co_lstat(pdu->s, &fullname, &stbuf); + if (err < 0) { + fidp->fid_type = P9_FID_NONE; + if (fidp->fs.fd) { + close(fidp->fs.fd); + } goto out; } - err = v9fs_do_lstat(s, &vs->fullname, &vs->stbuf); + iounit = get_iounit(pdu->s, &fidp->path); + v9fs_string_copy(&fidp->path, &fullname); + stat_to_qid(&stbuf, &qid); + offset += pdu_marshal(pdu, offset, "Qd", &qid, iounit); + err = offset; out: - v9fs_post_symlink(s, vs, err); + complete_pdu(pdu->s, pdu, err); + v9fs_string_free(&name); + v9fs_string_free(&extension); + v9fs_string_free(&fullname); } static void v9fs_symlink(void *opaque) { V9fsPDU *pdu = opaque; - V9fsState *s = pdu->s; + V9fsString name; + V9fsString symname; + V9fsString fullname; + V9fsFidState *dfidp; + V9fsQID qid; + struct stat stbuf; int32_t dfid; - V9fsSymlinkState *vs; int err = 0; gid_t gid; + size_t offset = 7; - vs = g_malloc(sizeof(*vs)); - vs->pdu = pdu; - vs->offset = 7; - - v9fs_string_init(&vs->fullname); - - pdu_unmarshal(vs->pdu, vs->offset, "dssd", &dfid, &vs->name, - &vs->symname, &gid); + v9fs_string_init(&fullname); + pdu_unmarshal(pdu, offset, "dssd", &dfid, &name, &symname, &gid); - vs->dfidp = lookup_fid(s, dfid); - if (vs->dfidp == NULL) { + dfidp = lookup_fid(pdu->s, dfid); + if (dfidp == NULL) { err = -EINVAL; goto out; } - v9fs_string_sprintf(&vs->fullname, "%s/%s", vs->dfidp->path.data, - vs->name.data); - err = v9fs_do_symlink(s, vs->dfidp, vs->symname.data, - vs->fullname.data, gid); - v9fs_symlink_post_do_symlink(s, vs, err); - return; - + v9fs_string_sprintf(&fullname, "%s/%s", dfidp->path.data, name.data); + err = v9fs_co_symlink(pdu->s, dfidp, symname.data, fullname.data, gid); + if (err < 0) { + goto out; + } + err = v9fs_co_lstat(pdu->s, &fullname, &stbuf); + if (err < 0) { + goto out; + } + stat_to_qid(&stbuf, &qid); + offset += pdu_marshal(pdu, offset, "Q", &qid); + err = offset; out: - complete_pdu(s, vs->pdu, err); - v9fs_string_free(&vs->name); - v9fs_string_free(&vs->symname); - g_free(vs); + complete_pdu(pdu->s, pdu, err); + v9fs_string_free(&name); + v9fs_string_free(&symname); + v9fs_string_free(&fullname); } static void v9fs_flush(void *opaque) @@ -2545,21 +2023,20 @@ static void v9fs_link(void *opaque) dfidp = lookup_fid(s, dfid); if (dfidp == NULL) { - err = -errno; + err = -ENOENT; goto out; } oldfidp = lookup_fid(s, oldfid); if (oldfidp == NULL) { - err = -errno; + err = -ENOENT; goto out; } v9fs_string_sprintf(&fullname, "%s/%s", dfidp->path.data, name.data); - err = offset; - err = v9fs_do_link(s, &oldfidp->path, &fullname); - if (err) { - err = -errno; + err = v9fs_co_link(s, &oldfidp->path, &fullname); + if (!err) { + err = offset; } v9fs_string_free(&fullname); @@ -2594,39 +2071,6 @@ out: complete_pdu(pdu->s, pdu, err); } -static void v9fs_wstat_post_truncate(V9fsState *s, V9fsWstatState *vs, int err) -{ - if (err < 0) { - goto out; - } - - err = vs->offset; - -out: - v9fs_stat_free(&vs->v9stat); - complete_pdu(s, vs->pdu, err); - g_free(vs); -} - -static void v9fs_wstat_post_rename(V9fsState *s, V9fsWstatState *vs, int err) -{ - if (err < 0) { - goto out; - } - if (vs->v9stat.length != -1) { - if (v9fs_do_truncate(s, &vs->fidp->path, vs->v9stat.length) < 0) { - err = -errno; - } - } - v9fs_wstat_post_truncate(s, vs, err); - return; - -out: - v9fs_stat_free(&vs->v9stat); - complete_pdu(s, vs->pdu, err); - g_free(vs); -} - static int v9fs_complete_rename(V9fsState *s, V9fsFidState *fidp, int32_t newdirfid, V9fsString *name) { @@ -2695,24 +2139,6 @@ out: return err; } -static void v9fs_wstat_post_chown(V9fsState *s, V9fsWstatState *vs, int err) -{ - if (err < 0) { - goto out; - } - - if (vs->v9stat.name.size != 0) { - err = v9fs_complete_rename(s, vs->fidp, -1, &vs->v9stat.name); - } - v9fs_wstat_post_rename(s, vs, err); - return; - -out: - v9fs_stat_free(&vs->v9stat); - complete_pdu(s, vs->pdu, err); - g_free(vs); -} - static void v9fs_rename(void *opaque) { int32_t fid; @@ -2742,143 +2168,90 @@ out: v9fs_string_free(&name); } -static void v9fs_wstat_post_utime(V9fsState *s, V9fsWstatState *vs, int err) +static void v9fs_wstat(void *opaque) { - if (err < 0) { - goto out; - } + int32_t fid; + int err = 0; + int16_t unused; + V9fsStat v9stat; + size_t offset = 7; + struct stat stbuf; + V9fsFidState *fidp; + V9fsPDU *pdu = opaque; + V9fsState *s = pdu->s; - if (vs->v9stat.n_gid != -1 || vs->v9stat.n_uid != -1) { - if (v9fs_do_chown(s, &vs->fidp->path, vs->v9stat.n_uid, - vs->v9stat.n_gid)) { - err = -errno; - } + pdu_unmarshal(pdu, offset, "dwS", &fid, &unused, &v9stat); + fidp = lookup_fid(s, fid); + if (fidp == NULL) { + err = -EINVAL; + goto out; } - v9fs_wstat_post_chown(s, vs, err); - return; - -out: - v9fs_stat_free(&vs->v9stat); - complete_pdu(s, vs->pdu, err); - g_free(vs); -} - -static void v9fs_wstat_post_chmod(V9fsState *s, V9fsWstatState *vs, int err) -{ - if (err < 0) { + /* do we need to sync the file? */ + if (donttouch_stat(&v9stat)) { + err = v9fs_co_fsync(s, fidp, 0); goto out; } - - if (vs->v9stat.mtime != -1 || vs->v9stat.atime != -1) { + if (v9stat.mode != -1) { + uint32_t v9_mode; + err = v9fs_co_lstat(s, &fidp->path, &stbuf); + if (err < 0) { + goto out; + } + v9_mode = stat_to_v9mode(&stbuf); + if ((v9stat.mode & P9_STAT_MODE_TYPE_BITS) != + (v9_mode & P9_STAT_MODE_TYPE_BITS)) { + /* Attempting to change the type */ + err = -EIO; + goto out; + } + err = v9fs_co_chmod(s, &fidp->path, + v9mode_to_mode(v9stat.mode, + &v9stat.extension)); + if (err < 0) { + goto out; + } + } + if (v9stat.mtime != -1 || v9stat.atime != -1) { struct timespec times[2]; - if (vs->v9stat.atime != -1) { - times[0].tv_sec = vs->v9stat.atime; + if (v9stat.atime != -1) { + times[0].tv_sec = v9stat.atime; times[0].tv_nsec = 0; } else { times[0].tv_nsec = UTIME_OMIT; } - if (vs->v9stat.mtime != -1) { - times[1].tv_sec = vs->v9stat.mtime; + if (v9stat.mtime != -1) { + times[1].tv_sec = v9stat.mtime; times[1].tv_nsec = 0; } else { times[1].tv_nsec = UTIME_OMIT; } - - if (v9fs_do_utimensat(s, &vs->fidp->path, times)) { - err = -errno; + err = v9fs_co_utimensat(s, &fidp->path, times); + if (err < 0) { + goto out; } } - - v9fs_wstat_post_utime(s, vs, err); - return; - -out: - v9fs_stat_free(&vs->v9stat); - complete_pdu(s, vs->pdu, err); - g_free(vs); -} - -static void v9fs_wstat_post_fsync(V9fsState *s, V9fsWstatState *vs, int err) -{ - if (err == -1) { - err = -errno; - } - v9fs_stat_free(&vs->v9stat); - complete_pdu(s, vs->pdu, err); - g_free(vs); -} - -static void v9fs_wstat_post_lstat(V9fsState *s, V9fsWstatState *vs, int err) -{ - uint32_t v9_mode; - - if (err == -1) { - err = -errno; - goto out; - } - - v9_mode = stat_to_v9mode(&vs->stbuf); - - if ((vs->v9stat.mode & P9_STAT_MODE_TYPE_BITS) != - (v9_mode & P9_STAT_MODE_TYPE_BITS)) { - /* Attempting to change the type */ - err = -EIO; + if (v9stat.n_gid != -1 || v9stat.n_uid != -1) { + err = v9fs_co_chown(s, &fidp->path, v9stat.n_uid, v9stat.n_gid); + if (err < 0) { goto out; + } } - - if (v9fs_do_chmod(s, &vs->fidp->path, v9mode_to_mode(vs->v9stat.mode, - &vs->v9stat.extension))) { - err = -errno; - } - v9fs_wstat_post_chmod(s, vs, err); - return; - -out: - v9fs_stat_free(&vs->v9stat); - complete_pdu(s, vs->pdu, err); - g_free(vs); -} - -static void v9fs_wstat(void *opaque) -{ - V9fsPDU *pdu = opaque; - V9fsState *s = pdu->s; - int32_t fid; - V9fsWstatState *vs; - int err = 0; - - vs = g_malloc(sizeof(*vs)); - vs->pdu = pdu; - vs->offset = 7; - - pdu_unmarshal(pdu, vs->offset, "dwS", &fid, &vs->unused, &vs->v9stat); - - vs->fidp = lookup_fid(s, fid); - if (vs->fidp == NULL) { - err = -EINVAL; - goto out; - } - - /* do we need to sync the file? */ - if (donttouch_stat(&vs->v9stat)) { - err = v9fs_do_fsync(s, vs->fidp->fs.fd, 0); - v9fs_wstat_post_fsync(s, vs, err); - return; + if (v9stat.name.size != 0) { + err = v9fs_complete_rename(s, fidp, -1, &v9stat.name); + if (err < 0) { + goto out; + } } - - if (vs->v9stat.mode != -1) { - err = v9fs_do_lstat(s, &vs->fidp->path, &vs->stbuf); - v9fs_wstat_post_lstat(s, vs, err); - return; + if (v9stat.length != -1) { + err = v9fs_co_truncate(s, &fidp->path, v9stat.length); + if (err < 0) { + goto out; + } } - - v9fs_wstat_post_chmod(s, vs, err); - return; - + err = offset; out: - v9fs_stat_free(&vs->v9stat); - complete_pdu(s, vs->pdu, err); - g_free(vs); + v9fs_stat_free(&v9stat); + complete_pdu(s, pdu, err); } static int v9fs_fill_statfs(V9fsState *s, V9fsPDU *pdu, struct statfs *stbuf) @@ -3006,89 +2379,81 @@ out: * do any thing in * qemu 9p server side lock code path. * So when a TLOCK request comes, always return success */ - static void v9fs_lock(void *opaque) { + int8_t status; + V9fsFlock *flock; + size_t offset = 7; + struct stat stbuf; + V9fsFidState *fidp; + int32_t fid, err = 0; V9fsPDU *pdu = opaque; V9fsState *s = pdu->s; - int32_t fid, err = 0; - V9fsLockState *vs; - - vs = g_malloc0(sizeof(*vs)); - vs->pdu = pdu; - vs->offset = 7; - vs->flock = g_malloc(sizeof(*vs->flock)); - pdu_unmarshal(vs->pdu, vs->offset, "dbdqqds", &fid, &vs->flock->type, - &vs->flock->flags, &vs->flock->start, &vs->flock->length, - &vs->flock->proc_id, &vs->flock->client_id); - - vs->status = P9_LOCK_ERROR; + flock = g_malloc(sizeof(*flock)); + pdu_unmarshal(pdu, offset, "dbdqqds", &fid, &flock->type, + &flock->flags, &flock->start, &flock->length, + &flock->proc_id, &flock->client_id); + status = P9_LOCK_ERROR; /* We support only block flag now (that too ignored currently) */ - if (vs->flock->flags & ~P9_LOCK_FLAGS_BLOCK) { + if (flock->flags & ~P9_LOCK_FLAGS_BLOCK) { err = -EINVAL; goto out; } - vs->fidp = lookup_fid(s, fid); - if (vs->fidp == NULL) { + fidp = lookup_fid(s, fid); + if (fidp == NULL) { err = -ENOENT; goto out; } - - err = v9fs_do_fstat(s, vs->fidp->fs.fd, &vs->stbuf); + err = v9fs_co_fstat(s, fidp->fs.fd, &stbuf); if (err < 0) { - err = -errno; goto out; } - vs->status = P9_LOCK_SUCCESS; + status = P9_LOCK_SUCCESS; out: - vs->offset += pdu_marshal(vs->pdu, vs->offset, "b", vs->status); - complete_pdu(s, vs->pdu, err); - g_free(vs->flock); - g_free(vs); + err = offset; + err += pdu_marshal(pdu, offset, "b", status); + complete_pdu(s, pdu, err); + g_free(flock); } /* * When a TGETLOCK request comes, always return success because all lock * handling is done by client's VFS layer. */ - static void v9fs_getlock(void *opaque) { + size_t offset = 7; + struct stat stbuf; + V9fsFidState *fidp; + V9fsGetlock *glock; + int32_t fid, err = 0; V9fsPDU *pdu = opaque; V9fsState *s = pdu->s; - int32_t fid, err = 0; - V9fsGetlockState *vs; - vs = g_malloc0(sizeof(*vs)); - vs->pdu = pdu; - vs->offset = 7; + glock = g_malloc(sizeof(*glock)); + pdu_unmarshal(pdu, offset, "dbqqds", &fid, &glock->type, + &glock->start, &glock->length, &glock->proc_id, + &glock->client_id); - vs->glock = g_malloc(sizeof(*vs->glock)); - pdu_unmarshal(vs->pdu, vs->offset, "dbqqds", &fid, &vs->glock->type, - &vs->glock->start, &vs->glock->length, &vs->glock->proc_id, - &vs->glock->client_id); - - vs->fidp = lookup_fid(s, fid); - if (vs->fidp == NULL) { + fidp = lookup_fid(s, fid); + if (fidp == NULL) { err = -ENOENT; goto out; } - - err = v9fs_do_fstat(s, vs->fidp->fs.fd, &vs->stbuf); + err = v9fs_co_fstat(s, fidp->fs.fd, &stbuf); if (err < 0) { - err = -errno; goto out; } - vs->glock->type = F_UNLCK; - vs->offset += pdu_marshal(vs->pdu, vs->offset, "bqqds", vs->glock->type, - vs->glock->start, vs->glock->length, vs->glock->proc_id, - &vs->glock->client_id); + glock->type = F_UNLCK; + offset += pdu_marshal(pdu, offset, "bqqds", glock->type, + glock->start, glock->length, glock->proc_id, + &glock->client_id); + err = offset; out: - complete_pdu(s, vs->pdu, err); - g_free(vs->glock); - g_free(vs); + complete_pdu(s, pdu, err); + g_free(glock); } static void v9fs_mkdir(void *opaque) diff --git a/hw/9pfs/virtio-9p.h b/hw/9pfs/virtio-9p.h index 46d79da920..1d8c1b1093 100644 --- a/hw/9pfs/virtio-9p.h +++ b/hw/9pfs/virtio-9p.h @@ -222,31 +222,6 @@ typedef struct V9fsState int32_t msize; } V9fsState; -typedef struct V9fsCreateState { - V9fsPDU *pdu; - size_t offset; - V9fsFidState *fidp; - V9fsQID qid; - int32_t perm; - int8_t mode; - struct stat stbuf; - V9fsString name; - V9fsString extension; - V9fsString fullname; - int iounit; -} V9fsCreateState; - -typedef struct V9fsLcreateState { - V9fsPDU *pdu; - size_t offset; - V9fsFidState *fidp; - V9fsQID qid; - int32_t iounit; - struct stat stbuf; - V9fsString name; - V9fsString fullname; -} V9fsLcreateState; - typedef struct V9fsStatState { V9fsPDU *pdu; size_t offset; @@ -278,19 +253,6 @@ typedef struct V9fsStatDotl { uint64_t st_data_version; } V9fsStatDotl; -typedef struct V9fsWalkState { - V9fsPDU *pdu; - size_t offset; - uint16_t nwnames; - int name_idx; - V9fsQID *qids; - V9fsFidState *fidp; - V9fsFidState *newfidp; - V9fsString path; - V9fsString *wnames; - struct stat stbuf; -} V9fsWalkState; - typedef struct V9fsOpenState { V9fsPDU *pdu; size_t offset; @@ -333,28 +295,6 @@ typedef struct V9fsWriteState { int cnt; } V9fsWriteState; -typedef struct V9fsWstatState -{ - V9fsPDU *pdu; - size_t offset; - int16_t unused; - V9fsStat v9stat; - V9fsFidState *fidp; - struct stat stbuf; -} V9fsWstatState; - -typedef struct V9fsSymlinkState -{ - V9fsPDU *pdu; - size_t offset; - V9fsString name; - V9fsString symname; - V9fsString fullname; - V9fsFidState *dfidp; - V9fsQID qid; - struct stat stbuf; -} V9fsSymlinkState; - typedef struct V9fsIattr { int32_t valid; @@ -403,16 +343,6 @@ typedef struct V9fsFlock V9fsString client_id; } V9fsFlock; -typedef struct V9fsLockState -{ - V9fsPDU *pdu; - size_t offset; - int8_t status; - struct stat stbuf; - V9fsFidState *fidp; - V9fsFlock *flock; -} V9fsLockState; - typedef struct V9fsGetlock { uint8_t type; @@ -422,15 +352,6 @@ typedef struct V9fsGetlock V9fsString client_id; } V9fsGetlock; -typedef struct V9fsGetlockState -{ - V9fsPDU *pdu; - size_t offset; - struct stat stbuf; - V9fsFidState *fidp; - V9fsGetlock *glock; -} V9fsGetlockState; - size_t pdu_packunpack(void *addr, struct iovec *sg, int sg_count, size_t offset, size_t size, int pack); diff --git a/hw/g364fb.c b/hw/g364fb.c index b3020c5a60..5e7bcfa278 100644 --- a/hw/g364fb.c +++ b/hw/g364fb.c @@ -1,7 +1,7 @@ /* * QEMU G364 framebuffer Emulator. * - * Copyright (c) 2007-2009 Herve Poussineau + * Copyright (c) 2007-2011 Herve Poussineau * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -18,27 +18,18 @@ */ #include "hw.h" -#include "mips.h" #include "console.h" #include "pixel_ops.h" - -//#define DEBUG_G364 - -#ifdef DEBUG_G364 -#define DPRINTF(fmt, ...) \ -do { printf("g364: " fmt , ## __VA_ARGS__); } while (0) -#else -#define DPRINTF(fmt, ...) do {} while (0) -#endif -#define BADF(fmt, ...) \ -do { fprintf(stderr, "g364 ERROR: " fmt , ## __VA_ARGS__);} while (0) +#include "trace.h" +#include "sysbus.h" typedef struct G364State { /* hardware */ uint8_t *vram; - ram_addr_t vram_offset; - int vram_size; + uint32_t vram_size; qemu_irq irq; + MemoryRegion mem_vram; + MemoryRegion mem_ctrl; /* registers */ uint8_t color_palette[256][3]; uint8_t cursor_palette[3][3]; @@ -53,31 +44,32 @@ typedef struct G364State { int blanked; } G364State; -#define REG_ID 0x000000 -#define REG_BOOT 0x080000 -#define REG_DISPLAY 0x080118 -#define REG_VDISPLAY 0x080150 -#define REG_CTLA 0x080300 -#define REG_TOP 0x080400 -#define REG_CURS_PAL 0x080508 -#define REG_CURS_POS 0x080638 -#define REG_CLR_PAL 0x080800 -#define REG_CURS_PAT 0x081000 -#define REG_RESET 0x180000 +#define REG_BOOT 0x000000 +#define REG_DISPLAY 0x000118 +#define REG_VDISPLAY 0x000150 +#define REG_CTLA 0x000300 +#define REG_TOP 0x000400 +#define REG_CURS_PAL 0x000508 +#define REG_CURS_POS 0x000638 +#define REG_CLR_PAL 0x000800 +#define REG_CURS_PAT 0x001000 +#define REG_RESET 0x100000 #define CTLA_FORCE_BLANK 0x00000400 #define CTLA_NO_CURSOR 0x00800000 -static inline int check_dirty(ram_addr_t page) +static inline int check_dirty(G364State *s, ram_addr_t page) { - return cpu_physical_memory_get_dirty(page, VGA_DIRTY_FLAG); + return memory_region_get_dirty(&s->mem_vram, page, DIRTY_MEMORY_VGA); } static inline void reset_dirty(G364State *s, ram_addr_t page_min, ram_addr_t page_max) { - cpu_physical_memory_reset_dirty(page_min, page_max + TARGET_PAGE_SIZE - 1, - VGA_DIRTY_FLAG); + memory_region_reset_dirty(&s->mem_vram, + page_min, + page_max + TARGET_PAGE_SIZE - page_min - 1, + DIRTY_MEMORY_VGA); } static void g364fb_draw_graphic8(G364State *s) @@ -110,11 +102,12 @@ static void g364fb_draw_graphic8(G364State *s) w = 4; break; default: - BADF("unknown host depth %d\n", ds_get_bits_per_pixel(s->ds)); + hw_error("g364: unknown host depth %d", + ds_get_bits_per_pixel(s->ds)); return; } - page = s->vram_offset; + page = 0; page_min = (ram_addr_t)-1; page_max = 0; @@ -135,7 +128,7 @@ static void g364fb_draw_graphic8(G364State *s) /* XXX: out of range in vram? */ data_display = dd = ds_get_data(s->ds); while (y < s->height) { - if (check_dirty(page)) { + if (check_dirty(s, page)) { if (y < ymin) ymin = ymax = y; if (page_min == (ram_addr_t)-1) @@ -262,7 +255,7 @@ static void g364fb_update_display(void *opaque) } else if (s->depth == 8) { g364fb_draw_graphic8(s); } else { - BADF("unknown guest depth %d\n", s->depth); + error_report("g364: unknown guest depth %d", s->depth); } qemu_irq_raise(s->irq); @@ -275,13 +268,12 @@ static inline void g364fb_invalidate_display(void *opaque) s->blanked = 0; for (i = 0; i < s->vram_size; i += TARGET_PAGE_SIZE) { - cpu_physical_memory_set_dirty(s->vram_offset + i); + memory_region_set_dirty(&s->mem_vram, i); } } -static void g364fb_reset(void *opaque) +static void g364fb_reset(G364State *s) { - G364State *s = opaque; qemu_irq_lower(s->irq); memset(s->color_palette, 0, sizeof(s->color_palette)); @@ -292,7 +284,7 @@ static void g364fb_reset(void *opaque) s->top_of_screen = 0; s->width = s->height = 0; memset(s->vram, 0, s->vram_size); - g364fb_invalidate_display(opaque); + g364fb_invalidate_display(s); } static void g364fb_screen_dump(void *opaque, const char *filename) @@ -304,7 +296,7 @@ static void g364fb_screen_dump(void *opaque, const char *filename) FILE *f; if (s->depth != 8) { - BADF("unknown guest depth %d\n", s->depth); + error_report("g364: unknown guest depth %d", s->depth); return; } @@ -336,7 +328,9 @@ static void g364fb_screen_dump(void *opaque, const char *filename) } /* called for accesses to io ports */ -static uint32_t g364fb_ctrl_readl(void *opaque, target_phys_addr_t addr) +static uint64_t g364fb_ctrl_read(void *opaque, + target_phys_addr_t addr, + unsigned int size) { G364State *s = opaque; uint32_t val; @@ -353,9 +347,6 @@ static uint32_t g364fb_ctrl_readl(void *opaque, target_phys_addr_t addr) val |= ((uint32_t)s->cursor_palette[idx][2] << 0); } else { switch (addr) { - case REG_ID: - val = 0x10; /* Mips G364 */ - break; case REG_DISPLAY: val = s->width / 4; break; @@ -367,33 +358,19 @@ static uint32_t g364fb_ctrl_readl(void *opaque, target_phys_addr_t addr) break; default: { - BADF("invalid read at [" TARGET_FMT_plx "]\n", addr); + error_report("g364: invalid read at [" TARGET_FMT_plx "]", + addr); val = 0; break; } } } - DPRINTF("read 0x%08x at [" TARGET_FMT_plx "]\n", val, addr); + trace_g364fb_read(addr, val); return val; } -static uint32_t g364fb_ctrl_readw(void *opaque, target_phys_addr_t addr) -{ - uint32_t v = g364fb_ctrl_readl(opaque, addr & ~0x3); - if (addr & 0x2) - return v >> 16; - else - return v & 0xffff; -} - -static uint32_t g364fb_ctrl_readb(void *opaque, target_phys_addr_t addr) -{ - uint32_t v = g364fb_ctrl_readl(opaque, addr & ~0x3); - return (v >> (8 * (addr & 0x3))) & 0xff; -} - static void g364fb_update_depth(G364State *s) { static const int depths[8] = { 1, 2, 4, 8, 15, 16, 0 }; @@ -411,15 +388,18 @@ static void g364_invalidate_cursor_position(G364State *s) end = (ymax + 1) * ds_get_linesize(s->ds); for (i = start; i < end; i += TARGET_PAGE_SIZE) { - cpu_physical_memory_set_dirty(s->vram_offset + i); + memory_region_set_dirty(&s->mem_vram, i); } } -static void g364fb_ctrl_writel(void *opaque, target_phys_addr_t addr, uint32_t val) +static void g364fb_ctrl_write(void *opaque, + target_phys_addr_t addr, + uint64_t val, + unsigned int size) { G364State *s = opaque; - DPRINTF("write 0x%08x at [" TARGET_FMT_plx "]\n", val, addr); + trace_g364fb_write(addr, val); if (addr >= REG_CLR_PAL && addr < REG_CLR_PAL + 0x800) { /* color palette */ @@ -442,120 +422,65 @@ static void g364fb_ctrl_writel(void *opaque, target_phys_addr_t addr, uint32_t v g364fb_invalidate_display(s); } else { switch (addr) { - case REG_ID: /* Card identifier; read-only */ - case REG_BOOT: /* Boot timing */ - case 0x80108: /* Line timing: half sync */ - case 0x80110: /* Line timing: back porch */ - case 0x80120: /* Line timing: short display */ - case 0x80128: /* Frame timing: broad pulse */ - case 0x80130: /* Frame timing: v sync */ - case 0x80138: /* Frame timing: v preequalise */ - case 0x80140: /* Frame timing: v postequalise */ - case 0x80148: /* Frame timing: v blank */ - case 0x80158: /* Line timing: line time */ - case 0x80160: /* Frame store: line start */ - case 0x80168: /* vram cycle: mem init */ - case 0x80170: /* vram cycle: transfer delay */ - case 0x80200: /* vram cycle: mask register */ - /* ignore */ - break; - case REG_TOP: - s->top_of_screen = val; - g364fb_invalidate_display(s); - break; - case REG_DISPLAY: - s->width = val * 4; - break; - case REG_VDISPLAY: - s->height = val / 2; - break; - case REG_CTLA: - s->ctla = val; - g364fb_update_depth(s); - g364fb_invalidate_display(s); - break; - case REG_CURS_POS: - g364_invalidate_cursor_position(s); - s->cursor_position = val; - g364_invalidate_cursor_position(s); - break; - case REG_RESET: - g364fb_reset(s); - break; - default: - BADF("invalid write of 0x%08x at [" TARGET_FMT_plx "]\n", val, addr); - break; + case REG_BOOT: /* Boot timing */ + case 0x00108: /* Line timing: half sync */ + case 0x00110: /* Line timing: back porch */ + case 0x00120: /* Line timing: short display */ + case 0x00128: /* Frame timing: broad pulse */ + case 0x00130: /* Frame timing: v sync */ + case 0x00138: /* Frame timing: v preequalise */ + case 0x00140: /* Frame timing: v postequalise */ + case 0x00148: /* Frame timing: v blank */ + case 0x00158: /* Line timing: line time */ + case 0x00160: /* Frame store: line start */ + case 0x00168: /* vram cycle: mem init */ + case 0x00170: /* vram cycle: transfer delay */ + case 0x00200: /* vram cycle: mask register */ + /* ignore */ + break; + case REG_TOP: + s->top_of_screen = val; + g364fb_invalidate_display(s); + break; + case REG_DISPLAY: + s->width = val * 4; + break; + case REG_VDISPLAY: + s->height = val / 2; + break; + case REG_CTLA: + s->ctla = val; + g364fb_update_depth(s); + g364fb_invalidate_display(s); + break; + case REG_CURS_POS: + g364_invalidate_cursor_position(s); + s->cursor_position = val; + g364_invalidate_cursor_position(s); + break; + case REG_RESET: + g364fb_reset(s); + break; + default: + error_report("g364: invalid write of 0x%" PRIx64 + " at [" TARGET_FMT_plx "]", val, addr); + break; } } qemu_irq_lower(s->irq); } -static void g364fb_ctrl_writew(void *opaque, target_phys_addr_t addr, uint32_t val) -{ - uint32_t old_val = g364fb_ctrl_readl(opaque, addr & ~0x3); - - if (addr & 0x2) - val = (val << 16) | (old_val & 0x0000ffff); - else - val = val | (old_val & 0xffff0000); - g364fb_ctrl_writel(opaque, addr & ~0x3, val); -} - -static void g364fb_ctrl_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) -{ - uint32_t old_val = g364fb_ctrl_readl(opaque, addr & ~0x3); - - switch (addr & 3) { - case 0: - val = val | (old_val & 0xffffff00); - break; - case 1: - val = (val << 8) | (old_val & 0xffff00ff); - break; - case 2: - val = (val << 16) | (old_val & 0xff00ffff); - break; - case 3: - val = (val << 24) | (old_val & 0x00ffffff); - break; - } - g364fb_ctrl_writel(opaque, addr & ~0x3, val); -} - -static CPUReadMemoryFunc * const g364fb_ctrl_read[3] = { - g364fb_ctrl_readb, - g364fb_ctrl_readw, - g364fb_ctrl_readl, -}; - -static CPUWriteMemoryFunc * const g364fb_ctrl_write[3] = { - g364fb_ctrl_writeb, - g364fb_ctrl_writew, - g364fb_ctrl_writel, +static const MemoryRegionOps g364fb_ctrl_ops = { + .read = g364fb_ctrl_read, + .write = g364fb_ctrl_write, + .endianness = DEVICE_LITTLE_ENDIAN, + .impl.min_access_size = 4, + .impl.max_access_size = 4, }; -static int g364fb_load(QEMUFile *f, void *opaque, int version_id) +static int g364fb_post_load(void *opaque, int version_id) { G364State *s = opaque; - unsigned int i, vram_size; - - if (version_id != 1) - return -EINVAL; - - vram_size = qemu_get_be32(f); - if (vram_size < s->vram_size) - return -EINVAL; - qemu_get_buffer(f, s->vram, s->vram_size); - for (i = 0; i < 256; i++) - qemu_get_buffer(f, s->color_palette[i], 3); - for (i = 0; i < 3; i++) - qemu_get_buffer(f, s->cursor_palette[i], 3); - qemu_get_buffer(f, (uint8_t *)s->cursor, sizeof(s->cursor)); - s->cursor_position = qemu_get_be32(f); - s->ctla = qemu_get_be32(f); - s->top_of_screen = qemu_get_be32(f); - s->width = qemu_get_be32(f); - s->height = qemu_get_be32(f); /* force refresh */ g364fb_update_depth(s); @@ -564,52 +489,80 @@ static int g364fb_load(QEMUFile *f, void *opaque, int version_id) return 0; } -static void g364fb_save(QEMUFile *f, void *opaque) -{ - G364State *s = opaque; - int i; - - qemu_put_be32(f, s->vram_size); - qemu_put_buffer(f, s->vram, s->vram_size); - for (i = 0; i < 256; i++) - qemu_put_buffer(f, s->color_palette[i], 3); - for (i = 0; i < 3; i++) - qemu_put_buffer(f, s->cursor_palette[i], 3); - qemu_put_buffer(f, (uint8_t *)s->cursor, sizeof(s->cursor)); - qemu_put_be32(f, s->cursor_position); - qemu_put_be32(f, s->ctla); - qemu_put_be32(f, s->top_of_screen); - qemu_put_be32(f, s->width); - qemu_put_be32(f, s->height); -} +static const VMStateDescription vmstate_g364fb = { + .name = "g364fb", + .version_id = 1, + .minimum_version_id = 1, + .minimum_version_id_old = 1, + .post_load = g364fb_post_load, + .fields = (VMStateField[]) { + VMSTATE_VBUFFER_UINT32(vram, G364State, 1, NULL, 0, vram_size), + VMSTATE_BUFFER_UNSAFE(color_palette, G364State, 0, 256 * 3), + VMSTATE_BUFFER_UNSAFE(cursor_palette, G364State, 0, 9), + VMSTATE_UINT16_ARRAY(cursor, G364State, 512), + VMSTATE_UINT32(cursor_position, G364State), + VMSTATE_UINT32(ctla, G364State), + VMSTATE_UINT32(top_of_screen, G364State), + VMSTATE_UINT32(width, G364State), + VMSTATE_UINT32(height, G364State), + VMSTATE_END_OF_LIST() + } +}; -int g364fb_mm_init(target_phys_addr_t vram_base, - target_phys_addr_t ctrl_base, int it_shift, - qemu_irq irq) +static void g364fb_init(DeviceState *dev, G364State *s) { - G364State *s; - int io_ctrl; - - s = g_malloc0(sizeof(G364State)); - - s->vram_size = 8 * 1024 * 1024; - s->vram_offset = qemu_ram_alloc(NULL, "g364fb.vram", s->vram_size); - s->vram = qemu_get_ram_ptr(s->vram_offset); - s->irq = irq; - - qemu_register_reset(g364fb_reset, s); - register_savevm(NULL, "g364fb", 0, 1, g364fb_save, g364fb_load, s); - g364fb_reset(s); + s->vram = g_malloc0(s->vram_size); s->ds = graphic_console_init(g364fb_update_display, g364fb_invalidate_display, g364fb_screen_dump, NULL, s); - cpu_register_physical_memory(vram_base, s->vram_size, s->vram_offset); + memory_region_init_io(&s->mem_ctrl, &g364fb_ctrl_ops, s, "ctrl", 0x180000); + memory_region_init_ram_ptr(&s->mem_vram, dev, "vram", + s->vram_size, s->vram); + memory_region_set_coalescing(&s->mem_vram); +} + +typedef struct { + SysBusDevice busdev; + G364State g364; +} G364SysBusState; - io_ctrl = cpu_register_io_memory(g364fb_ctrl_read, g364fb_ctrl_write, s, - DEVICE_NATIVE_ENDIAN); - cpu_register_physical_memory(ctrl_base, 0x200000, io_ctrl); +static int g364fb_sysbus_init(SysBusDevice *dev) +{ + G364State *s = &FROM_SYSBUS(G364SysBusState, dev)->g364; + + g364fb_init(&dev->qdev, s); + sysbus_init_irq(dev, &s->irq); + sysbus_init_mmio_region(dev, &s->mem_ctrl); + sysbus_init_mmio_region(dev, &s->mem_vram); return 0; } + +static void g364fb_sysbus_reset(DeviceState *d) +{ + G364SysBusState *s = DO_UPCAST(G364SysBusState, busdev.qdev, d); + g364fb_reset(&s->g364); +} + +static SysBusDeviceInfo g364fb_sysbus_info = { + .init = g364fb_sysbus_init, + .qdev.name = "sysbus-g364", + .qdev.desc = "G364 framebuffer", + .qdev.size = sizeof(G364SysBusState), + .qdev.vmsd = &vmstate_g364fb, + .qdev.reset = g364fb_sysbus_reset, + .qdev.props = (Property[]) { + DEFINE_PROP_HEX32("vram_size", G364SysBusState, g364.vram_size, + 8 * 1024 * 1024), + DEFINE_PROP_END_OF_LIST(), + } +}; + +static void g364fb_register(void) +{ + sysbus_register_withprop(&g364fb_sysbus_info); +} + +device_init(g364fb_register); diff --git a/hw/gt64xxx.c b/hw/gt64xxx.c index 6af9782d90..1c3425372a 100644 --- a/hw/gt64xxx.c +++ b/hw/gt64xxx.c @@ -297,7 +297,11 @@ static void gt64120_pci_mapping(GT64120State *s) s->PCI0IO_start = s->regs[GT_PCI0IOLD] << 21; s->PCI0IO_length = ((s->regs[GT_PCI0IOHD] + 1) - (s->regs[GT_PCI0IOLD] & 0x7f)) << 21; isa_mem_base = s->PCI0IO_start; - isa_mmio_init(s->PCI0IO_start, s->PCI0IO_length); + if (s->PCI0IO_length) { + isa_mmio_setup(&s->PCI0IO_mem, s->PCI0IO_length); + memory_region_add_subregion(get_system_memory(), s->PCI0IO_start, + &s->PCI0IO_mem); + } } } @@ -8,11 +8,6 @@ PCIBus *gt64120_register(qemu_irq *pic); /* bonito.c */ PCIBus *bonito_init(qemu_irq *pic); -/* g364fb.c */ -int g364fb_mm_init(target_phys_addr_t vram_base, - target_phys_addr_t ctrl_base, int it_shift, - qemu_irq irq); - /* mipsnet.c */ void mipsnet_init(int base, qemu_irq irq, NICInfo *nd); diff --git a/hw/mips_jazz.c b/hw/mips_jazz.c index 84ce0613a3..f3c9f93204 100644 --- a/hw/mips_jazz.c +++ b/hw/mips_jazz.c @@ -195,7 +195,20 @@ void mips_jazz_init (ram_addr_t ram_size, /* Video card */ switch (jazz_model) { case JAZZ_MAGNUM: - g364fb_mm_init(0x40000000, 0x60000000, 0, rc4030[3]); + dev = qdev_create(NULL, "sysbus-g364"); + qdev_init_nofail(dev); + sysbus = sysbus_from_qdev(dev); + sysbus_mmio_map(sysbus, 0, 0x60080000); + sysbus_mmio_map(sysbus, 1, 0x40000000); + sysbus_connect_irq(sysbus, 0, rc4030[3]); + { + /* Simple ROM, so user doesn't have to provide one */ + ram_addr_t rom_offset = qemu_ram_alloc(NULL, "g364fb.rom", 0x80000); + uint8_t *rom = qemu_get_ram_ptr(rom_offset); + cpu_register_physical_memory(0x60000000, 0x80000, + rom_offset | IO_MEM_ROM); + rom[0] = 0x10; /* Mips G364 */ + } break; case JAZZ_PICA61: isa_vga_mm_init(0x40000000, 0x60000000, 0, get_system_memory()); diff --git a/hw/omap_gpmc.c b/hw/omap_gpmc.c index 922d622008..673dddd237 100644 --- a/hw/omap_gpmc.c +++ b/hw/omap_gpmc.c @@ -135,7 +135,6 @@ void omap_gpmc_reset(struct omap_gpmc_s *s) s->cs_file[i].config[6] & 0x1f, /* MASKADDR */ (s->cs_file[i].config[6] >> 8 & 0xf)); /* BASEADDR */ } - omap_gpmc_cs_map(s->cs_file, 0, 0xf); s->ecc_cs = 0; s->ecc_ptr = 0; s->ecc_cfg = 0x3fcff000; @@ -1811,6 +1811,25 @@ static uint8_t pci_find_capability_list(PCIDevice *pdev, uint8_t cap_id, return next; } +static uint8_t pci_find_capability_at_offset(PCIDevice *pdev, uint8_t offset) +{ + uint8_t next, prev, found = 0; + + if (!(pdev->used[offset])) { + return 0; + } + + assert(pdev->config[PCI_STATUS] & PCI_STATUS_CAP_LIST); + + for (prev = PCI_CAPABILITY_LIST; (next = pdev->config[prev]); + prev = next + PCI_CAP_LIST_NEXT) { + if (next <= offset && next > found) { + found = next; + } + } + return found; +} + /* Patch the PCI vendor and device ids in a PCI rom image if necessary. This is needed for an option rom which is used for more than one device. */ static void pci_patch_ids(PCIDevice *pdev, uint8_t *ptr, int size) @@ -1952,11 +1971,30 @@ int pci_add_capability(PCIDevice *pdev, uint8_t cap_id, uint8_t offset, uint8_t size) { uint8_t *config; + int i, overlapping_cap; + if (!offset) { offset = pci_find_space(pdev, size); if (!offset) { return -ENOSPC; } + } else { + /* Verify that capabilities don't overlap. Note: device assignment + * depends on this check to verify that the device is not broken. + * Should never trigger for emulated devices, but it's helpful + * for debugging these. */ + for (i = offset; i < offset + size; i++) { + overlapping_cap = pci_find_capability_at_offset(pdev, i); + if (overlapping_cap) { + fprintf(stderr, "ERROR: %04x:%02x:%02x.%x " + "Attempt to add PCI capability %x at offset " + "%x overlaps existing capability %x at offset %x\n", + pci_find_domain(pdev->bus), pci_bus_num(pdev->bus), + PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), + cap_id, offset, overlapping_cap, i); + return -EINVAL; + } + } } config = pdev->config + offset; @@ -175,6 +175,14 @@ static void hotplug_event_notify(PCIDevice *dev) } } +static void hotplug_event_clear(PCIDevice *dev) +{ + hotplug_event_update_event_status(dev); + if (!msix_enabled(dev) && !msi_enabled(dev) && !dev->exp.hpev_notified) { + qemu_set_irq(dev->irq[dev->exp.hpev_intx], 0); + } +} + /* * A PCI Express Hot-Plug Event has occurred, so update slot status register * and notify OS of the event if necessary. @@ -320,6 +328,10 @@ void pcie_cap_slot_write_config(PCIDevice *dev, uint8_t *exp_cap = dev->config + pos; uint16_t sltsta = pci_get_word(exp_cap + PCI_EXP_SLTSTA); + if (ranges_overlap(addr, len, pos + PCI_EXP_SLTSTA, 2)) { + hotplug_event_clear(dev); + } + if (!ranges_overlap(addr, len, pos + PCI_EXP_SLTCTL, 2)) { return; } diff --git a/hw/pcie_aer.c b/hw/pcie_aer.c index 2ae65ec807..62c06eafd6 100644 --- a/hw/pcie_aer.c +++ b/hw/pcie_aer.c @@ -415,7 +415,7 @@ static void pcie_aer_update_log(PCIDevice *dev, const PCIEAERErr *err) int i; assert(err->status); - assert(err->status & (err->status - 1)); + assert(!(err->status & (err->status - 1))); errcap &= ~(PCI_ERR_CAP_FEP_MASK | PCI_ERR_CAP_TLP); errcap |= PCI_ERR_CAP_FEP(first_bit); @@ -495,7 +495,7 @@ static int pcie_aer_record_error(PCIDevice *dev, int fep = PCI_ERR_CAP_FEP(errcap); assert(err->status); - assert(err->status & (err->status - 1)); + assert(!(err->status & (err->status - 1))); if (errcap & PCI_ERR_CAP_MHRE && (pci_get_long(aer_cap + PCI_ERR_UNCOR_STATUS) & (1U << fep))) { @@ -979,20 +979,21 @@ int do_pcie_aer_inejct_error(Monitor *mon, if (pcie_aer_parse_error_string(error_name, &error_status, &correctable)) { char *e = NULL; error_status = strtoul(error_name, &e, 0); - correctable = !!qdict_get_int(qdict, "correctable"); + correctable = qdict_get_try_bool(qdict, "correctable", 0); if (!e || *e != '\0') { monitor_printf(mon, "invalid error status value. \"%s\"", error_name); return -EINVAL; } } + err.status = error_status; err.source_id = (pci_bus_num(dev->bus) << 8) | dev->devfn; err.flags = 0; if (correctable) { err.flags |= PCIE_AER_ERR_IS_CORRECTABLE; } - if (qdict_get_int(qdict, "advisory_non_fatal")) { + if (qdict_get_try_bool(qdict, "advisory_non_fatal", 0)) { err.flags |= PCIE_AER_ERR_MAYBE_ADVISORY; } if (qdict_haskey(qdict, "header0")) { diff --git a/hw/ppc_newworld.c b/hw/ppc_newworld.c index 4727e0790c..fbd443d90f 100644 --- a/hw/ppc_newworld.c +++ b/hw/ppc_newworld.c @@ -146,6 +146,7 @@ static void ppc_core99_init (ram_addr_t ram_size, MacIONVRAMState *nvr; int bios_size; MemoryRegion *pic_mem, *dbdma_mem, *cuda_mem, *escc_mem; + MemoryRegion *escc_bar = g_new(MemoryRegion, 1); MemoryRegion *ide_mem[3]; int ppc_boot_device; DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS]; @@ -328,6 +329,8 @@ static void ppc_core99_init (ram_addr_t ram_size, escc_mem = escc_init(0x80013000, pic[0x25], pic[0x24], serial_hds[0], serial_hds[1], ESCC_CLOCK, 4); + memory_region_init_alias(escc_bar, "escc-bar", + escc_mem, 0, memory_region_size(escc_mem)); for(i = 0; i < nb_nics; i++) pci_nic_init_nofail(&nd_table[i], "ne2k_pci", NULL); @@ -350,7 +353,7 @@ static void ppc_core99_init (ram_addr_t ram_size, adb_mouse_init(&adb_bus); macio_init(pci_bus, PCI_DEVICE_ID_APPLE_UNI_N_KEYL, 0, pic_mem, - dbdma_mem, cuda_mem, NULL, 3, ide_mem, escc_mem); + dbdma_mem, cuda_mem, NULL, 3, ide_mem, escc_bar); if (usb_enabled) { usb_ohci_init_pci(pci_bus, -1); diff --git a/hw/ppc_oldworld.c b/hw/ppc_oldworld.c index 0071fc950e..235d2efc7b 100644 --- a/hw/ppc_oldworld.c +++ b/hw/ppc_oldworld.c @@ -83,7 +83,7 @@ static void ppc_heathrow_init (ram_addr_t ram_size, MacIONVRAMState *nvr; int bios_size; MemoryRegion *pic_mem, *dbdma_mem, *cuda_mem; - MemoryRegion *escc_mem, *ide_mem[2]; + MemoryRegion *escc_mem, *escc_bar = g_new(MemoryRegion, 1), *ide_mem[2]; uint16_t ppc_boot_device; DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS]; void *fw_cfg; @@ -241,6 +241,8 @@ static void ppc_heathrow_init (ram_addr_t ram_size, escc_mem = escc_init(0x80013000, pic[0x0f], pic[0x10], serial_hds[0], serial_hds[1], ESCC_CLOCK, 4); + memory_region_init_alias(escc_bar, "escc-bar", + escc_mem, 0, memory_region_size(escc_mem)); for(i = 0; i < nb_nics; i++) pci_nic_init_nofail(&nd_table[i], "ne2k_pci", NULL); @@ -269,7 +271,7 @@ static void ppc_heathrow_init (ram_addr_t ram_size, pmac_format_nvram_partition(nvr, 0x2000); macio_init(pci_bus, PCI_DEVICE_ID_APPLE_343S1201, 1, pic_mem, - dbdma_mem, cuda_mem, nvr, 2, ide_mem, escc_mem); + dbdma_mem, cuda_mem, nvr, 2, ide_mem, escc_bar); if (usb_enabled) { usb_ohci_init_pci(pci_bus, -1); diff --git a/hw/sh_pci.c b/hw/sh_pci.c index 76061bb756..36f39300d5 100644 --- a/hw/sh_pci.c +++ b/hw/sh_pci.c @@ -150,7 +150,7 @@ static int sh_pci_init_device(SysBusDevice *dev) PCI_DEVFN(0, 0), 4); memory_region_init_io(&s->memconfig_p4, &sh_pci_reg_ops, s, "sh_pci", 0x224); - memory_region_init_alias(&s->memconfig_a7, "sh_pci.2", &s->memconfig_a7, + memory_region_init_alias(&s->memconfig_a7, "sh_pci.2", &s->memconfig_p4, 0, 0x224); isa_mmio_setup(&s->isa, 0x40000); sysbus_init_mmio_cb2(dev, sh_pci_map, sh_pci_unmap); diff --git a/hw/sun4u.c b/hw/sun4u.c index 1b60e4ef59..32e6ab9beb 100644 --- a/hw/sun4u.c +++ b/hw/sun4u.c @@ -261,7 +261,9 @@ void cpu_check_irqs(CPUState *env) pil |= 1 << 14; } - if (!pil) { + /* The bit corresponding to psrpil is (1<< psrpil), the next bit + is (2 << psrpil). */ + if (pil < (2 << env->psrpil)){ if (env->interrupt_request & CPU_INTERRUPT_HARD) { CPUIRQ_DPRINTF("Reset CPU IRQ (current interrupt %x)\n", env->interrupt_index); @@ -293,10 +295,12 @@ void cpu_check_irqs(CPUState *env) break; } } - } else { + } else if (env->interrupt_request & CPU_INTERRUPT_HARD) { CPUIRQ_DPRINTF("Interrupts disabled, pil=%08x pil_in=%08x softint=%08x " "current interrupt %x\n", pil, env->pil_in, env->softint, env->interrupt_index); + env->interrupt_index = 0; + cpu_reset_interrupt(env, CPU_INTERRUPT_HARD); } } @@ -176,6 +176,7 @@ static void vga_update_memory_access(VGACommonState *s) size = 0x8000; break; case 3: + default: base = 0xb8000; size = 0x8000; break; diff --git a/hw/vhost.c b/hw/vhost.c index 18860678ba..0870cb7d85 100644 --- a/hw/vhost.c +++ b/hw/vhost.c @@ -515,11 +515,6 @@ static int vhost_virtqueue_init(struct vhost_dev *dev, }; struct VirtQueue *vvq = virtio_get_queue(vdev, idx); - if (!vdev->binding->set_host_notifier) { - fprintf(stderr, "binding does not support host notifiers\n"); - return -ENOSYS; - } - vq->num = state.num = virtio_queue_get_num(vdev, idx); r = ioctl(dev->control, VHOST_SET_VRING_NUM, &state); if (r) { @@ -567,12 +562,6 @@ static int vhost_virtqueue_init(struct vhost_dev *dev, r = -errno; goto fail_alloc; } - r = vdev->binding->set_host_notifier(vdev->binding_opaque, idx, true); - if (r < 0) { - fprintf(stderr, "Error binding host notifier: %d\n", -r); - goto fail_host_notifier; - } - file.fd = event_notifier_get_fd(virtio_queue_get_host_notifier(vvq)); r = ioctl(dev->control, VHOST_SET_VRING_KICK, &file); if (r) { @@ -591,8 +580,6 @@ static int vhost_virtqueue_init(struct vhost_dev *dev, fail_call: fail_kick: - vdev->binding->set_host_notifier(vdev->binding_opaque, idx, false); -fail_host_notifier: fail_alloc: cpu_physical_memory_unmap(vq->ring, virtio_queue_get_ring_size(vdev, idx), 0, 0); @@ -618,12 +605,6 @@ static void vhost_virtqueue_cleanup(struct vhost_dev *dev, .index = idx, }; int r; - r = vdev->binding->set_host_notifier(vdev->binding_opaque, idx, false); - if (r < 0) { - fprintf(stderr, "vhost VQ %d host cleanup failed: %d\n", idx, r); - fflush(stderr); - } - assert (r >= 0); r = ioctl(dev->control, VHOST_GET_VRING_BASE, &state); if (r < 0) { fprintf(stderr, "vhost VQ %d ring restore failed: %d\n", idx, r); @@ -697,6 +678,60 @@ bool vhost_dev_query(struct vhost_dev *hdev, VirtIODevice *vdev) hdev->force; } +/* Stop processing guest IO notifications in qemu. + * Start processing them in vhost in kernel. + */ +int vhost_dev_enable_notifiers(struct vhost_dev *hdev, VirtIODevice *vdev) +{ + int i, r; + if (!vdev->binding->set_host_notifier) { + fprintf(stderr, "binding does not support host notifiers\n"); + r = -ENOSYS; + goto fail; + } + + for (i = 0; i < hdev->nvqs; ++i) { + r = vdev->binding->set_host_notifier(vdev->binding_opaque, i, true); + if (r < 0) { + fprintf(stderr, "vhost VQ %d notifier binding failed: %d\n", i, -r); + goto fail_vq; + } + } + + return 0; +fail_vq: + while (--i >= 0) { + r = vdev->binding->set_host_notifier(vdev->binding_opaque, i, false); + if (r < 0) { + fprintf(stderr, "vhost VQ %d notifier cleanup error: %d\n", i, -r); + fflush(stderr); + } + assert (r >= 0); + } +fail: + return r; +} + +/* Stop processing guest IO notifications in vhost. + * Start processing them in qemu. + * This might actually run the qemu handlers right away, + * so virtio in qemu must be completely setup when this is called. + */ +void vhost_dev_disable_notifiers(struct vhost_dev *hdev, VirtIODevice *vdev) +{ + int i, r; + + for (i = 0; i < hdev->nvqs; ++i) { + r = vdev->binding->set_host_notifier(vdev->binding_opaque, i, false); + if (r < 0) { + fprintf(stderr, "vhost VQ %d notifier cleanup failed: %d\n", i, -r); + fflush(stderr); + } + assert (r >= 0); + } +} + +/* Host notifiers must be enabled at this point. */ int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev) { int i, r; @@ -762,6 +797,7 @@ fail: return r; } +/* Host notifiers must be enabled at this point. */ void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev) { int i, r; diff --git a/hw/vhost.h b/hw/vhost.h index c8c595a147..c9452f0732 100644 --- a/hw/vhost.h +++ b/hw/vhost.h @@ -46,5 +46,7 @@ void vhost_dev_cleanup(struct vhost_dev *hdev); bool vhost_dev_query(struct vhost_dev *hdev, VirtIODevice *vdev); int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev); void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev); +int vhost_dev_enable_notifiers(struct vhost_dev *hdev, VirtIODevice *vdev); +void vhost_dev_disable_notifiers(struct vhost_dev *hdev, VirtIODevice *vdev); #endif diff --git a/hw/vhost_net.c b/hw/vhost_net.c index a55981200d..950a6b8d99 100644 --- a/hw/vhost_net.c +++ b/hw/vhost_net.c @@ -139,16 +139,22 @@ int vhost_net_start(struct vhost_net *net, { struct vhost_vring_file file = { }; int r; + + net->dev.nvqs = 2; + net->dev.vqs = net->vqs; + + r = vhost_dev_enable_notifiers(&net->dev, dev); + if (r < 0) { + goto fail_notifiers; + } if (net->dev.acked_features & (1 << VIRTIO_NET_F_MRG_RXBUF)) { tap_set_vnet_hdr_len(net->vc, sizeof(struct virtio_net_hdr_mrg_rxbuf)); } - net->dev.nvqs = 2; - net->dev.vqs = net->vqs; r = vhost_dev_start(&net->dev, dev); if (r < 0) { - return r; + goto fail_start; } net->vc->info->poll(net->vc, false); @@ -173,6 +179,9 @@ fail: if (net->dev.acked_features & (1 << VIRTIO_NET_F_MRG_RXBUF)) { tap_set_vnet_hdr_len(net->vc, sizeof(struct virtio_net_hdr)); } +fail_start: + vhost_dev_disable_notifiers(&net->dev, dev); +fail_notifiers: return r; } @@ -190,6 +199,7 @@ void vhost_net_stop(struct vhost_net *net, if (net->dev.acked_features & (1 << VIRTIO_NET_F_MRG_RXBUF)) { tap_set_vnet_hdr_len(net->vc, sizeof(struct virtio_net_hdr)); } + vhost_dev_disable_notifiers(&net->dev, dev); } void vhost_net_cleanup(struct vhost_net *net) diff --git a/hw/xilinx_ethlite.c b/hw/xilinx_ethlite.c index f35ba8461a..6f44c8466e 100644 --- a/hw/xilinx_ethlite.c +++ b/hw/xilinx_ethlite.c @@ -50,6 +50,7 @@ struct xlx_ethlite { SysBusDevice busdev; + MemoryRegion mmio; qemu_irq irq; NICState *nic; NICConf conf; @@ -70,7 +71,8 @@ static inline void eth_pulse_irq(struct xlx_ethlite *s) } } -static uint32_t eth_readl (void *opaque, target_phys_addr_t addr) +static uint64_t +eth_read(void *opaque, target_phys_addr_t addr, unsigned int size) { struct xlx_ethlite *s = opaque; uint32_t r = 0; @@ -98,10 +100,12 @@ static uint32_t eth_readl (void *opaque, target_phys_addr_t addr) } static void -eth_writel (void *opaque, target_phys_addr_t addr, uint32_t value) +eth_write(void *opaque, target_phys_addr_t addr, + uint64_t val64, unsigned int size) { struct xlx_ethlite *s = opaque; unsigned int base = 0; + uint32_t value = val64; addr >>= 2; switch (addr) @@ -146,12 +150,14 @@ eth_writel (void *opaque, target_phys_addr_t addr, uint32_t value) } } -static CPUReadMemoryFunc * const eth_read[] = { - NULL, NULL, ð_readl, -}; - -static CPUWriteMemoryFunc * const eth_write[] = { - NULL, NULL, ð_writel, +static const MemoryRegionOps eth_ops = { + .read = eth_read, + .write = eth_write, + .endianness = DEVICE_NATIVE_ENDIAN, + .valid = { + .min_access_size = 4, + .max_access_size = 4 + } }; static int eth_can_rx(VLANClientState *nc) @@ -206,13 +212,12 @@ static NetClientInfo net_xilinx_ethlite_info = { static int xilinx_ethlite_init(SysBusDevice *dev) { struct xlx_ethlite *s = FROM_SYSBUS(typeof (*s), dev); - int regs; sysbus_init_irq(dev, &s->irq); s->rxbuf = 0; - regs = cpu_register_io_memory(eth_read, eth_write, s, DEVICE_NATIVE_ENDIAN); - sysbus_init_mmio(dev, R_MAX * 4, regs); + memory_region_init_io(&s->mmio, ð_ops, s, "xilinx-ethlite", R_MAX * 4); + sysbus_init_mmio_region(dev, &s->mmio); qemu_macaddr_default_if_unset(&s->conf.macaddr); s->nic = qemu_new_nic(&net_xilinx_ethlite_info, &s->conf, diff --git a/hw/xilinx_intc.c b/hw/xilinx_intc.c index cb72d5a14e..58b73d95cc 100644 --- a/hw/xilinx_intc.c +++ b/hw/xilinx_intc.c @@ -40,6 +40,7 @@ struct xlx_pic { SysBusDevice busdev; + MemoryRegion mmio; qemu_irq parent_irq; /* Configuration reg chosen at synthesis-time. QEMU populates @@ -72,7 +73,8 @@ static void update_irq(struct xlx_pic *p) } } -static uint32_t pic_readl (void *opaque, target_phys_addr_t addr) +static uint64_t +pic_read(void *opaque, target_phys_addr_t addr, unsigned int size) { struct xlx_pic *p = opaque; uint32_t r = 0; @@ -91,9 +93,11 @@ static uint32_t pic_readl (void *opaque, target_phys_addr_t addr) } static void -pic_writel (void *opaque, target_phys_addr_t addr, uint32_t value) +pic_write(void *opaque, target_phys_addr_t addr, + uint64_t val64, unsigned int size) { struct xlx_pic *p = opaque; + uint32_t value = val64; addr >>= 2; D(qemu_log("%s addr=%x val=%x\n", __func__, addr * 4, value)); @@ -116,14 +120,14 @@ pic_writel (void *opaque, target_phys_addr_t addr, uint32_t value) update_irq(p); } -static CPUReadMemoryFunc * const pic_read[] = { - NULL, NULL, - &pic_readl, -}; - -static CPUWriteMemoryFunc * const pic_write[] = { - NULL, NULL, - &pic_writel, +static const MemoryRegionOps pic_ops = { + .read = pic_read, + .write = pic_write, + .endianness = DEVICE_NATIVE_ENDIAN, + .valid = { + .min_access_size = 4, + .max_access_size = 4 + } }; static void irq_handler(void *opaque, int irq, int level) @@ -148,13 +152,12 @@ static void irq_handler(void *opaque, int irq, int level) static int xilinx_intc_init(SysBusDevice *dev) { struct xlx_pic *p = FROM_SYSBUS(typeof (*p), dev); - int pic_regs; qdev_init_gpio_in(&dev->qdev, irq_handler, 32); sysbus_init_irq(dev, &p->parent_irq); - pic_regs = cpu_register_io_memory(pic_read, pic_write, p, DEVICE_NATIVE_ENDIAN); - sysbus_init_mmio(dev, R_MAX * 4, pic_regs); + memory_region_init_io(&p->mmio, &pic_ops, p, "xilinx-pic", R_MAX * 4); + sysbus_init_mmio_region(dev, &p->mmio); return 0; } diff --git a/hw/xilinx_timer.c b/hw/xilinx_timer.c index f1c7abc99e..8779c56f0b 100644 --- a/hw/xilinx_timer.c +++ b/hw/xilinx_timer.c @@ -59,6 +59,7 @@ struct xlx_timer struct timerblock { SysBusDevice busdev; + MemoryRegion mmio; qemu_irq irq; uint32_t nr_timers; uint32_t freq_hz; @@ -85,7 +86,8 @@ static void timer_update_irq(struct timerblock *t) qemu_set_irq(t->irq, !!irq); } -static uint32_t timer_readl (void *opaque, target_phys_addr_t addr) +static uint64_t +timer_read(void *opaque, target_phys_addr_t addr, unsigned int size) { struct timerblock *t = opaque; struct xlx_timer *xt; @@ -134,11 +136,13 @@ static void timer_enable(struct xlx_timer *xt) } static void -timer_writel (void *opaque, target_phys_addr_t addr, uint32_t value) +timer_write(void *opaque, target_phys_addr_t addr, + uint64_t val64, unsigned int size) { struct timerblock *t = opaque; struct xlx_timer *xt; unsigned int timer; + uint32_t value = val64; addr >>= 2; timer = timer_from_addr(addr); @@ -166,14 +170,14 @@ timer_writel (void *opaque, target_phys_addr_t addr, uint32_t value) timer_update_irq(t); } -static CPUReadMemoryFunc * const timer_read[] = { - NULL, NULL, - &timer_readl, -}; - -static CPUWriteMemoryFunc * const timer_write[] = { - NULL, NULL, - &timer_writel, +static const MemoryRegionOps timer_ops = { + .read = timer_read, + .write = timer_write, + .endianness = DEVICE_NATIVE_ENDIAN, + .valid = { + .min_access_size = 4, + .max_access_size = 4 + } }; static void timer_hit(void *opaque) @@ -192,7 +196,6 @@ static int xilinx_timer_init(SysBusDevice *dev) { struct timerblock *t = FROM_SYSBUS(typeof (*t), dev); unsigned int i; - int timer_regs; /* All timers share a single irq line. */ sysbus_init_irq(dev, &t->irq); @@ -209,9 +212,9 @@ static int xilinx_timer_init(SysBusDevice *dev) ptimer_set_freq(xt->ptimer, t->freq_hz); } - timer_regs = cpu_register_io_memory(timer_read, timer_write, t, - DEVICE_NATIVE_ENDIAN); - sysbus_init_mmio(dev, R_MAX * 4 * t->nr_timers, timer_regs); + memory_region_init_io(&t->mmio, &timer_ops, t, "xilinx-timer", + R_MAX * 4 * t->nr_timers); + sysbus_init_mmio_region(dev, &t->mmio); return 0; } diff --git a/hw/xilinx_uartlite.c b/hw/xilinx_uartlite.c index 467a26cc9e..ceb7b4d9ed 100644 --- a/hw/xilinx_uartlite.c +++ b/hw/xilinx_uartlite.c @@ -49,6 +49,7 @@ struct xlx_uartlite { SysBusDevice busdev; + MemoryRegion mmio; CharDriverState *chr; qemu_irq irq; @@ -82,7 +83,8 @@ static void uart_update_status(struct xlx_uartlite *s) s->regs[R_STATUS] = r; } -static uint32_t uart_readl (void *opaque, target_phys_addr_t addr) +static uint64_t +uart_read(void *opaque, target_phys_addr_t addr, unsigned int size) { struct xlx_uartlite *s = opaque; uint32_t r = 0; @@ -107,9 +109,11 @@ static uint32_t uart_readl (void *opaque, target_phys_addr_t addr) } static void -uart_writel (void *opaque, target_phys_addr_t addr, uint32_t value) +uart_write(void *opaque, target_phys_addr_t addr, + uint64_t val64, unsigned int size) { struct xlx_uartlite *s = opaque; + uint32_t value = val64; unsigned char ch = value; addr >>= 2; @@ -147,16 +151,14 @@ uart_writel (void *opaque, target_phys_addr_t addr, uint32_t value) uart_update_irq(s); } -static CPUReadMemoryFunc * const uart_read[] = { - &uart_readl, - &uart_readl, - &uart_readl, -}; - -static CPUWriteMemoryFunc * const uart_write[] = { - &uart_writel, - &uart_writel, - &uart_writel, +static const MemoryRegionOps uart_ops = { + .read = uart_read, + .write = uart_write, + .endianness = DEVICE_NATIVE_ENDIAN, + .valid = { + .min_access_size = 1, + .max_access_size = 4 + } }; static void uart_rx(void *opaque, const uint8_t *buf, int size) @@ -196,14 +198,12 @@ static void uart_event(void *opaque, int event) static int xilinx_uartlite_init(SysBusDevice *dev) { struct xlx_uartlite *s = FROM_SYSBUS(typeof (*s), dev); - int uart_regs; sysbus_init_irq(dev, &s->irq); uart_update_status(s); - uart_regs = cpu_register_io_memory(uart_read, uart_write, s, - DEVICE_NATIVE_ENDIAN); - sysbus_init_mmio(dev, R_MAX * 4, uart_regs); + memory_region_init_io(&s->mmio, &uart_ops, s, "xilinx-uartlite", R_MAX * 4); + sysbus_init_mmio_region(dev, &s->mmio); s->chr = qdev_init_chardev(&dev->qdev); if (s->chr) @@ -42,16 +42,16 @@ SECTIONS .rel.plt : { *(.rel.plt) - PROVIDE_HIDDEN (__rel_iplt_start = .); + PROVIDE (__rel_iplt_start = .); *(.rel.iplt) - PROVIDE_HIDDEN (__rel_iplt_end = .); + PROVIDE (__rel_iplt_end = .); } .rela.plt : { *(.rela.plt) - PROVIDE_HIDDEN (__rela_iplt_start = .); + PROVIDE (__rela_iplt_start = .); *(.rela.iplt) - PROVIDE_HIDDEN (__rela_iplt_end = .); + PROVIDE (__rela_iplt_end = .); } .init : { *(.init) } =0x47ff041f .text : diff --git a/libcacard/Makefile b/libcacard/Makefile index b3f5e6c011..bf052bcc12 100644 --- a/libcacard/Makefile +++ b/libcacard/Makefile @@ -20,7 +20,7 @@ QEMU_CFLAGS+=$(GLIB_CFLAGS) libcacard.lib-y=$(addsuffix .lo,$(basename $(libcacard-y))) vscclient: $(libcacard-y) $(QEMU_OBJS) vscclient.o - $(call quiet-command,$(CC) -o $@ $^ $(libcacard_libs) $(LIBS) -lrt," LINK $@") + $(call quiet-command,$(CC) -o $@ $^ $(libcacard_libs) $(LIBS)," LINK $@") clean: rm -f *.o */*.o *.d */*.d *.a */*.a *~ */*~ vscclient *.lo .libs/* *.la *.pc @@ -39,7 +39,7 @@ install-libcacard: @echo "libtool is missing, please install and rerun configure"; exit 1 else libcacard.la: $(libcacard.lib-y) $(QEMU_OBJS_LIB) - $(call quiet-command,$(LIBTOOL) --mode=link --quiet --tag=CC $(CC) -rpath $(libdir) -o $@ $^ $(libcacard_libs) -lrt," lt LINK $@") + $(call quiet-command,$(LIBTOOL) --mode=link --quiet --tag=CC $(CC) -rpath $(libdir) -o $@ $^ $(libcacard_libs)," lt LINK $@") libcacard.pc: $(libcacard_srcpath)/libcacard.pc.in sed -e 's|@LIBDIR@|$(libdir)|' \ diff --git a/linux-user/signal.c b/linux-user/signal.c index 07ad07a58f..89276eb6a5 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -3064,10 +3064,10 @@ static void setup_frame(int sig, struct target_sigaction *ka, goto give_sigsegv; /* Set up registers for signal handler */ - regs->gregs[15] = (unsigned long) frame; + regs->gregs[15] = frame_addr; regs->gregs[4] = signal; /* Arg for signal handler */ regs->gregs[5] = 0; - regs->gregs[6] = (unsigned long) &frame->sc; + regs->gregs[6] = frame_addr += offsetof(typeof(*frame), sc); regs->pc = (unsigned long) ka->_sa_handler; unlock_user_struct(frame, frame_addr, 1); @@ -3127,10 +3127,10 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka, goto give_sigsegv; /* Set up registers for signal handler */ - regs->gregs[15] = (unsigned long) frame; + regs->gregs[15] = frame_addr; regs->gregs[4] = signal; /* Arg for signal handler */ - regs->gregs[5] = (unsigned long) &frame->info; - regs->gregs[6] = (unsigned long) &frame->uc; + regs->gregs[5] = frame_addr + offsetof(typeof(*frame), info); + regs->gregs[6] = frame_addr + offsetof(typeof(*frame), uc); regs->pc = (unsigned long) ka->_sa_handler; unlock_user_struct(frame, frame_addr, 1); @@ -3381,11 +3381,12 @@ static void setup_frame(int sig, struct target_sigaction *ka, goto badframe; /* Set up registers for signal handler */ - env->regs[1] = (unsigned long) frame; + env->regs[1] = frame_addr; /* Signal handler args: */ env->regs[5] = sig; /* Arg 0: signum */ env->regs[6] = 0; - env->regs[7] = (unsigned long) &frame->uc; /* arg 1: sigcontext */ + /* arg 1: sigcontext */ + env->regs[7] = frame_addr += offsetof(typeof(*frame), uc); /* Offset of 4 to handle microblaze rtid r14, 0 */ env->sregs[SR_PC] = (unsigned long)ka->_sa_handler; @@ -3559,11 +3560,11 @@ static void setup_frame(int sig, struct target_sigaction *ka, setup_sigcontext(&frame->sc, env); /* Move the stack and setup the arguments for the handler. */ - env->regs[R_SP] = (uint32_t) (unsigned long) frame; + env->regs[R_SP] = frame_addr; env->regs[10] = sig; env->pc = (unsigned long) ka->_sa_handler; /* Link SRP so the guest returns through the trampoline. */ - env->pregs[PR_SRP] = (uint32_t) (unsigned long) &frame->retcode[0]; + env->pregs[PR_SRP] = frame_addr + offsetof(typeof(*frame), retcode); unlock_user_struct(frame, frame_addr, 1); return; @@ -3769,11 +3770,11 @@ static void setup_frame(int sig, struct target_sigaction *ka, } /* Set up registers for signal handler */ - env->regs[15] = (target_ulong)(unsigned long) frame; + env->regs[15] = frame_addr; env->psw.addr = (target_ulong) ka->_sa_handler | PSW_ADDR_AMODE; env->regs[2] = sig; //map_signal(sig); - env->regs[3] = (target_ulong)(unsigned long) &frame->sc; + env->regs[3] = frame_addr += offsetof(typeof(*frame), sc); /* We forgot to include these in the sigcontext. To avoid breaking binary compatibility, they are passed as args. */ @@ -3844,12 +3845,12 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka, } /* Set up registers for signal handler */ - env->regs[15] = (target_ulong)(unsigned long) frame; + env->regs[15] = frame_addr; env->psw.addr = (target_ulong) ka->_sa_handler | PSW_ADDR_AMODE; env->regs[2] = sig; //map_signal(sig); - env->regs[3] = (target_ulong)(unsigned long) &frame->info; - env->regs[4] = (target_ulong)(unsigned long) &frame->uc; + env->regs[3] = frame_addr + offsetof(typeof(*frame), info); + env->regs[4] = frame_addr + offsetof(typeof(*frame), uc); return; give_sigsegv: @@ -304,7 +304,7 @@ static void as_memory_range_add(AddressSpace *as, FlatRange *fr) } if (!fr->readable) { - phys_offset &= TARGET_PAGE_MASK; + phys_offset &= ~TARGET_PAGE_MASK & ~IO_MEM_ROMD; } cpu_register_physical_memory_log(fr->addr.start, @@ -962,11 +962,14 @@ void memory_region_init_alias(MemoryRegion *mr, void memory_region_init_rom_device(MemoryRegion *mr, const MemoryRegionOps *ops, + void *opaque, DeviceState *dev, const char *name, uint64_t size) { memory_region_init(mr, name, size); + mr->ops = ops; + mr->opaque = opaque; mr->terminates = true; mr->destructor = memory_region_destructor_rom_device; mr->ram_addr = qemu_ram_alloc(dev, name, size); @@ -235,6 +235,7 @@ void memory_region_init_alias(MemoryRegion *mr, */ void memory_region_init_rom_device(MemoryRegion *mr, const MemoryRegionOps *ops, + void *opaque, DeviceState *dev, /* FIXME: layering violation */ const char *name, uint64_t size); @@ -79,36 +79,34 @@ SECTIONS } .sbss2 : { *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) } .eh_frame_hdr : { *(.eh_frame_hdr) } - .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) } - .gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) } /* Adjust the address for the data segment. We want to adjust up to the same address within the page on the next page up. */ . = ALIGN (0x40000) - ((0x40000 - .) & (0x40000 - 1)); . = DATA_SEGMENT_ALIGN (0x40000, 0x1000); /* Exception handling */ - .eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) } - .gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) } + .eh_frame : { KEEP (*(.eh_frame)) } + .gcc_except_table : { *(.gcc_except_table .gcc_except_table.*) } /* Thread Local Storage sections */ .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) } .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } .preinit_array : { - PROVIDE_HIDDEN (__preinit_array_start = .); + PROVIDE (__preinit_array_start = .); KEEP (*(.preinit_array)) - PROVIDE_HIDDEN (__preinit_array_end = .); + PROVIDE (__preinit_array_end = .); } .init_array : { - PROVIDE_HIDDEN (__init_array_start = .); + PROVIDE (__init_array_start = .); KEEP (*(SORT(.init_array.*))) KEEP (*(.init_array)) - PROVIDE_HIDDEN (__init_array_end = .); + PROVIDE (__init_array_end = .); } .fini_array : { - PROVIDE_HIDDEN (__fini_array_start = .); + PROVIDE (__fini_array_start = .); KEEP (*(.fini_array)) KEEP (*(SORT(.fini_array.*))) - PROVIDE_HIDDEN (__fini_array_end = .); + PROVIDE (__fini_array_end = .); } .ctors : { @@ -1189,7 +1189,6 @@ static int add_graphics_client(Monitor *mon, const QDict *qdict, QObject **ret_d { const char *protocol = qdict_get_str(qdict, "protocol"); const char *fdname = qdict_get_str(qdict, "fdname"); - int skipauth = qdict_get_try_bool(qdict, "skipauth", 0); CharDriverState *s; if (strcmp(protocol, "spice") == 0) { @@ -1203,6 +1202,7 @@ static int add_graphics_client(Monitor *mon, const QDict *qdict, QObject **ret_d #ifdef CONFIG_VNC } else if (strcmp(protocol, "vnc") == 0) { int fd = monitor_get_fd(mon, fdname); + int skipauth = qdict_get_try_bool(qdict, "skipauth", 0); vnc_display_add_client(NULL, fd, skipauth); return 0; #endif @@ -79,36 +79,34 @@ SECTIONS } .sbss2 : { *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) } .eh_frame_hdr : { *(.eh_frame_hdr) } - .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) } - .gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) } /* Adjust the address for the data segment. We want to adjust up to the same address within the page on the next page up. */ . = ALIGN (0x10000) - ((0x10000 - .) & (0x10000 - 1)); . = DATA_SEGMENT_ALIGN (0x10000, 0x1000); /* Exception handling */ - .eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) } - .gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) } + .eh_frame : { KEEP (*(.eh_frame)) } + .gcc_except_table : { *(.gcc_except_table .gcc_except_table.*) } /* Thread Local Storage sections */ .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) } .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } .preinit_array : { - PROVIDE_HIDDEN (__preinit_array_start = .); + PROVIDE (__preinit_array_start = .); KEEP (*(.preinit_array)) - PROVIDE_HIDDEN (__preinit_array_end = .); + PROVIDE (__preinit_array_end = .); } .init_array : { - PROVIDE_HIDDEN (__init_array_start = .); + PROVIDE (__init_array_start = .); KEEP (*(SORT(.init_array.*))) KEEP (*(.init_array)) - PROVIDE_HIDDEN (__init_array_end = .); + PROVIDE (__init_array_end = .); } .fini_array : { - PROVIDE_HIDDEN (__fini_array_start = .); + PROVIDE (__fini_array_start = .); KEEP (*(.fini_array)) KEEP (*(SORT(.fini_array.*))) - PROVIDE_HIDDEN (__fini_array_end = .); + PROVIDE (__fini_array_end = .); } .ctors : { @@ -81,14 +81,12 @@ SECTIONS .sdata2 : { *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) } .sbss2 : { *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) } .eh_frame_hdr : { *(.eh_frame_hdr) } - .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) } - .gcc_except_table : ONLY_IF_RO { KEEP (*(.gcc_except_table)) *(.gcc_except_table.*) } /* Adjust the address for the data segment. We want to adjust up to + the same address within the page on the next page up. */ . = ALIGN (0x10000) - ((0x10000 - .) & (0x10000 - 1)); . = DATA_SEGMENT_ALIGN (0x10000, 0x1000); /* Exception handling */ - .eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) } - .gcc_except_table : ONLY_IF_RW { KEEP (*(.gcc_except_table)) + .eh_frame : { KEEP (*(.eh_frame)) } + .gcc_except_table : { KEEP (*(.gcc_except_table)) *(.gcc_except_table.*) } /* Thread Local Storage sections */ .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) } .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 3498425fff..0eba357cc2 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -2532,7 +2532,7 @@ sub process { $allowed = 1; } } - if (!$seen) { + if ($seen != ($#chunks + 1)) { WARN("braces {} are necessary for all arms of this statement\n" . $herectx); } } @@ -67,23 +67,23 @@ SECTIONS .tbss : { *(.tbss) } .preinit_array : { - PROVIDE_HIDDEN (__preinit_array_start = .); + PROVIDE (__preinit_array_start = .); KEEP (*(.preinit_array)) - PROVIDE_HIDDEN (__preinit_array_end = .); + PROVIDE (__preinit_array_end = .); } .init_array : { - PROVIDE_HIDDEN (__init_array_start = .); + PROVIDE (__init_array_start = .); KEEP (*(SORT(.init_array.*))) KEEP (*(.init_array)) - PROVIDE_HIDDEN (__init_array_end = .); + PROVIDE (__init_array_end = .); } .fini_array : { - PROVIDE_HIDDEN (__fini_array_start = .); + PROVIDE (__fini_array_start = .); KEEP (*(.fini_array)) KEEP (*(SORT(.fini_array.*))) - PROVIDE_HIDDEN (__fini_array_end = .); + PROVIDE (__fini_array_end = .); } .ctors : { diff --git a/target-i386/kvm.c b/target-i386/kvm.c index bd850ed7c0..1d9b20c706 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -501,8 +501,9 @@ int kvm_arch_init_vcpu(CPUState *env) qemu_add_vm_change_state_handler(cpu_update_state, env); r = kvm_vcpu_ioctl(env, KVM_SET_CPUID2, &cpuid_data); - if (r) - return r; + if (r) { + return r; + } r = kvm_check_extension(env->kvm_state, KVM_CAP_TSC_CONTROL); if (r && env->tsc_khz) { diff --git a/target-microblaze/cpu.h b/target-microblaze/cpu.h index a81da629de..35302863cb 100644 --- a/target-microblaze/cpu.h +++ b/target-microblaze/cpu.h @@ -65,6 +65,7 @@ struct CPUMBState; #define MSR_DCE (1<<7) /* 0x080 */ #define MSR_EE (1<<8) /* 0x100 */ #define MSR_EIP (1<<9) /* 0x200 */ +#define MSR_PVR (1<<10) /* 0x400 */ #define MSR_CC (1<<31) /* Machine State Register (MSR) Fields */ diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c index 1a862d31e3..366fd3e607 100644 --- a/target-microblaze/translate.c +++ b/target-microblaze/translate.c @@ -424,10 +424,15 @@ static inline void msr_read(DisasContext *dc, TCGv d) static inline void msr_write(DisasContext *dc, TCGv v) { + TCGv t; + + t = tcg_temp_new(); dc->cpustate_changed = 1; - tcg_gen_mov_tl(cpu_SR[SR_MSR], v); - /* PVR, we have a processor version register. */ - tcg_gen_ori_tl(cpu_SR[SR_MSR], cpu_SR[SR_MSR], (1 << 10)); + /* PVR bit is not writable. */ + tcg_gen_andi_tl(t, v, ~MSR_PVR); + tcg_gen_andi_tl(cpu_SR[SR_MSR], cpu_SR[SR_MSR], MSR_PVR); + tcg_gen_or_tl(cpu_SR[SR_MSR], cpu_SR[SR_MSR], v); + tcg_temp_free(t); } static void dec_msr(DisasContext *dc) diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h index 024eb6f8ab..b8d42e0b2c 100644 --- a/target-ppc/cpu.h +++ b/target-ppc/cpu.h @@ -516,7 +516,22 @@ struct ppc_slb_t { #endif /* Exception state register bits definition */ -#define ESR_ST 23 /* Exception was caused by a store type access. */ +#define ESR_PIL (1 << (63 - 36)) /* Illegal Instruction */ +#define ESR_PPR (1 << (63 - 37)) /* Privileged Instruction */ +#define ESR_PTR (1 << (63 - 38)) /* Trap */ +#define ESR_FP (1 << (63 - 39)) /* Floating-Point Operation */ +#define ESR_ST (1 << (63 - 40)) /* Store Operation */ +#define ESR_AP (1 << (63 - 44)) /* Auxiliary Processor Operation */ +#define ESR_PUO (1 << (63 - 45)) /* Unimplemented Operation */ +#define ESR_BO (1 << (63 - 46)) /* Byte Ordering */ +#define ESR_PIE (1 << (63 - 47)) /* Imprecise exception */ +#define ESR_DATA (1 << (63 - 53)) /* Data Access (Embedded page table) */ +#define ESR_TLBI (1 << (63 - 54)) /* TLB Ineligible (Embedded page table) */ +#define ESR_PT (1 << (63 - 55)) /* Page Table (Embedded page table) */ +#define ESR_SPV (1 << (63 - 56)) /* SPE/VMX operation */ +#define ESR_EPID (1 << (63 - 57)) /* External Process ID operation */ +#define ESR_VLEMI (1 << (63 - 58)) /* VLE operation */ +#define ESR_MIF (1 << (63 - 62)) /* Misaligned instruction (VLE) */ enum { POWERPC_FLAG_NONE = 0x00000000, diff --git a/target-ppc/helper.c b/target-ppc/helper.c index 3abab1a22c..5ec83f2c66 100644 --- a/target-ppc/helper.c +++ b/target-ppc/helper.c @@ -1837,7 +1837,7 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw, env->exception_index = POWERPC_EXCP_DTLB; env->error_code = 0; env->spr[SPR_BOOKE_DEAR] = address; - env->spr[SPR_BOOKE_ESR] = rw ? 1 << ESR_ST : 0; + env->spr[SPR_BOOKE_ESR] = rw ? ESR_ST : 0; return -1; case POWERPC_MMU_REAL: cpu_abort(env, "PowerPC in real mode should never raise " @@ -1861,7 +1861,7 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw, } else if ((env->mmu_model == POWERPC_MMU_BOOKE) || (env->mmu_model == POWERPC_MMU_BOOKE206)) { env->spr[SPR_BOOKE_DEAR] = address; - env->spr[SPR_BOOKE_ESR] = rw ? 1 << ESR_ST : 0; + env->spr[SPR_BOOKE_ESR] = rw ? ESR_ST : 0; } else { env->spr[SPR_DAR] = address; if (rw == 1) { @@ -2484,16 +2484,19 @@ static inline void powerpc_excp(CPUState *env, int excp_model, int excp) if (lpes1 == 0) new_msr |= (target_ulong)MSR_HVB; msr |= 0x00080000; + env->spr[SPR_BOOKE_ESR] = ESR_PIL; break; case POWERPC_EXCP_PRIV: if (lpes1 == 0) new_msr |= (target_ulong)MSR_HVB; msr |= 0x00040000; + env->spr[SPR_BOOKE_ESR] = ESR_PPR; break; case POWERPC_EXCP_TRAP: if (lpes1 == 0) new_msr |= (target_ulong)MSR_HVB; msr |= 0x00020000; + env->spr[SPR_BOOKE_ESR] = ESR_PTR; break; default: /* Should never occur */ @@ -2556,16 +2559,19 @@ static inline void powerpc_excp(CPUState *env, int excp_model, int excp) cpu_abort(env, "Debug exception is not implemented yet !\n"); goto store_next; case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavailable */ + env->spr[SPR_BOOKE_ESR] = ESR_SPV; goto store_current; case POWERPC_EXCP_EFPDI: /* Embedded floating-point data interrupt */ /* XXX: TODO */ cpu_abort(env, "Embedded floating point data exception " "is not implemented yet !\n"); + env->spr[SPR_BOOKE_ESR] = ESR_SPV; goto store_next; case POWERPC_EXCP_EFPRI: /* Embedded floating-point round interrupt */ /* XXX: TODO */ cpu_abort(env, "Embedded floating point round exception " "is not implemented yet !\n"); + env->spr[SPR_BOOKE_ESR] = ESR_SPV; goto store_next; case POWERPC_EXCP_EPERFM: /* Embedded performance monitor interrupt */ /* XXX: TODO */ diff --git a/target-ppc/translate.c b/target-ppc/translate.c index fd7c2087d7..4277460692 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -6622,7 +6622,7 @@ static inline void gen_evmra(DisasContext *ctx) { if (unlikely(!ctx->spe_enabled)) { - gen_exception(ctx, POWERPC_EXCP_APU); + gen_exception(ctx, POWERPC_EXCP_SPEU); return; } @@ -6693,7 +6693,7 @@ static inline void gen_speundef(DisasContext *ctx) static inline void gen_##name(DisasContext *ctx) \ { \ if (unlikely(!ctx->spe_enabled)) { \ - gen_exception(ctx, POWERPC_EXCP_APU); \ + gen_exception(ctx, POWERPC_EXCP_SPEU); \ return; \ } \ tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], \ @@ -6704,7 +6704,7 @@ static inline void gen_##name(DisasContext *ctx) \ static inline void gen_##name(DisasContext *ctx) \ { \ if (unlikely(!ctx->spe_enabled)) { \ - gen_exception(ctx, POWERPC_EXCP_APU); \ + gen_exception(ctx, POWERPC_EXCP_SPEU); \ return; \ } \ tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], \ @@ -6729,7 +6729,7 @@ GEN_SPEOP_LOGIC2(evnand, tcg_gen_nand_tl); static inline void gen_##name(DisasContext *ctx) \ { \ if (unlikely(!ctx->spe_enabled)) { \ - gen_exception(ctx, POWERPC_EXCP_APU); \ + gen_exception(ctx, POWERPC_EXCP_SPEU); \ return; \ } \ TCGv_i32 t0 = tcg_temp_local_new_i32(); \ @@ -6750,7 +6750,7 @@ static inline void gen_##name(DisasContext *ctx) \ static inline void gen_##name(DisasContext *ctx) \ { \ if (unlikely(!ctx->spe_enabled)) { \ - gen_exception(ctx, POWERPC_EXCP_APU); \ + gen_exception(ctx, POWERPC_EXCP_SPEU); \ return; \ } \ tcg_opi(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], \ @@ -6770,7 +6770,7 @@ GEN_SPEOP_TCG_LOGIC_IMM2(evrlwi, tcg_gen_rotli_i32); static inline void gen_##name(DisasContext *ctx) \ { \ if (unlikely(!ctx->spe_enabled)) { \ - gen_exception(ctx, POWERPC_EXCP_APU); \ + gen_exception(ctx, POWERPC_EXCP_SPEU); \ return; \ } \ TCGv_i32 t0 = tcg_temp_local_new_i32(); \ @@ -6791,7 +6791,7 @@ static inline void gen_##name(DisasContext *ctx) \ static inline void gen_##name(DisasContext *ctx) \ { \ if (unlikely(!ctx->spe_enabled)) { \ - gen_exception(ctx, POWERPC_EXCP_APU); \ + gen_exception(ctx, POWERPC_EXCP_SPEU); \ return; \ } \ tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]); \ @@ -6829,7 +6829,7 @@ GEN_SPEOP_ARITH1(evcntlzw, gen_helper_cntlzw32); static inline void gen_##name(DisasContext *ctx) \ { \ if (unlikely(!ctx->spe_enabled)) { \ - gen_exception(ctx, POWERPC_EXCP_APU); \ + gen_exception(ctx, POWERPC_EXCP_SPEU); \ return; \ } \ TCGv_i32 t0 = tcg_temp_local_new_i32(); \ @@ -6855,7 +6855,7 @@ static inline void gen_##name(DisasContext *ctx) \ static inline void gen_##name(DisasContext *ctx) \ { \ if (unlikely(!ctx->spe_enabled)) { \ - gen_exception(ctx, POWERPC_EXCP_APU); \ + gen_exception(ctx, POWERPC_EXCP_SPEU); \ return; \ } \ tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], \ @@ -6933,7 +6933,7 @@ GEN_SPEOP_ARITH2(evrlw, gen_op_evrlw); static inline void gen_evmergehi(DisasContext *ctx) { if (unlikely(!ctx->spe_enabled)) { - gen_exception(ctx, POWERPC_EXCP_APU); + gen_exception(ctx, POWERPC_EXCP_SPEU); return; } #if defined(TARGET_PPC64) @@ -6962,7 +6962,7 @@ GEN_SPEOP_ARITH2(evsubfw, gen_op_evsubf); static inline void gen_##name(DisasContext *ctx) \ { \ if (unlikely(!ctx->spe_enabled)) { \ - gen_exception(ctx, POWERPC_EXCP_APU); \ + gen_exception(ctx, POWERPC_EXCP_SPEU); \ return; \ } \ TCGv_i32 t0 = tcg_temp_local_new_i32(); \ @@ -6983,7 +6983,7 @@ static inline void gen_##name(DisasContext *ctx) \ static inline void gen_##name(DisasContext *ctx) \ { \ if (unlikely(!ctx->spe_enabled)) { \ - gen_exception(ctx, POWERPC_EXCP_APU); \ + gen_exception(ctx, POWERPC_EXCP_SPEU); \ return; \ } \ tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], \ @@ -7001,7 +7001,7 @@ GEN_SPEOP_ARITH_IMM2(evsubifw, tcg_gen_subi_i32); static inline void gen_##name(DisasContext *ctx) \ { \ if (unlikely(!ctx->spe_enabled)) { \ - gen_exception(ctx, POWERPC_EXCP_APU); \ + gen_exception(ctx, POWERPC_EXCP_SPEU); \ return; \ } \ int l1 = gen_new_label(); \ @@ -7041,7 +7041,7 @@ static inline void gen_##name(DisasContext *ctx) \ static inline void gen_##name(DisasContext *ctx) \ { \ if (unlikely(!ctx->spe_enabled)) { \ - gen_exception(ctx, POWERPC_EXCP_APU); \ + gen_exception(ctx, POWERPC_EXCP_SPEU); \ return; \ } \ int l1 = gen_new_label(); \ @@ -7084,7 +7084,7 @@ static inline void gen_brinc(DisasContext *ctx) static inline void gen_evmergelo(DisasContext *ctx) { if (unlikely(!ctx->spe_enabled)) { - gen_exception(ctx, POWERPC_EXCP_APU); + gen_exception(ctx, POWERPC_EXCP_SPEU); return; } #if defined(TARGET_PPC64) @@ -7103,7 +7103,7 @@ static inline void gen_evmergelo(DisasContext *ctx) static inline void gen_evmergehilo(DisasContext *ctx) { if (unlikely(!ctx->spe_enabled)) { - gen_exception(ctx, POWERPC_EXCP_APU); + gen_exception(ctx, POWERPC_EXCP_SPEU); return; } #if defined(TARGET_PPC64) @@ -7122,7 +7122,7 @@ static inline void gen_evmergehilo(DisasContext *ctx) static inline void gen_evmergelohi(DisasContext *ctx) { if (unlikely(!ctx->spe_enabled)) { - gen_exception(ctx, POWERPC_EXCP_APU); + gen_exception(ctx, POWERPC_EXCP_SPEU); return; } #if defined(TARGET_PPC64) @@ -7245,7 +7245,7 @@ static inline void gen_evmwumi(DisasContext *ctx) TCGv_i64 t0, t1; if (unlikely(!ctx->spe_enabled)) { - gen_exception(ctx, POWERPC_EXCP_APU); + gen_exception(ctx, POWERPC_EXCP_SPEU); return; } @@ -7274,7 +7274,7 @@ static inline void gen_evmwumia(DisasContext *ctx) TCGv_i64 tmp; if (unlikely(!ctx->spe_enabled)) { - gen_exception(ctx, POWERPC_EXCP_APU); + gen_exception(ctx, POWERPC_EXCP_SPEU); return; } @@ -7294,7 +7294,7 @@ static inline void gen_evmwumiaa(DisasContext *ctx) TCGv_i64 tmp; if (unlikely(!ctx->spe_enabled)) { - gen_exception(ctx, POWERPC_EXCP_APU); + gen_exception(ctx, POWERPC_EXCP_SPEU); return; } @@ -7327,7 +7327,7 @@ static inline void gen_evmwsmi(DisasContext *ctx) TCGv_i64 t0, t1; if (unlikely(!ctx->spe_enabled)) { - gen_exception(ctx, POWERPC_EXCP_APU); + gen_exception(ctx, POWERPC_EXCP_SPEU); return; } @@ -7746,7 +7746,7 @@ static void glue(gen_, name)(DisasContext *ctx) { \ TCGv t0; \ if (unlikely(!ctx->spe_enabled)) { \ - gen_exception(ctx, POWERPC_EXCP_APU); \ + gen_exception(ctx, POWERPC_EXCP_SPEU); \ return; \ } \ gen_set_access_type(ctx, ACCESS_INT); \ @@ -7904,7 +7904,7 @@ static inline void gen_##name(DisasContext *ctx) \ TCGv_i32 t0, t1; \ TCGv_i64 t2; \ if (unlikely(!ctx->spe_enabled)) { \ - gen_exception(ctx, POWERPC_EXCP_APU); \ + gen_exception(ctx, POWERPC_EXCP_SPEU); \ return; \ } \ t0 = tcg_temp_new_i32(); \ @@ -7925,7 +7925,7 @@ static inline void gen_##name(DisasContext *ctx) \ static inline void gen_##name(DisasContext *ctx) \ { \ if (unlikely(!ctx->spe_enabled)) { \ - gen_exception(ctx, POWERPC_EXCP_APU); \ + gen_exception(ctx, POWERPC_EXCP_SPEU); \ return; \ } \ gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], \ @@ -7936,7 +7936,7 @@ static inline void gen_##name(DisasContext *ctx) \ { \ TCGv_i32 t0, t1; \ if (unlikely(!ctx->spe_enabled)) { \ - gen_exception(ctx, POWERPC_EXCP_APU); \ + gen_exception(ctx, POWERPC_EXCP_SPEU); \ return; \ } \ t0 = tcg_temp_new_i32(); \ @@ -7951,7 +7951,7 @@ static inline void gen_##name(DisasContext *ctx) \ static inline void gen_##name(DisasContext *ctx) \ { \ if (unlikely(!ctx->spe_enabled)) { \ - gen_exception(ctx, POWERPC_EXCP_APU); \ + gen_exception(ctx, POWERPC_EXCP_SPEU); \ return; \ } \ gen_helper_##name(cpu_crf[crfD(ctx->opcode)], \ @@ -7992,7 +7992,7 @@ static inline void gen_##name(DisasContext *ctx) \ static inline void gen_##name(DisasContext *ctx) \ { \ if (unlikely(!ctx->spe_enabled)) { \ - gen_exception(ctx, POWERPC_EXCP_APU); \ + gen_exception(ctx, POWERPC_EXCP_SPEU); \ return; \ } \ gen_helper_##name(cpu_gpr[rD(ctx->opcode)], \ @@ -8003,7 +8003,7 @@ static inline void gen_##name(DisasContext *ctx) \ { \ TCGv_i64 t0, t1; \ if (unlikely(!ctx->spe_enabled)) { \ - gen_exception(ctx, POWERPC_EXCP_APU); \ + gen_exception(ctx, POWERPC_EXCP_SPEU); \ return; \ } \ t0 = tcg_temp_new_i64(); \ @@ -8019,7 +8019,7 @@ static inline void gen_##name(DisasContext *ctx) \ static inline void gen_##name(DisasContext *ctx) \ { \ if (unlikely(!ctx->spe_enabled)) { \ - gen_exception(ctx, POWERPC_EXCP_APU); \ + gen_exception(ctx, POWERPC_EXCP_SPEU); \ return; \ } \ gen_helper_##name(cpu_crf[crfD(ctx->opcode)], \ @@ -8030,7 +8030,7 @@ static inline void gen_##name(DisasContext *ctx) \ { \ TCGv_i64 t0, t1; \ if (unlikely(!ctx->spe_enabled)) { \ - gen_exception(ctx, POWERPC_EXCP_APU); \ + gen_exception(ctx, POWERPC_EXCP_SPEU); \ return; \ } \ t0 = tcg_temp_new_i64(); \ @@ -8052,7 +8052,7 @@ GEN_SPEFPUOP_ARITH2_64_64(evfsdiv); static inline void gen_evfsabs(DisasContext *ctx) { if (unlikely(!ctx->spe_enabled)) { - gen_exception(ctx, POWERPC_EXCP_APU); + gen_exception(ctx, POWERPC_EXCP_SPEU); return; } #if defined(TARGET_PPC64) @@ -8065,7 +8065,7 @@ static inline void gen_evfsabs(DisasContext *ctx) static inline void gen_evfsnabs(DisasContext *ctx) { if (unlikely(!ctx->spe_enabled)) { - gen_exception(ctx, POWERPC_EXCP_APU); + gen_exception(ctx, POWERPC_EXCP_SPEU); return; } #if defined(TARGET_PPC64) @@ -8078,7 +8078,7 @@ static inline void gen_evfsnabs(DisasContext *ctx) static inline void gen_evfsneg(DisasContext *ctx) { if (unlikely(!ctx->spe_enabled)) { - gen_exception(ctx, POWERPC_EXCP_APU); + gen_exception(ctx, POWERPC_EXCP_SPEU); return; } #if defined(TARGET_PPC64) @@ -8134,7 +8134,7 @@ GEN_SPEFPUOP_ARITH2_32_32(efsdiv); static inline void gen_efsabs(DisasContext *ctx) { if (unlikely(!ctx->spe_enabled)) { - gen_exception(ctx, POWERPC_EXCP_APU); + gen_exception(ctx, POWERPC_EXCP_SPEU); return; } tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], (target_long)~0x80000000LL); @@ -8142,7 +8142,7 @@ static inline void gen_efsabs(DisasContext *ctx) static inline void gen_efsnabs(DisasContext *ctx) { if (unlikely(!ctx->spe_enabled)) { - gen_exception(ctx, POWERPC_EXCP_APU); + gen_exception(ctx, POWERPC_EXCP_SPEU); return; } tcg_gen_ori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000); @@ -8150,7 +8150,7 @@ static inline void gen_efsnabs(DisasContext *ctx) static inline void gen_efsneg(DisasContext *ctx) { if (unlikely(!ctx->spe_enabled)) { - gen_exception(ctx, POWERPC_EXCP_APU); + gen_exception(ctx, POWERPC_EXCP_SPEU); return; } tcg_gen_xori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000); @@ -8202,7 +8202,7 @@ GEN_SPEFPUOP_ARITH2_64_64(efddiv); static inline void gen_efdabs(DisasContext *ctx) { if (unlikely(!ctx->spe_enabled)) { - gen_exception(ctx, POWERPC_EXCP_APU); + gen_exception(ctx, POWERPC_EXCP_SPEU); return; } #if defined(TARGET_PPC64) @@ -8215,7 +8215,7 @@ static inline void gen_efdabs(DisasContext *ctx) static inline void gen_efdnabs(DisasContext *ctx) { if (unlikely(!ctx->spe_enabled)) { - gen_exception(ctx, POWERPC_EXCP_APU); + gen_exception(ctx, POWERPC_EXCP_SPEU); return; } #if defined(TARGET_PPC64) @@ -8228,7 +8228,7 @@ static inline void gen_efdnabs(DisasContext *ctx) static inline void gen_efdneg(DisasContext *ctx) { if (unlikely(!ctx->spe_enabled)) { - gen_exception(ctx, POWERPC_EXCP_APU); + gen_exception(ctx, POWERPC_EXCP_SPEU); return; } #if defined(TARGET_PPC64) diff --git a/tcg/optimize.c b/tcg/optimize.c index 7e7f2b2020..9c65474a8c 100644 --- a/tcg/optimize.c +++ b/tcg/optimize.c @@ -87,13 +87,13 @@ static void reset_temp(TCGArg temp, int nb_temps, int nb_globals) } } -static int op_bits(enum TCGOpcode op) +static int op_bits(TCGOpcode op) { const TCGOpDef *def = &tcg_op_defs[op]; return def->flags & TCG_OPF_64BIT ? 64 : 32; } -static int op_to_movi(int op) +static TCGOpcode op_to_movi(TCGOpcode op) { switch (op_bits(op)) { case 32: @@ -143,7 +143,7 @@ static void tcg_opt_gen_movi(TCGArg *gen_args, TCGArg dst, TCGArg val, gen_args[1] = val; } -static int op_to_mov(int op) +static TCGOpcode op_to_mov(TCGOpcode op) { switch (op_bits(op)) { case 32: @@ -157,7 +157,7 @@ static int op_to_mov(int op) } } -static TCGArg do_constant_folding_2(int op, TCGArg x, TCGArg y) +static TCGArg do_constant_folding_2(TCGOpcode op, TCGArg x, TCGArg y) { switch (op) { CASE_OP_32_64(add): @@ -258,7 +258,7 @@ static TCGArg do_constant_folding_2(int op, TCGArg x, TCGArg y) } } -static TCGArg do_constant_folding(int op, TCGArg x, TCGArg y) +static TCGArg do_constant_folding(TCGOpcode op, TCGArg x, TCGArg y) { TCGArg res = do_constant_folding_2(op, x, y); if (op_bits(op) == 32) { @@ -271,7 +271,8 @@ static TCGArg do_constant_folding(int op, TCGArg x, TCGArg y) static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, TCGArg *args, TCGOpDef *tcg_op_defs) { - int i, nb_ops, op_index, op, nb_temps, nb_globals, nb_call_args; + int i, nb_ops, op_index, nb_temps, nb_globals, nb_call_args; + TCGOpcode op; const TCGOpDef *def; TCGArg *gen_args; TCGArg tmp; @@ -377,6 +378,8 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, continue; } break; + default: + break; } /* Propagate constants through copy operations and do constant @@ -1128,18 +1128,19 @@ void tcg_add_target_add_op_defs(const TCGTargetOpDef *tdefs) #if defined(CONFIG_DEBUG_TCG) i = 0; for (op = 0; op < ARRAY_SIZE(tcg_op_defs); op++) { - if (op < INDEX_op_call || op == INDEX_op_debug_insn_start) { + const TCGOpDef *def = &tcg_op_defs[op]; + if (op < INDEX_op_call + || op == INDEX_op_debug_insn_start + || (def->flags & TCG_OPF_NOT_PRESENT)) { /* Wrong entry in op definitions? */ - if (tcg_op_defs[op].used) { - fprintf(stderr, "Invalid op definition for %s\n", - tcg_op_defs[op].name); + if (def->used) { + fprintf(stderr, "Invalid op definition for %s\n", def->name); i = 1; } } else { /* Missing entry in op definitions? */ - if (!tcg_op_defs[op].used) { - fprintf(stderr, "Missing op definition for %s\n", - tcg_op_defs[op].name); + if (!def->used) { + fprintf(stderr, "Missing op definition for %s\n", def->name); i = 1; } } diff --git a/trace-events b/trace-events index dc300a29b1..f08d6d0b41 100644 --- a/trace-events +++ b/trace-events @@ -284,6 +284,10 @@ disable qed_aio_write_prefill(void *s, void *acb, uint64_t start, size_t len, ui disable qed_aio_write_postfill(void *s, void *acb, uint64_t start, size_t len, uint64_t offset) "s %p acb %p start %"PRIu64" len %zu offset %"PRIu64"" disable qed_aio_write_main(void *s, void *acb, int ret, uint64_t offset, size_t len) "s %p acb %p ret %d offset %"PRIu64" len %zu" +# hw/g364fb.c +disable g364fb_read(uint64_t addr, uint32_t val) "read addr=0x%"PRIx64": 0x%x" +disable g364fb_write(uint64_t addr, uint32_t new) "write addr=0x%"PRIx64": 0x%x" + # hw/grlib_gptimer.c disable grlib_gptimer_enable(int id, uint32_t count) "timer:%d set count 0x%x and run" disable grlib_gptimer_disabled(int id, uint32_t config) "timer:%d Timer disable config 0x%x" @@ -38,16 +38,16 @@ SECTIONS .rel.plt : { *(.rel.plt) - PROVIDE_HIDDEN (__rel_iplt_start = .); + PROVIDE (__rel_iplt_start = .); *(.rel.iplt) - PROVIDE_HIDDEN (__rel_iplt_end = .); + PROVIDE (__rel_iplt_end = .); } .rela.plt : { *(.rela.plt) - PROVIDE_HIDDEN (__rela_iplt_start = .); + PROVIDE (__rela_iplt_start = .); *(.rela.iplt) - PROVIDE_HIDDEN (__rela_iplt_end = .); + PROVIDE (__rela_iplt_end = .); } .init : { @@ -70,8 +70,6 @@ SECTIONS .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } .rodata1 : { *(.rodata1) } .eh_frame_hdr : { *(.eh_frame_hdr) } - .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) } - .gcc_except_table : ONLY_IF_RO { *(.gcc_except_table) } /* Adjust the address for the data segment. We want to adjust up to the same address within the page on the next page up. */ . = ALIGN (0x100000) - ((0x100000 - .) & (0x100000 - 1)); . = DATA_SEGMENT_ALIGN (0x100000, 0x1000); @@ -97,8 +95,8 @@ SECTIONS .data1 : { *(.data1) } .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) } .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } - .eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) } - .gcc_except_table : ONLY_IF_RW { *(.gcc_except_table) } + .eh_frame : { KEEP (*(.eh_frame)) } + .gcc_except_table : { *(.gcc_except_table) } .dynamic : { *(.dynamic) } .ctors : { |