/*
 * Copyright 2007-2008 Paul Mackerras, IBM Corp.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version
 * 2 of the License, or (at your option) any later version.
 */

#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/gfp.h>
#include <linux/slab.h>
#include <linux/types.h>
#include <linux/mm.h>
#include <linux/hugetlb.h>

#include <asm/pgtable.h>
#include <asm/uaccess.h>
#include <asm/tlbflush.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(pgd_t *pgd)
{
	struct subpage_prot_table *spt = pgd_subpage_prot(pgd);
	unsigned long i, j, addr;
	u32 **p;

	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 < 2; ++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;
}

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

	pgd = pgd_offset(mm, addr);
	if (pgd_none(*pgd))
		return;
	pud = pud_offset(pgd, 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);
		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 = pgd_subpage_prot(mm->pgd);
	u32 **spm, *spp;
	int i, nw;
	unsigned long next, limit;

	down_write(&mm->mmap_sem);
	limit = addr + len;
	if (limit > spt->maxaddr)
		limit = spt->maxaddr;
	for (; addr < limit; addr = next) {
		next = pmd_addr_end(addr, limit);
		if (addr < 0x100000000) {
			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);
	}
	up_write(&mm->mmap_sem);
}

/*
 * 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.
 */
long sys_subpage_prot(unsigned long addr, unsigned long len, u32 __user *map)
{
	struct mm_struct *mm = current->mm;
	struct subpage_prot_table *spt = pgd_subpage_prot(mm->pgd);
	u32 **spm, *spp;
	int i, nw;
	unsigned long next, limit;
	int err;

	/* Check parameters */
	if ((addr & ~PAGE_MASK) || (len & ~PAGE_MASK) ||
	    addr >= TASK_SIZE || len >= TASK_SIZE || addr + len > 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(VERIFY_READ, map, (len >> PAGE_SHIFT) * sizeof(u32)))
		return -EFAULT;

	down_write(&mm->mmap_sem);
	for (limit = addr + len; addr < limit; addr = next) {
		next = pmd_addr_end(addr, limit);
		err = -ENOMEM;
		if (addr < 0x100000000) {
			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;

		up_write(&mm->mmap_sem);
		err = -EFAULT;
		if (__copy_from_user(spp, map, nw * sizeof(u32)))
			goto out2;
		map += nw;
		down_write(&mm->mmap_sem);

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