Files
cubelinux-kernel/drivers/gpu/drm/xe/xe_guc_pagefault.c
T
Greg Kroah-Hartman 598cf27219 Linux 6.19.3
Link: https://lore.kernel.org/r/20260217200002.683975158@linuxfoundation.org
Tested-by: Florian Fainelli <florian.fainelli@broadcom.com>
Tested-by: Takeshi Ogasawara <takeshi.ogasawara@futuring-girl.com>
Tested-by: Peter Schneider <pschneider1968@googlemail.com>
Tested-by: Jon Hunter <jonathanh@nvidia.com>
Tested-by: Salvatore Bonaccorso <carnil@debian.org>
Tested-by: Brett A C Sheffield <bacs@librecast.net>
Tested-by: Mark Brown <broonie@kernel.org>
Tested-by: Luna Jernberg <droidbittin@gmail.com>
Tested-by: Ronald Warsow <rwarsow@gmx.de>
Tested-by: Justin M. Forbes <jforbes@fedoraproject.org>
Tested-by: Ron Economos <re@w6rz.net>
Tested-by: Miguel Ojeda <ojeda@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2026-02-19 16:33:27 +01:00

96 lines
2.8 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// SPDX-License-Identifier: MIT
/*
* Copyright © 2025 Intel Corporation
*/
#include "abi/guc_actions_abi.h"
#include "xe_guc.h"
#include "xe_guc_ct.h"
#include "xe_guc_pagefault.h"
#include "xe_pagefault.h"
static void guc_ack_fault(struct xe_pagefault *pf, int err)
{
u32 vfid = FIELD_GET(PFD_VFID, pf->producer.msg[2]);
u32 engine_instance = FIELD_GET(PFD_ENG_INSTANCE, pf->producer.msg[0]);
u32 engine_class = FIELD_GET(PFD_ENG_CLASS, pf->producer.msg[0]);
u32 pdata = FIELD_GET(PFD_PDATA_LO, pf->producer.msg[0]) |
(FIELD_GET(PFD_PDATA_HI, pf->producer.msg[1]) <<
PFD_PDATA_HI_SHIFT);
u32 action[] = {
XE_GUC_ACTION_PAGE_FAULT_RES_DESC,
FIELD_PREP(PFR_VALID, 1) |
FIELD_PREP(PFR_SUCCESS, !!err) |
FIELD_PREP(PFR_REPLY, PFR_ACCESS) |
FIELD_PREP(PFR_DESC_TYPE, FAULT_RESPONSE_DESC) |
FIELD_PREP(PFR_ASID, pf->consumer.asid),
FIELD_PREP(PFR_VFID, vfid) |
FIELD_PREP(PFR_ENG_INSTANCE, engine_instance) |
FIELD_PREP(PFR_ENG_CLASS, engine_class) |
FIELD_PREP(PFR_PDATA, pdata),
};
struct xe_guc *guc = pf->producer.private;
xe_guc_ct_send(&guc->ct, action, ARRAY_SIZE(action), 0, 0);
}
static const struct xe_pagefault_ops guc_pagefault_ops = {
.ack_fault = guc_ack_fault,
};
/**
* xe_guc_pagefault_handler() - G2H page fault handler
* @guc: GuC object
* @msg: G2H message
* @len: Length of G2H message
*
* Parse GuC to host (G2H) message into a struct xe_pagefault and forward onto
* the Xe page fault layer.
*
* Return: 0 on success, errno on failure
*/
int xe_guc_pagefault_handler(struct xe_guc *guc, u32 *msg, u32 len)
{
struct xe_pagefault pf;
int i;
#define GUC_PF_MSG_LEN_DW \
(sizeof(struct xe_guc_pagefault_desc) / sizeof(u32))
BUILD_BUG_ON(GUC_PF_MSG_LEN_DW > XE_PAGEFAULT_PRODUCER_MSG_LEN_DW);
if (len != GUC_PF_MSG_LEN_DW)
return -EPROTO;
pf.gt = guc_to_gt(guc);
/*
* XXX: These values happen to match the enum in xe_pagefault_types.h.
* If that changes, we’ll need to remap them here.
*/
pf.consumer.page_addr = ((u64)FIELD_GET(PFD_VIRTUAL_ADDR_HI, msg[3])
<< PFD_VIRTUAL_ADDR_HI_SHIFT) |
(FIELD_GET(PFD_VIRTUAL_ADDR_LO, msg[2]) <<
PFD_VIRTUAL_ADDR_LO_SHIFT);
pf.consumer.asid = FIELD_GET(PFD_ASID, msg[1]);
pf.consumer.access_type = FIELD_GET(PFD_ACCESS_TYPE, msg[2]);
pf.consumer.fault_type = FIELD_GET(PFD_FAULT_TYPE, msg[2]);
if (FIELD_GET(XE2_PFD_TRVA_FAULT, msg[0]))
pf.consumer.fault_level = XE_PAGEFAULT_LEVEL_NACK;
else
pf.consumer.fault_level = FIELD_GET(PFD_FAULT_LEVEL, msg[0]);
pf.consumer.engine_class = FIELD_GET(PFD_ENG_CLASS, msg[0]);
pf.consumer.engine_instance = FIELD_GET(PFD_ENG_INSTANCE, msg[0]);
pf.producer.private = guc;
pf.producer.ops = &guc_pagefault_ops;
for (i = 0; i < GUC_PF_MSG_LEN_DW; ++i)
pf.producer.msg[i] = msg[i];
#undef GUC_PF_MSG_LEN_DW
return xe_pagefault_handler(guc_to_xe(guc), &pf);
}