aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/xen/Makefile2
-rw-r--r--arch/x86/xen/enlighten.c6
-rw-r--r--arch/x86/xen/mmu.c46
-rw-r--r--arch/x86/xen/smp.c2
-rw-r--r--arch/x86/xen/suspend.c42
-rw-r--r--arch/x86/xen/time.c8
-rw-r--r--arch/x86/xen/xen-ops.h4
-rw-r--r--drivers/xen/events.c83
-rw-r--r--drivers/xen/grant-table.c4
-rw-r--r--drivers/xen/manage.c126
-rw-r--r--include/linux/page-flags.h1
-rw-r--r--include/xen/events.h3
-rw-r--r--include/xen/grant_table.h3
-rw-r--r--include/xen/xen-ops.h9
14 files changed, 318 insertions, 21 deletions
diff --git a/arch/x86/xen/Makefile b/arch/x86/xen/Makefile
index 40b119b6b103..2ba2d1649131 100644
--- a/arch/x86/xen/Makefile
+++ b/arch/x86/xen/Makefile
@@ -1,4 +1,4 @@
1obj-y := enlighten.o setup.o multicalls.o mmu.o \ 1obj-y := enlighten.o setup.o multicalls.o mmu.o \
2 time.o xen-asm.o grant-table.o 2 time.o xen-asm.o grant-table.o suspend.o
3 3
4obj-$(CONFIG_SMP) += smp.o 4obj-$(CONFIG_SMP) += smp.o
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index ce67dc8f36af..b94f63ac228b 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -857,7 +857,7 @@ static __init void xen_pagetable_setup_start(pgd_t *base)
857 PFN_DOWN(__pa(xen_start_info->pt_base))); 857 PFN_DOWN(__pa(xen_start_info->pt_base)));
858} 858}
859 859
860static __init void setup_shared_info(void) 860void xen_setup_shared_info(void)
861{ 861{
862 if (!xen_feature(XENFEAT_auto_translated_physmap)) { 862 if (!xen_feature(XENFEAT_auto_translated_physmap)) {
863 unsigned long addr = fix_to_virt(FIX_PARAVIRT_BOOTMAP); 863 unsigned long addr = fix_to_virt(FIX_PARAVIRT_BOOTMAP);
@@ -894,7 +894,7 @@ static __init void xen_pagetable_setup_done(pgd_t *base)
894 pv_mmu_ops.release_pmd = xen_release_pmd; 894 pv_mmu_ops.release_pmd = xen_release_pmd;
895 pv_mmu_ops.set_pte = xen_set_pte; 895 pv_mmu_ops.set_pte = xen_set_pte;
896 896
897 setup_shared_info(); 897 xen_setup_shared_info();
898 898
899 /* Actually pin the pagetable down, but we can't set PG_pinned 899 /* Actually pin the pagetable down, but we can't set PG_pinned
900 yet because the page structures don't exist yet. */ 900 yet because the page structures don't exist yet. */
@@ -902,7 +902,7 @@ static __init void xen_pagetable_setup_done(pgd_t *base)
902} 902}
903 903
904/* This is called once we have the cpu_possible_map */ 904/* This is called once we have the cpu_possible_map */
905void __init xen_setup_vcpu_info_placement(void) 905void xen_setup_vcpu_info_placement(void)
906{ 906{
907 int cpu; 907 int cpu;
908 908
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c
index 4740cda36563..e95955968ba3 100644
--- a/arch/x86/xen/mmu.c
+++ b/arch/x86/xen/mmu.c
@@ -560,6 +560,29 @@ void xen_pgd_pin(pgd_t *pgd)
560 xen_mc_issue(0); 560 xen_mc_issue(0);
561} 561}
562 562
563/*
564 * On save, we need to pin all pagetables to make sure they get their
565 * mfns turned into pfns. Search the list for any unpinned pgds and pin
566 * them (unpinned pgds are not currently in use, probably because the
567 * process is under construction or destruction).
568 */
569void xen_mm_pin_all(void)
570{
571 unsigned long flags;
572 struct page *page;
573
574 spin_lock_irqsave(&pgd_lock, flags);
575
576 list_for_each_entry(page, &pgd_list, lru) {
577 if (!PagePinned(page)) {
578 xen_pgd_pin((pgd_t *)page_address(page));
579 SetPageSavePinned(page);
580 }
581 }
582
583 spin_unlock_irqrestore(&pgd_lock, flags);
584}
585
563/* The init_mm pagetable is really pinned as soon as its created, but 586/* The init_mm pagetable is really pinned as soon as its created, but
564 that's before we have page structures to store the bits. So do all 587 that's before we have page structures to store the bits. So do all
565 the book-keeping now. */ 588 the book-keeping now. */
@@ -617,6 +640,29 @@ static void xen_pgd_unpin(pgd_t *pgd)
617 xen_mc_issue(0); 640 xen_mc_issue(0);
618} 641}
619 642
643/*
644 * On resume, undo any pinning done at save, so that the rest of the
645 * kernel doesn't see any unexpected pinned pagetables.
646 */
647void xen_mm_unpin_all(void)
648{
649 unsigned long flags;
650 struct page *page;
651
652 spin_lock_irqsave(&pgd_lock, flags);
653
654 list_for_each_entry(page, &pgd_list, lru) {
655 if (PageSavePinned(page)) {
656 BUG_ON(!PagePinned(page));
657 printk("unpinning pinned %p\n", page_address(page));
658 xen_pgd_unpin((pgd_t *)page_address(page));
659 ClearPageSavePinned(page);
660 }
661 }
662
663 spin_unlock_irqrestore(&pgd_lock, flags);
664}
665
620void xen_activate_mm(struct mm_struct *prev, struct mm_struct *next) 666void xen_activate_mm(struct mm_struct *prev, struct mm_struct *next)
621{ 667{
622 spin_lock(&next->page_table_lock); 668 spin_lock(&next->page_table_lock);
diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c
index 74ab8968c525..d2e3c20127d7 100644
--- a/arch/x86/xen/smp.c
+++ b/arch/x86/xen/smp.c
@@ -35,7 +35,7 @@
35#include "xen-ops.h" 35#include "xen-ops.h"
36#include "mmu.h" 36#include "mmu.h"
37 37
38static cpumask_t xen_cpu_initialized_map; 38cpumask_t xen_cpu_initialized_map;
39static DEFINE_PER_CPU(int, resched_irq) = -1; 39static DEFINE_PER_CPU(int, resched_irq) = -1;
40static DEFINE_PER_CPU(int, callfunc_irq) = -1; 40static DEFINE_PER_CPU(int, callfunc_irq) = -1;
41static DEFINE_PER_CPU(int, debug_irq) = -1; 41static DEFINE_PER_CPU(int, debug_irq) = -1;
diff --git a/arch/x86/xen/suspend.c b/arch/x86/xen/suspend.c
new file mode 100644
index 000000000000..7620a16fe535
--- /dev/null
+++ b/arch/x86/xen/suspend.c
@@ -0,0 +1,42 @@
1#include <linux/types.h>
2
3#include <xen/interface/xen.h>
4#include <xen/grant_table.h>
5#include <xen/events.h>
6
7#include <asm/xen/hypercall.h>
8#include <asm/xen/page.h>
9
10#include "xen-ops.h"
11#include "mmu.h"
12
13void xen_pre_suspend(void)
14{
15 xen_start_info->store_mfn = mfn_to_pfn(xen_start_info->store_mfn);
16 xen_start_info->console.domU.mfn =
17 mfn_to_pfn(xen_start_info->console.domU.mfn);
18
19 BUG_ON(!irqs_disabled());
20
21 HYPERVISOR_shared_info = &xen_dummy_shared_info;
22 if (HYPERVISOR_update_va_mapping(fix_to_virt(FIX_PARAVIRT_BOOTMAP),
23 __pte_ma(0), 0))
24 BUG();
25}
26
27void xen_post_suspend(int suspend_cancelled)
28{
29 if (suspend_cancelled) {
30 xen_start_info->store_mfn =
31 pfn_to_mfn(xen_start_info->store_mfn);
32 xen_start_info->console.domU.mfn =
33 pfn_to_mfn(xen_start_info->console.domU.mfn);
34 } else {
35#ifdef CONFIG_SMP
36 xen_cpu_initialized_map = cpu_online_map;
37#endif
38 }
39
40 xen_setup_shared_info();
41}
42
diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c
index c39e1a5aa241..0bef256e5f2d 100644
--- a/arch/x86/xen/time.c
+++ b/arch/x86/xen/time.c
@@ -572,6 +572,14 @@ void xen_setup_cpu_clockevents(void)
572 clockevents_register_device(&__get_cpu_var(xen_clock_events)); 572 clockevents_register_device(&__get_cpu_var(xen_clock_events));
573} 573}
574 574
575void xen_time_suspend(void)
576{
577}
578
579void xen_time_resume(void)
580{
581}
582
575__init void xen_time_init(void) 583__init void xen_time_init(void)
576{ 584{
577 int cpu = smp_processor_id(); 585 int cpu = smp_processor_id();
diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h
index a1bc89a8f169..a0503acad664 100644
--- a/arch/x86/xen/xen-ops.h
+++ b/arch/x86/xen/xen-ops.h
@@ -9,6 +9,7 @@
9extern const char xen_hypervisor_callback[]; 9extern const char xen_hypervisor_callback[];
10extern const char xen_failsafe_callback[]; 10extern const char xen_failsafe_callback[];
11 11
12struct trap_info;
12void xen_copy_trap_info(struct trap_info *traps); 13void xen_copy_trap_info(struct trap_info *traps);
13 14
14DECLARE_PER_CPU(unsigned long, xen_cr3); 15DECLARE_PER_CPU(unsigned long, xen_cr3);
@@ -19,6 +20,7 @@ extern struct shared_info xen_dummy_shared_info;
19extern struct shared_info *HYPERVISOR_shared_info; 20extern struct shared_info *HYPERVISOR_shared_info;
20 21
21void xen_setup_mfn_list_list(void); 22void xen_setup_mfn_list_list(void);
23void xen_setup_shared_info(void);
22 24
23char * __init xen_memory_setup(void); 25char * __init xen_memory_setup(void);
24void __init xen_arch_setup(void); 26void __init xen_arch_setup(void);
@@ -59,6 +61,8 @@ int xen_smp_call_function_single(int cpu, void (*func) (void *info), void *info,
59int xen_smp_call_function_mask(cpumask_t mask, void (*func)(void *), 61int xen_smp_call_function_mask(cpumask_t mask, void (*func)(void *),
60 void *info, int wait); 62 void *info, int wait);
61 63
64extern cpumask_t xen_cpu_initialized_map;
65
62 66
63/* Declare an asm function, along with symbols needed to make it 67/* Declare an asm function, along with symbols needed to make it
64 inlineable */ 68 inlineable */
diff --git a/drivers/xen/events.c b/drivers/xen/events.c
index 70375a690761..73d78dc9b875 100644
--- a/drivers/xen/events.c
+++ b/drivers/xen/events.c
@@ -674,6 +674,89 @@ static int retrigger_dynirq(unsigned int irq)
674 return ret; 674 return ret;
675} 675}
676 676
677static void restore_cpu_virqs(unsigned int cpu)
678{
679 struct evtchn_bind_virq bind_virq;
680 int virq, irq, evtchn;
681
682 for (virq = 0; virq < NR_VIRQS; virq++) {
683 if ((irq = per_cpu(virq_to_irq, cpu)[virq]) == -1)
684 continue;
685
686 BUG_ON(irq_info[irq].type != IRQT_VIRQ);
687 BUG_ON(irq_info[irq].index != virq);
688
689 /* Get a new binding from Xen. */
690 bind_virq.virq = virq;
691 bind_virq.vcpu = cpu;
692 if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_virq,
693 &bind_virq) != 0)
694 BUG();
695 evtchn = bind_virq.port;
696
697 /* Record the new mapping. */
698 evtchn_to_irq[evtchn] = irq;
699 irq_info[irq] = mk_irq_info(IRQT_VIRQ, virq, evtchn);
700 bind_evtchn_to_cpu(evtchn, cpu);
701
702 /* Ready for use. */
703 unmask_evtchn(evtchn);
704 }
705}
706
707static void restore_cpu_ipis(unsigned int cpu)
708{
709 struct evtchn_bind_ipi bind_ipi;
710 int ipi, irq, evtchn;
711
712 for (ipi = 0; ipi < XEN_NR_IPIS; ipi++) {
713 if ((irq = per_cpu(ipi_to_irq, cpu)[ipi]) == -1)
714 continue;
715
716 BUG_ON(irq_info[irq].type != IRQT_IPI);
717 BUG_ON(irq_info[irq].index != ipi);
718
719 /* Get a new binding from Xen. */
720 bind_ipi.vcpu = cpu;
721 if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_ipi,
722 &bind_ipi) != 0)
723 BUG();
724 evtchn = bind_ipi.port;
725
726 /* Record the new mapping. */
727 evtchn_to_irq[evtchn] = irq;
728 irq_info[irq] = mk_irq_info(IRQT_IPI, ipi, evtchn);
729 bind_evtchn_to_cpu(evtchn, cpu);
730
731 /* Ready for use. */
732 unmask_evtchn(evtchn);
733
734 }
735}
736
737void xen_irq_resume(void)
738{
739 unsigned int cpu, irq, evtchn;
740
741 init_evtchn_cpu_bindings();
742
743 /* New event-channel space is not 'live' yet. */
744 for (evtchn = 0; evtchn < NR_EVENT_CHANNELS; evtchn++)
745 mask_evtchn(evtchn);
746
747 /* No IRQ <-> event-channel mappings. */
748 for (irq = 0; irq < NR_IRQS; irq++)
749 irq_info[irq].evtchn = 0; /* zap event-channel binding */
750
751 for (evtchn = 0; evtchn < NR_EVENT_CHANNELS; evtchn++)
752 evtchn_to_irq[evtchn] = -1;
753
754 for_each_possible_cpu(cpu) {
755 restore_cpu_virqs(cpu);
756 restore_cpu_ipis(cpu);
757 }
758}
759
677static struct irq_chip xen_dynamic_chip __read_mostly = { 760static struct irq_chip xen_dynamic_chip __read_mostly = {
678 .name = "xen-dyn", 761 .name = "xen-dyn",
679 .mask = disable_dynirq, 762 .mask = disable_dynirq,
diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c
index 52b6b41b909d..e9e11168616a 100644
--- a/drivers/xen/grant-table.c
+++ b/drivers/xen/grant-table.c
@@ -471,14 +471,14 @@ static int gnttab_map(unsigned int start_idx, unsigned int end_idx)
471 return 0; 471 return 0;
472} 472}
473 473
474static int gnttab_resume(void) 474int gnttab_resume(void)
475{ 475{
476 if (max_nr_grant_frames() < nr_grant_frames) 476 if (max_nr_grant_frames() < nr_grant_frames)
477 return -ENOSYS; 477 return -ENOSYS;
478 return gnttab_map(0, nr_grant_frames - 1); 478 return gnttab_map(0, nr_grant_frames - 1);
479} 479}
480 480
481static int gnttab_suspend(void) 481int gnttab_suspend(void)
482{ 482{
483 arch_gnttab_unmap_shared(shared, nr_grant_frames); 483 arch_gnttab_unmap_shared(shared, nr_grant_frames);
484 return 0; 484 return 0;
diff --git a/drivers/xen/manage.c b/drivers/xen/manage.c
index aa7af9e6abc0..ba85fa2cff33 100644
--- a/drivers/xen/manage.c
+++ b/drivers/xen/manage.c
@@ -5,21 +5,113 @@
5#include <linux/err.h> 5#include <linux/err.h>
6#include <linux/reboot.h> 6#include <linux/reboot.h>
7#include <linux/sysrq.h> 7#include <linux/sysrq.h>
8#include <linux/stop_machine.h>
9#include <linux/freezer.h>
8 10
9#include <xen/xenbus.h> 11#include <xen/xenbus.h>
10 12#include <xen/grant_table.h>
11#define SHUTDOWN_INVALID -1 13#include <xen/events.h>
12#define SHUTDOWN_POWEROFF 0 14#include <xen/hvc-console.h>
13#define SHUTDOWN_SUSPEND 2 15#include <xen/xen-ops.h>
14/* Code 3 is SHUTDOWN_CRASH, which we don't use because the domain can only 16
15 * report a crash, not be instructed to crash! 17#include <asm/xen/hypercall.h>
16 * HALT is the same as POWEROFF, as far as we're concerned. The tools use 18#include <asm/xen/page.h>
17 * the distinction when we return the reason code to them. 19
18 */ 20enum shutdown_state {
19#define SHUTDOWN_HALT 4 21 SHUTDOWN_INVALID = -1,
22 SHUTDOWN_POWEROFF = 0,
23 SHUTDOWN_SUSPEND = 2,
24 /* Code 3 is SHUTDOWN_CRASH, which we don't use because the domain can only
25 report a crash, not be instructed to crash!
26 HALT is the same as POWEROFF, as far as we're concerned. The tools use
27 the distinction when we return the reason code to them. */
28 SHUTDOWN_HALT = 4,
29};
20 30
21/* Ignore multiple shutdown requests. */ 31/* Ignore multiple shutdown requests. */
22static int shutting_down = SHUTDOWN_INVALID; 32static enum shutdown_state shutting_down = SHUTDOWN_INVALID;
33
34static int xen_suspend(void *data)
35{
36 int *cancelled = data;
37
38 BUG_ON(!irqs_disabled());
39
40 load_cr3(swapper_pg_dir);
41
42 xen_mm_pin_all();
43 gnttab_suspend();
44 xen_time_suspend();
45 xen_pre_suspend();
46
47 /*
48 * This hypercall returns 1 if suspend was cancelled
49 * or the domain was merely checkpointed, and 0 if it
50 * is resuming in a new domain.
51 */
52 *cancelled = HYPERVISOR_suspend(virt_to_mfn(xen_start_info));
53
54 xen_post_suspend(*cancelled);
55 xen_time_resume();
56 gnttab_resume();
57 xen_mm_unpin_all();
58
59 if (!*cancelled) {
60 xen_irq_resume();
61 xen_console_resume();
62 }
63
64 return 0;
65}
66
67static void do_suspend(void)
68{
69 int err;
70 int cancelled = 1;
71
72 shutting_down = SHUTDOWN_SUSPEND;
73
74#ifdef CONFIG_PREEMPT
75 /* If the kernel is preemptible, we need to freeze all the processes
76 to prevent them from being in the middle of a pagetable update
77 during suspend. */
78 err = freeze_processes();
79 if (err) {
80 printk(KERN_ERR "xen suspend: freeze failed %d\n", err);
81 return;
82 }
83#endif
84
85 err = device_suspend(PMSG_SUSPEND);
86 if (err) {
87 printk(KERN_ERR "xen suspend: device_suspend %d\n", err);
88 goto out;
89 }
90
91 printk("suspending xenbus...\n");
92 /* XXX use normal device tree? */
93 xenbus_suspend();
94
95 err = stop_machine_run(xen_suspend, &cancelled, 0);
96 if (err) {
97 printk(KERN_ERR "failed to start xen_suspend: %d\n", err);
98 goto out;
99 }
100
101 if (!cancelled)
102 xenbus_resume();
103 else
104 xenbus_suspend_cancel();
105
106 device_resume();
107
108
109out:
110#ifdef CONFIG_PREEMPT
111 thaw_processes();
112#endif
113 shutting_down = SHUTDOWN_INVALID;
114}
23 115
24static void shutdown_handler(struct xenbus_watch *watch, 116static void shutdown_handler(struct xenbus_watch *watch,
25 const char **vec, unsigned int len) 117 const char **vec, unsigned int len)
@@ -52,11 +144,17 @@ static void shutdown_handler(struct xenbus_watch *watch,
52 } 144 }
53 145
54 if (strcmp(str, "poweroff") == 0 || 146 if (strcmp(str, "poweroff") == 0 ||
55 strcmp(str, "halt") == 0) 147 strcmp(str, "halt") == 0) {
148 shutting_down = SHUTDOWN_POWEROFF;
56 orderly_poweroff(false); 149 orderly_poweroff(false);
57 else if (strcmp(str, "reboot") == 0) 150 } else if (strcmp(str, "reboot") == 0) {
151 shutting_down = SHUTDOWN_POWEROFF; /* ? */
58 ctrl_alt_del(); 152 ctrl_alt_del();
59 else { 153#ifdef CONFIG_PM_SLEEP
154 } else if (strcmp(str, "suspend") == 0) {
155 do_suspend();
156#endif
157 } else {
60 printk(KERN_INFO "Ignoring shutdown request: %s\n", str); 158 printk(KERN_INFO "Ignoring shutdown request: %s\n", str);
61 shutting_down = SHUTDOWN_INVALID; 159 shutting_down = SHUTDOWN_INVALID;
62 } 160 }
diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
index 590cff32415d..02955a1c3d76 100644
--- a/include/linux/page-flags.h
+++ b/include/linux/page-flags.h
@@ -157,6 +157,7 @@ PAGEFLAG(Active, active) __CLEARPAGEFLAG(Active, active)
157__PAGEFLAG(Slab, slab) 157__PAGEFLAG(Slab, slab)
158PAGEFLAG(Checked, owner_priv_1) /* Used by some filesystems */ 158PAGEFLAG(Checked, owner_priv_1) /* Used by some filesystems */
159PAGEFLAG(Pinned, owner_priv_1) TESTSCFLAG(Pinned, owner_priv_1) /* Xen */ 159PAGEFLAG(Pinned, owner_priv_1) TESTSCFLAG(Pinned, owner_priv_1) /* Xen */
160PAGEFLAG(SavePinned, dirty); /* Xen */
160PAGEFLAG(Reserved, reserved) __CLEARPAGEFLAG(Reserved, reserved) 161PAGEFLAG(Reserved, reserved) __CLEARPAGEFLAG(Reserved, reserved)
161PAGEFLAG(Private, private) __CLEARPAGEFLAG(Private, private) 162PAGEFLAG(Private, private) __CLEARPAGEFLAG(Private, private)
162 __SETPAGEFLAG(Private, private) 163 __SETPAGEFLAG(Private, private)
diff --git a/include/xen/events.h b/include/xen/events.h
index a82ec0c45c38..67c4436554a9 100644
--- a/include/xen/events.h
+++ b/include/xen/events.h
@@ -41,4 +41,7 @@ static inline void notify_remote_via_evtchn(int port)
41} 41}
42 42
43extern void notify_remote_via_irq(int irq); 43extern void notify_remote_via_irq(int irq);
44
45extern void xen_irq_resume(void);
46
44#endif /* _XEN_EVENTS_H */ 47#endif /* _XEN_EVENTS_H */
diff --git a/include/xen/grant_table.h b/include/xen/grant_table.h
index 466204846121..a40f1cd91be1 100644
--- a/include/xen/grant_table.h
+++ b/include/xen/grant_table.h
@@ -51,6 +51,9 @@ struct gnttab_free_callback {
51 u16 count; 51 u16 count;
52}; 52};
53 53
54int gnttab_suspend(void);
55int gnttab_resume(void);
56
54int gnttab_grant_foreign_access(domid_t domid, unsigned long frame, 57int gnttab_grant_foreign_access(domid_t domid, unsigned long frame,
55 int readonly); 58 int readonly);
56 59
diff --git a/include/xen/xen-ops.h b/include/xen/xen-ops.h
index 10ddfe0142d0..5d7a6db54a8c 100644
--- a/include/xen/xen-ops.h
+++ b/include/xen/xen-ops.h
@@ -5,4 +5,13 @@
5 5
6DECLARE_PER_CPU(struct vcpu_info *, xen_vcpu); 6DECLARE_PER_CPU(struct vcpu_info *, xen_vcpu);
7 7
8void xen_pre_suspend(void);
9void xen_post_suspend(int suspend_cancelled);
10
11void xen_mm_pin_all(void);
12void xen_mm_unpin_all(void);
13
14void xen_time_suspend(void);
15void xen_time_resume(void);
16
8#endif /* INCLUDE_XEN_OPS_H */ 17#endif /* INCLUDE_XEN_OPS_H */