# HG changeset patch
# User Alex Williamson <alex.williamson@xxxxxx>
# Date 1181935991 21600
# Node ID 3b51eebdf9ab83e4473913358d4924370fa75763
# Parent fe42519fb10eba65cf7034e105738f71010933ca
# Parent f1ba2e652724cb505a85eef64eaafe9774421011
merge with xen-unstable.hg
---
buildconfigs/mk.linux-2.6-xen | 6
docs/src/user.tex | 2
tools/libxen/src/xen_vbd.c | 4
tools/libxen/src/xen_vm.c | 6
tools/python/xen/xend/XendAPI.py | 17 +
tools/python/xen/xend/osdep.py | 10
tools/python/xen/xend/server/DevController.py | 32 +-
tools/xenfb/xenfb.c | 1
tools/xenstat/xentop/xentop.c | 53 ++-
unmodified_drivers/linux-2.6/mkbuildtree | 3
xen/arch/x86/genapic/es7000plat.c | 4
xen/arch/x86/hvm/hpet.c | 3
xen/arch/x86/hvm/hvm.c | 4
xen/arch/x86/hvm/i8254.c | 379 ++++++++++++--------------
xen/arch/x86/hvm/pmtimer.c | 15 -
xen/arch/x86/hvm/rtc.c | 139 ++++-----
xen/arch/x86/hvm/svm/svm.c | 9
xen/arch/x86/hvm/vlapic.c | 4
xen/arch/x86/hvm/vmx/intr.c | 73 ++---
xen/arch/x86/hvm/vmx/vmcs.c | 5
xen/arch/x86/hvm/vmx/vmx.c | 18 +
xen/arch/x86/hvm/vpt.c | 105 +++----
xen/arch/x86/io_apic.c | 9
xen/include/asm-x86/hvm/vmx/vmcs.h | 10
xen/include/asm-x86/hvm/vmx/vmx.h | 14
xen/include/asm-x86/hvm/vpt.h | 8
xen/include/asm-x86/msr.h | 1
xen/include/public/io/ring.h | 2
xen/include/public/io/xs_wire.h | 6
29 files changed, 509 insertions(+), 433 deletions(-)
diff -r fe42519fb10e -r 3b51eebdf9ab buildconfigs/mk.linux-2.6-xen
--- a/buildconfigs/mk.linux-2.6-xen Fri Jun 15 12:38:35 2007 -0600
+++ b/buildconfigs/mk.linux-2.6-xen Fri Jun 15 13:33:11 2007 -0600
@@ -49,7 +49,7 @@ endif
mkdir -p $(INSTALL_BOOT_PATH)
$(MAKE) -C $(LINUX_DIR) ARCH=$(LINUX_ARCH)
INSTALL_PATH=$(INSTALL_BOOT_PATH) install
-$(LINUX_DIR)/include/linux/autoconf.h: CONFIG_FILE=$(PWD)/$(LINUX_DIR)/.config
+$(LINUX_DIR)/include/linux/autoconf.h:
CONFIG_FILE=$(CURDIR)/$(LINUX_DIR)/.config
$(LINUX_DIR)/include/linux/autoconf.h: $(LINUX_SRCDIR)/.valid-src
rm -rf $(LINUX_DIR)
mkdir -p $(LINUX_DIR)
@@ -90,8 +90,8 @@ endif
echo "VERSION = 2"; \
echo "PATCHLEVEL = 6"; \
echo ""; \
- echo "KERNELSRC := $(PWD)/$(LINUX_SRCDIR)"; \
- echo "KERNELOUTPUT := $(PWD)/$(LINUX_DIR)"; \
+ echo "KERNELSRC := $(CURDIR)/$(LINUX_SRCDIR)"; \
+ echo "KERNELOUTPUT := $(CURDIR)/$(LINUX_DIR)"; \
echo ""; \
echo "MAKEFLAGS += --no-print-directory"; \
echo ""; \
diff -r fe42519fb10e -r 3b51eebdf9ab docs/src/user.tex
--- a/docs/src/user.tex Fri Jun 15 12:38:35 2007 -0600
+++ b/docs/src/user.tex Fri Jun 15 13:33:11 2007 -0600
@@ -3195,6 +3195,8 @@ writing to the VGA console after domain
\item [ edid=no,force ] (x86 only) Either force retrieval of monitor
EDID information via VESA DDC, or disable it (edid=no). This option
should not normally be required except for debugging purposes.
+\item [ edd=off,on,skipmbr ] (x86 only) Control retrieval of Extended
+ Disc Data (EDD) from the BIOS during boot.
\item [ console\_to\_ring ] Place guest console output into the
hypervisor console ring buffer. This is disabled by default.
When enabled, both hypervisor output and guest console output
diff -r fe42519fb10e -r 3b51eebdf9ab tools/libxen/src/xen_vbd.c
--- a/tools/libxen/src/xen_vbd.c Fri Jun 15 12:38:35 2007 -0600
+++ b/tools/libxen/src/xen_vbd.c Fri Jun 15 13:33:11 2007 -0600
@@ -463,7 +463,7 @@ xen_vbd_set_mode(xen_session *session, x
{ .type = &abstract_type_string,
.u.string_val = vbd },
{ .type = &xen_vbd_mode_abstract_type_,
- .u.string_val = xen_vbd_mode_to_string(mode) }
+ .u.enum_val = mode }
};
xen_call_(session, "VBD.set_mode", param_values, 2, NULL, NULL);
@@ -479,7 +479,7 @@ xen_vbd_set_type(xen_session *session, x
{ .type = &abstract_type_string,
.u.string_val = vbd },
{ .type = &xen_vbd_type_abstract_type_,
- .u.string_val = xen_vbd_type_to_string(type) }
+ .u.enum_val = type }
};
xen_call_(session, "VBD.set_type", param_values, 2, NULL, NULL);
diff -r fe42519fb10e -r 3b51eebdf9ab tools/libxen/src/xen_vm.c
--- a/tools/libxen/src/xen_vm.c Fri Jun 15 12:38:35 2007 -0600
+++ b/tools/libxen/src/xen_vm.c Fri Jun 15 13:33:11 2007 -0600
@@ -1142,7 +1142,7 @@ xen_vm_set_actions_after_shutdown(xen_se
{ .type = &abstract_type_string,
.u.string_val = vm },
{ .type = &xen_on_normal_exit_abstract_type_,
- .u.string_val = xen_on_normal_exit_to_string(after_shutdown) }
+ .u.enum_val = after_shutdown }
};
xen_call_(session, "VM.set_actions_after_shutdown", param_values, 2, NULL,
NULL);
@@ -1158,7 +1158,7 @@ xen_vm_set_actions_after_reboot(xen_sess
{ .type = &abstract_type_string,
.u.string_val = vm },
{ .type = &xen_on_normal_exit_abstract_type_,
- .u.string_val = xen_on_normal_exit_to_string(after_reboot) }
+ .u.enum_val = after_reboot }
};
xen_call_(session, "VM.set_actions_after_reboot", param_values, 2, NULL,
NULL);
@@ -1174,7 +1174,7 @@ xen_vm_set_actions_after_crash(xen_sessi
{ .type = &abstract_type_string,
.u.string_val = vm },
{ .type = &xen_on_crash_behaviour_abstract_type_,
- .u.string_val = xen_on_crash_behaviour_to_string(after_crash) }
+ .u.enum_val = after_crash }
};
xen_call_(session, "VM.set_actions_after_crash", param_values, 2, NULL,
NULL);
diff -r fe42519fb10e -r 3b51eebdf9ab tools/python/xen/xend/XendAPI.py
--- a/tools/python/xen/xend/XendAPI.py Fri Jun 15 12:38:35 2007 -0600
+++ b/tools/python/xen/xend/XendAPI.py Fri Jun 15 13:33:11 2007 -0600
@@ -1483,6 +1483,12 @@ class XendAPI(object):
else:
return xen_api_success_void()
+ def VM_set_VCPUs_at_startup(self, session, vm_ref, num):
+ return self.VM_set('VCPUs_at_startup', session, vm_ref, num)
+
+ def VM_set_VCPUs_max(self, session, vm_ref, num):
+ return self.VM_set('VCPUs_max', session, vm_ref, num)
+
def VM_set_actions_after_shutdown(self, session, vm_ref, action):
if action not in XEN_API_ON_NORMAL_EXIT:
return xen_api_error(['VM_ON_NORMAL_EXIT_INVALID', vm_ref])
@@ -1887,6 +1893,17 @@ class XendAPI(object):
xd.managed_config_save(vm)
return xen_api_success_void()
+ def VBD_set_mode(self, session, vbd_ref, mode):
+ if mode == 'RW':
+ mode = 'w'
+ else:
+ mode = 'r'
+ xd = XendDomain.instance()
+ vm = xd.get_vm_with_dev_uuid('vbd', vbd_ref)
+ vm.set_dev_property('vbd', vbd_ref, 'mode', mode)
+ xd.managed_config_save(vm)
+ return xen_api_success_void()
+
def VBD_get_all(self, session):
xendom = XendDomain.instance()
vbds = [d.get_vbds() for d in XendDomain.instance().list('all')]
diff -r fe42519fb10e -r 3b51eebdf9ab tools/python/xen/xend/osdep.py
--- a/tools/python/xen/xend/osdep.py Fri Jun 15 12:38:35 2007 -0600
+++ b/tools/python/xen/xend/osdep.py Fri Jun 15 13:33:11 2007 -0600
@@ -65,11 +65,11 @@ def _solaris_balloon_stat(label):
import fcntl
import array
DEV_XEN_BALLOON = '/dev/xen/balloon'
- BLN_IOCTL_CURRENT = 0x4201
- BLN_IOCTL_TARGET = 0x4202
- BLN_IOCTL_LOW = 0x4203
- BLN_IOCTL_HIGH = 0x4204
- BLN_IOCTL_LIMIT = 0x4205
+ BLN_IOCTL_CURRENT = 0x42410001
+ BLN_IOCTL_TARGET = 0x42410002
+ BLN_IOCTL_LOW = 0x42410003
+ BLN_IOCTL_HIGH = 0x42410004
+ BLN_IOCTL_LIMIT = 0x42410005
label_to_ioctl = { 'Current allocation' : BLN_IOCTL_CURRENT,
'Requested target' : BLN_IOCTL_TARGET,
'Low-mem balloon' : BLN_IOCTL_LOW,
diff -r fe42519fb10e -r 3b51eebdf9ab
tools/python/xen/xend/server/DevController.py
--- a/tools/python/xen/xend/server/DevController.py Fri Jun 15 12:38:35
2007 -0600
+++ b/tools/python/xen/xend/server/DevController.py Fri Jun 15 13:33:11
2007 -0600
@@ -213,7 +213,7 @@ class DevController:
devid = int(devid)
frontpath = self.frontendPath(devid)
- if frontpath:
+ if frontpath:
backpath = xstransact.Read(frontpath, "backend")
# Modify online status /before/ updating state (latter is watched by
@@ -224,22 +224,22 @@ class DevController:
if force:
if backpath:
xstransact.Remove(backpath)
- if frontpath:
+ if frontpath:
xstransact.Remove(frontpath)
- return
-
- # Wait till both frontpath and backpath are removed from
- # xenstore, or timed out
- if frontpath:
- status = self.waitUntilDestroyed(frontpath)
- if status == Timeout:
- # Exception will be caught by destroyDevice in XendDomainInfo.py
- raise EnvironmentError
- if backpath:
- status = self.waitUntilDestroyed(backpath)
- if status == Timeout:
- # Exception will be caught by destroyDevice in XendDomainInfo.py
- raise EnvironmentError
+ return
+
+ # Wait till both frontpath and backpath are removed from
+ # xenstore, or timed out
+ if frontpath:
+ status = self.waitUntilDestroyed(frontpath)
+ if status == Timeout:
+ # Exception will be caught by destroyDevice in
XendDomainInfo.py
+ raise EnvironmentError
+ if backpath:
+ status = self.waitUntilDestroyed(backpath)
+ if status == Timeout:
+ # Exception will be caught by destroyDevice in
XendDomainInfo.py
+ raise EnvironmentError
self.vm._removeVm("device/%s/%d" % (self.deviceClass, devid))
diff -r fe42519fb10e -r 3b51eebdf9ab tools/xenfb/xenfb.c
--- a/tools/xenfb/xenfb.c Fri Jun 15 12:38:35 2007 -0600
+++ b/tools/xenfb/xenfb.c Fri Jun 15 13:33:11 2007 -0600
@@ -10,7 +10,6 @@
#include <xen/io/protocols.h>
#include <sys/select.h>
#include <stdbool.h>
-#include <xen/linux/evtchn.h>
#include <xen/event_channel.h>
#include <sys/mman.h>
#include <errno.h>
diff -r fe42519fb10e -r 3b51eebdf9ab tools/xenstat/xentop/xentop.c
--- a/tools/xenstat/xentop/xentop.c Fri Jun 15 12:38:35 2007 -0600
+++ b/tools/xenstat/xentop/xentop.c Fri Jun 15 13:33:11 2007 -0600
@@ -290,12 +290,24 @@ static void print(const char *fmt, ...)
}
}
+static void xentop_attron(int attr)
+{
+ if (!batch)
+ attron(attr);
+}
+
+static void xentop_attroff(int attr)
+{
+ if (!batch)
+ attroff(attr);
+}
+
/* Print a string with the given attributes set. */
static void attr_addstr(int attr, const char *str)
{
- attron(attr);
+ xentop_attron(attr);
addstr((curses_str_t)str);
- attroff(attr);
+ xentop_attroff(attr);
}
/* Handle setting the delay from the user-supplied value in prompt_val */
@@ -780,18 +792,18 @@ void do_header(void)
field_id i;
/* Turn on REVERSE highlight attribute for headings */
- attron(A_REVERSE);
+ xentop_attron(A_REVERSE);
for(i = 0; i < NUM_FIELDS; i++) {
- if(i != 0)
+ if (i != 0)
print(" ");
/* The BOLD attribute is turned on for the sort column */
- if(i == sort_field)
- attron(A_BOLD);
+ if (i == sort_field)
+ xentop_attron(A_BOLD);
print("%*s", fields[i].default_width, fields[i].header);
- if(i == sort_field)
- attroff(A_BOLD);
- }
- attroff(A_REVERSE);
+ if (i == sort_field)
+ xentop_attroff(A_BOLD);
+ }
+ xentop_attroff(A_REVERSE);
print("\n");
}
@@ -838,14 +850,14 @@ void do_domain(xenstat_domain *domain)
void do_domain(xenstat_domain *domain)
{
unsigned int i;
- for(i = 0; i < NUM_FIELDS; i++) {
- if(i != 0)
+ for (i = 0; i < NUM_FIELDS; i++) {
+ if (i != 0)
print(" ");
- if(i == sort_field)
- attron(A_BOLD);
+ if (i == sort_field)
+ xentop_attron(A_BOLD);
fields[i].print(domain);
- if(i == sort_field)
- attroff(A_BOLD);
+ if (i == sort_field)
+ xentop_attroff(A_BOLD);
}
print("\n");
}
@@ -956,7 +968,8 @@ static void top(void)
fail("Failed to retrieve statistics from libxenstat\n");
/* dump summary top information */
- do_summary();
+ if (!batch)
+ do_summary();
/* Count the number of domains for which to report data */
num_domains = xenstat_node_num_domains(cur_node);
@@ -976,7 +989,7 @@ static void top(void)
first_domain_index = num_domains-1;
for (i = first_domain_index; i < num_domains; i++) {
- if(current_row() == lines()-1)
+ if(!batch && current_row() == lines()-1)
break;
if (i == first_domain_index || repeat_header)
do_header();
@@ -989,8 +1002,8 @@ static void top(void)
do_vbd(domains[i]);
}
- if(!batch)
- do_bottom_line();
+ if (!batch)
+ do_bottom_line();
free(domains);
}
diff -r fe42519fb10e -r 3b51eebdf9ab unmodified_drivers/linux-2.6/mkbuildtree
--- a/unmodified_drivers/linux-2.6/mkbuildtree Fri Jun 15 12:38:35 2007 -0600
+++ b/unmodified_drivers/linux-2.6/mkbuildtree Fri Jun 15 13:33:11 2007 -0600
@@ -51,6 +51,7 @@ in
ln -sf ${XL}/include/asm-x86_64/mach-xen/asm/hypercall.h include/asm
ln -sf ${XL}/include/asm-x86_64/mach-xen/asm/synch_bitops.h include/asm
ln -sf ${XL}/include/asm-x86_64/mach-xen/asm/maddr.h include/asm
+ ln -sf ${XL}/include/asm-x86_64/mach-xen/asm/gnttab_dma.h include/asm
mkdir -p include/asm-i386
lndir -silent ${XL}/include/asm-i386 include/asm-i386
;;
@@ -59,12 +60,14 @@ i[34567]86)
ln -sf ${XL}/include/asm-i386/mach-xen/asm/hypercall.h include/asm
ln -sf ${XL}/include/asm-i386/mach-xen/asm/synch_bitops.h include/asm
ln -sf ${XL}/include/asm-i386/mach-xen/asm/maddr.h include/asm
+ ln -sf ${XL}/include/asm-i386/mach-xen/asm/gnttab_dma.h include/asm
;;
"ia64")
ln -sf ${XL}/include/asm-ia64/hypervisor.h include/asm
ln -sf ${XL}/include/asm-ia64/hypercall.h include/asm
ln -sf ${XL}/include/asm-ia64/synch_bitops.h include/asm
ln -sf ${XL}/include/asm-ia64/maddr.h include/asm
+ ln -sf ${XL}/include/asm-ia64/gnttab_dma.h include/asm
mkdir -p include/asm/xen
ln -sf ${XL}/include/asm-ia64/xen/xcom_hcall.h include/asm/xen
ln -sf ${XL}/include/asm-ia64/xen/xencomm.h include/asm/xen
diff -r fe42519fb10e -r 3b51eebdf9ab xen/arch/x86/genapic/es7000plat.c
--- a/xen/arch/x86/genapic/es7000plat.c Fri Jun 15 12:38:35 2007 -0600
+++ b/xen/arch/x86/genapic/es7000plat.c Fri Jun 15 13:33:11 2007 -0600
@@ -299,12 +299,12 @@ void __init
void __init
es7000_sw_apic()
{
- if (es7000_plat) {
+ if (es7000_plat && (es7000_plat != ES7000_ZORRO)) {
int mip_status;
struct mip_reg es7000_mip_reg;
printk("ES7000: Enabling APIC mode.\n");
- memset(&es7000_mip_reg, 0, sizeof(struct mip_reg));
+ memset(&es7000_mip_reg, 0, sizeof(struct mip_reg));
es7000_mip_reg.off_0 = MIP_SW_APIC;
es7000_mip_reg.off_38 = (MIP_VALID);
while ((mip_status = es7000_mip_write(&es7000_mip_reg)) != 0)
diff -r fe42519fb10e -r 3b51eebdf9ab xen/arch/x86/hvm/hpet.c
--- a/xen/arch/x86/hvm/hpet.c Fri Jun 15 12:38:35 2007 -0600
+++ b/xen/arch/x86/hvm/hpet.c Fri Jun 15 13:33:11 2007 -0600
@@ -381,6 +381,9 @@ void hpet_migrate_timers(struct vcpu *v)
struct HPETState *h = &v->domain->arch.hvm_domain.pl_time.vhpet;
int i;
+ if ( v != h->vcpu )
+ return;
+
for ( i = 0; i < HPET_TIMER_NUM; i++ )
migrate_timer(&h->timers[i], v->processor);
}
diff -r fe42519fb10e -r 3b51eebdf9ab xen/arch/x86/hvm/hvm.c
--- a/xen/arch/x86/hvm/hvm.c Fri Jun 15 12:38:35 2007 -0600
+++ b/xen/arch/x86/hvm/hvm.c Fri Jun 15 13:33:11 2007 -0600
@@ -109,11 +109,9 @@ u64 hvm_get_guest_time(struct vcpu *v)
void hvm_migrate_timers(struct vcpu *v)
{
- pit_migrate_timers(v);
rtc_migrate_timers(v);
hpet_migrate_timers(v);
- if ( vcpu_vlapic(v)->pt.enabled )
- migrate_timer(&vcpu_vlapic(v)->pt.timer, v->processor);
+ pt_migrate(v);
}
void hvm_do_resume(struct vcpu *v)
diff -r fe42519fb10e -r 3b51eebdf9ab xen/arch/x86/hvm/i8254.c
--- a/xen/arch/x86/hvm/i8254.c Fri Jun 15 12:38:35 2007 -0600
+++ b/xen/arch/x86/hvm/i8254.c Fri Jun 15 13:33:11 2007 -0600
@@ -3,12 +3,13 @@
*
* Copyright (c) 2003-2004 Fabrice Bellard
* Copyright (c) 2006 Intel Corperation
+ * Copyright (c) 2007 Keir Fraser, XenSource Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
@@ -18,14 +19,9 @@
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-/* Edwin Zhai <edwin.zhai@xxxxxxxxx>, Eddie Dong <eddie.dong@xxxxxxxxx>
- * Ported to xen:
- * Add a new layer of periodic time on top of PIT;
- * move speaker io access to hypervisor;
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
*/
#include <xen/config.h>
@@ -41,8 +37,11 @@
#include <asm/hvm/vpt.h>
#include <asm/current.h>
-/* Enable DEBUG_PIT may cause guest calibration inaccuracy */
-/* #define DEBUG_PIT */
+#define domain_vpit(d) (&(d)->arch.hvm_domain.pl_time.vpit)
+#define vcpu_vpit(vcpu) (domain_vpit((vcpu)->domain))
+#define vpit_domain(pit) (container_of((pit), struct domain, \
+ arch.hvm_domain.pl_time.vpit))
+#define vpit_vcpu(pit) (vpit_domain(pit)->vcpu[0])
#define RW_STATE_LSB 1
#define RW_STATE_MSB 2
@@ -52,8 +51,8 @@ static int handle_pit_io(ioreq_t *p);
static int handle_pit_io(ioreq_t *p);
static int handle_speaker_io(ioreq_t *p);
-/* compute with 96 bit intermediate result: (a*b)/c */
-uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c)
+/* Compute with 96 bit intermediate result: (a*b)/c */
+static uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c)
{
union {
uint64_t ll;
@@ -76,16 +75,18 @@ uint64_t muldiv64(uint64_t a, uint32_t b
return res.ll;
}
-static int pit_get_count(PITState *s, int channel)
+static int pit_get_count(PITState *pit, int channel)
{
uint64_t d;
int counter;
- struct hvm_hw_pit_channel *c = &s->hw.channels[channel];
- struct periodic_time *pt = &s->pt[channel];
-
- d = muldiv64(hvm_get_guest_time(pt->vcpu) - s->count_load_time[channel],
- PIT_FREQ, ticks_per_sec(pt->vcpu));
- switch(c->mode) {
+ struct hvm_hw_pit_channel *c = &pit->hw.channels[channel];
+ struct vcpu *v = vpit_vcpu(pit);
+
+ d = muldiv64(hvm_get_guest_time(v) - pit->count_load_time[channel],
+ PIT_FREQ, ticks_per_sec(v));
+
+ switch ( c->mode )
+ {
case 0:
case 1:
case 4:
@@ -103,16 +104,18 @@ static int pit_get_count(PITState *s, in
return counter;
}
-/* get pit output bit */
-int pit_get_out(PITState *pit, int channel, int64_t current_time)
+static int pit_get_out(PITState *pit, int channel)
{
struct hvm_hw_pit_channel *s = &pit->hw.channels[channel];
uint64_t d;
int out;
-
- d = muldiv64(current_time - pit->count_load_time[channel],
- PIT_FREQ, ticks_per_sec(pit->pt[channel].vcpu));
- switch(s->mode) {
+ struct vcpu *v = vpit_vcpu(pit);
+
+ d = muldiv64(hvm_get_guest_time(v) - pit->count_load_time[channel],
+ PIT_FREQ, ticks_per_sec(v));
+
+ switch ( s->mode )
+ {
default:
case 0:
out = (d >= s->count);
@@ -121,29 +124,27 @@ int pit_get_out(PITState *pit, int chann
out = (d < s->count);
break;
case 2:
- if ((d % s->count) == 0 && d != 0)
- out = 1;
- else
- out = 0;
+ out = (((d % s->count) == 0) && (d != 0));
break;
case 3:
- out = (d % s->count) < ((s->count + 1) >> 1);
+ out = ((d % s->count) < ((s->count + 1) >> 1));
break;
case 4:
case 5:
out = (d == s->count);
break;
}
+
return out;
}
-/* val must be 0 or 1 */
-void pit_set_gate(PITState *pit, int channel, int val)
+static void pit_set_gate(PITState *pit, int channel, int val)
{
struct hvm_hw_pit_channel *s = &pit->hw.channels[channel];
- struct periodic_time *pt = &pit->pt[channel];
-
- switch(s->mode) {
+ struct vcpu *v = vpit_vcpu(pit);
+
+ switch ( s->mode )
+ {
default:
case 0:
case 4:
@@ -151,22 +152,14 @@ void pit_set_gate(PITState *pit, int cha
break;
case 1:
case 5:
- if (s->gate < val) {
- /* restart counting on rising edge */
- pit->count_load_time[channel] = hvm_get_guest_time(pt->vcpu);
-// pit_irq_timer_update(s, s->count_load_time);
- }
- break;
case 2:
case 3:
- if (s->gate < val) {
- /* restart counting on rising edge */
- pit->count_load_time[channel] = hvm_get_guest_time(pt->vcpu);
-// pit_irq_timer_update(s, s->count_load_time);
- }
- /* XXX: disable/enable counting */
- break;
- }
+ /* Restart counting on rising edge. */
+ if ( s->gate < val )
+ pit->count_load_time[channel] = hvm_get_guest_time(v);
+ break;
+ }
+
s->gate = val;
}
@@ -175,57 +168,40 @@ int pit_get_gate(PITState *pit, int chan
return pit->hw.channels[channel].gate;
}
-void pit_time_fired(struct vcpu *v, void *priv)
+static void pit_time_fired(struct vcpu *v, void *priv)
{
uint64_t *count_load_time = priv;
*count_load_time = hvm_get_guest_time(v);
}
-static inline void pit_load_count(PITState *pit, int channel, int val)
+static void pit_load_count(PITState *pit, int channel, int val)
{
u32 period;
struct hvm_hw_pit_channel *s = &pit->hw.channels[channel];
struct periodic_time *pt = &pit->pt[channel];
- struct vcpu *v;
-
- if (val == 0)
+ struct vcpu *v = vpit_vcpu(pit);
+
+ if ( val == 0 )
val = 0x10000;
+
pit->count_load_time[channel] = hvm_get_guest_time(pt->vcpu);
s->count = val;
period = DIV_ROUND((val * 1000000000ULL), PIT_FREQ);
- if (channel != 0)
+ if ( (v == NULL) || !is_hvm_vcpu(v) || (channel != 0) )
return;
-#ifdef DEBUG_PIT
- printk("HVM_PIT: pit-load-counter(%p), count=0x%x, period=%uns mode=%d,
load_time=%lld\n",
- s,
- val,
- period,
- s->mode,
- (long long)pit->count_load_time[channel]);
-#endif
-
- /* Choose a vcpu to set the timer on: current if appropriate else vcpu 0 */
- if ( likely(pit == ¤t->domain->arch.hvm_domain.pl_time.vpit) )
- v = current;
- else
- v = container_of(pit, struct domain,
- arch.hvm_domain.pl_time.vpit)->vcpu[0];
-
- switch (s->mode) {
+ switch ( s->mode )
+ {
case 2:
- /* create periodic time */
+ /* Periodic timer. */
create_periodic_time(v, pt, period, 0, 0, pit_time_fired,
&pit->count_load_time[channel]);
break;
case 1:
- /* create one shot time */
+ /* One-shot timer. */
create_periodic_time(v, pt, period, 0, 1, pit_time_fired,
&pit->count_load_time[channel]);
-#ifdef DEBUG_PIT
- printk("HVM_PIT: create one shot time.\n");
-#endif
break;
default:
destroy_periodic_time(pt);
@@ -233,63 +209,84 @@ static inline void pit_load_count(PITSta
}
}
-/* if already latched, do not latch again */
static void pit_latch_count(PITState *s, int channel)
{
struct hvm_hw_pit_channel *c = &s->hw.channels[channel];
- if (!c->count_latched) {
+ if ( !c->count_latched )
+ {
c->latched_count = pit_get_count(s, channel);
c->count_latched = c->rw_mode;
}
}
-static void pit_ioport_write(void *opaque, uint32_t addr, uint32_t val)
-{
- PITState *pit = opaque;
+static void pit_latch_status(PITState *s, int channel)
+{
+ struct hvm_hw_pit_channel *c = &s->hw.channels[channel];
+ if ( !c->status_latched )
+ {
+ /* TODO: Return NULL COUNT (bit 6). */
+ c->status = ((pit_get_out(s, channel) << 7) |
+ (c->rw_mode << 4) |
+ (c->mode << 1) |
+ c->bcd);
+ c->status_latched = 1;
+ }
+}
+
+static void pit_ioport_write(struct PITState *pit, uint32_t addr, uint32_t val)
+{
int channel, access;
struct hvm_hw_pit_channel *s;
- val &= 0xff;
-
+
+ val &= 0xff;
addr &= 3;
- if (addr == 3) {
+
+ if ( addr == 3 )
+ {
channel = val >> 6;
- if (channel == 3) {
- /* read back command */
- for(channel = 0; channel < 3; channel++) {
+ if ( channel == 3 )
+ {
+ /* Read-Back Command. */
+ for ( channel = 0; channel < 3; channel++ )
+ {
s = &pit->hw.channels[channel];
- if (val & (2 << channel)) {
- if (!(val & 0x20)) {
+ if ( val & (2 << channel) )
+ {
+ if ( !(val & 0x20) )
pit_latch_count(pit, channel);
- }
- if (!(val & 0x10) && !s->status_latched) {
- /* status latch */
- /* XXX: add BCD and null count */
- s->status = (pit_get_out(pit, channel,
hvm_get_guest_time(pit->pt[channel].vcpu)) << 7) |
- (s->rw_mode << 4) |
- (s->mode << 1) |
- s->bcd;
- s->status_latched = 1;
- }
+ if ( !(val & 0x10) )
+ pit_latch_status(pit, channel);
}
}
- } else {
+ }
+ else
+ {
+ /* Select Counter <channel>. */
s = &pit->hw.channels[channel];
access = (val >> 4) & 3;
- if (access == 0) {
+ if ( access == 0 )
+ {
pit_latch_count(pit, channel);
- } else {
+ }
+ else
+ {
s->rw_mode = access;
s->read_state = access;
s->write_state = access;
-
s->mode = (val >> 1) & 7;
+ if ( s->mode > 5 )
+ s->mode -= 4;
s->bcd = val & 1;
/* XXX: update irq timer ? */
}
}
- } else {
+ }
+ else
+ {
+ /* Write Count. */
s = &pit->hw.channels[addr];
- switch(s->write_state) {
+ switch ( s->write_state )
+ {
default:
case RW_STATE_LSB:
pit_load_count(pit, addr, val);
@@ -309,19 +306,23 @@ static void pit_ioport_write(void *opaqu
}
}
-static uint32_t pit_ioport_read(void *opaque, uint32_t addr)
-{
- PITState *pit = opaque;
+static uint32_t pit_ioport_read(struct PITState *pit, uint32_t addr)
+{
int ret, count;
struct hvm_hw_pit_channel *s;
addr &= 3;
s = &pit->hw.channels[addr];
- if (s->status_latched) {
+
+ if ( s->status_latched )
+ {
s->status_latched = 0;
ret = s->status;
- } else if (s->count_latched) {
- switch(s->count_latched) {
+ }
+ else if ( s->count_latched )
+ {
+ switch ( s->count_latched )
+ {
default:
case RW_STATE_LSB:
ret = s->latched_count & 0xff;
@@ -336,8 +337,11 @@ static uint32_t pit_ioport_read(void *op
s->count_latched = RW_STATE_MSB;
break;
}
- } else {
- switch(s->read_state) {
+ }
+ else
+ {
+ switch ( s->read_state )
+ {
default:
case RW_STATE_LSB:
count = pit_get_count(pit, addr);
@@ -359,10 +363,11 @@ static uint32_t pit_ioport_read(void *op
break;
}
}
+
return ret;
}
-void pit_stop_channel0_irq(PITState * pit)
+void pit_stop_channel0_irq(PITState *pit)
{
destroy_periodic_time(&pit->pt[0]);
}
@@ -374,7 +379,8 @@ static void pit_info(PITState *pit)
struct periodic_time *pt;
int i;
- for(i = 0; i < 3; i++) {
+ for ( i = 0; i < 3; i++ )
+ {
printk("*****pit channel %d's state:*****\n", i);
s = &pit->hw.channels[i];
printk("pit 0x%x.\n", s->count);
@@ -392,7 +398,8 @@ static void pit_info(PITState *pit)
printk("pit %"PRId64"\n", pit->count_load_time[i]);
pt = &pit->pt[i];
- if (pt) {
+ if ( pt )
+ {
printk("pit channel %d has a periodic timer:\n", i);
printk("pt %d.\n", pt->enabled);
printk("pt %d.\n", pt->one_shot);
@@ -405,7 +412,6 @@ static void pit_info(PITState *pit)
printk("pt %"PRId64"\n", pt->last_plt_gtime);
}
}
-
}
#else
static void pit_info(PITState *pit)
@@ -415,7 +421,7 @@ static void pit_info(PITState *pit)
static int pit_save(struct domain *d, hvm_domain_context_t *h)
{
- PITState *pit = &d->arch.hvm_domain.pl_time.vpit;
+ PITState *pit = domain_vpit(d);
pit_info(pit);
@@ -425,7 +431,7 @@ static int pit_save(struct domain *d, hv
static int pit_load(struct domain *d, hvm_domain_context_t *h)
{
- PITState *pit = &d->arch.hvm_domain.pl_time.vpit;
+ PITState *pit = domain_vpit(d);
int i;
/* Restore the PIT hardware state */
@@ -435,8 +441,8 @@ static int pit_load(struct domain *d, hv
/* Recreate platform timers from hardware state. There will be some
* time jitter here, but the wall-clock will have jumped massively, so
* we hope the guest can handle it. */
-
- for(i = 0; i < 3; i++) {
+ for ( i = 0; i < 3; i++ )
+ {
pit_load_count(pit, i, pit->hw.channels[i].count);
pit->pt[i].last_plt_gtime = hvm_get_guest_time(d->vcpu[0]);
}
@@ -447,121 +453,94 @@ static int pit_load(struct domain *d, hv
HVM_REGISTER_SAVE_RESTORE(PIT, pit_save, pit_load, 1, HVMSR_PER_DOM);
-static void pit_reset(void *opaque)
-{
- PITState *pit = opaque;
+void pit_init(struct vcpu *v, unsigned long cpu_khz)
+{
+ PITState *pit = vcpu_vpit(v);
+ struct periodic_time *pt;
struct hvm_hw_pit_channel *s;
int i;
- for(i = 0;i < 3; i++) {
- s = &pit->hw.channels[i];
- destroy_periodic_time(&pit->pt[i]);
- s->mode = 0xff; /* the init mode */
- s->gate = (i != 2);
- pit_load_count(pit, i, 0);
- }
-}
-
-void pit_init(struct vcpu *v, unsigned long cpu_khz)
-{
- PITState *pit = &v->domain->arch.hvm_domain.pl_time.vpit;
- struct periodic_time *pt;
-
pt = &pit->pt[0];
- pt->vcpu = v;
- /* the timer 0 is connected to an IRQ */
- init_timer(&pt->timer, pt_timer_fn, pt, v->processor);
- pt++; pt->vcpu = v;
- pt++; pt->vcpu = v;
+ pt[0].vcpu = v;
+ pt[1].vcpu = v;
+ pt[2].vcpu = v;
register_portio_handler(v->domain, PIT_BASE, 4, handle_pit_io);
/* register the speaker port */
register_portio_handler(v->domain, 0x61, 1, handle_speaker_io);
ticks_per_sec(v) = cpu_khz * (int64_t)1000;
-#ifdef DEBUG_PIT
- printk("HVM_PIT: guest frequency =%lld\n", (long long)ticks_per_sec(v));
-#endif
- pit_reset(pit);
- return;
-}
-
-void pit_migrate_timers(struct vcpu *v)
-{
- PITState *pit = &v->domain->arch.hvm_domain.pl_time.vpit;
- struct periodic_time *pt;
-
- pt = &pit->pt[0];
- if ( pt->vcpu == v && pt->enabled )
- migrate_timer(&pt->timer, v->processor);
+
+ for ( i = 0; i < 3; i++ )
+ {
+ s = &pit->hw.channels[i];
+ s->mode = 0xff; /* the init mode */
+ s->gate = (i != 2);
+ pit_load_count(pit, i, 0);
+ }
}
void pit_deinit(struct domain *d)
{
- PITState *pit = &d->arch.hvm_domain.pl_time.vpit;
-
- kill_timer(&pit->pt[0].timer);
+ PITState *pit = domain_vpit(d);
+ destroy_periodic_time(&pit->pt[0]);
}
/* the intercept action for PIT DM retval:0--not handled; 1--handled */
static int handle_pit_io(ioreq_t *p)
{
- struct vcpu *v = current;
- struct PITState *vpit = &(v->domain->arch.hvm_domain.pl_time.vpit);
-
- if (p->size != 1 ||
- p->data_is_ptr ||
- p->type != IOREQ_TYPE_PIO){
- printk("HVM_PIT:wrong PIT IO!\n");
+ struct PITState *vpit = vcpu_vpit(current);
+
+ if ( (p->size != 1) || p->data_is_ptr || (p->type != IOREQ_TYPE_PIO) )
+ {
+ gdprintk(XENLOG_WARNING, "HVM_PIT bad access\n");
return 1;
}
- if (p->dir == 0) {/* write */
+ if ( p->dir == IOREQ_WRITE )
+ {
pit_ioport_write(vpit, p->addr, p->data);
- } else if (p->dir == 1) { /* read */
- if ( (p->addr & 3) != 3 ) {
+ }
+ else
+ {
+ if ( (p->addr & 3) != 3 )
p->data = pit_ioport_read(vpit, p->addr);
- } else {
- printk("HVM_PIT: read A1:A0=3!\n");
- }
- }
+ else
+ gdprintk(XENLOG_WARNING, "HVM_PIT: read A1:A0=3!\n");
+ }
+
return 1;
}
-static void speaker_ioport_write(void *opaque, uint32_t addr, uint32_t val)
-{
- PITState *pit = opaque;
+static void speaker_ioport_write(
+ struct PITState *pit, uint32_t addr, uint32_t val)
+{
pit->hw.speaker_data_on = (val >> 1) & 1;
pit_set_gate(pit, 2, val & 1);
}
-static uint32_t speaker_ioport_read(void *opaque, uint32_t addr)
-{
- PITState *pit = opaque;
- int out = pit_get_out(pit, 2,
- hvm_get_guest_time(pit->pt[2].vcpu));
+static uint32_t speaker_ioport_read(
+ struct PITState *pit, uint32_t addr)
+{
/* Refresh clock toggles at about 15us. We approximate as 2^14ns. */
unsigned int refresh_clock = ((unsigned int)NOW() >> 14) & 1;
return ((pit->hw.speaker_data_on << 1) | pit_get_gate(pit, 2) |
- (out << 5) | refresh_clock << 4);
+ (pit_get_out(pit, 2) << 5) | (refresh_clock << 4));
}
static int handle_speaker_io(ioreq_t *p)
{
- struct vcpu *v = current;
- struct PITState *vpit = &(v->domain->arch.hvm_domain.pl_time.vpit);
-
- if (p->size != 1 ||
- p->data_is_ptr ||
- p->type != IOREQ_TYPE_PIO){
- printk("HVM_SPEAKER:wrong SPEAKER IO!\n");
+ struct PITState *vpit = vcpu_vpit(current);
+
+ if ( (p->size != 1) || p->data_is_ptr || (p->type != IOREQ_TYPE_PIO) )
+ {
+ gdprintk(XENLOG_WARNING, "HVM_SPEAKER bad access\n");
return 1;
}
- if (p->dir == 0) {/* write */
+ if ( p->dir == IOREQ_WRITE )
speaker_ioport_write(vpit, p->addr, p->data);
- } else if (p->dir == 1) {/* read */
+ else
p->data = speaker_ioport_read(vpit, p->addr);
- }
return 1;
}
@@ -576,7 +555,7 @@ int pv_pit_handler(int port, int data, i
.data = write ? data : 0,
};
- if (port == 0x61)
+ if ( port == 0x61 )
handle_speaker_io(&ioreq);
else
handle_pit_io(&ioreq);
diff -r fe42519fb10e -r 3b51eebdf9ab xen/arch/x86/hvm/pmtimer.c
--- a/xen/arch/x86/hvm/pmtimer.c Fri Jun 15 12:38:35 2007 -0600
+++ b/xen/arch/x86/hvm/pmtimer.c Fri Jun 15 13:33:11 2007 -0600
@@ -50,7 +50,6 @@
#define TMR_VAL_MASK (0xffffffff)
#define TMR_VAL_MSB (0x80000000)
-
/* Dispatch SCIs based on the PM1a_STS and PM1a_EN registers */
static void pmt_update_sci(PMTState *s)
{
@@ -89,19 +88,19 @@ static void pmt_timer_callback(void *opa
PMTState *s = opaque;
uint32_t pmt_cycles_until_flip;
uint64_t time_until_flip;
-
+
/* Recalculate the timer and make sure we get an SCI if we need one */
pmt_update_time(s);
-
+
/* How close are we to the next MSB flip? */
pmt_cycles_until_flip = TMR_VAL_MSB - (s->pm.tmr_val & (TMR_VAL_MSB - 1));
-
+
/* Overall time between MSB flips */
- time_until_flip = (1000000000ULL << 31) / FREQUENCE_PMTIMER;
-
+ time_until_flip = (1000000000ULL << 23) / FREQUENCE_PMTIMER;
+
/* Reduced appropriately */
- time_until_flip = (time_until_flip * pmt_cycles_until_flip) / (1ULL<<31);
-
+ time_until_flip = (time_until_flip * pmt_cycles_until_flip) >> 23;
+
/* Wake up again near the next bit-flip */
set_timer(&s->timer, NOW() + time_until_flip + MILLISECS(1));
}
diff -r fe42519fb10e -r 3b51eebdf9ab xen/arch/x86/hvm/rtc.c
--- a/xen/arch/x86/hvm/rtc.c Fri Jun 15 12:38:35 2007 -0600
+++ b/xen/arch/x86/hvm/rtc.c Fri Jun 15 13:33:11 2007 -0600
@@ -28,7 +28,11 @@
#include <asm/hvm/support.h>
#include <asm/current.h>
-/* #define DEBUG_RTC */
+#define domain_vrtc(d) (&(d)->arch.hvm_domain.pl_time.vrtc)
+#define vcpu_vrtc(vcpu) (domain_vrtc((vcpu)->domain))
+#define vrtc_domain(rtc) (container_of((rtc), struct domain, \
+ arch.hvm_domain.pl_time.vrtc))
+#define vrtc_vcpu(rtc) (vrtc_domain(rtc)->vcpu[0])
void rtc_periodic_cb(struct vcpu *v, void *opaque)
{
@@ -41,31 +45,31 @@ int is_rtc_periodic_irq(void *opaque)
RTCState *s = opaque;
return !(s->hw.cmos_data[RTC_REG_C] & RTC_AF ||
- s->hw.cmos_data[RTC_REG_C] & RTC_UF);
+ s->hw.cmos_data[RTC_REG_C] & RTC_UF);
}
/* Enable/configure/disable the periodic timer based on the RTC_PIE and
* RTC_RATE_SELECT settings */
-static void rtc_timer_update(RTCState *s, struct vcpu *v)
-{
- int period_code;
- int period;
+static void rtc_timer_update(RTCState *s)
+{
+ int period_code, period;
+ struct vcpu *v = vrtc_vcpu(s);
period_code = s->hw.cmos_data[RTC_REG_A] & RTC_RATE_SELECT;
if ( (period_code != 0) && (s->hw.cmos_data[RTC_REG_B] & RTC_PIE) )
{
if ( period_code <= 2 )
period_code += 7;
-
+
period = 1 << (period_code - 1); /* period in 32 Khz cycles */
period = DIV_ROUND((period * 1000000000ULL), 32768); /* period in ns */
-#ifdef DEBUG_RTC
- printk("HVM_RTC: period = %uns\n", period);
-#endif
- create_periodic_time(v, &s->pt, period, RTC_IRQ, 0, rtc_periodic_cb,
s);
- }
- else
+ create_periodic_time(v, &s->pt, period, RTC_IRQ,
+ 0, rtc_periodic_cb, s);
+ }
+ else
+ {
destroy_periodic_time(&s->pt);
+ }
}
static void rtc_set_time(RTCState *s);
@@ -80,13 +84,8 @@ static int rtc_ioport_write(void *opaque
return (s->hw.cmos_index < RTC_CMOS_SIZE);
}
- if (s->hw.cmos_index >= RTC_CMOS_SIZE)
+ if ( s->hw.cmos_index >= RTC_CMOS_SIZE )
return 0;
-
-#ifdef DEBUG_RTC
- printk("HVM_RTC: write index=0x%02x val=0x%02x\n",
- s->hw.cmos_index, data);
-#endif
switch ( s->hw.cmos_index )
{
@@ -111,7 +110,7 @@ static int rtc_ioport_write(void *opaque
/* UIP bit is read only */
s->hw.cmos_data[RTC_REG_A] = (data & ~RTC_UIP) |
(s->hw.cmos_data[RTC_REG_A] & RTC_UIP);
- rtc_timer_update(s, current);
+ rtc_timer_update(s);
break;
case RTC_REG_B:
if ( data & RTC_SET )
@@ -127,7 +126,7 @@ static int rtc_ioport_write(void *opaque
rtc_set_time(s);
}
s->hw.cmos_data[RTC_REG_B] = data;
- rtc_timer_update(s, current);
+ rtc_timer_update(s);
break;
case RTC_REG_C:
case RTC_REG_D:
@@ -181,10 +180,12 @@ static void rtc_copy_date(RTCState *s)
static void rtc_copy_date(RTCState *s)
{
const struct tm *tm = &s->current_tm;
-
- if (s->time_offset_seconds != s->pt.vcpu->domain->time_offset_seconds) {
- s->current_tm = gmtime(get_localtime(s->pt.vcpu->domain));
- s->time_offset_seconds = s->pt.vcpu->domain->time_offset_seconds;
+ struct domain *d = vrtc_domain(s);
+
+ if ( s->time_offset_seconds != d->time_offset_seconds )
+ {
+ s->current_tm = gmtime(get_localtime(d));
+ s->time_offset_seconds = d->time_offset_seconds;
}
s->hw.cmos_data[RTC_SECONDS] = to_bcd(s, tm->tm_sec);
@@ -228,34 +229,43 @@ static void rtc_next_second(RTCState *s)
{
struct tm *tm = &s->current_tm;
int days_in_month;
-
- if (s->time_offset_seconds != s->pt.vcpu->domain->time_offset_seconds) {
- s->current_tm = gmtime(get_localtime(s->pt.vcpu->domain));
- s->time_offset_seconds = s->pt.vcpu->domain->time_offset_seconds;
+ struct domain *d = vrtc_domain(s);
+
+ if ( s->time_offset_seconds != d->time_offset_seconds )
+ {
+ s->current_tm = gmtime(get_localtime(d));
+ s->time_offset_seconds = d->time_offset_seconds;
}
tm->tm_sec++;
- if ((unsigned)tm->tm_sec >= 60) {
+ if ( (unsigned)tm->tm_sec >= 60 )
+ {
tm->tm_sec = 0;
tm->tm_min++;
- if ((unsigned)tm->tm_min >= 60) {
+ if ( (unsigned)tm->tm_min >= 60 )
+ {
tm->tm_min = 0;
tm->tm_hour++;
- if ((unsigned)tm->tm_hour >= 24) {
+ if ( (unsigned)tm->tm_hour >= 24 )
+ {
tm->tm_hour = 0;
/* next day */
tm->tm_wday++;
- if ((unsigned)tm->tm_wday >= 7)
+ if ( (unsigned)tm->tm_wday >= 7 )
tm->tm_wday = 0;
days_in_month = get_days_in_month(tm->tm_mon,
tm->tm_year + 1900);
tm->tm_mday++;
- if (tm->tm_mday < 1) {
+ if ( tm->tm_mday < 1 )
+ {
tm->tm_mday = 1;
- } else if (tm->tm_mday > days_in_month) {
+ }
+ else if ( tm->tm_mday > days_in_month )
+ {
tm->tm_mday = 1;
tm->tm_mon++;
- if (tm->tm_mon >= 12) {
+ if ( tm->tm_mon >= 12 )
+ {
tm->tm_mon = 0;
tm->tm_year++;
}
@@ -290,6 +300,7 @@ static void rtc_update_second2(void *opa
static void rtc_update_second2(void *opaque)
{
RTCState *s = opaque;
+ struct domain *d = vrtc_domain(s);
if ( !(s->hw.cmos_data[RTC_REG_B] & RTC_SET) )
rtc_copy_date(s);
@@ -308,8 +319,8 @@ static void rtc_update_second2(void *opa
s->current_tm.tm_hour) )
{
s->hw.cmos_data[RTC_REG_C] |= 0xa0;
- hvm_isa_irq_deassert(s->pt.vcpu->domain, RTC_IRQ);
- hvm_isa_irq_assert(s->pt.vcpu->domain, RTC_IRQ);
+ hvm_isa_irq_deassert(d, RTC_IRQ);
+ hvm_isa_irq_assert(d, RTC_IRQ);
}
}
@@ -317,8 +328,8 @@ static void rtc_update_second2(void *opa
if ( s->hw.cmos_data[RTC_REG_B] & RTC_UIE )
{
s->hw.cmos_data[RTC_REG_C] |= 0x90;
- hvm_isa_irq_deassert(s->pt.vcpu->domain, RTC_IRQ);
- hvm_isa_irq_assert(s->pt.vcpu->domain, RTC_IRQ);
+ hvm_isa_irq_deassert(d, RTC_IRQ);
+ hvm_isa_irq_assert(d, RTC_IRQ);
}
/* clear update in progress bit */
@@ -352,39 +363,33 @@ static uint32_t rtc_ioport_read(void *op
break;
case RTC_REG_C:
ret = s->hw.cmos_data[s->hw.cmos_index];
- hvm_isa_irq_deassert(s->pt.vcpu->domain, RTC_IRQ);
- s->hw.cmos_data[RTC_REG_C] = 0x00;
+ hvm_isa_irq_deassert(vrtc_domain(s), RTC_IRQ);
+ s->hw.cmos_data[RTC_REG_C] = 0x00;
break;
default:
ret = s->hw.cmos_data[s->hw.cmos_index];
break;
}
-#ifdef DEBUG_RTC
- printk("HVM_RTC: read index=0x%02x val=0x%02x\n",
- s->hw.cmos_index, ret);
-#endif
-
return ret;
}
static int handle_rtc_io(ioreq_t *p)
{
- struct vcpu *v = current;
- struct RTCState *vrtc = &v->domain->arch.hvm_domain.pl_time.vrtc;
+ struct RTCState *vrtc = vcpu_vrtc(current);
if ( (p->size != 1) || p->data_is_ptr || (p->type != IOREQ_TYPE_PIO) )
{
- printk("HVM_RTC: wrong RTC IO!\n");
+ gdprintk(XENLOG_WARNING, "HVM_RTC bas access\n");
return 1;
}
- if ( p->dir == 0 ) /* write */
+ if ( p->dir == IOREQ_WRITE )
{
if ( rtc_ioport_write(vrtc, p->addr, p->data & 0xFF) )
return 1;
}
- else if ( (p->dir == 1) && (vrtc->hw.cmos_index < RTC_CMOS_SIZE) ) /* read
*/
+ else if ( vrtc->hw.cmos_index < RTC_CMOS_SIZE )
{
p->data = rtc_ioport_read(vrtc, p->addr);
return 1;
@@ -393,15 +398,12 @@ static int handle_rtc_io(ioreq_t *p)
return 0;
}
-/* Move the RTC timers on to this vcpu's current cpu */
void rtc_migrate_timers(struct vcpu *v)
{
- RTCState *s = &v->domain->arch.hvm_domain.pl_time.vrtc;
-
- if ( s->pt.vcpu == v )
- {
- if ( s->pt.enabled )
- migrate_timer(&s->pt.timer, v->processor);
+ RTCState *s = vcpu_vrtc(v);
+
+ if ( v->vcpu_id == 0 )
+ {
migrate_timer(&s->second_timer, v->processor);
migrate_timer(&s->second_timer2, v->processor);
}
@@ -410,13 +412,14 @@ void rtc_migrate_timers(struct vcpu *v)
/* Save RTC hardware state */
static int rtc_save(struct domain *d, hvm_domain_context_t *h)
{
- return hvm_save_entry(RTC, 0, h, &d->arch.hvm_domain.pl_time.vrtc.hw);
+ RTCState *s = domain_vrtc(d);
+ return hvm_save_entry(RTC, 0, h, &s->hw);
}
/* Reload the hardware state from a saved domain */
static int rtc_load(struct domain *d, hvm_domain_context_t *h)
{
- RTCState *s = &d->arch.hvm_domain.pl_time.vrtc;
+ RTCState *s = domain_vrtc(d);
/* Restore the registers */
if ( hvm_load_entry(RTC, h, &s->hw) != 0 )
@@ -431,7 +434,7 @@ static int rtc_load(struct domain *d, hv
set_timer(&s->second_timer2, s->next_second_time);
/* Reset the periodic interrupt timer based on the registers */
- rtc_timer_update(s, d->vcpu[0]);
+ rtc_timer_update(s);
return 0;
}
@@ -441,9 +444,8 @@ HVM_REGISTER_SAVE_RESTORE(RTC, rtc_save,
void rtc_init(struct vcpu *v, int base)
{
- RTCState *s = &v->domain->arch.hvm_domain.pl_time.vrtc;
-
- s->pt.vcpu = v;
+ RTCState *s = vcpu_vrtc(v);
+
s->hw.cmos_data[RTC_REG_A] = RTC_REF_CLCK_32KHZ | 6; /* ~1kHz */
s->hw.cmos_data[RTC_REG_B] = RTC_24H;
s->hw.cmos_data[RTC_REG_C] = 0;
@@ -452,7 +454,6 @@ void rtc_init(struct vcpu *v, int base)
s->current_tm = gmtime(get_localtime(v->domain));
rtc_copy_date(s);
- init_timer(&s->pt.timer, pt_timer_fn, &s->pt, v->processor);
init_timer(&s->second_timer, rtc_update_second, s, v->processor);
init_timer(&s->second_timer2, rtc_update_second2, s, v->processor);
@@ -464,9 +465,9 @@ void rtc_init(struct vcpu *v, int base)
void rtc_deinit(struct domain *d)
{
- RTCState *s = &d->arch.hvm_domain.pl_time.vrtc;
-
- kill_timer(&s->pt.timer);
+ RTCState *s = domain_vrtc(d);
+
+ destroy_periodic_time(&s->pt);
kill_timer(&s->second_timer);
kill_timer(&s->second_timer2);
}
diff -r fe42519fb10e -r 3b51eebdf9ab xen/arch/x86/hvm/svm/svm.c
--- a/xen/arch/x86/hvm/svm/svm.c Fri Jun 15 12:38:35 2007 -0600
+++ b/xen/arch/x86/hvm/svm/svm.c Fri Jun 15 13:33:11 2007 -0600
@@ -2089,6 +2089,15 @@ static inline void svm_do_msr_access(
msr_content = 1ULL << 61; /* MC4_MISC.Locked */
break;
+ case MSR_IA32_EBC_FREQUENCY_ID:
+ /*
+ * This Intel-only register may be accessed if this HVM guest
+ * has been migrated from an Intel host. The value zero is not
+ * particularly meaningful, but at least avoids the guest crashing!
+ */
+ msr_content = 0;
+ break;
+
default:
if ( rdmsr_hypervisor_regs(ecx, &eax, &edx) ||
rdmsr_safe(ecx, eax, edx) == 0 )
diff -r fe42519fb10e -r 3b51eebdf9ab xen/arch/x86/hvm/vlapic.c
--- a/xen/arch/x86/hvm/vlapic.c Fri Jun 15 12:38:35 2007 -0600
+++ b/xen/arch/x86/hvm/vlapic.c Fri Jun 15 13:33:11 2007 -0600
@@ -944,8 +944,6 @@ int vlapic_init(struct vcpu *v)
if ( v->vcpu_id == 0 )
vlapic->hw.apic_base_msr |= MSR_IA32_APICBASE_BSP;
- init_timer(&vlapic->pt.timer, pt_timer_fn, &vlapic->pt, v->processor);
-
return 0;
}
@@ -953,7 +951,7 @@ void vlapic_destroy(struct vcpu *v)
{
struct vlapic *vlapic = vcpu_vlapic(v);
- kill_timer(&vlapic->pt.timer);
+ destroy_periodic_time(&vlapic->pt);
unmap_domain_page_global(vlapic->regs);
free_domheap_page(vlapic->regs_page);
}
diff -r fe42519fb10e -r 3b51eebdf9ab xen/arch/x86/hvm/vmx/intr.c
--- a/xen/arch/x86/hvm/vmx/intr.c Fri Jun 15 12:38:35 2007 -0600
+++ b/xen/arch/x86/hvm/vmx/intr.c Fri Jun 15 13:33:11 2007 -0600
@@ -1,6 +1,7 @@
/*
- * io.c: handling I/O, interrupts related VMX entry/exit
+ * intr.c: handling I/O, interrupts related VMX entry/exit
* Copyright (c) 2004, Intel Corporation.
+ * Copyright (c) 2004-2007, XenSource Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -14,7 +15,6 @@
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place - Suite 330, Boston, MA 02111-1307 USA.
- *
*/
#include <xen/config.h>
@@ -24,7 +24,6 @@
#include <xen/errno.h>
#include <xen/trace.h>
#include <xen/event.h>
-
#include <asm/current.h>
#include <asm/cpufeature.h>
#include <asm/processor.h>
@@ -39,32 +38,48 @@
#include <public/hvm/ioreq.h>
#include <asm/hvm/trace.h>
+/*
+ * A few notes on virtual NMI and INTR delivery, and interactions with
+ * interruptibility states:
+ *
+ * We can only inject an ExtInt if EFLAGS.IF = 1 and no blocking by
+ * STI nor MOV SS. Otherwise the VM entry fails. The 'virtual interrupt
+ * pending' control causes a VM exit when all these checks succeed. It will
+ * exit immediately after VM entry if the checks succeed at that point.
+ *
+ * We can only inject an NMI if no blocking by MOV SS (also, depending on
+ * implementation, if no blocking by STI). If pin-based 'virtual NMIs'
+ * control is specified then the NMI-blocking interruptibility flag is
+ * also checked. The 'virtual NMI pending' control (available only in
+ * conjunction with 'virtual NMIs') causes a VM exit when all these checks
+ * succeed. It will exit immediately after VM entry if the checks succeed
+ * at that point.
+ *
+ * Because a processor may or may not check blocking-by-STI when injecting
+ * a virtual NMI, it will be necessary to convert that to block-by-MOV-SS
+ * before specifying the 'virtual NMI pending' control. Otherwise we could
+ * enter an infinite loop where we check blocking-by-STI in software and
+ * thus delay delivery of a virtual NMI, but the processor causes immediate
+ * VM exit because it does not check blocking-by-STI.
+ *
+ * Injecting a virtual NMI sets the NMI-blocking interruptibility flag only
+ * if the 'virtual NMIs' control is set. Injecting *any* kind of event clears
+ * the STI- and MOV-SS-blocking interruptibility-state flags.
+ *
+ * If MOV/POP SS is executed while MOV-SS-blocking is in effect, the effect
+ * is cleared. If STI is executed while MOV-SS- or STI-blocking is in effect,
+ * the effect is cleared. (i.e., MOV-SS-blocking 'dominates' STI-blocking).
+ */
-static inline void
-enable_irq_window(struct vcpu *v)
+static void enable_irq_window(struct vcpu *v)
{
u32 *cpu_exec_control = &v->arch.hvm_vcpu.u.vmx.exec_control;
- if (!(*cpu_exec_control & CPU_BASED_VIRTUAL_INTR_PENDING)) {
+ if ( !(*cpu_exec_control & CPU_BASED_VIRTUAL_INTR_PENDING) )
+ {
*cpu_exec_control |= CPU_BASED_VIRTUAL_INTR_PENDING;
__vmwrite(CPU_BASED_VM_EXEC_CONTROL, *cpu_exec_control);
}
-}
-
-static inline void
-disable_irq_window(struct vcpu *v)
-{
- u32 *cpu_exec_control = &v->arch.hvm_vcpu.u.vmx.exec_control;
-
- if ( *cpu_exec_control & CPU_BASED_VIRTUAL_INTR_PENDING ) {
- *cpu_exec_control &= ~CPU_BASED_VIRTUAL_INTR_PENDING;
- __vmwrite(CPU_BASED_VM_EXEC_CONTROL, *cpu_exec_control);
- }
-}
-
-static inline int is_interruptibility_state(void)
-{
- return __vmread(GUEST_INTERRUPTIBILITY_INFO);
}
static void update_tpr_threshold(struct vlapic *vlapic)
@@ -87,13 +102,11 @@ static void update_tpr_threshold(struct
asmlinkage void vmx_intr_assist(void)
{
- int intr_type = 0;
- int intr_vector;
- unsigned long eflags;
+ int has_ext_irq, intr_vector, intr_type = 0;
+ unsigned long eflags, intr_shadow;
struct vcpu *v = current;
unsigned int idtv_info_field;
unsigned long inst_len;
- int has_ext_irq;
pt_update_irq(v);
@@ -125,10 +138,10 @@ asmlinkage void vmx_intr_assist(void)
inst_len = __vmread(VM_EXIT_INSTRUCTION_LEN); /* Safe */
__vmwrite(VM_ENTRY_INSTRUCTION_LEN, inst_len);
- if (unlikely(idtv_info_field & 0x800)) /* valid error code */
+ if ( unlikely(idtv_info_field & 0x800) ) /* valid error code */
__vmwrite(VM_ENTRY_EXCEPTION_ERROR_CODE,
__vmread(IDT_VECTORING_ERROR_CODE));
- if (unlikely(has_ext_irq))
+ if ( unlikely(has_ext_irq) )
enable_irq_window(v);
HVM_DBG_LOG(DBG_LEVEL_1, "idtv_info_field=%x", idtv_info_field);
@@ -138,9 +151,9 @@ asmlinkage void vmx_intr_assist(void)
if ( likely(!has_ext_irq) )
return;
- if ( unlikely(is_interruptibility_state()) )
+ intr_shadow = __vmread(GUEST_INTERRUPTIBILITY_INFO);
+ if ( unlikely(intr_shadow & (VMX_INTR_SHADOW_STI|VMX_INTR_SHADOW_MOV_SS)) )
{
- /* pre-cleared for emulated instruction */
enable_irq_window(v);
HVM_DBG_LOG(DBG_LEVEL_1, "interruptibility");
return;
diff -r fe42519fb10e -r 3b51eebdf9ab xen/arch/x86/hvm/vmx/vmcs.c
--- a/xen/arch/x86/hvm/vmx/vmcs.c Fri Jun 15 12:38:35 2007 -0600
+++ b/xen/arch/x86/hvm/vmx/vmcs.c Fri Jun 15 13:33:11 2007 -0600
@@ -70,8 +70,9 @@ void vmx_init_vmcs_config(void)
u32 _vmx_vmexit_control;
u32 _vmx_vmentry_control;
- min = PIN_BASED_EXT_INTR_MASK | PIN_BASED_NMI_EXITING;
- opt = 0;
+ min = (PIN_BASED_EXT_INTR_MASK |
+ PIN_BASED_NMI_EXITING);
+ opt = 0; /*PIN_BASED_VIRTUAL_NMIS*/
_vmx_pin_based_exec_control = adjust_vmx_controls(
min, opt, MSR_IA32_VMX_PINBASED_CTLS);
diff -r fe42519fb10e -r 3b51eebdf9ab xen/arch/x86/hvm/vmx/vmx.c
--- a/xen/arch/x86/hvm/vmx/vmx.c Fri Jun 15 12:38:35 2007 -0600
+++ b/xen/arch/x86/hvm/vmx/vmx.c Fri Jun 15 13:33:11 2007 -0600
@@ -1300,11 +1300,17 @@ static int __get_instruction_length(void
static void inline __update_guest_eip(unsigned long inst_len)
{
- unsigned long current_eip;
+ unsigned long current_eip, intr_shadow;
current_eip = __vmread(GUEST_RIP);
__vmwrite(GUEST_RIP, current_eip + inst_len);
- __vmwrite(GUEST_INTERRUPTIBILITY_INFO, 0);
+
+ intr_shadow = __vmread(GUEST_INTERRUPTIBILITY_INFO);
+ if ( intr_shadow & (VMX_INTR_SHADOW_STI | VMX_INTR_SHADOW_MOV_SS) )
+ {
+ intr_shadow &= ~(VMX_INTR_SHADOW_STI | VMX_INTR_SHADOW_MOV_SS);
+ __vmwrite(GUEST_INTERRUPTIBILITY_INFO, intr_shadow);
+ }
}
static void vmx_do_no_device_fault(void)
@@ -2902,9 +2908,15 @@ asmlinkage void vmx_vmexit_handler(struc
case EXIT_REASON_TRIPLE_FAULT:
hvm_triple_fault();
break;
- case EXIT_REASON_PENDING_INTERRUPT:
+ case EXIT_REASON_PENDING_VIRT_INTR:
/* Disable the interrupt window. */
v->arch.hvm_vcpu.u.vmx.exec_control &= ~CPU_BASED_VIRTUAL_INTR_PENDING;
+ __vmwrite(CPU_BASED_VM_EXEC_CONTROL,
+ v->arch.hvm_vcpu.u.vmx.exec_control);
+ break;
+ case EXIT_REASON_PENDING_VIRT_NMI:
+ /* Disable the NMI window. */
+ v->arch.hvm_vcpu.u.vmx.exec_control &= ~CPU_BASED_VIRTUAL_NMI_PENDING;
__vmwrite(CPU_BASED_VM_EXEC_CONTROL,
v->arch.hvm_vcpu.u.vmx.exec_control);
break;
diff -r fe42519fb10e -r 3b51eebdf9ab xen/arch/x86/hvm/vpt.c
--- a/xen/arch/x86/hvm/vpt.c Fri Jun 15 12:38:35 2007 -0600
+++ b/xen/arch/x86/hvm/vpt.c Fri Jun 15 13:33:11 2007 -0600
@@ -22,31 +22,31 @@
#include <asm/hvm/vpt.h>
#include <asm/event.h>
-static __inline__ void missed_ticks(struct periodic_time *pt)
+static void missed_ticks(struct periodic_time *pt)
{
s_time_t missed_ticks;
missed_ticks = NOW() - pt->scheduled;
- if ( missed_ticks > 0 )
- {
- missed_ticks = missed_ticks / (s_time_t) pt->period + 1;
- if ( missed_ticks > 1000 )
- {
- /* TODO: Adjust guest time together */
- pt->pending_intr_nr++;
- }
- else
- {
- pt->pending_intr_nr += missed_ticks;
- }
- pt->scheduled += missed_ticks * pt->period;
- }
+ if ( missed_ticks <= 0 )
+ return;
+
+ missed_ticks = missed_ticks / (s_time_t) pt->period + 1;
+ if ( missed_ticks > 1000 )
+ {
+ /* TODO: Adjust guest time together */
+ pt->pending_intr_nr++;
+ }
+ else
+ {
+ pt->pending_intr_nr += missed_ticks;
+ }
+
+ pt->scheduled += missed_ticks * pt->period;
}
void pt_freeze_time(struct vcpu *v)
{
struct list_head *head = &v->arch.hvm_vcpu.tm_list;
- struct list_head *list;
struct periodic_time *pt;
if ( test_bit(_VPF_blocked, &v->pause_flags) )
@@ -54,17 +54,13 @@ void pt_freeze_time(struct vcpu *v)
v->arch.hvm_vcpu.guest_time = hvm_get_guest_time(v);
- list_for_each( list, head )
- {
- pt = list_entry(list, struct periodic_time, list);
+ list_for_each_entry ( pt, head, list )
stop_timer(&pt->timer);
- }
}
void pt_thaw_time(struct vcpu *v)
{
struct list_head *head = &v->arch.hvm_vcpu.tm_list;
- struct list_head *list;
struct periodic_time *pt;
if ( v->arch.hvm_vcpu.guest_time )
@@ -72,17 +68,15 @@ void pt_thaw_time(struct vcpu *v)
hvm_set_guest_time(v, v->arch.hvm_vcpu.guest_time);
v->arch.hvm_vcpu.guest_time = 0;
- list_for_each( list, head )
- {
- pt = list_entry(list, struct periodic_time, list);
+ list_for_each_entry ( pt, head, list )
+ {
missed_ticks(pt);
set_timer(&pt->timer, pt->scheduled);
}
}
}
-/* Hook function for the platform periodic time */
-void pt_timer_fn(void *data)
+static void pt_timer_fn(void *data)
{
struct periodic_time *pt = data;
@@ -100,14 +94,12 @@ void pt_update_irq(struct vcpu *v)
void pt_update_irq(struct vcpu *v)
{
struct list_head *head = &v->arch.hvm_vcpu.tm_list;
- struct list_head *list;
struct periodic_time *pt;
uint64_t max_lag = -1ULL;
int irq = -1;
- list_for_each( list, head )
- {
- pt = list_entry(list, struct periodic_time, list);
+ list_for_each_entry ( pt, head, list )
+ {
if ( !is_isa_irq_masked(v, pt->irq) && pt->pending_intr_nr &&
((pt->last_plt_gtime + pt->period_cycles) < max_lag) )
{
@@ -130,14 +122,12 @@ struct periodic_time *is_pt_irq(struct v
struct periodic_time *is_pt_irq(struct vcpu *v, int vector, int type)
{
struct list_head *head = &v->arch.hvm_vcpu.tm_list;
- struct list_head *list;
struct periodic_time *pt;
struct RTCState *rtc = &v->domain->arch.hvm_domain.pl_time.vrtc;
int vec;
- list_for_each( list, head )
- {
- pt = list_entry(list, struct periodic_time, list);
+ list_for_each_entry ( pt, head, list )
+ {
if ( !pt->pending_intr_nr )
continue;
@@ -177,17 +167,14 @@ void pt_intr_post(struct vcpu *v, int ve
pt->cb(pt->vcpu, pt->priv);
}
-/* If pt is enabled, discard pending intr */
void pt_reset(struct vcpu *v)
{
struct list_head *head = &v->arch.hvm_vcpu.tm_list;
- struct list_head *list;
- struct periodic_time *pt;
-
- list_for_each( list, head )
- {
- pt = list_entry(list, struct periodic_time, list);
- if ( pt->enabled )
+ struct periodic_time *pt;
+
+ list_for_each_entry ( pt, head, list )
+ {
+ if ( pt->enabled )
{
pt->pending_intr_nr = 0;
pt->last_plt_gtime = hvm_get_guest_time(pt->vcpu);
@@ -197,11 +184,25 @@ void pt_reset(struct vcpu *v)
}
}
-void create_periodic_time(struct vcpu *v, struct periodic_time *pt, uint64_t
period,
- uint8_t irq, char one_shot, time_cb *cb, void *data)
+void pt_migrate(struct vcpu *v)
+{
+ struct list_head *head = &v->arch.hvm_vcpu.tm_list;
+ struct periodic_time *pt;
+
+ list_for_each_entry ( pt, head, list )
+ {
+ if ( pt->enabled )
+ migrate_timer(&pt->timer, v->processor);
+ }
+}
+
+void create_periodic_time(
+ struct vcpu *v, struct periodic_time *pt, uint64_t period,
+ uint8_t irq, char one_shot, time_cb *cb, void *data)
{
destroy_periodic_time(pt);
+ init_timer(&pt->timer, pt_timer_fn, pt, v->processor);
pt->enabled = 1;
if ( period < 900000 ) /* < 0.9 ms */
{
@@ -226,11 +227,11 @@ void create_periodic_time(struct vcpu *v
void destroy_periodic_time(struct periodic_time *pt)
{
- if ( pt->enabled )
- {
- pt->enabled = 0;
- pt->pending_intr_nr = 0;
- list_del(&pt->list);
- stop_timer(&pt->timer);
- }
-}
+ if ( !pt->enabled )
+ return;
+
+ pt->enabled = 0;
+ pt->pending_intr_nr = 0;
+ list_del(&pt->list);
+ kill_timer(&pt->timer);
+}
diff -r fe42519fb10e -r 3b51eebdf9ab xen/arch/x86/io_apic.c
--- a/xen/arch/x86/io_apic.c Fri Jun 15 12:38:35 2007 -0600
+++ b/xen/arch/x86/io_apic.c Fri Jun 15 13:33:11 2007 -0600
@@ -2114,6 +2114,15 @@ int ioapic_guest_write(unsigned long phy
return 0;
}
+ /* Special delivery modes (SMI,NMI,INIT,ExtInt) should have no vector. */
+ if ( (old_rte.delivery_mode > dest_LowestPrio) && (old_rte.vector != 0) )
+ {
+ WARN_BOGUS_WRITE("Special delivery mode %d with non-zero vector "
+ "%02x\n", old_rte.delivery_mode, old_rte.vector);
+ /* Nobble the vector here as it does not relate to a valid irq. */
+ old_rte.vector = 0;
+ }
+
if ( old_rte.vector >= FIRST_DYNAMIC_VECTOR )
old_irq = vector_irq[old_rte.vector];
if ( new_rte.vector >= FIRST_DYNAMIC_VECTOR )
diff -r fe42519fb10e -r 3b51eebdf9ab xen/include/asm-x86/hvm/vmx/vmcs.h
--- a/xen/include/asm-x86/hvm/vmx/vmcs.h Fri Jun 15 12:38:35 2007 -0600
+++ b/xen/include/asm-x86/hvm/vmx/vmcs.h Fri Jun 15 13:33:11 2007 -0600
@@ -104,6 +104,7 @@ void vmx_vmcs_exit(struct vcpu *v);
#define CPU_BASED_CR8_LOAD_EXITING 0x00080000
#define CPU_BASED_CR8_STORE_EXITING 0x00100000
#define CPU_BASED_TPR_SHADOW 0x00200000
+#define CPU_BASED_VIRTUAL_NMI_PENDING 0x00400000
#define CPU_BASED_MOV_DR_EXITING 0x00800000
#define CPU_BASED_UNCOND_IO_EXITING 0x01000000
#define CPU_BASED_ACTIVATE_IO_BITMAP 0x02000000
@@ -115,6 +116,7 @@ extern u32 vmx_cpu_based_exec_control;
#define PIN_BASED_EXT_INTR_MASK 0x00000001
#define PIN_BASED_NMI_EXITING 0x00000008
+#define PIN_BASED_VIRTUAL_NMIS 0x00000020
extern u32 vmx_pin_based_exec_control;
#define VM_EXIT_IA32E_MODE 0x00000200
@@ -137,7 +139,13 @@ extern u32 vmx_secondary_exec_control;
(vmx_cpu_based_exec_control & CPU_BASED_ACTIVATE_MSR_BITMAP)
extern char *vmx_msr_bitmap;
-/* VMCS Encordings */
+/* GUEST_INTERRUPTIBILITY_INFO flags. */
+#define VMX_INTR_SHADOW_STI 0x00000001
+#define VMX_INTR_SHADOW_MOV_SS 0x00000002
+#define VMX_INTR_SHADOW_SMI 0x00000004
+#define VMX_INTR_SHADOW_NMI 0x00000008
+
+/* VMCS field encodings. */
enum vmcs_field {
GUEST_ES_SELECTOR = 0x00000800,
GUEST_CS_SELECTOR = 0x00000802,
diff -r fe42519fb10e -r 3b51eebdf9ab xen/include/asm-x86/hvm/vmx/vmx.h
--- a/xen/include/asm-x86/hvm/vmx/vmx.h Fri Jun 15 12:38:35 2007 -0600
+++ b/xen/include/asm-x86/hvm/vmx/vmx.h Fri Jun 15 13:33:11 2007 -0600
@@ -46,8 +46,8 @@ void vmx_vlapic_msr_changed(struct vcpu
#define EXIT_REASON_SIPI 4
#define EXIT_REASON_IO_SMI 5
#define EXIT_REASON_OTHER_SMI 6
-#define EXIT_REASON_PENDING_INTERRUPT 7
-
+#define EXIT_REASON_PENDING_VIRT_INTR 7
+#define EXIT_REASON_PENDING_VIRT_NMI 8
#define EXIT_REASON_TASK_SWITCH 9
#define EXIT_REASON_CPUID 10
#define EXIT_REASON_HLT 12
@@ -295,7 +295,14 @@ static inline void __vmx_inject_exceptio
{
unsigned long intr_fields;
- /* Reflect it back into the guest */
+ /*
+ * NB. Callers do not need to worry about clearing STI/MOV-SS blocking:
+ * "If the VM entry is injecting, there is no blocking by STI or by
+ * MOV SS following the VM entry, regardless of the contents of the
+ * interruptibility-state field [in the guest-state area before the
+ * VM entry]", PRM Vol. 3, 22.6.1 (Interruptibility State).
+ */
+
intr_fields = (INTR_INFO_VALID_MASK | type | trap);
if ( error_code != VMX_DELIVER_NO_ERROR_CODE ) {
__vmwrite(VM_ENTRY_EXCEPTION_ERROR_CODE, error_code);
@@ -332,7 +339,6 @@ static inline void vmx_inject_extint(str
static inline void vmx_inject_extint(struct vcpu *v, int trap, int error_code)
{
__vmx_inject_exception(v, trap, INTR_TYPE_EXT_INTR, error_code, 0);
- __vmwrite(GUEST_INTERRUPTIBILITY_INFO, 0);
}
#endif /* __ASM_X86_HVM_VMX_VMX_H__ */
diff -r fe42519fb10e -r 3b51eebdf9ab xen/include/asm-x86/hvm/vpt.h
--- a/xen/include/asm-x86/hvm/vpt.h Fri Jun 15 12:38:35 2007 -0600
+++ b/xen/include/asm-x86/hvm/vpt.h Fri Jun 15 13:33:11 2007 -0600
@@ -115,19 +115,19 @@ struct pl_time { /* platform time */
void pt_freeze_time(struct vcpu *v);
void pt_thaw_time(struct vcpu *v);
-void pt_timer_fn(void *data);
void pt_update_irq(struct vcpu *v);
struct periodic_time *is_pt_irq(struct vcpu *v, int vector, int type);
void pt_intr_post(struct vcpu *v, int vector, int type);
void pt_reset(struct vcpu *v);
-void create_periodic_time(struct vcpu *v, struct periodic_time *pt, uint64_t
period,
- uint8_t irq, char one_shot, time_cb *cb, void *data);
+void pt_migrate(struct vcpu *v);
+void create_periodic_time(
+ struct vcpu *v, struct periodic_time *pt, uint64_t period,
+ uint8_t irq, char one_shot, time_cb *cb, void *data);
void destroy_periodic_time(struct periodic_time *pt);
int pv_pit_handler(int port, int data, int write);
void pit_init(struct vcpu *v, unsigned long cpu_khz);
void pit_stop_channel0_irq(PITState * pit);
-void pit_migrate_timers(struct vcpu *v);
void pit_deinit(struct domain *d);
void rtc_init(struct vcpu *v, int base);
void rtc_migrate_timers(struct vcpu *v);
diff -r fe42519fb10e -r 3b51eebdf9ab xen/include/asm-x86/msr.h
--- a/xen/include/asm-x86/msr.h Fri Jun 15 12:38:35 2007 -0600
+++ b/xen/include/asm-x86/msr.h Fri Jun 15 13:33:11 2007 -0600
@@ -96,6 +96,7 @@ static inline void wrmsrl(unsigned int m
#define MSR_IA32_TIME_STAMP_COUNTER 0x10
#define MSR_IA32_PLATFORM_ID 0x17
#define MSR_IA32_EBL_CR_POWERON 0x2a
+#define MSR_IA32_EBC_FREQUENCY_ID 0x2c
#define MSR_IA32_APICBASE 0x1b
#define MSR_IA32_APICBASE_BSP (1<<8)
diff -r fe42519fb10e -r 3b51eebdf9ab xen/include/public/io/ring.h
--- a/xen/include/public/io/ring.h Fri Jun 15 12:38:35 2007 -0600
+++ b/xen/include/public/io/ring.h Fri Jun 15 13:33:11 2007 -0600
@@ -133,7 +133,7 @@ typedef struct __name##_back_ring __name
#define SHARED_RING_INIT(_s) do { \
(_s)->req_prod = (_s)->rsp_prod = 0; \
(_s)->req_event = (_s)->rsp_event = 1; \
- memset((_s)->pad, 0, sizeof((_s)->pad)); \
+ (void)memset((_s)->pad, 0, sizeof((_s)->pad)); \
} while(0)
#define FRONT_RING_INIT(_r, _s, __size) do { \
diff -r fe42519fb10e -r 3b51eebdf9ab xen/include/public/io/xs_wire.h
--- a/xen/include/public/io/xs_wire.h Fri Jun 15 12:38:35 2007 -0600
+++ b/xen/include/public/io/xs_wire.h Fri Jun 15 13:33:11 2007 -0600
@@ -60,7 +60,11 @@ struct xsd_errors
const char *errstring;
};
#define XSD_ERROR(x) { x, #x }
-static struct xsd_errors xsd_errors[] __attribute__((unused)) = {
+static struct xsd_errors xsd_errors[]
+#if defined(__GNUC__)
+__attribute__((unused))
+#endif
+ = {
XSD_ERROR(EINVAL),
XSD_ERROR(EACCES),
XSD_ERROR(EEXIST),
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|