aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/xen
diff options
context:
space:
mode:
authorJeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>2010-08-04 17:49:16 -0400
committerJeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>2010-08-04 17:49:16 -0400
commitca50a5f39041497253c6362f2ba4da1b56d3e6cb (patch)
tree482f1607d12b60f6ef482bb4af2c9c58d7814d5f /arch/x86/xen
parenta70ce4b6064b64477ed12ef1878980f842819094 (diff)
parentca65f9fc0c447da5b270b05c41c21b19c88617c3 (diff)
Merge branch 'upstream/pvhvm' into upstream/xen
* upstream/pvhvm: Introduce CONFIG_XEN_PVHVM compile option blkfront: do not create a PV cdrom device if xen_hvm_guest support multiple .discard.* sections to avoid section type conflicts xen/pvhvm: fix build problem when !CONFIG_XEN xenfs: enable for HVM domains too x86: Call HVMOP_pagetable_dying on exit_mmap. x86: Unplug emulated disks and nics. x86: Use xen_vcpuop_clockevent, xen_clocksource and xen wallclock. xen: Fix find_unbound_irq in presence of ioapic irqs. xen: Add suspend/resume support for PV on HVM guests. xen: Xen PCI platform device driver. x86/xen: event channels delivery on HVM. x86: early PV on HVM features initialization. xen: Add support for HVM hypercalls. Conflicts: arch/x86/xen/enlighten.c arch/x86/xen/time.c
Diffstat (limited to 'arch/x86/xen')
-rw-r--r--arch/x86/xen/Kconfig5
-rw-r--r--arch/x86/xen/Makefile2
-rw-r--r--arch/x86/xen/enlighten.c158
-rw-r--r--arch/x86/xen/mmu.c35
-rw-r--r--arch/x86/xen/mmu.h1
-rw-r--r--arch/x86/xen/platform-pci-unplug.c137
-rw-r--r--arch/x86/xen/suspend.c12
-rw-r--r--arch/x86/xen/time.c57
-rw-r--r--arch/x86/xen/xen-ops.h11
9 files changed, 396 insertions, 22 deletions
diff --git a/arch/x86/xen/Kconfig b/arch/x86/xen/Kconfig
index b83e119fbeb0..68128a1b401a 100644
--- a/arch/x86/xen/Kconfig
+++ b/arch/x86/xen/Kconfig
@@ -13,6 +13,11 @@ config XEN
13 kernel to boot in a paravirtualized environment under the 13 kernel to boot in a paravirtualized environment under the
14 Xen hypervisor. 14 Xen hypervisor.
15 15
16config XEN_PVHVM
17 def_bool y
18 depends on XEN
19 depends on X86_LOCAL_APIC
20
16config XEN_MAX_DOMAIN_MEMORY 21config XEN_MAX_DOMAIN_MEMORY
17 int "Maximum allowed size of a domain in gigabytes" 22 int "Maximum allowed size of a domain in gigabytes"
18 default 8 if X86_32 23 default 8 if X86_32
diff --git a/arch/x86/xen/Makefile b/arch/x86/xen/Makefile
index 3bb4fc21f4f2..930954685980 100644
--- a/arch/x86/xen/Makefile
+++ b/arch/x86/xen/Makefile
@@ -12,7 +12,7 @@ CFLAGS_mmu.o := $(nostackp)
12 12
13obj-y := enlighten.o setup.o multicalls.o mmu.o irq.o \ 13obj-y := enlighten.o setup.o multicalls.o mmu.o irq.o \
14 time.o xen-asm.o xen-asm_$(BITS).o \ 14 time.o xen-asm.o xen-asm_$(BITS).o \
15 grant-table.o suspend.o 15 grant-table.o suspend.o platform-pci-unplug.o
16 16
17obj-$(CONFIG_SMP) += smp.o 17obj-$(CONFIG_SMP) += smp.o
18obj-$(CONFIG_PARAVIRT_SPINLOCKS)+= spinlock.o 18obj-$(CONFIG_PARAVIRT_SPINLOCKS)+= spinlock.o
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index 3c4da8bee06f..d4ff5e83621d 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -11,6 +11,7 @@
11 * Jeremy Fitzhardinge <jeremy@xensource.com>, XenSource Inc, 2007 11 * Jeremy Fitzhardinge <jeremy@xensource.com>, XenSource Inc, 2007
12 */ 12 */
13 13
14#include <linux/cpu.h>
14#include <linux/kernel.h> 15#include <linux/kernel.h>
15#include <linux/init.h> 16#include <linux/init.h>
16#include <linux/smp.h> 17#include <linux/smp.h>
@@ -35,8 +36,10 @@
35#include <xen/interface/version.h> 36#include <xen/interface/version.h>
36#include <xen/interface/physdev.h> 37#include <xen/interface/physdev.h>
37#include <xen/interface/vcpu.h> 38#include <xen/interface/vcpu.h>
39#include <xen/interface/memory.h>
38#include <xen/features.h> 40#include <xen/features.h>
39#include <xen/page.h> 41#include <xen/page.h>
42#include <xen/hvm.h>
40#include <xen/hvc-console.h> 43#include <xen/hvc-console.h>
41 44
42#include <asm/paravirt.h> 45#include <asm/paravirt.h>
@@ -55,7 +58,9 @@
55#include <asm/pgtable.h> 58#include <asm/pgtable.h>
56#include <asm/tlbflush.h> 59#include <asm/tlbflush.h>
57#include <asm/reboot.h> 60#include <asm/reboot.h>
61#include <asm/setup.h>
58#include <asm/stackprotector.h> 62#include <asm/stackprotector.h>
63#include <asm/hypervisor.h>
59 64
60#include "xen-ops.h" 65#include "xen-ops.h"
61#include "mmu.h" 66#include "mmu.h"
@@ -76,6 +81,10 @@ struct shared_info xen_dummy_shared_info;
76 81
77void *xen_initial_gdt; 82void *xen_initial_gdt;
78 83
84RESERVE_BRK(shared_info_page_brk, PAGE_SIZE);
85__read_mostly int xen_have_vector_callback;
86EXPORT_SYMBOL_GPL(xen_have_vector_callback);
87
79/* 88/*
80 * Point at some empty memory to start with. We map the real shared_info 89 * Point at some empty memory to start with. We map the real shared_info
81 * page as soon as fixmap is up and running. 90 * page as soon as fixmap is up and running.
@@ -938,10 +947,6 @@ static const struct pv_init_ops xen_init_ops __initdata = {
938 .patch = xen_patch, 947 .patch = xen_patch,
939}; 948};
940 949
941static const struct pv_time_ops xen_time_ops __initdata = {
942 .sched_clock = xen_clocksource_read,
943};
944
945static const struct pv_cpu_ops xen_cpu_ops __initdata = { 950static const struct pv_cpu_ops xen_cpu_ops __initdata = {
946 .cpuid = xen_cpuid, 951 .cpuid = xen_cpuid,
947 952
@@ -1096,7 +1101,6 @@ asmlinkage void __init xen_start_kernel(void)
1096 /* Install Xen paravirt ops */ 1101 /* Install Xen paravirt ops */
1097 pv_info = xen_info; 1102 pv_info = xen_info;
1098 pv_init_ops = xen_init_ops; 1103 pv_init_ops = xen_init_ops;
1099 pv_time_ops = xen_time_ops;
1100 pv_cpu_ops = xen_cpu_ops; 1104 pv_cpu_ops = xen_cpu_ops;
1101 pv_apic_ops = xen_apic_ops; 1105 pv_apic_ops = xen_apic_ops;
1102 1106
@@ -1104,13 +1108,7 @@ asmlinkage void __init xen_start_kernel(void)
1104 x86_init.oem.arch_setup = xen_arch_setup; 1108 x86_init.oem.arch_setup = xen_arch_setup;
1105 x86_init.oem.banner = xen_banner; 1109 x86_init.oem.banner = xen_banner;
1106 1110
1107 x86_init.timers.timer_init = xen_time_init; 1111 xen_init_time_ops();
1108 x86_init.timers.setup_percpu_clockev = x86_init_noop;
1109 x86_cpuinit.setup_percpu_clockev = x86_init_noop;
1110
1111 x86_platform.calibrate_tsc = xen_tsc_khz;
1112 x86_platform.get_wallclock = xen_get_wallclock;
1113 x86_platform.set_wallclock = xen_set_wallclock;
1114 1112
1115 /* 1113 /*
1116 * Set up some pagetable state before starting to set any ptes. 1114 * Set up some pagetable state before starting to set any ptes.
@@ -1235,3 +1233,139 @@ asmlinkage void __init xen_start_kernel(void)
1235 x86_64_start_reservations((char *)__pa_symbol(&boot_params)); 1233 x86_64_start_reservations((char *)__pa_symbol(&boot_params));
1236#endif 1234#endif
1237} 1235}
1236
1237static uint32_t xen_cpuid_base(void)
1238{
1239 uint32_t base, eax, ebx, ecx, edx;
1240 char signature[13];
1241
1242 for (base = 0x40000000; base < 0x40010000; base += 0x100) {
1243 cpuid(base, &eax, &ebx, &ecx, &edx);
1244 *(uint32_t *)(signature + 0) = ebx;
1245 *(uint32_t *)(signature + 4) = ecx;
1246 *(uint32_t *)(signature + 8) = edx;
1247 signature[12] = 0;
1248
1249 if (!strcmp("XenVMMXenVMM", signature) && ((eax - base) >= 2))
1250 return base;
1251 }
1252
1253 return 0;
1254}
1255
1256static int init_hvm_pv_info(int *major, int *minor)
1257{
1258 uint32_t eax, ebx, ecx, edx, pages, msr, base;
1259 u64 pfn;
1260
1261 base = xen_cpuid_base();
1262 cpuid(base + 1, &eax, &ebx, &ecx, &edx);
1263
1264 *major = eax >> 16;
1265 *minor = eax & 0xffff;
1266 printk(KERN_INFO "Xen version %d.%d.\n", *major, *minor);
1267
1268 cpuid(base + 2, &pages, &msr, &ecx, &edx);
1269
1270 pfn = __pa(hypercall_page);
1271 wrmsr_safe(msr, (u32)pfn, (u32)(pfn >> 32));
1272
1273 xen_setup_features();
1274
1275 pv_info = xen_info;
1276 pv_info.kernel_rpl = 0;
1277
1278 xen_domain_type = XEN_HVM_DOMAIN;
1279
1280 return 0;
1281}
1282
1283void xen_hvm_init_shared_info(void)
1284{
1285 int cpu;
1286 struct xen_add_to_physmap xatp;
1287 static struct shared_info *shared_info_page = 0;
1288
1289 if (!shared_info_page)
1290 shared_info_page = (struct shared_info *)
1291 extend_brk(PAGE_SIZE, PAGE_SIZE);
1292 xatp.domid = DOMID_SELF;
1293 xatp.idx = 0;
1294 xatp.space = XENMAPSPACE_shared_info;
1295 xatp.gpfn = __pa(shared_info_page) >> PAGE_SHIFT;
1296 if (HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp))
1297 BUG();
1298
1299 HYPERVISOR_shared_info = (struct shared_info *)shared_info_page;
1300
1301 /* xen_vcpu is a pointer to the vcpu_info struct in the shared_info
1302 * page, we use it in the event channel upcall and in some pvclock
1303 * related functions. We don't need the vcpu_info placement
1304 * optimizations because we don't use any pv_mmu or pv_irq op on
1305 * HVM.
1306 * When xen_hvm_init_shared_info is run at boot time only vcpu 0 is
1307 * online but xen_hvm_init_shared_info is run at resume time too and
1308 * in that case multiple vcpus might be online. */
1309 for_each_online_cpu(cpu) {
1310 per_cpu(xen_vcpu, cpu) = &HYPERVISOR_shared_info->vcpu_info[cpu];
1311 }
1312}
1313
1314#ifdef CONFIG_XEN_PVHVM
1315static int __cpuinit xen_hvm_cpu_notify(struct notifier_block *self,
1316 unsigned long action, void *hcpu)
1317{
1318 int cpu = (long)hcpu;
1319 switch (action) {
1320 case CPU_UP_PREPARE:
1321 per_cpu(xen_vcpu, cpu) = &HYPERVISOR_shared_info->vcpu_info[cpu];
1322 break;
1323 default:
1324 break;
1325 }
1326 return NOTIFY_OK;
1327}
1328
1329static struct notifier_block __cpuinitdata xen_hvm_cpu_notifier = {
1330 .notifier_call = xen_hvm_cpu_notify,
1331};
1332
1333static void __init xen_hvm_guest_init(void)
1334{
1335 int r;
1336 int major, minor;
1337
1338 r = init_hvm_pv_info(&major, &minor);
1339 if (r < 0)
1340 return;
1341
1342 xen_hvm_init_shared_info();
1343
1344 if (xen_feature(XENFEAT_hvm_callback_vector))
1345 xen_have_vector_callback = 1;
1346 register_cpu_notifier(&xen_hvm_cpu_notifier);
1347 xen_unplug_emulated_devices();
1348 have_vcpu_info_placement = 0;
1349 x86_init.irqs.intr_init = xen_init_IRQ;
1350 xen_hvm_init_time_ops();
1351 xen_hvm_init_mmu_ops();
1352}
1353
1354static bool __init xen_hvm_platform(void)
1355{
1356 if (xen_pv_domain())
1357 return false;
1358
1359 if (!xen_cpuid_base())
1360 return false;
1361
1362 return true;
1363}
1364
1365const __refconst struct hypervisor_x86 x86_hyper_xen_hvm = {
1366 .name = "Xen HVM",
1367 .detect = xen_hvm_platform,
1368 .init_platform = xen_hvm_guest_init,
1369};
1370EXPORT_SYMBOL(x86_hyper_xen_hvm);
1371#endif
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c
index 914f04695ce5..413b19b3d0fe 100644
--- a/arch/x86/xen/mmu.c
+++ b/arch/x86/xen/mmu.c
@@ -58,6 +58,7 @@
58 58
59#include <xen/page.h> 59#include <xen/page.h>
60#include <xen/interface/xen.h> 60#include <xen/interface/xen.h>
61#include <xen/interface/hvm/hvm_op.h>
61#include <xen/interface/version.h> 62#include <xen/interface/version.h>
62#include <xen/hvc-console.h> 63#include <xen/hvc-console.h>
63 64
@@ -1941,6 +1942,40 @@ void __init xen_init_mmu_ops(void)
1941 pv_mmu_ops = xen_mmu_ops; 1942 pv_mmu_ops = xen_mmu_ops;
1942} 1943}
1943 1944
1945#ifdef CONFIG_XEN_PVHVM
1946static void xen_hvm_exit_mmap(struct mm_struct *mm)
1947{
1948 struct xen_hvm_pagetable_dying a;
1949 int rc;
1950
1951 a.domid = DOMID_SELF;
1952 a.gpa = __pa(mm->pgd);
1953 rc = HYPERVISOR_hvm_op(HVMOP_pagetable_dying, &a);
1954 WARN_ON_ONCE(rc < 0);
1955}
1956
1957static int is_pagetable_dying_supported(void)
1958{
1959 struct xen_hvm_pagetable_dying a;
1960 int rc = 0;
1961
1962 a.domid = DOMID_SELF;
1963 a.gpa = 0x00;
1964 rc = HYPERVISOR_hvm_op(HVMOP_pagetable_dying, &a);
1965 if (rc < 0) {
1966 printk(KERN_DEBUG "HVMOP_pagetable_dying not supported\n");
1967 return 0;
1968 }
1969 return 1;
1970}
1971
1972void __init xen_hvm_init_mmu_ops(void)
1973{
1974 if (is_pagetable_dying_supported())
1975 pv_mmu_ops.exit_mmap = xen_hvm_exit_mmap;
1976}
1977#endif
1978
1944#ifdef CONFIG_XEN_DEBUG_FS 1979#ifdef CONFIG_XEN_DEBUG_FS
1945 1980
1946static struct dentry *d_mmu_debug; 1981static struct dentry *d_mmu_debug;
diff --git a/arch/x86/xen/mmu.h b/arch/x86/xen/mmu.h
index 5fe6bc7f5ecf..fa938c4aa2f7 100644
--- a/arch/x86/xen/mmu.h
+++ b/arch/x86/xen/mmu.h
@@ -60,4 +60,5 @@ void xen_ptep_modify_prot_commit(struct mm_struct *mm, unsigned long addr,
60unsigned long xen_read_cr2_direct(void); 60unsigned long xen_read_cr2_direct(void);
61 61
62extern void xen_init_mmu_ops(void); 62extern void xen_init_mmu_ops(void);
63extern void xen_hvm_init_mmu_ops(void);
63#endif /* _XEN_MMU_H */ 64#endif /* _XEN_MMU_H */
diff --git a/arch/x86/xen/platform-pci-unplug.c b/arch/x86/xen/platform-pci-unplug.c
new file mode 100644
index 000000000000..554c002a1e1a
--- /dev/null
+++ b/arch/x86/xen/platform-pci-unplug.c
@@ -0,0 +1,137 @@
1/******************************************************************************
2 * platform-pci-unplug.c
3 *
4 * Xen platform PCI device driver
5 * Copyright (c) 2010, Citrix
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms and conditions of the GNU General Public License,
9 * version 2, as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
18 * Place - Suite 330, Boston, MA 02111-1307 USA.
19 *
20 */
21
22#include <linux/init.h>
23#include <linux/io.h>
24#include <linux/module.h>
25
26#include <xen/platform_pci.h>
27
28#define XEN_PLATFORM_ERR_MAGIC -1
29#define XEN_PLATFORM_ERR_PROTOCOL -2
30#define XEN_PLATFORM_ERR_BLACKLIST -3
31
32/* store the value of xen_emul_unplug after the unplug is done */
33int xen_platform_pci_unplug;
34EXPORT_SYMBOL_GPL(xen_platform_pci_unplug);
35#ifdef CONFIG_XEN_PVHVM
36static int xen_emul_unplug;
37
38static int __init check_platform_magic(void)
39{
40 short magic;
41 char protocol;
42
43 magic = inw(XEN_IOPORT_MAGIC);
44 if (magic != XEN_IOPORT_MAGIC_VAL) {
45 printk(KERN_ERR "Xen Platform PCI: unrecognised magic value\n");
46 return XEN_PLATFORM_ERR_MAGIC;
47 }
48
49 protocol = inb(XEN_IOPORT_PROTOVER);
50
51 printk(KERN_DEBUG "Xen Platform PCI: I/O protocol version %d\n",
52 protocol);
53
54 switch (protocol) {
55 case 1:
56 outw(XEN_IOPORT_LINUX_PRODNUM, XEN_IOPORT_PRODNUM);
57 outl(XEN_IOPORT_LINUX_DRVVER, XEN_IOPORT_DRVVER);
58 if (inw(XEN_IOPORT_MAGIC) != XEN_IOPORT_MAGIC_VAL) {
59 printk(KERN_ERR "Xen Platform: blacklisted by host\n");
60 return XEN_PLATFORM_ERR_BLACKLIST;
61 }
62 break;
63 default:
64 printk(KERN_WARNING "Xen Platform PCI: unknown I/O protocol version");
65 return XEN_PLATFORM_ERR_PROTOCOL;
66 }
67
68 return 0;
69}
70
71void __init xen_unplug_emulated_devices(void)
72{
73 int r;
74
75 /* check the version of the xen platform PCI device */
76 r = check_platform_magic();
77 /* If the version matches enable the Xen platform PCI driver.
78 * Also enable the Xen platform PCI driver if the version is really old
79 * and the user told us to ignore it. */
80 if (r && !(r == XEN_PLATFORM_ERR_MAGIC &&
81 (xen_emul_unplug & XEN_UNPLUG_IGNORE)))
82 return;
83 /* Set the default value of xen_emul_unplug depending on whether or
84 * not the Xen PV frontends and the Xen platform PCI driver have
85 * been compiled for this kernel (modules or built-in are both OK). */
86 if (!xen_emul_unplug) {
87 if (xen_must_unplug_nics()) {
88 printk(KERN_INFO "Netfront and the Xen platform PCI driver have "
89 "been compiled for this kernel: unplug emulated NICs.\n");
90 xen_emul_unplug |= XEN_UNPLUG_ALL_NICS;
91 }
92 if (xen_must_unplug_disks()) {
93 printk(KERN_INFO "Blkfront and the Xen platform PCI driver have "
94 "been compiled for this kernel: unplug emulated disks.\n"
95 "You might have to change the root device\n"
96 "from /dev/hd[a-d] to /dev/xvd[a-d]\n"
97 "in your root= kernel command line option\n");
98 xen_emul_unplug |= XEN_UNPLUG_ALL_IDE_DISKS;
99 }
100 }
101 /* Now unplug the emulated devices */
102 if (!(xen_emul_unplug & XEN_UNPLUG_IGNORE))
103 outw(xen_emul_unplug, XEN_IOPORT_UNPLUG);
104 xen_platform_pci_unplug = xen_emul_unplug;
105}
106
107static int __init parse_xen_emul_unplug(char *arg)
108{
109 char *p, *q;
110 int l;
111
112 for (p = arg; p; p = q) {
113 q = strchr(p, ',');
114 if (q) {
115 l = q - p;
116 q++;
117 } else {
118 l = strlen(p);
119 }
120 if (!strncmp(p, "all", l))
121 xen_emul_unplug |= XEN_UNPLUG_ALL;
122 else if (!strncmp(p, "ide-disks", l))
123 xen_emul_unplug |= XEN_UNPLUG_ALL_IDE_DISKS;
124 else if (!strncmp(p, "aux-ide-disks", l))
125 xen_emul_unplug |= XEN_UNPLUG_AUX_IDE_DISKS;
126 else if (!strncmp(p, "nics", l))
127 xen_emul_unplug |= XEN_UNPLUG_ALL_NICS;
128 else if (!strncmp(p, "ignore", l))
129 xen_emul_unplug |= XEN_UNPLUG_IGNORE;
130 else
131 printk(KERN_WARNING "unrecognised option '%s' "
132 "in parameter 'xen_emul_unplug'\n", p);
133 }
134 return 0;
135}
136early_param("xen_emul_unplug", parse_xen_emul_unplug);
137#endif
diff --git a/arch/x86/xen/suspend.c b/arch/x86/xen/suspend.c
index a9c661108034..1d789d56877c 100644
--- a/arch/x86/xen/suspend.c
+++ b/arch/x86/xen/suspend.c
@@ -26,6 +26,18 @@ void xen_pre_suspend(void)
26 BUG(); 26 BUG();
27} 27}
28 28
29void xen_hvm_post_suspend(int suspend_cancelled)
30{
31 int cpu;
32 xen_hvm_init_shared_info();
33 xen_callback_vector();
34 if (xen_feature(XENFEAT_hvm_safe_pvclock)) {
35 for_each_online_cpu(cpu) {
36 xen_setup_runstate_info(cpu);
37 }
38 }
39}
40
29void xen_post_suspend(int suspend_cancelled) 41void xen_post_suspend(int suspend_cancelled)
30{ 42{
31 xen_build_mfn_list_list(); 43 xen_build_mfn_list_list();
diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c
index a86df42e46ad..1a5353a753fc 100644
--- a/arch/x86/xen/time.c
+++ b/arch/x86/xen/time.c
@@ -20,6 +20,7 @@
20#include <asm/xen/hypercall.h> 20#include <asm/xen/hypercall.h>
21 21
22#include <xen/events.h> 22#include <xen/events.h>
23#include <xen/features.h>
23#include <xen/interface/xen.h> 24#include <xen/interface/xen.h>
24#include <xen/interface/vcpu.h> 25#include <xen/interface/vcpu.h>
25 26
@@ -156,7 +157,7 @@ static void do_stolen_accounting(void)
156} 157}
157 158
158/* Get the TSC speed from Xen */ 159/* Get the TSC speed from Xen */
159unsigned long xen_tsc_khz(void) 160static unsigned long xen_tsc_khz(void)
160{ 161{
161 struct pvclock_vcpu_time_info *info = 162 struct pvclock_vcpu_time_info *info =
162 &HYPERVISOR_shared_info->vcpu_info[0].time; 163 &HYPERVISOR_shared_info->vcpu_info[0].time;
@@ -191,7 +192,7 @@ static void xen_read_wallclock(struct timespec *ts)
191 put_cpu_var(xen_vcpu); 192 put_cpu_var(xen_vcpu);
192} 193}
193 194
194unsigned long xen_get_wallclock(void) 195static unsigned long xen_get_wallclock(void)
195{ 196{
196 struct timespec ts; 197 struct timespec ts;
197 198
@@ -199,7 +200,7 @@ unsigned long xen_get_wallclock(void)
199 return ts.tv_sec; 200 return ts.tv_sec;
200} 201}
201 202
202int xen_set_wallclock(unsigned long now) 203static int xen_set_wallclock(unsigned long now)
203{ 204{
204 /* do nothing for domU */ 205 /* do nothing for domU */
205 return -1; 206 return -1;
@@ -434,7 +435,11 @@ void xen_timer_resume(void)
434 } 435 }
435} 436}
436 437
437__init void xen_time_init(void) 438static const struct pv_time_ops xen_time_ops __initdata = {
439 .sched_clock = xen_clocksource_read,
440};
441
442static __init void xen_time_init(void)
438{ 443{
439 int cpu = smp_processor_id(); 444 int cpu = smp_processor_id();
440 struct timespec tp; 445 struct timespec tp;
@@ -458,3 +463,47 @@ __init void xen_time_init(void)
458 xen_setup_timer(cpu); 463 xen_setup_timer(cpu);
459 xen_setup_cpu_clockevents(); 464 xen_setup_cpu_clockevents();
460} 465}
466
467__init void xen_init_time_ops(void)
468{
469 pv_time_ops = xen_time_ops;
470
471 x86_init.timers.timer_init = xen_time_init;
472 x86_init.timers.setup_percpu_clockev = x86_init_noop;
473 x86_cpuinit.setup_percpu_clockev = x86_init_noop;
474
475 x86_platform.calibrate_tsc = xen_tsc_khz;
476 x86_platform.get_wallclock = xen_get_wallclock;
477 x86_platform.set_wallclock = xen_set_wallclock;
478}
479
480#ifdef CONFIG_XEN_PVHVM
481static void xen_hvm_setup_cpu_clockevents(void)
482{
483 int cpu = smp_processor_id();
484 xen_setup_runstate_info(cpu);
485 xen_setup_timer(cpu);
486 xen_setup_cpu_clockevents();
487}
488
489__init void xen_hvm_init_time_ops(void)
490{
491 /* vector callback is needed otherwise we cannot receive interrupts
492 * on cpu > 0 */
493 if (!xen_have_vector_callback && num_present_cpus() > 1)
494 return;
495 if (!xen_feature(XENFEAT_hvm_safe_pvclock)) {
496 printk(KERN_INFO "Xen doesn't support pvclock on HVM,"
497 "disable pv timer\n");
498 return;
499 }
500
501 pv_time_ops = xen_time_ops;
502 x86_init.timers.setup_percpu_clockev = xen_time_init;
503 x86_cpuinit.setup_percpu_clockev = xen_hvm_setup_cpu_clockevents;
504
505 x86_platform.calibrate_tsc = xen_tsc_khz;
506 x86_platform.get_wallclock = xen_get_wallclock;
507 x86_platform.set_wallclock = xen_set_wallclock;
508}
509#endif
diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h
index 00d59d608edf..7c8ab86163e9 100644
--- a/arch/x86/xen/xen-ops.h
+++ b/arch/x86/xen/xen-ops.h
@@ -38,6 +38,10 @@ void xen_enable_sysenter(void);
38void xen_enable_syscall(void); 38void xen_enable_syscall(void);
39void xen_vcpu_restore(void); 39void xen_vcpu_restore(void);
40 40
41void xen_callback_vector(void);
42void xen_hvm_init_shared_info(void);
43void __init xen_unplug_emulated_devices(void);
44
41void __init xen_build_dynamic_phys_to_machine(void); 45void __init xen_build_dynamic_phys_to_machine(void);
42 46
43void xen_init_irq_ops(void); 47void xen_init_irq_ops(void);
@@ -46,11 +50,8 @@ void xen_setup_runstate_info(int cpu);
46void xen_teardown_timer(int cpu); 50void xen_teardown_timer(int cpu);
47cycle_t xen_clocksource_read(void); 51cycle_t xen_clocksource_read(void);
48void xen_setup_cpu_clockevents(void); 52void xen_setup_cpu_clockevents(void);
49unsigned long xen_tsc_khz(void); 53void __init xen_init_time_ops(void);
50void __init xen_time_init(void); 54void __init xen_hvm_init_time_ops(void);
51unsigned long xen_get_wallclock(void);
52int xen_set_wallclock(unsigned long time);
53unsigned long long xen_sched_clock(void);
54 55
55irqreturn_t xen_debug_interrupt(int irq, void *dev_id); 56irqreturn_t xen_debug_interrupt(int irq, void *dev_id);
56 57