Building for 32-bit RISC-V kernel
Subsystems (2)
cover Building for 32-bit RISC-V kernel
These patches are for building 32-bit RISC-V kernel.
- Fix the compile errors and warnings on RV32I.
- Fix some incompatible problem on RV32I.
- Add format.h for compatible of print format.
Zong Li (5):
RISC-V: Add conditional macro for zone of DMA32
RISC-V: Select GENERIC_UCMPDI2 on RV32I
RISC-V: Add definiion of extract symbol's index and type for 32-bit
RISC-V: Change variable type for 32-bit compatible
RISC-V: Use fixed width integer types for 32-bit compatible
arch/riscv/Kconfig | 1 + arch/riscv/include/asm/format.h | 20 ++++++++++++++++++++ arch/riscv/include/uapi/asm/elf.h | 9 +++++++-- arch/riscv/kernel/module.c | 35 ++++++++++++++++++----------------- arch/riscv/mm/init.c | 3 +++ 5 files changed, 49 insertions(+), 19 deletions(-) create mode 100644 arch/riscv/include/asm/format.h
Signature · 1 line
2.16.1
PATCH 1/5 RISC-V: Add conditional macro for zone of DMA32
The DMA32 is for 64-bit usage.
--- arch/riscv/mm/init.c | 3 +++ 1 file changed, 3 insertions(+)
arch/riscv/mm/init.c +3 -0
@@ -28,8 +28,11 @@ static void __init zone_sizes_init(void) {unsigned long max_zone_pfns[MAX_NR_ZONES ] = {0 , }; +#ifdef CONFIG_ZONE_DMA32 max_zone_pfns[ZONE_DMA32 ] =PFN_DOWN (min (4UL *SZ_1G , max_low_pfn)); +#else max_zone_pfns[ZONE_NORMAL ] = max_low_pfn; +#endif free_area_init_nodes (max_zone_pfns); }
Signature · 1 line
2.16.1
Re: [PATCH 1/5] RISC-V: Add conditional macro for zone of DMA32
Quoted 12 lines · Zong Li
The DMA32 is for 64-bit usage.
Signed-off-by Zong Li <[email protected]>--- arch/riscv/mm/init.c | 3 +++ 1 file changed, 3 insertions(+)arch/riscv/mm/init.c +0
-0
arch/riscv/mm/init.c static void __init zone_sizes_init(void) · line 35
Quoted 8 lines
arch/riscv/mm/init.c +3
-0@@ -28,8 +28,11 @@ static void __init zone_sizes_init(void) {unsigned long max_zone_pfns[MAX_NR_ZONES ] = {0 , }; +#ifdef CONFIG_ZONE_DMA32 max_zone_pfns[ZONE_DMA32 ] =PFN_DOWN (min (4UL *SZ_1G , max_low_pfn)); +#else max_zone_pfns[ZONE_NORMAL ] = max_low_pfn; +#endif
This breaks the 64-bit setup. The second line needs to be kept for the CONFIG_ZONE_DMA32 case.
Re: [PATCH 1/5] RISC-V: Add conditional macro for zone of DMA32
Christoph Hellwig <[email protected]> ? 2018?6?21? ?? ??2:40???
Quoted 17 lines · Zong Li
Quoted 15 lines
The DMA32 is for 64-bit usage.
Signed-off-by Zong Li <[email protected]>--- arch/riscv/mm/init.c | 3 +++ 1 file changed, 3 insertions(+)arch/riscv/mm/init.c +0
-0@@ -28,8 +28,11 @@ static void __init zone_sizes_init(void) {unsigned long max_zone_pfns[MAX_NR_ZONES ] = {0 , };
Quoted 8 lines
arch/riscv/mm/init.c static void __init zone_sizes_init(void) · line 35
Quoted 5 lines
arch/riscv/mm/init.c +3
-0+#ifdef CONFIG_ZONE_DMA32 max_zone_pfns[ZONE_DMA32 ] =PFN_DOWN (min (4UL *SZ_1G , max_low_pfn)); +#else max_zone_pfns[ZONE_NORMAL ] = max_low_pfn; +#endif This breaks the 64-bit setup. The second line needs to be kept for the
CONFIG_ZONE_DMA32case.
Yes, it should be
#ifdef CONFIG_ZONE_DMA32
max_zone_pfns[ZONE_DMA32] = PFN_DOWN(min(4UL * SZ_1G, max_low_pfn));
#endif
max_zone_pfns[ZONE_NORMAL] = max_low_pfn;Thanks!
PATCH 1/1 RISC-V: Add conditional marco for boot_sec_cpu
In reply to Zong LiFix link error when disable support SMP. It causes the undefined reference to `smp_callin'.
--- arch/riscv/kernel/head.S | 2 ++ 1 file changed, 2 insertions(+)
arch/riscv/kernel/head.S +2 -0
@@ -152,6 +152,7 @@ END(_start) .section .text .global boot_sec_cpu +#ifdef CONFIG_HOTPLUG_CPU boot_sec_cpu: /* clear all pending flags */ csrw sip, zero
@@ -160,6 +161,7 @@ boot_sec_cpu: fence tail smp_callin +#endif __PAGE_ALIGNED_BSS /* Empty zero page */
Signature · 1 line
2.16.1
PATCH 2/5 RISC-V: Select GENERIC_UCMPDI2 on RV32I
In reply to Zong LiOn 32-bit, it need to use __ucmpdi2, otherwise, it can't find the __ucmpdi2 symbol.
--- arch/riscv/Kconfig | 1 + 1 file changed, 1 insertion(+)
arch/riscv/Kconfig +1 -0
@@ -122,6 +122,7 @@ config ARCH_RV32I select GENERIC_ASHLDI3 select GENERIC_ASHRDI3 select GENERIC_LSHRDI3 + select GENERIC_UCMPDI2 config ARCH_RV64I bool "RV64I"
Signature · 1 line
2.16.1
PATCH 3/5 RISC-V: Add definiion of extract symbol's index and type for 32-bit
In reply to Zong LiUse generic marco to get the index and type of symbol.
--- arch/riscv/include/uapi/asm/elf.h | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
arch/riscv/include/uapi/asm/elf.h +7 -2
@@ -21,8 +21,13 @@ typedef struct user_regs_struct elf_gregset_t;typedef union __riscv_fp_state elf_fpregset_t ; -#define ELF_RISCV_R_SYM (r_info) ((r_info) >> 32) -#define ELF_RISCV_R_TYPE (r_info) ((r_info) & 0xffffffff) +#if __riscv_xlen ==64 +#define ELF_RISCV_R_SYM (r_info) ELF64_R_SYM(r_info) +#define ELF_RISCV_R_TYPE (r_info) ELF64_R_TYPE(r_info) +#else +#define ELF_RISCV_R_SYM (r_info) ELF32_R_SYM(r_info) +#define ELF_RISCV_R_TYPE (r_info) ELF32_R_TYPE(r_info) +#endif /* * RISC-V relocation types
Signature · 1 line
2.16.1
PATCH 4/5 RISC-V: Change variable type for 32-bit compatible
In reply to Zong Li--- arch/riscv/kernel/module.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-)
arch/riscv/kernel/module.c +11 -11
@@ -39,7 +39,7 @@ static int apply_r_riscv_64_rela(struct module *me, u32 *location, Elf_Addr v)static int apply_r_riscv_branch_rela (struct module *me,u32 *location,Elf_Addr v) { -s64 offset = (void *)v - (void *)location; +uintptr_t offset = (void *)v - (void *)location;u32 imm12 = (offset &0x1000 ) << (31 -12 );u32 imm11 = (offset &0x800 ) >> (11 -7 );u32 imm10_5 = (offset &0x7e0 ) << (30 -10 );
@@ -52,7 +52,7 @@ static int apply_r_riscv_branch_rela(struct module *me, u32 *location,static int apply_r_riscv_jal_rela (struct module *me,u32 *location,Elf_Addr v) { -s64 offset = (void *)v - (void *)location; +uintptr_t offset = (void *)v - (void *)location;u32 imm20 = (offset &0x100000 ) << (31 -20 );u32 imm19_12 = (offset &0xff000 );u32 imm11 = (offset &0x800 ) << (20 -11 );
@@ -65,7 +65,7 @@ static int apply_r_riscv_jal_rela(struct module *me, u32 *location,static int apply_r_riscv_rcv_branch_rela (struct module *me,u32 *location,Elf_Addr v) { -s64 offset = (void *)v - (void *)location; +uintptr_t offset = (void *)v - (void *)location;u16 imm8 = (offset &0x100 ) << (12 -8 );u16 imm7_6 = (offset &0xc0 ) >> (6 -5 );u16 imm5 = (offset &0x20 ) >> (5 -2 );
@@ -80,7 +80,7 @@ static int apply_r_riscv_rcv_branch_rela(struct module *me, u32 *location,static int apply_r_riscv_rvc_jump_rela (struct module *me,u32 *location,Elf_Addr v) { -s64 offset = (void *)v - (void *)location; +uintptr_t offset = (void *)v - (void *)location;u16 imm11 = (offset &0x800 ) << (12 -11 );u16 imm10 = (offset &0x400 ) >> (10 -8 );u16 imm9_8 = (offset &0x300 ) << (12 -11 );
@@ -98,7 +98,7 @@ static int apply_r_riscv_rvc_jump_rela(struct module *me, u32 *location,static int apply_r_riscv_pcrel_hi20_rela (struct module *me,u32 *location,Elf_Addr v) { -s64 offset = (void *)v - (void *)location; +uintptr_t offset = (void *)v - (void *)location;s32 hi20;if (offset != (s32 )offset) {
@@ -180,7 +180,7 @@ static int apply_r_riscv_lo12_s_rela(struct module *me, u32 *location,static int apply_r_riscv_got_hi20_rela (struct module *me,u32 *location,Elf_Addr v) { -s64 offset = (void *)v - (void *)location; +uintptr_t offset = (void *)v - (void *)location;s32 hi20;/* Always emit the got entry */
@@ -202,7 +202,7 @@ static int apply_r_riscv_got_hi20_rela(struct module *me, u32 *location,static int apply_r_riscv_call_plt_rela (struct module *me,u32 *location,Elf_Addr v) { -s64 offset = (void *)v - (void *)location; +uintptr_t offset = (void *)v - (void *)location;s32 fill_v = offset;u32 hi20, lo12;
@@ -229,7 +229,7 @@ static int apply_r_riscv_call_plt_rela(struct module *me, u32 *location,static int apply_r_riscv_call_rela (struct module *me,u32 *location,Elf_Addr v) { -s64 offset = (void *)v - (void *)location; +uintptr_t offset = (void *)v - (void *)location;s32 fill_v = offset;u32 hi20, lo12;
@@ -349,7 +349,7 @@ int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab,unsigned int j;for (j =0 ; j < sechdrs[relsec].sh_size /sizeof (*rel); j++) { -u64 hi20_loc = +unsigned long hi20_loc = sechdrs[sechdrs[relsec].sh_info].sh_addr + rel[j].r_offset;u32 hi20_type =ELF_RISCV_R_TYPE (rel[j].r_info);
@@ -362,12 +362,12 @@ int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab,Elf_Sym *hi20_sym = (Elf_Sym *)sechdrs[symindex].sh_addr +ELF_RISCV_R_SYM (rel[j].r_info); -u64 hi20_sym_val = +unsigned long hi20_sym_val = hi20_sym->st_value + rel[j].r_addend;/* Calculate lo12 */ -u64 offset = hi20_sym_val - hi20_loc; +size_t offset = hi20_sym_val - hi20_loc;if (IS_ENABLED (CONFIG_MODULE_SECTIONS ) && hi20_type ==R_RISCV_GOT_HI20 ) { offset = module_emit_got_entry(
Signature · 1 line
2.16.1
Re: [PATCH 4/5] RISC-V: Change variable type for 32-bit compatible
Review
Quoted 2 lines
(quoted diff) +1
-1- s64 offset = (void *)v - (void *)location; + uintptr_t offset = (void *)v - (void *)location;
s64 is signed, uintptr is not, so this might change behavior and needs an explanation.
Re: [PATCH 4/5] RISC-V: Change variable type for 32-bit compatible
Quoted 6 lines
Review
Quoted 2 lines
(quoted diff) +1
-1- s64 offset = (void *)v - (void *)location; + uintptr_t offset = (void *)v - (void *)location;s64 is signed, uintptr is not, so this might change behavior and needs an explanation.
Yes, it should be intptr_t. Thanks!
Re: [PATCH 4/5] RISC-V: Change variable type for 32-bit compatible
Quoted 8 lines
Quoted 6 lines
Review
Quoted 2 lines
(quoted diff) +1
-1- s64 offset = (void *)v - (void *)location; + uintptr_t offset = (void *)v - (void *)location;s64 is signed, uintptr is not, so this might change behavior and needs an explanation.
Yes, it should be
intptr_t. Thanks!
Correct, it should be ptrdiff_t. In kernel, there is no intptr_t definition.
PATCH 5/5 RISC-V: Use fixed width integer types for 32-bit compatible
In reply to Zong LiUse fixed width integer types for print format on 32/64 bit to fix warning about format compatible.
Like inttypes.h, but more simpler for RISC-V usage.
--- arch/riscv/include/asm/format.h | 20 ++++++++++++++++++++ arch/riscv/kernel/module.c | 13 +++++++------ 2 files changed, 27 insertions(+), 6 deletions(-) create mode 100644 arch/riscv/include/asm/format.h
arch/riscv/include/asm/format.h new file +20 -0
@@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (C) 2018 Andes Technology Corporation */ + +#ifndef _ASM_RISCV_FORMAT_H +#define _ASM_RISCV_FORMAT_H + +#if __riscv_xlen ==64 +#define __PRI_PREFIX "ll" +#else +#define __PRI_PREFIX +#endif + +#define PRIdX __PRI_PREFIX "d" +#define PRIiX __PRI_PREFIX "i" +#define PRIuX __PRI_PREFIX "u" +#define PRIoX __PRI_PREFIX "o" +#define PRIxX __PRI_PREFIX "x" +#define PRIXX __PRI_PREFIX "X" + +#endif /* _ASM_RISCV_FORMAT_H */
arch/riscv/kernel/module.c +7 -6
@@ -18,11 +18,12 @@#include <linux/moduleloader.h> #include <linux/vmalloc.h> #include <asm/pgtable.h> +#include <asm/format.h> static int apply_r_riscv_32_rela (struct module *me,u32 *location,Elf_Addr v) {if (v != (u32 )v) { -pr_err ("%s: value %016llx out of range for 32-bit field\n" , +pr_err ("%s: value %016" PRIxX"out of range for 32-bit field\n" , me->name, v);return -EINVAL ; }
@@ -103,7 +104,7 @@ static int apply_r_riscv_pcrel_hi20_rela(struct module *me, u32 *location,if (offset != (s32 )offset) {pr_err ( -"%s: target %016llx can not be addressed by the 32-bit offset from PC = %p\n" , +"%s: target %016" PRIxX"can not be addressed by the 32-bit offset from PC = %p\n" , me->name, v, location);return -EINVAL ; }
@@ -145,7 +146,7 @@ static int apply_r_riscv_hi20_rela(struct module *me, u32 *location,if (IS_ENABLED (CMODEL_MEDLOW )) {pr_err ( -"%s: target %016llx can not be addressed by the 32-bit offset from PC = %p\n" , +"%s: target %016" PRIxX"can not be addressed by the 32-bit offset from PC = %p\n" , me->name, v, location);return -EINVAL ; }
@@ -189,7 +190,7 @@ static int apply_r_riscv_got_hi20_rela(struct module *me, u32 *location, offset = (void *)offset - (void *)location; }else {pr_err ( -"%s: can not generate the GOT entry for symbol = %016llx from PC = %p\n" , +"%s: can not generate the GOT entry for symbol = %016" PRIxX"from PC = %p\n" , me->name, v, location);return -EINVAL ; }
@@ -213,7 +214,7 @@ static int apply_r_riscv_call_plt_rela(struct module *me, u32 *location, offset = (void *)offset - (void *)location; }else {pr_err ( -"%s: target %016llx can not be addressed by the 32-bit offset from PC = %p\n" , +"%s: target %016" PRIxX"can not be addressed by the 32-bit offset from PC = %p\n" , me->name, v, location);return -EINVAL ; }
@@ -235,7 +236,7 @@ static int apply_r_riscv_call_rela(struct module *me, u32 *location,if (offset != fill_v) {pr_err ( -"%s: target %016llx can not be addressed by the 32-bit offset from PC = %p\n" , +"%s: target %016" PRIxX"can not be addressed by the 32-bit offset from PC = %p\n" , me->name, v, location);return -EINVAL ; }
Signature · 1 line
2.16.1
Re: [PATCH 5/5] RISC-V: Use fixed width integer types for 32-bit compatible
Quoted 28 lines · Zong Li
Use fixed width integer types for print format on 32/64 bit to fix warning about format compatible.
Like
inttypes.h, but more simpler for RISC-V usage.Signed-off-by Zong Li <[email protected]>--- arch/riscv/include/asm/format.h | 20 ++++++++++++++++++++ arch/riscv/kernel/module.c | 13 +++++++------ 2 files changed, 27 insertions(+), 6 deletions(-) create mode 100644 arch/riscv/include/asm/format.harch/riscv/include/asm/format.h new file +10
-0@@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (C) 2018 Andes Technology Corporation */ + +#ifndef _ASM_RISCV_FORMAT_H +#define _ASM_RISCV_FORMAT_H + +#if __riscv_xlen ==64 +#define __PRI_PREFIX "ll" +#else +#define __PRI_PREFIX
arch/riscv/include/asm/format.h line 20
Quoted 10 lines
arch/riscv/include/asm/format.h new file +10
-0+#endif + +#define PRIdX __PRI_PREFIX "d" +#define PRIiX __PRI_PREFIX "i" +#define PRIuX __PRI_PREFIX "u" +#define PRIoX __PRI_PREFIX "o" +#define PRIxX __PRI_PREFIX "x" +#define PRIXX __PRI_PREFIX "X" + +#endif /* _ASM_RISCV_FORMAT_H */
If you want these prefixed submit them to the core kernel, not under asm/ for RISC-V.
arch/riscv/include/asm/format.h
Quoted 8 lines
static int
apply_r_riscv_32_rela(struct module *me, u32 *location, Elf_Addr v){arch/riscv/include/asm/format.h new file +1
-1if (v != (u32 )v) { -pr_err ("%s: value %016llx out of range for 32-bit field\n" , +pr_err ("%s: value %016" PRIxX"out of range for 32-bit field\n" , me->name, v);return -EINVAL ;
But in general Linux uXX and sXX values are always the same underlying fundamental C type. What is the mismatch here?
Re: [PATCH 5/5] RISC-V: Use fixed width integer types for 32-bit compatible
Christoph Hellwig <[email protected]> ? 2018?6?21? ?? ??2:43???
Quoted 35 lines · Zong Li
Quoted 33 lines
Use fixed width integer types for print format on 32/64 bit to fix warning about format compatible.
Like
inttypes.h, but more simpler for RISC-V usage.Signed-off-by Zong Li <[email protected]>--- arch/riscv/include/asm/format.h | 20 ++++++++++++++++++++ arch/riscv/kernel/module.c | 13 +++++++------ 2 files changed, 27 insertions(+), 6 deletions(-) create mode 100644 arch/riscv/include/asm/format.harch/riscv/include/asm/format.h new file +15
-0@@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (C) 2018 Andes Technology Corporation */ + +#ifndef _ASM_RISCV_FORMAT_H +#define _ASM_RISCV_FORMAT_H + +#if __riscv_xlen ==64 +#define __PRI_PREFIX "ll" +#else +#define __PRI_PREFIX +#endif + +#define PRIdX __PRI_PREFIX "d" +#define PRIiX __PRI_PREFIX "i" +#define PRIuX __PRI_PREFIX "u"
Quoted 9 lines
arch/riscv/include/asm/format.h line 20
Quoted 5 lines
arch/riscv/include/asm/format.h new file +5
-0+#define PRIoX __PRI_PREFIX "o" +#define PRIxX __PRI_PREFIX "x" +#define PRIXX __PRI_PREFIX "X" + +#endif /* _ASM_RISCV_FORMAT_H */ If you want these prefixed submit them to the core kernel, not under asm/ for RISC-V.
Maybe I can move to core kernel after this patch?
And I think I can rename the "PRIdX" to "PRIdXELF" to avoid ambiguous in C definition.
Quoted 9 lines
arch/riscv/include/asm/format.h
Quoted 8 lines
static int
apply_r_riscv_32_rela(struct module *me, u32 *location, Elf_Addr v){ if (v != (u32)v) {arch/riscv/include/asm/format.h new file +1
-1-pr_err ("%s: value %016llx out of range for 32-bit field\n" , +pr_err ("%s: value %016" PRIxX"out of range for 32-bit field\n" , me->name, v);return -EINVAL ;
Quoted 3 lines
But in general Linux uXX and sXX values are always the same underlying fundamental C type. What is the mismatch here?
This relocation type was added by Andreas, and there is some discussions on the mail list
(ref: http://lists.infradead.org/pipermail/linux-riscv/2018-June/000706.html)
As I see it, there is truncate situation on 64-bit system, or maybe there is no R_RISCV_32 relocation
type on 64-bit system?
Re: [PATCH 5/5] RISC-V: Use fixed width integer types for 32-bit compatible
In reply to Christoph HellwigQuoted 10 lines · Christoph Hellwig
arch/riscv/kernel/module.c line 28
Quoted 7 lines
static int
apply_r_riscv_32_rela(struct module *me, u32 *location, Elf_Addr v){arch/riscv/kernel/module.c +1
-1if (v != (u32 )v) { -pr_err ("%s: value %016llx out of range for 32-bit field\n" , +pr_err ("%s: value %016" PRIxX"out of range for 32-bit field\n" , me->name, v);return -EINVAL ;But in general Linux uXX and sXX values are always the same underlying fundamental C type. What is the mismatch here?
The mismatch is that v is Elf_Addr, not u32.
Andreas.
Signature · 3 lines
Andreas Schwab, SUSE Labs, schwab at suse.de GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE 1748 E4D4 88E3 0EEA B9D7 "And now for something completely different."
Re: [PATCH 5/5] RISC-V: Use fixed width integer types for 32-bit compatible
Quoted 13 lines · Andreas Schwab
Quoted 10 lines · Christoph Hellwig
arch/riscv/kernel/module.c line 28
Quoted 7 lines
static int
apply_r_riscv_32_rela(struct module *me, u32 *location, Elf_Addr v){arch/riscv/kernel/module.c +1
-1if (v != (u32 )v) { -pr_err ("%s: value %016llx out of range for 32-bit field\n" , +pr_err ("%s: value %016" PRIxX"out of range for 32-bit field\n" , me->name, v);return -EINVAL ;But in general Linux uXX and sXX values are always the same underlying fundamental C type. What is the mismatch here?
Quoted 1 line
The mismatch is that v is
Elf_Addr, not u32.
Then we'll have to cast to unsigned long before printing, like we do elsewhere in kernel.