host side to implement vgpu PV CTB protocol. based on the protocol, CTB read functionality is implemented to handle pv command from guest. Signed-off-by: Xiaolin Zhang <xiaolin.zhang@xxxxxxxxx> --- drivers/gpu/drm/i915/gvt/handlers.c | 118 +++++++++++++++++++++++++++++++++++- 1 file changed, 117 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/gvt/handlers.c b/drivers/gpu/drm/i915/gvt/handlers.c index 67cdae4..a9f91da 100644 --- a/drivers/gpu/drm/i915/gvt/handlers.c +++ b/drivers/gpu/drm/i915/gvt/handlers.c @@ -1218,6 +1218,118 @@ static int pvinfo_mmio_read(struct intel_vgpu *vgpu, unsigned int offset, return 0; } +static inline unsigned int ct_header_get_len(u32 header) +{ + return (header >> PV_CT_MSG_LEN_SHIFT) & PV_CT_MSG_LEN_MASK; +} + +static inline unsigned int ct_header_get_action(u32 header) +{ + return (header >> PV_CT_MSG_ACTION_SHIFT) & PV_CT_MSG_ACTION_MASK; +} + +static int fetch_pv_command_buffer(struct intel_vgpu *vgpu, + struct intel_vgpu_pv_ct_buf_desc *desc, + u32 *fence, u32 *action, u32 *data) +{ + u32 head, tail, len, size, off; + u32 cmd_head; + u32 avail; + u32 ret; + + /* fetch command descriptor */ + off = PV_DESC_OFF; + ret = intel_gvt_read_shared_page(vgpu, off, desc, sizeof(*desc)); + if (ret) + return ret; + + GEM_BUG_ON(desc->size % 4); + GEM_BUG_ON(desc->head % 4); + GEM_BUG_ON(desc->tail % 4); + GEM_BUG_ON(tail >= size); + GEM_BUG_ON(head >= size); + + /* tail == head condition indicates empty */ + head = desc->head / 4; + tail = desc->tail / 4; + size = desc->size / 4; + + if (unlikely((tail - head) == 0)) + return -ENODATA; + + /* fetch command head */ + off = desc->addr + head * 4; + ret = intel_gvt_read_shared_page(vgpu, off, &cmd_head, 4); + head = (head + 1) % size; + if (ret) + goto err; + + len = ct_header_get_len(cmd_head) - 1; + *action = ct_header_get_action(cmd_head); + + /* fetch command fence */ + off = desc->addr + head * 4; + ret = intel_gvt_read_shared_page(vgpu, off, fence, 4); + head = (head + 1) % size; + if (ret) + goto err; + + /* no command data */ + if (len == 0) + goto err; + + /* fetch command data */ + avail = size - head; + if (len <= avail) { + off = desc->addr + head * 4; + ret = intel_gvt_read_shared_page(vgpu, off, data, len * 4); + head = (head + len) % size; + } else { + /* swap case */ + off = desc->addr + head * 4; + ret = intel_gvt_read_shared_page(vgpu, off, data, avail * 4); + head = (head + avail) % size; + if (ret) + goto err; + + off = desc->addr; + ret = intel_gvt_read_shared_page(vgpu, off, &data[avail], + (len - avail) * 4); + head = (head + len - avail) % size; + } + +err: + desc->head = head * 4; + return ret; +} + +static int pv_command_buffer_read(struct intel_vgpu *vgpu, + u32 *cmd, u32 *data) +{ + struct intel_vgpu_pv_ct_buf_desc desc; + u32 fence, off = PV_DESC_OFF; + int ret; + + ret = fetch_pv_command_buffer(vgpu, &desc, &fence, cmd, data); + + /* write command descriptor back */ + desc.fence = fence; + desc.status = ret; + + ret = intel_gvt_write_shared_page(vgpu, off, &desc, sizeof(desc)); + return ret; +} + +static int handle_pv_commands(struct intel_vgpu *vgpu) +{ + u32 cmd; + u32 data[32]; + int ret; + + ret = pv_command_buffer_read(vgpu, &cmd, data); + return ret; +} + static int handle_g2v_notification(struct intel_vgpu *vgpu, int notification) { enum intel_gvt_gtt_type root_entry_type = GTT_TYPE_PPGTT_ROOT_L4_ENTRY; @@ -1226,6 +1338,7 @@ static int handle_g2v_notification(struct intel_vgpu *vgpu, int notification) unsigned long gpa, gfn; u16 ver_major = PV_MAJOR; u16 ver_minor = PV_MINOR; + int ret = 0; pdps = (u64 *)&vgpu_vreg64_t(vgpu, vgtif_reg(pdp[0])); @@ -1252,6 +1365,9 @@ static int handle_g2v_notification(struct intel_vgpu *vgpu, int notification) intel_gvt_write_shared_page(vgpu, 0, &ver_major, 2); intel_gvt_write_shared_page(vgpu, 2, &ver_minor, 2); break; + case VGT_G2V_PV_SEND_TRIGGER: + ret = handle_pv_commands(vgpu); + break; case VGT_G2V_EXECLIST_CONTEXT_CREATE: case VGT_G2V_EXECLIST_CONTEXT_DESTROY: case 1: /* Remove this in guest driver. */ @@ -1259,7 +1375,7 @@ static int handle_g2v_notification(struct intel_vgpu *vgpu, int notification) default: gvt_vgpu_err("Invalid PV notification %d\n", notification); } - return 0; + return ret; } static int send_display_ready_uevent(struct intel_vgpu *vgpu, int ready) -- 2.7.4 _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/intel-gfx