8 messages in com.xensource.lists.xen-ia64-devel[Xen-ia64-devel] GET_THIS_PADDR appea...| From | Sent On | Attachments |
|---|---|---|
| Horms | 27 Jun 2007 02:59 | |
| tgin...@free.fr | 27 Jun 2007 05:18 | |
| Horms | 27 Jun 2007 06:38 | |
| tgin...@free.fr | 27 Jun 2007 08:30 | |
| Horms | 27 Jun 2007 18:11 | |
| Tristan Gingold | 27 Jun 2007 20:07 | |
| Tristan Gingold | 27 Jun 2007 20:14 | |
| Horms | 27 Jun 2007 21:17 |
| Subject: | [Xen-ia64-devel] GET_THIS_PADDR appears to be broken![]() |
|---|---|
| From: | Horms (hor...@verge.net.au) |
| Date: | 06/27/2007 02:59:35 AM |
| List: | com.xensource.lists.xen-ia64-devel |
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-...@lists.xensource.com http://lists.xensource.com/xen-ia64-devel




