diff options
| author | Ben Skeggs <bskeggs@redhat.com> | 2010-02-19 17:06:36 -0500 |
|---|---|---|
| committer | Ben Skeggs <bskeggs@redhat.com> | 2010-02-22 22:50:21 -0500 |
| commit | 76befb8c30cebe2af83fa346bdaf75b430893511 (patch) | |
| tree | 57dd1258fa78ab7c955d3bf87ebb584566f16727 | |
| parent | 531e77139f26e8da32ee694b9ee5e6f4c764f1db (diff) | |
drm/nv50: fix instmem binding on IGPs to point at stolen system memory
This also modifies the unused PRAMIN PT entries to be all zeroes, can't
really recall why I used 9/0 initially, just that it didn't work for
some reason. It was likely masking a bug elsewhere that's since been
fixed.
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
| -rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_drv.h | 1 | ||||
| -rw-r--r-- | drivers/gpu/drm/nouveau/nv50_instmem.c | 58 |
2 files changed, 41 insertions, 18 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index 5445cefdd03e..1c15ef37b71c 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h | |||
| @@ -583,6 +583,7 @@ struct drm_nouveau_private { | |||
| 583 | uint64_t vm_end; | 583 | uint64_t vm_end; |
| 584 | struct nouveau_gpuobj *vm_vram_pt[NV50_VM_VRAM_NR]; | 584 | struct nouveau_gpuobj *vm_vram_pt[NV50_VM_VRAM_NR]; |
| 585 | int vm_vram_pt_nr; | 585 | int vm_vram_pt_nr; |
| 586 | uint64_t vram_sys_base; | ||
| 586 | 587 | ||
| 587 | /* the mtrr covering the FB */ | 588 | /* the mtrr covering the FB */ |
| 588 | int fb_mtrr; | 589 | int fb_mtrr; |
diff --git a/drivers/gpu/drm/nouveau/nv50_instmem.c b/drivers/gpu/drm/nouveau/nv50_instmem.c index 94400f777e7f..f0dc4e36ef05 100644 --- a/drivers/gpu/drm/nouveau/nv50_instmem.c +++ b/drivers/gpu/drm/nouveau/nv50_instmem.c | |||
| @@ -76,6 +76,11 @@ nv50_instmem_init(struct drm_device *dev) | |||
| 76 | for (i = 0x1700; i <= 0x1710; i += 4) | 76 | for (i = 0x1700; i <= 0x1710; i += 4) |
| 77 | priv->save1700[(i-0x1700)/4] = nv_rd32(dev, i); | 77 | priv->save1700[(i-0x1700)/4] = nv_rd32(dev, i); |
| 78 | 78 | ||
| 79 | if (dev_priv->chipset == 0xaa || dev_priv->chipset == 0xac) | ||
| 80 | dev_priv->vram_sys_base = nv_rd32(dev, 0x100e10) << 12; | ||
| 81 | else | ||
| 82 | dev_priv->vram_sys_base = 0; | ||
| 83 | |||
| 79 | /* Reserve the last MiB of VRAM, we should probably try to avoid | 84 | /* Reserve the last MiB of VRAM, we should probably try to avoid |
| 80 | * setting up the below tables over the top of the VBIOS image at | 85 | * setting up the below tables over the top of the VBIOS image at |
| 81 | * some point. | 86 | * some point. |
| @@ -172,16 +177,28 @@ nv50_instmem_init(struct drm_device *dev) | |||
| 172 | * We map the entire fake channel into the start of the PRAMIN BAR | 177 | * We map the entire fake channel into the start of the PRAMIN BAR |
| 173 | */ | 178 | */ |
| 174 | ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, pt_size, 0x1000, | 179 | ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, pt_size, 0x1000, |
| 175 | 0, &priv->pramin_pt); | 180 | 0, &priv->pramin_pt); |
| 176 | if (ret) | 181 | if (ret) |
| 177 | return ret; | 182 | return ret; |
| 178 | 183 | ||
| 179 | for (i = 0, v = c_offset; i < pt_size; i += 8, v += 0x1000) { | 184 | v = c_offset | 1; |
| 180 | if (v < (c_offset + c_size)) | 185 | if (dev_priv->vram_sys_base) { |
| 181 | BAR0_WI32(priv->pramin_pt->gpuobj, i + 0, v | 1); | 186 | v += dev_priv->vram_sys_base; |
| 182 | else | 187 | v |= 0x30; |
| 183 | BAR0_WI32(priv->pramin_pt->gpuobj, i + 0, 0x00000009); | 188 | } |
| 189 | |||
| 190 | i = 0; | ||
| 191 | while (v < dev_priv->vram_sys_base + c_offset + c_size) { | ||
| 192 | BAR0_WI32(priv->pramin_pt->gpuobj, i + 0, v); | ||
| 193 | BAR0_WI32(priv->pramin_pt->gpuobj, i + 4, 0x00000000); | ||
| 194 | v += 0x1000; | ||
| 195 | i += 8; | ||
| 196 | } | ||
| 197 | |||
| 198 | while (i < pt_size) { | ||
| 199 | BAR0_WI32(priv->pramin_pt->gpuobj, i + 0, 0x00000000); | ||
| 184 | BAR0_WI32(priv->pramin_pt->gpuobj, i + 4, 0x00000000); | 200 | BAR0_WI32(priv->pramin_pt->gpuobj, i + 4, 0x00000000); |
| 201 | i += 8; | ||
| 185 | } | 202 | } |
| 186 | 203 | ||
| 187 | BAR0_WI32(chan->vm_pd, 0x00, priv->pramin_pt->instance | 0x63); | 204 | BAR0_WI32(chan->vm_pd, 0x00, priv->pramin_pt->instance | 0x63); |
| @@ -416,7 +433,9 @@ nv50_instmem_bind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) | |||
| 416 | { | 433 | { |
| 417 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 434 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
| 418 | struct nv50_instmem_priv *priv = dev_priv->engine.instmem.priv; | 435 | struct nv50_instmem_priv *priv = dev_priv->engine.instmem.priv; |
| 419 | uint32_t pte, pte_end, vram; | 436 | struct nouveau_gpuobj *pramin_pt = priv->pramin_pt->gpuobj; |
| 437 | uint32_t pte, pte_end; | ||
| 438 | uint64_t vram; | ||
| 420 | 439 | ||
| 421 | if (!gpuobj->im_backing || !gpuobj->im_pramin || gpuobj->im_bound) | 440 | if (!gpuobj->im_backing || !gpuobj->im_pramin || gpuobj->im_bound) |
| 422 | return -EINVAL; | 441 | return -EINVAL; |
| @@ -424,20 +443,24 @@ nv50_instmem_bind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) | |||
| 424 | NV_DEBUG(dev, "st=0x%0llx sz=0x%0llx\n", | 443 | NV_DEBUG(dev, "st=0x%0llx sz=0x%0llx\n", |
| 425 | gpuobj->im_pramin->start, gpuobj->im_pramin->size); | 444 | gpuobj->im_pramin->start, gpuobj->im_pramin->size); |
| 426 | 445 | ||
| 427 | pte = (gpuobj->im_pramin->start >> 12) << 3; | 446 | pte = (gpuobj->im_pramin->start >> 12) << 1; |
| 428 | pte_end = ((gpuobj->im_pramin->size >> 12) << 3) + pte; | 447 | pte_end = ((gpuobj->im_pramin->size >> 12) << 1) + pte; |
| 429 | vram = gpuobj->im_backing_start; | 448 | vram = gpuobj->im_backing_start; |
| 430 | 449 | ||
| 431 | NV_DEBUG(dev, "pramin=0x%llx, pte=%d, pte_end=%d\n", | 450 | NV_DEBUG(dev, "pramin=0x%llx, pte=%d, pte_end=%d\n", |
| 432 | gpuobj->im_pramin->start, pte, pte_end); | 451 | gpuobj->im_pramin->start, pte, pte_end); |
| 433 | NV_DEBUG(dev, "first vram page: 0x%08x\n", gpuobj->im_backing_start); | 452 | NV_DEBUG(dev, "first vram page: 0x%08x\n", gpuobj->im_backing_start); |
| 434 | 453 | ||
| 454 | vram |= 1; | ||
| 455 | if (dev_priv->vram_sys_base) { | ||
| 456 | vram += dev_priv->vram_sys_base; | ||
| 457 | vram |= 0x30; | ||
| 458 | } | ||
| 459 | |||
| 435 | dev_priv->engine.instmem.prepare_access(dev, true); | 460 | dev_priv->engine.instmem.prepare_access(dev, true); |
| 436 | while (pte < pte_end) { | 461 | while (pte < pte_end) { |
| 437 | nv_wo32(dev, priv->pramin_pt->gpuobj, (pte + 0)/4, vram | 1); | 462 | nv_wo32(dev, pramin_pt, pte++, lower_32_bits(vram)); |
| 438 | nv_wo32(dev, priv->pramin_pt->gpuobj, (pte + 4)/4, 0x00000000); | 463 | nv_wo32(dev, pramin_pt, pte++, upper_32_bits(vram)); |
| 439 | |||
| 440 | pte += 8; | ||
| 441 | vram += NV50_INSTMEM_PAGE_SIZE; | 464 | vram += NV50_INSTMEM_PAGE_SIZE; |
| 442 | } | 465 | } |
| 443 | dev_priv->engine.instmem.finish_access(dev); | 466 | dev_priv->engine.instmem.finish_access(dev); |
| @@ -470,14 +493,13 @@ nv50_instmem_unbind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) | |||
| 470 | if (gpuobj->im_bound == 0) | 493 | if (gpuobj->im_bound == 0) |
| 471 | return -EINVAL; | 494 | return -EINVAL; |
| 472 | 495 | ||
| 473 | pte = (gpuobj->im_pramin->start >> 12) << 3; | 496 | pte = (gpuobj->im_pramin->start >> 12) << 1; |
| 474 | pte_end = ((gpuobj->im_pramin->size >> 12) << 3) + pte; | 497 | pte_end = ((gpuobj->im_pramin->size >> 12) << 1) + pte; |
| 475 | 498 | ||
| 476 | dev_priv->engine.instmem.prepare_access(dev, true); | 499 | dev_priv->engine.instmem.prepare_access(dev, true); |
| 477 | while (pte < pte_end) { | 500 | while (pte < pte_end) { |
| 478 | nv_wo32(dev, priv->pramin_pt->gpuobj, (pte + 0)/4, 0x00000009); | 501 | nv_wo32(dev, priv->pramin_pt->gpuobj, pte++, 0x00000000); |
| 479 | nv_wo32(dev, priv->pramin_pt->gpuobj, (pte + 4)/4, 0x00000000); | 502 | nv_wo32(dev, priv->pramin_pt->gpuobj, pte++, 0x00000000); |
| 480 | pte += 8; | ||
| 481 | } | 503 | } |
| 482 | dev_priv->engine.instmem.finish_access(dev); | 504 | dev_priv->engine.instmem.finish_access(dev); |
| 483 | 505 | ||
