[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