Merge remote-tracking branch 'origin/master' into xbox

Conflicts:
	qemu-config.c
This commit is contained in:
espes 2012-11-12 10:49:52 +11:00
commit cdcbc81ad8
742 changed files with 35083 additions and 6032 deletions

3
.gitmodules vendored
View File

@ -19,3 +19,6 @@
[submodule "roms/sgabios"]
path = roms/sgabios
url = git://git.qemu.org/sgabios.git
[submodule "pixman"]
path = pixman
url = git://anongit.freedesktop.org/pixman

View File

@ -118,6 +118,15 @@ endif
subdir-libcacard: $(oslib-obj-y) $(trace-obj-y) qemu-timer-common.o
subdir-pixman: pixman/Makefile
$(call quiet-command,$(MAKE) $(SUBDIR_MAKEFLAGS) -C pixman V="$(V)" all,)
pixman/Makefile: $(SRC_PATH)/pixman/configure
(cd pixman; $(SRC_PATH)/pixman/configure --disable-shared --enable-static)
$(SRC_PATH)/pixman/configure:
(cd $(SRC_PATH)/pixman; autoreconf -v --install)
$(filter %-softmmu,$(SUBDIR_RULES)): $(universal-obj-y) $(trace-obj-y) $(common-obj-y) $(extra-obj-y) subdir-libdis
$(filter %-user,$(SUBDIR_RULES)): $(universal-obj-y) $(trace-obj-y) subdir-libdis-user subdir-libuser
@ -171,8 +180,7 @@ endif
qemu-img.o: qemu-img-cmds.h
tools-obj-y = $(oslib-obj-y) $(trace-obj-y) qemu-tool.o qemu-timer.o \
qemu-timer-common.o main-loop.o notify.o \
iohandler.o cutils.o iov.o async.o error.o
main-loop.o iohandler.o error.o
tools-obj-$(CONFIG_POSIX) += compatfd.o
qemu-img$(EXESUF): qemu-img.o $(tools-obj-y) $(block-obj-y)
@ -181,7 +189,7 @@ qemu-io$(EXESUF): qemu-io.o cmd.o $(tools-obj-y) $(block-obj-y)
qemu-bridge-helper$(EXESUF): qemu-bridge-helper.o
vscclient$(EXESUF): $(libcacard-y) $(oslib-obj-y) $(trace-obj-y) $(tools-obj-y) qemu-timer-common.o libcacard/vscclient.o
vscclient$(EXESUF): $(libcacard-y) $(oslib-obj-y) $(trace-obj-y) libcacard/vscclient.o
$(call quiet-command,$(CC) $(LDFLAGS) -o $@ $^ $(libcacard_libs) $(LIBS)," LINK $@")
fsdev/virtfs-proxy-helper$(EXESUF): fsdev/virtfs-proxy-helper.o fsdev/virtio-9p-marshal.o oslib-posix.o $(trace-obj-y)
@ -224,7 +232,7 @@ $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/scripts/qapi-commands.py $(qapi-py)
QGALIB_GEN=$(addprefix qga/qapi-generated/, qga-qapi-types.h qga-qapi-visit.h qga-qmp-commands.h)
$(qga-obj-y) qemu-ga.o: $(QGALIB_GEN)
qemu-ga$(EXESUF): qemu-ga.o $(qga-obj-y) $(tools-obj-y) $(qapi-obj-y) $(qobject-obj-y) $(version-obj-y)
qemu-ga$(EXESUF): qemu-ga.o $(qga-obj-y) $(oslib-obj-y) $(trace-obj-y) $(qapi-obj-y) $(qobject-obj-y) $(version-obj-y)
QEMULIBS=libuser libdis libdis-user

View File

@ -19,7 +19,7 @@ universal-obj-y += $(qom-obj-y)
#######################################################################
# oslib-obj-y is code depending on the OS (win32 vs posix)
oslib-obj-y = osdep.o
oslib-obj-y = osdep.o cutils.o qemu-timer-common.o
oslib-obj-$(CONFIG_WIN32) += oslib-win32.o qemu-thread-win32.o
oslib-obj-$(CONFIG_POSIX) += oslib-posix.o qemu-thread-posix.o
@ -41,12 +41,12 @@ coroutine-obj-$(CONFIG_WIN32) += coroutine-win32.o
#######################################################################
# block-obj-y is code used by both qemu system emulation and qemu-img
block-obj-y = cutils.o iov.o cache-utils.o qemu-option.o module.o async.o
block-obj-y += nbd.o block.o blockjob.o aio.o aes.o qemu-config.o
block-obj-y += qemu-progress.o qemu-sockets.o uri.o notify.o
block-obj-y = iov.o cache-utils.o qemu-option.o module.o async.o
block-obj-y += nbd.o block.o blockjob.o aes.o qemu-config.o
block-obj-y += thread-pool.o qemu-progress.o qemu-sockets.o uri.o notify.o
block-obj-y += $(coroutine-obj-y) $(qobject-obj-y) $(version-obj-y)
block-obj-$(CONFIG_POSIX) += posix-aio-compat.o
block-obj-$(CONFIG_LINUX_AIO) += linux-aio.o
block-obj-$(CONFIG_POSIX) += event_notifier-posix.o aio-posix.o
block-obj-$(CONFIG_WIN32) += event_notifier-win32.o aio-win32.o
block-obj-y += block/
block-obj-y += $(qapi-obj-y) qapi-types.o qapi-visit.o
@ -65,6 +65,7 @@ common-obj-y = $(block-obj-y) blockdev.o blockdev-nbd.o block/
common-obj-y += net.o net/
common-obj-y += qom/
common-obj-y += readline.o console.o cursor.o
common-obj-y += qemu-pixman.o
common-obj-y += $(oslib-obj-y)
common-obj-$(CONFIG_WIN32) += os-win32.o
common-obj-$(CONFIG_POSIX) += os-posix.o
@ -92,9 +93,8 @@ common-obj-y += ui/
common-obj-y += bt-host.o bt-vhci.o
common-obj-y += dma-helpers.o
common-obj-y += iov.o acl.o
common-obj-y += acl.o
common-obj-$(CONFIG_POSIX) += compatfd.o
common-obj-y += event_notifier.o
common-obj-y += qemu-timer.o qemu-timer-common.o
common-obj-y += qtest.o
common-obj-y += vl.o
@ -113,7 +113,7 @@ endif
user-obj-y =
user-obj-y += envlist.o path.o
user-obj-y += tcg-runtime.o host-utils.o
user-obj-y += cutils.o iov.o cache-utils.o
user-obj-y += cache-utils.o
user-obj-y += module.o
user-obj-y += qemu-user.o
user-obj-y += $(trace-obj-y)
@ -228,9 +228,8 @@ universal-obj-y += $(qapi-obj-y)
######################################################################
# guest agent
qga-obj-y = qga/ qemu-ga.o module.o
qga-obj-$(CONFIG_WIN32) += oslib-win32.o
qga-obj-$(CONFIG_POSIX) += oslib-posix.o qemu-sockets.o qemu-option.o
qga-obj-y = qga/ qemu-ga.o module.o qemu-tool.o
qga-obj-$(CONFIG_POSIX) += qemu-sockets.o qemu-option.o
vl.o: QEMU_CFLAGS+=$(GPROF_CFLAGS)

268
aio-posix.c Normal file
View File

@ -0,0 +1,268 @@
/*
* QEMU aio implementation
*
* Copyright IBM, Corp. 2008
*
* Authors:
* Anthony Liguori <aliguori@us.ibm.com>
*
* This work is licensed under the terms of the GNU GPL, version 2. See
* the COPYING file in the top-level directory.
*
* Contributions after 2012-01-13 are licensed under the terms of the
* GNU GPL, version 2 or (at your option) any later version.
*/
#include "qemu-common.h"
#include "block.h"
#include "qemu-queue.h"
#include "qemu_socket.h"
struct AioHandler
{
GPollFD pfd;
IOHandler *io_read;
IOHandler *io_write;
AioFlushHandler *io_flush;
int deleted;
void *opaque;
QLIST_ENTRY(AioHandler) node;
};
static AioHandler *find_aio_handler(AioContext *ctx, int fd)
{
AioHandler *node;
QLIST_FOREACH(node, &ctx->aio_handlers, node) {
if (node->pfd.fd == fd)
if (!node->deleted)
return node;
}
return NULL;
}
void aio_set_fd_handler(AioContext *ctx,
int fd,
IOHandler *io_read,
IOHandler *io_write,
AioFlushHandler *io_flush,
void *opaque)
{
AioHandler *node;
node = find_aio_handler(ctx, fd);
/* Are we deleting the fd handler? */
if (!io_read && !io_write) {
if (node) {
g_source_remove_poll(&ctx->source, &node->pfd);
/* If the lock is held, just mark the node as deleted */
if (ctx->walking_handlers) {
node->deleted = 1;
node->pfd.revents = 0;
} else {
/* Otherwise, delete it for real. We can't just mark it as
* deleted because deleted nodes are only cleaned up after
* releasing the walking_handlers lock.
*/
QLIST_REMOVE(node, node);
g_free(node);
}
}
} else {
if (node == NULL) {
/* Alloc and insert if it's not already there */
node = g_malloc0(sizeof(AioHandler));
node->pfd.fd = fd;
QLIST_INSERT_HEAD(&ctx->aio_handlers, node, node);
g_source_add_poll(&ctx->source, &node->pfd);
}
/* Update handler with latest information */
node->io_read = io_read;
node->io_write = io_write;
node->io_flush = io_flush;
node->opaque = opaque;
node->pfd.events = (io_read ? G_IO_IN | G_IO_HUP : 0);
node->pfd.events |= (io_write ? G_IO_OUT : 0);
}
aio_notify(ctx);
}
void aio_set_event_notifier(AioContext *ctx,
EventNotifier *notifier,
EventNotifierHandler *io_read,
AioFlushEventNotifierHandler *io_flush)
{
aio_set_fd_handler(ctx, event_notifier_get_fd(notifier),
(IOHandler *)io_read, NULL,
(AioFlushHandler *)io_flush, notifier);
}
bool aio_pending(AioContext *ctx)
{
AioHandler *node;
QLIST_FOREACH(node, &ctx->aio_handlers, node) {
int revents;
/*
* FIXME: right now we cannot get G_IO_HUP and G_IO_ERR because
* main-loop.c is still select based (due to the slirp legacy).
* If main-loop.c ever switches to poll, G_IO_ERR should be
* tested too. Dispatching G_IO_ERR to both handlers should be
* okay, since handlers need to be ready for spurious wakeups.
*/
revents = node->pfd.revents & node->pfd.events;
if (revents & (G_IO_IN | G_IO_HUP | G_IO_ERR) && node->io_read) {
return true;
}
if (revents & (G_IO_OUT | G_IO_ERR) && node->io_write) {
return true;
}
}
return false;
}
bool aio_poll(AioContext *ctx, bool blocking)
{
static struct timeval tv0;
AioHandler *node;
fd_set rdfds, wrfds;
int max_fd = -1;
int ret;
bool busy, progress;
progress = false;
/*
* If there are callbacks left that have been queued, we need to call then.
* Do not call select in this case, because it is possible that the caller
* does not need a complete flush (as is the case for qemu_aio_wait loops).
*/
if (aio_bh_poll(ctx)) {
blocking = false;
progress = true;
}
/*
* Then dispatch any pending callbacks from the GSource.
*
* We have to walk very carefully in case qemu_aio_set_fd_handler is
* called while we're walking.
*/
node = QLIST_FIRST(&ctx->aio_handlers);
while (node) {
AioHandler *tmp;
int revents;
ctx->walking_handlers++;
revents = node->pfd.revents & node->pfd.events;
node->pfd.revents = 0;
/* See comment in aio_pending. */
if (revents & (G_IO_IN | G_IO_HUP | G_IO_ERR) && node->io_read) {
node->io_read(node->opaque);
progress = true;
}
if (revents & (G_IO_OUT | G_IO_ERR) && node->io_write) {
node->io_write(node->opaque);
progress = true;
}
tmp = node;
node = QLIST_NEXT(node, node);
ctx->walking_handlers--;
if (!ctx->walking_handlers && tmp->deleted) {
QLIST_REMOVE(tmp, node);
g_free(tmp);
}
}
if (progress && !blocking) {
return true;
}
ctx->walking_handlers++;
FD_ZERO(&rdfds);
FD_ZERO(&wrfds);
/* fill fd sets */
busy = false;
QLIST_FOREACH(node, &ctx->aio_handlers, node) {
/* If there aren't pending AIO operations, don't invoke callbacks.
* Otherwise, if there are no AIO requests, qemu_aio_wait() would
* wait indefinitely.
*/
if (!node->deleted && node->io_flush) {
if (node->io_flush(node->opaque) == 0) {
continue;
}
busy = true;
}
if (!node->deleted && node->io_read) {
FD_SET(node->pfd.fd, &rdfds);
max_fd = MAX(max_fd, node->pfd.fd + 1);
}
if (!node->deleted && node->io_write) {
FD_SET(node->pfd.fd, &wrfds);
max_fd = MAX(max_fd, node->pfd.fd + 1);
}
}
ctx->walking_handlers--;
/* No AIO operations? Get us out of here */
if (!busy) {
return progress;
}
/* wait until next event */
ret = select(max_fd, &rdfds, &wrfds, NULL, blocking ? NULL : &tv0);
/* if we have any readable fds, dispatch event */
if (ret > 0) {
/* we have to walk very carefully in case
* qemu_aio_set_fd_handler is called while we're walking */
node = QLIST_FIRST(&ctx->aio_handlers);
while (node) {
AioHandler *tmp;
ctx->walking_handlers++;
if (!node->deleted &&
FD_ISSET(node->pfd.fd, &rdfds) &&
node->io_read) {
node->io_read(node->opaque);
progress = true;
}
if (!node->deleted &&
FD_ISSET(node->pfd.fd, &wrfds) &&
node->io_write) {
node->io_write(node->opaque);
progress = true;
}
tmp = node;
node = QLIST_NEXT(node, node);
ctx->walking_handlers--;
if (!ctx->walking_handlers && tmp->deleted) {
QLIST_REMOVE(tmp, node);
g_free(tmp);
}
}
}
return progress;
}

215
aio-win32.c Normal file
View File

@ -0,0 +1,215 @@
/*
* QEMU aio implementation
*
* Copyright IBM Corp., 2008
* Copyright Red Hat Inc., 2012
*
* Authors:
* Anthony Liguori <aliguori@us.ibm.com>
* Paolo Bonzini <pbonzini@redhat.com>
*
* This work is licensed under the terms of the GNU GPL, version 2. See
* the COPYING file in the top-level directory.
*
* Contributions after 2012-01-13 are licensed under the terms of the
* GNU GPL, version 2 or (at your option) any later version.
*/
#include "qemu-common.h"
#include "block.h"
#include "qemu-queue.h"
#include "qemu_socket.h"
struct AioHandler {
EventNotifier *e;
EventNotifierHandler *io_notify;
AioFlushEventNotifierHandler *io_flush;
GPollFD pfd;
int deleted;
QLIST_ENTRY(AioHandler) node;
};
void aio_set_event_notifier(AioContext *ctx,
EventNotifier *e,
EventNotifierHandler *io_notify,
AioFlushEventNotifierHandler *io_flush)
{
AioHandler *node;
QLIST_FOREACH(node, &ctx->aio_handlers, node) {
if (node->e == e && !node->deleted) {
break;
}
}
/* Are we deleting the fd handler? */
if (!io_notify) {
if (node) {
g_source_remove_poll(&ctx->source, &node->pfd);
/* If the lock is held, just mark the node as deleted */
if (ctx->walking_handlers) {
node->deleted = 1;
node->pfd.revents = 0;
} else {
/* Otherwise, delete it for real. We can't just mark it as
* deleted because deleted nodes are only cleaned up after
* releasing the walking_handlers lock.
*/
QLIST_REMOVE(node, node);
g_free(node);
}
}
} else {
if (node == NULL) {
/* Alloc and insert if it's not already there */
node = g_malloc0(sizeof(AioHandler));
node->e = e;
node->pfd.fd = (uintptr_t)event_notifier_get_handle(e);
node->pfd.events = G_IO_IN;
QLIST_INSERT_HEAD(&ctx->aio_handlers, node, node);
g_source_add_poll(&ctx->source, &node->pfd);
}
/* Update handler with latest information */
node->io_notify = io_notify;
node->io_flush = io_flush;
}
aio_notify(ctx);
}
bool aio_pending(AioContext *ctx)
{
AioHandler *node;
QLIST_FOREACH(node, &ctx->aio_handlers, node) {
if (node->pfd.revents && node->io_notify) {
return true;
}
}
return false;
}
bool aio_poll(AioContext *ctx, bool blocking)
{
AioHandler *node;
HANDLE events[MAXIMUM_WAIT_OBJECTS + 1];
bool busy, progress;
int count;
progress = false;
/*
* If there are callbacks left that have been queued, we need to call then.
* Do not call select in this case, because it is possible that the caller
* does not need a complete flush (as is the case for qemu_aio_wait loops).
*/
if (aio_bh_poll(ctx)) {
blocking = false;
progress = true;
}
/*
* Then dispatch any pending callbacks from the GSource.
*
* We have to walk very carefully in case qemu_aio_set_fd_handler is
* called while we're walking.
*/
node = QLIST_FIRST(&ctx->aio_handlers);
while (node) {
AioHandler *tmp;
ctx->walking_handlers++;
if (node->pfd.revents && node->io_notify) {
node->pfd.revents = 0;
node->io_notify(node->e);
progress = true;
}
tmp = node;
node = QLIST_NEXT(node, node);
ctx->walking_handlers--;
if (!ctx->walking_handlers && tmp->deleted) {
QLIST_REMOVE(tmp, node);
g_free(tmp);
}
}
if (progress && !blocking) {
return true;
}
ctx->walking_handlers++;
/* fill fd sets */
busy = false;
count = 0;
QLIST_FOREACH(node, &ctx->aio_handlers, node) {
/* If there aren't pending AIO operations, don't invoke callbacks.
* Otherwise, if there are no AIO requests, qemu_aio_wait() would
* wait indefinitely.
*/
if (!node->deleted && node->io_flush) {
if (node->io_flush(node->e) == 0) {
continue;
}
busy = true;
}
if (!node->deleted && node->io_notify) {
events[count++] = event_notifier_get_handle(node->e);
}
}
ctx->walking_handlers--;
/* No AIO operations? Get us out of here */
if (!busy) {
return progress;
}
/* wait until next event */
for (;;) {
int timeout = blocking ? INFINITE : 0;
int ret = WaitForMultipleObjects(count, events, FALSE, timeout);
/* if we have any signaled events, dispatch event */
if ((DWORD) (ret - WAIT_OBJECT_0) >= count) {
break;
}
blocking = false;
/* we have to walk very carefully in case
* qemu_aio_set_fd_handler is called while we're walking */
node = QLIST_FIRST(&ctx->aio_handlers);
while (node) {
AioHandler *tmp;
ctx->walking_handlers++;
if (!node->deleted &&
event_notifier_get_handle(node->e) == events[ret - WAIT_OBJECT_0] &&
node->io_notify) {
node->io_notify(node->e);
progress = true;
}
tmp = node;
node = QLIST_NEXT(node, node);
ctx->walking_handlers--;
if (!ctx->walking_handlers && tmp->deleted) {
QLIST_REMOVE(tmp, node);
g_free(tmp);
}
}
}
return progress;
}

194
aio.c
View File

@ -1,194 +0,0 @@
/*
* QEMU aio implementation
*
* Copyright IBM, Corp. 2008
*
* Authors:
* Anthony Liguori <aliguori@us.ibm.com>
*
* This work is licensed under the terms of the GNU GPL, version 2. See
* the COPYING file in the top-level directory.
*
* Contributions after 2012-01-13 are licensed under the terms of the
* GNU GPL, version 2 or (at your option) any later version.
*/
#include "qemu-common.h"
#include "block.h"
#include "qemu-queue.h"
#include "qemu_socket.h"
typedef struct AioHandler AioHandler;
/* The list of registered AIO handlers */
static QLIST_HEAD(, AioHandler) aio_handlers;
/* This is a simple lock used to protect the aio_handlers list. Specifically,
* it's used to ensure that no callbacks are removed while we're walking and
* dispatching callbacks.
*/
static int walking_handlers;
struct AioHandler
{
int fd;
IOHandler *io_read;
IOHandler *io_write;
AioFlushHandler *io_flush;
int deleted;
void *opaque;
QLIST_ENTRY(AioHandler) node;
};
static AioHandler *find_aio_handler(int fd)
{
AioHandler *node;
QLIST_FOREACH(node, &aio_handlers, node) {
if (node->fd == fd)
if (!node->deleted)
return node;
}
return NULL;
}
int qemu_aio_set_fd_handler(int fd,
IOHandler *io_read,
IOHandler *io_write,
AioFlushHandler *io_flush,
void *opaque)
{
AioHandler *node;
node = find_aio_handler(fd);
/* Are we deleting the fd handler? */
if (!io_read && !io_write) {
if (node) {
/* If the lock is held, just mark the node as deleted */
if (walking_handlers)
node->deleted = 1;
else {
/* Otherwise, delete it for real. We can't just mark it as
* deleted because deleted nodes are only cleaned up after
* releasing the walking_handlers lock.
*/
QLIST_REMOVE(node, node);
g_free(node);
}
}
} else {
if (node == NULL) {
/* Alloc and insert if it's not already there */
node = g_malloc0(sizeof(AioHandler));
node->fd = fd;
QLIST_INSERT_HEAD(&aio_handlers, node, node);
}
/* Update handler with latest information */
node->io_read = io_read;
node->io_write = io_write;
node->io_flush = io_flush;
node->opaque = opaque;
}
qemu_set_fd_handler2(fd, NULL, io_read, io_write, opaque);
return 0;
}
void qemu_aio_flush(void)
{
while (qemu_aio_wait());
}
bool qemu_aio_wait(void)
{
AioHandler *node;
fd_set rdfds, wrfds;
int max_fd = -1;
int ret;
bool busy;
/*
* If there are callbacks left that have been queued, we need to call then.
* Do not call select in this case, because it is possible that the caller
* does not need a complete flush (as is the case for qemu_aio_wait loops).
*/
if (qemu_bh_poll()) {
return true;
}
walking_handlers++;
FD_ZERO(&rdfds);
FD_ZERO(&wrfds);
/* fill fd sets */
busy = false;
QLIST_FOREACH(node, &aio_handlers, node) {
/* If there aren't pending AIO operations, don't invoke callbacks.
* Otherwise, if there are no AIO requests, qemu_aio_wait() would
* wait indefinitely.
*/
if (node->io_flush) {
if (node->io_flush(node->opaque) == 0) {
continue;
}
busy = true;
}
if (!node->deleted && node->io_read) {
FD_SET(node->fd, &rdfds);
max_fd = MAX(max_fd, node->fd + 1);
}
if (!node->deleted && node->io_write) {
FD_SET(node->fd, &wrfds);
max_fd = MAX(max_fd, node->fd + 1);
}
}
walking_handlers--;
/* No AIO operations? Get us out of here */
if (!busy) {
return false;
}
/* wait until next event */
ret = select(max_fd, &rdfds, &wrfds, NULL, NULL);
/* if we have any readable fds, dispatch event */
if (ret > 0) {
/* we have to walk very carefully in case
* qemu_aio_set_fd_handler is called while we're walking */
node = QLIST_FIRST(&aio_handlers);
while (node) {
AioHandler *tmp;
walking_handlers++;
if (!node->deleted &&
FD_ISSET(node->fd, &rdfds) &&
node->io_read) {
node->io_read(node->opaque);
}
if (!node->deleted &&
FD_ISSET(node->fd, &wrfds) &&
node->io_write) {
node->io_write(node->opaque);
}
tmp = node;
node = QLIST_NEXT(node, node);
walking_handlers--;
if (!walking_handlers && tmp->deleted) {
QLIST_REMOVE(tmp, node);
g_free(tmp);
}
}
}
return true;
}

View File

@ -34,6 +34,6 @@ int tcg_available(void);
int kvm_available(void);
int xen_available(void);
CpuDefinitionInfoList GCC_WEAK_DECL *arch_query_cpu_definitions(Error **errp);
CpuDefinitionInfoList *arch_query_cpu_definitions(Error **errp);
#endif

118
async.c
View File

@ -26,13 +26,11 @@
#include "qemu-aio.h"
#include "main-loop.h"
/* Anchor of the list of Bottom Halves belonging to the context */
static struct QEMUBH *first_bh;
/***********************************************************/
/* bottom halves (can be seen as timers which expire ASAP) */
struct QEMUBH {
AioContext *ctx;
QEMUBHFunc *cb;
void *opaque;
QEMUBH *next;
@ -41,27 +39,27 @@ struct QEMUBH {
bool deleted;
};
QEMUBH *qemu_bh_new(QEMUBHFunc *cb, void *opaque)
QEMUBH *aio_bh_new(AioContext *ctx, QEMUBHFunc *cb, void *opaque)
{
QEMUBH *bh;
bh = g_malloc0(sizeof(QEMUBH));
bh->ctx = ctx;
bh->cb = cb;
bh->opaque = opaque;
bh->next = first_bh;
first_bh = bh;
bh->next = ctx->first_bh;
ctx->first_bh = bh;
return bh;
}
int qemu_bh_poll(void)
int aio_bh_poll(AioContext *ctx)
{
QEMUBH *bh, **bhp, *next;
int ret;
static int nesting = 0;
nesting++;
ctx->walking_bh++;
ret = 0;
for (bh = first_bh; bh; bh = next) {
for (bh = ctx->first_bh; bh; bh = next) {
next = bh->next;
if (!bh->deleted && bh->scheduled) {
bh->scheduled = 0;
@ -72,11 +70,11 @@ int qemu_bh_poll(void)
}
}
nesting--;
ctx->walking_bh--;
/* remove deleted bhs */
if (!nesting) {
bhp = &first_bh;
if (!ctx->walking_bh) {
bhp = &ctx->first_bh;
while (*bhp) {
bh = *bhp;
if (bh->deleted) {
@ -105,8 +103,7 @@ void qemu_bh_schedule(QEMUBH *bh)
return;
bh->scheduled = 1;
bh->idle = 0;
/* stop the currently executing CPU to execute the BH ASAP */
qemu_notify_event();
aio_notify(bh->ctx);
}
void qemu_bh_cancel(QEMUBH *bh)
@ -120,16 +117,20 @@ void qemu_bh_delete(QEMUBH *bh)
bh->deleted = 1;
}
void qemu_bh_update_timeout(uint32_t *timeout)
static gboolean
aio_ctx_prepare(GSource *source, gint *timeout)
{
AioContext *ctx = (AioContext *) source;
QEMUBH *bh;
bool scheduled = false;
for (bh = first_bh; bh; bh = bh->next) {
for (bh = ctx->first_bh; bh; bh = bh->next) {
if (!bh->deleted && bh->scheduled) {
scheduled = true;
if (bh->idle) {
/* idle bottom halves will be polled at least
* every 10ms */
*timeout = MIN(10, *timeout);
*timeout = 10;
} else {
/* non-idle bottom halves will be executed
* immediately */
@ -138,5 +139,86 @@ void qemu_bh_update_timeout(uint32_t *timeout)
}
}
}
return scheduled;
}
static gboolean
aio_ctx_check(GSource *source)
{
AioContext *ctx = (AioContext *) source;
QEMUBH *bh;
for (bh = ctx->first_bh; bh; bh = bh->next) {
if (!bh->deleted && bh->scheduled) {
return true;
}
}
return aio_pending(ctx);
}
static gboolean
aio_ctx_dispatch(GSource *source,
GSourceFunc callback,
gpointer user_data)
{
AioContext *ctx = (AioContext *) source;
assert(callback == NULL);
aio_poll(ctx, false);
return true;
}
static void
aio_ctx_finalize(GSource *source)
{
AioContext *ctx = (AioContext *) source;
aio_set_event_notifier(ctx, &ctx->notifier, NULL, NULL);
event_notifier_cleanup(&ctx->notifier);
}
static GSourceFuncs aio_source_funcs = {
aio_ctx_prepare,
aio_ctx_check,
aio_ctx_dispatch,
aio_ctx_finalize
};
GSource *aio_get_g_source(AioContext *ctx)
{
g_source_ref(&ctx->source);
return &ctx->source;
}
void aio_notify(AioContext *ctx)
{
event_notifier_set(&ctx->notifier);
}
AioContext *aio_context_new(void)
{
AioContext *ctx;
ctx = (AioContext *) g_source_new(&aio_source_funcs, sizeof(AioContext));
event_notifier_init(&ctx->notifier, false);
aio_set_event_notifier(ctx, &ctx->notifier,
(EventNotifierHandler *)
event_notifier_test_and_clear, NULL);
return ctx;
}
void aio_context_ref(AioContext *ctx)
{
g_source_ref(&ctx->source);
}
void aio_context_unref(AioContext *ctx)
{
g_source_unref(&ctx->source);
}
void aio_flush(AioContext *ctx)
{
while (aio_poll(ctx, true));
}

View File

@ -2,13 +2,18 @@ block-obj-y += raw.o cow.o qcow.o vdi.o vmdk.o cloop.o dmg.o bochs.o vpc.o vvfat
block-obj-y += qcow2.o qcow2-refcount.o qcow2-cluster.o qcow2-snapshot.o qcow2-cache.o
block-obj-y += qed.o qed-gencb.o qed-l2-cache.o qed-table.o qed-cluster.o
block-obj-y += qed-check.o
block-obj-y += parallels.o nbd.o blkdebug.o sheepdog.o blkverify.o
block-obj-$(CONFIG_WIN32) += raw-win32.o
block-obj-y += parallels.o blkdebug.o blkverify.o
block-obj-$(CONFIG_WIN32) += raw-win32.o win32-aio.o
block-obj-$(CONFIG_POSIX) += raw-posix.o
block-obj-$(CONFIG_LINUX_AIO) += linux-aio.o
ifeq ($(CONFIG_POSIX),y)
block-obj-y += nbd.o sheepdog.o
block-obj-$(CONFIG_LIBISCSI) += iscsi.o
block-obj-$(CONFIG_CURL) += curl.o
block-obj-$(CONFIG_RBD) += rbd.o
block-obj-$(CONFIG_GLUSTERFS) += gluster.o
endif
common-obj-y += stream.o
common-obj-y += commit.o

View File

@ -9,9 +9,10 @@
*/
#include "qemu-common.h"
#include "qemu-aio.h"
#include "block/raw-posix-aio.h"
#include "qemu-queue.h"
#include "block/raw-aio.h"
#include "event_notifier.h"
#include <sys/eventfd.h>
#include <libaio.h>
/*
@ -37,7 +38,7 @@ struct qemu_laiocb {
struct qemu_laio_state {
io_context_t ctx;
int efd;
EventNotifier e;
int count;
};
@ -76,29 +77,17 @@ static void qemu_laio_process_completion(struct qemu_laio_state *s,
qemu_aio_release(laiocb);
}
static void qemu_laio_completion_cb(void *opaque)
static void qemu_laio_completion_cb(EventNotifier *e)
{
struct qemu_laio_state *s = opaque;
struct qemu_laio_state *s = container_of(e, struct qemu_laio_state, e);
while (1) {
while (event_notifier_test_and_clear(&s->e)) {
struct io_event events[MAX_EVENTS];
uint64_t val;
ssize_t ret;
struct timespec ts = { 0 };
int nevents, i;
do {
ret = read(s->efd, &val, sizeof(val));
} while (ret == -1 && errno == EINTR);
if (ret == -1 && errno == EAGAIN)
break;
if (ret != 8)
break;
do {
nevents = io_getevents(s->ctx, val, MAX_EVENTS, events, &ts);
nevents = io_getevents(s->ctx, MAX_EVENTS, MAX_EVENTS, events, &ts);
} while (nevents == -EINTR);
for (i = 0; i < nevents; i++) {
@ -112,9 +101,9 @@ static void qemu_laio_completion_cb(void *opaque)
}
}
static int qemu_laio_flush_cb(void *opaque)
static int qemu_laio_flush_cb(EventNotifier *e)
{
struct qemu_laio_state *s = opaque;
struct qemu_laio_state *s = container_of(e, struct qemu_laio_state, e);
return (s->count > 0) ? 1 : 0;
}
@ -146,8 +135,9 @@ static void laio_cancel(BlockDriverAIOCB *blockacb)
* We might be able to do this slightly more optimal by removing the
* O_NONBLOCK flag.
*/
while (laiocb->ret == -EINPROGRESS)
qemu_laio_completion_cb(laiocb->ctx);
while (laiocb->ret == -EINPROGRESS) {
qemu_laio_completion_cb(&laiocb->ctx->e);
}
}
static AIOPool laio_pool = {
@ -186,7 +176,7 @@ BlockDriverAIOCB *laio_submit(BlockDriverState *bs, void *aio_ctx, int fd,
__func__, type);
goto out_free_aiocb;
}
io_set_eventfd(&laiocb->iocb, s->efd);
io_set_eventfd(&laiocb->iocb, event_notifier_get_fd(&s->e));
s->count++;
if (io_submit(s->ctx, 1, &iocbs) < 0)
@ -205,21 +195,21 @@ void *laio_init(void)
struct qemu_laio_state *s;
s = g_malloc0(sizeof(*s));
s->efd = eventfd(0, 0);
if (s->efd == -1)
if (event_notifier_init(&s->e, false) < 0) {
goto out_free_state;
fcntl(s->efd, F_SETFL, O_NONBLOCK);
}
if (io_setup(MAX_EVENTS, &s->ctx) != 0)
if (io_setup(MAX_EVENTS, &s->ctx) != 0) {
goto out_close_efd;
}
qemu_aio_set_fd_handler(s->efd, qemu_laio_completion_cb, NULL,
qemu_laio_flush_cb, s);
qemu_aio_set_event_notifier(&s->e, qemu_laio_completion_cb,
qemu_laio_flush_cb);
return s;
out_close_efd:
close(s->efd);
event_notifier_cleanup(&s->e);
out_free_state:
g_free(s);
return NULL;

View File

@ -1,5 +1,5 @@
/*
* QEMU Posix block I/O backend AIO support
* Declarations for AIO in the raw protocol
*
* Copyright IBM, Corp. 2008
*
@ -12,8 +12,8 @@
* Contributions after 2012-01-13 are licensed under the terms of the
* GNU GPL, version 2 or (at your option) any later version.
*/
#ifndef QEMU_RAW_POSIX_AIO_H
#define QEMU_RAW_POSIX_AIO_H
#ifndef QEMU_RAW_AIO_H
#define QEMU_RAW_AIO_H
/* AIO request types */
#define QEMU_AIO_READ 0x0001
@ -27,19 +27,22 @@
#define QEMU_AIO_MISALIGNED 0x1000
/* posix-aio-compat.c - thread pool based implementation */
int paio_init(void);
BlockDriverAIOCB *paio_submit(BlockDriverState *bs, int fd,
int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
BlockDriverCompletionFunc *cb, void *opaque, int type);
BlockDriverAIOCB *paio_ioctl(BlockDriverState *bs, int fd,
unsigned long int req, void *buf,
BlockDriverCompletionFunc *cb, void *opaque);
/* linux-aio.c - Linux native implementation */
#ifdef CONFIG_LINUX_AIO
void *laio_init(void);
BlockDriverAIOCB *laio_submit(BlockDriverState *bs, void *aio_ctx, int fd,
int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
BlockDriverCompletionFunc *cb, void *opaque, int type);
#endif
#endif /* QEMU_RAW_POSIX_AIO_H */
#ifdef _WIN32
typedef struct QEMUWin32AIOState QEMUWin32AIOState;
QEMUWin32AIOState *win32_aio_init(void);
int win32_aio_attach(QEMUWin32AIOState *aio, HANDLE hfile);
BlockDriverAIOCB *win32_aio_submit(BlockDriverState *bs,
QEMUWin32AIOState *aio, HANDLE hfile,
int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
BlockDriverCompletionFunc *cb, void *opaque, int type);
#endif
#endif /* QEMU_RAW_AIO_H */

View File

@ -27,7 +27,10 @@
#include "qemu-log.h"
#include "block_int.h"
#include "module.h"
#include "block/raw-posix-aio.h"
#include "trace.h"
#include "thread-pool.h"
#include "iov.h"
#include "raw-aio.h"
#if defined(__APPLE__) && (__MACH__)
#include <paths.h>
@ -149,6 +152,20 @@ typedef struct BDRVRawReopenState {
static int fd_open(BlockDriverState *bs);
static int64_t raw_getlength(BlockDriverState *bs);
typedef struct RawPosixAIOData {
BlockDriverState *bs;
int aio_fildes;
union {
struct iovec *aio_iov;
void *aio_ioctl_buf;
};
int aio_niov;
size_t aio_nbytes;
#define aio_ioctl_cmd aio_nbytes /* for QEMU_AIO_IOCTL */
off_t aio_offset;
int aio_type;
} RawPosixAIOData;
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
static int cdrom_reopen(BlockDriverState *bs);
#endif
@ -266,14 +283,10 @@ static int raw_open_common(BlockDriverState *bs, const char *filename,
}
s->fd = fd;
/* We're falling back to POSIX AIO in some cases so init always */
if (paio_init() < 0) {
goto out_close;
}
#ifdef CONFIG_LINUX_AIO
if (raw_set_aio(&s->aio_ctx, &s->use_aio, bdrv_flags)) {
goto out_close;
qemu_close(fd);
return -errno;
}
#endif
@ -284,10 +297,6 @@ static int raw_open_common(BlockDriverState *bs, const char *filename,
#endif
return 0;
out_close:
qemu_close(fd);
return -errno;
}
static int raw_open(BlockDriverState *bs, const char *filename, int flags)
@ -434,6 +443,283 @@ static int qiov_is_aligned(BlockDriverState *bs, QEMUIOVector *qiov)
return 1;
}
static ssize_t handle_aiocb_ioctl(RawPosixAIOData *aiocb)
{
int ret;
ret = ioctl(aiocb->aio_fildes, aiocb->aio_ioctl_cmd, aiocb->aio_ioctl_buf);
if (ret == -1) {
return -errno;
}
/*
* This looks weird, but the aio code only considers a request
* successful if it has written the full number of bytes.
*
* Now we overload aio_nbytes as aio_ioctl_cmd for the ioctl command,
* so in fact we return the ioctl command here to make posix_aio_read()
* happy..
*/
return aiocb->aio_nbytes;
}
static ssize_t handle_aiocb_flush(RawPosixAIOData *aiocb)
{
int ret;
ret = qemu_fdatasync(aiocb->aio_fildes);
if (ret == -1) {
return -errno;
}
return 0;
}
#ifdef CONFIG_PREADV
static bool preadv_present = true;
static ssize_t
qemu_preadv(int fd, const struct iovec *iov, int nr_iov, off_t offset)
{
return preadv(fd, iov, nr_iov, offset);
}
static ssize_t
qemu_pwritev(int fd, const struct iovec *iov, int nr_iov, off_t offset)
{
return pwritev(fd, iov, nr_iov, offset);
}
#else
static bool preadv_present = false;
static ssize_t
qemu_preadv(int fd, const struct iovec *iov, int nr_iov, off_t offset)
{
return -ENOSYS;
}
static ssize_t
qemu_pwritev(int fd, const struct iovec *iov, int nr_iov, off_t offset)
{
return -ENOSYS;
}
#endif
static ssize_t handle_aiocb_rw_vector(RawPosixAIOData *aiocb)
{
ssize_t len;
do {
if (aiocb->aio_type & QEMU_AIO_WRITE)
len = qemu_pwritev(aiocb->aio_fildes,
aiocb->aio_iov,
aiocb->aio_niov,
aiocb->aio_offset);
else
len = qemu_preadv(aiocb->aio_fildes,
aiocb->aio_iov,
aiocb->aio_niov,
aiocb->aio_offset);
} while (len == -1 && errno == EINTR);
if (len == -1) {
return -errno;
}
return len;
}
/*
* Read/writes the data to/from a given linear buffer.
*
* Returns the number of bytes handles or -errno in case of an error. Short
* reads are only returned if the end of the file is reached.
*/
static ssize_t handle_aiocb_rw_linear(RawPosixAIOData *aiocb, char *buf)
{
ssize_t offset = 0;
ssize_t len;
while (offset < aiocb->aio_nbytes) {
if (aiocb->aio_type & QEMU_AIO_WRITE) {
len = pwrite(aiocb->aio_fildes,
(const char *)buf + offset,
aiocb->aio_nbytes - offset,
aiocb->aio_offset + offset);
} else {
len = pread(aiocb->aio_fildes,
buf + offset,
aiocb->aio_nbytes - offset,
aiocb->aio_offset + offset);
}
if (len == -1 && errno == EINTR) {
continue;
} else if (len == -1) {
offset = -errno;
break;
} else if (len == 0) {
break;
}
offset += len;
}
return offset;
}
static ssize_t handle_aiocb_rw(RawPosixAIOData *aiocb)
{
ssize_t nbytes;
char *buf;
if (!(aiocb->aio_type & QEMU_AIO_MISALIGNED)) {
/*
* If there is just a single buffer, and it is properly aligned
* we can just use plain pread/pwrite without any problems.
*/
if (aiocb->aio_niov == 1) {
return handle_aiocb_rw_linear(aiocb, aiocb->aio_iov->iov_base);
}
/*
* We have more than one iovec, and all are properly aligned.
*
* Try preadv/pwritev first and fall back to linearizing the
* buffer if it's not supported.
*/
if (preadv_present) {
nbytes = handle_aiocb_rw_vector(aiocb);
if (nbytes == aiocb->aio_nbytes ||
(nbytes < 0 && nbytes != -ENOSYS)) {
return nbytes;
}
preadv_present = false;
}
/*
* XXX(hch): short read/write. no easy way to handle the reminder
* using these interfaces. For now retry using plain
* pread/pwrite?
*/
}
/*
* Ok, we have to do it the hard way, copy all segments into
* a single aligned buffer.
*/
buf = qemu_blockalign(aiocb->bs, aiocb->aio_nbytes);
if (aiocb->aio_type & QEMU_AIO_WRITE) {
char *p = buf;
int i;
for (i = 0; i < aiocb->aio_niov; ++i) {
memcpy(p, aiocb->aio_iov[i].iov_base, aiocb->aio_iov[i].iov_len);
p += aiocb->aio_iov[i].iov_len;
}
}
nbytes = handle_aiocb_rw_linear(aiocb, buf);
if (!(aiocb->aio_type & QEMU_AIO_WRITE)) {
char *p = buf;
size_t count = aiocb->aio_nbytes, copy;
int i;
for (i = 0; i < aiocb->aio_niov && count; ++i) {
copy = count;
if (copy > aiocb->aio_iov[i].iov_len) {
copy = aiocb->aio_iov[i].iov_len;
}
memcpy(aiocb->aio_iov[i].iov_base, p, copy);
p += copy;
count -= copy;
}
}
qemu_vfree(buf);
return nbytes;
}
static int aio_worker(void *arg)
{
RawPosixAIOData *aiocb = arg;
ssize_t ret = 0;
switch (aiocb->aio_type & QEMU_AIO_TYPE_MASK) {
case QEMU_AIO_READ:
ret = handle_aiocb_rw(aiocb);
if (ret >= 0 && ret < aiocb->aio_nbytes && aiocb->bs->growable) {
iov_memset(aiocb->aio_iov, aiocb->aio_niov, ret,
0, aiocb->aio_nbytes - ret);
ret = aiocb->aio_nbytes;
}
if (ret == aiocb->aio_nbytes) {
ret = 0;
} else if (ret >= 0 && ret < aiocb->aio_nbytes) {
ret = -EINVAL;
}
break;
case QEMU_AIO_WRITE:
ret = handle_aiocb_rw(aiocb);
if (ret == aiocb->aio_nbytes) {
ret = 0;
} else if (ret >= 0 && ret < aiocb->aio_nbytes) {
ret = -EINVAL;
}
break;
case QEMU_AIO_FLUSH:
ret = handle_aiocb_flush(aiocb);
break;
case QEMU_AIO_IOCTL:
ret = handle_aiocb_ioctl(aiocb);
break;
default:
fprintf(stderr, "invalid aio request (0x%x)\n", aiocb->aio_type);
ret = -EINVAL;
break;
}
g_slice_free(RawPosixAIOData, aiocb);
return ret;
}
static BlockDriverAIOCB *paio_submit(BlockDriverState *bs, int fd,
int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
BlockDriverCompletionFunc *cb, void *opaque, int type)
{
RawPosixAIOData *acb = g_slice_new(RawPosixAIOData);
acb->bs = bs;
acb->aio_type = type;
acb->aio_fildes = fd;
if (qiov) {
acb->aio_iov = qiov->iov;
acb->aio_niov = qiov->niov;
}
acb->aio_nbytes = nb_sectors * 512;
acb->aio_offset = sector_num * 512;
trace_paio_submit(acb, opaque, sector_num, nb_sectors, type);
return thread_pool_submit_aio(aio_worker, acb, cb, opaque);
}
static BlockDriverAIOCB *paio_ioctl(BlockDriverState *bs, int fd,
unsigned long int req, void *buf,
BlockDriverCompletionFunc *cb, void *opaque)
{
RawPosixAIOData *acb = g_slice_new(RawPosixAIOData);
acb->bs = bs;
acb->aio_type = QEMU_AIO_IOCTL;
acb->aio_fildes = fd;
acb->aio_offset = 0;
acb->aio_ioctl_buf = buf;
acb->aio_ioctl_cmd = req;
return thread_pool_submit_aio(aio_worker, acb, cb, opaque);
}
static BlockDriverAIOCB *raw_aio_submit(BlockDriverState *bs,
int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
BlockDriverCompletionFunc *cb, void *opaque, int type)

View File

@ -25,6 +25,10 @@
#include "qemu-timer.h"
#include "block_int.h"
#include "module.h"
#include "raw-aio.h"
#include "trace.h"
#include "thread-pool.h"
#include "iov.h"
#include <windows.h>
#include <winioctl.h>
@ -32,12 +36,130 @@
#define FTYPE_CD 1
#define FTYPE_HARDDISK 2
static QEMUWin32AIOState *aio;
typedef struct RawWin32AIOData {
BlockDriverState *bs;
HANDLE hfile;
struct iovec *aio_iov;
int aio_niov;
size_t aio_nbytes;
off64_t aio_offset;
int aio_type;
} RawWin32AIOData;
typedef struct BDRVRawState {
HANDLE hfile;
int type;
char drive_path[16]; /* format: "d:\" */
QEMUWin32AIOState *aio;
} BDRVRawState;
/*
* Read/writes the data to/from a given linear buffer.
*
* Returns the number of bytes handles or -errno in case of an error. Short
* reads are only returned if the end of the file is reached.
*/
static size_t handle_aiocb_rw(RawWin32AIOData *aiocb)
{
size_t offset = 0;
int i;
for (i = 0; i < aiocb->aio_niov; i++) {
OVERLAPPED ov;
DWORD ret, ret_count, len;
memset(&ov, 0, sizeof(ov));
ov.Offset = (aiocb->aio_offset + offset);
ov.OffsetHigh = (aiocb->aio_offset + offset) >> 32;
len = aiocb->aio_iov[i].iov_len;
if (aiocb->aio_type & QEMU_AIO_WRITE) {
ret = WriteFile(aiocb->hfile, aiocb->aio_iov[i].iov_base,
len, &ret_count, &ov);
} else {
ret = ReadFile(aiocb->hfile, aiocb->aio_iov[i].iov_base,
len, &ret_count, &ov);
}
if (!ret) {
ret_count = 0;
}
if (ret_count != len) {
break;
}
offset += len;
}
return offset;
}
static int aio_worker(void *arg)
{
RawWin32AIOData *aiocb = arg;
ssize_t ret = 0;
size_t count;
switch (aiocb->aio_type & QEMU_AIO_TYPE_MASK) {
case QEMU_AIO_READ:
count = handle_aiocb_rw(aiocb);
if (count < aiocb->aio_nbytes && aiocb->bs->growable) {
/* A short read means that we have reached EOF. Pad the buffer
* with zeros for bytes after EOF. */
iov_memset(aiocb->aio_iov, aiocb->aio_niov, count,
0, aiocb->aio_nbytes - count);
count = aiocb->aio_nbytes;
}
if (count == aiocb->aio_nbytes) {
ret = 0;
} else {
ret = -EINVAL;
}
break;
case QEMU_AIO_WRITE:
count = handle_aiocb_rw(aiocb);
if (count == aiocb->aio_nbytes) {
count = 0;
} else {
count = -EINVAL;
}
break;
case QEMU_AIO_FLUSH:
if (!FlushFileBuffers(aiocb->hfile)) {
return -EIO;
}
break;
default:
fprintf(stderr, "invalid aio request (0x%x)\n", aiocb->aio_type);
ret = -EINVAL;
break;
}
g_slice_free(RawWin32AIOData, aiocb);
return ret;
}
static BlockDriverAIOCB *paio_submit(BlockDriverState *bs, HANDLE hfile,
int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
BlockDriverCompletionFunc *cb, void *opaque, int type)
{
RawWin32AIOData *acb = g_slice_new(RawWin32AIOData);
acb->bs = bs;
acb->hfile = hfile;
acb->aio_type = type;
if (qiov) {
acb->aio_iov = qiov->iov;
acb->aio_niov = qiov->niov;
}
acb->aio_nbytes = nb_sectors * 512;
acb->aio_offset = sector_num * 512;
trace_paio_submit(acb, opaque, sector_num, nb_sectors, type);
return thread_pool_submit_aio(aio_worker, acb, cb, opaque);
}
int qemu_ftruncate64(int fd, int64_t length)
{
LARGE_INTEGER li;
@ -89,6 +211,9 @@ static void raw_parse_flags(int flags, int *access_flags, DWORD *overlapped)
}
*overlapped = FILE_ATTRIBUTE_NORMAL;
if (flags & BDRV_O_NATIVE_AIO) {
*overlapped |= FILE_FLAG_OVERLAPPED;
}
if (flags & BDRV_O_NOCACHE) {
*overlapped |= FILE_FLAG_NO_BUFFERING;
}
@ -103,6 +228,13 @@ static int raw_open(BlockDriverState *bs, const char *filename, int flags)
s->type = FTYPE_FILE;
raw_parse_flags(flags, &access_flags, &overlapped);
if ((flags & BDRV_O_NATIVE_AIO) && aio == NULL) {
aio = win32_aio_init();
if (aio == NULL) {
return -EINVAL;
}
}
s->hfile = CreateFile(filename, access_flags,
FILE_SHARE_READ, NULL,
@ -112,64 +244,53 @@ static int raw_open(BlockDriverState *bs, const char *filename, int flags)
if (err == ERROR_ACCESS_DENIED)
return -EACCES;
return -1;
return -EINVAL;
}
if (flags & BDRV_O_NATIVE_AIO) {
int ret = win32_aio_attach(aio, s->hfile);
if (ret < 0) {
CloseHandle(s->hfile);
return ret;
}
s->aio = aio;
}
return 0;
}
static int raw_read(BlockDriverState *bs, int64_t sector_num,
uint8_t *buf, int nb_sectors)
static BlockDriverAIOCB *raw_aio_readv(BlockDriverState *bs,
int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
BlockDriverCompletionFunc *cb, void *opaque)
{
BDRVRawState *s = bs->opaque;
OVERLAPPED ov;
DWORD ret_count;
int ret;
int64_t offset = sector_num * 512;
int count = nb_sectors * 512;
memset(&ov, 0, sizeof(ov));
ov.Offset = offset;
ov.OffsetHigh = offset >> 32;
ret = ReadFile(s->hfile, buf, count, &ret_count, &ov);
if (!ret)
return ret_count;
if (ret_count == count)
ret_count = 0;
return ret_count;
}
static int raw_write(BlockDriverState *bs, int64_t sector_num,
const uint8_t *buf, int nb_sectors)
{
BDRVRawState *s = bs->opaque;
OVERLAPPED ov;
DWORD ret_count;
int ret;
int64_t offset = sector_num * 512;
int count = nb_sectors * 512;
memset(&ov, 0, sizeof(ov));
ov.Offset = offset;
ov.OffsetHigh = offset >> 32;
ret = WriteFile(s->hfile, buf, count, &ret_count, &ov);
if (!ret)
return ret_count;
if (ret_count == count)
ret_count = 0;
return ret_count;
}
static int raw_flush(BlockDriverState *bs)
{
BDRVRawState *s = bs->opaque;
int ret;
ret = FlushFileBuffers(s->hfile);
if (ret == 0) {
return -EIO;
if (s->aio) {
return win32_aio_submit(bs, s->aio, s->hfile, sector_num, qiov,
nb_sectors, cb, opaque, QEMU_AIO_READ);
} else {
return paio_submit(bs, s->hfile, sector_num, qiov, nb_sectors,
cb, opaque, QEMU_AIO_READ);
}
}
return 0;
static BlockDriverAIOCB *raw_aio_writev(BlockDriverState *bs,
int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
BlockDriverCompletionFunc *cb, void *opaque)
{
BDRVRawState *s = bs->opaque;
if (s->aio) {
return win32_aio_submit(bs, s->aio, s->hfile, sector_num, qiov,
nb_sectors, cb, opaque, QEMU_AIO_WRITE);
} else {
return paio_submit(bs, s->hfile, sector_num, qiov, nb_sectors,
cb, opaque, QEMU_AIO_WRITE);
}
}
static BlockDriverAIOCB *raw_aio_flush(BlockDriverState *bs,
BlockDriverCompletionFunc *cb, void *opaque)
{
BDRVRawState *s = bs->opaque;
return paio_submit(bs, s->hfile, 0, NULL, 0, cb, opaque, QEMU_AIO_FLUSH);
}
static void raw_close(BlockDriverState *bs)
@ -290,9 +411,9 @@ static BlockDriver bdrv_file = {
.bdrv_close = raw_close,
.bdrv_create = raw_create,
.bdrv_read = raw_read,
.bdrv_write = raw_write,
.bdrv_co_flush_to_disk = raw_flush,
.bdrv_aio_readv = raw_aio_readv,
.bdrv_aio_writev = raw_aio_writev,
.bdrv_aio_flush = raw_aio_flush,
.bdrv_truncate = raw_truncate,
.bdrv_getlength = raw_getlength,
@ -413,9 +534,9 @@ static BlockDriver bdrv_host_device = {
.bdrv_close = raw_close,
.bdrv_has_zero_init = hdev_has_zero_init,
.bdrv_read = raw_read,
.bdrv_write = raw_write,
.bdrv_co_flush_to_disk = raw_flush,
.bdrv_aio_readv = raw_aio_readv,
.bdrv_aio_writev = raw_aio_writev,
.bdrv_aio_flush = raw_aio_flush,
.bdrv_getlength = raw_getlength,
.bdrv_get_allocated_file_size

226
block/win32-aio.c Normal file
View File

@ -0,0 +1,226 @@
/*
* Block driver for RAW files (win32)
*
* Copyright (c) 2006 Fabrice Bellard
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "qemu-common.h"
#include "qemu-timer.h"
#include "block_int.h"
#include "module.h"
#include "qemu-common.h"
#include "qemu-aio.h"
#include "raw-aio.h"
#include "event_notifier.h"
#include <windows.h>
#include <winioctl.h>
#define FTYPE_FILE 0
#define FTYPE_CD 1
#define FTYPE_HARDDISK 2
struct QEMUWin32AIOState {
HANDLE hIOCP;
EventNotifier e;
int count;
};
typedef struct QEMUWin32AIOCB {
BlockDriverAIOCB common;
struct QEMUWin32AIOState *ctx;
int nbytes;
OVERLAPPED ov;
QEMUIOVector *qiov;
void *buf;
bool is_read;
bool is_linear;
} QEMUWin32AIOCB;
/*
* Completes an AIO request (calls the callback and frees the ACB).
*/
static void win32_aio_process_completion(QEMUWin32AIOState *s,
QEMUWin32AIOCB *waiocb, DWORD count)
{
int ret;
s->count--;
if (waiocb->ov.Internal != 0) {
ret = -EIO;
} else {
ret = 0;
if (count < waiocb->nbytes) {
/* Short reads mean EOF, pad with zeros. */
if (waiocb->is_read) {
qemu_iovec_memset(waiocb->qiov, count, 0,
waiocb->qiov->size - count);
} else {
ret = -EINVAL;
}
}
}
if (!waiocb->is_linear) {
if (ret == 0 && waiocb->is_read) {
QEMUIOVector *qiov = waiocb->qiov;
char *p = waiocb->buf;
int i;
for (i = 0; i < qiov->niov; ++i) {
memcpy(p, qiov->iov[i].iov_base, qiov->iov[i].iov_len);
p += qiov->iov[i].iov_len;
}
g_free(waiocb->buf);
}
}
waiocb->common.cb(waiocb->common.opaque, ret);
qemu_aio_release(waiocb);
}
static void win32_aio_completion_cb(EventNotifier *e)
{
QEMUWin32AIOState *s = container_of(e, QEMUWin32AIOState, e);
DWORD count;
ULONG_PTR key;
OVERLAPPED *ov;
event_notifier_test_and_clear(&s->e);
while (GetQueuedCompletionStatus(s->hIOCP, &count, &key, &ov, 0)) {
QEMUWin32AIOCB *waiocb = container_of(ov, QEMUWin32AIOCB, ov);
win32_aio_process_completion(s, waiocb, count);
}
}
static int win32_aio_flush_cb(EventNotifier *e)
{
QEMUWin32AIOState *s = container_of(e, QEMUWin32AIOState, e);
return (s->count > 0) ? 1 : 0;
}
static void win32_aio_cancel(BlockDriverAIOCB *blockacb)
{
QEMUWin32AIOCB *waiocb = (QEMUWin32AIOCB *)blockacb;
/*
* CancelIoEx is only supported in Vista and newer. For now, just
* wait for completion.
*/
while (!HasOverlappedIoCompleted(&waiocb->ov)) {
qemu_aio_wait();
}
}
static AIOPool win32_aio_pool = {
.aiocb_size = sizeof(QEMUWin32AIOCB),
.cancel = win32_aio_cancel,
};
BlockDriverAIOCB *win32_aio_submit(BlockDriverState *bs,
QEMUWin32AIOState *aio, HANDLE hfile,
int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
BlockDriverCompletionFunc *cb, void *opaque, int type)
{
struct QEMUWin32AIOCB *waiocb;
uint64_t offset = sector_num * 512;
DWORD rc;
waiocb = qemu_aio_get(&win32_aio_pool, bs, cb, opaque);
waiocb->nbytes = nb_sectors * 512;
waiocb->qiov = qiov;
waiocb->is_read = (type == QEMU_AIO_READ);
if (qiov->niov > 1) {
waiocb->buf = qemu_blockalign(bs, qiov->size);
if (type & QEMU_AIO_WRITE) {
char *p = waiocb->buf;
int i;
for (i = 0; i < qiov->niov; ++i) {
memcpy(p, qiov->iov[i].iov_base, qiov->iov[i].iov_len);
p += qiov->iov[i].iov_len;
}
}
waiocb->is_linear = false;
} else {
waiocb->buf = qiov->iov[0].iov_base;
waiocb->is_linear = true;
}
waiocb->ov = (OVERLAPPED) {
.Offset = (DWORD) offset,
.OffsetHigh = (DWORD) (offset >> 32),
.hEvent = event_notifier_get_handle(&aio->e)
};
aio->count++;
if (type & QEMU_AIO_READ) {
rc = ReadFile(hfile, waiocb->buf, waiocb->nbytes, NULL, &waiocb->ov);
} else {
rc = WriteFile(hfile, waiocb->buf, waiocb->nbytes, NULL, &waiocb->ov);
}
if(rc == 0 && GetLastError() != ERROR_IO_PENDING) {
goto out_dec_count;
}
return &waiocb->common;
out_dec_count:
aio->count--;
qemu_aio_release(waiocb);
return NULL;
}
int win32_aio_attach(QEMUWin32AIOState *aio, HANDLE hfile)
{
if (CreateIoCompletionPort(hfile, aio->hIOCP, (ULONG_PTR) 0, 0) == NULL) {
return -EINVAL;
} else {
return 0;
}
}
QEMUWin32AIOState *win32_aio_init(void)
{
QEMUWin32AIOState *s;
s = g_malloc0(sizeof(*s));
if (event_notifier_init(&s->e, false) < 0) {
goto out_free_state;
}
s->hIOCP = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
if (s->hIOCP == NULL) {
goto out_close_efd;
}
qemu_aio_set_event_notifier(&s->e, win32_aio_completion_cb,
win32_aio_flush_cb);
return s;
out_close_efd:
event_notifier_cleanup(&s->e);
out_free_state:
g_free(s);
return NULL;
}

View File

@ -436,6 +436,12 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi)
return NULL;
}
if (qemu_opt_get(opts, "boot") != NULL) {
fprintf(stderr, "qemu-kvm: boot=on|off is deprecated and will be "
"ignored. Future versions will reject this parameter. Please "
"update your scripts.\n");
}
on_write_error = BLOCKDEV_ON_ERROR_ENOSPC;
if ((buf = qemu_opt_get(opts, "werror")) != NULL) {
if (type != IF_IDE && type != IF_SCSI && type != IF_VIRTIO && type != IF_NONE) {

View File

@ -174,6 +174,13 @@ static int buffered_close(void *opaque)
* 1: Time to stop
* negative: There has been an error
*/
static int buffered_get_fd(void *opaque)
{
QEMUFileBuffered *s = opaque;
return qemu_get_fd(s->file);
}
static int buffered_rate_limit(void *opaque)
{
QEMUFileBuffered *s = opaque;
@ -234,6 +241,15 @@ static void buffered_rate_tick(void *opaque)
buffered_put_buffer(s, NULL, 0, 0);
}
static const QEMUFileOps buffered_file_ops = {
.get_fd = buffered_get_fd,
.put_buffer = buffered_put_buffer,
.close = buffered_close,
.rate_limit = buffered_rate_limit,
.get_rate_limit = buffered_get_rate_limit,
.set_rate_limit = buffered_set_rate_limit,
};
QEMUFile *qemu_fopen_ops_buffered(MigrationState *migration_state)
{
QEMUFileBuffered *s;
@ -243,10 +259,7 @@ QEMUFile *qemu_fopen_ops_buffered(MigrationState *migration_state)
s->migration_state = migration_state;
s->xfer_limit = migration_state->bandwidth_limit / 10;
s->file = qemu_fopen_ops(s, buffered_put_buffer, NULL,
buffered_close, buffered_rate_limit,
buffered_set_rate_limit,
buffered_get_rate_limit);
s->file = qemu_fopen_ops(s, &buffered_file_ops);
s->timer = qemu_new_timer_ms(rt_clock, buffered_rate_tick, s);

View File

@ -50,16 +50,20 @@
# define __printf__ __gnu_printf__
# endif
# endif
#if defined(_WIN32)
#define GCC_WEAK __attribute__((weak))
#define GCC_WEAK_DECL GCC_WEAK
#else
#define GCC_WEAK __attribute__((weak))
#define GCC_WEAK_DECL
#endif
# if defined(__APPLE__)
# define QEMU_WEAK_ALIAS(newname, oldname) \
static typeof(oldname) weak_##newname __attribute__((unused, weakref(#oldname)))
# define QEMU_WEAK_REF(newname, oldname) (weak_##newname ? weak_##newname : oldname)
# else
# define QEMU_WEAK_ALIAS(newname, oldname) \
typeof(oldname) newname __attribute__((weak, alias (#oldname)))
# define QEMU_WEAK_REF(newname, oldname) newname
# endif
#else
#define GCC_ATTR /**/
#define GCC_FMT_ATTR(n, m)
#define QEMU_WEAK_ALIAS(newname, oldname) \
_Pragma("weak " #newname "=" #oldname)
#endif
#endif /* COMPILER_H */

46
configure vendored
View File

@ -147,6 +147,7 @@ curses=""
docs=""
fdt=""
nptl=""
pixman=""
sdl=""
virtfs=""
vnc="yes"
@ -642,6 +643,10 @@ for opt do
# configure to be used by RPM and similar macros that set
# lots of directory switches by default.
;;
--with-system-pixman) pixman="system"
;;
--without-system-pixman) pixman="internal"
;;
--disable-sdl) sdl="no"
;;
--enable-sdl) sdl="yes"
@ -2094,6 +2099,34 @@ else
exit 1
fi
##########################################
# pixman support probe
if test "$pixman" = ""; then
if $pkg_config pixman-1 > /dev/null 2>&1; then
pixman="system"
else
pixman="internal"
fi
fi
if test "$pixman" = "system"; then
pixman_cflags=`$pkg_config --cflags pixman-1 2>/dev/null`
pixman_libs=`$pkg_config --libs pixman-1 2>/dev/null`
else
if test ! -d ${source_path}/pixman/pixman; then
echo "ERROR: pixman not present. Your options:"
echo " (1) Prefered: Install the pixman devel package (any recent"
echo " distro should have packages as Xorg needs pixman too)."
echo " (2) Fetch the pixman submodule, using:"
echo " git submodule update --init pixman"
exit 1
fi
pixman_cflags="-I${source_path}/pixman/pixman"
pixman_libs="-Lpixman/pixman/.libs -lpixman-1"
fi
QEMU_CFLAGS="$QEMU_CFLAGS $pixman_cflags"
libs_softmmu="$libs_softmmu $pixman_libs"
##########################################
# libcap probe
@ -2768,7 +2801,7 @@ fi
# check for usbredirparser for usb network redirection support
if test "$usb_redir" != "no" ; then
if $pkg_config --atleast-version=0.5 libusbredirparser-0.5 >/dev/null 2>&1 ; then
if $pkg_config --atleast-version=0.5.3 libusbredirparser-0.5 >/dev/null 2>&1 ; then
usb_redir="yes"
usb_redir_cflags=$($pkg_config --cflags libusbredirparser-0.5 2>/dev/null)
usb_redir_libs=$($pkg_config --libs libusbredirparser-0.5 2>/dev/null)
@ -3155,6 +3188,7 @@ echo "-Werror enabled $werror"
if test "$darwin" = "yes" ; then
echo "Cocoa support $cocoa"
fi
echo "pixman $pixman"
echo "SDL support $sdl"
echo "curses support $curses"
echo "curl support $curl"
@ -3859,6 +3893,12 @@ upper() {
echo "$@"| LC_ALL=C tr '[a-z]' '[A-Z]'
}
case "$cpu" in
i386|x86_64|ppc)
echo "CONFIG_QEMU_LDST_OPTIMIZATION=y" >> $config_target_mak
;;
esac
echo "TARGET_SHORT_ALIGNMENT=$target_short_alignment" >> $config_target_mak
echo "TARGET_INT_ALIGNMENT=$target_int_alignment" >> $config_target_mak
echo "TARGET_LONG_ALIGNMENT=$target_long_alignment" >> $config_target_mak
@ -3920,6 +3960,9 @@ if test "$target_softmmu" = "yes" ; then
if test "$smartcard_nss" = "yes" ; then
echo "subdir-$target: subdir-libcacard" >> $config_host_mak
fi
if test "$pixman" = "internal" ; then
echo "subdir-$target: subdir-pixman" >> $config_host_mak
fi
case "$target_arch2" in
i386|x86_64)
echo "CONFIG_HAVE_CORE_DUMP=y" >> $config_target_mak
@ -4123,6 +4166,7 @@ DIRS="$DIRS pc-bios/optionrom pc-bios/spapr-rtas"
DIRS="$DIRS roms/seabios roms/vgabios"
DIRS="$DIRS qapi-generated"
DIRS="$DIRS libcacard libcacard/libcacard libcacard/trace"
DIRS="$DIRS pixman"
FILES="Makefile tests/tcg/Makefile qdict-test-data.txt"
FILES="$FILES tests/tcg/cris/Makefile tests/tcg/cris/.gdbinit"
FILES="$FILES tests/tcg/lm32/Makefile libcacard/Makefile"

252
console.c
View File

@ -114,20 +114,20 @@ typedef enum {
TEXT_CONSOLE_FIXED_SIZE
} console_type_t;
/* ??? This is mis-named.
It is used for both text and graphical consoles. */
struct TextConsole {
struct QemuConsole {
int index;
console_type_t console_type;
DisplayState *ds;
/* Graphic console state. */
vga_hw_update_ptr hw_update;
vga_hw_invalidate_ptr hw_invalidate;
vga_hw_screen_dump_ptr hw_screen_dump;
vga_hw_text_update_ptr hw_text_update;
void *hw;
int g_width, g_height;
/* Text console state */
int width;
int height;
int total_height;
@ -161,8 +161,8 @@ struct TextConsole {
};
static DisplayState *display_state;
static TextConsole *active_console;
static TextConsole *consoles[MAX_CONSOLES];
static QemuConsole *active_console;
static QemuConsole *consoles[MAX_CONSOLES];
static int nb_consoles = 0;
void vga_hw_update(void)
@ -179,7 +179,7 @@ void vga_hw_invalidate(void)
void qmp_screendump(const char *filename, Error **errp)
{
TextConsole *previous_active_console;
QemuConsole *previous_active_console;
bool cswitch;
previous_active_console = active_console;
@ -521,7 +521,7 @@ static void vga_putcharxy(DisplayState *ds, int x, int y, int ch,
}
}
static void text_console_resize(TextConsole *s)
static void text_console_resize(QemuConsole *s)
{
TextCell *cells, *c, *c1;
int w1, x, y, last_width;
@ -553,7 +553,7 @@ static void text_console_resize(TextConsole *s)
s->cells = cells;
}
static inline void text_update_xy(TextConsole *s, int x, int y)
static inline void text_update_xy(QemuConsole *s, int x, int y)
{
s->text_x[0] = MIN(s->text_x[0], x);
s->text_x[1] = MAX(s->text_x[1], x);
@ -561,7 +561,7 @@ static inline void text_update_xy(TextConsole *s, int x, int y)
s->text_y[1] = MAX(s->text_y[1], y);
}
static void invalidate_xy(TextConsole *s, int x, int y)
static void invalidate_xy(QemuConsole *s, int x, int y)
{
if (s->update_x0 > x * FONT_WIDTH)
s->update_x0 = x * FONT_WIDTH;
@ -573,7 +573,7 @@ static void invalidate_xy(TextConsole *s, int x, int y)
s->update_y1 = (y + 1) * FONT_HEIGHT;
}
static void update_xy(TextConsole *s, int x, int y)
static void update_xy(QemuConsole *s, int x, int y)
{
TextCell *c;
int y1, y2;
@ -597,7 +597,7 @@ static void update_xy(TextConsole *s, int x, int y)
}
}
static void console_show_cursor(TextConsole *s, int show)
static void console_show_cursor(QemuConsole *s, int show)
{
TextCell *c;
int y, y1;
@ -631,42 +631,45 @@ static void console_show_cursor(TextConsole *s, int show)
}
}
static void console_refresh(TextConsole *s)
static void console_refresh(QemuConsole *s)
{
TextCell *c;
int x, y, y1;
if (s != active_console)
return;
if (!ds_get_bits_per_pixel(s->ds)) {
if (s->ds->have_text) {
s->text_x[0] = 0;
s->text_y[0] = 0;
s->text_x[1] = s->width - 1;
s->text_y[1] = s->height - 1;
s->cursor_invalidate = 1;
return;
}
vga_fill_rect(s->ds, 0, 0, ds_get_width(s->ds), ds_get_height(s->ds),
color_table[0][COLOR_BLACK]);
y1 = s->y_displayed;
for(y = 0; y < s->height; y++) {
c = s->cells + y1 * s->width;
for(x = 0; x < s->width; x++) {
vga_putcharxy(s->ds, x, y, c->ch,
&(c->t_attrib));
c++;
if (s->ds->have_gfx) {
vga_fill_rect(s->ds, 0, 0, ds_get_width(s->ds), ds_get_height(s->ds),
color_table[0][COLOR_BLACK]);
y1 = s->y_displayed;
for (y = 0; y < s->height; y++) {
c = s->cells + y1 * s->width;
for (x = 0; x < s->width; x++) {
vga_putcharxy(s->ds, x, y, c->ch,
&(c->t_attrib));
c++;
}
if (++y1 == s->total_height) {
y1 = 0;
}
}
if (++y1 == s->total_height)
y1 = 0;
console_show_cursor(s, 1);
dpy_gfx_update(s->ds, 0, 0, ds_get_width(s->ds), ds_get_height(s->ds));
}
console_show_cursor(s, 1);
dpy_update(s->ds, 0, 0, ds_get_width(s->ds), ds_get_height(s->ds));
}
static void console_scroll(int ydelta)
{
TextConsole *s;
QemuConsole *s;
int i, y1;
s = active_console;
@ -698,7 +701,7 @@ static void console_scroll(int ydelta)
console_refresh(s);
}
static void console_put_lf(TextConsole *s)
static void console_put_lf(QemuConsole *s)
{
TextCell *c;
int x, y1;
@ -749,7 +752,7 @@ static void console_put_lf(TextConsole *s)
* NOTE: I know this code is not very efficient (checking every color for it
* self) but it is more readable and better maintainable.
*/
static void console_handle_escape(TextConsole *s)
static void console_handle_escape(QemuConsole *s)
{
int i;
@ -842,7 +845,7 @@ static void console_handle_escape(TextConsole *s)
}
}
static void console_clear_xy(TextConsole *s, int x, int y)
static void console_clear_xy(QemuConsole *s, int x, int y)
{
int y1 = (s->y_base + y) % s->total_height;
TextCell *c = &s->cells[y1 * s->width + x];
@ -852,7 +855,7 @@ static void console_clear_xy(TextConsole *s, int x, int y)
}
/* set cursor, checking bounds */
static void set_cursor(TextConsole *s, int x, int y)
static void set_cursor(QemuConsole *s, int x, int y)
{
if (x < 0) {
x = 0;
@ -871,7 +874,7 @@ static void set_cursor(TextConsole *s, int x, int y)
s->y = y;
}
static void console_putchar(TextConsole *s, int ch)
static void console_putchar(QemuConsole *s, int ch)
{
TextCell *c;
int y1, i;
@ -1078,7 +1081,7 @@ static void console_putchar(TextConsole *s, int ch)
void console_select(unsigned int index)
{
TextConsole *s;
QemuConsole *s;
if (index >= MAX_CONSOLES)
return;
@ -1094,24 +1097,24 @@ void console_select(unsigned int index)
qemu_del_timer(active_console->cursor_timer);
}
active_console = s;
if (ds_get_bits_per_pixel(s->ds)) {
if (ds->have_gfx) {
ds->surface = qemu_resize_displaysurface(ds, s->g_width, s->g_height);
} else {
s->ds->surface->width = s->width;
s->ds->surface->height = s->height;
dpy_gfx_resize(ds);
}
if (ds->have_text) {
dpy_text_resize(ds, s->width, s->height);
}
if (s->cursor_timer) {
qemu_mod_timer(s->cursor_timer,
qemu_get_clock_ms(rt_clock) + CONSOLE_CURSOR_PERIOD / 2);
}
dpy_resize(s->ds);
vga_hw_invalidate();
}
}
static int console_puts(CharDriverState *chr, const uint8_t *buf, int len)
{
TextConsole *s = chr->opaque;
QemuConsole *s = chr->opaque;
int i;
s->update_x0 = s->width * FONT_WIDTH;
@ -1123,17 +1126,17 @@ static int console_puts(CharDriverState *chr, const uint8_t *buf, int len)
console_putchar(s, buf[i]);
}
console_show_cursor(s, 1);
if (ds_get_bits_per_pixel(s->ds) && s->update_x0 < s->update_x1) {
dpy_update(s->ds, s->update_x0, s->update_y0,
s->update_x1 - s->update_x0,
s->update_y1 - s->update_y0);
if (s->ds->have_gfx && s->update_x0 < s->update_x1) {
dpy_gfx_update(s->ds, s->update_x0, s->update_y0,
s->update_x1 - s->update_x0,
s->update_y1 - s->update_y0);
}
return len;
}
static void kbd_send_chars(void *opaque)
{
TextConsole *s = opaque;
QemuConsole *s = opaque;
int len;
uint8_t buf[16];
@ -1156,7 +1159,7 @@ static void kbd_send_chars(void *opaque)
/* called when an ascii key is pressed */
void kbd_put_keysym(int keysym)
{
TextConsole *s;
QemuConsole *s;
uint8_t buf[16], *q;
int c;
@ -1211,7 +1214,7 @@ void kbd_put_keysym(int keysym)
static void text_console_invalidate(void *opaque)
{
TextConsole *s = (TextConsole *) opaque;
QemuConsole *s = (QemuConsole *) opaque;
if (!ds_get_bits_per_pixel(s->ds) && s->console_type == TEXT_CONSOLE) {
s->g_width = ds_get_width(s->ds);
s->g_height = ds_get_height(s->ds);
@ -1222,7 +1225,7 @@ static void text_console_invalidate(void *opaque)
static void text_console_update(void *opaque, console_ch_t *chardata)
{
TextConsole *s = (TextConsole *) opaque;
QemuConsole *s = (QemuConsole *) opaque;
int i, j, src;
if (s->text_x[0] <= s->text_x[1]) {
@ -1234,23 +1237,23 @@ static void text_console_update(void *opaque, console_ch_t *chardata)
(s->cells[src].t_attrib.fgcol << 12) |
(s->cells[src].t_attrib.bgcol << 8) |
(s->cells[src].t_attrib.bold << 21));
dpy_update(s->ds, s->text_x[0], s->text_y[0],
s->text_x[1] - s->text_x[0], i - s->text_y[0]);
dpy_text_update(s->ds, s->text_x[0], s->text_y[0],
s->text_x[1] - s->text_x[0], i - s->text_y[0]);
s->text_x[0] = s->width;
s->text_y[0] = s->height;
s->text_x[1] = 0;
s->text_y[1] = 0;
}
if (s->cursor_invalidate) {
dpy_cursor(s->ds, s->x, s->y);
dpy_text_cursor(s->ds, s->x, s->y);
s->cursor_invalidate = 0;
}
}
static TextConsole *get_graphic_console(DisplayState *ds)
static QemuConsole *get_graphic_console(DisplayState *ds)
{
int i;
TextConsole *s;
QemuConsole *s;
for (i = 0; i < nb_consoles; i++) {
s = consoles[i];
if (s->console_type == GRAPHIC_CONSOLE && s->ds == ds)
@ -1259,14 +1262,14 @@ static TextConsole *get_graphic_console(DisplayState *ds)
return NULL;
}
static TextConsole *new_console(DisplayState *ds, console_type_t console_type)
static QemuConsole *new_console(DisplayState *ds, console_type_t console_type)
{
TextConsole *s;
QemuConsole *s;
int i;
if (nb_consoles >= MAX_CONSOLES)
return NULL;
s = g_malloc0(sizeof(TextConsole));
s = g_malloc0(sizeof(QemuConsole));
if (!active_console || ((active_console->console_type != GRAPHIC_CONSOLE) &&
(console_type == GRAPHIC_CONSOLE))) {
active_console = s;
@ -1291,85 +1294,86 @@ static TextConsole *new_console(DisplayState *ds, console_type_t console_type)
return s;
}
static DisplaySurface* defaultallocator_create_displaysurface(int width, int height)
static void qemu_alloc_display(DisplaySurface *surface, int width, int height,
int linesize, PixelFormat pf, int newflags)
{
DisplaySurface *surface = (DisplaySurface*) g_malloc0(sizeof(DisplaySurface));
int linesize = width * 4;
qemu_alloc_display(surface, width, height, linesize,
qemu_default_pixelformat(32), 0);
return surface;
}
static DisplaySurface* defaultallocator_resize_displaysurface(DisplaySurface *surface,
int width, int height)
{
int linesize = width * 4;
qemu_alloc_display(surface, width, height, linesize,
qemu_default_pixelformat(32), 0);
return surface;
}
void qemu_alloc_display(DisplaySurface *surface, int width, int height,
int linesize, PixelFormat pf, int newflags)
{
void *data;
surface->width = width;
surface->height = height;
surface->linesize = linesize;
surface->pf = pf;
if (surface->flags & QEMU_ALLOCATED_FLAG) {
data = g_realloc(surface->data,
surface->linesize * surface->height);
} else {
data = g_malloc(surface->linesize * surface->height);
}
surface->data = (uint8_t *)data;
qemu_pixman_image_unref(surface->image);
surface->image = NULL;
surface->format = qemu_pixman_get_format(&pf);
assert(surface->format != 0);
surface->image = pixman_image_create_bits(surface->format,
width, height,
NULL, linesize);
assert(surface->image != NULL);
surface->flags = newflags | QEMU_ALLOCATED_FLAG;
#ifdef HOST_WORDS_BIGENDIAN
surface->flags |= QEMU_BIG_ENDIAN_FLAG;
#endif
}
DisplaySurface* qemu_create_displaysurface_from(int width, int height, int bpp,
int linesize, uint8_t *data)
DisplaySurface *qemu_create_displaysurface(DisplayState *ds,
int width, int height)
{
DisplaySurface *surface = (DisplaySurface*) g_malloc0(sizeof(DisplaySurface));
DisplaySurface *surface = g_new0(DisplaySurface, 1);
int linesize = width * 4;
qemu_alloc_display(surface, width, height, linesize,
qemu_default_pixelformat(32), 0);
return surface;
}
DisplaySurface *qemu_resize_displaysurface(DisplayState *ds,
int width, int height)
{
int linesize = width * 4;
trace_displaysurface_resize(ds, ds->surface, width, height);
qemu_alloc_display(ds->surface, width, height, linesize,
qemu_default_pixelformat(32), 0);
return ds->surface;
}
DisplaySurface *qemu_create_displaysurface_from(int width, int height, int bpp,
int linesize, uint8_t *data)
{
DisplaySurface *surface = g_new0(DisplaySurface, 1);
surface->width = width;
surface->height = height;
surface->linesize = linesize;
surface->pf = qemu_default_pixelformat(bpp);
surface->format = qemu_pixman_get_format(&surface->pf);
assert(surface->format != 0);
surface->image = pixman_image_create_bits(surface->format,
width, height,
(void *)data, linesize);
assert(surface->image != NULL);
#ifdef HOST_WORDS_BIGENDIAN
surface->flags = QEMU_BIG_ENDIAN_FLAG;
#endif
surface->data = data;
return surface;
}
static void defaultallocator_free_displaysurface(DisplaySurface *surface)
void qemu_free_displaysurface(DisplayState *ds)
{
if (surface == NULL)
trace_displaysurface_free(ds, ds->surface);
if (ds->surface == NULL) {
return;
if (surface->flags & QEMU_ALLOCATED_FLAG)
g_free(surface->data);
g_free(surface);
}
qemu_pixman_image_unref(ds->surface->image);
g_free(ds->surface);
}
static struct DisplayAllocator default_allocator = {
defaultallocator_create_displaysurface,
defaultallocator_resize_displaysurface,
defaultallocator_free_displaysurface
};
static void dumb_display_init(void)
{
DisplayState *ds = g_malloc0(sizeof(DisplayState));
int width = 640;
int height = 480;
ds->allocator = &default_allocator;
if (is_fixedsize_console()) {
width = active_console->g_width;
height = active_console->g_height;
@ -1399,29 +1403,16 @@ DisplayState *get_displaystate(void)
return display_state;
}
DisplayAllocator *register_displayallocator(DisplayState *ds, DisplayAllocator *da)
{
if(ds->allocator == &default_allocator) {
DisplaySurface *surf;
surf = da->create_displaysurface(ds_get_width(ds), ds_get_height(ds));
defaultallocator_free_displaysurface(ds->surface);
ds->surface = surf;
ds->allocator = da;
}
return ds->allocator;
}
DisplayState *graphic_console_init(vga_hw_update_ptr update,
vga_hw_invalidate_ptr invalidate,
vga_hw_screen_dump_ptr screen_dump,
vga_hw_text_update_ptr text_update,
void *opaque)
{
TextConsole *s;
QemuConsole *s;
DisplayState *ds;
ds = (DisplayState *) g_malloc0(sizeof(DisplayState));
ds->allocator = &default_allocator;
ds->surface = qemu_create_displaysurface(ds, 640, 480);
s = new_console(ds, GRAPHIC_CONSOLE);
@ -1463,14 +1454,14 @@ void console_color_init(DisplayState *ds)
static void text_console_set_echo(CharDriverState *chr, bool echo)
{
TextConsole *s = chr->opaque;
QemuConsole *s = chr->opaque;
s->echo = echo;
}
static void text_console_update_cursor(void *opaque)
{
TextConsole *s = opaque;
QemuConsole *s = opaque;
s->cursor_visible_phase = !s->cursor_visible_phase;
vga_hw_invalidate();
@ -1480,7 +1471,7 @@ static void text_console_update_cursor(void *opaque)
static void text_console_do_init(CharDriverState *chr, DisplayState *ds)
{
TextConsole *s;
QemuConsole *s;
static int color_inited;
s = chr->opaque;
@ -1543,7 +1534,7 @@ static void text_console_do_init(CharDriverState *chr, DisplayState *ds)
CharDriverState *text_console_init(QemuOpts *opts)
{
CharDriverState *chr;
TextConsole *s;
QemuConsole *s;
unsigned width;
unsigned height;
@ -1589,14 +1580,14 @@ void text_consoles_set_display(DisplayState *ds)
void qemu_console_resize(DisplayState *ds, int width, int height)
{
TextConsole *s = get_graphic_console(ds);
QemuConsole *s = get_graphic_console(ds);
if (!s) return;
s->g_width = width;
s->g_height = height;
if (is_graphic_console()) {
ds->surface = qemu_resize_displaysurface(ds, width, height);
dpy_resize(ds);
dpy_gfx_resize(ds);
}
}
@ -1604,7 +1595,7 @@ void qemu_console_copy(DisplayState *ds, int src_x, int src_y,
int dst_x, int dst_y, int w, int h)
{
if (is_graphic_console()) {
dpy_copy(ds, src_x, src_y, dst_x, dst_y, w, h);
dpy_gfx_copy(ds, src_x, src_y, dst_x, dst_y, w, h);
}
}
@ -1715,18 +1706,15 @@ PixelFormat qemu_default_pixelformat(int bpp)
pf.rmask = 0x00FF0000;
pf.gmask = 0x0000FF00;
pf.bmask = 0x000000FF;
pf.amax = 255;
pf.rmax = 255;
pf.gmax = 255;
pf.bmax = 255;
pf.ashift = 24;
pf.rshift = 16;
pf.gshift = 8;
pf.bshift = 0;
pf.rbits = 8;
pf.gbits = 8;
pf.bbits = 8;
pf.abits = 8;
break;
default:
break;

259
console.h
View File

@ -2,6 +2,7 @@
#define CONSOLE_H
#include "qemu-char.h"
#include "qemu-pixman.h"
#include "qdict.h"
#include "notify.h"
#include "monitor.h"
@ -107,7 +108,6 @@ void kbd_put_keysym(int keysym);
#define QEMU_BIG_ENDIAN_FLAG 0x01
#define QEMU_ALLOCATED_FLAG 0x02
#define QEMU_REALPIXELS_FLAG 0x04
struct PixelFormat {
uint8_t bits_per_pixel;
@ -120,11 +120,9 @@ struct PixelFormat {
};
struct DisplaySurface {
pixman_format_code_t format;
pixman_image_t *image;
uint8_t flags;
int width;
int height;
int linesize; /* bytes per line */
uint8_t *data;
struct PixelFormat pf;
};
@ -154,35 +152,32 @@ struct DisplayChangeListener {
int idle;
uint64_t gui_timer_interval;
void (*dpy_update)(struct DisplayState *s, int x, int y, int w, int h);
void (*dpy_resize)(struct DisplayState *s);
void (*dpy_setdata)(struct DisplayState *s);
void (*dpy_refresh)(struct DisplayState *s);
void (*dpy_copy)(struct DisplayState *s, int src_x, int src_y,
int dst_x, int dst_y, int w, int h);
void (*dpy_fill)(struct DisplayState *s, int x, int y,
int w, int h, uint32_t c);
void (*dpy_gfx_update)(struct DisplayState *s, int x, int y, int w, int h);
void (*dpy_gfx_resize)(struct DisplayState *s);
void (*dpy_gfx_setdata)(struct DisplayState *s);
void (*dpy_gfx_copy)(struct DisplayState *s, int src_x, int src_y,
int dst_x, int dst_y, int w, int h);
void (*dpy_text_cursor)(struct DisplayState *s, int x, int y);
void (*dpy_text_resize)(struct DisplayState *s, int w, int h);
void (*dpy_text_update)(struct DisplayState *s, int x, int y, int w, int h);
struct DisplayChangeListener *next;
};
void (*dpy_mouse_set)(struct DisplayState *s, int x, int y, int on);
void (*dpy_cursor_define)(struct DisplayState *s, QEMUCursor *cursor);
struct DisplayAllocator {
DisplaySurface* (*create_displaysurface)(int width, int height);
DisplaySurface* (*resize_displaysurface)(DisplaySurface *surface, int width, int height);
void (*free_displaysurface)(DisplaySurface *surface);
QLIST_ENTRY(DisplayChangeListener) next;
};
struct DisplayState {
struct DisplaySurface *surface;
void *opaque;
struct QEMUTimer *gui_timer;
bool have_gfx;
bool have_text;
struct DisplayAllocator* allocator;
struct DisplayChangeListener* listeners;
void (*mouse_set)(int x, int y, int on);
void (*cursor_define)(QEMUCursor *cursor);
QLIST_HEAD(, DisplayChangeListener) listeners;
struct DisplayState *next;
};
@ -191,29 +186,14 @@ void register_displaystate(DisplayState *ds);
DisplayState *get_displaystate(void);
DisplaySurface* qemu_create_displaysurface_from(int width, int height, int bpp,
int linesize, uint8_t *data);
void qemu_alloc_display(DisplaySurface *surface, int width, int height,
int linesize, PixelFormat pf, int newflags);
PixelFormat qemu_different_endianness_pixelformat(int bpp);
PixelFormat qemu_default_pixelformat(int bpp);
DisplayAllocator *register_displayallocator(DisplayState *ds, DisplayAllocator *da);
static inline DisplaySurface* qemu_create_displaysurface(DisplayState *ds, int width, int height)
{
return ds->allocator->create_displaysurface(width, height);
}
static inline DisplaySurface* qemu_resize_displaysurface(DisplayState *ds, int width, int height)
{
trace_displaysurface_resize(ds, ds->surface, width, height);
return ds->allocator->resize_displaysurface(ds->surface, width, height);
}
static inline void qemu_free_displaysurface(DisplayState *ds)
{
trace_displaysurface_free(ds, ds->surface);
ds->allocator->free_displaysurface(ds->surface);
}
DisplaySurface *qemu_create_displaysurface(DisplayState *ds,
int width, int height);
DisplaySurface *qemu_resize_displaysurface(DisplayState *ds,
int width, int height);
void qemu_free_displaysurface(DisplayState *ds);
static inline int is_surface_bgr(DisplaySurface *surface)
{
@ -225,109 +205,196 @@ static inline int is_surface_bgr(DisplaySurface *surface)
static inline int is_buffer_shared(DisplaySurface *surface)
{
return (!(surface->flags & QEMU_ALLOCATED_FLAG) &&
!(surface->flags & QEMU_REALPIXELS_FLAG));
return !(surface->flags & QEMU_ALLOCATED_FLAG);
}
void gui_setup_refresh(DisplayState *ds);
static inline void register_displaychangelistener(DisplayState *ds, DisplayChangeListener *dcl)
{
dcl->next = ds->listeners;
ds->listeners = dcl;
}
static inline void dpy_update(DisplayState *s, int x, int y, int w, int h)
{
struct DisplayChangeListener *dcl = s->listeners;
while (dcl != NULL) {
dcl->dpy_update(s, x, y, w, h);
dcl = dcl->next;
QLIST_INSERT_HEAD(&ds->listeners, dcl, next);
gui_setup_refresh(ds);
if (dcl->dpy_gfx_resize) {
dcl->dpy_gfx_resize(ds);
}
}
static inline void dpy_resize(DisplayState *s)
static inline void unregister_displaychangelistener(DisplayState *ds,
DisplayChangeListener *dcl)
{
struct DisplayChangeListener *dcl = s->listeners;
while (dcl != NULL) {
dcl->dpy_resize(s);
dcl = dcl->next;
QLIST_REMOVE(dcl, next);
gui_setup_refresh(ds);
}
static inline void dpy_gfx_update(DisplayState *s, int x, int y, int w, int h)
{
struct DisplayChangeListener *dcl;
QLIST_FOREACH(dcl, &s->listeners, next) {
if (dcl->dpy_gfx_update) {
dcl->dpy_gfx_update(s, x, y, w, h);
}
}
}
static inline void dpy_setdata(DisplayState *s)
static inline void dpy_gfx_resize(DisplayState *s)
{
struct DisplayChangeListener *dcl = s->listeners;
while (dcl != NULL) {
if (dcl->dpy_setdata) dcl->dpy_setdata(s);
dcl = dcl->next;
struct DisplayChangeListener *dcl;
QLIST_FOREACH(dcl, &s->listeners, next) {
if (dcl->dpy_gfx_resize) {
dcl->dpy_gfx_resize(s);
}
}
}
static inline void dpy_gfx_setdata(DisplayState *s)
{
struct DisplayChangeListener *dcl;
QLIST_FOREACH(dcl, &s->listeners, next) {
if (dcl->dpy_gfx_setdata) {
dcl->dpy_gfx_setdata(s);
}
}
}
static inline void dpy_refresh(DisplayState *s)
{
struct DisplayChangeListener *dcl = s->listeners;
while (dcl != NULL) {
if (dcl->dpy_refresh) dcl->dpy_refresh(s);
dcl = dcl->next;
struct DisplayChangeListener *dcl;
QLIST_FOREACH(dcl, &s->listeners, next) {
if (dcl->dpy_refresh) {
dcl->dpy_refresh(s);
}
}
}
static inline void dpy_copy(struct DisplayState *s, int src_x, int src_y,
int dst_x, int dst_y, int w, int h) {
struct DisplayChangeListener *dcl = s->listeners;
while (dcl != NULL) {
if (dcl->dpy_copy)
dcl->dpy_copy(s, src_x, src_y, dst_x, dst_y, w, h);
else /* TODO */
dcl->dpy_update(s, dst_x, dst_y, w, h);
dcl = dcl->next;
static inline void dpy_gfx_copy(struct DisplayState *s, int src_x, int src_y,
int dst_x, int dst_y, int w, int h)
{
struct DisplayChangeListener *dcl;
QLIST_FOREACH(dcl, &s->listeners, next) {
if (dcl->dpy_gfx_copy) {
dcl->dpy_gfx_copy(s, src_x, src_y, dst_x, dst_y, w, h);
} else { /* TODO */
dcl->dpy_gfx_update(s, dst_x, dst_y, w, h);
}
}
}
static inline void dpy_fill(struct DisplayState *s, int x, int y,
int w, int h, uint32_t c) {
struct DisplayChangeListener *dcl = s->listeners;
while (dcl != NULL) {
if (dcl->dpy_fill) dcl->dpy_fill(s, x, y, w, h, c);
dcl = dcl->next;
static inline void dpy_text_cursor(struct DisplayState *s, int x, int y)
{
struct DisplayChangeListener *dcl;
QLIST_FOREACH(dcl, &s->listeners, next) {
if (dcl->dpy_text_cursor) {
dcl->dpy_text_cursor(s, x, y);
}
}
}
static inline void dpy_cursor(struct DisplayState *s, int x, int y) {
struct DisplayChangeListener *dcl = s->listeners;
while (dcl != NULL) {
if (dcl->dpy_text_cursor) dcl->dpy_text_cursor(s, x, y);
dcl = dcl->next;
static inline void dpy_text_update(DisplayState *s, int x, int y, int w, int h)
{
struct DisplayChangeListener *dcl;
QLIST_FOREACH(dcl, &s->listeners, next) {
if (dcl->dpy_text_update) {
dcl->dpy_text_update(s, x, y, w, h);
}
}
}
static inline void dpy_text_resize(DisplayState *s, int w, int h)
{
struct DisplayChangeListener *dcl;
QLIST_FOREACH(dcl, &s->listeners, next) {
if (dcl->dpy_text_resize) {
dcl->dpy_text_resize(s, w, h);
}
}
}
static inline void dpy_mouse_set(struct DisplayState *s, int x, int y, int on)
{
struct DisplayChangeListener *dcl;
QLIST_FOREACH(dcl, &s->listeners, next) {
if (dcl->dpy_mouse_set) {
dcl->dpy_mouse_set(s, x, y, on);
}
}
}
static inline void dpy_cursor_define(struct DisplayState *s, QEMUCursor *cursor)
{
struct DisplayChangeListener *dcl;
QLIST_FOREACH(dcl, &s->listeners, next) {
if (dcl->dpy_cursor_define) {
dcl->dpy_cursor_define(s, cursor);
}
}
}
static inline bool dpy_cursor_define_supported(struct DisplayState *s)
{
struct DisplayChangeListener *dcl;
QLIST_FOREACH(dcl, &s->listeners, next) {
if (dcl->dpy_cursor_define) {
return true;
}
}
return false;
}
static inline int ds_get_linesize(DisplayState *ds)
{
return ds->surface->linesize;
return pixman_image_get_stride(ds->surface->image);
}
static inline uint8_t* ds_get_data(DisplayState *ds)
{
return ds->surface->data;
return (void *)pixman_image_get_data(ds->surface->image);
}
static inline int ds_get_width(DisplayState *ds)
{
return ds->surface->width;
return pixman_image_get_width(ds->surface->image);
}
static inline int ds_get_height(DisplayState *ds)
{
return ds->surface->height;
return pixman_image_get_height(ds->surface->image);
}
static inline int ds_get_bits_per_pixel(DisplayState *ds)
{
return ds->surface->pf.bits_per_pixel;
int bits = PIXMAN_FORMAT_BPP(ds->surface->format);
return bits;
}
static inline int ds_get_bytes_per_pixel(DisplayState *ds)
{
return ds->surface->pf.bytes_per_pixel;
int bits = PIXMAN_FORMAT_BPP(ds->surface->format);
return (bits + 7) / 8;
}
static inline pixman_format_code_t ds_get_format(DisplayState *ds)
{
return ds->surface->format;
}
static inline int ds_get_depth(DisplayState *ds)
{
return ds->surface->pf.depth;
}
static inline int ds_get_rmask(DisplayState *ds)
{
return ds->surface->pf.rmask;
}
static inline int ds_get_gmask(DisplayState *ds)
{
return ds->surface->pf.gmask;
}
static inline int ds_get_bmask(DisplayState *ds)
{
return ds->surface->pf.bmask;
}
#ifdef CONFIG_CURSES
@ -377,10 +444,8 @@ void cocoa_display_init(DisplayState *ds, int full_screen);
/* vnc.c */
void vnc_display_init(DisplayState *ds);
void vnc_display_close(DisplayState *ds);
void vnc_display_open(DisplayState *ds, const char *display, Error **errp);
void vnc_display_add_client(DisplayState *ds, int csock, int skipauth);
int vnc_display_disable_login(DisplayState *ds);
char *vnc_display_local_addr(DisplayState *ds);
#ifdef CONFIG_VNC
int vnc_display_password(DisplayState *ds, const char *password);

View File

@ -438,8 +438,6 @@ void cpu_reset_interrupt(CPUArchState *env, int mask);
void cpu_exit(CPUArchState *s);
bool qemu_cpu_has_work(CPUArchState *env);
/* Breakpoint/watchpoint flags */
#define BP_MEM_READ 0x01
#define BP_MEM_WRITE 0x02
@ -466,8 +464,6 @@ void cpu_watchpoint_remove_all(CPUArchState *env, int mask);
#define SSTEP_NOTIMER 0x4 /* Do not Timers while single stepping */
void cpu_single_step(CPUArchState *env, int enabled);
int cpu_is_stopped(CPUArchState *env);
void run_on_cpu(CPUArchState *env, void (*func)(void *data), void *data);
#if !defined(CONFIG_USER_ONLY)

View File

@ -39,10 +39,6 @@ typedef uint32_t CPUReadMemoryFunc(void *opaque, hwaddr addr);
void qemu_ram_remap(ram_addr_t addr, ram_addr_t length);
/* This should only be used for ram local to a device. */
void *qemu_get_ram_ptr(ram_addr_t addr);
void *qemu_ram_ptr_length(ram_addr_t addr, ram_addr_t *size);
/* Same but slower, to use for migration, where the order of
* RAMBlocks must not change. */
void *qemu_safe_ram_ptr(ram_addr_t addr);
void qemu_put_ram_ptr(void *addr);
/* This should not be used by devices. */
int qemu_ram_addr_from_host(void *ptr, ram_addr_t *ram_addr);
@ -67,7 +63,6 @@ void *cpu_physical_memory_map(hwaddr addr,
void cpu_physical_memory_unmap(void *buffer, hwaddr len,
int is_write, hwaddr access_len);
void *cpu_register_map_client(void *opaque, void (*callback)(void *opaque));
void cpu_unregister_map_client(void *cookie);
bool cpu_physical_memory_is_io(hwaddr phys_addr);

View File

@ -201,15 +201,9 @@ typedef struct CPUWatchpoint {
int nr_cores; /* number of cores within this CPU package */ \
int nr_threads;/* number of threads within this CPU */ \
int running; /* Nonzero if cpu is currently running(usermode). */ \
int thread_id; \
/* user data */ \
void *opaque; \
\
uint32_t created; \
uint32_t stop; /* Stop request */ \
uint32_t stopped; /* Artificially stopped */ \
struct QemuCond *halt_cond; \
struct qemu_work_item *queued_work_first, *queued_work_last; \
const char *cpu_model_str; \
struct KVMState *kvm_state; \
struct kvm_run *kvm_run; \

View File

@ -27,9 +27,9 @@ int tb_invalidated_flag;
//#define CONFIG_DEBUG_EXEC
bool qemu_cpu_has_work(CPUArchState *env)
bool qemu_cpu_has_work(CPUState *cpu)
{
return cpu_has_work(env);
return cpu_has_work(cpu);
}
void cpu_loop_exit(CPUArchState *env)
@ -181,16 +181,14 @@ volatile sig_atomic_t exit_request;
int cpu_exec(CPUArchState *env)
{
#ifdef TARGET_PPC
CPUState *cpu = ENV_GET_CPU(env);
#endif
int ret, interrupt_request;
TranslationBlock *tb;
uint8_t *tc_ptr;
tcg_target_ulong next_tb;
if (env->halted) {
if (!cpu_has_work(env)) {
if (!cpu_has_work(cpu)) {
return EXCP_HALTED;
}

193
cpus.c
View File

@ -64,13 +64,15 @@ static CPUArchState *next_cpu;
static bool cpu_thread_is_idle(CPUArchState *env)
{
if (env->stop || env->queued_work_first) {
CPUState *cpu = ENV_GET_CPU(env);
if (cpu->stop || cpu->queued_work_first) {
return false;
}
if (env->stopped || !runstate_is_running()) {
if (cpu->stopped || !runstate_is_running()) {
return true;
}
if (!env->halted || qemu_cpu_has_work(env) ||
if (!env->halted || qemu_cpu_has_work(cpu) ||
kvm_async_interrupts_enabled()) {
return false;
}
@ -428,9 +430,9 @@ void cpu_synchronize_all_post_init(void)
}
}
int cpu_is_stopped(CPUArchState *env)
bool cpu_is_stopped(CPUState *cpu)
{
return !runstate_is_running() || env->stopped;
return !runstate_is_running() || cpu->stopped;
}
static void do_vm_stop(RunState state)
@ -446,22 +448,24 @@ static void do_vm_stop(RunState state)
}
}
static int cpu_can_run(CPUArchState *env)
static bool cpu_can_run(CPUState *cpu)
{
if (env->stop) {
return 0;
if (cpu->stop) {
return false;
}
if (env->stopped || !runstate_is_running()) {
return 0;
if (cpu->stopped || !runstate_is_running()) {
return false;
}
return 1;
return true;
}
static void cpu_handle_guest_debug(CPUArchState *env)
{
CPUState *cpu = ENV_GET_CPU(env);
gdb_set_stop_cpu(env);
qemu_system_debug_request();
env->stopped = 1;
cpu->stopped = true;
}
static void cpu_signal(int sig)
@ -636,27 +640,27 @@ void qemu_init_cpu_loop(void)
qemu_thread_get_self(&io_thread);
}
void run_on_cpu(CPUArchState *env, void (*func)(void *data), void *data)
void run_on_cpu(CPUState *cpu, void (*func)(void *data), void *data)
{
struct qemu_work_item wi;
if (qemu_cpu_is_self(env)) {
if (qemu_cpu_is_self(cpu)) {
func(data);
return;
}
wi.func = func;
wi.data = data;
if (!env->queued_work_first) {
env->queued_work_first = &wi;
if (cpu->queued_work_first == NULL) {
cpu->queued_work_first = &wi;
} else {
env->queued_work_last->next = &wi;
cpu->queued_work_last->next = &wi;
}
env->queued_work_last = &wi;
cpu->queued_work_last = &wi;
wi.next = NULL;
wi.done = false;
qemu_cpu_kick(env);
qemu_cpu_kick(cpu);
while (!wi.done) {
CPUArchState *self_env = cpu_single_env;
@ -665,33 +669,31 @@ void run_on_cpu(CPUArchState *env, void (*func)(void *data), void *data)
}
}
static void flush_queued_work(CPUArchState *env)
static void flush_queued_work(CPUState *cpu)
{
struct qemu_work_item *wi;
if (!env->queued_work_first) {
if (cpu->queued_work_first == NULL) {
return;
}
while ((wi = env->queued_work_first)) {
env->queued_work_first = wi->next;
while ((wi = cpu->queued_work_first)) {
cpu->queued_work_first = wi->next;
wi->func(wi->data);
wi->done = true;
}
env->queued_work_last = NULL;
cpu->queued_work_last = NULL;
qemu_cond_broadcast(&qemu_work_cond);
}
static void qemu_wait_io_event_common(CPUArchState *env)
static void qemu_wait_io_event_common(CPUState *cpu)
{
CPUState *cpu = ENV_GET_CPU(env);
if (env->stop) {
env->stop = 0;
env->stopped = 1;
if (cpu->stop) {
cpu->stop = false;
cpu->stopped = true;
qemu_cond_signal(&qemu_pause_cond);
}
flush_queued_work(env);
flush_queued_work(cpu);
cpu->thread_kicked = false;
}
@ -711,18 +713,20 @@ static void qemu_tcg_wait_io_event(void)
}
for (env = first_cpu; env != NULL; env = env->next_cpu) {
qemu_wait_io_event_common(env);
qemu_wait_io_event_common(ENV_GET_CPU(env));
}
}
static void qemu_kvm_wait_io_event(CPUArchState *env)
{
CPUState *cpu = ENV_GET_CPU(env);
while (cpu_thread_is_idle(env)) {
qemu_cond_wait(env->halt_cond, &qemu_global_mutex);
qemu_cond_wait(cpu->halt_cond, &qemu_global_mutex);
}
qemu_kvm_eat_signals(env);
qemu_wait_io_event_common(env);
qemu_wait_io_event_common(cpu);
}
static void *qemu_kvm_cpu_thread_fn(void *arg)
@ -733,7 +737,7 @@ static void *qemu_kvm_cpu_thread_fn(void *arg)
qemu_mutex_lock(&qemu_global_mutex);
qemu_thread_get_self(cpu->thread);
env->thread_id = qemu_get_thread_id();
cpu->thread_id = qemu_get_thread_id();
cpu_single_env = env;
r = kvm_init_vcpu(env);
@ -745,11 +749,11 @@ static void *qemu_kvm_cpu_thread_fn(void *arg)
qemu_kvm_init_cpu_signals(env);
/* signal CPU creation */
env->created = 1;
cpu->created = true;
qemu_cond_signal(&qemu_cpu_cond);
while (1) {
if (cpu_can_run(env)) {
if (cpu_can_run(cpu)) {
r = kvm_cpu_exec(env);
if (r == EXCP_DEBUG) {
cpu_handle_guest_debug(env);
@ -774,13 +778,13 @@ static void *qemu_dummy_cpu_thread_fn(void *arg)
qemu_mutex_lock_iothread();
qemu_thread_get_self(cpu->thread);
env->thread_id = qemu_get_thread_id();
cpu->thread_id = qemu_get_thread_id();
sigemptyset(&waitset);
sigaddset(&waitset, SIG_IPI);
/* signal CPU creation */
env->created = 1;
cpu->created = true;
qemu_cond_signal(&qemu_cpu_cond);
cpu_single_env = env;
@ -797,7 +801,7 @@ static void *qemu_dummy_cpu_thread_fn(void *arg)
}
qemu_mutex_lock_iothread();
cpu_single_env = env;
qemu_wait_io_event_common(env);
qemu_wait_io_event_common(cpu);
}
return NULL;
@ -808,8 +812,8 @@ static void tcg_exec_all(void);
static void *qemu_tcg_cpu_thread_fn(void *arg)
{
CPUArchState *env = arg;
CPUState *cpu = ENV_GET_CPU(env);
CPUState *cpu = arg;
CPUArchState *env;
qemu_tcg_init_cpu_signals();
qemu_thread_get_self(cpu->thread);
@ -817,18 +821,19 @@ static void *qemu_tcg_cpu_thread_fn(void *arg)
/* signal CPU creation */
qemu_mutex_lock(&qemu_global_mutex);
for (env = first_cpu; env != NULL; env = env->next_cpu) {
env->thread_id = qemu_get_thread_id();
env->created = 1;
cpu = ENV_GET_CPU(env);
cpu->thread_id = qemu_get_thread_id();
cpu->created = true;
}
qemu_cond_signal(&qemu_cpu_cond);
/* wait for initial kick-off after machine start */
while (first_cpu->stopped) {
while (ENV_GET_CPU(first_cpu)->stopped) {
qemu_cond_wait(tcg_halt_cond, &qemu_global_mutex);
/* process any pending work */
for (env = first_cpu; env != NULL; env = env->next_cpu) {
qemu_wait_io_event_common(env);
qemu_wait_io_event_common(ENV_GET_CPU(env));
}
}
@ -843,9 +848,8 @@ static void *qemu_tcg_cpu_thread_fn(void *arg)
return NULL;
}
static void qemu_cpu_kick_thread(CPUArchState *env)
static void qemu_cpu_kick_thread(CPUState *cpu)
{
CPUState *cpu = ENV_GET_CPU(env);
#ifndef _WIN32
int err;
@ -855,7 +859,7 @@ static void qemu_cpu_kick_thread(CPUArchState *env)
exit(1);
}
#else /* _WIN32 */
if (!qemu_cpu_is_self(env)) {
if (!qemu_cpu_is_self(cpu)) {
SuspendThread(cpu->hThread);
cpu_signal(0);
ResumeThread(cpu->hThread);
@ -863,14 +867,11 @@ static void qemu_cpu_kick_thread(CPUArchState *env)
#endif
}
void qemu_cpu_kick(void *_env)
void qemu_cpu_kick(CPUState *cpu)
{
CPUArchState *env = _env;
CPUState *cpu = ENV_GET_CPU(env);
qemu_cond_broadcast(env->halt_cond);
qemu_cond_broadcast(cpu->halt_cond);
if (!tcg_enabled() && !cpu->thread_kicked) {
qemu_cpu_kick_thread(env);
qemu_cpu_kick_thread(cpu);
cpu->thread_kicked = true;
}
}
@ -882,7 +883,7 @@ void qemu_cpu_kick_self(void)
CPUState *cpu_single_cpu = ENV_GET_CPU(cpu_single_env);
if (!cpu_single_cpu->thread_kicked) {
qemu_cpu_kick_thread(cpu_single_env);
qemu_cpu_kick_thread(cpu_single_cpu);
cpu_single_cpu->thread_kicked = true;
}
#else
@ -890,17 +891,14 @@ void qemu_cpu_kick_self(void)
#endif
}
int qemu_cpu_is_self(void *_env)
bool qemu_cpu_is_self(CPUState *cpu)
{
CPUArchState *env = _env;
CPUState *cpu = ENV_GET_CPU(env);
return qemu_thread_is_self(cpu->thread);
}
static bool qemu_in_vcpu_thread(void)
{
return cpu_single_env && qemu_cpu_is_self(cpu_single_env);
return cpu_single_env && qemu_cpu_is_self(ENV_GET_CPU(cpu_single_env));
}
void qemu_mutex_lock_iothread(void)
@ -910,7 +908,7 @@ void qemu_mutex_lock_iothread(void)
} else {
iothread_requesting_mutex = true;
if (qemu_mutex_trylock(&qemu_global_mutex)) {
qemu_cpu_kick_thread(first_cpu);
qemu_cpu_kick_thread(ENV_GET_CPU(first_cpu));
qemu_mutex_lock(&qemu_global_mutex);
}
iothread_requesting_mutex = false;
@ -928,7 +926,8 @@ static int all_vcpus_paused(void)
CPUArchState *penv = first_cpu;
while (penv) {
if (!penv->stopped) {
CPUState *pcpu = ENV_GET_CPU(penv);
if (!pcpu->stopped) {
return 0;
}
penv = penv->next_cpu;
@ -943,8 +942,9 @@ void pause_all_vcpus(void)
qemu_clock_enable(vm_clock, false);
while (penv) {
penv->stop = 1;
qemu_cpu_kick(penv);
CPUState *pcpu = ENV_GET_CPU(penv);
pcpu->stop = true;
qemu_cpu_kick(pcpu);
penv = penv->next_cpu;
}
@ -952,8 +952,9 @@ void pause_all_vcpus(void)
cpu_stop_current();
if (!kvm_enabled()) {
while (penv) {
penv->stop = 0;
penv->stopped = 1;
CPUState *pcpu = ENV_GET_CPU(penv);
pcpu->stop = 0;
pcpu->stopped = true;
penv = penv->next_cpu;
}
return;
@ -964,7 +965,7 @@ void pause_all_vcpus(void)
qemu_cond_wait(&qemu_pause_cond, &qemu_global_mutex);
penv = first_cpu;
while (penv) {
qemu_cpu_kick(penv);
qemu_cpu_kick(ENV_GET_CPU(penv));
penv = penv->next_cpu;
}
}
@ -976,36 +977,34 @@ void resume_all_vcpus(void)
qemu_clock_enable(vm_clock, true);
while (penv) {
penv->stop = 0;
penv->stopped = 0;
qemu_cpu_kick(penv);
CPUState *pcpu = ENV_GET_CPU(penv);
pcpu->stop = false;
pcpu->stopped = false;
qemu_cpu_kick(pcpu);
penv = penv->next_cpu;
}
}
static void qemu_tcg_init_vcpu(void *_env)
static void qemu_tcg_init_vcpu(CPUState *cpu)
{
CPUArchState *env = _env;
CPUState *cpu = ENV_GET_CPU(env);
/* share a single thread for all cpus with TCG */
if (!tcg_cpu_thread) {
cpu->thread = g_malloc0(sizeof(QemuThread));
env->halt_cond = g_malloc0(sizeof(QemuCond));
qemu_cond_init(env->halt_cond);
tcg_halt_cond = env->halt_cond;
qemu_thread_create(cpu->thread, qemu_tcg_cpu_thread_fn, env,
cpu->halt_cond = g_malloc0(sizeof(QemuCond));
qemu_cond_init(cpu->halt_cond);
tcg_halt_cond = cpu->halt_cond;
qemu_thread_create(cpu->thread, qemu_tcg_cpu_thread_fn, cpu,
QEMU_THREAD_JOINABLE);
#ifdef _WIN32
cpu->hThread = qemu_thread_get_handle(cpu->thread);
#endif
while (env->created == 0) {
while (!cpu->created) {
qemu_cond_wait(&qemu_cpu_cond, &qemu_global_mutex);
}
tcg_cpu_thread = cpu->thread;
} else {
cpu->thread = tcg_cpu_thread;
env->halt_cond = tcg_halt_cond;
cpu->halt_cond = tcg_halt_cond;
}
}
@ -1014,11 +1013,11 @@ static void qemu_kvm_start_vcpu(CPUArchState *env)
CPUState *cpu = ENV_GET_CPU(env);
cpu->thread = g_malloc0(sizeof(QemuThread));
env->halt_cond = g_malloc0(sizeof(QemuCond));
qemu_cond_init(env->halt_cond);
cpu->halt_cond = g_malloc0(sizeof(QemuCond));
qemu_cond_init(cpu->halt_cond);
qemu_thread_create(cpu->thread, qemu_kvm_cpu_thread_fn, env,
QEMU_THREAD_JOINABLE);
while (env->created == 0) {
while (!cpu->created) {
qemu_cond_wait(&qemu_cpu_cond, &qemu_global_mutex);
}
}
@ -1028,11 +1027,11 @@ static void qemu_dummy_start_vcpu(CPUArchState *env)
CPUState *cpu = ENV_GET_CPU(env);
cpu->thread = g_malloc0(sizeof(QemuThread));
env->halt_cond = g_malloc0(sizeof(QemuCond));
qemu_cond_init(env->halt_cond);
cpu->halt_cond = g_malloc0(sizeof(QemuCond));
qemu_cond_init(cpu->halt_cond);
qemu_thread_create(cpu->thread, qemu_dummy_cpu_thread_fn, env,
QEMU_THREAD_JOINABLE);
while (env->created == 0) {
while (!cpu->created) {
qemu_cond_wait(&qemu_cpu_cond, &qemu_global_mutex);
}
}
@ -1040,14 +1039,15 @@ static void qemu_dummy_start_vcpu(CPUArchState *env)
void qemu_init_vcpu(void *_env)
{
CPUArchState *env = _env;
CPUState *cpu = ENV_GET_CPU(env);
env->nr_cores = smp_cores;
env->nr_threads = smp_threads;
env->stopped = 1;
cpu->stopped = true;
if (kvm_enabled()) {
qemu_kvm_start_vcpu(env);
} else if (tcg_enabled()) {
qemu_tcg_init_vcpu(env);
qemu_tcg_init_vcpu(cpu);
} else {
qemu_dummy_start_vcpu(env);
}
@ -1056,8 +1056,9 @@ void qemu_init_vcpu(void *_env)
void cpu_stop_current(void)
{
if (cpu_single_env) {
cpu_single_env->stop = 0;
cpu_single_env->stopped = 1;
CPUState *cpu_single_cpu = ENV_GET_CPU(cpu_single_env);
cpu_single_cpu->stop = false;
cpu_single_cpu->stopped = true;
cpu_exit(cpu_single_env);
qemu_cond_signal(&qemu_pause_cond);
}
@ -1138,17 +1139,18 @@ static void tcg_exec_all(void)
}
for (; next_cpu != NULL && !exit_request; next_cpu = next_cpu->next_cpu) {
CPUArchState *env = next_cpu;
CPUState *cpu = ENV_GET_CPU(env);
qemu_clock_enable(vm_clock,
(env->singlestep_enabled & SSTEP_NOTIMER) == 0);
if (cpu_can_run(env)) {
if (cpu_can_run(cpu)) {
r = tcg_cpu_exec(env);
if (r == EXCP_DEBUG) {
cpu_handle_guest_debug(env);
break;
}
} else if (env->stop || env->stopped) {
} else if (cpu->stop || cpu->stopped) {
break;
}
}
@ -1203,7 +1205,8 @@ CpuInfoList *qmp_query_cpus(Error **errp)
CpuInfoList *head = NULL, *cur_item = NULL;
CPUArchState *env;
for(env = first_cpu; env != NULL; env = env->next_cpu) {
for (env = first_cpu; env != NULL; env = env->next_cpu) {
CPUState *cpu = ENV_GET_CPU(env);
CpuInfoList *info;
cpu_synchronize_state(env);
@ -1213,7 +1216,7 @@ CpuInfoList *qmp_query_cpus(Error **errp)
info->value->CPU = env->cpu_index;
info->value->current = (env == first_cpu);
info->value->halted = env->halted;
info->value->thread_id = env->thread_id;
info->value->thread_id = cpu->thread_id;
#if defined(TARGET_I386)
info->value->has_pc = true;
info->value->pc = env->eip + env->segs[R_CS].base;

108
cutils.c
View File

@ -142,109 +142,6 @@ int qemu_fdatasync(int fd)
#endif
}
/* io vectors */
void qemu_iovec_init(QEMUIOVector *qiov, int alloc_hint)
{
qiov->iov = g_malloc(alloc_hint * sizeof(struct iovec));
qiov->niov = 0;
qiov->nalloc = alloc_hint;
qiov->size = 0;
}
void qemu_iovec_init_external(QEMUIOVector *qiov, struct iovec *iov, int niov)
{
int i;
qiov->iov = iov;
qiov->niov = niov;
qiov->nalloc = -1;
qiov->size = 0;
for (i = 0; i < niov; i++)
qiov->size += iov[i].iov_len;
}
void qemu_iovec_add(QEMUIOVector *qiov, void *base, size_t len)
{
assert(qiov->nalloc != -1);
if (qiov->niov == qiov->nalloc) {
qiov->nalloc = 2 * qiov->nalloc + 1;
qiov->iov = g_realloc(qiov->iov, qiov->nalloc * sizeof(struct iovec));
}
qiov->iov[qiov->niov].iov_base = base;
qiov->iov[qiov->niov].iov_len = len;
qiov->size += len;
++qiov->niov;
}
/*
* Concatenates (partial) iovecs from src to the end of dst.
* It starts copying after skipping `soffset' bytes at the
* beginning of src and adds individual vectors from src to
* dst copies up to `sbytes' bytes total, or up to the end
* of src if it comes first. This way, it is okay to specify
* very large value for `sbytes' to indicate "up to the end
* of src".
* Only vector pointers are processed, not the actual data buffers.
*/
void qemu_iovec_concat(QEMUIOVector *dst,
QEMUIOVector *src, size_t soffset, size_t sbytes)
{
int i;
size_t done;
struct iovec *siov = src->iov;
assert(dst->nalloc != -1);
assert(src->size >= soffset);
for (i = 0, done = 0; done < sbytes && i < src->niov; i++) {
if (soffset < siov[i].iov_len) {
size_t len = MIN(siov[i].iov_len - soffset, sbytes - done);
qemu_iovec_add(dst, siov[i].iov_base + soffset, len);
done += len;
soffset = 0;
} else {
soffset -= siov[i].iov_len;
}
}
/* return done; */
}
void qemu_iovec_destroy(QEMUIOVector *qiov)
{
assert(qiov->nalloc != -1);
qemu_iovec_reset(qiov);
g_free(qiov->iov);
qiov->nalloc = 0;
qiov->iov = NULL;
}
void qemu_iovec_reset(QEMUIOVector *qiov)
{
assert(qiov->nalloc != -1);
qiov->niov = 0;
qiov->size = 0;
}
size_t qemu_iovec_to_buf(QEMUIOVector *qiov, size_t offset,
void *buf, size_t bytes)
{
return iov_to_buf(qiov->iov, qiov->niov, offset, buf, bytes);
}
size_t qemu_iovec_from_buf(QEMUIOVector *qiov, size_t offset,
const void *buf, size_t bytes)
{
return iov_from_buf(qiov->iov, qiov->niov, offset, buf, bytes);
}
size_t qemu_iovec_memset(QEMUIOVector *qiov, size_t offset,
int fillc, size_t bytes)
{
return iov_memset(qiov->iov, qiov->niov, offset, fillc, bytes);
}
/*
* Checks if a buffer is all zeroes
*
@ -383,11 +280,6 @@ int qemu_parse_fd(const char *param)
return fd;
}
int qemu_parse_fdset(const char *param)
{
return qemu_parse_fd(param);
}
/* round down to the nearest power of 2*/
int64_t pow2floor(int64_t value)
{

149
disas.c
View File

@ -7,6 +7,11 @@
#include "cpu.h"
#include "disas.h"
typedef struct CPUDebug {
struct disassemble_info info;
CPUArchState *env;
} CPUDebug;
/* Filled in by elfload.c. Simplistic, but will do for now. */
struct syminfo *syminfos = NULL;
@ -32,7 +37,9 @@ target_read_memory (bfd_vma memaddr,
int length,
struct disassemble_info *info)
{
cpu_memory_rw_debug(cpu_single_env, memaddr, myaddr, length, 0);
CPUDebug *s = container_of(info, CPUDebug, info);
cpu_memory_rw_debug(s->env, memaddr, myaddr, length, 0);
return 0;
}
@ -158,32 +165,35 @@ print_insn_thumb1(bfd_vma pc, disassemble_info *info)
ppc - nonzero means little endian
other targets - unused
*/
void target_disas(FILE *out, target_ulong code, target_ulong size, int flags)
void target_disas(FILE *out, CPUArchState *env, target_ulong code,
target_ulong size, int flags)
{
target_ulong pc;
int count;
struct disassemble_info disasm_info;
CPUDebug s;
int (*print_insn)(bfd_vma pc, disassemble_info *info);
INIT_DISASSEMBLE_INFO(disasm_info, out, fprintf);
INIT_DISASSEMBLE_INFO(s.info, out, fprintf);
disasm_info.read_memory_func = target_read_memory;
disasm_info.buffer_vma = code;
disasm_info.buffer_length = size;
disasm_info.print_address_func = generic_print_target_address;
s.env = env;
s.info.read_memory_func = target_read_memory;
s.info.buffer_vma = code;
s.info.buffer_length = size;
s.info.print_address_func = generic_print_target_address;
#ifdef TARGET_WORDS_BIGENDIAN
disasm_info.endian = BFD_ENDIAN_BIG;
s.info.endian = BFD_ENDIAN_BIG;
#else
disasm_info.endian = BFD_ENDIAN_LITTLE;
s.info.endian = BFD_ENDIAN_LITTLE;
#endif
#if defined(TARGET_I386)
if (flags == 2)
disasm_info.mach = bfd_mach_x86_64;
else if (flags == 1)
disasm_info.mach = bfd_mach_i386_i8086;
else
disasm_info.mach = bfd_mach_i386_i386;
if (flags == 2) {
s.info.mach = bfd_mach_x86_64;
} else if (flags == 1) {
s.info.mach = bfd_mach_i386_i8086;
} else {
s.info.mach = bfd_mach_i386_i386;
}
print_insn = print_insn_i386;
#elif defined(TARGET_ARM)
if (flags & 1) {
@ -193,27 +203,28 @@ void target_disas(FILE *out, target_ulong code, target_ulong size, int flags)
}
if (flags & 2) {
#ifdef TARGET_WORDS_BIGENDIAN
disasm_info.endian = BFD_ENDIAN_LITTLE;
s.info.endian = BFD_ENDIAN_LITTLE;
#else
disasm_info.endian = BFD_ENDIAN_BIG;
s.info.endian = BFD_ENDIAN_BIG;
#endif
}
#elif defined(TARGET_SPARC)
print_insn = print_insn_sparc;
#ifdef TARGET_SPARC64
disasm_info.mach = bfd_mach_sparc_v9b;
s.info.mach = bfd_mach_sparc_v9b;
#endif
#elif defined(TARGET_PPC)
if (flags >> 16)
disasm_info.endian = BFD_ENDIAN_LITTLE;
if (flags >> 16) {
s.info.endian = BFD_ENDIAN_LITTLE;
}
if (flags & 0xFFFF) {
/* If we have a precise definitions of the instructions set, use it */
disasm_info.mach = flags & 0xFFFF;
s.info.mach = flags & 0xFFFF;
} else {
#ifdef TARGET_PPC64
disasm_info.mach = bfd_mach_ppc64;
s.info.mach = bfd_mach_ppc64;
#else
disasm_info.mach = bfd_mach_ppc;
s.info.mach = bfd_mach_ppc;
#endif
}
print_insn = print_insn_ppc;
@ -226,27 +237,27 @@ void target_disas(FILE *out, target_ulong code, target_ulong size, int flags)
print_insn = print_insn_little_mips;
#endif
#elif defined(TARGET_SH4)
disasm_info.mach = bfd_mach_sh4;
s.info.mach = bfd_mach_sh4;
print_insn = print_insn_sh;
#elif defined(TARGET_ALPHA)
disasm_info.mach = bfd_mach_alpha_ev6;
s.info.mach = bfd_mach_alpha_ev6;
print_insn = print_insn_alpha;
#elif defined(TARGET_CRIS)
if (flags != 32) {
disasm_info.mach = bfd_mach_cris_v0_v10;
s.info.mach = bfd_mach_cris_v0_v10;
print_insn = print_insn_crisv10;
} else {
disasm_info.mach = bfd_mach_cris_v32;
s.info.mach = bfd_mach_cris_v32;
print_insn = print_insn_crisv32;
}
#elif defined(TARGET_S390X)
disasm_info.mach = bfd_mach_s390_64;
s.info.mach = bfd_mach_s390_64;
print_insn = print_insn_s390;
#elif defined(TARGET_MICROBLAZE)
disasm_info.mach = bfd_arch_microblaze;
s.info.mach = bfd_arch_microblaze;
print_insn = print_insn_microblaze;
#elif defined(TARGET_LM32)
disasm_info.mach = bfd_mach_lm32;
s.info.mach = bfd_mach_lm32;
print_insn = print_insn_lm32;
#else
fprintf(out, "0x" TARGET_FMT_lx
@ -256,14 +267,14 @@ void target_disas(FILE *out, target_ulong code, target_ulong size, int flags)
for (pc = code; size > 0; pc += count, size -= count) {
fprintf(out, "0x" TARGET_FMT_lx ": ", pc);
count = print_insn(pc, &disasm_info);
count = print_insn(pc, &s.info);
#if 0
{
int i;
uint8_t b;
fprintf(out, " {");
for(i = 0; i < count; i++) {
target_read_memory(pc + i, &b, 1, &disasm_info);
target_read_memory(pc + i, &b, 1, &s.info);
fprintf(out, " %02x", b);
}
fprintf(out, " }");
@ -287,28 +298,28 @@ void disas(FILE *out, void *code, unsigned long size)
{
uintptr_t pc;
int count;
struct disassemble_info disasm_info;
CPUDebug s;
int (*print_insn)(bfd_vma pc, disassemble_info *info);
INIT_DISASSEMBLE_INFO(disasm_info, out, fprintf);
disasm_info.print_address_func = generic_print_host_address;
INIT_DISASSEMBLE_INFO(s.info, out, fprintf);
s.info.print_address_func = generic_print_host_address;
disasm_info.buffer = code;
disasm_info.buffer_vma = (uintptr_t)code;
disasm_info.buffer_length = size;
s.info.buffer = code;
s.info.buffer_vma = (uintptr_t)code;
s.info.buffer_length = size;
#ifdef HOST_WORDS_BIGENDIAN
disasm_info.endian = BFD_ENDIAN_BIG;
s.info.endian = BFD_ENDIAN_BIG;
#else
disasm_info.endian = BFD_ENDIAN_LITTLE;
s.info.endian = BFD_ENDIAN_LITTLE;
#endif
#if defined(CONFIG_TCG_INTERPRETER)
print_insn = print_insn_tci;
#elif defined(__i386__)
disasm_info.mach = bfd_mach_i386_i386;
s.info.mach = bfd_mach_i386_i386;
print_insn = print_insn_i386;
#elif defined(__x86_64__)
disasm_info.mach = bfd_mach_x86_64;
s.info.mach = bfd_mach_x86_64;
print_insn = print_insn_i386;
#elif defined(_ARCH_PPC)
print_insn = print_insn_ppc;
@ -316,7 +327,7 @@ void disas(FILE *out, void *code, unsigned long size)
print_insn = print_insn_alpha;
#elif defined(__sparc__)
print_insn = print_insn_sparc;
disasm_info.mach = bfd_mach_sparc_v9b;
s.info.mach = bfd_mach_sparc_v9b;
#elif defined(__arm__)
print_insn = print_insn_arm;
#elif defined(__MIPSEB__)
@ -338,7 +349,7 @@ void disas(FILE *out, void *code, unsigned long size)
#endif
for (pc = (uintptr_t)code; size > 0; pc += count, size -= count) {
fprintf(out, "0x%08" PRIxPTR ": ", pc);
count = print_insn(pc, &disasm_info);
count = print_insn(pc, &s.info);
fprintf(out, "\n");
if (count < 0)
break;
@ -366,16 +377,17 @@ const char *lookup_symbol(target_ulong orig_addr)
#include "monitor.h"
static int monitor_disas_is_physical;
static CPUArchState *monitor_disas_env;
static int
monitor_read_memory (bfd_vma memaddr, bfd_byte *myaddr, int length,
struct disassemble_info *info)
{
CPUDebug *s = container_of(info, CPUDebug, info);
if (monitor_disas_is_physical) {
cpu_physical_memory_read(memaddr, myaddr, length);
} else {
cpu_memory_rw_debug(monitor_disas_env, memaddr,myaddr, length, 0);
cpu_memory_rw_debug(s->env, memaddr,myaddr, length, 0);
}
return 0;
}
@ -394,30 +406,31 @@ void monitor_disas(Monitor *mon, CPUArchState *env,
target_ulong pc, int nb_insn, int is_physical, int flags)
{
int count, i;
struct disassemble_info disasm_info;
CPUDebug s;
int (*print_insn)(bfd_vma pc, disassemble_info *info);
INIT_DISASSEMBLE_INFO(disasm_info, (FILE *)mon, monitor_fprintf);
INIT_DISASSEMBLE_INFO(s.info, (FILE *)mon, monitor_fprintf);
monitor_disas_env = env;
s.env = env;
monitor_disas_is_physical = is_physical;
disasm_info.read_memory_func = monitor_read_memory;
disasm_info.print_address_func = generic_print_target_address;
s.info.read_memory_func = monitor_read_memory;
s.info.print_address_func = generic_print_target_address;
disasm_info.buffer_vma = pc;
s.info.buffer_vma = pc;
#ifdef TARGET_WORDS_BIGENDIAN
disasm_info.endian = BFD_ENDIAN_BIG;
s.info.endian = BFD_ENDIAN_BIG;
#else
disasm_info.endian = BFD_ENDIAN_LITTLE;
s.info.endian = BFD_ENDIAN_LITTLE;
#endif
#if defined(TARGET_I386)
if (flags == 2)
disasm_info.mach = bfd_mach_x86_64;
else if (flags == 1)
disasm_info.mach = bfd_mach_i386_i8086;
else
disasm_info.mach = bfd_mach_i386_i386;
if (flags == 2) {
s.info.mach = bfd_mach_x86_64;
} else if (flags == 1) {
s.info.mach = bfd_mach_i386_i8086;
} else {
s.info.mach = bfd_mach_i386_i386;
}
print_insn = print_insn_i386;
#elif defined(TARGET_ARM)
print_insn = print_insn_arm;
@ -426,13 +439,13 @@ void monitor_disas(Monitor *mon, CPUArchState *env,
#elif defined(TARGET_SPARC)
print_insn = print_insn_sparc;
#ifdef TARGET_SPARC64
disasm_info.mach = bfd_mach_sparc_v9b;
s.info.mach = bfd_mach_sparc_v9b;
#endif
#elif defined(TARGET_PPC)
#ifdef TARGET_PPC64
disasm_info.mach = bfd_mach_ppc64;
s.info.mach = bfd_mach_ppc64;
#else
disasm_info.mach = bfd_mach_ppc;
s.info.mach = bfd_mach_ppc;
#endif
print_insn = print_insn_ppc;
#elif defined(TARGET_M68K)
@ -444,13 +457,13 @@ void monitor_disas(Monitor *mon, CPUArchState *env,
print_insn = print_insn_little_mips;
#endif
#elif defined(TARGET_SH4)
disasm_info.mach = bfd_mach_sh4;
s.info.mach = bfd_mach_sh4;
print_insn = print_insn_sh;
#elif defined(TARGET_S390X)
disasm_info.mach = bfd_mach_s390_64;
s.info.mach = bfd_mach_s390_64;
print_insn = print_insn_s390;
#elif defined(TARGET_LM32)
disasm_info.mach = bfd_mach_lm32;
s.info.mach = bfd_mach_lm32;
print_insn = print_insn_lm32;
#else
monitor_printf(mon, "0x" TARGET_FMT_lx
@ -460,7 +473,7 @@ void monitor_disas(Monitor *mon, CPUArchState *env,
for(i = 0; i < nb_insn; i++) {
monitor_printf(mon, "0x" TARGET_FMT_lx ": ", pc);
count = print_insn(pc, &disasm_info);
count = print_insn(pc, &s.info);
monitor_printf(mon, "\n");
if (count < 0)
break;

View File

@ -6,7 +6,8 @@
#ifdef NEED_CPU_H
/* Disassemble this for me please... (debugging). */
void disas(FILE *out, void *code, unsigned long size);
void target_disas(FILE *out, target_ulong code, target_ulong size, int flags);
void target_disas(FILE *out, CPUArchState *env, target_ulong code,
target_ulong size, int flags);
void monitor_disas(Monitor *mon, CPUArchState *env,
target_ulong pc, int nb_insn, int is_physical, int flags);

120
event_notifier-posix.c Normal file
View File

@ -0,0 +1,120 @@
/*
* event notifier support
*
* Copyright Red Hat, Inc. 2010
*
* Authors:
* Michael S. Tsirkin <mst@redhat.com>
*
* This work is licensed under the terms of the GNU GPL, version 2 or later.
* See the COPYING file in the top-level directory.
*/
#include "qemu-common.h"
#include "event_notifier.h"
#include "qemu-char.h"
#ifdef CONFIG_EVENTFD
#include <sys/eventfd.h>
#endif
void event_notifier_init_fd(EventNotifier *e, int fd)
{
e->rfd = fd;
e->wfd = fd;
}
int event_notifier_init(EventNotifier *e, int active)
{
int fds[2];
int ret;
#ifdef CONFIG_EVENTFD
ret = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
#else
ret = -1;
errno = ENOSYS;
#endif
if (ret >= 0) {
e->rfd = e->wfd = ret;
} else {
if (errno != ENOSYS) {
return -errno;
}
if (qemu_pipe(fds) < 0) {
return -errno;
}
ret = fcntl_setfl(fds[0], O_NONBLOCK);
if (ret < 0) {
ret = -errno;
goto fail;
}
ret = fcntl_setfl(fds[1], O_NONBLOCK);
if (ret < 0) {
ret = -errno;
goto fail;
}
e->rfd = fds[0];
e->wfd = fds[1];
}
if (active) {
event_notifier_set(e);
}
return 0;
fail:
close(fds[0]);
close(fds[1]);
return ret;
}
void event_notifier_cleanup(EventNotifier *e)
{
if (e->rfd != e->wfd) {
close(e->rfd);
}
close(e->wfd);
}
int event_notifier_get_fd(EventNotifier *e)
{
return e->rfd;
}
int event_notifier_set_handler(EventNotifier *e,
EventNotifierHandler *handler)
{
return qemu_set_fd_handler(e->rfd, (IOHandler *)handler, NULL, e);
}
int event_notifier_set(EventNotifier *e)
{
static const uint64_t value = 1;
ssize_t ret;
do {
ret = write(e->wfd, &value, sizeof(value));
} while (ret < 0 && errno == EINTR);
/* EAGAIN is fine, a read must be pending. */
if (ret < 0 && errno != EAGAIN) {
return -errno;
}
return 0;
}
int event_notifier_test_and_clear(EventNotifier *e)
{
int value;
ssize_t len;
char buffer[512];
/* Drain the notify pipe. For eventfd, only 8 bytes will be read. */
value = 0;
do {
len = read(e->rfd, buffer, sizeof(buffer));
value |= (len > 0);
} while ((len == -1 && errno == EINTR) || len == sizeof(buffer));
return value;
}

59
event_notifier-win32.c Normal file
View File

@ -0,0 +1,59 @@
/*
* event notifier support
*
* Copyright Red Hat, Inc. 2010
*
* Authors:
* Michael S. Tsirkin <mst@redhat.com>
*
* This work is licensed under the terms of the GNU GPL, version 2 or later.
* See the COPYING file in the top-level directory.
*/
#include "qemu-common.h"
#include "event_notifier.h"
#include "main-loop.h"
int event_notifier_init(EventNotifier *e, int active)
{
e->event = CreateEvent(NULL, FALSE, FALSE, NULL);
assert(e->event);
return 0;
}
void event_notifier_cleanup(EventNotifier *e)
{
CloseHandle(e->event);
}
HANDLE event_notifier_get_handle(EventNotifier *e)
{
return e->event;
}
int event_notifier_set_handler(EventNotifier *e,
EventNotifierHandler *handler)
{
if (handler) {
return qemu_add_wait_object(e->event, (IOHandler *)handler, e);
} else {
qemu_del_wait_object(e->event, (IOHandler *)handler, e);
return 0;
}
}
int event_notifier_set(EventNotifier *e)
{
SetEvent(e->event);
return 0;
}
int event_notifier_test_and_clear(EventNotifier *e)
{
int ret = WaitForSingleObject(e->event, 0);
if (ret == WAIT_OBJECT_0) {
ResetEvent(e->event);
return true;
}
return false;
}

View File

@ -1,67 +0,0 @@
/*
* event notifier support
*
* Copyright Red Hat, Inc. 2010
*
* Authors:
* Michael S. Tsirkin <mst@redhat.com>
*
* This work is licensed under the terms of the GNU GPL, version 2 or later.
* See the COPYING file in the top-level directory.
*/
#include "qemu-common.h"
#include "event_notifier.h"
#include "qemu-char.h"
#ifdef CONFIG_EVENTFD
#include <sys/eventfd.h>
#endif
void event_notifier_init_fd(EventNotifier *e, int fd)
{
e->fd = fd;
}
int event_notifier_init(EventNotifier *e, int active)
{
#ifdef CONFIG_EVENTFD
int fd = eventfd(!!active, EFD_NONBLOCK | EFD_CLOEXEC);
if (fd < 0)
return -errno;
e->fd = fd;
return 0;
#else
return -ENOSYS;
#endif
}
void event_notifier_cleanup(EventNotifier *e)
{
close(e->fd);
}
int event_notifier_get_fd(EventNotifier *e)
{
return e->fd;
}
int event_notifier_set_handler(EventNotifier *e,
EventNotifierHandler *handler)
{
return qemu_set_fd_handler(e->fd, (IOHandler *)handler, NULL, e);
}
int event_notifier_set(EventNotifier *e)
{
uint64_t value = 1;
int r = write(e->fd, &value, sizeof(value));
return r == sizeof(value);
}
int event_notifier_test_and_clear(EventNotifier *e)
{
uint64_t value;
int r = read(e->fd, &value, sizeof(value));
return r == sizeof(value);
}

View File

@ -15,18 +15,32 @@
#include "qemu-common.h"
#ifdef _WIN32
#include <windows.h>
#endif
struct EventNotifier {
int fd;
#ifdef _WIN32
HANDLE event;
#else
int rfd;
int wfd;
#endif
};
typedef void EventNotifierHandler(EventNotifier *);
void event_notifier_init_fd(EventNotifier *, int fd);
int event_notifier_init(EventNotifier *, int active);
void event_notifier_cleanup(EventNotifier *);
int event_notifier_get_fd(EventNotifier *);
int event_notifier_set(EventNotifier *);
int event_notifier_test_and_clear(EventNotifier *);
int event_notifier_set_handler(EventNotifier *, EventNotifierHandler *);
#ifdef CONFIG_POSIX
void event_notifier_init_fd(EventNotifier *, int fd);
int event_notifier_get_fd(EventNotifier *);
#else
HANDLE event_notifier_get_handle(EventNotifier *);
#endif
#endif

View File

@ -194,8 +194,6 @@ static inline unsigned int tb_phys_hash_func(tb_page_addr_t pc)
void tb_free(TranslationBlock *tb);
void tb_flush(CPUArchState *env);
void tb_link_page(TranslationBlock *tb,
tb_page_addr_t phys_pc, tb_page_addr_t phys_page2);
void tb_phys_invalidate(TranslationBlock *tb, tb_page_addr_t page_addr);
extern TranslationBlock *tb_phys_hash[CODE_GEN_PHYS_HASH_SIZE];
@ -310,6 +308,45 @@ extern uintptr_t tci_tb_ptr;
# define GETPC() ((uintptr_t)__builtin_return_address(0) - 1)
#endif
#if defined(CONFIG_QEMU_LDST_OPTIMIZATION) && defined(CONFIG_SOFTMMU)
/* qemu_ld/st optimization split code generation to fast and slow path, thus,
it needs special handling for an MMU helper which is called from the slow
path, to get the fast path's pc without any additional argument.
It uses a tricky solution which embeds the fast path pc into the slow path.
Code flow in slow path:
(1) pre-process
(2) call MMU helper
(3) jump to (5)
(4) fast path information (implementation specific)
(5) post-process (e.g. stack adjust)
(6) jump to corresponding code of the next of fast path
*/
# if defined(__i386__) || defined(__x86_64__)
/* To avoid broken disassembling, long jmp is used for embedding fast path pc,
so that the destination is the next code of fast path, though this jmp is
never executed.
call MMU helper
jmp POST_PROC (2byte) <- GETRA()
jmp NEXT_CODE (5byte)
POST_PROCESS ... <- GETRA() + 7
*/
# define GETRA() ((uintptr_t)__builtin_return_address(0))
# define GETPC_LDST() ((uintptr_t)(GETRA() + 7 + \
*(int32_t *)((void *)GETRA() + 3) - 1))
# elif defined (_ARCH_PPC) && !defined (_ARCH_PPC64)
# define GETRA() ((uintptr_t)__builtin_return_address(0))
# define GETPC_LDST() ((uintptr_t) ((*(int32_t *)(GETRA() - 4)) - 1))
# else
# error "CONFIG_QEMU_LDST_OPTIMIZATION needs GETPC_LDST() implementation!"
# endif
bool is_tcg_gen_code(uintptr_t pc_ptr);
# define GETPC_EXT() (is_tcg_gen_code(GETRA()) ? GETPC_LDST() : GETPC())
#else
# define GETPC_EXT() GETPC()
#endif
#if !defined(CONFIG_USER_ONLY)
struct MemoryRegion *iotlb_to_region(hwaddr index);

36
exec.c
View File

@ -188,9 +188,12 @@ static unsigned phys_map_nodes_nb, phys_map_nodes_nb_alloc;
static void io_mem_init(void);
static void memory_map_init(void);
static void *qemu_safe_ram_ptr(ram_addr_t addr);
static MemoryRegion io_mem_watch;
#endif
static void tb_link_page(TranslationBlock *tb, tb_page_addr_t phys_pc,
tb_page_addr_t phys_page2);
/* statistics */
static int tb_flush_count;
@ -689,6 +692,9 @@ CPUArchState *qemu_get_cpu(int cpu)
void cpu_exec_init(CPUArchState *env)
{
#ifndef CONFIG_USER_ONLY
CPUState *cpu = ENV_GET_CPU(env);
#endif
CPUArchState **penv;
int cpu_index;
@ -707,7 +713,7 @@ void cpu_exec_init(CPUArchState *env)
QTAILQ_INIT(&env->breakpoints);
QTAILQ_INIT(&env->watchpoints);
#ifndef CONFIG_USER_ONLY
env->thread_id = qemu_get_thread_id();
cpu->thread_id = qemu_get_thread_id();
#endif
*penv = env;
#if defined(CONFIG_USER_ONLY)
@ -1349,8 +1355,8 @@ static inline void tb_alloc_page(TranslationBlock *tb,
/* add a new TB and link it to the physical page tables. phys_page2 is
(-1) to indicate that only one page contains the TB. */
void tb_link_page(TranslationBlock *tb,
tb_page_addr_t phys_pc, tb_page_addr_t phys_page2)
static void tb_link_page(TranslationBlock *tb, tb_page_addr_t phys_pc,
tb_page_addr_t phys_page2)
{
unsigned int h;
TranslationBlock **ptb;
@ -1387,6 +1393,17 @@ void tb_link_page(TranslationBlock *tb,
mmap_unlock();
}
#if defined(CONFIG_QEMU_LDST_OPTIMIZATION) && defined(CONFIG_SOFTMMU)
/* check whether the given addr is in TCG generated code buffer or not */
bool is_tcg_gen_code(uintptr_t tc_ptr)
{
/* This can be called during code generation, code_gen_buffer_max_size
is used instead of code_gen_ptr for upper boundary checking */
return (tc_ptr >= (uintptr_t)code_gen_buffer &&
tc_ptr < (uintptr_t)(code_gen_buffer + code_gen_buffer_max_size));
}
#endif
/* find the TB 'tb' such that tb[0].tc_ptr <= tc_ptr <
tb[1].tc_ptr. Return NULL if not found */
TranslationBlock *tb_find_pc(uintptr_t tc_ptr)
@ -1693,6 +1710,7 @@ static void cpu_unlink_tb(CPUArchState *env)
/* mask must never be zero, except for A20 change call */
static void tcg_handle_interrupt(CPUArchState *env, int mask)
{
CPUState *cpu = ENV_GET_CPU(env);
int old_mask;
old_mask = env->interrupt_request;
@ -1702,8 +1720,8 @@ static void tcg_handle_interrupt(CPUArchState *env, int mask)
* If called from iothread context, wake the target cpu in
* case its halted.
*/
if (!qemu_cpu_is_self(env)) {
qemu_cpu_kick(env);
if (!qemu_cpu_is_self(cpu)) {
qemu_cpu_kick(cpu);
return;
}
@ -1859,7 +1877,7 @@ void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end,
}
}
int cpu_physical_memory_set_dirty_tracking(int enable)
static int cpu_physical_memory_set_dirty_tracking(int enable)
{
int ret = 0;
in_migration = enable;
@ -2741,7 +2759,7 @@ void *qemu_get_ram_ptr(ram_addr_t addr)
/* Return a host pointer to ram allocated with qemu_ram_alloc.
* Same as qemu_get_ram_ptr but avoid reordering ramblocks.
*/
void *qemu_safe_ram_ptr(ram_addr_t addr)
static void *qemu_safe_ram_ptr(ram_addr_t addr)
{
RAMBlock *block;
@ -2771,7 +2789,7 @@ void *qemu_safe_ram_ptr(ram_addr_t addr)
/* Return a host pointer to guest's ram. Similar to qemu_get_ram_ptr
* but takes a size argument */
void *qemu_ram_ptr_length(ram_addr_t addr, ram_addr_t *size)
static void *qemu_ram_ptr_length(ram_addr_t addr, ram_addr_t *size)
{
if (*size == 0) {
return NULL;
@ -3519,7 +3537,7 @@ void *cpu_register_map_client(void *opaque, void (*callback)(void *opaque))
return client;
}
void cpu_unregister_map_client(void *_client)
static void cpu_unregister_map_client(void *_client)
{
MapClient *client = (MapClient *)_client;

View File

@ -486,6 +486,33 @@ static int pickNaNMulAdd(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN,
return 1;
}
}
#elif defined(TARGET_MIPS)
static int pickNaNMulAdd(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN,
flag cIsQNaN, flag cIsSNaN, flag infzero STATUS_PARAM)
{
/* For MIPS, the (inf,zero,qnan) case sets InvalidOp and returns
* the default NaN
*/
if (infzero) {
float_raise(float_flag_invalid STATUS_VAR);
return 3;
}
/* Prefer sNaN over qNaN, in the a, b, c order. */
if (aIsSNaN) {
return 0;
} else if (bIsSNaN) {
return 1;
} else if (cIsSNaN) {
return 2;
} else if (aIsQNaN) {
return 0;
} else if (bIsQNaN) {
return 1;
} else {
return 2;
}
}
#elif defined(TARGET_PPC)
static int pickNaNMulAdd(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN,
flag cIsQNaN, flag cIsSNaN, flag infzero STATUS_PARAM)

View File

@ -108,10 +108,10 @@ int adb_poll(ADBBusState *s, uint8_t *obuf)
return olen;
}
ADBDevice *adb_register_device(ADBBusState *s, int devaddr,
ADBDeviceRequest *devreq,
ADBDeviceReset *devreset,
void *opaque)
static ADBDevice *adb_register_device(ADBBusState *s, int devaddr,
ADBDeviceRequest *devreq,
ADBDeviceReset *devreset,
void *opaque)
{
ADBDevice *d;
if (s->nb_devices >= MAX_ADB_DEVICES)

View File

@ -56,10 +56,6 @@ int adb_request(ADBBusState *s, uint8_t *buf_out,
const uint8_t *buf, int len);
int adb_poll(ADBBusState *s, uint8_t *buf_out);
ADBDevice *adb_register_device(ADBBusState *s, int devaddr,
ADBDeviceRequest *devreq,
ADBDeviceReset *devreset,
void *opaque);
void adb_kbd_init(ADBBusState *bus);
void adb_mouse_init(ADBBusState *bus);

View File

@ -107,7 +107,7 @@ static void apic_sync_vapic(APICCommonState *s, int sync_type)
length = offsetof(VAPICState, enabled) - offsetof(VAPICState, isr);
if (sync_type & SYNC_TO_VAPIC) {
assert(qemu_cpu_is_self(s->cpu_env));
assert(qemu_cpu_is_self(CPU(s->cpu)));
vapic_state.tpr = s->tpr;
vapic_state.enabled = 1;
@ -151,15 +151,15 @@ static void apic_local_deliver(APICCommonState *s, int vector)
switch ((lvt >> 8) & 7) {
case APIC_DM_SMI:
cpu_interrupt(s->cpu_env, CPU_INTERRUPT_SMI);
cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_SMI);
break;
case APIC_DM_NMI:
cpu_interrupt(s->cpu_env, CPU_INTERRUPT_NMI);
cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_NMI);
break;
case APIC_DM_EXTINT:
cpu_interrupt(s->cpu_env, CPU_INTERRUPT_HARD);
cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_HARD);
break;
case APIC_DM_FIXED:
@ -187,7 +187,7 @@ void apic_deliver_pic_intr(DeviceState *d, int level)
reset_bit(s->irr, lvt & 0xff);
/* fall through */
case APIC_DM_EXTINT:
cpu_reset_interrupt(s->cpu_env, CPU_INTERRUPT_HARD);
cpu_reset_interrupt(&s->cpu->env, CPU_INTERRUPT_HARD);
break;
}
}
@ -248,18 +248,22 @@ static void apic_bus_deliver(const uint32_t *deliver_bitmask,
case APIC_DM_SMI:
foreach_apic(apic_iter, deliver_bitmask,
cpu_interrupt(apic_iter->cpu_env, CPU_INTERRUPT_SMI) );
cpu_interrupt(&apic_iter->cpu->env, CPU_INTERRUPT_SMI)
);
return;
case APIC_DM_NMI:
foreach_apic(apic_iter, deliver_bitmask,
cpu_interrupt(apic_iter->cpu_env, CPU_INTERRUPT_NMI) );
cpu_interrupt(&apic_iter->cpu->env, CPU_INTERRUPT_NMI)
);
return;
case APIC_DM_INIT:
/* normal INIT IPI sent to processors */
foreach_apic(apic_iter, deliver_bitmask,
cpu_interrupt(apic_iter->cpu_env, CPU_INTERRUPT_INIT) );
cpu_interrupt(&apic_iter->cpu->env,
CPU_INTERRUPT_INIT)
);
return;
case APIC_DM_EXTINT:
@ -293,7 +297,7 @@ static void apic_set_base(APICCommonState *s, uint64_t val)
/* if disabled, cannot be enabled again */
if (!(val & MSR_IA32_APICBASE_ENABLE)) {
s->apicbase &= ~MSR_IA32_APICBASE_ENABLE;
cpu_clear_apic_feature(s->cpu_env);
cpu_clear_apic_feature(&s->cpu->env);
s->spurious_vec &= ~APIC_SV_ENABLE;
}
}
@ -359,13 +363,15 @@ static int apic_irq_pending(APICCommonState *s)
/* signal the CPU if an irq is pending */
static void apic_update_irq(APICCommonState *s)
{
CPUState *cpu = CPU(s->cpu);
if (!(s->spurious_vec & APIC_SV_ENABLE)) {
return;
}
if (!qemu_cpu_is_self(s->cpu_env)) {
cpu_interrupt(s->cpu_env, CPU_INTERRUPT_POLL);
if (!qemu_cpu_is_self(cpu)) {
cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_POLL);
} else if (apic_irq_pending(s) > 0) {
cpu_interrupt(s->cpu_env, CPU_INTERRUPT_HARD);
cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_HARD);
}
}
@ -472,18 +478,18 @@ static void apic_get_delivery_bitmask(uint32_t *deliver_bitmask,
static void apic_startup(APICCommonState *s, int vector_num)
{
s->sipi_vector = vector_num;
cpu_interrupt(s->cpu_env, CPU_INTERRUPT_SIPI);
cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_SIPI);
}
void apic_sipi(DeviceState *d)
{
APICCommonState *s = DO_UPCAST(APICCommonState, busdev.qdev, d);
cpu_reset_interrupt(s->cpu_env, CPU_INTERRUPT_SIPI);
cpu_reset_interrupt(&s->cpu->env, CPU_INTERRUPT_SIPI);
if (!s->wait_for_sipi)
return;
cpu_x86_load_seg_cache_sipi(s->cpu_env, s->sipi_vector);
cpu_x86_load_seg_cache_sipi(s->cpu, s->sipi_vector);
s->wait_for_sipi = 0;
}
@ -672,7 +678,7 @@ static uint32_t apic_mem_readl(void *opaque, hwaddr addr)
case 0x08:
apic_sync_vapic(s, SYNC_FROM_VAPIC);
if (apic_report_tpr_access) {
cpu_report_tpr_access(s->cpu_env, TPR_ACCESS_READ);
cpu_report_tpr_access(&s->cpu->env, TPR_ACCESS_READ);
}
val = s->tpr;
break;
@ -774,7 +780,7 @@ static void apic_mem_writel(void *opaque, hwaddr addr, uint32_t val)
break;
case 0x08:
if (apic_report_tpr_access) {
cpu_report_tpr_access(s->cpu_env, TPR_ACCESS_WRITE);
cpu_report_tpr_access(&s->cpu->env, TPR_ACCESS_WRITE);
}
s->tpr = val;
apic_sync_vapic(s, SYNC_TO_VAPIC);

View File

@ -103,7 +103,7 @@ void apic_handle_tpr_access_report(DeviceState *d, target_ulong ip,
{
APICCommonState *s = DO_UPCAST(APICCommonState, busdev.qdev, d);
vapic_report_tpr_access(s->vapic, s->cpu_env, ip, access);
vapic_report_tpr_access(s->vapic, &s->cpu->env, ip, access);
}
void apic_report_irq_delivered(int delivered)
@ -217,7 +217,7 @@ static void apic_reset_common(DeviceState *d)
APICCommonClass *info = APIC_COMMON_GET_CLASS(s);
bool bsp;
bsp = cpu_is_bsp(x86_env_get_cpu(s->cpu_env));
bsp = cpu_is_bsp(s->cpu);
s->apicbase = 0xfee00000 |
(bsp ? MSR_IA32_APICBASE_BSP : 0) | MSR_IA32_APICBASE_ENABLE;
@ -368,7 +368,6 @@ static const VMStateDescription vmstate_apic_common = {
static Property apic_properties_common[] = {
DEFINE_PROP_UINT8("id", APICCommonState, id, -1),
DEFINE_PROP_PTR("cpu_env", APICCommonState, cpu_env),
DEFINE_PROP_BIT("vapic", APICCommonState, vapic_control, VAPIC_ENABLE_BIT,
true),
DEFINE_PROP_END_OF_LIST(),

View File

@ -95,8 +95,9 @@ typedef struct APICCommonClass
struct APICCommonState {
SysBusDevice busdev;
MemoryRegion io_memory;
void *cpu_env;
X86CPU *cpu;
uint32_t apicbase;
uint8_t id;
uint8_t arb_id;

View File

@ -56,6 +56,7 @@ struct arm_boot_info {
const struct arm_boot_info *info);
/* Used internally by arm_boot.c */
int is_linux;
hwaddr initrd_start;
hwaddr initrd_size;
hwaddr entry;
};

View File

@ -44,7 +44,9 @@ static uint64_t mpcore_scu_read(void *opaque, hwaddr offset,
case 0x0c: /* Invalidate all. */
return 0;
default:
hw_error("mpcore_priv_read: Bad offset %x\n", (int)offset);
qemu_log_mask(LOG_GUEST_ERROR,
"mpcore_priv_read: Bad offset %x\n", (int)offset);
return 0;
}
}
@ -61,7 +63,8 @@ static void mpcore_scu_write(void *opaque, hwaddr offset,
/* This is a no-op as cache is not emulated. */
break;
default:
hw_error("mpcore_priv_read: Bad offset %x\n", (int)offset);
qemu_log_mask(LOG_GUEST_ERROR,
"mpcore_priv_read: Bad offset %x\n", (int)offset);
}
}

View File

@ -18,7 +18,6 @@
#define KERNEL_ARGS_ADDR 0x100
#define KERNEL_LOAD_ADDR 0x00010000
#define INITRD_LOAD_ADDR 0x00d00000
/* The worlds second smallest bootloader. Set r0-r2, then jump to kernel. */
static uint32_t bootloader[] = {
@ -109,7 +108,7 @@ static void set_kernel_args(const struct arm_boot_info *info)
/* ATAG_INITRD2 */
WRITE_WORD(p, 4);
WRITE_WORD(p, 0x54420005);
WRITE_WORD(p, info->loader_start + INITRD_LOAD_ADDR);
WRITE_WORD(p, info->initrd_start);
WRITE_WORD(p, initrd_size);
}
if (info->kernel_cmdline && *info->kernel_cmdline) {
@ -185,10 +184,11 @@ static void set_kernel_args_old(const struct arm_boot_info *info)
/* pages_in_vram */
WRITE_WORD(p, 0);
/* initrd_start */
if (initrd_size)
WRITE_WORD(p, info->loader_start + INITRD_LOAD_ADDR);
else
if (initrd_size) {
WRITE_WORD(p, info->initrd_start);
} else {
WRITE_WORD(p, 0);
}
/* initrd_size */
WRITE_WORD(p, initrd_size);
/* rd_start */
@ -281,14 +281,13 @@ static int load_dtb(hwaddr addr, const struct arm_boot_info *binfo)
if (binfo->initrd_size) {
rc = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-start",
binfo->loader_start + INITRD_LOAD_ADDR);
binfo->initrd_start);
if (rc < 0) {
fprintf(stderr, "couldn't set /chosen/linux,initrd-start\n");
}
rc = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-end",
binfo->loader_start + INITRD_LOAD_ADDR +
binfo->initrd_size);
binfo->initrd_start + binfo->initrd_size);
if (rc < 0) {
fprintf(stderr, "couldn't set /chosen/linux,initrd-end\n");
}
@ -375,6 +374,19 @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
big_endian = 0;
#endif
/* We want to put the initrd far enough into RAM that when the
* kernel is uncompressed it will not clobber the initrd. However
* on boards without much RAM we must ensure that we still leave
* enough room for a decent sized initrd, and on boards with large
* amounts of RAM we must avoid the initrd being so far up in RAM
* that it is outside lowmem and inaccessible to the kernel.
* So for boards with less than 256MB of RAM we put the initrd
* halfway into RAM, and for boards with 256MB of RAM or more we put
* the initrd at 128MB.
*/
info->initrd_start = info->loader_start +
MIN(info->ram_size / 2, 128 * 1024 * 1024);
/* Assume that raw images are linux kernels, and ELF images are not. */
kernel_size = load_elf(info->kernel_filename, NULL, NULL, &elf_entry,
NULL, NULL, big_endian, ELF_MACHINE, 1);
@ -398,10 +410,9 @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
if (is_linux) {
if (info->initrd_filename) {
initrd_size = load_image_targphys(info->initrd_filename,
info->loader_start
+ INITRD_LOAD_ADDR,
info->ram_size
- INITRD_LOAD_ADDR);
info->initrd_start,
info->ram_size -
info->initrd_start);
if (initrd_size < 0) {
fprintf(stderr, "qemu: could not load initrd '%s'\n",
info->initrd_filename);
@ -419,9 +430,8 @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
*/
if (info->dtb_filename) {
/* Place the DTB after the initrd in memory */
hwaddr dtb_start = TARGET_PAGE_ALIGN(info->loader_start
+ INITRD_LOAD_ADDR
+ initrd_size);
hwaddr dtb_start = TARGET_PAGE_ALIGN(info->initrd_start +
initrd_size);
if (load_dtb(dtb_start, info)) {
exit(1);
}

View File

@ -324,7 +324,8 @@ static uint32_t gic_dist_readb(void *opaque, hwaddr offset)
}
return res;
bad_reg:
hw_error("gic_dist_readb: Bad offset %x\n", (int)offset);
qemu_log_mask(LOG_GUEST_ERROR,
"gic_dist_readb: Bad offset %x\n", (int)offset);
return 0;
}
@ -487,7 +488,8 @@ static void gic_dist_writeb(void *opaque, hwaddr offset,
gic_update(s);
return;
bad_reg:
hw_error("gic_dist_writeb: Bad offset %x\n", (int)offset);
qemu_log_mask(LOG_GUEST_ERROR,
"gic_dist_writeb: Bad offset %x\n", (int)offset);
}
static void gic_dist_writew(void *opaque, hwaddr offset,
@ -556,7 +558,8 @@ static uint32_t gic_cpu_read(GICState *s, int cpu, int offset)
case 0x18: /* Highest Pending Interrupt */
return s->current_pending[cpu];
default:
hw_error("gic_cpu_read: Bad offset %x\n", (int)offset);
qemu_log_mask(LOG_GUEST_ERROR,
"gic_cpu_read: Bad offset %x\n", (int)offset);
return 0;
}
}
@ -577,7 +580,8 @@ static void gic_cpu_write(GICState *s, int cpu, int offset, uint32_t value)
case 0x10: /* End Of Interrupt */
return gic_complete_irq(s, cpu, value & 0x3ff);
default:
hw_error("gic_cpu_write: Bad offset %x\n", (int)offset);
qemu_log_mask(LOG_GUEST_ERROR,
"gic_cpu_write: Bad offset %x\n", (int)offset);
return;
}
gic_update(s);

View File

@ -87,7 +87,8 @@ static uint64_t l2x0_priv_read(void *opaque, hwaddr offset,
case 0xF80:
return 0;
default:
fprintf(stderr, "l2x0_priv_read: Bad offset %x\n", (int)offset);
qemu_log_mask(LOG_GUEST_ERROR,
"l2x0_priv_read: Bad offset %x\n", (int)offset);
break;
}
return 0;
@ -128,7 +129,8 @@ static void l2x0_priv_write(void *opaque, hwaddr offset,
case 0xF80:
return;
default:
fprintf(stderr, "l2x0_priv_write: Bad offset %x\n", (int)offset);
qemu_log_mask(LOG_GUEST_ERROR,
"l2x0_priv_write: Bad offset %x\n", (int)offset);
break;
}
}

View File

@ -184,7 +184,9 @@ static uint64_t arm_sysctl_read(void *opaque, hwaddr offset,
return s->sys_cfgstat;
default:
bad_reg:
printf ("arm_sysctl_read: Bad register offset 0x%x\n", (int)offset);
qemu_log_mask(LOG_GUEST_ERROR,
"arm_sysctl_read: Bad register offset 0x%x\n",
(int)offset);
return 0;
}
}
@ -339,7 +341,9 @@ static void arm_sysctl_write(void *opaque, hwaddr offset,
return;
default:
bad_reg:
printf ("arm_sysctl_write: Bad register offset 0x%x\n", (int)offset);
qemu_log_mask(LOG_GUEST_ERROR,
"arm_sysctl_write: Bad register offset 0x%x\n",
(int)offset);
return;
}
}

View File

@ -64,7 +64,8 @@ static uint32_t arm_timer_read(void *opaque, hwaddr offset)
return 0;
return s->int_level;
default:
hw_error("%s: Bad offset %x\n", __func__, (int)offset);
qemu_log_mask(LOG_GUEST_ERROR,
"%s: Bad offset %x\n", __func__, (int)offset);
return 0;
}
}
@ -131,7 +132,8 @@ static void arm_timer_write(void *opaque, hwaddr offset,
arm_timer_recalibrate(s, 0);
break;
default:
hw_error("%s: Bad offset %x\n", __func__, (int)offset);
qemu_log_mask(LOG_GUEST_ERROR,
"%s: Bad offset %x\n", __func__, (int)offset);
}
arm_timer_update(s);
}
@ -223,10 +225,14 @@ static uint64_t sp804_read(void *opaque, hwaddr offset,
/* Integration Test control registers, which we won't support */
case 0xf00: /* TimerITCR */
case 0xf04: /* TimerITOP (strictly write only but..) */
qemu_log_mask(LOG_UNIMP,
"%s: integration test registers unimplemented\n",
__func__);
return 0;
}
hw_error("%s: Bad offset %x\n", __func__, (int)offset);
qemu_log_mask(LOG_GUEST_ERROR,
"%s: Bad offset %x\n", __func__, (int)offset);
return 0;
}
@ -246,7 +252,8 @@ static void sp804_write(void *opaque, hwaddr offset,
}
/* Technically we could be writing to the Test Registers, but not likely */
hw_error("%s: Bad offset %x\n", __func__, (int)offset);
qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %x\n",
__func__, (int)offset);
}
static const MemoryRegionOps sp804_ops = {
@ -300,7 +307,7 @@ static uint64_t icp_pit_read(void *opaque, hwaddr offset,
/* ??? Don't know the PrimeCell ID for this device. */
n = offset >> 8;
if (n > 2) {
hw_error("%s: Bad timer %d\n", __func__, n);
qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad timer %d\n", __func__, n);
}
return arm_timer_read(s->timer[n], offset & 0xff);
@ -314,7 +321,7 @@ static void icp_pit_write(void *opaque, hwaddr offset,
n = offset >> 8;
if (n > 2) {
hw_error("%s: Bad timer %d\n", __func__, n);
qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad timer %d\n", __func__, n);
}
arm_timer_write(s->timer[n], offset & 0xff, value);

View File

@ -138,9 +138,8 @@ void armv7m_nvic_complete_irq(void *opaque, int irq)
gic_complete_irq(&s->gic, 0, irq);
}
static uint32_t nvic_readl(void *opaque, uint32_t offset)
static uint32_t nvic_readl(nvic_state *s, uint32_t offset)
{
nvic_state *s = (nvic_state *)opaque;
uint32_t val;
int irq;
@ -216,14 +215,6 @@ static uint32_t nvic_readl(void *opaque, uint32_t offset)
case 0xd14: /* Configuration Control. */
/* TODO: Implement Configuration Control bits. */
return 0;
case 0xd18: case 0xd1c: case 0xd20: /* System Handler Priority. */
irq = offset - 0xd14;
val = 0;
val |= s->gic.priority1[irq++][0];
val |= s->gic.priority1[irq++][0] << 8;
val |= s->gic.priority1[irq++][0] << 16;
val |= s->gic.priority1[irq][0] << 24;
return val;
case 0xd24: /* System Handler Status. */
val = 0;
if (s->gic.irq_state[ARMV7M_EXCP_MEM].active) val |= (1 << 0);
@ -243,7 +234,7 @@ static uint32_t nvic_readl(void *opaque, uint32_t offset)
return val;
case 0xd28: /* Configurable Fault Status. */
/* TODO: Implement Fault Status. */
hw_error("Not implemented: Configurable Fault Status.");
qemu_log_mask(LOG_UNIMP, "Configurable Fault Status unimplemented\n");
return 0;
case 0xd2c: /* Hard Fault Status. */
case 0xd30: /* Debug Fault Status. */
@ -251,7 +242,8 @@ static uint32_t nvic_readl(void *opaque, uint32_t offset)
case 0xd38: /* Bus Fault Address. */
case 0xd3c: /* Aux Fault Status. */
/* TODO: Implement fault status registers. */
goto bad_reg;
qemu_log_mask(LOG_UNIMP, "Fault status registers unimplemented\n");
return 0;
case 0xd40: /* PFR0. */
return 0x00000030;
case 0xd44: /* PRF1. */
@ -280,14 +272,13 @@ static uint32_t nvic_readl(void *opaque, uint32_t offset)
return 0x01310102;
/* TODO: Implement debug registers. */
default:
bad_reg:
hw_error("NVIC: Bad read offset 0x%x\n", offset);
qemu_log_mask(LOG_GUEST_ERROR, "NVIC: Bad read offset 0x%x\n", offset);
return 0;
}
}
static void nvic_writel(void *opaque, uint32_t offset, uint32_t value)
static void nvic_writel(nvic_state *s, uint32_t offset, uint32_t value)
{
nvic_state *s = (nvic_state *)opaque;
uint32_t oldval;
switch (offset) {
case 0x10: /* SysTick Control and Status. */
@ -345,27 +336,17 @@ static void nvic_writel(void *opaque, uint32_t offset, uint32_t value)
case 0xd0c: /* Application Interrupt/Reset Control. */
if ((value >> 16) == 0x05fa) {
if (value & 2) {
hw_error("VECTCLRACTIVE not implemented");
qemu_log_mask(LOG_UNIMP, "VECTCLRACTIVE unimplemented\n");
}
if (value & 5) {
hw_error("System reset");
qemu_log_mask(LOG_UNIMP, "AIRCR system reset unimplemented\n");
}
}
break;
case 0xd10: /* System Control. */
case 0xd14: /* Configuration Control. */
/* TODO: Implement control registers. */
goto bad_reg;
case 0xd18: case 0xd1c: case 0xd20: /* System Handler Priority. */
{
int irq;
irq = offset - 0xd14;
s->gic.priority1[irq++][0] = value & 0xff;
s->gic.priority1[irq++][0] = (value >> 8) & 0xff;
s->gic.priority1[irq++][0] = (value >> 16) & 0xff;
s->gic.priority1[irq][0] = (value >> 24) & 0xff;
gic_update(&s->gic);
}
qemu_log_mask(LOG_UNIMP, "NVIC: SCR and CCR unimplemented\n");
break;
case 0xd24: /* System Handler Control. */
/* TODO: Real hardware allows you to set/clear the active bits
@ -380,47 +361,71 @@ static void nvic_writel(void *opaque, uint32_t offset, uint32_t value)
case 0xd34: /* Mem Manage Address. */
case 0xd38: /* Bus Fault Address. */
case 0xd3c: /* Aux Fault Status. */
goto bad_reg;
qemu_log_mask(LOG_UNIMP,
"NVIC: fault status registers unimplemented\n");
break;
case 0xf00: /* Software Triggered Interrupt Register */
if ((value & 0x1ff) < s->num_irq) {
gic_set_pending_private(&s->gic, 0, value & 0x1ff);
}
break;
default:
bad_reg:
hw_error("NVIC: Bad write offset 0x%x\n", offset);
qemu_log_mask(LOG_GUEST_ERROR,
"NVIC: Bad write offset 0x%x\n", offset);
}
}
static uint64_t nvic_sysreg_read(void *opaque, hwaddr addr,
unsigned size)
{
/* At the moment we only support the ID registers for byte/word access.
* This is not strictly correct as a few of the other registers also
* allow byte access.
*/
nvic_state *s = (nvic_state *)opaque;
uint32_t offset = addr;
if (offset >= 0xfe0) {
int i;
uint32_t val;
switch (offset) {
case 0xd18 ... 0xd23: /* System Handler Priority. */
val = 0;
for (i = 0; i < size; i++) {
val |= s->gic.priority1[(offset - 0xd14) + i][0] << (i * 8);
}
return val;
case 0xfe0 ... 0xfff: /* ID. */
if (offset & 3) {
return 0;
}
return nvic_id[(offset - 0xfe0) >> 2];
}
if (size == 4) {
return nvic_readl(opaque, offset);
return nvic_readl(s, offset);
}
hw_error("NVIC: Bad read of size %d at offset 0x%x\n", size, offset);
qemu_log_mask(LOG_GUEST_ERROR,
"NVIC: Bad read of size %d at offset 0x%x\n", size, offset);
return 0;
}
static void nvic_sysreg_write(void *opaque, hwaddr addr,
uint64_t value, unsigned size)
{
nvic_state *s = (nvic_state *)opaque;
uint32_t offset = addr;
if (size == 4) {
nvic_writel(opaque, offset, value);
int i;
switch (offset) {
case 0xd18 ... 0xd23: /* System Handler Priority. */
for (i = 0; i < size; i++) {
s->gic.priority1[(offset - 0xd14) + i][0] =
(value >> (i * 8)) & 0xff;
}
gic_update(&s->gic);
return;
}
hw_error("NVIC: Bad write of size %d at offset 0x%x\n", size, offset);
if (size == 4) {
nvic_writel(s, offset, value);
return;
}
qemu_log_mask(LOG_GUEST_ERROR,
"NVIC: Bad write of size %d at offset 0x%x\n", size, offset);
}
static const MemoryRegionOps nvic_sysreg_ops = {

View File

@ -921,8 +921,8 @@ static void blizzard_update_display(void *opaque)
for (; y < s->my[1]; y ++, src += bypl, dst += bypl)
memcpy(dst, src, bwidth);
dpy_update(s->state, s->mx[0], s->my[0],
s->mx[1] - s->mx[0], y - s->my[0]);
dpy_gfx_update(s->state, s->mx[0], s->my[0],
s->mx[1] - s->mx[0], y - s->my[0]);
s->mx[0] = s->x;
s->mx[1] = 0;

View File

@ -359,7 +359,7 @@ static void uart_write(void *opaque, hwaddr offset,
{
UartState *s = (UartState *)opaque;
DB_PRINT(" offset:%x data:%08x\n", offset, (unsigned)value);
DB_PRINT(" offset:%x data:%08x\n", (unsigned)offset, (unsigned)value);
offset >>= 2;
switch (offset) {
case R_IER: /* ier (wts imr) */
@ -405,12 +405,15 @@ static uint64_t uart_read(void *opaque, hwaddr offset,
offset >>= 2;
if (offset >= R_MAX) {
return 0;
c = 0;
} else if (offset == R_TX_RX) {
uart_read_rx_fifo(s, &c);
return c;
} else {
c = s->r[offset];
}
return s->r[offset];
DB_PRINT(" offset:%x data:%08x\n", (unsigned)(offset << 2), (unsigned)c);
return c;
}
static const MemoryRegionOps uart_ops = {

View File

@ -42,8 +42,6 @@
//#define DEBUG_CIRRUS
//#define DEBUG_BITBLT
#define VGA_RAM_SIZE (8192 * 1024)
/***************************************
*
* definitions
@ -2856,7 +2854,8 @@ static void cirrus_init_common(CirrusVGAState * s, int device_id, int is_pci,
/* I/O handler for LFB */
memory_region_init_io(&s->cirrus_linear_io, &cirrus_linear_io_ops, s,
"cirrus-linear-io", VGA_RAM_SIZE);
"cirrus-linear-io", s->vga.vram_size_mb
* 1024 * 1024);
memory_region_set_flush_coalesced(&s->cirrus_linear_io);
/* I/O handler for LFB */
@ -2899,7 +2898,6 @@ static int vga_initfn(ISADevice *dev)
ISACirrusVGAState *d = DO_UPCAST(ISACirrusVGAState, dev, dev);
VGACommonState *s = &d->cirrus_vga.vga;
s->vram_size_mb = VGA_RAM_SIZE >> 20;
vga_common_init(s);
cirrus_init_common(&d->cirrus_vga, CIRRUS_ID_CLGD5430, 0,
isa_address_space(dev));
@ -2912,6 +2910,12 @@ static int vga_initfn(ISADevice *dev)
return 0;
}
static Property isa_vga_cirrus_properties[] = {
DEFINE_PROP_UINT32("vgamem_mb", struct ISACirrusVGAState,
cirrus_vga.vga.vram_size_mb, 8),
DEFINE_PROP_END_OF_LIST(),
};
static void isa_cirrus_vga_class_init(ObjectClass *klass, void *data)
{
ISADeviceClass *k = ISA_DEVICE_CLASS(klass);
@ -2919,6 +2923,7 @@ static void isa_cirrus_vga_class_init(ObjectClass *klass, void *data)
dc->vmsd = &vmstate_cirrus_vga;
k->init = vga_initfn;
dc->props = isa_vga_cirrus_properties;
}
static TypeInfo isa_cirrus_vga_info = {
@ -2942,7 +2947,6 @@ static int pci_cirrus_vga_initfn(PCIDevice *dev)
int16_t device_id = pc->device_id;
/* setup VGA */
s->vga.vram_size_mb = VGA_RAM_SIZE >> 20;
vga_common_init(&s->vga);
cirrus_init_common(s, device_id, 1, pci_address_space(dev));
s->vga.ds = graphic_console_init(s->vga.update, s->vga.invalidate,
@ -2969,6 +2973,12 @@ static int pci_cirrus_vga_initfn(PCIDevice *dev)
return 0;
}
static Property pci_vga_cirrus_properties[] = {
DEFINE_PROP_UINT32("vgamem_mb", struct PCICirrusVGAState,
cirrus_vga.vga.vram_size_mb, 8),
DEFINE_PROP_END_OF_LIST(),
};
static void cirrus_vga_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
@ -2982,6 +2992,7 @@ static void cirrus_vga_class_init(ObjectClass *klass, void *data)
k->class_id = PCI_CLASS_DISPLAY_VGA;
dc->desc = "Cirrus CLGD 54xx VGA";
dc->vmsd = &vmstate_pci_cirrus_vga;
dc->props = pci_vga_cirrus_properties;
}
static TypeInfo cirrus_vga_info = {

View File

@ -92,7 +92,6 @@ typedef struct E1000State_st {
uint32_t rxbuf_size;
uint32_t rxbuf_min_shift;
int check_rxov;
struct e1000_tx {
unsigned char header[256];
unsigned char vlan_header[4];
@ -266,6 +265,8 @@ rxbufsize(uint32_t v)
static void e1000_reset(void *opaque)
{
E1000State *d = opaque;
uint8_t *macaddr = d->conf.macaddr.a;
int i;
qemu_del_timer(d->autoneg_timer);
memset(d->phy_reg, 0, sizeof d->phy_reg);
@ -278,6 +279,14 @@ static void e1000_reset(void *opaque)
if (d->nic->nc.link_down) {
e1000_link_down(d);
}
/* Some guests expect pre-initialized RAH/RAL (AddrValid flag + MACaddr) */
d->mac_reg[RA] = 0;
d->mac_reg[RA + 1] = E1000_RAH_AV;
for (i = 0; i < 4; i++) {
d->mac_reg[RA] |= macaddr[i] << (8 * i);
d->mac_reg[RA + 1] |= (i < 2) ? macaddr[i + 4] << (8 * i) : 0;
}
}
static void
@ -741,11 +750,11 @@ static bool e1000_has_rxbufs(E1000State *s, size_t total_size)
int bufs;
/* Fast-path short packets */
if (total_size <= s->rxbuf_size) {
return s->mac_reg[RDH] != s->mac_reg[RDT] || !s->check_rxov;
return s->mac_reg[RDH] != s->mac_reg[RDT];
}
if (s->mac_reg[RDH] < s->mac_reg[RDT]) {
bufs = s->mac_reg[RDT] - s->mac_reg[RDH];
} else if (s->mac_reg[RDH] > s->mac_reg[RDT] || !s->check_rxov) {
} else if (s->mac_reg[RDH] > s->mac_reg[RDT]) {
bufs = s->mac_reg[RDLEN] / sizeof(struct e1000_rx_desc) +
s->mac_reg[RDT] - s->mac_reg[RDH];
} else {
@ -848,7 +857,6 @@ e1000_receive(NetClientState *nc, const uint8_t *buf, size_t size)
if (++s->mac_reg[RDH] * sizeof(desc) >= s->mac_reg[RDLEN])
s->mac_reg[RDH] = 0;
s->check_rxov = 1;
/* see comment in start_xmit; same here */
if (s->mac_reg[RDH] == rdh_start) {
DBGOUT(RXERR, "RDH wraparound @%x, RDT %x, RDLEN %x\n",
@ -925,7 +933,6 @@ mac_writereg(E1000State *s, int index, uint32_t val)
static void
set_rdt(E1000State *s, int index, uint32_t val)
{
s->check_rxov = 0;
s->mac_reg[index] = val & 0xffff;
if (e1000_has_rxbufs(s, 1)) {
qemu_flush_queued_packets(&s->nic->nc);

View File

@ -1307,7 +1307,7 @@ static void exynos4210_fimd_update(void *opaque)
fimd_copy_line_toqemu(global_width, s->ifb + global_width * line *
RGBA_SIZE, d + global_width * line * bpp);
}
dpy_update(s->console, 0, 0, global_width, global_height);
dpy_gfx_update(s->console, 0, 0, global_width, global_height);
}
s->invalidate = false;
s->vidintcon[1] |= FIMD_VIDINT_INTFRMPEND;

View File

@ -93,11 +93,8 @@ static void lan9215_init(uint32_t base, qemu_irq irq)
}
}
static Exynos4210State *exynos4_boards_init_common(
const char *kernel_filename,
const char *kernel_cmdline,
const char *initrd_filename,
Exynos4BoardType board_type)
static Exynos4210State *exynos4_boards_init_common(QEMUMachineInitArgs *args,
Exynos4BoardType board_type)
{
if (smp_cpus != EXYNOS4210_NCPUS) {
fprintf(stderr, "%s board supports only %d CPU cores. Ignoring smp_cpus"
@ -110,9 +107,9 @@ static Exynos4210State *exynos4_boards_init_common(
exynos4_board_binfo.board_id = exynos4_board_id[board_type];
exynos4_board_binfo.smp_bootreg_addr =
exynos4_board_smp_bootreg_addr[board_type];
exynos4_board_binfo.kernel_filename = kernel_filename;
exynos4_board_binfo.initrd_filename = initrd_filename;
exynos4_board_binfo.kernel_cmdline = kernel_cmdline;
exynos4_board_binfo.kernel_filename = args->kernel_filename;
exynos4_board_binfo.initrd_filename = args->initrd_filename;
exynos4_board_binfo.kernel_cmdline = args->kernel_cmdline;
exynos4_board_binfo.gic_cpu_if_addr =
EXYNOS4210_SMP_PRIVATE_BASE_ADDR + 0x100;
@ -122,9 +119,9 @@ static Exynos4210State *exynos4_boards_init_common(
" initrd_filename: %s\n",
exynos4_board_ram_size[board_type] / 1048576,
exynos4_board_ram_size[board_type],
kernel_filename,
kernel_cmdline,
initrd_filename);
args->kernel_filename,
args->kernel_cmdline,
args->initrd_filename);
return exynos4210_init(get_system_memory(),
exynos4_board_ram_size[board_type]);
@ -132,22 +129,15 @@ static Exynos4210State *exynos4_boards_init_common(
static void nuri_init(QEMUMachineInitArgs *args)
{
const char *kernel_filename = args->kernel_filename;
const char *kernel_cmdline = args->kernel_cmdline;
const char *initrd_filename = args->initrd_filename;
exynos4_boards_init_common(kernel_filename, kernel_cmdline,
initrd_filename, EXYNOS4_BOARD_NURI);
exynos4_boards_init_common(args, EXYNOS4_BOARD_NURI);
arm_load_kernel(arm_env_get_cpu(first_cpu), &exynos4_board_binfo);
}
static void smdkc210_init(QEMUMachineInitArgs *args)
{
const char *kernel_filename = args->kernel_filename;
const char *kernel_cmdline = args->kernel_cmdline;
const char *initrd_filename = args->initrd_filename;
Exynos4210State *s = exynos4_boards_init_common(kernel_filename,
kernel_cmdline, initrd_filename, EXYNOS4_BOARD_SMDKC210);
Exynos4210State *s = exynos4_boards_init_common(args,
EXYNOS4_BOARD_SMDKC210);
lan9215_init(SMDK_LAN9118_BASE_ADDR,
qemu_irq_invert(s->irq_table[exynos4210_get_irq(37, 1)]));

View File

@ -197,7 +197,8 @@ static void g364fb_draw_graphic8(G364State *s)
reset_dirty(s, page_min, page_max);
page_min = (ram_addr_t)-1;
page_max = 0;
dpy_update(s->ds, xmin, ymin, xmax - xmin + 1, ymax - ymin + 1);
dpy_gfx_update(s->ds, xmin, ymin,
xmax - xmin + 1, ymax - ymin + 1);
xmin = s->width;
xmax = 0;
ymin = s->height;
@ -216,7 +217,7 @@ static void g364fb_draw_graphic8(G364State *s)
done:
if (page_min != (ram_addr_t)-1) {
dpy_update(s->ds, xmin, ymin, xmax - xmin + 1, ymax - ymin + 1);
dpy_gfx_update(s->ds, xmin, ymin, xmax - xmin + 1, ymax - ymin + 1);
reset_dirty(s, page_min, page_max);
}
}
@ -238,7 +239,7 @@ static void g364fb_draw_blank(G364State *s)
d += ds_get_linesize(s->ds);
}
dpy_update(s->ds, 0, 0, s->width, s->height);
dpy_gfx_update(s->ds, 0, 0, s->width, s->height);
s->blanked = 1;
}

View File

@ -10,6 +10,7 @@
#include "ioport.h"
#include "irq.h"
#include "qemu-aio.h"
#include "qemu-file.h"
#include "vmstate.h"
#include "qemu-log.h"

View File

@ -196,7 +196,7 @@ static void jazz_led_update_display(void *opaque)
}
s->state = REDRAW_NONE;
dpy_update(ds, 0, 0, ds_get_width(ds), ds_get_height(ds));
dpy_gfx_update(ds, 0, 0, ds_get_width(ds), ds_get_height(ds));
}
static void jazz_led_invalidate_display(void *opaque)
@ -210,7 +210,7 @@ static void jazz_led_text_update(void *opaque, console_ch_t *chardata)
LedState *s = opaque;
char buf[2];
dpy_cursor(s->ds, -1, -1);
dpy_text_cursor(s->ds, -1, -1);
qemu_console_resize(s->ds, 2, 1);
/* TODO: draw the segments */
@ -218,7 +218,7 @@ static void jazz_led_text_update(void *opaque, console_ch_t *chardata)
console_write_ch(chardata++, 0x00200100 | buf[0]);
console_write_ch(chardata++, 0x00200100 | buf[1]);
dpy_update(s->ds, 0, 0, 2, 1);
dpy_text_update(s->ds, 0, 0, 2, 1);
}
static int jazz_led_post_load(void *opaque, int version_id)

View File

@ -104,7 +104,7 @@ static void kvm_apic_enable_tpr_reporting(APICCommonState *s, bool enable)
.enabled = enable
};
kvm_vcpu_ioctl(s->cpu_env, KVM_TPR_ACCESS_REPORTING, &ctl);
kvm_vcpu_ioctl(&s->cpu->env, KVM_TPR_ACCESS_REPORTING, &ctl);
}
static void kvm_apic_vapic_base_update(APICCommonState *s)
@ -114,7 +114,7 @@ static void kvm_apic_vapic_base_update(APICCommonState *s)
};
int ret;
ret = kvm_vcpu_ioctl(s->cpu_env, KVM_SET_VAPIC_ADDR, &vapid_addr);
ret = kvm_vcpu_ioctl(&s->cpu->env, KVM_SET_VAPIC_ADDR, &vapid_addr);
if (ret < 0) {
fprintf(stderr, "KVM: setting VAPIC address failed (%s)\n",
strerror(-ret));
@ -125,7 +125,7 @@ static void kvm_apic_vapic_base_update(APICCommonState *s)
static void do_inject_external_nmi(void *data)
{
APICCommonState *s = data;
CPUX86State *env = s->cpu_env;
CPUX86State *env = &s->cpu->env;
uint32_t lvt;
int ret;
@ -143,7 +143,7 @@ static void do_inject_external_nmi(void *data)
static void kvm_apic_external_nmi(APICCommonState *s)
{
run_on_cpu(s->cpu_env, do_inject_external_nmi, s);
run_on_cpu(CPU(s->cpu), do_inject_external_nmi, s);
}
static uint64_t kvm_apic_mem_read(void *opaque, hwaddr addr,

View File

@ -384,10 +384,13 @@ static void patch_call(VAPICROMState *s, CPUX86State *env, target_ulong ip,
static void patch_instruction(VAPICROMState *s, CPUX86State *env, target_ulong ip)
{
hwaddr paddr;
VAPICHandlers *handlers;
uint8_t opcode[2];
uint32_t imm32;
TranslationBlock *current_tb;
target_ulong current_pc = 0;
target_ulong current_cs_base = 0;
int current_flags = 0;
if (smp_cpus == 1) {
handlers = &s->rom_state.up;
@ -395,6 +398,13 @@ static void patch_instruction(VAPICROMState *s, CPUX86State *env, target_ulong i
handlers = &s->rom_state.mp;
}
if (!kvm_enabled()) {
current_tb = tb_find_pc(env->mem_io_pc);
cpu_restore_state(current_tb, env, env->mem_io_pc);
cpu_get_tb_cpu_state(env, &current_pc, &current_cs_base,
&current_flags);
}
pause_all_vcpus();
cpu_memory_rw_debug(env, ip, opcode, sizeof(opcode), 0);
@ -430,9 +440,11 @@ static void patch_instruction(VAPICROMState *s, CPUX86State *env, target_ulong i
resume_all_vcpus();
paddr = cpu_get_phys_page_debug(env, ip);
paddr += ip & ~TARGET_PAGE_MASK;
tb_invalidate_phys_page_range(paddr, paddr + 1, 1);
if (!kvm_enabled()) {
env->current_tb = NULL;
tb_gen_code(env, current_pc, current_cs_base, current_flags, 1);
cpu_resume_from_signal(env, NULL);
}
}
void vapic_report_tpr_access(DeviceState *dev, void *cpu, target_ulong ip,
@ -475,11 +487,13 @@ static void vapic_enable_tpr_reporting(bool enable)
VAPICEnableTPRReporting info = {
.enable = enable,
};
X86CPU *cpu;
CPUX86State *env;
for (env = first_cpu; env != NULL; env = env->next_cpu) {
cpu = x86_env_get_cpu(env);
info.apic = env->apic_state;
run_on_cpu(env, vapic_do_enable_tpr_reporting, &info);
run_on_cpu(CPU(cpu), vapic_do_enable_tpr_reporting, &info);
}
}
@ -717,7 +731,7 @@ static int vapic_post_load(void *opaque, int version_id)
}
if (s->state == VAPIC_ACTIVE) {
if (smp_cpus == 1) {
run_on_cpu(first_cpu, do_vapic_enable, s);
run_on_cpu(ENV_GET_CPU(first_cpu), do_vapic_enable, s);
} else {
zero = g_malloc0(s->rom_state.vapic_size);
cpu_physical_memory_rw(s->vapic_paddr, zero,

View File

@ -468,13 +468,6 @@ uint32_t m48t59_read (void *opaque, uint32_t addr)
return retval;
}
void m48t59_set_addr (void *opaque, uint32_t addr)
{
M48t59State *NVRAM = opaque;
NVRAM->addr = addr;
}
void m48t59_toggle_lock (void *opaque, int lock)
{
M48t59State *NVRAM = opaque;

View File

@ -95,10 +95,8 @@ static struct arm_boot_info mainstone_binfo = {
};
static void mainstone_common_init(MemoryRegion *address_space_mem,
ram_addr_t ram_size,
const char *kernel_filename,
const char *kernel_cmdline, const char *initrd_filename,
const char *cpu_model, enum mainstone_model_e model, int arm_id)
QEMUMachineInitArgs *args,
enum mainstone_model_e model, int arm_id)
{
uint32_t sector_len = 256 * 1024;
hwaddr mainstone_flash_base[] = { MST_FLASH_0, MST_FLASH_1 };
@ -108,6 +106,7 @@ static void mainstone_common_init(MemoryRegion *address_space_mem,
int i;
int be;
MemoryRegion *rom = g_new(MemoryRegion, 1);
const char *cpu_model = args->cpu_model;
if (!cpu_model)
cpu_model = "pxa270-c5";
@ -164,22 +163,16 @@ static void mainstone_common_init(MemoryRegion *address_space_mem,
smc91c111_init(&nd_table[0], MST_ETH_PHYS,
qdev_get_gpio_in(mst_irq, ETHERNET_IRQ));
mainstone_binfo.kernel_filename = kernel_filename;
mainstone_binfo.kernel_cmdline = kernel_cmdline;
mainstone_binfo.initrd_filename = initrd_filename;
mainstone_binfo.kernel_filename = args->kernel_filename;
mainstone_binfo.kernel_cmdline = args->kernel_cmdline;
mainstone_binfo.initrd_filename = args->initrd_filename;
mainstone_binfo.board_id = arm_id;
arm_load_kernel(mpu->cpu, &mainstone_binfo);
}
static void mainstone_init(QEMUMachineInitArgs *args)
{
ram_addr_t ram_size = args->ram_size;
const char *cpu_model = args->cpu_model;
const char *kernel_filename = args->kernel_filename;
const char *kernel_cmdline = args->kernel_cmdline;
const char *initrd_filename = args->initrd_filename;
mainstone_common_init(get_system_memory(), ram_size, kernel_filename,
kernel_cmdline, initrd_filename, cpu_model, mainstone, 0x196);
mainstone_common_init(get_system_memory(), args, mainstone, 0x196);
}
static QEMUMachine mainstone2_machine = {

View File

@ -134,7 +134,7 @@ static void vgafb_update_display(void *opaque)
&first, &last);
if (first >= 0) {
dpy_update(s->ds, 0, first, s->regs[R_HRES], last - first + 1);
dpy_gfx_update(s->ds, 0, first, s->regs[R_HRES], last - first + 1);
}
s->invalidate = 0;
}

View File

@ -526,7 +526,7 @@ static void lcd_refresh(void *opaque)
ds_get_bits_per_pixel(s->ds));
}
dpy_update(s->ds, 0, 0, 128*3, 64*3);
dpy_gfx_update(s->ds, 0, 0, 128*3, 64*3);
}
static void lcd_invalidate(void *opaque)

View File

@ -1284,17 +1284,15 @@ static int n810_atag_setup(const struct arm_boot_info *info, void *p)
return n8x0_atag_setup(p, 810);
}
static void n8x0_init(ram_addr_t ram_size, const char *boot_device,
const char *kernel_filename,
const char *kernel_cmdline, const char *initrd_filename,
const char *cpu_model, struct arm_boot_info *binfo, int model)
static void n8x0_init(QEMUMachineInitArgs *args,
struct arm_boot_info *binfo, int model)
{
MemoryRegion *sysmem = get_system_memory();
struct n800_s *s = (struct n800_s *) g_malloc0(sizeof(*s));
int sdram_size = binfo->ram_size;
DisplayState *ds;
s->mpu = omap2420_mpu_init(sysmem, sdram_size, cpu_model);
s->mpu = omap2420_mpu_init(sysmem, sdram_size, args->cpu_model);
/* Setup peripherals
*
@ -1338,17 +1336,18 @@ static void n8x0_init(ram_addr_t ram_size, const char *boot_device,
n8x0_usb_setup(s);
}
if (kernel_filename) {
if (args->kernel_filename) {
/* Or at the linux loader. */
binfo->kernel_filename = kernel_filename;
binfo->kernel_cmdline = kernel_cmdline;
binfo->initrd_filename = initrd_filename;
binfo->kernel_filename = args->kernel_filename;
binfo->kernel_cmdline = args->kernel_cmdline;
binfo->initrd_filename = args->initrd_filename;
arm_load_kernel(s->mpu->cpu, binfo);
qemu_register_reset(n8x0_boot_init, s);
}
if (option_rom[0].name && (boot_device[0] == 'n' || !kernel_filename)) {
if (option_rom[0].name &&
(args->boot_device[0] == 'n' || !args->kernel_filename)) {
int rom_size;
uint8_t nolo_tags[0x10000];
/* No, wait, better start at the ROM. */
@ -1376,7 +1375,7 @@ static void n8x0_init(ram_addr_t ram_size, const char *boot_device,
size until the guest activates the display. */
ds = get_displaystate();
ds->surface = qemu_resize_displaysurface(ds, 800, 480);
dpy_resize(ds);
dpy_gfx_resize(ds);
}
static struct arm_boot_info n800_binfo = {
@ -1400,28 +1399,12 @@ static struct arm_boot_info n810_binfo = {
static void n800_init(QEMUMachineInitArgs *args)
{
ram_addr_t ram_size = args->ram_size;
const char *cpu_model = args->cpu_model;
const char *kernel_filename = args->kernel_filename;
const char *kernel_cmdline = args->kernel_cmdline;
const char *initrd_filename = args->initrd_filename;
const char *boot_device = args->boot_device;
return n8x0_init(ram_size, boot_device,
kernel_filename, kernel_cmdline, initrd_filename,
cpu_model, &n800_binfo, 800);
return n8x0_init(args, &n800_binfo, 800);
}
static void n810_init(QEMUMachineInitArgs *args)
{
ram_addr_t ram_size = args->ram_size;
const char *cpu_model = args->cpu_model;
const char *kernel_filename = args->kernel_filename;
const char *kernel_cmdline = args->kernel_cmdline;
const char *initrd_filename = args->initrd_filename;
const char *boot_device = args->boot_device;
return n8x0_init(ram_size, boot_device,
kernel_filename, kernel_cmdline, initrd_filename,
cpu_model, &n810_binfo, 810);
return n8x0_init(args, &n810_binfo, 810);
}
static QEMUMachine n800_machine = {

View File

@ -10,17 +10,9 @@ typedef struct nvram_t {
nvram_write_t write_fn;
} nvram_t;
void NVRAM_set_byte (nvram_t *nvram, uint32_t addr, uint8_t value);
uint8_t NVRAM_get_byte (nvram_t *nvram, uint32_t addr);
void NVRAM_set_word (nvram_t *nvram, uint32_t addr, uint16_t value);
uint16_t NVRAM_get_word (nvram_t *nvram, uint32_t addr);
void NVRAM_set_lword (nvram_t *nvram, uint32_t addr, uint32_t value);
uint32_t NVRAM_get_lword (nvram_t *nvram, uint32_t addr);
void NVRAM_set_string (nvram_t *nvram, uint32_t addr,
const char *str, uint32_t max);
int NVRAM_get_string (nvram_t *nvram, uint8_t *dst, uint16_t addr, int max);
void NVRAM_set_crc (nvram_t *nvram, uint32_t addr,
uint32_t start, uint32_t count);
int PPC_NVRAM_set_params (nvram_t *nvram, uint16_t NVRAM_size,
const char *arch,
uint32_t RAM_size, int boot_device,
@ -38,6 +30,5 @@ M48t59State *m48t59_init_isa(ISABus *bus, uint32_t io_base, uint16_t size,
int type);
M48t59State *m48t59_init(qemu_irq IRQ, hwaddr mem_base,
uint32_t io_base, uint16_t size, int type);
void m48t59_set_addr (void *opaque, uint32_t addr);
#endif /* !NVRAM_H */

View File

@ -219,7 +219,7 @@ static void omap_update_display(void *opaque)
draw_line, omap_lcd->palette,
&first, &last);
if (first >= 0) {
dpy_update(omap_lcd->state, 0, first, width, last - first + 1);
dpy_gfx_update(omap_lcd->state, 0, first, width, last - first + 1);
}
omap_lcd->invalidate = 0;
}

View File

@ -97,11 +97,7 @@ static struct arm_boot_info sx1_binfo = {
.board_id = 0x265,
};
static void sx1_init(ram_addr_t ram_size,
const char *boot_device,
const char *kernel_filename, const char *kernel_cmdline,
const char *initrd_filename, const char *cpu_model,
const int version)
static void sx1_init(QEMUMachineInitArgs *args, const int version)
{
struct omap_mpu_state_s *mpu;
MemoryRegion *address_space = get_system_memory();
@ -121,7 +117,7 @@ static void sx1_init(ram_addr_t ram_size,
flash_size = flash2_size;
}
mpu = omap310_mpu_init(address_space, sx1_binfo.ram_size, cpu_model);
mpu = omap310_mpu_init(address_space, sx1_binfo.ram_size, args->cpu_model);
/* External Flash (EMIFS) */
memory_region_init_ram(flash, "omap_sx1.flash0-0", flash_size);
@ -192,16 +188,16 @@ static void sx1_init(ram_addr_t ram_size,
OMAP_CS1_BASE, &cs[1]);
}
if (!kernel_filename && !fl_idx) {
if (!args->kernel_filename && !fl_idx) {
fprintf(stderr, "Kernel or Flash image must be specified\n");
exit(1);
}
/* Load the kernel. */
if (kernel_filename) {
sx1_binfo.kernel_filename = kernel_filename;
sx1_binfo.kernel_cmdline = kernel_cmdline;
sx1_binfo.initrd_filename = initrd_filename;
if (args->kernel_filename) {
sx1_binfo.kernel_filename = args->kernel_filename;
sx1_binfo.kernel_cmdline = args->kernel_cmdline;
sx1_binfo.initrd_filename = args->initrd_filename;
arm_load_kernel(mpu->cpu, &sx1_binfo);
}
@ -211,26 +207,12 @@ static void sx1_init(ram_addr_t ram_size,
static void sx1_init_v1(QEMUMachineInitArgs *args)
{
ram_addr_t ram_size = args->ram_size;
const char *cpu_model = args->cpu_model;
const char *kernel_filename = args->kernel_filename;
const char *kernel_cmdline = args->kernel_cmdline;
const char *initrd_filename = args->initrd_filename;
const char *boot_device = args->boot_device;
sx1_init(ram_size, boot_device, kernel_filename,
kernel_cmdline, initrd_filename, cpu_model, 1);
sx1_init(args, 1);
}
static void sx1_init_v2(QEMUMachineInitArgs *args)
{
ram_addr_t ram_size = args->ram_size;
const char *cpu_model = args->cpu_model;
const char *kernel_filename = args->kernel_filename;
const char *kernel_cmdline = args->kernel_cmdline;
const char *initrd_filename = args->initrd_filename;
const char *boot_device = args->boot_device;
sx1_init(ram_size, boot_device, kernel_filename,
kernel_cmdline, initrd_filename, cpu_model, 2);
sx1_init(args, 2);
}
static QEMUMachine sx1_machine_v2 = {

View File

@ -273,7 +273,7 @@ static void palmte_init(QEMUMachineInitArgs *args)
will set the size once configured, so this just sets an initial
size until the guest activates the display. */
ds->surface = qemu_resize_displaysurface(ds, 320, 320);
dpy_resize(ds);
dpy_gfx_resize(ds);
}
static QEMUMachine palmte_machine = {

56
hw/pc.c
View File

@ -71,8 +71,6 @@
#define FW_CFG_E820_TABLE (FW_CFG_ARCH_LOCAL + 3)
#define FW_CFG_HPET (FW_CFG_ARCH_LOCAL + 4)
#define MSI_ADDR_BASE 0xfee00000
#define E820_NR_ENTRIES 16
struct e820_entry {
@ -849,35 +847,6 @@ DeviceState *cpu_get_current_apic(void)
}
}
static DeviceState *apic_init(void *env, uint8_t apic_id)
{
DeviceState *dev;
static int apic_mapped;
if (kvm_irqchip_in_kernel()) {
dev = qdev_create(NULL, "kvm-apic");
} else if (xen_enabled()) {
dev = qdev_create(NULL, "xen-apic");
} else {
dev = qdev_create(NULL, "apic");
}
qdev_prop_set_uint8(dev, "id", apic_id);
qdev_prop_set_ptr(dev, "cpu_env", env);
qdev_init_nofail(dev);
/* XXX: mapping more APICs at the same memory location */
if (apic_mapped == 0) {
/* NOTE: the APIC is directly connected to the CPU - it is not
on the global memory bus. */
/* XXX: what if the base changes? */
sysbus_mmio_map(sysbus_from_qdev(dev), 0, MSI_ADDR_BASE);
apic_mapped = 1;
}
return dev;
}
void pc_acpi_smi_interrupt(void *opaque, int irq, int level)
{
CPUX86State *s = opaque;
@ -887,24 +856,6 @@ void pc_acpi_smi_interrupt(void *opaque, int irq, int level)
}
}
static X86CPU *pc_new_cpu(const char *cpu_model)
{
X86CPU *cpu;
CPUX86State *env;
cpu = cpu_x86_init(cpu_model);
if (cpu == NULL) {
fprintf(stderr, "Unable to find x86 CPU definition\n");
exit(1);
}
env = &cpu->env;
if ((env->cpuid_features & CPUID_APIC) || smp_cpus > 1) {
env->apic_state = apic_init(env, env->cpuid_apic_id);
}
cpu_reset(CPU(cpu));
return cpu;
}
void pc_cpus_init(const char *cpu_model)
{
int i;
@ -918,8 +869,11 @@ void pc_cpus_init(const char *cpu_model)
#endif
}
for(i = 0; i < smp_cpus; i++) {
pc_new_cpu(cpu_model);
for (i = 0; i < smp_cpus; i++) {
if (!cpu_x86_init(cpu_model)) {
fprintf(stderr, "Unable to find x86 CPU definition\n");
exit(1);
}
}
}

View File

@ -178,7 +178,7 @@ static void pc_init1(MemoryRegion *system_memory,
fw_cfg = pc_memory_init(system_memory,
kernel_filename, kernel_cmdline, initrd_filename,
below_4g_mem_size, above_4g_mem_size,
pci_enabled ? rom_memory : system_memory, &ram_memory);
rom_memory, &ram_memory);
}
gsi_state = g_malloc0(sizeof(*gsi_state));

View File

@ -42,6 +42,7 @@
#include "qemu-timer.h"
#include "exec-memory.h"
#include "host-utils.h"
#include "sysbus.h"
#define PFLASH_BUG(fmt, ...) \
do { \
@ -60,23 +61,28 @@ do { \
#endif
struct pflash_t {
SysBusDevice busdev;
BlockDriverState *bs;
hwaddr base;
hwaddr sector_len;
hwaddr total_len;
int width;
uint32_t nb_blocs;
uint64_t sector_len;
uint8_t width;
uint8_t be;
int wcycle; /* if 0, the flash is read normally */
int bypass;
int ro;
uint8_t cmd;
uint8_t status;
uint16_t ident[4];
uint16_t ident0;
uint16_t ident1;
uint16_t ident2;
uint16_t ident3;
uint8_t cfi_len;
uint8_t cfi_table[0x52];
hwaddr counter;
unsigned int writeblock_size;
QEMUTimer *timer;
MemoryRegion mem;
char *name;
void *storage;
};
@ -168,15 +174,16 @@ static uint32_t pflash_read (pflash_t *pfl, hwaddr offset,
case 0x90:
switch (boff) {
case 0:
ret = pfl->ident[0] << 8 | pfl->ident[1];
ret = pfl->ident0 << 8 | pfl->ident1;
DPRINTF("%s: Manufacturer Code %04x\n", __func__, ret);
break;
case 1:
ret = pfl->ident[2] << 8 | pfl->ident[3];
ret = pfl->ident2 << 8 | pfl->ident3;
DPRINTF("%s: Device ID Code %04x\n", __func__, ret);
break;
default:
DPRINTF("%s: Read Device Information boff=%x\n", __func__, boff);
DPRINTF("%s: Read Device Information boff=%x\n", __func__,
(unsigned)boff);
ret = 0;
break;
}
@ -279,9 +286,8 @@ static void pflash_write(pflash_t *pfl, hwaddr offset,
p = pfl->storage;
offset &= ~(pfl->sector_len - 1);
DPRINTF("%s: block erase at " TARGET_FMT_plx " bytes "
TARGET_FMT_plx "\n",
__func__, offset, pfl->sector_len);
DPRINTF("%s: block erase at " TARGET_FMT_plx " bytes %x\n",
__func__, offset, (unsigned)pfl->sector_len);
if (!pfl->ro) {
memset(p + offset, 0xff, pfl->sector_len);
@ -543,19 +549,13 @@ static const MemoryRegionOps pflash_cfi01_ops_le = {
.endianness = DEVICE_NATIVE_ENDIAN,
};
pflash_t *pflash_cfi01_register(hwaddr base,
DeviceState *qdev, const char *name,
hwaddr size,
BlockDriverState *bs, uint32_t sector_len,
int nb_blocs, int width,
uint16_t id0, uint16_t id1,
uint16_t id2, uint16_t id3, int be)
static int pflash_cfi01_init(SysBusDevice *dev)
{
pflash_t *pfl;
hwaddr total_len;
pflash_t *pfl = FROM_SYSBUS(typeof(*pfl), dev);
uint64_t total_len;
int ret;
total_len = sector_len * nb_blocs;
total_len = pfl->sector_len * pfl->nb_blocs;
/* XXX: to be fixed */
#if 0
@ -564,27 +564,22 @@ pflash_t *pflash_cfi01_register(hwaddr base,
return NULL;
#endif
pfl = g_malloc0(sizeof(pflash_t));
memory_region_init_rom_device(
&pfl->mem, be ? &pflash_cfi01_ops_be : &pflash_cfi01_ops_le, pfl,
name, size);
vmstate_register_ram(&pfl->mem, qdev);
&pfl->mem, pfl->be ? &pflash_cfi01_ops_be : &pflash_cfi01_ops_le, pfl,
pfl->name, total_len);
vmstate_register_ram(&pfl->mem, DEVICE(pfl));
pfl->storage = memory_region_get_ram_ptr(&pfl->mem);
memory_region_add_subregion(get_system_memory(), base, &pfl->mem);
sysbus_init_mmio(dev, &pfl->mem);
pfl->bs = bs;
if (pfl->bs) {
/* read the initial flash content */
ret = bdrv_read(pfl->bs, 0, pfl->storage, total_len >> 9);
if (ret < 0) {
memory_region_del_subregion(get_system_memory(), &pfl->mem);
vmstate_unregister_ram(&pfl->mem, qdev);
vmstate_unregister_ram(&pfl->mem, DEVICE(pfl));
memory_region_destroy(&pfl->mem);
g_free(pfl);
return NULL;
return 1;
}
bdrv_attach_dev_nofail(pfl->bs, pfl);
}
if (pfl->bs) {
@ -594,17 +589,9 @@ pflash_t *pflash_cfi01_register(hwaddr base,
}
pfl->timer = qemu_new_timer_ns(vm_clock, pflash_timer, pfl);
pfl->base = base;
pfl->sector_len = sector_len;
pfl->total_len = total_len;
pfl->width = width;
pfl->wcycle = 0;
pfl->cmd = 0;
pfl->status = 0;
pfl->ident[0] = id0;
pfl->ident[1] = id1;
pfl->ident[2] = id2;
pfl->ident[3] = id3;
/* Hardcoded CFI table */
pfl->cfi_len = 0x52;
/* Standard "QRY" string */
@ -653,7 +640,7 @@ pflash_t *pflash_cfi01_register(hwaddr base,
pfl->cfi_table[0x28] = 0x02;
pfl->cfi_table[0x29] = 0x00;
/* Max number of bytes in multi-bytes write */
if (width == 1) {
if (pfl->width == 1) {
pfl->cfi_table[0x2A] = 0x08;
} else {
pfl->cfi_table[0x2A] = 0x0B;
@ -664,10 +651,10 @@ pflash_t *pflash_cfi01_register(hwaddr base,
/* Number of erase block regions (uniform) */
pfl->cfi_table[0x2C] = 0x01;
/* Erase block region 1 */
pfl->cfi_table[0x2D] = nb_blocs - 1;
pfl->cfi_table[0x2E] = (nb_blocs - 1) >> 8;
pfl->cfi_table[0x2F] = sector_len >> 8;
pfl->cfi_table[0x30] = sector_len >> 16;
pfl->cfi_table[0x2D] = pfl->nb_blocs - 1;
pfl->cfi_table[0x2E] = (pfl->nb_blocs - 1) >> 8;
pfl->cfi_table[0x2F] = pfl->sector_len >> 8;
pfl->cfi_table[0x30] = pfl->sector_len >> 16;
/* Extended */
pfl->cfi_table[0x31] = 'P';
@ -689,6 +676,75 @@ pflash_t *pflash_cfi01_register(hwaddr base,
pfl->cfi_table[0x3f] = 0x01; /* Number of protection fields */
return 0;
}
static Property pflash_cfi01_properties[] = {
DEFINE_PROP_DRIVE("drive", struct pflash_t, bs),
DEFINE_PROP_UINT32("num-blocks", struct pflash_t, nb_blocs, 0),
DEFINE_PROP_UINT64("sector-length", struct pflash_t, sector_len, 0),
DEFINE_PROP_UINT8("width", struct pflash_t, width, 0),
DEFINE_PROP_UINT8("big-endian", struct pflash_t, be, 0),
DEFINE_PROP_UINT16("id0", struct pflash_t, ident0, 0),
DEFINE_PROP_UINT16("id1", struct pflash_t, ident1, 0),
DEFINE_PROP_UINT16("id2", struct pflash_t, ident2, 0),
DEFINE_PROP_UINT16("id3", struct pflash_t, ident3, 0),
DEFINE_PROP_STRING("name", struct pflash_t, name),
DEFINE_PROP_END_OF_LIST(),
};
static void pflash_cfi01_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
k->init = pflash_cfi01_init;
dc->props = pflash_cfi01_properties;
}
static const TypeInfo pflash_cfi01_info = {
.name = "cfi.pflash01",
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(struct pflash_t),
.class_init = pflash_cfi01_class_init,
};
static void pflash_cfi01_register_types(void)
{
type_register_static(&pflash_cfi01_info);
}
type_init(pflash_cfi01_register_types)
pflash_t *pflash_cfi01_register(hwaddr base,
DeviceState *qdev, const char *name,
hwaddr size,
BlockDriverState *bs,
uint32_t sector_len, int nb_blocs, int width,
uint16_t id0, uint16_t id1,
uint16_t id2, uint16_t id3, int be)
{
DeviceState *dev = qdev_create(NULL, "cfi.pflash01");
SysBusDevice *busdev = sysbus_from_qdev(dev);
pflash_t *pfl = (pflash_t *)object_dynamic_cast(OBJECT(dev),
"cfi.pflash01");
if (bs && qdev_prop_set_drive(dev, "drive", bs)) {
abort();
}
qdev_prop_set_uint32(dev, "num-blocks", nb_blocs);
qdev_prop_set_uint64(dev, "sector-length", sector_len);
qdev_prop_set_uint8(dev, "width", width);
qdev_prop_set_uint8(dev, "big-endian", !!be);
qdev_prop_set_uint16(dev, "id0", id0);
qdev_prop_set_uint16(dev, "id1", id1);
qdev_prop_set_uint16(dev, "id2", id2);
qdev_prop_set_uint16(dev, "id3", id3);
qdev_prop_set_string(dev, "name", name);
qdev_init_nofail(dev);
sysbus_mmio_map(busdev, 0, base);
return pfl;
}

View File

@ -41,6 +41,7 @@
#include "block.h"
#include "exec-memory.h"
#include "host-utils.h"
#include "sysbus.h"
//#define PFLASH_DEBUG
#ifdef PFLASH_DEBUG
@ -55,19 +56,26 @@ do { \
#define PFLASH_LAZY_ROMD_THRESHOLD 42
struct pflash_t {
SysBusDevice busdev;
BlockDriverState *bs;
hwaddr base;
uint32_t sector_len;
uint32_t nb_blocs;
uint32_t chip_len;
int mappings;
int width;
uint8_t mappings;
uint8_t width;
uint8_t be;
int wcycle; /* if 0, the flash is read normally */
int bypass;
int ro;
uint8_t cmd;
uint8_t status;
uint16_t ident[4];
uint16_t unlock_addr[2];
/* FIXME: implement array device properties */
uint16_t ident0;
uint16_t ident1;
uint16_t ident2;
uint16_t ident3;
uint16_t unlock_addr0;
uint16_t unlock_addr1;
uint8_t cfi_len;
uint8_t cfi_table[0x52];
QEMUTimer *timer;
@ -80,6 +88,7 @@ struct pflash_t {
MemoryRegion orig_mem;
int rom_mode;
int read_counter; /* used for lazy switch-back to rom mode */
char *name;
void *storage;
};
@ -190,16 +199,17 @@ static uint32_t pflash_read (pflash_t *pfl, hwaddr offset,
switch (boff) {
case 0x00:
case 0x01:
ret = pfl->ident[boff & 0x01];
ret = boff & 0x01 ? pfl->ident1 : pfl->ident0;
break;
case 0x02:
ret = 0x00; /* Pretend all sectors are unprotected */
break;
case 0x0E:
case 0x0F:
if (pfl->ident[2 + (boff & 0x01)] == (uint8_t)-1)
ret = boff & 0x01 ? pfl->ident3 : pfl->ident2;
if (ret == (uint8_t)-1) {
goto flash_read;
ret = pfl->ident[2 + (boff & 0x01)];
}
break;
default:
goto flash_read;
@ -283,9 +293,9 @@ static void pflash_write (pflash_t *pfl, hwaddr offset,
pfl->cmd = 0x98;
return;
}
if (boff != pfl->unlock_addr[0] || cmd != 0xAA) {
if (boff != pfl->unlock_addr0 || cmd != 0xAA) {
DPRINTF("%s: unlock0 failed " TARGET_FMT_plx " %02x %04x\n",
__func__, boff, cmd, pfl->unlock_addr[0]);
__func__, boff, cmd, pfl->unlock_addr0);
goto reset_flash;
}
DPRINTF("%s: unlock sequence started\n", __func__);
@ -293,7 +303,7 @@ static void pflash_write (pflash_t *pfl, hwaddr offset,
case 1:
/* We started an unlock sequence */
check_unlock1:
if (boff != pfl->unlock_addr[1] || cmd != 0x55) {
if (boff != pfl->unlock_addr1 || cmd != 0x55) {
DPRINTF("%s: unlock1 failed " TARGET_FMT_plx " %02x\n", __func__,
boff, cmd);
goto reset_flash;
@ -302,7 +312,7 @@ static void pflash_write (pflash_t *pfl, hwaddr offset,
break;
case 2:
/* We finished an unlock sequence */
if (!pfl->bypass && boff != pfl->unlock_addr[0]) {
if (!pfl->bypass && boff != pfl->unlock_addr0) {
DPRINTF("%s: command failed " TARGET_FMT_plx " %02x\n", __func__,
boff, cmd);
goto reset_flash;
@ -400,7 +410,7 @@ static void pflash_write (pflash_t *pfl, hwaddr offset,
case 5:
switch (cmd) {
case 0x10:
if (boff != pfl->unlock_addr[0]) {
if (boff != pfl->unlock_addr0) {
DPRINTF("%s: chip erase: invalid address " TARGET_FMT_plx "\n",
__func__, offset);
goto reset_flash;
@ -575,50 +585,38 @@ static const MemoryRegionOps pflash_cfi02_ops_le = {
.endianness = DEVICE_NATIVE_ENDIAN,
};
pflash_t *pflash_cfi02_register(hwaddr base,
DeviceState *qdev, const char *name,
hwaddr size,
BlockDriverState *bs, uint32_t sector_len,
int nb_blocs, int nb_mappings, int width,
uint16_t id0, uint16_t id1,
uint16_t id2, uint16_t id3,
uint16_t unlock_addr0, uint16_t unlock_addr1,
int be)
static int pflash_cfi02_init(SysBusDevice *dev)
{
pflash_t *pfl;
int32_t chip_len;
pflash_t *pfl = FROM_SYSBUS(typeof(*pfl), dev);
uint32_t chip_len;
int ret;
chip_len = sector_len * nb_blocs;
chip_len = pfl->sector_len * pfl->nb_blocs;
/* XXX: to be fixed */
#if 0
if (total_len != (8 * 1024 * 1024) && total_len != (16 * 1024 * 1024) &&
total_len != (32 * 1024 * 1024) && total_len != (64 * 1024 * 1024))
return NULL;
#endif
pfl = g_malloc0(sizeof(pflash_t));
memory_region_init_rom_device(
&pfl->orig_mem, be ? &pflash_cfi02_ops_be : &pflash_cfi02_ops_le, pfl,
name, size);
vmstate_register_ram(&pfl->orig_mem, qdev);
memory_region_init_rom_device(&pfl->orig_mem, pfl->be ?
&pflash_cfi02_ops_be : &pflash_cfi02_ops_le,
pfl, pfl->name, chip_len);
vmstate_register_ram(&pfl->orig_mem, DEVICE(pfl));
pfl->storage = memory_region_get_ram_ptr(&pfl->orig_mem);
pfl->base = base;
pfl->chip_len = chip_len;
pfl->mappings = nb_mappings;
pfl->bs = bs;
if (pfl->bs) {
/* read the initial flash content */
ret = bdrv_read(pfl->bs, 0, pfl->storage, chip_len >> 9);
if (ret < 0) {
g_free(pfl);
return NULL;
return 1;
}
bdrv_attach_dev_nofail(pfl->bs, pfl);
}
pflash_setup_mappings(pfl);
pfl->rom_mode = 1;
memory_region_add_subregion(get_system_memory(), pfl->base, &pfl->mem);
sysbus_init_mmio(dev, &pfl->mem);
if (pfl->bs) {
pfl->ro = bdrv_is_read_only(pfl->bs);
@ -627,17 +625,9 @@ pflash_t *pflash_cfi02_register(hwaddr base,
}
pfl->timer = qemu_new_timer_ns(vm_clock, pflash_timer, pfl);
pfl->sector_len = sector_len;
pfl->width = width;
pfl->wcycle = 0;
pfl->cmd = 0;
pfl->status = 0;
pfl->ident[0] = id0;
pfl->ident[1] = id1;
pfl->ident[2] = id2;
pfl->ident[3] = id3;
pfl->unlock_addr[0] = unlock_addr0;
pfl->unlock_addr[1] = unlock_addr1;
/* Hardcoded CFI table (mostly from SG29 Spansion flash) */
pfl->cfi_len = 0x52;
/* Standard "QRY" string */
@ -693,10 +683,10 @@ pflash_t *pflash_cfi02_register(hwaddr base,
/* Number of erase block regions (uniform) */
pfl->cfi_table[0x2C] = 0x01;
/* Erase block region 1 */
pfl->cfi_table[0x2D] = nb_blocs - 1;
pfl->cfi_table[0x2E] = (nb_blocs - 1) >> 8;
pfl->cfi_table[0x2F] = sector_len >> 8;
pfl->cfi_table[0x30] = sector_len >> 16;
pfl->cfi_table[0x2D] = pfl->nb_blocs - 1;
pfl->cfi_table[0x2E] = (pfl->nb_blocs - 1) >> 8;
pfl->cfi_table[0x2F] = pfl->sector_len >> 8;
pfl->cfi_table[0x30] = pfl->sector_len >> 16;
/* Extended */
pfl->cfi_table[0x31] = 'P';
@ -716,5 +706,81 @@ pflash_t *pflash_cfi02_register(hwaddr base,
pfl->cfi_table[0x3b] = 0x00;
pfl->cfi_table[0x3c] = 0x00;
return 0;
}
static Property pflash_cfi02_properties[] = {
DEFINE_PROP_DRIVE("drive", struct pflash_t, bs),
DEFINE_PROP_UINT32("num-blocks", struct pflash_t, nb_blocs, 0),
DEFINE_PROP_UINT32("sector-length", struct pflash_t, sector_len, 0),
DEFINE_PROP_UINT8("width", struct pflash_t, width, 0),
DEFINE_PROP_UINT8("mappings", struct pflash_t, mappings, 0),
DEFINE_PROP_UINT8("big-endian", struct pflash_t, be, 0),
DEFINE_PROP_UINT16("id0", struct pflash_t, ident0, 0),
DEFINE_PROP_UINT16("id1", struct pflash_t, ident1, 0),
DEFINE_PROP_UINT16("id2", struct pflash_t, ident2, 0),
DEFINE_PROP_UINT16("id3", struct pflash_t, ident3, 0),
DEFINE_PROP_UINT16("unlock-addr0", struct pflash_t, unlock_addr0, 0),
DEFINE_PROP_UINT16("unlock-addr1", struct pflash_t, unlock_addr1, 0),
DEFINE_PROP_STRING("name", struct pflash_t, name),
DEFINE_PROP_END_OF_LIST(),
};
static void pflash_cfi02_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
k->init = pflash_cfi02_init;
dc->props = pflash_cfi02_properties;
}
static const TypeInfo pflash_cfi02_info = {
.name = "cfi.pflash02",
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(struct pflash_t),
.class_init = pflash_cfi02_class_init,
};
static void pflash_cfi02_register_types(void)
{
type_register_static(&pflash_cfi02_info);
}
type_init(pflash_cfi02_register_types)
pflash_t *pflash_cfi02_register(hwaddr base,
DeviceState *qdev, const char *name,
hwaddr size,
BlockDriverState *bs, uint32_t sector_len,
int nb_blocs, int nb_mappings, int width,
uint16_t id0, uint16_t id1,
uint16_t id2, uint16_t id3,
uint16_t unlock_addr0, uint16_t unlock_addr1,
int be)
{
DeviceState *dev = qdev_create(NULL, "cfi.pflash02");
SysBusDevice *busdev = sysbus_from_qdev(dev);
pflash_t *pfl = (pflash_t *)object_dynamic_cast(OBJECT(dev),
"cfi.pflash02");
if (bs && qdev_prop_set_drive(dev, "drive", bs)) {
abort();
}
qdev_prop_set_uint32(dev, "num-blocks", nb_blocs);
qdev_prop_set_uint32(dev, "sector-length", sector_len);
qdev_prop_set_uint8(dev, "width", width);
qdev_prop_set_uint8(dev, "mappings", nb_mappings);
qdev_prop_set_uint8(dev, "big-endian", !!be);
qdev_prop_set_uint16(dev, "id0", id0);
qdev_prop_set_uint16(dev, "id1", id1);
qdev_prop_set_uint16(dev, "id2", id2);
qdev_prop_set_uint16(dev, "id3", id3);
qdev_prop_set_uint16(dev, "unlock-addr0", unlock_addr0);
qdev_prop_set_uint16(dev, "unlock-addr1", unlock_addr1);
qdev_prop_set_string(dev, "name", name);
qdev_init_nofail(dev);
sysbus_mmio_map(busdev, 0, base);
return pfl;
}

View File

@ -95,7 +95,8 @@ static uint64_t pl050_read(void *opaque, hwaddr offset,
case 4: /* KMIIR */
return s->pending | 2;
default:
hw_error("pl050_read: Bad offset %x\n", (int)offset);
qemu_log_mask(LOG_GUEST_ERROR,
"pl050_read: Bad offset %x\n", (int)offset);
return 0;
}
}
@ -123,7 +124,8 @@ static void pl050_write(void *opaque, hwaddr offset,
s->clk = value;
return;
default:
hw_error("pl050_write: Bad offset %x\n", (int)offset);
qemu_log_mask(LOG_GUEST_ERROR,
"pl050_write: Bad offset %x\n", (int)offset);
}
}
static const MemoryRegionOps pl050_ops = {

View File

@ -164,7 +164,8 @@ static uint64_t pl061_read(void *opaque, hwaddr offset,
case 0x528: /* Analog mode select */
return s->amsel;
default:
hw_error("pl061_read: Bad offset %x\n", (int)offset);
qemu_log_mask(LOG_GUEST_ERROR,
"pl061_read: Bad offset %x\n", (int)offset);
return 0;
}
}
@ -239,7 +240,8 @@ static void pl061_write(void *opaque, hwaddr offset,
s->amsel = value & 0xff;
break;
default:
hw_error("pl061_write: Bad offset %x\n", (int)offset);
qemu_log_mask(LOG_GUEST_ERROR,
"pl061_write: Bad offset %x\n", (int)offset);
}
pl061_update(s);
}

View File

@ -281,7 +281,8 @@ static uint64_t pl080_read(void *opaque, hwaddr offset,
return s->sync;
default:
bad_offset:
hw_error("pl080_read: Bad offset %x\n", (int)offset);
qemu_log_mask(LOG_GUEST_ERROR,
"pl080_read: Bad offset %x\n", (int)offset);
return 0;
}
}
@ -327,12 +328,13 @@ static void pl080_write(void *opaque, hwaddr offset,
case 10: /* SoftLBReq */
case 11: /* SoftLSReq */
/* ??? Implement these. */
hw_error("pl080_write: Soft DMA not implemented\n");
qemu_log_mask(LOG_UNIMP, "pl080_write: Soft DMA not implemented\n");
break;
case 12: /* Configuration */
s->conf = value;
if (s->conf & (PL080_CONF_M1 | PL080_CONF_M1)) {
hw_error("pl080_write: Big-endian DMA not implemented\n");
qemu_log_mask(LOG_UNIMP,
"pl080_write: Big-endian DMA not implemented\n");
}
pl080_run(s);
break;
@ -341,7 +343,8 @@ static void pl080_write(void *opaque, hwaddr offset,
break;
default:
bad_offset:
hw_error("pl080_write: Bad offset %x\n", (int)offset);
qemu_log_mask(LOG_GUEST_ERROR,
"pl080_write: Bad offset %x\n", (int)offset);
}
pl080_update(s);
}

View File

@ -239,7 +239,7 @@ static void pl110_update_display(void *opaque)
fn, s->palette,
&first, &last);
if (first >= 0) {
dpy_update(s->ds, 0, first, s->cols, last - first + 1);
dpy_gfx_update(s->ds, 0, first, s->cols, last - first + 1);
}
s->invalidate = 0;
}
@ -349,7 +349,8 @@ static uint64_t pl110_read(void *opaque, hwaddr offset,
case 12: /* LCDLPCURR */
return s->lpbase;
default:
hw_error("pl110_read: Bad offset %x\n", (int)offset);
qemu_log_mask(LOG_GUEST_ERROR,
"pl110_read: Bad offset %x\n", (int)offset);
return 0;
}
}
@ -417,7 +418,8 @@ static void pl110_write(void *opaque, hwaddr offset,
pl110_update(s);
break;
default:
hw_error("pl110_write: Bad offset %x\n", (int)offset);
qemu_log_mask(LOG_GUEST_ERROR,
"pl110_write: Bad offset %x\n", (int)offset);
}
}

View File

@ -199,7 +199,7 @@ static void pl190_write(void *opaque, hwaddr offset,
break;
case 0xc0: /* ITCR */
if (val) {
hw_error("pl190: Test mode not implemented\n");
qemu_log_mask(LOG_UNIMP, "pl190: Test mode not implemented\n");
}
break;
default:

View File

@ -75,9 +75,10 @@ void ppc_set_irq(CPUPPCState *env, int n_IRQ, int level)
}
/* PowerPC 6xx / 7xx internal IRQ controller */
static void ppc6xx_set_irq (void *opaque, int pin, int level)
static void ppc6xx_set_irq(void *opaque, int pin, int level)
{
CPUPPCState *env = opaque;
PowerPCCPU *cpu = opaque;
CPUPPCState *env = &cpu->env;
int cur_level;
LOG_IRQ("%s: env %p pin %d level %d\n", __func__,
@ -151,17 +152,20 @@ static void ppc6xx_set_irq (void *opaque, int pin, int level)
}
}
void ppc6xx_irq_init (CPUPPCState *env)
void ppc6xx_irq_init(CPUPPCState *env)
{
env->irq_inputs = (void **)qemu_allocate_irqs(&ppc6xx_set_irq, env,
PowerPCCPU *cpu = ppc_env_get_cpu(env);
env->irq_inputs = (void **)qemu_allocate_irqs(&ppc6xx_set_irq, cpu,
PPC6xx_INPUT_NB);
}
#if defined(TARGET_PPC64)
/* PowerPC 970 internal IRQ controller */
static void ppc970_set_irq (void *opaque, int pin, int level)
static void ppc970_set_irq(void *opaque, int pin, int level)
{
CPUPPCState *env = opaque;
PowerPCCPU *cpu = opaque;
CPUPPCState *env = &cpu->env;
int cur_level;
LOG_IRQ("%s: env %p pin %d level %d\n", __func__,
@ -202,7 +206,7 @@ static void ppc970_set_irq (void *opaque, int pin, int level)
} else {
LOG_IRQ("%s: restart the CPU\n", __func__);
env->halted = 0;
qemu_cpu_kick(env);
qemu_cpu_kick(CPU(cpu));
}
break;
case PPC970_INPUT_HRESET:
@ -233,16 +237,19 @@ static void ppc970_set_irq (void *opaque, int pin, int level)
}
}
void ppc970_irq_init (CPUPPCState *env)
void ppc970_irq_init(CPUPPCState *env)
{
env->irq_inputs = (void **)qemu_allocate_irqs(&ppc970_set_irq, env,
PowerPCCPU *cpu = ppc_env_get_cpu(env);
env->irq_inputs = (void **)qemu_allocate_irqs(&ppc970_set_irq, cpu,
PPC970_INPUT_NB);
}
/* POWER7 internal IRQ controller */
static void power7_set_irq (void *opaque, int pin, int level)
static void power7_set_irq(void *opaque, int pin, int level)
{
CPUPPCState *env = opaque;
PowerPCCPU *cpu = opaque;
CPUPPCState *env = &cpu->env;
LOG_IRQ("%s: env %p pin %d level %d\n", __func__,
env, pin, level);
@ -266,17 +273,20 @@ static void power7_set_irq (void *opaque, int pin, int level)
}
}
void ppcPOWER7_irq_init (CPUPPCState *env)
void ppcPOWER7_irq_init(CPUPPCState *env)
{
env->irq_inputs = (void **)qemu_allocate_irqs(&power7_set_irq, env,
PowerPCCPU *cpu = ppc_env_get_cpu(env);
env->irq_inputs = (void **)qemu_allocate_irqs(&power7_set_irq, cpu,
POWER7_INPUT_NB);
}
#endif /* defined(TARGET_PPC64) */
/* PowerPC 40x internal IRQ controller */
static void ppc40x_set_irq (void *opaque, int pin, int level)
static void ppc40x_set_irq(void *opaque, int pin, int level)
{
CPUPPCState *env = opaque;
PowerPCCPU *cpu = opaque;
CPUPPCState *env = &cpu->env;
int cur_level;
LOG_IRQ("%s: env %p pin %d level %d\n", __func__,
@ -325,7 +335,7 @@ static void ppc40x_set_irq (void *opaque, int pin, int level)
} else {
LOG_IRQ("%s: restart the CPU\n", __func__);
env->halted = 0;
qemu_cpu_kick(env);
qemu_cpu_kick(CPU(cpu));
}
break;
case PPC40x_INPUT_DEBUG:
@ -346,16 +356,19 @@ static void ppc40x_set_irq (void *opaque, int pin, int level)
}
}
void ppc40x_irq_init (CPUPPCState *env)
void ppc40x_irq_init(CPUPPCState *env)
{
PowerPCCPU *cpu = ppc_env_get_cpu(env);
env->irq_inputs = (void **)qemu_allocate_irqs(&ppc40x_set_irq,
env, PPC40x_INPUT_NB);
cpu, PPC40x_INPUT_NB);
}
/* PowerPC E500 internal IRQ controller */
static void ppce500_set_irq (void *opaque, int pin, int level)
static void ppce500_set_irq(void *opaque, int pin, int level)
{
CPUPPCState *env = opaque;
PowerPCCPU *cpu = opaque;
CPUPPCState *env = &cpu->env;
int cur_level;
LOG_IRQ("%s: env %p pin %d level %d\n", __func__,
@ -407,10 +420,12 @@ static void ppce500_set_irq (void *opaque, int pin, int level)
}
}
void ppce500_irq_init (CPUPPCState *env)
void ppce500_irq_init(CPUPPCState *env)
{
PowerPCCPU *cpu = ppc_env_get_cpu(env);
env->irq_inputs = (void **)qemu_allocate_irqs(&ppce500_set_irq,
env, PPCE500_INPUT_NB);
cpu, PPCE500_INPUT_NB);
}
/*****************************************************************************/
/* PowerPC time base and decrementer emulation */
@ -721,7 +736,7 @@ static void cpu_ppc_hdecr_cb (void *opaque)
_cpu_ppc_store_hdecr(opaque, 0x00000000, 0xFFFFFFFF, 1);
}
void cpu_ppc_store_purr (CPUPPCState *env, uint64_t value)
static void cpu_ppc_store_purr(CPUPPCState *env, uint64_t value)
{
ppc_tb_t *tb_env = env->tb_env;
@ -1152,23 +1167,23 @@ static inline void nvram_write (nvram_t *nvram, uint32_t addr, uint32_t val)
(*nvram->write_fn)(nvram->opaque, addr, val);
}
void NVRAM_set_byte (nvram_t *nvram, uint32_t addr, uint8_t value)
static void NVRAM_set_byte(nvram_t *nvram, uint32_t addr, uint8_t value)
{
nvram_write(nvram, addr, value);
}
uint8_t NVRAM_get_byte (nvram_t *nvram, uint32_t addr)
static uint8_t NVRAM_get_byte(nvram_t *nvram, uint32_t addr)
{
return nvram_read(nvram, addr);
}
void NVRAM_set_word (nvram_t *nvram, uint32_t addr, uint16_t value)
static void NVRAM_set_word(nvram_t *nvram, uint32_t addr, uint16_t value)
{
nvram_write(nvram, addr, value >> 8);
nvram_write(nvram, addr + 1, value & 0xFF);
}
uint16_t NVRAM_get_word (nvram_t *nvram, uint32_t addr)
static uint16_t NVRAM_get_word(nvram_t *nvram, uint32_t addr)
{
uint16_t tmp;
@ -1178,7 +1193,7 @@ uint16_t NVRAM_get_word (nvram_t *nvram, uint32_t addr)
return tmp;
}
void NVRAM_set_lword (nvram_t *nvram, uint32_t addr, uint32_t value)
static void NVRAM_set_lword(nvram_t *nvram, uint32_t addr, uint32_t value)
{
nvram_write(nvram, addr, value >> 24);
nvram_write(nvram, addr + 1, (value >> 16) & 0xFF);
@ -1198,8 +1213,8 @@ uint32_t NVRAM_get_lword (nvram_t *nvram, uint32_t addr)
return tmp;
}
void NVRAM_set_string (nvram_t *nvram, uint32_t addr,
const char *str, uint32_t max)
static void NVRAM_set_string(nvram_t *nvram, uint32_t addr, const char *str,
uint32_t max)
{
int i;

View File

@ -49,7 +49,7 @@ typedef struct spin_state {
} SpinState;
typedef struct spin_kick {
CPUPPCState *env;
PowerPCCPU *cpu;
SpinInfo *spin;
} SpinKick;
@ -92,7 +92,8 @@ static void mmubooke_create_initial_mapping(CPUPPCState *env,
static void spin_kick(void *data)
{
SpinKick *kick = data;
CPUPPCState *env = kick->env;
CPUState *cpu = CPU(kick->cpu);
CPUPPCState *env = &kick->cpu->env;
SpinInfo *curspin = kick->spin;
hwaddr map_size = 64 * 1024 * 1024;
hwaddr map_start;
@ -113,8 +114,8 @@ static void spin_kick(void *data)
env->halted = 0;
env->exception_index = -1;
env->stopped = 0;
qemu_cpu_kick(env);
cpu->stopped = false;
qemu_cpu_kick(cpu);
}
static void spin_write(void *opaque, hwaddr addr, uint64_t value,
@ -158,11 +159,11 @@ static void spin_write(void *opaque, hwaddr addr, uint64_t value,
if (!(ldq_p(&curspin->addr) & 1)) {
/* run CPU */
SpinKick kick = {
.env = env,
.cpu = ppc_env_get_cpu(env),
.spin = curspin,
};
run_on_cpu(env, spin_kick, &kick);
run_on_cpu(CPU(kick.cpu), spin_kick, &kick);
}
}

View File

@ -871,20 +871,20 @@ static void pxa2xx_update_display(void *opaque)
if (miny >= 0) {
switch (s->orientation) {
case 0:
dpy_update(s->ds, 0, miny, s->xres, maxy - miny + 1);
dpy_gfx_update(s->ds, 0, miny, s->xres, maxy - miny + 1);
break;
case 90:
dpy_update(s->ds, miny, 0, maxy - miny + 1, s->xres);
dpy_gfx_update(s->ds, miny, 0, maxy - miny + 1, s->xres);
break;
case 180:
maxy = s->yres - maxy - 1;
miny = s->yres - miny - 1;
dpy_update(s->ds, 0, maxy, s->xres, miny - maxy + 1);
dpy_gfx_update(s->ds, 0, maxy, s->xres, miny - maxy + 1);
break;
case 270:
maxy = s->yres - maxy - 1;
miny = s->yres - miny - 1;
dpy_update(s->ds, maxy, 0, miny - maxy + 1, s->xres);
dpy_gfx_update(s->ds, maxy, 0, miny - maxy + 1, s->xres);
break;
}
}

View File

@ -24,7 +24,7 @@
static void qxl_blit(PCIQXLDevice *qxl, QXLRect *rect)
{
uint8_t *src;
uint8_t *dst = qxl->vga.ds->surface->data;
uint8_t *dst = ds_get_data(qxl->vga.ds);
int len, i;
if (is_buffer_shared(qxl->vga.ds->surface)) {
@ -123,17 +123,17 @@ static void qxl_render_update_area_unlocked(PCIQXLDevice *qxl)
qxl->guest_primary.surface.width,
qxl->guest_primary.surface.height);
}
dpy_resize(vga->ds);
dpy_gfx_resize(vga->ds);
}
for (i = 0; i < qxl->num_dirty_rects; i++) {
if (qemu_spice_rect_is_empty(qxl->dirty+i)) {
break;
}
qxl_blit(qxl, qxl->dirty+i);
dpy_update(vga->ds,
qxl->dirty[i].left, qxl->dirty[i].top,
qxl->dirty[i].right - qxl->dirty[i].left,
qxl->dirty[i].bottom - qxl->dirty[i].top);
dpy_gfx_update(vga->ds,
qxl->dirty[i].left, qxl->dirty[i].top,
qxl->dirty[i].right - qxl->dirty[i].left,
qxl->dirty[i].bottom - qxl->dirty[i].top);
}
qxl->num_dirty_rects = 0;
}
@ -234,7 +234,7 @@ int qxl_render_cursor(PCIQXLDevice *qxl, QXLCommandExt *ext)
return 1;
}
if (!qxl->ssd.ds->mouse_set || !qxl->ssd.ds->cursor_define) {
if (!dpy_cursor_define_supported(qxl->ssd.ds)) {
return 0;
}

View File

@ -1864,8 +1864,8 @@ static void display_refresh(struct DisplayState *ds)
}
static DisplayChangeListener display_listener = {
.dpy_update = display_update,
.dpy_resize = display_resize,
.dpy_gfx_update = display_update,
.dpy_gfx_resize = display_resize,
.dpy_refresh = display_refresh,
};

View File

@ -44,11 +44,8 @@ static const int realview_board_id[] = {
0x76d
};
static void realview_init(ram_addr_t ram_size,
const char *boot_device,
const char *kernel_filename, const char *kernel_cmdline,
const char *initrd_filename, const char *cpu_model,
enum realview_board_type board_type)
static void realview_init(QEMUMachineInitArgs *args,
enum realview_board_type board_type)
{
ARMCPU *cpu = NULL;
CPUARMState *env;
@ -73,6 +70,7 @@ static void realview_init(ram_addr_t ram_size,
uint32_t proc_id = 0;
uint32_t sys_id;
ram_addr_t low_ram_size;
ram_addr_t ram_size = args->ram_size;
switch (board_type) {
case BOARD_EB:
@ -89,7 +87,7 @@ static void realview_init(ram_addr_t ram_size,
break;
}
for (n = 0; n < smp_cpus; n++) {
cpu = cpu_arm_init(cpu_model);
cpu = cpu_arm_init(args->cpu_model);
if (!cpu) {
fprintf(stderr, "Unable to find CPU definition\n");
exit(1);
@ -321,9 +319,9 @@ static void realview_init(ram_addr_t ram_size,
memory_region_add_subregion(sysmem, SMP_BOOT_ADDR, ram_hack);
realview_binfo.ram_size = ram_size;
realview_binfo.kernel_filename = kernel_filename;
realview_binfo.kernel_cmdline = kernel_cmdline;
realview_binfo.initrd_filename = initrd_filename;
realview_binfo.kernel_filename = args->kernel_filename;
realview_binfo.kernel_cmdline = args->kernel_cmdline;
realview_binfo.initrd_filename = args->initrd_filename;
realview_binfo.nb_cpus = smp_cpus;
realview_binfo.board_id = realview_board_id[board_type];
realview_binfo.loader_start = (board_type == BOARD_PB_A8 ? 0x70000000 : 0);
@ -332,62 +330,34 @@ static void realview_init(ram_addr_t ram_size,
static void realview_eb_init(QEMUMachineInitArgs *args)
{
ram_addr_t ram_size = args->ram_size;
const char *cpu_model = args->cpu_model;
const char *kernel_filename = args->kernel_filename;
const char *kernel_cmdline = args->kernel_cmdline;
const char *initrd_filename = args->initrd_filename;
const char *boot_device = args->boot_device;
if (!cpu_model) {
cpu_model = "arm926";
if (!args->cpu_model) {
args->cpu_model = "arm926";
}
realview_init(ram_size, boot_device, kernel_filename, kernel_cmdline,
initrd_filename, cpu_model, BOARD_EB);
realview_init(args, BOARD_EB);
}
static void realview_eb_mpcore_init(QEMUMachineInitArgs *args)
{
ram_addr_t ram_size = args->ram_size;
const char *cpu_model = args->cpu_model;
const char *kernel_filename = args->kernel_filename;
const char *kernel_cmdline = args->kernel_cmdline;
const char *initrd_filename = args->initrd_filename;
const char *boot_device = args->boot_device;
if (!cpu_model) {
cpu_model = "arm11mpcore";
if (!args->cpu_model) {
args->cpu_model = "arm11mpcore";
}
realview_init(ram_size, boot_device, kernel_filename, kernel_cmdline,
initrd_filename, cpu_model, BOARD_EB_MPCORE);
realview_init(args, BOARD_EB_MPCORE);
}
static void realview_pb_a8_init(QEMUMachineInitArgs *args)
{
ram_addr_t ram_size = args->ram_size;
const char *cpu_model = args->cpu_model;
const char *kernel_filename = args->kernel_filename;
const char *kernel_cmdline = args->kernel_cmdline;
const char *initrd_filename = args->initrd_filename;
const char *boot_device = args->boot_device;
if (!cpu_model) {
cpu_model = "cortex-a8";
if (!args->cpu_model) {
args->cpu_model = "cortex-a8";
}
realview_init(ram_size, boot_device, kernel_filename, kernel_cmdline,
initrd_filename, cpu_model, BOARD_PB_A8);
realview_init(args, BOARD_PB_A8);
}
static void realview_pbx_a9_init(QEMUMachineInitArgs *args)
{
ram_addr_t ram_size = args->ram_size;
const char *cpu_model = args->cpu_model;
const char *kernel_filename = args->kernel_filename;
const char *kernel_cmdline = args->kernel_cmdline;
const char *initrd_filename = args->initrd_filename;
const char *boot_device = args->boot_device;
if (!cpu_model) {
cpu_model = "cortex-a9";
if (!args->cpu_model) {
args->cpu_model = "cortex-a9";
}
realview_init(ram_size, boot_device, kernel_filename, kernel_cmdline,
initrd_filename, cpu_model, BOARD_PBX_A9);
realview_init(args, BOARD_PBX_A9);
}
static QEMUMachine realview_eb_machine = {

106
hw/sd.c
View File

@ -55,24 +55,28 @@ typedef enum {
sd_illegal = -2,
} sd_rsp_type_t;
enum SDCardModes {
sd_inactive,
sd_card_identification_mode,
sd_data_transfer_mode,
};
enum SDCardStates {
sd_inactive_state = -1,
sd_idle_state = 0,
sd_ready_state,
sd_identification_state,
sd_standby_state,
sd_transfer_state,
sd_sendingdata_state,
sd_receivingdata_state,
sd_programming_state,
sd_disconnect_state,
};
struct SDState {
enum {
sd_inactive,
sd_card_identification_mode,
sd_data_transfer_mode,
} mode;
enum {
sd_inactive_state = -1,
sd_idle_state = 0,
sd_ready_state,
sd_identification_state,
sd_standby_state,
sd_transfer_state,
sd_sendingdata_state,
sd_receivingdata_state,
sd_programming_state,
sd_disconnect_state,
} state;
uint32_t mode; /* current card mode, one of SDCardModes */
int32_t state; /* current card state, one of SDCardStates */
uint32_t ocr;
uint8_t scr[8];
uint8_t cid[16];
@ -83,21 +87,22 @@ struct SDState {
uint32_t vhs;
bool wp_switch;
unsigned long *wp_groups;
int32_t wpgrps_size;
uint64_t size;
int blk_len;
uint32_t blk_len;
uint32_t erase_start;
uint32_t erase_end;
uint8_t pwd[16];
int pwd_len;
int function_group[6];
uint32_t pwd_len;
uint8_t function_group[6];
bool spi;
int current_cmd;
uint8_t current_cmd;
/* True if we will handle the next command as an ACMD. Note that this does
* *not* track the APP_CMD status bit!
*/
bool expecting_acmd;
int blk_written;
uint32_t blk_written;
uint64_t data_start;
uint32_t data_offset;
uint8_t data[512];
@ -421,8 +426,9 @@ static void sd_reset(SDState *sd, BlockDriverState *bdrv)
if (sd->wp_groups)
g_free(sd->wp_groups);
sd->wp_switch = bdrv ? bdrv_is_read_only(bdrv) : false;
sd->wp_groups = bitmap_new(sect);
memset(sd->function_group, 0, sizeof(int) * 6);
sd->wpgrps_size = sect;
sd->wp_groups = bitmap_new(sd->wpgrps_size);
memset(sd->function_group, 0, sizeof(sd->function_group));
sd->erase_start = 0;
sd->erase_end = 0;
sd->size = size;
@ -446,6 +452,38 @@ static const BlockDevOps sd_block_ops = {
.change_media_cb = sd_cardchange,
};
static const VMStateDescription sd_vmstate = {
.name = "sd-card",
.version_id = 1,
.minimum_version_id = 1,
.fields = (VMStateField[]) {
VMSTATE_UINT32(mode, SDState),
VMSTATE_INT32(state, SDState),
VMSTATE_UINT8_ARRAY(cid, SDState, 16),
VMSTATE_UINT8_ARRAY(csd, SDState, 16),
VMSTATE_UINT16(rca, SDState),
VMSTATE_UINT32(card_status, SDState),
VMSTATE_PARTIAL_BUFFER(sd_status, SDState, 1),
VMSTATE_UINT32(vhs, SDState),
VMSTATE_BITMAP(wp_groups, SDState, 0, wpgrps_size),
VMSTATE_UINT32(blk_len, SDState),
VMSTATE_UINT32(erase_start, SDState),
VMSTATE_UINT32(erase_end, SDState),
VMSTATE_UINT8_ARRAY(pwd, SDState, 16),
VMSTATE_UINT32(pwd_len, SDState),
VMSTATE_UINT8_ARRAY(function_group, SDState, 6),
VMSTATE_UINT8(current_cmd, SDState),
VMSTATE_BOOL(expecting_acmd, SDState),
VMSTATE_UINT32(blk_written, SDState),
VMSTATE_UINT64(data_start, SDState),
VMSTATE_UINT32(data_offset, SDState),
VMSTATE_UINT8_ARRAY(data, SDState, 512),
VMSTATE_BUFFER_UNSAFE(buf, SDState, 1, 512),
VMSTATE_BOOL(enable, SDState),
VMSTATE_END_OF_LIST()
}
};
/* We do not model the chip select pin, so allow the board to select
whether card should be in SSI or MMC/SD mode. It is also up to the
board to ensure that ssi transfers only occur when the chip select
@ -463,6 +501,7 @@ SDState *sd_init(BlockDriverState *bs, bool is_spi)
bdrv_attach_dev_nofail(sd->bdrv, sd);
bdrv_set_dev_ops(sd->bdrv, &sd_block_ops, sd);
}
vmstate_register(NULL, -1, &sd_vmstate, sd);
return sd;
}
@ -476,19 +515,28 @@ void sd_set_cb(SDState *sd, qemu_irq readonly, qemu_irq insert)
static void sd_erase(SDState *sd)
{
int i, start, end;
int i;
uint64_t erase_start = sd->erase_start;
uint64_t erase_end = sd->erase_end;
if (!sd->erase_start || !sd->erase_end) {
sd->card_status |= ERASE_SEQ_ERROR;
return;
}
start = sd_addr_to_wpnum(sd->erase_start);
end = sd_addr_to_wpnum(sd->erase_end);
if (extract32(sd->ocr, OCR_CCS_BITN, 1)) {
/* High capacity memory card: erase units are 512 byte blocks */
erase_start *= 512;
erase_end *= 512;
}
erase_start = sd_addr_to_wpnum(erase_start);
erase_end = sd_addr_to_wpnum(erase_end);
sd->erase_start = 0;
sd->erase_end = 0;
sd->csd[14] |= 0x40;
for (i = start; i <= end; i++) {
for (i = erase_start; i <= erase_end; i++) {
if (test_bit(i, sd->wp_groups)) {
sd->card_status |= WP_ERASE_SKIP;
}
@ -567,7 +615,7 @@ static void sd_lock_command(SDState *sd)
sd->card_status |= LOCK_UNLOCK_FAILED;
return;
}
bitmap_zero(sd->wp_groups, sd_addr_to_wpnum(sd->size) + 1);
bitmap_zero(sd->wp_groups, sd->wpgrps_size);
sd->csd[14] &= ~0x10;
sd->card_status &= ~CARD_IS_LOCKED;
sd->pwd_len = 0;

View File

@ -50,6 +50,7 @@
#define READY_FOR_DATA (1 << 8)
#define APP_CMD (1 << 5)
#define AKE_SEQ_ERROR (1 << 3)
#define OCR_CCS_BITN 30
typedef enum {
sd_none = -1,

View File

@ -1351,7 +1351,7 @@ static void sm501_draw_crt(SM501State * s)
} else {
if (y_start >= 0) {
/* flush to display */
dpy_update(s->ds, 0, y_start, width, y - y_start);
dpy_gfx_update(s->ds, 0, y_start, width, y - y_start);
y_start = -1;
}
}
@ -1362,7 +1362,7 @@ static void sm501_draw_crt(SM501State * s)
/* complete flush to display */
if (y_start >= 0)
dpy_update(s->ds, 0, y_start, width, y - y_start);
dpy_gfx_update(s->ds, 0, y_start, width, y - y_start);
/* clear dirty flags */
if (page_min != ~0l) {

View File

@ -576,13 +576,15 @@ static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
return (addr & 0x0fffffff) + KERNEL_LOAD_ADDR;
}
static void emulate_spapr_hypercall(CPUPPCState *env)
static void emulate_spapr_hypercall(PowerPCCPU *cpu)
{
CPUPPCState *env = &cpu->env;
if (msr_pr) {
hcall_dprintf("Hypercall made with MSR[PR]=1\n");
env->gpr[3] = H_PRIVILEGE;
} else {
env->gpr[3] = spapr_hypercall(env, env->gpr[3], &env->gpr[4]);
env->gpr[3] = spapr_hypercall(cpu, env->gpr[3], &env->gpr[4]);
}
}

View File

@ -286,12 +286,12 @@ extern sPAPREnvironment *spapr;
do { } while (0)
#endif
typedef target_ulong (*spapr_hcall_fn)(CPUPPCState *env, sPAPREnvironment *spapr,
typedef target_ulong (*spapr_hcall_fn)(PowerPCCPU *cpu, sPAPREnvironment *spapr,
target_ulong opcode,
target_ulong *args);
void spapr_register_hypercall(target_ulong opcode, spapr_hcall_fn fn);
target_ulong spapr_hypercall(CPUPPCState *env, target_ulong opcode,
target_ulong spapr_hypercall(PowerPCCPU *cpu, target_ulong opcode,
target_ulong *args);
int spapr_allocate_irq(int hint, bool lsi);

View File

@ -75,9 +75,10 @@ static target_ulong compute_tlbie_rb(target_ulong v, target_ulong r,
return rb;
}
static target_ulong h_enter(CPUPPCState *env, sPAPREnvironment *spapr,
static target_ulong h_enter(PowerPCCPU *cpu, sPAPREnvironment *spapr,
target_ulong opcode, target_ulong *args)
{
CPUPPCState *env = &cpu->env;
target_ulong flags = args[0];
target_ulong pte_index = args[1];
target_ulong pteh = args[2];
@ -192,9 +193,10 @@ static target_ulong remove_hpte(CPUPPCState *env, target_ulong ptex,
return REMOVE_SUCCESS;
}
static target_ulong h_remove(CPUPPCState *env, sPAPREnvironment *spapr,
static target_ulong h_remove(PowerPCCPU *cpu, sPAPREnvironment *spapr,
target_ulong opcode, target_ulong *args)
{
CPUPPCState *env = &cpu->env;
target_ulong flags = args[0];
target_ulong pte_index = args[1];
target_ulong avpn = args[2];
@ -238,9 +240,10 @@ static target_ulong h_remove(CPUPPCState *env, sPAPREnvironment *spapr,
#define H_BULK_REMOVE_MAX_BATCH 4
static target_ulong h_bulk_remove(CPUPPCState *env, sPAPREnvironment *spapr,
static target_ulong h_bulk_remove(PowerPCCPU *cpu, sPAPREnvironment *spapr,
target_ulong opcode, target_ulong *args)
{
CPUPPCState *env = &cpu->env;
int i;
for (i = 0; i < H_BULK_REMOVE_MAX_BATCH; i++) {
@ -284,9 +287,10 @@ static target_ulong h_bulk_remove(CPUPPCState *env, sPAPREnvironment *spapr,
return H_SUCCESS;
}
static target_ulong h_protect(CPUPPCState *env, sPAPREnvironment *spapr,
static target_ulong h_protect(PowerPCCPU *cpu, sPAPREnvironment *spapr,
target_ulong opcode, target_ulong *args)
{
CPUPPCState *env = &cpu->env;
target_ulong flags = args[0];
target_ulong pte_index = args[1];
target_ulong avpn = args[2];
@ -321,7 +325,7 @@ static target_ulong h_protect(CPUPPCState *env, sPAPREnvironment *spapr,
return H_SUCCESS;
}
static target_ulong h_set_dabr(CPUPPCState *env, sPAPREnvironment *spapr,
static target_ulong h_set_dabr(PowerPCCPU *cpu, sPAPREnvironment *spapr,
target_ulong opcode, target_ulong *args)
{
/* FIXME: actually implement this */
@ -457,7 +461,7 @@ static target_ulong deregister_dtl(CPUPPCState *env, target_ulong addr)
return H_SUCCESS;
}
static target_ulong h_register_vpa(CPUPPCState *env, sPAPREnvironment *spapr,
static target_ulong h_register_vpa(PowerPCCPU *cpu, sPAPREnvironment *spapr,
target_ulong opcode, target_ulong *args)
{
target_ulong flags = args[0];
@ -505,12 +509,14 @@ static target_ulong h_register_vpa(CPUPPCState *env, sPAPREnvironment *spapr,
return ret;
}
static target_ulong h_cede(CPUPPCState *env, sPAPREnvironment *spapr,
static target_ulong h_cede(PowerPCCPU *cpu, sPAPREnvironment *spapr,
target_ulong opcode, target_ulong *args)
{
CPUPPCState *env = &cpu->env;
env->msr |= (1ULL << MSR_EE);
hreg_compute_hflags(env);
if (!cpu_has_work(env)) {
if (!cpu_has_work(CPU(cpu))) {
env->halted = 1;
env->exception_index = EXCP_HLT;
env->exit_request = 1;
@ -518,7 +524,7 @@ static target_ulong h_cede(CPUPPCState *env, sPAPREnvironment *spapr,
return H_SUCCESS;
}
static target_ulong h_rtas(CPUPPCState *env, sPAPREnvironment *spapr,
static target_ulong h_rtas(PowerPCCPU *cpu, sPAPREnvironment *spapr,
target_ulong opcode, target_ulong *args)
{
target_ulong rtas_r3 = args[0];
@ -530,7 +536,7 @@ static target_ulong h_rtas(CPUPPCState *env, sPAPREnvironment *spapr,
nret, rtas_r3 + 12 + 4*nargs);
}
static target_ulong h_logical_load(CPUPPCState *env, sPAPREnvironment *spapr,
static target_ulong h_logical_load(PowerPCCPU *cpu, sPAPREnvironment *spapr,
target_ulong opcode, target_ulong *args)
{
target_ulong size = args[0];
@ -553,7 +559,7 @@ static target_ulong h_logical_load(CPUPPCState *env, sPAPREnvironment *spapr,
return H_PARAMETER;
}
static target_ulong h_logical_store(CPUPPCState *env, sPAPREnvironment *spapr,
static target_ulong h_logical_store(PowerPCCPU *cpu, sPAPREnvironment *spapr,
target_ulong opcode, target_ulong *args)
{
target_ulong size = args[0];
@ -577,7 +583,7 @@ static target_ulong h_logical_store(CPUPPCState *env, sPAPREnvironment *spapr,
return H_PARAMETER;
}
static target_ulong h_logical_memop(CPUPPCState *env, sPAPREnvironment *spapr,
static target_ulong h_logical_memop(PowerPCCPU *cpu, sPAPREnvironment *spapr,
target_ulong opcode, target_ulong *args)
{
target_ulong dst = args[0]; /* Destination address */
@ -644,14 +650,14 @@ static target_ulong h_logical_memop(CPUPPCState *env, sPAPREnvironment *spapr,
return H_SUCCESS;
}
static target_ulong h_logical_icbi(CPUPPCState *env, sPAPREnvironment *spapr,
static target_ulong h_logical_icbi(PowerPCCPU *cpu, sPAPREnvironment *spapr,
target_ulong opcode, target_ulong *args)
{
/* Nothing to do on emulation, KVM will trap this in the kernel */
return H_SUCCESS;
}
static target_ulong h_logical_dcbf(CPUPPCState *env, sPAPREnvironment *spapr,
static target_ulong h_logical_dcbf(PowerPCCPU *cpu, sPAPREnvironment *spapr,
target_ulong opcode, target_ulong *args)
{
/* Nothing to do on emulation, KVM will trap this in the kernel */
@ -679,7 +685,7 @@ void spapr_register_hypercall(target_ulong opcode, spapr_hcall_fn fn)
*slot = fn;
}
target_ulong spapr_hypercall(CPUPPCState *env, target_ulong opcode,
target_ulong spapr_hypercall(PowerPCCPU *cpu, target_ulong opcode,
target_ulong *args)
{
if ((opcode <= MAX_HCALL_OPCODE)
@ -687,14 +693,14 @@ target_ulong spapr_hypercall(CPUPPCState *env, target_ulong opcode,
spapr_hcall_fn fn = papr_hypercall_table[opcode / 4];
if (fn) {
return fn(env, spapr, opcode, args);
return fn(cpu, spapr, opcode, args);
}
} else if ((opcode >= KVMPPC_HCALL_BASE) &&
(opcode <= KVMPPC_HCALL_MAX)) {
spapr_hcall_fn fn = kvmppc_hypercall_table[opcode - KVMPPC_HCALL_BASE];
if (fn) {
return fn(env, spapr, opcode, args);
return fn(cpu, spapr, opcode, args);
}
}

View File

@ -204,7 +204,7 @@ static target_ulong put_tce_emu(sPAPRTCETable *tcet, target_ulong ioba,
return H_SUCCESS;
}
static target_ulong h_put_tce(CPUPPCState *env, sPAPREnvironment *spapr,
static target_ulong h_put_tce(PowerPCCPU *cpu, sPAPREnvironment *spapr,
target_ulong opcode, target_ulong *args)
{
target_ulong liobn = args[0];

View File

@ -264,7 +264,7 @@ static int check_bd(VIOsPAPRVLANDevice *dev, vlan_bd_t bd,
return 0;
}
static target_ulong h_register_logical_lan(CPUPPCState *env,
static target_ulong h_register_logical_lan(PowerPCCPU *cpu,
sPAPREnvironment *spapr,
target_ulong opcode,
target_ulong *args)
@ -328,7 +328,7 @@ static target_ulong h_register_logical_lan(CPUPPCState *env,
}
static target_ulong h_free_logical_lan(CPUPPCState *env, sPAPREnvironment *spapr,
static target_ulong h_free_logical_lan(PowerPCCPU *cpu, sPAPREnvironment *spapr,
target_ulong opcode, target_ulong *args)
{
target_ulong reg = args[0];
@ -349,7 +349,7 @@ static target_ulong h_free_logical_lan(CPUPPCState *env, sPAPREnvironment *spapr
return H_SUCCESS;
}
static target_ulong h_add_logical_lan_buffer(CPUPPCState *env,
static target_ulong h_add_logical_lan_buffer(PowerPCCPU *cpu,
sPAPREnvironment *spapr,
target_ulong opcode,
target_ulong *args)
@ -398,7 +398,7 @@ static target_ulong h_add_logical_lan_buffer(CPUPPCState *env,
return H_SUCCESS;
}
static target_ulong h_send_logical_lan(CPUPPCState *env, sPAPREnvironment *spapr,
static target_ulong h_send_logical_lan(PowerPCCPU *cpu, sPAPREnvironment *spapr,
target_ulong opcode, target_ulong *args)
{
target_ulong reg = args[0];
@ -467,7 +467,7 @@ static target_ulong h_send_logical_lan(CPUPPCState *env, sPAPREnvironment *spapr
return H_SUCCESS;
}
static target_ulong h_multicast_ctrl(CPUPPCState *env, sPAPREnvironment *spapr,
static target_ulong h_multicast_ctrl(PowerPCCPU *cpu, sPAPREnvironment *spapr,
target_ulong opcode, target_ulong *args)
{
target_ulong reg = args[0];

View File

@ -439,6 +439,43 @@ static void pci_spapr_set_irq(void *opaque, int irq_num, int level)
qemu_set_irq(spapr_phb_lsi_qirq(phb, irq_num), level);
}
static uint64_t spapr_io_read(void *opaque, hwaddr addr,
unsigned size)
{
switch (size) {
case 1:
return cpu_inb(addr);
case 2:
return cpu_inw(addr);
case 4:
return cpu_inl(addr);
}
assert(0);
}
static void spapr_io_write(void *opaque, hwaddr addr,
uint64_t data, unsigned size)
{
switch (size) {
case 1:
cpu_outb(addr, data);
return;
case 2:
cpu_outw(addr, data);
return;
case 4:
cpu_outl(addr, data);
return;
}
assert(0);
}
static const MemoryRegionOps spapr_io_ops = {
.endianness = DEVICE_LITTLE_ENDIAN,
.read = spapr_io_read,
.write = spapr_io_write
};
/*
* MSI/MSIX memory region implementation.
* The handler handles both MSI and MSIX.
@ -508,9 +545,14 @@ static int spapr_phb_init(SysBusDevice *s)
* old_portion are updated */
sprintf(namebuf, "%s.io", sphb->dtbusname);
memory_region_init(&sphb->iospace, namebuf, SPAPR_PCI_IO_WIN_SIZE);
/* FIXME: fix to support multiple PHBs */
memory_region_add_subregion(get_system_io(), 0, &sphb->iospace);
sprintf(namebuf, "%s.io-alias", sphb->dtbusname);
memory_region_init_io(&sphb->iowindow, &spapr_io_ops, sphb,
namebuf, SPAPR_PCI_IO_WIN_SIZE);
memory_region_add_subregion(get_system_memory(), sphb->io_win_addr,
&sphb->iospace);
&sphb->iowindow);
/* As MSI/MSIX interrupts trigger by writing at MSI/MSIX vectors,
* we need to allocate some memory to catch those writes coming

View File

@ -44,7 +44,7 @@ typedef struct sPAPRPHBState {
MemoryRegion memspace, iospace;
hwaddr mem_win_addr, mem_win_size, io_win_addr, io_win_size;
hwaddr msi_win_addr;
MemoryRegion memwindow, msiwindow;
MemoryRegion memwindow, iowindow, msiwindow;
uint32_t dma_liobn;
uint64_t dma_window_start;

View File

@ -163,6 +163,7 @@ static void rtas_start_cpu(sPAPREnvironment *spapr,
uint32_t nret, target_ulong rets)
{
target_ulong id, start, r3;
CPUState *cpu;
CPUPPCState *env;
if (nargs != 3 || nret != 1) {
@ -175,6 +176,8 @@ static void rtas_start_cpu(sPAPREnvironment *spapr,
r3 = rtas_ld(args, 2);
for (env = first_cpu; env; env = env->next_cpu) {
cpu = ENV_GET_CPU(env);
if (env->cpu_index != id) {
continue;
}
@ -194,7 +197,7 @@ static void rtas_start_cpu(sPAPREnvironment *spapr,
env->gpr[3] = r3;
env->halted = 0;
qemu_cpu_kick(env);
qemu_cpu_kick(cpu);
rtas_st(rets, 0, 0);
return;

View File

@ -161,7 +161,7 @@ static int vio_make_devnode(VIOsPAPRDevice *dev,
/*
* CRQ handling
*/
static target_ulong h_reg_crq(CPUPPCState *env, sPAPREnvironment *spapr,
static target_ulong h_reg_crq(PowerPCCPU *cpu, sPAPREnvironment *spapr,
target_ulong opcode, target_ulong *args)
{
target_ulong reg = args[0];
@ -219,7 +219,7 @@ static target_ulong free_crq(VIOsPAPRDevice *dev)
return H_SUCCESS;
}
static target_ulong h_free_crq(CPUPPCState *env, sPAPREnvironment *spapr,
static target_ulong h_free_crq(PowerPCCPU *cpu, sPAPREnvironment *spapr,
target_ulong opcode, target_ulong *args)
{
target_ulong reg = args[0];
@ -233,7 +233,7 @@ static target_ulong h_free_crq(CPUPPCState *env, sPAPREnvironment *spapr,
return free_crq(dev);
}
static target_ulong h_send_crq(CPUPPCState *env, sPAPREnvironment *spapr,
static target_ulong h_send_crq(PowerPCCPU *cpu, sPAPREnvironment *spapr,
target_ulong opcode, target_ulong *args)
{
target_ulong reg = args[0];
@ -256,7 +256,7 @@ static target_ulong h_send_crq(CPUPPCState *env, sPAPREnvironment *spapr,
return H_HARDWARE;
}
static target_ulong h_enable_crq(CPUPPCState *env, sPAPREnvironment *spapr,
static target_ulong h_enable_crq(PowerPCCPU *cpu, sPAPREnvironment *spapr,
target_ulong opcode, target_ulong *args)
{
target_ulong reg = args[0];
@ -463,7 +463,7 @@ static int spapr_vio_busdev_init(DeviceState *qdev)
return pc->init(dev);
}
static target_ulong h_vio_signal(CPUPPCState *env, sPAPREnvironment *spapr,
static target_ulong h_vio_signal(PowerPCCPU *cpu, sPAPREnvironment *spapr,
target_ulong opcode,
target_ulong *args)
{

View File

@ -70,7 +70,7 @@ static int spapr_vty_init(VIOsPAPRDevice *sdev)
}
/* Forward declaration */
static target_ulong h_put_term_char(CPUPPCState *env, sPAPREnvironment *spapr,
static target_ulong h_put_term_char(PowerPCCPU *cpu, sPAPREnvironment *spapr,
target_ulong opcode, target_ulong *args)
{
target_ulong reg = args[0];
@ -97,7 +97,7 @@ static target_ulong h_put_term_char(CPUPPCState *env, sPAPREnvironment *spapr,
return H_SUCCESS;
}
static target_ulong h_get_term_char(CPUPPCState *env, sPAPREnvironment *spapr,
static target_ulong h_get_term_char(PowerPCCPU *cpu, sPAPREnvironment *spapr,
target_ulong opcode, target_ulong *args)
{
target_ulong reg = args[0];

View File

@ -879,15 +879,14 @@ static struct arm_boot_info spitz_binfo = {
.ram_size = 0x04000000,
};
static void spitz_common_init(ram_addr_t ram_size,
const char *kernel_filename,
const char *kernel_cmdline, const char *initrd_filename,
const char *cpu_model, enum spitz_model_e model, int arm_id)
static void spitz_common_init(QEMUMachineInitArgs *args,
enum spitz_model_e model, int arm_id)
{
PXA2xxState *mpu;
DeviceState *scp0, *scp1 = NULL;
MemoryRegion *address_space_mem = get_system_memory();
MemoryRegion *rom = g_new(MemoryRegion, 1);
const char *cpu_model = args->cpu_model;
if (!cpu_model)
cpu_model = (model == terrier) ? "pxa270-c5" : "pxa270-c0";
@ -928,9 +927,9 @@ static void spitz_common_init(ram_addr_t ram_size,
/* A 4.0 GB microdrive is permanently sitting in CF slot 0. */
spitz_microdrive_attach(mpu, 0);
spitz_binfo.kernel_filename = kernel_filename;
spitz_binfo.kernel_cmdline = kernel_cmdline;
spitz_binfo.initrd_filename = initrd_filename;
spitz_binfo.kernel_filename = args->kernel_filename;
spitz_binfo.kernel_cmdline = args->kernel_cmdline;
spitz_binfo.initrd_filename = args->initrd_filename;
spitz_binfo.board_id = arm_id;
arm_load_kernel(mpu->cpu, &spitz_binfo);
sl_bootparam_write(SL_PXA_PARAM_BASE);
@ -938,46 +937,22 @@ static void spitz_common_init(ram_addr_t ram_size,
static void spitz_init(QEMUMachineInitArgs *args)
{
ram_addr_t ram_size = args->ram_size;
const char *cpu_model = args->cpu_model;
const char *kernel_filename = args->kernel_filename;
const char *kernel_cmdline = args->kernel_cmdline;
const char *initrd_filename = args->initrd_filename;
spitz_common_init(ram_size, kernel_filename,
kernel_cmdline, initrd_filename, cpu_model, spitz, 0x2c9);
spitz_common_init(args, spitz, 0x2c9);
}
static void borzoi_init(QEMUMachineInitArgs *args)
{
ram_addr_t ram_size = args->ram_size;
const char *cpu_model = args->cpu_model;
const char *kernel_filename = args->kernel_filename;
const char *kernel_cmdline = args->kernel_cmdline;
const char *initrd_filename = args->initrd_filename;
spitz_common_init(ram_size, kernel_filename,
kernel_cmdline, initrd_filename, cpu_model, borzoi, 0x33f);
spitz_common_init(args, borzoi, 0x33f);
}
static void akita_init(QEMUMachineInitArgs *args)
{
ram_addr_t ram_size = args->ram_size;
const char *cpu_model = args->cpu_model;
const char *kernel_filename = args->kernel_filename;
const char *kernel_cmdline = args->kernel_cmdline;
const char *initrd_filename = args->initrd_filename;
spitz_common_init(ram_size, kernel_filename,
kernel_cmdline, initrd_filename, cpu_model, akita, 0x2e8);
spitz_common_init(args, akita, 0x2e8);
}
static void terrier_init(QEMUMachineInitArgs *args)
{
ram_addr_t ram_size = args->ram_size;
const char *cpu_model = args->cpu_model;
const char *kernel_filename = args->kernel_filename;
const char *kernel_cmdline = args->kernel_cmdline;
const char *initrd_filename = args->initrd_filename;
spitz_common_init(ram_size, kernel_filename,
kernel_cmdline, initrd_filename, cpu_model, terrier, 0x33f);
spitz_common_init(args, terrier, 0x33f);
}
static QEMUMachine akitapda_machine = {

View File

@ -252,7 +252,7 @@ static void ssd0303_update_display(void *opaque)
}
}
s->redraw = 0;
dpy_update(s->ds, 0, 0, 96 * MAGNIFY, 16 * MAGNIFY);
dpy_gfx_update(s->ds, 0, 0, 96 * MAGNIFY, 16 * MAGNIFY);
}
static void ssd0303_invalidate_display(void * opaque)

View File

@ -260,7 +260,7 @@ static void ssd0323_update_display(void *opaque)
}
}
s->redraw = 0;
dpy_update(s->ds, 0, 0, 128 * MAGNIFY, 64 * MAGNIFY);
dpy_gfx_update(s->ds, 0, 0, 128 * MAGNIFY, 64 * MAGNIFY);
}
static void ssd0323_invalidate_display(void * opaque)

View File

@ -94,29 +94,6 @@ static const MemoryRegionOps sun4c_intctl_mem_ops = {
},
};
void sun4c_pic_info(Monitor *mon, void *opaque)
{
Sun4c_INTCTLState *s = opaque;
monitor_printf(mon, "master: pending 0x%2.2x, enabled 0x%2.2x\n",
s->pending, s->reg);
}
void sun4c_irq_info(Monitor *mon, void *opaque)
{
#ifndef DEBUG_IRQ_COUNT
monitor_printf(mon, "irq statistic code not compiled.\n");
#else
Sun4c_INTCTLState *s = opaque;
int64_t count;
monitor_printf(mon, "IRQ statistics:\n");
count = s->irq_count;
if (count > 0)
monitor_printf(mon, " %" PRId64 "\n", count);
#endif
}
static const uint32_t intbit_to_level[] = { 0, 1, 4, 6, 8, 10, 0, 14, };
static void sun4c_check_interrupts(void *opaque)

Some files were not shown because too many files have changed in this diff Show More