pvr_device.h 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735
  1. /* SPDX-License-Identifier: GPL-2.0-only OR MIT */
  2. /* Copyright (c) 2023 Imagination Technologies Ltd. */
  3. #ifndef PVR_DEVICE_H
  4. #define PVR_DEVICE_H
  5. #include "pvr_ccb.h"
  6. #include "pvr_device_info.h"
  7. #include "pvr_fw.h"
  8. #include "pvr_params.h"
  9. #include "pvr_rogue_fwif_stream.h"
  10. #include "pvr_stream.h"
  11. #include <drm/drm_device.h>
  12. #include <drm/drm_file.h>
  13. #include <drm/drm_mm.h>
  14. #include <linux/bits.h>
  15. #include <linux/compiler_attributes.h>
  16. #include <linux/compiler_types.h>
  17. #include <linux/io.h>
  18. #include <linux/iopoll.h>
  19. #include <linux/kernel.h>
  20. #include <linux/math.h>
  21. #include <linux/mutex.h>
  22. #include <linux/spinlock_types.h>
  23. #include <linux/timer.h>
  24. #include <linux/types.h>
  25. #include <linux/wait.h>
  26. #include <linux/workqueue.h>
  27. #include <linux/xarray.h>
  28. /* Forward declaration from <linux/clk.h>. */
  29. struct clk;
  30. /* Forward declaration from <linux/firmware.h>. */
  31. struct firmware;
  32. /**
  33. * struct pvr_gpu_id - Hardware GPU ID information for a PowerVR device
  34. * @b: Branch ID.
  35. * @v: Version ID.
  36. * @n: Number of scalable units.
  37. * @c: Config ID.
  38. */
  39. struct pvr_gpu_id {
  40. u16 b, v, n, c;
  41. };
  42. /**
  43. * struct pvr_fw_version - Firmware version information
  44. * @major: Major version number.
  45. * @minor: Minor version number.
  46. */
  47. struct pvr_fw_version {
  48. u16 major, minor;
  49. };
  50. /**
  51. * struct pvr_device - powervr-specific wrapper for &struct drm_device
  52. */
  53. struct pvr_device {
  54. /**
  55. * @base: The underlying &struct drm_device.
  56. *
  57. * Do not access this member directly, instead call
  58. * from_pvr_device().
  59. */
  60. struct drm_device base;
  61. /** @gpu_id: GPU ID detected at runtime. */
  62. struct pvr_gpu_id gpu_id;
  63. /**
  64. * @features: Hardware feature information.
  65. *
  66. * Do not access this member directly, instead use PVR_HAS_FEATURE()
  67. * or PVR_FEATURE_VALUE() macros.
  68. */
  69. struct pvr_device_features features;
  70. /**
  71. * @quirks: Hardware quirk information.
  72. *
  73. * Do not access this member directly, instead use PVR_HAS_QUIRK().
  74. */
  75. struct pvr_device_quirks quirks;
  76. /**
  77. * @enhancements: Hardware enhancement information.
  78. *
  79. * Do not access this member directly, instead use
  80. * PVR_HAS_ENHANCEMENT().
  81. */
  82. struct pvr_device_enhancements enhancements;
  83. /** @fw_version: Firmware version detected at runtime. */
  84. struct pvr_fw_version fw_version;
  85. /** @regs_resource: Resource representing device control registers. */
  86. struct resource *regs_resource;
  87. /**
  88. * @regs: Device control registers.
  89. *
  90. * These are mapped into memory when the device is initialized; that
  91. * location is where this pointer points.
  92. */
  93. void __iomem *regs;
  94. /**
  95. * @core_clk: General core clock.
  96. *
  97. * This is the primary clock used by the entire GPU core.
  98. */
  99. struct clk *core_clk;
  100. /**
  101. * @sys_clk: Optional system bus clock.
  102. *
  103. * This may be used on some platforms to provide an independent clock to the SoC Interface
  104. * (SOCIF). If present, this needs to be enabled/disabled together with @core_clk.
  105. */
  106. struct clk *sys_clk;
  107. /**
  108. * @mem_clk: Optional memory clock.
  109. *
  110. * This may be used on some platforms to provide an independent clock to the Memory
  111. * Interface (MEMIF). If present, this needs to be enabled/disabled together with @core_clk.
  112. */
  113. struct clk *mem_clk;
  114. /** @irq: IRQ number. */
  115. int irq;
  116. /** @fwccb: Firmware CCB. */
  117. struct pvr_ccb fwccb;
  118. /**
  119. * @kernel_vm_ctx: Virtual memory context used for kernel mappings.
  120. *
  121. * This is used for mappings in the firmware address region when a META firmware processor
  122. * is in use.
  123. *
  124. * When a MIPS firmware processor is in use, this will be %NULL.
  125. */
  126. struct pvr_vm_context *kernel_vm_ctx;
  127. /** @fw_dev: Firmware related data. */
  128. struct pvr_fw_device fw_dev;
  129. /**
  130. * @params: Device-specific parameters.
  131. *
  132. * The values of these parameters are initialized from the
  133. * defaults specified as module parameters. They may be
  134. * modified at runtime via debugfs (if enabled).
  135. */
  136. struct pvr_device_params params;
  137. /** @stream_musthave_quirks: Bit array of "must-have" quirks for stream commands. */
  138. u32 stream_musthave_quirks[PVR_STREAM_TYPE_MAX][PVR_STREAM_EXTHDR_TYPE_MAX];
  139. /**
  140. * @mmu_flush_cache_flags: Records which MMU caches require flushing
  141. * before submitting the next job.
  142. */
  143. atomic_t mmu_flush_cache_flags;
  144. /**
  145. * @ctx_ids: Array of contexts belonging to this device. Array members
  146. * are of type "struct pvr_context *".
  147. *
  148. * This array is used to allocate IDs used by the firmware.
  149. */
  150. struct xarray ctx_ids;
  151. /**
  152. * @free_list_ids: Array of free lists belonging to this device. Array members
  153. * are of type "struct pvr_free_list *".
  154. *
  155. * This array is used to allocate IDs used by the firmware.
  156. */
  157. struct xarray free_list_ids;
  158. /**
  159. * @job_ids: Array of jobs belonging to this device. Array members
  160. * are of type "struct pvr_job *".
  161. */
  162. struct xarray job_ids;
  163. /**
  164. * @queues: Queue-related fields.
  165. */
  166. struct {
  167. /** @queues.active: Active queue list. */
  168. struct list_head active;
  169. /** @queues.idle: Idle queue list. */
  170. struct list_head idle;
  171. /** @queues.lock: Lock protecting access to the active/idle
  172. * lists. */
  173. struct mutex lock;
  174. } queues;
  175. /**
  176. * @watchdog: Watchdog for communications with firmware.
  177. */
  178. struct {
  179. /** @watchdog.work: Work item for watchdog callback. */
  180. struct delayed_work work;
  181. /**
  182. * @watchdog.old_kccb_cmds_executed: KCCB command execution
  183. * count at last watchdog poll.
  184. */
  185. u32 old_kccb_cmds_executed;
  186. /**
  187. * @watchdog.kccb_stall_count: Number of watchdog polls
  188. * KCCB has been stalled for.
  189. */
  190. u32 kccb_stall_count;
  191. } watchdog;
  192. /**
  193. * @kccb: Circular buffer for communications with firmware.
  194. */
  195. struct {
  196. /** @kccb.ccb: Kernel CCB. */
  197. struct pvr_ccb ccb;
  198. /** @kccb.rtn_q: Waitqueue for KCCB command return waiters. */
  199. wait_queue_head_t rtn_q;
  200. /** @kccb.rtn_obj: Object representing KCCB return slots. */
  201. struct pvr_fw_object *rtn_obj;
  202. /**
  203. * @kccb.rtn: Pointer to CPU mapping of KCCB return slots.
  204. * Must be accessed by READ_ONCE()/WRITE_ONCE().
  205. */
  206. u32 *rtn;
  207. /** @kccb.slot_count: Total number of KCCB slots available. */
  208. u32 slot_count;
  209. /** @kccb.reserved_count: Number of KCCB slots reserved for
  210. * future use. */
  211. u32 reserved_count;
  212. /**
  213. * @kccb.waiters: List of KCCB slot waiters.
  214. */
  215. struct list_head waiters;
  216. /** @kccb.fence_ctx: KCCB fence context. */
  217. struct {
  218. /** @kccb.fence_ctx.id: KCCB fence context ID
  219. * allocated with dma_fence_context_alloc(). */
  220. u64 id;
  221. /** @kccb.fence_ctx.seqno: Sequence number incremented
  222. * each time a fence is created. */
  223. atomic_t seqno;
  224. /**
  225. * @kccb.fence_ctx.lock: Lock used to synchronize
  226. * access to fences allocated by this context.
  227. */
  228. spinlock_t lock;
  229. } fence_ctx;
  230. } kccb;
  231. /**
  232. * @lost: %true if the device has been lost.
  233. *
  234. * This variable is set if the device has become irretrievably unavailable, e.g. if the
  235. * firmware processor has stopped responding and can not be revived via a hard reset.
  236. */
  237. bool lost;
  238. /**
  239. * @reset_sem: Reset semaphore.
  240. *
  241. * GPU reset code will lock this for writing. Any code that submits commands to the firmware
  242. * that isn't in an IRQ handler or on the scheduler workqueue must lock this for reading.
  243. * Once this has been successfully locked, &pvr_dev->lost _must_ be checked, and -%EIO must
  244. * be returned if it is set.
  245. */
  246. struct rw_semaphore reset_sem;
  247. /** @sched_wq: Workqueue for schedulers. */
  248. struct workqueue_struct *sched_wq;
  249. /**
  250. * @ctx_list_lock: Lock to be held when accessing the context list in
  251. * struct pvr_file.
  252. */
  253. spinlock_t ctx_list_lock;
  254. };
  255. /**
  256. * struct pvr_file - powervr-specific data to be assigned to &struct
  257. * drm_file.driver_priv
  258. */
  259. struct pvr_file {
  260. /**
  261. * @file: A reference to the parent &struct drm_file.
  262. *
  263. * Do not access this member directly, instead call from_pvr_file().
  264. */
  265. struct drm_file *file;
  266. /**
  267. * @pvr_dev: A reference to the powervr-specific wrapper for the
  268. * associated device. Saves on repeated calls to to_pvr_device().
  269. */
  270. struct pvr_device *pvr_dev;
  271. /**
  272. * @ctx_handles: Array of contexts belonging to this file. Array members
  273. * are of type "struct pvr_context *".
  274. *
  275. * This array is used to allocate handles returned to userspace.
  276. */
  277. struct xarray ctx_handles;
  278. /**
  279. * @free_list_handles: Array of free lists belonging to this file. Array
  280. * members are of type "struct pvr_free_list *".
  281. *
  282. * This array is used to allocate handles returned to userspace.
  283. */
  284. struct xarray free_list_handles;
  285. /**
  286. * @hwrt_handles: Array of HWRT datasets belonging to this file. Array
  287. * members are of type "struct pvr_hwrt_dataset *".
  288. *
  289. * This array is used to allocate handles returned to userspace.
  290. */
  291. struct xarray hwrt_handles;
  292. /**
  293. * @vm_ctx_handles: Array of VM contexts belonging to this file. Array
  294. * members are of type "struct pvr_vm_context *".
  295. *
  296. * This array is used to allocate handles returned to userspace.
  297. */
  298. struct xarray vm_ctx_handles;
  299. /** @contexts: PVR context list. */
  300. struct list_head contexts;
  301. };
  302. /**
  303. * PVR_HAS_FEATURE() - Tests whether a PowerVR device has a given feature
  304. * @pvr_dev: [IN] Target PowerVR device.
  305. * @feature: [IN] Hardware feature name.
  306. *
  307. * Feature names are derived from those found in &struct pvr_device_features by
  308. * dropping the 'has_' prefix, which is applied by this macro.
  309. *
  310. * Return:
  311. * * true if the named feature is present in the hardware
  312. * * false if the named feature is not present in the hardware
  313. */
  314. #define PVR_HAS_FEATURE(pvr_dev, feature) ((pvr_dev)->features.has_##feature)
  315. /**
  316. * PVR_FEATURE_VALUE() - Gets a PowerVR device feature value
  317. * @pvr_dev: [IN] Target PowerVR device.
  318. * @feature: [IN] Feature name.
  319. * @value_out: [OUT] Feature value.
  320. *
  321. * This macro will get a feature value for those features that have values.
  322. * If the feature is not present, nothing will be stored to @value_out.
  323. *
  324. * Feature names are derived from those found in &struct pvr_device_features by
  325. * dropping the 'has_' prefix.
  326. *
  327. * Return:
  328. * * 0 on success, or
  329. * * -%EINVAL if the named feature is not present in the hardware
  330. */
  331. #define PVR_FEATURE_VALUE(pvr_dev, feature, value_out) \
  332. ({ \
  333. struct pvr_device *_pvr_dev = pvr_dev; \
  334. int _ret = -EINVAL; \
  335. if (_pvr_dev->features.has_##feature) { \
  336. *(value_out) = _pvr_dev->features.feature; \
  337. _ret = 0; \
  338. } \
  339. _ret; \
  340. })
  341. /**
  342. * PVR_HAS_QUIRK() - Tests whether a physical device has a given quirk
  343. * @pvr_dev: [IN] Target PowerVR device.
  344. * @quirk: [IN] Hardware quirk name.
  345. *
  346. * Quirk numbers are derived from those found in #pvr_device_quirks by
  347. * dropping the 'has_brn' prefix, which is applied by this macro.
  348. *
  349. * Returns
  350. * * true if the quirk is present in the hardware, or
  351. * * false if the quirk is not present in the hardware.
  352. */
  353. #define PVR_HAS_QUIRK(pvr_dev, quirk) ((pvr_dev)->quirks.has_brn##quirk)
  354. /**
  355. * PVR_HAS_ENHANCEMENT() - Tests whether a physical device has a given
  356. * enhancement
  357. * @pvr_dev: [IN] Target PowerVR device.
  358. * @enhancement: [IN] Hardware enhancement name.
  359. *
  360. * Enhancement numbers are derived from those found in #pvr_device_enhancements
  361. * by dropping the 'has_ern' prefix, which is applied by this macro.
  362. *
  363. * Returns
  364. * * true if the enhancement is present in the hardware, or
  365. * * false if the enhancement is not present in the hardware.
  366. */
  367. #define PVR_HAS_ENHANCEMENT(pvr_dev, enhancement) ((pvr_dev)->enhancements.has_ern##enhancement)
  368. #define from_pvr_device(pvr_dev) (&(pvr_dev)->base)
  369. #define to_pvr_device(drm_dev) container_of_const(drm_dev, struct pvr_device, base)
  370. #define from_pvr_file(pvr_file) ((pvr_file)->file)
  371. #define to_pvr_file(file) ((file)->driver_priv)
  372. /**
  373. * PVR_PACKED_BVNC() - Packs B, V, N and C values into a 64-bit unsigned integer
  374. * @b: Branch ID.
  375. * @v: Version ID.
  376. * @n: Number of scalable units.
  377. * @c: Config ID.
  378. *
  379. * The packed layout is as follows:
  380. *
  381. * +--------+--------+--------+-------+
  382. * | 63..48 | 47..32 | 31..16 | 15..0 |
  383. * +========+========+========+=======+
  384. * | B | V | N | C |
  385. * +--------+--------+--------+-------+
  386. *
  387. * pvr_gpu_id_to_packed_bvnc() should be used instead of this macro when a
  388. * &struct pvr_gpu_id is available in order to ensure proper type checking.
  389. *
  390. * Return: Packed BVNC.
  391. */
  392. /* clang-format off */
  393. #define PVR_PACKED_BVNC(b, v, n, c) \
  394. ((((u64)(b) & GENMASK_ULL(15, 0)) << 48) | \
  395. (((u64)(v) & GENMASK_ULL(15, 0)) << 32) | \
  396. (((u64)(n) & GENMASK_ULL(15, 0)) << 16) | \
  397. (((u64)(c) & GENMASK_ULL(15, 0)) << 0))
  398. /* clang-format on */
  399. /**
  400. * pvr_gpu_id_to_packed_bvnc() - Packs B, V, N and C values into a 64-bit
  401. * unsigned integer
  402. * @gpu_id: GPU ID.
  403. *
  404. * The packed layout is as follows:
  405. *
  406. * +--------+--------+--------+-------+
  407. * | 63..48 | 47..32 | 31..16 | 15..0 |
  408. * +========+========+========+=======+
  409. * | B | V | N | C |
  410. * +--------+--------+--------+-------+
  411. *
  412. * This should be used in preference to PVR_PACKED_BVNC() when a &struct
  413. * pvr_gpu_id is available in order to ensure proper type checking.
  414. *
  415. * Return: Packed BVNC.
  416. */
  417. static __always_inline u64
  418. pvr_gpu_id_to_packed_bvnc(struct pvr_gpu_id *gpu_id)
  419. {
  420. return PVR_PACKED_BVNC(gpu_id->b, gpu_id->v, gpu_id->n, gpu_id->c);
  421. }
  422. static __always_inline void
  423. packed_bvnc_to_pvr_gpu_id(u64 bvnc, struct pvr_gpu_id *gpu_id)
  424. {
  425. gpu_id->b = (bvnc & GENMASK_ULL(63, 48)) >> 48;
  426. gpu_id->v = (bvnc & GENMASK_ULL(47, 32)) >> 32;
  427. gpu_id->n = (bvnc & GENMASK_ULL(31, 16)) >> 16;
  428. gpu_id->c = bvnc & GENMASK_ULL(15, 0);
  429. }
  430. int pvr_device_init(struct pvr_device *pvr_dev);
  431. void pvr_device_fini(struct pvr_device *pvr_dev);
  432. void pvr_device_reset(struct pvr_device *pvr_dev);
  433. bool
  434. pvr_device_has_uapi_quirk(struct pvr_device *pvr_dev, u32 quirk);
  435. bool
  436. pvr_device_has_uapi_enhancement(struct pvr_device *pvr_dev, u32 enhancement);
  437. bool
  438. pvr_device_has_feature(struct pvr_device *pvr_dev, u32 feature);
  439. /**
  440. * PVR_CR_FIELD_GET() - Extract a single field from a PowerVR control register
  441. * @val: Value of the target register.
  442. * @field: Field specifier, as defined in "pvr_rogue_cr_defs.h".
  443. *
  444. * Return: The extracted field.
  445. */
  446. #define PVR_CR_FIELD_GET(val, field) FIELD_GET(~ROGUE_CR_##field##_CLRMSK, val)
  447. /**
  448. * pvr_cr_read32() - Read a 32-bit register from a PowerVR device
  449. * @pvr_dev: Target PowerVR device.
  450. * @reg: Target register.
  451. *
  452. * Return: The value of the requested register.
  453. */
  454. static __always_inline u32
  455. pvr_cr_read32(struct pvr_device *pvr_dev, u32 reg)
  456. {
  457. return ioread32(pvr_dev->regs + reg);
  458. }
  459. /**
  460. * pvr_cr_read64() - Read a 64-bit register from a PowerVR device
  461. * @pvr_dev: Target PowerVR device.
  462. * @reg: Target register.
  463. *
  464. * Return: The value of the requested register.
  465. */
  466. static __always_inline u64
  467. pvr_cr_read64(struct pvr_device *pvr_dev, u32 reg)
  468. {
  469. return ioread64(pvr_dev->regs + reg);
  470. }
  471. /**
  472. * pvr_cr_write32() - Write to a 32-bit register in a PowerVR device
  473. * @pvr_dev: Target PowerVR device.
  474. * @reg: Target register.
  475. * @val: Value to write.
  476. */
  477. static __always_inline void
  478. pvr_cr_write32(struct pvr_device *pvr_dev, u32 reg, u32 val)
  479. {
  480. iowrite32(val, pvr_dev->regs + reg);
  481. }
  482. /**
  483. * pvr_cr_write64() - Write to a 64-bit register in a PowerVR device
  484. * @pvr_dev: Target PowerVR device.
  485. * @reg: Target register.
  486. * @val: Value to write.
  487. */
  488. static __always_inline void
  489. pvr_cr_write64(struct pvr_device *pvr_dev, u32 reg, u64 val)
  490. {
  491. iowrite64(val, pvr_dev->regs + reg);
  492. }
  493. /**
  494. * pvr_cr_poll_reg32() - Wait for a 32-bit register to match a given value by
  495. * polling
  496. * @pvr_dev: Target PowerVR device.
  497. * @reg_addr: Address of register.
  498. * @reg_value: Expected register value (after masking).
  499. * @reg_mask: Mask of bits valid for comparison with @reg_value.
  500. * @timeout_usec: Timeout length, in us.
  501. *
  502. * Returns:
  503. * * 0 on success, or
  504. * * -%ETIMEDOUT on timeout.
  505. */
  506. static __always_inline int
  507. pvr_cr_poll_reg32(struct pvr_device *pvr_dev, u32 reg_addr, u32 reg_value,
  508. u32 reg_mask, u64 timeout_usec)
  509. {
  510. u32 value;
  511. return readl_poll_timeout(pvr_dev->regs + reg_addr, value,
  512. (value & reg_mask) == reg_value, 0, timeout_usec);
  513. }
  514. /**
  515. * pvr_cr_poll_reg64() - Wait for a 64-bit register to match a given value by
  516. * polling
  517. * @pvr_dev: Target PowerVR device.
  518. * @reg_addr: Address of register.
  519. * @reg_value: Expected register value (after masking).
  520. * @reg_mask: Mask of bits valid for comparison with @reg_value.
  521. * @timeout_usec: Timeout length, in us.
  522. *
  523. * Returns:
  524. * * 0 on success, or
  525. * * -%ETIMEDOUT on timeout.
  526. */
  527. static __always_inline int
  528. pvr_cr_poll_reg64(struct pvr_device *pvr_dev, u32 reg_addr, u64 reg_value,
  529. u64 reg_mask, u64 timeout_usec)
  530. {
  531. u64 value;
  532. return readq_poll_timeout(pvr_dev->regs + reg_addr, value,
  533. (value & reg_mask) == reg_value, 0, timeout_usec);
  534. }
  535. /**
  536. * pvr_round_up_to_cacheline_size() - Round up a provided size to be cacheline
  537. * aligned
  538. * @pvr_dev: Target PowerVR device.
  539. * @size: Initial size, in bytes.
  540. *
  541. * Returns:
  542. * * Size aligned to cacheline size.
  543. */
  544. static __always_inline size_t
  545. pvr_round_up_to_cacheline_size(struct pvr_device *pvr_dev, size_t size)
  546. {
  547. u16 slc_cacheline_size_bits = 0;
  548. u16 slc_cacheline_size_bytes;
  549. WARN_ON(!PVR_HAS_FEATURE(pvr_dev, slc_cache_line_size_bits));
  550. PVR_FEATURE_VALUE(pvr_dev, slc_cache_line_size_bits,
  551. &slc_cacheline_size_bits);
  552. slc_cacheline_size_bytes = slc_cacheline_size_bits / 8;
  553. return round_up(size, slc_cacheline_size_bytes);
  554. }
  555. /**
  556. * DOC: IOCTL validation helpers
  557. *
  558. * To validate the constraints imposed on IOCTL argument structs, a collection
  559. * of macros and helper functions exist in ``pvr_device.h``.
  560. *
  561. * Of the current helpers, it should only be necessary to call
  562. * PVR_IOCTL_UNION_PADDING_CHECK() directly. This macro should be used once in
  563. * every code path which extracts a union member from a struct passed from
  564. * userspace.
  565. */
  566. /**
  567. * pvr_ioctl_union_padding_check() - Validate that the implicit padding between
  568. * the end of a union member and the end of the union itself is zeroed.
  569. * @instance: Pointer to the instance of the struct to validate.
  570. * @union_offset: Offset into the type of @instance of the target union. Must
  571. * be 64-bit aligned.
  572. * @union_size: Size of the target union in the type of @instance. Must be
  573. * 64-bit aligned.
  574. * @member_size: Size of the target member in the target union specified by
  575. * @union_offset and @union_size. It is assumed that the offset of the target
  576. * member is zero relative to @union_offset. Must be 64-bit aligned.
  577. *
  578. * You probably want to use PVR_IOCTL_UNION_PADDING_CHECK() instead of calling
  579. * this function directly, since that macro abstracts away much of the setup,
  580. * and also provides some static validation. See its docs for details.
  581. *
  582. * Return:
  583. * * %true if every byte between the end of the used member of the union and
  584. * the end of that union is zeroed, or
  585. * * %false otherwise.
  586. */
  587. static __always_inline bool
  588. pvr_ioctl_union_padding_check(void *instance, size_t union_offset,
  589. size_t union_size, size_t member_size)
  590. {
  591. /*
  592. * void pointer arithmetic is technically illegal - cast to a byte
  593. * pointer so this addition works safely.
  594. */
  595. void *padding_start = ((u8 *)instance) + union_offset + member_size;
  596. size_t padding_size = union_size - member_size;
  597. return mem_is_zero(padding_start, padding_size);
  598. }
  599. /**
  600. * PVR_STATIC_ASSERT_64BIT_ALIGNED() - Inline assertion for 64-bit alignment.
  601. * @static_expr_: Target expression to evaluate.
  602. *
  603. * If @static_expr_ does not evaluate to a constant integer which would be a
  604. * 64-bit aligned address (i.e. a multiple of 8), compilation will fail.
  605. *
  606. * Return:
  607. * The value of @static_expr_.
  608. */
  609. #define PVR_STATIC_ASSERT_64BIT_ALIGNED(static_expr_) \
  610. ({ \
  611. static_assert(((static_expr_) & (sizeof(u64) - 1)) == 0); \
  612. (static_expr_); \
  613. })
  614. /**
  615. * PVR_IOCTL_UNION_PADDING_CHECK() - Validate that the implicit padding between
  616. * the end of a union member and the end of the union itself is zeroed.
  617. * @struct_instance_: An expression which evaluates to a pointer to a UAPI data
  618. * struct.
  619. * @union_: The name of the union member of @struct_instance_ to check. If the
  620. * union member is nested within the type of @struct_instance_, this may
  621. * contain the member access operator (".").
  622. * @member_: The name of the member of @union_ to assess.
  623. *
  624. * This is a wrapper around pvr_ioctl_union_padding_check() which performs
  625. * alignment checks and simplifies things for the caller.
  626. *
  627. * Return:
  628. * * %true if every byte in @struct_instance_ between the end of @member_ and
  629. * the end of @union_ is zeroed, or
  630. * * %false otherwise.
  631. */
  632. #define PVR_IOCTL_UNION_PADDING_CHECK(struct_instance_, union_, member_) \
  633. ({ \
  634. typeof(struct_instance_) __instance = (struct_instance_); \
  635. size_t __union_offset = PVR_STATIC_ASSERT_64BIT_ALIGNED( \
  636. offsetof(typeof(*__instance), union_)); \
  637. size_t __union_size = PVR_STATIC_ASSERT_64BIT_ALIGNED( \
  638. sizeof(__instance->union_)); \
  639. size_t __member_size = PVR_STATIC_ASSERT_64BIT_ALIGNED( \
  640. sizeof(__instance->union_.member_)); \
  641. pvr_ioctl_union_padding_check(__instance, __union_offset, \
  642. __union_size, __member_size); \
  643. })
  644. #define PVR_FW_PROCESSOR_TYPE_META 0
  645. #define PVR_FW_PROCESSOR_TYPE_MIPS 1
  646. #define PVR_FW_PROCESSOR_TYPE_RISCV 2
  647. #endif /* PVR_DEVICE_H */