[Devel] [PATCH RHEL7 COMMIT] ve/printk/ppc: fix asm modifier in DEFINE_STRUCT_MEMBER_ALIAS
Konstantin Khorenko
khorenko at odin.com
Thu May 7 09:28:18 PDT 2015
The commit is pushed to "branch-rh7-3.10.0-123.1.2-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-123.1.2.vz7.4.10
------>
commit d2b8e29be14cbd4da0b641156fffd9204ca0d70a
Author: Vladimir Davydov <vdavydov at parallels.com>
Date: Thu May 7 20:28:18 2015 +0400
ve/printk/ppc: fix asm modifier in DEFINE_STRUCT_MEMBER_ALIAS
This was found while tring to compile the kernel with a stock
config (i.e. no CONFIG_BEANCOUNTERS, CONFIG_VE etc.) and
boot it on IBM Power8.
=============================================================
gcc fails to parse %a0 on PPC for some reason.
Use conventional %c0 instead.
> â%cdigitâ can be used to substitute an operand that is a constant
> value without the syntax that normally indicates an immediate operand.
[...]
> â%adigitâ can be used to substitute an operand as if it were a memory
> reference, with the actual operand treated as the address. This may be
> useful when outputting a âload addressâ instruction, because often the
> assembler syntax for such an instruction requires you to write the
> operand as if it were a memory reference.
(Source: https://gcc.gnu.org/onlinedocs/gccint/Output-Template.html#Output-Template)
Also from GCC source code (gcc/final.c):
> /* Output text from TEMPLATE to the assembler output file,
> obeying %-directions to substitute operands taken from
> the vector OPERANDS.
>
> %N (for N a digit) means print operand N in usual manner.
> %lN means require operand N to be a CODE_LABEL or LABEL_REF
> and print the label name with no punctuation.
> %cN means require operand N to be a constant
> and print the constant expression with no punctuation.
> %aN means expect operand N to be a memory address
> (not a memory reference!) and print a reference
> to that address.
> %nN means expect operand N to be a constant
> and print a constant expression for minus the value
> of the operand, with no other punctuation. */
I want to define log_buf, log_buf_len, etc as aliases for
init_log_state.buf, init_log_state.buf_len, etc. So for log_buf_len
(offset 0x8 in struct log_state on 64 bit) I want to generate
.globl log_buf_len
.set log_buf_len, init_log_state+0x8
^^^
NOTE: No punctuation here
(no $ sign, which is prepended if "%N" is used)
So I obviously should have used "%cN", because it explicitly states:
"constant expression with no punctuation".
It turns out that "%aN" also fits on Linux/x86, because it seems that a
memory address can always be used as a memory offset. However, it seems
that on Linux/PPC gcc expects a memory address to be in some specific
range, otherwise it just crashes, so that offset and address are
orthogonal things.
Hope this explains the magic behind this patch.
Signed-off-by: Vladimir Davydov <vdavydov at parallels.com>
---
kernel/printk.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/kernel/printk.c b/kernel/printk.c
index 9ee2b80..51805a54 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -293,7 +293,7 @@ static struct log_state {
static void ____ ## name ## _definition(void) __attribute__((used)); \
static void ____ ## name ## _definition(void) \
{ \
- asm (".globl " #name "\n\t.set " #name ", " #inst "+%a0" \
+ asm (".globl " #name "\n\t.set " #name ", " #inst "+%c0" \
: : "g" (offsetof(typeof(inst), memb))); \
} \
extern typeof(inst.memb) name;
More information about the Devel
mailing list