1 // SPDX-License-Identifier: MIT 2 /* 3 * Copyright © 2023 Intel Corporation 4 */ 5 6 #include "xe_reg_whitelist.h" 7 8 #include "regs/xe_engine_regs.h" 9 #include "regs/xe_gt_regs.h" 10 #include "regs/xe_oa_regs.h" 11 #include "xe_device.h" 12 #include "xe_gt.h" 13 #include "xe_gt_types.h" 14 #include "xe_gt_printk.h" 15 #include "xe_platform_types.h" 16 #include "xe_reg_sr.h" 17 #include "xe_rtp.h" 18 #include "xe_step.h" 19 20 #undef XE_REG_MCR 21 #define XE_REG_MCR(...) XE_REG(__VA_ARGS__, .mcr = 1) 22 23 static bool match_not_render(const struct xe_device *xe, 24 const struct xe_gt *gt, 25 const struct xe_hw_engine *hwe) 26 { 27 return hwe->class != XE_ENGINE_CLASS_RENDER; 28 } 29 30 static bool match_has_mert(const struct xe_device *xe, 31 const struct xe_gt *gt, 32 const struct xe_hw_engine *hwe) 33 { 34 return xe_device_has_mert((struct xe_device *)xe); 35 } 36 37 static bool match_multi_queue_class(const struct xe_device *xe, 38 const struct xe_gt *gt, 39 const struct xe_hw_engine *hwe) 40 { 41 return xe_gt_supports_multi_queue(gt, hwe->class); 42 } 43 44 static const struct xe_rtp_entry_sr register_whitelist[] = { 45 { XE_RTP_NAME("WaAllowPMDepthAndInvocationCountAccessFromUMD, 1408556865"), 46 XE_RTP_RULES(GRAPHICS_VERSION_RANGE(1200, 1210), ENGINE_CLASS(RENDER)), 47 XE_RTP_ACTIONS(WHITELIST(PS_INVOCATION_COUNT, 48 RING_FORCE_TO_NONPRIV_ACCESS_RD | 49 RING_FORCE_TO_NONPRIV_RANGE_4)) 50 }, 51 { XE_RTP_NAME("1508744258, 14012131227, 1808121037"), 52 XE_RTP_RULES(GRAPHICS_VERSION_RANGE(1200, 1210), ENGINE_CLASS(RENDER)), 53 XE_RTP_ACTIONS(WHITELIST(COMMON_SLICE_CHICKEN1, 0)) 54 }, 55 { XE_RTP_NAME("1806527549"), 56 XE_RTP_RULES(GRAPHICS_VERSION_RANGE(1200, 1210), ENGINE_CLASS(RENDER)), 57 XE_RTP_ACTIONS(WHITELIST(HIZ_CHICKEN, 0)) 58 }, 59 { XE_RTP_NAME("allow_read_ctx_timestamp"), 60 XE_RTP_RULES(GRAPHICS_VERSION_RANGE(1200, 1260), FUNC(match_not_render)), 61 XE_RTP_ACTIONS(WHITELIST(RING_CTX_TIMESTAMP(0), 62 RING_FORCE_TO_NONPRIV_ACCESS_RD, 63 XE_RTP_ACTION_FLAG(ENGINE_BASE))) 64 }, 65 { XE_RTP_NAME("allow_read_queue_timestamp"), 66 XE_RTP_RULES(GRAPHICS_VERSION_RANGE(3500, 3511), FUNC(match_multi_queue_class)), 67 XE_RTP_ACTIONS(WHITELIST(RING_QUEUE_TIMESTAMP(0), 68 RING_FORCE_TO_NONPRIV_ACCESS_RD, 69 XE_RTP_ACTION_FLAG(ENGINE_BASE))) 70 }, 71 { XE_RTP_NAME("16014440446"), 72 XE_RTP_RULES(PLATFORM(PVC)), 73 XE_RTP_ACTIONS(WHITELIST(XE_REG(0x4400), 74 RING_FORCE_TO_NONPRIV_DENY | 75 RING_FORCE_TO_NONPRIV_RANGE_64), 76 WHITELIST(XE_REG(0x4500), 77 RING_FORCE_TO_NONPRIV_DENY | 78 RING_FORCE_TO_NONPRIV_RANGE_64)) 79 }, 80 { XE_RTP_NAME("16017236439"), 81 XE_RTP_RULES(PLATFORM(PVC), ENGINE_CLASS(COPY)), 82 XE_RTP_ACTIONS(WHITELIST(BCS_SWCTRL(0), 83 RING_FORCE_TO_NONPRIV_DENY, 84 XE_RTP_ACTION_FLAG(ENGINE_BASE))) 85 }, 86 { XE_RTP_NAME("16020183090"), 87 XE_RTP_RULES(GRAPHICS_VERSION(2004), GRAPHICS_STEP(A0, B0), 88 ENGINE_CLASS(RENDER)), 89 XE_RTP_ACTIONS(WHITELIST(CSBE_DEBUG_STATUS(RENDER_RING_BASE), 0)) 90 }, 91 { XE_RTP_NAME("14024997852"), 92 XE_RTP_RULES(GRAPHICS_VERSION_RANGE(2001, 3005), ENGINE_CLASS(RENDER)), 93 XE_RTP_ACTIONS(WHITELIST(FF_MODE, 94 RING_FORCE_TO_NONPRIV_ACCESS_RW), 95 WHITELIST(VFLSKPD, 96 RING_FORCE_TO_NONPRIV_ACCESS_RW)) 97 }, 98 { XE_RTP_NAME("14024997852"), 99 XE_RTP_RULES(GRAPHICS_VERSION(3510), GRAPHICS_STEP(A0, B0), 100 ENGINE_CLASS(RENDER)), 101 XE_RTP_ACTIONS(WHITELIST(FF_MODE, 102 RING_FORCE_TO_NONPRIV_ACCESS_RW), 103 WHITELIST(VFLSKPD, 104 RING_FORCE_TO_NONPRIV_ACCESS_RW)) 105 }, 106 107 #define WHITELIST_OA_MMIO_TRG(trg, status, head) \ 108 WHITELIST(trg, RING_FORCE_TO_NONPRIV_ACCESS_RW), \ 109 WHITELIST(status, RING_FORCE_TO_NONPRIV_ACCESS_RD), \ 110 WHITELIST(head, RING_FORCE_TO_NONPRIV_ACCESS_RD | RING_FORCE_TO_NONPRIV_RANGE_4) 111 112 #define WHITELIST_OAG_MMIO_TRG \ 113 WHITELIST_OA_MMIO_TRG(OAG_MMIOTRIGGER, OAG_OASTATUS, OAG_OAHEADPTR) 114 115 #define WHITELIST_OAM_MMIO_TRG \ 116 WHITELIST_OA_MMIO_TRG(OAM_MMIO_TRG(XE_OAM_SAG_BASE_ADJ), \ 117 OAM_STATUS(XE_OAM_SAG_BASE_ADJ), \ 118 OAM_HEAD_POINTER(XE_OAM_SAG_BASE_ADJ)), \ 119 WHITELIST_OA_MMIO_TRG(OAM_MMIO_TRG(XE_OAM_SCMI_0_BASE_ADJ), \ 120 OAM_STATUS(XE_OAM_SCMI_0_BASE_ADJ), \ 121 OAM_HEAD_POINTER(XE_OAM_SCMI_0_BASE_ADJ)), \ 122 WHITELIST_OA_MMIO_TRG(OAM_MMIO_TRG(XE_OAM_SCMI_1_BASE_ADJ), \ 123 OAM_STATUS(XE_OAM_SCMI_1_BASE_ADJ), \ 124 OAM_HEAD_POINTER(XE_OAM_SCMI_1_BASE_ADJ)) 125 126 #define WHITELIST_OA_MERT_MMIO_TRG \ 127 WHITELIST_OA_MMIO_TRG(OAMERT_MMIO_TRG, OAMERT_STATUS, OAMERT_HEAD_POINTER) 128 129 { XE_RTP_NAME("oag_mmio_trg_rcs"), 130 XE_RTP_RULES(GRAPHICS_VERSION_RANGE(1200, XE_RTP_END_VERSION_UNDEFINED), 131 ENGINE_CLASS(RENDER)), 132 XE_RTP_ACTIONS(WHITELIST_OAG_MMIO_TRG) 133 }, 134 { XE_RTP_NAME("oag_mmio_trg_ccs"), 135 XE_RTP_RULES(GRAPHICS_VERSION_RANGE(1200, XE_RTP_END_VERSION_UNDEFINED), 136 ENGINE_CLASS(COMPUTE)), 137 XE_RTP_ACTIONS(WHITELIST_OAG_MMIO_TRG) 138 }, 139 { XE_RTP_NAME("oam_mmio_trg_vcs"), 140 XE_RTP_RULES(MEDIA_VERSION_RANGE(1300, XE_RTP_END_VERSION_UNDEFINED), 141 ENGINE_CLASS(VIDEO_DECODE)), 142 XE_RTP_ACTIONS(WHITELIST_OAM_MMIO_TRG) 143 }, 144 { XE_RTP_NAME("oam_mmio_trg_vecs"), 145 XE_RTP_RULES(MEDIA_VERSION_RANGE(1300, XE_RTP_END_VERSION_UNDEFINED), 146 ENGINE_CLASS(VIDEO_ENHANCE)), 147 XE_RTP_ACTIONS(WHITELIST_OAM_MMIO_TRG) 148 }, 149 { XE_RTP_NAME("oa_mert_mmio_trg_ccs"), 150 XE_RTP_RULES(FUNC(match_has_mert), ENGINE_CLASS(COMPUTE)), 151 XE_RTP_ACTIONS(WHITELIST_OA_MERT_MMIO_TRG) 152 }, 153 { XE_RTP_NAME("oa_mert_mmio_trg_bcs"), 154 XE_RTP_RULES(FUNC(match_has_mert), ENGINE_CLASS(COPY)), 155 XE_RTP_ACTIONS(WHITELIST_OA_MERT_MMIO_TRG) 156 }, 157 }; 158 159 static void whitelist_apply_to_hwe(struct xe_hw_engine *hwe) 160 { 161 struct xe_reg_sr *sr = &hwe->reg_whitelist; 162 struct xe_reg_sr_entry *entry; 163 struct drm_printer p; 164 unsigned long reg; 165 unsigned int slot; 166 167 xe_gt_dbg(hwe->gt, "Add %s whitelist to engine\n", sr->name); 168 p = xe_gt_dbg_printer(hwe->gt); 169 170 slot = 0; 171 xa_for_each(&sr->xa, reg, entry) { 172 struct xe_reg_sr_entry hwe_entry = { 173 .reg = RING_FORCE_TO_NONPRIV(hwe->mmio_base, slot), 174 .set_bits = entry->reg.addr | entry->set_bits, 175 .clr_bits = ~0u, 176 .read_mask = entry->read_mask, 177 }; 178 179 if (slot == RING_MAX_NONPRIV_SLOTS) { 180 xe_gt_err(hwe->gt, 181 "hwe %s: maximum register whitelist slots (%d) reached, refusing to add more\n", 182 hwe->name, RING_MAX_NONPRIV_SLOTS); 183 break; 184 } 185 186 xe_reg_whitelist_print_entry(&p, 0, reg, entry); 187 xe_reg_sr_add(&hwe->reg_sr, &hwe_entry, hwe->gt); 188 189 slot++; 190 } 191 } 192 193 /** 194 * xe_reg_whitelist_process_engine - process table of registers to whitelist 195 * @hwe: engine instance to process whitelist for 196 * 197 * Process wwhitelist table for this platform, saving in @hwe all the 198 * registers that need to be whitelisted by the hardware so they can be accessed 199 * by userspace. 200 */ 201 void xe_reg_whitelist_process_engine(struct xe_hw_engine *hwe) 202 { 203 struct xe_rtp_process_ctx ctx = XE_RTP_PROCESS_CTX_INITIALIZER(hwe); 204 205 xe_rtp_process_to_sr(&ctx, register_whitelist, ARRAY_SIZE(register_whitelist), 206 &hwe->reg_whitelist, false); 207 whitelist_apply_to_hwe(hwe); 208 } 209 210 /** 211 * xe_reg_whitelist_print_entry - print one whitelist entry 212 * @p: DRM printer 213 * @indent: indent level 214 * @reg: register allowed/denied 215 * @entry: save-restore entry 216 * 217 * Print details about the entry added to allow/deny access 218 */ 219 void xe_reg_whitelist_print_entry(struct drm_printer *p, unsigned int indent, 220 u32 reg, struct xe_reg_sr_entry *entry) 221 { 222 u32 val = entry->set_bits; 223 const char *access_str = "(invalid)"; 224 unsigned int range_bit = 2; 225 u32 range_start, range_end; 226 bool deny; 227 228 deny = val & RING_FORCE_TO_NONPRIV_DENY; 229 230 switch (val & RING_FORCE_TO_NONPRIV_RANGE_MASK) { 231 case RING_FORCE_TO_NONPRIV_RANGE_4: 232 range_bit = 4; 233 break; 234 case RING_FORCE_TO_NONPRIV_RANGE_16: 235 range_bit = 6; 236 break; 237 case RING_FORCE_TO_NONPRIV_RANGE_64: 238 range_bit = 8; 239 break; 240 } 241 242 range_start = reg & REG_GENMASK(25, range_bit); 243 range_end = range_start | REG_GENMASK(range_bit - 1, 0); 244 245 switch (val & RING_FORCE_TO_NONPRIV_ACCESS_MASK) { 246 case RING_FORCE_TO_NONPRIV_ACCESS_RW: 247 access_str = "rw"; 248 break; 249 case RING_FORCE_TO_NONPRIV_ACCESS_RD: 250 access_str = "read"; 251 break; 252 case RING_FORCE_TO_NONPRIV_ACCESS_WR: 253 access_str = "write"; 254 break; 255 } 256 257 drm_printf_indent(p, indent, "REG[0x%x-0x%x]: %s %s access\n", 258 range_start, range_end, 259 deny ? "deny" : "allow", 260 access_str); 261 } 262 263 /** 264 * xe_reg_whitelist_dump - print all whitelist entries 265 * @sr: Save/restore entries 266 * @p: DRM printer 267 */ 268 void xe_reg_whitelist_dump(struct xe_reg_sr *sr, struct drm_printer *p) 269 { 270 struct xe_reg_sr_entry *entry; 271 unsigned long reg; 272 273 if (!sr->name || xa_empty(&sr->xa)) 274 return; 275 276 drm_printf(p, "%s\n", sr->name); 277 xa_for_each(&sr->xa, reg, entry) 278 xe_reg_whitelist_print_entry(p, 1, reg, entry); 279 } 280