Merge commit 'v2.6.26-rc8' into x86/xen
Ingo Molnar [Wed, 25 Jun 2008 10:16:51 +0000 (12:16 +0200)]
Conflicts:

arch/x86/xen/enlighten.c
arch/x86/xen/mmu.c

Signed-off-by: Ingo Molnar <mingo@elte.hu>

1  2 
arch/x86/xen/Kconfig
arch/x86/xen/time.c

diff --combined arch/x86/xen/Kconfig
@@@ -5,19 -5,10 +5,20 @@@
  config XEN
        bool "Xen guest support"
        select PARAVIRT
+       select PARAVIRT_CLOCK
        depends on X86_32
        depends on X86_CMPXCHG && X86_TSC && X86_PAE && !(X86_VISWS || X86_VOYAGER)
        help
          This is the Linux Xen port.  Enabling this will allow the
          kernel to boot in a paravirtualized environment under the
          Xen hypervisor.
 +
 +config XEN_MAX_DOMAIN_MEMORY
 +       int "Maximum allowed size of a domain in gigabytes"
 +       default 8
 +       depends on XEN
 +       help
 +         The pseudo-physical to machine address array is sized
 +         according to the maximum possible memory size of a Xen
 +         domain.  This array uses 1 page per gigabyte, so there's no
 +         need to be too stingy here.
diff --combined arch/x86/xen/time.c
@@@ -14,6 -14,7 +14,7 @@@
  #include <linux/kernel_stat.h>
  #include <linux/math64.h>
  
+ #include <asm/pvclock.h>
  #include <asm/xen/hypervisor.h>
  #include <asm/xen/hypercall.h>
  
  
  static cycle_t xen_clocksource_read(void);
  
- /* These are perodically updated in shared_info, and then copied here. */
- struct shadow_time_info {
-       u64 tsc_timestamp;     /* TSC at last update of time vals.  */
-       u64 system_timestamp;  /* Time, in nanosecs, since boot.    */
-       u32 tsc_to_nsec_mul;
-       int tsc_shift;
-       u32 version;
- };
- static DEFINE_PER_CPU(struct shadow_time_info, shadow_time);
  /* runstate info updated by Xen */
  static DEFINE_PER_CPU(struct vcpu_runstate_info, runstate);
  
@@@ -211,7 -201,7 +201,7 @@@ unsigned long long xen_sched_clock(void
  unsigned long xen_cpu_khz(void)
  {
        u64 xen_khz = 1000000ULL << 32;
-       const struct vcpu_time_info *info =
+       const struct pvclock_vcpu_time_info *info =
                &HYPERVISOR_shared_info->vcpu_info[0].time;
  
        do_div(xen_khz, info->tsc_to_system_mul);
        return xen_khz;
  }
  
- /*
-  * Reads a consistent set of time-base values from Xen, into a shadow data
-  * area.
-  */
- static unsigned get_time_values_from_xen(void)
- {
-       struct vcpu_time_info   *src;
-       struct shadow_time_info *dst;
-       /* src is shared memory with the hypervisor, so we need to
-          make sure we get a consistent snapshot, even in the face of
-          being preempted. */
-       src = &__get_cpu_var(xen_vcpu)->time;
-       dst = &__get_cpu_var(shadow_time);
-       do {
-               dst->version = src->version;
-               rmb();          /* fetch version before data */
-               dst->tsc_timestamp     = src->tsc_timestamp;
-               dst->system_timestamp  = src->system_time;
-               dst->tsc_to_nsec_mul   = src->tsc_to_system_mul;
-               dst->tsc_shift         = src->tsc_shift;
-               rmb();          /* test version after fetching data */
-       } while ((src->version & 1) | (dst->version ^ src->version));
-       return dst->version;
- }
- /*
-  * Scale a 64-bit delta by scaling and multiplying by a 32-bit fraction,
-  * yielding a 64-bit result.
-  */
- static inline u64 scale_delta(u64 delta, u32 mul_frac, int shift)
- {
-       u64 product;
- #ifdef __i386__
-       u32 tmp1, tmp2;
- #endif
-       if (shift < 0)
-               delta >>= -shift;
-       else
-               delta <<= shift;
- #ifdef __i386__
-       __asm__ (
-               "mul  %5       ; "
-               "mov  %4,%%eax ; "
-               "mov  %%edx,%4 ; "
-               "mul  %5       ; "
-               "xor  %5,%5    ; "
-               "add  %4,%%eax ; "
-               "adc  %5,%%edx ; "
-               : "=A" (product), "=r" (tmp1), "=r" (tmp2)
-               : "a" ((u32)delta), "1" ((u32)(delta >> 32)), "2" (mul_frac) );
- #elif __x86_64__
-       __asm__ (
-               "mul %%rdx ; shrd $32,%%rdx,%%rax"
-               : "=a" (product) : "0" (delta), "d" ((u64)mul_frac) );
- #else
- #error implement me!
- #endif
-       return product;
- }
- static u64 get_nsec_offset(struct shadow_time_info *shadow)
- {
-       u64 now, delta;
-       now = native_read_tsc();
-       delta = now - shadow->tsc_timestamp;
-       return scale_delta(delta, shadow->tsc_to_nsec_mul, shadow->tsc_shift);
- }
  static cycle_t xen_clocksource_read(void)
  {
-       struct shadow_time_info *shadow = &get_cpu_var(shadow_time);
+         struct pvclock_vcpu_time_info *src;
        cycle_t ret;
-       unsigned version;
-       do {
-               version = get_time_values_from_xen();
-               barrier();
-               ret = shadow->system_timestamp + get_nsec_offset(shadow);
-               barrier();
-       } while (version != __get_cpu_var(xen_vcpu)->time.version);
-       put_cpu_var(shadow_time);
  
+       src = &get_cpu_var(xen_vcpu)->time;
+       ret = pvclock_clocksource_read(src);
+       put_cpu_var(xen_vcpu);
        return ret;
  }
  
  static void xen_read_wallclock(struct timespec *ts)
  {
-       const struct shared_info *s = HYPERVISOR_shared_info;
-       u32 version;
-       u64 delta;
-       struct timespec now;
-       /* get wallclock at system boot */
-       do {
-               version = s->wc_version;
-               rmb();          /* fetch version before time */
-               now.tv_sec  = s->wc_sec;
-               now.tv_nsec = s->wc_nsec;
-               rmb();          /* fetch time before checking version */
-       } while ((s->wc_version & 1) | (version ^ s->wc_version));
+       struct shared_info *s = HYPERVISOR_shared_info;
+       struct pvclock_wall_clock *wall_clock = &(s->wc);
+         struct pvclock_vcpu_time_info *vcpu_time;
  
-       delta = xen_clocksource_read(); /* time since system boot */
-       delta += now.tv_sec * (u64)NSEC_PER_SEC + now.tv_nsec;
-       now.tv_nsec = do_div(delta, NSEC_PER_SEC);
-       now.tv_sec = delta;
-       set_normalized_timespec(ts, now.tv_sec, now.tv_nsec);
+       vcpu_time = &get_cpu_var(xen_vcpu)->time;
+       pvclock_read_wallclock(wall_clock, vcpu_time, ts);
+       put_cpu_var(xen_vcpu);
  }
  
  unsigned long xen_get_wallclock(void)
        struct timespec ts;
  
        xen_read_wallclock(&ts);
        return ts.tv_sec;
  }
  
@@@ -565,25 -459,10 +459,23 @@@ void xen_setup_cpu_clockevents(void
        clockevents_register_device(&__get_cpu_var(xen_clock_events));
  }
  
 +void xen_timer_resume(void)
 +{
 +      int cpu;
 +
 +      if (xen_clockevent != &xen_vcpuop_clockevent)
 +              return;
 +
 +      for_each_online_cpu(cpu) {
 +              if (HYPERVISOR_vcpu_op(VCPUOP_stop_periodic_timer, cpu, NULL))
 +                      BUG();
 +      }
 +}
 +
  __init void xen_time_init(void)
  {
        int cpu = smp_processor_id();
  
-       get_time_values_from_xen();
        clocksource_register(&xen_clocksource);
  
        if (HYPERVISOR_vcpu_op(VCPUOP_stop_periodic_timer, cpu, NULL) == 0) {