// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * Copyright 2007-2008 Paul Mackerras, IBM Corp.
 */

#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/gfp.h>
#include <linux/types.h>
#include <linux/pagewalk.h>
#include <linux/hugetlb.h>
#include <linux/syscalls.h>

#include <linux/pgtable.h>
#include <linux/uaccess.h>

/*
 * Free all pages allocated for subpage protection maps and pointers.
 * Also makes sure that the subpage_prot_table structure is
 * reinitialized for the next user.
 */
void subpage_prot_free(struct mm_struct *mm)
{
	struct subpage_prot_table *spt = mm_ctx_subpage_prot(&mm->context);
	unsigned long i, j, addr;
	u32 **p;

	if (!spt)
		return;

	for (i = 0; i < 4; ++i) {
		if (spt->low_prot[i]) {
			free_page((unsigned long)spt->low_prot[i]);
			spt->low_prot[i] = NULL;
		}
	}
	addr = 0;
	for (i = 0; i < (TASK_SIZE_USER64 >> 43); ++i) {
		p = spt->protptrs[i];
		if (!p)
			continue;
		spt->protptrs[i] = NULL;
		for (j = 0; j < SBP_L2_COUNT && addr < spt->maxaddr;
		     ++j, addr += PAGE_SIZE)
			if (p[j])
				free_page((unsigned long)p[j]);
		free_page((unsigned long)p);
	}
	spt->maxaddr = 0;
	kfree(spt);
}

static void hpte_flush_range(struct mm_struct *mm, unsigned long addr,
			     int npages)
{
	pgd_t *pgd;
	p4d_t *p4d;
	pud_t *pud;
	pmd_t *pmd;
	pte_t *pte;
	spinlock_t *ptl;

	pgd = pgd_offset(mm, addr);
	p4d = p4d_offset(pgd, addr);
	if (p4d_none(*p4d))
		return;
	pud = pud_offset(p4d, addr);
	if (pud_none(*pud))
		return;
	pmd = pmd_offset(pud, addr);
	if (pmd_none(*pmd))
		return;
	pte = pte_offset_map_lock(mm, pmd, addr, &ptl);
	arch_enter_lazy_mmu_mode();
	for (; npages > 0; --npages) {
		pte_update(mm, addr, pte, 0, 0, 0);
		addr += PAGE_SIZE;
		++pte;
	}
	arch_leave_lazy_mmu_mode();
	pte_unmap_unlock(pte - 1, ptl);
}

/*
 * Clear the subpage protection map for an address range, allowing
 * all accesses that are allowed by the pte permissions.
 */
static void subpage_prot_clear(unsigned long addr, unsigned long len)
{
	struct mm_struct *mm = current->mm;
	struct subpage_prot_table *spt;
	u32 **spm, *spp;
	unsigned long i;
	size_t nw;
	unsigned long next, limit;

	mmap_write_lock(mm);

	spt = mm_ctx_subpage_prot(&mm->context);
	if (!spt)
		goto err_out;

	limit = addr + len;
	if (limit > spt->maxaddr)
		limit = spt->maxaddr;
	for (; addr < limit; addr = next) {
		next = pmd_addr_end(addr, limit);
		if (addr < 0x100000000UL) {
			spm = spt->low_prot;
		} else {
			spm = spt->protptrs[addr >> SBP_L3_SHIFT];
			if (!spm)
				continue;
		}
		spp = spm[(addr >> SBP_L2_SHIFT) & (SBP_L2_COUNT - 1)];
		if (!spp)
			continue;
		spp += (addr >> PAGE_SHIFT) & (SBP_L1_COUNT - 1);

		i = (addr >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
		nw = PTRS_PER_PTE - i;
		if (addr + (nw << PAGE_SHIFT) > next)
			nw = (next - addr) >> PAGE_SHIFT;

		memset(spp, 0, nw * sizeof(u32));

		/* now flush any existing HPTEs for the range */
		hpte_flush_range(mm, addr, nw);
	}

err_out:
	mmap_write_unlock(mm);
}

#ifdef CONFIG_TRANSPARENT_HUGEPAGE
static int subpage_walk_pmd_entry(pmd_t *pmd, unsigned long addr,
				  unsigned long end, struct mm_walk *walk)
{
	struct vm_area_struct *vma = walk->vma;
	split_huge_pmd(vma, pmd, addr);
	return 0;
}

static const struct mm_walk_ops subpage_walk_ops = {
	.pmd_entry	= subpage_walk_pmd_entry,
};

static void subpage_mark_vma_nohuge(struct mm_struct *mm, unsigned long addr,
				    unsigned long len)
{
	struct vm_area_struct *vma;

	/*
	 * We don't try too hard, we just mark all the vma in that range
	 * VM_NOHUGEPAGE and split them.
	 */
	vma = find_vma(mm, addr);
	/*
	 * If the range is in unmapped range, just return
	 */
	if (vma && ((addr + len) <= vma->vm_start))
		return;

	while (vma) {
		if (vma->vm_start >= (addr + len))
			break;
		vma->vm_flags |= VM_NOHUGEPAGE;
		walk_page_vma(vma, &subpage_walk_ops, NULL);
		vma = vma->vm_next;
	}
}
#else
static void subpage_mark_vma_nohuge(struct mm_struct *mm, unsigned long addr,
				    unsigned long len)
{
	return;
}
#endif

/*
 * Copy in a subpage protection map for an address range.
 * The map has 2 bits per 4k subpage, so 32 bits per 64k page.
 * Each 2-bit field is 0 to allow any access, 1 to prevent writes,
 * 2 or 3 to prevent all accesses.
 * Note that the normal page protections also apply; the subpage
 * protection mechanism is an additional constraint, so putting 0
 * in a 2-bit field won't allow writes to a page that is otherwise
 * write-protected.
 */
SYSCALL_DEFINE3(subpage_prot, unsigned long, addr,
		unsigned long, len, u32 __user *, map)
{
	struct mm_struct *mm = current->mm;
	struct subpage_prot_table *spt;
	u32 **spm, *spp;
	unsigned long i;
	size_t nw;
	unsigned long next, limit;
	int err;

	if (radix_enabled())
		return -ENOENT;

	/* Check parameters */
	if ((addr & ~PAGE_MASK) || (len & ~PAGE_MASK) ||
	    addr >= mm->task_size || len >= mm->task_size ||
	    addr + len > mm->task_size)
		return -EINVAL;

	if (is_hugepage_only_range(mm, addr, len))
		return -EINVAL;

	if (!map) {
		/* Clear out the protection map for the address range */
		subpage_prot_clear(addr, len);
		return 0;
	}

	if (!access_ok(map, (len >> PAGE_SHIFT) * sizeof(u32)))
		return -EFAULT;

	mmap_write_lock(mm);

	spt = mm_ctx_subpage_prot(&mm->context);
	if (!spt) {
		/*
		 * Allocate subpage prot table if not already done.
		 * Do this with mmap_lock held
		 */
		spt = kzalloc(sizeof(struct subpage_prot_table), GFP_KERNEL);
		if (!spt) {
			err = -ENOMEM;
			goto out;
		}
		mm->context.hash_context->spt = spt;
	}

	subpage_mark_vma_nohuge(mm, addr, len);
	for (limit = addr + len; addr < limit; addr = next) {
		next = pmd_addr_end(addr, limit);
		err = -ENOMEM;
		if (addr < 0x100000000UL) {
			spm = spt->low_prot;
		} else {
			spm = spt->protptrs[addr >> SBP_L3_SHIFT];
			if (!spm) {
				spm = (u32 **)get_zeroed_page(GFP_KERNEL);
				if (!spm)
					goto out;
				spt->protptrs[addr >> SBP_L3_SHIFT] = spm;
			}
		}
		spm += (addr >> SBP_L2_SHIFT) & (SBP_L2_COUNT - 1);
		spp = *spm;
		if (!spp) {
			spp = (u32 *)get_zeroed_page(GFP_KERNEL);
			if (!spp)
				goto out;
			*spm = spp;
		}
		spp += (addr >> PAGE_SHIFT) & (SBP_L1_COUNT - 1);

		local_irq_disable();
		demote_segment_4k(mm, addr);
		local_irq_enable();

		i = (addr >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
		nw = PTRS_PER_PTE - i;
		if (addr + (nw << PAGE_SHIFT) > next)
			nw = (next - addr) >> PAGE_SHIFT;

		mmap_write_unlock(mm);
		if (__copy_from_user(spp, map, nw * sizeof(u32)))
			return -EFAULT;
		map += nw;
		mmap_write_lock(mm);

		/* now flush any existing HPTEs for the range */
		hpte_flush_range(mm, addr, nw);
	}
	if (limit > spt->maxaddr)
		spt->maxaddr = limit;
	err = 0;
 out:
	mmap_write_unlock(mm);
	return err;
}
