diff options
Diffstat (limited to 'arch/arm/include')
| -rw-r--r-- | arch/arm/include/asm/Kbuild | 2 | ||||
| -rw-r--r-- | arch/arm/include/asm/arch_timer.h | 18 | ||||
| -rw-r--r-- | arch/arm/include/asm/cp15.h | 2 | ||||
| -rw-r--r-- | arch/arm/include/asm/io.h | 2 | ||||
| -rw-r--r-- | arch/arm/include/asm/kvm_mmu.h | 11 | ||||
| -rw-r--r-- | arch/arm/include/asm/stage2_pgtable.h | 6 | ||||
| -rw-r--r-- | arch/arm/include/asm/syscall.h | 49 | ||||
| -rw-r--r-- | arch/arm/include/asm/tlb.h | 255 | ||||
| -rw-r--r-- | arch/arm/include/uapi/asm/Kbuild | 1 | ||||
| -rw-r--r-- | arch/arm/include/uapi/asm/kvm_para.h | 2 | 
10 files changed, 57 insertions, 291 deletions
| diff --git a/arch/arm/include/asm/Kbuild b/arch/arm/include/asm/Kbuild index a8a4eb7f6dae..41deac2451af 100644 --- a/arch/arm/include/asm/Kbuild +++ b/arch/arm/include/asm/Kbuild @@ -9,10 +9,10 @@ generic-y += kdebug.h  generic-y += local.h  generic-y += local64.h  generic-y += mm-arch-hooks.h +generic-y += mmiowb.h  generic-y += msi.h  generic-y += parport.h  generic-y += preempt.h -generic-y += rwsem.h  generic-y += seccomp.h  generic-y += segment.h  generic-y += serial.h diff --git a/arch/arm/include/asm/arch_timer.h b/arch/arm/include/asm/arch_timer.h index 0a8d7bba2cb0..4b66ecd6be99 100644 --- a/arch/arm/include/asm/arch_timer.h +++ b/arch/arm/include/asm/arch_timer.h @@ -11,6 +11,10 @@  #include <clocksource/arm_arch_timer.h>  #ifdef CONFIG_ARM_ARCH_TIMER +/* 32bit ARM doesn't know anything about timer errata... */ +#define has_erratum_handler(h)		(false) +#define erratum_handler(h)		(arch_timer_##h) +  int arch_timer_arch_init(void);  /* @@ -79,7 +83,7 @@ static inline u32 arch_timer_get_cntfrq(void)  	return val;  } -static inline u64 arch_counter_get_cntpct(void) +static inline u64 __arch_counter_get_cntpct(void)  {  	u64 cval; @@ -88,7 +92,12 @@ static inline u64 arch_counter_get_cntpct(void)  	return cval;  } -static inline u64 arch_counter_get_cntvct(void) +static inline u64 __arch_counter_get_cntpct_stable(void) +{ +	return __arch_counter_get_cntpct(); +} + +static inline u64 __arch_counter_get_cntvct(void)  {  	u64 cval; @@ -97,6 +106,11 @@ static inline u64 arch_counter_get_cntvct(void)  	return cval;  } +static inline u64 __arch_counter_get_cntvct_stable(void) +{ +	return __arch_counter_get_cntvct(); +} +  static inline u32 arch_timer_get_cntkctl(void)  {  	u32 cntkctl; diff --git a/arch/arm/include/asm/cp15.h b/arch/arm/include/asm/cp15.h index 07e27f212dc7..d2453e2d3f1f 100644 --- a/arch/arm/include/asm/cp15.h +++ b/arch/arm/include/asm/cp15.h @@ -68,6 +68,8 @@  #define BPIALL				__ACCESS_CP15(c7, 0, c5, 6)  #define ICIALLU				__ACCESS_CP15(c7, 0, c5, 0) +#define CNTVCT				__ACCESS_CP15_64(1, c14) +  extern unsigned long cr_alignment;	/* defined in entry-armv.S */  static inline unsigned long get_cr(void) diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h index 6b51826ab3d1..7e22c81398c4 100644 --- a/arch/arm/include/asm/io.h +++ b/arch/arm/include/asm/io.h @@ -281,8 +281,6 @@ extern void _memcpy_fromio(void *, const volatile void __iomem *, size_t);  extern void _memcpy_toio(volatile void __iomem *, const void *, size_t);  extern void _memset_io(volatile void __iomem *, int, size_t); -#define mmiowb() -  /*   *  Memory access primitives   *  ------------------------ diff --git a/arch/arm/include/asm/kvm_mmu.h b/arch/arm/include/asm/kvm_mmu.h index 2de96a180166..31de4ab93005 100644 --- a/arch/arm/include/asm/kvm_mmu.h +++ b/arch/arm/include/asm/kvm_mmu.h @@ -381,6 +381,17 @@ static inline int kvm_read_guest_lock(struct kvm *kvm,  	return ret;  } +static inline int kvm_write_guest_lock(struct kvm *kvm, gpa_t gpa, +				       const void *data, unsigned long len) +{ +	int srcu_idx = srcu_read_lock(&kvm->srcu); +	int ret = kvm_write_guest(kvm, gpa, data, len); + +	srcu_read_unlock(&kvm->srcu, srcu_idx); + +	return ret; +} +  static inline void *kvm_get_hyp_vector(void)  {  	switch(read_cpuid_part()) { diff --git a/arch/arm/include/asm/stage2_pgtable.h b/arch/arm/include/asm/stage2_pgtable.h index de2089501b8b..9587517649bd 100644 --- a/arch/arm/include/asm/stage2_pgtable.h +++ b/arch/arm/include/asm/stage2_pgtable.h @@ -32,14 +32,14 @@  #define stage2_pgd_present(kvm, pgd)		pgd_present(pgd)  #define stage2_pgd_populate(kvm, pgd, pud)	pgd_populate(NULL, pgd, pud)  #define stage2_pud_offset(kvm, pgd, address)	pud_offset(pgd, address) -#define stage2_pud_free(kvm, pud)		pud_free(NULL, pud) +#define stage2_pud_free(kvm, pud)		do { } while (0)  #define stage2_pud_none(kvm, pud)		pud_none(pud)  #define stage2_pud_clear(kvm, pud)		pud_clear(pud)  #define stage2_pud_present(kvm, pud)		pud_present(pud)  #define stage2_pud_populate(kvm, pud, pmd)	pud_populate(NULL, pud, pmd)  #define stage2_pmd_offset(kvm, pud, address)	pmd_offset(pud, address) -#define stage2_pmd_free(kvm, pmd)		pmd_free(NULL, pmd) +#define stage2_pmd_free(kvm, pmd)		free_page((unsigned long)pmd)  #define stage2_pud_huge(kvm, pud)		pud_huge(pud) @@ -75,6 +75,8 @@ static inline bool kvm_stage2_has_pud(struct kvm *kvm)  #define S2_PMD_MASK				PMD_MASK  #define S2_PMD_SIZE				PMD_SIZE +#define S2_PUD_MASK				PUD_MASK +#define S2_PUD_SIZE				PUD_SIZE  static inline bool kvm_stage2_has_pmd(struct kvm *kvm)  { diff --git a/arch/arm/include/asm/syscall.h b/arch/arm/include/asm/syscall.h index 06dea6bce293..fd02761ba06c 100644 --- a/arch/arm/include/asm/syscall.h +++ b/arch/arm/include/asm/syscall.h @@ -55,56 +55,25 @@ static inline void syscall_set_return_value(struct task_struct *task,  static inline void syscall_get_arguments(struct task_struct *task,  					 struct pt_regs *regs, -					 unsigned int i, unsigned int n,  					 unsigned long *args)  { -	if (n == 0) -		return; - -	if (i + n > SYSCALL_MAX_ARGS) { -		unsigned long *args_bad = args + SYSCALL_MAX_ARGS - i; -		unsigned int n_bad = n + i - SYSCALL_MAX_ARGS; -		pr_warn("%s called with max args %d, handling only %d\n", -			__func__, i + n, SYSCALL_MAX_ARGS); -		memset(args_bad, 0, n_bad * sizeof(args[0])); -		n = SYSCALL_MAX_ARGS - i; -	} - -	if (i == 0) { -		args[0] = regs->ARM_ORIG_r0; -		args++; -		i++; -		n--; -	} - -	memcpy(args, ®s->ARM_r0 + i, n * sizeof(args[0])); +	args[0] = regs->ARM_ORIG_r0; +	args++; + +	memcpy(args, ®s->ARM_r0 + 1, 5 * sizeof(args[0]));  }  static inline void syscall_set_arguments(struct task_struct *task,  					 struct pt_regs *regs, -					 unsigned int i, unsigned int n,  					 const unsigned long *args)  { -	if (n == 0) -		return; - -	if (i + n > SYSCALL_MAX_ARGS) { -		pr_warn("%s called with max args %d, handling only %d\n", -			__func__, i + n, SYSCALL_MAX_ARGS); -		n = SYSCALL_MAX_ARGS - i; -	} - -	if (i == 0) { -		regs->ARM_ORIG_r0 = args[0]; -		args++; -		i++; -		n--; -	} - -	memcpy(®s->ARM_r0 + i, args, n * sizeof(args[0])); +	regs->ARM_ORIG_r0 = args[0]; +	args++; + +	memcpy(®s->ARM_r0 + 1, args, 5 * sizeof(args[0]));  } -static inline int syscall_get_arch(void) +static inline int syscall_get_arch(struct task_struct *task)  {  	/* ARM tasks don't change audit architectures on the fly. */  	return AUDIT_ARCH_ARM; diff --git a/arch/arm/include/asm/tlb.h b/arch/arm/include/asm/tlb.h index f854148c8d7c..bc6d04a09899 100644 --- a/arch/arm/include/asm/tlb.h +++ b/arch/arm/include/asm/tlb.h @@ -33,271 +33,42 @@  #include <asm/pgalloc.h>  #include <asm/tlbflush.h> -#define MMU_GATHER_BUNDLE	8 - -#ifdef CONFIG_HAVE_RCU_TABLE_FREE  static inline void __tlb_remove_table(void *_table)  {  	free_page_and_swap_cache((struct page *)_table);  } -struct mmu_table_batch { -	struct rcu_head		rcu; -	unsigned int		nr; -	void			*tables[0]; -}; - -#define MAX_TABLE_BATCH		\ -	((PAGE_SIZE - sizeof(struct mmu_table_batch)) / sizeof(void *)) - -extern void tlb_table_flush(struct mmu_gather *tlb); -extern void tlb_remove_table(struct mmu_gather *tlb, void *table); - -#define tlb_remove_entry(tlb, entry)	tlb_remove_table(tlb, entry) -#else -#define tlb_remove_entry(tlb, entry)	tlb_remove_page(tlb, entry) -#endif /* CONFIG_HAVE_RCU_TABLE_FREE */ - -/* - * TLB handling.  This allows us to remove pages from the page - * tables, and efficiently handle the TLB issues. - */ -struct mmu_gather { -	struct mm_struct	*mm; -#ifdef CONFIG_HAVE_RCU_TABLE_FREE -	struct mmu_table_batch	*batch; -	unsigned int		need_flush; -#endif -	unsigned int		fullmm; -	struct vm_area_struct	*vma; -	unsigned long		start, end; -	unsigned long		range_start; -	unsigned long		range_end; -	unsigned int		nr; -	unsigned int		max; -	struct page		**pages; -	struct page		*local[MMU_GATHER_BUNDLE]; -}; - -DECLARE_PER_CPU(struct mmu_gather, mmu_gathers); - -/* - * This is unnecessarily complex.  There's three ways the TLB shootdown - * code is used: - *  1. Unmapping a range of vmas.  See zap_page_range(), unmap_region(). - *     tlb->fullmm = 0, and tlb_start_vma/tlb_end_vma will be called. - *     tlb->vma will be non-NULL. - *  2. Unmapping all vmas.  See exit_mmap(). - *     tlb->fullmm = 1, and tlb_start_vma/tlb_end_vma will be called. - *     tlb->vma will be non-NULL.  Additionally, page tables will be freed. - *  3. Unmapping argument pages.  See shift_arg_pages(). - *     tlb->fullmm = 0, but tlb_start_vma/tlb_end_vma will not be called. - *     tlb->vma will be NULL. - */ -static inline void tlb_flush(struct mmu_gather *tlb) -{ -	if (tlb->fullmm || !tlb->vma) -		flush_tlb_mm(tlb->mm); -	else if (tlb->range_end > 0) { -		flush_tlb_range(tlb->vma, tlb->range_start, tlb->range_end); -		tlb->range_start = TASK_SIZE; -		tlb->range_end = 0; -	} -} - -static inline void tlb_add_flush(struct mmu_gather *tlb, unsigned long addr) -{ -	if (!tlb->fullmm) { -		if (addr < tlb->range_start) -			tlb->range_start = addr; -		if (addr + PAGE_SIZE > tlb->range_end) -			tlb->range_end = addr + PAGE_SIZE; -	} -} - -static inline void __tlb_alloc_page(struct mmu_gather *tlb) -{ -	unsigned long addr = __get_free_pages(GFP_NOWAIT | __GFP_NOWARN, 0); - -	if (addr) { -		tlb->pages = (void *)addr; -		tlb->max = PAGE_SIZE / sizeof(struct page *); -	} -} - -static inline void tlb_flush_mmu_tlbonly(struct mmu_gather *tlb) -{ -	tlb_flush(tlb); -#ifdef CONFIG_HAVE_RCU_TABLE_FREE -	tlb_table_flush(tlb); -#endif -} - -static inline void tlb_flush_mmu_free(struct mmu_gather *tlb) -{ -	free_pages_and_swap_cache(tlb->pages, tlb->nr); -	tlb->nr = 0; -	if (tlb->pages == tlb->local) -		__tlb_alloc_page(tlb); -} - -static inline void tlb_flush_mmu(struct mmu_gather *tlb) -{ -	tlb_flush_mmu_tlbonly(tlb); -	tlb_flush_mmu_free(tlb); -} - -static inline void -arch_tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, -			unsigned long start, unsigned long end) -{ -	tlb->mm = mm; -	tlb->fullmm = !(start | (end+1)); -	tlb->start = start; -	tlb->end = end; -	tlb->vma = NULL; -	tlb->max = ARRAY_SIZE(tlb->local); -	tlb->pages = tlb->local; -	tlb->nr = 0; -	__tlb_alloc_page(tlb); +#include <asm-generic/tlb.h> -#ifdef CONFIG_HAVE_RCU_TABLE_FREE -	tlb->batch = NULL; +#ifndef CONFIG_HAVE_RCU_TABLE_FREE +#define tlb_remove_table(tlb, entry) tlb_remove_page(tlb, entry)  #endif -} - -static inline void -arch_tlb_finish_mmu(struct mmu_gather *tlb, -			unsigned long start, unsigned long end, bool force) -{ -	if (force) { -		tlb->range_start = start; -		tlb->range_end = end; -	} - -	tlb_flush_mmu(tlb); - -	/* keep the page table cache within bounds */ -	check_pgt_cache(); - -	if (tlb->pages != tlb->local) -		free_pages((unsigned long)tlb->pages, 0); -} - -/* - * Memorize the range for the TLB flush. - */ -static inline void -tlb_remove_tlb_entry(struct mmu_gather *tlb, pte_t *ptep, unsigned long addr) -{ -	tlb_add_flush(tlb, addr); -} - -#define tlb_remove_huge_tlb_entry(h, tlb, ptep, address)	\ -	tlb_remove_tlb_entry(tlb, ptep, address) -/* - * In the case of tlb vma handling, we can optimise these away in the - * case where we're doing a full MM flush.  When we're doing a munmap, - * the vmas are adjusted to only cover the region to be torn down. - */ -static inline void -tlb_start_vma(struct mmu_gather *tlb, struct vm_area_struct *vma) -{ -	if (!tlb->fullmm) { -		flush_cache_range(vma, vma->vm_start, vma->vm_end); -		tlb->vma = vma; -		tlb->range_start = TASK_SIZE; -		tlb->range_end = 0; -	} -}  static inline void -tlb_end_vma(struct mmu_gather *tlb, struct vm_area_struct *vma) -{ -	if (!tlb->fullmm) -		tlb_flush(tlb); -} - -static inline bool __tlb_remove_page(struct mmu_gather *tlb, struct page *page) -{ -	tlb->pages[tlb->nr++] = page; -	VM_WARN_ON(tlb->nr > tlb->max); -	if (tlb->nr == tlb->max) -		return true; -	return false; -} - -static inline void tlb_remove_page(struct mmu_gather *tlb, struct page *page) -{ -	if (__tlb_remove_page(tlb, page)) -		tlb_flush_mmu(tlb); -} - -static inline bool __tlb_remove_page_size(struct mmu_gather *tlb, -					  struct page *page, int page_size) -{ -	return __tlb_remove_page(tlb, page); -} - -static inline void tlb_remove_page_size(struct mmu_gather *tlb, -					struct page *page, int page_size) -{ -	return tlb_remove_page(tlb, page); -} - -static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte, -	unsigned long addr) +__pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte, unsigned long addr)  {  	pgtable_page_dtor(pte); -#ifdef CONFIG_ARM_LPAE -	tlb_add_flush(tlb, addr); -#else +#ifndef CONFIG_ARM_LPAE  	/*  	 * With the classic ARM MMU, a pte page has two corresponding pmd  	 * entries, each covering 1MB.  	 */ -	addr &= PMD_MASK; -	tlb_add_flush(tlb, addr + SZ_1M - PAGE_SIZE); -	tlb_add_flush(tlb, addr + SZ_1M); +	addr = (addr & PMD_MASK) + SZ_1M; +	__tlb_adjust_range(tlb, addr - PAGE_SIZE, 2 * PAGE_SIZE);  #endif -	tlb_remove_entry(tlb, pte); -} - -static inline void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmdp, -				  unsigned long addr) -{ -#ifdef CONFIG_ARM_LPAE -	tlb_add_flush(tlb, addr); -	tlb_remove_entry(tlb, virt_to_page(pmdp)); -#endif +	tlb_remove_table(tlb, pte);  }  static inline void -tlb_remove_pmd_tlb_entry(struct mmu_gather *tlb, pmd_t *pmdp, unsigned long addr) -{ -	tlb_add_flush(tlb, addr); -} - -#define pte_free_tlb(tlb, ptep, addr)	__pte_free_tlb(tlb, ptep, addr) -#define pmd_free_tlb(tlb, pmdp, addr)	__pmd_free_tlb(tlb, pmdp, addr) -#define pud_free_tlb(tlb, pudp, addr)	pud_free((tlb)->mm, pudp) - -#define tlb_migrate_finish(mm)		do { } while (0) - -#define tlb_remove_check_page_size_change tlb_remove_check_page_size_change -static inline void tlb_remove_check_page_size_change(struct mmu_gather *tlb, -						     unsigned int page_size) +__pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmdp, unsigned long addr)  { -} - -static inline void tlb_flush_remove_tables(struct mm_struct *mm) -{ -} +#ifdef CONFIG_ARM_LPAE +	struct page *page = virt_to_page(pmdp); -static inline void tlb_flush_remove_tables_local(void *arg) -{ +	tlb_remove_table(tlb, page); +#endif  }  #endif /* CONFIG_MMU */ diff --git a/arch/arm/include/uapi/asm/Kbuild b/arch/arm/include/uapi/asm/Kbuild index 23b4464c0995..ce8573157774 100644 --- a/arch/arm/include/uapi/asm/Kbuild +++ b/arch/arm/include/uapi/asm/Kbuild @@ -3,3 +3,4 @@  generated-y += unistd-common.h  generated-y += unistd-oabi.h  generated-y += unistd-eabi.h +generic-y += kvm_para.h diff --git a/arch/arm/include/uapi/asm/kvm_para.h b/arch/arm/include/uapi/asm/kvm_para.h deleted file mode 100644 index baacc4996d18..000000000000 --- a/arch/arm/include/uapi/asm/kvm_para.h +++ /dev/null @@ -1,2 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -#include <asm-generic/kvm_para.h> |