drm/xe: Fix out-of-bounds field write in MI_STORE_DATA_IMM
authorJia Yao <jia.yao@intel.com>
Thu, 12 Jun 2025 22:46:20 +0000 (22:46 +0000)
committerLucas De Marchi <lucas.demarchi@intel.com>
Tue, 1 Jul 2025 20:04:00 +0000 (13:04 -0700)
According to Bspec, bits 0~9 of MI_STORE_DATA_IMM must not exceed 0x3FE.
The macro MI_SDI_NUM_QW(x) evaluates to 2 * x + 1, which means the
condition 2 * x + 1 <= 0x3FE must be satisfied. Therefore, the maximum
valid value for x is 0x1FE, not 0x1FF.

v2
 - Replace 0x1fe with macro MAX_PTE_PER_SDI (Auld, Matthew & Patelczyk, Maciej)

v3
 - Change macro MAX_PTE_PER_SDI from 0x1fe to 0x1feU (De Marchi, Lucas)

Bspec: 60246

Fixes: 9c44fd5f6e8a ("drm/xe: Add migrate layer functions for SVM support")
Cc: Matthew Brost <matthew.brost@intel.com>
Cc: Brian3 Nguyen <brian3.nguyen@intel.com>
Cc: Alex Zuo <alex.zuo@intel.com>
Cc: Matthew Auld <matthew.auld@intel.com>
Cc: Maciej Patelczyk <maciej.patelczyk@intel.com>
Cc: Lucas De Marchi <lucas.demarchi@intel.com>
Suggested-by: Shuicheng Lin <shuicheng.lin@intel.com>
Signed-off-by: Jia Yao <jia.yao@intel.com>
Reviewed-by: Matthew Brost <matthew.brost@intel.com>
Reviewed-by: Lucas De Marchi <lucas.demarchi@intel.com>
Reviewed-by: Maciej Patelczyk <maciej.patelczyk@intel.com>
Link: https://lore.kernel.org/r/20250612224620.161105-1-jia.yao@intel.com
Signed-off-by: Lucas De Marchi <lucas.demarchi@intel.com>
(cherry picked from commit c038bdba98c9f6a36378044a9d4385531a194d3e)
Signed-off-by: Lucas De Marchi <lucas.demarchi@intel.com>
drivers/gpu/drm/xe/xe_migrate.c

index 8f8e9fdfb2a813dfc7619f626f919c3f70441527..7acdc4c78866681a45c31ca18715ef8b1c4d15aa 100644 (file)
@@ -82,7 +82,7 @@ struct xe_migrate {
  * of the instruction.  Subtracting the instruction header (1 dword) and
  * address (2 dwords), that leaves 0x3FD dwords (0x1FE qwords) for PTE values.
  */
-#define MAX_PTE_PER_SDI 0x1FE
+#define MAX_PTE_PER_SDI 0x1FEU
 
 /**
  * xe_tile_migrate_exec_queue() - Get this tile's migrate exec queue.
@@ -1553,15 +1553,17 @@ static u32 pte_update_cmd_size(u64 size)
        u64 entries = DIV_U64_ROUND_UP(size, XE_PAGE_SIZE);
 
        XE_WARN_ON(size > MAX_PREEMPTDISABLE_TRANSFER);
+
        /*
         * MI_STORE_DATA_IMM command is used to update page table. Each
-        * instruction can update maximumly 0x1ff pte entries. To update
-        * n (n <= 0x1ff) pte entries, we need:
-        * 1 dword for the MI_STORE_DATA_IMM command header (opcode etc)
-        * 2 dword for the page table's physical location
-        * 2*n dword for value of pte to fill (each pte entry is 2 dwords)
+        * instruction can update maximumly MAX_PTE_PER_SDI pte entries. To
+        * update n (n <= MAX_PTE_PER_SDI) pte entries, we need:
+        *
+        * - 1 dword for the MI_STORE_DATA_IMM command header (opcode etc)
+        * - 2 dword for the page table's physical location
+        * - 2*n dword for value of pte to fill (each pte entry is 2 dwords)
         */
-       num_dword = (1 + 2) * DIV_U64_ROUND_UP(entries, 0x1ff);
+       num_dword = (1 + 2) * DIV_U64_ROUND_UP(entries, MAX_PTE_PER_SDI);
        num_dword += entries * 2;
 
        return num_dword;
@@ -1577,7 +1579,7 @@ static void build_pt_update_batch_sram(struct xe_migrate *m,
 
        ptes = DIV_ROUND_UP(size, XE_PAGE_SIZE);
        while (ptes) {
-               u32 chunk = min(0x1ffU, ptes);
+               u32 chunk = min(MAX_PTE_PER_SDI, ptes);
 
                bb->cs[bb->len++] = MI_STORE_DATA_IMM | MI_SDI_NUM_QW(chunk);
                bb->cs[bb->len++] = pt_offset;