mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 10:11:27 +01:00
Merge xen-ia64-unstable.hg
This commit is contained in:
commit
2f760d09a8
13 files changed
+247
-243
No files matched your search
@@ -166,6 +166,7 @@
|
||||
^tools/xenstore/xenstore-read$
|
||||
^tools/xenstore/xenstore-rm$
|
||||
^tools/xenstore/xenstore-write$
|
||||
^tools/xenstore/xenstore-control$
|
||||
^tools/xenstore/xenstore-ls$
|
||||
^tools/xenstore/xenstored$
|
||||
^tools/xenstore/xenstored_test$
|
||||
|
||||
@@ -1,89 +0,0 @@
|
||||
/*
|
||||
* Simple prototyle Xen Store Daemon providing simple tree-like database.
|
||||
* Copyright (C) 2005 Rusty Russell IBM Corporation
|
||||
*
|
||||
* This file may be distributed separately from the Linux kernel, or
|
||||
* incorporated into other software packages, subject to the following license:
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this source file (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.
|
||||
*/
|
||||
|
||||
#ifndef _XENSTORED_H
|
||||
#define _XENSTORED_H
|
||||
|
||||
enum xsd_sockmsg_type
|
||||
{
|
||||
XS_DEBUG,
|
||||
XS_SHUTDOWN,
|
||||
XS_DIRECTORY,
|
||||
XS_READ,
|
||||
XS_GET_PERMS,
|
||||
XS_WATCH,
|
||||
XS_WATCH_ACK,
|
||||
XS_UNWATCH,
|
||||
XS_TRANSACTION_START,
|
||||
XS_TRANSACTION_END,
|
||||
XS_OP_READ_ONLY = XS_TRANSACTION_END,
|
||||
XS_INTRODUCE,
|
||||
XS_RELEASE,
|
||||
XS_GET_DOMAIN_PATH,
|
||||
XS_WRITE,
|
||||
XS_MKDIR,
|
||||
XS_RM,
|
||||
XS_SET_PERMS,
|
||||
XS_WATCH_EVENT,
|
||||
XS_ERROR,
|
||||
};
|
||||
|
||||
#define XS_WRITE_NONE "NONE"
|
||||
#define XS_WRITE_CREATE "CREATE"
|
||||
#define XS_WRITE_CREATE_EXCL "CREATE|EXCL"
|
||||
|
||||
/* We hand errors as strings, for portability. */
|
||||
struct xsd_errors
|
||||
{
|
||||
int errnum;
|
||||
const char *errstring;
|
||||
};
|
||||
#define XSD_ERROR(x) { x, #x }
|
||||
static struct xsd_errors xsd_errors[] __attribute__((unused)) = {
|
||||
XSD_ERROR(EINVAL),
|
||||
XSD_ERROR(EACCES),
|
||||
XSD_ERROR(EEXIST),
|
||||
XSD_ERROR(EISDIR),
|
||||
XSD_ERROR(ENOENT),
|
||||
XSD_ERROR(ENOMEM),
|
||||
XSD_ERROR(ENOSPC),
|
||||
XSD_ERROR(EIO),
|
||||
XSD_ERROR(ENOTEMPTY),
|
||||
XSD_ERROR(ENOSYS),
|
||||
XSD_ERROR(EROFS),
|
||||
XSD_ERROR(EBUSY),
|
||||
XSD_ERROR(EAGAIN),
|
||||
XSD_ERROR(EISCONN),
|
||||
};
|
||||
struct xsd_sockmsg
|
||||
{
|
||||
u32 type;
|
||||
u32 len; /* Length of data following this. */
|
||||
|
||||
/* Generally followed by nul-terminated string(s). */
|
||||
};
|
||||
|
||||
#endif /* _XENSTORED_H */
|
||||
@@ -129,7 +129,14 @@ check_sharing()
|
||||
same_vm()
|
||||
{
|
||||
local otherdom="$1"
|
||||
local othervm=$(xenstore-read "/local/domain/$otherdom/vm")
|
||||
# Note that othervm can be MISSING here, because Xend will be racing with
|
||||
# the hotplug scripts -- the entries in /local/domain can be removed by
|
||||
# Xend before the hotplug scripts have removed the entry in
|
||||
# /local/domain/0/backend/. In this case, we want to pretend that the
|
||||
# VM is the same as FRONTEND_UUID, because that way the 'sharing' will be
|
||||
# allowed.
|
||||
local othervm=$(xenstore_read_default "/local/domain/$otherdom/vm" \
|
||||
"$FRONTEND_UUID")
|
||||
|
||||
[ "$FRONTEND_UUID" == "$othervm" ]
|
||||
}
|
||||
|
||||
@@ -12,10 +12,11 @@ dir=$(dirname "$0")
|
||||
claim_lock "block"
|
||||
|
||||
# remove device frontend store entries
|
||||
xenstore-rm -t $(xenstore-read "$XENBUS_PATH/frontend") || true
|
||||
xenstore-rm -t \
|
||||
$(xenstore-read "$XENBUS_PATH/frontend" 2>/dev/null) 2>/dev/null || true
|
||||
|
||||
# remove device backend store entries
|
||||
xenstore-rm -t "$XENBUS_PATH" || true
|
||||
xenstore-rm -t "error/$XENBUS_PATH" || true
|
||||
xenstore-rm -t "$XENBUS_PATH" 2>/dev/null || true
|
||||
xenstore-rm -t "error/$XENBUS_PATH" 2>/dev/null || true
|
||||
|
||||
release_lock "block"
|
||||
+13
-5
@@ -27,7 +27,10 @@ CLIENTS := xenstore-exists xenstore-list xenstore-read xenstore-rm
|
||||
CLIENTS += xenstore-write
|
||||
CLIENTS_OBJS := $(patsubst xenstore-%,xenstore_%.o,$(CLIENTS))
|
||||
|
||||
all: libxenstore.so xenstored $(CLIENTS) xs_tdb_dump xenstore-ls
|
||||
all: libxenstore.so xenstored $(CLIENTS) xs_tdb_dump xenstore-control xenstore-ls
|
||||
|
||||
test_interleaved_transactions: test_interleaved_transactions.o
|
||||
$(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -L. -lxenstore -o $@
|
||||
|
||||
testcode: xs_test xenstored_test xs_random
|
||||
|
||||
@@ -35,13 +38,16 @@ xenstored: xenstored_core.o xenstored_watch.o xenstored_domain.o xenstored_trans
|
||||
$(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -lxenctrl -o $@
|
||||
|
||||
$(CLIENTS): xenstore-%: xenstore_%.o libxenstore.so
|
||||
$(LINK.o) $< $(LOADLIBES) $(LDLIBS) -lxenctrl -L. -lxenstore -o $@
|
||||
$(LINK.o) $< $(LOADLIBES) $(LDLIBS) -L. -lxenstore -o $@
|
||||
|
||||
$(CLIENTS_OBJS): xenstore_%.o: xenstore_client.c
|
||||
$(COMPILE.c) -DCLIENT_$(*F) -o $@ $<
|
||||
|
||||
xenstore-control: xenstore_control.o libxenstore.so
|
||||
$(LINK.o) $< $(LOADLIBES) $(LDLIBS) -L. -lxenstore -o $@
|
||||
|
||||
xenstore-ls: xsls.o libxenstore.so
|
||||
$(LINK.o) $< $(LOADLIBES) $(LDLIBS) -lxenctrl -L. -lxenstore -o $@
|
||||
$(LINK.o) $< $(LOADLIBES) $(LDLIBS) -L. -lxenstore -o $@
|
||||
|
||||
xenstored_test: xenstored_core_test.o xenstored_watch_test.o xenstored_domain_test.o xenstored_transaction_test.o xs_lib.o talloc_test.o fake_libxc.o utils.o tdb.o
|
||||
$(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $@
|
||||
@@ -77,7 +83,8 @@ libxenstore.so: xs.opic xs_lib.opic
|
||||
clean: testsuite-clean
|
||||
rm -f *.o *.opic *.so
|
||||
rm -f xenstored xs_random xs_stress xs_crashme
|
||||
rm -f xs_test xenstored_test xs_tdb_dump xenstore-ls $(CLIENTS)
|
||||
rm -f xs_test xenstored_test xs_tdb_dump xenstore-control xenstore-ls
|
||||
rm -f $(CLIENTS)
|
||||
$(RM) $(PROG_DEP)
|
||||
|
||||
print-dir:
|
||||
@@ -129,7 +136,7 @@ TAGS:
|
||||
tarball: clean
|
||||
cd .. && tar -c -j -v -h -f xenstore.tar.bz2 xenstore/
|
||||
|
||||
install: libxenstore.so xenstored xenstore-ls $(CLIENTS)
|
||||
install: all
|
||||
$(INSTALL_DIR) -p $(DESTDIR)/var/run/xenstored
|
||||
$(INSTALL_DIR) -p $(DESTDIR)/var/lib/xenstored
|
||||
$(INSTALL_DIR) -p $(DESTDIR)/usr/bin
|
||||
@@ -137,6 +144,7 @@ install: libxenstore.so xenstored xenstore-ls $(CLIENTS)
|
||||
$(INSTALL_DIR) -p $(DESTDIR)/usr/include
|
||||
$(INSTALL_PROG) xenstored $(DESTDIR)/usr/sbin
|
||||
$(INSTALL_PROG) $(CLIENTS) $(DESTDIR)/usr/bin
|
||||
$(INSTALL_PROG) xenstore-control $(DESTDIR)/usr/bin
|
||||
$(INSTALL_PROG) xenstore-ls $(DESTDIR)/usr/bin
|
||||
$(INSTALL_DIR) -p $(DESTDIR)/usr/$(LIBDIR)
|
||||
$(INSTALL_DATA) libxenstore.so $(DESTDIR)/usr/$(LIBDIR)
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "xs.h"
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
struct xs_handle * xsh;
|
||||
|
||||
if (argc < 2 ||
|
||||
strcmp(argv[1], "check"))
|
||||
{
|
||||
fprintf(stderr,
|
||||
"Usage:\n"
|
||||
"\n"
|
||||
" %s check\n"
|
||||
"\n", argv[0]);
|
||||
return 2;
|
||||
}
|
||||
|
||||
xsh = xs_daemon_open();
|
||||
|
||||
xs_debug_command(xsh, argv[1], NULL, 0);
|
||||
|
||||
xs_daemon_close(xsh);
|
||||
|
||||
return 0;
|
||||
}
|
||||
+128
-45
@@ -60,6 +60,18 @@ static int reopen_log_pipe[2];
|
||||
static char *tracefile = NULL;
|
||||
static TDB_CONTEXT *tdb_ctx;
|
||||
|
||||
static void corrupt(struct connection *conn, const char *fmt, ...);
|
||||
static void check_store();
|
||||
|
||||
#define log(...) \
|
||||
do { \
|
||||
char *s = talloc_asprintf(NULL, __VA_ARGS__); \
|
||||
trace("%s\n", s); \
|
||||
syslog(LOG_ERR, "%s", s); \
|
||||
talloc_free(s); \
|
||||
} while (0)
|
||||
|
||||
|
||||
#ifdef TESTING
|
||||
static bool failtest = false;
|
||||
|
||||
@@ -104,33 +116,6 @@ int test_mkdir(const char *dir, int perms)
|
||||
|
||||
#include "xenstored_test.h"
|
||||
|
||||
/* FIXME: Ideally, this should never be called. Some can be eliminated. */
|
||||
/* Something is horribly wrong: shutdown immediately. */
|
||||
void __attribute__((noreturn)) corrupt(struct connection *conn,
|
||||
const char *fmt, ...)
|
||||
{
|
||||
va_list arglist;
|
||||
char *str;
|
||||
int saved_errno = errno;
|
||||
|
||||
va_start(arglist, fmt);
|
||||
str = talloc_vasprintf(NULL, fmt, arglist);
|
||||
va_end(arglist);
|
||||
|
||||
trace("xenstored corruption: connection id %i: err %s: %s",
|
||||
conn ? (int)conn->id : -1, strerror(saved_errno), str);
|
||||
eprintf("xenstored corruption: connection id %i: err %s: %s",
|
||||
conn ? (int)conn->id : -1, strerror(saved_errno), str);
|
||||
#ifdef TESTING
|
||||
/* Allow them to attach debugger. */
|
||||
sleep(30);
|
||||
#endif
|
||||
syslog(LOG_DAEMON,
|
||||
"xenstored corruption: connection id %i: err %s: %s",
|
||||
conn ? (int)conn->id : -1, strerror(saved_errno), str);
|
||||
_exit(2);
|
||||
}
|
||||
|
||||
TDB_CONTEXT *tdb_context(struct connection *conn)
|
||||
{
|
||||
/* conn = NULL used in manual_node at setup. */
|
||||
@@ -216,8 +201,9 @@ static void trace_io(const struct connection *conn,
|
||||
now = time(NULL);
|
||||
tm = localtime(&now);
|
||||
|
||||
trace("%s %p %02d:%02d:%02d %s (", prefix, conn,
|
||||
tm->tm_hour, tm->tm_min, tm->tm_sec,
|
||||
trace("%s %p %p %04d%02d%02d %02d:%02d:%02d %s (", prefix, conn,
|
||||
conn->transaction, tm->tm_year + 1900, tm->tm_mon + 1,
|
||||
tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec,
|
||||
sockmsg_string(data->hdr.msg.type));
|
||||
|
||||
for (i = 0; i < data->hdr.msg.len; i++)
|
||||
@@ -837,8 +823,6 @@ static int destroy_node(void *_node)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Be careful: create heirarchy, put entry in existing parent *last*.
|
||||
* This helps fsck if we die during this. */
|
||||
static struct node *create_node(struct connection *conn,
|
||||
const char *name,
|
||||
void *data, unsigned int datalen)
|
||||
@@ -939,8 +923,9 @@ static void delete_node(struct connection *conn, struct node *node)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
/* Delete self, then delete children. If something goes wrong,
|
||||
* consistency check will clean up this way. */
|
||||
/* Delete self, then delete children. If we crash, then the worst
|
||||
that can happen is the children will continue to take up space, but
|
||||
will otherwise be unreachable. */
|
||||
delete_node_single(conn, node);
|
||||
|
||||
/* Delete children, too. */
|
||||
@@ -950,9 +935,14 @@ static void delete_node(struct connection *conn, struct node *node)
|
||||
child = read_node(conn,
|
||||
talloc_asprintf(node, "%s/%s", node->name,
|
||||
node->children + i));
|
||||
if (!child)
|
||||
corrupt(conn, "No child '%s' found", child);
|
||||
delete_node(conn, child);
|
||||
if (child) {
|
||||
delete_node(conn, child);
|
||||
}
|
||||
else {
|
||||
trace("delete_node: No child '%s/%s' found!\n",
|
||||
node->name, node->children + i);
|
||||
/* Skip it, we've already deleted the parent. */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -976,12 +966,15 @@ static bool delete_child(struct connection *conn,
|
||||
}
|
||||
}
|
||||
corrupt(conn, "Can't find child '%s' in %s", childname, node->name);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static int _rm(struct connection *conn, struct node *node, const char *name)
|
||||
{
|
||||
/* Delete from parent first, then if something explodes fsck cleans. */
|
||||
/* Delete from parent first, then if we crash, the worst that can
|
||||
happen is the child will continue to take up space, but will
|
||||
otherwise be unreachable. */
|
||||
struct node *parent = read_node(conn, get_parent(name));
|
||||
if (!parent) {
|
||||
send_error(conn, EINVAL);
|
||||
@@ -1000,10 +993,11 @@ static int _rm(struct connection *conn, struct node *node, const char *name)
|
||||
|
||||
static void internal_rm(const char *name)
|
||||
{
|
||||
char *tname = talloc_strdup(talloc_autofree_context(), name);
|
||||
char *tname = talloc_strdup(NULL, name);
|
||||
struct node *node = read_node(NULL, tname);
|
||||
if (node)
|
||||
_rm(NULL, node, tname);
|
||||
talloc_free(tname);
|
||||
}
|
||||
|
||||
|
||||
@@ -1149,18 +1143,19 @@ static void process_message(struct connection *conn, struct buffered_data *in)
|
||||
case XS_DEBUG:
|
||||
if (streq(in->buffer, "print"))
|
||||
xprintf("debug: %s", in->buffer + get_string(in, 0));
|
||||
if (streq(in->buffer, "check"))
|
||||
check_store();
|
||||
#ifdef TESTING
|
||||
/* For testing, we allow them to set id. */
|
||||
if (streq(in->buffer, "setid")) {
|
||||
conn->id = atoi(in->buffer + get_string(in, 0));
|
||||
send_ack(conn, XS_DEBUG);
|
||||
} else if (streq(in->buffer, "failtest")) {
|
||||
if (get_string(in, 0) < in->used)
|
||||
srandom(atoi(in->buffer + get_string(in, 0)));
|
||||
send_ack(conn, XS_DEBUG);
|
||||
failtest = true;
|
||||
}
|
||||
#endif /* TESTING */
|
||||
send_ack(conn, XS_DEBUG);
|
||||
break;
|
||||
|
||||
case XS_WATCH:
|
||||
@@ -1258,7 +1253,7 @@ static void handle_input(struct connection *conn)
|
||||
|
||||
if (in->hdr.msg.len > PATH_MAX) {
|
||||
#ifndef TESTING
|
||||
syslog(LOG_DAEMON, "Client tried to feed us %i",
|
||||
syslog(LOG_ERR, "Client tried to feed us %i",
|
||||
in->hdr.msg.len);
|
||||
#endif
|
||||
goto bad_client;
|
||||
@@ -1425,10 +1420,16 @@ static void setup_structure(void)
|
||||
balloon driver will pick up stale entries. In the case of
|
||||
the balloon driver, this can be fatal.
|
||||
*/
|
||||
char *tlocal = talloc_strdup(talloc_autofree_context(),
|
||||
"/local");
|
||||
char *tlocal = talloc_strdup(NULL, "/local");
|
||||
|
||||
check_store();
|
||||
|
||||
internal_rm("/local");
|
||||
create_node(NULL, tlocal, NULL, 0);
|
||||
|
||||
talloc_free(tlocal);
|
||||
|
||||
check_store();
|
||||
}
|
||||
else {
|
||||
tdb_ctx = tdb_open(tdbname, 7919, TDB_FLAGS, O_RDWR|O_CREAT,
|
||||
@@ -1439,11 +1440,93 @@ static void setup_structure(void)
|
||||
manual_node("/", "tool");
|
||||
manual_node("/tool", "xenstored");
|
||||
manual_node("/tool/xenstored", NULL);
|
||||
}
|
||||
|
||||
/* FIXME: Fsck */
|
||||
check_store();
|
||||
}
|
||||
}
|
||||
|
||||
static char *child_name(const char *s1, const char *s2)
|
||||
{
|
||||
if (strcmp(s1, "/")) {
|
||||
return talloc_asprintf(NULL, "%s/%s", s1, s2);
|
||||
}
|
||||
else {
|
||||
return talloc_asprintf(NULL, "/%s", s2);
|
||||
}
|
||||
}
|
||||
|
||||
static void check_store_(const char *name)
|
||||
{
|
||||
struct node *node = read_node(NULL, name);
|
||||
|
||||
if (node) {
|
||||
size_t i = 0;
|
||||
|
||||
while (i < node->childlen) {
|
||||
size_t childlen = strlen(node->children + i);
|
||||
char * childname = child_name(node->name,
|
||||
node->children + i);
|
||||
struct node *childnode = read_node(NULL, childname);
|
||||
|
||||
if (childnode) {
|
||||
check_store_(childname);
|
||||
i += childlen + 1;
|
||||
}
|
||||
else {
|
||||
log("check_store: No child '%s' found!\n",
|
||||
childname);
|
||||
|
||||
memdel(node->children, i, childlen + 1,
|
||||
node->childlen);
|
||||
node->childlen -= childlen + 1;
|
||||
write_node(NULL, node);
|
||||
}
|
||||
|
||||
talloc_free(childname);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Impossible, because no database should ever be without the
|
||||
root, and otherwise, we've just checked in our caller
|
||||
(which made a recursive call to get here). */
|
||||
|
||||
log("check_store: No child '%s' found: impossible!", name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void check_store()
|
||||
{
|
||||
char * root = talloc_strdup(NULL, "/");
|
||||
log("Checking store ...");
|
||||
check_store_(root);
|
||||
log("Checking store complete.");
|
||||
talloc_free(root);
|
||||
}
|
||||
|
||||
|
||||
/* Something is horribly wrong: check the store. */
|
||||
static void corrupt(struct connection *conn, const char *fmt, ...)
|
||||
{
|
||||
va_list arglist;
|
||||
char *str;
|
||||
int saved_errno = errno;
|
||||
|
||||
va_start(arglist, fmt);
|
||||
str = talloc_vasprintf(NULL, fmt, arglist);
|
||||
va_end(arglist);
|
||||
|
||||
log("corruption detected by connection %i: err %s: %s",
|
||||
conn ? (int)conn->id : -1, strerror(saved_errno), str);
|
||||
|
||||
#ifdef TESTING
|
||||
/* Allow them to attach debugger. */
|
||||
sleep(30);
|
||||
#endif
|
||||
check_store();
|
||||
}
|
||||
|
||||
|
||||
static void write_pidfile(const char *pidfile)
|
||||
{
|
||||
char buf[100];
|
||||
|
||||
@@ -148,10 +148,6 @@ int destroy_tdb(void *_tdb);
|
||||
/* Replace the tdb: required for transaction code */
|
||||
bool replace_tdb(const char *newname, TDB_CONTEXT *newtdb);
|
||||
|
||||
/* Fail due to excessive corruption, capitalist pigdogs! */
|
||||
void __attribute__((noreturn)) corrupt(struct connection *conn,
|
||||
const char *fmt, ...);
|
||||
|
||||
struct connection *new_connection(connwritefn_t *write, connreadfn_t *read);
|
||||
|
||||
|
||||
|
||||
+13
-14
@@ -247,6 +247,7 @@ void svm_load_msrs(void)
|
||||
void svm_restore_msrs(struct vcpu *v)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#define IS_CANO_ADDRESS(add) 1
|
||||
|
||||
@@ -297,8 +298,13 @@ static inline int long_mode_do_msr_read(struct cpu_user_regs *regs)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef __x86_64__
|
||||
HVM_DBG_LOG(DBG_LEVEL_2, "mode_do_msr_read: msr_content: %lx\n",
|
||||
msr_content);
|
||||
#else
|
||||
HVM_DBG_LOG(DBG_LEVEL_2, "mode_do_msr_read: msr_content: %llx\n",
|
||||
msr_content);
|
||||
#endif
|
||||
|
||||
regs->eax = msr_content & 0xffffffff;
|
||||
regs->edx = msr_content >> 32;
|
||||
@@ -311,12 +317,18 @@ static inline int long_mode_do_msr_write(struct cpu_user_regs *regs)
|
||||
struct vcpu *vc = current;
|
||||
struct vmcb_struct *vmcb = vc->arch.hvm_svm.vmcb;
|
||||
|
||||
#ifdef __x86_64__
|
||||
HVM_DBG_LOG(DBG_LEVEL_1, "mode_do_msr_write msr %lx msr_content %lx\n",
|
||||
regs->ecx, msr_content);
|
||||
#else
|
||||
HVM_DBG_LOG(DBG_LEVEL_1, "mode_do_msr_write msr %x msr_content %llx\n",
|
||||
regs->ecx, msr_content);
|
||||
#endif
|
||||
|
||||
switch (regs->ecx)
|
||||
{
|
||||
case MSR_EFER:
|
||||
#ifdef __x86_64__
|
||||
if ((msr_content & EFER_LME) ^ test_bit(SVM_CPU_STATE_LME_ENABLED,
|
||||
&vc->arch.hvm_svm.cpu_state))
|
||||
{
|
||||
@@ -337,6 +349,7 @@ static inline int long_mode_do_msr_write(struct cpu_user_regs *regs)
|
||||
if ((msr_content ^ vmcb->efer) & EFER_LME)
|
||||
msr_content &= ~EFER_LME;
|
||||
/* No update for LME/LMA since it have no effect */
|
||||
#endif
|
||||
vmcb->efer = msr_content | EFER_SVME;
|
||||
break;
|
||||
|
||||
@@ -383,18 +396,6 @@ static inline int long_mode_do_msr_write(struct cpu_user_regs *regs)
|
||||
return 1;
|
||||
}
|
||||
|
||||
#else
|
||||
static inline int long_mode_do_msr_read(struct cpu_user_regs *regs)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int long_mode_do_msr_write(struct cpu_user_regs *regs)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
void svm_store_cpu_guest_ctrl_regs(struct vcpu *v, unsigned long crs[8])
|
||||
{
|
||||
struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
|
||||
@@ -937,10 +938,8 @@ static void svm_vmexit_do_cpuid(struct vmcb_struct *vmcb, unsigned long input,
|
||||
|
||||
if (input == 1)
|
||||
{
|
||||
#ifndef __x86_64__
|
||||
if ( hvm_apic_support(v->domain) &&
|
||||
!vlapic_global_enabled((VLAPIC(v))) )
|
||||
#endif
|
||||
clear_bit(X86_FEATURE_APIC, &edx);
|
||||
|
||||
#if CONFIG_PAGING_LEVELS < 3
|
||||
|
||||
@@ -88,9 +88,6 @@
|
||||
#define STGI .byte 0x0F,0x01,0xDC
|
||||
#define CLGI .byte 0x0F,0x01,0xDD
|
||||
|
||||
#define DO_TSC_OFFSET 0
|
||||
#define DO_FPUSAVE 0
|
||||
|
||||
ENTRY(svm_asm_do_launch)
|
||||
sti
|
||||
CLGI
|
||||
@@ -101,36 +98,6 @@ ENTRY(svm_asm_do_launch)
|
||||
movl VCPU_svm_hsa_pa(%ebx), %eax
|
||||
VMSAVE
|
||||
|
||||
#if DO_FPUSAVE
|
||||
mov %cr0, %eax
|
||||
push %eax
|
||||
clts
|
||||
lea VCPU_arch_guest_fpu_ctxt(%ebx), %eax
|
||||
fxrstor (%eax)
|
||||
pop %eax
|
||||
mov %eax, %cr0
|
||||
#endif
|
||||
|
||||
#if (DO_TSC_OFFSET)
|
||||
pushl %edx /* eax and edx get trashed by rdtsc */
|
||||
pushl %eax
|
||||
rdtsc
|
||||
subl VCPU_svm_vmexit_tsc(%ebx),%eax /* tsc's from */
|
||||
sbbl VCPU_svm_vmexit_tsc+4(%ebx),%edx /* last #VMEXIT? */
|
||||
subl %eax,VMCB_tsc_offset(%ecx) /* subtract from running TSC_OFFSET */
|
||||
sbbl %edx,VMCB_tsc_offset+4(%ecx)
|
||||
subl $20000,VMCB_tsc_offset(%ecx) /* fudge factor for VMXXX calls */
|
||||
sbbl $0,VMCB_tsc_offset+4(%ecx)
|
||||
|
||||
/*
|
||||
* TODO: may need to add a kludge factor to account for all the cycles
|
||||
* burned in VMLOAD, VMSAVE, VMRUN...
|
||||
*/
|
||||
|
||||
popl %eax
|
||||
popl %edx
|
||||
#endif
|
||||
|
||||
movl VCPU_svm_vmcb_pa(%ebx), %eax
|
||||
popl %ebx
|
||||
popl %ecx
|
||||
@@ -150,31 +117,7 @@ ENTRY(svm_asm_do_launch)
|
||||
VMSAVE
|
||||
/* eax is the only register we're allowed to touch here... */
|
||||
|
||||
#if DO_FPUSAVE
|
||||
mov %cr0, %eax
|
||||
push %eax
|
||||
clts
|
||||
GET_CURRENT(%eax)
|
||||
lea VCPU_arch_guest_fpu_ctxt(%eax), %eax
|
||||
fxsave (%eax)
|
||||
fnclex
|
||||
pop %eax
|
||||
mov %eax, %cr0
|
||||
#endif
|
||||
|
||||
GET_CURRENT(%eax)
|
||||
|
||||
#if (DO_TSC_OFFSET)
|
||||
pushl %edx
|
||||
pushl %ebx
|
||||
movl %eax,%ebx
|
||||
rdtsc
|
||||
movl %eax,VCPU_svm_vmexit_tsc(%ebx)
|
||||
movl %edx,VCPU_svm_vmexit_tsc+4(%ebx)
|
||||
movl %ebx,%eax
|
||||
popl %ebx
|
||||
popl %edx
|
||||
#endif
|
||||
|
||||
movl VCPU_svm_hsa_pa(%eax), %eax
|
||||
VMLOAD
|
||||
|
||||
+11
-14
@@ -506,7 +506,6 @@ get_page_from_l2e(
|
||||
vaddr <<= PGT_va_shift;
|
||||
rc = get_page_and_type_from_pagenr(
|
||||
l2e_get_pfn(l2e), PGT_l1_page_table | vaddr, d);
|
||||
|
||||
#if CONFIG_PAGING_LEVELS == 2
|
||||
if ( unlikely(!rc) )
|
||||
rc = get_linear_pagetable(l2e, pfn, d);
|
||||
@@ -3187,8 +3186,8 @@ static int ptwr_emulated_update(
|
||||
ptwr_flush(d, PTWR_PT_INACTIVE);
|
||||
|
||||
/* Read the PTE that maps the page being updated. */
|
||||
if (__copy_from_user(&pte, &linear_pg_table[l1_linear_offset(addr)],
|
||||
sizeof(pte)))
|
||||
if ( __copy_from_user(&pte, &linear_pg_table[l1_linear_offset(addr)],
|
||||
sizeof(pte)) )
|
||||
{
|
||||
MEM_LOG("ptwr_emulate: Cannot read thru linear_pg_table");
|
||||
return X86EMUL_UNHANDLEABLE;
|
||||
@@ -3198,15 +3197,10 @@ static int ptwr_emulated_update(
|
||||
page = mfn_to_page(pfn);
|
||||
|
||||
/* We are looking only for read-only mappings of p.t. pages. */
|
||||
if ( ((l1e_get_flags(pte) & (_PAGE_RW|_PAGE_PRESENT)) != _PAGE_PRESENT) ||
|
||||
((page->u.inuse.type_info & PGT_type_mask) != PGT_l1_page_table) ||
|
||||
(page_get_owner(page) != d) )
|
||||
{
|
||||
MEM_LOG("ptwr_emulate: Page is mistyped or bad pte "
|
||||
"(%lx, %" PRtype_info ")",
|
||||
l1e_get_pfn(pte), page->u.inuse.type_info);
|
||||
return X86EMUL_UNHANDLEABLE;
|
||||
}
|
||||
ASSERT((l1e_get_flags(pte) & (_PAGE_RW|_PAGE_PRESENT)) == _PAGE_PRESENT);
|
||||
ASSERT((page->u.inuse.type_info & PGT_type_mask) == PGT_l1_page_table);
|
||||
ASSERT((page->u.inuse.type_info & PGT_count_mask) != 0);
|
||||
ASSERT(page_get_owner(page) == d);
|
||||
|
||||
/* Check the new PTE. */
|
||||
nl1e = l1e_from_intpte(val);
|
||||
@@ -3266,8 +3260,11 @@ static int ptwr_emulated_cmpxchg8b(
|
||||
unsigned long new,
|
||||
unsigned long new_hi)
|
||||
{
|
||||
return ptwr_emulated_update(
|
||||
addr, ((u64)old_hi << 32) | old, ((u64)new_hi << 32) | new, 8, 1);
|
||||
if ( CONFIG_PAGING_LEVELS == 2 )
|
||||
return X86EMUL_UNHANDLEABLE;
|
||||
else
|
||||
return ptwr_emulated_update(
|
||||
addr, ((u64)old_hi << 32) | old, ((u64)new_hi << 32) | new, 8, 1);
|
||||
}
|
||||
|
||||
static struct x86_mem_emulator ptwr_mem_emulator = {
|
||||
|
||||
@@ -279,8 +279,8 @@ alloc_shadow_page(struct domain *d,
|
||||
psh_type == PGT_l4_shadow ) /* allocated for PAE PDP page */
|
||||
page = alloc_domheap_pages(NULL, 0, ALLOC_DOM_DMA);
|
||||
else if ( d->arch.ops->guest_paging_levels == PAGING_L3 &&
|
||||
psh_type == PGT_l3_shadow ) /* allocated for PAE PDP page */
|
||||
page = alloc_domheap_pages(NULL, 0, ALLOC_DOM_DMA);
|
||||
(psh_type == PGT_l3_shadow || psh_type == PGT_l4_shadow) )
|
||||
page = alloc_domheap_pages(NULL, 0, ALLOC_DOM_DMA); /* allocated for PAE PDP page */
|
||||
else
|
||||
page = alloc_domheap_page(NULL);
|
||||
#endif
|
||||
|
||||
@@ -11,15 +11,40 @@
|
||||
#include <xen/mm.h>
|
||||
#include <xen/perfc.h>
|
||||
#include <xen/domain_page.h>
|
||||
#include <xen/shadow.h>
|
||||
#include <asm/current.h>
|
||||
#include <asm/flushtlb.h>
|
||||
#include <asm/hardirq.h>
|
||||
|
||||
static inline struct vcpu *mapcache_current_vcpu(void)
|
||||
{
|
||||
struct vcpu *v;
|
||||
|
||||
/* In the common case we use the mapcache of the running VCPU. */
|
||||
v = current;
|
||||
|
||||
/*
|
||||
* If guest_table is NULL, and we are running a paravirtualised guest,
|
||||
* then it means we are running on the idle domain's page table and must
|
||||
* therefore use its mapcache.
|
||||
*/
|
||||
if ( unlikely(!pagetable_get_pfn(v->arch.guest_table)) && !HVM_DOMAIN(v) )
|
||||
{
|
||||
/* If we really are idling, perform lazy context switch now. */
|
||||
if ( (v = idle_vcpu[smp_processor_id()]) == current )
|
||||
__sync_lazy_execstate();
|
||||
/* We must now be running on the idle page table. */
|
||||
ASSERT(read_cr3() == __pa(idle_pg_table));
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
void *map_domain_page(unsigned long pfn)
|
||||
{
|
||||
unsigned long va;
|
||||
unsigned int idx, i, vcpu = current->vcpu_id;
|
||||
struct domain *d;
|
||||
unsigned int idx, i, vcpu;
|
||||
struct vcpu *v;
|
||||
struct mapcache *cache;
|
||||
struct vcpu_maphash_entry *hashent;
|
||||
|
||||
@@ -27,12 +52,10 @@ void *map_domain_page(unsigned long pfn)
|
||||
|
||||
perfc_incrc(map_domain_page_count);
|
||||
|
||||
/* If we are the idle domain, ensure that we run on our own page tables. */
|
||||
d = current->domain;
|
||||
if ( unlikely(is_idle_domain(d)) )
|
||||
__sync_lazy_execstate();
|
||||
v = mapcache_current_vcpu();
|
||||
|
||||
cache = &d->arch.mapcache;
|
||||
vcpu = v->vcpu_id;
|
||||
cache = &v->domain->arch.mapcache;
|
||||
|
||||
hashent = &cache->vcpu_maphash[vcpu].hash[MAPHASH_HASHFN(pfn)];
|
||||
if ( hashent->pfn == pfn )
|
||||
@@ -93,7 +116,8 @@ void *map_domain_page(unsigned long pfn)
|
||||
void unmap_domain_page(void *va)
|
||||
{
|
||||
unsigned int idx;
|
||||
struct mapcache *cache = ¤t->domain->arch.mapcache;
|
||||
struct vcpu *v;
|
||||
struct mapcache *cache;
|
||||
unsigned long pfn;
|
||||
struct vcpu_maphash_entry *hashent;
|
||||
|
||||
@@ -102,9 +126,13 @@ void unmap_domain_page(void *va)
|
||||
ASSERT((void *)MAPCACHE_VIRT_START <= va);
|
||||
ASSERT(va < (void *)MAPCACHE_VIRT_END);
|
||||
|
||||
v = mapcache_current_vcpu();
|
||||
|
||||
cache = &v->domain->arch.mapcache;
|
||||
|
||||
idx = ((unsigned long)va - MAPCACHE_VIRT_START) >> PAGE_SHIFT;
|
||||
pfn = l1e_get_pfn(cache->l1tab[idx]);
|
||||
hashent = &cache->vcpu_maphash[current->vcpu_id].hash[MAPHASH_HASHFN(pfn)];
|
||||
hashent = &cache->vcpu_maphash[v->vcpu_id].hash[MAPHASH_HASHFN(pfn)];
|
||||
|
||||
if ( hashent->idx == idx )
|
||||
{
|
||||
|
||||