docs: sparc: convert to ReST
[linux-2.6-microblaze.git] / Documentation / sparc / adi.txt
diff --git a/Documentation/sparc/adi.txt b/Documentation/sparc/adi.txt
deleted file mode 100644 (file)
index e1aed15..0000000
+++ /dev/null
@@ -1,278 +0,0 @@
-Application Data Integrity (ADI)
-================================
-
-SPARC M7 processor adds the Application Data Integrity (ADI) feature.
-ADI allows a task to set version tags on any subset of its address
-space. Once ADI is enabled and version tags are set for ranges of
-address space of a task, the processor will compare the tag in pointers
-to memory in these ranges to the version set by the application
-previously. Access to memory is granted only if the tag in given pointer
-matches the tag set by the application. In case of mismatch, processor
-raises an exception.
-
-Following steps must be taken by a task to enable ADI fully:
-
-1. Set the user mode PSTATE.mcde bit. This acts as master switch for
-   the task's entire address space to enable/disable ADI for the task.
-
-2. Set TTE.mcd bit on any TLB entries that correspond to the range of
-   addresses ADI is being enabled on. MMU checks the version tag only
-   on the pages that have TTE.mcd bit set.
-
-3. Set the version tag for virtual addresses using stxa instruction
-   and one of the MCD specific ASIs. Each stxa instruction sets the
-   given tag for one ADI block size number of bytes. This step must
-   be repeated for entire page to set tags for entire page.
-
-ADI block size for the platform is provided by the hypervisor to kernel
-in machine description tables. Hypervisor also provides the number of
-top bits in the virtual address that specify the version tag.  Once
-version tag has been set for a memory location, the tag is stored in the
-physical memory and the same tag must be present in the ADI version tag
-bits of the virtual address being presented to the MMU. For example on
-SPARC M7 processor, MMU uses bits 63-60 for version tags and ADI block
-size is same as cacheline size which is 64 bytes. A task that sets ADI
-version to, say 10, on a range of memory, must access that memory using
-virtual addresses that contain 0xa in bits 63-60.
-
-ADI is enabled on a set of pages using mprotect() with PROT_ADI flag.
-When ADI is enabled on a set of pages by a task for the first time,
-kernel sets the PSTATE.mcde bit fot the task. Version tags for memory
-addresses are set with an stxa instruction on the addresses using
-ASI_MCD_PRIMARY or ASI_MCD_ST_BLKINIT_PRIMARY. ADI block size is
-provided by the hypervisor to the kernel.  Kernel returns the value of
-ADI block size to userspace using auxiliary vector along with other ADI
-info. Following auxiliary vectors are provided by the kernel:
-
-       AT_ADI_BLKSZ    ADI block size. This is the granularity and
-                       alignment, in bytes, of ADI versioning.
-       AT_ADI_NBITS    Number of ADI version bits in the VA
-
-
-IMPORTANT NOTES:
-
-- Version tag values of 0x0 and 0xf are reserved. These values match any
-  tag in virtual address and never generate a mismatch exception.
-
-- Version tags are set on virtual addresses from userspace even though
-  tags are stored in physical memory. Tags are set on a physical page
-  after it has been allocated to a task and a pte has been created for
-  it.
-
-- When a task frees a memory page it had set version tags on, the page
-  goes back to free page pool. When this page is re-allocated to a task,
-  kernel clears the page using block initialization ASI which clears the
-  version tags as well for the page. If a page allocated to a task is
-  freed and allocated back to the same task, old version tags set by the
-  task on that page will no longer be present.
-
-- ADI tag mismatches are not detected for non-faulting loads.
-
-- Kernel does not set any tags for user pages and it is entirely a
-  task's responsibility to set any version tags. Kernel does ensure the
-  version tags are preserved if a page is swapped out to the disk and
-  swapped back in. It also preserves that version tags if a page is
-  migrated.
-
-- ADI works for any size pages. A userspace task need not be aware of
-  page size when using ADI. It can simply select a virtual address
-  range, enable ADI on the range using mprotect() and set version tags
-  for the entire range. mprotect() ensures range is aligned to page size
-  and is a multiple of page size.
-
-- ADI tags can only be set on writable memory. For example, ADI tags can
-  not be set on read-only mappings.
-
-
-
-ADI related traps
------------------
-
-With ADI enabled, following new traps may occur:
-
-Disrupting memory corruption
-
-       When a store accesses a memory localtion that has TTE.mcd=1,
-       the task is running with ADI enabled (PSTATE.mcde=1), and the ADI
-       tag in the address used (bits 63:60) does not match the tag set on
-       the corresponding cacheline, a memory corruption trap occurs. By
-       default, it is a disrupting trap and is sent to the hypervisor
-       first. Hypervisor creates a sun4v error report and sends a
-       resumable error (TT=0x7e) trap to the kernel. The kernel sends
-       a SIGSEGV to the task that resulted in this trap with the following
-       info:
-
-               siginfo.si_signo = SIGSEGV;
-               siginfo.errno = 0;
-               siginfo.si_code = SEGV_ADIDERR;
-               siginfo.si_addr = addr; /* PC where first mismatch occurred */
-               siginfo.si_trapno = 0;
-
-
-Precise memory corruption
-
-       When a store accesses a memory location that has TTE.mcd=1,
-       the task is running with ADI enabled (PSTATE.mcde=1), and the ADI
-       tag in the address used (bits 63:60) does not match the tag set on
-       the corresponding cacheline, a memory corruption trap occurs. If
-       MCD precise exception is enabled (MCDPERR=1), a precise
-       exception is sent to the kernel with TT=0x1a. The kernel sends
-       a SIGSEGV to the task that resulted in this trap with the following
-       info:
-
-               siginfo.si_signo = SIGSEGV;
-               siginfo.errno = 0;
-               siginfo.si_code = SEGV_ADIPERR;
-               siginfo.si_addr = addr; /* address that caused trap */
-               siginfo.si_trapno = 0;
-
-       NOTE: ADI tag mismatch on a load always results in precise trap.
-
-
-MCD disabled
-
-       When a task has not enabled ADI and attempts to set ADI version
-       on a memory address, processor sends an MCD disabled trap. This
-       trap is handled by hypervisor first and the hypervisor vectors this
-       trap through to the kernel as Data Access Exception trap with
-       fault type set to 0xa (invalid ASI). When this occurs, the kernel
-       sends the task SIGSEGV signal with following info:
-
-               siginfo.si_signo = SIGSEGV;
-               siginfo.errno = 0;
-               siginfo.si_code = SEGV_ACCADI;
-               siginfo.si_addr = addr; /* address that caused trap */
-               siginfo.si_trapno = 0;
-
-
-Sample program to use ADI
--------------------------
-
-Following sample program is meant to illustrate how to use the ADI
-functionality.
-
-#include <unistd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <elf.h>
-#include <sys/ipc.h>
-#include <sys/shm.h>
-#include <sys/mman.h>
-#include <asm/asi.h>
-
-#ifndef AT_ADI_BLKSZ
-#define AT_ADI_BLKSZ   48
-#endif
-#ifndef AT_ADI_NBITS
-#define AT_ADI_NBITS   49
-#endif
-
-#ifndef PROT_ADI
-#define PROT_ADI       0x10
-#endif
-
-#define BUFFER_SIZE     32*1024*1024UL
-
-main(int argc, char* argv[], char* envp[])
-{
-        unsigned long i, mcde, adi_blksz, adi_nbits;
-        char *shmaddr, *tmp_addr, *end, *veraddr, *clraddr;
-        int shmid, version;
-       Elf64_auxv_t *auxv;
-
-       adi_blksz = 0;
-
-       while(*envp++ != NULL);
-       for (auxv = (Elf64_auxv_t *)envp; auxv->a_type != AT_NULL; auxv++) {
-               switch (auxv->a_type) {
-               case AT_ADI_BLKSZ:
-                       adi_blksz = auxv->a_un.a_val;
-                       break;
-               case AT_ADI_NBITS:
-                       adi_nbits = auxv->a_un.a_val;
-                       break;
-               }
-       }
-       if (adi_blksz == 0) {
-               fprintf(stderr, "Oops! ADI is not supported\n");
-               exit(1);
-       }
-
-       printf("ADI capabilities:\n");
-       printf("\tBlock size = %ld\n", adi_blksz);
-       printf("\tNumber of bits = %ld\n", adi_nbits);
-
-        if ((shmid = shmget(2, BUFFER_SIZE,
-                                IPC_CREAT | SHM_R | SHM_W)) < 0) {
-                perror("shmget failed");
-                exit(1);
-        }
-
-        shmaddr = shmat(shmid, NULL, 0);
-        if (shmaddr == (char *)-1) {
-                perror("shm attach failed");
-                shmctl(shmid, IPC_RMID, NULL);
-                exit(1);
-        }
-
-       if (mprotect(shmaddr, BUFFER_SIZE, PROT_READ|PROT_WRITE|PROT_ADI)) {
-               perror("mprotect failed");
-               goto err_out;
-       }
-
-        /* Set the ADI version tag on the shm segment
-         */
-        version = 10;
-        tmp_addr = shmaddr;
-        end = shmaddr + BUFFER_SIZE;
-        while (tmp_addr < end) {
-                asm volatile(
-                        "stxa %1, [%0]0x90\n\t"
-                        :
-                        : "r" (tmp_addr), "r" (version));
-                tmp_addr += adi_blksz;
-        }
-       asm volatile("membar #Sync\n\t");
-
-        /* Create a versioned address from the normal address by placing
-        * version tag in the upper adi_nbits bits
-         */
-        tmp_addr = (void *) ((unsigned long)shmaddr << adi_nbits);
-        tmp_addr = (void *) ((unsigned long)tmp_addr >> adi_nbits);
-        veraddr = (void *) (((unsigned long)version << (64-adi_nbits))
-                        | (unsigned long)tmp_addr);
-
-        printf("Starting the writes:\n");
-        for (i = 0; i < BUFFER_SIZE; i++) {
-                veraddr[i] = (char)(i);
-                if (!(i % (1024 * 1024)))
-                        printf(".");
-        }
-        printf("\n");
-
-        printf("Verifying data...");
-       fflush(stdout);
-        for (i = 0; i < BUFFER_SIZE; i++)
-                if (veraddr[i] != (char)i)
-                        printf("\nIndex %lu mismatched\n", i);
-        printf("Done.\n");
-
-        /* Disable ADI and clean up
-         */
-       if (mprotect(shmaddr, BUFFER_SIZE, PROT_READ|PROT_WRITE)) {
-               perror("mprotect failed");
-               goto err_out;
-       }
-
-        if (shmdt((const void *)shmaddr) != 0)
-                perror("Detach failure");
-        shmctl(shmid, IPC_RMID, NULL);
-
-        exit(0);
-
-err_out:
-        if (shmdt((const void *)shmaddr) != 0)
-                perror("Detach failure");
-        shmctl(shmid, IPC_RMID, NULL);
-        exit(1);
-}