# HG changeset patch
# User Isaku Yamahata <yamahata@xxxxxxxxxxxxx>
# Date 1220255983 -32400
# Node ID d0a544d8a3f3194dda7c928572ac191358cc2204
# Parent 48db4eee7d588ea340535ae3ef60862686207210
# Parent 05c7efee10a1d253b9b7f8b52464627aff441931
merge with xen-unstable.hg
---
docs/misc/vtpm.txt | 4
docs/src/user.tex | 71 +++-----
docs/xen-api/xenapi-datamodel-graph.dot | 2
extras/mini-os/include/posix/dirent.h | 2
extras/mini-os/include/posix/err.h | 15 +
extras/mini-os/include/posix/pthread.h | 7
extras/mini-os/include/posix/syslog.h | 37 ++++
extras/mini-os/include/xenbus.h | 7
extras/mini-os/lib/sys.c | 153 +++++++++++++++---
extras/mini-os/main.c | 35 +++-
extras/mini-os/xenbus/xenbus.c | 6
stubdom/Makefile | 4
tools/Makefile | 3
tools/Rules.mk | 3
tools/cross-install | 2
tools/examples/xmexample.pv-grub | 28 ---
tools/firmware/hvmloader/32bitbios_support.c | 2
tools/firmware/hvmloader/acpi/Makefile | 6
tools/firmware/hvmloader/acpi/build.c | 4
tools/firmware/hvmloader/hvmloader.c | 25 ++
tools/firmware/hvmloader/util.c | 21 +-
tools/firmware/hvmloader/util.h | 2
tools/ioemu/hw/cirrus_vga.c | 218 +++++++++-----------------
tools/ioemu/hw/ide.c | 28 +--
tools/ioemu/hw/pass-through.c | 5
tools/ioemu/hw/vga.c | 150 +++++++++++++----
tools/ioemu/hw/vga_int.h | 4
tools/ioemu/hw/xen_platform.c | 38 ++++
tools/ioemu/vl.c | 32 ---
tools/ioemu/vl.h | 3
tools/libxc/xc_dom_boot.c | 9 -
tools/libxc/xc_domain.c | 27 +++
tools/libxc/xc_domain_save.c | 6
tools/libxc/xc_minios.c | 10 -
tools/libxc/xenctrl.h | 6
tools/pygrub/src/pygrub | 32 ++-
tools/python/xen/util/pci.py | 37 ++++
tools/python/xen/xend/XendConfig.py | 6
tools/python/xen/xend/XendDomain.py | 4
tools/python/xen/xend/XendDomainInfo.py | 60 ++++---
tools/python/xen/xend/image.py | 3
tools/python/xen/xend/server/DevController.py | 8
tools/python/xen/xend/server/pciif.py | 25 --
tools/xenmon/Makefile | 4
xen/Makefile | 6
xen/arch/ia64/xen/mm.c | 70 ++++++++
xen/arch/x86/acpi/power.c | 5
xen/arch/x86/cpu/amd.c | 138 ++++++++++++++++
xen/arch/x86/cpu/amd.h | 103 ++++++++++++
xen/arch/x86/hvm/emulate.c | 58 +++++-
xen/arch/x86/irq.c | 2
xen/arch/x86/microcode.c | 4
xen/arch/x86/mm.c | 58 ++++++
xen/arch/x86/platform_hypercall.c | 3
xen/arch/x86/time.c | 20 --
xen/arch/x86/x86_64/compat/mm.c | 14 +
xen/common/softirq.c | 1
xen/common/timer.c | 177 ++++++++++++++++-----
xen/common/xmalloc.c | 17 --
xen/drivers/passthrough/vtd/intremap.c | 89 +++++++---
xen/drivers/passthrough/vtd/iommu.c | 70 +++-----
xen/include/asm-x86/io_apic.h | 4
xen/include/asm-x86/msr-index.h | 3
xen/include/asm-x86/processor.h | 2
xen/include/asm-x86/softirq.h | 5
xen/include/public/memory.h | 17 ++
xen/include/public/platform.h | 2
xen/include/xen/compat.h | 4
xen/include/xen/iommu.h | 4
xen/include/xen/timer.h | 33 ++-
xen/include/xlat.lst | 1
xen/include/xsm/xsm.h | 6
xen/xsm/dummy.c | 6
xen/xsm/flask/hooks.c | 6
74 files changed, 1466 insertions(+), 616 deletions(-)
diff -r 48db4eee7d58 -r d0a544d8a3f3 docs/misc/vtpm.txt
--- a/docs/misc/vtpm.txt Mon Aug 25 19:04:37 2008 +0900
+++ b/docs/misc/vtpm.txt Mon Sep 01 16:59:43 2008 +0900
@@ -92,8 +92,8 @@ can be different. This is the case if fo
can be different. This is the case if for example that particular
instance is already used by another virtual machine. The association
of which TPM instance number is used by which virtual machine is
-kept in the file /etc/xen/vtpm.db. Associations are maintained by
-domain name and instance number.
+kept in the file /var/vtpm/vtpm.db. Associations are maintained by
+a xend-internal vTPM UUID and vTPM instance number.
Note: If you do not want TPM functionality for your user domain simply
leave out the 'vtpm' line in the configuration file.
diff -r 48db4eee7d58 -r d0a544d8a3f3 docs/src/user.tex
--- a/docs/src/user.tex Mon Aug 25 19:04:37 2008 +0900
+++ b/docs/src/user.tex Mon Sep 01 16:59:43 2008 +0900
@@ -22,7 +22,7 @@
\vfill
\begin{tabular}{l}
{\Huge \bf Users' Manual} \\[4mm]
-{\huge Xen v3.0} \\[80mm]
+{\huge Xen v3.3} \\[80mm]
\end{tabular}
\end{center}
@@ -42,9 +42,7 @@ welcome.}
\vspace*{\fill}
-Xen is Copyright \copyright 2002-2005, University of Cambridge, UK, XenSource
-Inc., IBM Corp., Hewlett-Packard Co., Intel Corp., AMD Inc., and others. All
-rights reserved.
+Xen is Copyright \copyright 2002-2008, Citrix Systems, Inc., University of
Cambridge, UK, XenSource Inc., IBM Corp., Hewlett-Packard Co., Intel Corp., AMD
Inc., and others. All rights reserved.
Xen is an open-source project. Most portions of Xen are licensed for copying
under the terms of the GNU General Public License, version 2. Other portions
@@ -116,16 +114,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE
Xen is an open-source \emph{para-virtualizing} virtual machine monitor
-(VMM), or ``hypervisor'', for the x86 processor architecture. Xen can
-securely execute multiple virtual machines on a single physical system
-with close-to-native performance. Xen facilitates enterprise-grade
-functionality, including:
+(VMM), or ``hypervisor'', for a variety of processor architectures including
x86. Xen can securely execute multiple virtual machines on a single physical
system with near native performance. Xen facilitates enterprise-grade
functionality, including:
\begin{itemize}
\item Virtual machines with performance close to native hardware.
\item Live migration of running virtual machines between physical hosts.
\item Up to 32\footnote{IA64 supports up to 64 virtual CPUs per guest virtual
machine} virtual CPUs per guest virtual machine, with VCPU hotplug.
-\item x86/32, x86/32 with PAE, x86/64, IA64 and Power platform support.
+\item x86/32 with PAE, x86/64, and IA64 platform support.
\item Intel and AMD Virtualization Technology for unmodified guest operating
systems (including Microsoft Windows).
\item Excellent hardware support (supports almost all Linux device
drivers).
@@ -182,22 +177,20 @@ unmodified guests running natively on th
Paravirtualized Xen support is available for increasingly many
operating systems: currently, mature Linux support is available and
-included in the standard distribution. Other OS ports---including
-NetBSD, FreeBSD and Solaris x86 v10---are nearing completion.
+included in the standard distribution. Other OS ports, including
+NetBSD, FreeBSD and Solaris are also complete.
\section{Hardware Support}
-Xen currently runs on the x86 architecture, requiring a ``P6'' or
-newer processor (e.g.\ Pentium Pro, Celeron, Pentium~II, Pentium~III,
-Pentium~IV, Xeon, AMD~Athlon, AMD~Duron). Multiprocessor machines are
-supported, and there is support for HyperThreading (SMT). In
-addition, ports to IA64 and Power architectures are supported.
-
-The default 32-bit Xen supports for Intel's Physical Addressing Extensions
(PAE), which enable x86/32 machines to address up to 64 GB of physical memory.
-It also supports non-PAE 32-bit Xen up to 4GB of memory.
-Xen also supports x86/64 platforms such as Intel EM64T and AMD Opteron
-which can currently address up to 1TB of physical memory.
+Xen currently runs on the IA64 and x86 architectures. Multiprocessor
+machines are supported, and there is support for HyperThreading (SMT).
+
+The default 32-bit Xen requires processor support for Physical
+Addressing Extensions (PAE), which enables the hypervisor to address
+up to 16GB of physical memory. Xen also supports x86/64 platforms
+such as Intel EM64T and AMD Opteron which can currently address up to
+1TB of physical memory.
Xen offloads most of the hardware support issues to the guest OS
running in the \emph{Domain~0} management virtual machine. Xen itself
@@ -253,8 +246,8 @@ Xen has grown into a fully-fledged proje
Xen has grown into a fully-fledged project in its own right, enabling us
to investigate interesting research issues regarding the best techniques
for virtualizing resources such as the CPU, memory, disk and network.
-Project contributors now include XenSource, Intel, IBM, HP, AMD, Novell,
-RedHat.
+Project contributors now include Citrix, Intel, IBM, HP, AMD, Novell,
+RedHat, Sun, Fujitsu, and Samsung.
Xen was first described in a paper presented at SOSP in
2003\footnote{\tt
@@ -265,25 +258,20 @@ sites.
\section{What's New}
-Xen 3.0.0 offers:
+Xen 3.3.0 offers:
\begin{itemize}
-\item Support for up to 32-way SMP guest operating systems
-\item Intel (Physical Addressing Extensions) PAE to support 32-bit
- servers with more than 4GB physical memory
-\item x86/64 support (Intel EM64T, AMD Opteron)
-\item Intel VT-x support to enable the running of unmodified guest
-operating systems (Windows XP/2003, Legacy Linux)
-\item Enhanced control tools
-\item Improved ACPI support
-\item AGP/DRM graphics
+\item IO Emulation (stub domains) for HVM IO performance and scailability
+\item Replacement of Intel VT vmxassist by new 16b emulation code
+\item Improved VT-d device pass-through e.g. for graphics devices
+\item Enhanced C and P state power management
+\item Exploitation of multi-queue support on modern NICs
+\item Removal of domain lock for improved PV guest scalability
+\item 2MB page support for HVM and PV guests
+\item CPU Portability
\end{itemize}
-
-Xen 3.0 features greatly enhanced hardware support, configuration
-flexibility, usability and a larger complement of supported operating
-systems. This latest release takes Xen a step closer to being the
-definitive open source solution for virtualization.
+Xen 3.3 delivers the capabilities needed by enterprise customers and gives
computing industry leaders a solid, secure platform to build upon for their
virtualization solutions. This latest release establishes Xen as the definitive
open source solution for virtualization.
@@ -295,7 +283,7 @@ The Xen distribution includes three main
The Xen distribution includes three main components: Xen itself, ports
of Linux and NetBSD to run on Xen, and the userspace tools required to
manage a Xen-based system. This chapter describes how to install the
-Xen~3.0 distribution from source. Alternatively, there may be pre-built
+Xen~3.3 distribution from source. Alternatively, there may be pre-built
packages available as part of your operating system distribution.
@@ -4029,9 +4017,8 @@ files: \path{Config.mk} and \path{Makefi
The former allows the overall build target architecture to be
specified. You will typically not need to modify this unless
-you are cross-compiling or if you wish to build a non-PAE
-Xen system. Additional configuration options are documented
-in the \path{Config.mk} file.
+you are cross-compiling. Additional configuration options are
+documented in the \path{Config.mk} file.
The top-level \path{Makefile} is chiefly used to customize the set of
kernels built. Look for the line:
diff -r 48db4eee7d58 -r d0a544d8a3f3 docs/xen-api/xenapi-datamodel-graph.dot
--- a/docs/xen-api/xenapi-datamodel-graph.dot Mon Aug 25 19:04:37 2008 +0900
+++ b/docs/xen-api/xenapi-datamodel-graph.dot Mon Sep 01 16:59:43 2008 +0900
@@ -14,7 +14,7 @@ fontname="Verdana";
node [ shape=box ]; session VM host network VIF PIF SR VDI VBD PBD user
XSPolicy ACMPolicy;
node [shape=ellipse]; PIF_metrics VIF_metrics VM_metrics VBD_metrics
PBD_metrics VM_guest_metrics host_metrics;
-node [shape=box]; DPCI PPCI host_cpu console
+node [shape=box]; DPCI PPCI host_cpu console VTPM
session -> host [ arrowhead="none" ]
session -> user [ arrowhead="none" ]
VM -> VM_metrics [ arrowhead="none" ]
diff -r 48db4eee7d58 -r d0a544d8a3f3 extras/mini-os/include/posix/dirent.h
--- a/extras/mini-os/include/posix/dirent.h Mon Aug 25 19:04:37 2008 +0900
+++ b/extras/mini-os/include/posix/dirent.h Mon Sep 01 16:59:43 2008 +0900
@@ -1,7 +1,7 @@
#ifndef _POSIX_DIRENT_H
#define _POSIX_DIRENT_H
-#include <sys/types.h>
+#include <stdint.h>
struct dirent {
char *d_name;
diff -r 48db4eee7d58 -r d0a544d8a3f3 extras/mini-os/include/posix/err.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/mini-os/include/posix/err.h Mon Sep 01 16:59:43 2008 +0900
@@ -0,0 +1,15 @@
+#ifndef _POSIX_ERR_H
+#define _POSIX_ERR_H
+
+#include <stdarg.h>
+
+void err(int eval, const char *fmt, ...);
+void errx(int eval, const char *fmt, ...);
+void warn(const char *fmt, ...);
+void warnx(const char *fmt, ...);
+void verr(int eval, const char *fmt, va_list args);
+void verrx(int eval, const char *fmt, va_list args);
+void vwarn(const char *fmt, va_list args);
+void vwarnx(const char *fmt, va_list args);
+
+#endif /* _POSIX_ERR_H */
diff -r 48db4eee7d58 -r d0a544d8a3f3 extras/mini-os/include/posix/pthread.h
--- a/extras/mini-os/include/posix/pthread.h Mon Aug 25 19:04:37 2008 +0900
+++ b/extras/mini-os/include/posix/pthread.h Mon Sep 01 16:59:43 2008 +0900
@@ -31,8 +31,15 @@ static inline int pthread_key_delete(pth
+typedef struct {} pthread_mutexattr_t;
+static inline int pthread_mutexattr_init(pthread_mutexattr_t *mattr) { return
0; }
+#define PTHREAD_MUTEX_NORMAL 0
+#define PTHREAD_MUTEX_RECURSIVE 1
+static inline int pthread_mutexattr_settype(pthread_mutexattr_t *mattr, int
kind) { return 0; }
+static inline int pthread_mutexattr_destroy(pthread_mutexattr_t *mattr) {
return 0; }
typedef struct {} pthread_mutex_t;
#define PTHREAD_MUTEX_INITIALIZER {}
+static inline int pthread_mutex_init(pthread_mutex_t *mutex,
pthread_mutexattr_t *mattr) { return 0; }
static inline int pthread_mutex_lock(pthread_mutex_t *mutex) { return 0; }
static inline int pthread_mutex_unlock(pthread_mutex_t *mutex) { return 0; }
diff -r 48db4eee7d58 -r d0a544d8a3f3 extras/mini-os/include/posix/syslog.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/mini-os/include/posix/syslog.h Mon Sep 01 16:59:43 2008 +0900
@@ -0,0 +1,37 @@
+#ifndef _POSIX_SYSLOG_H
+#define _POSIX_SYSLOG_H
+
+#include <stdarg.h>
+
+#define LOG_PID 0
+#define LOG_CONS 0
+#define LOG_NDELAY 0
+#define LOG_ODELAY 0
+#define LOG_NOWAIT 0
+
+#define LOG_KERN 0
+#define LOG_USER 0
+#define LOG_MAIL 0
+#define LOG_NEWS 0
+#define LOG_UUCP 0
+#define LOG_DAEMON 0
+#define LOG_AUTH 0
+#define LOG_CRON 0
+#define LOG_LPR 0
+
+/* TODO: support */
+#define LOG_EMERG 0
+#define LOG_ALERT 1
+#define LOG_CRIT 2
+#define LOG_ERR 3
+#define LOG_WARNING 4
+#define LOG_NOTICE 5
+#define LOG_INFO 6
+#define LOG_DEBUG 7
+
+void openlog(const char *ident, int option, int facility);
+void syslog(int priority, const char *format, ...);
+void closelog(void);
+void vsyslog(int priority, const char *format, va_list ap);
+
+#endif /* _POSIX_SYSLOG_H */
diff -r 48db4eee7d58 -r d0a544d8a3f3 extras/mini-os/include/xenbus.h
--- a/extras/mini-os/include/xenbus.h Mon Aug 25 19:04:37 2008 +0900
+++ b/extras/mini-os/include/xenbus.h Mon Sep 01 16:59:43 2008 +0900
@@ -83,12 +83,13 @@ char *xenbus_transaction_end(xenbus_tran
int *retry);
/* Read path and parse it as an integer. Returns -1 on error. */
-int xenbus_read_integer(char *path);
+int xenbus_read_integer(const char *path);
/* Contraction of snprintf and xenbus_write(path/node). */
char* xenbus_printf(xenbus_transaction_t xbt,
- char* node, char* path,
- char* fmt, ...);
+ const char* node, const char* path,
+ const char* fmt, ...)
+ __attribute__((__format__(printf, 4, 5)));
/* Reset the XenBus system. */
void fini_xenbus(void);
diff -r 48db4eee7d58 -r d0a544d8a3f3 extras/mini-os/lib/sys.c
--- a/extras/mini-os/lib/sys.c Mon Aug 25 19:04:37 2008 +0900
+++ b/extras/mini-os/lib/sys.c Mon Sep 01 16:59:43 2008 +0900
@@ -1007,6 +1007,96 @@ LWIP_STUB(int, getsockname, (int s, stru
LWIP_STUB(int, getsockname, (int s, struct sockaddr *name, socklen_t
*namelen), (s, name, namelen))
#endif
+static char *syslog_ident;
+void openlog(const char *ident, int option, int facility)
+{
+ if (syslog_ident)
+ free(syslog_ident);
+ syslog_ident = strdup(ident);
+}
+
+void vsyslog(int priority, const char *format, va_list ap)
+{
+ printk("%s: ", syslog_ident);
+ print(0, format, ap);
+}
+
+void syslog(int priority, const char *format, ...)
+{
+ va_list ap;
+ va_start(ap, format);
+ vsyslog(priority, format, ap);
+ va_end(ap);
+}
+
+void closelog(void)
+{
+ free(syslog_ident);
+ syslog_ident = NULL;
+}
+
+void vwarn(const char *format, va_list ap)
+{
+ int the_errno = errno;
+ printk("stubdom: ");
+ if (format) {
+ print(0, format, ap);
+ printk(", ");
+ }
+ printk("%s", strerror(the_errno));
+}
+
+void warn(const char *format, ...)
+{
+ va_list ap;
+ va_start(ap, format);
+ vwarn(format, ap);
+ va_end(ap);
+}
+
+void verr(int eval, const char *format, va_list ap)
+{
+ vwarn(format, ap);
+ exit(eval);
+}
+
+void err(int eval, const char *format, ...)
+{
+ va_list ap;
+ va_start(ap, format);
+ verr(eval, format, ap);
+ va_end(ap);
+}
+
+void vwarnx(const char *format, va_list ap)
+{
+ printk("stubdom: ");
+ if (format)
+ print(0, format, ap);
+}
+
+void warnx(const char *format, ...)
+{
+ va_list ap;
+ va_start(ap, format);
+ vwarnx(format, ap);
+ va_end(ap);
+}
+
+void verrx(int eval, const char *format, va_list ap)
+{
+ vwarnx(format, ap);
+ exit(eval);
+}
+
+void errx(int eval, const char *format, ...)
+{
+ va_list ap;
+ va_start(ap, format);
+ verrx(eval, format, ap);
+ va_end(ap);
+}
+
int nanosleep(const struct timespec *req, struct timespec *rem)
{
s_time_t start = NOW();
@@ -1115,34 +1205,47 @@ void *mmap(void *start, size_t length, i
} else ASSERT(0);
}
+#define UNMAP_BATCH ((STACK_SIZE / 2) / sizeof(multicall_entry_t))
int munmap(void *start, size_t length)
{
- int i, n = length / PAGE_SIZE;
- multicall_entry_t call[n];
- unsigned char (*data)[PAGE_SIZE] = start;
- int ret;
+ int total = length / PAGE_SIZE;
ASSERT(!((unsigned long)start & ~PAGE_MASK));
- ASSERT(!(length & ~PAGE_MASK));
-
- for (i = 0; i < n; i++) {
- call[i].op = __HYPERVISOR_update_va_mapping;
- call[i].args[0] = (unsigned long) &data[i];
- call[i].args[1] = 0;
- call[i].args[2] = 0;
- call[i].args[3] = UVMF_INVLPG;
- }
-
- ret = HYPERVISOR_multicall(call, n);
- if (ret) {
- errno = -ret;
- return -1;
- }
-
- for (i = 0; i < n; i++) {
- if (call[i].result) {
- errno = call[i].result;
- return -1;
- }
+ while (total) {
+ int n = UNMAP_BATCH;
+ if (n > total)
+ n = total;
+ {
+ int i;
+ multicall_entry_t call[n];
+ unsigned char (*data)[PAGE_SIZE] = start;
+ int ret;
+
+ for (i = 0; i < n; i++) {
+ int arg = 0;
+ call[i].op = __HYPERVISOR_update_va_mapping;
+ call[i].args[arg++] = (unsigned long) &data[i];
+ call[i].args[arg++] = 0;
+#ifdef __i386__
+ call[i].args[arg++] = 0;
+#endif
+ call[i].args[arg++] = UVMF_INVLPG;
+ }
+
+ ret = HYPERVISOR_multicall(call, n);
+ if (ret) {
+ errno = -ret;
+ return -1;
+ }
+
+ for (i = 0; i < n; i++) {
+ if (call[i].result) {
+ errno = call[i].result;
+ return -1;
+ }
+ }
+ }
+ start = (char *)start + n * PAGE_SIZE;
+ total -= n;
}
return 0;
}
diff -r 48db4eee7d58 -r d0a544d8a3f3 extras/mini-os/main.c
--- a/extras/mini-os/main.c Mon Aug 25 19:04:37 2008 +0900
+++ b/extras/mini-os/main.c Mon Sep 01 16:59:43 2008 +0900
@@ -42,7 +42,7 @@ extern char __app_bss_start, __app_bss_e
extern char __app_bss_start, __app_bss_end;
static void call_main(void *p)
{
- char *c;
+ char *c, quote;
#ifdef CONFIG_QEMU
char *domargs, *msg;
#endif
@@ -101,32 +101,53 @@ static void call_main(void *p)
argc = 1;
-#define PARSE_ARGS(ARGS,START,END) \
+#define PARSE_ARGS(ARGS,START,QUOTE,END) \
c = ARGS; \
+ quote = 0; \
while (*c) { \
if (*c != ' ') { \
START; \
- while (*c && *c != ' ') \
+ while (*c) { \
+ if (quote) { \
+ if (*c == quote) { \
+ quote = 0; \
+ QUOTE; \
+ continue; \
+ } \
+ } else if (*c == ' ') \
+ break; \
+ if (*c == '"' || *c == '\'') { \
+ quote = *c; \
+ QUOTE; \
+ continue; \
+ } \
c++; \
+ } \
} else { \
END; \
while (*c == ' ') \
c++; \
} \
+ } \
+ if (quote) {\
+ printk("Warning: unterminated quotation %c\n", quote); \
+ quote = 0; \
}
+#define PARSE_ARGS_COUNT(ARGS) PARSE_ARGS(ARGS, argc++, c++, )
+#define PARSE_ARGS_STORE(ARGS) PARSE_ARGS(ARGS, argv[argc++] = c, memmove(c, c
+ 1, strlen(c + 1) + 1), *c++ = 0)
- PARSE_ARGS((char*)start_info.cmd_line, argc++, );
+ PARSE_ARGS_COUNT((char*)start_info.cmd_line);
#ifdef CONFIG_QEMU
- PARSE_ARGS(domargs, argc++, );
+ PARSE_ARGS_COUNT(domargs);
#endif
argv = alloca((argc + 1) * sizeof(char *));
argv[0] = "main";
argc = 1;
- PARSE_ARGS((char*)start_info.cmd_line, argv[argc++] = c, *c++ = 0)
+ PARSE_ARGS_STORE((char*)start_info.cmd_line)
#ifdef CONFIG_QEMU
- PARSE_ARGS(domargs, argv[argc++] = c, *c++ = 0)
+ PARSE_ARGS_STORE(domargs)
#endif
argv[argc] = NULL;
diff -r 48db4eee7d58 -r d0a544d8a3f3 extras/mini-os/xenbus/xenbus.c
--- a/extras/mini-os/xenbus/xenbus.c Mon Aug 25 19:04:37 2008 +0900
+++ b/extras/mini-os/xenbus/xenbus.c Mon Sep 01 16:59:43 2008 +0900
@@ -633,7 +633,7 @@ xenbus_transaction_end(xenbus_transactio
return NULL;
}
-int xenbus_read_integer(char *path)
+int xenbus_read_integer(const char *path)
{
char *res, *buf;
int t;
@@ -650,8 +650,8 @@ int xenbus_read_integer(char *path)
}
char* xenbus_printf(xenbus_transaction_t xbt,
- char* node, char* path,
- char* fmt, ...)
+ const char* node, const char* path,
+ const char* fmt, ...)
{
#define BUFFER_SIZE 256
char fullpath[BUFFER_SIZE];
diff -r 48db4eee7d58 -r d0a544d8a3f3 stubdom/Makefile
--- a/stubdom/Makefile Mon Aug 25 19:04:37 2008 +0900
+++ b/stubdom/Makefile Mon Sep 01 16:59:43 2008 +0900
@@ -9,7 +9,7 @@ include $(XEN_ROOT)/Config.mk
override CONFIG_QEMU=ioemu
-IOEMU_OPTIONS=--disable-sdl --disable-opengl --disable-gfx-check
--disable-vnc-tls --disable-brlapi --disable-kqemu
+IOEMU_OPTIONS=--disable-sdl --disable-opengl --disable-vnc-tls
--disable-brlapi --disable-kqemu
ZLIB_URL?=http://www.zlib.net
ZLIB_VERSION=1.2.3
LIBPCI_URL?=http://www.kernel.org/pub/software/utils/pciutils
@@ -53,7 +53,7 @@ TARGET_CFLAGS += $(call cc-option,$(CC),
TARGET_CFLAGS += $(call cc-option,$(CC),-fno-stack-protector-all,)
# Do not use host headers and libs
-GCC_INSTALL = $(shell gcc -print-search-dirs | sed -n -e 's/install:
\(.*\)/\1/p')
+GCC_INSTALL = $(shell LANG=C gcc -print-search-dirs | sed -n -e 's/install:
\(.*\)/\1/p')
TARGET_CPPFLAGS += -U __linux__ -U __FreeBSD__ -U __sun__
TARGET_CPPFLAGS += -nostdinc
TARGET_CPPFLAGS += -isystem $(CURDIR)/$(MINI_OS)/include/posix
diff -r 48db4eee7d58 -r d0a544d8a3f3 tools/Makefile
--- a/tools/Makefile Mon Aug 25 19:04:37 2008 +0900
+++ b/tools/Makefile Mon Sep 01 16:59:43 2008 +0900
@@ -59,8 +59,7 @@ ifneq ($(XEN_COMPILE_ARCH),$(XEN_TARGET_
ifneq ($(XEN_COMPILE_ARCH),$(XEN_TARGET_ARCH))
IOEMU_CONFIGURE_CROSS ?= --cpu=$(XEN_TARGET_ARCH) \
--cross-prefix=$(CROSS_COMPILE) \
- --interp-prefix=$(CROSS_SYS_ROOT) \
- --install=$(CURDIR)/cross-install
+ --interp-prefix=$(CROSS_SYS_ROOT)
endif
ioemu/config-host.mak:
diff -r 48db4eee7d58 -r d0a544d8a3f3 tools/Rules.mk
--- a/tools/Rules.mk Mon Aug 25 19:04:37 2008 +0900
+++ b/tools/Rules.mk Mon Sep 01 16:59:43 2008 +0900
@@ -4,6 +4,9 @@ all:
all:
include $(XEN_ROOT)/Config.mk
+
+export _INSTALL := $(INSTALL)
+INSTALL = $(XEN_ROOT)/tools/cross-install
XEN_INCLUDE = $(XEN_ROOT)/tools/include
XEN_XC = $(XEN_ROOT)/tools/python/xen/lowlevel/xc
diff -r 48db4eee7d58 -r d0a544d8a3f3 tools/cross-install
--- a/tools/cross-install Mon Aug 25 19:04:37 2008 +0900
+++ b/tools/cross-install Mon Sep 01 16:59:43 2008 +0900
@@ -5,4 +5,4 @@ if [ -n "$CROSS_BIN_PATH" ]; then
PATH="$CROSS_BIN_PATH:$PATH"
fi
-exec install "$@"
+exec $_INSTALL "$@"
diff -r 48db4eee7d58 -r d0a544d8a3f3 tools/examples/xmexample.pv-grub
--- a/tools/examples/xmexample.pv-grub Mon Aug 25 19:04:37 2008 +0900
+++ b/tools/examples/xmexample.pv-grub Mon Sep 01 16:59:43 2008 +0900
@@ -25,7 +25,7 @@ extra = "(hd0,0)/boot/grub/menu.lst"
# WARNING: Creating a domain with insufficient memory may cause out of
# memory errors. The domain needs enough memory to boot kernel
# and modules. Allocating less than 32MBs is not recommended.
-memory = 64
+memory = 128
# A name for your domain. All domains must have different names.
name = "ExampleDomain"
@@ -119,32 +119,6 @@ disk = [ 'phy:hda1,hda1,w' ]
#vtpm = [ 'instance=1,backend=0' ]
#----------------------------------------------------------------------------
-# Set the kernel command line for the new domain.
-# You only need to define the IP parameters and hostname if the domain's
-# IP config doesn't, e.g. in ifcfg-eth0 or via DHCP.
-# You can use 'extra' to set the runlevel and custom environment
-# variables used by custom rc scripts (e.g. VMID=, usr= ).
-
-# Set if you want dhcp to allocate the IP address.
-#dhcp="dhcp"
-# Set netmask.
-#netmask=
-# Set default gateway.
-#gateway=
-# Set the hostname.
-#hostname= "vm%d" % vmid
-
-# Set root device.
-root = "/dev/hda1 ro"
-
-# Root device for nfs.
-#root = "/dev/nfs"
-# The nfs server.
-#nfs_server = '192.0.2.1'
-# Root directory on the nfs server.
-#nfs_root = '/full/path/to/root/directory'
-
-#----------------------------------------------------------------------------
# Configure the behaviour when a domain exits. There are three 'reasons'
# for a domain to stop: poweroff, reboot, and crash. For each of these you
# may specify:
diff -r 48db4eee7d58 -r d0a544d8a3f3
tools/firmware/hvmloader/32bitbios_support.c
--- a/tools/firmware/hvmloader/32bitbios_support.c Mon Aug 25 19:04:37
2008 +0900
+++ b/tools/firmware/hvmloader/32bitbios_support.c Mon Sep 01 16:59:43
2008 +0900
@@ -76,7 +76,7 @@ static void relocate_32bitbios(char *elf
*/
reloc_size = reloc_off;
printf("%d bytes of ROMBIOS high-memory extensions:\n", reloc_size);
- highbiosarea = (char *)(long)e820_malloc(reloc_size);
+ highbiosarea = (char *)(long)e820_malloc(reloc_size, 0);
BUG_ON(highbiosarea == NULL);
printf(" Relocating to 0x%x-0x%x ... ",
(uint32_t)&highbiosarea[0],
diff -r 48db4eee7d58 -r d0a544d8a3f3 tools/firmware/hvmloader/acpi/Makefile
--- a/tools/firmware/hvmloader/acpi/Makefile Mon Aug 25 19:04:37 2008 +0900
+++ b/tools/firmware/hvmloader/acpi/Makefile Mon Sep 01 16:59:43 2008 +0900
@@ -22,8 +22,8 @@ H_SRC = $(wildcard *.h)
H_SRC = $(wildcard *.h)
OBJS = $(patsubst %.c,%.o,$(C_SRC))
-IASL_VER = acpica-unix-20060707
-IASL_URL =
http://developer.intel.com/technology/iapc/acpi/downloads/$(IASL_VER).tar.gz
+IASL_VER = acpica-unix-20080729
+IASL_URL = http://acpica.org/download/$(IASL_VER).tar.gz
CFLAGS += -I. -I.. $(CFLAGS_include)
@@ -48,7 +48,7 @@ iasl:
@echo "ACPI ASL compiler(iasl) is needed"
@echo "Download Intel ACPI CA"
@echo "If wget failed, please download and compile manually from"
- @echo "http://developer.intel.com/technology/iapc/acpi/downloads.htm"
+ @echo "http://acpica.org/downloads/"
@echo
wget $(IASL_URL)
tar xzf $(IASL_VER).tar.gz
diff -r 48db4eee7d58 -r d0a544d8a3f3 tools/firmware/hvmloader/acpi/build.c
--- a/tools/firmware/hvmloader/acpi/build.c Mon Aug 25 19:04:37 2008 +0900
+++ b/tools/firmware/hvmloader/acpi/build.c Mon Sep 01 16:59:43 2008 +0900
@@ -233,7 +233,7 @@ static int construct_secondary_tables(ui
tcpa->header.oem_revision = ACPI_OEM_REVISION;
tcpa->header.creator_id = ACPI_CREATOR_ID;
tcpa->header.creator_revision = ACPI_CREATOR_REVISION;
- tcpa->lasa = e820_malloc(ACPI_2_0_TCPA_LAML_SIZE);
+ tcpa->lasa = e820_malloc(ACPI_2_0_TCPA_LAML_SIZE, 0);
if ( tcpa->lasa )
{
tcpa->laml = ACPI_2_0_TCPA_LAML_SIZE;
@@ -363,7 +363,7 @@ void acpi_build_tables(void)
memset(buf, 0, high_sz);
/* Allocate data area and set up ACPI tables there. */
- buf = (uint8_t *)e820_malloc(high_sz);
+ buf = (uint8_t *)e820_malloc(high_sz, 0);
__acpi_build_tables(buf, &low_sz, &high_sz);
printf(" - Lo data: %08lx-%08lx\n"
diff -r 48db4eee7d58 -r d0a544d8a3f3 tools/firmware/hvmloader/hvmloader.c
--- a/tools/firmware/hvmloader/hvmloader.c Mon Aug 25 19:04:37 2008 +0900
+++ b/tools/firmware/hvmloader/hvmloader.c Mon Sep 01 16:59:43 2008 +0900
@@ -243,6 +243,13 @@ static void pci_setup(void)
bars[i].bar_sz = bar_sz;
nr_bars++;
+
+ /* Skip the upper-half of the address for a 64-bit BAR. */
+ if ( (bar_data & (PCI_BASE_ADDRESS_SPACE |
+ PCI_BASE_ADDRESS_MEM_TYPE_MASK)) ==
+ (PCI_BASE_ADDRESS_SPACE_MEMORY |
+ PCI_BASE_ADDRESS_MEM_TYPE_64) )
+ bar++;
}
/* Map the interrupt. */
@@ -430,11 +437,13 @@ static void cmos_write_memory_size(void)
cmos_outb(0x35, (uint8_t)( alt_mem >> 8));
}
-static void init_xen_platform_io_base(void)
+static uint16_t init_xen_platform_io_base(void)
{
struct bios_info *bios_info = (struct bios_info *)ACPI_PHYSICAL_ADDRESS;
uint32_t devfn, bar_data;
uint16_t vendor_id, device_id;
+
+ bios_info->xen_pfiob = 0;
for ( devfn = 0; devfn < 128; devfn++ )
{
@@ -445,12 +454,16 @@ static void init_xen_platform_io_base(vo
bar_data = pci_readl(devfn, PCI_BASE_ADDRESS_0);
bios_info->xen_pfiob = bar_data & PCI_BASE_ADDRESS_IO_MASK;
}
+
+ return bios_info->xen_pfiob;
}
int main(void)
{
int vgabios_sz = 0, etherboot_sz = 0, rombios_sz, smbios_sz;
int extboot_sz = 0;
+ uint32_t vga_ram = 0;
+ uint16_t xen_pfiob;
printf("HVM Loader\n");
@@ -495,6 +508,12 @@ int main(void)
default:
printf("No emulated VGA adaptor ...\n");
break;
+ }
+
+ if ( virtual_vga != VGA_none )
+ {
+ vga_ram = e820_malloc(8 << 20, 4096);
+ printf("VGA RAM at %08x\n", vga_ram);
}
etherboot_sz = scan_etherboot_nic((void*)ETHERBOOT_PHYSICAL_ADDRESS);
@@ -537,7 +556,9 @@ int main(void)
ROMBIOS_PHYSICAL_ADDRESS,
ROMBIOS_PHYSICAL_ADDRESS + rombios_sz - 1);
- init_xen_platform_io_base();
+ xen_pfiob = init_xen_platform_io_base();
+ if ( xen_pfiob && vga_ram )
+ outl(xen_pfiob + 4, vga_ram);
printf("Invoking ROMBIOS ...\n");
return 0;
diff -r 48db4eee7d58 -r d0a544d8a3f3 tools/firmware/hvmloader/util.c
--- a/tools/firmware/hvmloader/util.c Mon Aug 25 19:04:37 2008 +0900
+++ b/tools/firmware/hvmloader/util.c Mon Sep 01 16:59:43 2008 +0900
@@ -325,35 +325,34 @@ static void e820_collapse(void)
}
}
-uint32_t e820_malloc(uint32_t size)
+uint32_t e820_malloc(uint32_t size, uint32_t align)
{
uint32_t addr;
int i;
struct e820entry *ent = (struct e820entry *)HVM_E820;
- /* Align allocation request to a reasonable boundary (1kB). */
- size = (size + 1023) & ~1023;
+ /* Align to at leats one kilobyte. */
+ if ( align < 1024 )
+ align = 1024;
for ( i = *HVM_E820_NR - 1; i >= 0; i-- )
{
- addr = ent[i].addr;
+ addr = (ent[i].addr + ent[i].size - size) & ~(align-1);
if ( (ent[i].type != E820_RAM) || /* not ram? */
- (ent[i].size < size) || /* too small? */
- (addr != ent[i].addr) || /* starts above 4gb? */
+ (addr < ent[i].addr) || /* too small or starts above 4gb? */
((addr + size) < addr) ) /* ends above 4gb? */
continue;
- if ( ent[i].size != size )
+ if ( addr != ent[i].addr )
{
memmove(&ent[i+1], &ent[i], (*HVM_E820_NR-i) * sizeof(*ent));
(*HVM_E820_NR)++;
- ent[i].size -= size;
- addr += ent[i].size;
+ ent[i].size = addr - ent[i].addr;
+ ent[i+1].addr = addr;
+ ent[i+1].size -= ent[i].size;
i++;
}
- ent[i].addr = addr;
- ent[i].size = size;
ent[i].type = E820_RESERVED;
e820_collapse();
diff -r 48db4eee7d58 -r d0a544d8a3f3 tools/firmware/hvmloader/util.h
--- a/tools/firmware/hvmloader/util.h Mon Aug 25 19:04:37 2008 +0900
+++ b/tools/firmware/hvmloader/util.h Mon Sep 01 16:59:43 2008 +0900
@@ -132,7 +132,7 @@ int vprintf(const char *fmt, va_list ap)
int vprintf(const char *fmt, va_list ap);
/* Reserve a RAM region in the e820 table. */
-uint32_t e820_malloc(uint32_t size);
+uint32_t e820_malloc(uint32_t size, uint32_t align);
/* Prepare the 32bit BIOS */
void highbios_setup(void);
diff -r 48db4eee7d58 -r d0a544d8a3f3 tools/ioemu/hw/cirrus_vga.c
--- a/tools/ioemu/hw/cirrus_vga.c Mon Aug 25 19:04:37 2008 +0900
+++ b/tools/ioemu/hw/cirrus_vga.c Mon Sep 01 16:59:43 2008 +0900
@@ -2543,34 +2543,28 @@ static CPUWriteMemoryFunc *cirrus_linear
cirrus_linear_bitblt_writel,
};
-static void *set_vram_mapping(unsigned long begin, unsigned long end)
-{
- xen_pfn_t *extent_start = NULL;
- unsigned long nr_extents;
- void *vram_pointer = NULL;
- int i;
-
- /* align begin and end address */
- begin = begin & TARGET_PAGE_MASK;
- end = begin + VGA_RAM_SIZE;
- end = (end + TARGET_PAGE_SIZE -1 ) & TARGET_PAGE_MASK;
- nr_extents = (end - begin) >> TARGET_PAGE_BITS;
-
- extent_start = malloc(sizeof(xen_pfn_t) * nr_extents);
- if (extent_start == NULL) {
- fprintf(stderr, "Failed malloc on set_vram_mapping\n");
- return NULL;
- }
-
- memset(extent_start, 0, sizeof(xen_pfn_t) * nr_extents);
-
- for (i = 0; i < nr_extents; i++)
- extent_start[i] = (begin + i * TARGET_PAGE_SIZE) >> TARGET_PAGE_BITS;
-
- if (set_mm_mapping(xc_handle, domid, nr_extents, 0, extent_start) < 0) {
- fprintf(logfile, "Failed set_mm_mapping\n");
- free(extent_start);
- return NULL;
+static void set_vram_mapping(CirrusVGAState *s, unsigned long begin, unsigned
long end)
+{
+ unsigned long i;
+ struct xen_add_to_physmap xatp;
+ int rc;
+
+ if (end > begin + VGA_RAM_SIZE)
+ end = begin + VGA_RAM_SIZE;
+
+ fprintf(logfile,"mapping vram to %lx - %lx\n", begin, end);
+
+ xatp.domid = domid;
+ xatp.space = XENMAPSPACE_mfn;
+
+ for (i = 0; i < (end - begin) >> TARGET_PAGE_BITS; i++) {
+ xatp.idx = s->vram_mfns[i];
+ xatp.gpfn = (begin >> TARGET_PAGE_BITS) + i;
+ rc = xc_memory_op(xc_handle, XENMEM_add_to_physmap, &xatp);
+ if (rc) {
+ fprintf(stderr, "add_to_physmap MFN %"PRI_xen_pfn" to PFN
%"PRI_xen_pfn" failed: %d\n", xatp.idx, xatp.gpfn, rc);
+ return;
+ }
}
(void)xc_domain_pin_memory_cacheattr(
@@ -2578,61 +2572,42 @@ static void *set_vram_mapping(unsigned l
begin >> TARGET_PAGE_BITS,
end >> TARGET_PAGE_BITS,
XEN_DOMCTL_MEM_CACHEATTR_WB);
-
- vram_pointer = xc_map_foreign_pages(xc_handle, domid,
- PROT_READ|PROT_WRITE,
- extent_start, nr_extents);
- if (vram_pointer == NULL) {
- fprintf(logfile, "xc_map_foreign_batch vgaram returned error %d\n",
- errno);
- free(extent_start);
- return NULL;
- }
-
- memset(vram_pointer, 0, nr_extents * TARGET_PAGE_SIZE);
-
-#ifdef CONFIG_STUBDOM
- xenfb_pv_display_start(vram_pointer);
-#endif
-
- free(extent_start);
-
- return vram_pointer;
-}
-
-static int unset_vram_mapping(unsigned long begin, unsigned long end,
- void *mapping)
-{
- xen_pfn_t *extent_start = NULL;
- unsigned long nr_extents;
- int i;
-
- /* align begin and end address */
-
- end = begin + VGA_RAM_SIZE;
- begin = begin & TARGET_PAGE_MASK;
- end = (end + TARGET_PAGE_SIZE -1 ) & TARGET_PAGE_MASK;
- nr_extents = (end - begin) >> TARGET_PAGE_BITS;
-
- extent_start = malloc(sizeof(xen_pfn_t) * nr_extents);
-
- if (extent_start == NULL) {
- fprintf(stderr, "Failed malloc on set_mm_mapping\n");
- return -1;
- }
-
- /* Drop our own references to the vram pages */
- munmap(mapping, nr_extents * TARGET_PAGE_SIZE);
-
- /* Now drop the guest's mappings */
- memset(extent_start, 0, sizeof(xen_pfn_t) * nr_extents);
- for (i = 0; i < nr_extents; i++)
- extent_start[i] = (begin + (i * TARGET_PAGE_SIZE)) >> TARGET_PAGE_BITS;
- unset_mm_mapping(xc_handle, domid, nr_extents, 0, extent_start);
-
- free(extent_start);
-
- return 0;
+}
+
+static void unset_vram_mapping(CirrusVGAState *s, unsigned long begin,
unsigned long end)
+{
+ if (s->stolen_vram_addr) {
+ /* We can put it there for xend to save it efficiently */
+ set_vram_mapping(s, s->stolen_vram_addr, s->stolen_vram_addr +
VGA_RAM_SIZE);
+ } else {
+ /* Old image, we have to unmap them completely */
+ struct xen_remove_from_physmap xrfp;
+ unsigned long i;
+ int rc;
+
+ if (end > begin + VGA_RAM_SIZE)
+ end = begin + VGA_RAM_SIZE;
+
+ fprintf(logfile,"unmapping vram from %lx - %lx\n", begin, end);
+
+ xrfp.domid = domid;
+
+ for (i = 0; i < (end - begin) >> TARGET_PAGE_BITS; i++) {
+ xrfp.gpfn = (begin >> TARGET_PAGE_BITS) + i;
+ rc = xc_memory_op(xc_handle, XENMEM_remove_from_physmap, &xrfp);
+ if (rc) {
+ fprintf(stderr, "remove_from_physmap PFN %"PRI_xen_pfn"
failed: %d\n", xrfp.gpfn, rc);
+ return;
+ }
+ }
+ }
+}
+
+void cirrus_restart_acc(CirrusVGAState *s)
+{
+ set_vram_mapping(s, s->lfb_addr, s->lfb_end);
+ s->map_addr = s->lfb_addr;
+ s->map_end = s->lfb_end;
}
/* Compute the memory access functions */
@@ -2654,17 +2629,7 @@ static void cirrus_update_memory_access(
mode = s->gr[0x05] & 0x7;
if (mode < 4 || mode > 5 || ((s->gr[0x0B] & 0x4) == 0)) {
if (s->lfb_addr && s->lfb_end && !s->map_addr) {
- void *vram_pointer, *old_vram;
-
- vram_pointer = set_vram_mapping(s->lfb_addr,
- s->lfb_end);
- if (!vram_pointer)
- fprintf(stderr, "NULL vram_pointer\n");
- else {
- old_vram = vga_update_vram((VGAState *)s, vram_pointer,
- VGA_RAM_SIZE);
- qemu_free(old_vram);
- }
+ set_vram_mapping(s, s->lfb_addr, s->lfb_end);
s->map_addr = s->lfb_addr;
s->map_end = s->lfb_end;
}
@@ -2674,14 +2639,7 @@ static void cirrus_update_memory_access(
} else {
generic_io:
if (s->lfb_addr && s->lfb_end && s->map_addr) {
- void *old_vram;
-
- old_vram = vga_update_vram((VGAState *)s, NULL, VGA_RAM_SIZE);
-
- unset_vram_mapping(s->lfb_addr,
- s->lfb_end,
- old_vram);
-
+ unset_vram_mapping(s, s->map_addr, s->map_end);
s->map_addr = s->map_end = 0;
}
s->cirrus_linear_write[0] = cirrus_linear_writeb;
@@ -3040,36 +2998,6 @@ static CPUWriteMemoryFunc *cirrus_mmio_w
cirrus_mmio_writel,
};
-void cirrus_stop_acc(CirrusVGAState *s)
-{
- if (s->map_addr){
- int error;
- s->map_addr = 0;
- error = unset_vram_mapping(s->lfb_addr,
- s->lfb_end, s->vram_ptr);
- fprintf(stderr, "cirrus_stop_acc:unset_vram_mapping.\n");
- }
-}
-
-void cirrus_restart_acc(CirrusVGAState *s)
-{
- if (s->lfb_addr && s->lfb_end) {
- void *vram_pointer, *old_vram;
- fprintf(stderr, "cirrus_vga_load:re-enable vga acc.lfb_addr=0x%lx,
lfb_end=0x%lx.\n",
- s->lfb_addr, s->lfb_end);
- vram_pointer = set_vram_mapping(s->lfb_addr ,s->lfb_end);
- if (!vram_pointer){
- fprintf(stderr, "cirrus_vga_load:NULL vram_pointer\n");
- } else {
- old_vram = vga_update_vram((VGAState *)s, vram_pointer,
- VGA_RAM_SIZE);
- qemu_free(old_vram);
- s->map_addr = s->lfb_addr;
- s->map_end = s->lfb_end;
- }
- }
-}
-
/* load/save state */
static void cirrus_vga_save(QEMUFile *f, void *opaque)
@@ -3118,7 +3046,10 @@ static void cirrus_vga_save(QEMUFile *f,
qemu_put_8s(f, &vga_acc);
qemu_put_be64s(f, (uint64_t*)&s->lfb_addr);
qemu_put_be64s(f, (uint64_t*)&s->lfb_end);
- qemu_put_buffer(f, s->vram_ptr, VGA_RAM_SIZE);
+ qemu_put_be64s(f, &s->stolen_vram_addr);
+ if (!s->stolen_vram_addr && !vga_acc)
+ /* Old guest: VRAM is not mapped, we have to save it ourselves */
+ qemu_put_buffer(f, s->vram_ptr, VGA_RAM_SIZE);
}
static int cirrus_vga_load(QEMUFile *f, void *opaque, int version_id)
@@ -3127,7 +3058,7 @@ static int cirrus_vga_load(QEMUFile *f,
uint8_t vga_acc = 0;
int ret;
- if (version_id > 2)
+ if (version_id > 3)
return -EINVAL;
if (s->pci_dev && version_id >= 2) {
@@ -3173,9 +3104,20 @@ static int cirrus_vga_load(QEMUFile *f,
qemu_get_8s(f, &vga_acc);
qemu_get_be64s(f, (uint64_t*)&s->lfb_addr);
qemu_get_be64s(f, (uint64_t*)&s->lfb_end);
- qemu_get_buffer(f, s->vram_ptr, VGA_RAM_SIZE);
- if (vga_acc){
- cirrus_restart_acc(s);
+ if (version_id >= 3) {
+ qemu_get_be64s(f, &s->stolen_vram_addr);
+ if (!s->stolen_vram_addr && !vga_acc) {
+ /* Old guest, VRAM is not mapped, we have to restore it ourselves
*/
+ qemu_get_buffer(f, s->vram_ptr, VGA_RAM_SIZE);
+ xen_vga_populate_vram(s->lfb_addr);
+ } else
+ xen_vga_vram_map(vga_acc ? s->lfb_addr : s->stolen_vram_addr, 0);
+ } else {
+ /* Old image, we have to populate and restore VRAM ourselves */
+ xen_vga_populate_vram(s->lfb_addr);
+ qemu_get_buffer(f, s->vram_ptr, VGA_RAM_SIZE);
+ if (vga_acc)
+ cirrus_restart_acc(s);
}
/* force refresh */
@@ -3297,7 +3239,7 @@ static void cirrus_init_common(CirrusVGA
s->cursor_invalidate = cirrus_cursor_invalidate;
s->cursor_draw_line = cirrus_cursor_draw_line;
- register_savevm("cirrus_vga", 0, 2, cirrus_vga_save, cirrus_vga_load, s);
+ register_savevm("cirrus_vga", 0, 3, cirrus_vga_save, cirrus_vga_load, s);
}
/***************************************
diff -r 48db4eee7d58 -r d0a544d8a3f3 tools/ioemu/hw/ide.c
--- a/tools/ioemu/hw/ide.c Mon Aug 25 19:04:37 2008 +0900
+++ b/tools/ioemu/hw/ide.c Mon Sep 01 16:59:43 2008 +0900
@@ -1108,14 +1108,14 @@ static void ide_flush_cb(void *opaque, i
return;
}
else
- s->status = READY_STAT;
+ s->status = READY_STAT | SEEK_STAT;
ide_set_irq(s);
}
static void ide_atapi_cmd_ok(IDEState *s)
{
s->error = 0;
- s->status = READY_STAT;
+ s->status = READY_STAT | SEEK_STAT;
s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD;
ide_set_irq(s);
}
@@ -1229,7 +1229,7 @@ static void ide_atapi_cmd_reply_end(IDES
if (s->packet_transfer_size <= 0) {
/* end of transfer */
ide_transfer_stop(s);
- s->status = READY_STAT;
+ s->status = READY_STAT | SEEK_STAT;
s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO |
ATAPI_INT_REASON_CD;
ide_set_irq(s);
#ifdef DEBUG_IDE_ATAPI
@@ -1307,10 +1307,10 @@ static void ide_atapi_cmd_reply(IDEState
s->io_buffer_index = 0;
if (s->atapi_dma) {
- s->status = READY_STAT | DRQ_STAT;
+ s->status = READY_STAT | SEEK_STAT | DRQ_STAT;
ide_dma_start(s, ide_atapi_cmd_read_dma_cb);
} else {
- s->status = READY_STAT;
+ s->status = READY_STAT | SEEK_STAT;
ide_atapi_cmd_reply_end(s);
}
}
@@ -1325,7 +1325,7 @@ static void ide_atapi_cmd_read_pio(IDESt
s->io_buffer_index = sector_size;
s->cd_sector_size = sector_size;
- s->status = READY_STAT;
+ s->status = READY_STAT | SEEK_STAT;
ide_atapi_cmd_reply_end(s);
}
@@ -1368,7 +1368,7 @@ static void ide_atapi_cmd_read_dma_cb(vo
}
if (s->packet_transfer_size <= 0) {
- s->status = READY_STAT;
+ s->status = READY_STAT | SEEK_STAT;
s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO |
ATAPI_INT_REASON_CD;
ide_set_irq(s);
eot:
@@ -1418,7 +1418,7 @@ static void ide_atapi_cmd_read_dma(IDESt
s->cd_sector_size = sector_size;
/* XXX: check if BUSY_STAT should be set */
- s->status = READY_STAT | DRQ_STAT | BUSY_STAT;
+ s->status = READY_STAT | SEEK_STAT | DRQ_STAT | BUSY_STAT;
ide_dma_start(s, ide_atapi_cmd_read_dma_cb);
}
@@ -1886,7 +1886,7 @@ static void ide_ioport_write(void *opaqu
ide_abort_command(s);
} else {
s->mult_sectors = s->nsector;
- s->status = READY_STAT;
+ s->status = READY_STAT | SEEK_STAT;
}
ide_set_irq(s);
break;
@@ -1896,7 +1896,7 @@ static void ide_ioport_write(void *opaqu
case WIN_VERIFY_ONCE:
/* do sector number check ? */
ide_cmd_lba48_transform(s, lba48);
- s->status = READY_STAT;
+ s->status = READY_STAT | SEEK_STAT;
ide_set_irq(s);
break;
case WIN_READ_EXT:
@@ -1965,12 +1965,12 @@ static void ide_ioport_write(void *opaqu
case WIN_READ_NATIVE_MAX:
ide_cmd_lba48_transform(s, lba48);
ide_set_sector(s, s->nb_sectors - 1);
- s->status = READY_STAT;
+ s->status = READY_STAT | SEEK_STAT;
ide_set_irq(s);
break;
case WIN_CHECKPOWERMODE1:
s->nsector = 0xff; /* device active or idle */
- s->status = READY_STAT;
+ s->status = READY_STAT | SEEK_STAT;
ide_set_irq(s);
break;
case WIN_SETFEATURES:
@@ -2070,7 +2070,7 @@ static void ide_ioport_write(void *opaqu
/* overlapping commands not supported */
if (s->feature & 0x02)
goto abort_cmd;
- s->status = READY_STAT;
+ s->status = READY_STAT | SEEK_STAT;
s->atapi_dma = s->feature & 1;
s->nsector = 1;
ide_transfer_start(s, s->io_buffer, ATAPI_PACKET_SIZE,
@@ -2289,7 +2289,7 @@ static void ide_reset(IDEState *s)
s->mult_sectors = MAX_MULT_SECTORS;
s->cur_drive = s;
s->select = 0xa0;
- s->status = READY_STAT;
+ s->status = READY_STAT | SEEK_STAT;
ide_set_signature(s);
/* init the transfer handler so that 0xffff is returned on data
accesses */
diff -r 48db4eee7d58 -r d0a544d8a3f3 tools/ioemu/hw/pass-through.c
--- a/tools/ioemu/hw/pass-through.c Mon Aug 25 19:04:37 2008 +0900
+++ b/tools/ioemu/hw/pass-through.c Mon Sep 01 16:59:43 2008 +0900
@@ -2340,11 +2340,6 @@ static int pt_bar_reg_write(struct pt_de
return -1;
}
- /* always keep the emulate register value to 0,
- * because hvmloader does not support high MMIO for now.
- */
- cfg_entry->data = 0;
-
/* never mapping the 'empty' upper region,
* because we'll do it enough for the lower region.
*/
diff -r 48db4eee7d58 -r d0a544d8a3f3 tools/ioemu/hw/vga.c
--- a/tools/ioemu/hw/vga.c Mon Aug 25 19:04:37 2008 +0900
+++ b/tools/ioemu/hw/vga.c Mon Sep 01 16:59:43 2008 +0900
@@ -23,6 +23,7 @@
*/
#include "vl.h"
#include "vga_int.h"
+#include <sys/mman.h>
//#define DEBUG_VGA
//#define DEBUG_VGA_MEM
@@ -1776,7 +1777,10 @@ static void vga_save(QEMUFile *f, void *
#endif
vram_size = s->vram_size;
qemu_put_be32s(f, &vram_size);
- qemu_put_buffer(f, s->vram_ptr, s->vram_size);
+ qemu_put_be64s(f, &s->stolen_vram_addr);
+ if (!s->stolen_vram_addr)
+ /* Old guest: VRAM is not mapped, we have to save it ourselves */
+ qemu_put_buffer(f, s->vram_ptr, VGA_RAM_SIZE);
}
static int vga_load(QEMUFile *f, void *opaque, int version_id)
@@ -1788,7 +1792,7 @@ static int vga_load(QEMUFile *f, void *o
int i;
#endif
- if (version_id > 3)
+ if (version_id > 4)
return -EINVAL;
if (s->pci_dev && version_id >= 2) {
@@ -1839,7 +1843,14 @@ static int vga_load(QEMUFile *f, void *o
qemu_get_be32s(f, &vram_size);
if (vram_size != s->vram_size)
return -EINVAL;
- qemu_get_buffer(f, s->vram_ptr, s->vram_size);
+ if (version_id >= 4) {
+ qemu_get_be64s(f, &s->stolen_vram_addr);
+ if (s->stolen_vram_addr)
+ xen_vga_vram_map(s->stolen_vram_addr, 0);
+ }
+ /* Old guest, VRAM is not mapped, we have to restore it ourselves */
+ if (!s->stolen_vram_addr)
+ qemu_get_buffer(f, s->vram_ptr, s->vram_size);
}
/* force refresh */
@@ -1994,6 +2005,100 @@ void vga_bios_init(VGAState *s)
/* TODO: add vbe support if enabled */
}
+
+static VGAState *xen_vga_state;
+
+/* When loading old images we have to populate the video ram ourselves */
+void xen_vga_populate_vram(uint64_t vram_addr)
+{
+ unsigned long nr_pfn;
+ struct xen_remove_from_physmap xrfp;
+ xen_pfn_t *pfn_list;
+ int i;
+ int rc;
+
+ fprintf(logfile, "populating video RAM at %lx\n", vram_addr);
+
+ nr_pfn = VGA_RAM_SIZE >> TARGET_PAGE_BITS;
+
+ pfn_list = malloc(sizeof(*pfn_list) * nr_pfn);
+
+ for (i = 0; i < nr_pfn; i++)
+ pfn_list[i] = (vram_addr >> TARGET_PAGE_BITS) + i;
+
+ if (xc_domain_memory_populate_physmap(xc_handle, domid, nr_pfn, 0, 0,
pfn_list)) {
+ fprintf(stderr, "Failed to populate video ram\n");
+ exit(1);
+ }
+ free(pfn_list);
+
+ xen_vga_vram_map(vram_addr, 0);
+
+ /* Unmap them from the guest for now. */
+ xrfp.domid = domid;
+ for (i = 0; i < nr_pfn; i++) {
+ xrfp.gpfn = (vram_addr >> TARGET_PAGE_BITS) + i;
+ rc = xc_memory_op(xc_handle, XENMEM_remove_from_physmap, &xrfp);
+ if (rc) {
+ fprintf(stderr, "remove_from_physmap PFN %"PRI_xen_pfn" failed:
%d\n", xrfp.gpfn, rc);
+ break;
+ }
+ }
+}
+
+/* Called once video memory has been allocated in the GPFN space */
+void xen_vga_vram_map(uint64_t vram_addr, int copy)
+{
+ unsigned long nr_pfn;
+ xen_pfn_t *pfn_list;
+ int i;
+ void *vram;
+
+ fprintf(logfile, "mapping video RAM from %lx\n", vram_addr);
+
+ nr_pfn = VGA_RAM_SIZE >> TARGET_PAGE_BITS;
+
+ pfn_list = malloc(sizeof(*pfn_list) * nr_pfn);
+
+ for (i = 0; i < nr_pfn; i++)
+ pfn_list[i] = (vram_addr >> TARGET_PAGE_BITS) + i;
+
+ vram = xc_map_foreign_pages(xc_handle, domid,
+ PROT_READ|PROT_WRITE,
+ pfn_list, nr_pfn);
+
+ if (!vram) {
+ fprintf(stderr, "Failed to map vram\n");
+ exit(1);
+ }
+
+ if (xc_domain_memory_translate_gpfn_list(xc_handle, domid, nr_pfn,
+ pfn_list, pfn_list)) {
+ fprintf(stderr, "Failed translation in xen_vga_vram_addr\n");
+ exit(1);
+ }
+
+ if (copy)
+ memcpy(vram, xen_vga_state->vram_ptr, VGA_RAM_SIZE);
+ qemu_free(xen_vga_state->vram_ptr);
+ xen_vga_state->vram_ptr = vram;
+ xen_vga_state->vram_mfns = pfn_list;
+#ifdef CONFIG_STUBDOM
+ xenfb_pv_display_start(vram);
+#endif
+}
+
+/* Called at boot time when the BIOS has allocated video RAM */
+void xen_vga_stolen_vram_addr(uint64_t stolen_vram_addr)
+{
+ fprintf(logfile, "stolen video RAM at %lx\n", stolen_vram_addr);
+
+ xen_vga_state->stolen_vram_addr = stolen_vram_addr;
+
+ /* And copy from the initialization value */
+ xen_vga_vram_map(stolen_vram_addr, 1);
+}
+
/* when used on xen environment, the vga_ram_base is not used */
void vga_common_init(VGAState *s, DisplayState *ds, uint8_t *vga_ram_base,
unsigned long vga_ram_offset, int vga_ram_size)
@@ -2025,13 +2130,9 @@ void vga_common_init(VGAState *s, Displa
vga_reset(s);
- /* Video RAM must be page-aligned for PVFB memory sharing */
- s->vram_ptr = s->vram_alloc = qemu_memalign(TARGET_PAGE_SIZE,
vga_ram_size);
-
-#ifdef CONFIG_STUBDOM
- if (!cirrus_vga_enabled)
- xenfb_pv_display_start(s->vram_ptr);
-#endif
+ s->vram_ptr = qemu_malloc(vga_ram_size);
+ s->vram_mfns = NULL;
+ xen_vga_state = s;
s->vram_offset = vga_ram_offset;
s->vram_size = vga_ram_size;
@@ -2051,7 +2152,7 @@ static void vga_init(VGAState *s)
{
int vga_io_memory;
- register_savevm("vga", 0, 3, vga_save, vga_load, s);
+ register_savevm("vga", 0, 4, vga_save, vga_load, s);
register_ioport_write(0x3c0, 16, 1, vga_ioport_write, s);
@@ -2163,33 +2264,6 @@ int pci_vga_init(PCIBus *bus, DisplaySta
return 0;
}
-void *vga_update_vram(VGAState *s, void *vga_ram_base, int vga_ram_size)
-{
- uint8_t *old_pointer;
-
- if (s->vram_size != vga_ram_size) {
- fprintf(stderr, "No support to change vga_ram_size\n");
- return NULL;
- }
-
- if (!vga_ram_base) {
- vga_ram_base = qemu_memalign(TARGET_PAGE_SIZE, vga_ram_size +
TARGET_PAGE_SIZE + 1);
- if (!vga_ram_base) {
- fprintf(stderr, "reallocate error\n");
- return NULL;
- }
- }
-
- /* XXX lock needed? */
- old_pointer = s->vram_alloc;
- s->vram_alloc = vga_ram_base;
- vga_ram_base = (uint8_t *)((long)(vga_ram_base + 15) & ~15L);
- memcpy(vga_ram_base, s->vram_ptr, vga_ram_size);
- s->vram_ptr = vga_ram_base;
-
- return old_pointer;
-}
-
/********************************************************/
/* vga screen dump */
diff -r 48db4eee7d58 -r d0a544d8a3f3 tools/ioemu/hw/vga_int.h
--- a/tools/ioemu/hw/vga_int.h Mon Aug 25 19:04:37 2008 +0900
+++ b/tools/ioemu/hw/vga_int.h Mon Sep 01 16:59:43 2008 +0900
@@ -80,9 +80,9 @@
#define VGA_MAX_HEIGHT 2048
#define VGA_STATE_COMMON \
- uint8_t *vram_alloc; \
uint8_t *vram_ptr; \
- uint8_t *vram_shadow; \
+ xen_pfn_t *vram_mfns; \
+ uint64_t stolen_vram_addr; /* Address of stolen RAM */ \
unsigned long vram_offset; \
unsigned int vram_size; \
unsigned long bios_offset; \
diff -r 48db4eee7d58 -r d0a544d8a3f3 tools/ioemu/hw/xen_platform.c
--- a/tools/ioemu/hw/xen_platform.c Mon Aug 25 19:04:37 2008 +0900
+++ b/tools/ioemu/hw/xen_platform.c Mon Sep 01 16:59:43 2008 +0900
@@ -34,6 +34,7 @@ typedef struct PCIXenPlatformState
{
PCIDevice pci_dev;
uint8_t platform_flags;
+ uint64_t vga_stolen_ram;
} PCIXenPlatformState;
static uint32_t xen_platform_ioport_readb(void *opaque, uint32_t addr)
@@ -69,11 +70,46 @@ static void xen_platform_ioport_writeb(v
}
+static uint32_t xen_platform_ioport_readl(void *opaque, uint32_t addr)
+{
+ PCIXenPlatformState *d = opaque;
+
+ addr &= 0xff;
+
+ switch (addr) {
+ case 4: /* VGA stolen memory address */
+ return d->vga_stolen_ram;
+ default:
+ return ~0u;
+ }
+}
+
+static void xen_platform_ioport_writel(void *opaque, uint32_t addr, uint32_t
val)
+{
+ PCIXenPlatformState *d = opaque;
+
+ addr &= 0xff;
+ val &= 0xffffffff;
+
+ switch (addr) {
+ case 4: /* VGA stolen memory address */
+ d->vga_stolen_ram = val;
+ xen_vga_stolen_vram_addr(val);
+ break;
+ default:
+ break;
+ }
+}
+
+
+
static void platform_ioport_map(PCIDevice *pci_dev, int region_num, uint32_t
addr, uint32_t size, int type)
{
PCIXenPlatformState *d = (PCIXenPlatformState *)pci_dev;
register_ioport_write(addr, size, 1, xen_platform_ioport_writeb, d);
+ register_ioport_write(addr, size, 4, xen_platform_ioport_writel, d);
register_ioport_read(addr, size, 1, xen_platform_ioport_readb, d);
+ register_ioport_read(addr, size, 4, xen_platform_ioport_readl, d);
}
static uint32_t platform_mmio_read(void *opaque, target_phys_addr_t addr)
@@ -155,6 +191,7 @@ void xen_pci_save(QEMUFile *f, void *opa
pci_device_save(&d->pci_dev, f);
qemu_put_8s(f, &d->platform_flags);
+ qemu_put_be64s(f, &d->vga_stolen_ram);
}
int xen_pci_load(QEMUFile *f, void *opaque, int version_id)
@@ -173,6 +210,7 @@ int xen_pci_load(QEMUFile *f, void *opaq
uint8_t flags;
qemu_get_8s(f, &flags);
xen_platform_ioport_writeb(d, 0, flags);
+ qemu_get_be64s(f, &d->vga_stolen_ram);
}
return 0;
diff -r 48db4eee7d58 -r d0a544d8a3f3 tools/ioemu/vl.c
--- a/tools/ioemu/vl.c Mon Aug 25 19:04:37 2008 +0900
+++ b/tools/ioemu/vl.c Mon Sep 01 16:59:43 2008 +0900
@@ -7022,38 +7022,6 @@ static BOOL WINAPI qemu_ctrl_handler(DWO
#define MAX_NET_CLIENTS 32
#include <xg_private.h>
-
-/* FIXME Flush the shadow page */
-int unset_mm_mapping(int xc_handle, uint32_t domid,
- unsigned long nr_pages, unsigned int address_bits,
- xen_pfn_t *extent_start)
-{
- int err = 0;
-
- err = xc_domain_memory_decrease_reservation(xc_handle, domid,
- nr_pages, 0, extent_start);
- if (err)
- fprintf(stderr, "Failed to decrease physmap\n");
-
- return err;
-}
-
-int set_mm_mapping(int xc_handle, uint32_t domid,
- unsigned long nr_pages, unsigned int address_bits,
- xen_pfn_t *extent_start)
-{
- int err = 0;
-
- err = xc_domain_memory_populate_physmap(
- xc_handle, domid, nr_pages, 0,
- XENMEMF_address_bits(address_bits), extent_start);
- if (err) {
- fprintf(stderr, "Failed to populate physmap\n");
- return -1;
- }
-
- return 0;
-}
int main(int argc, char **argv)
diff -r 48db4eee7d58 -r d0a544d8a3f3 tools/ioemu/vl.h
--- a/tools/ioemu/vl.h Mon Aug 25 19:04:37 2008 +0900
+++ b/tools/ioemu/vl.h Mon Sep 01 16:59:43 2008 +0900
@@ -1560,6 +1560,9 @@ void timeoffset_get(void);
/* xen_platform.c */
#ifndef QEMU_TOOL
void pci_xen_platform_init(PCIBus *bus);
+void xen_vga_stolen_vram_addr(uint64_t vram_addr);
+void xen_vga_populate_vram(uint64_t vram_addr);
+void xen_vga_vram_map(uint64_t vram_addr, int copy);
#endif
/* pci_emulation.c */
diff -r 48db4eee7d58 -r d0a544d8a3f3 tools/libxc/xc_dom_boot.c
--- a/tools/libxc/xc_dom_boot.c Mon Aug 25 19:04:37 2008 +0900
+++ b/tools/libxc/xc_dom_boot.c Mon Sep 01 16:59:43 2008 +0900
@@ -187,7 +187,7 @@ int xc_dom_boot_image(struct xc_dom_imag
int xc_dom_boot_image(struct xc_dom_image *dom)
{
DECLARE_DOMCTL;
- void *ctxt;
+ vcpu_guest_context_any_t ctxt;
int rc;
xc_dom_printf("%s: called\n", __FUNCTION__);
@@ -245,12 +245,11 @@ int xc_dom_boot_image(struct xc_dom_imag
return rc;
/* let the vm run */
- ctxt = xc_dom_malloc(dom, PAGE_SIZE * 2 /* FIXME */ );
- memset(ctxt, 0, PAGE_SIZE * 2);
- if ( (rc = dom->arch_hooks->vcpu(dom, ctxt)) != 0 )
+ memset(&ctxt, 0, sizeof(ctxt));
+ if ( (rc = dom->arch_hooks->vcpu(dom, &ctxt)) != 0 )
return rc;
xc_dom_unmap_all(dom);
- rc = launch_vm(dom->guest_xc, dom->guest_domid, ctxt);
+ rc = launch_vm(dom->guest_xc, dom->guest_domid, &ctxt);
return rc;
}
diff -r 48db4eee7d58 -r d0a544d8a3f3 tools/libxc/xc_domain.c
--- a/tools/libxc/xc_domain.c Mon Aug 25 19:04:37 2008 +0900
+++ b/tools/libxc/xc_domain.c Mon Sep 01 16:59:43 2008 +0900
@@ -531,6 +531,33 @@ int xc_domain_memory_populate_physmap(in
DPRINTF("Failed allocation for dom %d: %ld extents of order %d\n",
domid, nr_extents, extent_order);
errno = EBUSY;
+ err = -1;
+ }
+
+ return err;
+}
+
+int xc_domain_memory_translate_gpfn_list(int xc_handle,
+ uint32_t domid,
+ unsigned long nr_gpfns,
+ xen_pfn_t *gpfn_list,
+ xen_pfn_t *mfn_list)
+{
+ int err;
+ struct xen_translate_gpfn_list translate_gpfn_list = {
+ .domid = domid,
+ .nr_gpfns = nr_gpfns,
+ };
+ set_xen_guest_handle(translate_gpfn_list.gpfn_list, gpfn_list);
+ set_xen_guest_handle(translate_gpfn_list.mfn_list, mfn_list);
+
+ err = xc_memory_op(xc_handle, XENMEM_translate_gpfn_list,
&translate_gpfn_list);
+
+ if ( err != 0 )
+ {
+ DPRINTF("Failed translation for dom %d (%ld PFNs)\n",
+ domid, nr_gpfns);
+ errno = -err;
err = -1;
}
diff -r 48db4eee7d58 -r d0a544d8a3f3 tools/libxc/xc_domain_save.c
--- a/tools/libxc/xc_domain_save.c Mon Aug 25 19:04:37 2008 +0900
+++ b/tools/libxc/xc_domain_save.c Mon Sep 01 16:59:43 2008 +0900
@@ -1109,12 +1109,6 @@ int xc_domain_save(int xc_handle, int io
if ( !((test_bit(n, to_send) && !test_bit(n, to_skip)) ||
(test_bit(n, to_send) && last_iter) ||
(test_bit(n, to_fix) && last_iter)) )
- continue;
-
- /* Skip PFNs that aren't really there */
- if ( hvm && ((n >= 0xa0 && n < 0xc0) /* VGA hole */
- || (n >= (HVM_BELOW_4G_MMIO_START >> PAGE_SHIFT)
- && n < (1ULL<<32) >> PAGE_SHIFT)) /* MMIO */ )
continue;
/*
diff -r 48db4eee7d58 -r d0a544d8a3f3 tools/libxc/xc_minios.c
--- a/tools/libxc/xc_minios.c Mon Aug 25 19:04:37 2008 +0900
+++ b/tools/libxc/xc_minios.c Mon Sep 01 16:59:43 2008 +0900
@@ -64,7 +64,6 @@ void *xc_map_foreign_range(int xc_handle
unsigned long mfn)
{
unsigned long pt_prot = 0;
- printf("xc_map_foreign_range(%lx, %d)\n", mfn, size);
#ifdef __ia64__
/* TODO */
#else
@@ -81,9 +80,10 @@ void *xc_map_foreign_ranges(int xc_handl
size_t size, int prot, size_t chunksize,
privcmd_mmap_entry_t entries[], int nentries)
{
- unsigned long mfns[size / PAGE_SIZE];
+ unsigned long *mfns;
int i, j, n;
unsigned long pt_prot = 0;
+ void *ret;
#ifdef __ia64__
/* TODO */
#else
@@ -93,12 +93,16 @@ void *xc_map_foreign_ranges(int xc_handl
pt_prot = L1_PROT;
#endif
+ mfns = malloc((size / PAGE_SIZE) * sizeof(*mfns));
+
n = 0;
for (i = 0; i < nentries; i++)
for (j = 0; j < chunksize / PAGE_SIZE; j++)
mfns[n++] = entries[i].mfn + j;
- return map_frames_ex(mfns, n, 1, 0, 1, dom, 0, pt_prot);
+ ret = map_frames_ex(mfns, n, 1, 0, 1, dom, 0, pt_prot);
+ free(mfns);
+ return ret;
}
diff -r 48db4eee7d58 -r d0a544d8a3f3 tools/libxc/xenctrl.h
--- a/tools/libxc/xenctrl.h Mon Aug 25 19:04:37 2008 +0900
+++ b/tools/libxc/xenctrl.h Mon Sep 01 16:59:43 2008 +0900
@@ -628,6 +628,12 @@ int xc_domain_memory_populate_physmap(in
unsigned int mem_flags,
xen_pfn_t *extent_start);
+int xc_domain_memory_translate_gpfn_list(int xc_handle,
+ uint32_t domid,
+ unsigned long nr_gpfns,
+ xen_pfn_t *gpfn_list,
+ xen_pfn_t *mfn_list);
+
int xc_domain_ioport_permission(int xc_handle,
uint32_t domid,
uint32_t first_port,
diff -r 48db4eee7d58 -r d0a544d8a3f3 tools/pygrub/src/pygrub
--- a/tools/pygrub/src/pygrub Mon Aug 25 19:04:37 2008 +0900
+++ b/tools/pygrub/src/pygrub Mon Sep 01 16:59:43 2008 +0900
@@ -124,7 +124,7 @@ class GrubLineEditor(curses.textpad.Text
class GrubLineEditor(curses.textpad.Textbox):
def __init__(self, screen, startx, starty, line = ""):
screen.addstr(startx, starty, "> ")
- screen.refresh()
+ screen.noutrefresh()
win = curses.newwin(1, 74, startx, starty + 2)
curses.textpad.Textbox.__init__(self, win)
@@ -137,7 +137,7 @@ class GrubLineEditor(curses.textpad.Text
"""Show the text. One of our advantages over standard textboxes
is that we can handle lines longer than the window."""
- self.win.clear()
+ self.win.erase()
p = self.pos
off = 0
while p > 70:
@@ -188,6 +188,7 @@ class GrubLineEditor(curses.textpad.Text
return 1
def edit(self):
+ curses.doupdate()
r = curses.textpad.Textbox.edit(self)
if self.cancelled:
return None
@@ -217,16 +218,15 @@ class Grub:
curses.def_prog_mode()
curses.reset_prog_mode()
- self.screen.clear()
- self.screen.refresh()
+ self.screen.erase()
# create basic grub screen with a box of entries and a textbox
self.screen.addstr(1, 4, "pyGRUB version %s" %(PYGRUB_VER,))
self.entry_win.box()
- self.screen.refresh()
+ self.screen.noutrefresh()
def fill_entry_list(self):
- self.entry_win.clear()
+ self.entry_win.erase()
self.entry_win.box()
maxy = self.entry_win.getmaxyx()[0]-3 # maxy - 2 for the frame + index
@@ -244,7 +244,7 @@ class Grub:
self.entry_win.addstr(y + 1 - self.start_image, 2,
i.title.ljust(70))
if y == self.selected_image:
self.entry_win.attroff(curses.A_REVERSE)
- self.entry_win.refresh()
+ self.entry_win.noutrefresh()
def edit_entry(self, origimg):
def draw():
@@ -259,13 +259,13 @@ class Grub:
self.text_win.addch(0, 14, curses.ACS_DARROW)
(y, x) = self.text_win.getmaxyx()
self.text_win.move(y - 1, x - 1)
- self.text_win.refresh()
+ self.text_win.noutrefresh()
curline = 1
img = copy.deepcopy(origimg)
while 1:
draw()
- self.entry_win.clear()
+ self.entry_win.erase()
self.entry_win.box()
for idx in range(1, len(img.lines)):
# current line should be highlighted
@@ -280,7 +280,8 @@ class Grub:
self.entry_win.addstr(idx, 2, l)
if idx == curline:
self.entry_win.attroff(curses.A_REVERSE)
- self.entry_win.refresh()
+ self.entry_win.noutrefresh()
+ curses.doupdate()
c = self.screen.getch()
if c in (ord('q'), 27): # 27 == esc
@@ -318,10 +319,10 @@ class Grub:
origimg.reset(img.lines)
def edit_line(self, line):
- self.screen.clear()
+ self.screen.erase()
self.screen.addstr(1, 2, "[ Minimal BASH-like line editing is
supported. ")
self.screen.addstr(2, 2, " ESC at any time cancels. ENTER at any
time accepts your changes. ]")
- self.screen.refresh()
+ self.screen.noutrefresh()
t = GrubLineEditor(self.screen, 5, 2, line)
enable_cursor(True)
@@ -331,10 +332,10 @@ class Grub:
return None
def command_line_mode(self):
- self.screen.clear()
+ self.screen.erase()
self.screen.addstr(1, 2, "[ Minimal BASH-like line editing is
supported. ESC at any time ")
self.screen.addstr(2, 2, " exits. Typing 'boot' will boot with your
entered commands. ] ")
- self.screen.refresh()
+ self.screen.noutrefresh()
y = 5
lines = []
@@ -420,7 +421,7 @@ class Grub:
self.text_win.addch(0, 14, curses.ACS_DARROW)
(y, x) = self.text_win.getmaxyx()
self.text_win.move(y - 1, x - 1)
- self.text_win.refresh()
+ self.text_win.noutrefresh()
# now loop until we hit the timeout or get a go from the user
mytime = 0
@@ -433,6 +434,7 @@ class Grub:
else:
self.screen.addstr(20, 5, " " * 80)
self.fill_entry_list()
+ curses.doupdate()
c = self.screen.getch()
if c == -1:
diff -r 48db4eee7d58 -r d0a544d8a3f3 tools/python/xen/util/pci.py
--- a/tools/python/xen/util/pci.py Mon Aug 25 19:04:37 2008 +0900
+++ b/tools/python/xen/util/pci.py Mon Sep 01 16:59:43 2008 +0900
@@ -40,6 +40,7 @@ DEV_TYPE_PCI_BRIDGE = 2
DEV_TYPE_PCI_BRIDGE = 2
DEV_TYPE_PCI = 3
+PCI_VENDOR_ID = 0x0
PCI_STATUS = 0x6
PCI_CLASS_DEVICE = 0x0a
PCI_CLASS_BRIDGE_PCI = 0x0604
@@ -68,6 +69,11 @@ PCI_PM_CTRL_NO_SOFT_RESET = 0x0004
PCI_PM_CTRL_NO_SOFT_RESET = 0x0004
PCI_PM_CTRL_STATE_MASK = 0x0003
PCI_D3hot = 3
+
+VENDOR_INTEL = 0x8086
+PCI_CAP_ID_VENDOR_SPECIFIC_CAP = 0x09
+PCI_CLASS_ID_USB = 0x0c03
+PCI_USB_FLRCTRL = 0x4
PCI_CAP_ID_AF = 0x13
PCI_AF_CAPs = 0x3
@@ -487,7 +493,7 @@ class PciDevice:
def do_Dstate_transition(self):
pos = self.find_cap_offset(PCI_CAP_ID_PM)
if pos == 0:
- return
+ return False
(pci_list, cfg_list) = save_pci_conf_space([self.name])
@@ -504,6 +510,31 @@ class PciDevice:
time.sleep(0.010)
restore_pci_conf_space((pci_list, cfg_list))
+ return True
+
+ def do_vendor_specific_FLR_method(self):
+ pos = self.find_cap_offset(PCI_CAP_ID_VENDOR_SPECIFIC_CAP)
+ if pos == 0:
+ return
+
+ vendor_id = self.pci_conf_read16(PCI_VENDOR_ID)
+ if vendor_id != VENDOR_INTEL:
+ return
+
+ class_id = self.pci_conf_read16(PCI_CLASS_DEVICE)
+ if class_id != PCI_CLASS_ID_USB:
+ return
+
+ (pci_list, cfg_list) = save_pci_conf_space([self.name])
+
+ self.pci_conf_write8(pos + PCI_USB_FLRCTRL, 1)
+ time.sleep(0.010)
+
+ restore_pci_conf_space((pci_list, cfg_list))
+
+ def do_FLR_for_integrated_device(self):
+ if not self.do_Dstate_transition():
+ self.do_vendor_specific_FLR_method()
def find_all_the_multi_functions(self):
sysfs_mnt = find_sysfs_mnt()
@@ -676,7 +707,7 @@ class PciDevice:
restore_pci_conf_space((pci_list, cfg_list))
else:
if self.bus == 0:
- self.do_Dstate_transition()
+ self.do_FLR_for_integrated_device()
else:
funcs = self.find_all_the_multi_functions()
self.devs_check_driver(funcs)
@@ -697,7 +728,7 @@ class PciDevice:
restore_pci_conf_space((pci_list, cfg_list))
else:
if self.bus == 0:
- self.do_Dstate_transition()
+ self.do_FLR_for_integrated_device()
else:
devs = self.find_coassigned_devices(False)
# Remove the element 0 which is a bridge
diff -r 48db4eee7d58 -r d0a544d8a3f3 tools/python/xen/xend/XendConfig.py
--- a/tools/python/xen/xend/XendConfig.py Mon Aug 25 19:04:37 2008 +0900
+++ b/tools/python/xen/xend/XendConfig.py Mon Sep 01 16:59:43 2008 +0900
@@ -1538,9 +1538,9 @@ class XendConfig(dict):
pci_dev_info[opt] = val
except TypeError:
pass
- # append uuid for each pci device.
- dpci_uuid = pci_dev_info.get('uuid', uuid.createString())
- pci_dev_info['uuid'] = dpci_uuid
+ # append uuid for each pci device.
+ dpci_uuid = pci_dev_info.get('uuid', uuid.createString())
+ pci_dev_info['uuid'] = dpci_uuid
pci_devs.append(pci_dev_info)
dev_config['devs'] = pci_devs
diff -r 48db4eee7d58 -r d0a544d8a3f3 tools/python/xen/xend/XendDomain.py
--- a/tools/python/xen/xend/XendDomain.py Mon Aug 25 19:04:37 2008 +0900
+++ b/tools/python/xen/xend/XendDomain.py Mon Sep 01 16:59:43 2008 +0900
@@ -419,6 +419,8 @@ class XendDomain:
except VmError:
log.exception("Unable to recreate domain")
try:
+ xc.domain_pause(domid)
+ do_FLR(domid)
xc.domain_destroy(domid)
except:
log.exception("Hard destruction of domain failed: %d" %
@@ -1255,6 +1257,8 @@ class XendDomain:
val = dominfo.destroy()
else:
try:
+ xc.domain_pause(int(domid))
+ do_FLR(int(domid))
val = xc.domain_destroy(int(domid))
except ValueError:
raise XendInvalidDomain(domid)
diff -r 48db4eee7d58 -r d0a544d8a3f3 tools/python/xen/xend/XendDomainInfo.py
--- a/tools/python/xen/xend/XendDomainInfo.py Mon Aug 25 19:04:37 2008 +0900
+++ b/tools/python/xen/xend/XendDomainInfo.py Mon Sep 01 16:59:43 2008 +0900
@@ -287,6 +287,28 @@ def dom_get(dom):
log.trace("domain_getinfo(%d) failed, ignoring: %s", dom, str(err))
return None
+def do_FLR(domid):
+ from xen.xend.server.pciif import parse_pci_name, PciDevice
+ path = '/local/domain/0/backend/pci/%u/0/' % domid
+ num_devs = xstransact.Read(path + 'num_devs');
+ if num_devs is None or num_devs == "":
+ return;
+
+ num_devs = int(xstransact.Read(path + 'num_devs'));
+
+ dev_str_list = []
+ for i in range(num_devs):
+ dev_str = xstransact.Read(path + 'dev-%i' % i)
+ dev_str_list = dev_str_list + [dev_str]
+
+ for dev_str in dev_str_list:
+ (dom, b, d, f) = parse_pci_name(dev_str)
+ try:
+ dev = PciDevice(dom, b, d, f)
+ except Exception, e:
+ raise VmError("pci: failed to locate device and "+
+ "parse it's resources - "+str(e))
+ dev.do_FLR()
class XendDomainInfo:
"""An object represents a domain.
@@ -2386,42 +2408,32 @@ class XendDomainInfo:
if self.domid is None:
return
+ from xen.xend import XendDomain
log.debug("XendDomainInfo.destroy: domid=%s", str(self.domid))
paths = self._prepare_phantom_paths()
self._cleanupVm()
if self.dompath is not None:
- self.destroyDomain()
-
- self._cleanup_phantom_devs(paths)
-
- if "transient" in self.info["other_config"] \
- and bool(self.info["other_config"]["transient"]):
- from xen.xend import XendDomain
- XendDomain.instance().domain_delete_by_dominfo(self)
-
-
- def destroyDomain(self):
- log.debug("XendDomainInfo.destroyDomain(%s)", str(self.domid))
-
- paths = self._prepare_phantom_paths()
-
- try:
- if self.domid is not None:
+ try:
xc.domain_destroy_hook(self.domid)
+ xc.domain_pause(self.domid)
+ do_FLR(self.domid)
xc.domain_destroy(self.domid)
for state in DOM_STATES_OLD:
self.info[state] = 0
self._stateSet(DOM_STATE_HALTED)
- except:
- log.exception("XendDomainInfo.destroy: xc.domain_destroy failed.")
-
- from xen.xend import XendDomain
- XendDomain.instance().remove_domain(self)
-
- self.cleanupDomain()
+ except:
+ log.exception("XendDomainInfo.destroy: domain destruction
failed.")
+
+ XendDomain.instance().remove_domain(self)
+ self.cleanupDomain()
+
self._cleanup_phantom_devs(paths)
+
+ if "transient" in self.info["other_config"] \
+ and bool(self.info["other_config"]["transient"]):
+ XendDomain.instance().domain_delete_by_dominfo(self)
def resetDomain(self):
diff -r 48db4eee7d58 -r d0a544d8a3f3 tools/python/xen/xend/image.py
--- a/tools/python/xen/xend/image.py Mon Aug 25 19:04:37 2008 +0900
+++ b/tools/python/xen/xend/image.py Mon Sep 01 16:59:43 2008 +0900
@@ -637,8 +637,9 @@ class LinuxImageHandler(ImageHandler):
log.debug("ramdisk = %s", self.ramdisk)
log.debug("vcpus = %d", self.vm.getVCpuCount())
log.debug("features = %s", self.vm.getFeatures())
+ log.debug("flags = %d", self.flags)
if arch.type == "ia64":
- log.debug("vhpt = %d", self.flags)
+ log.debug("vhpt = %d", self.vhpt)
return xc.linux_build(domid = self.vm.getDomid(),
memsize = mem_mb,
diff -r 48db4eee7d58 -r d0a544d8a3f3
tools/python/xen/xend/server/DevController.py
--- a/tools/python/xen/xend/server/DevController.py Mon Aug 25 19:04:37
2008 +0900
+++ b/tools/python/xen/xend/server/DevController.py Mon Sep 01 16:59:43
2008 +0900
@@ -223,12 +223,6 @@ class DevController:
raise VmError('%s devices may not be reconfigured' % self.deviceClass)
- def cleanupDeviceOnDomainDestroy(self, devid):
- """ Some devices may need special cleanup when the guest domain
- is destroyed.
- """
- return
-
def destroyDevice(self, devid, force):
"""Destroy the specified device.
@@ -244,8 +238,6 @@ class DevController:
"""
dev = self.convertToDeviceNumber(devid)
-
- self.cleanupDeviceOnDomainDestroy(dev)
# Modify online status /before/ updating state (latter is watched by
# drivers, so this ordering avoids a race).
diff -r 48db4eee7d58 -r d0a544d8a3f3 tools/python/xen/xend/server/pciif.py
--- a/tools/python/xen/xend/server/pciif.py Mon Aug 25 19:04:37 2008 +0900
+++ b/tools/python/xen/xend/server/pciif.py Mon Sep 01 16:59:43 2008 +0900
@@ -383,10 +383,10 @@ class PciController(DevController):
if (dev.dev_type == DEV_TYPE_PCIe_ENDPOINT) and not dev.pcie_flr:
if dev.bus == 0:
# We cope with this case by using the Dstate transition
- # method for now.
+ # method or some vendor specific methods for now.
err_msg = 'pci: %s: it is on bus 0, but has no PCIe' +\
' FLR Capability. Will try the Dstate transition'+\
- ' method if available.'
+ ' method or some vendor specific methods if available.'
log.warn(err_msg % dev.name)
else:
funcs = dev.find_all_the_multi_functions()
@@ -404,10 +404,11 @@ class PciController(DevController):
if dev.bus == 0 or arch.type == "ia64":
if not dev.pci_af_flr:
# We cope with this case by using the Dstate transition
- # method for now.
+ # method or some vendor specific methods for now.
err_msg = 'pci: %s: it is on bus 0, but has no PCI' +\
' Advanced Capabilities for FLR. Will try the'+\
- ' Dstate transition method if available.'
+ ' Dstate transition method or some vendor' +\
+ ' specific methods if available.'
log.warn(err_msg % dev.name)
else:
# All devices behind the uppermost PCI/PCI-X bridge must
be\
@@ -543,22 +544,6 @@ class PciController(DevController):
return new_num_devs
- def cleanupDeviceOnDomainDestroy(self, devid):
- num_devs = int(self.readBackend(devid, 'num_devs'))
- dev_str_list = []
- for i in range(num_devs):
- dev_str = self.readBackend(devid, 'dev-%i' % i)
- dev_str_list = dev_str_list + [dev_str]
-
- for dev_str in dev_str_list:
- (dom, b, d, f) = parse_pci_name(dev_str)
- try:
- dev = PciDevice(dom, b, d, f)
- except Exception, e:
- raise VmError("pci: failed to locate device and "+
- "parse it's resources - "+str(e))
- dev.do_FLR()
-
def waitForBackend(self,devid):
return (0, "ok - no hotplug")
diff -r 48db4eee7d58 -r d0a544d8a3f3 tools/xenmon/Makefile
--- a/tools/xenmon/Makefile Mon Aug 25 19:04:37 2008 +0900
+++ b/tools/xenmon/Makefile Mon Sep 01 16:59:43 2008 +0900
@@ -42,6 +42,6 @@ clean:
%: %.c Makefile
- $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $<
+ $(CC) $(CFLAGS) $< $(LDFLAGS) -o $@
xentrace_%: %.c Makefile
- $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $<
+ $(CC) $(CFLAGS) $< $(LDFLAGS) -o $@
diff -r 48db4eee7d58 -r d0a544d8a3f3 xen/Makefile
--- a/xen/Makefile Mon Aug 25 19:04:37 2008 +0900
+++ b/xen/Makefile Mon Sep 01 16:59:43 2008 +0900
@@ -1,8 +1,8 @@
# This is the correct place to edit the build version.
# All other places this is stored (eg. compile.h) should be autogenerated.
export XEN_VERSION = 3
-export XEN_SUBVERSION = 3
-export XEN_EXTRAVERSION ?= .0-rc8-pre$(XEN_VENDORVERSION)
+export XEN_SUBVERSION = 4
+export XEN_EXTRAVERSION ?= -unstable$(XEN_VENDORVERSION)
export XEN_FULLVERSION = $(XEN_VERSION).$(XEN_SUBVERSION)$(XEN_EXTRAVERSION)
-include xen-version
@@ -87,7 +87,7 @@ include/xen/compile.h: include/xen/compi
-e 's/@@whoami@@/$(XEN_WHOAMI)/g' \
-e 's/@@domain@@/$(XEN_DOMAIN)/g' \
-e 's/@@hostname@@/$(shell hostname)/g' \
- -e 's!@@compiler@@!$(shell $(CC) $(CFLAGS) -v 2>&1 | grep -i
"gcc.*version")!g' \
+ -e 's!@@compiler@@!$(shell $(CC) $(CFLAGS) -v 2>&1 | tail -1)!g' \
-e 's/@@version@@/$(XEN_VERSION)/g' \
-e 's/@@subversion@@/$(XEN_SUBVERSION)/g' \
-e 's/@@extraversion@@/$(XEN_EXTRAVERSION)/g' \
diff -r 48db4eee7d58 -r d0a544d8a3f3 xen/arch/ia64/xen/mm.c
--- a/xen/arch/ia64/xen/mm.c Mon Aug 25 19:04:37 2008 +0900
+++ b/xen/arch/ia64/xen/mm.c Mon Sep 01 16:59:43 2008 +0900
@@ -2698,6 +2698,20 @@ void put_page_type(struct page_info *pag
}
+static int get_page_from_pagenr(unsigned long page_nr, struct domain *d)
+{
+ struct page_info *page = mfn_to_page(page_nr);
+
+ if ( unlikely(!mfn_valid(page_nr)) || unlikely(!get_page(page, d)) )
+ {
+ MEM_LOG("Could not get page ref for pfn %lx", page_nr);
+ return 0;
+ }
+
+ return 1;
+}
+
+
int get_page_type(struct page_info *page, u32 type)
{
u64 nx, x, y = page->u.inuse.type_info;
@@ -2792,6 +2806,8 @@ long
long
arch_memory_op(int op, XEN_GUEST_HANDLE(void) arg)
{
+ struct page_info *page = NULL;
+
switch (op) {
case XENMEM_add_to_physmap:
{
@@ -2836,11 +2852,21 @@ arch_memory_op(int op, XEN_GUEST_HANDLE(
spin_unlock(&d->grant_table->lock);
break;
+ case XENMAPSPACE_mfn:
+ {
+ if ( get_page_from_pagenr(xatp.idx, d) ) {
+ mfn = xatp.idx;
+ page = mfn_to_page(mfn);
+ }
+ break;
+ }
default:
break;
}
if (mfn == 0) {
+ if ( page )
+ put_page(page);
rcu_unlock_domain(d);
return -EINVAL;
}
@@ -2872,11 +2898,53 @@ arch_memory_op(int op, XEN_GUEST_HANDLE(
out:
domain_unlock(d);
-
+
+ if ( page )
+ put_page(page);
+
rcu_unlock_domain(d);
break;
}
+
+ case XENMEM_remove_from_physmap:
+ {
+ struct xen_remove_from_physmap xrfp;
+ unsigned long mfn;
+ struct domain *d;
+
+ if ( copy_from_guest(&xrfp, arg, 1) )
+ return -EFAULT;
+
+ if ( xrfp.domid == DOMID_SELF )
+ {
+ d = rcu_lock_current_domain();
+ }
+ else
+ {
+ if ( (d = rcu_lock_domain_by_id(xrfp.domid)) == NULL )
+ return -ESRCH;
+ if ( !IS_PRIV_FOR(current->domain, d) )
+ {
+ rcu_unlock_domain(d);
+ return -EPERM;
+ }
+ }
+
+ domain_lock(d);
+
+ mfn = gmfn_to_mfn(d, xrfp.gpfn);
+
+ if ( mfn_valid(mfn) )
+ guest_physmap_remove_page(d, xrfp.gpfn, mfn, 0);
+
+ domain_unlock(d);
+
+ rcu_unlock_domain(d);
+
+ break;
+ }
+
case XENMEM_machine_memory_map:
{
diff -r 48db4eee7d58 -r d0a544d8a3f3 xen/arch/x86/acpi/power.c
--- a/xen/arch/x86/acpi/power.c Mon Aug 25 19:04:37 2008 +0900
+++ b/xen/arch/x86/acpi/power.c Mon Sep 01 16:59:43 2008 +0900
@@ -24,6 +24,7 @@
#include <xen/sched.h>
#include <xen/domain.h>
#include <xen/console.h>
+#include <xen/iommu.h>
#include <public/platform.h>
#include <asm/tboot.h>
@@ -41,6 +42,8 @@ void do_suspend_lowlevel(void);
static int device_power_down(void)
{
+ iommu_suspend();
+
console_suspend();
time_suspend();
@@ -65,6 +68,8 @@ static void device_power_up(void)
time_resume();
console_resume();
+
+ iommu_resume();
}
static void freeze_domains(void)
diff -r 48db4eee7d58 -r d0a544d8a3f3 xen/arch/x86/cpu/amd.c
--- a/xen/arch/x86/cpu/amd.c Mon Aug 25 19:04:37 2008 +0900
+++ b/xen/arch/x86/cpu/amd.c Mon Sep 01 16:59:43 2008 +0900
@@ -10,8 +10,142 @@
#include <asm/hvm/support.h>
#include "cpu.h"
+#include "amd.h"
int start_svm(struct cpuinfo_x86 *c);
+
+/*
+ * Pre-canned values for overriding the CPUID features
+ * and extended features masks.
+ *
+ * Currently supported processors:
+ *
+ * "fam_0f_rev_c"
+ * "fam_0f_rev_d"
+ * "fam_0f_rev_e"
+ * "fam_0f_rev_f"
+ * "fam_0f_rev_g"
+ * "fam_10_rev_b"
+ * "fam_10_rev_c"
+ * "fam_11_rev_b"
+ */
+static char opt_famrev[14];
+string_param("cpuid_mask_cpu", opt_famrev);
+
+/* Finer-grained CPUID feature control. */
+static unsigned int opt_cpuid_mask_ecx, opt_cpuid_mask_edx;
+integer_param("cpuid_mask_ecx", opt_cpuid_mask_ecx);
+integer_param("cpuid_mask_edx", opt_cpuid_mask_edx);
+static unsigned int opt_cpuid_mask_ext_ecx, opt_cpuid_mask_ext_edx;
+integer_param("cpuid_mask_ecx", opt_cpuid_mask_ext_ecx);
+integer_param("cpuid_mask_edx", opt_cpuid_mask_ext_edx);
+
+static inline void wrmsr_amd(unsigned int index, unsigned int lo,
+ unsigned int hi)
+{
+ asm volatile (
+ "wrmsr"
+ : /* No outputs */
+ : "c" (index), "a" (lo),
+ "d" (hi), "D" (0x9c5a203a)
+ );
+}
+
+/*
+ * Mask the features and extended features returned by CPUID. Parameters are
+ * set from the boot line via two methods:
+ *
+ * 1) Specific processor revision string
+ * 2) User-defined masks
+ *
+ * The processor revision string parameter has precedene.
+ */
+static void __devinit set_cpuidmask(struct cpuinfo_x86 *c)
+{
+ static unsigned int feat_ecx, feat_edx;
+ static unsigned int extfeat_ecx, extfeat_edx;
+ static enum { not_parsed, no_mask, set_mask } status;
+
+ if (status == no_mask)
+ return;
+
+ if (status == set_mask)
+ goto setmask;
+
+ ASSERT((status == not_parsed) && (smp_processor_id() == 0));
+ status = no_mask;
+
+ if (opt_cpuid_mask_ecx | opt_cpuid_mask_edx |
+ opt_cpuid_mask_ext_ecx | opt_cpuid_mask_ext_edx) {
+ feat_ecx = opt_cpuid_mask_ecx ? : ~0U;
+ feat_edx = opt_cpuid_mask_edx ? : ~0U;
+ extfeat_ecx = opt_cpuid_mask_ext_ecx ? : ~0U;
+ extfeat_edx = opt_cpuid_mask_ext_edx ? : ~0U;
+ } else if (*opt_famrev == '\0') {
+ return;
+ } else if (!strcmp(opt_famrev, "fam_0f_rev_c")) {
+ feat_ecx = AMD_FEATURES_K8_REV_C_ECX;
+ feat_edx = AMD_FEATURES_K8_REV_C_EDX;
+ extfeat_ecx = AMD_EXTFEATURES_K8_REV_C_ECX;
+ extfeat_edx = AMD_EXTFEATURES_K8_REV_C_EDX;
+ } else if (!strcmp(opt_famrev, "fam_0f_rev_d")) {
+ feat_ecx = AMD_FEATURES_K8_REV_D_ECX;
+ feat_edx = AMD_FEATURES_K8_REV_D_EDX;
+ extfeat_ecx = AMD_EXTFEATURES_K8_REV_D_ECX;
+ extfeat_edx = AMD_EXTFEATURES_K8_REV_D_EDX;
+ } else if (!strcmp(opt_famrev, "fam_0f_rev_e")) {
+ feat_ecx = AMD_FEATURES_K8_REV_E_ECX;
+ feat_edx = AMD_FEATURES_K8_REV_E_EDX;
+ extfeat_ecx = AMD_EXTFEATURES_K8_REV_E_ECX;
+ extfeat_edx = AMD_EXTFEATURES_K8_REV_E_EDX;
+ } else if (!strcmp(opt_famrev, "fam_0f_rev_f")) {
+ feat_ecx = AMD_FEATURES_K8_REV_F_ECX;
+ feat_edx = AMD_FEATURES_K8_REV_F_EDX;
+ extfeat_ecx = AMD_EXTFEATURES_K8_REV_F_ECX;
+ extfeat_edx = AMD_EXTFEATURES_K8_REV_F_EDX;
+ } else if (!strcmp(opt_famrev, "fam_0f_rev_g")) {
+ feat_ecx = AMD_FEATURES_K8_REV_G_ECX;
+ feat_edx = AMD_FEATURES_K8_REV_G_EDX;
+ extfeat_ecx = AMD_EXTFEATURES_K8_REV_G_ECX;
+ extfeat_edx = AMD_EXTFEATURES_K8_REV_G_EDX;
+ } else if (!strcmp(opt_famrev, "fam_10_rev_b")) {
+ feat_ecx = AMD_FEATURES_FAM10h_REV_B_ECX;
+ feat_edx = AMD_FEATURES_FAM10h_REV_B_EDX;
+ extfeat_ecx = AMD_EXTFEATURES_FAM10h_REV_B_ECX;
+ extfeat_edx = AMD_EXTFEATURES_FAM10h_REV_B_EDX;
+ } else if (!strcmp(opt_famrev, "fam_10_rev_c")) {
+ feat_ecx = AMD_FEATURES_FAM10h_REV_C_ECX;
+ feat_edx = AMD_FEATURES_FAM10h_REV_C_EDX;
+ extfeat_ecx = AMD_EXTFEATURES_FAM10h_REV_C_ECX;
+ extfeat_edx = AMD_EXTFEATURES_FAM10h_REV_C_EDX;
+ } else if (!strcmp(opt_famrev, "fam_11_rev_b")) {
+ feat_ecx = AMD_FEATURES_FAM11h_REV_B_ECX;
+ feat_edx = AMD_FEATURES_FAM11h_REV_B_EDX;
+ extfeat_ecx = AMD_EXTFEATURES_FAM11h_REV_B_ECX;
+ extfeat_edx = AMD_EXTFEATURES_FAM11h_REV_B_EDX;
+ } else {
+ printk("Invalid processor string: %s\n", opt_famrev);
+ printk("CPUID will not be masked\n");
+ return;
+ }
+
+ status = set_mask;
+ printk("Writing CPUID feature mask ECX:EDX -> %08Xh:%08Xh\n",
+ feat_ecx, feat_edx);
+ printk("Writing CPUID extended feature mask ECX:EDX -> %08Xh:%08Xh\n",
+ extfeat_ecx, extfeat_edx);
+
+ setmask:
+ /* FIXME check if processor supports CPUID masking */
+ /* AMD processors prior to family 10h required a 32-bit password */
+ if (c->x86 >= 0x10) {
+ wrmsr(MSR_K8_FEATURE_MASK, feat_edx, feat_ecx);
+ wrmsr(MSR_K8_EXT_FEATURE_MASK, extfeat_edx, extfeat_ecx);
+ } else if (c->x86 == 0x0f) {
+ wrmsr_amd(MSR_K8_FEATURE_MASK, feat_edx, feat_ecx);
+ wrmsr_amd(MSR_K8_EXT_FEATURE_MASK, extfeat_edx, extfeat_ecx);
+ }
+}
/*
* amd_flush_filter={on,off}. Forcibly Enable or disable the TLB flush
@@ -115,7 +249,7 @@ static void check_disable_c1e(unsigned i
on_each_cpu(disable_c1e, NULL, 1, 1);
}
-static void __init init_amd(struct cpuinfo_x86 *c)
+static void __devinit init_amd(struct cpuinfo_x86 *c)
{
u32 l, h;
int mbytes = num_physpages >> (20-PAGE_SHIFT);
@@ -367,6 +501,8 @@ static void __init init_amd(struct cpuin
/* Prevent TSC drift in non single-processor, single-core platforms. */
if ((smp_processor_id() == 1) && c1_ramping_may_cause_clock_drift(c))
disable_c1_ramping();
+
+ set_cpuidmask(c);
start_svm(c);
}
diff -r 48db4eee7d58 -r d0a544d8a3f3 xen/arch/x86/cpu/amd.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/x86/cpu/amd.h Mon Sep 01 16:59:43 2008 +0900
@@ -0,0 +1,103 @@
+/*
+ * amd.h - AMD processor specific definitions
+ */
+
+#ifndef __AMD_H__
+#define __AMD_H__
+
+#include <asm/cpufeature.h>
+
+/* CPUID masked for use by AMD-V Extended Migration */
+
+#define X86_FEATURE_BITPOS(_feature_) ((_feature_) % 32)
+#define __bit(_x_) (1U << X86_FEATURE_BITPOS(_x_))
+
+/* Family 0Fh, Revision C */
+#define AMD_FEATURES_K8_REV_C_ECX 0
+#define AMD_FEATURES_K8_REV_C_EDX ( \
+ __bit(X86_FEATURE_FPU) | __bit(X86_FEATURE_VME) | \
+ __bit(X86_FEATURE_DE) | __bit(X86_FEATURE_PSE) | \
+ __bit(X86_FEATURE_TSC) | __bit(X86_FEATURE_MSR) | \
+ __bit(X86_FEATURE_PAE) | __bit(X86_FEATURE_MCE) | \
+ __bit(X86_FEATURE_CX8) | __bit(X86_FEATURE_APIC) | \
+ __bit(X86_FEATURE_SEP) | __bit(X86_FEATURE_MTRR) | \
+ __bit(X86_FEATURE_PGE) | __bit(X86_FEATURE_MCA) | \
+ __bit(X86_FEATURE_CMOV) | __bit(X86_FEATURE_PAT) | \
+ __bit(X86_FEATURE_PSE36) | __bit(X86_FEATURE_CLFLSH)| \
+ __bit(X86_FEATURE_MMX) | __bit(X86_FEATURE_FXSR) | \
+ __bit(X86_FEATURE_XMM) | __bit(X86_FEATURE_XMM2))
+#define AMD_EXTFEATURES_K8_REV_C_ECX 0
+#define AMD_EXTFEATURES_K8_REV_C_EDX (
\
+ __bit(X86_FEATURE_FPU) | __bit(X86_FEATURE_VME) | \
+ __bit(X86_FEATURE_DE) | __bit(X86_FEATURE_PSE) | \
+ __bit(X86_FEATURE_TSC) | __bit(X86_FEATURE_MSR) | \
+ __bit(X86_FEATURE_PAE) | __bit(X86_FEATURE_MCE) | \
+ __bit(X86_FEATURE_CX8) | __bit(X86_FEATURE_APIC) | \
+ __bit(X86_FEATURE_SYSCALL) | __bit(X86_FEATURE_MTRR) | \
+ __bit(X86_FEATURE_PGE) | __bit(X86_FEATURE_MCA) | \
+ __bit(X86_FEATURE_CMOV) | __bit(X86_FEATURE_PAT) | \
+ __bit(X86_FEATURE_PSE36) | __bit(X86_FEATURE_NX) | \
+ __bit(X86_FEATURE_MMXEXT) | __bit(X86_FEATURE_MMX) | \
+ __bit(X86_FEATURE_FXSR) | __bit(X86_FEATURE_LM) | \
+ __bit(X86_FEATURE_3DNOWEXT) | __bit(X86_FEATURE_3DNOW))
+
+/* Family 0Fh, Revision D */
+#define AMD_FEATURES_K8_REV_D_ECX AMD_FEATURES_K8_REV_C_ECX
+#define AMD_FEATURES_K8_REV_D_EDX AMD_FEATURES_K8_REV_C_EDX
+#define AMD_EXTFEATURES_K8_REV_D_ECX (AMD_EXTFEATURES_K8_REV_C_ECX |\
+ __bit(X86_FEATURE_LAHF_LM))
+#define AMD_EXTFEATURES_K8_REV_D_EDX (AMD_EXTFEATURES_K8_REV_C_EDX |\
+ __bit(X86_FEATURE_FFXSR))
+
+/* Family 0Fh, Revision E */
+#define AMD_FEATURES_K8_REV_E_ECX (AMD_FEATURES_K8_REV_D_ECX | \
+ __bit(X86_FEATURE_XMM3))
+#define AMD_FEATURES_K8_REV_E_EDX (AMD_FEATURES_K8_REV_D_EDX | \
+ __bit(X86_FEATURE_HT))
+#define AMD_EXTFEATURES_K8_REV_E_ECX (AMD_EXTFEATURES_K8_REV_D_ECX |\
+ __bit(X86_FEATURE_CMP_LEGACY))
+#define AMD_EXTFEATURES_K8_REV_E_EDX AMD_EXTFEATURES_K8_REV_D_EDX
+
+/* Family 0Fh, Revision F */
+#define AMD_FEATURES_K8_REV_F_ECX (AMD_FEATURES_K8_REV_E_ECX | \
+ __bit(X86_FEATURE_CX16))
+#define AMD_FEATURES_K8_REV_F_EDX AMD_FEATURES_K8_REV_E_EDX
+#define AMD_EXTFEATURES_K8_REV_F_ECX (AMD_EXTFEATURES_K8_REV_E_ECX |\
+ __bit(X86_FEATURE_SVME) | __bit(X86_FEATURE_EXTAPICSPACE) | \
+ __bit(X86_FEATURE_ALTMOVCR))
+#define AMD_EXTFEATURES_K8_REV_F_EDX (AMD_EXTFEATURES_K8_REV_E_EDX |\
+ __bit(X86_FEATURE_RDTSCP))
+
+/* Family 0Fh, Revision G */
+#define AMD_FEATURES_K8_REV_G_ECX AMD_FEATURES_K8_REV_F_ECX
+#define AMD_FEATURES_K8_REV_G_EDX AMD_FEATURES_K8_REV_F_EDX
+#define AMD_EXTFEATURES_K8_REV_G_ECX (AMD_EXTFEATURES_K8_REV_F_ECX |\
+ __bit(X86_FEATURE_3DNOWPF))
+#define AMD_EXTFEATURES_K8_REV_G_EDX AMD_EXTFEATURES_K8_REV_F_EDX
+
+/* Family 10h, Revision B */
+#define AMD_FEATURES_FAM10h_REV_B_ECX (AMD_FEATURES_K8_REV_F_ECX | \
+ __bit(X86_FEATURE_POPCNT) | __bit(X86_FEATURE_MWAIT))
+#define AMD_FEATURES_FAM10h_REV_B_EDX AMD_FEATURES_K8_REV_F_EDX
+#define AMD_EXTFEATURES_FAM10h_REV_B_ECX (AMD_EXTFEATURES_K8_REV_F_ECX |\
+ __bit(X86_FEATURE_ABM) | __bit(X86_FEATURE_SSE4A) | \
+ __bit(X86_FEATURE_MISALIGNSSE) | __bit(X86_FEATURE_OSVW) | \
+ __bit(X86_FEATURE_IBS))
+#define AMD_EXTFEATURES_FAM10h_REV_B_EDX (AMD_EXTFEATURES_K8_REV_F_EDX |\
+ __bit(X86_FEATURE_PAGE1GB))
+
+/* Family 10h, Revision C */
+#define AMD_FEATURES_FAM10h_REV_C_ECX AMD_FEATURES_FAM10h_REV_B_ECX
+#define AMD_FEATURES_FAM10h_REV_C_EDX AMD_FEATURES_FAM10h_REV_B_EDX
+#define AMD_EXTFEATURES_FAM10h_REV_C_ECX (AMD_EXTFEATURES_FAM10h_REV_B_ECX |\
+ __bit(X86_FEATURE_SKINIT) | __bit(X86_FEATURE_WDT))
+#define AMD_EXTFEATURES_FAM10h_REV_C_EDX AMD_EXTFEATURES_FAM10h_REV_B_EDX
+
+/* Family 11h, Revision B */
+#define AMD_FEATURES_FAM11h_REV_B_ECX AMD_FEATURES_K8_REV_G_ECX
+#define AMD_FEATURES_FAM11h_REV_B_EDX AMD_FEATURES_K8_REV_G_EDX
+#define AMD_EXTFEATURES_FAM11h_REV_B_ECX (AMD_EXTFEATURES_K8_REV_G_ECX |\
+ __bit(X86_FEATURE_SKINIT))
+#define AMD_EXTFEATURES_FAM11h_REV_B_EDX AMD_EXTFEATURES_K8_REV_G_EDX
+
+#endif /* __AMD_H__ */
diff -r 48db4eee7d58 -r d0a544d8a3f3 xen/arch/x86/hvm/emulate.c
--- a/xen/arch/x86/hvm/emulate.c Mon Aug 25 19:04:37 2008 +0900
+++ b/xen/arch/x86/hvm/emulate.c Mon Sep 01 16:59:43 2008 +0900
@@ -571,11 +571,12 @@ static int hvmemul_rep_movs(
{
struct hvm_emulate_ctxt *hvmemul_ctxt =
container_of(ctxt, struct hvm_emulate_ctxt, ctxt);
- unsigned long saddr, daddr;
+ unsigned long saddr, daddr, bytes;
paddr_t sgpa, dgpa;
uint32_t pfec = PFEC_page_present;
p2m_type_t p2mt;
- int rc;
+ int rc, df = !!(ctxt->regs->eflags & X86_EFLAGS_DF);
+ char *buf;
rc = hvmemul_virtual_to_linear(
src_seg, src_offset, bytes_per_rep, reps, hvm_access_read,
@@ -606,15 +607,56 @@ static int hvmemul_rep_movs(
(void)gfn_to_mfn_current(sgpa >> PAGE_SHIFT, &p2mt);
if ( !p2m_is_ram(p2mt) )
return hvmemul_do_mmio(
- sgpa, reps, bytes_per_rep, dgpa, IOREQ_READ,
- !!(ctxt->regs->eflags & X86_EFLAGS_DF), NULL);
+ sgpa, reps, bytes_per_rep, dgpa, IOREQ_READ, df, NULL);
(void)gfn_to_mfn_current(dgpa >> PAGE_SHIFT, &p2mt);
- if ( p2m_is_ram(p2mt) )
+ if ( !p2m_is_ram(p2mt) )
+ return hvmemul_do_mmio(
+ dgpa, reps, bytes_per_rep, sgpa, IOREQ_WRITE, df, NULL);
+
+ /* RAM-to-RAM copy: emulate as equivalent of memmove(dgpa, sgpa, bytes). */
+ bytes = *reps * bytes_per_rep;
+
+ /* Adjust source address for reverse copy. */
+ if ( df )
+ sgpa -= bytes - bytes_per_rep;
+
+ /*
+ * Will first iteration copy fall within source range? If not then entire
+ * copy does not corrupt itself. If so, then this is more complex than
+ * can be emulated by a source-to-buffer-to-destination block copy.
+ */
+ if ( ((dgpa + bytes_per_rep) > sgpa) && (dgpa < (sgpa + bytes)) )
return X86EMUL_UNHANDLEABLE;
- return hvmemul_do_mmio(
- dgpa, reps, bytes_per_rep, sgpa, IOREQ_WRITE,
- !!(ctxt->regs->eflags & X86_EFLAGS_DF), NULL);
+
+ /* Adjust destination address for reverse copy. */
+ if ( df )
+ dgpa -= bytes - bytes_per_rep;
+
+ /* Allocate temporary buffer. Fall back to slow emulation if this fails. */
+ buf = xmalloc_bytes(bytes);
+ if ( buf == NULL )
+ return X86EMUL_UNHANDLEABLE;
+
+ /*
+ * We do a modicum of checking here, just for paranoia's sake and to
+ * definitely avoid copying an unitialised buffer into guest address space.
+ */
+ rc = hvm_copy_from_guest_phys(buf, sgpa, bytes);
+ if ( rc == HVMCOPY_okay )
+ rc = hvm_copy_to_guest_phys(dgpa, buf, bytes);
+
+ xfree(buf);
+
+ if ( rc != HVMCOPY_okay )
+ {
+ gdprintk(XENLOG_WARNING, "Failed memory-to-memory REP MOVS: sgpa=%"
+ PRIpaddr" dgpa=%"PRIpaddr" reps=%lu bytes_per_rep=%u\n",
+ sgpa, dgpa, *reps, bytes_per_rep);
+ return X86EMUL_UNHANDLEABLE;
+ }
+
+ return X86EMUL_OKAY;
}
static int hvmemul_read_segment(
diff -r 48db4eee7d58 -r d0a544d8a3f3 xen/arch/x86/irq.c
--- a/xen/arch/x86/irq.c Mon Aug 25 19:04:37 2008 +0900
+++ b/xen/arch/x86/irq.c Mon Sep 01 16:59:43 2008 +0900
@@ -63,7 +63,9 @@ asmlinkage void do_IRQ(struct cpu_user_r
if ( likely(desc->status & IRQ_GUEST) )
{
+ irq_enter();
__do_IRQ_guest(vector);
+ irq_exit();
spin_unlock(&desc->lock);
return;
}
diff -r 48db4eee7d58 -r d0a544d8a3f3 xen/arch/x86/microcode.c
--- a/xen/arch/x86/microcode.c Mon Aug 25 19:04:37 2008 +0900
+++ b/xen/arch/x86/microcode.c Mon Sep 01 16:59:43 2008 +0900
@@ -124,7 +124,7 @@ static DEFINE_SPINLOCK(microcode_update_
/* no concurrent ->write()s are allowed on /dev/cpu/microcode */
static DEFINE_MUTEX(microcode_mutex);
-static void __user *user_buffer; /* user area microcode data buffer */
+static const void __user *user_buffer; /* user area microcode data buffer */
static unsigned int user_buffer_size; /* it's size */
typedef enum mc_error_code {
@@ -455,7 +455,7 @@ out:
return error;
}
-int microcode_update(XEN_GUEST_HANDLE(void) buf, unsigned long len)
+int microcode_update(XEN_GUEST_HANDLE(const_void) buf, unsigned long len)
{
int ret;
diff -r 48db4eee7d58 -r d0a544d8a3f3 xen/arch/x86/mm.c
--- a/xen/arch/x86/mm.c Mon Aug 25 19:04:37 2008 +0900
+++ b/xen/arch/x86/mm.c Mon Sep 01 16:59:43 2008 +0900
@@ -3339,6 +3339,7 @@ DEFINE_XEN_GUEST_HANDLE(e820entry_t);
long arch_memory_op(int op, XEN_GUEST_HANDLE(void) arg)
{
+ struct page_info *page = NULL;
switch ( op )
{
case XENMEM_add_to_physmap:
@@ -3389,12 +3390,22 @@ long arch_memory_op(int op, XEN_GUEST_HA
spin_unlock(&d->grant_table->lock);
break;
+ case XENMAPSPACE_mfn:
+ {
+ if ( get_page_from_pagenr(xatp.idx, d) ) {
+ mfn = xatp.idx;
+ page = mfn_to_page(mfn);
+ }
+ break;
+ }
default:
break;
}
if ( !paging_mode_translate(d) || (mfn == 0) )
{
+ if ( page )
+ put_page(page);
rcu_unlock_domain(d);
return -EINVAL;
}
@@ -3420,6 +3431,53 @@ long arch_memory_op(int op, XEN_GUEST_HA
/* Map at new location. */
guest_physmap_add_page(d, xatp.gpfn, mfn, 0);
+
+ domain_unlock(d);
+
+ if ( page )
+ put_page(page);
+
+ rcu_unlock_domain(d);
+
+ break;
+ }
+
+ case XENMEM_remove_from_physmap:
+ {
+ struct xen_remove_from_physmap xrfp;
+ unsigned long mfn;
+ struct domain *d;
+
+ if ( copy_from_guest(&xrfp, arg, 1) )
+ return -EFAULT;
+
+ if ( xrfp.domid == DOMID_SELF )
+ {
+ d = rcu_lock_current_domain();
+ }
+ else
+ {
+ if ( (d = rcu_lock_domain_by_id(xrfp.domid)) == NULL )
+ return -ESRCH;
+ if ( !IS_PRIV_FOR(current->domain, d) )
+ {
+ rcu_unlock_domain(d);
+ return -EPERM;
+ }
+ }
+
+ if ( xsm_remove_from_physmap(current->domain, d) )
+ {
+ rcu_unlock_domain(d);
+ return -EPERM;
+ }
+
+ domain_lock(d);
+
+ mfn = gmfn_to_mfn(d, xrfp.gpfn);
+
+ if ( mfn_valid(mfn) )
+ guest_physmap_remove_page(d, xrfp.gpfn, mfn, 0);
domain_unlock(d);
diff -r 48db4eee7d58 -r d0a544d8a3f3 xen/arch/x86/platform_hypercall.c
--- a/xen/arch/x86/platform_hypercall.c Mon Aug 25 19:04:37 2008 +0900
+++ b/xen/arch/x86/platform_hypercall.c Mon Sep 01 16:59:43 2008 +0900
@@ -147,8 +147,7 @@ ret_t do_platform_op(XEN_GUEST_HANDLE(xe
case XENPF_microcode_update:
{
- extern int microcode_update(XEN_GUEST_HANDLE(void), unsigned long len);
- XEN_GUEST_HANDLE(void) data;
+ XEN_GUEST_HANDLE(const_void) data;
ret = xsm_microcode();
if ( ret )
diff -r 48db4eee7d58 -r d0a544d8a3f3 xen/arch/x86/time.c
--- a/xen/arch/x86/time.c Mon Aug 25 19:04:37 2008 +0900
+++ b/xen/arch/x86/time.c Mon Sep 01 16:59:43 2008 +0900
@@ -840,12 +840,11 @@ struct cpu_calibration {
u64 local_tsc_stamp;
s_time_t stime_local_stamp;
s_time_t stime_master_stamp;
- struct timer softirq_callback;
};
static DEFINE_PER_CPU(struct cpu_calibration, cpu_calibration);
/* Softirq handler for per-CPU time calibration. */
-static void local_time_calibration(void *unused)
+static void local_time_calibration(void)
{
struct cpu_time *t = &this_cpu(cpu_time);
struct cpu_calibration *c = &this_cpu(cpu_calibration);
@@ -1004,13 +1003,12 @@ static void time_calibration_rendezvous(
struct cpu_calibration *c = &this_cpu(cpu_calibration);
struct calibration_rendezvous *r = _r;
- local_irq_disable();
-
if ( smp_processor_id() == 0 )
{
while ( atomic_read(&r->nr_cpus) != (total_cpus - 1) )
cpu_relax();
r->master_stime = read_platform_stime();
+ mb(); /* write r->master_stime /then/ signal */
atomic_inc(&r->nr_cpus);
}
else
@@ -1018,16 +1016,14 @@ static void time_calibration_rendezvous(
atomic_inc(&r->nr_cpus);
while ( atomic_read(&r->nr_cpus) != total_cpus )
cpu_relax();
+ mb(); /* receive signal /then/ read r->master_stime */
}
rdtscll(c->local_tsc_stamp);
c->stime_local_stamp = get_s_time();
c->stime_master_stamp = r->master_stime;
- local_irq_enable();
-
- /* Callback in softirq context as soon as possible. */
- set_timer(&c->softirq_callback, c->stime_local_stamp);
+ raise_softirq(TIME_CALIBRATE_SOFTIRQ);
}
static void time_calibration(void *unused)
@@ -1036,6 +1032,7 @@ static void time_calibration(void *unuse
.nr_cpus = ATOMIC_INIT(0)
};
+ /* @wait=1 because we must wait for all cpus before freeing @r. */
on_each_cpu(time_calibration_rendezvous, &r, 0, 1);
}
@@ -1053,9 +1050,6 @@ void init_percpu_time(void)
t->stime_master_stamp = now;
t->stime_local_stamp = now;
- init_timer(&this_cpu(cpu_calibration).softirq_callback,
- local_time_calibration, NULL, smp_processor_id());
-
if ( smp_processor_id() == 0 )
{
init_timer(&calibration_timer, time_calibration, NULL, 0);
@@ -1072,6 +1066,8 @@ int __init init_xen_time(void)
this is a new feature introduced by Nehalem*/
if ( cpuid_edx(0x80000007) & (1u<<8) )
tsc_invariant = 1;
+
+ open_softirq(TIME_CALIBRATE_SOFTIRQ, local_time_calibration);
init_percpu_time();
@@ -1180,7 +1176,7 @@ int time_suspend(void)
}
/* Better to cancel calibration timer for accuracy. */
- kill_timer(&this_cpu(cpu_calibration).softirq_callback);
+ clear_bit(TIME_CALIBRATE_SOFTIRQ, &softirq_pending(smp_processor_id()));
return 0;
}
diff -r 48db4eee7d58 -r d0a544d8a3f3 xen/arch/x86/x86_64/compat/mm.c
--- a/xen/arch/x86/x86_64/compat/mm.c Mon Aug 25 19:04:37 2008 +0900
+++ b/xen/arch/x86/x86_64/compat/mm.c Mon Sep 01 16:59:43 2008 +0900
@@ -64,6 +64,20 @@ int compat_arch_memory_op(int op, XEN_GU
return -EFAULT;
XLAT_add_to_physmap(nat, &cmp);
+ rc = arch_memory_op(op, guest_handle_from_ptr(nat, void));
+
+ break;
+ }
+
+ case XENMEM_remove_from_physmap:
+ {
+ struct compat_remove_from_physmap cmp;
+ struct xen_remove_from_physmap *nat = (void
*)COMPAT_ARG_XLAT_VIRT_BASE;
+
+ if ( copy_from_guest(&cmp, arg, 1) )
+ return -EFAULT;
+
+ XLAT_remove_from_physmap(nat, &cmp);
rc = arch_memory_op(op, guest_handle_from_ptr(nat, void));
break;
diff -r 48db4eee7d58 -r d0a544d8a3f3 xen/common/softirq.c
--- a/xen/common/softirq.c Mon Aug 25 19:04:37 2008 +0900
+++ b/xen/common/softirq.c Mon Sep 01 16:59:43 2008 +0900
@@ -49,6 +49,7 @@ asmlinkage void do_softirq(void)
void open_softirq(int nr, softirq_handler handler)
{
+ ASSERT(nr < NR_SOFTIRQS);
softirq_handlers[nr] = handler;
}
diff -r 48db4eee7d58 -r d0a544d8a3f3 xen/common/timer.c
--- a/xen/common/timer.c Mon Aug 25 19:04:37 2008 +0900
+++ b/xen/common/timer.c Mon Sep 01 16:59:43 2008 +0900
@@ -30,6 +30,7 @@ struct timers {
struct timers {
spinlock_t lock;
struct timer **heap;
+ struct timer *list;
struct timer *running;
} __cacheline_aligned;
@@ -86,12 +87,10 @@ static void up_heap(struct timer **heap,
/* Delete @t from @heap. Return TRUE if new top of heap. */
-static int remove_entry(struct timer **heap, struct timer *t)
+static int remove_from_heap(struct timer **heap, struct timer *t)
{
int sz = GET_HEAP_SIZE(heap);
int pos = t->heap_offset;
-
- t->heap_offset = 0;
if ( unlikely(pos == sz) )
{
@@ -115,7 +114,7 @@ static int remove_entry(struct timer **h
/* Add new entry @t to @heap. Return TRUE if new top of heap. */
-static int add_entry(struct timer ***pheap, struct timer *t)
+static int add_to_heap(struct timer ***pheap, struct timer *t)
{
struct timer **heap = *pheap;
int sz = GET_HEAP_SIZE(heap);
@@ -126,8 +125,11 @@ static int add_entry(struct timer ***phe
/* old_limit == (2^n)-1; new_limit == (2^(n+4))-1 */
int old_limit = GET_HEAP_LIMIT(heap);
int new_limit = ((old_limit + 1) << 4) - 1;
+ if ( in_irq() )
+ goto out;
heap = xmalloc_array(struct timer *, new_limit + 1);
- BUG_ON(heap == NULL);
+ if ( heap == NULL )
+ goto out;
memcpy(heap, *pheap, (old_limit + 1) * sizeof(*heap));
SET_HEAP_LIMIT(heap, new_limit);
if ( old_limit != 0 )
@@ -139,7 +141,38 @@ static int add_entry(struct timer ***phe
heap[sz] = t;
t->heap_offset = sz;
up_heap(heap, sz);
+ out:
return (t->heap_offset == 1);
+}
+
+
+/****************************************************************************
+ * LINKED LIST OPERATIONS.
+ */
+
+static int remove_from_list(struct timer **pprev, struct timer *t)
+{
+ struct timer *curr, **_pprev = pprev;
+
+ while ( (curr = *_pprev) != t )
+ _pprev = &curr->list_next;
+
+ *_pprev = t->list_next;
+
+ return (_pprev == pprev);
+}
+
+static int add_to_list(struct timer **pprev, struct timer *t)
+{
+ struct timer *curr, **_pprev = pprev;
+
+ while ( ((curr = *_pprev) != NULL) && (curr->expires <= t->expires) )
+ _pprev = &curr->list_next;
+
+ t->list_next = curr;
+ *_pprev = t;
+
+ return (_pprev == pprev);
}
@@ -147,18 +180,56 @@ static int add_entry(struct timer ***phe
* TIMER OPERATIONS.
*/
+static int remove_entry(struct timers *timers, struct timer *t)
+{
+ int rc;
+
+ switch ( t->status )
+ {
+ case TIMER_STATUS_in_heap:
+ rc = remove_from_heap(timers->heap, t);
+ break;
+ case TIMER_STATUS_in_list:
+ rc = remove_from_list(&timers->list, t);
+ break;
+ default:
+ rc = 0;
+ BUG();
+ }
+
+ t->status = TIMER_STATUS_inactive;
+ return rc;
+}
+
+static int add_entry(struct timers *timers, struct timer *t)
+{
+ int rc;
+
+ ASSERT(t->status == TIMER_STATUS_inactive);
+
+ /* Try to add to heap. t->heap_offset indicates whether we succeed. */
+ t->heap_offset = 0;
+ t->status = TIMER_STATUS_in_heap;
+ rc = add_to_heap(&timers->heap, t);
+ if ( t->heap_offset != 0 )
+ return rc;
+
+ /* Fall back to adding to the slower linked list. */
+ t->status = TIMER_STATUS_in_list;
+ return add_to_list(&timers->list, t);
+}
+
static inline void __add_timer(struct timer *timer)
{
int cpu = timer->cpu;
- if ( add_entry(&per_cpu(timers, cpu).heap, timer) )
+ if ( add_entry(&per_cpu(timers, cpu), timer) )
cpu_raise_softirq(cpu, TIMER_SOFTIRQ);
}
-
static inline void __stop_timer(struct timer *timer)
{
int cpu = timer->cpu;
- if ( remove_entry(per_cpu(timers, cpu).heap, timer) )
+ if ( remove_entry(&per_cpu(timers, cpu), timer) )
cpu_raise_softirq(cpu, TIMER_SOFTIRQ);
}
@@ -203,7 +274,7 @@ void set_timer(struct timer *timer, s_ti
timer->expires = expires;
- if ( likely(!timer->killed) )
+ if ( likely(timer->status != TIMER_STATUS_killed) )
__add_timer(timer);
timer_unlock_irqrestore(timer, flags);
@@ -278,7 +349,7 @@ void kill_timer(struct timer *timer)
if ( active_timer(timer) )
__stop_timer(timer);
- timer->killed = 1;
+ timer->status = TIMER_STATUS_killed;
timer_unlock_irqrestore(timer, flags);
@@ -290,43 +361,76 @@ void kill_timer(struct timer *timer)
static void timer_softirq_action(void)
{
- struct timer *t, **heap;
+ struct timer *t, **heap, *next;
struct timers *ts;
- s_time_t now;
+ s_time_t now, deadline;
void (*fn)(void *);
void *data;
ts = &this_cpu(timers);
spin_lock_irq(&ts->lock);
+
+ /* Try to move timers from overflow linked list to more efficient heap. */
+ next = ts->list;
+ ts->list = NULL;
+ while ( unlikely((t = next) != NULL) )
+ {
+ next = t->list_next;
+ t->status = TIMER_STATUS_inactive;
+ add_entry(ts, t);
+ }
- do {
+ heap = ts->heap;
+ now = NOW();
+
+ while ( (GET_HEAP_SIZE(heap) != 0) &&
+ ((t = heap[1])->expires < (now + TIMER_SLOP)) )
+ {
+ remove_entry(ts, t);
+
+ ts->running = t;
+
+ fn = t->function;
+ data = t->data;
+
+ spin_unlock_irq(&ts->lock);
+ (*fn)(data);
+ spin_lock_irq(&ts->lock);
+
+ /* Heap may have grown while the lock was released. */
heap = ts->heap;
- now = NOW();
-
- while ( (GET_HEAP_SIZE(heap) != 0) &&
- ((t = heap[1])->expires < (now + TIMER_SLOP)) )
+ }
+
+ deadline = GET_HEAP_SIZE(heap) ? heap[1]->expires : 0;
+
+ while ( unlikely((t = ts->list) != NULL) )
+ {
+ if ( t->expires >= (now + TIMER_SLOP) )
{
- remove_entry(heap, t);
-
- ts->running = t;
-
- fn = t->function;
- data = t->data;
-
- spin_unlock_irq(&ts->lock);
- (*fn)(data);
- spin_lock_irq(&ts->lock);
-
- /* Heap may have grown while the lock was released. */
- heap = ts->heap;
+ if ( (deadline == 0) || (deadline > t->expires) )
+ deadline = t->expires;
+ break;
}
- ts->running = NULL;
-
- this_cpu(timer_deadline) = GET_HEAP_SIZE(heap) ? heap[1]->expires : 0;
- }
- while ( !reprogram_timer(this_cpu(timer_deadline)) );
+ ts->list = t->list_next;
+ t->status = TIMER_STATUS_inactive;
+
+ ts->running = t;
+
+ fn = t->function;
+ data = t->data;
+
+ spin_unlock_irq(&ts->lock);
+ (*fn)(data);
+ spin_lock_irq(&ts->lock);
+ }
+
+ ts->running = NULL;
+
+ this_cpu(timer_deadline) = deadline;
+ if ( !reprogram_timer(deadline) )
+ raise_softirq(TIMER_SOFTIRQ);
spin_unlock_irq(&ts->lock);
}
@@ -364,6 +468,9 @@ static void dump_timerq(unsigned char ke
printk (" %d : %p ex=0x%08X%08X %p\n",
j, t, (u32)(t->expires>>32), (u32)t->expires, t->data);
}
+ for ( t = ts->list, j = 0; t != NULL; t = t->list_next, j++ )
+ printk (" L%d : %p ex=0x%08X%08X %p\n",
+ j, t, (u32)(t->expires>>32), (u32)t->expires, t->data);
spin_unlock_irqrestore(&ts->lock, flags);
printk("\n");
}
diff -r 48db4eee7d58 -r d0a544d8a3f3 xen/common/xmalloc.c
--- a/xen/common/xmalloc.c Mon Aug 25 19:04:37 2008 +0900
+++ b/xen/common/xmalloc.c Mon Sep 01 16:59:43 2008 +0900
@@ -136,15 +136,14 @@ static void *xmalloc_new_page(size_t siz
static void *xmalloc_new_page(size_t size)
{
struct xmalloc_hdr *hdr;
- unsigned long flags;
hdr = alloc_xenheap_page();
if ( hdr == NULL )
return NULL;
- spin_lock_irqsave(&freelist_lock, flags);
+ spin_lock(&freelist_lock);
maybe_split(hdr, size, PAGE_SIZE);
- spin_unlock_irqrestore(&freelist_lock, flags);
+ spin_unlock(&freelist_lock);
return data_from_header(hdr);
}
@@ -175,7 +174,6 @@ void *_xmalloc(size_t size, size_t align
void *_xmalloc(size_t size, size_t align)
{
struct xmalloc_hdr *i;
- unsigned long flags;
ASSERT(!in_irq());
@@ -196,17 +194,17 @@ void *_xmalloc(size_t size, size_t align
return xmalloc_whole_pages(size);
/* Search free list. */
- spin_lock_irqsave(&freelist_lock, flags);
+ spin_lock(&freelist_lock);
list_for_each_entry( i, &freelist, freelist )
{
if ( i->size < size )
continue;
del_from_freelist(i);
maybe_split(i, size, i->size);
- spin_unlock_irqrestore(&freelist_lock, flags);
+ spin_unlock(&freelist_lock);
return data_from_header(i);
}
- spin_unlock_irqrestore(&freelist_lock, flags);
+ spin_unlock(&freelist_lock);
/* Alloc a new page and return from that. */
return xmalloc_new_page(size);
@@ -214,7 +212,6 @@ void *_xmalloc(size_t size, size_t align
void xfree(void *p)
{
- unsigned long flags;
struct xmalloc_hdr *i, *tmp, *hdr;
ASSERT(!in_irq());
@@ -238,7 +235,7 @@ void xfree(void *p)
}
/* Merge with other free block, or put in list. */
- spin_lock_irqsave(&freelist_lock, flags);
+ spin_lock(&freelist_lock);
list_for_each_entry_safe( i, tmp, &freelist, freelist )
{
unsigned long _i = (unsigned long)i;
@@ -275,7 +272,7 @@ void xfree(void *p)
add_to_freelist(hdr);
}
- spin_unlock_irqrestore(&freelist_lock, flags);
+ spin_unlock(&freelist_lock);
}
/*
diff -r 48db4eee7d58 -r d0a544d8a3f3 xen/drivers/passthrough/vtd/intremap.c
--- a/xen/drivers/passthrough/vtd/intremap.c Mon Aug 25 19:04:37 2008 +0900
+++ b/xen/drivers/passthrough/vtd/intremap.c Mon Sep 01 16:59:43 2008 +0900
@@ -43,7 +43,7 @@ u16 apicid_to_bdf(int apic_id)
return 0;
}
-static void remap_entry_to_ioapic_rte(
+static int remap_entry_to_ioapic_rte(
struct iommu *iommu, struct IO_APIC_route_entry *old_rte)
{
struct iremap_entry *iremap_entry = NULL, *iremap_entries;
@@ -56,15 +56,19 @@ static void remap_entry_to_ioapic_rte(
{
dprintk(XENLOG_ERR VTDPREFIX,
"remap_entry_to_ioapic_rte: ir_ctl is not ready\n");
- return;
+ return -EFAULT;
}
remap_rte = (struct IO_APIC_route_remap_entry *) old_rte;
index = (remap_rte->index_15 << 15) | remap_rte->index_0_14;
if ( index > ir_ctrl->iremap_index )
- panic("%s: index (%d) is larger than remap table entry size (%d)!\n",
- __func__, index, ir_ctrl->iremap_index);
+ {
+ dprintk(XENLOG_ERR VTDPREFIX,
+ "%s: index (%d) is larger than remap table entry size (%d)!\n",
+ __func__, index, ir_ctrl->iremap_index);
+ return -EFAULT;
+ }
spin_lock_irqsave(&ir_ctrl->iremap_lock, flags);
@@ -82,9 +86,10 @@ static void remap_entry_to_ioapic_rte(
unmap_vtd_domain_page(iremap_entries);
spin_unlock_irqrestore(&ir_ctrl->iremap_lock, flags);
-}
-
-static void ioapic_rte_to_remap_entry(struct iommu *iommu,
+ return 0;
+}
+
+static int ioapic_rte_to_remap_entry(struct iommu *iommu,
int apic_id, struct IO_APIC_route_entry *old_rte,
unsigned int rte_upper, unsigned int value)
{
@@ -108,7 +113,14 @@ static void ioapic_rte_to_remap_entry(st
index = (remap_rte->index_15 << 15) | remap_rte->index_0_14;
if ( index > IREMAP_ENTRY_NR - 1 )
- panic("ioapic_rte_to_remap_entry: intremap index is more than 256!\n");
+ {
+ dprintk(XENLOG_ERR VTDPREFIX,
+ "%s: intremap index (%d) is larger than"
+ " the maximum index (%ld)!\n",
+ __func__, index, IREMAP_ENTRY_NR - 1);
+ spin_unlock_irqrestore(&ir_ctrl->iremap_lock, flags);
+ return -EFAULT;
+ }
iremap_entries =
(struct iremap_entry *)map_vtd_domain_page(ir_ctrl->iremap_maddr);
@@ -159,7 +171,7 @@ static void ioapic_rte_to_remap_entry(st
unmap_vtd_domain_page(iremap_entries);
spin_unlock_irqrestore(&ir_ctrl->iremap_lock, flags);
- return;
+ return 0;
}
unsigned int io_apic_read_remap_rte(
@@ -189,23 +201,22 @@ unsigned int io_apic_read_remap_rte(
remap_rte = (struct IO_APIC_route_remap_entry *) &old_rte;
- if ( remap_rte->mask || (remap_rte->format == 0) )
- {
- *IO_APIC_BASE(apic) = reg;
+ if ( remap_rte->format == 0 )
+ {
+ *IO_APIC_BASE(apic) = rte_upper ? (reg + 1) : reg;
return *(IO_APIC_BASE(apic)+4);
}
- remap_entry_to_ioapic_rte(iommu, &old_rte);
+ if ( remap_entry_to_ioapic_rte(iommu, &old_rte) )
+ {
+ *IO_APIC_BASE(apic) = rte_upper ? (reg + 1) : reg;
+ return *(IO_APIC_BASE(apic)+4);
+ }
+
if ( rte_upper )
- {
- *IO_APIC_BASE(apic) = reg + 1;
return (*(((u32 *)&old_rte) + 1));
- }
else
- {
- *IO_APIC_BASE(apic) = reg;
return (*(((u32 *)&old_rte) + 0));
- }
}
void io_apic_write_remap_rte(
@@ -243,8 +254,13 @@ void io_apic_write_remap_rte(
*(IO_APIC_BASE(apic)+4) = *(((int *)&old_rte)+0);
remap_rte->mask = saved_mask;
- ioapic_rte_to_remap_entry(iommu, mp_ioapics[apic].mpc_apicid,
- &old_rte, rte_upper, value);
+ if ( ioapic_rte_to_remap_entry(iommu, mp_ioapics[apic].mpc_apicid,
+ &old_rte, rte_upper, value) )
+ {
+ *IO_APIC_BASE(apic) = rte_upper ? (reg + 1) : reg;
+ *(IO_APIC_BASE(apic)+4) = value;
+ return;
+ }
/* write new entry to ioapic */
*IO_APIC_BASE(apic) = reg;
@@ -253,7 +269,7 @@ void io_apic_write_remap_rte(
*(IO_APIC_BASE(apic)+4) = *(((u32 *)&old_rte)+1);
}
-static void remap_entry_to_msi_msg(
+static int remap_entry_to_msi_msg(
struct iommu *iommu, struct msi_msg *msg)
{
struct iremap_entry *iremap_entry = NULL, *iremap_entries;
@@ -266,7 +282,7 @@ static void remap_entry_to_msi_msg(
{
dprintk(XENLOG_ERR VTDPREFIX,
"remap_entry_to_msi_msg: ir_ctl == NULL");
- return;
+ return -EFAULT;
}
remap_rte = (struct msi_msg_remap_entry *) msg;
@@ -274,8 +290,12 @@ static void remap_entry_to_msi_msg(
remap_rte->address_lo.index_0_14;
if ( index > ir_ctrl->iremap_index )
- panic("%s: index (%d) is larger than remap table entry size (%d)\n",
- __func__, index, ir_ctrl->iremap_index);
+ {
+ dprintk(XENLOG_ERR VTDPREFIX,
+ "%s: index (%d) is larger than remap table entry size (%d)\n",
+ __func__, index, ir_ctrl->iremap_index);
+ return -EFAULT;
+ }
spin_lock_irqsave(&ir_ctrl->iremap_lock, flags);
@@ -304,9 +324,10 @@ static void remap_entry_to_msi_msg(
unmap_vtd_domain_page(iremap_entries);
spin_unlock_irqrestore(&ir_ctrl->iremap_lock, flags);
-}
-
-static void msi_msg_to_remap_entry(
+ return 0;
+}
+
+static int msi_msg_to_remap_entry(
struct iommu *iommu, struct pci_dev *pdev, struct msi_msg *msg)
{
struct iremap_entry *iremap_entry = NULL, *iremap_entries;
@@ -343,7 +364,15 @@ static void msi_msg_to_remap_entry(
index = i;
if ( index > IREMAP_ENTRY_NR - 1 )
- panic("msi_msg_to_remap_entry: intremap index is more than 256!\n");
+ {
+ dprintk(XENLOG_ERR VTDPREFIX,
+ "%s: intremap index (%d) is larger than"
+ " the maximum index (%ld)!\n",
+ __func__, index, IREMAP_ENTRY_NR - 1);
+ unmap_vtd_domain_page(iremap_entries);
+ spin_unlock_irqrestore(&ir_ctrl->iremap_lock, flags);
+ return -EFAULT;
+ }
iremap_entry = &iremap_entries[index];
memcpy(&new_ire, iremap_entry, sizeof(struct iremap_entry));
@@ -385,7 +414,7 @@ static void msi_msg_to_remap_entry(
unmap_vtd_domain_page(iremap_entries);
spin_unlock_irqrestore(&ir_ctrl->iremap_lock, flags);
- return;
+ return 0;
}
void msi_msg_read_remap_rte(
diff -r 48db4eee7d58 -r d0a544d8a3f3 xen/drivers/passthrough/vtd/iommu.c
--- a/xen/drivers/passthrough/vtd/iommu.c Mon Aug 25 19:04:37 2008 +0900
+++ b/xen/drivers/passthrough/vtd/iommu.c Mon Sep 01 16:59:43 2008 +0900
@@ -624,15 +624,10 @@ static int iommu_set_root_entry(struct i
unsigned long flags;
s_time_t start_time;
- if ( iommu->root_maddr != 0 )
- {
- free_pgtable_maddr(iommu->root_maddr);
- iommu->root_maddr = 0;
- }
-
spin_lock_irqsave(&iommu->register_lock, flags);
- iommu->root_maddr = alloc_pgtable_maddr();
+ if ( iommu->root_maddr == 0 )
+ iommu->root_maddr = alloc_pgtable_maddr();
if ( iommu->root_maddr == 0 )
{
spin_unlock_irqrestore(&iommu->register_lock, flags);
@@ -1864,37 +1859,31 @@ static int intel_iommu_group_id(u8 bus,
return -1;
}
-u8 iommu_state[MAX_IOMMU_REGS * MAX_IOMMUS];
+static u32 iommu_state[MAX_IOMMUS][MAX_IOMMU_REGS];
int iommu_suspend(void)
{
struct acpi_drhd_unit *drhd;
struct iommu *iommu;
- int i = 0;
+ u32 i;
+
+ if ( !vtd_enabled )
+ return 0;
iommu_flush_all();
for_each_drhd_unit ( drhd )
{
iommu = drhd->iommu;
- iommu_state[DMAR_RTADDR_REG * i] =
- (u64) dmar_readq(iommu->reg, DMAR_RTADDR_REG);
- iommu_state[DMAR_FECTL_REG * i] =
+ i = iommu->index;
+
+ iommu_state[i][DMAR_FECTL_REG] =
(u32) dmar_readl(iommu->reg, DMAR_FECTL_REG);
- iommu_state[DMAR_FEDATA_REG * i] =
+ iommu_state[i][DMAR_FEDATA_REG] =
(u32) dmar_readl(iommu->reg, DMAR_FEDATA_REG);
- iommu_state[DMAR_FEADDR_REG * i] =
+ iommu_state[i][DMAR_FEADDR_REG] =
(u32) dmar_readl(iommu->reg, DMAR_FEADDR_REG);
- iommu_state[DMAR_FEUADDR_REG * i] =
+ iommu_state[i][DMAR_FEUADDR_REG] =
(u32) dmar_readl(iommu->reg, DMAR_FEUADDR_REG);
- iommu_state[DMAR_PLMBASE_REG * i] =
- (u32) dmar_readl(iommu->reg, DMAR_PLMBASE_REG);
- iommu_state[DMAR_PLMLIMIT_REG * i] =
- (u32) dmar_readl(iommu->reg, DMAR_PLMLIMIT_REG);
- iommu_state[DMAR_PHMBASE_REG * i] =
- (u64) dmar_readq(iommu->reg, DMAR_PHMBASE_REG);
- iommu_state[DMAR_PHMLIMIT_REG * i] =
- (u64) dmar_readq(iommu->reg, DMAR_PHMLIMIT_REG);
- i++;
}
return 0;
@@ -1904,37 +1893,34 @@ int iommu_resume(void)
{
struct acpi_drhd_unit *drhd;
struct iommu *iommu;
- int i = 0;
+ u32 i;
+
+ if ( !vtd_enabled )
+ return 0;
iommu_flush_all();
- init_vtd_hw();
+ if ( init_vtd_hw() != 0 && force_iommu )
+ panic("IOMMU setup failed, crash Xen for security purpose!\n");
+
for_each_drhd_unit ( drhd )
{
iommu = drhd->iommu;
- dmar_writeq( iommu->reg, DMAR_RTADDR_REG,
- (u64) iommu_state[DMAR_RTADDR_REG * i]);
+ i = iommu->index;
+
dmar_writel(iommu->reg, DMAR_FECTL_REG,
- (u32) iommu_state[DMAR_FECTL_REG * i]);
+ (u32) iommu_state[i][DMAR_FECTL_REG]);
dmar_writel(iommu->reg, DMAR_FEDATA_REG,
- (u32) iommu_state[DMAR_FEDATA_REG * i]);
+ (u32) iommu_state[i][DMAR_FEDATA_REG]);
dmar_writel(iommu->reg, DMAR_FEADDR_REG,
- (u32) iommu_state[DMAR_FEADDR_REG * i]);
+ (u32) iommu_state[i][DMAR_FEADDR_REG]);
dmar_writel(iommu->reg, DMAR_FEUADDR_REG,
- (u32) iommu_state[DMAR_FEUADDR_REG * i]);
- dmar_writel(iommu->reg, DMAR_PLMBASE_REG,
- (u32) iommu_state[DMAR_PLMBASE_REG * i]);
- dmar_writel(iommu->reg, DMAR_PLMLIMIT_REG,
- (u32) iommu_state[DMAR_PLMLIMIT_REG * i]);
- dmar_writeq(iommu->reg, DMAR_PHMBASE_REG,
- (u64) iommu_state[DMAR_PHMBASE_REG * i]);
- dmar_writeq(iommu->reg, DMAR_PHMLIMIT_REG,
- (u64) iommu_state[DMAR_PHMLIMIT_REG * i]);
+ (u32) iommu_state[i][DMAR_FEUADDR_REG]);
if ( iommu_enable_translation(iommu) )
return -EIO;
- i++;
- }
+ }
+
return 0;
}
diff -r 48db4eee7d58 -r d0a544d8a3f3 xen/include/asm-x86/io_apic.h
--- a/xen/include/asm-x86/io_apic.h Mon Aug 25 19:04:37 2008 +0900
+++ b/xen/include/asm-x86/io_apic.h Mon Sep 01 16:59:43 2008 +0900
@@ -125,7 +125,7 @@ extern int mpc_default_type;
static inline unsigned int io_apic_read(unsigned int apic, unsigned int reg)
{
- if (vtd_enabled)
+ if (iommu_enabled)
return io_apic_read_remap_rte(apic, reg);
*IO_APIC_BASE(apic) = reg;
return *(IO_APIC_BASE(apic)+4);
@@ -152,6 +152,8 @@ extern int sis_apic_bug;
#endif
static inline void io_apic_modify(unsigned int apic, unsigned int reg,
unsigned int value)
{
+ if (iommu_enabled)
+ return iommu_update_ire_from_apic(apic, reg, value);
if (sis_apic_bug)
*IO_APIC_BASE(apic) = reg;
*(IO_APIC_BASE(apic)+4) = value;
diff -r 48db4eee7d58 -r d0a544d8a3f3 xen/include/asm-x86/msr-index.h
--- a/xen/include/asm-x86/msr-index.h Mon Aug 25 19:04:37 2008 +0900
+++ b/xen/include/asm-x86/msr-index.h Mon Sep 01 16:59:43 2008 +0900
@@ -186,6 +186,9 @@
#define MSR_K8_ENABLE_C1E 0xc0010055
#define MSR_K8_VM_CR 0xc0010114
#define MSR_K8_VM_HSAVE_PA 0xc0010117
+
+#define MSR_K8_FEATURE_MASK 0xc0011004
+#define MSR_K8_EXT_FEATURE_MASK 0xc0011005
/* MSR_K8_VM_CR bits: */
#define _K8_VMCR_SVME_DISABLE 4
diff -r 48db4eee7d58 -r d0a544d8a3f3 xen/include/asm-x86/processor.h
--- a/xen/include/asm-x86/processor.h Mon Aug 25 19:04:37 2008 +0900
+++ b/xen/include/asm-x86/processor.h Mon Sep 01 16:59:43 2008 +0900
@@ -583,6 +583,8 @@ int wrmsr_hypervisor_regs(
int wrmsr_hypervisor_regs(
uint32_t idx, uint32_t eax, uint32_t edx);
+int microcode_update(XEN_GUEST_HANDLE(const_void), unsigned long len);
+
#endif /* !__ASSEMBLY__ */
#endif /* __ASM_X86_PROCESSOR_H */
diff -r 48db4eee7d58 -r d0a544d8a3f3 xen/include/asm-x86/softirq.h
--- a/xen/include/asm-x86/softirq.h Mon Aug 25 19:04:37 2008 +0900
+++ b/xen/include/asm-x86/softirq.h Mon Sep 01 16:59:43 2008 +0900
@@ -1,8 +1,9 @@
#ifndef __ASM_SOFTIRQ_H__
#define __ASM_SOFTIRQ_H__
-#define NMI_MCE_SOFTIRQ (NR_COMMON_SOFTIRQS + 0)
+#define NMI_MCE_SOFTIRQ (NR_COMMON_SOFTIRQS + 0)
+#define TIME_CALIBRATE_SOFTIRQ (NR_COMMON_SOFTIRQS + 1)
-#define NR_ARCH_SOFTIRQS 1
+#define NR_ARCH_SOFTIRQS 2
#endif /* __ASM_SOFTIRQ_H__ */
diff -r 48db4eee7d58 -r d0a544d8a3f3 xen/include/public/memory.h
--- a/xen/include/public/memory.h Mon Aug 25 19:04:37 2008 +0900
+++ b/xen/include/public/memory.h Mon Sep 01 16:59:43 2008 +0900
@@ -204,6 +204,7 @@ struct xen_add_to_physmap {
/* Source mapping space. */
#define XENMAPSPACE_shared_info 0 /* shared info page */
#define XENMAPSPACE_grant_table 1 /* grant table page */
+#define XENMAPSPACE_mfn 2 /* usual MFN */
unsigned int space;
/* Index into source mapping space. */
@@ -214,6 +215,22 @@ struct xen_add_to_physmap {
};
typedef struct xen_add_to_physmap xen_add_to_physmap_t;
DEFINE_XEN_GUEST_HANDLE(xen_add_to_physmap_t);
+
+/*
+ * Unmaps the page appearing at a particular GPFN from the specified guest's
+ * pseudophysical address space.
+ * arg == addr of xen_remove_from_physmap_t.
+ */
+#define XENMEM_remove_from_physmap 15
+struct xen_remove_from_physmap {
+ /* Which domain to change the mapping for. */
+ domid_t domid;
+
+ /* GPFN of the current mapping of the page. */
+ xen_pfn_t gpfn;
+};
+typedef struct xen_remove_from_physmap xen_remove_from_physmap_t;
+DEFINE_XEN_GUEST_HANDLE(xen_remove_from_physmap_t);
/*
* Translates a list of domain-specific GPFNs into MFNs. Returns a -ve error
diff -r 48db4eee7d58 -r d0a544d8a3f3 xen/include/public/platform.h
--- a/xen/include/public/platform.h Mon Aug 25 19:04:37 2008 +0900
+++ b/xen/include/public/platform.h Mon Sep 01 16:59:43 2008 +0900
@@ -97,7 +97,7 @@ DEFINE_XEN_GUEST_HANDLE(xenpf_read_memty
#define XENPF_microcode_update 35
struct xenpf_microcode_update {
/* IN variables. */
- XEN_GUEST_HANDLE(void) data; /* Pointer to microcode data */
+ XEN_GUEST_HANDLE(const_void) data;/* Pointer to microcode data */
uint32_t length; /* Length of microcode data. */
};
typedef struct xenpf_microcode_update xenpf_microcode_update_t;
diff -r 48db4eee7d58 -r d0a544d8a3f3 xen/include/xen/compat.h
--- a/xen/include/xen/compat.h Mon Aug 25 19:04:37 2008 +0900
+++ b/xen/include/xen/compat.h Mon Sep 01 16:59:43 2008 +0900
@@ -19,7 +19,9 @@
type *_[0] __attribute__((__packed__)); \
} __compat_handle_ ## name
-#define DEFINE_COMPAT_HANDLE(name) __DEFINE_COMPAT_HANDLE(name, name)
+#define DEFINE_COMPAT_HANDLE(name) \
+ __DEFINE_COMPAT_HANDLE(name, name); \
+ __DEFINE_COMPAT_HANDLE(const_ ## name, const name)
#define COMPAT_HANDLE(name) __compat_handle_ ## name
/* Is the compat handle a NULL reference? */
diff -r 48db4eee7d58 -r d0a544d8a3f3 xen/include/xen/iommu.h
--- a/xen/include/xen/iommu.h Mon Aug 25 19:04:37 2008 +0900
+++ b/xen/include/xen/iommu.h Mon Sep 01 16:59:43 2008 +0900
@@ -109,4 +109,8 @@ struct iommu_ops {
void iommu_update_ire_from_apic(unsigned int apic, unsigned int reg, unsigned
int value);
void iommu_update_ire_from_msi(struct msi_desc *msi_desc, struct msi_msg *msg);
+
+int iommu_suspend(void);
+int iommu_resume(void);
+
#endif /* _IOMMU_H_ */
diff -r 48db4eee7d58 -r d0a544d8a3f3 xen/include/xen/timer.h
--- a/xen/include/xen/timer.h Mon Aug 25 19:04:37 2008 +0900
+++ b/xen/include/xen/timer.h Mon Sep 01 16:59:43 2008 +0900
@@ -14,16 +14,29 @@
struct timer {
/* System time expiry value (nanoseconds since boot). */
- s_time_t expires;
+ s_time_t expires;
+
+ /* Position in active-timer data structure. */
+ union {
+ /* Timer-heap offset. */
+ unsigned int heap_offset;
+ /* Overflow linked list. */
+ struct timer *list_next;
+ };
+
+ /* On expiry, '(*function)(data)' will be executed in softirq context. */
+ void (*function)(void *);
+ void *data;
+
/* CPU on which this timer will be installed and executed. */
- unsigned int cpu;
- /* On expiry, '(*function)(data)' will be executed in softirq context. */
- void (*function)(void *);
- void *data;
- /* Timer-heap offset. */
- unsigned int heap_offset;
- /* Has this timer been killed (cannot be activated)? */
- int killed;
+ uint16_t cpu;
+
+ /* Timer status. */
+#define TIMER_STATUS_inactive 0 /* Not in use; can be activated. */
+#define TIMER_STATUS_killed 1 /* Not in use; canot be activated. */
+#define TIMER_STATUS_in_heap 2 /* In use; on timer heap. */
+#define TIMER_STATUS_in_list 3 /* In use; on overflow linked list. */
+ uint8_t status;
};
/*
@@ -37,7 +50,7 @@ struct timer {
*/
static inline int active_timer(struct timer *timer)
{
- return (timer->heap_offset != 0);
+ return (timer->status >= TIMER_STATUS_in_heap);
}
/*
diff -r 48db4eee7d58 -r d0a544d8a3f3 xen/include/xlat.lst
--- a/xen/include/xlat.lst Mon Aug 25 19:04:37 2008 +0900
+++ b/xen/include/xlat.lst Mon Sep 01 16:59:43 2008 +0900
@@ -33,6 +33,7 @@
! kexec_image kexec.h
! kexec_range kexec.h
! add_to_physmap memory.h
+! remove_from_physmap memory.h
! foreign_memory_map memory.h
! memory_exchange memory.h
! memory_map memory.h
diff -r 48db4eee7d58 -r d0a544d8a3f3 xen/include/xsm/xsm.h
--- a/xen/include/xsm/xsm.h Mon Aug 25 19:04:37 2008 +0900
+++ b/xen/include/xsm/xsm.h Mon Sep 01 16:59:43 2008 +0900
@@ -136,6 +136,7 @@ struct xsm_operations {
int (*mmu_machphys_update) (struct domain *d, unsigned long mfn);
int (*update_va_mapping) (struct domain *d, l1_pgentry_t pte);
int (*add_to_physmap) (struct domain *d1, struct domain *d2);
+ int (*remove_from_physmap) (struct domain *d1, struct domain *d2);
#endif
};
@@ -532,6 +533,11 @@ static inline int xsm_add_to_physmap(str
{
return xsm_call(add_to_physmap(d1, d2));
}
+
+static inline int xsm_remove_from_physmap(struct domain *d1, struct domain *d2)
+{
+ return xsm_call(remove_from_physmap(d1, d2));
+}
#endif /* CONFIG_X86 */
#endif /* __XSM_H */
diff -r 48db4eee7d58 -r d0a544d8a3f3 xen/xsm/dummy.c
--- a/xen/xsm/dummy.c Mon Aug 25 19:04:37 2008 +0900
+++ b/xen/xsm/dummy.c Mon Sep 01 16:59:43 2008 +0900
@@ -382,6 +382,11 @@ static int dummy_update_va_mapping (stru
}
static int dummy_add_to_physmap (struct domain *d1, struct domain *d2)
+{
+ return 0;
+}
+
+static int dummy_remove_from_physmap (struct domain *d1, struct domain *d2)
{
return 0;
}
@@ -484,5 +489,6 @@ void xsm_fixup_ops (struct xsm_operation
set_to_dummy_if_null(ops, mmu_machphys_update);
set_to_dummy_if_null(ops, update_va_mapping);
set_to_dummy_if_null(ops, add_to_physmap);
+ set_to_dummy_if_null(ops, remove_from_physmap);
#endif
}
diff -r 48db4eee7d58 -r d0a544d8a3f3 xen/xsm/flask/hooks.c
--- a/xen/xsm/flask/hooks.c Mon Aug 25 19:04:37 2008 +0900
+++ b/xen/xsm/flask/hooks.c Mon Sep 01 16:59:43 2008 +0900
@@ -1025,6 +1025,11 @@ static int flask_update_va_mapping(struc
}
static int flask_add_to_physmap(struct domain *d1, struct domain *d2)
+{
+ return domain_has_perm(d1, d2, SECCLASS_MMU, MMU__PHYSMAP);
+}
+
+static int flask_remove_from_physmap(struct domain *d1, struct domain *d2)
{
return domain_has_perm(d1, d2, SECCLASS_MMU, MMU__PHYSMAP);
}
@@ -1115,6 +1120,7 @@ static struct xsm_operations flask_ops =
.mmu_machphys_update = flask_mmu_machphys_update,
.update_va_mapping = flask_update_va_mapping,
.add_to_physmap = flask_add_to_physmap,
+ .remove_from_physmap = flask_remove_from_physmap,
#endif
};
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|