Documentation: x86: convert protection-keys.txt to reST

This converts the plain text documentation to reStructuredText format and
add it to Sphinx TOC tree. No essential content change.

Signed-off-by: Changbin Du <changbin.du@gmail.com>
Reviewed-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
Signed-off-by: Jonathan Corbet <corbet@lwn.net>
This commit is contained in:
Changbin Du 2019-05-08 23:21:26 +08:00 committed by Jonathan Corbet
parent 2f6eae4730
commit 28e21eac94
2 changed files with 22 additions and 12 deletions

View File

@ -18,3 +18,4 @@ x86-specific Documentation
tlb tlb
mtrr mtrr
pat pat
protection-keys

View File

@ -1,3 +1,9 @@
.. SPDX-License-Identifier: GPL-2.0
======================
Memory Protection Keys
======================
Memory Protection Keys for Userspace (PKU aka PKEYs) is a feature Memory Protection Keys for Userspace (PKU aka PKEYs) is a feature
which is found on Intel's Skylake "Scalable Processor" Server CPUs. which is found on Intel's Skylake "Scalable Processor" Server CPUs.
It will be avalable in future non-server parts. It will be avalable in future non-server parts.
@ -23,9 +29,10 @@ even though there is theoretically space in the PAE PTEs. These
permissions are enforced on data access only and have no effect on permissions are enforced on data access only and have no effect on
instruction fetches. instruction fetches.
=========================== Syscalls =========================== Syscalls
========
There are 3 system calls which directly interact with pkeys: There are 3 system calls which directly interact with pkeys::
int pkey_alloc(unsigned long flags, unsigned long init_access_rights) int pkey_alloc(unsigned long flags, unsigned long init_access_rights)
int pkey_free(int pkey); int pkey_free(int pkey);
@ -37,6 +44,7 @@ pkey_alloc(). An application calls the WRPKRU instruction
directly in order to change access permissions to memory covered directly in order to change access permissions to memory covered
with a key. In this example WRPKRU is wrapped by a C function with a key. In this example WRPKRU is wrapped by a C function
called pkey_set(). called pkey_set().
::
int real_prot = PROT_READ|PROT_WRITE; int real_prot = PROT_READ|PROT_WRITE;
pkey = pkey_alloc(0, PKEY_DISABLE_WRITE); pkey = pkey_alloc(0, PKEY_DISABLE_WRITE);
@ -45,43 +53,44 @@ called pkey_set().
... application runs here ... application runs here
Now, if the application needs to update the data at 'ptr', it can Now, if the application needs to update the data at 'ptr', it can
gain access, do the update, then remove its write access: gain access, do the update, then remove its write access::
pkey_set(pkey, 0); // clear PKEY_DISABLE_WRITE pkey_set(pkey, 0); // clear PKEY_DISABLE_WRITE
*ptr = foo; // assign something *ptr = foo; // assign something
pkey_set(pkey, PKEY_DISABLE_WRITE); // set PKEY_DISABLE_WRITE again pkey_set(pkey, PKEY_DISABLE_WRITE); // set PKEY_DISABLE_WRITE again
Now when it frees the memory, it will also free the pkey since it Now when it frees the memory, it will also free the pkey since it
is no longer in use: is no longer in use::
munmap(ptr, PAGE_SIZE); munmap(ptr, PAGE_SIZE);
pkey_free(pkey); pkey_free(pkey);
(Note: pkey_set() is a wrapper for the RDPKRU and WRPKRU instructions. .. note:: pkey_set() is a wrapper for the RDPKRU and WRPKRU instructions.
An example implementation can be found in An example implementation can be found in
tools/testing/selftests/x86/protection_keys.c) tools/testing/selftests/x86/protection_keys.c.
=========================== Behavior =========================== Behavior
========
The kernel attempts to make protection keys consistent with the The kernel attempts to make protection keys consistent with the
behavior of a plain mprotect(). For instance if you do this: behavior of a plain mprotect(). For instance if you do this::
mprotect(ptr, size, PROT_NONE); mprotect(ptr, size, PROT_NONE);
something(ptr); something(ptr);
you can expect the same effects with protection keys when doing this: you can expect the same effects with protection keys when doing this::
pkey = pkey_alloc(0, PKEY_DISABLE_WRITE | PKEY_DISABLE_READ); pkey = pkey_alloc(0, PKEY_DISABLE_WRITE | PKEY_DISABLE_READ);
pkey_mprotect(ptr, size, PROT_READ|PROT_WRITE, pkey); pkey_mprotect(ptr, size, PROT_READ|PROT_WRITE, pkey);
something(ptr); something(ptr);
That should be true whether something() is a direct access to 'ptr' That should be true whether something() is a direct access to 'ptr'
like: like::
*ptr = foo; *ptr = foo;
or when the kernel does the access on the application's behalf like or when the kernel does the access on the application's behalf like
with a read(): with a read()::
read(fd, ptr, 1); read(fd, ptr, 1);