[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-ia64-devel] GET_THIS_PADDR appears to be broken



GET_THIS_PADDR() doesn't appear to work correclty
on xen-ia64-unstable.hg 15165:96331db61e47

Long-winded description of why

  cpu_data           = 0xf000000004410000
  ia64_tpa(cpu_data) = 0x0000000004410000
  __per_cpu_start    = 0x0003ffffffff0000

  ia64_set_kr(IA64_KR_PER_CPU_DATA,
              ia64_tpa(cpu_data) - (long) __per_cpu_start);
  ar.k3              = ia64_tpa(cpu_data) - __per_cpu_start;
                     = 0x0000000004410000 - 0xf000000004410000
                   = 0x0f00000004420000 # N.B Underflow

  #ifdef XEN
  #define GET_THIS_PADDR(reg, var)                        \
          mov        reg = IA64_KR(PER_CPU_DATA);;        \
          addl       reg = THIS_CPU(var) - PERCPU_ADDR, reg
  #else
  #define GET_THIS_PADDR(reg, var)                        \
          mov        reg = IA64_KR(PER_CPU_DATA);;        \
          addl       reg = THIS_CPU(var), reg
  #endif


  IA64_KR(PER_CPU_DATA)       = ar.k3
                              = 0x0f00000004420000
  THIS_CPU(ia64_mca_pal_base) = &per_cpu__ia64_mca_pal_bas
                              = 0xf0ffffffffff0320
  PERCPU_ADDR                 = 0xf0ffffffffff0000

  GET_THIS_PADDR(r2, ia64_mca_pal_base)
                           r2 = (THIS_CPU(ia64_mca_pal_base) - PERCPU_ADDR) +
                                IA64_KR(PER_CPU_DATA)
                              = (0xf0ffffffffff0320 - 0xf0ffffffffff0000) +
                                0x0f00000004420000
                              = 0x0000000000000320 + 0x0f00000004420000
                              = 0x0f00000004420320 # N.B Overflow

  On the machine in question 0x0f00000004420320 is not a valid
  physical address.

  But if we use the linux version of GET_THIS_PADDR, here is
  how things pan out.

  GET_THIS_PADDR(r2, ia64_mca_pal_base)
                           r2 = THIS_CPU(ia64_mca_pal_base) +
                                IA64_KR(PER_CPU_DATA)
                              = 0xf0ffffffffff0320 + 0x0f00000004420000
                              = 0x0000000004410320 # N.B Overflow

  By inspection I was able to determine that 0x0000000004410320 is the
  correct physical address.

  It can also be derived using the following calculation, which is
  in some ways a little clearer as it doesn't include underflow
  or overflow.

  r2 = (THIS_CPU(ia64_mca_pal_base) - PERCPU_ADDR) + ia64_tpa(cpu_data)
     = (0xf0ffffffffff0320 - 0xf0ffffffffff0000) + 0x0000000004410000
     = 0x0000000000000320 + 0x0000000004410000
     = 0x0000000004410320

Solution 1

Use the Linux variant of GET_THIS_PADDR(reg, var)

  #define GET_THIS_PADDR(reg, var)                        \
          mov        reg = IA64_KR(PER_CPU_DATA);;        \
          addl       reg = THIS_CPU(var), reg

This seems like a simple and logical solition that accodring to the
maths above should work. However, when I try to compile this
I get a relocation error.

ia64-unknown-linux-gnu-ld -g -T xen.lds.s -N \
                -Map map.out linux-xen/head.o 
/home/horms/work/xen/xen-ia64-unstable.hg/xen/common/built_in.o 
/home/horms/work/xen/xen-ia64-unstable.hg/xen/drivers/built_in.o 
/home/horms/work/xen/xen-ia64-unstable.hg/xen/arch/ia64/built_in.o \
                
/home/horms/work/xen/xen-ia64-unstable.hg/xen/common/symbols-dummy.o -o 
/home/horms/work/xen/xen-ia64-unstable.hg/xen/xen-syms
/home/horms/work/xen/xen-ia64-unstable.hg/xen/arch/ia64/linux-xen/mca_asm.S:271:
 relocation truncated to fit: IMM22 against symbol `per_cpu__ia64_mca_pal_base' 
defined in .data.percpu section in 
/home/horms/work/xen/xen-ia64-unstable.hg/xen/arch/ia64/built_in.o

I'm not really sure what that means, other than that
per_cpu__ia64_mca_pal_base aka THIS_CPU(ia64_mca_pal_base)
ought to be a 22bit integer, which it isn't.

I also noticed that the assembled code on xen and linux differ.
Though I'm no linker expert, so I don't understand why.

  Linux
  # objdump -D arch/ia64/kernel/built-in.o
  00000000000000f8 <per_cpu__ia64_mca_pal_base>:
  f8:   00 00 00 00 00 00                   break.i 0x0


  Xen
  # objdump -D arch/ia64/built_in.o
  00000000000000a0 <per_cpu__ia64_mca_pal_base>:
  a0:   00 00 00 00 00 00       [MII]       break.m 0x0

Solution 2

  Change the value that is stored in ar.k3
  from ia64_tpa(cpu_data) - __per_cpu_start
  to simply ia64_tpa(cpu_data)

  This reduces GET_THIS_PADDR() to
  (THIS_CPU(ia64_mca_pal_base) - PERCPU_ADDR) + ia64_tpa(cpu_data)
  which has been shown to be correct above.

  This isn't an entirely ideal solution as it uneccesarily
  diverges both ar.k3 and GET_THIS_PADDR() from the Linux versions,
  however testing shows that it does seem to work.

Previous Solutions

  Until 12448:efb346a02e70 there was a tpa based version of
  GET_THIS_PADDR().

   #define GET_THIS_PADDR(reg, var)             \
        movl    reg = THIS_CPU(var)             \
        tpa     reg = reg

  It did not appear to work in the tests I ran either.
  Even after adding ;; after THIS_CPU(var)
  But I didn't persevere for very long.


Index: xen-ia64-unstable.hg/xen/arch/ia64/linux-xen/setup.c
===================================================================
--- xen-ia64-unstable.hg.orig/xen/arch/ia64/linux-xen/setup.c   2007-06-27 
18:16:19.000000000 +0900
+++ xen-ia64-unstable.hg/xen/arch/ia64/linux-xen/setup.c        2007-06-27 
18:16:22.000000000 +0900
@@ -918,7 +918,11 @@ cpu_init (void)
         *   phys = ar.k3 + &per_cpu_var
         */
        ia64_set_kr(IA64_KR_PER_CPU_DATA,
+#ifdef XEN
+                   ia64_tpa(cpu_data));
+#else
                    ia64_tpa(cpu_data) - (long) __per_cpu_start);
+#endif
 
        get_max_cacheline_size();
 


_______________________________________________
Xen-ia64-devel mailing list
Xen-ia64-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-ia64-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.