Skip to content
This repository was archived by the owner on Nov 8, 2023. It is now read-only.

Commit 5c89186

Browse files
Merge remote-tracking branch 'palmer/fixes' into for-next
I don't usually merge these in, but I missed sending a PR due to the holidays. * palmer/fixes: riscv: Fix set_direct_map_default_noflush() to reset _PAGE_EXEC riscv: Fix module_alloc() that did not reset the linear mapping permissions riscv: Fix wrong usage of lm_alias() when splitting a huge linear mapping riscv: Check if the code to patch lies in the exit section riscv: errata: andes: Probe for IOCP only once in boot stage riscv: Fix SMP when shadow call stacks are enabled dt-bindings: perf: riscv,pmu: drop unneeded quotes riscv: fix misaligned access handling of C.SWSP and C.SDSP RISC-V: hwprobe: Always use u64 for extension bits Support rv32 ULEB128 test riscv: Correct type casting in module loading riscv: Safely remove entries from relocation list Signed-off-by: Palmer Dabbelt <[email protected]>
2 parents 869436d + b8b2711 commit 5c89186

File tree

11 files changed

+130
-52
lines changed

11 files changed

+130
-52
lines changed

Documentation/devicetree/bindings/perf/riscv,pmu.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ properties:
9090
bitmap of all MHPMCOUNTERx that can monitor the range of events
9191

9292
dependencies:
93-
"riscv,event-to-mhpmevent": [ "riscv,event-to-mhpmcounters" ]
93+
riscv,event-to-mhpmevent: [ "riscv,event-to-mhpmcounters" ]
9494

9595
required:
9696
- compatible

arch/riscv/errata/andes/errata.c

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,29 +38,35 @@ static long ax45mp_iocp_sw_workaround(void)
3838
return ret.error ? 0 : ret.value;
3939
}
4040

41-
static bool errata_probe_iocp(unsigned int stage, unsigned long arch_id, unsigned long impid)
41+
static void errata_probe_iocp(unsigned int stage, unsigned long arch_id, unsigned long impid)
4242
{
43+
static bool done;
44+
4345
if (!IS_ENABLED(CONFIG_ERRATA_ANDES_CMO))
44-
return false;
46+
return;
47+
48+
if (done)
49+
return;
50+
51+
done = true;
4552

4653
if (arch_id != ANDESTECH_AX45MP_MARCHID || impid != ANDESTECH_AX45MP_MIMPID)
47-
return false;
54+
return;
4855

4956
if (!ax45mp_iocp_sw_workaround())
50-
return false;
57+
return;
5158

5259
/* Set this just to make core cbo code happy */
5360
riscv_cbom_block_size = 1;
5461
riscv_noncoherent_supported();
55-
56-
return true;
5762
}
5863

5964
void __init_or_module andes_errata_patch_func(struct alt_entry *begin, struct alt_entry *end,
6065
unsigned long archid, unsigned long impid,
6166
unsigned int stage)
6267
{
63-
errata_probe_iocp(stage, archid, impid);
68+
if (stage == RISCV_ALTERNATIVES_BOOT)
69+
errata_probe_iocp(stage, archid, impid);
6470

6571
/* we have nothing to patch here ATM so just return back */
6672
}

arch/riscv/include/asm/sections.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ extern char _start_kernel[];
1313
extern char __init_data_begin[], __init_data_end[];
1414
extern char __init_text_begin[], __init_text_end[];
1515
extern char __alt_start[], __alt_end[];
16+
extern char __exittext_begin[], __exittext_end[];
1617

1718
static inline bool is_va_kernel_text(uintptr_t va)
1819
{

arch/riscv/kernel/head.S

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,6 @@ secondary_start_sbi:
153153
XIP_FIXUP_OFFSET a3
154154
add a3, a3, a1
155155
REG_L sp, (a3)
156-
scs_load_current
157156

158157
.Lsecondary_start_common:
159158

@@ -164,6 +163,7 @@ secondary_start_sbi:
164163
call relocate_enable_mmu
165164
#endif
166165
call .Lsetup_trap_vector
166+
scs_load_current
167167
tail smp_callin
168168
#endif /* CONFIG_SMP */
169169

arch/riscv/kernel/module.c

Lines changed: 86 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -40,15 +40,6 @@ struct relocation_handlers {
4040
long buffer);
4141
};
4242

43-
unsigned int initialize_relocation_hashtable(unsigned int num_relocations);
44-
void process_accumulated_relocations(struct module *me);
45-
int add_relocation_to_accumulate(struct module *me, int type, void *location,
46-
unsigned int hashtable_bits, Elf_Addr v);
47-
48-
struct hlist_head *relocation_hashtable;
49-
50-
struct list_head used_buckets_list;
51-
5243
/*
5344
* The auipc+jalr instruction pair can reach any PC-relative offset
5445
* in the range [-2^31 - 2^11, 2^31 - 2^11)
@@ -64,7 +55,7 @@ static bool riscv_insn_valid_32bit_offset(ptrdiff_t val)
6455

6556
static int riscv_insn_rmw(void *location, u32 keep, u32 set)
6657
{
67-
u16 *parcel = location;
58+
__le16 *parcel = location;
6859
u32 insn = (u32)le16_to_cpu(parcel[0]) | (u32)le16_to_cpu(parcel[1]) << 16;
6960

7061
insn &= keep;
@@ -77,7 +68,7 @@ static int riscv_insn_rmw(void *location, u32 keep, u32 set)
7768

7869
static int riscv_insn_rvc_rmw(void *location, u16 keep, u16 set)
7970
{
80-
u16 *parcel = location;
71+
__le16 *parcel = location;
8172
u16 insn = le16_to_cpu(*parcel);
8273

8374
insn &= keep;
@@ -604,7 +595,10 @@ static const struct relocation_handlers reloc_handlers[] = {
604595
/* 192-255 nonstandard ABI extensions */
605596
};
606597

607-
void process_accumulated_relocations(struct module *me)
598+
static void
599+
process_accumulated_relocations(struct module *me,
600+
struct hlist_head **relocation_hashtable,
601+
struct list_head *used_buckets_list)
608602
{
609603
/*
610604
* Only ADD/SUB/SET/ULEB128 should end up here.
@@ -624,18 +618,25 @@ void process_accumulated_relocations(struct module *me)
624618
* - Each relocation entry for a location address
625619
*/
626620
struct used_bucket *bucket_iter;
621+
struct used_bucket *bucket_iter_tmp;
627622
struct relocation_head *rel_head_iter;
623+
struct hlist_node *rel_head_iter_tmp;
628624
struct relocation_entry *rel_entry_iter;
625+
struct relocation_entry *rel_entry_iter_tmp;
629626
int curr_type;
630627
void *location;
631628
long buffer;
632629

633-
list_for_each_entry(bucket_iter, &used_buckets_list, head) {
634-
hlist_for_each_entry(rel_head_iter, bucket_iter->bucket, node) {
630+
list_for_each_entry_safe(bucket_iter, bucket_iter_tmp,
631+
used_buckets_list, head) {
632+
hlist_for_each_entry_safe(rel_head_iter, rel_head_iter_tmp,
633+
bucket_iter->bucket, node) {
635634
buffer = 0;
636635
location = rel_head_iter->location;
637-
list_for_each_entry(rel_entry_iter,
638-
rel_head_iter->rel_entry, head) {
636+
list_for_each_entry_safe(rel_entry_iter,
637+
rel_entry_iter_tmp,
638+
rel_head_iter->rel_entry,
639+
head) {
639640
curr_type = rel_entry_iter->type;
640641
reloc_handlers[curr_type].reloc_handler(
641642
me, &buffer, rel_entry_iter->value);
@@ -648,11 +649,14 @@ void process_accumulated_relocations(struct module *me)
648649
kfree(bucket_iter);
649650
}
650651

651-
kfree(relocation_hashtable);
652+
kfree(*relocation_hashtable);
652653
}
653654

654-
int add_relocation_to_accumulate(struct module *me, int type, void *location,
655-
unsigned int hashtable_bits, Elf_Addr v)
655+
static int add_relocation_to_accumulate(struct module *me, int type,
656+
void *location,
657+
unsigned int hashtable_bits, Elf_Addr v,
658+
struct hlist_head *relocation_hashtable,
659+
struct list_head *used_buckets_list)
656660
{
657661
struct relocation_entry *entry;
658662
struct relocation_head *rel_head;
@@ -661,6 +665,10 @@ int add_relocation_to_accumulate(struct module *me, int type, void *location,
661665
unsigned long hash;
662666

663667
entry = kmalloc(sizeof(*entry), GFP_KERNEL);
668+
669+
if (!entry)
670+
return -ENOMEM;
671+
664672
INIT_LIST_HEAD(&entry->head);
665673
entry->type = type;
666674
entry->value = v;
@@ -669,7 +677,10 @@ int add_relocation_to_accumulate(struct module *me, int type, void *location,
669677

670678
current_head = &relocation_hashtable[hash];
671679

672-
/* Find matching location (if any) */
680+
/*
681+
* Search for the relocation_head for the relocations that happen at the
682+
* provided location
683+
*/
673684
bool found = false;
674685
struct relocation_head *rel_head_iter;
675686

@@ -681,19 +692,45 @@ int add_relocation_to_accumulate(struct module *me, int type, void *location,
681692
}
682693
}
683694

695+
/*
696+
* If there has not yet been any relocations at the provided location,
697+
* create a relocation_head for that location and populate it with this
698+
* relocation_entry.
699+
*/
684700
if (!found) {
685701
rel_head = kmalloc(sizeof(*rel_head), GFP_KERNEL);
702+
703+
if (!rel_head) {
704+
kfree(entry);
705+
return -ENOMEM;
706+
}
707+
686708
rel_head->rel_entry =
687709
kmalloc(sizeof(struct list_head), GFP_KERNEL);
710+
711+
if (!rel_head->rel_entry) {
712+
kfree(entry);
713+
kfree(rel_head);
714+
return -ENOMEM;
715+
}
716+
688717
INIT_LIST_HEAD(rel_head->rel_entry);
689718
rel_head->location = location;
690719
INIT_HLIST_NODE(&rel_head->node);
691720
if (!current_head->first) {
692721
bucket =
693722
kmalloc(sizeof(struct used_bucket), GFP_KERNEL);
723+
724+
if (!bucket) {
725+
kfree(entry);
726+
kfree(rel_head);
727+
kfree(rel_head->rel_entry);
728+
return -ENOMEM;
729+
}
730+
694731
INIT_LIST_HEAD(&bucket->head);
695732
bucket->bucket = current_head;
696-
list_add(&bucket->head, &used_buckets_list);
733+
list_add(&bucket->head, used_buckets_list);
697734
}
698735
hlist_add_head(&rel_head->node, current_head);
699736
}
@@ -704,7 +741,9 @@ int add_relocation_to_accumulate(struct module *me, int type, void *location,
704741
return 0;
705742
}
706743

707-
unsigned int initialize_relocation_hashtable(unsigned int num_relocations)
744+
static unsigned int
745+
initialize_relocation_hashtable(unsigned int num_relocations,
746+
struct hlist_head **relocation_hashtable)
708747
{
709748
/* Can safely assume that bits is not greater than sizeof(long) */
710749
unsigned long hashtable_size = roundup_pow_of_two(num_relocations);
@@ -720,12 +759,13 @@ unsigned int initialize_relocation_hashtable(unsigned int num_relocations)
720759

721760
hashtable_size <<= should_double_size;
722761

723-
relocation_hashtable = kmalloc_array(hashtable_size,
724-
sizeof(*relocation_hashtable),
725-
GFP_KERNEL);
726-
__hash_init(relocation_hashtable, hashtable_size);
762+
*relocation_hashtable = kmalloc_array(hashtable_size,
763+
sizeof(*relocation_hashtable),
764+
GFP_KERNEL);
765+
if (!*relocation_hashtable)
766+
return -ENOMEM;
727767

728-
INIT_LIST_HEAD(&used_buckets_list);
768+
__hash_init(*relocation_hashtable, hashtable_size);
729769

730770
return hashtable_bits;
731771
}
@@ -742,7 +782,17 @@ int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab,
742782
Elf_Addr v;
743783
int res;
744784
unsigned int num_relocations = sechdrs[relsec].sh_size / sizeof(*rel);
745-
unsigned int hashtable_bits = initialize_relocation_hashtable(num_relocations);
785+
struct hlist_head *relocation_hashtable;
786+
struct list_head used_buckets_list;
787+
unsigned int hashtable_bits;
788+
789+
hashtable_bits = initialize_relocation_hashtable(num_relocations,
790+
&relocation_hashtable);
791+
792+
if (hashtable_bits < 0)
793+
return hashtable_bits;
794+
795+
INIT_LIST_HEAD(&used_buckets_list);
746796

747797
pr_debug("Applying relocate section %u to %u\n", relsec,
748798
sechdrs[relsec].sh_info);
@@ -823,14 +873,18 @@ int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab,
823873
}
824874

825875
if (reloc_handlers[type].accumulate_handler)
826-
res = add_relocation_to_accumulate(me, type, location, hashtable_bits, v);
876+
res = add_relocation_to_accumulate(me, type, location,
877+
hashtable_bits, v,
878+
relocation_hashtable,
879+
&used_buckets_list);
827880
else
828881
res = handler(me, location, v);
829882
if (res)
830883
return res;
831884
}
832885

833-
process_accumulated_relocations(me);
886+
process_accumulated_relocations(me, &relocation_hashtable,
887+
&used_buckets_list);
834888

835889
return 0;
836890
}
@@ -840,7 +894,8 @@ void *module_alloc(unsigned long size)
840894
{
841895
return __vmalloc_node_range(size, 1, MODULES_VADDR,
842896
MODULES_END, GFP_KERNEL,
843-
PAGE_KERNEL, 0, NUMA_NO_NODE,
897+
PAGE_KERNEL, VM_FLUSH_RESET_PERMS,
898+
NUMA_NO_NODE,
844899
__builtin_return_address(0));
845900
}
846901
#endif

arch/riscv/kernel/patch.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include <asm/fixmap.h>
1515
#include <asm/ftrace.h>
1616
#include <asm/patch.h>
17+
#include <asm/sections.h>
1718

1819
struct patch_insn {
1920
void *addr;
@@ -25,6 +26,14 @@ struct patch_insn {
2526
int riscv_patch_in_stop_machine = false;
2627

2728
#ifdef CONFIG_MMU
29+
30+
static inline bool is_kernel_exittext(uintptr_t addr)
31+
{
32+
return system_state < SYSTEM_RUNNING &&
33+
addr >= (uintptr_t)__exittext_begin &&
34+
addr < (uintptr_t)__exittext_end;
35+
}
36+
2837
/*
2938
* The fix_to_virt(, idx) needs a const value (not a dynamic variable of
3039
* reg-a0) or BUILD_BUG_ON failed with "idx >= __end_of_fixed_addresses".
@@ -35,7 +44,7 @@ static __always_inline void *patch_map(void *addr, const unsigned int fixmap)
3544
uintptr_t uintaddr = (uintptr_t) addr;
3645
struct page *page;
3746

38-
if (core_kernel_text(uintaddr))
47+
if (core_kernel_text(uintaddr) || is_kernel_exittext(uintaddr))
3948
page = phys_to_page(__pa_symbol(addr));
4049
else if (IS_ENABLED(CONFIG_STRICT_MODULE_RWX))
4150
page = vmalloc_to_page(addr);

arch/riscv/kernel/tests/module_test/test_uleb128.S

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@
66
.text
77
.global test_uleb_basic
88
test_uleb_basic:
9-
ld a0, second
9+
lw a0, second
1010
addi a0, a0, -127
1111
ret
1212

1313
.global test_uleb_large
1414
test_uleb_large:
15-
ld a0, fourth
15+
lw a0, fourth
1616
addi a0, a0, -0x07e8
1717
ret
1818

@@ -22,10 +22,10 @@ first:
2222
second:
2323
.reloc second, R_RISCV_SET_ULEB128, second
2424
.reloc second, R_RISCV_SUB_ULEB128, first
25-
.dword 0
25+
.word 0
2626
third:
2727
.space 1000
2828
fourth:
2929
.reloc fourth, R_RISCV_SET_ULEB128, fourth
3030
.reloc fourth, R_RISCV_SUB_ULEB128, third
31-
.dword 0
31+
.word 0

arch/riscv/kernel/traps_misaligned.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -550,16 +550,14 @@ int handle_misaligned_store(struct pt_regs *regs)
550550
} else if ((insn & INSN_MASK_C_SD) == INSN_MATCH_C_SD) {
551551
len = 8;
552552
val.data_ulong = GET_RS2S(insn, regs);
553-
} else if ((insn & INSN_MASK_C_SDSP) == INSN_MATCH_C_SDSP &&
554-
((insn >> SH_RD) & 0x1f)) {
553+
} else if ((insn & INSN_MASK_C_SDSP) == INSN_MATCH_C_SDSP) {
555554
len = 8;
556555
val.data_ulong = GET_RS2C(insn, regs);
557556
#endif
558557
} else if ((insn & INSN_MASK_C_SW) == INSN_MATCH_C_SW) {
559558
len = 4;
560559
val.data_ulong = GET_RS2S(insn, regs);
561-
} else if ((insn & INSN_MASK_C_SWSP) == INSN_MATCH_C_SWSP &&
562-
((insn >> SH_RD) & 0x1f)) {
560+
} else if ((insn & INSN_MASK_C_SWSP) == INSN_MATCH_C_SWSP) {
563561
len = 4;
564562
val.data_ulong = GET_RS2C(insn, regs);
565563
} else if ((insn & INSN_MASK_C_FSD) == INSN_MATCH_C_FSD) {

0 commit comments

Comments
 (0)