diff options
| author | Joshua Bakita <bakitajoshua@gmail.com> | 2023-07-18 10:49:19 -0400 |
|---|---|---|
| committer | Joshua Bakita <bakitajoshua@gmail.com> | 2023-07-18 10:49:19 -0400 |
| commit | a1598f27a124cb0b5263276f7098ae3a68460b61 (patch) | |
| tree | 8593b040bb609a67b8bab8dad745b59cbe8f16c9 | |
| parent | 073e8978334a07e0053ee08310743ddf3046d7d2 (diff) | |
Fail reads which return the flag value for a non-existent register
Also check for read success in get_runlist_iter().
| -rw-r--r-- | nvdebug.h | 30 | ||||
| -rw-r--r-- | runlist.c | 2 |
2 files changed, 23 insertions, 9 deletions
| @@ -960,30 +960,42 @@ static inline int file2parentgpuidx(const struct file *f) { | |||
| 960 | // Similar to nvgpu_readl() | 960 | // Similar to nvgpu_readl() |
| 961 | // (except we don't try to resolve situations where regs is NULL) | 961 | // (except we don't try to resolve situations where regs is NULL) |
| 962 | static inline u32 nvdebug_readl(struct nvdebug_state *s, u32 r) { | 962 | static inline u32 nvdebug_readl(struct nvdebug_state *s, u32 r) { |
| 963 | u32 ret; | ||
| 963 | if (unlikely(!s->regs || (s->g && !gk20a_regs(s->g)))) { | 964 | if (unlikely(!s->regs || (s->g && !gk20a_regs(s->g)))) { |
| 964 | printk(KERN_ERR "[nvdebug] Attempted nvgpu_readl on non-existent registers!\n"); | 965 | printk(KERN_ERR "[nvdebug] nvdebug_readl: Unable to read; registers unavailable. Is GPU on?\n"); |
| 965 | return -1; | 966 | return -1; |
| 966 | } | 967 | } |
| 967 | return readl(s->regs + r); | 968 | ret = readl(s->regs + r); |
| 969 | // It seems like the GPU returns this as a flag value for bad addresses | ||
| 970 | if (ret == 0xbadf5040) { | ||
| 971 | printk(KERN_ERR "[nvdebug] nvdebug_readl: Unable to read from register offset %#x; bad data\n", r); | ||
| 972 | return -1; | ||
| 973 | } | ||
| 974 | return ret; | ||
| 968 | } | 975 | } |
| 969 | 976 | ||
| 970 | // quadword version of nvdebug_readl() | 977 | // quadword version of nvdebug_readl() |
| 971 | static inline u64 nvdebug_readq(struct nvdebug_state *s, u32 r) { | 978 | static inline u64 nvdebug_readq(struct nvdebug_state *s, u32 r) { |
| 972 | u64 ret; | 979 | u64 ret; |
| 973 | if (unlikely(!s->regs || (s->g && !gk20a_regs(s->g)))) { | 980 | if (unlikely(!s->regs || (s->g && !gk20a_regs(s->g)))) { |
| 974 | printk(KERN_ERR "[nvdebug] Attempted nvgpu_readl on non-existent registers!\n"); | 981 | printk(KERN_ERR "[nvdebug] nvdebug_readq: Unable to read; registers unavailable. Is GPU on?\n"); |
| 975 | return -1; | 982 | return -1; |
| 976 | } | 983 | } |
| 977 | // readq seems to always return the uppermost 32 bits as 0, so workaround with readl | 984 | // readq seems to always return the uppermost 32 bits as 0, so workaround with readl |
| 978 | ret = readl(s->regs + r); | 985 | ret = readl(s->regs + r); |
| 979 | ret |= ((u64)readl(s->regs + r + 4)) << 32; | 986 | ret |= ((u64)readl(s->regs + r + 4)) << 32; |
| 987 | // It seems like the GPU returns this as a flag value for bad addresses | ||
| 988 | if ((ret & 0xffffffffull) == 0xbadf5040ull) { | ||
| 989 | printk(KERN_ERR "[nvdebug] nvdebug_readq: Unable to read from register offset %#x; bad data\n", r); | ||
| 990 | return -1; | ||
| 991 | } | ||
| 980 | return ret; | 992 | return ret; |
| 981 | } | 993 | } |
| 982 | 994 | ||
| 983 | // Similar to nvgpu_writel() | 995 | // Similar to nvgpu_writel() |
| 984 | static inline void nvdebug_writel(struct nvdebug_state *s, u32 r, u32 v) { | 996 | static inline void nvdebug_writel(struct nvdebug_state *s, u32 r, u32 v) { |
| 985 | if (unlikely(!s->regs || (s->g && !gk20a_regs(s->g)))) { | 997 | if (unlikely(!s->regs || (s->g && !gk20a_regs(s->g)))) { |
| 986 | printk(KERN_ERR "[nvdebug] Attempted nvgpu_writel on non-existent registers!\n"); | 998 | printk(KERN_ERR "[nvdebug] nvdebug_writel: Unable to write; registers unavailable. Is GPU on?\n"); |
| 987 | return; | 999 | return; |
| 988 | } | 1000 | } |
| 989 | writel_relaxed(v, s->regs + r); | 1001 | writel_relaxed(v, s->regs + r); |
| @@ -994,9 +1006,9 @@ static inline void nvdebug_writel(struct nvdebug_state *s, u32 r, u32 v) { | |||
| 994 | // XXX: This probably doesn't work XXX: Untested | 1006 | // XXX: This probably doesn't work XXX: Untested |
| 995 | static inline void nvdebug_writeq(struct nvdebug_state *s, u32 r, u64 v) { | 1007 | static inline void nvdebug_writeq(struct nvdebug_state *s, u32 r, u64 v) { |
| 996 | if (unlikely(!s->regs || (s->g && !gk20a_regs(s->g)))) { | 1008 | if (unlikely(!s->regs || (s->g && !gk20a_regs(s->g)))) { |
| 997 | printk(KERN_ERR "[nvdebug] Attempted nvgpu_writel on non-existent registers!\n"); | 1009 | printk(KERN_ERR "[nvdebug] nvdebug_writeq: Unable to write; registers unavailable. Is GPU on?\n"); |
| 998 | return; | 1010 | return; |
| 999 | } | 1011 | } |
| 1000 | writeq_relaxed(v, s->regs + r); | 1012 | writeq_relaxed(v, s->regs + r); |
| 1001 | wmb(); | 1013 | wmb(); |
| 1002 | } | 1014 | } |
| @@ -41,6 +41,8 @@ int get_runlist_iter(struct nvdebug_state *g, int rl_id, struct runlist_iter *rl | |||
| 41 | // before because the GPU had simply gone to sleep and invalidated its | 41 | // before because the GPU had simply gone to sleep and invalidated its |
| 42 | // register state, so nvgpu_readl() was simply returning garbage. | 42 | // register state, so nvgpu_readl() was simply returning garbage. |
| 43 | rl_info.raw = nvdebug_readl(g, NV_PFIFO_ENG_RUNLIST(rl_id)); | 43 | rl_info.raw = nvdebug_readl(g, NV_PFIFO_ENG_RUNLIST(rl_id)); |
| 44 | if (rl_info.raw == -1) | ||
| 45 | return -EIO; | ||
| 44 | runlist_iova = ((u64)rl_base.ptr) << 12; | 46 | runlist_iova = ((u64)rl_base.ptr) << 12; |
| 45 | printk(KERN_INFO "[nvdebug] Runlist %d @ %llx in %s (config raw: %x)\n", | 47 | printk(KERN_INFO "[nvdebug] Runlist %d @ %llx in %s (config raw: %x)\n", |
| 46 | rl_id, runlist_iova, target_to_text(rl_base.target), rl_base.raw); | 48 | rl_id, runlist_iova, target_to_text(rl_base.target), rl_base.raw); |
