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
--
2.16.1
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(+)
diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c
index c77df8142be2..91a5852e28fd 100644
--- a/arch/riscv/mm/init.c
+++ b/arch/riscv/mm/init.c
@@ -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);
}
--
2.16.1
Fix link error when disable support SMP.
It causes the undefined reference to `smp_callin'.
Signed-off-by: Zong Li <[email protected]>
---
arch/riscv/kernel/head.S | 2 ++
1 file changed, 2 insertions(+)
diff --git a/arch/riscv/kernel/head.S b/arch/riscv/kernel/head.S
index 3b6293f10e3e..396ec7b349ce 100644
--- a/arch/riscv/kernel/head.S
+++ b/arch/riscv/kernel/head.S
@@ -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 */
--
2.16.1
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.h
diff --git a/arch/riscv/include/asm/format.h b/arch/riscv/include/asm/format.h
new file mode 100644
index 000000000000..9b68ca7fac46
--- /dev/null
+++ b/arch/riscv/include/asm/format.h
@@ -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 */
diff --git a/arch/riscv/kernel/module.c b/arch/riscv/kernel/module.c
index c88d2ee918a5..039f755ff3e3 100644
--- a/arch/riscv/kernel/module.c
+++ b/arch/riscv/kernel/module.c
@@ -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;
}
--
2.16.1
Signed-off-by: Zong Li <[email protected]>
---
arch/riscv/kernel/module.c | 22 +++++++++++-----------
1 file changed, 11 insertions(+), 11 deletions(-)
diff --git a/arch/riscv/kernel/module.c b/arch/riscv/kernel/module.c
index 29d265d0cf45..c88d2ee918a5 100644
--- a/arch/riscv/kernel/module.c
+++ b/arch/riscv/kernel/module.c
@@ -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(
--
2.16.1
Use generic marco to get the index and type of symbol.
Signed-off-by: Zong Li <[email protected]>
---
arch/riscv/include/uapi/asm/elf.h | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/arch/riscv/include/uapi/asm/elf.h b/arch/riscv/include/uapi/asm/elf.h
index 5cae4c30cd8e..1e0dfc36aab9 100644
--- a/arch/riscv/include/uapi/asm/elf.h
+++ b/arch/riscv/include/uapi/asm/elf.h
@@ -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
--
2.16.1
On 32-bit, it need to use __ucmpdi2, otherwise, it can't find the __ucmpdi2
symbol.
Signed-off-by: Zong Li <[email protected]>
---
arch/riscv/Kconfig | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index 6debcc4afc72..3e683be9b7a8 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -122,6 +122,7 @@ config ARCH_RV32I
select GENERIC_ASHLDI3
select GENERIC_ASHRDI3
select GENERIC_LSHRDI3
+ select GENERIC_UCMPDI2
config ARCH_RV64I
bool "RV64I"
--
2.16.1
On Thu, Jun 21, 2018 at 09:41:41AM +0800, Zong Li wrote:
> 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(+)
>
> diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c
> index c77df8142be2..91a5852e28fd 100644
> --- a/arch/riscv/mm/init.c
> +++ b/arch/riscv/mm/init.c
> @@ -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.
> - 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.
On Thu, Jun 21, 2018 at 09:41:46AM +0800, Zong Li wrote:
> 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.h
>
> diff --git a/arch/riscv/include/asm/format.h b/arch/riscv/include/asm/format.h
> new file mode 100644
> index 000000000000..9b68ca7fac46
> --- /dev/null
> +++ b/arch/riscv/include/asm/format.h
> @@ -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 */
If you want these prefixed submit them to the core kernel, not
under asm/ for RISC-V.
>
> 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;
But in general Linux uXX and sXX values are always the same underlying
fundamental C type. What is the mismatch here?
Christoph Hellwig <[email protected]> 於 2018年6月21日 週四 下午2:40寫道:
>
> On Thu, Jun 21, 2018 at 09:41:41AM +0800, Zong Li wrote:
> > 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(+)
> >
> > diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c
> > index c77df8142be2..91a5852e28fd 100644
> > --- a/arch/riscv/mm/init.c
> > +++ b/arch/riscv/mm/init.c
> > @@ -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.
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!
> > - 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!
Christoph Hellwig <[email protected]> 於 2018年6月21日 週四 下午2:43寫道:
>
> On Thu, Jun 21, 2018 at 09:41:46AM +0800, Zong Li wrote:
> > 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.h
> >
> > diff --git a/arch/riscv/include/asm/format.h b/arch/riscv/include/asm/format.h
> > new file mode 100644
> > index 000000000000..9b68ca7fac46
> > --- /dev/null
> > +++ b/arch/riscv/include/asm/format.h
> > @@ -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 */
>
> 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.
> >
> > 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;
>
> 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?
On Jun 20 2018, Christoph Hellwig <[email protected]> wrote:
>> 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;
>
> 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.
--
Andreas Schwab, SUSE Labs, [email protected]
GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE 1748 E4D4 88E3 0EEA B9D7
"And now for something completely different."
On Thu, Jun 21, 2018 at 12:21:19PM +0200, Andreas Schwab wrote:
> On Jun 20 2018, Christoph Hellwig <[email protected]> wrote:
>
> >> 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;
> >
> > 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.
Then we'll have to cast to unsigned long before printing, like we
do elsewhere in kernel.
> > > - 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.