diff options
Diffstat (limited to 'kernel/gsp_rm_emulation.c')
| -rw-r--r-- | kernel/gsp_rm_emulation.c | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/kernel/gsp_rm_emulation.c b/kernel/gsp_rm_emulation.c index 44de6c0..a21cf28 100644 --- a/kernel/gsp_rm_emulation.c +++ b/kernel/gsp_rm_emulation.c @@ -15,6 +15,7 @@ #include "gsp_emulation.h" #include "gsp_rm_emulation.h" #include "gsp_rm_tu104.h" +#include "gsp_sema_service.h" /* ============================================================ * Guest-memory access ("virtual DMA" on behalf of the device) @@ -1925,6 +1926,57 @@ static void gsp_rm_handle_copy_server_pdes(struct gsp_emu_context *ctx, static bool gsp_rm_alloc_interesting(u32 class_id); /* + * Channel (GPFIFO) classes across generations. Their allocation parameters + * carry the GPFIFO GPU VA/entry count and the guest-physical USERD/instance + * blocks, which is what the emulated-GPU progress service needs to run the + * work the guest submits on the channel. + */ +static bool gsp_rm_is_channel_class(u32 class_id) +{ + switch (class_id) { + case 0x906f: /* MAXWELL_CHANNEL_GPFIFO_A */ + case 0xa06f: /* KEPLER_CHANNEL_GPFIFO_A */ + case 0xb06f: /* PASCAL_CHANNEL_GPFIFO_A */ + case 0xc06f: /* VOLTA_CHANNEL_GPFIFO_A */ + case 0xc46f: /* TURING_CHANNEL_GPFIFO_A */ + return true; + default: + return false; + } +} + +/* NV_CHANNEL_ALLOC_PARAMS offsets (alloc/alloc_channel.h) */ +#define GSPRM_CHAN_GPFIFO_OFFSET 8 +#define GSPRM_CHAN_GPFIFO_ENTRIES 16 +#define GSPRM_CHAN_ENGINE_TYPE 128 +#define GSPRM_CHAN_INSTANCE_MEM 144 +#define GSPRM_CHAN_USERD_MEM 168 +#define GSPRM_CHAN_MEM_APERTURE 16 /* offset of addressSpace in the desc */ +#define GSPRM_CHAN_NOTIFIER_MEM 248 + +static void gsp_rm_register_channel(struct gsp_emu_context *ctx, u32 h_object, + const u8 *params, u32 params_size) +{ + struct sema_channel_desc desc; + + if (params_size < GSPRM_CHAN_NOTIFIER_MEM + 8) + return; + + memset(&desc, 0, sizeof(desc)); + desc.h_object = h_object; + memcpy(&desc.gpfifo_va, params + GSPRM_CHAN_GPFIFO_OFFSET, 8); + memcpy(&desc.gpfifo_entries, params + GSPRM_CHAN_GPFIFO_ENTRIES, 4); + memcpy(&desc.engine_type, params + GSPRM_CHAN_ENGINE_TYPE, 4); + memcpy(&desc.instance_pa, params + GSPRM_CHAN_INSTANCE_MEM, 8); + memcpy(&desc.userd_pa, params + GSPRM_CHAN_USERD_MEM, 8); + memcpy(&desc.userd_as, params + GSPRM_CHAN_USERD_MEM + + GSPRM_CHAN_MEM_APERTURE, 4); + memcpy(&desc.notifier_pa, params + GSPRM_CHAN_NOTIFIER_MEM, 8); + + gsp_sema_service_channel_add(&desc); +} + +/* * GSP_RM_ALLOC (103) - rpc_gsp_rm_alloc_v03_00 (32 byte header) followed by * the class-specific allocation parameters. * @@ -1981,6 +2033,11 @@ static void gsp_rm_handle_rm_alloc(struct gsp_emu_context *ctx, } } + /* Channels: hand the progress service everything it needs to run the + * work submitted on this channel (GPFIFO ring + USERD). */ + if (gsp_rm_is_channel_class(class_id)) + gsp_rm_register_channel(ctx, ho, params, params_size); + /* Echo the fixed alloc header + as many param bytes as are contiguous * in the first queue element. */ echo_len = min(params_size, @@ -2244,6 +2301,8 @@ static void gsp_rm_handle_free(struct gsp_emu_context *ctx, const u8 *elem, memcpy(&hObjOld, params + 8, 4); memset(params + 12, 0, 4); /* status = NV_OK */ + gsp_sema_service_channel_del(hObjOld); + nv_vgpu_info(ctx->vgpu, "GSPRM: FREE hObjOld=0x%x seq=%u cmd_read=%u stat_write=%u", hObjOld, sequence, rm->cmd_read, rm->stat_write); |
