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.

at master 103 lines 3.2 kB view raw
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#include "xe_pagefault_types.h" 12 13static void guc_ack_fault(struct xe_pagefault *pf, int err) 14{ 15 u32 vfid = FIELD_GET(PFD_VFID, pf->producer.msg[2]); 16 u32 prefetch = FIELD_GET(PFD_PREFETCH, pf->producer.msg[2]); 17 u32 engine_instance = FIELD_GET(PFD_ENG_INSTANCE, pf->producer.msg[0]); 18 u32 engine_class = FIELD_GET(PFD_ENG_CLASS, pf->producer.msg[0]); 19 u32 pdata = FIELD_GET(PFD_PDATA_LO, pf->producer.msg[0]) | 20 (FIELD_GET(PFD_PDATA_HI, pf->producer.msg[1]) << 21 PFD_PDATA_HI_SHIFT); 22 u32 asid = FIELD_GET(PFD_ASID, pf->producer.msg[1]); 23 u32 action[] = { 24 XE_GUC_ACTION_PAGE_FAULT_RES_DESC, 25 26 FIELD_PREP(PFR_VALID, 1) | 27 FIELD_PREP(PFR_SUCCESS, !!err) | 28 FIELD_PREP(PFR_REPLY, PFR_ACCESS) | 29 FIELD_PREP(PFR_DESC_TYPE, FAULT_RESPONSE_DESC) | 30 FIELD_PREP(PFR_ASID, asid), 31 32 FIELD_PREP(PFR_VFID, vfid) | 33 FIELD_PREP(PFR_PREFETCH, err ? prefetch : 0) | 34 FIELD_PREP(PFR_ENG_INSTANCE, engine_instance) | 35 FIELD_PREP(PFR_ENG_CLASS, engine_class) | 36 FIELD_PREP(PFR_PDATA, pdata), 37 }; 38 struct xe_guc *guc = pf->producer.private; 39 40 xe_guc_ct_send(&guc->ct, action, ARRAY_SIZE(action), 0, 0); 41} 42 43static const struct xe_pagefault_ops guc_pagefault_ops = { 44 .ack_fault = guc_ack_fault, 45}; 46 47/** 48 * xe_guc_pagefault_handler() - G2H page fault handler 49 * @guc: GuC object 50 * @msg: G2H message 51 * @len: Length of G2H message 52 * 53 * Parse GuC to host (G2H) message into a struct xe_pagefault and forward onto 54 * the Xe page fault layer. 55 * 56 * Return: 0 on success, errno on failure 57 */ 58int xe_guc_pagefault_handler(struct xe_guc *guc, u32 *msg, u32 len) 59{ 60 struct xe_pagefault pf; 61 int i; 62 63#define GUC_PF_MSG_LEN_DW \ 64 (sizeof(struct xe_guc_pagefault_desc) / sizeof(u32)) 65 66 BUILD_BUG_ON(GUC_PF_MSG_LEN_DW > XE_PAGEFAULT_PRODUCER_MSG_LEN_DW); 67 68 if (len != GUC_PF_MSG_LEN_DW) 69 return -EPROTO; 70 71 pf.gt = guc_to_gt(guc); 72 73 /* 74 * XXX: These values happen to match the enum in xe_pagefault_types.h. 75 * If that changes, we’ll need to remap them here. 76 */ 77 pf.consumer.page_addr = ((u64)FIELD_GET(PFD_VIRTUAL_ADDR_HI, msg[3]) 78 << PFD_VIRTUAL_ADDR_HI_SHIFT) | 79 (FIELD_GET(PFD_VIRTUAL_ADDR_LO, msg[2]) << 80 PFD_VIRTUAL_ADDR_LO_SHIFT); 81 pf.consumer.asid = FIELD_GET(PFD_ASID, msg[1]); 82 pf.consumer.access_type = FIELD_GET(PFD_ACCESS_TYPE, msg[2]) | 83 (FIELD_GET(PFD_PREFETCH, msg[2]) ? XE_PAGEFAULT_ACCESS_PREFETCH : 0); 84 if (FIELD_GET(XE2_PFD_TRVA_FAULT, msg[0])) 85 pf.consumer.fault_type_level = XE_PAGEFAULT_TYPE_LEVEL_NACK; 86 else 87 pf.consumer.fault_type_level = 88 FIELD_PREP(XE_PAGEFAULT_LEVEL_MASK, 89 FIELD_GET(PFD_FAULT_LEVEL, msg[0])) | 90 FIELD_PREP(XE_PAGEFAULT_TYPE_MASK, 91 FIELD_GET(PFD_FAULT_TYPE, msg[2])); 92 pf.consumer.engine_class = FIELD_GET(PFD_ENG_CLASS, msg[0]); 93 pf.consumer.engine_instance = FIELD_GET(PFD_ENG_INSTANCE, msg[0]); 94 95 pf.producer.private = guc; 96 pf.producer.ops = &guc_pagefault_ops; 97 for (i = 0; i < GUC_PF_MSG_LEN_DW; ++i) 98 pf.producer.msg[i] = msg[i]; 99 100#undef GUC_PF_MSG_LEN_DW 101 102 return xe_pagefault_handler(guc_to_xe(guc), &pf); 103}