diff options
Diffstat (limited to 'kernel/gsp_sema_service.c')
| -rw-r--r-- | kernel/gsp_sema_service.c | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c index c30cc22..234932c 100644 --- a/kernel/gsp_sema_service.c +++ b/kernel/gsp_sema_service.c @@ -3586,6 +3586,107 @@ static int svc_promo_lookup(u64 va, u64 *addr, int *ap) } /* + * SESSION 153-CONTINUED-95: per-(engine,bufferId) record of the guest + * driver's GR context-buffer promote statements, for the launch-time + * CTX-BIND receipt. The response-free sema promote table above is keyed by + * VA and answers translations; this one keeps the latest PROMOTE_CTX entry + * for the context buffers the mission asks about - MAIN (bufferId 0) and + * PATCH (bufferId 2) - including the bInitialize flag, so a launch can log + * whether the client's promoted GR context buffer is installed on the + * engine's replay channel (it is not: the channel's context is the + * server/own buffer the ladder built; this record proves which buffer the + * client believes is its context, with pa/va/size/init as sent). + */ +#define SVC_CTXP_MAX 8 +struct svc_ctxp_rec { + u32 engine; + u32 buffer_id; + u64 pa; + u64 va; + u64 size; + u32 phys_attr; + u32 b_init; + unsigned long seq; + bool valid; +}; +static struct svc_ctxp_rec svc_ctxp[SVC_CTXP_MAX]; +static unsigned long svc_ctxp_seq; +static DEFINE_SPINLOCK(svc_ctxp_lock); + +void gsp_sema_service_ctx_promote_note(u32 engine, u32 buffer_id, u64 pa, + u64 va, u64 size, u32 phys_attr, + u32 b_init) +{ + struct svc_ctxp_rec *rec = NULL, *free_rec = NULL, *oldest = NULL; + unsigned long flags; + int i; + + spin_lock_irqsave(&svc_ctxp_lock, flags); + for (i = 0; i < SVC_CTXP_MAX; i++) { + if (svc_ctxp[i].valid && + svc_ctxp[i].engine == engine && + svc_ctxp[i].buffer_id == buffer_id) { + rec = &svc_ctxp[i]; + break; + } + if (!svc_ctxp[i].valid && !free_rec) + free_rec = &svc_ctxp[i]; + if (svc_ctxp[i].valid && + (!oldest || svc_ctxp[i].seq < oldest->seq)) + oldest = &svc_ctxp[i]; + } + if (!rec) + rec = free_rec ? free_rec : oldest; + if (rec) { + rec->engine = engine; + rec->buffer_id = buffer_id; + rec->pa = pa; + rec->va = va; + rec->size = size; + rec->phys_attr = phys_attr; + rec->b_init = b_init; + rec->seq = ++svc_ctxp_seq; + rec->valid = true; + } + spin_unlock_irqrestore(&svc_ctxp_lock, flags); +} + +int gsp_sema_service_ctx_promote_get(u32 engine, u32 buffer_id, u64 *pa, + u64 *va, u64 *size, u32 *phys_attr, + u32 *b_init) +{ + unsigned long flags; + u64 best_seq = 0; + int rc = -ENOENT; + int i; + + spin_lock_irqsave(&svc_ctxp_lock, flags); + for (i = 0; i < SVC_CTXP_MAX; i++) { + const struct svc_ctxp_rec *rec = &svc_ctxp[i]; + + if (!rec->valid || rec->engine != engine || + rec->buffer_id != buffer_id) + continue; + if (best_seq && rec->seq <= best_seq) + continue; + best_seq = rec->seq; + if (pa) + *pa = rec->pa; + if (va) + *va = rec->va; + if (size) + *size = rec->size; + if (phys_attr) + *phys_attr = rec->phys_attr; + if (b_init) + *b_init = rec->b_init; + rc = 0; + } + spin_unlock_irqrestore(&svc_ctxp_lock, flags); + return rc; +} + +/* * VA shadow: page-granular backing for device VAs whose VA->PA translation * cannot be derived from the guest's page tables. * |
