Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) ================================
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) Application Data Integrity (ADI)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3) ================================
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5) SPARC M7 processor adds the Application Data Integrity (ADI) feature.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6) ADI allows a task to set version tags on any subset of its address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) space. Once ADI is enabled and version tags are set for ranges of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) address space of a task, the processor will compare the tag in pointers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) to memory in these ranges to the version set by the application
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) previously. Access to memory is granted only if the tag in given pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) matches the tag set by the application. In case of mismatch, processor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) raises an exception.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) Following steps must be taken by a task to enable ADI fully:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) 1. Set the user mode PSTATE.mcde bit. This acts as master switch for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17)    the task's entire address space to enable/disable ADI for the task.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) 2. Set TTE.mcd bit on any TLB entries that correspond to the range of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20)    addresses ADI is being enabled on. MMU checks the version tag only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21)    on the pages that have TTE.mcd bit set.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) 3. Set the version tag for virtual addresses using stxa instruction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24)    and one of the MCD specific ASIs. Each stxa instruction sets the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25)    given tag for one ADI block size number of bytes. This step must
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26)    be repeated for entire page to set tags for entire page.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) ADI block size for the platform is provided by the hypervisor to kernel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) in machine description tables. Hypervisor also provides the number of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) top bits in the virtual address that specify the version tag.  Once
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) version tag has been set for a memory location, the tag is stored in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) physical memory and the same tag must be present in the ADI version tag
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) bits of the virtual address being presented to the MMU. For example on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) SPARC M7 processor, MMU uses bits 63-60 for version tags and ADI block
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) size is same as cacheline size which is 64 bytes. A task that sets ADI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) version to, say 10, on a range of memory, must access that memory using
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) virtual addresses that contain 0xa in bits 63-60.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) ADI is enabled on a set of pages using mprotect() with PROT_ADI flag.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) When ADI is enabled on a set of pages by a task for the first time,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) kernel sets the PSTATE.mcde bit fot the task. Version tags for memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) addresses are set with an stxa instruction on the addresses using
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) ASI_MCD_PRIMARY or ASI_MCD_ST_BLKINIT_PRIMARY. ADI block size is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) provided by the hypervisor to the kernel.  Kernel returns the value of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) ADI block size to userspace using auxiliary vector along with other ADI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) info. Following auxiliary vectors are provided by the kernel:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 	============	===========================================
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 	AT_ADI_BLKSZ	ADI block size. This is the granularity and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 			alignment, in bytes, of ADI versioning.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 	AT_ADI_NBITS	Number of ADI version bits in the VA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 	============	===========================================
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) IMPORTANT NOTES
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) ===============
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) - Version tag values of 0x0 and 0xf are reserved. These values match any
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59)   tag in virtual address and never generate a mismatch exception.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) - Version tags are set on virtual addresses from userspace even though
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62)   tags are stored in physical memory. Tags are set on a physical page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63)   after it has been allocated to a task and a pte has been created for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64)   it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) - When a task frees a memory page it had set version tags on, the page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67)   goes back to free page pool. When this page is re-allocated to a task,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68)   kernel clears the page using block initialization ASI which clears the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69)   version tags as well for the page. If a page allocated to a task is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70)   freed and allocated back to the same task, old version tags set by the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71)   task on that page will no longer be present.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) - ADI tag mismatches are not detected for non-faulting loads.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) - Kernel does not set any tags for user pages and it is entirely a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76)   task's responsibility to set any version tags. Kernel does ensure the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77)   version tags are preserved if a page is swapped out to the disk and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78)   swapped back in. It also preserves that version tags if a page is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79)   migrated.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) - ADI works for any size pages. A userspace task need not be aware of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82)   page size when using ADI. It can simply select a virtual address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83)   range, enable ADI on the range using mprotect() and set version tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84)   for the entire range. mprotect() ensures range is aligned to page size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85)   and is a multiple of page size.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) - ADI tags can only be set on writable memory. For example, ADI tags can
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88)   not be set on read-only mappings.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) ADI related traps
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) =================
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) With ADI enabled, following new traps may occur:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) Disrupting memory corruption
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) ----------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	When a store accesses a memory localtion that has TTE.mcd=1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 	the task is running with ADI enabled (PSTATE.mcde=1), and the ADI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 	tag in the address used (bits 63:60) does not match the tag set on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 	the corresponding cacheline, a memory corruption trap occurs. By
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 	default, it is a disrupting trap and is sent to the hypervisor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	first. Hypervisor creates a sun4v error report and sends a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 	resumable error (TT=0x7e) trap to the kernel. The kernel sends
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 	a SIGSEGV to the task that resulted in this trap with the following
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 	info::
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 		siginfo.si_signo = SIGSEGV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 		siginfo.errno = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 		siginfo.si_code = SEGV_ADIDERR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 		siginfo.si_addr = addr; /* PC where first mismatch occurred */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 		siginfo.si_trapno = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) Precise memory corruption
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) -------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 	When a store accesses a memory location that has TTE.mcd=1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 	the task is running with ADI enabled (PSTATE.mcde=1), and the ADI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 	tag in the address used (bits 63:60) does not match the tag set on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 	the corresponding cacheline, a memory corruption trap occurs. If
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 	MCD precise exception is enabled (MCDPERR=1), a precise
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 	exception is sent to the kernel with TT=0x1a. The kernel sends
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 	a SIGSEGV to the task that resulted in this trap with the following
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 	info::
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 		siginfo.si_signo = SIGSEGV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 		siginfo.errno = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 		siginfo.si_code = SEGV_ADIPERR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 		siginfo.si_addr = addr;	/* address that caused trap */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 		siginfo.si_trapno = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 	NOTE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 		ADI tag mismatch on a load always results in precise trap.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) MCD disabled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) ------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 	When a task has not enabled ADI and attempts to set ADI version
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 	on a memory address, processor sends an MCD disabled trap. This
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 	trap is handled by hypervisor first and the hypervisor vectors this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 	trap through to the kernel as Data Access Exception trap with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 	fault type set to 0xa (invalid ASI). When this occurs, the kernel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 	sends the task SIGSEGV signal with following info::
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 		siginfo.si_signo = SIGSEGV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 		siginfo.errno = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 		siginfo.si_code = SEGV_ACCADI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 		siginfo.si_addr = addr;	/* address that caused trap */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 		siginfo.si_trapno = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) Sample program to use ADI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) -------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) Following sample program is meant to illustrate how to use the ADI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) functionality::
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)   #include <unistd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)   #include <stdio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)   #include <stdlib.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)   #include <elf.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)   #include <sys/ipc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)   #include <sys/shm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)   #include <sys/mman.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)   #include <asm/asi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)   #ifndef AT_ADI_BLKSZ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)   #define AT_ADI_BLKSZ	48
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)   #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)   #ifndef AT_ADI_NBITS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)   #define AT_ADI_NBITS	49
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)   #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)   #ifndef PROT_ADI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)   #define PROT_ADI	0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)   #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)   #define BUFFER_SIZE     32*1024*1024UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)   main(int argc, char* argv[], char* envp[])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)   {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)           unsigned long i, mcde, adi_blksz, adi_nbits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)           char *shmaddr, *tmp_addr, *end, *veraddr, *clraddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)           int shmid, version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 	Elf64_auxv_t *auxv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 	adi_blksz = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 	while(*envp++ != NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 	for (auxv = (Elf64_auxv_t *)envp; auxv->a_type != AT_NULL; auxv++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 		switch (auxv->a_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 		case AT_ADI_BLKSZ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 			adi_blksz = auxv->a_un.a_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 		case AT_ADI_NBITS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 			adi_nbits = auxv->a_un.a_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 	if (adi_blksz == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 		fprintf(stderr, "Oops! ADI is not supported\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 		exit(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 	printf("ADI capabilities:\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 	printf("\tBlock size = %ld\n", adi_blksz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 	printf("\tNumber of bits = %ld\n", adi_nbits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)           if ((shmid = shmget(2, BUFFER_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)                                   IPC_CREAT | SHM_R | SHM_W)) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)                   perror("shmget failed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)                   exit(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)           }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)           shmaddr = shmat(shmid, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)           if (shmaddr == (char *)-1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)                   perror("shm attach failed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)                   shmctl(shmid, IPC_RMID, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)                   exit(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)           }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 	if (mprotect(shmaddr, BUFFER_SIZE, PROT_READ|PROT_WRITE|PROT_ADI)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 		perror("mprotect failed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 		goto err_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)           /* Set the ADI version tag on the shm segment
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)            */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)           version = 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)           tmp_addr = shmaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)           end = shmaddr + BUFFER_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)           while (tmp_addr < end) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)                   asm volatile(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)                           "stxa %1, [%0]0x90\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)                           :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)                           : "r" (tmp_addr), "r" (version));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)                   tmp_addr += adi_blksz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)           }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 	asm volatile("membar #Sync\n\t");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)           /* Create a versioned address from the normal address by placing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 	 * version tag in the upper adi_nbits bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)            */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)           tmp_addr = (void *) ((unsigned long)shmaddr << adi_nbits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)           tmp_addr = (void *) ((unsigned long)tmp_addr >> adi_nbits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)           veraddr = (void *) (((unsigned long)version << (64-adi_nbits))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)                           | (unsigned long)tmp_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)           printf("Starting the writes:\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)           for (i = 0; i < BUFFER_SIZE; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)                   veraddr[i] = (char)(i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)                   if (!(i % (1024 * 1024)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)                           printf(".");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)           }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)           printf("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261)           printf("Verifying data...");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 	fflush(stdout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)           for (i = 0; i < BUFFER_SIZE; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)                   if (veraddr[i] != (char)i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)                           printf("\nIndex %lu mismatched\n", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)           printf("Done.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)           /* Disable ADI and clean up
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)            */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 	if (mprotect(shmaddr, BUFFER_SIZE, PROT_READ|PROT_WRITE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 		perror("mprotect failed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 		goto err_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)           if (shmdt((const void *)shmaddr) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)                   perror("Detach failure");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)           shmctl(shmid, IPC_RMID, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)           exit(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)   err_out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)           if (shmdt((const void *)shmaddr) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283)                   perror("Detach failure");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)           shmctl(shmid, IPC_RMID, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)           exit(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)   }