Hi, all,
I have a question. Why shall we need a RELOC_HIDE() macro in the
definition of per_cpu()? Maybe the question is actually why we need
macro RELOC_HIDE() at all. I changed the following line in
include/asm-generic/percpu.h, from
#define per_cpu(var, cpu) (*RELOC_HIDE(&per_cpu__##var, __per_cpu_offset[cpu]))
to
#define per_cpu(var, cpu) (*((unsigned long)(&per_cpu__##var) +
__per_cpu_offset[cpu]))
I recompiled the code and it works well on my Intel Dual-core laptop.
It essentially the same as to change the definition of RELOC_HIDE(),
from
#define RELOC_HIDE(ptr, off) \
({ unsigned long __ptr; \
__asm__ ("" : "=r"(__ptr) : "0"(ptr)); \
(typeof(ptr)) (__ptr + (off)); })
to
#define RELOC_HIDE(ptr, off) \
({ unsigned long __ptr; \
__ptr = (unsigned long)ptr; \
(typeof(ptr)) (__ptr + (off)); })
Why shouldn't we have a pure C solution in this part?
Best Regards.
Feng,Dong
Hi, all,
I have a question. Why shall we need a RELOC_HIDE() macro in the
definition of per_cpu()? Maybe the question is actually why we need
macro RELOC_HIDE() at all. I changed the following line in
include/asm-generic/percpu.h, from
#define per_cpu(var, cpu) (*RELOC_HIDE(&per_cpu__##var, __per_cpu_offset[cpu]))
to
#define per_cpu(var, cpu) (*((unsigned long)(&per_cpu__##var) +
__per_cpu_offset[cpu]))
I recompiled the code and it works well on my Intel Dual-core laptop.
It essentially the same as to change the definition of RELOC_HIDE(),
from
#define RELOC_HIDE(ptr, off) \
({ unsigned long __ptr; \
__asm__ ("" : "=r"(__ptr) : "0"(ptr)); \
(typeof(ptr)) (__ptr + (off)); })
to
#define RELOC_HIDE(ptr, off) \
({ unsigned long __ptr; \
__ptr = (unsigned long)ptr; \
(typeof(ptr)) (__ptr + (off)); })
Why shouldn't we have a pure C solution in this part?
Best Regards.
Feng,Dong
On Wed, 23 Aug 2006, Dong Feng wrote:
> I have a question. Why shall we need a RELOC_HIDE() macro in the
> definition of per_cpu()? Maybe the question is actually why we need
> macro RELOC_HIDE() at all. I changed the following line in
> include/asm-generic/percpu.h, from
Guess it was copied from IA64 but the semantics were not preserved.
I think it should either be changed the way you suggest or the
implementation needs to be fixed to actually do a linker relocation.
On Thursday 24 August 2006 20:26, Christoph Lameter wrote:
> On Wed, 23 Aug 2006, Dong Feng wrote:
>
> > I have a question. Why shall we need a RELOC_HIDE() macro in the
> > definition of per_cpu()? Maybe the question is actually why we need
> > macro RELOC_HIDE() at all. I changed the following line in
> > include/asm-generic/percpu.h, from
>
> Guess it was copied from IA64 but the semantics were not preserved.
> I think it should either be changed the way you suggest or the
> implementation needs to be fixed to actually do a linker relocation.
The reason the original code is like it is because gcc assumes there
is no wrapping on arithmetic on symbol addresses (it is allowed to assume
that because it is undefined in the C standard). And in same cases wrapping
can happen. There was at least one miscompilation in the past that lead to the
current construct.
-Andi
Christoph Lameter writes:
> On Wed, 23 Aug 2006, Dong Feng wrote:
>
> > I have a question. Why shall we need a RELOC_HIDE() macro in the
> > definition of per_cpu()? Maybe the question is actually why we need
> > macro RELOC_HIDE() at all. I changed the following line in
> > include/asm-generic/percpu.h, from
>
> Guess it was copied from IA64 but the semantics were not preserved.
> I think it should either be changed the way you suggest or the
> implementation needs to be fixed to actually do a linker relocation.
No, RELOC_HIDE came from ppc originally. The reason for it is that
gcc assumes that if you add something on to the address of a symbol,
the resulting address is still inside the bounds of the symbol, and do
optimizations based on that. The RELOC_HIDE macro is designed to
prevent gcc knowing that the resulting pointer is obtained by adding
an offset to the address of a symbol. As far as gcc knows, the
resulting pointer could point to anything.
It has nothing to do with linker relocations.
Paul.
Sorry for perhaps extending the specific question to a more generic
one. In which cases shall we, in current or future development,
prevent gcc from knowing a pointer-addition in the way RELOC_HIDE? And
in what cases shall we just write pure C point addition?
After all, we are writing an OS in C not in pure assembly, so I am
just trying to learn some generial rules to mimize the raw assembly in
development.
Feng,Dong
2006/8/25, Paul Mackerras <[email protected]>:
> Christoph Lameter writes:
>
> No, RELOC_HIDE came from ppc originally. The reason for it is that
> gcc assumes that if you add something on to the address of a symbol,
> the resulting address is still inside the bounds of the symbol, and do
> optimizations based on that. The RELOC_HIDE macro is designed to
> prevent gcc knowing that the resulting pointer is obtained by adding
> an offset to the address of a symbol. As far as gcc knows, the
> resulting pointer could point to anything.
>
> It has nothing to do with linker relocations.
>
> Paul.
Dong Feng writes:
> Sorry for perhaps extending the specific question to a more generic
> one. In which cases shall we, in current or future development,
> prevent gcc from knowing a pointer-addition in the way RELOC_HIDE? And
> in what cases shall we just write pure C point addition?
Where you are saying to gcc "you think this variable is at this
address, but I know it's actually at this other address over here" you
should use RELOC_HIDE. Where the addition is being used to get the
address of some part of the object (so the resulting address is still
within the object) you can just use plain addition.
Paul.
On Friday 25 August 2006 03:30, Dong Feng wrote:
> Sorry for perhaps extending the specific question to a more generic
> one. In which cases shall we, in current or future development,
> prevent gcc from knowing a pointer-addition in the way RELOC_HIDE? And
> in what cases shall we just write pure C point addition?
>
> After all, we are writing an OS in C not in pure assembly, so I am
> just trying to learn some generial rules to mimize the raw assembly in
> development.
In theory anything that is undefined in the C standard should be avoided
because gcc is free to make assumptions about it and generate unexpected
code.
In practice Linux does a lot of not-quite-legal-in-portable-C things
already, but tries to avoid areas that are known to have miscompiled in
the past.
Best is to avoid undefined behaviour in new code.
-Andi
Andi Kleen writes:
> Best is to avoid undefined behaviour in new code.
Of course. But do you have a way to implement per_cpu() without it?
Paul.
On Friday 25 August 2006 09:20, Paul Mackerras wrote:
> Andi Kleen writes:
>
> > Best is to avoid undefined behaviour in new code.
>
> Of course. But do you have a way to implement per_cpu() without it?
I was describing the ideal, not the practical reality.
-Andi