Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8f0a76b8 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "arm: mm: program ptes for access restriction"

parents cf2156f9 f3962317
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -230,6 +230,9 @@ config NEED_RET_TO_USER
config ARCH_MTD_XIP
	bool

config ARCH_WANT_KMAP_ATOMIC_FLUSH
	bool

config VECTORS_BASE
	hex
	default 0xffff0000 if MMU || CPU_HIGH_VECTOR
@@ -652,6 +655,7 @@ config ARCH_QCOM
	select SPARSE_IRQ
	select USE_OF
	select PINCTRL
	select ARCH_WANT_KMAP_ATOMIC_FLUSH
	help
	  Support for Qualcomm MSM/QSD based systems.  This runs on the
	  apps processor of the MSM/QSD and depends on a shared memory
+11 −0
Original line number Diff line number Diff line
@@ -320,6 +320,17 @@
			alignment = <0x0 0x400000>;
			size = <0x0 0x5c00000>;
		};

		/* global autoconfigured region for contiguous allocations */
		linux,cma {
			compatible = "shared-dma-pool";
			alloc-ranges = <0x0 0x00000000 0x0 0xffffffff>;
			reusable;
			alignment = <0x0 0x400000>;
			size = <0x0 0x2000000>;
			linux,cma-default;
		};

	};

	bluetooth: bt_wcn3990 {
+56 −0
Original line number Diff line number Diff line
@@ -10,6 +10,7 @@
 * published by the Free Software Foundation.
 */

#include <linux/cpu.h>
#include <linux/module.h>
#include <linux/highmem.h>
#include <linux/interrupt.h>
@@ -147,3 +148,58 @@ void *kmap_atomic_pfn(unsigned long pfn)

	return (void *)vaddr;
}

#ifdef CONFIG_ARCH_WANT_KMAP_ATOMIC_FLUSH
static void kmap_remove_unused_cpu(int cpu)
{
	int start_idx, idx, type;

	pagefault_disable();
	type = kmap_atomic_idx();
	start_idx = type + 1 + KM_TYPE_NR * cpu;

	for (idx = start_idx; idx < KM_TYPE_NR + KM_TYPE_NR * cpu; idx++) {
		unsigned long vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
		pte_t ptep;

		ptep = get_top_pte(vaddr);
		if (ptep)
			set_top_pte(vaddr, __pte(0));
	}
	pagefault_enable();
}

static void kmap_remove_unused(void *unused)
{
	kmap_remove_unused_cpu(smp_processor_id());
}

void kmap_atomic_flush_unused(void)
{
	on_each_cpu(kmap_remove_unused, NULL, 1);
}

static int hotplug_kmap_atomic_callback(struct notifier_block *nfb,
					unsigned long action, void *hcpu)
{
	switch (action & (~CPU_TASKS_FROZEN)) {
	case CPU_DYING:
		kmap_remove_unused_cpu((int)hcpu);
		break;
	default:
		break;
	}

	return NOTIFY_OK;
}

static struct notifier_block hotplug_kmap_atomic_notifier = {
	.notifier_call = hotplug_kmap_atomic_callback,
};

static int __init init_kmap_atomic(void)
{
	return register_hotcpu_notifier(&hotplug_kmap_atomic_notifier);
}
early_initcall(init_kmap_atomic);
#endif
+54 −4
Original line number Diff line number Diff line
@@ -625,6 +625,9 @@ struct section_perm {
	pmdval_t mask;
	pmdval_t prot;
	pmdval_t clear;
	pteval_t ptemask;
	pteval_t pteprot;
	pteval_t pteclear;
};

static struct section_perm nx_perms[] = {
@@ -634,6 +637,8 @@ static struct section_perm nx_perms[] = {
		.end	= (unsigned long)_stext,
		.mask	= ~PMD_SECT_XN,
		.prot	= PMD_SECT_XN,
		.ptemask = ~L_PTE_XN,
		.pteprot = L_PTE_XN,
	},
	/* Make init RW (set NX). */
	{
@@ -641,6 +646,8 @@ static struct section_perm nx_perms[] = {
		.end	= (unsigned long)_sdata,
		.mask	= ~PMD_SECT_XN,
		.prot	= PMD_SECT_XN,
		.ptemask = ~L_PTE_XN,
		.pteprot = L_PTE_XN,
	},
#ifdef CONFIG_DEBUG_RODATA
	/* Make rodata NX (set RO in ro_perms below). */
@@ -649,6 +656,8 @@ static struct section_perm nx_perms[] = {
		.end    = (unsigned long)__init_begin,
		.mask   = ~PMD_SECT_XN,
		.prot   = PMD_SECT_XN,
		.ptemask = ~L_PTE_XN,
		.pteprot = L_PTE_XN,
	},
#endif
};
@@ -667,6 +676,8 @@ static struct section_perm ro_perms[] = {
		.prot   = PMD_SECT_APX | PMD_SECT_AP_WRITE,
		.clear  = PMD_SECT_AP_WRITE,
#endif
		.ptemask = ~L_PTE_RDONLY,
		.pteprot = L_PTE_RDONLY,
	},
};
#endif
@@ -676,6 +687,35 @@ static struct section_perm ro_perms[] = {
 * copied into each mm). During startup, this is the init_mm. Is only
 * safe to be called with preemption disabled, as under stop_machine().
 */
struct pte_data {
	pteval_t mask;
	pteval_t val;
};

static int __pte_update(pte_t *ptep, pgtable_t token, unsigned long addr,
			void *d)
{
	struct pte_data *data = d;
	pte_t pte = *ptep;

	pte = __pte((pte_val(*ptep) & data->mask) | data->val);
	set_pte_ext(ptep, pte, 0);

	return 0;
}

static inline void pte_update(unsigned long addr, pteval_t mask,
				  pteval_t prot, struct mm_struct *mm)
{
	struct pte_data data;

	data.mask = mask;
	data.val = prot;

	apply_to_page_range(mm, addr, SECTION_SIZE, __pte_update, &data);
	flush_tlb_kernel_range(addr, addr + SECTION_SIZE);
}

static inline void section_update(unsigned long addr, pmdval_t mask,
				  pmdval_t prot, struct mm_struct *mm)
{
@@ -724,11 +764,21 @@ void set_section_perms(struct section_perm *perms, int n, bool set,

		for (addr = perms[i].start;
		     addr < perms[i].end;
		     addr += SECTION_SIZE)
		     addr += SECTION_SIZE) {
			pmd_t *pmd;

			pmd = pmd_offset(pud_offset(pgd_offset(mm, addr),
						addr), addr);
			if (pmd_bad(*pmd))
				section_update(addr, perms[i].mask,
				set ? perms[i].prot : perms[i].clear, mm);
					       set ? perms[i].prot : perms[i].clear,
					       mm);
			else
				pte_update(addr, perms[i].ptemask,
					       set ? perms[i].pteprot : perms[i].pteclear,
					       mm);
		}
	}

}

static void update_sections_early(struct section_perm perms[], int n)