Re: [PATCH v2] [POWERPC] Provide a way to protect 4k subpages when using 64k pages

2008-01-05 Thread Arnd Bergmann
On Saturday 05 January 2008, Paul Mackerras wrote:
> This version allocates a new system call number for the subpage_prot
> syscall.

Ah, good. Thanks!

> --- a/arch/powerpc/kernel/syscalls.c
> +++ b/arch/powerpc/kernel/syscalls.c
> @@ -328,3 +328,7 @@ void do_show_syscall_exit(unsigned long r3)
>  {
> printk(" -> %lx, current=%p cpu=%d\n", r3, current, 
> smp_processor_id());
>  }
> +
> +#ifndef CONFIG_PPC_SUBPAGE_PROT
> +cond_syscall(subpage_prot);
> +#endif

cond_syscall is defined in a way that you don't need the #ifdef here,
and the other users always have it unconditionally.

> +/*
> + * 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)

syscalls are normally marked asmlinkage, right? I know that it doesn't
have an effect on powerpc, but so far, we have been using the convention
anyway, AFAIK.

Also, I think there should be a declaration in asm/syscalls.h so we don't
get a warning about an undeclared global function from sparse.

> diff --git a/include/asm-powerpc/systbl.h b/include/asm-powerpc/systbl.h
> index 11d5383..0c8b0d6 100644
> --- a/include/asm-powerpc/systbl.h
> +++ b/include/asm-powerpc/systbl.h
> @@ -313,3 +313,4 @@ COMPAT_SYS_SPU(timerfd)
>  SYSCALL_SPU(eventfd)
>  COMPAT_SYS_SPU(sync_file_range2)
>  COMPAT_SYS(fallocate)
> +SYSCALL(subpage_prot)

The convention I've used for SPU syscalls is to allow them unless there is
a specific reason why it's harmful or not possible for the SPU to do it.
I think it should be SYSCALL_SPU because of that.

I already missed the addition of fallocate, which I think should have been
COMPAT_SYS_SPU. I can send you a patch for that one if you like.

Arnd <><
___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


[PATCH v2] [POWERPC] Provide a way to protect 4k subpages when using 64k pages

2008-01-05 Thread Paul Mackerras
Using 64k pages on 64-bit PowerPC systems makes life difficult for
emulators that are trying to emulate an ISA, such as x86, which use a
smaller page size, since the emulator can no longer use the MMU and
the normal system calls for controlling page protections.  Of course,
the emulator can emulate the MMU by checking and possibly remapping
the address for each memory access in software, but that is pretty
slow.

This provides a facility for such programs to control the access
permissions on individual 4k sub-pages of 64k pages.  The idea is
that the emulator supplies an array of protection masks to apply to a
specified range of virtual addresses.  These masks are applied at the
level where hardware PTEs are inserted into the hardware page table
based on the Linux PTEs, so the Linux PTEs are not affected.  Note
that this new mechanism does not allow any access that would otherwise
be prohibited; it can only prohibit accesses that would otherwise be
allowed.  This new facility is only available on 64-bit PowerPC and
only when the kernel is configured for 64k pages.

The masks are supplied using a new subpage_prot system call, which
takes a starting virtual address and length, and a pointer to an array
of protection masks in memory.  The array has a 32-bit word per 64k
page to be protected; each 32-bit word consists of 16 2-bit fields,
for which 0 allows any access (that is otherwise allowed), 1 prevents
write accesses, and 2 or 3 prevent any access.

Implicit in this is that the regions of the address space that are
protected are switched to use 4k hardware pages rather than 64k
hardware pages (on machines with hardware 64k page support).  In fact
the whole process is switched to use 4k hardware pages when the
subpage_prot system call is used, but this could be improved in future
to switch only the affected segments.

The subpage protection bits are stored in a 3 level tree akin to the
page table tree.  The top level of this tree is stored in a structure
that is appended to the top level of the page table tree, i.e., the
pgd array.  Since it will often only be 32-bit addresses (below 4GB)
that are protected, the pointers to the first four bottom level pages
are also stored in this structure (each bottom level page contains the
protection bits for 1GB of address space), so the protection bits for
addresses below 4GB can be accessed with one fewer loads than those
for higher addresses.

Signed-off-by: Paul Mackerras <[EMAIL PROTECTED]>
---
This version allocates a new system call number for the subpage_prot
syscall.

diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 66a3d8c..53d0955 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -342,6 +342,14 @@ config PPC_64K_PAGES
  while on hardware with such support, it will be used to map
  normal application pages.
 
+config PPC_SUBPAGE_PROT
+   bool "Support setting protections for 4k subpages"
+   depends on PPC_64K_PAGES
+   help
+ This option adds support for a system call to allow user programs
+ to set access permissions (read/write, readonly, or no access)
+ on the 4k subpages of each 64k page.
+
 config SCHED_SMT
bool "SMT (Hyperthreading) scheduler support"
depends on PPC64 && SMP
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S
index c349868..11b4f6d 100644
--- a/arch/powerpc/kernel/head_64.S
+++ b/arch/powerpc/kernel/head_64.S
@@ -903,6 +903,7 @@ handle_page_fault:
  * the PTE insertion
  */
 12:bl  .save_nvgprs
+   mr  r5,r3
addir3,r1,STACK_FRAME_OVERHEAD
ld  r4,_DAR(r1)
bl  .low_hash_fault
diff --git a/arch/powerpc/kernel/syscalls.c b/arch/powerpc/kernel/syscalls.c
index 3b1d5dd..18be22e 100644
--- a/arch/powerpc/kernel/syscalls.c
+++ b/arch/powerpc/kernel/syscalls.c
@@ -328,3 +328,7 @@ void do_show_syscall_exit(unsigned long r3)
 {
printk(" -> %lx, current=%p cpu=%d\n", r3, current, smp_processor_id());
 }
+
+#ifndef CONFIG_PPC_SUBPAGE_PROT
+cond_syscall(subpage_prot);
+#endif
diff --git a/arch/powerpc/mm/Makefile b/arch/powerpc/mm/Makefile
index 20629ae..41649a5 100644
--- a/arch/powerpc/mm/Makefile
+++ b/arch/powerpc/mm/Makefile
@@ -22,3 +22,4 @@ obj-$(CONFIG_FSL_BOOKE)   += fsl_booke_mmu.o
 obj-$(CONFIG_NEED_MULTIPLE_NODES) += numa.o
 obj-$(CONFIG_PPC_MM_SLICES)+= slice.o
 obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
+obj-$(CONFIG_PPC_SUBPAGE_PROT) += subpage-prot.o
diff --git a/arch/powerpc/mm/hash_low_64.S b/arch/powerpc/mm/hash_low_64.S
index e935edd..21d2484 100644
--- a/arch/powerpc/mm/hash_low_64.S
+++ b/arch/powerpc/mm/hash_low_64.S
@@ -331,7 +331,8 @@ htab_pte_insert_failure:
  */
 
 /* _hash_page_4K(unsigned long ea, unsigned long access, unsigned long vsid,
- *  pte_t *ptep, unsigned long trap, int local, int ssize)
+ *  pte_t *ptep, unsigned lo