scheduler.c (d8235b5e55845de19983cec38af245cc200b81e2) | scheduler.c (6d76303553bab75ffc53993c56aad06251d8de60) |
---|---|
1/* 2 * Copyright(c) 2011-2016 Intel Corporation. All rights reserved. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the --- 778 unchanged lines hidden (view full) --- 787 788 complete_current_workload(gvt, ring_id); 789 790 if (need_force_wake) 791 intel_uncore_forcewake_put(gvt->dev_priv, 792 FORCEWAKE_ALL); 793 794 intel_runtime_pm_put(gvt->dev_priv); | 1/* 2 * Copyright(c) 2011-2016 Intel Corporation. All rights reserved. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the --- 778 unchanged lines hidden (view full) --- 787 788 complete_current_workload(gvt, ring_id); 789 790 if (need_force_wake) 791 intel_uncore_forcewake_put(gvt->dev_priv, 792 FORCEWAKE_ALL); 793 794 intel_runtime_pm_put(gvt->dev_priv); |
795 if (ret && (vgpu_is_vm_unhealthy(ret))) { 796 mutex_lock(&gvt->lock); 797 intel_vgpu_clean_execlist(vgpu); 798 mutex_unlock(&gvt->lock); | 795 if (ret && (vgpu_is_vm_unhealthy(ret))) |
799 enter_failsafe_mode(vgpu, GVT_FAILSAFE_GUEST_ERR); | 796 enter_failsafe_mode(vgpu, GVT_FAILSAFE_GUEST_ERR); |
800 } 801 | |
802 } 803 return 0; 804} 805 806void intel_gvt_wait_vgpu_idle(struct intel_vgpu *vgpu) 807{ 808 struct intel_vgpu_submission *s = &vgpu->submission; 809 struct intel_gvt *gvt = vgpu->gvt; --- 142 unchanged lines hidden (view full) --- 952 struct intel_vgpu_submission *s = &workload->vgpu->submission; 953 954 if (workload->shadow_mm) 955 intel_gvt_mm_unreference(workload->shadow_mm); 956 957 kmem_cache_free(s->workloads, workload); 958} 959 | 797 } 798 return 0; 799} 800 801void intel_gvt_wait_vgpu_idle(struct intel_vgpu *vgpu) 802{ 803 struct intel_vgpu_submission *s = &vgpu->submission; 804 struct intel_gvt *gvt = vgpu->gvt; --- 142 unchanged lines hidden (view full) --- 947 struct intel_vgpu_submission *s = &workload->vgpu->submission; 948 949 if (workload->shadow_mm) 950 intel_gvt_mm_unreference(workload->shadow_mm); 951 952 kmem_cache_free(s->workloads, workload); 953} 954 |
955static struct intel_vgpu_workload * 956alloc_workload(struct intel_vgpu *vgpu) 957{ 958 struct intel_vgpu_submission *s = &vgpu->submission; 959 struct intel_vgpu_workload *workload; 960 961 workload = kmem_cache_zalloc(s->workloads, GFP_KERNEL); 962 if (!workload) 963 return ERR_PTR(-ENOMEM); 964 965 INIT_LIST_HEAD(&workload->list); 966 INIT_LIST_HEAD(&workload->shadow_bb); 967 968 init_waitqueue_head(&workload->shadow_ctx_status_wq); 969 atomic_set(&workload->shadow_ctx_active, 0); 970 971 workload->status = -EINPROGRESS; 972 workload->shadowed = false; 973 workload->vgpu = vgpu; 974 975 return workload; 976} 977 978#define RING_CTX_OFF(x) \ 979 offsetof(struct execlist_ring_context, x) 980 981static void read_guest_pdps(struct intel_vgpu *vgpu, 982 u64 ring_context_gpa, u32 pdp[8]) 983{ 984 u64 gpa; 985 int i; 986 987 gpa = ring_context_gpa + RING_CTX_OFF(pdp3_UDW.val); 988 989 for (i = 0; i < 8; i++) 990 intel_gvt_hypervisor_read_gpa(vgpu, 991 gpa + i * 8, &pdp[7 - i], 4); 992} 993 994static int prepare_mm(struct intel_vgpu_workload *workload) 995{ 996 struct execlist_ctx_descriptor_format *desc = &workload->ctx_desc; 997 struct intel_vgpu_mm *mm; 998 struct intel_vgpu *vgpu = workload->vgpu; 999 int page_table_level; 1000 u32 pdp[8]; 1001 1002 if (desc->addressing_mode == 1) { /* legacy 32-bit */ 1003 page_table_level = 3; 1004 } else if (desc->addressing_mode == 3) { /* legacy 64 bit */ 1005 page_table_level = 4; 1006 } else { 1007 gvt_vgpu_err("Advanced Context mode(SVM) is not supported!\n"); 1008 return -EINVAL; 1009 } 1010 1011 read_guest_pdps(workload->vgpu, workload->ring_context_gpa, pdp); 1012 1013 mm = intel_vgpu_find_ppgtt_mm(workload->vgpu, page_table_level, pdp); 1014 if (mm) { 1015 intel_gvt_mm_reference(mm); 1016 } else { 1017 1018 mm = intel_vgpu_create_mm(workload->vgpu, INTEL_GVT_MM_PPGTT, 1019 pdp, page_table_level, 0); 1020 if (IS_ERR(mm)) { 1021 gvt_vgpu_err("fail to create mm object.\n"); 1022 return PTR_ERR(mm); 1023 } 1024 } 1025 workload->shadow_mm = mm; 1026 return 0; 1027} 1028 1029#define same_context(a, b) (((a)->context_id == (b)->context_id) && \ 1030 ((a)->lrca == (b)->lrca)) 1031 1032#define get_last_workload(q) \ 1033 (list_empty(q) ? NULL : container_of(q->prev, \ 1034 struct intel_vgpu_workload, list)) |
|
960/** 961 * intel_vgpu_create_workload - create a vGPU workload 962 * @vgpu: a vGPU | 1035/** 1036 * intel_vgpu_create_workload - create a vGPU workload 1037 * @vgpu: a vGPU |
1038 * @desc: a guest context descriptor |
|
963 * 964 * This function is called when creating a vGPU workload. 965 * 966 * Returns: 967 * struct intel_vgpu_workload * on success, negative error code in 968 * pointer if failed. 969 * 970 */ 971struct intel_vgpu_workload * | 1039 * 1040 * This function is called when creating a vGPU workload. 1041 * 1042 * Returns: 1043 * struct intel_vgpu_workload * on success, negative error code in 1044 * pointer if failed. 1045 * 1046 */ 1047struct intel_vgpu_workload * |
972intel_vgpu_create_workload(struct intel_vgpu *vgpu) | 1048intel_vgpu_create_workload(struct intel_vgpu *vgpu, int ring_id, 1049 struct execlist_ctx_descriptor_format *desc) |
973{ 974 struct intel_vgpu_submission *s = &vgpu->submission; | 1050{ 1051 struct intel_vgpu_submission *s = &vgpu->submission; |
975 struct intel_vgpu_workload *workload; | 1052 struct list_head *q = workload_q_head(vgpu, ring_id); 1053 struct intel_vgpu_workload *last_workload = get_last_workload(q); 1054 struct intel_vgpu_workload *workload = NULL; 1055 struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; 1056 u64 ring_context_gpa; 1057 u32 head, tail, start, ctl, ctx_ctl, per_ctx, indirect_ctx; 1058 int ret; |
976 | 1059 |
977 workload = kmem_cache_zalloc(s->workloads, GFP_KERNEL); 978 if (!workload) 979 return ERR_PTR(-ENOMEM); | 1060 ring_context_gpa = intel_vgpu_gma_to_gpa(vgpu->gtt.ggtt_mm, 1061 (u32)((desc->lrca + 1) << GTT_PAGE_SHIFT)); 1062 if (ring_context_gpa == INTEL_GVT_INVALID_ADDR) { 1063 gvt_vgpu_err("invalid guest context LRCA: %x\n", desc->lrca); 1064 return ERR_PTR(-EINVAL); 1065 } |
980 | 1066 |
981 INIT_LIST_HEAD(&workload->list); 982 INIT_LIST_HEAD(&workload->shadow_bb); | 1067 intel_gvt_hypervisor_read_gpa(vgpu, ring_context_gpa + 1068 RING_CTX_OFF(ring_header.val), &head, 4); |
983 | 1069 |
984 init_waitqueue_head(&workload->shadow_ctx_status_wq); 985 atomic_set(&workload->shadow_ctx_active, 0); | 1070 intel_gvt_hypervisor_read_gpa(vgpu, ring_context_gpa + 1071 RING_CTX_OFF(ring_tail.val), &tail, 4); |
986 | 1072 |
987 workload->status = -EINPROGRESS; 988 workload->shadowed = false; 989 workload->vgpu = vgpu; | 1073 head &= RB_HEAD_OFF_MASK; 1074 tail &= RB_TAIL_OFF_MASK; |
990 | 1075 |
1076 if (last_workload && same_context(&last_workload->ctx_desc, desc)) { 1077 gvt_dbg_el("ring id %d cur workload == last\n", ring_id); 1078 gvt_dbg_el("ctx head %x real head %lx\n", head, 1079 last_workload->rb_tail); 1080 /* 1081 * cannot use guest context head pointer here, 1082 * as it might not be updated at this time 1083 */ 1084 head = last_workload->rb_tail; 1085 } 1086 1087 gvt_dbg_el("ring id %d begin a new workload\n", ring_id); 1088 1089 /* record some ring buffer register values for scan and shadow */ 1090 intel_gvt_hypervisor_read_gpa(vgpu, ring_context_gpa + 1091 RING_CTX_OFF(rb_start.val), &start, 4); 1092 intel_gvt_hypervisor_read_gpa(vgpu, ring_context_gpa + 1093 RING_CTX_OFF(rb_ctrl.val), &ctl, 4); 1094 intel_gvt_hypervisor_read_gpa(vgpu, ring_context_gpa + 1095 RING_CTX_OFF(ctx_ctrl.val), &ctx_ctl, 4); 1096 1097 workload = alloc_workload(vgpu); 1098 if (IS_ERR(workload)) 1099 return workload; 1100 1101 workload->ring_id = ring_id; 1102 workload->ctx_desc = *desc; 1103 workload->ring_context_gpa = ring_context_gpa; 1104 workload->rb_head = head; 1105 workload->rb_tail = tail; 1106 workload->rb_start = start; 1107 workload->rb_ctl = ctl; 1108 1109 if (ring_id == RCS) { 1110 intel_gvt_hypervisor_read_gpa(vgpu, ring_context_gpa + 1111 RING_CTX_OFF(bb_per_ctx_ptr.val), &per_ctx, 4); 1112 intel_gvt_hypervisor_read_gpa(vgpu, ring_context_gpa + 1113 RING_CTX_OFF(rcs_indirect_ctx.val), &indirect_ctx, 4); 1114 1115 workload->wa_ctx.indirect_ctx.guest_gma = 1116 indirect_ctx & INDIRECT_CTX_ADDR_MASK; 1117 workload->wa_ctx.indirect_ctx.size = 1118 (indirect_ctx & INDIRECT_CTX_SIZE_MASK) * 1119 CACHELINE_BYTES; 1120 workload->wa_ctx.per_ctx.guest_gma = 1121 per_ctx & PER_CTX_ADDR_MASK; 1122 workload->wa_ctx.per_ctx.valid = per_ctx & 1; 1123 } 1124 1125 gvt_dbg_el("workload %p ring id %d head %x tail %x start %x ctl %x\n", 1126 workload, ring_id, head, tail, start, ctl); 1127 1128 ret = prepare_mm(workload); 1129 if (ret) { 1130 kmem_cache_free(s->workloads, workload); 1131 return ERR_PTR(ret); 1132 } 1133 1134 /* Only scan and shadow the first workload in the queue 1135 * as there is only one pre-allocated buf-obj for shadow. 1136 */ 1137 if (list_empty(workload_q_head(vgpu, ring_id))) { 1138 intel_runtime_pm_get(dev_priv); 1139 mutex_lock(&dev_priv->drm.struct_mutex); 1140 ret = intel_gvt_scan_and_shadow_workload(workload); 1141 mutex_unlock(&dev_priv->drm.struct_mutex); 1142 intel_runtime_pm_put(dev_priv); 1143 } 1144 1145 if (ret && (vgpu_is_vm_unhealthy(ret))) { 1146 enter_failsafe_mode(vgpu, GVT_FAILSAFE_GUEST_ERR); 1147 intel_vgpu_destroy_workload(workload); 1148 return ERR_PTR(ret); 1149 } 1150 |
|
991 return workload; 992} | 1151 return workload; 1152} |