diff options
| -rw-r--r-- | arch/riscv/Kconfig | 10 | ||||
| -rw-r--r-- | arch/riscv/include/asm/Kbuild | 1 | ||||
| -rw-r--r-- | arch/riscv/include/asm/csr.h | 14 | ||||
| -rw-r--r-- | arch/riscv/include/asm/ftrace.h | 10 | ||||
| -rw-r--r-- | arch/riscv/include/asm/mmu_context.h | 17 | ||||
| -rw-r--r-- | arch/riscv/include/asm/tlbflush.h | 20 | ||||
| -rw-r--r-- | arch/riscv/include/asm/unistd.h | 1 | ||||
| -rw-r--r-- | arch/riscv/kernel/Makefile | 7 | ||||
| -rw-r--r-- | arch/riscv/kernel/entry.S | 9 | ||||
| -rw-r--r-- | arch/riscv/kernel/ftrace.c | 41 | ||||
| -rw-r--r-- | arch/riscv/kernel/head.S | 6 | ||||
| -rw-r--r-- | arch/riscv/kernel/mcount.S | 126 | ||||
| -rw-r--r-- | arch/riscv/kernel/setup.c | 44 | ||||
| -rw-r--r-- | arch/riscv/kernel/vdso.c | 2 | ||||
| -rw-r--r-- | arch/riscv/mm/fault.c | 4 | ||||
| -rw-r--r-- | arch/riscv/mm/init.c | 12 | ||||
| -rw-r--r-- | include/asm-generic/audit_dir_write.h | 2 | 
17 files changed, 250 insertions, 76 deletions
| diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig index 865e14f50c14..b6722c246d9c 100644 --- a/arch/riscv/Kconfig +++ b/arch/riscv/Kconfig @@ -22,6 +22,7 @@ config RISCV  	select GENERIC_ATOMIC64 if !64BIT || !RISCV_ISA_A  	select ARCH_WANT_OPTIONAL_GPIOLIB  	select HAVE_MEMBLOCK +	select HAVE_MEMBLOCK_NODE_MAP  	select HAVE_DMA_API_DEBUG  	select HAVE_DMA_CONTIGUOUS  	select HAVE_GENERIC_DMA_COHERENT @@ -43,6 +44,10 @@ config MMU  config ARCH_PHYS_ADDR_T_64BIT  	def_bool y +config ZONE_DMA32 +	bool +	default y +  config ARCH_DMA_ADDR_T_64BIT  	def_bool y @@ -55,6 +60,9 @@ config PAGE_OFFSET  config STACKTRACE_SUPPORT  	def_bool y +config TRACE_IRQFLAGS_SUPPORT +	def_bool y +  config RWSEM_GENERIC_SPINLOCK  	def_bool y @@ -107,6 +115,8 @@ config ARCH_RV64I  	bool "RV64I"  	select CPU_SUPPORTS_64BIT_KERNEL  	select 64BIT +	select HAVE_FUNCTION_TRACER +	select HAVE_FUNCTION_GRAPH_TRACER  endchoice diff --git a/arch/riscv/include/asm/Kbuild b/arch/riscv/include/asm/Kbuild index 681ac0d09314..4286a5f83876 100644 --- a/arch/riscv/include/asm/Kbuild +++ b/arch/riscv/include/asm/Kbuild @@ -12,7 +12,6 @@ generic-y += errno.h  generic-y += exec.h  generic-y += fb.h  generic-y += fcntl.h -generic-y += ftrace.h  generic-y += futex.h  generic-y += hardirq.h  generic-y += hash.h diff --git a/arch/riscv/include/asm/csr.h b/arch/riscv/include/asm/csr.h index 3c7a2c97e377..421fa3585798 100644 --- a/arch/riscv/include/asm/csr.h +++ b/arch/riscv/include/asm/csr.h @@ -40,15 +40,15 @@  #define SR_SD   _AC(0x8000000000000000, UL) /* FS/XS dirty */  #endif -/* SPTBR flags */ +/* SATP flags */  #if __riscv_xlen == 32 -#define SPTBR_PPN     _AC(0x003FFFFF, UL) -#define SPTBR_MODE_32 _AC(0x80000000, UL) -#define SPTBR_MODE    SPTBR_MODE_32 +#define SATP_PPN     _AC(0x003FFFFF, UL) +#define SATP_MODE_32 _AC(0x80000000, UL) +#define SATP_MODE    SATP_MODE_32  #else -#define SPTBR_PPN     _AC(0x00000FFFFFFFFFFF, UL) -#define SPTBR_MODE_39 _AC(0x8000000000000000, UL) -#define SPTBR_MODE    SPTBR_MODE_39 +#define SATP_PPN     _AC(0x00000FFFFFFFFFFF, UL) +#define SATP_MODE_39 _AC(0x8000000000000000, UL) +#define SATP_MODE    SATP_MODE_39  #endif  /* Interrupt Enable and Interrupt Pending flags */ diff --git a/arch/riscv/include/asm/ftrace.h b/arch/riscv/include/asm/ftrace.h new file mode 100644 index 000000000000..66d4175eb13e --- /dev/null +++ b/arch/riscv/include/asm/ftrace.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (C) 2017 Andes Technology Corporation */ + +/* + * The graph frame test is not possible if CONFIG_FRAME_POINTER is not enabled. + * Check arch/riscv/kernel/mcount.S for detail. + */ +#if defined(CONFIG_FUNCTION_GRAPH_TRACER) && defined(CONFIG_FRAME_POINTER) +#define HAVE_FUNCTION_GRAPH_FP_TEST +#endif diff --git a/arch/riscv/include/asm/mmu_context.h b/arch/riscv/include/asm/mmu_context.h index 97424834dce2..336d60ec5698 100644 --- a/arch/riscv/include/asm/mmu_context.h +++ b/arch/riscv/include/asm/mmu_context.h @@ -39,16 +39,6 @@ static inline void destroy_context(struct mm_struct *mm)  {  } -static inline pgd_t *current_pgdir(void) -{ -	return pfn_to_virt(csr_read(sptbr) & SPTBR_PPN); -} - -static inline void set_pgdir(pgd_t *pgd) -{ -	csr_write(sptbr, virt_to_pfn(pgd) | SPTBR_MODE); -} -  /*   * When necessary, performs a deferred icache flush for the given MM context,   * on the local CPU.  RISC-V has no direct mechanism for instruction cache @@ -93,7 +83,12 @@ static inline void switch_mm(struct mm_struct *prev,  		cpumask_clear_cpu(cpu, mm_cpumask(prev));  		cpumask_set_cpu(cpu, mm_cpumask(next)); -		set_pgdir(next->pgd); +		/* +		 * Use the old spbtr name instead of using the current satp +		 * name to support binutils 2.29 which doesn't know about the +		 * privileged ISA 1.10 yet. +		 */ +		csr_write(sptbr, virt_to_pfn(next->pgd) | SATP_MODE);  		local_flush_tlb_all();  		flush_icache_deferred(next); diff --git a/arch/riscv/include/asm/tlbflush.h b/arch/riscv/include/asm/tlbflush.h index 7b9c24ebdf52..7b209aec355d 100644 --- a/arch/riscv/include/asm/tlbflush.h +++ b/arch/riscv/include/asm/tlbflush.h @@ -36,7 +36,14 @@ static inline void local_flush_tlb_page(unsigned long addr)  #define flush_tlb_all() local_flush_tlb_all()  #define flush_tlb_page(vma, addr) local_flush_tlb_page(addr) -#define flush_tlb_range(vma, start, end) local_flush_tlb_all() + +static inline void flush_tlb_range(struct vm_area_struct *vma, +		unsigned long start, unsigned long end) +{ +	local_flush_tlb_all(); +} + +#define flush_tlb_mm(mm) flush_tlb_all()  #else /* CONFIG_SMP */ @@ -45,16 +52,13 @@ static inline void local_flush_tlb_page(unsigned long addr)  #define flush_tlb_all() sbi_remote_sfence_vma(0, 0, -1)  #define flush_tlb_page(vma, addr) flush_tlb_range(vma, addr, 0)  #define flush_tlb_range(vma, start, end) \ -	sbi_remote_sfence_vma(0, start, (end) - (start)) +	sbi_remote_sfence_vma(mm_cpumask((vma)->vm_mm)->bits, \ +			      start, (end) - (start)) +#define flush_tlb_mm(mm) \ +	sbi_remote_sfence_vma(mm_cpumask(mm)->bits, 0, -1)  #endif /* CONFIG_SMP */ -/* Flush the TLB entries of the specified mm context */ -static inline void flush_tlb_mm(struct mm_struct *mm) -{ -	flush_tlb_all(); -} -  /* Flush a range of kernel pages */  static inline void flush_tlb_kernel_range(unsigned long start,  	unsigned long end) diff --git a/arch/riscv/include/asm/unistd.h b/arch/riscv/include/asm/unistd.h index 2f704a5c4196..080fb28061de 100644 --- a/arch/riscv/include/asm/unistd.h +++ b/arch/riscv/include/asm/unistd.h @@ -11,7 +11,6 @@   *   GNU General Public License for more details.   */ -#define __ARCH_HAVE_MMU  #define __ARCH_WANT_SYS_CLONE  #include <uapi/asm/unistd.h>  #include <uapi/asm/syscalls.h> diff --git a/arch/riscv/kernel/Makefile b/arch/riscv/kernel/Makefile index ab8baf7bd142..196f62ffc428 100644 --- a/arch/riscv/kernel/Makefile +++ b/arch/riscv/kernel/Makefile @@ -2,6 +2,11 @@  # Makefile for the RISC-V Linux kernel  # +ifdef CONFIG_FTRACE +CFLAGS_REMOVE_ftrace.o = -pg +CFLAGS_REMOVE_setup.o = -pg +endif +  extra-y += head.o  extra-y += vmlinux.lds @@ -29,5 +34,7 @@ CFLAGS_setup.o := -mcmodel=medany  obj-$(CONFIG_SMP)		+= smpboot.o  obj-$(CONFIG_SMP)		+= smp.o  obj-$(CONFIG_MODULES)		+= module.o +obj-$(CONFIG_FUNCTION_TRACER)	+= mcount.o +obj-$(CONFIG_FUNCTION_GRAPH_TRACER)	+= ftrace.o  clean: diff --git a/arch/riscv/kernel/entry.S b/arch/riscv/kernel/entry.S index 7404ec222406..87fc045be51f 100644 --- a/arch/riscv/kernel/entry.S +++ b/arch/riscv/kernel/entry.S @@ -78,10 +78,13 @@ _save_context:  	REG_S x31, PT_T6(sp)  	/* -	 * Disable FPU to detect illegal usage of -	 * floating point in kernel space +	 * Disable user-mode memory access as it should only be set in the +	 * actual user copy routines. +	 * +	 * Disable the FPU to detect illegal usage of floating point in kernel +	 * space.  	 */ -	li t0, SR_FS +	li t0, SR_SUM | SR_FS  	REG_L s0, TASK_TI_USER_SP(tp)  	csrrc s1, sstatus, t0 diff --git a/arch/riscv/kernel/ftrace.c b/arch/riscv/kernel/ftrace.c new file mode 100644 index 000000000000..d0de68d144cb --- /dev/null +++ b/arch/riscv/kernel/ftrace.c @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2013 Linaro Limited + * Author: AKASHI Takahiro <takahiro.akashi@linaro.org> + * Copyright (C) 2017 Andes Technology Corporation + */ + +#include <linux/ftrace.h> + +/* + * Most of this file is copied from arm64. + */ +void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr, +			   unsigned long frame_pointer) +{ +	unsigned long return_hooker = (unsigned long)&return_to_handler; +	unsigned long old; +	struct ftrace_graph_ent trace; +	int err; + +	if (unlikely(atomic_read(¤t->tracing_graph_pause))) +		return; + +	/* +	 * We don't suffer access faults, so no extra fault-recovery assembly +	 * is needed here. +	 */ +	old = *parent; + +	trace.func = self_addr; +	trace.depth = current->curr_ret_stack + 1; + +	if (!ftrace_graph_entry(&trace)) +		return; + +	err = ftrace_push_return_trace(old, self_addr, &trace.depth, +				       frame_pointer, NULL); +	if (err == -EBUSY) +		return; +	*parent = return_hooker; +} diff --git a/arch/riscv/kernel/head.S b/arch/riscv/kernel/head.S index 78f670d70133..226eeb190f90 100644 --- a/arch/riscv/kernel/head.S +++ b/arch/riscv/kernel/head.S @@ -74,15 +74,15 @@ relocate:  	sub a1, a1, a0  	add ra, ra, a1 -	/* Point stvec to virtual address of intruction after sptbr write */ +	/* Point stvec to virtual address of intruction after satp write */  	la a0, 1f  	add a0, a0, a1  	csrw stvec, a0 -	/* Compute sptbr for kernel page tables, but don't load it yet */ +	/* Compute satp for kernel page tables, but don't load it yet */  	la a2, swapper_pg_dir  	srl a2, a2, PAGE_SHIFT -	li a1, SPTBR_MODE +	li a1, SATP_MODE  	or a2, a2, a1  	/* diff --git a/arch/riscv/kernel/mcount.S b/arch/riscv/kernel/mcount.S new file mode 100644 index 000000000000..c46a778627be --- /dev/null +++ b/arch/riscv/kernel/mcount.S @@ -0,0 +1,126 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (C) 2017 Andes Technology Corporation */ + +#include <linux/init.h> +#include <linux/linkage.h> +#include <asm/asm.h> +#include <asm/csr.h> +#include <asm/unistd.h> +#include <asm/thread_info.h> +#include <asm/asm-offsets.h> +#include <asm-generic/export.h> +#include <asm/ftrace.h> + +	.text + +	.macro SAVE_ABI_STATE +	addi	sp, sp, -16 +	sd	s0, 0(sp) +	sd	ra, 8(sp) +	addi	s0, sp, 16 +	.endm + +	/* +	 * The call to ftrace_return_to_handler would overwrite the return +	 * register if a0 was not saved. +	 */ +	.macro SAVE_RET_ABI_STATE +	addi	sp, sp, -32 +	sd	s0, 16(sp) +	sd	ra, 24(sp) +	sd	a0, 8(sp) +	addi	s0, sp, 32 +	.endm + +	.macro STORE_ABI_STATE +	ld	ra, 8(sp) +	ld	s0, 0(sp) +	addi	sp, sp, 16 +	.endm + +	.macro STORE_RET_ABI_STATE +	ld	ra, 24(sp) +	ld	s0, 16(sp) +	ld	a0, 8(sp) +	addi	sp, sp, 32 +	.endm + +ENTRY(ftrace_stub) +	ret +ENDPROC(ftrace_stub) + +#ifdef CONFIG_FUNCTION_GRAPH_TRACER +ENTRY(return_to_handler) +/* + * On implementing the frame point test, the ideal way is to compare the + * s0 (frame pointer, if enabled) on entry and the sp (stack pointer) on return. + * However, the psABI of variable-length-argument functions does not allow this. + * + * So alternatively we check the *old* frame pointer position, that is, the + * value stored in -16(s0) on entry, and the s0 on return. + */ +#ifdef HAVE_FUNCTION_GRAPH_FP_TEST +	mv	t6, s0 +#endif +	SAVE_RET_ABI_STATE +#ifdef HAVE_FUNCTION_GRAPH_FP_TEST +	mv	a0, t6 +#endif +	la	t0, ftrace_return_to_handler +	jalr	t0 +	mv	a1, a0 +	STORE_RET_ABI_STATE +	jalr	a1 +ENDPROC(return_to_handler) +EXPORT_SYMBOL(return_to_handler) +#endif + +ENTRY(_mcount) +	la	t4, ftrace_stub +#ifdef CONFIG_FUNCTION_GRAPH_TRACER +	la	t0, ftrace_graph_return +	ld	t1, 0(t0) +	bne	t1, t4, do_ftrace_graph_caller + +	la	t3, ftrace_graph_entry +	ld	t2, 0(t3) +	la	t6, ftrace_graph_entry_stub +	bne	t2, t6, do_ftrace_graph_caller +#endif +	la	t3, ftrace_trace_function +	ld	t5, 0(t3) +	bne	t5, t4, do_trace +	ret + +#ifdef CONFIG_FUNCTION_GRAPH_TRACER +/* + * A pseudo representation for the function graph tracer: + * prepare_to_return(&ra_to_caller_of_caller, ra_to_caller) + */ +do_ftrace_graph_caller: +	addi	a0, s0, -8 +	mv	a1, ra +#ifdef HAVE_FUNCTION_GRAPH_FP_TEST +	ld	a2, -16(s0) +#endif +	SAVE_ABI_STATE +	la	t0, prepare_ftrace_return +	jalr	t0 +	STORE_ABI_STATE +	ret +#endif + +/* + * A pseudo representation for the function tracer: + * (*ftrace_trace_function)(ra_to_caller, ra_to_caller_of_caller) + */ +do_trace: +	ld	a1, -8(s0) +	mv	a0, ra + +	SAVE_ABI_STATE +	jalr	t5 +	STORE_ABI_STATE +	ret +ENDPROC(_mcount) +EXPORT_SYMBOL(_mcount) diff --git a/arch/riscv/kernel/setup.c b/arch/riscv/kernel/setup.c index cb7b0c63014e..09f7064e898c 100644 --- a/arch/riscv/kernel/setup.c +++ b/arch/riscv/kernel/setup.c @@ -49,10 +49,6 @@ struct screen_info screen_info = {  };  #endif -#ifdef CONFIG_CMDLINE_BOOL -static char __initdata builtin_cmdline[COMMAND_LINE_SIZE] = CONFIG_CMDLINE; -#endif /* CONFIG_CMDLINE_BOOL */ -  unsigned long va_pa_offset;  EXPORT_SYMBOL(va_pa_offset);  unsigned long pfn_base; @@ -153,25 +149,6 @@ void __init sbi_save(unsigned int hartid, void *dtb)  	early_init_dt_scan(__va(dtb));  } -/* - * Allow the user to manually add a memory region (in case DTS is broken); - * "mem_end=nn[KkMmGg]" - */ -static int __init mem_end_override(char *p) -{ -	resource_size_t base, end; - -	if (!p) -		return -EINVAL; -	base = (uintptr_t) __pa(PAGE_OFFSET); -	end = memparse(p, &p) & PMD_MASK; -	if (end == 0) -		return -EINVAL; -	memblock_add(base, end - base); -	return 0; -} -early_param("mem_end", mem_end_override); -  static void __init setup_bootmem(void)  {  	struct memblock_region *reg; @@ -204,22 +181,19 @@ static void __init setup_bootmem(void)  	early_init_fdt_scan_reserved_mem();  	memblock_allow_resize();  	memblock_dump_all(); + +	for_each_memblock(memory, reg) { +		unsigned long start_pfn = memblock_region_memory_base_pfn(reg); +		unsigned long end_pfn = memblock_region_memory_end_pfn(reg); + +		memblock_set_node(PFN_PHYS(start_pfn), +		                  PFN_PHYS(end_pfn - start_pfn), +		                  &memblock.memory, 0); +	}  }  void __init setup_arch(char **cmdline_p)  { -#ifdef CONFIG_CMDLINE_BOOL -#ifdef CONFIG_CMDLINE_OVERRIDE -	strlcpy(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE); -#else -	if (builtin_cmdline[0] != '\0') { -		/* Append bootloader command line to built-in */ -		strlcat(builtin_cmdline, " ", COMMAND_LINE_SIZE); -		strlcat(builtin_cmdline, boot_command_line, COMMAND_LINE_SIZE); -		strlcpy(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE); -	} -#endif /* CONFIG_CMDLINE_OVERRIDE */ -#endif /* CONFIG_CMDLINE_BOOL */  	*cmdline_p = boot_command_line;  	parse_early_param(); diff --git a/arch/riscv/kernel/vdso.c b/arch/riscv/kernel/vdso.c index e8a178df8144..582cb153eb24 100644 --- a/arch/riscv/kernel/vdso.c +++ b/arch/riscv/kernel/vdso.c @@ -74,7 +74,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm,  	down_write(&mm->mmap_sem);  	vdso_base = get_unmapped_area(NULL, 0, vdso_len, 0, 0); -	if (unlikely(IS_ERR_VALUE(vdso_base))) { +	if (IS_ERR_VALUE(vdso_base)) {  		ret = vdso_base;  		goto end;  	} diff --git a/arch/riscv/mm/fault.c b/arch/riscv/mm/fault.c index ceebfc29305b..148c98ca9b45 100644 --- a/arch/riscv/mm/fault.c +++ b/arch/riscv/mm/fault.c @@ -238,6 +238,10 @@ vmalloc_fault:  		 * Do _not_ use "tsk->active_mm->pgd" here.  		 * We might be inside an interrupt in the middle  		 * of a task switch. +		 * +		 * Note: Use the old spbtr name instead of using the current +		 * satp name to support binutils 2.29 which doesn't know about +		 * the privileged ISA 1.10 yet.  		 */  		index = pgd_index(addr);  		pgd = (pgd_t *)pfn_to_virt(csr_read(sptbr)) + index; diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c index 9f4bee5e51fd..c77df8142be2 100644 --- a/arch/riscv/mm/init.c +++ b/arch/riscv/mm/init.c @@ -17,6 +17,7 @@  #include <linux/initrd.h>  #include <linux/memblock.h>  #include <linux/swap.h> +#include <linux/sizes.h>  #include <asm/tlbflush.h>  #include <asm/sections.h> @@ -25,11 +26,12 @@  static void __init zone_sizes_init(void)  { -	unsigned long zones_size[MAX_NR_ZONES]; +	unsigned long max_zone_pfns[MAX_NR_ZONES] = { 0, }; -	memset(zones_size, 0, sizeof(zones_size)); -	zones_size[ZONE_NORMAL] = max_mapnr; -	free_area_init_node(0, zones_size, pfn_base, NULL); +	max_zone_pfns[ZONE_DMA32] = PFN_DOWN(min(4UL * SZ_1G, max_low_pfn)); +	max_zone_pfns[ZONE_NORMAL] = max_low_pfn; + +	free_area_init_nodes(max_zone_pfns);  }  void setup_zero_page(void) @@ -39,8 +41,6 @@ void setup_zero_page(void)  void __init paging_init(void)  { -	init_mm.pgd = (pgd_t *)pfn_to_virt(csr_read(sptbr)); -  	setup_zero_page();  	local_flush_tlb_all();  	zone_sizes_init(); diff --git a/include/asm-generic/audit_dir_write.h b/include/asm-generic/audit_dir_write.h index da09fb986459..dd5a9dd7a102 100644 --- a/include/asm-generic/audit_dir_write.h +++ b/include/asm-generic/audit_dir_write.h @@ -27,7 +27,9 @@ __NR_mknod,  __NR_mkdirat,  __NR_mknodat,  __NR_unlinkat, +#ifdef __NR_renameat  __NR_renameat, +#endif  __NR_linkat,  __NR_symlinkat,  #endif | 
