msm_smem.txt 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595
  1. Introduction
  2. ============
  3. The Shared Memory (SMEM) protocol allows multiple processors in Qualcomm
  4. Technologies, Inc. MSM System on Chips to communicate at a low level using a
  5. segment of shared system memory that is accessible by any of the processors.
  6. This is accomplished by an operating-system independent mechanism that allows a
  7. client on any processor to dynamically allocate a block of memory from shared
  8. system memory which is then visible and accessible to clients on other
  9. processors for the purpose of storing and exchanging data.
  10. +-------------+
  11. SMEM | Processor 1 |
  12. +---------+ +------------+ +-------------+
  13. | |+--------------->| Item 1 |<----------------+ ^
  14. | Linux | | | |
  15. | |<---------------+| |+-------------------+
  16. +---------+ +------------+
  17. ^ + | Item 2 | +-------------+
  18. | | | |<--------------+| Processor 2 |
  19. | | | |+-------------->| |
  20. | | | | +-------------+
  21. | | | |
  22. | | | | +-------------+
  23. | | +------------+ | Processor 3 |
  24. | | . +-------------+
  25. | | . + ^ .
  26. | | +------------+ | | .
  27. | +----------------->| Item N |<-----------------+ | .
  28. +---------------------+| |+--------------------+ .
  29. | | +-------------+
  30. | |+-------------->| |
  31. | | | Processor N |
  32. | |<--------------+| |
  33. +------------+ +-------------+
  34. The SMEM driver supports all known versions of the SMEM protocol.
  35. Hardware description
  36. ====================
  37. The SMEM protocol requires a contiguous segment of system memory that is
  38. accessible by both the local processor and one or more remote processors.
  39. Each processor supporting the SMEM protocol must configure their MMUs and other
  40. applicable hardware such that accesses to shared memory are non-cacheable.
  41. Optionally, additional segments of system memory may be provided to act as
  42. auxiliary memory areas for the SMEM protocol. Such segments may provide
  43. performance benefits to certain processors by optimizing access latency. Such
  44. auxiliary memory areas must be a slave to the single main SMEM area.
  45. While the SMEM protocol has provisions for software-based remote spinlocks to
  46. manage synchronization between processors, this functionality may be
  47. substituted with dedicated hardware. Such hardware is expected to be managed
  48. by another driver providing a standardized API.
  49. Software description
  50. ====================
  51. At its core, the SMEM protocol is a heap memory management system. The core
  52. functionality consists of allocating segments of memory, and lookup operations
  53. to find the address of existing segments of memory. There is no provision to
  54. free memory that is allocated.
  55. Allocated segments of memory are called SMEM items. Each SMEM item has a unique
  56. 32-bit identifier which maps each specific SMEM item to a slot in the table of
  57. contents that lives at the start of the SMEM region.
  58. A SMEM client that wishes to allocate a SMEM item will provide the item
  59. identifier and a desired size in bytes. Assuming there is enough free space in
  60. the SMEM region to accommodate the request, the amount of desired bytes will be
  61. carved out, and the base address and size for the item will be stored in the
  62. table of contents. The base address will be returned as a pointer to the
  63. client, so that the client may use the SMEM item as if it were normal memory
  64. allocated through "malloc".
  65. A SMEM client that wishes to find an already allocated SMEM item will provide
  66. the item identifier and the size in bytes that the client expects for the item.
  67. A lookup in the table of contents for the specified item identifier will be
  68. performed. Assuming a matching SMEM item is found, the size of the item that
  69. is stored in the table of contents will be compared to the size specified by the
  70. client. This sanity check of the expected vs actual size is done to ensure that
  71. all users of a particular SMEM item agree on the size of the data to be
  72. exchanged under the assumption that if the users do not agree on the item size,
  73. then they will not be able to successfully communicate as one or more sides may
  74. view a corruption of the data stored in the SMEM item. Assuming the sizes
  75. match, the virtual address corresponding to the base address stored in the table
  76. of contents for the item will be returned to the client.
  77. +------+ Request +-----------+ Memory
  78. |Client|+----------------->|SMEM Driver| +---------------+
  79. +------+ Item X of size Y +-----------+ | |
  80. ^ + | |
  81. | | Lookup/Alloc +---------------+ Find X
  82. | +--------------->| TOC[X] |+--------+
  83. | +---------------+ |
  84. | | | |
  85. | | | |
  86. | | | |
  87. | | | |
  88. | | | |
  89. | | | |
  90. | Return pointer for client +---------------+ |
  91. +---------------------------------------------+| Item X |<--------+
  92. +---------------+
  93. | |
  94. | |
  95. | |
  96. +---------------+
  97. The SMEM driver depends on the kernel memory management subsystem for managing
  98. the system memory that SMEM uses. The main SMEM memory region is statically
  99. mapped at boot, and the virtual address for the base of the region is stored
  100. in MSM_SHARED_RAM_BASE. Auxiliary memory regions are ioremap'd at driver init.
  101. All SMEM regions are mapped as non-cacheable.
  102. Although the SMEM driver is aware of auxiliary memory regions, and capable of
  103. understanding SMEM items that exist in auxiliary memory regions, the SMEM
  104. driver does not allocate from the auxiliary memory regions. A detailed
  105. description of the purpose and use of auxiliary memory regions is outside the
  106. scope of this document.
  107. Design
  108. ======
  109. The SMEM protocol requires that the system bootloader initialize (zero out) and
  110. bootstrap the main SMEM region before any processor in the system has booted to
  111. avoid an initialization race condition.
  112. SMEM regions are configured as non-cachable memory. While this results in a
  113. small performance hit, it significantly reduces the complexity for the SMEM
  114. driver and clients in terms of cache management and memory barriers. Clients
  115. are generally able to treat their SMEM items like regular local memory, which
  116. eases the requirements to write correct code.
  117. The unsigned data type is assumed to be an unsigned 32-bit integer value.
  118. The root structure at the base of the main SMEM region is:
  119. #define SMD_HEAP_SIZE 512
  120. struct smem_shared {
  121. struct smem_proc_comm proc_comm[4];
  122. unsigned version[32];
  123. struct smem_heap_info heap_info;
  124. struct smem_heap_entry heap_toc[SMD_HEAP_SIZE];
  125. };
  126. This structure and its fields are initialized by the bootloader.
  127. The proc_comm field is reserved as the first part of the SMEM region to maintain
  128. compatibility with legacy systems, but is otherwise deprecated. While the
  129. proc comm driver is beyond the scope of this document, the remaining structure
  130. definition to fully define smem_shared is:
  131. struct smem_proc_comm {
  132. unsigned command;
  133. unsigned status;
  134. unsigned data1;
  135. unsigned data2;
  136. };
  137. The version field of the smem_shared struct is an array of version entries
  138. specifying the SMEM protocol version of every supporting processor active in the
  139. system. Each unsigned value in the array corresponds to one entry. This
  140. provides a mechanism for ensuring protocol version compatibility between
  141. processors. While the full table of assigned and reserved entries in the array
  142. is beyond the scope of this document, index 8 (smem_shared.version[8]) is
  143. reserved for any future use by Linux. The bootloader always initializes it's
  144. entry (index 7, or smem_shared.version[7]) to the SMEM protocol version
  145. supported by the bootloader. Checking the value of the bootloader's entry can
  146. be used as a sanity check to determine if the SMEM region was successfully
  147. initialized.
  148. The heap_info field of smem_shared contains basic information of the SMEM heap.
  149. The bootloader fills in values corresponding to the main SMEM region when it
  150. initializes the heap. It is defined as:
  151. struct smem_heap_info {
  152. unsigned initialized;
  153. unsigned free_offset;
  154. unsigned heap_remaining;
  155. unsigned reserved;
  156. };
  157. The initialized field is set to 1 by the bootloader when it initializes the
  158. heap. The free_offset field contains the offset from the base of the SMEM
  159. region for the first free byte in the heap. When a new SMEM item is allocated,
  160. free_offset is incremented by the size of the allocated item. SMEM item sizes
  161. are 8-byte aligned. The heap_remaining field contains the number of free bytes
  162. remaining in the heap. When a new SMEM item is allocated, heap_remaining is
  163. decremented by the size of the item. The reserved field is defined to be 0.
  164. The heap_toc field of smem_shared is the heap table of contents. It is an array
  165. containing a slot for every defined SMEM item. SMEM item identifiers index into
  166. this array. The structures definition is:
  167. struct smem_heap_entry {
  168. unsigned allocated;
  169. unsigned offset;
  170. unsigned size;
  171. unsigned reserved; /* bits 1:0 reserved, bits 31:2 aux smem base addr */
  172. };
  173. If an SMEM item is allocated, the allocated field is 1. The offset field is
  174. either the offset from the main SMEM region base where this SMEM item exists, or
  175. the offset from the auxiliary SMEM region base specified in the reserved field.
  176. The size field contains the size of the SMEM item in bytes. The size is defined
  177. to be 8-byte aligned. The reserved field is 0 if the SMEM item is located in
  178. the main SMEM region, or bits 31(MSB) to 2 specify the physical address of the
  179. auxiliary SMEM region where the SMEM item resides. If reserved is used as a
  180. physical address, then the address must be 4-byte aligned per ARM architectural
  181. requirements.
  182. The bootloader allocates and intializes the following SMEM items:
  183. Name ID Size (bytes)
  184. ----------------------------------------------------
  185. SMEM_PROC_COMM 0 64
  186. SMEM_HEAP_INFO 1 16
  187. SMEM_ALLOCATION_TABLE 2 8192
  188. SMEM_VERSION_INFO 3 128
  189. SMEM_HW_RESET_DETECT 4 8
  190. SMEM_AARM_WARM_BOOT 5 4
  191. SMEM_DIAG_ERR_MESSAGE 6 200
  192. SMEM_SPINLOCK_ARRAY 7 32
  193. SMEM_MEMORY_BARRIER_LOCATION 8 4
  194. All other SMEM items are dynamically allocated by processors in the system.
  195. Although the SMEM protocol requires the bootloader to initialize the SMEM region
  196. before any processor in the system is active, early development of new systems
  197. do not always have a fully functional bootloader. To determine if the
  198. bootloader initialized the main SMEM region properly, the SMEM driver will check
  199. the expected values of smem_shared.heap_info.initialized,
  200. smem_shared.heap_info.reserved, and the bootloader entry of the
  201. SMEM_VERSION_INFO SMEM item. If this check fails, the SMEM driver will print
  202. an error message to the kernel log, and enter a disabled state.
  203. Security Feature
  204. ----------------
  205. The SMEM protocol supports an optional security feature that segments the main
  206. SMEM region into multiple partitions. Each partition becomes a unique item
  207. namespace. Access to partitions is restricted to a maximum of two processors
  208. and enforced by Memory Protection Units (MPUs). The exceptions to this are the
  209. Partition Table of Contents partition, which is read-only accessible by all
  210. processors, and the Legacy/Default partition, which is freely accessible by all
  211. processors.
  212. +-------------------------+ SMEM Base address
  213. |Legacy/Default |
  214. |SMEM Partition |
  215. +-------------------------+
  216. |SMEM Partition 0 |
  217. |Processor 1 - Processor 2|
  218. +-------------------------+
  219. |SMEM Partition 1 |
  220. |Processor 1 - Processor 3|
  221. +-------------------------+
  222. |SMEM Partition 2 |
  223. |Processor 4 - Processor 5|
  224. +-------------------------+
  225. .
  226. .
  227. .
  228. +-------------------------+
  229. |SMEM Partition N |
  230. |Processor N - Processor M|
  231. +-------------------------+ SMEM Base address + SMEM size - 4k
  232. |Table of Contents |
  233. | |
  234. +-------------------------+ SMEM Base address + SMEM size
  235. SMEM items which are point-to-point in nature and accessed by two or fewer
  236. processors may be allocated from a partition that is restricted to those
  237. processors. SMEM items which are non-sensitive, accessed by 3 or more
  238. processors, and/or do not correspond to a secured partition are allocated from
  239. the Legacy/Default partition.
  240. During the firmware boot process, the Table of Contents is initialized with a
  241. description of all the secured partitions. Each secured partition is also
  242. initialized. The required MPU settings to protect the Table of Contents and the
  243. secured partitions are also established. The Table of Contents is located 4k
  244. bytes prior to the end of the main SMEM region so that it is in a known position
  245. for all processors to find and do local configuration.
  246. The Table of Contents is defined as:
  247. struct smem_toc {
  248. /*
  249. * Identifier is a constant for use in debugging and identifying this
  250. * struct in a binary capture. Set to 0x434f5424 ("$TOC").
  251. */
  252. uint32_t identifier;
  253. /* Version number */
  254. uint32_t version;
  255. /* Number of entries in the table */
  256. uint32_t num_entries;
  257. uint32_t reserved[5];
  258. /* Zero or more entries follow */
  259. struct smem_toc_entry entry[];
  260. };
  261. Each entry in the Table of Contents is defined as:
  262. struct smem_toc_entry {
  263. /* Offset in bytes from SMEM base of the region */
  264. uint32_t offset;
  265. /* Size in bytes of the region */
  266. uint32_t size;
  267. /* Flags for this region */
  268. uint32_t flags;
  269. /*
  270. * IDs for the 2 subsystems which have access to this partition.
  271. * Order does not matter.
  272. * For the entry which describes the TOC itself, these are both set to
  273. * SMEM_INVALID_HOST.
  274. * Use uint16_t, rather than enum type, to ensure size.
  275. */
  276. uint16_t host0;
  277. uint16_t host1;
  278. /*
  279. * Lowest common multiple of cacheline sizes for both endpoints. For
  280. * example, if host0 has cacheline size of 32 and host1 has cacheline
  281. * size of 64, this value is set to 64.
  282. */
  283. uint32_t size_cacheline;
  284. uint32_t reserved[3];
  285. /*
  286. * Sizes of sub ranges that are part of the region, but are excluded
  287. * from the SMEM heap. These are allocated from the end of the region
  288. * starting with sizes[0]. Set to 0 when not used.
  289. */
  290. uint32_t exclusion_sizes[SMEM_TOC_MAX_EXCLUSIONS];
  291. };
  292. While the Legacy/Default partition maintains the structure and format of the
  293. main SMEM region with the security feature disabled, the secured partitions have
  294. a different format and structure:
  295. +--------------+ +--------------------------+ Partition Base Address
  296. | | | Partition Header |
  297. | | | | +
  298. | Uncached Page| +--------------------------+ |
  299. | | | Item A Header | |
  300. | | +--------------------------+ |
  301. | | | Item A Data | |
  302. +--------------+ | | |
  303. | | | | |
  304. | | +--------------------------+ |
  305. | Uncached Page| | Item B Header | |Direction of heap growth
  306. | | +--------------------------+ |
  307. | | | Item B Data | |
  308. | | | | |
  309. +--------------+ | | |
  310. | | +--------------------------+ |
  311. | | | | |
  312. | Uncached Page| | Unused Heap | |
  313. | | | space to | v
  314. | | | page boundary |
  315. | | | |
  316. +--------------+ +--------------------------+<----------+ End of heap
  317. . . . . . .
  318. Free Space
  319. Can be used for
  320. either heap.
  321. . . . . . .
  322. +--------------+ +--------------------------+<----------+ End of heap
  323. | | | |
  324. | | | Unused Heap |
  325. | Cached Page | | space to | ^
  326. | | | page boundary | |
  327. | | +--------------------------+ |
  328. | | | Item Y Data | |
  329. +--------------+ | | |
  330. | | +--------------------------+ |
  331. | | | Item Y Header | |
  332. | Cached Page | +--------------------------+ |
  333. | | | Item Y Header Padding | |Direction of heap growth
  334. | | +--------------------------+ |
  335. | | | Item Z Data | |
  336. +--------------+ | | |
  337. | | | | |
  338. | | | | |
  339. | Cached Page | +--------------------------+ |
  340. | | | Item Z Header | |
  341. | | +--------------------------+ + Padding is here to ensure
  342. | | | Item Z Header Padding | the the data buffer start
  343. +--------------+ +--------------------------+ and end addresses are
  344. | | aligned to cachelines for
  345. | | Exclusion Range both endpoints.
  346. | Uncached Page|. . . Free Space . . .
  347. | | +--------------------------+
  348. | | | Exclusion Ranges 0..N |
  349. | | | |
  350. +--------------+ +--------------------------+ Partition Base Address + size
  351. The design of the secured partitions has two advantages over the Legacy/Default
  352. Partition
  353. 1. Using a linked list instead of a static array to track allocated SMEM
  354. items maximizes space utilization
  355. 2. Creating two heaps allows one to be cacheline aligned, thus providing
  356. an option for a higher level of performance to clients (requires
  357. client to specify they want their SMEM item allocated in the
  358. cached area)
  359. The partition header struct is defined as:
  360. struct smem_partition_header {
  361. /* Identifier magic number - 0x54525024 ("$PRT") */
  362. uint32_t identifier;
  363. /*
  364. * IDs for the 2 subsystems which have access to this partition.
  365. * Order does not matter.
  366. * Use uint16_t, rather than enum type, to ensure size.
  367. */
  368. uint16_t host0;
  369. uint16_t host1;
  370. /* Partition size, in bytes, not including the exclusion ranges */
  371. uint32_t size;
  372. /* Offset of the byte following the last allocation in uncached heap */
  373. uint32_t offset_free_uncached;
  374. /* Offset of the byte following the last allocation in cached heap */
  375. uint32_t offset_free_cached;
  376. uint32_t reserved[3];
  377. };
  378. The allocated SMEM item header struct is defined as:
  379. struct smem_partition_allocation_header {
  380. /* 0xa5a5 canary value to detect overrun problems */
  381. uint16_t canary;
  382. /* SMEM item ID. Use uint16_t here, rather than enum, to ensure size. */
  383. uint16_t smem_id;
  384. /* Size of the allocated item, includes any necessary padding. */
  385. uint32_t size;
  386. /* Size of the data padding for cacheline alignment, if applicable */
  387. uint16_t data_padding;
  388. /* Size of the header padding for cacheline alignment, if applicable */
  389. uint16_t header_padding;
  390. uint32_t reserved[1];
  391. };
  392. SMP/multi-core
  393. ==============
  394. The SMEM driver expects a remote spinlock driver to provide inter-processor
  395. synchronization primitives which not only provide locking between multiple cores
  396. but locking between multiple processors to protect the state of structures
  397. stored in SMEM regions during allocation and lookup. Once a pointer to a SMEM
  398. item is returned to a client, that client is expected to provide all the
  399. necessary locking and other synchronization as required.
  400. The remote spinlocks may make use of the SMEM_SPINLOCK_ARRAY SMEM item (typical
  401. of legacy systems).
  402. SMEM regions are non-cachable to maintain a consistent state of the data
  403. throughout all operations. This simplifies cache management and memory barrier
  404. requirements to a few key points in the SMEM item allocation process, and allows
  405. clients to treat SMEM items like local memory once allocated.
  406. Security
  407. ========
  408. SMEM by default provides no security of SMEM items. If a SMEM item is intended
  409. to only be used between clients on processors A and B, malicious clients on
  410. processor C are free to sniff or inject data into the SMEM item.
  411. An optional security feature may be enabled that makes use of Memory Protection
  412. Units (MPUs) to limit access of special segments of the main SMEM region.
  413. Access to these partitions is limited to two processors, so only point-to-point
  414. traffic (such as SMD or SMP2P) is able to be protected. Auxiliary SMEM regions
  415. are not protected under this feature. Support for this feature is activated by
  416. a Device Tree property.
  417. Performance
  418. ===========
  419. Some client use cases such as SMD may benefit from caching, but that places an
  420. additional burden of cache maintenance and protocol design onto the clients.
  421. Interface
  422. =========
  423. Kernel-space APIs:
  424. /**
  425. * smem_alloc() - Find an existing item, otherwise allocate it with security
  426. * support
  427. *
  428. * @id: ID of SMEM item
  429. * @size_in: Size of the SMEM item
  430. * @to_proc: SMEM host that shares the item with apps
  431. * @flags: Item attribute flags
  432. * @returns: Pointer to SMEM item, NULL if it couldn't be found/allocated, or
  433. * -EPROBE_DEFER if the driver is not ready
  434. */
  435. void *smem_alloc(unsigned id, unsigned size_in, unsigned to_proc,
  436. unsigned flags);
  437. /**
  438. * smem_get_entry() - Get existing item with security support
  439. *
  440. * @id: ID of SMEM item
  441. * @size: Pointer to size variable for storing the result
  442. * @to_proc: SMEM host that shares the item with apps
  443. * @flags: Item attribute flags
  444. * @returns: Pointer to SMEM item, NULL if it doesn't exist, or -EPROBE_DEFER
  445. * if the driver isn't ready
  446. */
  447. void *smem_get_entry(unsigned id, unsigned *size, unsigned to_proc,
  448. unsigned flags);
  449. /**
  450. * smem_get_entry_no_rlock() - Get existing item without using remote spinlock.
  451. *
  452. * @id: ID of SMEM item
  453. * @size_out: Pointer to size variable for storing the result
  454. * @to_proc: SMEM host that shares the item with apps
  455. * @flags: Item attribute flags
  456. * @returns: Pointer to SMEM item, NULL if it doesn't exist, or -EPROBE_DEFER
  457. * if the driver isn't ready
  458. *
  459. * This function does not lock the remote spinlock and should only be used in
  460. * failure-recover cases such as retrieving the subsystem failure reason during
  461. * subsystem restart.
  462. */
  463. void *smem_get_entry_no_rlock(unsigned id, unsigned *size_out, unsigned to_proc,
  464. unsigned flags);
  465. /**
  466. * smem_find() - Find existing item with security support
  467. *
  468. * @id: ID of SMEM item
  469. * @size_in: Size of the SMEM item
  470. * @to_proc: SMEM host that shares the item with apps
  471. * @flags: Item attribute flags
  472. * @returns: Pointer to SMEM item, NULL if it doesn't exist, or -EPROBE_DEFER
  473. * if the driver is not ready
  474. */
  475. void *smem_find(unsigned id, unsigned size);
  476. /**
  477. * smem_virt_to_phys() - Convert SMEM address to physical address.
  478. *
  479. * @smem_address: Address of SMEM item (returned by smem_alloc(), etc)
  480. * @returns: Physical address (or NULL if there is a failure)
  481. *
  482. * This function should only be used if an SMEM item needs to be handed
  483. * off to a DMA engine. This function will not return a version of EPROBE_DEFER
  484. * if the driver is not ready since the caller should obtain @smem_address from
  485. * one of the other public APIs and get EPROBE_DEFER at that time, if
  486. * applicable.
  487. */
  488. phys_addr_t smem_virt_to_phys(void *smem_address);
  489. Driver parameters
  490. =================
  491. Module parameters:
  492. debug_mask - 0 for off (default), 1 for on.
  493. Enables or disables printing debug messages to the kernel log
  494. Config options
  495. ==============
  496. Configuration of SMEM regions is done via Device Tree per the format in
  497. Documentation/devicetree/bindings/arm/msm/smem.txt.
  498. Dependencies
  499. ============
  500. Drivers needed:
  501. Remote spinlocks
  502. Depends on the system bootloader to initialize the main SMEM region.
  503. Known issues
  504. ============
  505. None.
  506. To do
  507. =====
  508. Convert use of the unsigned data type to well defined value such as uint32_t for
  509. better portability.