aboutsummaryrefslogtreecommitdiffstats
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
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
-rw-r--r--Documentation/kernel-parameters.txt11
-rw-r--r--arch/x86/include/asm/hypervisor.h1
-rw-r--r--arch/x86/include/asm/irq_vectors.h3
-rw-r--r--arch/x86/include/asm/setup.h2
-rw-r--r--arch/x86/include/asm/xen/hypercall.h6
-rw-r--r--arch/x86/kernel/cpu/hypervisor.c3
-rw-r--r--arch/x86/kernel/entry_32.S3
-rw-r--r--arch/x86/kernel/entry_64.S3
-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
-rw-r--r--drivers/block/xen-blkfront.c30
-rw-r--r--drivers/input/xen-kbdfront.c2
-rw-r--r--drivers/video/xen-fbfront.c2
-rw-r--r--drivers/xen/Kconfig9
-rw-r--r--drivers/xen/Makefile3
-rw-r--r--drivers/xen/events.c95
-rw-r--r--drivers/xen/grant-table.c77
-rw-r--r--drivers/xen/manage.c46
-rw-r--r--drivers/xen/platform-pci.c207
-rw-r--r--drivers/xen/xenbus/xenbus_probe.c47
-rw-r--r--drivers/xen/xenfs/super.c4
-rw-r--r--include/asm-generic/vmlinux.lds.h1
-rw-r--r--include/linux/pci_ids.h3
-rw-r--r--include/xen/events.h7
-rw-r--r--include/xen/grant_table.h4
-rw-r--r--include/xen/hvm.h30
-rw-r--r--include/xen/interface/features.h6
-rw-r--r--include/xen/interface/grant_table.h1
-rw-r--r--include/xen/interface/hvm/hvm_op.h46
-rw-r--r--include/xen/interface/hvm/params.h95
-rw-r--r--include/xen/platform_pci.h49
-rw-r--r--include/xen/xen-ops.h3
39 files changed, 1156 insertions, 61 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 2b2407d9a6d0..2f32da74f5b1 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -115,6 +115,7 @@ parameter is applicable:
115 More X86-64 boot options can be found in 115 More X86-64 boot options can be found in
116 Documentation/x86/x86_64/boot-options.txt . 116 Documentation/x86/x86_64/boot-options.txt .
117 X86 Either 32bit or 64bit x86 (same as X86-32+X86-64) 117 X86 Either 32bit or 64bit x86 (same as X86-32+X86-64)
118 XEN Xen support is enabled
118 119
119In addition, the following text indicates that the option: 120In addition, the following text indicates that the option:
120 121
@@ -2879,6 +2880,16 @@ and is between 256 and 4096 characters. It is defined in the file
2879 xd= [HW,XT] Original XT pre-IDE (RLL encoded) disks. 2880 xd= [HW,XT] Original XT pre-IDE (RLL encoded) disks.
2880 xd_geo= See header of drivers/block/xd.c. 2881 xd_geo= See header of drivers/block/xd.c.
2881 2882
2883 xen_emul_unplug= [HW,X86,XEN]
2884 Unplug Xen emulated devices
2885 Format: [unplug0,][unplug1]
2886 ide-disks -- unplug primary master IDE devices
2887 aux-ide-disks -- unplug non-primary-master IDE devices
2888 nics -- unplug network devices
2889 all -- unplug all emulated devices (NICs and IDE disks)
2890 ignore -- continue loading the Xen platform PCI driver even
2891 if the version check failed
2892
2882 xirc2ps_cs= [NET,PCMCIA] 2893 xirc2ps_cs= [NET,PCMCIA]
2883 Format: 2894 Format:
2884 <irq>,<irq_mask>,<io>,<full_duplex>,<do_sound>,<lockup_hack>[,<irq2>[,<irq3>[,<irq4>]]] 2895 <irq>,<irq_mask>,<io>,<full_duplex>,<do_sound>,<lockup_hack>[,<irq2>[,<irq3>[,<irq4>]]]
diff --git a/arch/x86/include/asm/hypervisor.h b/arch/x86/include/asm/hypervisor.h
index 70abda7058c8..ff2546ce7178 100644
--- a/arch/x86/include/asm/hypervisor.h
+++ b/arch/x86/include/asm/hypervisor.h
@@ -45,5 +45,6 @@ extern const struct hypervisor_x86 *x86_hyper;
45/* Recognized hypervisors */ 45/* Recognized hypervisors */
46extern const struct hypervisor_x86 x86_hyper_vmware; 46extern const struct hypervisor_x86 x86_hyper_vmware;
47extern const struct hypervisor_x86 x86_hyper_ms_hyperv; 47extern const struct hypervisor_x86 x86_hyper_ms_hyperv;
48extern const struct hypervisor_x86 x86_hyper_xen_hvm;
48 49
49#endif 50#endif
diff --git a/arch/x86/include/asm/irq_vectors.h b/arch/x86/include/asm/irq_vectors.h
index 8767d99c4f64..e2ca30092557 100644
--- a/arch/x86/include/asm/irq_vectors.h
+++ b/arch/x86/include/asm/irq_vectors.h
@@ -125,6 +125,9 @@
125 */ 125 */
126#define MCE_SELF_VECTOR 0xeb 126#define MCE_SELF_VECTOR 0xeb
127 127
128/* Xen vector callback to receive events in a HVM domain */
129#define XEN_HVM_EVTCHN_CALLBACK 0xe9
130
128#define NR_VECTORS 256 131#define NR_VECTORS 256
129 132
130#define FPU_IRQ 13 133#define FPU_IRQ 13
diff --git a/arch/x86/include/asm/setup.h b/arch/x86/include/asm/setup.h
index 86b1506f4179..ef292c792d74 100644
--- a/arch/x86/include/asm/setup.h
+++ b/arch/x86/include/asm/setup.h
@@ -82,7 +82,7 @@ void *extend_brk(size_t size, size_t align);
82 * executable.) 82 * executable.)
83 */ 83 */
84#define RESERVE_BRK(name,sz) \ 84#define RESERVE_BRK(name,sz) \
85 static void __section(.discard) __used \ 85 static void __section(.discard.text) __used \
86 __brk_reservation_fn_##name##__(void) { \ 86 __brk_reservation_fn_##name##__(void) { \
87 asm volatile ( \ 87 asm volatile ( \
88 ".pushsection .brk_reservation,\"aw\",@nobits;" \ 88 ".pushsection .brk_reservation,\"aw\",@nobits;" \
diff --git a/arch/x86/include/asm/xen/hypercall.h b/arch/x86/include/asm/xen/hypercall.h
index 9c371e4a9fa6..7fda040a76cd 100644
--- a/arch/x86/include/asm/xen/hypercall.h
+++ b/arch/x86/include/asm/xen/hypercall.h
@@ -417,6 +417,12 @@ HYPERVISOR_nmi_op(unsigned long op, unsigned long arg)
417 return _hypercall2(int, nmi_op, op, arg); 417 return _hypercall2(int, nmi_op, op, arg);
418} 418}
419 419
420static inline unsigned long __must_check
421HYPERVISOR_hvm_op(int op, void *arg)
422{
423 return _hypercall2(unsigned long, hvm_op, op, arg);
424}
425
420static inline void 426static inline void
421MULTI_fpu_taskswitch(struct multicall_entry *mcl, int set) 427MULTI_fpu_taskswitch(struct multicall_entry *mcl, int set)
422{ 428{
diff --git a/arch/x86/kernel/cpu/hypervisor.c b/arch/x86/kernel/cpu/hypervisor.c
index dd531cc56a8f..8095f8611f8a 100644
--- a/arch/x86/kernel/cpu/hypervisor.c
+++ b/arch/x86/kernel/cpu/hypervisor.c
@@ -34,6 +34,9 @@ static const __initconst struct hypervisor_x86 * const hypervisors[] =
34{ 34{
35 &x86_hyper_vmware, 35 &x86_hyper_vmware,
36 &x86_hyper_ms_hyperv, 36 &x86_hyper_ms_hyperv,
37#ifdef CONFIG_XEN_PVHVM
38 &x86_hyper_xen_hvm,
39#endif
37}; 40};
38 41
39const struct hypervisor_x86 *x86_hyper; 42const struct hypervisor_x86 *x86_hyper;
diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S
index cd49141cf153..6b196834a0dd 100644
--- a/arch/x86/kernel/entry_32.S
+++ b/arch/x86/kernel/entry_32.S
@@ -1166,6 +1166,9 @@ ENTRY(xen_failsafe_callback)
1166.previous 1166.previous
1167ENDPROC(xen_failsafe_callback) 1167ENDPROC(xen_failsafe_callback)
1168 1168
1169BUILD_INTERRUPT3(xen_hvm_callback_vector, XEN_HVM_EVTCHN_CALLBACK,
1170 xen_evtchn_do_upcall)
1171
1169#endif /* CONFIG_XEN */ 1172#endif /* CONFIG_XEN */
1170 1173
1171#ifdef CONFIG_FUNCTION_TRACER 1174#ifdef CONFIG_FUNCTION_TRACER
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
index 4db7c4d12ffa..649ed17f7009 100644
--- a/arch/x86/kernel/entry_64.S
+++ b/arch/x86/kernel/entry_64.S
@@ -1329,6 +1329,9 @@ ENTRY(xen_failsafe_callback)
1329 CFI_ENDPROC 1329 CFI_ENDPROC
1330END(xen_failsafe_callback) 1330END(xen_failsafe_callback)
1331 1331
1332apicinterrupt XEN_HVM_EVTCHN_CALLBACK \
1333 xen_hvm_callback_vector xen_evtchn_do_upcall
1334
1332#endif /* CONFIG_XEN */ 1335#endif /* CONFIG_XEN */
1333 1336
1334/* 1337/*
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
diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c
index 82ed403147c0..f63ac3d1f8a4 100644
--- a/drivers/block/xen-blkfront.c
+++ b/drivers/block/xen-blkfront.c
@@ -48,6 +48,7 @@
48#include <xen/grant_table.h> 48#include <xen/grant_table.h>
49#include <xen/events.h> 49#include <xen/events.h>
50#include <xen/page.h> 50#include <xen/page.h>
51#include <xen/platform_pci.h>
51 52
52#include <xen/interface/grant_table.h> 53#include <xen/interface/grant_table.h>
53#include <xen/interface/io/blkif.h> 54#include <xen/interface/io/blkif.h>
@@ -737,6 +738,35 @@ static int blkfront_probe(struct xenbus_device *dev,
737 } 738 }
738 } 739 }
739 740
741 if (xen_hvm_domain()) {
742 char *type;
743 int len;
744 /* no unplug has been done: do not hook devices != xen vbds */
745 if (xen_platform_pci_unplug & XEN_UNPLUG_IGNORE) {
746 int major;
747
748 if (!VDEV_IS_EXTENDED(vdevice))
749 major = BLKIF_MAJOR(vdevice);
750 else
751 major = XENVBD_MAJOR;
752
753 if (major != XENVBD_MAJOR) {
754 printk(KERN_INFO
755 "%s: HVM does not support vbd %d as xen block device\n",
756 __FUNCTION__, vdevice);
757 return -ENODEV;
758 }
759 }
760 /* do not create a PV cdrom device if we are an HVM guest */
761 type = xenbus_read(XBT_NIL, dev->nodename, "device-type", &len);
762 if (IS_ERR(type))
763 return -ENODEV;
764 if (strncmp(type, "cdrom", 5) == 0) {
765 kfree(type);
766 return -ENODEV;
767 }
768 kfree(type);
769 }
740 info = kzalloc(sizeof(*info), GFP_KERNEL); 770 info = kzalloc(sizeof(*info), GFP_KERNEL);
741 if (!info) { 771 if (!info) {
742 xenbus_dev_fatal(dev, -ENOMEM, "allocating info structure"); 772 xenbus_dev_fatal(dev, -ENOMEM, "allocating info structure");
diff --git a/drivers/input/xen-kbdfront.c b/drivers/input/xen-kbdfront.c
index e14081675bb2..ebb11907d402 100644
--- a/drivers/input/xen-kbdfront.c
+++ b/drivers/input/xen-kbdfront.c
@@ -339,7 +339,7 @@ static struct xenbus_driver xenkbd_driver = {
339 339
340static int __init xenkbd_init(void) 340static int __init xenkbd_init(void)
341{ 341{
342 if (!xen_domain()) 342 if (!xen_pv_domain())
343 return -ENODEV; 343 return -ENODEV;
344 344
345 /* Nothing to do if running in dom0. */ 345 /* Nothing to do if running in dom0. */
diff --git a/drivers/video/xen-fbfront.c b/drivers/video/xen-fbfront.c
index fa97d3e7c21a..7c7f42a12796 100644
--- a/drivers/video/xen-fbfront.c
+++ b/drivers/video/xen-fbfront.c
@@ -684,7 +684,7 @@ static struct xenbus_driver xenfb_driver = {
684 684
685static int __init xenfb_init(void) 685static int __init xenfb_init(void)
686{ 686{
687 if (!xen_domain()) 687 if (!xen_pv_domain())
688 return -ENODEV; 688 return -ENODEV;
689 689
690 /* Nothing to do if running in dom0. */ 690 /* Nothing to do if running in dom0. */
diff --git a/drivers/xen/Kconfig b/drivers/xen/Kconfig
index fad3df2c1276..0a8826936639 100644
--- a/drivers/xen/Kconfig
+++ b/drivers/xen/Kconfig
@@ -62,4 +62,13 @@ config XEN_SYS_HYPERVISOR
62 virtual environment, /sys/hypervisor will still be present, 62 virtual environment, /sys/hypervisor will still be present,
63 but will have no xen contents. 63 but will have no xen contents.
64 64
65config XEN_PLATFORM_PCI
66 tristate "xen platform pci device driver"
67 depends on XEN_PVHVM
68 default m
69 help
70 Driver for the Xen PCI Platform device: it is responsible for
71 initializing xenbus and grant_table when running in a Xen HVM
72 domain. As a consequence this driver is required to run any Xen PV
73 frontend on Xen HVM.
65endmenu 74endmenu
diff --git a/drivers/xen/Makefile b/drivers/xen/Makefile
index 7c284342f30f..e392fb776af3 100644
--- a/drivers/xen/Makefile
+++ b/drivers/xen/Makefile
@@ -9,4 +9,5 @@ obj-$(CONFIG_XEN_XENCOMM) += xencomm.o
9obj-$(CONFIG_XEN_BALLOON) += balloon.o 9obj-$(CONFIG_XEN_BALLOON) += balloon.o
10obj-$(CONFIG_XEN_DEV_EVTCHN) += evtchn.o 10obj-$(CONFIG_XEN_DEV_EVTCHN) += evtchn.o
11obj-$(CONFIG_XENFS) += xenfs/ 11obj-$(CONFIG_XENFS) += xenfs/
12obj-$(CONFIG_XEN_SYS_HYPERVISOR) += sys-hypervisor.o \ No newline at end of file 12obj-$(CONFIG_XEN_SYS_HYPERVISOR) += sys-hypervisor.o
13obj-$(CONFIG_XEN_PLATFORM_PCI) += platform-pci.o
diff --git a/drivers/xen/events.c b/drivers/xen/events.c
index db8f506817f0..5e1f34892dcc 100644
--- a/drivers/xen/events.c
+++ b/drivers/xen/events.c
@@ -29,6 +29,7 @@
29#include <linux/bootmem.h> 29#include <linux/bootmem.h>
30#include <linux/slab.h> 30#include <linux/slab.h>
31 31
32#include <asm/desc.h>
32#include <asm/ptrace.h> 33#include <asm/ptrace.h>
33#include <asm/irq.h> 34#include <asm/irq.h>
34#include <asm/idle.h> 35#include <asm/idle.h>
@@ -36,10 +37,14 @@
36#include <asm/xen/hypercall.h> 37#include <asm/xen/hypercall.h>
37#include <asm/xen/hypervisor.h> 38#include <asm/xen/hypervisor.h>
38 39
40#include <xen/xen.h>
41#include <xen/hvm.h>
39#include <xen/xen-ops.h> 42#include <xen/xen-ops.h>
40#include <xen/events.h> 43#include <xen/events.h>
41#include <xen/interface/xen.h> 44#include <xen/interface/xen.h>
42#include <xen/interface/event_channel.h> 45#include <xen/interface/event_channel.h>
46#include <xen/interface/hvm/hvm_op.h>
47#include <xen/interface/hvm/params.h>
43 48
44/* 49/*
45 * This lock protects updates to the following mapping and reference-count 50 * This lock protects updates to the following mapping and reference-count
@@ -335,9 +340,18 @@ static int find_unbound_irq(void)
335 int irq; 340 int irq;
336 struct irq_desc *desc; 341 struct irq_desc *desc;
337 342
338 for (irq = 0; irq < nr_irqs; irq++) 343 for (irq = 0; irq < nr_irqs; irq++) {
344 desc = irq_to_desc(irq);
345 /* only 0->15 have init'd desc; handle irq > 16 */
346 if (desc == NULL)
347 break;
348 if (desc->chip == &no_irq_chip)
349 break;
350 if (desc->chip != &xen_dynamic_chip)
351 continue;
339 if (irq_info[irq].type == IRQT_UNBOUND) 352 if (irq_info[irq].type == IRQT_UNBOUND)
340 break; 353 break;
354 }
341 355
342 if (irq == nr_irqs) 356 if (irq == nr_irqs)
343 panic("No available IRQ to bind to: increase nr_irqs!\n"); 357 panic("No available IRQ to bind to: increase nr_irqs!\n");
@@ -346,7 +360,7 @@ static int find_unbound_irq(void)
346 if (WARN_ON(desc == NULL)) 360 if (WARN_ON(desc == NULL))
347 return -1; 361 return -1;
348 362
349 dynamic_irq_init(irq); 363 dynamic_irq_init_keep_chip_data(irq);
350 364
351 return irq; 365 return irq;
352} 366}
@@ -617,17 +631,13 @@ static DEFINE_PER_CPU(unsigned, xed_nesting_count);
617 * a bitset of words which contain pending event bits. The second 631 * a bitset of words which contain pending event bits. The second
618 * level is a bitset of pending events themselves. 632 * level is a bitset of pending events themselves.
619 */ 633 */
620void xen_evtchn_do_upcall(struct pt_regs *regs) 634static void __xen_evtchn_do_upcall(void)
621{ 635{
622 int cpu = get_cpu(); 636 int cpu = get_cpu();
623 struct pt_regs *old_regs = set_irq_regs(regs);
624 struct shared_info *s = HYPERVISOR_shared_info; 637 struct shared_info *s = HYPERVISOR_shared_info;
625 struct vcpu_info *vcpu_info = __get_cpu_var(xen_vcpu); 638 struct vcpu_info *vcpu_info = __get_cpu_var(xen_vcpu);
626 unsigned count; 639 unsigned count;
627 640
628 exit_idle();
629 irq_enter();
630
631 do { 641 do {
632 unsigned long pending_words; 642 unsigned long pending_words;
633 643
@@ -664,14 +674,31 @@ void xen_evtchn_do_upcall(struct pt_regs *regs)
664 674
665 count = __get_cpu_var(xed_nesting_count); 675 count = __get_cpu_var(xed_nesting_count);
666 __get_cpu_var(xed_nesting_count) = 0; 676 __get_cpu_var(xed_nesting_count) = 0;
667 } while(count != 1); 677 } while (count != 1 || vcpu_info->evtchn_upcall_pending);
668 678
669out: 679out:
680
681 put_cpu();
682}
683
684void xen_evtchn_do_upcall(struct pt_regs *regs)
685{
686 struct pt_regs *old_regs = set_irq_regs(regs);
687
688 exit_idle();
689 irq_enter();
690
691 __xen_evtchn_do_upcall();
692
670 irq_exit(); 693 irq_exit();
671 set_irq_regs(old_regs); 694 set_irq_regs(old_regs);
695}
672 696
673 put_cpu(); 697void xen_hvm_evtchn_do_upcall(void)
698{
699 __xen_evtchn_do_upcall();
674} 700}
701EXPORT_SYMBOL_GPL(xen_hvm_evtchn_do_upcall);
675 702
676/* Rebind a new event channel to an existing irq. */ 703/* Rebind a new event channel to an existing irq. */
677void rebind_evtchn_irq(int evtchn, int irq) 704void rebind_evtchn_irq(int evtchn, int irq)
@@ -708,7 +735,10 @@ static int rebind_irq_to_cpu(unsigned irq, unsigned tcpu)
708 struct evtchn_bind_vcpu bind_vcpu; 735 struct evtchn_bind_vcpu bind_vcpu;
709 int evtchn = evtchn_from_irq(irq); 736 int evtchn = evtchn_from_irq(irq);
710 737
711 if (!VALID_EVTCHN(evtchn)) 738 /* events delivered via platform PCI interrupts are always
739 * routed to vcpu 0 */
740 if (!VALID_EVTCHN(evtchn) ||
741 (xen_hvm_domain() && !xen_have_vector_callback))
712 return -1; 742 return -1;
713 743
714 /* Send future instances of this interrupt to other vcpu. */ 744 /* Send future instances of this interrupt to other vcpu. */
@@ -933,6 +963,44 @@ static struct irq_chip xen_dynamic_chip __read_mostly = {
933 .retrigger = retrigger_dynirq, 963 .retrigger = retrigger_dynirq,
934}; 964};
935 965
966int xen_set_callback_via(uint64_t via)
967{
968 struct xen_hvm_param a;
969 a.domid = DOMID_SELF;
970 a.index = HVM_PARAM_CALLBACK_IRQ;
971 a.value = via;
972 return HYPERVISOR_hvm_op(HVMOP_set_param, &a);
973}
974EXPORT_SYMBOL_GPL(xen_set_callback_via);
975
976#ifdef CONFIG_XEN_PVHVM
977/* Vector callbacks are better than PCI interrupts to receive event
978 * channel notifications because we can receive vector callbacks on any
979 * vcpu and we don't need PCI support or APIC interactions. */
980void xen_callback_vector(void)
981{
982 int rc;
983 uint64_t callback_via;
984 if (xen_have_vector_callback) {
985 callback_via = HVM_CALLBACK_VECTOR(XEN_HVM_EVTCHN_CALLBACK);
986 rc = xen_set_callback_via(callback_via);
987 if (rc) {
988 printk(KERN_ERR "Request for Xen HVM callback vector"
989 " failed.\n");
990 xen_have_vector_callback = 0;
991 return;
992 }
993 printk(KERN_INFO "Xen HVM callback vector for event delivery is "
994 "enabled\n");
995 /* in the restore case the vector has already been allocated */
996 if (!test_bit(XEN_HVM_EVTCHN_CALLBACK, used_vectors))
997 alloc_intr_gate(XEN_HVM_EVTCHN_CALLBACK, xen_hvm_callback_vector);
998 }
999}
1000#else
1001void xen_callback_vector(void) {}
1002#endif
1003
936void __init xen_init_IRQ(void) 1004void __init xen_init_IRQ(void)
937{ 1005{
938 int i; 1006 int i;
@@ -947,5 +1015,10 @@ void __init xen_init_IRQ(void)
947 for (i = 0; i < NR_EVENT_CHANNELS; i++) 1015 for (i = 0; i < NR_EVENT_CHANNELS; i++)
948 mask_evtchn(i); 1016 mask_evtchn(i);
949 1017
950 irq_ctx_init(smp_processor_id()); 1018 if (xen_hvm_domain()) {
1019 xen_callback_vector();
1020 native_init_IRQ();
1021 } else {
1022 irq_ctx_init(smp_processor_id());
1023 }
951} 1024}
diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c
index f66db3b91d61..6c4531816496 100644
--- a/drivers/xen/grant-table.c
+++ b/drivers/xen/grant-table.c
@@ -37,11 +37,13 @@
37#include <linux/slab.h> 37#include <linux/slab.h>
38#include <linux/vmalloc.h> 38#include <linux/vmalloc.h>
39#include <linux/uaccess.h> 39#include <linux/uaccess.h>
40#include <linux/io.h>
40 41
41#include <xen/xen.h> 42#include <xen/xen.h>
42#include <xen/interface/xen.h> 43#include <xen/interface/xen.h>
43#include <xen/page.h> 44#include <xen/page.h>
44#include <xen/grant_table.h> 45#include <xen/grant_table.h>
46#include <xen/interface/memory.h>
45#include <asm/xen/hypercall.h> 47#include <asm/xen/hypercall.h>
46 48
47#include <asm/pgtable.h> 49#include <asm/pgtable.h>
@@ -59,6 +61,8 @@ static unsigned int boot_max_nr_grant_frames;
59static int gnttab_free_count; 61static int gnttab_free_count;
60static grant_ref_t gnttab_free_head; 62static grant_ref_t gnttab_free_head;
61static DEFINE_SPINLOCK(gnttab_list_lock); 63static DEFINE_SPINLOCK(gnttab_list_lock);
64unsigned long xen_hvm_resume_frames;
65EXPORT_SYMBOL_GPL(xen_hvm_resume_frames);
62 66
63static struct grant_entry *shared; 67static struct grant_entry *shared;
64 68
@@ -433,7 +437,7 @@ static unsigned int __max_nr_grant_frames(void)
433 return query.max_nr_frames; 437 return query.max_nr_frames;
434} 438}
435 439
436static inline unsigned int max_nr_grant_frames(void) 440unsigned int gnttab_max_grant_frames(void)
437{ 441{
438 unsigned int xen_max = __max_nr_grant_frames(); 442 unsigned int xen_max = __max_nr_grant_frames();
439 443
@@ -441,6 +445,7 @@ static inline unsigned int max_nr_grant_frames(void)
441 return boot_max_nr_grant_frames; 445 return boot_max_nr_grant_frames;
442 return xen_max; 446 return xen_max;
443} 447}
448EXPORT_SYMBOL_GPL(gnttab_max_grant_frames);
444 449
445static int gnttab_map(unsigned int start_idx, unsigned int end_idx) 450static int gnttab_map(unsigned int start_idx, unsigned int end_idx)
446{ 451{
@@ -449,6 +454,30 @@ static int gnttab_map(unsigned int start_idx, unsigned int end_idx)
449 unsigned int nr_gframes = end_idx + 1; 454 unsigned int nr_gframes = end_idx + 1;
450 int rc; 455 int rc;
451 456
457 if (xen_hvm_domain()) {
458 struct xen_add_to_physmap xatp;
459 unsigned int i = end_idx;
460 rc = 0;
461 /*
462 * Loop backwards, so that the first hypercall has the largest
463 * index, ensuring that the table will grow only once.
464 */
465 do {
466 xatp.domid = DOMID_SELF;
467 xatp.idx = i;
468 xatp.space = XENMAPSPACE_grant_table;
469 xatp.gpfn = (xen_hvm_resume_frames >> PAGE_SHIFT) + i;
470 rc = HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp);
471 if (rc != 0) {
472 printk(KERN_WARNING
473 "grant table add_to_physmap failed, err=%d\n", rc);
474 break;
475 }
476 } while (i-- > start_idx);
477
478 return rc;
479 }
480
452 frames = kmalloc(nr_gframes * sizeof(unsigned long), GFP_ATOMIC); 481 frames = kmalloc(nr_gframes * sizeof(unsigned long), GFP_ATOMIC);
453 if (!frames) 482 if (!frames)
454 return -ENOMEM; 483 return -ENOMEM;
@@ -465,7 +494,7 @@ static int gnttab_map(unsigned int start_idx, unsigned int end_idx)
465 494
466 BUG_ON(rc || setup.status); 495 BUG_ON(rc || setup.status);
467 496
468 rc = arch_gnttab_map_shared(frames, nr_gframes, max_nr_grant_frames(), 497 rc = arch_gnttab_map_shared(frames, nr_gframes, gnttab_max_grant_frames(),
469 &shared); 498 &shared);
470 BUG_ON(rc); 499 BUG_ON(rc);
471 500
@@ -476,9 +505,27 @@ static int gnttab_map(unsigned int start_idx, unsigned int end_idx)
476 505
477int gnttab_resume(void) 506int gnttab_resume(void)
478{ 507{
479 if (max_nr_grant_frames() < nr_grant_frames) 508 unsigned int max_nr_gframes;
509
510 max_nr_gframes = gnttab_max_grant_frames();
511 if (max_nr_gframes < nr_grant_frames)
480 return -ENOSYS; 512 return -ENOSYS;
481 return gnttab_map(0, nr_grant_frames - 1); 513
514 if (xen_pv_domain())
515 return gnttab_map(0, nr_grant_frames - 1);
516
517 if (!shared) {
518 shared = ioremap(xen_hvm_resume_frames, PAGE_SIZE * max_nr_gframes);
519 if (shared == NULL) {
520 printk(KERN_WARNING
521 "Failed to ioremap gnttab share frames!");
522 return -ENOMEM;
523 }
524 }
525
526 gnttab_map(0, nr_grant_frames - 1);
527
528 return 0;
482} 529}
483 530
484int gnttab_suspend(void) 531int gnttab_suspend(void)
@@ -495,7 +542,7 @@ static int gnttab_expand(unsigned int req_entries)
495 cur = nr_grant_frames; 542 cur = nr_grant_frames;
496 extra = ((req_entries + (GREFS_PER_GRANT_FRAME-1)) / 543 extra = ((req_entries + (GREFS_PER_GRANT_FRAME-1)) /
497 GREFS_PER_GRANT_FRAME); 544 GREFS_PER_GRANT_FRAME);
498 if (cur + extra > max_nr_grant_frames()) 545 if (cur + extra > gnttab_max_grant_frames())
499 return -ENOSPC; 546 return -ENOSPC;
500 547
501 rc = gnttab_map(cur, cur + extra - 1); 548 rc = gnttab_map(cur, cur + extra - 1);
@@ -505,15 +552,12 @@ static int gnttab_expand(unsigned int req_entries)
505 return rc; 552 return rc;
506} 553}
507 554
508static int __devinit gnttab_init(void) 555int gnttab_init(void)
509{ 556{
510 int i; 557 int i;
511 unsigned int max_nr_glist_frames, nr_glist_frames; 558 unsigned int max_nr_glist_frames, nr_glist_frames;
512 unsigned int nr_init_grefs; 559 unsigned int nr_init_grefs;
513 560
514 if (!xen_domain())
515 return -ENODEV;
516
517 nr_grant_frames = 1; 561 nr_grant_frames = 1;
518 boot_max_nr_grant_frames = __max_nr_grant_frames(); 562 boot_max_nr_grant_frames = __max_nr_grant_frames();
519 563
@@ -556,5 +600,18 @@ static int __devinit gnttab_init(void)
556 kfree(gnttab_list); 600 kfree(gnttab_list);
557 return -ENOMEM; 601 return -ENOMEM;
558} 602}
603EXPORT_SYMBOL_GPL(gnttab_init);
604
605static int __devinit __gnttab_init(void)
606{
607 /* Delay grant-table initialization in the PV on HVM case */
608 if (xen_hvm_domain())
609 return 0;
610
611 if (!xen_pv_domain())
612 return -ENODEV;
613
614 return gnttab_init();
615}
559 616
560core_initcall(gnttab_init); 617core_initcall(__gnttab_init);
diff --git a/drivers/xen/manage.c b/drivers/xen/manage.c
index 07e857b0de13..1799bd890315 100644
--- a/drivers/xen/manage.c
+++ b/drivers/xen/manage.c
@@ -9,6 +9,7 @@
9#include <linux/stop_machine.h> 9#include <linux/stop_machine.h>
10#include <linux/freezer.h> 10#include <linux/freezer.h>
11 11
12#include <xen/xen.h>
12#include <xen/xenbus.h> 13#include <xen/xenbus.h>
13#include <xen/grant_table.h> 14#include <xen/grant_table.h>
14#include <xen/events.h> 15#include <xen/events.h>
@@ -17,6 +18,7 @@
17 18
18#include <asm/xen/hypercall.h> 19#include <asm/xen/hypercall.h>
19#include <asm/xen/page.h> 20#include <asm/xen/page.h>
21#include <asm/xen/hypervisor.h>
20 22
21enum shutdown_state { 23enum shutdown_state {
22 SHUTDOWN_INVALID = -1, 24 SHUTDOWN_INVALID = -1,
@@ -33,10 +35,30 @@ enum shutdown_state {
33static enum shutdown_state shutting_down = SHUTDOWN_INVALID; 35static enum shutdown_state shutting_down = SHUTDOWN_INVALID;
34 36
35#ifdef CONFIG_PM_SLEEP 37#ifdef CONFIG_PM_SLEEP
36static int xen_suspend(void *data) 38static int xen_hvm_suspend(void *data)
37{ 39{
40 struct sched_shutdown r = { .reason = SHUTDOWN_suspend };
38 int *cancelled = data; 41 int *cancelled = data;
42
43 BUG_ON(!irqs_disabled());
44
45 *cancelled = HYPERVISOR_sched_op(SCHEDOP_shutdown, &r);
46
47 xen_hvm_post_suspend(*cancelled);
48 gnttab_resume();
49
50 if (!*cancelled) {
51 xen_irq_resume();
52 xen_timer_resume();
53 }
54
55 return 0;
56}
57
58static int xen_suspend(void *data)
59{
39 int err; 60 int err;
61 int *cancelled = data;
40 62
41 BUG_ON(!irqs_disabled()); 63 BUG_ON(!irqs_disabled());
42 64
@@ -106,7 +128,10 @@ static void do_suspend(void)
106 goto out_resume; 128 goto out_resume;
107 } 129 }
108 130
109 err = stop_machine(xen_suspend, &cancelled, cpumask_of(0)); 131 if (xen_hvm_domain())
132 err = stop_machine(xen_hvm_suspend, &cancelled, cpumask_of(0));
133 else
134 err = stop_machine(xen_suspend, &cancelled, cpumask_of(0));
110 135
111 dpm_resume_noirq(PMSG_RESUME); 136 dpm_resume_noirq(PMSG_RESUME);
112 137
@@ -255,7 +280,19 @@ static int shutdown_event(struct notifier_block *notifier,
255 return NOTIFY_DONE; 280 return NOTIFY_DONE;
256} 281}
257 282
258static int __init setup_shutdown_event(void) 283static int __init __setup_shutdown_event(void)
284{
285 /* Delay initialization in the PV on HVM case */
286 if (xen_hvm_domain())
287 return 0;
288
289 if (!xen_pv_domain())
290 return -ENODEV;
291
292 return xen_setup_shutdown_event();
293}
294
295int xen_setup_shutdown_event(void)
259{ 296{
260 static struct notifier_block xenstore_notifier = { 297 static struct notifier_block xenstore_notifier = {
261 .notifier_call = shutdown_event 298 .notifier_call = shutdown_event
@@ -264,5 +301,6 @@ static int __init setup_shutdown_event(void)
264 301
265 return 0; 302 return 0;
266} 303}
304EXPORT_SYMBOL_GPL(xen_setup_shutdown_event);
267 305
268subsys_initcall(setup_shutdown_event); 306subsys_initcall(__setup_shutdown_event);
diff --git a/drivers/xen/platform-pci.c b/drivers/xen/platform-pci.c
new file mode 100644
index 000000000000..c01b5ddce529
--- /dev/null
+++ b/drivers/xen/platform-pci.c
@@ -0,0 +1,207 @@
1/******************************************************************************
2 * platform-pci.c
3 *
4 * Xen platform PCI device driver
5 * Copyright (c) 2005, Intel Corporation.
6 * Copyright (c) 2007, XenSource Inc.
7 * Copyright (c) 2010, Citrix
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms and conditions of the GNU General Public License,
11 * version 2, as published by the Free Software Foundation.
12 *
13 * This program is distributed in the hope it will be useful, but WITHOUT
14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 * more details.
17 *
18 * You should have received a copy of the GNU General Public License along with
19 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
20 * Place - Suite 330, Boston, MA 02111-1307 USA.
21 *
22 */
23
24
25#include <linux/interrupt.h>
26#include <linux/io.h>
27#include <linux/module.h>
28#include <linux/pci.h>
29
30#include <xen/platform_pci.h>
31#include <xen/grant_table.h>
32#include <xen/xenbus.h>
33#include <xen/events.h>
34#include <xen/hvm.h>
35#include <xen/xen-ops.h>
36
37#define DRV_NAME "xen-platform-pci"
38
39MODULE_AUTHOR("ssmith@xensource.com and stefano.stabellini@eu.citrix.com");
40MODULE_DESCRIPTION("Xen platform PCI device");
41MODULE_LICENSE("GPL");
42
43static unsigned long platform_mmio;
44static unsigned long platform_mmio_alloc;
45static unsigned long platform_mmiolen;
46static uint64_t callback_via;
47
48unsigned long alloc_xen_mmio(unsigned long len)
49{
50 unsigned long addr;
51
52 addr = platform_mmio + platform_mmio_alloc;
53 platform_mmio_alloc += len;
54 BUG_ON(platform_mmio_alloc > platform_mmiolen);
55
56 return addr;
57}
58
59static uint64_t get_callback_via(struct pci_dev *pdev)
60{
61 u8 pin;
62 int irq;
63
64 irq = pdev->irq;
65 if (irq < 16)
66 return irq; /* ISA IRQ */
67
68 pin = pdev->pin;
69
70 /* We don't know the GSI. Specify the PCI INTx line instead. */
71 return ((uint64_t)0x01 << 56) | /* PCI INTx identifier */
72 ((uint64_t)pci_domain_nr(pdev->bus) << 32) |
73 ((uint64_t)pdev->bus->number << 16) |
74 ((uint64_t)(pdev->devfn & 0xff) << 8) |
75 ((uint64_t)(pin - 1) & 3);
76}
77
78static irqreturn_t do_hvm_evtchn_intr(int irq, void *dev_id)
79{
80 xen_hvm_evtchn_do_upcall();
81 return IRQ_HANDLED;
82}
83
84static int xen_allocate_irq(struct pci_dev *pdev)
85{
86 return request_irq(pdev->irq, do_hvm_evtchn_intr,
87 IRQF_DISABLED | IRQF_NOBALANCING | IRQF_TRIGGER_RISING,
88 "xen-platform-pci", pdev);
89}
90
91static int platform_pci_resume(struct pci_dev *pdev)
92{
93 int err;
94 if (xen_have_vector_callback)
95 return 0;
96 err = xen_set_callback_via(callback_via);
97 if (err) {
98 dev_err(&pdev->dev, "platform_pci_resume failure!\n");
99 return err;
100 }
101 return 0;
102}
103
104static int __devinit platform_pci_init(struct pci_dev *pdev,
105 const struct pci_device_id *ent)
106{
107 int i, ret;
108 long ioaddr, iolen;
109 long mmio_addr, mmio_len;
110 unsigned int max_nr_gframes;
111
112 i = pci_enable_device(pdev);
113 if (i)
114 return i;
115
116 ioaddr = pci_resource_start(pdev, 0);
117 iolen = pci_resource_len(pdev, 0);
118
119 mmio_addr = pci_resource_start(pdev, 1);
120 mmio_len = pci_resource_len(pdev, 1);
121
122 if (mmio_addr == 0 || ioaddr == 0) {
123 dev_err(&pdev->dev, "no resources found\n");
124 ret = -ENOENT;
125 goto pci_out;
126 }
127
128 if (request_mem_region(mmio_addr, mmio_len, DRV_NAME) == NULL) {
129 dev_err(&pdev->dev, "MEM I/O resource 0x%lx @ 0x%lx busy\n",
130 mmio_addr, mmio_len);
131 ret = -EBUSY;
132 goto pci_out;
133 }
134
135 if (request_region(ioaddr, iolen, DRV_NAME) == NULL) {
136 dev_err(&pdev->dev, "I/O resource 0x%lx @ 0x%lx busy\n",
137 iolen, ioaddr);
138 ret = -EBUSY;
139 goto mem_out;
140 }
141
142 platform_mmio = mmio_addr;
143 platform_mmiolen = mmio_len;
144
145 if (!xen_have_vector_callback) {
146 ret = xen_allocate_irq(pdev);
147 if (ret) {
148 dev_warn(&pdev->dev, "request_irq failed err=%d\n", ret);
149 goto out;
150 }
151 callback_via = get_callback_via(pdev);
152 ret = xen_set_callback_via(callback_via);
153 if (ret) {
154 dev_warn(&pdev->dev, "Unable to set the evtchn callback "
155 "err=%d\n", ret);
156 goto out;
157 }
158 }
159
160 max_nr_gframes = gnttab_max_grant_frames();
161 xen_hvm_resume_frames = alloc_xen_mmio(PAGE_SIZE * max_nr_gframes);
162 ret = gnttab_init();
163 if (ret)
164 goto out;
165 xenbus_probe(NULL);
166 ret = xen_setup_shutdown_event();
167 if (ret)
168 goto out;
169 return 0;
170
171out:
172 release_region(ioaddr, iolen);
173mem_out:
174 release_mem_region(mmio_addr, mmio_len);
175pci_out:
176 pci_disable_device(pdev);
177 return ret;
178}
179
180static struct pci_device_id platform_pci_tbl[] __devinitdata = {
181 {PCI_VENDOR_ID_XEN, PCI_DEVICE_ID_XEN_PLATFORM,
182 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
183 {0,}
184};
185
186MODULE_DEVICE_TABLE(pci, platform_pci_tbl);
187
188static struct pci_driver platform_driver = {
189 .name = DRV_NAME,
190 .probe = platform_pci_init,
191 .id_table = platform_pci_tbl,
192#ifdef CONFIG_PM
193 .resume_early = platform_pci_resume,
194#endif
195};
196
197static int __init platform_pci_module_init(void)
198{
199 /* no unplug has been done, IGNORE hasn't been specified: just
200 * return now */
201 if (!xen_platform_pci_unplug)
202 return -ENODEV;
203
204 return pci_register_driver(&platform_driver);
205}
206
207module_init(platform_pci_module_init);
diff --git a/drivers/xen/xenbus/xenbus_probe.c b/drivers/xen/xenbus/xenbus_probe.c
index abc12426ef0a..29bac5118877 100644
--- a/drivers/xen/xenbus/xenbus_probe.c
+++ b/drivers/xen/xenbus/xenbus_probe.c
@@ -56,6 +56,9 @@
56#include <xen/events.h> 56#include <xen/events.h>
57#include <xen/page.h> 57#include <xen/page.h>
58 58
59#include <xen/platform_pci.h>
60#include <xen/hvm.h>
61
59#include "xenbus_comms.h" 62#include "xenbus_comms.h"
60#include "xenbus_probe.h" 63#include "xenbus_probe.h"
61 64
@@ -776,8 +779,23 @@ void xenbus_probe(struct work_struct *unused)
776 /* Notify others that xenstore is up */ 779 /* Notify others that xenstore is up */
777 blocking_notifier_call_chain(&xenstore_chain, 0, NULL); 780 blocking_notifier_call_chain(&xenstore_chain, 0, NULL);
778} 781}
782EXPORT_SYMBOL_GPL(xenbus_probe);
779 783
780static int __init xenbus_probe_init(void) 784static int __init xenbus_probe_initcall(void)
785{
786 if (!xen_domain())
787 return -ENODEV;
788
789 if (xen_initial_domain() || xen_hvm_domain())
790 return 0;
791
792 xenbus_probe(NULL);
793 return 0;
794}
795
796device_initcall(xenbus_probe_initcall);
797
798static int __init xenbus_init(void)
781{ 799{
782 int err = 0; 800 int err = 0;
783 801
@@ -802,11 +820,24 @@ static int __init xenbus_probe_init(void)
802 if (xen_initial_domain()) { 820 if (xen_initial_domain()) {
803 /* dom0 not yet supported */ 821 /* dom0 not yet supported */
804 } else { 822 } else {
823 if (xen_hvm_domain()) {
824 uint64_t v = 0;
825 err = hvm_get_parameter(HVM_PARAM_STORE_EVTCHN, &v);
826 if (err)
827 goto out_error;
828 xen_store_evtchn = (int)v;
829 err = hvm_get_parameter(HVM_PARAM_STORE_PFN, &v);
830 if (err)
831 goto out_error;
832 xen_store_mfn = (unsigned long)v;
833 xen_store_interface = ioremap(xen_store_mfn << PAGE_SHIFT, PAGE_SIZE);
834 } else {
835 xen_store_evtchn = xen_start_info->store_evtchn;
836 xen_store_mfn = xen_start_info->store_mfn;
837 xen_store_interface = mfn_to_virt(xen_store_mfn);
838 }
805 xenstored_ready = 1; 839 xenstored_ready = 1;
806 xen_store_evtchn = xen_start_info->store_evtchn;
807 xen_store_mfn = xen_start_info->store_mfn;
808 } 840 }
809 xen_store_interface = mfn_to_virt(xen_store_mfn);
810 841
811 /* Initialize the interface to xenstore. */ 842 /* Initialize the interface to xenstore. */
812 err = xs_init(); 843 err = xs_init();
@@ -816,9 +847,6 @@ static int __init xenbus_probe_init(void)
816 goto out_unreg_back; 847 goto out_unreg_back;
817 } 848 }
818 849
819 if (!xen_initial_domain())
820 xenbus_probe(NULL);
821
822#ifdef CONFIG_XEN_COMPAT_XENFS 850#ifdef CONFIG_XEN_COMPAT_XENFS
823 /* 851 /*
824 * Create xenfs mountpoint in /proc for compatibility with 852 * Create xenfs mountpoint in /proc for compatibility with
@@ -839,7 +867,7 @@ static int __init xenbus_probe_init(void)
839 return err; 867 return err;
840} 868}
841 869
842postcore_initcall(xenbus_probe_init); 870postcore_initcall(xenbus_init);
843 871
844MODULE_LICENSE("GPL"); 872MODULE_LICENSE("GPL");
845 873
@@ -947,6 +975,9 @@ static void wait_for_devices(struct xenbus_driver *xendrv)
947#ifndef MODULE 975#ifndef MODULE
948static int __init boot_wait_for_devices(void) 976static int __init boot_wait_for_devices(void)
949{ 977{
978 if (xen_hvm_domain() && !xen_platform_pci_unplug)
979 return -ENODEV;
980
950 ready_to_wait_for_devices = 1; 981 ready_to_wait_for_devices = 1;
951 wait_for_devices(NULL); 982 wait_for_devices(NULL);
952 return 0; 983 return 0;
diff --git a/drivers/xen/xenfs/super.c b/drivers/xen/xenfs/super.c
index 8924d93136f1..78bfab0700ba 100644
--- a/drivers/xen/xenfs/super.c
+++ b/drivers/xen/xenfs/super.c
@@ -65,7 +65,7 @@ static struct file_system_type xenfs_type = {
65 65
66static int __init xenfs_init(void) 66static int __init xenfs_init(void)
67{ 67{
68 if (xen_pv_domain()) 68 if (xen_domain())
69 return register_filesystem(&xenfs_type); 69 return register_filesystem(&xenfs_type);
70 70
71 printk(KERN_INFO "XENFS: not registering filesystem on non-xen platform\n"); 71 printk(KERN_INFO "XENFS: not registering filesystem on non-xen platform\n");
@@ -74,7 +74,7 @@ static int __init xenfs_init(void)
74 74
75static void __exit xenfs_exit(void) 75static void __exit xenfs_exit(void)
76{ 76{
77 if (xen_pv_domain()) 77 if (xen_domain())
78 unregister_filesystem(&xenfs_type); 78 unregister_filesystem(&xenfs_type);
79} 79}
80 80
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 030a954ed292..4e7ae6002056 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -653,6 +653,7 @@
653 EXIT_DATA \ 653 EXIT_DATA \
654 EXIT_CALL \ 654 EXIT_CALL \
655 *(.discard) \ 655 *(.discard) \
656 *(.discard.*) \
656 } 657 }
657 658
658/** 659/**
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index 3bedcc149c84..cca2526f28d7 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -2772,3 +2772,6 @@
2772#define PCI_DEVICE_ID_RME_DIGI32 0x9896 2772#define PCI_DEVICE_ID_RME_DIGI32 0x9896
2773#define PCI_DEVICE_ID_RME_DIGI32_PRO 0x9897 2773#define PCI_DEVICE_ID_RME_DIGI32_PRO 0x9897
2774#define PCI_DEVICE_ID_RME_DIGI32_8 0x9898 2774#define PCI_DEVICE_ID_RME_DIGI32_8 0x9898
2775
2776#define PCI_VENDOR_ID_XEN 0x5853
2777#define PCI_DEVICE_ID_XEN_PLATFORM 0x0001
diff --git a/include/xen/events.h b/include/xen/events.h
index e68d59a90ca8..a15d93262e30 100644
--- a/include/xen/events.h
+++ b/include/xen/events.h
@@ -56,4 +56,11 @@ void xen_poll_irq(int irq);
56/* Determine the IRQ which is bound to an event channel */ 56/* Determine the IRQ which is bound to an event channel */
57unsigned irq_from_evtchn(unsigned int evtchn); 57unsigned irq_from_evtchn(unsigned int evtchn);
58 58
59/* Xen HVM evtchn vector callback */
60extern void xen_hvm_callback_vector(void);
61extern int xen_have_vector_callback;
62int xen_set_callback_via(uint64_t via);
63void xen_evtchn_do_upcall(struct pt_regs *regs);
64void xen_hvm_evtchn_do_upcall(void);
65
59#endif /* _XEN_EVENTS_H */ 66#endif /* _XEN_EVENTS_H */
diff --git a/include/xen/grant_table.h b/include/xen/grant_table.h
index a40f1cd91be1..9a731706a016 100644
--- a/include/xen/grant_table.h
+++ b/include/xen/grant_table.h
@@ -51,6 +51,7 @@ struct gnttab_free_callback {
51 u16 count; 51 u16 count;
52}; 52};
53 53
54int gnttab_init(void);
54int gnttab_suspend(void); 55int gnttab_suspend(void);
55int gnttab_resume(void); 56int gnttab_resume(void);
56 57
@@ -112,6 +113,9 @@ int arch_gnttab_map_shared(unsigned long *frames, unsigned long nr_gframes,
112void arch_gnttab_unmap_shared(struct grant_entry *shared, 113void arch_gnttab_unmap_shared(struct grant_entry *shared,
113 unsigned long nr_gframes); 114 unsigned long nr_gframes);
114 115
116extern unsigned long xen_hvm_resume_frames;
117unsigned int gnttab_max_grant_frames(void);
118
115#define gnttab_map_vaddr(map) ((void *)(map.host_virt_addr)) 119#define gnttab_map_vaddr(map) ((void *)(map.host_virt_addr))
116 120
117#endif /* __ASM_GNTTAB_H__ */ 121#endif /* __ASM_GNTTAB_H__ */
diff --git a/include/xen/hvm.h b/include/xen/hvm.h
new file mode 100644
index 000000000000..b193fa2f9fdd
--- /dev/null
+++ b/include/xen/hvm.h
@@ -0,0 +1,30 @@
1/* Simple wrappers around HVM functions */
2#ifndef XEN_HVM_H__
3#define XEN_HVM_H__
4
5#include <xen/interface/hvm/params.h>
6#include <asm/xen/hypercall.h>
7
8static inline int hvm_get_parameter(int idx, uint64_t *value)
9{
10 struct xen_hvm_param xhv;
11 int r;
12
13 xhv.domid = DOMID_SELF;
14 xhv.index = idx;
15 r = HYPERVISOR_hvm_op(HVMOP_get_param, &xhv);
16 if (r < 0) {
17 printk(KERN_ERR "Cannot get hvm parameter %d: %d!\n",
18 idx, r);
19 return r;
20 }
21 *value = xhv.value;
22 return r;
23}
24
25#define HVM_CALLBACK_VIA_TYPE_VECTOR 0x2
26#define HVM_CALLBACK_VIA_TYPE_SHIFT 56
27#define HVM_CALLBACK_VECTOR(x) (((uint64_t)HVM_CALLBACK_VIA_TYPE_VECTOR)<<\
28 HVM_CALLBACK_VIA_TYPE_SHIFT | (x))
29
30#endif /* XEN_HVM_H__ */
diff --git a/include/xen/interface/features.h b/include/xen/interface/features.h
index f51b6413b054..70d2563ab166 100644
--- a/include/xen/interface/features.h
+++ b/include/xen/interface/features.h
@@ -41,6 +41,12 @@
41/* x86: Does this Xen host support the MMU_PT_UPDATE_PRESERVE_AD hypercall? */ 41/* x86: Does this Xen host support the MMU_PT_UPDATE_PRESERVE_AD hypercall? */
42#define XENFEAT_mmu_pt_update_preserve_ad 5 42#define XENFEAT_mmu_pt_update_preserve_ad 5
43 43
44/* x86: Does this Xen host support the HVM callback vector type? */
45#define XENFEAT_hvm_callback_vector 8
46
47/* x86: pvclock algorithm is safe to use on HVM */
48#define XENFEAT_hvm_safe_pvclock 9
49
44#define XENFEAT_NR_SUBMAPS 1 50#define XENFEAT_NR_SUBMAPS 1
45 51
46#endif /* __XEN_PUBLIC_FEATURES_H__ */ 52#endif /* __XEN_PUBLIC_FEATURES_H__ */
diff --git a/include/xen/interface/grant_table.h b/include/xen/interface/grant_table.h
index 39da93c21de0..39e571796e32 100644
--- a/include/xen/interface/grant_table.h
+++ b/include/xen/interface/grant_table.h
@@ -28,6 +28,7 @@
28#ifndef __XEN_PUBLIC_GRANT_TABLE_H__ 28#ifndef __XEN_PUBLIC_GRANT_TABLE_H__
29#define __XEN_PUBLIC_GRANT_TABLE_H__ 29#define __XEN_PUBLIC_GRANT_TABLE_H__
30 30
31#include <xen/interface/xen.h>
31 32
32/*********************************** 33/***********************************
33 * GRANT TABLE REPRESENTATION 34 * GRANT TABLE REPRESENTATION
diff --git a/include/xen/interface/hvm/hvm_op.h b/include/xen/interface/hvm/hvm_op.h
new file mode 100644
index 000000000000..a4827f46ee97
--- /dev/null
+++ b/include/xen/interface/hvm/hvm_op.h
@@ -0,0 +1,46 @@
1/*
2 * Permission is hereby granted, free of charge, to any person obtaining a copy
3 * of this software and associated documentation files (the "Software"), to
4 * deal in the Software without restriction, including without limitation the
5 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
6 * sell copies of the Software, and to permit persons to whom the Software is
7 * furnished to do so, subject to the following conditions:
8 *
9 * The above copyright notice and this permission notice shall be included in
10 * all copies or substantial portions of the Software.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
13 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
14 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
15 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
16 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
17 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
18 * DEALINGS IN THE SOFTWARE.
19 */
20
21#ifndef __XEN_PUBLIC_HVM_HVM_OP_H__
22#define __XEN_PUBLIC_HVM_HVM_OP_H__
23
24/* Get/set subcommands: the second argument of the hypercall is a
25 * pointer to a xen_hvm_param struct. */
26#define HVMOP_set_param 0
27#define HVMOP_get_param 1
28struct xen_hvm_param {
29 domid_t domid; /* IN */
30 uint32_t index; /* IN */
31 uint64_t value; /* IN/OUT */
32};
33DEFINE_GUEST_HANDLE_STRUCT(xen_hvm_param);
34
35/* Hint from PV drivers for pagetable destruction. */
36#define HVMOP_pagetable_dying 9
37struct xen_hvm_pagetable_dying {
38 /* Domain with a pagetable about to be destroyed. */
39 domid_t domid;
40 /* guest physical address of the toplevel pagetable dying */
41 aligned_u64 gpa;
42};
43typedef struct xen_hvm_pagetable_dying xen_hvm_pagetable_dying_t;
44DEFINE_GUEST_HANDLE_STRUCT(xen_hvm_pagetable_dying_t);
45
46#endif /* __XEN_PUBLIC_HVM_HVM_OP_H__ */
diff --git a/include/xen/interface/hvm/params.h b/include/xen/interface/hvm/params.h
new file mode 100644
index 000000000000..1888d8c157e6
--- /dev/null
+++ b/include/xen/interface/hvm/params.h
@@ -0,0 +1,95 @@
1/*
2 * Permission is hereby granted, free of charge, to any person obtaining a copy
3 * of this software and associated documentation files (the "Software"), to
4 * deal in the Software without restriction, including without limitation the
5 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
6 * sell copies of the Software, and to permit persons to whom the Software is
7 * furnished to do so, subject to the following conditions:
8 *
9 * The above copyright notice and this permission notice shall be included in
10 * all copies or substantial portions of the Software.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
13 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
14 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
15 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
16 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
17 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
18 * DEALINGS IN THE SOFTWARE.
19 */
20
21#ifndef __XEN_PUBLIC_HVM_PARAMS_H__
22#define __XEN_PUBLIC_HVM_PARAMS_H__
23
24#include "hvm_op.h"
25
26/*
27 * Parameter space for HVMOP_{set,get}_param.
28 */
29
30/*
31 * How should CPU0 event-channel notifications be delivered?
32 * val[63:56] == 0: val[55:0] is a delivery GSI (Global System Interrupt).
33 * val[63:56] == 1: val[55:0] is a delivery PCI INTx line, as follows:
34 * Domain = val[47:32], Bus = val[31:16],
35 * DevFn = val[15: 8], IntX = val[ 1: 0]
36 * val[63:56] == 2: val[7:0] is a vector number.
37 * If val == 0 then CPU0 event-channel notifications are not delivered.
38 */
39#define HVM_PARAM_CALLBACK_IRQ 0
40
41#define HVM_PARAM_STORE_PFN 1
42#define HVM_PARAM_STORE_EVTCHN 2
43
44#define HVM_PARAM_PAE_ENABLED 4
45
46#define HVM_PARAM_IOREQ_PFN 5
47
48#define HVM_PARAM_BUFIOREQ_PFN 6
49
50/*
51 * Set mode for virtual timers (currently x86 only):
52 * delay_for_missed_ticks (default):
53 * Do not advance a vcpu's time beyond the correct delivery time for
54 * interrupts that have been missed due to preemption. Deliver missed
55 * interrupts when the vcpu is rescheduled and advance the vcpu's virtual
56 * time stepwise for each one.
57 * no_delay_for_missed_ticks:
58 * As above, missed interrupts are delivered, but guest time always tracks
59 * wallclock (i.e., real) time while doing so.
60 * no_missed_ticks_pending:
61 * No missed interrupts are held pending. Instead, to ensure ticks are
62 * delivered at some non-zero rate, if we detect missed ticks then the
63 * internal tick alarm is not disabled if the VCPU is preempted during the
64 * next tick period.
65 * one_missed_tick_pending:
66 * Missed interrupts are collapsed together and delivered as one 'late tick'.
67 * Guest time always tracks wallclock (i.e., real) time.
68 */
69#define HVM_PARAM_TIMER_MODE 10
70#define HVMPTM_delay_for_missed_ticks 0
71#define HVMPTM_no_delay_for_missed_ticks 1
72#define HVMPTM_no_missed_ticks_pending 2
73#define HVMPTM_one_missed_tick_pending 3
74
75/* Boolean: Enable virtual HPET (high-precision event timer)? (x86-only) */
76#define HVM_PARAM_HPET_ENABLED 11
77
78/* Identity-map page directory used by Intel EPT when CR0.PG=0. */
79#define HVM_PARAM_IDENT_PT 12
80
81/* Device Model domain, defaults to 0. */
82#define HVM_PARAM_DM_DOMAIN 13
83
84/* ACPI S state: currently support S0 and S3 on x86. */
85#define HVM_PARAM_ACPI_S_STATE 14
86
87/* TSS used on Intel when CR0.PE=0. */
88#define HVM_PARAM_VM86_TSS 15
89
90/* Boolean: Enable aligning all periodic vpts to reduce interrupts */
91#define HVM_PARAM_VPT_ALIGN 16
92
93#define HVM_NR_PARAMS 17
94
95#endif /* __XEN_PUBLIC_HVM_PARAMS_H__ */
diff --git a/include/xen/platform_pci.h b/include/xen/platform_pci.h
new file mode 100644
index 000000000000..ce9d671c636c
--- /dev/null
+++ b/include/xen/platform_pci.h
@@ -0,0 +1,49 @@
1#ifndef _XEN_PLATFORM_PCI_H
2#define _XEN_PLATFORM_PCI_H
3
4#define XEN_IOPORT_MAGIC_VAL 0x49d2
5#define XEN_IOPORT_LINUX_PRODNUM 0x0003
6#define XEN_IOPORT_LINUX_DRVVER 0x0001
7
8#define XEN_IOPORT_BASE 0x10
9
10#define XEN_IOPORT_PLATFLAGS (XEN_IOPORT_BASE + 0) /* 1 byte access (R/W) */
11#define XEN_IOPORT_MAGIC (XEN_IOPORT_BASE + 0) /* 2 byte access (R) */
12#define XEN_IOPORT_UNPLUG (XEN_IOPORT_BASE + 0) /* 2 byte access (W) */
13#define XEN_IOPORT_DRVVER (XEN_IOPORT_BASE + 0) /* 4 byte access (W) */
14
15#define XEN_IOPORT_SYSLOG (XEN_IOPORT_BASE + 2) /* 1 byte access (W) */
16#define XEN_IOPORT_PROTOVER (XEN_IOPORT_BASE + 2) /* 1 byte access (R) */
17#define XEN_IOPORT_PRODNUM (XEN_IOPORT_BASE + 2) /* 2 byte access (W) */
18
19#define XEN_UNPLUG_ALL_IDE_DISKS 1
20#define XEN_UNPLUG_ALL_NICS 2
21#define XEN_UNPLUG_AUX_IDE_DISKS 4
22#define XEN_UNPLUG_ALL 7
23#define XEN_UNPLUG_IGNORE 8
24
25static inline int xen_must_unplug_nics(void) {
26#if (defined(CONFIG_XEN_NETDEV_FRONTEND) || \
27 defined(CONFIG_XEN_NETDEV_FRONTEND_MODULE)) && \
28 (defined(CONFIG_XEN_PLATFORM_PCI) || \
29 defined(CONFIG_XEN_PLATFORM_PCI_MODULE))
30 return 1;
31#else
32 return 0;
33#endif
34}
35
36static inline int xen_must_unplug_disks(void) {
37#if (defined(CONFIG_XEN_BLKDEV_FRONTEND) || \
38 defined(CONFIG_XEN_BLKDEV_FRONTEND_MODULE)) && \
39 (defined(CONFIG_XEN_PLATFORM_PCI) || \
40 defined(CONFIG_XEN_PLATFORM_PCI_MODULE))
41 return 1;
42#else
43 return 0;
44#endif
45}
46
47extern int xen_platform_pci_unplug;
48
49#endif /* _XEN_PLATFORM_PCI_H */
diff --git a/include/xen/xen-ops.h b/include/xen/xen-ops.h
index 883a21bba24b..46bc81ef74c6 100644
--- a/include/xen/xen-ops.h
+++ b/include/xen/xen-ops.h
@@ -7,6 +7,7 @@ DECLARE_PER_CPU(struct vcpu_info *, xen_vcpu);
7 7
8void xen_pre_suspend(void); 8void xen_pre_suspend(void);
9void xen_post_suspend(int suspend_cancelled); 9void xen_post_suspend(int suspend_cancelled);
10void xen_hvm_post_suspend(int suspend_cancelled);
10 11
11void xen_mm_pin_all(void); 12void xen_mm_pin_all(void);
12void xen_mm_unpin_all(void); 13void xen_mm_unpin_all(void);
@@ -14,4 +15,6 @@ void xen_mm_unpin_all(void);
14void xen_timer_resume(void); 15void xen_timer_resume(void);
15void xen_arch_resume(void); 16void xen_arch_resume(void);
16 17
18int xen_setup_shutdown_event(void);
19
17#endif /* INCLUDE_XEN_OPS_H */ 20#endif /* INCLUDE_XEN_OPS_H */