diff options
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/gsp_sema_service.c | 90 |
1 files changed, 72 insertions, 18 deletions
diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c index 7475ea7..fa0fe65 100644 --- a/kernel/gsp_sema_service.c +++ b/kernel/gsp_sema_service.c @@ -167,14 +167,21 @@ static u32 svc_map_hash[SEMA_MAP_MAX * 2]; * (debug injection) and that must not be evicted by the learned cache, which * is content-addressed and gets thrashed by the lookup stream. */ -#define SVC_PIN_SLOTS 32768 +#define SVC_PIN_SLOTS (1u << 17) /* * Linear-probe window for the pin table. The table is now the primary * VA->PA store (push-buffer regions and bridged client mappings add * thousands of pages at a time), so a short window would silently drop - * inserts and mis-resolve lookups once it is half full. + * inserts and mis-resolve lookups once it is half full. Drops are counted + * (pin_drop) instead of being invisible. */ -#define SVC_PIN_PROBE 32 +#define SVC_PIN_PROBE 128 +/* + * Host-injected translations (debug `sema_map_add`): authoritative, never + * overwritten by self-discovery, checked before every other source. + */ +#define SVC_IPIN_SLOTS (1u << 13) +#define SVC_IPIN_PROBE 64 struct svc_pin { u64 va_page; @@ -305,6 +312,10 @@ struct sema_svc { struct svc_lat lat[SVC_LAT_MAX]; struct svc_pin pin[SVC_PIN_SLOTS]; u32 pin_n; + u64 pin_drop; + struct svc_pin ipin[SVC_IPIN_SLOTS]; + u32 ipin_n; + u64 ipin_drop; /* stats */ u64 walks_ok; @@ -1033,15 +1044,16 @@ static void svc_lat_store(u64 va, u64 addr, int ap) l->valid = true; } -static int svc_pin_lookup(u64 va, u64 *pa, int *ap) +static int pin_lookup_tab(const struct svc_pin *tab, u32 slots, u32 probe_max, + u64 va, u64 *pa, int *ap) { u64 page = va & ~(u64)(SEMA_PAGE_SIZE - 1); - u32 mask = SVC_PIN_SLOTS - 1; + u32 mask = slots - 1; u32 h = (u32)((page >> SEMA_PAGE_SHIFT) * 2654435761u) & mask; u32 probe; - for (probe = 0; probe < SVC_PIN_PROBE; probe++) { - struct svc_pin *p = &svc.pin[(h + probe) & mask]; + for (probe = 0; probe < probe_max; probe++) { + const struct svc_pin *p = &tab[(h + probe) & mask]; if (!p->va_page) return -ENOENT; @@ -1054,25 +1066,66 @@ static int svc_pin_lookup(u64 va, u64 *pa, int *ap) return -ENOENT; } -static void svc_pin_store(u64 va, u64 pa, int ap) +static void pin_store_tab(struct svc_pin *tab, u32 slots, u32 probe_max, + u32 *n, u64 *drops, u64 va, u64 pa, int ap) { u64 page = va & ~(u64)(SEMA_PAGE_SIZE - 1); - u32 mask = SVC_PIN_SLOTS - 1; + u32 mask = slots - 1; u32 h = (u32)((page >> SEMA_PAGE_SHIFT) * 2654435761u) & mask; u32 probe; - for (probe = 0; probe < SVC_PIN_PROBE; probe++) { - struct svc_pin *p = &svc.pin[(h + probe) & mask]; + for (probe = 0; probe < probe_max; probe++) { + struct svc_pin *p = &tab[(h + probe) & mask]; if (!p->va_page || p->va_page == page) { if (!p->va_page) - svc.pin_n++; + (*n)++; p->va_page = page; p->pa_page = pa & ~(u64)(SEMA_PAGE_SIZE - 1); p->ap = ap; return; } } + (*drops)++; +} + +static int svc_pin_lookup(u64 va, u64 *pa, int *ap) +{ + return pin_lookup_tab(svc.pin, SVC_PIN_SLOTS, SVC_PIN_PROBE, va, pa, ap); +} + +static void svc_pin_store(u64 va, u64 pa, int ap) +{ + pin_store_tab(svc.pin, SVC_PIN_SLOTS, SVC_PIN_PROBE, &svc.pin_n, + &svc.pin_drop, va, pa, ap); +} + +/* + * Injected (host-tool) translations. Kept separate from the discovered pin + * table so a hand-verified VA->PA pair can never be shadowed, evicted or + * silently dropped by the self-discovery stream: in the shared table a hot + * hash cluster longer than the probe window dropped inserts while lookups + * fell through to the content-scanned map and answered with a stale page + * (observed: the CE push-buffer page resolved to a zero-filled page and + * every push was "implausible"). + */ +static int svc_ipin_lookup(u64 va, u64 *pa, int *ap) +{ + return pin_lookup_tab(svc.ipin, SVC_IPIN_SLOTS, SVC_IPIN_PROBE, va, pa, ap); +} + +static void svc_ipin_store(u64 va, u64 pa, int ap) +{ + pin_store_tab(svc.ipin, SVC_IPIN_SLOTS, SVC_IPIN_PROBE, &svc.ipin_n, + &svc.ipin_drop, va, pa, ap); +} + +/* Any pinned translation: injected truth first, then self-discovered pins. */ +static int svc_pin_lookup_any(u64 va, u64 *pa, int *ap) +{ + if (!svc_ipin_lookup(va, pa, ap)) + return 0; + return svc_pin_lookup(va, pa, ap); } static void svc_add_map(u64 gpu_va, u64 pa); @@ -1258,7 +1311,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)) { + if (!svc_pin_lookup_any(va, addr, ap)) { return 0; } if (!svc_lat_lookup(va, addr, ap)) @@ -1711,9 +1764,10 @@ static void svc_rebuild(struct nv_vgpu_device *vgpu) svc.pushes_nomap, svc.memsets_done, svc.memsets_nomap, svc.memsets_fail, svc.ring_ops, svc.ops_denied, svc.false_trans, svc.gpfifo_skipped, svc.releases_faked); - pr_info("sema-svc: gpfifo done=%llu nomap=%llu vidmem_writes=%llu ring_auto=%u pb=%u/%u\n", + pr_info("sema-svc: gpfifo done=%llu nomap=%llu vidmem_writes=%llu ring_auto=%u pb=%u/%u pins=%u/%llu ipins=%u/%llu\n", svc.gpfifo_entries_done, svc.gpfifo_nomap, - svc.vidmem_writes, svc_ring_n, svc_pb_n, svc_pb_passes); + svc.vidmem_writes, svc_ring_n, svc_pb_n, svc_pb_passes, + svc.pin_n, svc.pin_drop, svc.ipin_n, svc.ipin_drop); /* show a few entries so mappings can be verified from dmesg */ { u32 shown; @@ -3266,7 +3320,7 @@ static void svc_gr_ring_autopin(struct nv_vgpu_device *vgpu, * The candidate chunk did not validate. If another source already * translates this ring VA (bridge or manual pin), trust it. */ - if (!svc_pin_lookup(ch->gpfifo_va, &pin_pa, &pin_ap)) { + if (!svc_pin_lookup_any(ch->gpfifo_va, &pin_pa, &pin_ap)) { set_bit(ch->gr_index, &svc_gr_ring_done); svc_ring_n++; return; @@ -3293,7 +3347,7 @@ static void svc_ring_autopin(struct nv_vgpu_device *vgpu, return; if (test_bit(ch->ce_index, &svc_ring_done)) return; - if (!svc_pin_lookup(ch->gpfifo_va, &pa, &ap)) { + if (!svc_pin_lookup_any(ch->gpfifo_va, &pa, &ap)) { set_bit(ch->ce_index, &svc_ring_done); svc_ring_n++; return; @@ -4327,7 +4381,7 @@ static void svc_handle_map_add(void) ap = req.ap ? req.ap : SVC_APERTURE_SYS; for (off = 0; off < (req.len ? req.len : 1); off += SEMA_PAGE_SIZE) { - svc_pin_store(req.va + off, req.pa + off, ap); + svc_ipin_store(req.va + off, req.pa + off, ap); svc_lat_store(req.va + off, req.pa + off, ap); } /* |
