Skip to content

Commit bc78497

Browse files
Ben Skeggsairlied
authored andcommitted
drm/nouveau/gsp: init client VMMs with NV0080_CTRL_DMA_SET_PAGE_DIRECTORY
The current code using NV90F1_CTRL_CMD_VASPACE_COPY_SERVER_RESERVED_PDES not only requires changes to support the new page table layout used on Hopper/Blackwell GPUs, but is also broken in that it always mirrors the PDEs used for virtual address 0, rather than the area reserved for RM. This works fine for the non-NVK case where the kernel has full control of the VMM layout and things end up in the right place, but NVK puts its kernel reserved area much higher in the address space. Fixing the code to work at any VA is not enough as some parts of RM want the reserved area in a specific location, and NVK would then hit other assertions in RM instead. Fortunately, it appears that RM never needs to allocate anything within its reserved area for DRM clients, and the COPY_SERVER_RESERVED_PDES control call primarily serves to allow RM to locate the root page table when initialising a channel's instance block. Flag VMMs allocated by the DRM driver as externally owned, and use NV0080_CTRL_CMD_DMA_SET_PAGE_DIRECTORY to inform RM of the root page table in a similar way to NVIDIA's UVM driver. The COPY_SERVER_RESERVED_PDES paths are kept for the golden context image and gr scrubber channel, where RM needs the reserved area. Signed-off-by: Ben Skeggs <[email protected]> Reviewed-by: Dave Airlie <[email protected]> Reviewed-by: Timur Tabi <[email protected]> Tested-by: Timur Tabi <[email protected]> Signed-off-by: Dave Airlie <[email protected]>
1 parent 708d81a commit bc78497

File tree

7 files changed

+106
-19
lines changed

7 files changed

+106
-19
lines changed

drivers/gpu/drm/nouveau/include/nvkm/subdev/mmu.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ struct nvkm_vmm {
7373
struct nvkm_gsp_object object;
7474

7575
struct nvkm_vma *rsvd;
76+
bool external;
7677
} rm;
7778
};
7879

drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/gr.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,6 @@ r535_gr_oneinit(struct nvkm_gr *base)
276276
struct nvkm_device *device = subdev->device;
277277
struct nvkm_gsp *gsp = device->gsp;
278278
struct nvkm_rm *rm = gsp->rm;
279-
struct nvkm_mmu *mmu = device->mmu;
280279
struct {
281280
struct nvkm_memory *inst;
282281
struct nvkm_vmm *vmm;
@@ -295,7 +294,7 @@ r535_gr_oneinit(struct nvkm_gr *base)
295294
if (ret)
296295
goto done;
297296

298-
ret = mmu->func->promote_vmm(golden.vmm);
297+
ret = r535_mmu_vaspace_new(golden.vmm, NVKM_RM_VASPACE, false);
299298
if (ret)
300299
goto done;
301300

drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/nvrm/vmm.h

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@ typedef struct
2323

2424
#define NV_VASPACE_ALLOCATION_INDEX_GPU_NEW 0x00 //<! Create new VASpace, by default
2525

26+
#define NV_VASPACE_ALLOCATION_FLAGS_IS_EXTERNALLY_OWNED BIT(3)
27+
28+
#define SPLIT_VAS_SERVER_RM_MANAGED_VA_START 0x100000000ULL // 4GB
29+
#define SPLIT_VAS_SERVER_RM_MANAGED_VA_SIZE 0x20000000ULL // 512MB
30+
2631
#define GMMU_FMT_MAX_LEVELS 6U
2732

2833
#define NV90F1_CTRL_CMD_VASPACE_COPY_SERVER_RESERVED_PDES (0x90f10106U) /* finn: Evaluated from "(FINN_FERMI_VASPACE_A_VASPACE_INTERFACE_ID << 8) | NV90F1_CTRL_VASPACE_COPY_SERVER_RESERVED_PDES_PARAMS_MESSAGE_ID" */
@@ -87,4 +92,41 @@ typedef struct NV90F1_CTRL_VASPACE_COPY_SERVER_RESERVED_PDES_PARAMS {
8792
NvU8 pageShift;
8893
} levels[GMMU_FMT_MAX_LEVELS];
8994
} NV90F1_CTRL_VASPACE_COPY_SERVER_RESERVED_PDES_PARAMS;
95+
96+
#define NV0080_CTRL_CMD_DMA_SET_PAGE_DIRECTORY (0x801813U) /* finn: Evaluated from "(FINN_NV01_DEVICE_0_DMA_INTERFACE_
97+
ID << 8) | NV0080_CTRL_DMA_SET_PAGE_DIRECTORY_PARAMS_MESSAGE_ID" */
98+
99+
typedef struct NV0080_CTRL_DMA_SET_PAGE_DIRECTORY_PARAMS {
100+
NV_DECLARE_ALIGNED(NvU64 physAddress, 8);
101+
NvU32 numEntries;
102+
NvU32 flags;
103+
NvHandle hVASpace;
104+
NvU32 chId;
105+
NvU32 subDeviceId; // ID+1, 0 for BC
106+
NvU32 pasid;
107+
} NV0080_CTRL_DMA_SET_PAGE_DIRECTORY_PARAMS;
108+
109+
#define NV0080_CTRL_DMA_SET_PAGE_DIRECTORY_FLAGS_APERTURE 1:0
110+
#define NV0080_CTRL_DMA_SET_PAGE_DIRECTORY_FLAGS_APERTURE_VIDMEM (0x00000000U)
111+
#define NV0080_CTRL_DMA_SET_PAGE_DIRECTORY_FLAGS_APERTURE_SYSMEM_COH (0x00000001U)
112+
#define NV0080_CTRL_DMA_SET_PAGE_DIRECTORY_FLAGS_APERTURE_SYSMEM_NONCOH (0x00000002U)
113+
#define NV0080_CTRL_DMA_SET_PAGE_DIRECTORY_FLAGS_PRESERVE_PDES 2:2
114+
#define NV0080_CTRL_DMA_SET_PAGE_DIRECTORY_FLAGS_PRESERVE_PDES_FALSE (0x00000000U)
115+
#define NV0080_CTRL_DMA_SET_PAGE_DIRECTORY_FLAGS_PRESERVE_PDES_TRUE (0x00000001U)
116+
#define NV0080_CTRL_DMA_SET_PAGE_DIRECTORY_FLAGS_ALL_CHANNELS 3:3
117+
#define NV0080_CTRL_DMA_SET_PAGE_DIRECTORY_FLAGS_ALL_CHANNELS_FALSE (0x00000000U)
118+
#define NV0080_CTRL_DMA_SET_PAGE_DIRECTORY_FLAGS_ALL_CHANNELS_TRUE (0x00000001U)
119+
#define NV0080_CTRL_DMA_SET_PAGE_DIRECTORY_FLAGS_IGNORE_CHANNEL_BUSY 4:4
120+
#define NV0080_CTRL_DMA_SET_PAGE_DIRECTORY_FLAGS_IGNORE_CHANNEL_BUSY_FALSE (0x00000000U)
121+
#define NV0080_CTRL_DMA_SET_PAGE_DIRECTORY_FLAGS_IGNORE_CHANNEL_BUSY_TRUE (0x00000001U)
122+
#define NV0080_CTRL_DMA_SET_PAGE_DIRECTORY_FLAGS_EXTEND_VASPACE 5:5
123+
#define NV0080_CTRL_DMA_SET_PAGE_DIRECTORY_FLAGS_EXTEND_VASPACE_FALSE (0x00000000U)
124+
#define NV0080_CTRL_DMA_SET_PAGE_DIRECTORY_FLAGS_EXTEND_VASPACE_TRUE (0x00000001U)
125+
126+
#define NV0080_CTRL_CMD_DMA_UNSET_PAGE_DIRECTORY (0x801814U) /* finn: Evaluated from "(FINN_NV01_DEVICE_0_DMA_INTERFACE_ID << 8) | NV0080_CTRL_DMA_UNSET_PAGE_DIRECTORY_PARAMS_MESSAGE_ID" */
127+
128+
typedef struct NV0080_CTRL_DMA_UNSET_PAGE_DIRECTORY_PARAMS {
129+
NvHandle hVASpace;
130+
NvU32 subDeviceId; // ID+1, 0 for BC
131+
} NV0080_CTRL_DMA_UNSET_PAGE_DIRECTORY_PARAMS;
90132
#endif

drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/vmm.c

Lines changed: 57 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,36 @@
2121
*/
2222
#include <subdev/mmu/vmm.h>
2323

24+
#include <nvhw/drf.h>
2425
#include "nvrm/vmm.h"
2526

27+
void
28+
r535_mmu_vaspace_del(struct nvkm_vmm *vmm)
29+
{
30+
if (vmm->rm.external) {
31+
NV0080_CTRL_DMA_UNSET_PAGE_DIRECTORY_PARAMS *ctrl;
32+
33+
ctrl = nvkm_gsp_rm_ctrl_get(&vmm->rm.device.object,
34+
NV0080_CTRL_CMD_DMA_UNSET_PAGE_DIRECTORY,
35+
sizeof(*ctrl));
36+
if (!IS_ERR(ctrl)) {
37+
ctrl->hVASpace = vmm->rm.object.handle;
38+
39+
WARN_ON(nvkm_gsp_rm_ctrl_wr(&vmm->rm.device.object, ctrl));
40+
}
41+
42+
vmm->rm.external = false;
43+
}
44+
45+
nvkm_gsp_rm_free(&vmm->rm.object);
46+
nvkm_gsp_device_dtor(&vmm->rm.device);
47+
nvkm_gsp_client_dtor(&vmm->rm.client);
48+
49+
nvkm_vmm_put(vmm, &vmm->rm.rsvd);
50+
}
51+
2652
int
27-
r535_mmu_vaspace_new(struct nvkm_vmm *vmm, u32 handle)
53+
r535_mmu_vaspace_new(struct nvkm_vmm *vmm, u32 handle, bool external)
2854
{
2955
NV_VASPACE_ALLOCATION_PARAMETERS *args;
3056
int ret;
@@ -40,12 +66,14 @@ r535_mmu_vaspace_new(struct nvkm_vmm *vmm, u32 handle)
4066
return PTR_ERR(args);
4167

4268
args->index = NV_VASPACE_ALLOCATION_INDEX_GPU_NEW;
69+
if (external)
70+
args->flags = NV_VASPACE_ALLOCATION_FLAGS_IS_EXTERNALLY_OWNED;
4371

4472
ret = nvkm_gsp_rm_alloc_wr(&vmm->rm.object, args);
4573
if (ret)
4674
return ret;
4775

48-
{
76+
if (!external) {
4977
NV90F1_CTRL_VASPACE_COPY_SERVER_RESERVED_PDES_PARAMS *ctrl;
5078

5179
mutex_lock(&vmm->mutex.vmm);
@@ -55,6 +83,11 @@ r535_mmu_vaspace_new(struct nvkm_vmm *vmm, u32 handle)
5583
if (ret)
5684
return ret;
5785

86+
/* Some parts of RM expect the server-reserved area to be in a specific location. */
87+
if (WARN_ON(vmm->rm.rsvd->addr != SPLIT_VAS_SERVER_RM_MANAGED_VA_START ||
88+
vmm->rm.rsvd->size != SPLIT_VAS_SERVER_RM_MANAGED_VA_SIZE))
89+
return -EINVAL;
90+
5891
ctrl = nvkm_gsp_rm_ctrl_get(&vmm->rm.object,
5992
NV90F1_CTRL_CMD_VASPACE_COPY_SERVER_RESERVED_PDES,
6093
sizeof(*ctrl));
@@ -73,14 +106,29 @@ r535_mmu_vaspace_new(struct nvkm_vmm *vmm, u32 handle)
73106
ctrl->levels[1].size = 0x1000;
74107
ctrl->levels[1].aperture = 1;
75108
ctrl->levels[1].pageShift = 0x26;
76-
if (vmm->pd->pde[0]->pde[0]) {
77-
ctrl->levels[2].physAddress = vmm->pd->pde[0]->pde[0]->pt[0]->addr;
78-
ctrl->levels[2].size = 0x1000;
79-
ctrl->levels[2].aperture = 1;
80-
ctrl->levels[2].pageShift = 0x1d;
81-
}
109+
ctrl->levels[2].physAddress = vmm->pd->pde[0]->pde[0]->pt[0]->addr;
110+
ctrl->levels[2].size = 0x1000;
111+
ctrl->levels[2].aperture = 1;
112+
ctrl->levels[2].pageShift = 0x1d;
82113

83114
ret = nvkm_gsp_rm_ctrl_wr(&vmm->rm.object, ctrl);
115+
} else {
116+
NV0080_CTRL_DMA_SET_PAGE_DIRECTORY_PARAMS *ctrl;
117+
118+
ctrl = nvkm_gsp_rm_ctrl_get(&vmm->rm.device.object,
119+
NV0080_CTRL_CMD_DMA_SET_PAGE_DIRECTORY,
120+
sizeof(*ctrl));
121+
if (IS_ERR(ctrl))
122+
return PTR_ERR(ctrl);
123+
124+
ctrl->physAddress = vmm->pd->pt[0]->addr;
125+
ctrl->numEntries = 1 << vmm->func->page[0].desc->bits;
126+
ctrl->flags = NVDEF(NV0080_CTRL_DMA_SET_PAGE_DIRECTORY, FLAGS, APERTURE, VIDMEM);
127+
ctrl->hVASpace = vmm->rm.object.handle;
128+
129+
ret = nvkm_gsp_rm_ctrl_wr(&vmm->rm.device.object, ctrl);
130+
if (ret == 0)
131+
vmm->rm.external = true;
84132
}
85133

86134
return ret;
@@ -89,7 +137,7 @@ r535_mmu_vaspace_new(struct nvkm_vmm *vmm, u32 handle)
89137
static int
90138
r535_mmu_promote_vmm(struct nvkm_vmm *vmm)
91139
{
92-
return r535_mmu_vaspace_new(vmm, NVKM_RM_VASPACE);
140+
return r535_mmu_vaspace_new(vmm, NVKM_RM_VASPACE, true);
93141
}
94142

95143
static void

drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r570/gr.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ r570_gr_scrubber_init(struct r535_gr *gr)
126126
if (ret)
127127
goto done;
128128

129-
ret = r535_mmu_vaspace_new(gr->scrubber.vmm, KGRAPHICS_SCRUBBER_HANDLE_VAS);
129+
ret = r535_mmu_vaspace_new(gr->scrubber.vmm, KGRAPHICS_SCRUBBER_HANDLE_VAS, false);
130130
if (ret)
131131
goto done;
132132

drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/rm.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,8 @@ extern const struct nvkm_rm_api_alloc r535_alloc;
147147
extern const struct nvkm_rm_api_client r535_client;
148148
void r535_gsp_client_dtor(struct nvkm_gsp_client *);
149149
extern const struct nvkm_rm_api_device r535_device;
150-
int r535_mmu_vaspace_new(struct nvkm_vmm *, u32 handle);
150+
int r535_mmu_vaspace_new(struct nvkm_vmm *, u32 handle, bool external);
151+
void r535_mmu_vaspace_del(struct nvkm_vmm *);
151152
extern const struct nvkm_rm_api_fbsr r535_fbsr;
152153
void r535_fbsr_resume(struct nvkm_gsp *);
153154
int r535_fbsr_memlist(struct nvkm_gsp_device *, u32 handle, enum nvkm_memory_target,

drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1030,12 +1030,8 @@ nvkm_vmm_dtor(struct nvkm_vmm *vmm)
10301030
struct nvkm_vma *vma;
10311031
struct rb_node *node;
10321032

1033-
if (vmm->rm.client.gsp) {
1034-
nvkm_gsp_rm_free(&vmm->rm.object);
1035-
nvkm_gsp_device_dtor(&vmm->rm.device);
1036-
nvkm_gsp_client_dtor(&vmm->rm.client);
1037-
nvkm_vmm_put(vmm, &vmm->rm.rsvd);
1038-
}
1033+
if (vmm->rm.client.gsp)
1034+
r535_mmu_vaspace_del(vmm);
10391035

10401036
if (0)
10411037
nvkm_vmm_dump(vmm);

0 commit comments

Comments
 (0)