summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/gsp_sema_service.c38
-rw-r--r--kernel/gsp_sema_service.h2
-rw-r--r--kernel/main.c17
3 files changed, 40 insertions, 17 deletions
diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c
index cb1255b..3b009ef 100644
--- a/kernel/gsp_sema_service.c
+++ b/kernel/gsp_sema_service.c
@@ -161,6 +161,7 @@ static u32 svc_map_hash[SEMA_MAP_MAX * 2];
struct svc_pin {
u64 va_page;
u64 pa_page;
+ int ap; /* SVC_APERTURE_* of the mapped page */
};
struct svc_vaspace {
@@ -862,7 +863,7 @@ static void svc_lat_store(u64 va, u64 addr, int ap)
l->valid = true;
}
-static int svc_pin_lookup(u64 va, u64 *pa)
+static int svc_pin_lookup(u64 va, u64 *pa, int *ap)
{
u64 page = va & ~(u64)(SEMA_PAGE_SIZE - 1);
u32 mask = SVC_PIN_SLOTS - 1;
@@ -876,13 +877,14 @@ static int svc_pin_lookup(u64 va, u64 *pa)
return -ENOENT;
if (p->va_page == page) {
*pa = p->pa_page | (va & (SEMA_PAGE_SIZE - 1));
+ *ap = p->ap;
return 0;
}
}
return -ENOENT;
}
-static void svc_pin_store(u64 va, u64 pa)
+static void svc_pin_store(u64 va, u64 pa, int ap)
{
u64 page = va & ~(u64)(SEMA_PAGE_SIZE - 1);
u32 mask = SVC_PIN_SLOTS - 1;
@@ -897,6 +899,7 @@ static void svc_pin_store(u64 va, u64 pa)
svc.pin_n++;
p->va_page = page;
p->pa_page = pa & ~(u64)(SEMA_PAGE_SIZE - 1);
+ p->ap = ap;
return;
}
}
@@ -915,8 +918,7 @@ static int svc_lookup_trusted(struct nv_vgpu_device *vgpu, u64 va, u64 *addr,
{
u64 pa = 0;
- if (!svc_pin_lookup(va, addr)) {
- *ap = SVC_APERTURE_SYS;
+ if (!svc_pin_lookup(va, addr, ap)) {
return 0;
}
if (!svc_lat_lookup(va, addr, ap))
@@ -2207,6 +2209,17 @@ static int svc_chan_userd(struct nv_vgpu_device *vgpu, struct svc_channel *ch,
if (ring_ap == SVC_APERTURE_FB && ring_pa) {
cand[nc] = ring_pa + 0x2000; as[nc++] = SVC_APERTURE_FB;
cand[nc] = ring_pa + 0x1000; as[nc++] = SVC_APERTURE_FB;
+ /*
+ * UVM's channel allocations place the USERD one 0x10000 block
+ * after the ring (observed for all eight CE channels: ring at
+ * FB 0x80000 + 0x20000*i, USERD at ring + 0x10000). The
+ * allocation parameters' userdMem base is relative to a client
+ * pool and does not describe this layout.
+ */
+ if (ch->engine_type != 0) {
+ cand[nc] = ring_pa + 0x10000;
+ as[nc++] = SVC_APERTURE_FB;
+ }
}
cand[nc] = ch->userd_pa; as[nc++] = ch->userd_as;
@@ -2518,10 +2531,12 @@ static struct completion map_add_done;
static u64 map_add_va;
static u64 map_add_pa;
static u64 map_add_len;
+static u32 map_add_ap;
static bool map_add_pending;
static void svc_handle_map_add(void)
{
+ u32 ap = map_add_ap ? map_add_ap : SVC_APERTURE_SYS;
u64 off;
if (!map_add_pending)
@@ -2529,28 +2544,29 @@ static void svc_handle_map_add(void)
for (off = 0; off < (map_add_len ? map_add_len : 1);
off += SEMA_PAGE_SIZE) {
- svc_pin_store(map_add_va + off, map_add_pa + off);
- svc_lat_store(map_add_va + off, map_add_pa + off,
- SVC_APERTURE_SYS);
+ svc_pin_store(map_add_va + off, map_add_pa + off, ap);
+ svc_lat_store(map_add_va + off, map_add_pa + off, ap);
}
- pr_info("sema-svc: injected mapping va=0x%llx -> pa=0x%llx len=0x%llx (sysmem)\n",
- map_add_va, map_add_pa, map_add_len);
+ pr_info("sema-svc: injected mapping va=0x%llx -> pa=0x%llx len=0x%llx (%s)\n",
+ map_add_va, map_add_pa, map_add_len,
+ ap == SVC_APERTURE_FB ? "vidmem" : "sysmem");
map_add_pending = false;
complete(&map_add_done);
}
-int gsp_sema_service_add_map(u64 gpu_va, u64 pa, u64 len)
+int gsp_sema_service_add_map(u64 gpu_va, u64 pa, u64 len, u32 ap)
{
if (!svc.task)
return -ENODEV;
- if (len > (64ULL << 20))
+ if (len > (64ULL << 20) || ap > SVC_APERTURE_FB)
return -EINVAL;
init_completion(&map_add_done);
map_add_va = gpu_va;
map_add_pa = pa;
map_add_len = len;
+ map_add_ap = ap;
map_add_pending = true;
if (!wait_for_completion_timeout(&map_add_done, 3 * HZ)) {
diff --git a/kernel/gsp_sema_service.h b/kernel/gsp_sema_service.h
index a6893bd..6b8dc6a 100644
--- a/kernel/gsp_sema_service.h
+++ b/kernel/gsp_sema_service.h
@@ -57,7 +57,7 @@ void gsp_sema_service_vaspace_del(u32 h_vaspace);
int gsp_sema_service_start(void);
void gsp_sema_service_stop(void);
int gsp_sema_service_probe(u64 gpu_va, u32 count);
-int gsp_sema_service_add_map(u64 gpu_va, u64 pa, u64 len);
+int gsp_sema_service_add_map(u64 gpu_va, u64 pa, u64 len, u32 ap);
void gsp_sema_service_doorbell(u32 token);
#endif /* _GSP_SEMA_SERVICE_H_ */
diff --git a/kernel/main.c b/kernel/main.c
index 25bd5eb..63657f3 100644
--- a/kernel/main.c
+++ b/kernel/main.c
@@ -2256,8 +2256,8 @@ MODULE_PARM_DESC(sema_probe, "Dump sema-service map + slot values for a GPU VA")
static int nv_vgpu_sema_map_add_set(const char *val, const struct kernel_param *kp)
{
char buf[64];
- char *comma, *comma2;
- u64 va = 0, pa = 0, len = 0;
+ char *comma, *comma2, *comma3;
+ u64 va = 0, pa = 0, len = 0, ap = 0;
strscpy(buf, val, sizeof(buf));
comma = strchr(buf, ',');
@@ -2269,10 +2269,17 @@ static int nv_vgpu_sema_map_add_set(const char *val, const struct kernel_param *
*comma2 = '\0';
if (kstrtoull(buf, 0, &va) || kstrtoull(comma + 1, 0, &pa))
return -EINVAL;
- if (comma2 && kstrtoull(comma2 + 1, 0, &len))
- return -EINVAL;
+ if (comma2) {
+ comma3 = strchr(comma2 + 1, ',');
+ if (comma3)
+ *comma3 = '\0';
+ if (kstrtoull(comma2 + 1, 0, &len))
+ return -EINVAL;
+ if (comma3 && kstrtoull(comma3 + 1, 0, &ap))
+ return -EINVAL;
+ }
- return gsp_sema_service_add_map(va, pa, len);
+ return gsp_sema_service_add_map(va, pa, len, (u32)ap);
}
static const struct kernel_param_ops nv_vgpu_sema_map_add_ops = {