- Update Xen patches to c/s 1011.
[opensuse:kernel-source.git] / patches.xen / xen-x86-per-cpu-vcpu-info
1 From: jbeulich@novell.com
2 Subject: x86: use per-cpu storage for shared vcpu_info structure
3 Patch-mainline: obsolete
4
5 ... reducing access code size and latency, as well as being the
6 prerequisite for removing the limitation on 32 vCPU-s per guest.
7
8 --- sle11sp1-2010-03-29.orig/arch/x86/include/asm/percpu.h      2010-03-29 09:00:34.000000000 +0200
9 +++ sle11sp1-2010-03-29/arch/x86/include/asm/percpu.h   2009-11-06 11:12:01.000000000 +0100
10 @@ -133,6 +133,38 @@ do {                                                       \
11         ret__;                                          \
12  })
13  
14 +#define percpu_xchg_op(op, var, val)                   \
15 +({                                                     \
16 +       typedef typeof(var) T__;                        \
17 +       T__ ret__;                                      \
18 +       if (0)                                          \
19 +               ret__ = (val);                          \
20 +       switch (sizeof(var)) {                          \
21 +       case 1:                                         \
22 +               asm(op "b %0,"__percpu_arg(1)           \
23 +                   : "=q" (ret__), "+m" (var)          \
24 +                   : "0" ((T__)(val)));                \
25 +               break;                                  \
26 +       case 2:                                         \
27 +               asm(op "w %0,"__percpu_arg(1)           \
28 +                   : "=r" (ret__), "+m" (var)          \
29 +                   : "0" ((T__)(val)));                \
30 +               break;                                  \
31 +       case 4:                                         \
32 +               asm(op "l %0,"__percpu_arg(1)           \
33 +                   : "=r" (ret__), "+m" (var)          \
34 +                   : "0" ((T__)(val)));                \
35 +               break;                                  \
36 +       case 8:                                         \
37 +               asm(op "q %0,"__percpu_arg(1)           \
38 +                   : "=r" (ret__), "+m" (var)          \
39 +                   : "0" ((T__)(val)));                \
40 +               break;                                  \
41 +       default: __bad_percpu_size();                   \
42 +       }                                               \
43 +       ret__;                                          \
44 +})
45 +
46  /*
47   * percpu_read() makes gcc load the percpu variable every time it is
48   * accessed while percpu_read_stable() allows the value to be cached.
49 @@ -152,6 +184,10 @@ do {                                                       \
50  #define percpu_and(var, val)   percpu_to_op("and", per_cpu__##var, val)
51  #define percpu_or(var, val)    percpu_to_op("or", per_cpu__##var, val)
52  #define percpu_xor(var, val)   percpu_to_op("xor", per_cpu__##var, val)
53 +#define percpu_xchg(var, val)   percpu_xchg_op("xchg", per_cpu__##var, val)
54 +#if defined(CONFIG_X86_XADD) || defined(CONFIG_X86_64)
55 +#define percpu_xadd(var, val)   percpu_xchg_op("xadd", per_cpu__##var, val)
56 +#endif
57  
58  /* This is not atomic against other CPUs -- CPU preemption needs to be off */
59  #define x86_test_and_clear_bit_percpu(bit, var)                                \
60 --- sle11sp1-2010-03-29.orig/arch/x86/include/mach-xen/asm/hypervisor.h 2009-11-23 10:49:39.000000000 +0100
61 +++ sle11sp1-2010-03-29/arch/x86/include/mach-xen/asm/hypervisor.h      2009-11-23 10:53:45.000000000 +0100
62 @@ -50,12 +50,26 @@
63  
64  extern shared_info_t *HYPERVISOR_shared_info;
65  
66 +#ifdef CONFIG_XEN_VCPU_INFO_PLACEMENT
67 +DECLARE_PER_CPU(struct vcpu_info, vcpu_info);
68 +#define vcpu_info(cpu) (&per_cpu(vcpu_info, cpu))
69 +#define current_vcpu_info() (&__get_cpu_var(vcpu_info))
70 +#define vcpu_info_read(fld) percpu_read(vcpu_info.fld)
71 +#define vcpu_info_write(fld, val) percpu_write(vcpu_info.fld, val)
72 +#define vcpu_info_xchg(fld, val) percpu_xchg(vcpu_info.fld, val)
73 +void setup_vcpu_info(unsigned int cpu);
74 +void adjust_boot_vcpu_info(void);
75 +#else
76  #define vcpu_info(cpu) (HYPERVISOR_shared_info->vcpu_info + (cpu))
77  #ifdef CONFIG_SMP
78  #define current_vcpu_info() vcpu_info(smp_processor_id())
79  #else
80  #define current_vcpu_info() vcpu_info(0)
81  #endif
82 +#define vcpu_info_read(fld) (current_vcpu_info()->fld)
83 +#define vcpu_info_write(fld, val) (current_vcpu_info()->fld = (val))
84 +static inline void setup_vcpu_info(unsigned int cpu) {}
85 +#endif
86  
87  #ifdef CONFIG_X86_32
88  extern unsigned long hypervisor_virt_start;
89 --- sle11sp1-2010-03-29.orig/arch/x86/include/mach-xen/asm/irqflags.h   2009-11-06 10:52:22.000000000 +0100
90 +++ sle11sp1-2010-03-29/arch/x86/include/mach-xen/asm/irqflags.h        2009-11-06 11:12:01.000000000 +0100
91 @@ -12,7 +12,7 @@
92   * includes these barriers, for example.
93   */
94  
95 -#define xen_save_fl(void) (current_vcpu_info()->evtchn_upcall_mask)
96 +#define xen_save_fl(void) vcpu_info_read(evtchn_upcall_mask)
97  
98  #define xen_restore_fl(f)                                      \
99  do {                                                           \
100 @@ -28,7 +28,7 @@ do {                                                          \
101  
102  #define xen_irq_disable()                                      \
103  do {                                                           \
104 -       current_vcpu_info()->evtchn_upcall_mask = 1;            \
105 +       vcpu_info_write(evtchn_upcall_mask, 1);                 \
106         barrier();                                              \
107  } while (0)
108  
109 @@ -90,8 +90,6 @@ static inline void halt(void)
110  #define evtchn_upcall_pending          /* 0 */
111  #define evtchn_upcall_mask             1
112  
113 -#define sizeof_vcpu_shift              6
114 -
115  #ifdef CONFIG_X86_64
116  # define __REG_si %rsi
117  # define __CPU_num PER_CPU_VAR(cpu_number)
118 @@ -100,6 +98,22 @@ static inline void halt(void)
119  # define __CPU_num TI_cpu(%ebp)
120  #endif
121  
122 +#ifdef CONFIG_XEN_VCPU_INFO_PLACEMENT
123 +
124 +#define GET_VCPU_INFO          PER_CPU(vcpu_info, __REG_si)
125 +#define __DISABLE_INTERRUPTS   movb $1,PER_CPU_VAR(vcpu_info+evtchn_upcall_mask)
126 +#define __ENABLE_INTERRUPTS    movb $0,PER_CPU_VAR(vcpu_info+evtchn_upcall_mask)
127 +#define __TEST_PENDING         cmpb $0,PER_CPU_VAR(vcpu_info+evtchn_upcall_pending+0)
128 +#define DISABLE_INTERRUPTS(clb)        __DISABLE_INTERRUPTS
129 +#define ENABLE_INTERRUPTS(clb) __ENABLE_INTERRUPTS
130 +
131 +#define __SIZEOF_DISABLE_INTERRUPTS 8
132 +#define __SIZEOF_TEST_PENDING  8
133 +
134 +#else /* CONFIG_XEN_VCPU_INFO_PLACEMENT */
135 +
136 +#define sizeof_vcpu_shift      6
137 +
138  #ifdef CONFIG_SMP
139  #define GET_VCPU_INFO          movl __CPU_num,%esi                     ; \
140                                 shl $sizeof_vcpu_shift,%esi             ; \
141 @@ -116,15 +130,21 @@ static inline void halt(void)
142  #define ENABLE_INTERRUPTS(clb) GET_VCPU_INFO                           ; \
143                                 __ENABLE_INTERRUPTS
144  
145 +#define __SIZEOF_DISABLE_INTERRUPTS 4
146 +#define __SIZEOF_TEST_PENDING  3
147 +
148 +#endif /* CONFIG_XEN_VCPU_INFO_PLACEMENT */
149 +
150  #ifndef CONFIG_X86_64
151  #define INTERRUPT_RETURN               iret
152 -#define ENABLE_INTERRUPTS_SYSEXIT      __ENABLE_INTERRUPTS             ; \
153 +#define ENABLE_INTERRUPTS_SYSEXIT                                        \
154 +       movb $0,evtchn_upcall_mask(%esi) /* __ENABLE_INTERRUPTS */      ; \
155  sysexit_scrit: /**** START OF SYSEXIT CRITICAL REGION ****/            ; \
156 -       __TEST_PENDING                                                  ; \
157 +       cmpb $0,evtchn_upcall_pending(%esi) /* __TEST_PENDING */        ; \
158         jnz  14f        /* process more events if necessary... */       ; \
159         movl PT_ESI(%esp), %esi                                         ; \
160         sysexit                                                         ; \
161 -14:    __DISABLE_INTERRUPTS                                            ; \
162 +14:    movb $1,evtchn_upcall_mask(%esi) /* __DISABLE_INTERRUPTS */     ; \
163         TRACE_IRQS_OFF                                                  ; \
164  sysexit_ecrit: /**** END OF SYSEXIT CRITICAL REGION ****/              ; \
165         mov  $__KERNEL_PERCPU, %ecx                                     ; \
166 --- sle11sp1-2010-03-29.orig/arch/x86/include/mach-xen/asm/pgtable_64.h 2009-10-13 17:22:09.000000000 +0200
167 +++ sle11sp1-2010-03-29/arch/x86/include/mach-xen/asm/pgtable_64.h      2009-11-06 11:12:01.000000000 +0100
168 @@ -117,6 +117,8 @@ static inline void xen_set_pgd(pgd_t *pg
169  
170  #define __pte_mfn(_pte) (((_pte).pte & PTE_PFN_MASK) >> PAGE_SHIFT)
171  
172 +extern unsigned long early_arbitrary_virt_to_mfn(void *va);
173 +
174  /*
175   * Conversion functions: convert a page and protection to a page entry,
176   * and a page entry and page directory to the page they refer to.
177 --- sle11sp1-2010-03-29.orig/arch/x86/include/mach-xen/asm/system.h     2009-11-06 10:52:22.000000000 +0100
178 +++ sle11sp1-2010-03-29/arch/x86/include/mach-xen/asm/system.h  2009-11-06 11:12:01.000000000 +0100
179 @@ -233,8 +233,8 @@ static inline void xen_write_cr0(unsigne
180         asm volatile("mov %0,%%cr0": : "r" (val), "m" (__force_order));
181  }
182  
183 -#define xen_read_cr2() (current_vcpu_info()->arch.cr2)
184 -#define xen_write_cr2(val) ((void)(current_vcpu_info()->arch.cr2 = (val)))
185 +#define xen_read_cr2() vcpu_info_read(arch.cr2)
186 +#define xen_write_cr2(val) vcpu_info_write(arch.cr2, val)
187  
188  static inline unsigned long xen_read_cr3(void)
189  {
190 --- sle11sp1-2010-03-29.orig/arch/x86/kernel/cpu/common-xen.c   2010-01-18 17:05:30.000000000 +0100
191 +++ sle11sp1-2010-03-29/arch/x86/kernel/cpu/common-xen.c        2009-11-06 11:12:01.000000000 +0100
192 @@ -335,8 +335,16 @@ static const char *__cpuinit table_looku
193  __u32 cpu_caps_cleared[NCAPINTS] __cpuinitdata;
194  __u32 cpu_caps_set[NCAPINTS] __cpuinitdata;
195  
196 -void load_percpu_segment(int cpu)
197 +void __ref load_percpu_segment(int cpu)
198  {
199 +#ifdef CONFIG_XEN_VCPU_INFO_PLACEMENT
200 +       static bool done;
201 +
202 +       if (!done) {
203 +               done = true;
204 +               adjust_boot_vcpu_info();
205 +       }
206 +#endif
207  #ifdef CONFIG_X86_32
208         loadsegment(fs, __KERNEL_PERCPU);
209  #else
210 --- sle11sp1-2010-03-29.orig/arch/x86/kernel/entry_32-xen.S     2009-10-13 17:01:47.000000000 +0200
211 +++ sle11sp1-2010-03-29/arch/x86/kernel/entry_32-xen.S  2009-11-06 11:12:01.000000000 +0100
212 @@ -463,6 +463,9 @@ sysenter_exit:
213         movl PT_EIP(%esp), %edx
214         movl PT_OLDESP(%esp), %ecx
215         xorl %ebp,%ebp
216 +#ifdef CONFIG_XEN_VCPU_INFO_PLACEMENT
217 +       GET_VCPU_INFO
218 +#endif
219         TRACE_IRQS_ON
220  1:     mov  PT_FS(%esp), %fs
221         PTGS_TO_GS
222 @@ -975,7 +978,9 @@ critical_region_fixup:
223  
224  .section .rodata,"a"
225  critical_fixup_table:
226 -       .byte -1,-1,-1                  # testb $0xff,(%esi) = __TEST_PENDING
227 +       .rept __SIZEOF_TEST_PENDING
228 +       .byte -1
229 +       .endr
230         .byte -1,-1                     # jnz  14f
231         .byte 0                         # pop  %ebx
232         .byte 1                         # pop  %ecx
233 @@ -994,7 +999,9 @@ critical_fixup_table:
234         .byte 10,10,10                  # add  $8,%esp
235  #endif
236         .byte 12                        # iret
237 -       .byte -1,-1,-1,-1               # movb $1,1(%esi) = __DISABLE_INTERRUPTS
238 +       .rept __SIZEOF_DISABLE_INTERRUPTS
239 +       .byte -1
240 +       .endr
241  .previous
242  
243  # Hypervisor uses this for application faults while it executes.
244 --- sle11sp1-2010-03-29.orig/arch/x86/kernel/head-xen.c 2009-10-15 15:32:46.000000000 +0200
245 +++ sle11sp1-2010-03-29/arch/x86/kernel/head-xen.c      2009-11-06 11:12:01.000000000 +0100
246 @@ -151,6 +151,8 @@ void __init xen_start_kernel(void)
247         HYPERVISOR_shared_info = (shared_info_t *)fix_to_virt(FIX_SHARED_INFO);
248         memset(empty_zero_page, 0, sizeof(empty_zero_page));
249  
250 +       setup_vcpu_info(0);
251 +
252         /* Set up mapping of lowest 1MB of physical memory. */
253         for (i = 0; i < NR_FIX_ISAMAPS; i++)
254                 if (is_initial_xendomain())
255 --- sle11sp1-2010-03-29.orig/arch/x86/kernel/time-xen.c 2010-02-04 09:43:52.000000000 +0100
256 +++ sle11sp1-2010-03-29/arch/x86/kernel/time-xen.c      2010-02-09 17:20:06.000000000 +0100
257 @@ -276,16 +276,10 @@ static void get_time_values_from_xen(uns
258         local_irq_restore(flags);
259  }
260  
261 -static inline int time_values_up_to_date(unsigned int cpu)
262 +static inline int time_values_up_to_date(void)
263  {
264 -       struct vcpu_time_info   *src;
265 -       struct shadow_time_info *dst;
266 -
267 -       src = &vcpu_info(cpu)->time;
268 -       dst = &per_cpu(shadow_time, cpu);
269 -
270         rmb();
271 -       return (dst->version == src->version);
272 +       return percpu_read(shadow_time.version) == vcpu_info_read(time.version);
273  }
274  
275  static void sync_xen_wallclock(unsigned long dummy);
276 @@ -331,7 +325,7 @@ static unsigned long long local_clock(vo
277                 local_time_version = shadow->version;
278                 rdtsc_barrier();
279                 time = shadow->system_timestamp + get_nsec_offset(shadow);
280 -               if (!time_values_up_to_date(cpu))
281 +               if (!time_values_up_to_date())
282                         get_time_values_from_xen(cpu);
283                 barrier();
284         } while (local_time_version != shadow->version);
285 @@ -455,7 +449,7 @@ static irqreturn_t timer_interrupt(int i
286                 delta_cpu -= per_cpu(processed_system_time, cpu);
287  
288                 get_runstate_snapshot(&runstate);
289 -       } while (!time_values_up_to_date(cpu));
290 +       } while (!time_values_up_to_date());
291  
292         if ((unlikely(delta < -(s64)permitted_clock_jitter) ||
293              unlikely(delta_cpu < -(s64)permitted_clock_jitter))
294 --- sle11sp1-2010-03-29.orig/arch/x86/mm/hypervisor.c   2009-12-11 15:27:37.000000000 +0100
295 +++ sle11sp1-2010-03-29/arch/x86/mm/hypervisor.c        2010-01-05 16:47:18.000000000 +0100
296 @@ -41,6 +41,7 @@
297  #include <xen/balloon.h>
298  #include <xen/features.h>
299  #include <xen/interface/memory.h>
300 +#include <xen/interface/vcpu.h>
301  #include <linux/module.h>
302  #include <linux/percpu.h>
303  #include <linux/highmem.h>
304 @@ -50,7 +51,105 @@
305  EXPORT_SYMBOL(hypercall_page);
306  
307  shared_info_t *__read_mostly HYPERVISOR_shared_info = (shared_info_t *)empty_zero_page;
308 +#ifndef CONFIG_XEN_VCPU_INFO_PLACEMENT
309  EXPORT_SYMBOL(HYPERVISOR_shared_info);
310 +#else
311 +DEFINE_PER_CPU(struct vcpu_info, vcpu_info) __aligned(sizeof(struct vcpu_info));
312 +EXPORT_PER_CPU_SYMBOL(vcpu_info);
313 +
314 +void __ref setup_vcpu_info(unsigned int cpu)
315 +{
316 +       struct vcpu_info *v = &per_cpu(vcpu_info, cpu);
317 +       struct vcpu_register_vcpu_info info;
318 +#ifdef CONFIG_X86_64
319 +       static bool first = true;
320 +
321 +       if (first) {
322 +               first = false;
323 +               info.mfn = early_arbitrary_virt_to_mfn(v);
324 +       } else
325 +#endif
326 +               info.mfn = arbitrary_virt_to_mfn(v);
327 +       info.offset = offset_in_page(v);
328 +
329 +       if (HYPERVISOR_vcpu_op(VCPUOP_register_vcpu_info,
330 +                              cpu, &info))
331 +               BUG();
332 +}
333 +
334 +void __init adjust_boot_vcpu_info(void)
335 +{
336 +       unsigned long lpfn, rpfn, lmfn, rmfn;
337 +       pte_t *lpte, *rpte;
338 +       unsigned int level;
339 +       mmu_update_t mmu[2];
340 +
341 +       /*
342 +        * setup_vcpu_info() cannot be used more than once for a given (v)CPU,
343 +        * hence we must swap the underlying MFNs of the two pages holding old
344 +        * and new vcpu_info of the boot CPU.
345 +        *
346 +        * Do *not* use __get_cpu_var() or percpu_{write,...}() here, as the per-
347 +        * CPU segment didn't get reloaded yet. Using percpu_read(), as in
348 +        * arch_use_lazy_mmu_mode(), though undesirable, is safe except for the
349 +        * accesses to variables that were updated in setup_percpu_areas().
350 +        */
351 +       lpte = lookup_address((unsigned long)&per_cpu_var(vcpu_info)
352 +                             + (__per_cpu_load - __per_cpu_start),
353 +                             &level);
354 +       rpte = lookup_address((unsigned long)&per_cpu(vcpu_info, 0), &level);
355 +       BUG_ON(!lpte || !(pte_flags(*lpte) & _PAGE_PRESENT));
356 +       BUG_ON(!rpte || !(pte_flags(*rpte) & _PAGE_PRESENT));
357 +       lmfn = __pte_mfn(*lpte);
358 +       rmfn = __pte_mfn(*rpte);
359 +
360 +       if (lmfn == rmfn)
361 +               return;
362 +
363 +       lpfn = mfn_to_local_pfn(lmfn);
364 +       rpfn = mfn_to_local_pfn(rmfn);
365 +
366 +       printk(KERN_INFO
367 +              "Swapping MFNs for PFN %lx and %lx (MFN %lx and %lx)\n",
368 +              lpfn, rpfn, lmfn, rmfn);
369 +
370 +       xen_l1_entry_update(lpte, pfn_pte_ma(rmfn, pte_pgprot(*lpte)));
371 +       xen_l1_entry_update(rpte, pfn_pte_ma(lmfn, pte_pgprot(*rpte)));
372 +#ifdef CONFIG_X86_64
373 +       if (HYPERVISOR_update_va_mapping((unsigned long)__va(lpfn<<PAGE_SHIFT),
374 +                                        pfn_pte_ma(rmfn, PAGE_KERNEL_RO), 0))
375 +               BUG();
376 +#endif
377 +       if (HYPERVISOR_update_va_mapping((unsigned long)__va(rpfn<<PAGE_SHIFT),
378 +                                        pfn_pte_ma(lmfn, PAGE_KERNEL),
379 +                                        UVMF_TLB_FLUSH))
380 +               BUG();
381 +
382 +       set_phys_to_machine(lpfn, rmfn);
383 +       set_phys_to_machine(rpfn, lmfn);
384 +
385 +       mmu[0].ptr = ((uint64_t)lmfn << PAGE_SHIFT) | MMU_MACHPHYS_UPDATE;
386 +       mmu[0].val = rpfn;
387 +       mmu[1].ptr = ((uint64_t)rmfn << PAGE_SHIFT) | MMU_MACHPHYS_UPDATE;
388 +       mmu[1].val = lpfn;
389 +       if (HYPERVISOR_mmu_update(mmu, 2, NULL, DOMID_SELF))
390 +               BUG();
391 +
392 +       /*
393 +        * Copy over all contents of the page just replaced, except for the
394 +        * vcpu_info itself, as it may have got updated after having been
395 +        * copied from __per_cpu_load[].
396 +        */
397 +       memcpy(__va(rpfn << PAGE_SHIFT),
398 +              __va(lpfn << PAGE_SHIFT),
399 +              (unsigned long)&per_cpu_var(vcpu_info) & (PAGE_SIZE - 1));
400 +       level = (unsigned long)(&per_cpu_var(vcpu_info) + 1) & (PAGE_SIZE - 1);
401 +       if (level)
402 +               memcpy(__va(rpfn << PAGE_SHIFT) + level,
403 +                      __va(lpfn << PAGE_SHIFT) + level,
404 +                      PAGE_SIZE - level);
405 +}
406 +#endif
407  
408  #define NR_MC     BITS_PER_LONG
409  #define NR_MMU    BITS_PER_LONG
410 --- sle11sp1-2010-03-29.orig/arch/x86/mm/init_64-xen.c  2009-11-12 17:37:05.000000000 +0100
411 +++ sle11sp1-2010-03-29/arch/x86/mm/init_64-xen.c       2009-11-06 11:12:01.000000000 +0100
412 @@ -116,6 +116,26 @@ void __meminit early_make_page_readonly(
413                 BUG();
414  }
415  
416 +unsigned long __init early_arbitrary_virt_to_mfn(void *v)
417 +{
418 +       unsigned long va = (unsigned long)v, addr, *page;
419 +
420 +       BUG_ON(va < __START_KERNEL_map);
421 +
422 +       page = (void *)(xen_read_cr3() + __START_KERNEL_map);
423 +
424 +       addr = page[pgd_index(va)];
425 +       addr_to_page(addr, page);
426 +
427 +       addr = page[pud_index(va)];
428 +       addr_to_page(addr, page);
429 +
430 +       addr = page[pmd_index(va)];
431 +       addr_to_page(addr, page);
432 +
433 +       return (page[pte_index(va)] & PHYSICAL_PAGE_MASK) >> PAGE_SHIFT;
434 +}
435 +
436  #ifndef CONFIG_XEN
437  static int __init parse_direct_gbpages_off(char *arg)
438  {
439 --- sle11sp1-2010-03-29.orig/drivers/xen/Kconfig        2010-03-29 09:13:58.000000000 +0200
440 +++ sle11sp1-2010-03-29/drivers/xen/Kconfig     2010-03-29 09:14:20.000000000 +0200
441 @@ -366,6 +366,18 @@ config XEN_COMPAT
442         default 0x030002 if XEN_COMPAT_030002_AND_LATER
443         default 0
444  
445 +config XEN_VCPU_INFO_PLACEMENT
446 +       bool "Place shared vCPU info in per-CPU storage"
447 +#      depends on X86 && (XEN_COMPAT >= 0x00030101)
448 +       depends on X86
449 +       depends on !XEN_COMPAT_030002_AND_LATER
450 +       depends on !XEN_COMPAT_030004_AND_LATER
451 +       depends on !XEN_COMPAT_030100_AND_LATER
452 +       default SMP
453 +       ---help---
454 +         This allows faster access to the per-vCPU shared info
455 +         structure.
456 +
457  endmenu
458  
459  config HAVE_IRQ_IGNORE_UNHANDLED
460 --- sle11sp1-2010-03-29.orig/drivers/xen/core/evtchn.c  2010-02-09 17:19:07.000000000 +0100
461 +++ sle11sp1-2010-03-29/drivers/xen/core/evtchn.c       2010-02-09 17:20:42.000000000 +0100
462 @@ -316,6 +316,24 @@ static DEFINE_PER_CPU(unsigned int, upca
463  static DEFINE_PER_CPU(unsigned int, current_l1i);
464  static DEFINE_PER_CPU(unsigned int, current_l2i);
465  
466 +#ifndef vcpu_info_xchg
467 +#define vcpu_info_xchg(fld, val) xchg(&current_vcpu_info()->fld, val)
468 +#endif
469 +
470 +#ifndef percpu_xadd
471 +#define percpu_xadd(var, val)                                  \
472 +({                                                             \
473 +       typeof(per_cpu_var(var)) __tmp_var__;                   \
474 +       unsigned long flags;                                    \
475 +       local_irq_save(flags);                                  \
476 +       __tmp_var__ = get_cpu_var(var);                         \
477 +       __get_cpu_var(var) += (val);                            \
478 +       put_cpu_var(var);                                       \
479 +       local_irq_restore(flags);                               \
480 +       __tmp_var__;                                            \
481 +})
482 +#endif
483 +
484  /* NB. Interrupts are disabled on entry. */
485  asmlinkage void __irq_entry evtchn_do_upcall(struct pt_regs *regs)
486  {
487 @@ -324,25 +342,25 @@ asmlinkage void __irq_entry evtchn_do_up
488         unsigned long       masked_l1, masked_l2;
489         unsigned int        l1i, l2i, start_l1i, start_l2i, port, count, i;
490         int                 irq;
491 -       vcpu_info_t        *vcpu_info = current_vcpu_info();
492  
493         exit_idle();
494         irq_enter();
495  
496         do {
497                 /* Avoid a callback storm when we reenable delivery. */
498 -               vcpu_info->evtchn_upcall_pending = 0;
499 +               vcpu_info_write(evtchn_upcall_pending, 0);
500  
501                 /* Nested invocations bail immediately. */
502 -               percpu_add(upcall_count, 1);
503 -               if (unlikely(percpu_read(upcall_count) != 1))
504 +               if (unlikely(percpu_xadd(upcall_count, 1)))
505                         break;
506  
507  #ifndef CONFIG_X86 /* No need for a barrier -- XCHG is a barrier on x86. */
508                 /* Clear master flag /before/ clearing selector flag. */
509                 wmb();
510 +#else
511 +               barrier();
512  #endif
513 -               l1 = xchg(&vcpu_info->evtchn_pending_sel, 0);
514 +               l1 = vcpu_info_xchg(evtchn_pending_sel, 0);
515  
516                 start_l1i = l1i = percpu_read(current_l1i);
517                 start_l2i = percpu_read(current_l2i);
518 @@ -1369,7 +1387,6 @@ void unmask_evtchn(int port)
519  {
520         shared_info_t *s = HYPERVISOR_shared_info;
521         unsigned int cpu = smp_processor_id();
522 -       vcpu_info_t *vcpu_info = &s->vcpu_info[cpu];
523  
524         BUG_ON(!irqs_disabled());
525  
526 @@ -1383,10 +1400,13 @@ void unmask_evtchn(int port)
527         synch_clear_bit(port, s->evtchn_mask);
528  
529         /* Did we miss an interrupt 'edge'? Re-fire if so. */
530 -       if (synch_test_bit(port, s->evtchn_pending) &&
531 -           !synch_test_and_set_bit(port / BITS_PER_LONG,
532 -                                   &vcpu_info->evtchn_pending_sel))
533 -               vcpu_info->evtchn_upcall_pending = 1;
534 +       if (synch_test_bit(port, s->evtchn_pending)) {
535 +               vcpu_info_t *vcpu_info = current_vcpu_info();
536 +
537 +               if (!synch_test_and_set_bit(port / BITS_PER_LONG,
538 +                                           &vcpu_info->evtchn_pending_sel))
539 +                       vcpu_info->evtchn_upcall_pending = 1;
540 +       }
541  }
542  EXPORT_SYMBOL_GPL(unmask_evtchn);
543  
544 --- sle11sp1-2010-03-29.orig/drivers/xen/core/machine_reboot.c  2009-12-18 14:15:04.000000000 +0100
545 +++ sle11sp1-2010-03-29/drivers/xen/core/machine_reboot.c       2009-12-18 14:15:17.000000000 +0100
546 @@ -73,7 +73,7 @@ static void pre_suspend(void)
547                 mfn_to_pfn(xen_start_info->console.domU.mfn);
548  }
549  
550 -static void post_suspend(int suspend_cancelled)
551 +static void post_suspend(int suspend_cancelled, int fast_suspend)
552  {
553         int i, j, k, fpp;
554         unsigned long shinfo_mfn;
555 @@ -90,8 +90,21 @@ static void post_suspend(int suspend_can
556  #ifdef CONFIG_SMP
557                 cpumask_copy(vcpu_initialized_mask, cpu_online_mask);
558  #endif
559 -               for_each_possible_cpu(i)
560 +               for_each_possible_cpu(i) {
561                         setup_runstate_area(i);
562 +
563 +#ifdef CONFIG_XEN_VCPU_INFO_PLACEMENT
564 +                       if (fast_suspend && i != smp_processor_id()
565 +                           && HYPERVISOR_vcpu_op(VCPUOP_down, i, NULL))
566 +                               BUG();
567 +
568 +                       setup_vcpu_info(i);
569 +
570 +                       if (fast_suspend && i != smp_processor_id()
571 +                           && HYPERVISOR_vcpu_op(VCPUOP_up, i, NULL))
572 +                               BUG();
573 +#endif
574 +               }
575         }
576  
577         shinfo_mfn = xen_start_info->shared_info >> PAGE_SHIFT;
578 @@ -133,7 +146,7 @@ static void post_suspend(int suspend_can
579  #define switch_idle_mm()       ((void)0)
580  #define mm_pin_all()           ((void)0)
581  #define pre_suspend()          xen_pre_suspend()
582 -#define post_suspend(x)                xen_post_suspend(x)
583 +#define post_suspend(x, f)     xen_post_suspend(x)
584  
585  #endif
586  
587 @@ -164,7 +177,7 @@ static int take_machine_down(void *_susp
588                 BUG_ON(suspend_cancelled > 0);
589         suspend->resume_notifier(suspend_cancelled);
590         if (suspend_cancelled >= 0) {
591 -               post_suspend(suspend_cancelled);
592 +               post_suspend(suspend_cancelled, suspend->fast_suspend);
593                 sysdev_resume();
594         }
595         if (!suspend_cancelled) {
596 --- sle11sp1-2010-03-29.orig/drivers/xen/core/smpboot.c 2010-03-22 12:59:04.000000000 +0100
597 +++ sle11sp1-2010-03-29/drivers/xen/core/smpboot.c      2010-03-22 12:59:52.000000000 +0100
598 @@ -369,8 +369,13 @@ void __init smp_prepare_cpus(unsigned in
599  
600  void __init smp_prepare_boot_cpu(void)
601  {
602 +       unsigned int cpu;
603 +
604         switch_to_new_gdt(smp_processor_id());
605         prefill_possible_map();
606 +       for_each_possible_cpu(cpu)
607 +               if (cpu != smp_processor_id())
608 +                       setup_vcpu_info(cpu);
609  }
610  
611  #ifdef CONFIG_HOTPLUG_CPU
612 --- sle11sp1-2010-03-29.orig/drivers/xen/core/spinlock.c        2010-03-22 12:58:39.000000000 +0100
613 +++ sle11sp1-2010-03-29/drivers/xen/core/spinlock.c     2010-03-22 12:59:54.000000000 +0100
614 @@ -104,7 +104,7 @@ bool xen_spin_wait(raw_spinlock_t *lock,
615         spinning.prev = percpu_read(spinning);
616         smp_wmb();
617         percpu_write(spinning, &spinning);
618 -       upcall_mask = current_vcpu_info()->evtchn_upcall_mask;
619 +       upcall_mask = vcpu_info_read(evtchn_upcall_mask);
620  
621         do {
622                 bool nested = false;
623 @@ -170,12 +170,12 @@ bool xen_spin_wait(raw_spinlock_t *lock,
624                  * intended event processing will happen with the poll
625                  * call.
626                  */
627 -               current_vcpu_info()->evtchn_upcall_mask =
628 -                       nested ? upcall_mask : flags;
629 +               vcpu_info_write(evtchn_upcall_mask,
630 +                               nested ? upcall_mask : flags);
631  
632                 xen_poll_irq(irq);
633  
634 -               current_vcpu_info()->evtchn_upcall_mask = upcall_mask;
635 +               vcpu_info_write(evtchn_upcall_mask, upcall_mask);
636  
637                 rc = !xen_test_irq_pending(irq);
638                 if (!rc)