Skip to content

Commit f289f78

Browse files
committed
drm/xe: Add xe_guc_pagefault layer
Add xe_guc_pagefault layer (producer) which parses G2H fault messages messages into struct xe_pagefault, forwards them to the page fault layer (consumer) for servicing, and provides a vfunc to acknowledge faults to the GuC upon completion. Replace the old (and incorrect) GT page fault layer with this new layer throughout the driver. As part of this change, the ACC handling code has been removed, as it is dead code that is currently unused. v2: - Include engine instance (Stuart) Signed-off-by: Matthew Brost <matthew.brost@intel.com> Reviewed-by: Lucas De Marchi <lucas.demarchi@intel.com> Tested-by: Francois Dugast <francois.dugast@intel.com> Link: https://patch.msgid.link/20251031165416.2871503-7-matthew.brost@intel.com
1 parent fb544b8 commit f289f78

7 files changed

Lines changed: 113 additions & 15 deletions

File tree

drivers/gpu/drm/xe/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,6 @@ xe-y += xe_bb.o \
5858
xe_gt_freq.o \
5959
xe_gt_idle.o \
6060
xe_gt_mcr.o \
61-
xe_gt_pagefault.o \
6261
xe_gt_sysfs.o \
6362
xe_gt_throttle.o \
6463
xe_gt_topology.o \
@@ -73,6 +72,7 @@ xe-y += xe_bb.o \
7372
xe_guc_id_mgr.o \
7473
xe_guc_klv_helpers.o \
7574
xe_guc_log.o \
75+
xe_guc_pagefault.o \
7676
xe_guc_pc.o \
7777
xe_guc_submit.o \
7878
xe_guc_tlb_inval.o \

drivers/gpu/drm/xe/xe_gt.c

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@
3232
#include "xe_gt_freq.h"
3333
#include "xe_gt_idle.h"
3434
#include "xe_gt_mcr.h"
35-
#include "xe_gt_pagefault.h"
3635
#include "xe_gt_printk.h"
3736
#include "xe_gt_sriov_pf.h"
3837
#include "xe_gt_sriov_vf.h"
@@ -645,10 +644,6 @@ int xe_gt_init(struct xe_gt *gt)
645644
if (err)
646645
return err;
647646

648-
err = xe_gt_pagefault_init(gt);
649-
if (err)
650-
return err;
651-
652647
err = xe_gt_idle_init(&gt->gtidle);
653648
if (err)
654649
return err;
@@ -855,7 +850,6 @@ static void gt_reset_worker(struct work_struct *w)
855850
xe_uc_gucrc_disable(&gt->uc);
856851
xe_uc_stop_prepare(&gt->uc);
857852
xe_pagefault_reset(gt_to_xe(gt), gt);
858-
xe_gt_pagefault_reset(gt);
859853

860854
xe_uc_stop(&gt->uc);
861855

drivers/gpu/drm/xe/xe_guc_ct.c

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,12 @@
2121
#include "xe_devcoredump.h"
2222
#include "xe_device.h"
2323
#include "xe_gt.h"
24-
#include "xe_gt_pagefault.h"
2524
#include "xe_gt_printk.h"
2625
#include "xe_gt_sriov_pf_control.h"
2726
#include "xe_gt_sriov_pf_monitor.h"
2827
#include "xe_guc.h"
2928
#include "xe_guc_log.h"
29+
#include "xe_guc_pagefault.h"
3030
#include "xe_guc_relay.h"
3131
#include "xe_guc_submit.h"
3232
#include "xe_guc_tlb_inval.h"
@@ -1548,10 +1548,6 @@ static int process_g2h_msg(struct xe_guc_ct *ct, u32 *msg, u32 len)
15481548
case XE_GUC_ACTION_TLB_INVALIDATION_DONE:
15491549
ret = xe_guc_tlb_inval_done_handler(guc, payload, adj_len);
15501550
break;
1551-
case XE_GUC_ACTION_ACCESS_COUNTER_NOTIFY:
1552-
ret = xe_guc_access_counter_notify_handler(guc, payload,
1553-
adj_len);
1554-
break;
15551551
case XE_GUC_ACTION_GUC2PF_RELAY_FROM_VF:
15561552
ret = xe_guc_relay_process_guc2pf(&guc->relay, hxg, hxg_len);
15571553
break;
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
// SPDX-License-Identifier: MIT
2+
/*
3+
* Copyright © 2025 Intel Corporation
4+
*/
5+
6+
#include "abi/guc_actions_abi.h"
7+
#include "xe_guc.h"
8+
#include "xe_guc_ct.h"
9+
#include "xe_guc_pagefault.h"
10+
#include "xe_pagefault.h"
11+
12+
static void guc_ack_fault(struct xe_pagefault *pf, int err)
13+
{
14+
u32 vfid = FIELD_GET(PFD_VFID, pf->producer.msg[2]);
15+
u32 engine_instance = FIELD_GET(PFD_ENG_INSTANCE, pf->producer.msg[0]);
16+
u32 engine_class = FIELD_GET(PFD_ENG_CLASS, pf->producer.msg[0]);
17+
u32 pdata = FIELD_GET(PFD_PDATA_LO, pf->producer.msg[0]) |
18+
(FIELD_GET(PFD_PDATA_HI, pf->producer.msg[1]) <<
19+
PFD_PDATA_HI_SHIFT);
20+
u32 action[] = {
21+
XE_GUC_ACTION_PAGE_FAULT_RES_DESC,
22+
23+
FIELD_PREP(PFR_VALID, 1) |
24+
FIELD_PREP(PFR_SUCCESS, !!err) |
25+
FIELD_PREP(PFR_REPLY, PFR_ACCESS) |
26+
FIELD_PREP(PFR_DESC_TYPE, FAULT_RESPONSE_DESC) |
27+
FIELD_PREP(PFR_ASID, pf->consumer.asid),
28+
29+
FIELD_PREP(PFR_VFID, vfid) |
30+
FIELD_PREP(PFR_ENG_INSTANCE, engine_instance) |
31+
FIELD_PREP(PFR_ENG_CLASS, engine_class) |
32+
FIELD_PREP(PFR_PDATA, pdata),
33+
};
34+
struct xe_guc *guc = pf->producer.private;
35+
36+
xe_guc_ct_send(&guc->ct, action, ARRAY_SIZE(action), 0, 0);
37+
}
38+
39+
static const struct xe_pagefault_ops guc_pagefault_ops = {
40+
.ack_fault = guc_ack_fault,
41+
};
42+
43+
/**
44+
* xe_guc_pagefault_handler() - G2H page fault handler
45+
* @guc: GuC object
46+
* @msg: G2H message
47+
* @len: Length of G2H message
48+
*
49+
* Parse GuC to host (G2H) message into a struct xe_pagefault and forward onto
50+
* the Xe page fault layer.
51+
*
52+
* Return: 0 on success, errno on failure
53+
*/
54+
int xe_guc_pagefault_handler(struct xe_guc *guc, u32 *msg, u32 len)
55+
{
56+
struct xe_pagefault pf;
57+
int i;
58+
59+
#define GUC_PF_MSG_LEN_DW \
60+
(sizeof(struct xe_guc_pagefault_desc) / sizeof(u32))
61+
62+
BUILD_BUG_ON(GUC_PF_MSG_LEN_DW > XE_PAGEFAULT_PRODUCER_MSG_LEN_DW);
63+
64+
if (len != GUC_PF_MSG_LEN_DW)
65+
return -EPROTO;
66+
67+
pf.gt = guc_to_gt(guc);
68+
69+
/*
70+
* XXX: These values happen to match the enum in xe_pagefault_types.h.
71+
* If that changes, we’ll need to remap them here.
72+
*/
73+
pf.consumer.page_addr = ((u64)FIELD_GET(PFD_VIRTUAL_ADDR_HI, msg[3])
74+
<< PFD_VIRTUAL_ADDR_HI_SHIFT) |
75+
(FIELD_GET(PFD_VIRTUAL_ADDR_LO, msg[2]) <<
76+
PFD_VIRTUAL_ADDR_LO_SHIFT);
77+
pf.consumer.asid = FIELD_GET(PFD_ASID, msg[1]);
78+
pf.consumer.access_type = FIELD_GET(PFD_ACCESS_TYPE, msg[2]);
79+
pf.consumer.fault_type = FIELD_GET(PFD_FAULT_TYPE, msg[2]);
80+
if (FIELD_GET(XE2_PFD_TRVA_FAULT, msg[0]))
81+
pf.consumer.fault_level = XE_PAGEFAULT_LEVEL_NACK;
82+
else
83+
pf.consumer.fault_level = FIELD_GET(PFD_FAULT_LEVEL, msg[0]);
84+
pf.consumer.engine_class = FIELD_GET(PFD_ENG_CLASS, msg[0]);
85+
pf.consumer.engine_instance = FIELD_GET(PFD_ENG_INSTANCE, msg[0]);
86+
87+
pf.producer.private = guc;
88+
pf.producer.ops = &guc_pagefault_ops;
89+
for (i = 0; i < GUC_PF_MSG_LEN_DW; ++i)
90+
pf.producer.msg[i] = msg[i];
91+
92+
#undef GUC_PF_MSG_LEN_DW
93+
94+
return xe_pagefault_handler(guc_to_xe(guc), &pf);
95+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/* SPDX-License-Identifier: MIT */
2+
/*
3+
* Copyright © 2025 Intel Corporation
4+
*/
5+
6+
#ifndef _XE_GUC_PAGEFAULT_H_
7+
#define _XE_GUC_PAGEFAULT_H_
8+
9+
#include <linux/types.h>
10+
11+
struct xe_guc;
12+
13+
int xe_guc_pagefault_handler(struct xe_guc *guc, u32 *msg, u32 len);
14+
15+
#endif

drivers/gpu/drm/xe/xe_svm.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,8 +104,7 @@ xe_svm_garbage_collector_add_range(struct xe_vm *vm, struct xe_svm_range *range,
104104
&vm->svm.garbage_collector.range_list);
105105
spin_unlock(&vm->svm.garbage_collector.lock);
106106

107-
queue_work(xe_device_get_root_tile(xe)->primary_gt->usm.pf_wq,
108-
&vm->svm.garbage_collector.work);
107+
queue_work(xe->usm.pf_wq, &vm->svm.garbage_collector.work);
109108
}
110109

111110
static void xe_svm_tlb_inval_count_stats_incr(struct xe_gt *gt)

drivers/gpu/drm/xe/xe_vm.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
#include "xe_device.h"
2828
#include "xe_drm_client.h"
2929
#include "xe_exec_queue.h"
30-
#include "xe_gt_pagefault.h"
3130
#include "xe_migrate.h"
3231
#include "xe_pat.h"
3332
#include "xe_pm.h"

0 commit comments

Comments
 (0)