Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'drm-xe-next-2025-02-24' of https://gitlab.freedesktop.org/drm/xe/kernel into drm-next

UAPI Changes:
- Add mmap support for PCI memory barrier (Tejas, Matthew Auld)
- Enable integration with perf pmu, exposing event counters: for now, just
GT C6 residency (Vinay, Lucas)
- Add "survivability mode" to allow putting the driver in a state capable of
firmware upgrade on critical failures (Riana, Rodrigo)
- Add PXP HWDRM support and enable for compatible platforms:
Meteor Lake and Lunar Lake (Daniele, John Harrison)
- Expose package and vram temperature over hwmon subsystem (Raag, Badal, Rodrigo)

Cross-subsystem Changes:
- Backmege drm-next to synchronize with i915 display and other internal APIs

Display Changes (including i915):
- Device probe re-order to help with flicker-free boot (Maarten)
- Align watermark, hpd and dsm with i915 (Rodrigo)
- Better abstraction for d3cold (Rodrigo)

Driver Changes:
- Make sure changes to ccs_mode is with helper for gt sync reset (Maciej)
- Drop mmio_ext abstraction since it didn't prove useful in its current form
(Matt Roper)
- Reject BO eviction if BO is bound to current VM (Oak, Thomas Hellström)
- Add GuC Power Conservation debugfs (Rodrigo)
- L3 cache topology updates for Xe3 (Francois, Matt Atwood)
- Better logging about missing GuC logs (John Harrison)
- Better logging for hwconfig-related data availability (John Harrison)
- Tracepoint updates for xe_bo_create, xe_vm and xe_vma (Oak)
- Add missing SPDX licenses (Francois)
- Xe suballocator imporovements (Michal Wajdeczko)
- Improve logging for native vs SR-IOV driver mode (Satyanarayana)
- Make sure VF bootstrap is not attempted in execlist mode (Maarten)
- Add GuC Buffer Cache abstraction for some CTB H2G actions and use
during VF provisioning (Michal Wajdeczko)
- Better synchronization in gtidle for new users (Vinay)
- New workarounds for Panther Lake (Nirmoy, Vinay)
- PCI ID updates for Panther Lake (Matt Atwood)
- Enable SR-IOV for Panther Lake (Michal Wajdeczko)
- Update MAINTAINERS to stop directing xe changes to drm-misc (Lucas)
- New PCI IDs for Battle Mage (Shekhar)
- Better pagefault logging (Francois)
- SR-IOV fixes and refactors for past and new platforms (Michal Wajdeczko)
- Platform descriptor refactors and updates (Sai Teja)
- Add gt stats debugfs (Francois)
- Add guc_log debugfs to dump to dmesg (Lucas)
- Abstract per-platform LMTT availability (Piotr Piórkowski)
- Refactor VRAM manager location (Piotr Piórkowski)
- Add missing xe_pm_runtime_put when forcing wedged mode (Shuicheng)
- Fix possible lockup when forcing wedged mode (Xin Wang)
- Probe refactors to use cleanup actions with better error handling (Lucas)
- XE_IOCTL_DBG clarification for userspace (Maarten)
- Better xe_mmio initialization and abstraction (Ilia)
- Drop unnecessary GT lookup (Matt Roper)
- Skip client engine usage from fdinfo for VFs (Marcin Bernatowicz)
- Allow to test xe_sync_entry_parse with error injection (Priyanka)
- OA fix for polled read (Umesh)

Signed-off-by: Dave Airlie <airlied@redhat.com>

From: Lucas De Marchi <lucas.demarchi@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/m3gbuh32wgiep43i4zxbyhxqbenvtgvtao5sczivlasj7tikwv@dmlba4bfg2ny

+5167 -690
+16
Documentation/ABI/testing/sysfs-driver-intel-xe-hwmon
··· 108 108 Description: RO. Package current voltage in millivolt. 109 109 110 110 Only supported for particular Intel Xe graphics platforms. 111 + 112 + What: /sys/bus/pci/drivers/xe/.../hwmon/hwmon<i>/temp2_input 113 + Date: March 2025 114 + KernelVersion: 6.14 115 + Contact: intel-xe@lists.freedesktop.org 116 + Description: RO. Package temperature in millidegree Celsius. 117 + 118 + Only supported for particular Intel Xe graphics platforms. 119 + 120 + What: /sys/bus/pci/drivers/xe/.../hwmon/hwmon<i>/temp3_input 121 + Date: March 2025 122 + KernelVersion: 6.14 123 + Contact: intel-xe@lists.freedesktop.org 124 + Description: RO. VRAM temperature in millidegree Celsius. 125 + 126 + Only supported for particular Intel Xe graphics platforms.
+1
MAINTAINERS
··· 7673 7673 X: drivers/gpu/drm/nouveau/ 7674 7674 X: drivers/gpu/drm/radeon/ 7675 7675 X: drivers/gpu/drm/tegra/ 7676 + X: drivers/gpu/drm/xe/ 7676 7677 7677 7678 DRM DRIVERS FOR ALLWINNER A10 7678 7679 M: Maxime Ripard <mripard@kernel.org>
+3 -3
drivers/gpu/drm/i915/display/intel_display.c
··· 685 685 if ((crtc_state->active_planes & ~BIT(PLANE_CURSOR)) == 0 && 686 686 hsw_ips_disable(crtc_state)) { 687 687 crtc_state->ips_enabled = false; 688 - intel_crtc_wait_for_next_vblank(crtc); 688 + intel_plane_initial_vblank_wait(crtc); 689 689 } 690 690 691 691 /* ··· 699 699 */ 700 700 if (HAS_GMCH(dev_priv) && 701 701 intel_set_memory_cxsr(dev_priv, false)) 702 - intel_crtc_wait_for_next_vblank(crtc); 702 + intel_plane_initial_vblank_wait(crtc); 703 703 704 704 /* 705 705 * Gen2 reports pipe underruns whenever all planes are disabled. ··· 709 709 intel_set_cpu_fifo_underrun_reporting(display, crtc->pipe, false); 710 710 711 711 intel_plane_disable_arm(NULL, plane, crtc_state); 712 - intel_crtc_wait_for_next_vblank(crtc); 712 + intel_plane_initial_vblank_wait(crtc); 713 713 } 714 714 715 715 unsigned int
+4
drivers/gpu/drm/i915/display/intel_display_driver.c
··· 564 564 565 565 intel_display_device_info_print(DISPLAY_INFO(display), 566 566 DISPLAY_RUNTIME_INFO(display), &p); 567 + 568 + intel_register_dsm_handler(); 567 569 } 568 570 569 571 /* part #1: call before irq uninstall */ ··· 640 638 { 641 639 if (!HAS_DISPLAY(display)) 642 640 return; 641 + 642 + intel_unregister_dsm_handler(); 643 643 644 644 drm_client_dev_unregister(display->drm); 645 645
+6 -1
drivers/gpu/drm/i915/display/intel_plane_initial.c
··· 14 14 #include "intel_frontbuffer.h" 15 15 #include "intel_plane_initial.h" 16 16 17 + void intel_plane_initial_vblank_wait(struct intel_crtc *crtc) 18 + { 19 + intel_crtc_wait_for_next_vblank(crtc); 20 + } 21 + 17 22 static bool 18 23 intel_reuse_initial_plane_obj(struct intel_crtc *this, 19 24 const struct intel_initial_plane_config plane_configs[], ··· 447 442 intel_find_initial_plane_obj(crtc, plane_configs); 448 443 449 444 if (display->funcs.display->fixup_initial_plane_config(crtc, plane_config)) 450 - intel_crtc_wait_for_next_vblank(crtc); 445 + intel_plane_initial_vblank_wait(crtc); 451 446 452 447 plane_config_fini(plane_config); 453 448 }
+2
drivers/gpu/drm/i915/display/intel_plane_initial.h
··· 6 6 #ifndef __INTEL_PLANE_INITIAL_H__ 7 7 #define __INTEL_PLANE_INITIAL_H__ 8 8 9 + struct intel_crtc; 9 10 struct intel_display; 10 11 11 12 void intel_initial_plane_config(struct intel_display *display); 13 + void intel_plane_initial_vblank_wait(struct intel_crtc *crtc); 12 14 13 15 #endif
-5
drivers/gpu/drm/i915/i915_driver.c
··· 46 46 #include <drm/drm_probe_helper.h> 47 47 48 48 #include "display/i9xx_display_sr.h" 49 - #include "display/intel_acpi.h" 50 49 #include "display/intel_bw.h" 51 50 #include "display/intel_cdclk.h" 52 51 #include "display/intel_crtc.h" ··· 656 657 intel_power_domains_enable(display); 657 658 intel_runtime_pm_enable(&dev_priv->runtime_pm); 658 659 659 - intel_register_dsm_handler(); 660 - 661 660 if (i915_switcheroo_register(dev_priv)) 662 661 drm_err(&dev_priv->drm, "Failed to register vga switcheroo!\n"); 663 662 } ··· 671 674 unsigned int i; 672 675 673 676 i915_switcheroo_unregister(dev_priv); 674 - 675 - intel_unregister_dsm_handler(); 676 677 677 678 intel_runtime_pm_disable(&dev_priv->runtime_pm); 678 679 intel_power_domains_disable(display);
+1
drivers/gpu/drm/xe/Kconfig.profile
··· 1 + # SPDX-License-Identifier: GPL-2.0-only 1 2 config DRM_XE_JOB_TIMEOUT_MAX 2 3 int "Default max job timeout (ms)" 3 4 default 10000 # milliseconds
+13 -6
drivers/gpu/drm/xe/Makefile
··· 34 34 xe_dma_buf.o \ 35 35 xe_drm_client.o \ 36 36 xe_exec.o \ 37 - xe_execlist.o \ 38 37 xe_exec_queue.o \ 38 + xe_execlist.o \ 39 39 xe_force_wake.o \ 40 40 xe_ggtt.o \ 41 41 xe_gpu_scheduler.o \ ··· 56 56 xe_gt_topology.o \ 57 57 xe_guc.o \ 58 58 xe_guc_ads.o \ 59 + xe_guc_buf.o \ 59 60 xe_guc_capture.o \ 60 61 xe_guc_ct.o \ 61 62 xe_guc_db_mgr.o \ ··· 67 66 xe_guc_pc.o \ 68 67 xe_guc_submit.o \ 69 68 xe_heci_gsc.o \ 69 + xe_huc.o \ 70 70 xe_hw_engine.o \ 71 71 xe_hw_engine_class_sysfs.o \ 72 72 xe_hw_engine_group.o \ 73 73 xe_hw_fence.o \ 74 - xe_huc.o \ 75 74 xe_irq.o \ 76 75 xe_lrc.o \ 77 76 xe_migrate.o \ ··· 87 86 xe_preempt_fence.o \ 88 87 xe_pt.o \ 89 88 xe_pt_walk.o \ 89 + xe_pxp.o \ 90 + xe_pxp_debugfs.o \ 91 + xe_pxp_submit.o \ 90 92 xe_query.o \ 91 93 xe_range_fence.o \ 92 94 xe_reg_sr.o \ 93 95 xe_reg_whitelist.o \ 94 - xe_rtp.o \ 95 96 xe_ring_ops.o \ 97 + xe_rtp.o \ 96 98 xe_sa.o \ 97 99 xe_sched_job.o \ 98 100 xe_step.o \ 101 + xe_survivability_mode.o \ 99 102 xe_sync.o \ 100 103 xe_tile.o \ 101 104 xe_tile_sysfs.o \ ··· 107 102 xe_trace_bo.o \ 108 103 xe_trace_guc.o \ 109 104 xe_trace_lrc.o \ 110 - xe_ttm_sys_mgr.o \ 111 105 xe_ttm_stolen_mgr.o \ 106 + xe_ttm_sys_mgr.o \ 112 107 xe_ttm_vram_mgr.o \ 113 108 xe_tuning.o \ 114 109 xe_uc.o \ ··· 117 112 xe_vram.o \ 118 113 xe_vram_freq.o \ 119 114 xe_vsec.o \ 120 - xe_wait_user_fence.o \ 121 115 xe_wa.o \ 116 + xe_wait_user_fence.o \ 122 117 xe_wopcm.o 123 118 124 119 xe-$(CONFIG_HMM_MIRROR) += xe_hmm.o 125 120 126 121 # graphics hardware monitoring (HWMON) support 127 122 xe-$(CONFIG_HWMON) += xe_hwmon.o 123 + 124 + xe-$(CONFIG_PERF_EVENTS) += xe_pmu.o 128 125 129 126 # graphics virtualization (SR-IOV) support 130 127 xe-y += \ ··· 229 222 i915-display/intel_display_wa.o \ 230 223 i915-display/intel_dkl_phy.o \ 231 224 i915-display/intel_dmc.o \ 225 + i915-display/intel_dmc_wl.o \ 232 226 i915-display/intel_dp.o \ 233 227 i915-display/intel_dp_aux.o \ 234 228 i915-display/intel_dp_aux_backlight.o \ ··· 278 270 i915-display/intel_vdsc.o \ 279 271 i915-display/intel_vga.o \ 280 272 i915-display/intel_vrr.o \ 281 - i915-display/intel_dmc_wl.o \ 282 273 i915-display/intel_wm.o \ 283 274 i915-display/skl_scaler.o \ 284 275 i915-display/skl_universal_plane.o \
+41
drivers/gpu/drm/xe/abi/gsc_pxp_commands_abi.h
··· 6 6 #ifndef _ABI_GSC_PXP_COMMANDS_ABI_H 7 7 #define _ABI_GSC_PXP_COMMANDS_ABI_H 8 8 9 + #include <linux/sizes.h> 9 10 #include <linux/types.h> 10 11 11 12 /* Heci client ID for PXP commands */ 12 13 #define HECI_MEADDRESS_PXP 17 13 14 14 15 #define PXP_APIVER(x, y) (((x) & 0xFFFF) << 16 | ((y) & 0xFFFF)) 16 + 17 + /* 18 + * A PXP sub-section in an HECI packet can be up to 64K big in each direction. 19 + * This does not include the top-level GSC header. 20 + */ 21 + #define PXP_MAX_PACKET_SIZE SZ_64K 15 22 16 23 /* 17 24 * there are a lot of status codes for PXP, but we only define the cross-API ··· 31 24 PXP_STATUS_NOT_READY = 0x100e, 32 25 PXP_STATUS_PLATFCONFIG_KF1_NOVERIF = 0x101a, 33 26 PXP_STATUS_PLATFCONFIG_KF1_BAD = 0x101f, 27 + PXP_STATUS_PLATFCONFIG_FIXED_KF1_NOT_SUPPORTED = 0x1037, 34 28 PXP_STATUS_OP_NOT_PERMITTED = 0x4013 35 29 }; 36 30 ··· 50 42 u32 buffer_len; 51 43 } __packed; 52 44 45 + #define PXP43_CMDID_INVALIDATE_STREAM_KEY 0x00000007 46 + #define PXP43_CMDID_INIT_SESSION 0x00000036 53 47 #define PXP43_CMDID_NEW_HUC_AUTH 0x0000003F /* MTL+ */ 54 48 55 49 /* PXP-Input-Packet: HUC Auth-only */ ··· 66 56 struct pxp_cmd_header header; 67 57 } __packed; 68 58 59 + /* PXP-Input-Packet: Init PXP session */ 60 + struct pxp43_create_arb_in { 61 + struct pxp_cmd_header header; 62 + /* header.stream_id fields for vesion 4.3 of Init PXP session: */ 63 + #define PXP43_INIT_SESSION_VALID BIT(0) 64 + #define PXP43_INIT_SESSION_APPTYPE BIT(1) 65 + #define PXP43_INIT_SESSION_APPID GENMASK(17, 2) 66 + u32 protection_mode; 67 + #define PXP43_INIT_SESSION_PROTECTION_ARB 0x2 68 + u32 sub_session_id; 69 + u32 init_flags; 70 + u32 rsvd[12]; 71 + } __packed; 72 + 73 + /* PXP-Input-Packet: Init PXP session */ 74 + struct pxp43_create_arb_out { 75 + struct pxp_cmd_header header; 76 + u32 rsvd[8]; 77 + } __packed; 78 + 79 + /* PXP-Input-Packet: Invalidate Stream Key */ 80 + struct pxp43_inv_stream_key_in { 81 + struct pxp_cmd_header header; 82 + u32 rsvd[3]; 83 + } __packed; 84 + 85 + /* PXP-Output-Packet: Invalidate Stream Key */ 86 + struct pxp43_inv_stream_key_out { 87 + struct pxp_cmd_header header; 88 + u32 rsvd; 89 + } __packed; 69 90 #endif
+5
drivers/gpu/drm/xe/compat-i915-headers/gem/i915_gem_stolen.h
··· 1 + /* SPDX-License-Identifier: MIT */ 2 + /* 3 + * Copyright © 2024 Intel Corporation 4 + */ 5 + 1 6 #ifndef _I915_GEM_STOLEN_H_ 2 7 #define _I915_GEM_STOLEN_H_ 3 8
+14 -4
drivers/gpu/drm/xe/compat-i915-headers/pxp/intel_pxp.h
··· 9 9 #include <linux/errno.h> 10 10 #include <linux/types.h> 11 11 12 - struct drm_gem_object; 13 - struct intel_pxp; 12 + #include "xe_pxp.h" 14 13 15 - static inline int intel_pxp_key_check(struct intel_pxp *pxp, 14 + struct drm_gem_object; 15 + struct xe_pxp; 16 + 17 + static inline int intel_pxp_key_check(struct xe_pxp *pxp, 16 18 struct drm_gem_object *obj, 17 19 bool assign) 18 20 { 19 - return -ENODEV; 21 + /* 22 + * The assign variable is used in i915 to assign the key to the BO at 23 + * first submission time. In Xe the key is instead assigned at BO 24 + * creation time, so the assign variable must always be false. 25 + */ 26 + if (assign) 27 + return -EINVAL; 28 + 29 + return xe_pxp_obj_key_check(pxp, obj); 20 30 } 21 31 22 32 #endif
+1 -1
drivers/gpu/drm/xe/display/intel_bo.c
··· 25 25 26 26 bool intel_bo_is_protected(struct drm_gem_object *obj) 27 27 { 28 - return false; 28 + return xe_bo_is_protected(gem_to_xe_bo(obj)); 29 29 } 30 30 31 31 void intel_bo_flush_if_display(struct drm_gem_object *obj)
+2 -2
drivers/gpu/drm/xe/display/intel_fb_bo.c
··· 50 50 /* 51 51 * XE_BO_FLAG_SCANOUT should ideally be set at creation, or is 52 52 * automatically set when creating FB. We cannot change caching 53 - * mode when the boect is VM_BINDed, so we can only set 53 + * mode when the bo is VM_BINDed, so we can only set 54 54 * coherency with display when unbound. 55 55 */ 56 - if (XE_IOCTL_DBG(xe, !list_empty(&bo->ttm.base.gpuva.list))) { 56 + if (XE_IOCTL_DBG(xe, xe_bo_is_vm_bound(bo))) { 57 57 ttm_bo_unreserve(&bo->ttm); 58 58 ret = -EINVAL; 59 59 goto err;
+90 -91
drivers/gpu/drm/xe/display/xe_display.c
··· 29 29 #include "intel_hdcp.h" 30 30 #include "intel_hotplug.h" 31 31 #include "intel_opregion.h" 32 + #include "skl_watermark.h" 32 33 #include "xe_module.h" 33 34 34 35 /* Xe device functions */ ··· 102 101 return drmm_add_action_or_reset(&xe->drm, display_destroy, NULL); 103 102 } 104 103 105 - static void xe_display_fini_nommio(struct drm_device *dev, void *dummy) 104 + static void xe_display_fini_early(void *arg) 106 105 { 107 - struct xe_device *xe = to_xe_device(dev); 106 + struct xe_device *xe = arg; 108 107 struct intel_display *display = &xe->display; 109 108 110 109 if (!xe->info.probe_display) 111 110 return; 112 111 112 + intel_display_driver_remove_nogem(display); 113 + intel_display_driver_remove_noirq(display); 114 + intel_opregion_cleanup(display); 113 115 intel_power_domains_cleanup(display); 114 116 } 115 117 116 - int xe_display_init_nommio(struct xe_device *xe) 118 + int xe_display_init_early(struct xe_device *xe) 117 119 { 120 + struct intel_display *display = &xe->display; 121 + int err; 122 + 118 123 if (!xe->info.probe_display) 119 124 return 0; 120 125 ··· 129 122 130 123 /* This must be called before any calls to HAS_PCH_* */ 131 124 intel_detect_pch(xe); 132 - 133 - return drmm_add_action_or_reset(&xe->drm, xe_display_fini_nommio, xe); 134 - } 135 - 136 - static void xe_display_fini_noirq(void *arg) 137 - { 138 - struct xe_device *xe = arg; 139 - struct intel_display *display = &xe->display; 140 - 141 - if (!xe->info.probe_display) 142 - return; 143 - 144 - intel_display_driver_remove_noirq(display); 145 - intel_opregion_cleanup(display); 146 - } 147 - 148 - int xe_display_init_noirq(struct xe_device *xe) 149 - { 150 - struct intel_display *display = &xe->display; 151 - int err; 152 - 153 - if (!xe->info.probe_display) 154 - return 0; 155 125 156 126 intel_display_driver_early_probe(display); 157 127 ··· 146 162 intel_display_device_info_runtime_init(display); 147 163 148 164 err = intel_display_driver_probe_noirq(display); 149 - if (err) { 150 - intel_opregion_cleanup(display); 151 - return err; 152 - } 165 + if (err) 166 + goto err_opregion; 153 167 154 - return devm_add_action_or_reset(xe->drm.dev, xe_display_fini_noirq, xe); 168 + err = intel_display_driver_probe_nogem(display); 169 + if (err) 170 + goto err_noirq; 171 + 172 + return devm_add_action_or_reset(xe->drm.dev, xe_display_fini_early, xe); 173 + err_noirq: 174 + intel_display_driver_remove_noirq(display); 175 + intel_power_domains_cleanup(display); 176 + err_opregion: 177 + intel_opregion_cleanup(display); 178 + return err; 155 179 } 156 180 157 - static void xe_display_fini_noaccel(void *arg) 181 + static void xe_display_fini(void *arg) 158 182 { 159 183 struct xe_device *xe = arg; 160 184 struct intel_display *display = &xe->display; 161 185 162 - if (!xe->info.probe_display) 163 - return; 164 - 165 - intel_display_driver_remove_nogem(display); 186 + intel_hpd_poll_fini(xe); 187 + intel_hdcp_component_fini(display); 188 + intel_audio_deinit(display); 166 189 } 167 190 168 - int xe_display_init_noaccel(struct xe_device *xe) 191 + int xe_display_init(struct xe_device *xe) 169 192 { 170 193 struct intel_display *display = &xe->display; 171 194 int err; ··· 180 189 if (!xe->info.probe_display) 181 190 return 0; 182 191 183 - err = intel_display_driver_probe_nogem(display); 192 + err = intel_display_driver_probe(display); 184 193 if (err) 185 194 return err; 186 195 187 - return devm_add_action_or_reset(xe->drm.dev, xe_display_fini_noaccel, xe); 188 - } 189 - 190 - int xe_display_init(struct xe_device *xe) 191 - { 192 - struct intel_display *display = &xe->display; 193 - 194 - if (!xe->info.probe_display) 195 - return 0; 196 - 197 - return intel_display_driver_probe(display); 198 - } 199 - 200 - void xe_display_fini(struct xe_device *xe) 201 - { 202 - struct intel_display *display = &xe->display; 203 - 204 - if (!xe->info.probe_display) 205 - return; 206 - 207 - intel_hpd_poll_fini(xe); 208 - 209 - intel_hdcp_component_fini(display); 210 - intel_audio_deinit(display); 196 + return xe_device_add_action_or_reset(xe, xe_display_fini, xe); 211 197 } 212 198 213 199 void xe_display_register(struct xe_device *xe) ··· 196 228 197 229 intel_display_driver_register(display); 198 230 intel_power_domains_enable(display); 199 - intel_register_dsm_handler(); 200 231 } 201 232 202 233 void xe_display_unregister(struct xe_device *xe) ··· 205 238 if (!xe->info.probe_display) 206 239 return; 207 240 208 - intel_unregister_dsm_handler(); 209 241 intel_power_domains_disable(display); 210 242 intel_display_driver_unregister(display); 211 243 } ··· 288 322 } 289 323 } 290 324 291 - /* TODO: System and runtime suspend/resume sequences will be sanitized as a follow-up. */ 292 - static void __xe_display_pm_suspend(struct xe_device *xe, bool runtime) 325 + static void xe_display_enable_d3cold(struct xe_device *xe) 293 326 { 294 327 struct intel_display *display = &xe->display; 295 - bool s2idle = suspend_to_idle(); 328 + 296 329 if (!xe->info.probe_display) 297 330 return; 298 331 ··· 300 335 * properly. 301 336 */ 302 337 intel_power_domains_disable(display); 303 - if (!runtime) 304 - intel_fbdev_set_suspend(&xe->drm, FBINFO_STATE_SUSPENDED, true); 305 338 306 - if (!runtime && has_display(xe)) { 339 + xe_display_flush_cleanup_work(xe); 340 + 341 + intel_opregion_suspend(display, PCI_D3cold); 342 + 343 + intel_dmc_suspend(display); 344 + 345 + if (has_display(xe)) 346 + intel_hpd_poll_enable(xe); 347 + } 348 + 349 + static void xe_display_disable_d3cold(struct xe_device *xe) 350 + { 351 + struct intel_display *display = &xe->display; 352 + 353 + if (!xe->info.probe_display) 354 + return; 355 + 356 + intel_dmc_resume(display); 357 + 358 + if (has_display(xe)) 359 + drm_mode_config_reset(&xe->drm); 360 + 361 + intel_display_driver_init_hw(display); 362 + 363 + intel_hpd_init(xe); 364 + 365 + if (has_display(xe)) 366 + intel_hpd_poll_disable(xe); 367 + 368 + intel_opregion_resume(display); 369 + 370 + intel_power_domains_enable(display); 371 + } 372 + 373 + void xe_display_pm_suspend(struct xe_device *xe) 374 + { 375 + struct intel_display *display = &xe->display; 376 + bool s2idle = suspend_to_idle(); 377 + 378 + if (!xe->info.probe_display) 379 + return; 380 + 381 + /* 382 + * We do a lot of poking in a lot of registers, make sure they work 383 + * properly. 384 + */ 385 + intel_power_domains_disable(display); 386 + intel_fbdev_set_suspend(&xe->drm, FBINFO_STATE_SUSPENDED, true); 387 + 388 + if (has_display(xe)) { 307 389 drm_kms_helper_poll_disable(&xe->drm); 308 390 intel_display_driver_disable_user_access(display); 309 391 intel_display_driver_suspend(display); ··· 360 348 361 349 intel_hpd_cancel_work(xe); 362 350 363 - if (!runtime && has_display(xe)) { 351 + if (has_display(xe)) { 364 352 intel_display_driver_suspend_access(display); 365 353 intel_encoder_suspend_all(&xe->display); 366 354 } ··· 368 356 intel_opregion_suspend(display, s2idle ? PCI_D1 : PCI_D3cold); 369 357 370 358 intel_dmc_suspend(display); 371 - 372 - if (runtime && has_display(xe)) 373 - intel_hpd_poll_enable(xe); 374 - } 375 - 376 - void xe_display_pm_suspend(struct xe_device *xe) 377 - { 378 - __xe_display_pm_suspend(xe, false); 379 359 } 380 360 381 361 void xe_display_pm_shutdown(struct xe_device *xe) ··· 406 402 return; 407 403 408 404 if (xe->d3cold.allowed) { 409 - __xe_display_pm_suspend(xe, true); 405 + xe_display_enable_d3cold(xe); 410 406 return; 411 407 } 412 408 ··· 467 463 intel_display_power_resume_early(display); 468 464 } 469 465 470 - static void __xe_display_pm_resume(struct xe_device *xe, bool runtime) 466 + void xe_display_pm_resume(struct xe_device *xe) 471 467 { 472 468 struct intel_display *display = &xe->display; 473 469 ··· 481 477 482 478 intel_display_driver_init_hw(display); 483 479 484 - if (!runtime && has_display(xe)) 480 + if (has_display(xe)) 485 481 intel_display_driver_resume_access(display); 486 482 487 483 intel_hpd_init(xe); 488 484 489 - if (!runtime && has_display(xe)) { 485 + if (has_display(xe)) { 490 486 intel_display_driver_resume(display); 491 487 drm_kms_helper_poll_enable(&xe->drm); 492 488 intel_display_driver_enable_user_access(display); ··· 497 493 498 494 intel_opregion_resume(display); 499 495 500 - if (!runtime) 501 - intel_fbdev_set_suspend(&xe->drm, FBINFO_STATE_RUNNING, false); 496 + intel_fbdev_set_suspend(&xe->drm, FBINFO_STATE_RUNNING, false); 502 497 503 498 intel_power_domains_enable(display); 504 - } 505 - 506 - void xe_display_pm_resume(struct xe_device *xe) 507 - { 508 - __xe_display_pm_resume(xe, false); 509 499 } 510 500 511 501 void xe_display_pm_runtime_resume(struct xe_device *xe) ··· 508 510 return; 509 511 510 512 if (xe->d3cold.allowed) { 511 - __xe_display_pm_resume(xe, true); 513 + xe_display_disable_d3cold(xe); 512 514 return; 513 515 } 514 516 515 517 intel_hpd_init(xe); 516 518 intel_hpd_poll_disable(xe); 519 + skl_watermark_ipc_update(xe); 517 520 } 518 521 519 522
+2 -8
drivers/gpu/drm/xe/display/xe_display.h
··· 20 20 21 21 int xe_display_probe(struct xe_device *xe); 22 22 23 - int xe_display_init_nommio(struct xe_device *xe); 24 - int xe_display_init_noirq(struct xe_device *xe); 25 - int xe_display_init_noaccel(struct xe_device *xe); 23 + int xe_display_init_early(struct xe_device *xe); 26 24 int xe_display_init(struct xe_device *xe); 27 - void xe_display_fini(struct xe_device *xe); 28 25 29 26 void xe_display_register(struct xe_device *xe); 30 27 void xe_display_unregister(struct xe_device *xe); ··· 51 54 52 55 static inline int xe_display_probe(struct xe_device *xe) { return 0; } 53 56 54 - static inline int xe_display_init_nommio(struct xe_device *xe) { return 0; } 55 - static inline int xe_display_init_noirq(struct xe_device *xe) { return 0; } 56 - static inline int xe_display_init_noaccel(struct xe_device *xe) { return 0; } 57 + static inline int xe_display_init_early(struct xe_device *xe) { return 0; } 57 58 static inline int xe_display_init(struct xe_device *xe) { return 0; } 58 - static inline void xe_display_fini(struct xe_device *xe) {} 59 59 60 60 static inline void xe_display_register(struct xe_device *xe) {} 61 61 static inline void xe_display_unregister(struct xe_device *xe) {}
+18 -1
drivers/gpu/drm/xe/display/xe_plane_initial.c
··· 8 8 9 9 #include "regs/xe_gtt_defs.h" 10 10 #include "xe_ggtt.h" 11 + #include "xe_mmio.h" 11 12 13 + #include "i915_reg.h" 12 14 #include "intel_atomic_plane.h" 13 15 #include "intel_crtc.h" 14 16 #include "intel_display.h" ··· 23 21 #include "xe_wa.h" 24 22 25 23 #include <generated/xe_wa_oob.h> 24 + 25 + void intel_plane_initial_vblank_wait(struct intel_crtc *crtc) 26 + { 27 + /* Early xe has no irq */ 28 + struct xe_device *xe = to_xe_device(crtc->base.dev); 29 + struct xe_reg pipe_frmtmstmp = XE_REG(i915_mmio_reg_offset(PIPE_FRMTMSTMP(crtc->pipe))); 30 + u32 timestamp; 31 + int ret; 32 + 33 + timestamp = xe_mmio_read32(xe_root_tile_mmio(xe), pipe_frmtmstmp); 34 + 35 + ret = xe_mmio_wait32_not(xe_root_tile_mmio(xe), pipe_frmtmstmp, ~0U, timestamp, 40000U, &timestamp, false); 36 + if (ret < 0) 37 + drm_warn(&xe->drm, "waiting for early vblank failed with %i\n", ret); 38 + } 26 39 27 40 static bool 28 41 intel_reuse_initial_plane_obj(struct intel_crtc *this, ··· 310 293 intel_find_initial_plane_obj(crtc, plane_configs); 311 294 312 295 if (display->funcs.display->fixup_initial_plane_config(crtc, plane_config)) 313 - intel_crtc_wait_for_next_vblank(crtc); 296 + intel_plane_initial_vblank_wait(crtc); 314 297 315 298 plane_config_fini(plane_config); 316 299 }
+1
drivers/gpu/drm/xe/instructions/xe_instr_defs.h
··· 16 16 #define XE_INSTR_CMD_TYPE GENMASK(31, 29) 17 17 #define XE_INSTR_MI REG_FIELD_PREP(XE_INSTR_CMD_TYPE, 0x0) 18 18 #define XE_INSTR_GSC REG_FIELD_PREP(XE_INSTR_CMD_TYPE, 0x2) 19 + #define XE_INSTR_VIDEOPIPE REG_FIELD_PREP(XE_INSTR_CMD_TYPE, 0x3) 19 20 #define XE_INSTR_GFXPIPE REG_FIELD_PREP(XE_INSTR_CMD_TYPE, 0x3) 20 21 #define XE_INSTR_GFX_STATE REG_FIELD_PREP(XE_INSTR_CMD_TYPE, 0x4) 21 22
+28
drivers/gpu/drm/xe/instructions/xe_mfx_commands.h
··· 1 + /* SPDX-License-Identifier: MIT */ 2 + /* 3 + * Copyright © 2024 Intel Corporation 4 + */ 5 + 6 + #ifndef _XE_MFX_COMMANDS_H_ 7 + #define _XE_MFX_COMMANDS_H_ 8 + 9 + #include "instructions/xe_instr_defs.h" 10 + 11 + #define MFX_CMD_SUBTYPE REG_GENMASK(28, 27) /* A.K.A cmd pipe */ 12 + #define MFX_CMD_OPCODE REG_GENMASK(26, 24) 13 + #define MFX_CMD_SUB_OPCODE REG_GENMASK(23, 16) 14 + #define MFX_FLAGS_AND_LEN REG_GENMASK(15, 0) 15 + 16 + #define XE_MFX_INSTR(subtype, op, sub_op) \ 17 + (XE_INSTR_VIDEOPIPE | \ 18 + REG_FIELD_PREP(MFX_CMD_SUBTYPE, subtype) | \ 19 + REG_FIELD_PREP(MFX_CMD_OPCODE, op) | \ 20 + REG_FIELD_PREP(MFX_CMD_SUB_OPCODE, sub_op)) 21 + 22 + #define MFX_WAIT XE_MFX_INSTR(1, 0, 0) 23 + #define MFX_WAIT_DW0_PXP_SYNC_CONTROL_FLAG REG_BIT(9) 24 + #define MFX_WAIT_DW0_MFX_SYNC_CONTROL_FLAG REG_BIT(8) 25 + 26 + #define CRYPTO_KEY_EXCHANGE XE_MFX_INSTR(2, 6, 9) 27 + 28 + #endif
+5
drivers/gpu/drm/xe/instructions/xe_mi_commands.h
··· 48 48 #define MI_LRI_LEN(x) (((x) & 0xff) + 1) 49 49 50 50 #define MI_FLUSH_DW __MI_INSTR(0x26) 51 + #define MI_FLUSH_DW_PROTECTED_MEM_EN REG_BIT(22) 51 52 #define MI_FLUSH_DW_STORE_INDEX REG_BIT(21) 52 53 #define MI_INVALIDATE_TLB REG_BIT(18) 53 54 #define MI_FLUSH_DW_CCS REG_BIT(16) ··· 66 65 #define MI_COPY_MEM_MEM_DST_GGTT REG_BIT(21) 67 66 68 67 #define MI_BATCH_BUFFER_START __MI_INSTR(0x31) 68 + 69 + #define MI_SET_APPID __MI_INSTR(0x0e) 70 + #define MI_SET_APPID_SESSION_ID_MASK REG_GENMASK(6, 0) 71 + #define MI_SET_APPID_SESSION_ID(x) REG_FIELD_PREP(MI_SET_APPID_SESSION_ID_MASK, x) 69 72 70 73 #endif
+1
drivers/gpu/drm/xe/regs/xe_engine_regs.h
··· 132 132 #define RING_EXECLIST_STATUS_HI(base) XE_REG((base) + 0x234 + 4) 133 133 134 134 #define RING_CONTEXT_CONTROL(base) XE_REG((base) + 0x244, XE_REG_OPTION_MASKED) 135 + #define CTX_CTRL_PXP_ENABLE REG_BIT(10) 135 136 #define CTX_CTRL_OAC_CONTEXT_ENABLE REG_BIT(8) 136 137 #define CTX_CTRL_RUN_ALONE REG_BIT(7) 137 138 #define CTX_CTRL_INDIRECT_RING_STATE_ENABLE REG_BIT(4)
+6
drivers/gpu/drm/xe/regs/xe_gt_regs.h
··· 221 221 222 222 #define MIRROR_FUSE1 XE_REG(0x911c) 223 223 224 + #define MIRROR_L3BANK_ENABLE XE_REG(0x9130) 225 + #define XE3_L3BANK_ENABLE REG_GENMASK(31, 0) 226 + 224 227 #define XELP_EU_ENABLE XE_REG(0x9134) /* "_DISABLE" on Xe_LP */ 225 228 #define XELP_EU_MASK REG_GENMASK(7, 0) 226 229 #define XELP_GT_SLICE_ENABLE XE_REG(0x9138) ··· 502 499 #define XEHP_HDC_CHICKEN0 XE_REG_MCR(0xe5f0, XE_REG_OPTION_MASKED) 503 500 #define LSC_L1_FLUSH_CTL_3D_DATAPORT_FLUSH_EVENTS_MASK REG_GENMASK(13, 11) 504 501 #define DIS_ATOMIC_CHAINING_TYPED_WRITES REG_BIT(3) 502 + 503 + #define TDL_CHICKEN XE_REG_MCR(0xe5f4, XE_REG_OPTION_MASKED) 504 + #define QID_WAIT_FOR_THREAD_NOT_RUN_DISABLE REG_BIT(12) 505 505 506 506 #define LSC_CHICKEN_BIT_0 XE_REG_MCR(0xe7c8) 507 507 #define DISABLE_D8_D16_COASLESCE REG_BIT(30)
+8
drivers/gpu/drm/xe/regs/xe_irq_regs.h
··· 44 44 #define ENGINE1_MASK REG_GENMASK(31, 16) 45 45 #define ENGINE0_MASK REG_GENMASK(15, 0) 46 46 #define GPM_WGBOXPERF_INTR_ENABLE XE_REG(0x19003c, XE_REG_OPTION_VF) 47 + #define CRYPTO_RSVD_INTR_ENABLE XE_REG(0x190040) 47 48 #define GUNIT_GSC_INTR_ENABLE XE_REG(0x190044, XE_REG_OPTION_VF) 48 49 #define CCS_RSVD_INTR_ENABLE XE_REG(0x190048, XE_REG_OPTION_VF) 49 50 ··· 55 54 #define INTR_ENGINE_INTR(x) REG_FIELD_GET(GENMASK(15, 0), x) 56 55 #define OTHER_GUC_INSTANCE 0 57 56 #define OTHER_GSC_HECI2_INSTANCE 3 57 + #define OTHER_KCR_INSTANCE 4 58 58 #define OTHER_GSC_INSTANCE 6 59 59 60 60 #define IIR_REG_SELECTOR(x) XE_REG(0x190070 + ((x) * 4), XE_REG_OPTION_VF) ··· 67 65 #define HECI2_RSVD_INTR_MASK XE_REG(0x1900e4) 68 66 #define GUC_SG_INTR_MASK XE_REG(0x1900e8, XE_REG_OPTION_VF) 69 67 #define GPM_WGBOXPERF_INTR_MASK XE_REG(0x1900ec, XE_REG_OPTION_VF) 68 + #define CRYPTO_RSVD_INTR_MASK XE_REG(0x1900f0) 70 69 #define GUNIT_GSC_INTR_MASK XE_REG(0x1900f4, XE_REG_OPTION_VF) 71 70 #define CCS0_CCS1_INTR_MASK XE_REG(0x190100) 72 71 #define CCS2_CCS3_INTR_MASK XE_REG(0x190104) ··· 81 78 #define GT_RENDER_PIPECTL_NOTIFY_INTERRUPT REG_BIT(4) 82 79 #define GT_CS_MASTER_ERROR_INTERRUPT REG_BIT(3) 83 80 #define GT_RENDER_USER_INTERRUPT REG_BIT(0) 81 + 82 + /* irqs for OTHER_KCR_INSTANCE */ 83 + #define KCR_PXP_STATE_TERMINATED_INTERRUPT REG_BIT(1) 84 + #define KCR_APP_TERMINATED_PER_FW_REQ_INTERRUPT REG_BIT(2) 85 + #define KCR_PXP_STATE_RESET_COMPLETE_INTERRUPT REG_BIT(3) 84 86 85 87 #endif
+3
drivers/gpu/drm/xe/regs/xe_mchbar_regs.h
··· 34 34 35 35 #define PCU_CR_PACKAGE_ENERGY_STATUS XE_REG(MCHBAR_MIRROR_BASE_SNB + 0x593c) 36 36 37 + #define PCU_CR_PACKAGE_TEMPERATURE XE_REG(MCHBAR_MIRROR_BASE_SNB + 0x5978) 38 + #define TEMP_MASK REG_GENMASK(7, 0) 39 + 37 40 #define PCU_CR_PACKAGE_RAPL_LIMIT XE_REG(MCHBAR_MIRROR_BASE_SNB + 0x59a0) 38 41 #define PKG_PWR_LIM_1 REG_GENMASK(14, 0) 39 42 #define PKG_PWR_LIM_1_EN REG_BIT(15)
+2
drivers/gpu/drm/xe/regs/xe_pcode_regs.h
··· 21 21 #define BMG_PACKAGE_POWER_SKU XE_REG(0x138098) 22 22 #define BMG_PACKAGE_POWER_SKU_UNIT XE_REG(0x1380dc) 23 23 #define BMG_PACKAGE_ENERGY_STATUS XE_REG(0x138120) 24 + #define BMG_VRAM_TEMPERATURE XE_REG(0x1382c0) 25 + #define BMG_PACKAGE_TEMPERATURE XE_REG(0x138434) 24 26 #define BMG_PACKAGE_RAPL_LIMIT XE_REG(0x138440) 25 27 #define BMG_PLATFORM_ENERGY_STATUS XE_REG(0x138458) 26 28 #define BMG_PLATFORM_POWER_LIMIT XE_REG(0x138460)
+23
drivers/gpu/drm/xe/regs/xe_pxp_regs.h
··· 1 + /* SPDX-License-Identifier: MIT */ 2 + /* 3 + * Copyright(c) 2024, Intel Corporation. All rights reserved. 4 + */ 5 + 6 + #ifndef __XE_PXP_REGS_H__ 7 + #define __XE_PXP_REGS_H__ 8 + 9 + #include "regs/xe_regs.h" 10 + 11 + /* The following registers are only valid on platforms with a media GT */ 12 + 13 + /* KCR enable/disable control */ 14 + #define KCR_INIT XE_REG(0x3860f0) 15 + #define KCR_INIT_ALLOW_DISPLAY_ME_WRITES REG_BIT(14) 16 + 17 + /* KCR hwdrm session in play status 0-31 */ 18 + #define KCR_SIP XE_REG(0x386260) 19 + 20 + /* PXP global terminate register for session termination */ 21 + #define KCR_GLOBAL_TERMINATE XE_REG(0x3860f8) 22 + 23 + #endif /* __XE_PXP_REGS_H__ */
+13 -15
drivers/gpu/drm/xe/regs/xe_reg_defs.h
··· 7 7 #define _XE_REG_DEFS_H_ 8 8 9 9 #include <linux/build_bug.h> 10 + #include <linux/log2.h> 11 + #include <linux/sizes.h> 10 12 11 13 #include "compat-i915-headers/i915_reg_defs.h" 14 + 15 + /** 16 + * XE_REG_ADDR_MAX - The upper limit on MMIO register address 17 + * 18 + * This macro specifies the upper limit (not inclusive) on MMIO register offset 19 + * supported by struct xe_reg and functions based on struct xe_mmio. 20 + * 21 + * Currently this is defined as 4 MiB. 22 + */ 23 + #define XE_REG_ADDR_MAX SZ_4M 12 24 13 25 /** 14 26 * struct xe_reg - Register definition ··· 33 21 union { 34 22 struct { 35 23 /** @addr: address */ 36 - u32 addr:28; 24 + u32 addr:const_ilog2(XE_REG_ADDR_MAX); 37 25 /** 38 26 * @masked: register is "masked", with upper 16bits used 39 27 * to identify the bits that are updated on the lower ··· 53 41 * @vf: register is accessible from the Virtual Function. 54 42 */ 55 43 u32 vf:1; 56 - /** 57 - * @ext: access MMIO extension space for current register. 58 - */ 59 - u32 ext:1; 60 44 }; 61 45 /** @raw: Raw value with both address and options */ 62 46 u32 raw; ··· 118 110 * options. 119 111 */ 120 112 #define XE_REG(r_, ...) ((const struct xe_reg)XE_REG_INITIALIZER(r_, ##__VA_ARGS__)) 121 - 122 - /** 123 - * XE_REG_EXT - Create a struct xe_reg from extension offset and additional 124 - * flags 125 - * @r_: Register extension offset 126 - * @...: Additional options like access mode. See struct xe_reg for available 127 - * options. 128 - */ 129 - #define XE_REG_EXT(r_, ...) \ 130 - ((const struct xe_reg)XE_REG_INITIALIZER(r_, ##__VA_ARGS__, .ext = 1)) 131 113 132 114 /** 133 115 * XE_REG_MCR - Create a struct xe_reg_mcr from offset and additional flags
+334
drivers/gpu/drm/xe/tests/xe_guc_buf_kunit.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 AND MIT 2 + /* 3 + * Copyright © 2024 Intel Corporation 4 + */ 5 + 6 + #include <kunit/static_stub.h> 7 + #include <kunit/test.h> 8 + #include <kunit/test-bug.h> 9 + 10 + #include "xe_device.h" 11 + #include "xe_ggtt.h" 12 + #include "xe_guc_ct.h" 13 + #include "xe_kunit_helpers.h" 14 + #include "xe_pci_test.h" 15 + 16 + #define DUT_GGTT_START SZ_1M 17 + #define DUT_GGTT_SIZE SZ_2M 18 + 19 + static struct xe_bo *replacement_xe_managed_bo_create_pin_map(struct xe_device *xe, 20 + struct xe_tile *tile, 21 + size_t size, u32 flags) 22 + { 23 + struct kunit *test = kunit_get_current_test(); 24 + struct xe_bo *bo; 25 + void *buf; 26 + 27 + bo = drmm_kzalloc(&xe->drm, sizeof(*bo), GFP_KERNEL); 28 + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, bo); 29 + 30 + buf = drmm_kzalloc(&xe->drm, size, GFP_KERNEL); 31 + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buf); 32 + 33 + bo->tile = tile; 34 + bo->ttm.bdev = &xe->ttm; 35 + bo->size = size; 36 + iosys_map_set_vaddr(&bo->vmap, buf); 37 + 38 + if (flags & XE_BO_FLAG_GGTT) { 39 + struct xe_ggtt *ggtt = tile->mem.ggtt; 40 + 41 + bo->ggtt_node[tile->id] = xe_ggtt_node_init(ggtt); 42 + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, bo->ggtt_node[tile->id]); 43 + 44 + KUNIT_ASSERT_EQ(test, 0, 45 + drm_mm_insert_node_in_range(&ggtt->mm, 46 + &bo->ggtt_node[tile->id]->base, 47 + bo->size, SZ_4K, 48 + 0, 0, U64_MAX, 0)); 49 + } 50 + 51 + return bo; 52 + } 53 + 54 + static int guc_buf_test_init(struct kunit *test) 55 + { 56 + struct xe_pci_fake_data fake = { 57 + .sriov_mode = XE_SRIOV_MODE_PF, 58 + .platform = XE_TIGERLAKE, /* some random platform */ 59 + .subplatform = XE_SUBPLATFORM_NONE, 60 + }; 61 + struct xe_ggtt *ggtt; 62 + struct xe_guc *guc; 63 + 64 + test->priv = &fake; 65 + xe_kunit_helper_xe_device_test_init(test); 66 + 67 + ggtt = xe_device_get_root_tile(test->priv)->mem.ggtt; 68 + guc = &xe_device_get_gt(test->priv, 0)->uc.guc; 69 + 70 + drm_mm_init(&ggtt->mm, DUT_GGTT_START, DUT_GGTT_SIZE); 71 + mutex_init(&ggtt->lock); 72 + 73 + kunit_activate_static_stub(test, xe_managed_bo_create_pin_map, 74 + replacement_xe_managed_bo_create_pin_map); 75 + 76 + KUNIT_ASSERT_EQ(test, 0, xe_guc_buf_cache_init(&guc->buf)); 77 + 78 + test->priv = &guc->buf; 79 + return 0; 80 + } 81 + 82 + static void test_smallest(struct kunit *test) 83 + { 84 + struct xe_guc_buf_cache *cache = test->priv; 85 + struct xe_guc_buf buf; 86 + 87 + buf = xe_guc_buf_reserve(cache, 1); 88 + KUNIT_ASSERT_TRUE(test, xe_guc_buf_is_valid(buf)); 89 + KUNIT_EXPECT_NOT_NULL(test, xe_guc_buf_cpu_ptr(buf)); 90 + KUNIT_EXPECT_NE(test, 0, xe_guc_buf_gpu_addr(buf)); 91 + KUNIT_EXPECT_LE(test, DUT_GGTT_START, xe_guc_buf_gpu_addr(buf)); 92 + KUNIT_EXPECT_GT(test, DUT_GGTT_START + DUT_GGTT_SIZE, xe_guc_buf_gpu_addr(buf)); 93 + xe_guc_buf_release(buf); 94 + } 95 + 96 + static void test_largest(struct kunit *test) 97 + { 98 + struct xe_guc_buf_cache *cache = test->priv; 99 + struct xe_guc_buf buf; 100 + 101 + buf = xe_guc_buf_reserve(cache, xe_guc_buf_cache_dwords(cache)); 102 + KUNIT_ASSERT_TRUE(test, xe_guc_buf_is_valid(buf)); 103 + KUNIT_EXPECT_NOT_NULL(test, xe_guc_buf_cpu_ptr(buf)); 104 + KUNIT_EXPECT_NE(test, 0, xe_guc_buf_gpu_addr(buf)); 105 + KUNIT_EXPECT_LE(test, DUT_GGTT_START, xe_guc_buf_gpu_addr(buf)); 106 + KUNIT_EXPECT_GT(test, DUT_GGTT_START + DUT_GGTT_SIZE, xe_guc_buf_gpu_addr(buf)); 107 + xe_guc_buf_release(buf); 108 + } 109 + 110 + static void test_granular(struct kunit *test) 111 + { 112 + struct xe_guc_buf_cache *cache = test->priv; 113 + struct xe_guc_buf *bufs; 114 + int n, dwords; 115 + 116 + dwords = xe_guc_buf_cache_dwords(cache); 117 + bufs = kunit_kcalloc(test, dwords, sizeof(*bufs), GFP_KERNEL); 118 + KUNIT_EXPECT_NOT_NULL(test, bufs); 119 + 120 + for (n = 0; n < dwords; n++) 121 + bufs[n] = xe_guc_buf_reserve(cache, 1); 122 + 123 + for (n = 0; n < dwords; n++) 124 + KUNIT_EXPECT_TRUE_MSG(test, xe_guc_buf_is_valid(bufs[n]), "n=%d", n); 125 + 126 + for (n = 0; n < dwords; n++) 127 + xe_guc_buf_release(bufs[n]); 128 + } 129 + 130 + static void test_unique(struct kunit *test) 131 + { 132 + struct xe_guc_buf_cache *cache = test->priv; 133 + struct xe_guc_buf *bufs; 134 + int n, m, dwords; 135 + 136 + dwords = xe_guc_buf_cache_dwords(cache); 137 + bufs = kunit_kcalloc(test, dwords, sizeof(*bufs), GFP_KERNEL); 138 + KUNIT_EXPECT_NOT_NULL(test, bufs); 139 + 140 + for (n = 0; n < dwords; n++) 141 + bufs[n] = xe_guc_buf_reserve(cache, 1); 142 + 143 + for (n = 0; n < dwords; n++) { 144 + for (m = n + 1; m < dwords; m++) { 145 + KUNIT_EXPECT_PTR_NE_MSG(test, xe_guc_buf_cpu_ptr(bufs[n]), 146 + xe_guc_buf_cpu_ptr(bufs[m]), "n=%d, m=%d", n, m); 147 + KUNIT_ASSERT_NE_MSG(test, xe_guc_buf_gpu_addr(bufs[n]), 148 + xe_guc_buf_gpu_addr(bufs[m]), "n=%d, m=%d", n, m); 149 + } 150 + } 151 + 152 + for (n = 0; n < dwords; n++) 153 + xe_guc_buf_release(bufs[n]); 154 + } 155 + 156 + static void test_overlap(struct kunit *test) 157 + { 158 + struct xe_guc_buf_cache *cache = test->priv; 159 + struct xe_guc_buf b1, b2; 160 + u32 dwords = xe_guc_buf_cache_dwords(cache) / 2; 161 + u32 bytes = dwords * sizeof(u32); 162 + void *p1, *p2; 163 + u64 a1, a2; 164 + 165 + b1 = xe_guc_buf_reserve(cache, dwords); 166 + b2 = xe_guc_buf_reserve(cache, dwords); 167 + 168 + p1 = xe_guc_buf_cpu_ptr(b1); 169 + p2 = xe_guc_buf_cpu_ptr(b2); 170 + 171 + a1 = xe_guc_buf_gpu_addr(b1); 172 + a2 = xe_guc_buf_gpu_addr(b2); 173 + 174 + KUNIT_EXPECT_PTR_NE(test, p1, p2); 175 + if (p1 < p2) 176 + KUNIT_EXPECT_LT(test, (uintptr_t)(p1 + bytes - 1), (uintptr_t)p2); 177 + else 178 + KUNIT_EXPECT_LT(test, (uintptr_t)(p2 + bytes - 1), (uintptr_t)p1); 179 + 180 + KUNIT_EXPECT_NE(test, a1, a2); 181 + if (a1 < a2) 182 + KUNIT_EXPECT_LT(test, a1 + bytes - 1, a2); 183 + else 184 + KUNIT_EXPECT_LT(test, a2 + bytes - 1, a1); 185 + 186 + xe_guc_buf_release(b1); 187 + xe_guc_buf_release(b2); 188 + } 189 + 190 + static void test_reusable(struct kunit *test) 191 + { 192 + struct xe_guc_buf_cache *cache = test->priv; 193 + struct xe_guc_buf b1, b2; 194 + void *p1; 195 + u64 a1; 196 + 197 + b1 = xe_guc_buf_reserve(cache, xe_guc_buf_cache_dwords(cache)); 198 + KUNIT_ASSERT_TRUE(test, xe_guc_buf_is_valid(b1)); 199 + KUNIT_EXPECT_NOT_NULL(test, p1 = xe_guc_buf_cpu_ptr(b1)); 200 + KUNIT_EXPECT_NE(test, 0, a1 = xe_guc_buf_gpu_addr(b1)); 201 + xe_guc_buf_release(b1); 202 + 203 + b2 = xe_guc_buf_reserve(cache, xe_guc_buf_cache_dwords(cache)); 204 + KUNIT_EXPECT_PTR_EQ(test, p1, xe_guc_buf_cpu_ptr(b2)); 205 + KUNIT_EXPECT_EQ(test, a1, xe_guc_buf_gpu_addr(b2)); 206 + xe_guc_buf_release(b2); 207 + } 208 + 209 + static void test_too_big(struct kunit *test) 210 + { 211 + struct xe_guc_buf_cache *cache = test->priv; 212 + struct xe_guc_buf buf; 213 + 214 + buf = xe_guc_buf_reserve(cache, xe_guc_buf_cache_dwords(cache) + 1); 215 + KUNIT_EXPECT_FALSE(test, xe_guc_buf_is_valid(buf)); 216 + xe_guc_buf_release(buf); /* shouldn't crash */ 217 + } 218 + 219 + static void test_flush(struct kunit *test) 220 + { 221 + struct xe_guc_buf_cache *cache = test->priv; 222 + struct xe_guc_buf buf; 223 + const u32 dwords = xe_guc_buf_cache_dwords(cache); 224 + const u32 bytes = dwords * sizeof(u32); 225 + u32 *s, *p, *d; 226 + int n; 227 + 228 + KUNIT_ASSERT_NOT_NULL(test, s = kunit_kcalloc(test, dwords, sizeof(u32), GFP_KERNEL)); 229 + KUNIT_ASSERT_NOT_NULL(test, d = kunit_kcalloc(test, dwords, sizeof(u32), GFP_KERNEL)); 230 + 231 + for (n = 0; n < dwords; n++) 232 + s[n] = n; 233 + 234 + buf = xe_guc_buf_reserve(cache, dwords); 235 + KUNIT_ASSERT_TRUE(test, xe_guc_buf_is_valid(buf)); 236 + KUNIT_ASSERT_NOT_NULL(test, p = xe_guc_buf_cpu_ptr(buf)); 237 + KUNIT_EXPECT_PTR_NE(test, p, s); 238 + KUNIT_EXPECT_PTR_NE(test, p, d); 239 + 240 + memcpy(p, s, bytes); 241 + KUNIT_EXPECT_NE(test, 0, xe_guc_buf_flush(buf)); 242 + 243 + iosys_map_memcpy_from(d, &cache->sam->bo->vmap, 0, bytes); 244 + KUNIT_EXPECT_MEMEQ(test, s, d, bytes); 245 + 246 + xe_guc_buf_release(buf); 247 + } 248 + 249 + static void test_lookup(struct kunit *test) 250 + { 251 + struct xe_guc_buf_cache *cache = test->priv; 252 + struct xe_guc_buf buf; 253 + u32 dwords; 254 + u64 addr; 255 + u32 *p; 256 + int n; 257 + 258 + dwords = xe_guc_buf_cache_dwords(cache); 259 + buf = xe_guc_buf_reserve(cache, dwords); 260 + KUNIT_ASSERT_TRUE(test, xe_guc_buf_is_valid(buf)); 261 + KUNIT_ASSERT_NOT_NULL(test, p = xe_guc_buf_cpu_ptr(buf)); 262 + KUNIT_ASSERT_NE(test, 0, addr = xe_guc_buf_gpu_addr(buf)); 263 + 264 + KUNIT_EXPECT_EQ(test, 0, xe_guc_cache_gpu_addr_from_ptr(cache, p - 1, sizeof(u32))); 265 + KUNIT_EXPECT_EQ(test, 0, xe_guc_cache_gpu_addr_from_ptr(cache, p + dwords, sizeof(u32))); 266 + 267 + for (n = 0; n < dwords; n++) 268 + KUNIT_EXPECT_EQ_MSG(test, xe_guc_cache_gpu_addr_from_ptr(cache, p + n, sizeof(u32)), 269 + addr + n * sizeof(u32), "n=%d", n); 270 + 271 + xe_guc_buf_release(buf); 272 + } 273 + 274 + static void test_data(struct kunit *test) 275 + { 276 + static const u32 data[] = { 1, 2, 3, 4, 5, 6 }; 277 + struct xe_guc_buf_cache *cache = test->priv; 278 + struct xe_guc_buf buf; 279 + void *p; 280 + 281 + buf = xe_guc_buf_from_data(cache, data, sizeof(data)); 282 + KUNIT_ASSERT_TRUE(test, xe_guc_buf_is_valid(buf)); 283 + KUNIT_ASSERT_NOT_NULL(test, p = xe_guc_buf_cpu_ptr(buf)); 284 + KUNIT_EXPECT_MEMEQ(test, p, data, sizeof(data)); 285 + 286 + xe_guc_buf_release(buf); 287 + } 288 + 289 + static void test_class(struct kunit *test) 290 + { 291 + struct xe_guc_buf_cache *cache = test->priv; 292 + u32 dwords = xe_guc_buf_cache_dwords(cache); 293 + 294 + { 295 + CLASS(xe_guc_buf, buf)(cache, dwords); 296 + KUNIT_ASSERT_TRUE(test, xe_guc_buf_is_valid(buf)); 297 + KUNIT_EXPECT_NOT_NULL(test, xe_guc_buf_cpu_ptr(buf)); 298 + KUNIT_EXPECT_NE(test, 0, xe_guc_buf_gpu_addr(buf)); 299 + KUNIT_EXPECT_LE(test, DUT_GGTT_START, xe_guc_buf_gpu_addr(buf)); 300 + KUNIT_EXPECT_GT(test, DUT_GGTT_START + DUT_GGTT_SIZE, xe_guc_buf_gpu_addr(buf)); 301 + } 302 + 303 + { 304 + CLASS(xe_guc_buf, buf)(cache, dwords); 305 + KUNIT_ASSERT_TRUE(test, xe_guc_buf_is_valid(buf)); 306 + KUNIT_EXPECT_NOT_NULL(test, xe_guc_buf_cpu_ptr(buf)); 307 + KUNIT_EXPECT_NE(test, 0, xe_guc_buf_gpu_addr(buf)); 308 + KUNIT_EXPECT_LE(test, DUT_GGTT_START, xe_guc_buf_gpu_addr(buf)); 309 + KUNIT_EXPECT_GT(test, DUT_GGTT_START + DUT_GGTT_SIZE, xe_guc_buf_gpu_addr(buf)); 310 + } 311 + } 312 + 313 + static struct kunit_case guc_buf_test_cases[] = { 314 + KUNIT_CASE(test_smallest), 315 + KUNIT_CASE(test_largest), 316 + KUNIT_CASE(test_granular), 317 + KUNIT_CASE(test_unique), 318 + KUNIT_CASE(test_overlap), 319 + KUNIT_CASE(test_reusable), 320 + KUNIT_CASE(test_too_big), 321 + KUNIT_CASE(test_flush), 322 + KUNIT_CASE(test_lookup), 323 + KUNIT_CASE(test_data), 324 + KUNIT_CASE(test_class), 325 + {} 326 + }; 327 + 328 + static struct kunit_suite guc_buf_suite = { 329 + .name = "guc_buf", 330 + .test_cases = guc_buf_test_cases, 331 + .init = guc_buf_test_init, 332 + }; 333 + 334 + kunit_test_suites(&guc_buf_suite);
+164 -11
drivers/gpu/drm/xe/xe_bo.c
··· 6 6 #include "xe_bo.h" 7 7 8 8 #include <linux/dma-buf.h> 9 + #include <linux/nospec.h> 9 10 10 11 #include <drm/drm_drv.h> 11 12 #include <drm/drm_gem_ttm_helper.h> ··· 15 14 #include <drm/ttm/ttm_placement.h> 16 15 #include <drm/ttm/ttm_tt.h> 17 16 #include <uapi/drm/xe_drm.h> 17 + 18 + #include <kunit/static_stub.h> 18 19 19 20 #include "xe_device.h" 20 21 #include "xe_dma_buf.h" ··· 27 24 #include "xe_migrate.h" 28 25 #include "xe_pm.h" 29 26 #include "xe_preempt_fence.h" 27 + #include "xe_pxp.h" 30 28 #include "xe_res_cursor.h" 31 29 #include "xe_trace_bo.h" 32 30 #include "xe_ttm_stolen_mgr.h" ··· 128 124 GRAPHICS_VERx100(xe_bo_device(bo)) >= 1270; 129 125 } 130 126 127 + /** 128 + * xe_bo_is_vm_bound - check if BO has any mappings through VM_BIND 129 + * @bo: The BO 130 + * 131 + * Check if a given bo is bound through VM_BIND. This requires the 132 + * reservation lock for the BO to be held. 133 + * 134 + * Returns: boolean 135 + */ 136 + bool xe_bo_is_vm_bound(struct xe_bo *bo) 137 + { 138 + xe_bo_assert_held(bo); 139 + 140 + return !list_empty(&bo->ttm.base.gpuva.list); 141 + } 142 + 131 143 static bool xe_bo_is_user(struct xe_bo *bo) 132 144 { 133 145 return bo->flags & XE_BO_FLAG_USER; ··· 159 139 return tile->migrate; 160 140 } 161 141 162 - static struct xe_mem_region *res_to_mem_region(struct ttm_resource *res) 142 + static struct xe_vram_region *res_to_mem_region(struct ttm_resource *res) 163 143 { 164 144 struct xe_device *xe = ttm_to_xe_device(res->bo->bdev); 165 145 struct ttm_resource_manager *mgr; 146 + struct xe_ttm_vram_mgr *vram_mgr; 166 147 167 148 xe_assert(xe, resource_is_vram(res)); 168 149 mgr = ttm_manager_type(&xe->ttm, res->mem_type); 169 - return to_xe_ttm_vram_mgr(mgr)->vram; 150 + vram_mgr = to_xe_ttm_vram_mgr(mgr); 151 + 152 + return container_of(vram_mgr, struct xe_vram_region, ttm); 170 153 } 171 154 172 155 static void try_add_system(struct xe_device *xe, struct xe_bo *bo, ··· 198 175 struct ttm_place *places, u32 bo_flags, u32 mem_type, u32 *c) 199 176 { 200 177 struct ttm_place place = { .mem_type = mem_type }; 201 - struct xe_mem_region *vram; 178 + struct ttm_resource_manager *mgr = ttm_manager_type(&xe->ttm, mem_type); 179 + struct xe_ttm_vram_mgr *vram_mgr = to_xe_ttm_vram_mgr(mgr); 180 + 181 + struct xe_vram_region *vram; 202 182 u64 io_size; 203 183 204 184 xe_assert(xe, *c < ARRAY_SIZE(bo->placements)); 205 185 206 - vram = to_xe_ttm_vram_mgr(ttm_manager_type(&xe->ttm, mem_type))->vram; 186 + vram = container_of(vram_mgr, struct xe_vram_region, ttm); 207 187 xe_assert(xe, vram && vram->usable_size); 208 188 io_size = vram->io_size; 209 189 ··· 490 464 return 0; 491 465 case XE_PL_VRAM0: 492 466 case XE_PL_VRAM1: { 493 - struct xe_mem_region *vram = res_to_mem_region(mem); 467 + struct xe_vram_region *vram = res_to_mem_region(mem); 494 468 495 469 if (!xe_ttm_resource_visible(mem)) 496 470 return -EINVAL; ··· 739 713 goto out; 740 714 } 741 715 716 + /* Reject BO eviction if BO is bound to current VM. */ 717 + if (evict && ctx->resv) { 718 + struct drm_gpuvm_bo *vm_bo; 719 + 720 + drm_gem_for_each_gpuvm_bo(vm_bo, &bo->ttm.base) { 721 + struct xe_vm *vm = gpuvm_to_vm(vm_bo->vm); 722 + 723 + if (xe_vm_resv(vm) == ctx->resv && 724 + xe_vm_in_preempt_fence_mode(vm)) { 725 + ret = -EBUSY; 726 + goto out; 727 + } 728 + } 729 + } 730 + 742 731 /* 743 732 * Failed multi-hop where the old_mem is still marked as 744 733 * TTM_PL_FLAG_TEMPORARY, should just be a dummy move. ··· 837 796 838 797 /* Create a new VMAP once kernel BO back in VRAM */ 839 798 if (!ret && resource_is_vram(new_mem)) { 840 - struct xe_mem_region *vram = res_to_mem_region(new_mem); 799 + struct xe_vram_region *vram = res_to_mem_region(new_mem); 841 800 void __iomem *new_addr = vram->mapping + 842 801 (new_mem->start << PAGE_SHIFT); 843 802 ··· 1047 1006 { 1048 1007 struct xe_bo *bo = ttm_to_xe_bo(ttm_bo); 1049 1008 struct xe_res_cursor cursor; 1050 - struct xe_mem_region *vram; 1009 + struct xe_vram_region *vram; 1051 1010 1052 1011 if (ttm_bo->resource->mem_type == XE_PL_STOLEN) 1053 1012 return xe_ttm_stolen_io_offset(bo, page_offset << PAGE_SHIFT) >> PAGE_SHIFT; ··· 1187 1146 struct xe_device *xe = ttm_to_xe_device(ttm_bo->bdev); 1188 1147 struct iosys_map vmap; 1189 1148 struct xe_res_cursor cursor; 1190 - struct xe_mem_region *vram; 1149 + struct xe_vram_region *vram; 1191 1150 int bytes_left = len; 1192 1151 1193 1152 xe_bo_assert_held(bo); ··· 1685 1644 } 1686 1645 } 1687 1646 1647 + trace_xe_bo_create(bo); 1688 1648 return bo; 1689 1649 1690 1650 err_unlock_put_bo: ··· 1822 1780 { 1823 1781 struct xe_bo *bo; 1824 1782 int ret; 1783 + 1784 + KUNIT_STATIC_STUB_REDIRECT(xe_managed_bo_create_pin_map, xe, tile, size, flags); 1825 1785 1826 1786 bo = xe_bo_create_pin_map(xe, tile, NULL, size, ttm_bo_type_kernel, flags); 1827 1787 if (IS_ERR(bo)) ··· 2179 2135 __xe_bo_vunmap(bo); 2180 2136 } 2181 2137 2138 + static int gem_create_set_pxp_type(struct xe_device *xe, struct xe_bo *bo, u64 value) 2139 + { 2140 + if (value == DRM_XE_PXP_TYPE_NONE) 2141 + return 0; 2142 + 2143 + /* we only support DRM_XE_PXP_TYPE_HWDRM for now */ 2144 + if (XE_IOCTL_DBG(xe, value != DRM_XE_PXP_TYPE_HWDRM)) 2145 + return -EINVAL; 2146 + 2147 + return xe_pxp_key_assign(xe->pxp, bo); 2148 + } 2149 + 2150 + typedef int (*xe_gem_create_set_property_fn)(struct xe_device *xe, 2151 + struct xe_bo *bo, 2152 + u64 value); 2153 + 2154 + static const xe_gem_create_set_property_fn gem_create_set_property_funcs[] = { 2155 + [DRM_XE_GEM_CREATE_EXTENSION_SET_PROPERTY] = gem_create_set_pxp_type, 2156 + }; 2157 + 2158 + static int gem_create_user_ext_set_property(struct xe_device *xe, 2159 + struct xe_bo *bo, 2160 + u64 extension) 2161 + { 2162 + u64 __user *address = u64_to_user_ptr(extension); 2163 + struct drm_xe_ext_set_property ext; 2164 + int err; 2165 + u32 idx; 2166 + 2167 + err = __copy_from_user(&ext, address, sizeof(ext)); 2168 + if (XE_IOCTL_DBG(xe, err)) 2169 + return -EFAULT; 2170 + 2171 + if (XE_IOCTL_DBG(xe, ext.property >= 2172 + ARRAY_SIZE(gem_create_set_property_funcs)) || 2173 + XE_IOCTL_DBG(xe, ext.pad) || 2174 + XE_IOCTL_DBG(xe, ext.property != DRM_XE_GEM_CREATE_EXTENSION_SET_PROPERTY)) 2175 + return -EINVAL; 2176 + 2177 + idx = array_index_nospec(ext.property, ARRAY_SIZE(gem_create_set_property_funcs)); 2178 + if (!gem_create_set_property_funcs[idx]) 2179 + return -EINVAL; 2180 + 2181 + return gem_create_set_property_funcs[idx](xe, bo, ext.value); 2182 + } 2183 + 2184 + typedef int (*xe_gem_create_user_extension_fn)(struct xe_device *xe, 2185 + struct xe_bo *bo, 2186 + u64 extension); 2187 + 2188 + static const xe_gem_create_user_extension_fn gem_create_user_extension_funcs[] = { 2189 + [DRM_XE_GEM_CREATE_EXTENSION_SET_PROPERTY] = gem_create_user_ext_set_property, 2190 + }; 2191 + 2192 + #define MAX_USER_EXTENSIONS 16 2193 + static int gem_create_user_extensions(struct xe_device *xe, struct xe_bo *bo, 2194 + u64 extensions, int ext_number) 2195 + { 2196 + u64 __user *address = u64_to_user_ptr(extensions); 2197 + struct drm_xe_user_extension ext; 2198 + int err; 2199 + u32 idx; 2200 + 2201 + if (XE_IOCTL_DBG(xe, ext_number >= MAX_USER_EXTENSIONS)) 2202 + return -E2BIG; 2203 + 2204 + err = __copy_from_user(&ext, address, sizeof(ext)); 2205 + if (XE_IOCTL_DBG(xe, err)) 2206 + return -EFAULT; 2207 + 2208 + if (XE_IOCTL_DBG(xe, ext.pad) || 2209 + XE_IOCTL_DBG(xe, ext.name >= ARRAY_SIZE(gem_create_user_extension_funcs))) 2210 + return -EINVAL; 2211 + 2212 + idx = array_index_nospec(ext.name, 2213 + ARRAY_SIZE(gem_create_user_extension_funcs)); 2214 + err = gem_create_user_extension_funcs[idx](xe, bo, extensions); 2215 + if (XE_IOCTL_DBG(xe, err)) 2216 + return err; 2217 + 2218 + if (ext.next_extension) 2219 + return gem_create_user_extensions(xe, bo, ext.next_extension, 2220 + ++ext_number); 2221 + 2222 + return 0; 2223 + } 2224 + 2182 2225 int xe_gem_create_ioctl(struct drm_device *dev, void *data, 2183 2226 struct drm_file *file) 2184 2227 { ··· 2278 2147 u32 handle; 2279 2148 int err; 2280 2149 2281 - if (XE_IOCTL_DBG(xe, args->extensions) || 2282 - XE_IOCTL_DBG(xe, args->pad[0] || args->pad[1] || args->pad[2]) || 2150 + if (XE_IOCTL_DBG(xe, args->pad[0] || args->pad[1] || args->pad[2]) || 2283 2151 XE_IOCTL_DBG(xe, args->reserved[0] || args->reserved[1])) 2284 2152 return -EINVAL; 2285 2153 ··· 2360 2230 goto out_vm; 2361 2231 } 2362 2232 2233 + if (args->extensions) { 2234 + err = gem_create_user_extensions(xe, bo, args->extensions, 0); 2235 + if (err) 2236 + goto out_bulk; 2237 + } 2238 + 2363 2239 err = drm_gem_handle_create(file, &bo->ttm.base, &handle); 2364 2240 if (err) 2365 2241 goto out_bulk; ··· 2399 2263 XE_IOCTL_DBG(xe, args->reserved[0] || args->reserved[1])) 2400 2264 return -EINVAL; 2401 2265 2402 - if (XE_IOCTL_DBG(xe, args->flags)) 2266 + if (XE_IOCTL_DBG(xe, args->flags & 2267 + ~DRM_XE_MMAP_OFFSET_FLAG_PCI_BARRIER)) 2403 2268 return -EINVAL; 2269 + 2270 + if (args->flags & DRM_XE_MMAP_OFFSET_FLAG_PCI_BARRIER) { 2271 + if (XE_IOCTL_DBG(xe, !IS_DGFX(xe))) 2272 + return -EINVAL; 2273 + 2274 + if (XE_IOCTL_DBG(xe, args->handle)) 2275 + return -EINVAL; 2276 + 2277 + if (XE_IOCTL_DBG(xe, PAGE_SIZE > SZ_4K)) 2278 + return -EINVAL; 2279 + 2280 + BUILD_BUG_ON(((XE_PCI_BARRIER_MMAP_OFFSET >> XE_PTE_SHIFT) + 2281 + SZ_4K) >= DRM_FILE_PAGE_OFFSET_START); 2282 + args->offset = XE_PCI_BARRIER_MMAP_OFFSET; 2283 + return 0; 2284 + } 2404 2285 2405 2286 gem_obj = drm_gem_object_lookup(file, args->handle); 2406 2287 if (XE_IOCTL_DBG(xe, !gem_obj))
+8
drivers/gpu/drm/xe/xe_bo.h
··· 75 75 76 76 #define XE_BO_PROPS_INVALID (-1) 77 77 78 + #define XE_PCI_BARRIER_MMAP_OFFSET (0x50 << XE_PTE_SHIFT) 79 + 78 80 struct sg_table; 79 81 80 82 struct xe_bo *xe_bo_alloc(void); ··· 186 184 return bo->ttm.pin_count; 187 185 } 188 186 187 + static inline bool xe_bo_is_protected(const struct xe_bo *bo) 188 + { 189 + return bo->pxp_key_instance; 190 + } 191 + 189 192 static inline void xe_bo_unpin_map_no_vm(struct xe_bo *bo) 190 193 { 191 194 if (likely(bo)) { ··· 241 234 bool xe_bo_is_vram(struct xe_bo *bo); 242 235 bool xe_bo_is_stolen(struct xe_bo *bo); 243 236 bool xe_bo_is_stolen_devmem(struct xe_bo *bo); 237 + bool xe_bo_is_vm_bound(struct xe_bo *bo); 244 238 bool xe_bo_has_single_placement(struct xe_bo *bo); 245 239 uint64_t vram_region_gpu_offset(struct ttm_resource *res); 246 240
+6
drivers/gpu/drm/xe/xe_bo_types.h
··· 57 57 */ 58 58 struct list_head client_link; 59 59 #endif 60 + /** 61 + * @pxp_key_instance: PXP key instance this BO was created against. A 62 + * 0 in this variable indicates that the BO does not use PXP encryption. 63 + */ 64 + u32 pxp_key_instance; 65 + 60 66 /** @freed: List node for delayed put. */ 61 67 struct llist_node freed; 62 68 /** @update_index: Update index if PT BO */
+5 -1
drivers/gpu/drm/xe/xe_debugfs.c
··· 18 18 #include "xe_gt_printk.h" 19 19 #include "xe_guc_ads.h" 20 20 #include "xe_pm.h" 21 + #include "xe_pxp_debugfs.h" 21 22 #include "xe_sriov.h" 22 23 #include "xe_step.h" 23 24 ··· 167 166 return -EINVAL; 168 167 169 168 if (xe->wedged.mode == wedged_mode) 170 - return 0; 169 + return size; 171 170 172 171 xe->wedged.mode = wedged_mode; 173 172 ··· 176 175 ret = xe_guc_ads_scheduler_policy_toggle_reset(&gt->uc.guc.ads); 177 176 if (ret) { 178 177 xe_gt_err(gt, "Failed to update GuC ADS scheduler policy. GuC may still cause engine reset even with wedged_mode=2\n"); 178 + xe_pm_runtime_put(xe); 179 179 return -EIO; 180 180 } 181 181 } ··· 231 229 232 230 for_each_gt(gt, xe, id) 233 231 xe_gt_debugfs_register(gt); 232 + 233 + xe_pxp_debugfs_register(xe->pxp); 234 234 235 235 fault_create_debugfs_attr("fail_gt_reset", root, &gt_reset_failure); 236 236 }
+225 -58
drivers/gpu/drm/xe/xe_device.c
··· 49 49 #include "xe_pat.h" 50 50 #include "xe_pcode.h" 51 51 #include "xe_pm.h" 52 + #include "xe_pmu.h" 53 + #include "xe_pxp.h" 52 54 #include "xe_query.h" 53 55 #include "xe_sriov.h" 56 + #include "xe_survivability_mode.h" 54 57 #include "xe_tile.h" 55 58 #include "xe_ttm_stolen_mgr.h" 56 59 #include "xe_ttm_sys_mgr.h" ··· 64 61 #include "xe_wa.h" 65 62 66 63 #include <generated/xe_wa_oob.h> 64 + 65 + struct xe_device_remove_action { 66 + struct list_head node; 67 + void (*action)(void *); 68 + void *data; 69 + }; 67 70 68 71 static int xe_file_open(struct drm_device *dev, struct drm_file *file) 69 72 { ··· 241 232 #define xe_drm_compat_ioctl NULL 242 233 #endif 243 234 235 + static void barrier_open(struct vm_area_struct *vma) 236 + { 237 + drm_dev_get(vma->vm_private_data); 238 + } 239 + 240 + static void barrier_close(struct vm_area_struct *vma) 241 + { 242 + drm_dev_put(vma->vm_private_data); 243 + } 244 + 245 + static void barrier_release_dummy_page(struct drm_device *dev, void *res) 246 + { 247 + struct page *dummy_page = (struct page *)res; 248 + 249 + __free_page(dummy_page); 250 + } 251 + 252 + static vm_fault_t barrier_fault(struct vm_fault *vmf) 253 + { 254 + struct drm_device *dev = vmf->vma->vm_private_data; 255 + struct vm_area_struct *vma = vmf->vma; 256 + vm_fault_t ret = VM_FAULT_NOPAGE; 257 + pgprot_t prot; 258 + int idx; 259 + 260 + prot = vm_get_page_prot(vma->vm_flags); 261 + 262 + if (drm_dev_enter(dev, &idx)) { 263 + unsigned long pfn; 264 + 265 + #define LAST_DB_PAGE_OFFSET 0x7ff001 266 + pfn = PHYS_PFN(pci_resource_start(to_pci_dev(dev->dev), 0) + 267 + LAST_DB_PAGE_OFFSET); 268 + ret = vmf_insert_pfn_prot(vma, vma->vm_start, pfn, 269 + pgprot_noncached(prot)); 270 + drm_dev_exit(idx); 271 + } else { 272 + struct page *page; 273 + 274 + /* Allocate new dummy page to map all the VA range in this VMA to it*/ 275 + page = alloc_page(GFP_KERNEL | __GFP_ZERO); 276 + if (!page) 277 + return VM_FAULT_OOM; 278 + 279 + /* Set the page to be freed using drmm release action */ 280 + if (drmm_add_action_or_reset(dev, barrier_release_dummy_page, page)) 281 + return VM_FAULT_OOM; 282 + 283 + ret = vmf_insert_pfn_prot(vma, vma->vm_start, page_to_pfn(page), 284 + prot); 285 + } 286 + 287 + return ret; 288 + } 289 + 290 + static const struct vm_operations_struct vm_ops_barrier = { 291 + .open = barrier_open, 292 + .close = barrier_close, 293 + .fault = barrier_fault, 294 + }; 295 + 296 + static int xe_pci_barrier_mmap(struct file *filp, 297 + struct vm_area_struct *vma) 298 + { 299 + struct drm_file *priv = filp->private_data; 300 + struct drm_device *dev = priv->minor->dev; 301 + struct xe_device *xe = to_xe_device(dev); 302 + 303 + if (!IS_DGFX(xe)) 304 + return -EINVAL; 305 + 306 + if (vma->vm_end - vma->vm_start > SZ_4K) 307 + return -EINVAL; 308 + 309 + if (is_cow_mapping(vma->vm_flags)) 310 + return -EINVAL; 311 + 312 + if (vma->vm_flags & (VM_READ | VM_EXEC)) 313 + return -EINVAL; 314 + 315 + vm_flags_clear(vma, VM_MAYREAD | VM_MAYEXEC); 316 + vm_flags_set(vma, VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP | VM_IO); 317 + vma->vm_ops = &vm_ops_barrier; 318 + vma->vm_private_data = dev; 319 + drm_dev_get(vma->vm_private_data); 320 + 321 + return 0; 322 + } 323 + 324 + static int xe_mmap(struct file *filp, struct vm_area_struct *vma) 325 + { 326 + struct drm_file *priv = filp->private_data; 327 + struct drm_device *dev = priv->minor->dev; 328 + 329 + if (drm_dev_is_unplugged(dev)) 330 + return -ENODEV; 331 + 332 + switch (vma->vm_pgoff) { 333 + case XE_PCI_BARRIER_MMAP_OFFSET >> XE_PTE_SHIFT: 334 + return xe_pci_barrier_mmap(filp, vma); 335 + } 336 + 337 + return drm_gem_mmap(filp, vma); 338 + } 339 + 244 340 static const struct file_operations xe_driver_fops = { 245 341 .owner = THIS_MODULE, 246 342 .open = drm_open, 247 343 .release = drm_release_noglobal, 248 344 .unlocked_ioctl = xe_drm_ioctl, 249 - .mmap = drm_gem_mmap, 345 + .mmap = xe_mmap, 250 346 .poll = drm_poll, 251 347 .read = drm_read, 252 348 .compat_ioctl = xe_drm_compat_ioctl, ··· 692 578 { 693 579 int err; 694 580 695 - err = xe_mmio_init(xe); 581 + err = xe_mmio_probe_early(xe); 696 582 if (err) 697 583 return err; 698 584 ··· 701 587 update_device_info(xe); 702 588 703 589 err = xe_pcode_probe_early(xe); 704 - if (err) 590 + if (err) { 591 + if (xe_survivability_mode_required(xe)) 592 + xe_survivability_mode_init(xe); 593 + 705 594 return err; 595 + } 706 596 707 597 err = wait_for_lmem_ready(xe); 708 598 if (err) ··· 741 623 "Flat CCS has been disabled in bios, May lead to performance impact"); 742 624 743 625 xe_force_wake_put(gt_to_fw(gt), fw_ref); 626 + 744 627 return 0; 745 628 } 746 629 ··· 750 631 struct xe_tile *tile; 751 632 struct xe_gt *gt; 752 633 int err; 753 - u8 last_gt; 754 634 u8 id; 635 + 636 + xe->probing = true; 637 + INIT_LIST_HEAD(&xe->remove_action_list); 755 638 756 639 xe_pat_init_early(xe); 757 640 ··· 762 641 return err; 763 642 764 643 xe->info.mem_region_mask = 1; 765 - err = xe_display_init_nommio(xe); 766 - if (err) 767 - return err; 768 - 769 644 err = xe_set_dma_info(xe); 770 645 if (err) 771 646 return err; ··· 812 695 err = xe_devcoredump_init(xe); 813 696 if (err) 814 697 return err; 698 + 699 + /* 700 + * From here on, if a step fails, make sure a Driver-FLR is triggereed 701 + */ 815 702 err = devm_add_action_or_reset(xe->drm.dev, xe_driver_flr_fini, xe); 816 703 if (err) 817 704 return err; 818 705 819 - err = xe_display_init_noirq(xe); 706 + err = probe_has_flat_ccs(xe); 820 707 if (err) 821 708 return err; 822 709 823 - err = xe_irq_install(xe); 824 - if (err) 825 - goto err; 826 - 827 - err = probe_has_flat_ccs(xe); 828 - if (err) 829 - goto err; 830 - 831 710 err = xe_vram_probe(xe); 832 711 if (err) 833 - goto err; 712 + return err; 834 713 835 714 for_each_tile(tile, xe, id) { 836 715 err = xe_tile_init_noalloc(tile); 837 716 if (err) 838 - goto err; 717 + return err; 839 718 } 840 719 841 720 /* Allocate and map stolen after potential VRAM resize */ 842 - xe_ttm_stolen_mgr_init(xe); 721 + err = xe_ttm_stolen_mgr_init(xe); 722 + if (err) 723 + return err; 843 724 844 725 /* 845 726 * Now that GT is initialized (TTM in particular), ··· 845 730 * This is the reason the first allocation needs to be done 846 731 * inside display. 847 732 */ 848 - err = xe_display_init_noaccel(xe); 733 + err = xe_display_init_early(xe); 849 734 if (err) 850 - goto err; 735 + return err; 736 + 737 + for_each_tile(tile, xe, id) { 738 + err = xe_tile_init(tile); 739 + if (err) 740 + return err; 741 + } 742 + 743 + err = xe_irq_install(xe); 744 + if (err) 745 + return err; 851 746 852 747 for_each_gt(gt, xe, id) { 853 - last_gt = id; 854 - 855 748 err = xe_gt_init(gt); 856 749 if (err) 857 - goto err_fini_gt; 750 + return err; 858 751 } 859 752 860 753 xe_heci_gsc_init(xe); 861 754 862 755 err = xe_oa_init(xe); 863 756 if (err) 864 - goto err_fini_gt; 757 + return err; 865 758 866 759 err = xe_display_init(xe); 867 760 if (err) 868 - goto err_fini_oa; 761 + return err; 762 + 763 + err = xe_pxp_init(xe); 764 + if (err) 765 + goto err_remove_display; 869 766 870 767 err = drm_dev_register(&xe->drm, 0); 871 768 if (err) 872 - goto err_fini_display; 769 + goto err_remove_display; 873 770 874 771 xe_display_register(xe); 875 772 876 - xe_oa_register(xe); 773 + err = xe_oa_register(xe); 774 + if (err) 775 + goto err_unregister_display; 776 + 777 + err = xe_pmu_register(&xe->pmu); 778 + if (err) 779 + goto err_unregister_display; 877 780 878 781 xe_debugfs_register(xe); 879 782 880 - xe_hwmon_register(xe); 783 + err = xe_hwmon_register(xe); 784 + if (err) 785 + goto err_unregister_display; 881 786 882 787 for_each_gt(gt, xe, id) 883 788 xe_gt_sanitize_freq(gt); 884 789 885 790 xe_vsec_init(xe); 886 791 792 + xe->probing = false; 793 + 887 794 return devm_add_action_or_reset(xe->drm.dev, xe_device_sanitize, xe); 888 795 889 - err_fini_display: 796 + err_unregister_display: 797 + xe_display_unregister(xe); 798 + err_remove_display: 890 799 xe_display_driver_remove(xe); 891 800 892 - err_fini_oa: 893 - xe_oa_fini(xe); 894 - 895 - err_fini_gt: 896 - for_each_gt(gt, xe, id) { 897 - if (id < last_gt) 898 - xe_gt_remove(gt); 899 - else 900 - break; 901 - } 902 - 903 - err: 904 - xe_display_fini(xe); 905 801 return err; 906 802 } 907 803 908 - static void xe_device_remove_display(struct xe_device *xe) 804 + /** 805 + * xe_device_call_remove_actions - Call the remove actions 806 + * @xe: xe device instance 807 + * 808 + * This is only to be used by xe_pci and xe_device to call the remove actions 809 + * while removing the driver or handling probe failures. 810 + */ 811 + void xe_device_call_remove_actions(struct xe_device *xe) 909 812 { 910 - xe_display_unregister(xe); 813 + struct xe_device_remove_action *ra, *tmp; 911 814 912 - drm_dev_unplug(&xe->drm); 913 - xe_display_driver_remove(xe); 815 + list_for_each_entry_safe(ra, tmp, &xe->remove_action_list, node) { 816 + ra->action(ra->data); 817 + list_del(&ra->node); 818 + kfree(ra); 819 + } 820 + 821 + xe->probing = false; 822 + } 823 + 824 + /** 825 + * xe_device_add_action_or_reset - Add an action to run on driver removal 826 + * @xe: xe device instance 827 + * @action: Function that should be called on device remove 828 + * @data: Pointer to data passed to @action implementation 829 + * 830 + * This adds a custom action to the list of remove callbacks executed on device 831 + * remove, before any dev or drm managed resources are removed. This is only 832 + * needed if the action leads to component_del()/component_master_del() since 833 + * that is not compatible with devres cleanup. 834 + * 835 + * Returns: 0 on success or a negative error code on failure, in which case 836 + * @action is already called. 837 + */ 838 + int xe_device_add_action_or_reset(struct xe_device *xe, 839 + void (*action)(void *), void *data) 840 + { 841 + struct xe_device_remove_action *ra; 842 + 843 + drm_WARN_ON(&xe->drm, !xe->probing); 844 + 845 + ra = kmalloc(sizeof(*ra), GFP_KERNEL); 846 + if (!ra) { 847 + action(data); 848 + return -ENOMEM; 849 + } 850 + 851 + INIT_LIST_HEAD(&ra->node); 852 + ra->action = action; 853 + ra->data = data; 854 + list_add(&ra->node, &xe->remove_action_list); 855 + 856 + return 0; 914 857 } 915 858 916 859 void xe_device_remove(struct xe_device *xe) 917 860 { 918 - struct xe_gt *gt; 919 - u8 id; 861 + xe_display_unregister(xe); 920 862 921 - xe_oa_unregister(xe); 863 + drm_dev_unplug(&xe->drm); 922 864 923 - xe_device_remove_display(xe); 924 - 925 - xe_display_fini(xe); 926 - 927 - xe_oa_fini(xe); 865 + xe_display_driver_remove(xe); 928 866 929 867 xe_heci_gsc_fini(xe); 930 868 931 - for_each_gt(gt, xe, id) 932 - xe_gt_remove(gt); 869 + xe_device_call_remove_actions(xe); 933 870 } 934 871 935 872 void xe_device_shutdown(struct xe_device *xe)
+8
drivers/gpu/drm/xe/xe_device.h
··· 45 45 const struct pci_device_id *ent); 46 46 int xe_device_probe_early(struct xe_device *xe); 47 47 int xe_device_probe(struct xe_device *xe); 48 + int xe_device_add_action_or_reset(struct xe_device *xe, 49 + void (*action)(void *), void *data); 50 + void xe_device_call_remove_actions(struct xe_device *xe); 48 51 void xe_device_remove(struct xe_device *xe); 49 52 void xe_device_shutdown(struct xe_device *xe); 50 53 ··· 171 168 static inline bool xe_device_uses_memirq(struct xe_device *xe) 172 169 { 173 170 return xe_device_has_memirq(xe) && (IS_SRIOV_VF(xe) || xe_device_has_msix(xe)); 171 + } 172 + 173 + static inline bool xe_device_has_lmtt(struct xe_device *xe) 174 + { 175 + return IS_DGFX(xe); 174 176 } 175 177 176 178 u32 xe_device_ccs_bytes(struct xe_device *xe, u64 size);
+35 -20
drivers/gpu/drm/xe/xe_device_types.h
··· 18 18 #include "xe_memirq_types.h" 19 19 #include "xe_oa_types.h" 20 20 #include "xe_platform_types.h" 21 + #include "xe_pmu_types.h" 21 22 #include "xe_pt_types.h" 22 23 #include "xe_sriov_types.h" 23 24 #include "xe_step_types.h" 25 + #include "xe_survivability_mode_types.h" 26 + #include "xe_ttm_vram_mgr_types.h" 24 27 25 28 #if IS_ENABLED(CONFIG_DRM_XE_DEBUG) 26 29 #define TEST_VM_OPS_ERROR ··· 37 34 38 35 struct xe_ggtt; 39 36 struct xe_pat_ops; 37 + struct xe_pxp; 40 38 41 39 #define XE_BO_INVALID_OFFSET LONG_MAX 42 40 ··· 71 67 struct xe_tile * : (tile__)->xe) 72 68 73 69 /** 74 - * struct xe_mem_region - memory region structure 70 + * struct xe_vram_region - memory region structure 75 71 * This is used to describe a memory region in xe 76 72 * device, such as HBM memory or CXL extension memory. 77 73 */ 78 - struct xe_mem_region { 74 + struct xe_vram_region { 79 75 /** @io_start: IO start address of this VRAM instance */ 80 76 resource_size_t io_start; 81 77 /** ··· 106 102 resource_size_t actual_physical_size; 107 103 /** @mapping: pointer to VRAM mappable space */ 108 104 void __iomem *mapping; 105 + /** @ttm: VRAM TTM manager */ 106 + struct xe_ttm_vram_mgr ttm; 109 107 }; 110 108 111 109 /** ··· 192 186 */ 193 187 struct xe_mmio mmio; 194 188 195 - /** 196 - * @mmio_ext: MMIO-extension info for a tile. 197 - * 198 - * Each tile has its own additional 256MB (28-bit) MMIO-extension space. 199 - */ 200 - struct xe_mmio mmio_ext; 201 - 202 189 /** @mem: memory management info for tile */ 203 190 struct { 204 191 /** ··· 200 201 * Although VRAM is associated with a specific tile, it can 201 202 * still be accessed by all tiles' GTs. 202 203 */ 203 - struct xe_mem_region vram; 204 - 205 - /** @mem.vram_mgr: VRAM TTM manager */ 206 - struct xe_ttm_vram_mgr *vram_mgr; 204 + struct xe_vram_region vram; 207 205 208 206 /** @mem.ggtt: Global graphics translation table */ 209 207 struct xe_ggtt *ggtt; ··· 259 263 const char *graphics_name; 260 264 /** @info.media_name: media IP name */ 261 265 const char *media_name; 262 - /** @info.tile_mmio_ext_size: size of MMIO extension space, per-tile */ 263 - u32 tile_mmio_ext_size; 264 266 /** @info.graphics_verx100: graphics IP version */ 265 267 u32 graphics_verx100; 266 268 /** @info.media_verx100: media IP version */ ··· 308 314 u8 has_heci_gscfi:1; 309 315 /** @info.has_llc: Device has a shared CPU+GPU last level cache */ 310 316 u8 has_llc:1; 311 - /** @info.has_mmio_ext: Device has extra MMIO address range */ 312 - u8 has_mmio_ext:1; 317 + /** @info.has_pxp: Device has PXP support */ 318 + u8 has_pxp:1; 313 319 /** @info.has_range_tlb_invalidation: Has range based TLB invalidations */ 314 320 u8 has_range_tlb_invalidation:1; 315 321 /** @info.has_sriov: Supports SR-IOV */ ··· 334 340 /** @info.skip_pcode: skip access to PCODE uC */ 335 341 u8 skip_pcode:1; 336 342 } info; 343 + 344 + /** @survivability: survivability information for device */ 345 + struct xe_survivability survivability; 337 346 338 347 /** @irq: device interrupt state */ 339 348 struct { ··· 369 372 /** @mem: memory info for device */ 370 373 struct { 371 374 /** @mem.vram: VRAM info for device */ 372 - struct xe_mem_region vram; 375 + struct xe_vram_region vram; 373 376 /** @mem.sys_mgr: system TTM manager */ 374 377 struct ttm_resource_manager sys_mgr; 375 378 } mem; ··· 427 430 428 431 /** @tiles: device tiles */ 429 432 struct xe_tile tiles[XE_MAX_TILES_PER_DEVICE]; 433 + 434 + /** 435 + * @remove_action_list: list of actions to execute on device remove. 436 + * Use xe_device_add_remove_action() for that. Actions can only be added 437 + * during probe and are executed during the call from PCI subsystem to 438 + * remove the driver from the device. 439 + */ 440 + struct list_head remove_action_list; 441 + 442 + /** 443 + * @probing: cover the section in which @remove_action_list can be used 444 + * to post cleaning actions 445 + */ 446 + bool probing; 430 447 431 448 /** 432 449 * @mem_access: keep track of memory access in the device, possibly ··· 525 514 /** @oa: oa observation subsystem */ 526 515 struct xe_oa oa; 527 516 517 + /** @pxp: Encapsulate Protected Xe Path support */ 518 + struct xe_pxp *pxp; 519 + 528 520 /** @needs_flr_on_fini: requests function-reset on fini */ 529 521 bool needs_flr_on_fini; 530 522 ··· 538 524 /** @wedged.mode: Mode controlled by kernel parameter and debugfs */ 539 525 int mode; 540 526 } wedged; 527 + 528 + /** @pmu: performance monitoring unit */ 529 + struct xe_pmu pmu; 541 530 542 531 #ifdef TEST_VM_OPS_ERROR 543 532 /** ··· 602 585 unsigned int czclk_freq; 603 586 unsigned int fsb_freq, mem_freq, is_ddr3; 604 587 }; 605 - 606 - void *pxp; 607 588 #endif 608 589 }; 609 590
+8
drivers/gpu/drm/xe/xe_drm_client.c
··· 325 325 unsigned int fw_ref; 326 326 327 327 /* 328 + * RING_TIMESTAMP registers are inaccessible in VF mode. 329 + * Without drm-total-cycles-*, other keys provide little value. 330 + * Show all or none of the optional "run_ticks" keys in this case. 331 + */ 332 + if (IS_SRIOV_VF(xe)) 333 + return; 334 + 335 + /* 328 336 * Wait for any exec queue going away: their cycles will get updated on 329 337 * context switch out, so wait for that to happen 330 338 */
+6
drivers/gpu/drm/xe/xe_exec.c
··· 262 262 goto err_exec; 263 263 } 264 264 265 + if (xe_exec_queue_uses_pxp(q)) { 266 + err = xe_vm_validate_protected(q->vm); 267 + if (err) 268 + goto err_exec; 269 + } 270 + 265 271 job = xe_sched_job_create(q, xe_exec_queue_is_parallel(q) ? 266 272 addresses : &args->address); 267 273 if (IS_ERR(job)) {
+60 -6
drivers/gpu/drm/xe/xe_exec_queue.c
··· 25 25 #include "xe_ring_ops_types.h" 26 26 #include "xe_trace.h" 27 27 #include "xe_vm.h" 28 + #include "xe_pxp.h" 28 29 29 30 enum xe_exec_queue_sched_prop { 30 31 XE_EXEC_QUEUE_JOB_TIMEOUT = 0, ··· 39 38 40 39 static void __xe_exec_queue_free(struct xe_exec_queue *q) 41 40 { 41 + if (xe_exec_queue_uses_pxp(q)) 42 + xe_pxp_exec_queue_remove(gt_to_xe(q->gt)->pxp, q); 42 43 if (q->vm) 43 44 xe_vm_put(q->vm); 44 45 ··· 81 78 INIT_LIST_HEAD(&q->lr.link); 82 79 INIT_LIST_HEAD(&q->multi_gt_link); 83 80 INIT_LIST_HEAD(&q->hw_engine_group_link); 81 + INIT_LIST_HEAD(&q->pxp.link); 84 82 85 83 q->sched_props.timeslice_us = hwe->eclass->sched_props.timeslice_us; 86 84 q->sched_props.preempt_timeout_us = ··· 116 112 { 117 113 struct xe_vm *vm = q->vm; 118 114 int i, err; 115 + u32 flags = 0; 116 + 117 + /* 118 + * PXP workloads executing on RCS or CCS must run in isolation (i.e. no 119 + * other workload can use the EUs at the same time). On MTL this is done 120 + * by setting the RUNALONE bit in the LRC, while starting on Xe2 there 121 + * is a dedicated bit for it. 122 + */ 123 + if (xe_exec_queue_uses_pxp(q) && 124 + (q->class == XE_ENGINE_CLASS_RENDER || q->class == XE_ENGINE_CLASS_COMPUTE)) { 125 + if (GRAPHICS_VER(gt_to_xe(q->gt)) >= 20) 126 + flags |= XE_LRC_CREATE_PXP; 127 + else 128 + flags |= XE_LRC_CREATE_RUNALONE; 129 + } 119 130 120 131 if (vm) { 121 132 err = xe_vm_lock(vm, true); ··· 139 120 } 140 121 141 122 for (i = 0; i < q->width; ++i) { 142 - q->lrc[i] = xe_lrc_create(q->hwe, q->vm, SZ_16K, q->msix_vec); 123 + q->lrc[i] = xe_lrc_create(q->hwe, q->vm, SZ_16K, q->msix_vec, flags); 143 124 if (IS_ERR(q->lrc[i])) { 144 125 err = PTR_ERR(q->lrc[i]); 145 126 goto err_unlock; ··· 172 153 struct xe_exec_queue *q; 173 154 int err; 174 155 156 + /* VMs for GSCCS queues (and only those) must have the XE_VM_FLAG_GSC flag */ 157 + xe_assert(xe, !vm || (!!(vm->flags & XE_VM_FLAG_GSC) == !!(hwe->engine_id == XE_HW_ENGINE_GSCCS0))); 158 + 175 159 q = __xe_exec_queue_alloc(xe, vm, logical_mask, width, hwe, flags, 176 160 extensions); 177 161 if (IS_ERR(q)) ··· 183 161 err = __xe_exec_queue_init(q); 184 162 if (err) 185 163 goto err_post_alloc; 164 + 165 + /* 166 + * We can only add the queue to the PXP list after the init is complete, 167 + * because the PXP termination can call exec_queue_kill and that will 168 + * go bad if the queue is only half-initialized. This means that we 169 + * can't do it when we handle the PXP extension in __xe_exec_queue_alloc 170 + * and we need to do it here instead. 171 + */ 172 + if (xe_exec_queue_uses_pxp(q)) { 173 + err = xe_pxp_exec_queue_add(xe->pxp, q); 174 + if (err) 175 + goto err_post_alloc; 176 + } 186 177 187 178 return q; 188 179 ··· 284 249 { 285 250 struct xe_exec_queue *q = container_of(ref, struct xe_exec_queue, refcount); 286 251 struct xe_exec_queue *eq, *next; 252 + 253 + if (xe_exec_queue_uses_pxp(q)) 254 + xe_pxp_exec_queue_remove(gt_to_xe(q->gt)->pxp, q); 287 255 288 256 xe_exec_queue_last_fence_put_unlocked(q); 289 257 if (!(q->flags & EXEC_QUEUE_FLAG_BIND_ENGINE_CHILD)) { ··· 443 405 return 0; 444 406 } 445 407 408 + static int 409 + exec_queue_set_pxp_type(struct xe_device *xe, struct xe_exec_queue *q, u64 value) 410 + { 411 + if (value == DRM_XE_PXP_TYPE_NONE) 412 + return 0; 413 + 414 + /* we only support HWDRM sessions right now */ 415 + if (XE_IOCTL_DBG(xe, value != DRM_XE_PXP_TYPE_HWDRM)) 416 + return -EINVAL; 417 + 418 + if (!xe_pxp_is_enabled(xe->pxp)) 419 + return -ENODEV; 420 + 421 + return xe_pxp_exec_queue_set_type(xe->pxp, q, DRM_XE_PXP_TYPE_HWDRM); 422 + } 423 + 446 424 typedef int (*xe_exec_queue_set_property_fn)(struct xe_device *xe, 447 425 struct xe_exec_queue *q, 448 426 u64 value); ··· 466 412 static const xe_exec_queue_set_property_fn exec_queue_set_property_funcs[] = { 467 413 [DRM_XE_EXEC_QUEUE_SET_PROPERTY_PRIORITY] = exec_queue_set_priority, 468 414 [DRM_XE_EXEC_QUEUE_SET_PROPERTY_TIMESLICE] = exec_queue_set_timeslice, 415 + [DRM_XE_EXEC_QUEUE_SET_PROPERTY_PXP_TYPE] = exec_queue_set_pxp_type, 469 416 }; 470 417 471 418 static int exec_queue_user_ext_set_property(struct xe_device *xe, ··· 486 431 ARRAY_SIZE(exec_queue_set_property_funcs)) || 487 432 XE_IOCTL_DBG(xe, ext.pad) || 488 433 XE_IOCTL_DBG(xe, ext.property != DRM_XE_EXEC_QUEUE_SET_PROPERTY_PRIORITY && 489 - ext.property != DRM_XE_EXEC_QUEUE_SET_PROPERTY_TIMESLICE)) 434 + ext.property != DRM_XE_EXEC_QUEUE_SET_PROPERTY_TIMESLICE && 435 + ext.property != DRM_XE_EXEC_QUEUE_SET_PROPERTY_PXP_TYPE)) 490 436 return -EINVAL; 491 437 492 438 idx = array_index_nospec(ext.property, ARRAY_SIZE(exec_queue_set_property_funcs)); ··· 539 483 return 0; 540 484 } 541 485 542 - static u32 calc_validate_logical_mask(struct xe_device *xe, struct xe_gt *gt, 486 + static u32 calc_validate_logical_mask(struct xe_device *xe, 543 487 struct drm_xe_engine_class_instance *eci, 544 488 u16 width, u16 num_placements) 545 489 { ··· 601 545 u64_to_user_ptr(args->instances); 602 546 struct xe_hw_engine *hwe; 603 547 struct xe_vm *vm; 604 - struct xe_gt *gt; 605 548 struct xe_tile *tile; 606 549 struct xe_exec_queue *q = NULL; 607 550 u32 logical_mask; ··· 653 598 &q->multi_gt_link); 654 599 } 655 600 } else { 656 - gt = xe_device_get_gt(xe, eci[0].gt_id); 657 - logical_mask = calc_validate_logical_mask(xe, gt, eci, 601 + logical_mask = calc_validate_logical_mask(xe, eci, 658 602 args->width, 659 603 args->num_placements); 660 604 if (XE_IOCTL_DBG(xe, !logical_mask))
+5
drivers/gpu/drm/xe/xe_exec_queue.h
··· 57 57 return q->width > 1; 58 58 } 59 59 60 + static inline bool xe_exec_queue_uses_pxp(struct xe_exec_queue *q) 61 + { 62 + return q->pxp.type; 63 + } 64 + 60 65 bool xe_exec_queue_is_lr(struct xe_exec_queue *q); 61 66 62 67 bool xe_exec_queue_ring_full(struct xe_exec_queue *q);
+8
drivers/gpu/drm/xe/xe_exec_queue_types.h
··· 130 130 struct list_head link; 131 131 } lr; 132 132 133 + /** @pxp: PXP info tracking */ 134 + struct { 135 + /** @pxp.type: PXP session type used by this queue */ 136 + u8 type; 137 + /** @pxp.link: link into the list of PXP exec queues */ 138 + struct list_head link; 139 + } pxp; 140 + 133 141 /** @ops: submission backend exec queue operations */ 134 142 const struct xe_exec_queue_ops *ops; 135 143
+1 -1
drivers/gpu/drm/xe/xe_execlist.c
··· 269 269 270 270 port->hwe = hwe; 271 271 272 - port->lrc = xe_lrc_create(hwe, NULL, SZ_16K, XE_IRQ_DEFAULT_MSIX); 272 + port->lrc = xe_lrc_create(hwe, NULL, SZ_16K, XE_IRQ_DEFAULT_MSIX, 0); 273 273 if (IS_ERR(port->lrc)) { 274 274 err = PTR_ERR(port->lrc); 275 275 goto err;
-9
drivers/gpu/drm/xe/xe_gsc.c
··· 555 555 flush_work(&gsc->work); 556 556 } 557 557 558 - /** 559 - * xe_gsc_remove() - Clean up the GSC structures before driver removal 560 - * @gsc: the GSC uC 561 - */ 562 - void xe_gsc_remove(struct xe_gsc *gsc) 563 - { 564 - xe_gsc_proxy_remove(gsc); 565 - } 566 - 567 558 /* 568 559 * wa_14015076503: if the GSC FW is loaded, we need to alert it before doing a 569 560 * GSC engine reset by writing a notification bit in the GS1 register and then
-1
drivers/gpu/drm/xe/xe_gsc.h
··· 17 17 int xe_gsc_init_post_hwconfig(struct xe_gsc *gsc); 18 18 void xe_gsc_wait_for_worker_completion(struct xe_gsc *gsc); 19 19 void xe_gsc_load_start(struct xe_gsc *gsc); 20 - void xe_gsc_remove(struct xe_gsc *gsc); 21 20 void xe_gsc_hwe_irq_handler(struct xe_hw_engine *hwe, u16 intr_vec); 22 21 23 22 void xe_gsc_wa_14015076503(struct xe_gt *gt, bool prep);
+29 -34
drivers/gpu/drm/xe/xe_gsc_proxy.c
··· 423 423 return 0; 424 424 } 425 425 426 + static void xe_gsc_proxy_remove(void *arg) 427 + { 428 + struct xe_gsc *gsc = arg; 429 + struct xe_gt *gt = gsc_to_gt(gsc); 430 + struct xe_device *xe = gt_to_xe(gt); 431 + unsigned int fw_ref = 0; 432 + 433 + if (!gsc->proxy.component_added) 434 + return; 435 + 436 + /* disable HECI2 IRQs */ 437 + xe_pm_runtime_get(xe); 438 + fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GSC); 439 + if (!fw_ref) 440 + xe_gt_err(gt, "failed to get forcewake to disable GSC interrupts\n"); 441 + 442 + /* try do disable irq even if forcewake failed */ 443 + gsc_proxy_irq_toggle(gsc, false); 444 + 445 + xe_force_wake_put(gt_to_fw(gt), fw_ref); 446 + xe_pm_runtime_put(xe); 447 + 448 + xe_gsc_wait_for_worker_completion(gsc); 449 + 450 + component_del(xe->drm.dev, &xe_gsc_proxy_component_ops); 451 + gsc->proxy.component_added = false; 452 + } 453 + 426 454 /** 427 455 * xe_gsc_proxy_init() - init objects and MEI component required by GSC proxy 428 456 * @gsc: the GSC uC ··· 490 462 491 463 gsc->proxy.component_added = true; 492 464 493 - /* the component must be removed before unload, so can't use drmm for cleanup */ 494 - 495 - return 0; 496 - } 497 - 498 - /** 499 - * xe_gsc_proxy_remove() - remove the GSC proxy MEI component 500 - * @gsc: the GSC uC 501 - */ 502 - void xe_gsc_proxy_remove(struct xe_gsc *gsc) 503 - { 504 - struct xe_gt *gt = gsc_to_gt(gsc); 505 - struct xe_device *xe = gt_to_xe(gt); 506 - unsigned int fw_ref = 0; 507 - 508 - if (!gsc->proxy.component_added) 509 - return; 510 - 511 - /* disable HECI2 IRQs */ 512 - xe_pm_runtime_get(xe); 513 - fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GSC); 514 - if (!fw_ref) 515 - xe_gt_err(gt, "failed to get forcewake to disable GSC interrupts\n"); 516 - 517 - /* try do disable irq even if forcewake failed */ 518 - gsc_proxy_irq_toggle(gsc, false); 519 - 520 - xe_force_wake_put(gt_to_fw(gt), fw_ref); 521 - xe_pm_runtime_put(xe); 522 - 523 - xe_gsc_wait_for_worker_completion(gsc); 524 - 525 - component_del(xe->drm.dev, &xe_gsc_proxy_component_ops); 526 - gsc->proxy.component_added = false; 465 + return xe_device_add_action_or_reset(xe, xe_gsc_proxy_remove, gsc); 527 466 } 528 467 529 468 /**
-1
drivers/gpu/drm/xe/xe_gsc_proxy.h
··· 12 12 13 13 int xe_gsc_proxy_init(struct xe_gsc *gsc); 14 14 bool xe_gsc_proxy_init_done(struct xe_gsc *gsc); 15 - void xe_gsc_proxy_remove(struct xe_gsc *gsc); 16 15 int xe_gsc_proxy_start(struct xe_gsc *gsc); 17 16 18 17 int xe_gsc_proxy_request_handler(struct xe_gsc *gsc);
+1
drivers/gpu/drm/xe/xe_gsc_types.h
··· 13 13 #include <linux/workqueue.h> 14 14 15 15 #include "xe_uc_fw_types.h" 16 + #include "xe_device_types.h" 16 17 17 18 struct xe_bo; 18 19 struct xe_exec_queue;
+29 -35
drivers/gpu/drm/xe/xe_gt.c
··· 32 32 #include "xe_gt_pagefault.h" 33 33 #include "xe_gt_printk.h" 34 34 #include "xe_gt_sriov_pf.h" 35 + #include "xe_gt_sriov_vf.h" 35 36 #include "xe_gt_sysfs.h" 36 37 #include "xe_gt_tlb_invalidation.h" 37 38 #include "xe_gt_topology.h" ··· 139 138 xe_gt_mcr_multicast_write(gt, XE2_GAMREQSTRM_CTRL, reg); 140 139 141 140 xe_force_wake_put(gt_to_fw(gt), fw_ref); 142 - } 143 - 144 - /** 145 - * xe_gt_remove() - Clean up the GT structures before driver removal 146 - * @gt: the GT object 147 - * 148 - * This function should only act on objects/structures that must be cleaned 149 - * before the driver removal callback is complete and therefore can't be 150 - * deferred to a drmm action. 151 - */ 152 - void xe_gt_remove(struct xe_gt *gt) 153 - { 154 - int i; 155 - 156 - xe_uc_remove(&gt->uc); 157 - 158 - for (i = 0; i < XE_ENGINE_CLASS_MAX; ++i) 159 - xe_hw_fence_irq_finish(&gt->fence_irq[i]); 160 - 161 - xe_gt_disable_host_l2_vram(gt); 162 141 } 163 142 164 143 static void gt_reset_worker(struct work_struct *w); ··· 389 408 static int gt_fw_domain_init(struct xe_gt *gt) 390 409 { 391 410 unsigned int fw_ref; 392 - int err, i; 411 + int err; 393 412 394 413 fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT); 395 - if (!fw_ref) { 396 - err = -ETIMEDOUT; 397 - goto err_hw_fence_irq; 398 - } 414 + if (!fw_ref) 415 + return -ETIMEDOUT; 399 416 400 417 if (!xe_gt_is_media_type(gt)) { 401 418 err = xe_ggtt_init(gt_to_tile(gt)->mem.ggtt); ··· 434 455 err_force_wake: 435 456 dump_pat_on_error(gt); 436 457 xe_force_wake_put(gt_to_fw(gt), fw_ref); 437 - err_hw_fence_irq: 438 - for (i = 0; i < XE_ENGINE_CLASS_MAX; ++i) 439 - xe_hw_fence_irq_finish(&gt->fence_irq[i]); 440 458 441 459 return err; 442 460 } ··· 441 465 static int all_fw_domain_init(struct xe_gt *gt) 442 466 { 443 467 unsigned int fw_ref; 444 - int err, i; 468 + int err; 445 469 446 470 fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FORCEWAKE_ALL); 447 471 if (!xe_force_wake_ref_has_domain(fw_ref, XE_FORCEWAKE_ALL)) { ··· 519 543 520 544 err_force_wake: 521 545 xe_force_wake_put(gt_to_fw(gt), fw_ref); 522 - for (i = 0; i < XE_ENGINE_CLASS_MAX; ++i) 523 - xe_hw_fence_irq_finish(&gt->fence_irq[i]); 524 546 525 547 return err; 526 548 } ··· 556 582 return err; 557 583 } 558 584 585 + static void xe_gt_fini(void *arg) 586 + { 587 + struct xe_gt *gt = arg; 588 + int i; 589 + 590 + for (i = 0; i < XE_ENGINE_CLASS_MAX; ++i) 591 + xe_hw_fence_irq_finish(&gt->fence_irq[i]); 592 + 593 + xe_gt_disable_host_l2_vram(gt); 594 + } 595 + 559 596 int xe_gt_init(struct xe_gt *gt) 560 597 { 561 598 int err; ··· 578 593 gt->ring_ops[i] = xe_ring_ops_get(gt, i); 579 594 xe_hw_fence_irq_init(&gt->fence_irq[i]); 580 595 } 596 + 597 + err = devm_add_action_or_reset(gt_to_xe(gt)->drm.dev, xe_gt_fini, gt); 598 + if (err) 599 + return err; 581 600 582 601 err = xe_gt_pagefault_init(gt); 583 602 if (err) ··· 626 637 void xe_gt_mmio_init(struct xe_gt *gt) 627 638 { 628 639 struct xe_tile *tile = gt_to_tile(gt); 640 + struct xe_device *xe = tile_to_xe(tile); 629 641 630 - gt->mmio.regs = tile->mmio.regs; 631 - gt->mmio.regs_size = tile->mmio.regs_size; 632 - gt->mmio.tile = tile; 642 + xe_mmio_init(&gt->mmio, tile, tile->mmio.regs, tile->mmio.regs_size); 633 643 634 644 if (gt->info.type == XE_GT_TYPE_MEDIA) { 635 645 gt->mmio.adj_offset = MEDIA_GT_GSI_OFFSET; 636 646 gt->mmio.adj_limit = MEDIA_GT_GSI_LENGTH; 647 + } else { 648 + gt->mmio.adj_offset = 0; 649 + gt->mmio.adj_limit = 0; 637 650 } 638 651 639 - if (IS_SRIOV_VF(gt_to_xe(gt))) 652 + if (IS_SRIOV_VF(xe)) 640 653 gt->mmio.sriov_vf_gt = gt; 641 654 } 642 655 ··· 666 675 static int do_gt_reset(struct xe_gt *gt) 667 676 { 668 677 int err; 678 + 679 + if (IS_SRIOV_VF(gt_to_xe(gt))) 680 + return xe_gt_sriov_vf_reset(gt); 669 681 670 682 xe_gsc_wa_14015076503(gt, true); 671 683
-1
drivers/gpu/drm/xe/xe_gt.h
··· 54 54 void xe_gt_reset_async(struct xe_gt *gt); 55 55 void xe_gt_sanitize(struct xe_gt *gt); 56 56 int xe_gt_sanitize_freq(struct xe_gt *gt); 57 - void xe_gt_remove(struct xe_gt *gt); 58 57 59 58 /** 60 59 * xe_gt_wait_for_reset - wait for gt's async reset to finalize.
+20 -3
drivers/gpu/drm/xe/xe_gt_idle.c
··· 69 69 { 70 70 u64 delta, overflow_residency, prev_residency; 71 71 72 + lockdep_assert_held(&gtidle->lock); 73 + 72 74 overflow_residency = BIT_ULL(32); 73 75 74 76 /* ··· 277 275 278 276 return sysfs_emit(buff, "%s\n", gt_idle_state_to_string(state)); 279 277 } 280 - static DEVICE_ATTR_RO(idle_status); 281 278 279 + u64 xe_gt_idle_residency_msec(struct xe_gt_idle *gtidle) 280 + { 281 + struct xe_guc_pc *pc = gtidle_to_pc(gtidle); 282 + u64 residency; 283 + unsigned long flags; 284 + 285 + raw_spin_lock_irqsave(&gtidle->lock, flags); 286 + residency = get_residency_ms(gtidle, gtidle->idle_residency(pc)); 287 + raw_spin_unlock_irqrestore(&gtidle->lock, flags); 288 + 289 + return residency; 290 + } 291 + 292 + static DEVICE_ATTR_RO(idle_status); 282 293 static ssize_t idle_residency_ms_show(struct device *dev, 283 294 struct device_attribute *attr, char *buff) 284 295 { ··· 300 285 u64 residency; 301 286 302 287 xe_pm_runtime_get(pc_to_xe(pc)); 303 - residency = gtidle->idle_residency(pc); 288 + residency = xe_gt_idle_residency_msec(gtidle); 304 289 xe_pm_runtime_put(pc_to_xe(pc)); 305 290 306 - return sysfs_emit(buff, "%llu\n", get_residency_ms(gtidle, residency)); 291 + return sysfs_emit(buff, "%llu\n", residency); 307 292 } 308 293 static DEVICE_ATTR_RO(idle_residency_ms); 309 294 ··· 345 330 kobj = kobject_create_and_add("gtidle", gt->sysfs); 346 331 if (!kobj) 347 332 return -ENOMEM; 333 + 334 + raw_spin_lock_init(&gtidle->lock); 348 335 349 336 if (xe_gt_is_media_type(gt)) { 350 337 snprintf(gtidle->name, sizeof(gtidle->name), "gt%d-mc", gt->info.id);
+1
drivers/gpu/drm/xe/xe_gt_idle.h
··· 17 17 void xe_gt_idle_enable_pg(struct xe_gt *gt); 18 18 void xe_gt_idle_disable_pg(struct xe_gt *gt); 19 19 int xe_gt_idle_pg_print(struct xe_gt *gt, struct drm_printer *p); 20 + u64 xe_gt_idle_residency_msec(struct xe_gt_idle *gtidle); 20 21 21 22 #endif /* _XE_GT_IDLE_H_ */
+3
drivers/gpu/drm/xe/xe_gt_idle_types.h
··· 6 6 #ifndef _XE_GT_IDLE_SYSFS_TYPES_H_ 7 7 #define _XE_GT_IDLE_SYSFS_TYPES_H_ 8 8 9 + #include <linux/spinlock.h> 9 10 #include <linux/types.h> 10 11 11 12 struct xe_guc_pc; ··· 32 31 u64 cur_residency; 33 32 /** @prev_residency: previous residency counter */ 34 33 u64 prev_residency; 34 + /** @lock: Lock protecting idle residency counters */ 35 + raw_spinlock_t lock; 35 36 /** @idle_status: get the current idle state */ 36 37 enum xe_gt_idle_state (*idle_status)(struct xe_guc_pc *pc); 37 38 /** @idle_residency: get idle residency counter */
+7 -1
drivers/gpu/drm/xe/xe_gt_mcr.c
··· 341 341 return DIV_ROUND_UP(max_subslices, max_slices); 342 342 343 343 fallback: 344 - xe_gt_dbg(gt, "GuC hwconfig cannot provide dss/slice; using typical fallback values\n"); 344 + /* 345 + * Some older platforms don't have tables or don't have complete tables. 346 + * Newer platforms should always have the required info. 347 + */ 348 + if (GRAPHICS_VERx100(gt_to_xe(gt)) >= 2000) 349 + xe_gt_err(gt, "Slice/Subslice counts missing from hwconfig table; using typical fallback values\n"); 350 + 345 351 if (gt_to_xe(gt)->info.platform == XE_PVC) 346 352 return 8; 347 353 else if (GRAPHICS_VERx100(gt_to_xe(gt)) >= 1250)
+10 -5
drivers/gpu/drm/xe/xe_gt_pagefault.c
··· 14 14 #include "abi/guc_actions_abi.h" 15 15 #include "xe_bo.h" 16 16 #include "xe_gt.h" 17 + #include "xe_gt_stats.h" 17 18 #include "xe_gt_tlb_invalidation.h" 18 19 #include "xe_guc.h" 19 20 #include "xe_guc_ct.h" ··· 125 124 return 0; 126 125 } 127 126 128 - static int handle_vma_pagefault(struct xe_tile *tile, struct pagefault *pf, 127 + static int handle_vma_pagefault(struct xe_gt *gt, struct pagefault *pf, 129 128 struct xe_vma *vma) 130 129 { 131 130 struct xe_vm *vm = xe_vma_vm(vma); 131 + struct xe_tile *tile = gt_to_tile(gt); 132 132 struct drm_exec exec; 133 133 struct dma_fence *fence; 134 134 ktime_t end = 0; 135 135 int err; 136 136 bool atomic; 137 + 138 + xe_gt_stats_incr(gt, XE_GT_STATS_ID_VMA_PAGEFAULT_COUNT, 1); 139 + xe_gt_stats_incr(gt, XE_GT_STATS_ID_VMA_PAGEFAULT_BYTES, xe_vma_size(vma)); 137 140 138 141 trace_xe_vma_pagefault(vma); 139 142 atomic = access_is_atomic(pf->access_type); ··· 207 202 static int handle_pagefault(struct xe_gt *gt, struct pagefault *pf) 208 203 { 209 204 struct xe_device *xe = gt_to_xe(gt); 210 - struct xe_tile *tile = gt_to_tile(gt); 211 205 struct xe_vm *vm; 212 206 struct xe_vma *vma = NULL; 213 207 int err; ··· 235 231 goto unlock_vm; 236 232 } 237 233 238 - err = handle_vma_pagefault(tile, pf, vma); 234 + err = handle_vma_pagefault(gt, pf, vma); 239 235 240 236 unlock_vm: 241 237 if (!err) ··· 267 263 "\tFaultType: %d\n" 268 264 "\tAccessType: %d\n" 269 265 "\tFaultLevel: %d\n" 270 - "\tEngineClass: %d\n" 266 + "\tEngineClass: %d %s\n" 271 267 "\tEngineInstance: %d\n", 272 268 pf->asid, pf->vfid, pf->pdata, upper_32_bits(pf->page_addr), 273 269 lower_32_bits(pf->page_addr), 274 270 pf->fault_type, pf->access_type, pf->fault_level, 275 - pf->engine_class, pf->engine_instance); 271 + pf->engine_class, xe_hw_engine_class_to_str(pf->engine_class), 272 + pf->engine_instance); 276 273 } 277 274 278 275 #define PF_MSG_LEN_DW 4
+47 -2
drivers/gpu/drm/xe/xe_gt_sriov_pf.c
··· 15 15 #include "xe_gt_sriov_pf_helpers.h" 16 16 #include "xe_gt_sriov_pf_migration.h" 17 17 #include "xe_gt_sriov_pf_service.h" 18 + #include "xe_gt_sriov_printk.h" 18 19 #include "xe_mmio.h" 20 + #include "xe_pm.h" 21 + 22 + static void pf_worker_restart_func(struct work_struct *w); 19 23 20 24 /* 21 25 * VF's metadata is maintained in the flexible array where: ··· 43 39 return -ENOMEM; 44 40 45 41 return 0; 42 + } 43 + 44 + static void pf_init_workers(struct xe_gt *gt) 45 + { 46 + INIT_WORK(&gt->sriov.pf.workers.restart, pf_worker_restart_func); 46 47 } 47 48 48 49 /** ··· 74 65 if (err) 75 66 return err; 76 67 68 + pf_init_workers(gt); 69 + 77 70 return 0; 78 71 } 79 72 ··· 89 78 */ 90 79 int xe_gt_sriov_pf_init(struct xe_gt *gt) 91 80 { 81 + int err; 82 + 83 + err = xe_gt_sriov_pf_config_init(gt); 84 + if (err) 85 + return err; 86 + 92 87 return xe_gt_sriov_pf_migration_init(gt); 93 88 } 94 89 ··· 172 155 pf_clear_vf_scratch_regs(gt, vfid); 173 156 } 174 157 158 + static void pf_restart(struct xe_gt *gt) 159 + { 160 + struct xe_device *xe = gt_to_xe(gt); 161 + 162 + xe_pm_runtime_get(xe); 163 + xe_gt_sriov_pf_config_restart(gt); 164 + xe_gt_sriov_pf_control_restart(gt); 165 + xe_pm_runtime_put(xe); 166 + 167 + xe_gt_sriov_dbg(gt, "restart completed\n"); 168 + } 169 + 170 + static void pf_worker_restart_func(struct work_struct *w) 171 + { 172 + struct xe_gt *gt = container_of(w, typeof(*gt), sriov.pf.workers.restart); 173 + 174 + pf_restart(gt); 175 + } 176 + 177 + static void pf_queue_restart(struct xe_gt *gt) 178 + { 179 + struct xe_device *xe = gt_to_xe(gt); 180 + 181 + xe_gt_assert(gt, IS_SRIOV_PF(xe)); 182 + 183 + if (!queue_work(xe->sriov.wq, &gt->sriov.pf.workers.restart)) 184 + xe_gt_sriov_dbg(gt, "restart already in queue!\n"); 185 + } 186 + 175 187 /** 176 188 * xe_gt_sriov_pf_restart - Restart SR-IOV support after a GT reset. 177 189 * @gt: the &xe_gt ··· 209 163 */ 210 164 void xe_gt_sriov_pf_restart(struct xe_gt *gt) 211 165 { 212 - xe_gt_sriov_pf_config_restart(gt); 213 - xe_gt_sriov_pf_control_restart(gt); 166 + pf_queue_restart(gt); 214 167 }
+113 -48
drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c
··· 20 20 #include "xe_gt_sriov_pf_policy.h" 21 21 #include "xe_gt_sriov_printk.h" 22 22 #include "xe_guc.h" 23 + #include "xe_guc_buf.h" 23 24 #include "xe_guc_ct.h" 24 25 #include "xe_guc_db_mgr.h" 25 26 #include "xe_guc_fwif.h" ··· 72 71 * Return: number of KLVs that were successfully parsed and saved, 73 72 * negative error code on failure. 74 73 */ 75 - static int pf_send_vf_cfg_klvs(struct xe_gt *gt, u32 vfid, const u32 *klvs, u32 num_dwords) 74 + static int pf_send_vf_buf_klvs(struct xe_gt *gt, u32 vfid, struct xe_guc_buf buf, u32 num_dwords) 76 75 { 77 - const u32 bytes = num_dwords * sizeof(u32); 78 - struct xe_tile *tile = gt_to_tile(gt); 79 - struct xe_device *xe = tile_to_xe(tile); 80 76 struct xe_guc *guc = &gt->uc.guc; 81 - struct xe_bo *bo; 82 - int ret; 83 77 84 - bo = xe_bo_create_pin_map(xe, tile, NULL, 85 - ALIGN(bytes, PAGE_SIZE), 86 - ttm_bo_type_kernel, 87 - XE_BO_FLAG_VRAM_IF_DGFX(tile) | 88 - XE_BO_FLAG_GGTT | 89 - XE_BO_FLAG_GGTT_INVALIDATE); 90 - if (IS_ERR(bo)) 91 - return PTR_ERR(bo); 92 - 93 - xe_map_memcpy_to(xe, &bo->vmap, 0, klvs, bytes); 94 - 95 - ret = guc_action_update_vf_cfg(guc, vfid, xe_bo_ggtt_addr(bo), num_dwords); 96 - 97 - xe_bo_unpin_map_no_vm(bo); 98 - 99 - return ret; 78 + return guc_action_update_vf_cfg(guc, vfid, xe_guc_buf_flush(buf), num_dwords); 100 79 } 101 80 102 81 /* 103 82 * Return: 0 on success, -ENOKEY if some KLVs were not updated, -EPROTO if reply was malformed, 104 83 * negative error code on failure. 105 84 */ 106 - static int pf_push_vf_cfg_klvs(struct xe_gt *gt, unsigned int vfid, u32 num_klvs, 107 - const u32 *klvs, u32 num_dwords) 85 + static int pf_push_vf_buf_klvs(struct xe_gt *gt, unsigned int vfid, u32 num_klvs, 86 + struct xe_guc_buf buf, u32 num_dwords) 108 87 { 109 88 int ret; 110 89 111 - xe_gt_assert(gt, num_klvs == xe_guc_klv_count(klvs, num_dwords)); 112 - 113 - ret = pf_send_vf_cfg_klvs(gt, vfid, klvs, num_dwords); 90 + ret = pf_send_vf_buf_klvs(gt, vfid, buf, num_dwords); 114 91 115 92 if (ret != num_klvs) { 116 93 int err = ret < 0 ? ret : ret < num_klvs ? -ENOKEY : -EPROTO; 94 + void *klvs = xe_guc_buf_cpu_ptr(buf); 117 95 struct drm_printer p = xe_gt_info_printer(gt); 118 96 char name[8]; 119 97 ··· 105 125 106 126 if (IS_ENABLED(CONFIG_DRM_XE_DEBUG_SRIOV)) { 107 127 struct drm_printer p = xe_gt_info_printer(gt); 128 + void *klvs = xe_guc_buf_cpu_ptr(buf); 129 + char name[8]; 108 130 131 + xe_gt_sriov_info(gt, "pushed %s config with %u KLV%s:\n", 132 + xe_sriov_function_name(vfid, name, sizeof(name)), 133 + num_klvs, str_plural(num_klvs)); 109 134 xe_guc_klv_print(klvs, num_dwords, &p); 110 135 } 111 136 112 137 return 0; 138 + } 139 + 140 + /* 141 + * Return: 0 on success, -ENOBUFS if no free buffer for the indirect data, 142 + * negative error code on failure. 143 + */ 144 + static int pf_push_vf_cfg_klvs(struct xe_gt *gt, unsigned int vfid, u32 num_klvs, 145 + const u32 *klvs, u32 num_dwords) 146 + { 147 + CLASS(xe_guc_buf_from_data, buf)(&gt->uc.guc.buf, klvs, num_dwords * sizeof(u32)); 148 + 149 + xe_gt_assert(gt, num_klvs == xe_guc_klv_count(klvs, num_dwords)); 150 + 151 + if (!xe_guc_buf_is_valid(buf)) 152 + return -ENOBUFS; 153 + 154 + return pf_push_vf_buf_klvs(gt, vfid, num_klvs, buf, num_dwords); 113 155 } 114 156 115 157 static int pf_push_vf_cfg_u32(struct xe_gt *gt, unsigned int vfid, u16 key, u32 value) ··· 264 262 265 263 n += encode_config_ggtt(cfg, config, details); 266 264 267 - if (details) { 265 + if (details && config->num_ctxs) { 268 266 cfg[n++] = PREP_GUC_KLV_TAG(VF_CFG_BEGIN_CONTEXT_ID); 269 267 cfg[n++] = config->begin_ctx; 270 268 } ··· 272 270 cfg[n++] = PREP_GUC_KLV_TAG(VF_CFG_NUM_CONTEXTS); 273 271 cfg[n++] = config->num_ctxs; 274 272 275 - if (details) { 273 + if (details && config->num_dbs) { 276 274 cfg[n++] = PREP_GUC_KLV_TAG(VF_CFG_BEGIN_DOORBELL_ID); 277 275 cfg[n++] = config->begin_db; 278 276 } ··· 306 304 static int pf_push_full_vf_config(struct xe_gt *gt, unsigned int vfid) 307 305 { 308 306 struct xe_gt_sriov_config *config = pf_pick_vf_config(gt, vfid); 309 - u32 max_cfg_dwords = SZ_4K / sizeof(u32); 307 + u32 max_cfg_dwords = xe_guc_buf_cache_dwords(&gt->uc.guc.buf); 308 + CLASS(xe_guc_buf, buf)(&gt->uc.guc.buf, max_cfg_dwords); 310 309 u32 num_dwords; 311 310 int num_klvs; 312 311 u32 *cfg; 313 312 int err; 314 313 315 - cfg = kcalloc(max_cfg_dwords, sizeof(u32), GFP_KERNEL); 316 - if (!cfg) 317 - return -ENOMEM; 314 + if (!xe_guc_buf_is_valid(buf)) 315 + return -ENOBUFS; 318 316 317 + cfg = xe_guc_buf_cpu_ptr(buf); 319 318 num_dwords = encode_config(cfg, config, true); 320 319 xe_gt_assert(gt, num_dwords <= max_cfg_dwords); 321 320 ··· 333 330 xe_gt_assert(gt, num_dwords <= max_cfg_dwords); 334 331 335 332 num_klvs = xe_guc_klv_count(cfg, num_dwords); 336 - err = pf_push_vf_cfg_klvs(gt, vfid, num_klvs, cfg, num_dwords); 333 + err = pf_push_vf_buf_klvs(gt, vfid, num_klvs, buf, num_dwords); 337 334 338 - kfree(cfg); 339 335 return err; 336 + } 337 + 338 + static int pf_push_vf_cfg(struct xe_gt *gt, unsigned int vfid, bool reset) 339 + { 340 + int err = 0; 341 + 342 + xe_gt_assert(gt, vfid); 343 + lockdep_assert_held(xe_gt_sriov_pf_master_mutex(gt)); 344 + 345 + if (reset) 346 + err = pf_send_vf_cfg_reset(gt, vfid); 347 + if (!err) 348 + err = pf_push_full_vf_config(gt, vfid); 349 + 350 + return err; 351 + } 352 + 353 + static int pf_refresh_vf_cfg(struct xe_gt *gt, unsigned int vfid) 354 + { 355 + return pf_push_vf_cfg(gt, vfid, true); 340 356 } 341 357 342 358 static u64 pf_get_ggtt_alignment(struct xe_gt *gt) ··· 454 432 return err; 455 433 456 434 pf_release_vf_config_ggtt(gt, config); 435 + 436 + err = pf_refresh_vf_cfg(gt, vfid); 437 + if (unlikely(err)) 438 + return err; 457 439 } 458 440 xe_gt_assert(gt, !xe_ggtt_node_allocated(config->ggtt_region)); 459 441 ··· 783 757 return ret; 784 758 785 759 pf_release_config_ctxs(gt, config); 760 + 761 + ret = pf_refresh_vf_cfg(gt, vfid); 762 + if (unlikely(ret)) 763 + return ret; 786 764 } 787 765 788 766 if (!num_ctxs) ··· 1084 1054 return ret; 1085 1055 1086 1056 pf_release_config_dbs(gt, config); 1057 + 1058 + ret = pf_refresh_vf_cfg(gt, vfid); 1059 + if (unlikely(ret)) 1060 + return ret; 1087 1061 } 1088 1062 1089 1063 if (!num_dbs) ··· 1336 1302 struct xe_tile *tile; 1337 1303 unsigned int tid; 1338 1304 1339 - xe_assert(xe, IS_DGFX(xe)); 1305 + xe_assert(xe, xe_device_has_lmtt(xe)); 1340 1306 xe_assert(xe, IS_SRIOV_PF(xe)); 1341 1307 1342 1308 for_each_tile(tile, xe, tid) { ··· 1357 1323 unsigned int tid; 1358 1324 int err; 1359 1325 1360 - xe_assert(xe, IS_DGFX(xe)); 1326 + xe_assert(xe, xe_device_has_lmtt(xe)); 1361 1327 xe_assert(xe, IS_SRIOV_PF(xe)); 1362 1328 1363 1329 total = 0; ··· 1434 1400 if (unlikely(err)) 1435 1401 return err; 1436 1402 1437 - pf_reset_vf_lmtt(xe, vfid); 1403 + if (xe_device_has_lmtt(xe)) 1404 + pf_reset_vf_lmtt(xe, vfid); 1438 1405 pf_release_vf_config_lmem(gt, config); 1439 1406 } 1440 1407 xe_gt_assert(gt, !config->lmem_obj); ··· 1455 1420 1456 1421 config->lmem_obj = bo; 1457 1422 1458 - err = pf_update_vf_lmtt(xe, vfid); 1459 - if (unlikely(err)) 1460 - goto release; 1423 + if (xe_device_has_lmtt(xe)) { 1424 + err = pf_update_vf_lmtt(xe, vfid); 1425 + if (unlikely(err)) 1426 + goto release; 1427 + } 1461 1428 1462 1429 err = pf_push_vf_cfg_lmem(gt, vfid, bo->size); 1463 1430 if (unlikely(err)) ··· 1470 1433 return 0; 1471 1434 1472 1435 reset_lmtt: 1473 - pf_reset_vf_lmtt(xe, vfid); 1436 + if (xe_device_has_lmtt(xe)) 1437 + pf_reset_vf_lmtt(xe, vfid); 1474 1438 release: 1475 1439 pf_release_vf_config_lmem(gt, config); 1476 1440 return err; ··· 1564 1526 { 1565 1527 struct xe_tile *tile = gt->tile; 1566 1528 1567 - return xe_ttm_vram_get_avail(&tile->mem.vram_mgr->manager); 1529 + return xe_ttm_vram_get_avail(&tile->mem.vram.ttm.manager); 1568 1530 } 1569 1531 1570 1532 static u64 pf_query_max_lmem(struct xe_gt *gt) ··· 1985 1947 pf_release_vf_config_ggtt(gt, config); 1986 1948 if (IS_DGFX(xe)) { 1987 1949 pf_release_vf_config_lmem(gt, config); 1988 - pf_update_vf_lmtt(xe, vfid); 1950 + if (xe_device_has_lmtt(xe)) 1951 + pf_update_vf_lmtt(xe, vfid); 1989 1952 } 1990 1953 } 1991 1954 pf_release_config_ctxs(gt, config); ··· 2124 2085 xe_gt_assert(gt, vfid); 2125 2086 2126 2087 mutex_lock(xe_gt_sriov_pf_master_mutex(gt)); 2127 - if (refresh) 2128 - err = pf_send_vf_cfg_reset(gt, vfid); 2129 - if (!err) 2130 - err = pf_push_full_vf_config(gt, vfid); 2088 + err = pf_push_vf_cfg(gt, vfid, refresh); 2131 2089 mutex_unlock(xe_gt_sriov_pf_master_mutex(gt)); 2132 2090 2133 2091 if (unlikely(err)) { ··· 2354 2318 mutex_unlock(xe_gt_sriov_pf_master_mutex(gt)); 2355 2319 2356 2320 return err; 2321 + } 2322 + 2323 + static void fini_config(void *arg) 2324 + { 2325 + struct xe_gt *gt = arg; 2326 + struct xe_device *xe = gt_to_xe(gt); 2327 + unsigned int n, total_vfs = xe_sriov_pf_get_totalvfs(xe); 2328 + 2329 + mutex_lock(xe_gt_sriov_pf_master_mutex(gt)); 2330 + for (n = 1; n <= total_vfs; n++) 2331 + pf_release_vf_config(gt, n); 2332 + mutex_unlock(xe_gt_sriov_pf_master_mutex(gt)); 2333 + } 2334 + 2335 + /** 2336 + * xe_gt_sriov_pf_config_init - Initialize SR-IOV configuration data. 2337 + * @gt: the &xe_gt 2338 + * 2339 + * This function can only be called on PF. 2340 + * 2341 + * Return: 0 on success or a negative error code on failure. 2342 + */ 2343 + int xe_gt_sriov_pf_config_init(struct xe_gt *gt) 2344 + { 2345 + struct xe_device *xe = gt_to_xe(gt); 2346 + 2347 + xe_gt_assert(gt, IS_SRIOV_PF(xe)); 2348 + 2349 + return devm_add_action_or_reset(xe->drm.dev, fini_config, gt); 2357 2350 } 2358 2351 2359 2352 /**
+1
drivers/gpu/drm/xe/xe_gt_sriov_pf_config.h
··· 63 63 64 64 bool xe_gt_sriov_pf_config_is_empty(struct xe_gt *gt, unsigned int vfid); 65 65 66 + int xe_gt_sriov_pf_config_init(struct xe_gt *gt); 66 67 void xe_gt_sriov_pf_config_restart(struct xe_gt *gt); 67 68 68 69 int xe_gt_sriov_pf_config_print_ggtt(struct xe_gt *gt, struct drm_printer *p);
+24 -26
drivers/gpu/drm/xe/xe_gt_sriov_pf_policy.c
··· 10 10 #include "xe_gt_sriov_pf_helpers.h" 11 11 #include "xe_gt_sriov_pf_policy.h" 12 12 #include "xe_gt_sriov_printk.h" 13 + #include "xe_guc_buf.h" 13 14 #include "xe_guc_ct.h" 14 15 #include "xe_guc_klv_helpers.h" 15 16 #include "xe_pm.h" ··· 35 34 * Return: number of KLVs that were successfully parsed and saved, 36 35 * negative error code on failure. 37 36 */ 38 - static int pf_send_policy_klvs(struct xe_gt *gt, const u32 *klvs, u32 num_dwords) 37 + static int pf_send_policy_klvs(struct xe_gt *gt, struct xe_guc_buf buf, u32 num_dwords) 39 38 { 40 - const u32 bytes = num_dwords * sizeof(u32); 41 - struct xe_tile *tile = gt_to_tile(gt); 42 - struct xe_device *xe = tile_to_xe(tile); 43 39 struct xe_guc *guc = &gt->uc.guc; 44 - struct xe_bo *bo; 45 - int ret; 46 40 47 - bo = xe_bo_create_pin_map(xe, tile, NULL, 48 - ALIGN(bytes, PAGE_SIZE), 49 - ttm_bo_type_kernel, 50 - XE_BO_FLAG_VRAM_IF_DGFX(tile) | 51 - XE_BO_FLAG_GGTT); 52 - if (IS_ERR(bo)) 53 - return PTR_ERR(bo); 54 - 55 - xe_map_memcpy_to(xe, &bo->vmap, 0, klvs, bytes); 56 - 57 - ret = guc_action_update_vgt_policy(guc, xe_bo_ggtt_addr(bo), num_dwords); 58 - 59 - xe_bo_unpin_map_no_vm(bo); 60 - 61 - return ret; 41 + return guc_action_update_vgt_policy(guc, xe_guc_buf_flush(buf), num_dwords); 62 42 } 63 43 64 44 /* 65 45 * Return: 0 on success, -ENOKEY if some KLVs were not updated, -EPROTO if reply was malformed, 66 46 * negative error code on failure. 67 47 */ 68 - static int pf_push_policy_klvs(struct xe_gt *gt, u32 num_klvs, 69 - const u32 *klvs, u32 num_dwords) 48 + static int pf_push_policy_buf_klvs(struct xe_gt *gt, u32 num_klvs, 49 + struct xe_guc_buf buf, u32 num_dwords) 70 50 { 71 51 int ret; 72 52 73 - xe_gt_assert(gt, num_klvs == xe_guc_klv_count(klvs, num_dwords)); 74 - 75 - ret = pf_send_policy_klvs(gt, klvs, num_dwords); 53 + ret = pf_send_policy_klvs(gt, buf, num_dwords); 76 54 77 55 if (ret != num_klvs) { 78 56 int err = ret < 0 ? ret : ret < num_klvs ? -ENOKEY : -EPROTO; 79 57 struct drm_printer p = xe_gt_info_printer(gt); 58 + void *klvs = xe_guc_buf_cpu_ptr(buf); 80 59 81 60 xe_gt_sriov_notice(gt, "Failed to push %u policy KLV%s (%pe)\n", 82 61 num_klvs, str_plural(num_klvs), ERR_PTR(err)); ··· 65 84 } 66 85 67 86 return 0; 87 + } 88 + 89 + /* 90 + * Return: 0 on success, -ENOBUFS if there is no free buffer for the indirect data, 91 + * negative error code on failure. 92 + */ 93 + static int pf_push_policy_klvs(struct xe_gt *gt, u32 num_klvs, 94 + const u32 *klvs, u32 num_dwords) 95 + { 96 + CLASS(xe_guc_buf_from_data, buf)(&gt->uc.guc.buf, klvs, num_dwords * sizeof(u32)); 97 + 98 + xe_gt_assert(gt, num_klvs == xe_guc_klv_count(klvs, num_dwords)); 99 + 100 + if (!xe_guc_buf_is_valid(buf)) 101 + return -ENOBUFS; 102 + 103 + return pf_push_policy_buf_klvs(gt, num_klvs, buf, num_dwords); 68 104 } 69 105 70 106 static int pf_push_policy_u32(struct xe_gt *gt, u16 key, u32 value)
+22 -1
drivers/gpu/drm/xe/xe_gt_sriov_pf_service.c
··· 176 176 TIMESTAMP_OVERRIDE, /* _MMIO(0x44074) */ 177 177 }; 178 178 179 + static const struct xe_reg ver_3000_runtime_regs[] = { 180 + RPM_CONFIG0, /* _MMIO(0x0d00) */ 181 + XEHP_FUSE4, /* _MMIO(0x9114) */ 182 + MIRROR_FUSE3, /* _MMIO(0x9118) */ 183 + MIRROR_FUSE1, /* _MMIO(0x911c) */ 184 + MIRROR_L3BANK_ENABLE, /* _MMIO(0x9130) */ 185 + XELP_EU_ENABLE, /* _MMIO(0x9134) */ 186 + XELP_GT_GEOMETRY_DSS_ENABLE, /* _MMIO(0x913c) */ 187 + GT_VEBOX_VDBOX_DISABLE, /* _MMIO(0x9140) */ 188 + XEHP_GT_COMPUTE_DSS_ENABLE, /* _MMIO(0x9144) */ 189 + XEHPC_GT_COMPUTE_DSS_ENABLE_EXT,/* _MMIO(0x9148) */ 190 + XE2_GT_COMPUTE_DSS_2, /* _MMIO(0x914c) */ 191 + XE2_GT_GEOMETRY_DSS_1, /* _MMIO(0x9150) */ 192 + XE2_GT_GEOMETRY_DSS_2, /* _MMIO(0x9154) */ 193 + CTC_MODE, /* _MMIO(0xa26c) */ 194 + HUC_KERNEL_LOAD_INFO, /* _MMIO(0xc1dc) */ 195 + }; 196 + 179 197 static const struct xe_reg *pick_runtime_regs(struct xe_device *xe, unsigned int *count) 180 198 { 181 199 const struct xe_reg *regs; 182 200 183 - if (GRAPHICS_VERx100(xe) >= 2000) { 201 + if (GRAPHICS_VERx100(xe) >= 3000) { 202 + *count = ARRAY_SIZE(ver_3000_runtime_regs); 203 + regs = ver_3000_runtime_regs; 204 + } else if (GRAPHICS_VERx100(xe) >= 2000) { 184 205 *count = ARRAY_SIZE(ver_2000_runtime_regs); 185 206 regs = ver_2000_runtime_regs; 186 207 } else if (GRAPHICS_VERx100(xe) >= 1270) {
+10
drivers/gpu/drm/xe/xe_gt_sriov_pf_types.h
··· 36 36 }; 37 37 38 38 /** 39 + * struct xe_gt_sriov_pf_workers - GT level workers used by the PF. 40 + */ 41 + struct xe_gt_sriov_pf_workers { 42 + /** @restart: worker that executes actions post GT reset */ 43 + struct work_struct restart; 44 + }; 45 + 46 + /** 39 47 * struct xe_gt_sriov_pf - GT level PF virtualization data. 48 + * @workers: workers data. 40 49 * @service: service data. 41 50 * @control: control data. 42 51 * @policy: policy data. ··· 54 45 * @vfs: metadata for all VFs. 55 46 */ 56 47 struct xe_gt_sriov_pf { 48 + struct xe_gt_sriov_pf_workers workers; 57 49 struct xe_gt_sriov_pf_service service; 58 50 struct xe_gt_sriov_pf_control control; 59 51 struct xe_gt_sriov_pf_policy policy;
+19
drivers/gpu/drm/xe/xe_gt_sriov_vf.c
··· 58 58 return err; 59 59 } 60 60 61 + /** 62 + * xe_gt_sriov_vf_reset - Reset GuC VF internal state. 63 + * @gt: the &xe_gt 64 + * 65 + * It requires functional `GuC MMIO based communication`_. 66 + * 67 + * Return: 0 on success or a negative error code on failure. 68 + */ 69 + int xe_gt_sriov_vf_reset(struct xe_gt *gt) 70 + { 71 + if (!xe_device_uc_enabled(gt_to_xe(gt))) 72 + return -ENODEV; 73 + 74 + return vf_reset_guc_state(gt); 75 + } 76 + 61 77 static int guc_action_match_version(struct xe_guc *guc, 62 78 u32 wanted_branch, u32 wanted_major, u32 wanted_minor, 63 79 u32 *branch, u32 *major, u32 *minor, u32 *patch) ··· 228 212 int xe_gt_sriov_vf_bootstrap(struct xe_gt *gt) 229 213 { 230 214 int err; 215 + 216 + if (!xe_device_uc_enabled(gt_to_xe(gt))) 217 + return -ENODEV; 231 218 232 219 err = vf_reset_guc_state(gt); 233 220 if (unlikely(err))
+1
drivers/gpu/drm/xe/xe_gt_sriov_vf.h
··· 12 12 struct xe_gt; 13 13 struct xe_reg; 14 14 15 + int xe_gt_sriov_vf_reset(struct xe_gt *gt); 15 16 int xe_gt_sriov_vf_bootstrap(struct xe_gt *gt); 16 17 int xe_gt_sriov_vf_query_config(struct xe_gt *gt); 17 18 int xe_gt_sriov_vf_connect(struct xe_gt *gt);
+2
drivers/gpu/drm/xe/xe_gt_stats.c
··· 28 28 29 29 static const char *const stat_description[__XE_GT_STATS_NUM_IDS] = { 30 30 "tlb_inval_count", 31 + "vma_pagefault_count", 32 + "vma_pagefault_bytes", 31 33 }; 32 34 33 35 /**
+2
drivers/gpu/drm/xe/xe_gt_stats_types.h
··· 8 8 9 9 enum xe_gt_stats_id { 10 10 XE_GT_STATS_ID_TLB_INVAL, 11 + XE_GT_STATS_ID_VMA_PAGEFAULT_COUNT, 12 + XE_GT_STATS_ID_VMA_PAGEFAULT_BYTES, 11 13 /* must be the last entry */ 12 14 __XE_GT_STATS_NUM_IDS, 13 15 };
+13 -3
drivers/gpu/drm/xe/xe_gt_topology.c
··· 129 129 load_l3_bank_mask(struct xe_gt *gt, xe_l3_bank_mask_t l3_bank_mask) 130 130 { 131 131 struct xe_device *xe = gt_to_xe(gt); 132 - u32 fuse3 = xe_mmio_read32(&gt->mmio, MIRROR_FUSE3); 132 + struct xe_mmio *mmio = &gt->mmio; 133 + u32 fuse3 = xe_mmio_read32(mmio, MIRROR_FUSE3); 133 134 134 135 /* 135 136 * PTL platforms with media version 30.00 do not provide proper values ··· 144 143 if (XE_WA(gt, no_media_l3)) 145 144 return; 146 145 147 - if (GRAPHICS_VER(xe) >= 20) { 146 + if (GRAPHICS_VER(xe) >= 30) { 147 + xe_l3_bank_mask_t per_node = {}; 148 + u32 meml3_en = REG_FIELD_GET(XE2_NODE_ENABLE_MASK, fuse3); 149 + u32 mirror_l3bank_enable = xe_mmio_read32(mmio, MIRROR_L3BANK_ENABLE); 150 + u32 bank_val = REG_FIELD_GET(XE3_L3BANK_ENABLE, mirror_l3bank_enable); 151 + 152 + bitmap_from_arr32(per_node, &bank_val, 32); 153 + gen_l3_mask_from_pattern(xe, l3_bank_mask, per_node, 32, 154 + meml3_en); 155 + } else if (GRAPHICS_VER(xe) >= 20) { 148 156 xe_l3_bank_mask_t per_node = {}; 149 157 u32 meml3_en = REG_FIELD_GET(XE2_NODE_ENABLE_MASK, fuse3); 150 158 u32 bank_val = REG_FIELD_GET(XE2_GT_L3_MODE_MASK, fuse3); ··· 165 155 xe_l3_bank_mask_t per_node = {}; 166 156 xe_l3_bank_mask_t per_mask_bit = {}; 167 157 u32 meml3_en = REG_FIELD_GET(MEML3_EN_MASK, fuse3); 168 - u32 fuse4 = xe_mmio_read32(&gt->mmio, XEHP_FUSE4); 158 + u32 fuse4 = xe_mmio_read32(mmio, XEHP_FUSE4); 169 159 u32 bank_val = REG_FIELD_GET(GT_L3_EXC_MASK, fuse4); 170 160 171 161 bitmap_set_value8(per_mask_bit, 0x3, 0);
+5
drivers/gpu/drm/xe/xe_guc.c
··· 23 23 #include "xe_gt_sriov_vf.h" 24 24 #include "xe_gt_throttle.h" 25 25 #include "xe_guc_ads.h" 26 + #include "xe_guc_buf.h" 26 27 #include "xe_guc_capture.h" 27 28 #include "xe_guc_ct.h" 28 29 #include "xe_guc_db_mgr.h" ··· 741 740 return ret; 742 741 743 742 ret = xe_guc_pc_init(&guc->pc); 743 + if (ret) 744 + return ret; 745 + 746 + ret = xe_guc_buf_cache_init(&guc->buf); 744 747 if (ret) 745 748 return ret; 746 749
+176
drivers/gpu/drm/xe/xe_guc_buf.c
··· 1 + // SPDX-License-Identifier: MIT 2 + /* 3 + * Copyright © 2024 Intel Corporation 4 + */ 5 + 6 + #include <linux/cleanup.h> 7 + #include <drm/drm_managed.h> 8 + 9 + #include "xe_assert.h" 10 + #include "xe_bo.h" 11 + #include "xe_gt_printk.h" 12 + #include "xe_guc.h" 13 + #include "xe_guc_buf.h" 14 + #include "xe_sa.h" 15 + 16 + static struct xe_guc *cache_to_guc(struct xe_guc_buf_cache *cache) 17 + { 18 + return container_of(cache, struct xe_guc, buf); 19 + } 20 + 21 + static struct xe_gt *cache_to_gt(struct xe_guc_buf_cache *cache) 22 + { 23 + return guc_to_gt(cache_to_guc(cache)); 24 + } 25 + 26 + /** 27 + * xe_guc_buf_cache_init() - Initialize the GuC Buffer Cache. 28 + * @cache: the &xe_guc_buf_cache to initialize 29 + * 30 + * The Buffer Cache allows to obtain a reusable buffer that can be used to pass 31 + * indirect H2G data to GuC without a need to create a ad-hoc allocation. 32 + * 33 + * Return: 0 on success or a negative error code on failure. 34 + */ 35 + int xe_guc_buf_cache_init(struct xe_guc_buf_cache *cache) 36 + { 37 + struct xe_gt *gt = cache_to_gt(cache); 38 + struct xe_sa_manager *sam; 39 + 40 + /* XXX: currently it's useful only for the PF actions */ 41 + if (!IS_SRIOV_PF(gt_to_xe(gt))) 42 + return 0; 43 + 44 + sam = __xe_sa_bo_manager_init(gt_to_tile(gt), SZ_8K, 0, sizeof(u32)); 45 + if (IS_ERR(sam)) 46 + return PTR_ERR(sam); 47 + cache->sam = sam; 48 + 49 + xe_gt_dbg(gt, "reusable buffer with %u dwords at %#x for %ps\n", 50 + xe_guc_buf_cache_dwords(cache), xe_bo_ggtt_addr(sam->bo), 51 + __builtin_return_address(0)); 52 + return 0; 53 + } 54 + 55 + /** 56 + * xe_guc_buf_cache_dwords() - Number of dwords the GuC Buffer Cache supports. 57 + * @cache: the &xe_guc_buf_cache to query 58 + * 59 + * Return: a size of the largest reusable buffer (in dwords) 60 + */ 61 + u32 xe_guc_buf_cache_dwords(struct xe_guc_buf_cache *cache) 62 + { 63 + return cache->sam ? cache->sam->base.size / sizeof(u32) : 0; 64 + } 65 + 66 + /** 67 + * xe_guc_buf_reserve() - Reserve a new sub-allocation. 68 + * @cache: the &xe_guc_buf_cache where reserve sub-allocation 69 + * @dwords: the requested size of the buffer in dwords 70 + * 71 + * Use xe_guc_buf_is_valid() to check if returned buffer reference is valid. 72 + * Must use xe_guc_buf_release() to release a sub-allocation. 73 + * 74 + * Return: a &xe_guc_buf of new sub-allocation. 75 + */ 76 + struct xe_guc_buf xe_guc_buf_reserve(struct xe_guc_buf_cache *cache, u32 dwords) 77 + { 78 + struct drm_suballoc *sa; 79 + 80 + if (cache->sam) 81 + sa = __xe_sa_bo_new(cache->sam, dwords * sizeof(u32), GFP_ATOMIC); 82 + else 83 + sa = ERR_PTR(-EOPNOTSUPP); 84 + 85 + return (struct xe_guc_buf){ .sa = sa }; 86 + } 87 + 88 + /** 89 + * xe_guc_buf_from_data() - Reserve a new sub-allocation using data. 90 + * @cache: the &xe_guc_buf_cache where reserve sub-allocation 91 + * @data: the data to flush the sub-allocation 92 + * @size: the size of the data 93 + * 94 + * Similar to xe_guc_buf_reserve() but flushes @data to the GPU memory. 95 + * 96 + * Return: a &xe_guc_buf of new sub-allocation. 97 + */ 98 + struct xe_guc_buf xe_guc_buf_from_data(struct xe_guc_buf_cache *cache, 99 + const void *data, size_t size) 100 + { 101 + struct drm_suballoc *sa; 102 + 103 + sa = __xe_sa_bo_new(cache->sam, size, GFP_ATOMIC); 104 + if (!IS_ERR(sa)) 105 + memcpy(xe_sa_bo_cpu_addr(sa), data, size); 106 + 107 + return (struct xe_guc_buf){ .sa = sa }; 108 + } 109 + 110 + /** 111 + * xe_guc_buf_release() - Release a sub-allocation. 112 + * @buf: the &xe_guc_buf to release 113 + * 114 + * Releases a sub-allocation reserved by the xe_guc_buf_reserve(). 115 + */ 116 + void xe_guc_buf_release(const struct xe_guc_buf buf) 117 + { 118 + if (xe_guc_buf_is_valid(buf)) 119 + xe_sa_bo_free(buf.sa, NULL); 120 + } 121 + 122 + /** 123 + * xe_guc_buf_flush() - Copy the data from the sub-allocation to the GPU memory. 124 + * @buf: the &xe_guc_buf to flush 125 + * 126 + * Return: a GPU address of the sub-allocation. 127 + */ 128 + u64 xe_guc_buf_flush(const struct xe_guc_buf buf) 129 + { 130 + xe_sa_bo_flush_write(buf.sa); 131 + return xe_sa_bo_gpu_addr(buf.sa); 132 + } 133 + 134 + /** 135 + * xe_guc_buf_cpu_ptr() - Obtain a CPU pointer to the sub-allocation. 136 + * @buf: the &xe_guc_buf to query 137 + * 138 + * Return: a CPU pointer of the sub-allocation. 139 + */ 140 + void *xe_guc_buf_cpu_ptr(const struct xe_guc_buf buf) 141 + { 142 + return xe_sa_bo_cpu_addr(buf.sa); 143 + } 144 + 145 + /** 146 + * xe_guc_buf_gpu_addr() - Obtain a GPU address of the sub-allocation. 147 + * @buf: the &xe_guc_buf to query 148 + * 149 + * Return: a GPU address of the sub-allocation. 150 + */ 151 + u64 xe_guc_buf_gpu_addr(const struct xe_guc_buf buf) 152 + { 153 + return xe_sa_bo_gpu_addr(buf.sa); 154 + } 155 + 156 + /** 157 + * xe_guc_cache_gpu_addr_from_ptr() - Lookup a GPU address using the pointer. 158 + * @cache: the &xe_guc_buf_cache with sub-allocations 159 + * @ptr: the CPU pointer of the sub-allocation 160 + * @size: the size of the data 161 + * 162 + * Return: a GPU address on success or 0 if the pointer was unrelated. 163 + */ 164 + u64 xe_guc_cache_gpu_addr_from_ptr(struct xe_guc_buf_cache *cache, const void *ptr, u32 size) 165 + { 166 + ptrdiff_t offset = ptr - cache->sam->cpu_ptr; 167 + 168 + if (offset < 0 || offset + size > cache->sam->base.size) 169 + return 0; 170 + 171 + return cache->sam->gpu_addr + offset; 172 + } 173 + 174 + #if IS_BUILTIN(CONFIG_DRM_XE_KUNIT_TEST) 175 + #include "tests/xe_guc_buf_kunit.c" 176 + #endif
+47
drivers/gpu/drm/xe/xe_guc_buf.h
··· 1 + /* SPDX-License-Identifier: MIT */ 2 + /* 3 + * Copyright © 2024 Intel Corporation 4 + */ 5 + 6 + #ifndef _XE_GUC_BUF_H_ 7 + #define _XE_GUC_BUF_H_ 8 + 9 + #include <linux/cleanup.h> 10 + #include <linux/err.h> 11 + 12 + #include "xe_guc_buf_types.h" 13 + 14 + int xe_guc_buf_cache_init(struct xe_guc_buf_cache *cache); 15 + u32 xe_guc_buf_cache_dwords(struct xe_guc_buf_cache *cache); 16 + struct xe_guc_buf xe_guc_buf_reserve(struct xe_guc_buf_cache *cache, u32 dwords); 17 + struct xe_guc_buf xe_guc_buf_from_data(struct xe_guc_buf_cache *cache, 18 + const void *data, size_t size); 19 + void xe_guc_buf_release(const struct xe_guc_buf buf); 20 + 21 + /** 22 + * xe_guc_buf_is_valid() - Check if a buffer reference is valid. 23 + * @buf: the &xe_guc_buf reference to check 24 + * 25 + * Return: true if @ref represents a valid sub-allication. 26 + */ 27 + static inline bool xe_guc_buf_is_valid(const struct xe_guc_buf buf) 28 + { 29 + return !IS_ERR_OR_NULL(buf.sa); 30 + } 31 + 32 + void *xe_guc_buf_cpu_ptr(const struct xe_guc_buf buf); 33 + u64 xe_guc_buf_flush(const struct xe_guc_buf buf); 34 + u64 xe_guc_buf_gpu_addr(const struct xe_guc_buf buf); 35 + u64 xe_guc_cache_gpu_addr_from_ptr(struct xe_guc_buf_cache *cache, const void *ptr, u32 size); 36 + 37 + DEFINE_CLASS(xe_guc_buf, struct xe_guc_buf, 38 + xe_guc_buf_release(_T), 39 + xe_guc_buf_reserve(cache, num), 40 + struct xe_guc_buf_cache *cache, u32 num); 41 + 42 + DEFINE_CLASS(xe_guc_buf_from_data, struct xe_guc_buf, 43 + xe_guc_buf_release(_T), 44 + xe_guc_buf_from_data(cache, data, size), 45 + struct xe_guc_buf_cache *cache, const void *data, size_t size); 46 + 47 + #endif
+28
drivers/gpu/drm/xe/xe_guc_buf_types.h
··· 1 + /* SPDX-License-Identifier: MIT */ 2 + /* 3 + * Copyright © 2024 Intel Corporation 4 + */ 5 + 6 + #ifndef _XE_GUC_BUF_TYPES_H_ 7 + #define _XE_GUC_BUF_TYPES_H_ 8 + 9 + struct drm_suballoc; 10 + struct xe_sa_manager; 11 + 12 + /** 13 + * struct xe_guc_buf_cache - GuC Data Buffer Cache. 14 + */ 15 + struct xe_guc_buf_cache { 16 + /* private: internal sub-allocation manager */ 17 + struct xe_sa_manager *sam; 18 + }; 19 + 20 + /** 21 + * struct xe_guc_buf - GuC Data Buffer Reference. 22 + */ 23 + struct xe_guc_buf { 24 + /* private: internal sub-allocation reference */ 25 + struct drm_suballoc *sa; 26 + }; 27 + 28 + #endif
+28
drivers/gpu/drm/xe/xe_guc_debugfs.c
··· 13 13 #include "xe_guc.h" 14 14 #include "xe_guc_ct.h" 15 15 #include "xe_guc_log.h" 16 + #include "xe_guc_pc.h" 16 17 #include "xe_macros.h" 17 18 #include "xe_pm.h" 18 19 ··· 48 47 return 0; 49 48 } 50 49 50 + static int guc_log_dmesg(struct seq_file *m, void *data) 51 + { 52 + struct xe_guc *guc = node_to_guc(m->private); 53 + struct xe_device *xe = guc_to_xe(guc); 54 + 55 + xe_pm_runtime_get(xe); 56 + xe_guc_log_print_dmesg(&guc->log); 57 + xe_pm_runtime_put(xe); 58 + 59 + return 0; 60 + } 61 + 51 62 static int guc_ctb(struct seq_file *m, void *data) 52 63 { 53 64 struct xe_guc *guc = node_to_guc(m->private); ··· 73 60 return 0; 74 61 } 75 62 63 + static int guc_pc(struct seq_file *m, void *data) 64 + { 65 + struct xe_guc *guc = node_to_guc(m->private); 66 + struct xe_device *xe = guc_to_xe(guc); 67 + struct drm_printer p = drm_seq_file_printer(m); 68 + 69 + xe_pm_runtime_get(xe); 70 + xe_guc_pc_print(&guc->pc, &p); 71 + xe_pm_runtime_put(xe); 72 + 73 + return 0; 74 + } 75 + 76 76 static const struct drm_info_list debugfs_list[] = { 77 77 {"guc_info", guc_info, 0}, 78 78 {"guc_log", guc_log, 0}, 79 + {"guc_log_dmesg", guc_log_dmesg, 0}, 79 80 {"guc_ctb", guc_ctb, 0}, 81 + {"guc_pc", guc_pc, 0}, 80 82 }; 81 83 82 84 void xe_guc_debugfs_register(struct xe_guc *guc, struct dentry *parent)
+2 -6
drivers/gpu/drm/xe/xe_guc_log.c
··· 149 149 size_t remain; 150 150 int i; 151 151 152 - if (!log->bo) { 153 - xe_gt_err(gt, "GuC log buffer not allocated\n"); 152 + if (!log->bo) 154 153 return NULL; 155 - } 156 154 157 155 snapshot = xe_guc_log_snapshot_alloc(log, atomic); 158 - if (!snapshot) { 159 - xe_gt_err(gt, "GuC log snapshot not allocated\n"); 156 + if (!snapshot) 160 157 return NULL; 161 - } 162 158 163 159 remain = snapshot->size; 164 160 for (i = 0; i < snapshot->num_chunks; i++) {
+71 -10
drivers/gpu/drm/xe/xe_guc_pc.c
··· 8 8 #include <linux/delay.h> 9 9 10 10 #include <drm/drm_managed.h> 11 + #include <drm/drm_print.h> 11 12 #include <generated/xe_wa_oob.h> 12 13 13 14 #include "abi/guc_actions_slpc_abi.h" ··· 363 362 u32 reg; 364 363 365 364 /* 366 - * For PVC we still need to use fused RP1 as the approximation for RPe 367 - * For other platforms than PVC we get the resolved RPe directly from 365 + * For PVC we still need to use fused RP0 as the approximation for RPa 366 + * For other platforms than PVC we get the resolved RPa directly from 368 367 * PCODE at a different register 369 368 */ 370 - if (xe->info.platform == XE_PVC) 369 + if (xe->info.platform == XE_PVC) { 371 370 reg = xe_mmio_read32(&gt->mmio, PVC_RP_STATE_CAP); 372 - else 371 + pc->rpa_freq = REG_FIELD_GET(RP0_MASK, reg) * GT_FREQUENCY_MULTIPLIER; 372 + } else { 373 373 reg = xe_mmio_read32(&gt->mmio, FREQ_INFO_REC); 374 - 375 - pc->rpa_freq = REG_FIELD_GET(RPA_MASK, reg) * GT_FREQUENCY_MULTIPLIER; 374 + pc->rpa_freq = REG_FIELD_GET(RPA_MASK, reg) * GT_FREQUENCY_MULTIPLIER; 375 + } 376 376 } 377 377 378 378 static void tgl_update_rpe_value(struct xe_guc_pc *pc) ··· 387 385 * For other platforms than PVC we get the resolved RPe directly from 388 386 * PCODE at a different register 389 387 */ 390 - if (xe->info.platform == XE_PVC) 388 + if (xe->info.platform == XE_PVC) { 391 389 reg = xe_mmio_read32(&gt->mmio, PVC_RP_STATE_CAP); 392 - else 390 + pc->rpe_freq = REG_FIELD_GET(RP1_MASK, reg) * GT_FREQUENCY_MULTIPLIER; 391 + } else { 393 392 reg = xe_mmio_read32(&gt->mmio, FREQ_INFO_REC); 394 - 395 - pc->rpe_freq = REG_FIELD_GET(RPE_MASK, reg) * GT_FREQUENCY_MULTIPLIER; 393 + pc->rpe_freq = REG_FIELD_GET(RPE_MASK, reg) * GT_FREQUENCY_MULTIPLIER; 394 + } 396 395 } 397 396 398 397 static void pc_update_rp_values(struct xe_guc_pc *pc) ··· 1133 1130 pc->bo = bo; 1134 1131 1135 1132 return devm_add_action_or_reset(xe->drm.dev, xe_guc_pc_fini_hw, pc); 1133 + } 1134 + 1135 + static const char *pc_get_state_string(struct xe_guc_pc *pc) 1136 + { 1137 + switch (slpc_shared_data_read(pc, header.global_state)) { 1138 + case SLPC_GLOBAL_STATE_NOT_RUNNING: 1139 + return "not running"; 1140 + case SLPC_GLOBAL_STATE_INITIALIZING: 1141 + return "initializing"; 1142 + case SLPC_GLOBAL_STATE_RESETTING: 1143 + return "resetting"; 1144 + case SLPC_GLOBAL_STATE_RUNNING: 1145 + return "running"; 1146 + case SLPC_GLOBAL_STATE_SHUTTING_DOWN: 1147 + return "shutting down"; 1148 + case SLPC_GLOBAL_STATE_ERROR: 1149 + return "error"; 1150 + default: 1151 + return "unknown"; 1152 + } 1153 + } 1154 + 1155 + /** 1156 + * xe_guc_pc_print - Print GuC's Power Conservation information for debug 1157 + * @pc: Xe_GuC_PC instance 1158 + * @p: drm_printer 1159 + */ 1160 + void xe_guc_pc_print(struct xe_guc_pc *pc, struct drm_printer *p) 1161 + { 1162 + drm_printf(p, "SLPC Shared Data Header:\n"); 1163 + drm_printf(p, "\tSize: %x\n", slpc_shared_data_read(pc, header.size)); 1164 + drm_printf(p, "\tGlobal State: %s\n", pc_get_state_string(pc)); 1165 + 1166 + if (pc_action_query_task_state(pc)) 1167 + return; 1168 + 1169 + drm_printf(p, "\nSLPC Tasks Status:\n"); 1170 + drm_printf(p, "\tGTPERF enabled: %s\n", 1171 + str_yes_no(slpc_shared_data_read(pc, task_state_data.status) & 1172 + SLPC_GTPERF_TASK_ENABLED)); 1173 + drm_printf(p, "\tDCC enabled: %s\n", 1174 + str_yes_no(slpc_shared_data_read(pc, task_state_data.status) & 1175 + SLPC_DCC_TASK_ENABLED)); 1176 + drm_printf(p, "\tDCC in use: %s\n", 1177 + str_yes_no(slpc_shared_data_read(pc, task_state_data.status) & 1178 + SLPC_IN_DCC)); 1179 + drm_printf(p, "\tBalancer enabled: %s\n", 1180 + str_yes_no(slpc_shared_data_read(pc, task_state_data.status) & 1181 + SLPC_BALANCER_ENABLED)); 1182 + drm_printf(p, "\tIBC enabled: %s\n", 1183 + str_yes_no(slpc_shared_data_read(pc, task_state_data.status) & 1184 + SLPC_IBC_TASK_ENABLED)); 1185 + drm_printf(p, "\tBalancer IA LMT enabled: %s\n", 1186 + str_yes_no(slpc_shared_data_read(pc, task_state_data.status) & 1187 + SLPC_BALANCER_IA_LMT_ENABLED)); 1188 + drm_printf(p, "\tBalancer IA LMT active: %s\n", 1189 + str_yes_no(slpc_shared_data_read(pc, task_state_data.status) & 1190 + SLPC_BALANCER_IA_LMT_ACTIVE)); 1136 1191 }
+2
drivers/gpu/drm/xe/xe_guc_pc.h
··· 10 10 11 11 struct xe_guc_pc; 12 12 enum slpc_gucrc_mode; 13 + struct drm_printer; 13 14 14 15 int xe_guc_pc_init(struct xe_guc_pc *pc); 15 16 int xe_guc_pc_start(struct xe_guc_pc *pc); ··· 18 17 int xe_guc_pc_gucrc_disable(struct xe_guc_pc *pc); 19 18 int xe_guc_pc_override_gucrc_mode(struct xe_guc_pc *pc, enum slpc_gucrc_mode mode); 20 19 int xe_guc_pc_unset_gucrc_mode(struct xe_guc_pc *pc); 20 + void xe_guc_pc_print(struct xe_guc_pc *pc, struct drm_printer *p); 21 21 22 22 u32 xe_guc_pc_get_act_freq(struct xe_guc_pc *pc); 23 23 int xe_guc_pc_get_cur_freq(struct xe_guc_pc *pc, u32 *freq);
+1 -1
drivers/gpu/drm/xe/xe_guc_relay.c
··· 225 225 * with CTB lock held which is marked as used in the reclaim path. 226 226 * Btw, that's one of the reason why we use mempool here! 227 227 */ 228 - txn = mempool_alloc(&relay->pool, incoming ? GFP_ATOMIC : GFP_KERNEL); 228 + txn = mempool_alloc(&relay->pool, incoming ? GFP_ATOMIC : GFP_NOWAIT); 229 229 if (!txn) 230 230 return ERR_PTR(-ENOMEM); 231 231
+3
drivers/gpu/drm/xe/xe_guc_types.h
··· 11 11 12 12 #include "regs/xe_reg_defs.h" 13 13 #include "xe_guc_ads_types.h" 14 + #include "xe_guc_buf_types.h" 14 15 #include "xe_guc_ct_types.h" 15 16 #include "xe_guc_fwif.h" 16 17 #include "xe_guc_log_types.h" ··· 59 58 struct xe_guc_ads ads; 60 59 /** @ct: GuC ct */ 61 60 struct xe_guc_ct ct; 61 + /** @buf: GuC Buffer Cache manager */ 62 + struct xe_guc_buf_cache buf; 62 63 /** @capture: the error-state-capture module's data and objects */ 63 64 struct xe_guc_state_capture *capture; 64 65 /** @pc: GuC Power Conservation */
+2 -1
drivers/gpu/drm/xe/xe_heci_gsc.c
··· 12 12 #include "xe_drv.h" 13 13 #include "xe_heci_gsc.h" 14 14 #include "xe_platform_types.h" 15 + #include "xe_survivability_mode.h" 15 16 16 17 #define GSC_BAR_LENGTH 0x00000FFC 17 18 ··· 201 200 return; 202 201 } 203 202 204 - if (!def->use_polling) { 203 + if (!def->use_polling && !xe_survivability_mode_enabled(xe)) { 205 204 ret = heci_gsc_irq_setup(xe); 206 205 if (ret) 207 206 goto fail;
+76 -15
drivers/gpu/drm/xe/xe_hwmon.c
··· 6 6 #include <linux/hwmon-sysfs.h> 7 7 #include <linux/hwmon.h> 8 8 #include <linux/types.h> 9 + #include <linux/units.h> 9 10 10 11 #include <drm/drm_managed.h> 11 12 #include "regs/xe_gt_regs.h" ··· 21 20 #include "xe_pm.h" 22 21 23 22 enum xe_hwmon_reg { 23 + REG_TEMP, 24 24 REG_PKG_RAPL_LIMIT, 25 25 REG_PKG_POWER_SKU, 26 26 REG_PKG_POWER_SKU_UNIT, ··· 38 36 enum xe_hwmon_channel { 39 37 CHANNEL_CARD, 40 38 CHANNEL_PKG, 39 + CHANNEL_VRAM, 41 40 CHANNEL_MAX, 42 41 }; 43 42 ··· 87 84 struct xe_device *xe = hwmon->xe; 88 85 89 86 switch (hwmon_reg) { 87 + case REG_TEMP: 88 + if (xe->info.platform == XE_BATTLEMAGE) { 89 + if (channel == CHANNEL_PKG) 90 + return BMG_PACKAGE_TEMPERATURE; 91 + else if (channel == CHANNEL_VRAM) 92 + return BMG_VRAM_TEMPERATURE; 93 + } else if (xe->info.platform == XE_DG2) { 94 + if (channel == CHANNEL_PKG) 95 + return PCU_CR_PACKAGE_TEMPERATURE; 96 + else if (channel == CHANNEL_VRAM) 97 + return BMG_VRAM_TEMPERATURE; 98 + } 99 + break; 90 100 case REG_PKG_RAPL_LIMIT: 91 101 if (xe->info.platform == XE_BATTLEMAGE) { 92 102 if (channel == CHANNEL_PKG) ··· 447 431 }; 448 432 449 433 static const struct hwmon_channel_info * const hwmon_info[] = { 434 + HWMON_CHANNEL_INFO(temp, HWMON_T_LABEL, HWMON_T_INPUT | HWMON_T_LABEL, 435 + HWMON_T_INPUT | HWMON_T_LABEL), 450 436 HWMON_CHANNEL_INFO(power, HWMON_P_MAX | HWMON_P_RATED_MAX | HWMON_P_LABEL, 451 437 HWMON_P_MAX | HWMON_P_RATED_MAX | HWMON_P_CRIT | HWMON_P_LABEL), 452 438 HWMON_CHANNEL_INFO(curr, HWMON_C_LABEL, HWMON_C_CRIT | HWMON_C_LABEL), ··· 522 504 reg_val = xe_mmio_read32(mmio, xe_hwmon_get_reg(hwmon, REG_GT_PERF_STATUS, channel)); 523 505 /* HW register value in units of 2.5 millivolt */ 524 506 *value = DIV_ROUND_CLOSEST(REG_FIELD_GET(VOLTAGE_MASK, reg_val) * 2500, SF_VOLTAGE); 507 + } 508 + 509 + static umode_t 510 + xe_hwmon_temp_is_visible(struct xe_hwmon *hwmon, u32 attr, int channel) 511 + { 512 + switch (attr) { 513 + case hwmon_temp_input: 514 + case hwmon_temp_label: 515 + return xe_reg_is_valid(xe_hwmon_get_reg(hwmon, REG_TEMP, channel)) ? 0444 : 0; 516 + default: 517 + return 0; 518 + } 519 + } 520 + 521 + static int 522 + xe_hwmon_temp_read(struct xe_hwmon *hwmon, u32 attr, int channel, long *val) 523 + { 524 + struct xe_mmio *mmio = xe_root_tile_mmio(hwmon->xe); 525 + u64 reg_val; 526 + 527 + switch (attr) { 528 + case hwmon_temp_input: 529 + reg_val = xe_mmio_read32(mmio, xe_hwmon_get_reg(hwmon, REG_TEMP, channel)); 530 + 531 + /* HW register value is in degrees Celsius, convert to millidegrees. */ 532 + *val = REG_FIELD_GET(TEMP_MASK, reg_val) * MILLIDEGREE_PER_DEGREE; 533 + return 0; 534 + default: 535 + return -EOPNOTSUPP; 536 + } 525 537 } 526 538 527 539 static umode_t ··· 715 667 xe_pm_runtime_get(hwmon->xe); 716 668 717 669 switch (type) { 670 + case hwmon_temp: 671 + ret = xe_hwmon_temp_is_visible(hwmon, attr, channel); 672 + break; 718 673 case hwmon_power: 719 674 ret = xe_hwmon_power_is_visible(hwmon, attr, channel); 720 675 break; ··· 750 699 xe_pm_runtime_get(hwmon->xe); 751 700 752 701 switch (type) { 702 + case hwmon_temp: 703 + ret = xe_hwmon_temp_read(hwmon, attr, channel, val); 704 + break; 753 705 case hwmon_power: 754 706 ret = xe_hwmon_power_read(hwmon, attr, channel, val); 755 707 break; ··· 806 752 u32 attr, int channel, const char **str) 807 753 { 808 754 switch (type) { 755 + case hwmon_temp: 756 + if (channel == CHANNEL_PKG) 757 + *str = "pkg"; 758 + else if (channel == CHANNEL_VRAM) 759 + *str = "vram"; 760 + return 0; 809 761 case hwmon_power: 810 762 case hwmon_energy: 811 763 case hwmon_curr: ··· 839 779 }; 840 780 841 781 static void 842 - xe_hwmon_get_preregistration_info(struct xe_device *xe) 782 + xe_hwmon_get_preregistration_info(struct xe_hwmon *hwmon) 843 783 { 844 - struct xe_mmio *mmio = xe_root_tile_mmio(xe); 845 - struct xe_hwmon *hwmon = xe->hwmon; 784 + struct xe_mmio *mmio = xe_root_tile_mmio(hwmon->xe); 846 785 long energy; 847 786 u64 val_sku_unit = 0; 848 787 int channel; ··· 875 816 mutex_destroy(&hwmon->hwmon_lock); 876 817 } 877 818 878 - void xe_hwmon_register(struct xe_device *xe) 819 + int xe_hwmon_register(struct xe_device *xe) 879 820 { 880 821 struct device *dev = xe->drm.dev; 881 822 struct xe_hwmon *hwmon; 823 + int ret; 882 824 883 825 /* hwmon is available only for dGfx */ 884 826 if (!IS_DGFX(xe)) 885 - return; 827 + return 0; 886 828 887 829 /* hwmon is not available on VFs */ 888 830 if (IS_SRIOV_VF(xe)) 889 - return; 831 + return 0; 890 832 891 833 hwmon = devm_kzalloc(dev, sizeof(*hwmon), GFP_KERNEL); 892 834 if (!hwmon) 893 - return; 894 - 895 - xe->hwmon = hwmon; 835 + return -ENOMEM; 896 836 897 837 mutex_init(&hwmon->hwmon_lock); 898 - if (devm_add_action_or_reset(dev, xe_hwmon_mutex_destroy, hwmon)) 899 - return; 838 + ret = devm_add_action_or_reset(dev, xe_hwmon_mutex_destroy, hwmon); 839 + if (ret) 840 + return ret; 900 841 901 842 /* There's only one instance of hwmon per device */ 902 843 hwmon->xe = xe; 844 + xe->hwmon = hwmon; 903 845 904 - xe_hwmon_get_preregistration_info(xe); 846 + xe_hwmon_get_preregistration_info(hwmon); 905 847 906 848 drm_dbg(&xe->drm, "Register xe hwmon interface\n"); 907 849 ··· 910 850 hwmon->hwmon_dev = devm_hwmon_device_register_with_info(dev, "xe", hwmon, 911 851 &hwmon_chip_info, 912 852 hwmon_groups); 913 - 914 853 if (IS_ERR(hwmon->hwmon_dev)) { 915 - drm_warn(&xe->drm, "Failed to register xe hwmon (%pe)\n", hwmon->hwmon_dev); 854 + drm_err(&xe->drm, "Failed to register xe hwmon (%pe)\n", hwmon->hwmon_dev); 916 855 xe->hwmon = NULL; 917 - return; 856 + return PTR_ERR(hwmon->hwmon_dev); 918 857 } 858 + 859 + return 0; 919 860 } 920 861
+2 -2
drivers/gpu/drm/xe/xe_hwmon.h
··· 11 11 struct xe_device; 12 12 13 13 #if IS_REACHABLE(CONFIG_HWMON) 14 - void xe_hwmon_register(struct xe_device *xe); 14 + int xe_hwmon_register(struct xe_device *xe); 15 15 #else 16 - static inline void xe_hwmon_register(struct xe_device *xe) { }; 16 + static inline int xe_hwmon_register(struct xe_device *xe) { return 0; }; 17 17 #endif 18 18 19 19 #endif /* _XE_HWMON_H_ */
+19 -1
drivers/gpu/drm/xe/xe_irq.c
··· 20 20 #include "xe_hw_engine.h" 21 21 #include "xe_memirq.h" 22 22 #include "xe_mmio.h" 23 + #include "xe_pxp.h" 23 24 #include "xe_sriov.h" 24 25 25 26 /* ··· 209 208 } 210 209 if (heci_mask) 211 210 xe_mmio_write32(mmio, HECI2_RSVD_INTR_MASK, ~(heci_mask << 16)); 211 + 212 + if (xe_pxp_is_supported(xe)) { 213 + u32 kcr_mask = KCR_PXP_STATE_TERMINATED_INTERRUPT | 214 + KCR_APP_TERMINATED_PER_FW_REQ_INTERRUPT | 215 + KCR_PXP_STATE_RESET_COMPLETE_INTERRUPT; 216 + 217 + xe_mmio_write32(mmio, CRYPTO_RSVD_INTR_ENABLE, kcr_mask << 16); 218 + xe_mmio_write32(mmio, CRYPTO_RSVD_INTR_MASK, ~(kcr_mask << 16)); 219 + } 212 220 } 213 221 } 214 222 ··· 340 330 } 341 331 342 332 if (class == XE_ENGINE_CLASS_OTHER) { 343 - /* HECI GSCFI interrupts come from outside of GT */ 333 + /* 334 + * HECI GSCFI interrupts come from outside of GT. 335 + * KCR irqs come from inside GT but are handled 336 + * by the global PXP subsystem. 337 + */ 344 338 if (xe->info.has_heci_gscfi && instance == OTHER_GSC_INSTANCE) 345 339 xe_heci_gsc_irq_handler(xe, intr_vec); 340 + else if (instance == OTHER_KCR_INSTANCE) 341 + xe_pxp_irq_handler(xe, intr_vec); 346 342 else 347 343 gt_other_irq_handler(engine_gt, instance, intr_vec); 348 344 } ··· 526 510 xe_mmio_write32(mmio, GUNIT_GSC_INTR_ENABLE, 0); 527 511 xe_mmio_write32(mmio, GUNIT_GSC_INTR_MASK, ~0); 528 512 xe_mmio_write32(mmio, HECI2_RSVD_INTR_MASK, ~0); 513 + xe_mmio_write32(mmio, CRYPTO_RSVD_INTR_ENABLE, 0); 514 + xe_mmio_write32(mmio, CRYPTO_RSVD_INTR_MASK, ~0); 529 515 } 530 516 531 517 xe_mmio_write32(mmio, GPM_WGBOXPERF_INTR_ENABLE, 0);
+2 -2
drivers/gpu/drm/xe/xe_lmtt.c
··· 164 164 lmtt_assert(lmtt, IS_SRIOV_PF(xe)); 165 165 lmtt_assert(lmtt, !lmtt->ops); 166 166 167 - if (!IS_DGFX(xe)) 167 + if (!xe_device_has_lmtt(xe)) 168 168 return 0; 169 169 170 170 if (xe_has_multi_level_lmtt(xe)) ··· 486 486 u64 pt_size; 487 487 488 488 lmtt_assert(lmtt, IS_SRIOV_PF(lmtt_to_xe(lmtt))); 489 - lmtt_assert(lmtt, IS_DGFX(lmtt_to_xe(lmtt))); 489 + lmtt_assert(lmtt, xe_device_has_lmtt(lmtt_to_xe(lmtt))); 490 490 lmtt_assert(lmtt, lmtt->ops); 491 491 492 492 pt_size = PAGE_ALIGN(lmtt->ops->lmtt_pte_size(level) *
+15 -3
drivers/gpu/drm/xe/xe_lrc.c
··· 883 883 #define PVC_CTX_ACC_CTR_THOLD (0x2a + 1) 884 884 885 885 static int xe_lrc_init(struct xe_lrc *lrc, struct xe_hw_engine *hwe, 886 - struct xe_vm *vm, u32 ring_size, u16 msix_vec) 886 + struct xe_vm *vm, u32 ring_size, u16 msix_vec, 887 + u32 init_flags) 887 888 { 888 889 struct xe_gt *gt = hwe->gt; 889 890 struct xe_tile *tile = gt_to_tile(gt); ··· 980 979 RING_CTL_SIZE(lrc->ring.size) | RING_VALID); 981 980 } 982 981 982 + if (init_flags & XE_LRC_CREATE_RUNALONE) 983 + xe_lrc_write_ctx_reg(lrc, CTX_CONTEXT_CONTROL, 984 + xe_lrc_read_ctx_reg(lrc, CTX_CONTEXT_CONTROL) | 985 + _MASKED_BIT_ENABLE(CTX_CTRL_RUN_ALONE)); 986 + 987 + if (init_flags & XE_LRC_CREATE_PXP) 988 + xe_lrc_write_ctx_reg(lrc, CTX_CONTEXT_CONTROL, 989 + xe_lrc_read_ctx_reg(lrc, CTX_CONTEXT_CONTROL) | 990 + _MASKED_BIT_ENABLE(CTX_CTRL_PXP_ENABLE)); 991 + 983 992 xe_lrc_write_ctx_reg(lrc, CTX_TIMESTAMP, 0); 984 993 985 994 if (xe->info.has_asid && vm) ··· 1032 1021 * @vm: The VM (address space) 1033 1022 * @ring_size: LRC ring size 1034 1023 * @msix_vec: MSI-X interrupt vector (for platforms that support it) 1024 + * @flags: LRC initialization flags 1035 1025 * 1036 1026 * Allocate and initialize the Logical Ring Context (LRC). 1037 1027 * ··· 1040 1028 * upon failure. 1041 1029 */ 1042 1030 struct xe_lrc *xe_lrc_create(struct xe_hw_engine *hwe, struct xe_vm *vm, 1043 - u32 ring_size, u16 msix_vec) 1031 + u32 ring_size, u16 msix_vec, u32 flags) 1044 1032 { 1045 1033 struct xe_lrc *lrc; 1046 1034 int err; ··· 1049 1037 if (!lrc) 1050 1038 return ERR_PTR(-ENOMEM); 1051 1039 1052 - err = xe_lrc_init(lrc, hwe, vm, ring_size, msix_vec); 1040 + err = xe_lrc_init(lrc, hwe, vm, ring_size, msix_vec, flags); 1053 1041 if (err) { 1054 1042 kfree(lrc); 1055 1043 return ERR_PTR(err);
+5 -2
drivers/gpu/drm/xe/xe_lrc.h
··· 39 39 u32 ctx_job_timestamp; 40 40 }; 41 41 42 - #define LRC_PPHWSP_SCRATCH_ADDR (0x34 * 4) 42 + #define LRC_PPHWSP_FLUSH_INVAL_SCRATCH_ADDR (0x34 * 4) 43 + #define LRC_PPHWSP_PXP_INVAL_SCRATCH_ADDR (0x40 * 4) 43 44 45 + #define XE_LRC_CREATE_RUNALONE 0x1 46 + #define XE_LRC_CREATE_PXP 0x2 44 47 struct xe_lrc *xe_lrc_create(struct xe_hw_engine *hwe, struct xe_vm *vm, 45 - u32 ring_size, u16 msix_vec); 48 + u32 ring_size, u16 msix_vec, u32 flags); 46 49 void xe_lrc_destroy(struct kref *ref); 47 50 48 51 /**
+24 -53
drivers/gpu/drm/xe/xe_mmio.c
··· 55 55 static void mmio_multi_tile_setup(struct xe_device *xe, size_t tile_mmio_size) 56 56 { 57 57 struct xe_tile *tile; 58 - void __iomem *regs; 59 58 u8 id; 60 59 61 60 /* 62 61 * Nothing to be done as tile 0 has already been setup earlier with the 63 - * entire BAR mapped - see xe_mmio_init() 62 + * entire BAR mapped - see xe_mmio_probe_early() 64 63 */ 65 64 if (xe->info.tile_count == 1) 66 65 return; ··· 73 74 /* 74 75 * Although the per-tile mmio regs are not yet initialized, this 75 76 * is fine as it's going to the root tile's mmio, that's 76 - * guaranteed to be initialized earlier in xe_mmio_init() 77 + * guaranteed to be initialized earlier in xe_mmio_probe_early() 77 78 */ 78 79 mtcfg = xe_mmio_read64_2x32(mmio, XEHP_MTCFG_ADDR); 79 80 tile_count = REG_FIELD_GET(TILE_COUNT, mtcfg) + 1; ··· 93 94 } 94 95 } 95 96 96 - regs = xe->mmio.regs; 97 - for_each_tile(tile, xe, id) { 98 - tile->mmio.regs_size = SZ_4M; 99 - tile->mmio.regs = regs; 100 - tile->mmio.tile = tile; 101 - regs += tile_mmio_size; 102 - } 103 - } 104 - 105 - /* 106 - * On top of all the multi-tile MMIO space there can be a platform-dependent 107 - * extension for each tile, resulting in a layout like below: 108 - * 109 - * .----------------------. <- ext_base + tile_count * tile_mmio_ext_size 110 - * | .... | 111 - * |----------------------| <- ext_base + 2 * tile_mmio_ext_size 112 - * | tile1->mmio_ext.regs | 113 - * |----------------------| <- ext_base + 1 * tile_mmio_ext_size 114 - * | tile0->mmio_ext.regs | 115 - * |======================| <- ext_base = tile_count * tile_mmio_size 116 - * | | 117 - * | mmio.regs | 118 - * | | 119 - * '----------------------' <- 0MB 120 - * 121 - * Set up the tile[]->mmio_ext pointers/sizes. 122 - */ 123 - static void mmio_extension_setup(struct xe_device *xe, size_t tile_mmio_size, 124 - size_t tile_mmio_ext_size) 125 - { 126 - struct xe_tile *tile; 127 - void __iomem *regs; 128 - u8 id; 129 - 130 - if (!xe->info.has_mmio_ext) 131 - return; 132 - 133 - regs = xe->mmio.regs + tile_mmio_size * xe->info.tile_count; 134 - for_each_tile(tile, xe, id) { 135 - tile->mmio_ext.regs_size = tile_mmio_ext_size; 136 - tile->mmio_ext.regs = regs; 137 - tile->mmio_ext.tile = tile; 138 - regs += tile_mmio_ext_size; 139 - } 97 + for_each_remote_tile(tile, xe, id) 98 + xe_mmio_init(&tile->mmio, tile, xe->mmio.regs + id * tile_mmio_size, SZ_4M); 140 99 } 141 100 142 101 int xe_mmio_probe_tiles(struct xe_device *xe) 143 102 { 144 103 size_t tile_mmio_size = SZ_16M; 145 - size_t tile_mmio_ext_size = xe->info.tile_mmio_ext_size; 146 104 147 105 mmio_multi_tile_setup(xe, tile_mmio_size); 148 - mmio_extension_setup(xe, tile_mmio_size, tile_mmio_ext_size); 149 106 150 107 return devm_add_action_or_reset(xe->drm.dev, tiles_fini, xe); 151 108 } ··· 116 161 root_tile->mmio.regs = NULL; 117 162 } 118 163 119 - int xe_mmio_init(struct xe_device *xe) 164 + int xe_mmio_probe_early(struct xe_device *xe) 120 165 { 121 166 struct xe_tile *root_tile = xe_device_get_root_tile(xe); 122 167 struct pci_dev *pdev = to_pci_dev(xe->drm.dev); ··· 134 179 } 135 180 136 181 /* Setup first tile; other tiles (if present) will be setup later. */ 137 - root_tile->mmio.regs_size = SZ_4M; 138 - root_tile->mmio.regs = xe->mmio.regs; 139 - root_tile->mmio.tile = root_tile; 182 + xe_mmio_init(&root_tile->mmio, root_tile, xe->mmio.regs, SZ_4M); 140 183 141 184 return devm_add_action_or_reset(xe->drm.dev, mmio_fini, xe); 185 + } 186 + 187 + /** 188 + * xe_mmio_init() - Initialize an MMIO instance 189 + * @mmio: Pointer to the MMIO instance to initialize 190 + * @tile: The tile to which the MMIO region belongs 191 + * @ptr: Pointer to the start of the MMIO region 192 + * @size: The size of the MMIO region in bytes 193 + * 194 + * This is a convenience function for minimal initialization of struct xe_mmio. 195 + */ 196 + void xe_mmio_init(struct xe_mmio *mmio, struct xe_tile *tile, void __iomem *ptr, u32 size) 197 + { 198 + xe_tile_assert(tile, size <= XE_REG_ADDR_MAX); 199 + 200 + mmio->regs = ptr; 201 + mmio->regs_size = size; 202 + mmio->tile = tile; 142 203 } 143 204 144 205 static void mmio_flush_pending_writes(struct xe_mmio *mmio)
+3 -1
drivers/gpu/drm/xe/xe_mmio.h
··· 11 11 struct xe_device; 12 12 struct xe_reg; 13 13 14 - int xe_mmio_init(struct xe_device *xe); 14 + int xe_mmio_probe_early(struct xe_device *xe); 15 15 int xe_mmio_probe_tiles(struct xe_device *xe); 16 + 17 + void xe_mmio_init(struct xe_mmio *mmio, struct xe_tile *tile, void __iomem *ptr, u32 size); 16 18 17 19 u8 xe_mmio_read8(struct xe_mmio *mmio, struct xe_reg reg); 18 20 u16 xe_mmio_read16(struct xe_mmio *mmio, struct xe_reg reg);
-5
drivers/gpu/drm/xe/xe_module.c
··· 77 77 void (*exit)(void); 78 78 }; 79 79 80 - static void xe_dummy_exit(void) 81 - { 82 - } 83 - 84 80 static const struct init_funcs init_funcs[] = { 85 81 { 86 82 .init = xe_check_nomodeset, ··· 99 103 }, 100 104 { 101 105 .init = xe_pm_module_init, 102 - .exit = xe_dummy_exit, 103 106 }, 104 107 }; 105 108
+48 -47
drivers/gpu/drm/xe/xe_oa.c
··· 548 548 mutex_unlock(&stream->stream_lock); 549 549 } while (!offset && !ret); 550 550 } else { 551 + xe_oa_buffer_check_unlocked(stream); 551 552 mutex_lock(&stream->stream_lock); 552 553 ret = __xe_oa_read(stream, buf, count, &offset); 553 554 mutex_unlock(&stream->stream_lock); ··· 2424 2423 return ret; 2425 2424 } 2426 2425 2427 - /** 2428 - * xe_oa_register - Xe OA registration 2429 - * @xe: @xe_device 2430 - * 2431 - * Exposes the metrics sysfs directory upon completion of module initialization 2432 - */ 2433 - void xe_oa_register(struct xe_device *xe) 2426 + static void xe_oa_unregister(void *arg) 2434 2427 { 2435 - struct xe_oa *oa = &xe->oa; 2436 - 2437 - if (!oa->xe) 2438 - return; 2439 - 2440 - oa->metrics_kobj = kobject_create_and_add("metrics", 2441 - &xe->drm.primary->kdev->kobj); 2442 - } 2443 - 2444 - /** 2445 - * xe_oa_unregister - Xe OA de-registration 2446 - * @xe: @xe_device 2447 - */ 2448 - void xe_oa_unregister(struct xe_device *xe) 2449 - { 2450 - struct xe_oa *oa = &xe->oa; 2428 + struct xe_oa *oa = arg; 2451 2429 2452 2430 if (!oa->metrics_kobj) 2453 2431 return; 2454 2432 2455 2433 kobject_put(oa->metrics_kobj); 2456 2434 oa->metrics_kobj = NULL; 2435 + } 2436 + 2437 + /** 2438 + * xe_oa_register - Xe OA registration 2439 + * @xe: @xe_device 2440 + * 2441 + * Exposes the metrics sysfs directory upon completion of module initialization 2442 + */ 2443 + int xe_oa_register(struct xe_device *xe) 2444 + { 2445 + struct xe_oa *oa = &xe->oa; 2446 + 2447 + if (!oa->xe) 2448 + return 0; 2449 + 2450 + oa->metrics_kobj = kobject_create_and_add("metrics", 2451 + &xe->drm.primary->kdev->kobj); 2452 + if (!oa->metrics_kobj) 2453 + return -ENOMEM; 2454 + 2455 + return devm_add_action_or_reset(xe->drm.dev, xe_oa_unregister, oa); 2457 2456 } 2458 2457 2459 2458 static u32 num_oa_units_per_gt(struct xe_gt *gt) ··· 2642 2641 } 2643 2642 } 2644 2643 2644 + static int destroy_config(int id, void *p, void *data) 2645 + { 2646 + xe_oa_config_put(p); 2647 + 2648 + return 0; 2649 + } 2650 + 2651 + static void xe_oa_fini(void *arg) 2652 + { 2653 + struct xe_device *xe = arg; 2654 + struct xe_oa *oa = &xe->oa; 2655 + 2656 + if (!oa->xe) 2657 + return; 2658 + 2659 + idr_for_each(&oa->metrics_idr, destroy_config, oa); 2660 + idr_destroy(&oa->metrics_idr); 2661 + 2662 + oa->xe = NULL; 2663 + } 2664 + 2645 2665 /** 2646 2666 * xe_oa_init - OA initialization during device probe 2647 2667 * @xe: @xe_device ··· 2694 2672 } 2695 2673 2696 2674 xe_oa_init_supported_formats(oa); 2697 - return 0; 2675 + 2676 + return devm_add_action_or_reset(xe->drm.dev, xe_oa_fini, xe); 2677 + 2698 2678 exit: 2699 2679 oa->xe = NULL; 2700 2680 return ret; 2701 - } 2702 - 2703 - static int destroy_config(int id, void *p, void *data) 2704 - { 2705 - xe_oa_config_put(p); 2706 - return 0; 2707 - } 2708 - 2709 - /** 2710 - * xe_oa_fini - OA de-initialization during device remove 2711 - * @xe: @xe_device 2712 - */ 2713 - void xe_oa_fini(struct xe_device *xe) 2714 - { 2715 - struct xe_oa *oa = &xe->oa; 2716 - 2717 - if (!oa->xe) 2718 - return; 2719 - 2720 - idr_for_each(&oa->metrics_idr, destroy_config, oa); 2721 - idr_destroy(&oa->metrics_idr); 2722 - 2723 - oa->xe = NULL; 2724 2681 }
+1 -3
drivers/gpu/drm/xe/xe_oa.h
··· 15 15 struct xe_hw_engine; 16 16 17 17 int xe_oa_init(struct xe_device *xe); 18 - void xe_oa_fini(struct xe_device *xe); 19 - void xe_oa_register(struct xe_device *xe); 20 - void xe_oa_unregister(struct xe_device *xe); 18 + int xe_oa_register(struct xe_device *xe); 21 19 int xe_oa_stream_open_ioctl(struct drm_device *dev, u64 data, struct drm_file *file); 22 20 int xe_oa_add_config_ioctl(struct drm_device *dev, u64 data, struct drm_file *file); 23 21 int xe_oa_remove_config_ioctl(struct drm_device *dev, u64 data, struct drm_file *file);
+55 -24
drivers/gpu/drm/xe/xe_pci.c
··· 30 30 #include "xe_pm.h" 31 31 #include "xe_sriov.h" 32 32 #include "xe_step.h" 33 + #include "xe_survivability_mode.h" 33 34 #include "xe_tile.h" 34 35 35 36 enum toggle_d3cold { ··· 55 54 56 55 enum xe_platform platform; 57 56 57 + u8 dma_mask_size; 58 + u8 max_remote_tiles:2; 59 + 58 60 u8 require_force_probe:1; 59 61 u8 is_dgfx:1; 60 62 ··· 65 61 u8 has_heci_gscfi:1; 66 62 u8 has_heci_cscfi:1; 67 63 u8 has_llc:1; 68 - u8 has_mmio_ext:1; 64 + u8 has_pxp:1; 69 65 u8 has_sriov:1; 70 66 u8 skip_guc_pc:1; 71 67 u8 skip_mtcfg:1; ··· 88 84 89 85 .hw_engine_mask = BIT(XE_HW_ENGINE_RCS0) | BIT(XE_HW_ENGINE_BCS0), 90 86 91 - .dma_mask_size = 39, 92 87 .va_bits = 48, 93 88 .vm_max_level = 3, 94 89 }; ··· 99 96 100 97 .hw_engine_mask = BIT(XE_HW_ENGINE_RCS0) | BIT(XE_HW_ENGINE_BCS0), 101 98 102 - .dma_mask_size = 39, 103 99 .va_bits = 48, 104 100 .vm_max_level = 3, 105 101 }; 106 102 107 103 #define XE_HP_FEATURES \ 108 104 .has_range_tlb_invalidation = true, \ 109 - .dma_mask_size = 46, \ 110 105 .va_bits = 48, \ 111 106 .vm_max_level = 3 112 107 ··· 139 138 BIT(XE_HW_ENGINE_CCS2) | BIT(XE_HW_ENGINE_CCS3), 140 139 141 140 XE_HP_FEATURES, 142 - .dma_mask_size = 52, 143 - .max_remote_tiles = 1, 144 141 .va_bits = 57, 145 142 .vm_max_level = 4, 146 143 .vram_flags = XE_VRAM_FLAGS_NEED64K, ··· 158 159 }; 159 160 160 161 #define XE2_GFX_FEATURES \ 161 - .dma_mask_size = 46, \ 162 162 .has_asid = 1, \ 163 163 .has_atomic_enable_pte_bit = 1, \ 164 164 .has_flat_ccs = 1, \ ··· 217 219 .graphics = &graphics_xelp, 218 220 .media = &media_xem, 219 221 PLATFORM(TIGERLAKE), 222 + .dma_mask_size = 39, 220 223 .has_display = true, 221 224 .has_llc = true, 222 225 .require_force_probe = true, ··· 227 228 .graphics = &graphics_xelp, 228 229 .media = &media_xem, 229 230 PLATFORM(ROCKETLAKE), 231 + .dma_mask_size = 39, 230 232 .has_display = true, 231 233 .has_llc = true, 232 234 .require_force_probe = true, ··· 239 239 .graphics = &graphics_xelp, 240 240 .media = &media_xem, 241 241 PLATFORM(ALDERLAKE_S), 242 + .dma_mask_size = 39, 242 243 .has_display = true, 243 244 .has_llc = true, 244 245 .require_force_probe = true, ··· 255 254 .graphics = &graphics_xelp, 256 255 .media = &media_xem, 257 256 PLATFORM(ALDERLAKE_P), 257 + .dma_mask_size = 39, 258 258 .has_display = true, 259 259 .has_llc = true, 260 260 .require_force_probe = true, ··· 269 267 .graphics = &graphics_xelp, 270 268 .media = &media_xem, 271 269 PLATFORM(ALDERLAKE_N), 270 + .dma_mask_size = 39, 272 271 .has_display = true, 273 272 .has_llc = true, 274 273 .require_force_probe = true, ··· 283 280 .media = &media_xem, 284 281 DGFX_FEATURES, 285 282 PLATFORM(DG1), 283 + .dma_mask_size = 39, 286 284 .has_display = true, 287 285 .has_heci_gscfi = 1, 288 286 .require_force_probe = true, ··· 307 303 static const struct xe_device_desc ats_m_desc = { 308 304 .graphics = &graphics_xehpg, 309 305 .media = &media_xehpm, 306 + .dma_mask_size = 46, 310 307 .require_force_probe = true, 311 308 312 309 DG2_FEATURES, ··· 317 312 static const struct xe_device_desc dg2_desc = { 318 313 .graphics = &graphics_xehpg, 319 314 .media = &media_xehpm, 315 + .dma_mask_size = 46, 320 316 .require_force_probe = true, 321 317 322 318 DG2_FEATURES, ··· 328 322 .graphics = &graphics_xehpc, 329 323 DGFX_FEATURES, 330 324 PLATFORM(PVC), 325 + .dma_mask_size = 52, 331 326 .has_display = false, 332 327 .has_heci_gscfi = 1, 328 + .max_remote_tiles = 1, 333 329 .require_force_probe = true, 334 330 }; 335 331 ··· 339 331 /* .graphics and .media determined via GMD_ID */ 340 332 .require_force_probe = true, 341 333 PLATFORM(METEORLAKE), 334 + .dma_mask_size = 46, 342 335 .has_display = true, 336 + .has_pxp = true, 343 337 }; 344 338 345 339 static const struct xe_device_desc lnl_desc = { 346 340 PLATFORM(LUNARLAKE), 341 + .dma_mask_size = 46, 347 342 .has_display = true, 343 + .has_pxp = true, 348 344 }; 349 345 350 346 static const struct xe_device_desc bmg_desc = { 351 347 DGFX_FEATURES, 352 348 PLATFORM(BATTLEMAGE), 349 + .dma_mask_size = 46, 353 350 .has_display = true, 354 351 .has_heci_cscfi = 1, 355 352 }; 356 353 357 354 static const struct xe_device_desc ptl_desc = { 358 355 PLATFORM(PANTHERLAKE), 356 + .dma_mask_size = 46, 359 357 .has_display = true, 358 + .has_sriov = true, 360 359 .require_force_probe = true, 361 360 }; 362 361 ··· 517 502 gt->info.type = XE_GT_TYPE_MAIN; 518 503 } 519 504 505 + xe_gt_mmio_init(gt); 520 506 xe_guc_comm_init_early(&gt->uc.guc); 521 507 522 508 /* Don't bother with GMDID if failed to negotiate the GuC ABI */ ··· 629 613 xe->info.subplatform = subplatform_desc ? 630 614 subplatform_desc->subplatform : XE_SUBPLATFORM_NONE; 631 615 616 + xe->info.dma_mask_size = desc->dma_mask_size; 632 617 xe->info.is_dgfx = desc->is_dgfx; 633 618 xe->info.has_heci_gscfi = desc->has_heci_gscfi; 634 619 xe->info.has_heci_cscfi = desc->has_heci_cscfi; 635 620 xe->info.has_llc = desc->has_llc; 636 - xe->info.has_mmio_ext = desc->has_mmio_ext; 621 + xe->info.has_pxp = desc->has_pxp; 637 622 xe->info.has_sriov = desc->has_sriov; 638 623 xe->info.skip_guc_pc = desc->skip_guc_pc; 639 624 xe->info.skip_mtcfg = desc->skip_mtcfg; ··· 643 626 xe->info.probe_display = IS_ENABLED(CONFIG_DRM_XE_DISPLAY) && 644 627 xe_modparam.probe_display && 645 628 desc->has_display; 629 + xe->info.tile_count = 1 + desc->max_remote_tiles; 646 630 647 631 err = xe_tile_init_early(xe_device_get_root_tile(xe), xe, 0); 648 632 if (err) ··· 695 677 696 678 xe->info.graphics_name = graphics_desc->name; 697 679 xe->info.media_name = media_desc ? media_desc->name : "none"; 698 - xe->info.tile_mmio_ext_size = graphics_desc->tile_mmio_ext_size; 699 680 700 - xe->info.dma_mask_size = graphics_desc->dma_mask_size; 701 681 xe->info.vram_flags = graphics_desc->vram_flags; 702 682 xe->info.va_bits = graphics_desc->va_bits; 703 683 xe->info.vm_max_level = graphics_desc->vm_max_level; ··· 710 694 xe->info.has_range_tlb_invalidation = graphics_desc->has_range_tlb_invalidation; 711 695 xe->info.has_usm = graphics_desc->has_usm; 712 696 713 - /* 714 - * All platforms have at least one primary GT. Any platform with media 715 - * version 13 or higher has an additional dedicated media GT. And 716 - * depending on the graphics IP there may be additional "remote tiles." 717 - * All of these together determine the overall GT count. 718 - * 719 - * FIXME: 'tile_count' here is misnamed since the rest of the driver 720 - * treats it as the number of GTs rather than just the number of tiles. 721 - */ 722 - xe->info.tile_count = 1 + graphics_desc->max_remote_tiles; 723 - 724 697 for_each_remote_tile(tile, xe, id) { 725 698 int err; 726 699 ··· 718 713 return err; 719 714 } 720 715 716 + /* 717 + * All platforms have at least one primary GT. Any platform with media 718 + * version 13 or higher has an additional dedicated media GT. And 719 + * depending on the graphics IP there may be additional "remote tiles." 720 + * All of these together determine the overall GT count. 721 + */ 721 722 for_each_tile(tile, xe, id) { 722 723 gt = tile->primary_gt; 723 724 gt->info.id = xe->info.gt_count++; ··· 773 762 774 763 if (IS_SRIOV_PF(xe)) 775 764 xe_pci_sriov_configure(pdev, 0); 765 + 766 + if (xe_survivability_mode_enabled(xe)) 767 + return xe_survivability_mode_remove(xe); 776 768 777 769 xe_device_remove(xe); 778 770 xe_pm_runtime_fini(xe); ··· 849 835 return err; 850 836 851 837 err = xe_device_probe_early(xe); 852 - if (err) 838 + 839 + /* 840 + * In Boot Survivability mode, no drm card is exposed 841 + * and driver is loaded with bare minimum to allow 842 + * for firmware to be flashed through mei. Return 843 + * success if survivability mode is enabled. 844 + */ 845 + if (err) { 846 + if (xe_survivability_mode_enabled(xe)) 847 + return 0; 848 + 853 849 return err; 850 + } 854 851 855 852 err = xe_info_init(xe, desc->graphics, desc->media); 856 853 if (err) ··· 900 875 return err; 901 876 902 877 err = xe_device_probe(xe); 903 - if (err) 878 + if (err) { 879 + xe_device_call_remove_actions(xe); 904 880 return err; 881 + } 905 882 906 883 err = xe_pm_init(xe); 907 884 if (err) ··· 950 923 static int xe_pci_suspend(struct device *dev) 951 924 { 952 925 struct pci_dev *pdev = to_pci_dev(dev); 926 + struct xe_device *xe = pdev_to_xe_device(pdev); 953 927 int err; 954 928 955 - err = xe_pm_suspend(pdev_to_xe_device(pdev)); 929 + if (xe_survivability_mode_enabled(xe)) 930 + return -EBUSY; 931 + 932 + err = xe_pm_suspend(xe); 956 933 if (err) 957 934 return err; 958 935
-5
drivers/gpu/drm/xe/xe_pci_types.h
··· 13 13 u8 ver; 14 14 u8 rel; 15 15 16 - u8 dma_mask_size; /* available DMA address bits */ 17 16 u8 va_bits; 18 17 u8 vm_max_level; 19 18 u8 vram_flags; 20 19 21 20 u64 hw_engine_mask; /* hardware engines provided by graphics IP */ 22 - 23 - u32 tile_mmio_ext_size; /* size of MMIO extension space, per-tile */ 24 - 25 - u8 max_remote_tiles:2; 26 21 27 22 u8 has_asid:1; 28 23 u8 has_atomic_enable_pte_bit:1;
+14
drivers/gpu/drm/xe/xe_pcode_api.h
··· 49 49 /* Domain IDs (param2) */ 50 50 #define PCODE_MBOX_DOMAIN_HBM 0x2 51 51 52 + #define PCODE_SCRATCH(x) XE_REG(0x138320 + ((x) * 4)) 53 + /* PCODE_SCRATCH0 */ 54 + #define AUXINFO_REG_OFFSET REG_GENMASK(17, 15) 55 + #define OVERFLOW_REG_OFFSET REG_GENMASK(14, 12) 56 + #define HISTORY_TRACKING REG_BIT(11) 57 + #define OVERFLOW_SUPPORT REG_BIT(10) 58 + #define AUXINFO_SUPPORT REG_BIT(9) 59 + #define BOOT_STATUS REG_GENMASK(3, 1) 60 + #define CRITICAL_FAILURE 4 61 + #define NON_CRITICAL_FAILURE 7 62 + 63 + /* Auxiliary info bits */ 64 + #define AUXINFO_HISTORY_OFFSET REG_GENMASK(31, 29) 65 + 52 66 struct pcode_err_decode { 53 67 int errno; 54 68 const char *str;
+31 -10
drivers/gpu/drm/xe/xe_pm.c
··· 22 22 #include "xe_guc.h" 23 23 #include "xe_irq.h" 24 24 #include "xe_pcode.h" 25 + #include "xe_pxp.h" 25 26 #include "xe_trace.h" 26 27 #include "xe_wa.h" 27 28 ··· 91 90 */ 92 91 bool xe_rpm_reclaim_safe(const struct xe_device *xe) 93 92 { 94 - return !xe->d3cold.capable && !xe->info.has_sriov; 93 + return !xe->d3cold.capable; 95 94 } 96 95 97 96 static void xe_rpm_lockmap_acquire(const struct xe_device *xe) ··· 123 122 drm_dbg(&xe->drm, "Suspending device\n"); 124 123 trace_xe_pm_suspend(xe, __builtin_return_address(0)); 125 124 125 + err = xe_pxp_pm_suspend(xe->pxp); 126 + if (err) 127 + goto err; 128 + 126 129 for_each_gt(gt, xe, id) 127 130 xe_gt_suspend_prepare(gt); 128 131 ··· 135 130 /* FIXME: Super racey... */ 136 131 err = xe_bo_evict_all(xe); 137 132 if (err) 138 - goto err; 133 + goto err_pxp; 139 134 140 135 for_each_gt(gt, xe, id) { 141 136 err = xe_gt_suspend(gt); 142 - if (err) { 143 - xe_display_pm_resume(xe); 144 - goto err; 145 - } 137 + if (err) 138 + goto err_display; 146 139 } 147 140 148 141 xe_irq_suspend(xe); ··· 149 146 150 147 drm_dbg(&xe->drm, "Device suspended\n"); 151 148 return 0; 149 + 150 + err_display: 151 + xe_display_pm_resume(xe); 152 + err_pxp: 153 + xe_pxp_pm_resume(xe->pxp); 152 154 err: 153 155 drm_dbg(&xe->drm, "Device suspend failed %d\n", err); 154 156 return err; ··· 202 194 err = xe_bo_restore_user(xe); 203 195 if (err) 204 196 goto err; 197 + 198 + xe_pxp_pm_resume(xe->pxp); 205 199 206 200 drm_dbg(&xe->drm, "Device resumed\n"); 207 201 return 0; ··· 399 389 */ 400 390 xe_rpm_lockmap_acquire(xe); 401 391 392 + err = xe_pxp_pm_suspend(xe->pxp); 393 + if (err) 394 + goto out; 395 + 402 396 /* 403 397 * Applying lock for entire list op as xe_ttm_bo_destroy and xe_bo_move_notify 404 398 * also checks and deletes bo entry from user fault list. ··· 418 404 if (xe->d3cold.allowed) { 419 405 err = xe_bo_evict_all(xe); 420 406 if (err) 421 - goto out; 407 + goto out_resume; 422 408 } 423 409 424 410 for_each_gt(gt, xe, id) { 425 411 err = xe_gt_suspend(gt); 426 412 if (err) 427 - goto out; 413 + goto out_resume; 428 414 } 429 415 430 416 xe_irq_suspend(xe); 431 417 432 418 xe_display_pm_runtime_suspend_late(xe); 433 419 420 + xe_rpm_lockmap_release(xe); 421 + xe_pm_write_callback_task(xe, NULL); 422 + return 0; 423 + 424 + out_resume: 425 + xe_display_pm_runtime_resume(xe); 426 + xe_pxp_pm_resume(xe->pxp); 434 427 out: 435 - if (err) 436 - xe_display_pm_runtime_resume(xe); 437 428 xe_rpm_lockmap_release(xe); 438 429 xe_pm_write_callback_task(xe, NULL); 439 430 return err; ··· 490 471 if (err) 491 472 goto out; 492 473 } 474 + 475 + xe_pxp_pm_resume(xe->pxp); 493 476 494 477 out: 495 478 xe_rpm_lockmap_release(xe);
+374
drivers/gpu/drm/xe/xe_pmu.c
··· 1 + // SPDX-License-Identifier: MIT 2 + /* 3 + * Copyright © 2025 Intel Corporation 4 + */ 5 + 6 + #include <drm/drm_drv.h> 7 + #include <linux/device.h> 8 + 9 + #include "xe_device.h" 10 + #include "xe_gt_idle.h" 11 + #include "xe_pm.h" 12 + #include "xe_pmu.h" 13 + 14 + /** 15 + * DOC: Xe PMU (Performance Monitoring Unit) 16 + * 17 + * Expose events/counters like GT-C6 residency and GT frequency to user land via 18 + * the perf interface. Events are per device. The GT can be selected with an 19 + * extra config sub-field (bits 60-63). 20 + * 21 + * All events are listed in sysfs: 22 + * 23 + * $ ls -ld /sys/bus/event_source/devices/xe_* 24 + * $ ls /sys/bus/event_source/devices/xe_0000_00_02.0/events/ 25 + * $ ls /sys/bus/event_source/devices/xe_0000_00_02.0/format/ 26 + * 27 + * The format directory has info regarding the configs that can be used. 28 + * The standard perf tool can be used to grep for a certain event as well. 29 + * Example: 30 + * 31 + * $ perf list | grep gt-c6 32 + * 33 + * To sample a specific event for a GT at regular intervals: 34 + * 35 + * $ perf stat -e <event_name,gt=> -I <interval> 36 + */ 37 + 38 + #define XE_PMU_EVENT_GT_MASK GENMASK_ULL(63, 60) 39 + #define XE_PMU_EVENT_ID_MASK GENMASK_ULL(11, 0) 40 + 41 + static unsigned int config_to_event_id(u64 config) 42 + { 43 + return FIELD_GET(XE_PMU_EVENT_ID_MASK, config); 44 + } 45 + 46 + static unsigned int config_to_gt_id(u64 config) 47 + { 48 + return FIELD_GET(XE_PMU_EVENT_GT_MASK, config); 49 + } 50 + 51 + #define XE_PMU_EVENT_GT_C6_RESIDENCY 0x01 52 + 53 + static struct xe_gt *event_to_gt(struct perf_event *event) 54 + { 55 + struct xe_device *xe = container_of(event->pmu, typeof(*xe), pmu.base); 56 + u64 gt = config_to_gt_id(event->attr.config); 57 + 58 + return xe_device_get_gt(xe, gt); 59 + } 60 + 61 + static bool event_supported(struct xe_pmu *pmu, unsigned int gt, 62 + unsigned int id) 63 + { 64 + if (gt >= XE_MAX_GT_PER_TILE) 65 + return false; 66 + 67 + return id < sizeof(pmu->supported_events) * BITS_PER_BYTE && 68 + pmu->supported_events & BIT_ULL(id); 69 + } 70 + 71 + static void xe_pmu_event_destroy(struct perf_event *event) 72 + { 73 + struct xe_device *xe = container_of(event->pmu, typeof(*xe), pmu.base); 74 + 75 + drm_WARN_ON(&xe->drm, event->parent); 76 + xe_pm_runtime_put(xe); 77 + drm_dev_put(&xe->drm); 78 + } 79 + 80 + static int xe_pmu_event_init(struct perf_event *event) 81 + { 82 + struct xe_device *xe = container_of(event->pmu, typeof(*xe), pmu.base); 83 + struct xe_pmu *pmu = &xe->pmu; 84 + unsigned int id, gt; 85 + 86 + if (!pmu->registered) 87 + return -ENODEV; 88 + 89 + if (event->attr.type != event->pmu->type) 90 + return -ENOENT; 91 + 92 + /* unsupported modes and filters */ 93 + if (event->attr.sample_period) /* no sampling */ 94 + return -EINVAL; 95 + 96 + if (event->cpu < 0) 97 + return -EINVAL; 98 + 99 + gt = config_to_gt_id(event->attr.config); 100 + id = config_to_event_id(event->attr.config); 101 + if (!event_supported(pmu, gt, id)) 102 + return -ENOENT; 103 + 104 + if (has_branch_stack(event)) 105 + return -EOPNOTSUPP; 106 + 107 + if (!event->parent) { 108 + drm_dev_get(&xe->drm); 109 + xe_pm_runtime_get(xe); 110 + event->destroy = xe_pmu_event_destroy; 111 + } 112 + 113 + return 0; 114 + } 115 + 116 + static u64 __xe_pmu_event_read(struct perf_event *event) 117 + { 118 + struct xe_gt *gt = event_to_gt(event); 119 + 120 + if (!gt) 121 + return 0; 122 + 123 + switch (config_to_event_id(event->attr.config)) { 124 + case XE_PMU_EVENT_GT_C6_RESIDENCY: 125 + return xe_gt_idle_residency_msec(&gt->gtidle); 126 + } 127 + 128 + return 0; 129 + } 130 + 131 + static void xe_pmu_event_update(struct perf_event *event) 132 + { 133 + struct hw_perf_event *hwc = &event->hw; 134 + u64 prev, new; 135 + 136 + prev = local64_read(&hwc->prev_count); 137 + do { 138 + new = __xe_pmu_event_read(event); 139 + } while (!local64_try_cmpxchg(&hwc->prev_count, &prev, new)); 140 + 141 + local64_add(new - prev, &event->count); 142 + } 143 + 144 + static void xe_pmu_event_read(struct perf_event *event) 145 + { 146 + struct xe_device *xe = container_of(event->pmu, typeof(*xe), pmu.base); 147 + struct xe_pmu *pmu = &xe->pmu; 148 + 149 + if (!pmu->registered) { 150 + event->hw.state = PERF_HES_STOPPED; 151 + return; 152 + } 153 + 154 + xe_pmu_event_update(event); 155 + } 156 + 157 + static void xe_pmu_enable(struct perf_event *event) 158 + { 159 + /* 160 + * Store the current counter value so we can report the correct delta 161 + * for all listeners. Even when the event was already enabled and has 162 + * an existing non-zero value. 163 + */ 164 + local64_set(&event->hw.prev_count, __xe_pmu_event_read(event)); 165 + } 166 + 167 + static void xe_pmu_event_start(struct perf_event *event, int flags) 168 + { 169 + struct xe_device *xe = container_of(event->pmu, typeof(*xe), pmu.base); 170 + struct xe_pmu *pmu = &xe->pmu; 171 + 172 + if (!pmu->registered) 173 + return; 174 + 175 + xe_pmu_enable(event); 176 + event->hw.state = 0; 177 + } 178 + 179 + static void xe_pmu_event_stop(struct perf_event *event, int flags) 180 + { 181 + struct xe_device *xe = container_of(event->pmu, typeof(*xe), pmu.base); 182 + struct xe_pmu *pmu = &xe->pmu; 183 + 184 + if (pmu->registered) 185 + if (flags & PERF_EF_UPDATE) 186 + xe_pmu_event_update(event); 187 + 188 + event->hw.state = PERF_HES_STOPPED; 189 + } 190 + 191 + static int xe_pmu_event_add(struct perf_event *event, int flags) 192 + { 193 + struct xe_device *xe = container_of(event->pmu, typeof(*xe), pmu.base); 194 + struct xe_pmu *pmu = &xe->pmu; 195 + 196 + if (!pmu->registered) 197 + return -ENODEV; 198 + 199 + if (flags & PERF_EF_START) 200 + xe_pmu_event_start(event, flags); 201 + 202 + return 0; 203 + } 204 + 205 + static void xe_pmu_event_del(struct perf_event *event, int flags) 206 + { 207 + xe_pmu_event_stop(event, PERF_EF_UPDATE); 208 + } 209 + 210 + PMU_FORMAT_ATTR(gt, "config:60-63"); 211 + PMU_FORMAT_ATTR(event, "config:0-11"); 212 + 213 + static struct attribute *pmu_format_attrs[] = { 214 + &format_attr_event.attr, 215 + &format_attr_gt.attr, 216 + NULL, 217 + }; 218 + 219 + static const struct attribute_group pmu_format_attr_group = { 220 + .name = "format", 221 + .attrs = pmu_format_attrs, 222 + }; 223 + 224 + static ssize_t event_attr_show(struct device *dev, 225 + struct device_attribute *attr, char *buf) 226 + { 227 + struct perf_pmu_events_attr *pmu_attr = 228 + container_of(attr, struct perf_pmu_events_attr, attr); 229 + 230 + return sprintf(buf, "event=%#04llx\n", pmu_attr->id); 231 + } 232 + 233 + #define XE_EVENT_ATTR(name_, v_, id_) \ 234 + PMU_EVENT_ATTR(name_, pmu_event_ ## v_, id_, event_attr_show) 235 + 236 + #define XE_EVENT_ATTR_UNIT(name_, v_, unit_) \ 237 + PMU_EVENT_ATTR_STRING(name_.unit, pmu_event_unit_ ## v_, unit_) 238 + 239 + #define XE_EVENT_ATTR_GROUP(v_, id_, ...) \ 240 + static struct attribute *pmu_attr_ ##v_[] = { \ 241 + __VA_ARGS__, \ 242 + NULL \ 243 + }; \ 244 + static umode_t is_visible_##v_(struct kobject *kobj, \ 245 + struct attribute *attr, int idx) \ 246 + { \ 247 + struct perf_pmu_events_attr *pmu_attr; \ 248 + struct xe_pmu *pmu; \ 249 + \ 250 + pmu_attr = container_of(attr, typeof(*pmu_attr), attr.attr); \ 251 + pmu = container_of(dev_get_drvdata(kobj_to_dev(kobj)), \ 252 + typeof(*pmu), base); \ 253 + \ 254 + return event_supported(pmu, 0, id_) ? attr->mode : 0; \ 255 + } \ 256 + static const struct attribute_group pmu_group_ ##v_ = { \ 257 + .name = "events", \ 258 + .attrs = pmu_attr_ ## v_, \ 259 + .is_visible = is_visible_ ## v_, \ 260 + } 261 + 262 + #define XE_EVENT_ATTR_SIMPLE(name_, v_, id_, unit_) \ 263 + XE_EVENT_ATTR(name_, v_, id_) \ 264 + XE_EVENT_ATTR_UNIT(name_, v_, unit_) \ 265 + XE_EVENT_ATTR_GROUP(v_, id_, &pmu_event_ ##v_.attr.attr, \ 266 + &pmu_event_unit_ ##v_.attr.attr) 267 + 268 + #define XE_EVENT_ATTR_NOUNIT(name_, v_, id_) \ 269 + XE_EVENT_ATTR(name_, v_, id_) \ 270 + XE_EVENT_ATTR_GROUP(v_, id_, &pmu_event_ ##v_.attr.attr) 271 + 272 + XE_EVENT_ATTR_SIMPLE(gt-c6-residency, gt_c6_residency, XE_PMU_EVENT_GT_C6_RESIDENCY, "ms"); 273 + 274 + static struct attribute *pmu_empty_event_attrs[] = { 275 + /* Empty - all events are added as groups with .attr_update() */ 276 + NULL, 277 + }; 278 + 279 + static const struct attribute_group pmu_events_attr_group = { 280 + .name = "events", 281 + .attrs = pmu_empty_event_attrs, 282 + }; 283 + 284 + static const struct attribute_group *pmu_events_attr_update[] = { 285 + &pmu_group_gt_c6_residency, 286 + NULL, 287 + }; 288 + 289 + static void set_supported_events(struct xe_pmu *pmu) 290 + { 291 + struct xe_device *xe = container_of(pmu, typeof(*xe), pmu); 292 + 293 + if (!xe->info.skip_guc_pc) 294 + pmu->supported_events |= BIT_ULL(XE_PMU_EVENT_GT_C6_RESIDENCY); 295 + } 296 + 297 + /** 298 + * xe_pmu_unregister() - Remove/cleanup PMU registration 299 + * @arg: Ptr to pmu 300 + */ 301 + static void xe_pmu_unregister(void *arg) 302 + { 303 + struct xe_pmu *pmu = arg; 304 + struct xe_device *xe = container_of(pmu, typeof(*xe), pmu); 305 + 306 + if (!pmu->registered) 307 + return; 308 + 309 + pmu->registered = false; 310 + 311 + perf_pmu_unregister(&pmu->base); 312 + kfree(pmu->name); 313 + } 314 + 315 + /** 316 + * xe_pmu_register() - Define basic PMU properties for Xe and add event callbacks. 317 + * @pmu: the PMU object 318 + * 319 + * Returns 0 on success and an appropriate error code otherwise 320 + */ 321 + int xe_pmu_register(struct xe_pmu *pmu) 322 + { 323 + struct xe_device *xe = container_of(pmu, typeof(*xe), pmu); 324 + static const struct attribute_group *attr_groups[] = { 325 + &pmu_format_attr_group, 326 + &pmu_events_attr_group, 327 + NULL 328 + }; 329 + int ret = -ENOMEM; 330 + char *name; 331 + 332 + BUILD_BUG_ON(XE_MAX_GT_PER_TILE != XE_PMU_MAX_GT); 333 + 334 + if (IS_SRIOV_VF(xe)) 335 + return 0; 336 + 337 + name = kasprintf(GFP_KERNEL, "xe_%s", 338 + dev_name(xe->drm.dev)); 339 + if (!name) 340 + goto err; 341 + 342 + /* tools/perf reserves colons as special. */ 343 + strreplace(name, ':', '_'); 344 + 345 + pmu->name = name; 346 + pmu->base.attr_groups = attr_groups; 347 + pmu->base.attr_update = pmu_events_attr_update; 348 + pmu->base.scope = PERF_PMU_SCOPE_SYS_WIDE; 349 + pmu->base.module = THIS_MODULE; 350 + pmu->base.task_ctx_nr = perf_invalid_context; 351 + pmu->base.event_init = xe_pmu_event_init; 352 + pmu->base.add = xe_pmu_event_add; 353 + pmu->base.del = xe_pmu_event_del; 354 + pmu->base.start = xe_pmu_event_start; 355 + pmu->base.stop = xe_pmu_event_stop; 356 + pmu->base.read = xe_pmu_event_read; 357 + 358 + set_supported_events(pmu); 359 + 360 + ret = perf_pmu_register(&pmu->base, pmu->name, -1); 361 + if (ret) 362 + goto err_name; 363 + 364 + pmu->registered = true; 365 + 366 + return devm_add_action_or_reset(xe->drm.dev, xe_pmu_unregister, pmu); 367 + 368 + err_name: 369 + kfree(name); 370 + err: 371 + drm_err(&xe->drm, "Failed to register PMU (ret=%d)!\n", ret); 372 + 373 + return ret; 374 + }
+18
drivers/gpu/drm/xe/xe_pmu.h
··· 1 + /* SPDX-License-Identifier: MIT */ 2 + /* 3 + * Copyright © 2025 Intel Corporation 4 + */ 5 + 6 + #ifndef _XE_PMU_H_ 7 + #define _XE_PMU_H_ 8 + 9 + #include "xe_pmu_types.h" 10 + 11 + #if IS_ENABLED(CONFIG_PERF_EVENTS) 12 + int xe_pmu_register(struct xe_pmu *pmu); 13 + #else 14 + static inline int xe_pmu_register(struct xe_pmu *pmu) { return 0; } 15 + #endif 16 + 17 + #endif 18 +
+39
drivers/gpu/drm/xe/xe_pmu_types.h
··· 1 + /* SPDX-License-Identifier: MIT */ 2 + /* 3 + * Copyright © 2025 Intel Corporation 4 + */ 5 + 6 + #ifndef _XE_PMU_TYPES_H_ 7 + #define _XE_PMU_TYPES_H_ 8 + 9 + #include <linux/perf_event.h> 10 + #include <linux/spinlock_types.h> 11 + 12 + #define XE_PMU_MAX_GT 2 13 + 14 + /** 15 + * struct xe_pmu - PMU related data per Xe device 16 + * 17 + * Stores per device PMU info that includes event/perf attributes and sampling 18 + * counters across all GTs for this device. 19 + */ 20 + struct xe_pmu { 21 + /** 22 + * @base: PMU base. 23 + */ 24 + struct pmu base; 25 + /** 26 + * @registered: PMU is registered and not in the unregistering process. 27 + */ 28 + bool registered; 29 + /** 30 + * @name: Name as registered with perf core. 31 + */ 32 + const char *name; 33 + /** 34 + * @supported_events: Bitmap of supported events, indexed by event id 35 + */ 36 + u64 supported_events; 37 + }; 38 + 39 + #endif
+906
drivers/gpu/drm/xe/xe_pxp.c
··· 1 + // SPDX-License-Identifier: MIT 2 + /* 3 + * Copyright(c) 2024 Intel Corporation. 4 + */ 5 + 6 + #include "xe_pxp.h" 7 + 8 + #include <drm/drm_managed.h> 9 + #include <uapi/drm/xe_drm.h> 10 + 11 + #include "xe_bo.h" 12 + #include "xe_bo_types.h" 13 + #include "xe_device_types.h" 14 + #include "xe_exec_queue.h" 15 + #include "xe_force_wake.h" 16 + #include "xe_guc_submit.h" 17 + #include "xe_gsc_proxy.h" 18 + #include "xe_gt.h" 19 + #include "xe_gt_types.h" 20 + #include "xe_huc.h" 21 + #include "xe_mmio.h" 22 + #include "xe_pm.h" 23 + #include "xe_pxp_submit.h" 24 + #include "xe_pxp_types.h" 25 + #include "xe_uc_fw.h" 26 + #include "regs/xe_irq_regs.h" 27 + #include "regs/xe_pxp_regs.h" 28 + 29 + /** 30 + * DOC: PXP 31 + * 32 + * PXP (Protected Xe Path) allows execution and flip to display of protected 33 + * (i.e. encrypted) objects. This feature is currently only supported in 34 + * integrated parts. 35 + */ 36 + 37 + #define ARB_SESSION DRM_XE_PXP_HWDRM_DEFAULT_SESSION /* shorter define */ 38 + 39 + /* 40 + * A submission to GSC can take up to 250ms to complete, so use a 300ms 41 + * timeout for activation where only one of those is involved. Termination 42 + * additionally requires a submission to VCS and an interaction with KCR, so 43 + * bump the timeout to 500ms for that. 44 + */ 45 + #define PXP_ACTIVATION_TIMEOUT_MS 300 46 + #define PXP_TERMINATION_TIMEOUT_MS 500 47 + 48 + bool xe_pxp_is_supported(const struct xe_device *xe) 49 + { 50 + return xe->info.has_pxp && IS_ENABLED(CONFIG_INTEL_MEI_GSC_PROXY); 51 + } 52 + 53 + bool xe_pxp_is_enabled(const struct xe_pxp *pxp) 54 + { 55 + return pxp; 56 + } 57 + 58 + static bool pxp_prerequisites_done(const struct xe_pxp *pxp) 59 + { 60 + struct xe_gt *gt = pxp->gt; 61 + unsigned int fw_ref; 62 + bool ready; 63 + 64 + fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FORCEWAKE_ALL); 65 + 66 + /* 67 + * If force_wake fails we could falsely report the prerequisites as not 68 + * done even if they are; the consequence of this would be that the 69 + * callers won't go ahead with using PXP, but if force_wake doesn't work 70 + * the GT is very likely in a bad state so not really a problem to abort 71 + * PXP. Therefore, we can just log the force_wake error and not escalate 72 + * it. 73 + */ 74 + XE_WARN_ON(!xe_force_wake_ref_has_domain(fw_ref, XE_FORCEWAKE_ALL)); 75 + 76 + /* PXP requires both HuC authentication via GSC and GSC proxy initialized */ 77 + ready = xe_huc_is_authenticated(&gt->uc.huc, XE_HUC_AUTH_VIA_GSC) && 78 + xe_gsc_proxy_init_done(&gt->uc.gsc); 79 + 80 + xe_force_wake_put(gt_to_fw(gt), fw_ref); 81 + 82 + return ready; 83 + } 84 + 85 + /** 86 + * xe_pxp_get_readiness_status - check whether PXP is ready for userspace use 87 + * @pxp: the xe_pxp pointer (can be NULL if PXP is disabled) 88 + * 89 + * Returns: 0 if PXP is not ready yet, 1 if it is ready, a negative errno value 90 + * if PXP is not supported/enabled or if something went wrong in the 91 + * initialization of the prerequisites. Note that the return values of this 92 + * function follow the uapi (see drm_xe_query_pxp_status), so they can be used 93 + * directly in the query ioctl. 94 + */ 95 + int xe_pxp_get_readiness_status(struct xe_pxp *pxp) 96 + { 97 + int ret = 0; 98 + 99 + if (!xe_pxp_is_enabled(pxp)) 100 + return -ENODEV; 101 + 102 + /* if the GSC or HuC FW are in an error state, PXP will never work */ 103 + if (xe_uc_fw_status_to_error(pxp->gt->uc.huc.fw.status) || 104 + xe_uc_fw_status_to_error(pxp->gt->uc.gsc.fw.status)) 105 + return -EIO; 106 + 107 + xe_pm_runtime_get(pxp->xe); 108 + 109 + /* PXP requires both HuC loaded and GSC proxy initialized */ 110 + if (pxp_prerequisites_done(pxp)) 111 + ret = 1; 112 + 113 + xe_pm_runtime_put(pxp->xe); 114 + return ret; 115 + } 116 + 117 + static bool pxp_session_is_in_play(struct xe_pxp *pxp, u32 id) 118 + { 119 + struct xe_gt *gt = pxp->gt; 120 + 121 + return xe_mmio_read32(&gt->mmio, KCR_SIP) & BIT(id); 122 + } 123 + 124 + static int pxp_wait_for_session_state(struct xe_pxp *pxp, u32 id, bool in_play) 125 + { 126 + struct xe_gt *gt = pxp->gt; 127 + u32 mask = BIT(id); 128 + 129 + return xe_mmio_wait32(&gt->mmio, KCR_SIP, mask, in_play ? mask : 0, 130 + 250, NULL, false); 131 + } 132 + 133 + static void pxp_invalidate_queues(struct xe_pxp *pxp); 134 + 135 + static void pxp_invalidate_state(struct xe_pxp *pxp) 136 + { 137 + pxp_invalidate_queues(pxp); 138 + 139 + if (pxp->status == XE_PXP_ACTIVE) 140 + pxp->key_instance++; 141 + } 142 + 143 + static int pxp_terminate_hw(struct xe_pxp *pxp) 144 + { 145 + struct xe_gt *gt = pxp->gt; 146 + unsigned int fw_ref; 147 + int ret = 0; 148 + 149 + drm_dbg(&pxp->xe->drm, "Terminating PXP\n"); 150 + 151 + fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT); 152 + if (!xe_force_wake_ref_has_domain(fw_ref, XE_FW_GT)) { 153 + ret = -EIO; 154 + goto out; 155 + } 156 + 157 + /* terminate the hw session */ 158 + ret = xe_pxp_submit_session_termination(pxp, ARB_SESSION); 159 + if (ret) 160 + goto out; 161 + 162 + ret = pxp_wait_for_session_state(pxp, ARB_SESSION, false); 163 + if (ret) 164 + goto out; 165 + 166 + /* Trigger full HW cleanup */ 167 + xe_mmio_write32(&gt->mmio, KCR_GLOBAL_TERMINATE, 1); 168 + 169 + /* now we can tell the GSC to clean up its own state */ 170 + ret = xe_pxp_submit_session_invalidation(&pxp->gsc_res, ARB_SESSION); 171 + 172 + out: 173 + xe_force_wake_put(gt_to_fw(gt), fw_ref); 174 + return ret; 175 + } 176 + 177 + static void mark_termination_in_progress(struct xe_pxp *pxp) 178 + { 179 + lockdep_assert_held(&pxp->mutex); 180 + 181 + reinit_completion(&pxp->termination); 182 + pxp->status = XE_PXP_TERMINATION_IN_PROGRESS; 183 + } 184 + 185 + static void pxp_terminate(struct xe_pxp *pxp) 186 + { 187 + int ret = 0; 188 + struct xe_device *xe = pxp->xe; 189 + 190 + if (!wait_for_completion_timeout(&pxp->activation, 191 + msecs_to_jiffies(PXP_ACTIVATION_TIMEOUT_MS))) 192 + drm_err(&xe->drm, "failed to wait for PXP start before termination\n"); 193 + 194 + mutex_lock(&pxp->mutex); 195 + 196 + pxp_invalidate_state(pxp); 197 + 198 + /* 199 + * we'll mark the status as needing termination on resume, so no need to 200 + * emit a termination now. 201 + */ 202 + if (pxp->status == XE_PXP_SUSPENDED) { 203 + mutex_unlock(&pxp->mutex); 204 + return; 205 + } 206 + 207 + /* 208 + * If we have a termination already in progress, we need to wait for 209 + * it to complete before queueing another one. Once the first 210 + * termination is completed we'll set the state back to 211 + * NEEDS_TERMINATION and leave it to the pxp start code to issue it. 212 + */ 213 + if (pxp->status == XE_PXP_TERMINATION_IN_PROGRESS) { 214 + pxp->status = XE_PXP_NEEDS_ADDITIONAL_TERMINATION; 215 + mutex_unlock(&pxp->mutex); 216 + return; 217 + } 218 + 219 + mark_termination_in_progress(pxp); 220 + 221 + mutex_unlock(&pxp->mutex); 222 + 223 + ret = pxp_terminate_hw(pxp); 224 + if (ret) { 225 + drm_err(&xe->drm, "PXP termination failed: %pe\n", ERR_PTR(ret)); 226 + mutex_lock(&pxp->mutex); 227 + pxp->status = XE_PXP_ERROR; 228 + complete_all(&pxp->termination); 229 + mutex_unlock(&pxp->mutex); 230 + } 231 + } 232 + 233 + static void pxp_terminate_complete(struct xe_pxp *pxp) 234 + { 235 + /* 236 + * We expect PXP to be in one of 3 states when we get here: 237 + * - XE_PXP_TERMINATION_IN_PROGRESS: a single termination event was 238 + * requested and it is now completing, so we're ready to start. 239 + * - XE_PXP_NEEDS_ADDITIONAL_TERMINATION: a second termination was 240 + * requested while the first one was still being processed. 241 + * - XE_PXP_SUSPENDED: PXP is now suspended, so we defer everything to 242 + * when we come back on resume. 243 + */ 244 + mutex_lock(&pxp->mutex); 245 + 246 + switch (pxp->status) { 247 + case XE_PXP_TERMINATION_IN_PROGRESS: 248 + pxp->status = XE_PXP_READY_TO_START; 249 + break; 250 + case XE_PXP_NEEDS_ADDITIONAL_TERMINATION: 251 + pxp->status = XE_PXP_NEEDS_TERMINATION; 252 + break; 253 + case XE_PXP_SUSPENDED: 254 + /* Nothing to do */ 255 + break; 256 + default: 257 + drm_err(&pxp->xe->drm, 258 + "PXP termination complete while status was %u\n", 259 + pxp->status); 260 + } 261 + 262 + complete_all(&pxp->termination); 263 + 264 + mutex_unlock(&pxp->mutex); 265 + } 266 + 267 + static void pxp_irq_work(struct work_struct *work) 268 + { 269 + struct xe_pxp *pxp = container_of(work, typeof(*pxp), irq.work); 270 + struct xe_device *xe = pxp->xe; 271 + u32 events = 0; 272 + 273 + spin_lock_irq(&xe->irq.lock); 274 + events = pxp->irq.events; 275 + pxp->irq.events = 0; 276 + spin_unlock_irq(&xe->irq.lock); 277 + 278 + if (!events) 279 + return; 280 + 281 + /* 282 + * If we're processing a termination irq while suspending then don't 283 + * bother, we're going to re-init everything on resume anyway. 284 + */ 285 + if ((events & PXP_TERMINATION_REQUEST) && !xe_pm_runtime_get_if_active(xe)) 286 + return; 287 + 288 + if (events & PXP_TERMINATION_REQUEST) { 289 + events &= ~PXP_TERMINATION_COMPLETE; 290 + pxp_terminate(pxp); 291 + } 292 + 293 + if (events & PXP_TERMINATION_COMPLETE) 294 + pxp_terminate_complete(pxp); 295 + 296 + if (events & PXP_TERMINATION_REQUEST) 297 + xe_pm_runtime_put(xe); 298 + } 299 + 300 + /** 301 + * xe_pxp_irq_handler - Handles PXP interrupts. 302 + * @xe: the xe_device structure 303 + * @iir: interrupt vector 304 + */ 305 + void xe_pxp_irq_handler(struct xe_device *xe, u16 iir) 306 + { 307 + struct xe_pxp *pxp = xe->pxp; 308 + 309 + if (!xe_pxp_is_enabled(pxp)) { 310 + drm_err(&xe->drm, "PXP irq 0x%x received with PXP disabled!\n", iir); 311 + return; 312 + } 313 + 314 + lockdep_assert_held(&xe->irq.lock); 315 + 316 + if (unlikely(!iir)) 317 + return; 318 + 319 + if (iir & (KCR_PXP_STATE_TERMINATED_INTERRUPT | 320 + KCR_APP_TERMINATED_PER_FW_REQ_INTERRUPT)) 321 + pxp->irq.events |= PXP_TERMINATION_REQUEST; 322 + 323 + if (iir & KCR_PXP_STATE_RESET_COMPLETE_INTERRUPT) 324 + pxp->irq.events |= PXP_TERMINATION_COMPLETE; 325 + 326 + if (pxp->irq.events) 327 + queue_work(pxp->irq.wq, &pxp->irq.work); 328 + } 329 + 330 + static int kcr_pxp_set_status(const struct xe_pxp *pxp, bool enable) 331 + { 332 + u32 val = enable ? _MASKED_BIT_ENABLE(KCR_INIT_ALLOW_DISPLAY_ME_WRITES) : 333 + _MASKED_BIT_DISABLE(KCR_INIT_ALLOW_DISPLAY_ME_WRITES); 334 + unsigned int fw_ref; 335 + 336 + fw_ref = xe_force_wake_get(gt_to_fw(pxp->gt), XE_FW_GT); 337 + if (!xe_force_wake_ref_has_domain(fw_ref, XE_FW_GT)) 338 + return -EIO; 339 + 340 + xe_mmio_write32(&pxp->gt->mmio, KCR_INIT, val); 341 + xe_force_wake_put(gt_to_fw(pxp->gt), fw_ref); 342 + 343 + return 0; 344 + } 345 + 346 + static int kcr_pxp_enable(const struct xe_pxp *pxp) 347 + { 348 + return kcr_pxp_set_status(pxp, true); 349 + } 350 + 351 + static int kcr_pxp_disable(const struct xe_pxp *pxp) 352 + { 353 + return kcr_pxp_set_status(pxp, false); 354 + } 355 + 356 + static void pxp_fini(void *arg) 357 + { 358 + struct xe_pxp *pxp = arg; 359 + 360 + destroy_workqueue(pxp->irq.wq); 361 + xe_pxp_destroy_execution_resources(pxp); 362 + 363 + /* no need to explicitly disable KCR since we're going to do an FLR */ 364 + } 365 + 366 + /** 367 + * xe_pxp_init - initialize PXP support 368 + * @xe: the xe_device structure 369 + * 370 + * Initialize the HW state and allocate the objects required for PXP support. 371 + * Note that some of the requirement for PXP support (GSC proxy init, HuC auth) 372 + * are performed asynchronously as part of the GSC init. PXP can only be used 373 + * after both this function and the async worker have completed. 374 + * 375 + * Returns 0 if PXP is not supported or if PXP initialization is successful, 376 + * other errno value if there is an error during the init. 377 + */ 378 + int xe_pxp_init(struct xe_device *xe) 379 + { 380 + struct xe_gt *gt = xe->tiles[0].media_gt; 381 + struct xe_pxp *pxp; 382 + int err; 383 + 384 + if (!xe_pxp_is_supported(xe)) 385 + return 0; 386 + 387 + /* we only support PXP on single tile devices with a media GT */ 388 + if (xe->info.tile_count > 1 || !gt) 389 + return 0; 390 + 391 + /* The GSCCS is required for submissions to the GSC FW */ 392 + if (!(gt->info.engine_mask & BIT(XE_HW_ENGINE_GSCCS0))) 393 + return 0; 394 + 395 + /* PXP requires both GSC and HuC firmwares to be available */ 396 + if (!xe_uc_fw_is_loadable(&gt->uc.gsc.fw) || 397 + !xe_uc_fw_is_loadable(&gt->uc.huc.fw)) { 398 + drm_info(&xe->drm, "skipping PXP init due to missing FW dependencies"); 399 + return 0; 400 + } 401 + 402 + pxp = drmm_kzalloc(&xe->drm, sizeof(struct xe_pxp), GFP_KERNEL); 403 + if (!pxp) { 404 + err = -ENOMEM; 405 + goto out; 406 + } 407 + 408 + INIT_LIST_HEAD(&pxp->queues.list); 409 + spin_lock_init(&pxp->queues.lock); 410 + INIT_WORK(&pxp->irq.work, pxp_irq_work); 411 + pxp->xe = xe; 412 + pxp->gt = gt; 413 + 414 + pxp->key_instance = 1; 415 + pxp->last_suspend_key_instance = 1; 416 + 417 + /* 418 + * we'll use the completions to check if there is an action pending, 419 + * so we start them as completed and we reinit it when an action is 420 + * triggered. 421 + */ 422 + init_completion(&pxp->activation); 423 + init_completion(&pxp->termination); 424 + complete_all(&pxp->termination); 425 + complete_all(&pxp->activation); 426 + 427 + mutex_init(&pxp->mutex); 428 + 429 + pxp->irq.wq = alloc_ordered_workqueue("pxp-wq", 0); 430 + if (!pxp->irq.wq) { 431 + err = -ENOMEM; 432 + goto out_free; 433 + } 434 + 435 + err = kcr_pxp_enable(pxp); 436 + if (err) 437 + goto out_wq; 438 + 439 + err = xe_pxp_allocate_execution_resources(pxp); 440 + if (err) 441 + goto out_kcr_disable; 442 + 443 + xe->pxp = pxp; 444 + 445 + return devm_add_action_or_reset(xe->drm.dev, pxp_fini, pxp); 446 + 447 + out_kcr_disable: 448 + kcr_pxp_disable(pxp); 449 + out_wq: 450 + destroy_workqueue(pxp->irq.wq); 451 + out_free: 452 + drmm_kfree(&xe->drm, pxp); 453 + out: 454 + drm_err(&xe->drm, "PXP initialization failed: %pe\n", ERR_PTR(err)); 455 + return err; 456 + } 457 + 458 + static int __pxp_start_arb_session(struct xe_pxp *pxp) 459 + { 460 + int ret; 461 + unsigned int fw_ref; 462 + 463 + fw_ref = xe_force_wake_get(gt_to_fw(pxp->gt), XE_FW_GT); 464 + if (!xe_force_wake_ref_has_domain(fw_ref, XE_FW_GT)) 465 + return -EIO; 466 + 467 + if (pxp_session_is_in_play(pxp, ARB_SESSION)) { 468 + ret = -EEXIST; 469 + goto out_force_wake; 470 + } 471 + 472 + ret = xe_pxp_submit_session_init(&pxp->gsc_res, ARB_SESSION); 473 + if (ret) { 474 + drm_err(&pxp->xe->drm, "Failed to init PXP arb session: %pe\n", ERR_PTR(ret)); 475 + goto out_force_wake; 476 + } 477 + 478 + ret = pxp_wait_for_session_state(pxp, ARB_SESSION, true); 479 + if (ret) { 480 + drm_err(&pxp->xe->drm, "PXP ARB session failed to go in play%pe\n", ERR_PTR(ret)); 481 + goto out_force_wake; 482 + } 483 + 484 + drm_dbg(&pxp->xe->drm, "PXP ARB session is active\n"); 485 + 486 + out_force_wake: 487 + xe_force_wake_put(gt_to_fw(pxp->gt), fw_ref); 488 + return ret; 489 + } 490 + 491 + /** 492 + * xe_pxp_exec_queue_set_type - Mark a queue as using PXP 493 + * @pxp: the xe->pxp pointer (it will be NULL if PXP is disabled) 494 + * @q: the queue to mark as using PXP 495 + * @type: the type of PXP session this queue will use 496 + * 497 + * Returns 0 if the selected PXP type is supported, -ENODEV otherwise. 498 + */ 499 + int xe_pxp_exec_queue_set_type(struct xe_pxp *pxp, struct xe_exec_queue *q, u8 type) 500 + { 501 + if (!xe_pxp_is_enabled(pxp)) 502 + return -ENODEV; 503 + 504 + /* we only support HWDRM sessions right now */ 505 + xe_assert(pxp->xe, type == DRM_XE_PXP_TYPE_HWDRM); 506 + 507 + q->pxp.type = type; 508 + 509 + return 0; 510 + } 511 + 512 + static void __exec_queue_add(struct xe_pxp *pxp, struct xe_exec_queue *q) 513 + { 514 + spin_lock_irq(&pxp->queues.lock); 515 + list_add_tail(&q->pxp.link, &pxp->queues.list); 516 + spin_unlock_irq(&pxp->queues.lock); 517 + } 518 + 519 + /** 520 + * xe_pxp_exec_queue_add - add a queue to the PXP list 521 + * @pxp: the xe->pxp pointer (it will be NULL if PXP is disabled) 522 + * @q: the queue to add to the list 523 + * 524 + * If PXP is enabled and the prerequisites are done, start the PXP ARB 525 + * session (if not already running) and add the queue to the PXP list. Note 526 + * that the queue must have previously been marked as using PXP with 527 + * xe_pxp_exec_queue_set_type. 528 + * 529 + * Returns 0 if the PXP ARB session is running and the queue is in the list, 530 + * -ENODEV if PXP is disabled, -EBUSY if the PXP prerequisites are not done, 531 + * other errno value if something goes wrong during the session start. 532 + */ 533 + int xe_pxp_exec_queue_add(struct xe_pxp *pxp, struct xe_exec_queue *q) 534 + { 535 + int ret = 0; 536 + 537 + if (!xe_pxp_is_enabled(pxp)) 538 + return -ENODEV; 539 + 540 + /* we only support HWDRM sessions right now */ 541 + xe_assert(pxp->xe, q->pxp.type == DRM_XE_PXP_TYPE_HWDRM); 542 + 543 + /* 544 + * Runtime suspend kills PXP, so we take a reference to prevent it from 545 + * happening while we have active queues that use PXP 546 + */ 547 + xe_pm_runtime_get(pxp->xe); 548 + 549 + if (!pxp_prerequisites_done(pxp)) { 550 + ret = -EBUSY; 551 + goto out; 552 + } 553 + 554 + wait_for_idle: 555 + /* 556 + * if there is an action in progress, wait for it. We need to wait 557 + * outside the lock because the completion is done from within the lock. 558 + * Note that the two action should never be pending at the same time. 559 + */ 560 + if (!wait_for_completion_timeout(&pxp->termination, 561 + msecs_to_jiffies(PXP_TERMINATION_TIMEOUT_MS))) { 562 + ret = -ETIMEDOUT; 563 + goto out; 564 + } 565 + 566 + if (!wait_for_completion_timeout(&pxp->activation, 567 + msecs_to_jiffies(PXP_ACTIVATION_TIMEOUT_MS))) { 568 + ret = -ETIMEDOUT; 569 + goto out; 570 + } 571 + 572 + mutex_lock(&pxp->mutex); 573 + 574 + /* If PXP is not already active, turn it on */ 575 + switch (pxp->status) { 576 + case XE_PXP_ERROR: 577 + ret = -EIO; 578 + break; 579 + case XE_PXP_ACTIVE: 580 + __exec_queue_add(pxp, q); 581 + mutex_unlock(&pxp->mutex); 582 + goto out; 583 + case XE_PXP_READY_TO_START: 584 + pxp->status = XE_PXP_START_IN_PROGRESS; 585 + reinit_completion(&pxp->activation); 586 + break; 587 + case XE_PXP_START_IN_PROGRESS: 588 + /* If a start is in progress then the completion must not be done */ 589 + XE_WARN_ON(completion_done(&pxp->activation)); 590 + mutex_unlock(&pxp->mutex); 591 + goto wait_for_idle; 592 + case XE_PXP_NEEDS_TERMINATION: 593 + mark_termination_in_progress(pxp); 594 + break; 595 + case XE_PXP_TERMINATION_IN_PROGRESS: 596 + case XE_PXP_NEEDS_ADDITIONAL_TERMINATION: 597 + /* If a termination is in progress then the completion must not be done */ 598 + XE_WARN_ON(completion_done(&pxp->termination)); 599 + mutex_unlock(&pxp->mutex); 600 + goto wait_for_idle; 601 + case XE_PXP_SUSPENDED: 602 + default: 603 + drm_err(&pxp->xe->drm, "unexpected state during PXP start: %u\n", pxp->status); 604 + ret = -EIO; 605 + break; 606 + } 607 + 608 + mutex_unlock(&pxp->mutex); 609 + 610 + if (ret) 611 + goto out; 612 + 613 + if (!completion_done(&pxp->termination)) { 614 + ret = pxp_terminate_hw(pxp); 615 + if (ret) { 616 + drm_err(&pxp->xe->drm, "PXP termination failed before start\n"); 617 + mutex_lock(&pxp->mutex); 618 + pxp->status = XE_PXP_ERROR; 619 + mutex_unlock(&pxp->mutex); 620 + 621 + goto out; 622 + } 623 + 624 + goto wait_for_idle; 625 + } 626 + 627 + /* All the cases except for start should have exited earlier */ 628 + XE_WARN_ON(completion_done(&pxp->activation)); 629 + ret = __pxp_start_arb_session(pxp); 630 + 631 + mutex_lock(&pxp->mutex); 632 + 633 + complete_all(&pxp->activation); 634 + 635 + /* 636 + * Any other process should wait until the state goes away from 637 + * XE_PXP_START_IN_PROGRESS, so if the state is not that something went 638 + * wrong. Mark the status as needing termination and try again. 639 + */ 640 + if (pxp->status != XE_PXP_START_IN_PROGRESS) { 641 + drm_err(&pxp->xe->drm, "unexpected state after PXP start: %u\n", pxp->status); 642 + pxp->status = XE_PXP_NEEDS_TERMINATION; 643 + mutex_unlock(&pxp->mutex); 644 + goto wait_for_idle; 645 + } 646 + 647 + /* If everything went ok, update the status and add the queue to the list */ 648 + if (!ret) { 649 + pxp->status = XE_PXP_ACTIVE; 650 + __exec_queue_add(pxp, q); 651 + } else { 652 + pxp->status = XE_PXP_ERROR; 653 + } 654 + 655 + mutex_unlock(&pxp->mutex); 656 + 657 + out: 658 + /* 659 + * in the successful case the PM ref is released from 660 + * xe_pxp_exec_queue_remove 661 + */ 662 + if (ret) 663 + xe_pm_runtime_put(pxp->xe); 664 + 665 + return ret; 666 + } 667 + 668 + /** 669 + * xe_pxp_exec_queue_remove - remove a queue from the PXP list 670 + * @pxp: the xe->pxp pointer (it will be NULL if PXP is disabled) 671 + * @q: the queue to remove from the list 672 + * 673 + * If PXP is enabled and the exec_queue is in the list, the queue will be 674 + * removed from the list and its PM reference will be released. It is safe to 675 + * call this function multiple times for the same queue. 676 + */ 677 + void xe_pxp_exec_queue_remove(struct xe_pxp *pxp, struct xe_exec_queue *q) 678 + { 679 + bool need_pm_put = false; 680 + 681 + if (!xe_pxp_is_enabled(pxp)) 682 + return; 683 + 684 + spin_lock_irq(&pxp->queues.lock); 685 + 686 + if (!list_empty(&q->pxp.link)) { 687 + list_del_init(&q->pxp.link); 688 + need_pm_put = true; 689 + } 690 + 691 + q->pxp.type = DRM_XE_PXP_TYPE_NONE; 692 + 693 + spin_unlock_irq(&pxp->queues.lock); 694 + 695 + if (need_pm_put) 696 + xe_pm_runtime_put(pxp->xe); 697 + } 698 + 699 + static void pxp_invalidate_queues(struct xe_pxp *pxp) 700 + { 701 + struct xe_exec_queue *tmp, *q; 702 + 703 + spin_lock_irq(&pxp->queues.lock); 704 + 705 + /* 706 + * Removing a queue from the PXP list requires a put of the RPM ref that 707 + * the queue holds to keep the PXP session alive, which can't be done 708 + * under spinlock. Since it is safe to kill a queue multiple times, we 709 + * can leave the invalid queue in the list for now and postpone the 710 + * removal and associated RPM put to when the queue is destroyed. 711 + */ 712 + list_for_each_entry(tmp, &pxp->queues.list, pxp.link) { 713 + q = xe_exec_queue_get_unless_zero(tmp); 714 + 715 + if (!q) 716 + continue; 717 + 718 + xe_exec_queue_kill(q); 719 + xe_exec_queue_put(q); 720 + } 721 + 722 + spin_unlock_irq(&pxp->queues.lock); 723 + } 724 + 725 + /** 726 + * xe_pxp_key_assign - mark a BO as using the current PXP key iteration 727 + * @pxp: the xe->pxp pointer (it will be NULL if PXP is disabled) 728 + * @bo: the BO to mark 729 + * 730 + * Returns: -ENODEV if PXP is disabled, 0 otherwise. 731 + */ 732 + int xe_pxp_key_assign(struct xe_pxp *pxp, struct xe_bo *bo) 733 + { 734 + if (!xe_pxp_is_enabled(pxp)) 735 + return -ENODEV; 736 + 737 + xe_assert(pxp->xe, !bo->pxp_key_instance); 738 + 739 + /* 740 + * Note that the PXP key handling is inherently racey, because the key 741 + * can theoretically change at any time (although it's unlikely to do 742 + * so without triggers), even right after we copy it. Taking a lock 743 + * wouldn't help because the value might still change as soon as we 744 + * release the lock. 745 + * Userspace needs to handle the fact that their BOs can go invalid at 746 + * any point. 747 + */ 748 + bo->pxp_key_instance = pxp->key_instance; 749 + 750 + return 0; 751 + } 752 + 753 + /** 754 + * xe_pxp_bo_key_check - check if the key used by a xe_bo is valid 755 + * @pxp: the xe->pxp pointer (it will be NULL if PXP is disabled) 756 + * @bo: the BO we want to check 757 + * 758 + * Checks whether a BO was encrypted with the current key or an obsolete one. 759 + * 760 + * Returns: 0 if the key is valid, -ENODEV if PXP is disabled, -EINVAL if the 761 + * BO is not using PXP, -ENOEXEC if the key is not valid. 762 + */ 763 + int xe_pxp_bo_key_check(struct xe_pxp *pxp, struct xe_bo *bo) 764 + { 765 + if (!xe_pxp_is_enabled(pxp)) 766 + return -ENODEV; 767 + 768 + if (!xe_bo_is_protected(bo)) 769 + return -EINVAL; 770 + 771 + xe_assert(pxp->xe, bo->pxp_key_instance); 772 + 773 + /* 774 + * Note that the PXP key handling is inherently racey, because the key 775 + * can theoretically change at any time (although it's unlikely to do 776 + * so without triggers), even right after we check it. Taking a lock 777 + * wouldn't help because the value might still change as soon as we 778 + * release the lock. 779 + * We mitigate the risk by checking the key at multiple points (on each 780 + * submission involving the BO and right before flipping it on the 781 + * display), but there is still a very small chance that we could 782 + * operate on an invalid BO for a single submission or a single frame 783 + * flip. This is a compromise made to protect the encrypted data (which 784 + * is what the key termination is for). 785 + */ 786 + if (bo->pxp_key_instance != pxp->key_instance) 787 + return -ENOEXEC; 788 + 789 + return 0; 790 + } 791 + 792 + /** 793 + * xe_pxp_obj_key_check - check if the key used by a drm_gem_obj is valid 794 + * @pxp: the xe->pxp pointer (it will be NULL if PXP is disabled) 795 + * @obj: the drm_gem_obj we want to check 796 + * 797 + * Checks whether a drm_gem_obj was encrypted with the current key or an 798 + * obsolete one. 799 + * 800 + * Returns: 0 if the key is valid, -ENODEV if PXP is disabled, -EINVAL if the 801 + * obj is not using PXP, -ENOEXEC if the key is not valid. 802 + */ 803 + int xe_pxp_obj_key_check(struct xe_pxp *pxp, struct drm_gem_object *obj) 804 + { 805 + return xe_pxp_bo_key_check(pxp, gem_to_xe_bo(obj)); 806 + } 807 + 808 + /** 809 + * xe_pxp_pm_suspend - prepare PXP for HW suspend 810 + * @pxp: the xe->pxp pointer (it will be NULL if PXP is disabled) 811 + * 812 + * Makes sure all PXP actions have completed and invalidates all PXP queues 813 + * and objects before we go into a suspend state. 814 + * 815 + * Returns: 0 if successful, a negative errno value otherwise. 816 + */ 817 + int xe_pxp_pm_suspend(struct xe_pxp *pxp) 818 + { 819 + int ret = 0; 820 + 821 + if (!xe_pxp_is_enabled(pxp)) 822 + return 0; 823 + 824 + wait_for_activation: 825 + if (!wait_for_completion_timeout(&pxp->activation, 826 + msecs_to_jiffies(PXP_ACTIVATION_TIMEOUT_MS))) 827 + ret = -ETIMEDOUT; 828 + 829 + mutex_lock(&pxp->mutex); 830 + 831 + switch (pxp->status) { 832 + case XE_PXP_ERROR: 833 + case XE_PXP_READY_TO_START: 834 + case XE_PXP_SUSPENDED: 835 + case XE_PXP_TERMINATION_IN_PROGRESS: 836 + case XE_PXP_NEEDS_ADDITIONAL_TERMINATION: 837 + /* 838 + * If PXP is not running there is nothing to cleanup. If there 839 + * is a termination pending then no need to issue another one. 840 + */ 841 + break; 842 + case XE_PXP_START_IN_PROGRESS: 843 + mutex_unlock(&pxp->mutex); 844 + goto wait_for_activation; 845 + case XE_PXP_NEEDS_TERMINATION: 846 + /* If PXP was never used we can skip the cleanup */ 847 + if (pxp->key_instance == pxp->last_suspend_key_instance) 848 + break; 849 + fallthrough; 850 + case XE_PXP_ACTIVE: 851 + pxp_invalidate_state(pxp); 852 + break; 853 + default: 854 + drm_err(&pxp->xe->drm, "unexpected state during PXP suspend: %u", 855 + pxp->status); 856 + ret = -EIO; 857 + goto out; 858 + } 859 + 860 + /* 861 + * We set this even if we were in error state, hoping the suspend clears 862 + * the error. Worse case we fail again and go in error state again. 863 + */ 864 + pxp->status = XE_PXP_SUSPENDED; 865 + 866 + mutex_unlock(&pxp->mutex); 867 + 868 + /* 869 + * if there is a termination in progress, wait for it. 870 + * We need to wait outside the lock because the completion is done from 871 + * within the lock 872 + */ 873 + if (!wait_for_completion_timeout(&pxp->termination, 874 + msecs_to_jiffies(PXP_TERMINATION_TIMEOUT_MS))) 875 + ret = -ETIMEDOUT; 876 + 877 + pxp->last_suspend_key_instance = pxp->key_instance; 878 + 879 + out: 880 + return ret; 881 + } 882 + 883 + /** 884 + * xe_pxp_pm_resume - re-init PXP after HW suspend 885 + * @pxp: the xe->pxp pointer (it will be NULL if PXP is disabled) 886 + */ 887 + void xe_pxp_pm_resume(struct xe_pxp *pxp) 888 + { 889 + int err; 890 + 891 + if (!xe_pxp_is_enabled(pxp)) 892 + return; 893 + 894 + err = kcr_pxp_enable(pxp); 895 + 896 + mutex_lock(&pxp->mutex); 897 + 898 + xe_assert(pxp->xe, pxp->status == XE_PXP_SUSPENDED); 899 + 900 + if (err) 901 + pxp->status = XE_PXP_ERROR; 902 + else 903 + pxp->status = XE_PXP_NEEDS_TERMINATION; 904 + 905 + mutex_unlock(&pxp->mutex); 906 + }
+35
drivers/gpu/drm/xe/xe_pxp.h
··· 1 + /* SPDX-License-Identifier: MIT */ 2 + /* 3 + * Copyright(c) 2024, Intel Corporation. All rights reserved. 4 + */ 5 + 6 + #ifndef __XE_PXP_H__ 7 + #define __XE_PXP_H__ 8 + 9 + #include <linux/types.h> 10 + 11 + struct drm_gem_object; 12 + struct xe_bo; 13 + struct xe_device; 14 + struct xe_exec_queue; 15 + struct xe_pxp; 16 + 17 + bool xe_pxp_is_supported(const struct xe_device *xe); 18 + bool xe_pxp_is_enabled(const struct xe_pxp *pxp); 19 + int xe_pxp_get_readiness_status(struct xe_pxp *pxp); 20 + 21 + int xe_pxp_init(struct xe_device *xe); 22 + void xe_pxp_irq_handler(struct xe_device *xe, u16 iir); 23 + 24 + int xe_pxp_pm_suspend(struct xe_pxp *pxp); 25 + void xe_pxp_pm_resume(struct xe_pxp *pxp); 26 + 27 + int xe_pxp_exec_queue_set_type(struct xe_pxp *pxp, struct xe_exec_queue *q, u8 type); 28 + int xe_pxp_exec_queue_add(struct xe_pxp *pxp, struct xe_exec_queue *q); 29 + void xe_pxp_exec_queue_remove(struct xe_pxp *pxp, struct xe_exec_queue *q); 30 + 31 + int xe_pxp_key_assign(struct xe_pxp *pxp, struct xe_bo *bo); 32 + int xe_pxp_bo_key_check(struct xe_pxp *pxp, struct xe_bo *bo); 33 + int xe_pxp_obj_key_check(struct xe_pxp *pxp, struct drm_gem_object *obj); 34 + 35 + #endif /* __XE_PXP_H__ */
+120
drivers/gpu/drm/xe/xe_pxp_debugfs.c
··· 1 + // SPDX-License-Identifier: MIT 2 + /* 3 + * Copyright © 2024 Intel Corporation 4 + */ 5 + 6 + #include "xe_pxp_debugfs.h" 7 + 8 + #include <linux/debugfs.h> 9 + 10 + #include <drm/drm_debugfs.h> 11 + #include <drm/drm_managed.h> 12 + #include <drm/drm_print.h> 13 + 14 + #include "xe_device.h" 15 + #include "xe_pxp.h" 16 + #include "xe_pxp_types.h" 17 + #include "regs/xe_irq_regs.h" 18 + 19 + static struct xe_pxp *node_to_pxp(struct drm_info_node *node) 20 + { 21 + return node->info_ent->data; 22 + } 23 + 24 + static const char *pxp_status_to_str(struct xe_pxp *pxp) 25 + { 26 + lockdep_assert_held(&pxp->mutex); 27 + 28 + switch (pxp->status) { 29 + case XE_PXP_ERROR: 30 + return "error"; 31 + case XE_PXP_NEEDS_TERMINATION: 32 + return "needs termination"; 33 + case XE_PXP_TERMINATION_IN_PROGRESS: 34 + return "termination in progress"; 35 + case XE_PXP_READY_TO_START: 36 + return "ready to start"; 37 + case XE_PXP_ACTIVE: 38 + return "active"; 39 + case XE_PXP_SUSPENDED: 40 + return "suspended"; 41 + default: 42 + return "unknown"; 43 + } 44 + }; 45 + 46 + static int pxp_info(struct seq_file *m, void *data) 47 + { 48 + struct xe_pxp *pxp = node_to_pxp(m->private); 49 + struct drm_printer p = drm_seq_file_printer(m); 50 + const char *status; 51 + 52 + if (!xe_pxp_is_enabled(pxp)) 53 + return -ENODEV; 54 + 55 + mutex_lock(&pxp->mutex); 56 + status = pxp_status_to_str(pxp); 57 + 58 + drm_printf(&p, "status: %s\n", status); 59 + drm_printf(&p, "instance counter: %u\n", pxp->key_instance); 60 + mutex_unlock(&pxp->mutex); 61 + 62 + return 0; 63 + } 64 + 65 + static int pxp_terminate(struct seq_file *m, void *data) 66 + { 67 + struct xe_pxp *pxp = node_to_pxp(m->private); 68 + struct drm_printer p = drm_seq_file_printer(m); 69 + 70 + if (!xe_pxp_is_enabled(pxp)) 71 + return -ENODEV; 72 + 73 + /* simulate a termination interrupt */ 74 + spin_lock_irq(&pxp->xe->irq.lock); 75 + xe_pxp_irq_handler(pxp->xe, KCR_PXP_STATE_TERMINATED_INTERRUPT); 76 + spin_unlock_irq(&pxp->xe->irq.lock); 77 + 78 + drm_printf(&p, "PXP termination queued\n"); 79 + 80 + return 0; 81 + } 82 + 83 + static const struct drm_info_list debugfs_list[] = { 84 + {"info", pxp_info, 0}, 85 + {"terminate", pxp_terminate, 0}, 86 + }; 87 + 88 + void xe_pxp_debugfs_register(struct xe_pxp *pxp) 89 + { 90 + struct drm_minor *minor; 91 + struct drm_info_list *local; 92 + struct dentry *root; 93 + int i; 94 + 95 + if (!xe_pxp_is_enabled(pxp)) 96 + return; 97 + 98 + minor = pxp->xe->drm.primary; 99 + if (!minor->debugfs_root) 100 + return; 101 + 102 + #define DEBUGFS_SIZE (ARRAY_SIZE(debugfs_list) * sizeof(struct drm_info_list)) 103 + local = drmm_kmalloc(&pxp->xe->drm, DEBUGFS_SIZE, GFP_KERNEL); 104 + if (!local) 105 + return; 106 + 107 + memcpy(local, debugfs_list, DEBUGFS_SIZE); 108 + #undef DEBUGFS_SIZE 109 + 110 + for (i = 0; i < ARRAY_SIZE(debugfs_list); ++i) 111 + local[i].data = pxp; 112 + 113 + root = debugfs_create_dir("pxp", minor->debugfs_root); 114 + if (IS_ERR(root)) 115 + return; 116 + 117 + drm_debugfs_create_files(local, 118 + ARRAY_SIZE(debugfs_list), 119 + root, minor); 120 + }
+13
drivers/gpu/drm/xe/xe_pxp_debugfs.h
··· 1 + /* SPDX-License-Identifier: MIT */ 2 + /* 3 + * Copyright © 2024 Intel Corporation 4 + */ 5 + 6 + #ifndef __XE_PXP_DEBUGFS_H__ 7 + #define __XE_PXP_DEBUGFS_H__ 8 + 9 + struct xe_pxp; 10 + 11 + void xe_pxp_debugfs_register(struct xe_pxp *pxp); 12 + 13 + #endif /* __XE_PXP_DEBUGFS_H__ */
+588
drivers/gpu/drm/xe/xe_pxp_submit.c
··· 1 + // SPDX-License-Identifier: MIT 2 + /* 3 + * Copyright(c) 2024 Intel Corporation. 4 + */ 5 + 6 + #include "xe_pxp_submit.h" 7 + 8 + #include <linux/delay.h> 9 + #include <uapi/drm/xe_drm.h> 10 + 11 + #include "xe_device_types.h" 12 + #include "xe_bb.h" 13 + #include "xe_bo.h" 14 + #include "xe_exec_queue.h" 15 + #include "xe_gsc_submit.h" 16 + #include "xe_gt.h" 17 + #include "xe_lrc.h" 18 + #include "xe_map.h" 19 + #include "xe_pxp.h" 20 + #include "xe_pxp_types.h" 21 + #include "xe_sched_job.h" 22 + #include "xe_vm.h" 23 + #include "abi/gsc_command_header_abi.h" 24 + #include "abi/gsc_pxp_commands_abi.h" 25 + #include "instructions/xe_gsc_commands.h" 26 + #include "instructions/xe_mfx_commands.h" 27 + #include "instructions/xe_mi_commands.h" 28 + 29 + /* 30 + * The VCS is used for kernel-owned GGTT submissions to issue key termination. 31 + * Terminations are serialized, so we only need a single queue and a single 32 + * batch. 33 + */ 34 + static int allocate_vcs_execution_resources(struct xe_pxp *pxp) 35 + { 36 + struct xe_gt *gt = pxp->gt; 37 + struct xe_device *xe = pxp->xe; 38 + struct xe_tile *tile = gt_to_tile(gt); 39 + struct xe_hw_engine *hwe; 40 + struct xe_exec_queue *q; 41 + struct xe_bo *bo; 42 + int err; 43 + 44 + hwe = xe_gt_hw_engine(gt, XE_ENGINE_CLASS_VIDEO_DECODE, 0, true); 45 + if (!hwe) 46 + return -ENODEV; 47 + 48 + q = xe_exec_queue_create(xe, NULL, BIT(hwe->logical_instance), 1, hwe, 49 + EXEC_QUEUE_FLAG_KERNEL | EXEC_QUEUE_FLAG_PERMANENT, 0); 50 + if (IS_ERR(q)) 51 + return PTR_ERR(q); 52 + 53 + /* 54 + * Each termination is 16 DWORDS, so 4K is enough to contain a 55 + * termination for each sessions. 56 + */ 57 + bo = xe_bo_create_pin_map(xe, tile, NULL, SZ_4K, ttm_bo_type_kernel, 58 + XE_BO_FLAG_SYSTEM | XE_BO_FLAG_PINNED | XE_BO_FLAG_GGTT); 59 + if (IS_ERR(bo)) { 60 + err = PTR_ERR(bo); 61 + goto out_queue; 62 + } 63 + 64 + pxp->vcs_exec.q = q; 65 + pxp->vcs_exec.bo = bo; 66 + 67 + return 0; 68 + 69 + out_queue: 70 + xe_exec_queue_put(q); 71 + return err; 72 + } 73 + 74 + static void destroy_vcs_execution_resources(struct xe_pxp *pxp) 75 + { 76 + if (pxp->vcs_exec.bo) 77 + xe_bo_unpin_map_no_vm(pxp->vcs_exec.bo); 78 + 79 + if (pxp->vcs_exec.q) 80 + xe_exec_queue_put(pxp->vcs_exec.q); 81 + } 82 + 83 + #define PXP_BB_SIZE XE_PAGE_SIZE 84 + static int allocate_gsc_client_resources(struct xe_gt *gt, 85 + struct xe_pxp_gsc_client_resources *gsc_res, 86 + size_t inout_size) 87 + { 88 + struct xe_tile *tile = gt_to_tile(gt); 89 + struct xe_device *xe = tile_to_xe(tile); 90 + struct xe_hw_engine *hwe; 91 + struct xe_vm *vm; 92 + struct xe_bo *bo; 93 + struct xe_exec_queue *q; 94 + struct dma_fence *fence; 95 + long timeout; 96 + int err = 0; 97 + 98 + hwe = xe_gt_hw_engine(gt, XE_ENGINE_CLASS_OTHER, 0, true); 99 + 100 + /* we shouldn't reach here if the GSC engine is not available */ 101 + xe_assert(xe, hwe); 102 + 103 + /* PXP instructions must be issued from PPGTT */ 104 + vm = xe_vm_create(xe, XE_VM_FLAG_GSC); 105 + if (IS_ERR(vm)) 106 + return PTR_ERR(vm); 107 + 108 + /* We allocate a single object for the batch and the in/out memory */ 109 + xe_vm_lock(vm, false); 110 + bo = xe_bo_create_pin_map(xe, tile, vm, PXP_BB_SIZE + inout_size * 2, 111 + ttm_bo_type_kernel, 112 + XE_BO_FLAG_SYSTEM | XE_BO_FLAG_PINNED | XE_BO_FLAG_NEEDS_UC); 113 + xe_vm_unlock(vm); 114 + if (IS_ERR(bo)) { 115 + err = PTR_ERR(bo); 116 + goto vm_out; 117 + } 118 + 119 + fence = xe_vm_bind_kernel_bo(vm, bo, NULL, 0, XE_CACHE_WB); 120 + if (IS_ERR(fence)) { 121 + err = PTR_ERR(fence); 122 + goto bo_out; 123 + } 124 + 125 + timeout = dma_fence_wait_timeout(fence, false, HZ); 126 + dma_fence_put(fence); 127 + if (timeout <= 0) { 128 + err = timeout ?: -ETIME; 129 + goto bo_out; 130 + } 131 + 132 + q = xe_exec_queue_create(xe, vm, BIT(hwe->logical_instance), 1, hwe, 133 + EXEC_QUEUE_FLAG_KERNEL | 134 + EXEC_QUEUE_FLAG_PERMANENT, 0); 135 + if (IS_ERR(q)) { 136 + err = PTR_ERR(q); 137 + goto bo_out; 138 + } 139 + 140 + gsc_res->vm = vm; 141 + gsc_res->bo = bo; 142 + gsc_res->inout_size = inout_size; 143 + gsc_res->batch = IOSYS_MAP_INIT_OFFSET(&bo->vmap, 0); 144 + gsc_res->msg_in = IOSYS_MAP_INIT_OFFSET(&bo->vmap, PXP_BB_SIZE); 145 + gsc_res->msg_out = IOSYS_MAP_INIT_OFFSET(&bo->vmap, PXP_BB_SIZE + inout_size); 146 + gsc_res->q = q; 147 + 148 + /* initialize host-session-handle (for all Xe-to-gsc-firmware PXP cmds) */ 149 + gsc_res->host_session_handle = xe_gsc_create_host_session_id(); 150 + 151 + return 0; 152 + 153 + bo_out: 154 + xe_bo_unpin_map_no_vm(bo); 155 + vm_out: 156 + xe_vm_close_and_put(vm); 157 + 158 + return err; 159 + } 160 + 161 + static void destroy_gsc_client_resources(struct xe_pxp_gsc_client_resources *gsc_res) 162 + { 163 + if (!gsc_res->q) 164 + return; 165 + 166 + xe_exec_queue_put(gsc_res->q); 167 + xe_bo_unpin_map_no_vm(gsc_res->bo); 168 + xe_vm_close_and_put(gsc_res->vm); 169 + } 170 + 171 + /** 172 + * xe_pxp_allocate_execution_resources - Allocate PXP submission objects 173 + * @pxp: the xe_pxp structure 174 + * 175 + * Allocates exec_queues objects for VCS and GSCCS submission. The GSCCS 176 + * submissions are done via PPGTT, so this function allocates a VM for it and 177 + * maps the object into it. 178 + * 179 + * Returns 0 if the allocation and mapping is successful, an errno value 180 + * otherwise. 181 + */ 182 + int xe_pxp_allocate_execution_resources(struct xe_pxp *pxp) 183 + { 184 + int err; 185 + 186 + err = allocate_vcs_execution_resources(pxp); 187 + if (err) 188 + return err; 189 + 190 + /* 191 + * PXP commands can require a lot of BO space (see PXP_MAX_PACKET_SIZE), 192 + * but we currently only support a subset of commands that are small 193 + * (< 20 dwords), so a single page is enough for now. 194 + */ 195 + err = allocate_gsc_client_resources(pxp->gt, &pxp->gsc_res, XE_PAGE_SIZE); 196 + if (err) 197 + goto destroy_vcs_context; 198 + 199 + return 0; 200 + 201 + destroy_vcs_context: 202 + destroy_vcs_execution_resources(pxp); 203 + return err; 204 + } 205 + 206 + void xe_pxp_destroy_execution_resources(struct xe_pxp *pxp) 207 + { 208 + destroy_gsc_client_resources(&pxp->gsc_res); 209 + destroy_vcs_execution_resources(pxp); 210 + } 211 + 212 + #define emit_cmd(xe_, map_, offset_, val_) \ 213 + xe_map_wr(xe_, map_, (offset_) * sizeof(u32), u32, val_) 214 + 215 + /* stall until prior PXP and MFX/HCP/HUC objects are completed */ 216 + #define MFX_WAIT_PXP (MFX_WAIT | \ 217 + MFX_WAIT_DW0_PXP_SYNC_CONTROL_FLAG | \ 218 + MFX_WAIT_DW0_MFX_SYNC_CONTROL_FLAG) 219 + static u32 pxp_emit_wait(struct xe_device *xe, struct iosys_map *batch, u32 offset) 220 + { 221 + /* wait for cmds to go through */ 222 + emit_cmd(xe, batch, offset++, MFX_WAIT_PXP); 223 + emit_cmd(xe, batch, offset++, 0); 224 + 225 + return offset; 226 + } 227 + 228 + static u32 pxp_emit_session_selection(struct xe_device *xe, struct iosys_map *batch, 229 + u32 offset, u32 idx) 230 + { 231 + offset = pxp_emit_wait(xe, batch, offset); 232 + 233 + /* pxp off */ 234 + emit_cmd(xe, batch, offset++, MI_FLUSH_DW | MI_FLUSH_IMM_DW); 235 + emit_cmd(xe, batch, offset++, 0); 236 + emit_cmd(xe, batch, offset++, 0); 237 + emit_cmd(xe, batch, offset++, 0); 238 + 239 + /* select session */ 240 + emit_cmd(xe, batch, offset++, MI_SET_APPID | MI_SET_APPID_SESSION_ID(idx)); 241 + emit_cmd(xe, batch, offset++, 0); 242 + 243 + offset = pxp_emit_wait(xe, batch, offset); 244 + 245 + /* pxp on */ 246 + emit_cmd(xe, batch, offset++, MI_FLUSH_DW | 247 + MI_FLUSH_DW_PROTECTED_MEM_EN | 248 + MI_FLUSH_DW_OP_STOREDW | MI_FLUSH_DW_STORE_INDEX | 249 + MI_FLUSH_IMM_DW); 250 + emit_cmd(xe, batch, offset++, LRC_PPHWSP_PXP_INVAL_SCRATCH_ADDR | 251 + MI_FLUSH_DW_USE_GTT); 252 + emit_cmd(xe, batch, offset++, 0); 253 + emit_cmd(xe, batch, offset++, 0); 254 + 255 + offset = pxp_emit_wait(xe, batch, offset); 256 + 257 + return offset; 258 + } 259 + 260 + static u32 pxp_emit_inline_termination(struct xe_device *xe, 261 + struct iosys_map *batch, u32 offset) 262 + { 263 + /* session inline termination */ 264 + emit_cmd(xe, batch, offset++, CRYPTO_KEY_EXCHANGE); 265 + emit_cmd(xe, batch, offset++, 0); 266 + 267 + return offset; 268 + } 269 + 270 + static u32 pxp_emit_session_termination(struct xe_device *xe, struct iosys_map *batch, 271 + u32 offset, u32 idx) 272 + { 273 + offset = pxp_emit_session_selection(xe, batch, offset, idx); 274 + offset = pxp_emit_inline_termination(xe, batch, offset); 275 + 276 + return offset; 277 + } 278 + 279 + /** 280 + * xe_pxp_submit_session_termination - submits a PXP inline termination 281 + * @pxp: the xe_pxp structure 282 + * @id: the session to terminate 283 + * 284 + * Emit an inline termination via the VCS engine to terminate a session. 285 + * 286 + * Returns 0 if the submission is successful, an errno value otherwise. 287 + */ 288 + int xe_pxp_submit_session_termination(struct xe_pxp *pxp, u32 id) 289 + { 290 + struct xe_sched_job *job; 291 + struct dma_fence *fence; 292 + long timeout; 293 + u32 offset = 0; 294 + u64 addr = xe_bo_ggtt_addr(pxp->vcs_exec.bo); 295 + 296 + offset = pxp_emit_session_termination(pxp->xe, &pxp->vcs_exec.bo->vmap, offset, id); 297 + offset = pxp_emit_wait(pxp->xe, &pxp->vcs_exec.bo->vmap, offset); 298 + emit_cmd(pxp->xe, &pxp->vcs_exec.bo->vmap, offset, MI_BATCH_BUFFER_END); 299 + 300 + job = xe_sched_job_create(pxp->vcs_exec.q, &addr); 301 + if (IS_ERR(job)) 302 + return PTR_ERR(job); 303 + 304 + xe_sched_job_arm(job); 305 + fence = dma_fence_get(&job->drm.s_fence->finished); 306 + xe_sched_job_push(job); 307 + 308 + timeout = dma_fence_wait_timeout(fence, false, HZ); 309 + 310 + dma_fence_put(fence); 311 + 312 + if (!timeout) 313 + return -ETIMEDOUT; 314 + else if (timeout < 0) 315 + return timeout; 316 + 317 + return 0; 318 + } 319 + 320 + static bool 321 + is_fw_err_platform_config(u32 type) 322 + { 323 + switch (type) { 324 + case PXP_STATUS_ERROR_API_VERSION: 325 + case PXP_STATUS_PLATFCONFIG_KF1_NOVERIF: 326 + case PXP_STATUS_PLATFCONFIG_KF1_BAD: 327 + case PXP_STATUS_PLATFCONFIG_FIXED_KF1_NOT_SUPPORTED: 328 + return true; 329 + default: 330 + break; 331 + } 332 + return false; 333 + } 334 + 335 + static const char * 336 + fw_err_to_string(u32 type) 337 + { 338 + switch (type) { 339 + case PXP_STATUS_ERROR_API_VERSION: 340 + return "ERR_API_VERSION"; 341 + case PXP_STATUS_NOT_READY: 342 + return "ERR_NOT_READY"; 343 + case PXP_STATUS_PLATFCONFIG_KF1_NOVERIF: 344 + case PXP_STATUS_PLATFCONFIG_KF1_BAD: 345 + case PXP_STATUS_PLATFCONFIG_FIXED_KF1_NOT_SUPPORTED: 346 + return "ERR_PLATFORM_CONFIG"; 347 + default: 348 + break; 349 + } 350 + return NULL; 351 + } 352 + 353 + static int pxp_pkt_submit(struct xe_exec_queue *q, u64 batch_addr) 354 + { 355 + struct xe_gt *gt = q->gt; 356 + struct xe_device *xe = gt_to_xe(gt); 357 + struct xe_sched_job *job; 358 + struct dma_fence *fence; 359 + long timeout; 360 + 361 + xe_assert(xe, q->hwe->engine_id == XE_HW_ENGINE_GSCCS0); 362 + 363 + job = xe_sched_job_create(q, &batch_addr); 364 + if (IS_ERR(job)) 365 + return PTR_ERR(job); 366 + 367 + xe_sched_job_arm(job); 368 + fence = dma_fence_get(&job->drm.s_fence->finished); 369 + xe_sched_job_push(job); 370 + 371 + timeout = dma_fence_wait_timeout(fence, false, HZ); 372 + dma_fence_put(fence); 373 + if (timeout < 0) 374 + return timeout; 375 + else if (!timeout) 376 + return -ETIME; 377 + 378 + return 0; 379 + } 380 + 381 + static void emit_pxp_heci_cmd(struct xe_device *xe, struct iosys_map *batch, 382 + u64 addr_in, u32 size_in, u64 addr_out, u32 size_out) 383 + { 384 + u32 len = 0; 385 + 386 + xe_map_wr(xe, batch, len++ * sizeof(u32), u32, GSC_HECI_CMD_PKT); 387 + xe_map_wr(xe, batch, len++ * sizeof(u32), u32, lower_32_bits(addr_in)); 388 + xe_map_wr(xe, batch, len++ * sizeof(u32), u32, upper_32_bits(addr_in)); 389 + xe_map_wr(xe, batch, len++ * sizeof(u32), u32, size_in); 390 + xe_map_wr(xe, batch, len++ * sizeof(u32), u32, lower_32_bits(addr_out)); 391 + xe_map_wr(xe, batch, len++ * sizeof(u32), u32, upper_32_bits(addr_out)); 392 + xe_map_wr(xe, batch, len++ * sizeof(u32), u32, size_out); 393 + xe_map_wr(xe, batch, len++ * sizeof(u32), u32, 0); 394 + xe_map_wr(xe, batch, len++ * sizeof(u32), u32, MI_BATCH_BUFFER_END); 395 + } 396 + 397 + #define GSC_PENDING_RETRY_MAXCOUNT 40 398 + #define GSC_PENDING_RETRY_PAUSE_MS 50 399 + static int gsccs_send_message(struct xe_pxp_gsc_client_resources *gsc_res, 400 + void *msg_in, size_t msg_in_size, 401 + void *msg_out, size_t msg_out_size_max) 402 + { 403 + struct xe_device *xe = gsc_res->vm->xe; 404 + const size_t max_msg_size = gsc_res->inout_size - sizeof(struct intel_gsc_mtl_header); 405 + u32 wr_offset; 406 + u32 rd_offset; 407 + u32 reply_size; 408 + u32 min_reply_size = 0; 409 + int ret; 410 + int retry = GSC_PENDING_RETRY_MAXCOUNT; 411 + 412 + if (msg_in_size > max_msg_size || msg_out_size_max > max_msg_size) 413 + return -ENOSPC; 414 + 415 + wr_offset = xe_gsc_emit_header(xe, &gsc_res->msg_in, 0, 416 + HECI_MEADDRESS_PXP, 417 + gsc_res->host_session_handle, 418 + msg_in_size); 419 + 420 + /* NOTE: zero size packets are used for session-cleanups */ 421 + if (msg_in && msg_in_size) { 422 + xe_map_memcpy_to(xe, &gsc_res->msg_in, wr_offset, 423 + msg_in, msg_in_size); 424 + min_reply_size = sizeof(struct pxp_cmd_header); 425 + } 426 + 427 + /* Make sure the reply header does not contain stale data */ 428 + xe_gsc_poison_header(xe, &gsc_res->msg_out, 0); 429 + 430 + /* 431 + * The BO is mapped at address 0 of the PPGTT, so no need to add its 432 + * base offset when calculating the in/out addresses. 433 + */ 434 + emit_pxp_heci_cmd(xe, &gsc_res->batch, PXP_BB_SIZE, 435 + wr_offset + msg_in_size, PXP_BB_SIZE + gsc_res->inout_size, 436 + wr_offset + msg_out_size_max); 437 + 438 + xe_device_wmb(xe); 439 + 440 + /* 441 + * If the GSC needs to communicate with CSME to complete our request, 442 + * it'll set the "pending" flag in the return header. In this scenario 443 + * we're expected to wait 50ms to give some time to the proxy code to 444 + * handle the GSC<->CSME communication and then try again. Note that, 445 + * although in most case the 50ms window is enough, the proxy flow is 446 + * not actually guaranteed to complete within that time period, so we 447 + * might have to try multiple times, up to a worst case of 2 seconds, 448 + * after which the request is considered aborted. 449 + */ 450 + do { 451 + ret = pxp_pkt_submit(gsc_res->q, 0); 452 + if (ret) 453 + break; 454 + 455 + if (xe_gsc_check_and_update_pending(xe, &gsc_res->msg_in, 0, 456 + &gsc_res->msg_out, 0)) { 457 + ret = -EAGAIN; 458 + msleep(GSC_PENDING_RETRY_PAUSE_MS); 459 + } 460 + } while (--retry && ret == -EAGAIN); 461 + 462 + if (ret) { 463 + drm_err(&xe->drm, "failed to submit GSC PXP message (%pe)\n", ERR_PTR(ret)); 464 + return ret; 465 + } 466 + 467 + ret = xe_gsc_read_out_header(xe, &gsc_res->msg_out, 0, 468 + min_reply_size, &rd_offset); 469 + if (ret) { 470 + drm_err(&xe->drm, "invalid GSC reply for PXP (%pe)\n", ERR_PTR(ret)); 471 + return ret; 472 + } 473 + 474 + if (msg_out && min_reply_size) { 475 + reply_size = xe_map_rd_field(xe, &gsc_res->msg_out, rd_offset, 476 + struct pxp_cmd_header, buffer_len); 477 + reply_size += sizeof(struct pxp_cmd_header); 478 + 479 + if (reply_size > msg_out_size_max) { 480 + drm_warn(&xe->drm, "PXP reply size overflow: %u (%zu)\n", 481 + reply_size, msg_out_size_max); 482 + reply_size = msg_out_size_max; 483 + } 484 + 485 + xe_map_memcpy_from(xe, msg_out, &gsc_res->msg_out, 486 + rd_offset, reply_size); 487 + } 488 + 489 + xe_gsc_poison_header(xe, &gsc_res->msg_in, 0); 490 + 491 + return ret; 492 + } 493 + 494 + /** 495 + * xe_pxp_submit_session_init - submits a PXP GSC session initialization 496 + * @gsc_res: the pxp client resources 497 + * @id: the session to initialize 498 + * 499 + * Submit a message to the GSC FW to initialize (i.e. start) a PXP session. 500 + * 501 + * Returns 0 if the submission is successful, an errno value otherwise. 502 + */ 503 + int xe_pxp_submit_session_init(struct xe_pxp_gsc_client_resources *gsc_res, u32 id) 504 + { 505 + struct xe_device *xe = gsc_res->vm->xe; 506 + struct pxp43_create_arb_in msg_in = {0}; 507 + struct pxp43_create_arb_out msg_out = {0}; 508 + int ret; 509 + 510 + msg_in.header.api_version = PXP_APIVER(4, 3); 511 + msg_in.header.command_id = PXP43_CMDID_INIT_SESSION; 512 + msg_in.header.stream_id = (FIELD_PREP(PXP43_INIT_SESSION_APPID, id) | 513 + FIELD_PREP(PXP43_INIT_SESSION_VALID, 1) | 514 + FIELD_PREP(PXP43_INIT_SESSION_APPTYPE, 0)); 515 + msg_in.header.buffer_len = sizeof(msg_in) - sizeof(msg_in.header); 516 + 517 + if (id == DRM_XE_PXP_HWDRM_DEFAULT_SESSION) 518 + msg_in.protection_mode = PXP43_INIT_SESSION_PROTECTION_ARB; 519 + 520 + ret = gsccs_send_message(gsc_res, &msg_in, sizeof(msg_in), 521 + &msg_out, sizeof(msg_out)); 522 + if (ret) { 523 + drm_err(&xe->drm, "Failed to init PXP session %u (%pe)\n", id, ERR_PTR(ret)); 524 + } else if (msg_out.header.status != 0) { 525 + ret = -EIO; 526 + 527 + if (is_fw_err_platform_config(msg_out.header.status)) 528 + drm_info_once(&xe->drm, 529 + "Failed to init PXP session %u due to BIOS/SOC, s=0x%x(%s)\n", 530 + id, msg_out.header.status, 531 + fw_err_to_string(msg_out.header.status)); 532 + else 533 + drm_dbg(&xe->drm, "Failed to init PXP session %u, s=0x%x\n", 534 + id, msg_out.header.status); 535 + } 536 + 537 + return ret; 538 + } 539 + 540 + /** 541 + * xe_pxp_submit_session_invalidation - submits a PXP GSC invalidation 542 + * @gsc_res: the pxp client resources 543 + * @id: the session to invalidate 544 + * 545 + * Submit a message to the GSC FW to notify it that a session has been 546 + * terminated and is therefore invalid. 547 + * 548 + * Returns 0 if the submission is successful, an errno value otherwise. 549 + */ 550 + int xe_pxp_submit_session_invalidation(struct xe_pxp_gsc_client_resources *gsc_res, u32 id) 551 + { 552 + struct xe_device *xe = gsc_res->vm->xe; 553 + struct pxp43_inv_stream_key_in msg_in = {0}; 554 + struct pxp43_inv_stream_key_out msg_out = {0}; 555 + int ret = 0; 556 + 557 + /* 558 + * Stream key invalidation reuses the same version 4.2 input/output 559 + * command format but firmware requires 4.3 API interaction 560 + */ 561 + msg_in.header.api_version = PXP_APIVER(4, 3); 562 + msg_in.header.command_id = PXP43_CMDID_INVALIDATE_STREAM_KEY; 563 + msg_in.header.buffer_len = sizeof(msg_in) - sizeof(msg_in.header); 564 + 565 + msg_in.header.stream_id = FIELD_PREP(PXP_CMDHDR_EXTDATA_SESSION_VALID, 1); 566 + msg_in.header.stream_id |= FIELD_PREP(PXP_CMDHDR_EXTDATA_APP_TYPE, 0); 567 + msg_in.header.stream_id |= FIELD_PREP(PXP_CMDHDR_EXTDATA_SESSION_ID, id); 568 + 569 + ret = gsccs_send_message(gsc_res, &msg_in, sizeof(msg_in), 570 + &msg_out, sizeof(msg_out)); 571 + if (ret) { 572 + drm_err(&xe->drm, "Failed to invalidate PXP stream-key %u (%pe)\n", 573 + id, ERR_PTR(ret)); 574 + } else if (msg_out.header.status != 0) { 575 + ret = -EIO; 576 + 577 + if (is_fw_err_platform_config(msg_out.header.status)) 578 + drm_info_once(&xe->drm, 579 + "Failed to invalidate PXP stream-key %u: BIOS/SOC 0x%08x(%s)\n", 580 + id, msg_out.header.status, 581 + fw_err_to_string(msg_out.header.status)); 582 + else 583 + drm_dbg(&xe->drm, "Failed to invalidate stream-key %u, s=0x%08x\n", 584 + id, msg_out.header.status); 585 + } 586 + 587 + return ret; 588 + }
+22
drivers/gpu/drm/xe/xe_pxp_submit.h
··· 1 + /* SPDX-License-Identifier: MIT */ 2 + /* 3 + * Copyright(c) 2024, Intel Corporation. All rights reserved. 4 + */ 5 + 6 + #ifndef __XE_PXP_SUBMIT_H__ 7 + #define __XE_PXP_SUBMIT_H__ 8 + 9 + #include <linux/types.h> 10 + 11 + struct xe_pxp; 12 + struct xe_pxp_gsc_client_resources; 13 + 14 + int xe_pxp_allocate_execution_resources(struct xe_pxp *pxp); 15 + void xe_pxp_destroy_execution_resources(struct xe_pxp *pxp); 16 + 17 + int xe_pxp_submit_session_init(struct xe_pxp_gsc_client_resources *gsc_res, u32 id); 18 + int xe_pxp_submit_session_termination(struct xe_pxp *pxp, u32 id); 19 + int xe_pxp_submit_session_invalidation(struct xe_pxp_gsc_client_resources *gsc_res, 20 + u32 id); 21 + 22 + #endif /* __XE_PXP_SUBMIT_H__ */
+135
drivers/gpu/drm/xe/xe_pxp_types.h
··· 1 + /* SPDX-License-Identifier: MIT */ 2 + /* 3 + * Copyright(c) 2024, Intel Corporation. All rights reserved. 4 + */ 5 + 6 + #ifndef __XE_PXP_TYPES_H__ 7 + #define __XE_PXP_TYPES_H__ 8 + 9 + #include <linux/completion.h> 10 + #include <linux/iosys-map.h> 11 + #include <linux/mutex.h> 12 + #include <linux/spinlock.h> 13 + #include <linux/types.h> 14 + #include <linux/workqueue.h> 15 + 16 + struct xe_bo; 17 + struct xe_exec_queue; 18 + struct xe_device; 19 + struct xe_gt; 20 + struct xe_vm; 21 + 22 + enum xe_pxp_status { 23 + XE_PXP_ERROR = -1, 24 + XE_PXP_NEEDS_TERMINATION = 0, /* starting status */ 25 + XE_PXP_NEEDS_ADDITIONAL_TERMINATION, 26 + XE_PXP_TERMINATION_IN_PROGRESS, 27 + XE_PXP_READY_TO_START, 28 + XE_PXP_START_IN_PROGRESS, 29 + XE_PXP_ACTIVE, 30 + XE_PXP_SUSPENDED, 31 + }; 32 + 33 + /** 34 + * struct xe_pxp_gsc_client_resources - resources for GSC submission by a PXP 35 + * client. The GSC FW supports multiple GSC client active at the same time. 36 + */ 37 + struct xe_pxp_gsc_client_resources { 38 + /** 39 + * @host_session_handle: handle used to identify the client in messages 40 + * sent to the GSC firmware. 41 + */ 42 + u64 host_session_handle; 43 + /** @vm: VM used for PXP submissions to the GSCCS */ 44 + struct xe_vm *vm; 45 + /** @q: GSCCS exec queue for PXP submissions */ 46 + struct xe_exec_queue *q; 47 + 48 + /** 49 + * @bo: BO used for submissions to the GSCCS and GSC FW. It includes 50 + * space for the GSCCS batch and the input/output buffers read/written 51 + * by the FW 52 + */ 53 + struct xe_bo *bo; 54 + /** @inout_size: size of each of the msg_in/out sections individually */ 55 + u32 inout_size; 56 + /** @batch: iosys_map to the batch memory within the BO */ 57 + struct iosys_map batch; 58 + /** @msg_in: iosys_map to the input memory within the BO */ 59 + struct iosys_map msg_in; 60 + /** @msg_out: iosys_map to the output memory within the BO */ 61 + struct iosys_map msg_out; 62 + }; 63 + 64 + /** 65 + * struct xe_pxp - pxp state 66 + */ 67 + struct xe_pxp { 68 + /** @xe: Backpoiner to the xe_device struct */ 69 + struct xe_device *xe; 70 + 71 + /** 72 + * @gt: pointer to the gt that owns the submission-side of PXP 73 + * (VDBOX, KCR and GSC) 74 + */ 75 + struct xe_gt *gt; 76 + 77 + /** @vcs_exec: kernel-owned objects for PXP submissions to the VCS */ 78 + struct { 79 + /** @vcs_exec.q: kernel-owned VCS exec queue used for PXP terminations */ 80 + struct xe_exec_queue *q; 81 + /** @vcs_exec.bo: BO used for submissions to the VCS */ 82 + struct xe_bo *bo; 83 + } vcs_exec; 84 + 85 + /** @gsc_res: kernel-owned objects for PXP submissions to the GSCCS */ 86 + struct xe_pxp_gsc_client_resources gsc_res; 87 + 88 + /** @irq: wrapper for the worker and queue used for PXP irq support */ 89 + struct { 90 + /** @irq.work: worker that manages irq events. */ 91 + struct work_struct work; 92 + /** @irq.wq: workqueue on which to queue the irq work. */ 93 + struct workqueue_struct *wq; 94 + /** @irq.events: pending events, protected with xe->irq.lock. */ 95 + u32 events; 96 + #define PXP_TERMINATION_REQUEST BIT(0) 97 + #define PXP_TERMINATION_COMPLETE BIT(1) 98 + } irq; 99 + 100 + /** @mutex: protects the pxp status and the queue list */ 101 + struct mutex mutex; 102 + /** @status: the current pxp status */ 103 + enum xe_pxp_status status; 104 + /** @activation: completion struct that tracks pxp start */ 105 + struct completion activation; 106 + /** @termination: completion struct that tracks terminations */ 107 + struct completion termination; 108 + 109 + /** @queues: management of exec_queues that use PXP */ 110 + struct { 111 + /** @queues.lock: spinlock protecting the queue management */ 112 + spinlock_t lock; 113 + /** @queues.list: list of exec_queues that use PXP */ 114 + struct list_head list; 115 + } queues; 116 + 117 + /** 118 + * @key_instance: keep track of the current iteration of the PXP key. 119 + * Note that, due to the time needed for PXP termination and re-start 120 + * to complete, the minimum time between 2 subsequent increases of this 121 + * variable is 50ms, and even that only if there is a continuous attack; 122 + * normal behavior is for this to increase much much slower than that. 123 + * This means that we don't expect this to ever wrap and don't implement 124 + * that case in the code. 125 + */ 126 + u32 key_instance; 127 + /** 128 + * @last_suspend_key_instance: value of key_instance at the last 129 + * suspend. Used to check if any PXP session has been created between 130 + * suspend cycles. 131 + */ 132 + u32 last_suspend_key_instance; 133 + }; 134 + 135 + #endif /* __XE_PXP_TYPES_H__ */
+32
drivers/gpu/drm/xe/xe_query.c
··· 24 24 #include "xe_macros.h" 25 25 #include "xe_mmio.h" 26 26 #include "xe_oa.h" 27 + #include "xe_pxp.h" 27 28 #include "xe_ttm_vram_mgr.h" 28 29 #include "xe_wa.h" 29 30 ··· 120 119 struct xe_hw_engine *hwe; 121 120 struct xe_gt *gt; 122 121 unsigned int fw_ref; 122 + 123 + if (IS_SRIOV_VF(xe)) 124 + return -EOPNOTSUPP; 123 125 124 126 if (query->size == 0) { 125 127 query->size = size; ··· 702 698 return ret ? -EFAULT : 0; 703 699 } 704 700 701 + static int query_pxp_status(struct xe_device *xe, struct drm_xe_device_query *query) 702 + { 703 + struct drm_xe_query_pxp_status __user *query_ptr = u64_to_user_ptr(query->data); 704 + size_t size = sizeof(struct drm_xe_query_pxp_status); 705 + struct drm_xe_query_pxp_status resp = { 0 }; 706 + int ret; 707 + 708 + if (query->size == 0) { 709 + query->size = size; 710 + return 0; 711 + } else if (XE_IOCTL_DBG(xe, query->size != size)) { 712 + return -EINVAL; 713 + } 714 + 715 + ret = xe_pxp_get_readiness_status(xe->pxp); 716 + if (ret < 0) 717 + return ret; 718 + 719 + resp.status = ret; 720 + resp.supported_session_types = BIT(DRM_XE_PXP_TYPE_HWDRM); 721 + 722 + if (copy_to_user(query_ptr, &resp, size)) 723 + return -EFAULT; 724 + 725 + return 0; 726 + } 727 + 705 728 static int (* const xe_query_funcs[])(struct xe_device *xe, 706 729 struct drm_xe_device_query *query) = { 707 730 query_engines, ··· 740 709 query_engine_cycles, 741 710 query_uc_fw_version, 742 711 query_oa_units, 712 + query_pxp_status, 743 713 }; 744 714 745 715 int xe_query_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
+2 -2
drivers/gpu/drm/xe/xe_ring_ops.c
··· 118 118 dw[i++] |= MI_INVALIDATE_TLB | MI_FLUSH_DW_OP_STOREDW | MI_FLUSH_IMM_DW | 119 119 MI_FLUSH_DW_STORE_INDEX; 120 120 121 - dw[i++] = LRC_PPHWSP_SCRATCH_ADDR | MI_FLUSH_DW_USE_GTT; 121 + dw[i++] = LRC_PPHWSP_FLUSH_INVAL_SCRATCH_ADDR | MI_FLUSH_DW_USE_GTT; 122 122 dw[i++] = 0; 123 123 dw[i++] = ~0U; 124 124 ··· 156 156 157 157 flags &= ~mask_flags; 158 158 159 - return emit_pipe_control(dw, i, 0, flags, LRC_PPHWSP_SCRATCH_ADDR, 0); 159 + return emit_pipe_control(dw, i, 0, flags, LRC_PPHWSP_FLUSH_INVAL_SCRATCH_ADDR, 0); 160 160 } 161 161 162 162 static int emit_store_imm_ppgtt_posted(u64 addr, u64 value,
+34 -17
drivers/gpu/drm/xe/xe_sa.c
··· 31 31 sa_manager->bo = NULL; 32 32 } 33 33 34 - struct xe_sa_manager *xe_sa_bo_manager_init(struct xe_tile *tile, u32 size, u32 align) 34 + /** 35 + * __xe_sa_bo_manager_init() - Create and initialize the suballocator 36 + * @tile: the &xe_tile where allocate 37 + * @size: number of bytes to allocate 38 + * @guard: number of bytes to exclude from suballocations 39 + * @align: alignment for each suballocated chunk 40 + * 41 + * Prepares the suballocation manager for suballocations. 42 + * 43 + * Return: a pointer to the &xe_sa_manager or an ERR_PTR on failure. 44 + */ 45 + struct xe_sa_manager *__xe_sa_bo_manager_init(struct xe_tile *tile, u32 size, u32 guard, u32 align) 35 46 { 36 47 struct xe_device *xe = tile_to_xe(tile); 37 - u32 managed_size = size - SZ_4K; 48 + struct xe_sa_manager *sa_manager; 49 + u32 managed_size; 38 50 struct xe_bo *bo; 39 51 int ret; 40 52 41 - struct xe_sa_manager *sa_manager = drmm_kzalloc(&tile_to_xe(tile)->drm, 42 - sizeof(*sa_manager), 43 - GFP_KERNEL); 53 + xe_tile_assert(tile, size > guard); 54 + managed_size = size - guard; 55 + 56 + sa_manager = drmm_kzalloc(&xe->drm, sizeof(*sa_manager), GFP_KERNEL); 44 57 if (!sa_manager) 45 58 return ERR_PTR(-ENOMEM); 46 - 47 - sa_manager->bo = NULL; 48 59 49 60 bo = xe_managed_bo_create_pin_map(xe, tile, size, 50 61 XE_BO_FLAG_VRAM_IF_DGFX(tile) | 51 62 XE_BO_FLAG_GGTT | 52 63 XE_BO_FLAG_GGTT_INVALIDATE); 53 64 if (IS_ERR(bo)) { 54 - drm_err(&xe->drm, "failed to allocate bo for sa manager: %ld\n", 55 - PTR_ERR(bo)); 65 + drm_err(&xe->drm, "Failed to prepare %uKiB BO for SA manager (%pe)\n", 66 + size / SZ_1K, bo); 56 67 return ERR_CAST(bo); 57 68 } 58 69 sa_manager->bo = bo; 59 70 sa_manager->is_iomem = bo->vmap.is_iomem; 60 - 61 - drm_suballoc_manager_init(&sa_manager->base, managed_size, align); 62 71 sa_manager->gpu_addr = xe_bo_ggtt_addr(bo); 63 72 64 73 if (bo->vmap.is_iomem) { 65 74 sa_manager->cpu_ptr = kvzalloc(managed_size, GFP_KERNEL); 66 - if (!sa_manager->cpu_ptr) { 67 - sa_manager->bo = NULL; 75 + if (!sa_manager->cpu_ptr) 68 76 return ERR_PTR(-ENOMEM); 69 - } 70 77 } else { 71 78 sa_manager->cpu_ptr = bo->vmap.vaddr; 72 79 memset(sa_manager->cpu_ptr, 0, bo->ttm.base.size); 73 80 } 74 81 82 + drm_suballoc_manager_init(&sa_manager->base, managed_size, align); 75 83 ret = drmm_add_action_or_reset(&xe->drm, xe_sa_bo_manager_fini, 76 84 sa_manager); 77 85 if (ret) ··· 88 80 return sa_manager; 89 81 } 90 82 91 - struct drm_suballoc *xe_sa_bo_new(struct xe_sa_manager *sa_manager, 92 - unsigned int size) 83 + /** 84 + * __xe_sa_bo_new() - Make a suballocation but use custom gfp flags. 85 + * @sa_manager: the &xe_sa_manager 86 + * @size: number of bytes we want to suballocate 87 + * @gfp: gfp flags used for memory allocation. Typically GFP_KERNEL. 88 + * 89 + * Try to make a suballocation of size @size. 90 + * 91 + * Return: a &drm_suballoc, or an ERR_PTR. 92 + */ 93 + struct drm_suballoc *__xe_sa_bo_new(struct xe_sa_manager *sa_manager, u32 size, gfp_t gfp) 93 94 { 94 95 /* 95 96 * BB to large, return -ENOBUFS indicating user should split ··· 107 90 if (size > sa_manager->base.size) 108 91 return ERR_PTR(-ENOBUFS); 109 92 110 - return drm_suballoc_new(&sa_manager->base, size, GFP_KERNEL, true, 0); 93 + return drm_suballoc_new(&sa_manager->base, size, gfp, true, 0); 111 94 } 112 95 113 96 void xe_sa_bo_flush_write(struct drm_suballoc *sa_bo)
+24 -6
drivers/gpu/drm/xe/xe_sa.h
··· 5 5 #ifndef _XE_SA_H_ 6 6 #define _XE_SA_H_ 7 7 8 + #include <linux/sizes.h> 9 + #include <linux/types.h> 8 10 #include "xe_sa_types.h" 9 11 10 12 struct dma_fence; 11 - struct xe_bo; 12 13 struct xe_tile; 13 14 14 - struct xe_sa_manager *xe_sa_bo_manager_init(struct xe_tile *tile, u32 size, u32 align); 15 + struct xe_sa_manager *__xe_sa_bo_manager_init(struct xe_tile *tile, u32 size, u32 guard, u32 align); 16 + struct drm_suballoc *__xe_sa_bo_new(struct xe_sa_manager *sa_manager, u32 size, gfp_t gfp); 15 17 16 - struct drm_suballoc *xe_sa_bo_new(struct xe_sa_manager *sa_manager, 17 - u32 size); 18 + static inline struct xe_sa_manager *xe_sa_bo_manager_init(struct xe_tile *tile, u32 size, u32 align) 19 + { 20 + return __xe_sa_bo_manager_init(tile, size, SZ_4K, align); 21 + } 22 + 23 + /** 24 + * xe_sa_bo_new() - Make a suballocation. 25 + * @sa_manager: the &xe_sa_manager 26 + * @size: number of bytes we want to suballocate 27 + * 28 + * Try to make a suballocation of size @size. 29 + * 30 + * Return: a &drm_suballoc, or an ERR_PTR. 31 + */ 32 + static inline struct drm_suballoc *xe_sa_bo_new(struct xe_sa_manager *sa_manager, u32 size) 33 + { 34 + return __xe_sa_bo_new(sa_manager, size, GFP_KERNEL); 35 + } 36 + 18 37 void xe_sa_bo_flush_write(struct drm_suballoc *sa_bo); 19 - void xe_sa_bo_free(struct drm_suballoc *sa_bo, 20 - struct dma_fence *fence); 38 + void xe_sa_bo_free(struct drm_suballoc *sa_bo, struct dma_fence *fence); 21 39 22 40 static inline struct xe_sa_manager * 23 41 to_xe_sa_manager(struct drm_suballoc_manager *mng)
+2 -2
drivers/gpu/drm/xe/xe_sched_job_types.h
··· 18 18 * struct xe_job_ptrs - Per hw engine instance data 19 19 */ 20 20 struct xe_job_ptrs { 21 - /** @lrc_fence: Pre-allocated uinitialized lrc fence.*/ 21 + /** @lrc_fence: Pre-allocated uninitialized lrc fence.*/ 22 22 struct dma_fence *lrc_fence; 23 - /** @chain_fence: Pre-allocated ninitialized fence chain node. */ 23 + /** @chain_fence: Pre-allocated uninitialized fence chain node. */ 24 24 struct dma_fence_chain *chain_fence; 25 25 /** @batch_addr: Batch buffer address. */ 26 26 u64 batch_addr;
+1 -1
drivers/gpu/drm/xe/xe_sriov.c
··· 81 81 xe->sriov.__mode = mode; 82 82 xe_assert(xe, xe->sriov.__mode); 83 83 84 - if (has_sriov) 84 + if (IS_SRIOV(xe)) 85 85 drm_info(&xe->drm, "Running in %s mode\n", 86 86 xe_sriov_mode_to_string(xe_device_sriov_mode(xe))); 87 87 }
+238
drivers/gpu/drm/xe/xe_survivability_mode.c
··· 1 + // SPDX-License-Identifier: MIT 2 + /* 3 + * Copyright © 2025 Intel Corporation 4 + */ 5 + 6 + #include "xe_survivability_mode.h" 7 + #include "xe_survivability_mode_types.h" 8 + 9 + #include <linux/kobject.h> 10 + #include <linux/pci.h> 11 + #include <linux/sysfs.h> 12 + 13 + #include "xe_device.h" 14 + #include "xe_gt.h" 15 + #include "xe_heci_gsc.h" 16 + #include "xe_mmio.h" 17 + #include "xe_pcode_api.h" 18 + #include "xe_vsec.h" 19 + 20 + #define MAX_SCRATCH_MMIO 8 21 + 22 + /** 23 + * DOC: Xe Boot Survivability 24 + * 25 + * Boot Survivability is a software based workflow for recovering a system in a failed boot state 26 + * Here system recoverability is concerned with recovering the firmware responsible for boot. 27 + * 28 + * This is implemented by loading the driver with bare minimum (no drm card) to allow the firmware 29 + * to be flashed through mei and collect telemetry. The driver's probe flow is modified 30 + * such that it enters survivability mode when pcode initialization is incomplete and boot status 31 + * denotes a failure. The driver then populates the survivability_mode PCI sysfs indicating 32 + * survivability mode and provides additional information required for debug 33 + * 34 + * KMD exposes below admin-only readable sysfs in survivability mode 35 + * 36 + * device/survivability_mode: The presence of this file indicates that the card is in survivability 37 + * mode. Also, provides additional information on why the driver entered 38 + * survivability mode. 39 + * 40 + * Capability Information - Provides boot status 41 + * Postcode Information - Provides information about the failure 42 + * Overflow Information - Provides history of previous failures 43 + * Auxiliary Information - Certain failures may have information in 44 + * addition to postcode information 45 + */ 46 + 47 + static u32 aux_history_offset(u32 reg_value) 48 + { 49 + return REG_FIELD_GET(AUXINFO_HISTORY_OFFSET, reg_value); 50 + } 51 + 52 + static void set_survivability_info(struct xe_mmio *mmio, struct xe_survivability_info *info, 53 + int id, char *name) 54 + { 55 + strscpy(info[id].name, name, sizeof(info[id].name)); 56 + info[id].reg = PCODE_SCRATCH(id).raw; 57 + info[id].value = xe_mmio_read32(mmio, PCODE_SCRATCH(id)); 58 + } 59 + 60 + static void populate_survivability_info(struct xe_device *xe) 61 + { 62 + struct xe_survivability *survivability = &xe->survivability; 63 + struct xe_survivability_info *info = survivability->info; 64 + struct xe_mmio *mmio; 65 + u32 id = 0, reg_value; 66 + char name[NAME_MAX]; 67 + int index; 68 + 69 + mmio = xe_root_tile_mmio(xe); 70 + set_survivability_info(mmio, info, id, "Capability Info"); 71 + reg_value = info[id].value; 72 + 73 + if (reg_value & HISTORY_TRACKING) { 74 + id++; 75 + set_survivability_info(mmio, info, id, "Postcode Info"); 76 + 77 + if (reg_value & OVERFLOW_SUPPORT) { 78 + id = REG_FIELD_GET(OVERFLOW_REG_OFFSET, reg_value); 79 + set_survivability_info(mmio, info, id, "Overflow Info"); 80 + } 81 + } 82 + 83 + if (reg_value & AUXINFO_SUPPORT) { 84 + id = REG_FIELD_GET(AUXINFO_REG_OFFSET, reg_value); 85 + 86 + for (index = 0; id && reg_value; index++, reg_value = info[id].value, 87 + id = aux_history_offset(reg_value)) { 88 + snprintf(name, NAME_MAX, "Auxiliary Info %d", index); 89 + set_survivability_info(mmio, info, id, name); 90 + } 91 + } 92 + } 93 + 94 + static void log_survivability_info(struct pci_dev *pdev) 95 + { 96 + struct xe_device *xe = pdev_to_xe_device(pdev); 97 + struct xe_survivability *survivability = &xe->survivability; 98 + struct xe_survivability_info *info = survivability->info; 99 + int id; 100 + 101 + dev_info(&pdev->dev, "Survivability Boot Status : Critical Failure (%d)\n", 102 + survivability->boot_status); 103 + for (id = 0; id < MAX_SCRATCH_MMIO; id++) { 104 + if (info[id].reg) 105 + dev_info(&pdev->dev, "%s: 0x%x - 0x%x\n", info[id].name, 106 + info[id].reg, info[id].value); 107 + } 108 + } 109 + 110 + static ssize_t survivability_mode_show(struct device *dev, 111 + struct device_attribute *attr, char *buff) 112 + { 113 + struct pci_dev *pdev = to_pci_dev(dev); 114 + struct xe_device *xe = pdev_to_xe_device(pdev); 115 + struct xe_survivability *survivability = &xe->survivability; 116 + struct xe_survivability_info *info = survivability->info; 117 + int index = 0, count = 0; 118 + 119 + for (index = 0; index < MAX_SCRATCH_MMIO; index++) { 120 + if (info[index].reg) 121 + count += sysfs_emit_at(buff, count, "%s: 0x%x - 0x%x\n", info[index].name, 122 + info[index].reg, info[index].value); 123 + } 124 + 125 + return count; 126 + } 127 + 128 + static DEVICE_ATTR_ADMIN_RO(survivability_mode); 129 + 130 + static void enable_survivability_mode(struct pci_dev *pdev) 131 + { 132 + struct device *dev = &pdev->dev; 133 + struct xe_device *xe = pdev_to_xe_device(pdev); 134 + struct xe_survivability *survivability = &xe->survivability; 135 + int ret = 0; 136 + 137 + /* set survivability mode */ 138 + survivability->mode = true; 139 + dev_info(dev, "In Survivability Mode\n"); 140 + 141 + /* create survivability mode sysfs */ 142 + ret = sysfs_create_file(&dev->kobj, &dev_attr_survivability_mode.attr); 143 + if (ret) { 144 + dev_warn(dev, "Failed to create survivability sysfs files\n"); 145 + return; 146 + } 147 + 148 + xe_heci_gsc_init(xe); 149 + 150 + xe_vsec_init(xe); 151 + } 152 + 153 + /** 154 + * xe_survivability_mode_enabled - check if survivability mode is enabled 155 + * @xe: xe device instance 156 + * 157 + * Returns true if in survivability mode, false otherwise 158 + */ 159 + bool xe_survivability_mode_enabled(struct xe_device *xe) 160 + { 161 + struct xe_survivability *survivability = &xe->survivability; 162 + 163 + return survivability->mode; 164 + } 165 + 166 + /** 167 + * xe_survivability_mode_required - checks if survivability mode is required 168 + * @xe: xe device instance 169 + * 170 + * This function reads the boot status from Pcode 171 + * 172 + * Return: true if boot status indicates failure, false otherwise 173 + */ 174 + bool xe_survivability_mode_required(struct xe_device *xe) 175 + { 176 + struct xe_survivability *survivability = &xe->survivability; 177 + struct xe_mmio *mmio = xe_root_tile_mmio(xe); 178 + u32 data; 179 + 180 + if (!IS_DGFX(xe) || xe->info.platform < XE_BATTLEMAGE || IS_SRIOV_VF(xe)) 181 + return false; 182 + 183 + data = xe_mmio_read32(mmio, PCODE_SCRATCH(0)); 184 + survivability->boot_status = REG_FIELD_GET(BOOT_STATUS, data); 185 + 186 + return (survivability->boot_status == NON_CRITICAL_FAILURE || 187 + survivability->boot_status == CRITICAL_FAILURE); 188 + } 189 + 190 + /** 191 + * xe_survivability_mode_remove - remove survivability mode 192 + * @xe: xe device instance 193 + * 194 + * clean up sysfs entries of survivability mode 195 + */ 196 + void xe_survivability_mode_remove(struct xe_device *xe) 197 + { 198 + struct xe_survivability *survivability = &xe->survivability; 199 + struct pci_dev *pdev = to_pci_dev(xe->drm.dev); 200 + struct device *dev = &pdev->dev; 201 + 202 + sysfs_remove_file(&dev->kobj, &dev_attr_survivability_mode.attr); 203 + xe_heci_gsc_fini(xe); 204 + kfree(survivability->info); 205 + pci_set_drvdata(pdev, NULL); 206 + } 207 + 208 + /** 209 + * xe_survivability_mode_init - Initialize the survivability mode 210 + * @xe: xe device instance 211 + * 212 + * Initializes survivability information and enables survivability mode 213 + */ 214 + void xe_survivability_mode_init(struct xe_device *xe) 215 + { 216 + struct xe_survivability *survivability = &xe->survivability; 217 + struct xe_survivability_info *info; 218 + struct pci_dev *pdev = to_pci_dev(xe->drm.dev); 219 + 220 + survivability->size = MAX_SCRATCH_MMIO; 221 + 222 + info = kcalloc(survivability->size, sizeof(*info), GFP_KERNEL); 223 + if (!info) 224 + return; 225 + 226 + survivability->info = info; 227 + 228 + populate_survivability_info(xe); 229 + 230 + /* Only log debug information and exit if it is a critical failure */ 231 + if (survivability->boot_status == CRITICAL_FAILURE) { 232 + log_survivability_info(pdev); 233 + kfree(survivability->info); 234 + return; 235 + } 236 + 237 + enable_survivability_mode(pdev); 238 + }
+18
drivers/gpu/drm/xe/xe_survivability_mode.h
··· 1 + /* SPDX-License-Identifier: MIT */ 2 + /* 3 + * Copyright © 2025 Intel Corporation 4 + */ 5 + 6 + #ifndef _XE_SURVIVABILITY_MODE_H_ 7 + #define _XE_SURVIVABILITY_MODE_H_ 8 + 9 + #include <linux/types.h> 10 + 11 + struct xe_device; 12 + 13 + void xe_survivability_mode_init(struct xe_device *xe); 14 + void xe_survivability_mode_remove(struct xe_device *xe); 15 + bool xe_survivability_mode_enabled(struct xe_device *xe); 16 + bool xe_survivability_mode_required(struct xe_device *xe); 17 + 18 + #endif /* _XE_SURVIVABILITY_MODE_H_ */
+35
drivers/gpu/drm/xe/xe_survivability_mode_types.h
··· 1 + /* SPDX-License-Identifier: MIT */ 2 + /* 3 + * Copyright © 2025 Intel Corporation 4 + */ 5 + 6 + #ifndef _XE_SURVIVABILITY_MODE_TYPES_H_ 7 + #define _XE_SURVIVABILITY_MODE_TYPES_H_ 8 + 9 + #include <linux/limits.h> 10 + #include <linux/types.h> 11 + 12 + struct xe_survivability_info { 13 + char name[NAME_MAX]; 14 + u32 reg; 15 + u32 value; 16 + }; 17 + 18 + /** 19 + * struct xe_survivability: Contains survivability mode information 20 + */ 21 + struct xe_survivability { 22 + /** @info: struct that holds survivability info from scratch registers */ 23 + struct xe_survivability_info *info; 24 + 25 + /** @size: number of scratch registers */ 26 + u32 size; 27 + 28 + /** @boot_status: indicates critical/non critical boot failure */ 29 + u8 boot_status; 30 + 31 + /** @mode: boolean to indicate survivability mode */ 32 + bool mode; 33 + }; 34 + 35 + #endif /* _XE_SURVIVABILITY_MODE_TYPES_H_ */
+1
drivers/gpu/drm/xe/xe_sync.c
··· 210 210 211 211 return 0; 212 212 } 213 + ALLOW_ERROR_INJECTION(xe_sync_entry_parse, ERRNO); 213 214 214 215 int xe_sync_entry_add_deps(struct xe_sync_entry *sync, struct xe_sched_job *job) 215 216 {
+8 -10
drivers/gpu/drm/xe/xe_tile.c
··· 94 94 return -ENOMEM; 95 95 tile->mem.ggtt->tile = tile; 96 96 97 - tile->mem.vram_mgr = drmm_kzalloc(drm, sizeof(*tile->mem.vram_mgr), GFP_KERNEL); 98 - if (!tile->mem.vram_mgr) 99 - return -ENOMEM; 100 - 101 97 return 0; 102 98 } 103 99 ··· 135 139 int err; 136 140 137 141 if (tile->mem.vram.usable_size) { 138 - err = xe_ttm_vram_mgr_init(tile, tile->mem.vram_mgr); 142 + err = xe_ttm_vram_mgr_init(tile, &tile->mem.vram.ttm); 139 143 if (err) 140 144 return err; 141 145 xe->info.mem_region_mask |= BIT(tile->id) << 1; ··· 166 170 if (err) 167 171 return err; 168 172 173 + xe_wa_apply_tile_workarounds(tile); 174 + 175 + return xe_tile_sysfs_init(tile); 176 + } 177 + 178 + int xe_tile_init(struct xe_tile *tile) 179 + { 169 180 tile->mem.kernel_bb_pool = xe_sa_bo_manager_init(tile, SZ_1M, 16); 170 181 if (IS_ERR(tile->mem.kernel_bb_pool)) 171 182 return PTR_ERR(tile->mem.kernel_bb_pool); 172 183 173 - xe_wa_apply_tile_workarounds(tile); 174 - 175 - err = xe_tile_sysfs_init(tile); 176 - 177 184 return 0; 178 185 } 179 - 180 186 void xe_tile_migrate_wait(struct xe_tile *tile) 181 187 { 182 188 xe_migrate_wait(tile->migrate);
+1
drivers/gpu/drm/xe/xe_tile.h
··· 12 12 13 13 int xe_tile_init_early(struct xe_tile *tile, struct xe_device *xe, u8 id); 14 14 int xe_tile_init_noalloc(struct xe_tile *tile); 15 + int xe_tile_init(struct xe_tile *tile); 15 16 16 17 void xe_tile_migrate_wait(struct xe_tile *tile); 17 18
+15 -4
drivers/gpu/drm/xe/xe_trace_bo.h
··· 53 53 TP_ARGS(bo) 54 54 ); 55 55 56 + DEFINE_EVENT(xe_bo, xe_bo_create, 57 + TP_PROTO(struct xe_bo *bo), 58 + TP_ARGS(bo) 59 + ); 60 + 56 61 TRACE_EVENT(xe_bo_move, 57 62 TP_PROTO(struct xe_bo *bo, uint32_t new_placement, uint32_t old_placement, 58 63 bool move_lacks_source), ··· 92 87 TP_STRUCT__entry( 93 88 __string(dev, __dev_name_vma(vma)) 94 89 __field(struct xe_vma *, vma) 90 + __field(struct xe_vm *, vm) 95 91 __field(u32, asid) 96 92 __field(u64, start) 97 93 __field(u64, end) ··· 102 96 TP_fast_assign( 103 97 __assign_str(dev); 104 98 __entry->vma = vma; 99 + __entry->vm = xe_vma_vm(vma); 105 100 __entry->asid = xe_vma_vm(vma)->usm.asid; 106 101 __entry->start = xe_vma_start(vma); 107 102 __entry->end = xe_vma_end(vma) - 1; 108 103 __entry->ptr = xe_vma_userptr(vma); 109 104 ), 110 105 111 - TP_printk("dev=%s, vma=%p, asid=0x%05x, start=0x%012llx, end=0x%012llx, userptr=0x%012llx,", 112 - __get_str(dev), __entry->vma, __entry->asid, __entry->start, 106 + TP_printk("dev=%s, vma=%p, vm=%p, asid=0x%05x, start=0x%012llx, end=0x%012llx, userptr=0x%012llx", 107 + __get_str(dev), __entry->vma, __entry->vm, 108 + __entry->asid, __entry->start, 113 109 __entry->end, __entry->ptr) 114 110 ) 115 111 ··· 193 185 __string(dev, __dev_name_vm(vm)) 194 186 __field(struct xe_vm *, vm) 195 187 __field(u32, asid) 188 + __field(u32, flags) 196 189 ), 197 190 198 191 TP_fast_assign( 199 192 __assign_str(dev); 200 193 __entry->vm = vm; 201 194 __entry->asid = vm->usm.asid; 195 + __entry->flags = vm->flags; 202 196 ), 203 197 204 - TP_printk("dev=%s, vm=%p, asid=0x%05x", __get_str(dev), 205 - __entry->vm, __entry->asid) 198 + TP_printk("dev=%s, vm=%p, asid=0x%05x, vm flags=0x%05x", 199 + __get_str(dev), __entry->vm, __entry->asid, 200 + __entry->flags) 206 201 ); 207 202 208 203 DEFINE_EVENT(xe_vm, xe_vm_kill,
+9 -8
drivers/gpu/drm/xe/xe_ttm_stolen_mgr.c
··· 207 207 #endif 208 208 } 209 209 210 - void xe_ttm_stolen_mgr_init(struct xe_device *xe) 210 + int xe_ttm_stolen_mgr_init(struct xe_device *xe) 211 211 { 212 - struct xe_ttm_stolen_mgr *mgr = drmm_kzalloc(&xe->drm, sizeof(*mgr), GFP_KERNEL); 213 212 struct pci_dev *pdev = to_pci_dev(xe->drm.dev); 213 + struct xe_ttm_stolen_mgr *mgr; 214 214 u64 stolen_size, io_size; 215 215 int err; 216 216 217 - if (!mgr) { 218 - drm_dbg_kms(&xe->drm, "Stolen mgr init failed\n"); 219 - return; 220 - } 217 + mgr = drmm_kzalloc(&xe->drm, sizeof(*mgr), GFP_KERNEL); 218 + if (!mgr) 219 + return -ENOMEM; 221 220 222 221 if (IS_SRIOV_VF(xe)) 223 222 stolen_size = 0; ··· 229 230 230 231 if (!stolen_size) { 231 232 drm_dbg_kms(&xe->drm, "No stolen memory support\n"); 232 - return; 233 + return 0; 233 234 } 234 235 235 236 /* ··· 245 246 io_size, PAGE_SIZE); 246 247 if (err) { 247 248 drm_dbg_kms(&xe->drm, "Stolen mgr init failed: %i\n", err); 248 - return; 249 + return err; 249 250 } 250 251 251 252 drm_dbg_kms(&xe->drm, "Initialized stolen memory support with %llu bytes\n", ··· 253 254 254 255 if (io_size) 255 256 mgr->mapping = devm_ioremap_wc(&pdev->dev, mgr->io_base, io_size); 257 + 258 + return 0; 256 259 } 257 260 258 261 u64 xe_ttm_stolen_io_offset(struct xe_bo *bo, u32 offset)
+1 -1
drivers/gpu/drm/xe/xe_ttm_stolen_mgr.h
··· 12 12 struct xe_bo; 13 13 struct xe_device; 14 14 15 - void xe_ttm_stolen_mgr_init(struct xe_device *xe); 15 + int xe_ttm_stolen_mgr_init(struct xe_device *xe); 16 16 int xe_ttm_stolen_io_mem_reserve(struct xe_device *xe, struct ttm_resource *mem); 17 17 bool xe_ttm_stolen_cpu_access_needs_ggtt(struct xe_device *xe); 18 18 u64 xe_ttm_stolen_io_offset(struct xe_bo *bo, u32 offset);
+1 -2
drivers/gpu/drm/xe/xe_ttm_vram_mgr.c
··· 340 340 int xe_ttm_vram_mgr_init(struct xe_tile *tile, struct xe_ttm_vram_mgr *mgr) 341 341 { 342 342 struct xe_device *xe = tile_to_xe(tile); 343 - struct xe_mem_region *vram = &tile->mem.vram; 343 + struct xe_vram_region *vram = &tile->mem.vram; 344 344 345 - mgr->vram = vram; 346 345 return __xe_ttm_vram_mgr_init(xe, mgr, XE_PL_VRAM0 + tile->id, 347 346 vram->usable_size, vram->io_size, 348 347 PAGE_SIZE);
-4
drivers/gpu/drm/xe/xe_ttm_vram_mgr_types.h
··· 9 9 #include <drm/drm_buddy.h> 10 10 #include <drm/ttm/ttm_device.h> 11 11 12 - struct xe_mem_region; 13 - 14 12 /** 15 13 * struct xe_ttm_vram_mgr - XE TTM VRAM manager 16 14 * ··· 19 21 struct ttm_resource_manager manager; 20 22 /** @mm: DRM buddy allocator which manages the VRAM */ 21 23 struct drm_buddy mm; 22 - /** @vram: ptr to details of associated VRAM region */ 23 - struct xe_mem_region *vram; 24 24 /** @visible_size: Proped size of the CPU visible portion */ 25 25 u64 visible_size; 26 26 /** @visible_avail: CPU visible portion still unallocated */
-13
drivers/gpu/drm/xe/xe_uc.c
··· 289 289 } 290 290 291 291 /** 292 - * xe_uc_remove() - Clean up the UC structures before driver removal 293 - * @uc: the UC object 294 - * 295 - * This function should only act on objects/structures that must be cleaned 296 - * before the driver removal callback is complete and therefore can't be 297 - * deferred to a drmm action. 298 - */ 299 - void xe_uc_remove(struct xe_uc *uc) 300 - { 301 - xe_gsc_remove(&uc->gsc); 302 - } 303 - 304 - /** 305 292 * xe_uc_declare_wedged() - Declare UC wedged 306 293 * @uc: the UC object 307 294 *
-1
drivers/gpu/drm/xe/xe_uc.h
··· 20 20 int xe_uc_start(struct xe_uc *uc); 21 21 int xe_uc_suspend(struct xe_uc *uc); 22 22 int xe_uc_sanitize_reset(struct xe_uc *uc); 23 - void xe_uc_remove(struct xe_uc *uc); 24 23 void xe_uc_declare_wedged(struct xe_uc *uc); 25 24 26 25 #endif
+154 -15
drivers/gpu/drm/xe/xe_vm.c
··· 33 33 #include "xe_pm.h" 34 34 #include "xe_preempt_fence.h" 35 35 #include "xe_pt.h" 36 + #include "xe_pxp.h" 36 37 #include "xe_res_cursor.h" 37 38 #include "xe_sync.h" 38 39 #include "xe_trace_bo.h" ··· 1383 1382 struct xe_tile *tile; 1384 1383 u8 id; 1385 1384 1385 + /* 1386 + * Since the GSCCS is not user-accessible, we don't expect a GSC VM to 1387 + * ever be in faulting mode. 1388 + */ 1389 + xe_assert(xe, !((flags & XE_VM_FLAG_GSC) && (flags & XE_VM_FLAG_FAULT_MODE))); 1390 + 1386 1391 vm = kzalloc(sizeof(*vm), GFP_KERNEL); 1387 1392 if (!vm) 1388 1393 return ERR_PTR(-ENOMEM); ··· 1399 1392 1400 1393 vm->flags = flags; 1401 1394 1402 - init_rwsem(&vm->lock); 1395 + /** 1396 + * GSC VMs are kernel-owned, only used for PXP ops and can sometimes be 1397 + * manipulated under the PXP mutex. However, the PXP mutex can be taken 1398 + * under a user-VM lock when the PXP session is started at exec_queue 1399 + * creation time. Those are different VMs and therefore there is no risk 1400 + * of deadlock, but we need to tell lockdep that this is the case or it 1401 + * will print a warning. 1402 + */ 1403 + if (flags & XE_VM_FLAG_GSC) { 1404 + static struct lock_class_key gsc_vm_key; 1405 + 1406 + __init_rwsem(&vm->lock, "gsc_vm", &gsc_vm_key); 1407 + } else { 1408 + init_rwsem(&vm->lock); 1409 + } 1403 1410 mutex_init(&vm->snap_mutex); 1404 1411 1405 1412 INIT_LIST_HEAD(&vm->rebind_list); ··· 2689 2668 for (i = 0; i < vops->num_syncs; i++) 2690 2669 xe_sync_entry_signal(vops->syncs + i, fence); 2691 2670 xe_exec_queue_last_fence_set(wait_exec_queue, vm, fence); 2692 - dma_fence_put(fence); 2693 2671 } 2694 2672 2695 - static int vm_bind_ioctl_ops_execute(struct xe_vm *vm, 2696 - struct xe_vma_ops *vops) 2673 + static struct dma_fence *vm_bind_ioctl_ops_execute(struct xe_vm *vm, 2674 + struct xe_vma_ops *vops) 2697 2675 { 2698 2676 struct drm_exec exec; 2699 2677 struct dma_fence *fence; ··· 2705 2685 drm_exec_until_all_locked(&exec) { 2706 2686 err = vm_bind_ioctl_ops_lock_and_prep(&exec, vm, vops); 2707 2687 drm_exec_retry_on_contention(&exec); 2708 - if (err) 2709 - goto unlock; 2710 - 2711 - fence = ops_execute(vm, vops); 2712 - if (IS_ERR(fence)) { 2713 - err = PTR_ERR(fence); 2688 + if (err) { 2689 + fence = ERR_PTR(err); 2714 2690 goto unlock; 2715 2691 } 2692 + 2693 + fence = ops_execute(vm, vops); 2694 + if (IS_ERR(fence)) 2695 + goto unlock; 2716 2696 2717 2697 vm_bind_ioctl_ops_fini(vm, vops, fence); 2718 2698 } 2719 2699 2720 2700 unlock: 2721 2701 drm_exec_fini(&exec); 2722 - return err; 2702 + return fence; 2723 2703 } 2724 2704 ALLOW_ERROR_INJECTION(vm_bind_ioctl_ops_execute, ERRNO); 2725 2705 ··· 2727 2707 (DRM_XE_VM_BIND_FLAG_READONLY | \ 2728 2708 DRM_XE_VM_BIND_FLAG_IMMEDIATE | \ 2729 2709 DRM_XE_VM_BIND_FLAG_NULL | \ 2730 - DRM_XE_VM_BIND_FLAG_DUMPABLE) 2710 + DRM_XE_VM_BIND_FLAG_DUMPABLE | \ 2711 + DRM_XE_VM_BIND_FLAG_CHECK_PXP) 2731 2712 2732 2713 #ifdef TEST_VM_OPS_ERROR 2733 2714 #define SUPPORTED_FLAGS (SUPPORTED_FLAGS_STUB | FORCE_OP_ERROR) ··· 2891 2870 2892 2871 static int xe_vm_bind_ioctl_validate_bo(struct xe_device *xe, struct xe_bo *bo, 2893 2872 u64 addr, u64 range, u64 obj_offset, 2894 - u16 pat_index) 2873 + u16 pat_index, u32 op, u32 bind_flags) 2895 2874 { 2896 2875 u16 coh_mode; 2897 2876 ··· 2935 2914 return -EINVAL; 2936 2915 } 2937 2916 2917 + /* If a BO is protected it can only be mapped if the key is still valid */ 2918 + if ((bind_flags & DRM_XE_VM_BIND_FLAG_CHECK_PXP) && xe_bo_is_protected(bo) && 2919 + op != DRM_XE_VM_BIND_OP_UNMAP && op != DRM_XE_VM_BIND_OP_UNMAP_ALL) 2920 + if (XE_IOCTL_DBG(xe, xe_pxp_bo_key_check(xe->pxp, bo) != 0)) 2921 + return -ENOEXEC; 2922 + 2938 2923 return 0; 2939 2924 } 2940 2925 ··· 2958 2931 struct xe_sync_entry *syncs = NULL; 2959 2932 struct drm_xe_vm_bind_op *bind_ops; 2960 2933 struct xe_vma_ops vops; 2934 + struct dma_fence *fence; 2961 2935 int err; 2962 2936 int i; 2963 2937 ··· 3030 3002 u32 obj = bind_ops[i].obj; 3031 3003 u64 obj_offset = bind_ops[i].obj_offset; 3032 3004 u16 pat_index = bind_ops[i].pat_index; 3005 + u32 op = bind_ops[i].op; 3006 + u32 bind_flags = bind_ops[i].flags; 3033 3007 3034 3008 if (!obj) 3035 3009 continue; ··· 3044 3014 bos[i] = gem_to_xe_bo(gem_obj); 3045 3015 3046 3016 err = xe_vm_bind_ioctl_validate_bo(xe, bos[i], addr, range, 3047 - obj_offset, pat_index); 3017 + obj_offset, pat_index, op, 3018 + bind_flags); 3048 3019 if (err) 3049 3020 goto put_obj; 3050 3021 } ··· 3126 3095 if (err) 3127 3096 goto unwind_ops; 3128 3097 3129 - err = vm_bind_ioctl_ops_execute(vm, &vops); 3098 + fence = vm_bind_ioctl_ops_execute(vm, &vops); 3099 + if (IS_ERR(fence)) 3100 + err = PTR_ERR(fence); 3101 + else 3102 + dma_fence_put(fence); 3130 3103 3131 3104 unwind_ops: 3132 3105 if (err && err != -ENODATA) ··· 3162 3127 if (args->num_binds > 1) 3163 3128 kvfree(bind_ops); 3164 3129 return err; 3130 + } 3131 + 3132 + /** 3133 + * xe_vm_bind_kernel_bo - bind a kernel BO to a VM 3134 + * @vm: VM to bind the BO to 3135 + * @bo: BO to bind 3136 + * @q: exec queue to use for the bind (optional) 3137 + * @addr: address at which to bind the BO 3138 + * @cache_lvl: PAT cache level to use 3139 + * 3140 + * Execute a VM bind map operation on a kernel-owned BO to bind it into a 3141 + * kernel-owned VM. 3142 + * 3143 + * Returns a dma_fence to track the binding completion if the job to do so was 3144 + * successfully submitted, an error pointer otherwise. 3145 + */ 3146 + struct dma_fence *xe_vm_bind_kernel_bo(struct xe_vm *vm, struct xe_bo *bo, 3147 + struct xe_exec_queue *q, u64 addr, 3148 + enum xe_cache_level cache_lvl) 3149 + { 3150 + struct xe_vma_ops vops; 3151 + struct drm_gpuva_ops *ops = NULL; 3152 + struct dma_fence *fence; 3153 + int err; 3154 + 3155 + xe_bo_get(bo); 3156 + xe_vm_get(vm); 3157 + if (q) 3158 + xe_exec_queue_get(q); 3159 + 3160 + down_write(&vm->lock); 3161 + 3162 + xe_vma_ops_init(&vops, vm, q, NULL, 0); 3163 + 3164 + ops = vm_bind_ioctl_ops_create(vm, bo, 0, addr, bo->size, 3165 + DRM_XE_VM_BIND_OP_MAP, 0, 0, 3166 + vm->xe->pat.idx[cache_lvl]); 3167 + if (IS_ERR(ops)) { 3168 + err = PTR_ERR(ops); 3169 + goto release_vm_lock; 3170 + } 3171 + 3172 + err = vm_bind_ioctl_ops_parse(vm, ops, &vops); 3173 + if (err) 3174 + goto release_vm_lock; 3175 + 3176 + xe_assert(vm->xe, !list_empty(&vops.list)); 3177 + 3178 + err = xe_vma_ops_alloc(&vops, false); 3179 + if (err) 3180 + goto unwind_ops; 3181 + 3182 + fence = vm_bind_ioctl_ops_execute(vm, &vops); 3183 + if (IS_ERR(fence)) 3184 + err = PTR_ERR(fence); 3185 + 3186 + unwind_ops: 3187 + if (err && err != -ENODATA) 3188 + vm_bind_ioctl_ops_unwind(vm, &ops, 1); 3189 + 3190 + xe_vma_ops_fini(&vops); 3191 + drm_gpuva_ops_free(&vm->gpuvm, ops); 3192 + 3193 + release_vm_lock: 3194 + up_write(&vm->lock); 3195 + 3196 + if (q) 3197 + xe_exec_queue_put(q); 3198 + xe_vm_put(vm); 3199 + xe_bo_put(bo); 3200 + 3201 + if (err) 3202 + fence = ERR_PTR(err); 3203 + 3204 + return fence; 3165 3205 } 3166 3206 3167 3207 /** ··· 3343 3233 vma->tile_invalidated = vma->tile_mask; 3344 3234 3345 3235 return ret; 3236 + } 3237 + 3238 + int xe_vm_validate_protected(struct xe_vm *vm) 3239 + { 3240 + struct drm_gpuva *gpuva; 3241 + int err = 0; 3242 + 3243 + if (!vm) 3244 + return -ENODEV; 3245 + 3246 + mutex_lock(&vm->snap_mutex); 3247 + 3248 + drm_gpuvm_for_each_va(gpuva, &vm->gpuvm) { 3249 + struct xe_vma *vma = gpuva_to_vma(gpuva); 3250 + struct xe_bo *bo = vma->gpuva.gem.obj ? 3251 + gem_to_xe_bo(vma->gpuva.gem.obj) : NULL; 3252 + 3253 + if (!bo) 3254 + continue; 3255 + 3256 + if (xe_bo_is_protected(bo)) { 3257 + err = xe_pxp_bo_key_check(vm->xe->pxp, bo); 3258 + if (err) 3259 + break; 3260 + } 3261 + } 3262 + 3263 + mutex_unlock(&vm->snap_mutex); 3264 + return err; 3346 3265 } 3347 3266 3348 3267 struct xe_vm_snapshot {
+8
drivers/gpu/drm/xe/xe_vm.h
··· 18 18 19 19 struct ttm_buffer_object; 20 20 21 + struct dma_fence; 22 + 21 23 struct xe_exec_queue; 22 24 struct xe_file; 23 25 struct xe_sync_entry; ··· 215 213 216 214 int xe_vm_invalidate_vma(struct xe_vma *vma); 217 215 216 + int xe_vm_validate_protected(struct xe_vm *vm); 217 + 218 218 static inline void xe_vm_queue_rebind_worker(struct xe_vm *vm) 219 219 { 220 220 xe_assert(vm->xe, xe_vm_in_preempt_fence_mode(vm)); ··· 250 246 251 247 int xe_vm_validate_rebind(struct xe_vm *vm, struct drm_exec *exec, 252 248 unsigned int num_fences); 249 + 250 + struct dma_fence *xe_vm_bind_kernel_bo(struct xe_vm *vm, struct xe_bo *bo, 251 + struct xe_exec_queue *q, u64 addr, 252 + enum xe_cache_level cache_lvl); 253 253 254 254 /** 255 255 * xe_vm_resv() - Return's the vm's reservation object
+1 -1
drivers/gpu/drm/xe/xe_vm_doc.h
··· 431 431 * bind path also acquires this lock in write while the exec / compute mode 432 432 * rebind worker acquires this lock in read mode. 433 433 * 434 - * VM dma-resv lock (vm->ttm.base.resv->lock) - WW lock. Protects VM dma-resv 434 + * VM dma-resv lock (vm->gpuvm.r_obj->resv->lock) - WW lock. Protects VM dma-resv 435 435 * slots which is shared with any private BO in the VM. Expected to be acquired 436 436 * during VM binds, execs, and compute mode rebind worker. This lock is also 437 437 * held when private BOs are being evicted.
+1
drivers/gpu/drm/xe/xe_vm_types.h
··· 164 164 #define XE_VM_FLAG_BANNED BIT(5) 165 165 #define XE_VM_FLAG_TILE_ID(flags) FIELD_GET(GENMASK(7, 6), flags) 166 166 #define XE_VM_FLAG_SET_TILE_ID(tile) FIELD_PREP(GENMASK(7, 6), (tile)->id) 167 + #define XE_VM_FLAG_GSC BIT(8) 167 168 unsigned long flags; 168 169 169 170 /** @composite_fence_ctx: context composite fence */
+7 -1
drivers/gpu/drm/xe/xe_wa.c
··· 599 599 /* Xe3_LPG */ 600 600 601 601 { XE_RTP_NAME("14021402888"), 602 - XE_RTP_RULES(GRAPHICS_VERSION_RANGE(3000, 3001), FUNC(xe_rtp_match_first_render_or_compute)), 602 + XE_RTP_RULES(GRAPHICS_VERSION_RANGE(3000, 3001), 603 + FUNC(xe_rtp_match_first_render_or_compute)), 603 604 XE_RTP_ACTIONS(SET(HALF_SLICE_CHICKEN7, CLEAR_OPTIMIZATION_DISABLE)) 604 605 }, 605 606 { XE_RTP_NAME("18034896535"), ··· 613 612 FUNC(xe_rtp_match_first_render_or_compute)), 614 613 XE_RTP_ACTIONS(FIELD_SET(SAMPLER_MODE, SMP_WAIT_FETCH_MERGING_COUNTER, 615 614 SMP_FORCE_128B_OVERFETCH)) 615 + }, 616 + { XE_RTP_NAME("14023061436"), 617 + XE_RTP_RULES(GRAPHICS_VERSION_RANGE(3000, 3001), 618 + FUNC(xe_rtp_match_first_render_or_compute)), 619 + XE_RTP_ACTIONS(SET(TDL_CHICKEN, QID_WAIT_FOR_THREAD_NOT_RUN_DISABLE)) 616 620 }, 617 621 618 622 {}
+1
drivers/gpu/drm/xe/xe_wa_oob.rules
··· 28 28 16022287689 GRAPHICS_VERSION(2001) 29 29 GRAPHICS_VERSION(2004) 30 30 13011645652 GRAPHICS_VERSION(2004) 31 + GRAPHICS_VERSION(3001) 31 32 14022293748 GRAPHICS_VERSION(2001) 32 33 GRAPHICS_VERSION(2004) 33 34 22019794406 GRAPHICS_VERSION(2001)
+6 -5
include/drm/intel/pciids.h
··· 849 849 MACRO__(0xE20B, ## __VA_ARGS__), \ 850 850 MACRO__(0xE20C, ## __VA_ARGS__), \ 851 851 MACRO__(0xE20D, ## __VA_ARGS__), \ 852 - MACRO__(0xE212, ## __VA_ARGS__) 852 + MACRO__(0xE210, ## __VA_ARGS__), \ 853 + MACRO__(0xE212, ## __VA_ARGS__), \ 854 + MACRO__(0xE215, ## __VA_ARGS__), \ 855 + MACRO__(0xE216, ## __VA_ARGS__) 853 856 854 857 /* PTL */ 855 858 #define INTEL_PTL_IDS(MACRO__, ...) \ 856 859 MACRO__(0xB080, ## __VA_ARGS__), \ 857 860 MACRO__(0xB081, ## __VA_ARGS__), \ 858 861 MACRO__(0xB082, ## __VA_ARGS__), \ 862 + MACRO__(0xB083, ## __VA_ARGS__), \ 863 + MACRO__(0xB08F, ## __VA_ARGS__), \ 859 864 MACRO__(0xB090, ## __VA_ARGS__), \ 860 - MACRO__(0xB091, ## __VA_ARGS__), \ 861 - MACRO__(0xB092, ## __VA_ARGS__), \ 862 865 MACRO__(0xB0A0, ## __VA_ARGS__), \ 863 - MACRO__(0xB0A1, ## __VA_ARGS__), \ 864 - MACRO__(0xB0A2, ## __VA_ARGS__), \ 865 866 MACRO__(0xB0B0, ## __VA_ARGS__) 866 867 867 868 #endif /* __PCIIDS_H__ */
+121 -2
include/uapi/drm/xe_drm.h
··· 630 630 }; 631 631 632 632 /** 633 + * struct drm_xe_query_pxp_status - query if PXP is ready 634 + * 635 + * If PXP is enabled and no fatal error has occurred, the status will be set to 636 + * one of the following values: 637 + * 0: PXP init still in progress 638 + * 1: PXP init complete 639 + * 640 + * If PXP is not enabled or something has gone wrong, the query will be failed 641 + * with one of the following error codes: 642 + * -ENODEV: PXP not supported or disabled; 643 + * -EIO: fatal error occurred during init, so PXP will never be enabled; 644 + * -EINVAL: incorrect value provided as part of the query; 645 + * -EFAULT: error copying the memory between kernel and userspace. 646 + * 647 + * The status can only be 0 in the first few seconds after driver load. If 648 + * everything works as expected, the status will transition to init complete in 649 + * less than 1 second, while in case of errors the driver might take longer to 650 + * start returning an error code, but it should still take less than 10 seconds. 651 + * 652 + * The supported session type bitmask is based on the values in 653 + * enum drm_xe_pxp_session_type. TYPE_NONE is always supported and therefore 654 + * is not reported in the bitmask. 655 + * 656 + */ 657 + struct drm_xe_query_pxp_status { 658 + /** @status: current PXP status */ 659 + __u32 status; 660 + 661 + /** @supported_session_types: bitmask of supported PXP session types */ 662 + __u32 supported_session_types; 663 + }; 664 + 665 + /** 633 666 * struct drm_xe_device_query - Input of &DRM_IOCTL_XE_DEVICE_QUERY - main 634 667 * structure to query device information 635 668 * ··· 681 648 * attributes. 682 649 * - %DRM_XE_DEVICE_QUERY_GT_TOPOLOGY 683 650 * - %DRM_XE_DEVICE_QUERY_ENGINE_CYCLES 651 + * - %DRM_XE_DEVICE_QUERY_PXP_STATUS 684 652 * 685 653 * If size is set to 0, the driver fills it with the required size for 686 654 * the requested type of data to query. If size is equal to the required ··· 734 700 #define DRM_XE_DEVICE_QUERY_ENGINE_CYCLES 6 735 701 #define DRM_XE_DEVICE_QUERY_UC_FW_VERSION 7 736 702 #define DRM_XE_DEVICE_QUERY_OA_UNITS 8 703 + #define DRM_XE_DEVICE_QUERY_PXP_STATUS 9 737 704 /** @query: The type of data to query */ 738 705 __u32 query; 739 706 ··· 778 743 * - %DRM_XE_GEM_CPU_CACHING_WC - Allocate the pages as write-combined. This 779 744 * is uncached. Scanout surfaces should likely use this. All objects 780 745 * that can be placed in VRAM must use this. 746 + * 747 + * This ioctl supports setting the following properties via the 748 + * %DRM_XE_GEM_CREATE_EXTENSION_SET_PROPERTY extension, which uses the 749 + * generic @drm_xe_ext_set_property struct: 750 + * 751 + * - %DRM_XE_GEM_CREATE_SET_PROPERTY_PXP_TYPE - set the type of PXP session 752 + * this object will be used with. Valid values are listed in enum 753 + * drm_xe_pxp_session_type. %DRM_XE_PXP_TYPE_NONE is the default behavior, so 754 + * there is no need to explicitly set that. Objects used with session of type 755 + * %DRM_XE_PXP_TYPE_HWDRM will be marked as invalid if a PXP invalidation 756 + * event occurs after their creation. Attempting to flip an invalid object 757 + * will cause a black frame to be displayed instead. Submissions with invalid 758 + * objects mapped in the VM will be rejected. 781 759 */ 782 760 struct drm_xe_gem_create { 761 + #define DRM_XE_GEM_CREATE_EXTENSION_SET_PROPERTY 0 762 + #define DRM_XE_GEM_CREATE_SET_PROPERTY_PXP_TYPE 0 783 763 /** @extensions: Pointer to the first extension struct, if any */ 784 764 __u64 extensions; 785 765 ··· 861 811 862 812 /** 863 813 * struct drm_xe_gem_mmap_offset - Input of &DRM_IOCTL_XE_GEM_MMAP_OFFSET 814 + * 815 + * The @flags can be: 816 + * - %DRM_XE_MMAP_OFFSET_FLAG_PCI_BARRIER - For user to query special offset 817 + * for use in mmap ioctl. Writing to the returned mmap address will generate a 818 + * PCI memory barrier with low overhead (avoiding IOCTL call as well as writing 819 + * to VRAM which would also add overhead), acting like an MI_MEM_FENCE 820 + * instruction. 821 + * 822 + * Note: The mmap size can be at most 4K, due to HW limitations. As a result 823 + * this interface is only supported on CPU architectures that support 4K page 824 + * size. The mmap_offset ioctl will detect this and gracefully return an 825 + * error, where userspace is expected to have a different fallback method for 826 + * triggering a barrier. 827 + * 828 + * Roughly the usage would be as follows: 829 + * 830 + * .. code-block:: C 831 + * 832 + * struct drm_xe_gem_mmap_offset mmo = { 833 + * .handle = 0, // must be set to 0 834 + * .flags = DRM_XE_MMAP_OFFSET_FLAG_PCI_BARRIER, 835 + * }; 836 + * 837 + * err = ioctl(fd, DRM_IOCTL_XE_GEM_MMAP_OFFSET, &mmo); 838 + * map = mmap(NULL, size, PROT_WRITE, MAP_SHARED, fd, mmo.offset); 839 + * map[i] = 0xdeadbeaf; // issue barrier 864 840 */ 865 841 struct drm_xe_gem_mmap_offset { 866 842 /** @extensions: Pointer to the first extension struct, if any */ ··· 895 819 /** @handle: Handle for the object being mapped. */ 896 820 __u32 handle; 897 821 898 - /** @flags: Must be zero */ 822 + #define DRM_XE_MMAP_OFFSET_FLAG_PCI_BARRIER (1 << 0) 823 + /** @flags: Flags */ 899 824 __u32 flags; 900 825 901 826 /** @offset: The fake offset to use for subsequent mmap call */ ··· 983 906 * will only be valid for DRM_XE_VM_BIND_OP_MAP operations, the BO 984 907 * handle MBZ, and the BO offset MBZ. This flag is intended to 985 908 * implement VK sparse bindings. 909 + * - %DRM_XE_VM_BIND_FLAG_CHECK_PXP - If the object is encrypted via PXP, 910 + * reject the binding if the encryption key is no longer valid. This 911 + * flag has no effect on BOs that are not marked as using PXP. 986 912 */ 987 913 struct drm_xe_vm_bind_op { 988 914 /** @extensions: Pointer to the first extension struct, if any */ ··· 1076 996 #define DRM_XE_VM_BIND_FLAG_IMMEDIATE (1 << 1) 1077 997 #define DRM_XE_VM_BIND_FLAG_NULL (1 << 2) 1078 998 #define DRM_XE_VM_BIND_FLAG_DUMPABLE (1 << 3) 999 + #define DRM_XE_VM_BIND_FLAG_CHECK_PXP (1 << 4) 1079 1000 /** @flags: Bind flags */ 1080 1001 __u32 flags; 1081 1002 ··· 1168 1087 /** 1169 1088 * struct drm_xe_exec_queue_create - Input of &DRM_IOCTL_XE_EXEC_QUEUE_CREATE 1170 1089 * 1090 + * This ioctl supports setting the following properties via the 1091 + * %DRM_XE_EXEC_QUEUE_EXTENSION_SET_PROPERTY extension, which uses the 1092 + * generic @drm_xe_ext_set_property struct: 1093 + * 1094 + * - %DRM_XE_EXEC_QUEUE_SET_PROPERTY_PRIORITY - set the queue priority. 1095 + * CAP_SYS_NICE is required to set a value above normal. 1096 + * - %DRM_XE_EXEC_QUEUE_SET_PROPERTY_TIMESLICE - set the queue timeslice 1097 + * duration in microseconds. 1098 + * - %DRM_XE_EXEC_QUEUE_SET_PROPERTY_PXP_TYPE - set the type of PXP session 1099 + * this queue will be used with. Valid values are listed in enum 1100 + * drm_xe_pxp_session_type. %DRM_XE_PXP_TYPE_NONE is the default behavior, so 1101 + * there is no need to explicitly set that. When a queue of type 1102 + * %DRM_XE_PXP_TYPE_HWDRM is created, the PXP default HWDRM session 1103 + * (%XE_PXP_HWDRM_DEFAULT_SESSION) will be started, if isn't already running. 1104 + * Given that going into a power-saving state kills PXP HWDRM sessions, 1105 + * runtime PM will be blocked while queues of this type are alive. 1106 + * All PXP queues will be killed if a PXP invalidation event occurs. 1107 + * 1171 1108 * The example below shows how to use @drm_xe_exec_queue_create to create 1172 1109 * a simple exec_queue (no parallel submission) of class 1173 1110 * &DRM_XE_ENGINE_CLASS_RENDER. ··· 1209 1110 #define DRM_XE_EXEC_QUEUE_EXTENSION_SET_PROPERTY 0 1210 1111 #define DRM_XE_EXEC_QUEUE_SET_PROPERTY_PRIORITY 0 1211 1112 #define DRM_XE_EXEC_QUEUE_SET_PROPERTY_TIMESLICE 1 1212 - 1113 + #define DRM_XE_EXEC_QUEUE_SET_PROPERTY_PXP_TYPE 2 1213 1114 /** @extensions: Pointer to the first extension struct, if any */ 1214 1115 __u64 extensions; 1215 1116 ··· 1827 1728 /** @reserved: reserved for future use */ 1828 1729 __u64 reserved[3]; 1829 1730 }; 1731 + 1732 + /** 1733 + * enum drm_xe_pxp_session_type - Supported PXP session types. 1734 + * 1735 + * We currently only support HWDRM sessions, which are used for protected 1736 + * content that ends up being displayed, but the HW supports multiple types, so 1737 + * we might extend support in the future. 1738 + */ 1739 + enum drm_xe_pxp_session_type { 1740 + /** @DRM_XE_PXP_TYPE_NONE: PXP not used */ 1741 + DRM_XE_PXP_TYPE_NONE = 0, 1742 + /** 1743 + * @DRM_XE_PXP_TYPE_HWDRM: HWDRM sessions are used for content that ends 1744 + * up on the display. 1745 + */ 1746 + DRM_XE_PXP_TYPE_HWDRM = 1, 1747 + }; 1748 + 1749 + /* ID of the protected content session managed by Xe when PXP is active */ 1750 + #define DRM_XE_PXP_HWDRM_DEFAULT_SESSION 0xf 1830 1751 1831 1752 #if defined(__cplusplus) 1832 1753 }