⬢ DragonFlyBSD Kernel Audit
DF-3838 / fix.diff
← back to finding ↓ download raw
--- a/sys/dev/drm/radeon/evergreen_cs.c
+++ b/sys/dev/drm/radeon/evergreen_cs.c
@@ -179,7 +179,7 @@
 	unsigned	nsamples;
 	/* output value */
 	unsigned	bpe;
-	unsigned	layer_size;
+	unsigned long	layer_size;
 	unsigned	palign;
 	unsigned	halign;
 	unsigned long	base_align;
@@ -189,7 +189,8 @@
 					  struct eg_surface *surf,
 					  const char *prefix)
 {
-	surf->layer_size = surf->nbx * surf->nby * surf->bpe * surf->nsamples;
+	surf->layer_size = (unsigned long)surf->nbx * surf->nby *
+			   surf->bpe * surf->nsamples;
 	surf->base_align = surf->bpe;
 	surf->palign = 1;
 	surf->halign = 1;
@@ -204,7 +205,8 @@
 	unsigned palign;
 
 	palign = MAX(64, track->group_size / surf->bpe);
-	surf->layer_size = surf->nbx * surf->nby * surf->bpe * surf->nsamples;
+	surf->layer_size = (unsigned long)surf->nbx * surf->nby *
+			   surf->bpe * surf->nsamples;
 	surf->base_align = track->group_size;
 	surf->palign = palign;
 	surf->halign = 1;
@@ -227,7 +229,7 @@
 
 	palign = track->group_size / (8 * surf->bpe * surf->nsamples);
 	palign = MAX(8, palign);
-	surf->layer_size = surf->nbx * surf->nby * surf->bpe;
+	surf->layer_size = (unsigned long)surf->nbx * surf->nby * surf->bpe;
 	surf->base_align = track->group_size;
 	surf->palign = palign;
 	surf->halign = 8;
@@ -268,8 +270,8 @@
 	halign = (8 * surf->bankh * surf->nbanks) / surf->mtilea;
 	mtileb = (palign / 8) * (halign / 8) * tileb;
 	mtile_pr = surf->nbx / palign;
-	mtile_ps = (mtile_pr * surf->nby) / halign;
-	surf->layer_size = mtile_ps * mtileb * slice_pt;
+	mtile_ps = ((unsigned long)mtile_pr * surf->nby) / halign;
+	surf->layer_size = (unsigned long)mtile_ps * mtileb * slice_pt;
 	surf->base_align = (palign / 8) * (halign / 8) * tileb;
 	surf->palign = palign;
 	surf->halign = halign;
@@ -398,10 +400,10 @@
 	int r;
 
 	mslice = G_028C6C_SLICE_MAX(track->cb_color_view[id]) + 1;
-	pitch = track->cb_color_pitch[id];
-	slice = track->cb_color_slice[id];
+	pitch = track->cb_color_pitch[id] & 0x7ff;	/* PITCH_TILE_MAX */
+	slice = track->cb_color_slice[id] & 0x3fff;	/* SLICE_TILE_MAX */
 	surf.nbx = (pitch + 1) * 8;
-	surf.nby = ((slice + 1) * 64) / surf.nbx;
+	surf.nby = ((uint64_t)(slice + 1) * 64) / surf.nbx;
 	surf.mode = G_028C70_ARRAY_MODE(track->cb_color_info[id]);
 	surf.format = G_028C70_FORMAT(track->cb_color_info[id]);
 	surf.tsplit = G_028C74_TILE_SPLIT(track->cb_color_attrib[id]);
@@ -432,14 +434,14 @@
 		return r;
 	}
 
-	offset = track->cb_color_bo_offset[id] << 8;
+	offset = (unsigned long)track->cb_color_bo_offset[id] << 8;
 	if (offset & (surf.base_align - 1)) {
 		dev_warn(p->dev, "%s:%d cb[%d] bo base %ld not aligned with %ld\n",
 			 __func__, __LINE__, id, offset, surf.base_align);
 		return -EINVAL;
 	}
 
-	offset += surf.layer_size * mslice;
+	offset += (unsigned long)surf.layer_size * mslice;
 	if (offset > radeon_bo_size(track->cb_color_bo[id])) {
 		/* old ddx are broken they allocate bo with w*h*bpp but
 		 * program slice with ALIGN(h, 8), catch this and patch
@@ -454,7 +456,7 @@
 				min = surf.nby - 8;
 			}
 			bsize = radeon_bo_size(track->cb_color_bo[id]);
-			tmp = track->cb_color_bo_offset[id] << 8;
+			tmp = (unsigned long)track->cb_color_bo_offset[id] << 8;
 			for (nby = surf.nby; nby > min; nby--) {
 				size = nby * surf.nbx * surf.bpe * surf.nsamples;
 				if ((tmp + size * mslice) <= bsize) {
@@ -544,7 +546,7 @@
 	nbx = nbx >> 3;
 	nby = nby >> 3;
 	/* size must be aligned on npipes * 2K boundary */
-	size = roundup(nbx * nby * 4, track->npipes * (2 << 10));
+	size = roundup((unsigned long)nbx * nby * 4, track->npipes * (2 << 10));
 	size += track->htile_offset;
 
 	if (size > radeon_bo_size(track->htile_bo)) {
@@ -566,9 +568,9 @@
 
 	mslice = G_028008_SLICE_MAX(track->db_depth_view) + 1;
 	pitch = G_028058_PITCH_TILE_MAX(track->db_depth_size);
-	slice = track->db_depth_slice;
+	slice = track->db_depth_slice & 0x3fff;	/* SLICE_TILE_MAX */
 	surf.nbx = (pitch + 1) * 8;
-	surf.nby = ((slice + 1) * 64) / surf.nbx;
+	surf.nby = ((uint64_t)(slice + 1) * 64) / surf.nbx;
 	surf.mode = G_028040_ARRAY_MODE(track->db_z_info);
 	surf.format = G_028044_FORMAT(track->db_s_info);
 	surf.tsplit = G_028044_TILE_SPLIT(track->db_s_info);
@@ -607,13 +609,13 @@
 		return r;
 	}
 
-	offset = track->db_s_read_offset << 8;
+	offset = (unsigned long)track->db_s_read_offset << 8;
 	if (offset & (surf.base_align - 1)) {
 		dev_warn(p->dev, "%s:%d stencil read bo base %ld not aligned with %ld\n",
 			 __func__, __LINE__, offset, surf.base_align);
 		return -EINVAL;
 	}
-	offset += surf.layer_size * mslice;
+	offset += (unsigned long)surf.layer_size * mslice;
 	if (offset > radeon_bo_size(track->db_s_read_bo)) {
 		dev_warn(p->dev, "%s:%d stencil read bo too small (layer size %d, "
 			 "offset %ld, max layer %d, bo size %ld)\n",
@@ -626,13 +628,13 @@
 		return -EINVAL;
 	}
 
-	offset = track->db_s_write_offset << 8;
+	offset = (unsigned long)track->db_s_write_offset << 8;
 	if (offset & (surf.base_align - 1)) {
 		dev_warn(p->dev, "%s:%d stencil write bo base %ld not aligned with %ld\n",
 			 __func__, __LINE__, offset, surf.base_align);
 		return -EINVAL;
 	}
-	offset += surf.layer_size * mslice;
+	offset += (unsigned long)surf.layer_size * mslice;
 	if (offset > radeon_bo_size(track->db_s_write_bo)) {
 		dev_warn(p->dev, "%s:%d stencil write bo too small (layer size %d, "
 			 "offset %ld, max layer %d, bo size %ld)\n",
@@ -663,9 +665,9 @@
 
 	mslice = G_028008_SLICE_MAX(track->db_depth_view) + 1;
 	pitch = G_028058_PITCH_TILE_MAX(track->db_depth_size);
-	slice = track->db_depth_slice;
+	slice = track->db_depth_slice & 0x3fff;	/* SLICE_TILE_MAX */
 	surf.nbx = (pitch + 1) * 8;
-	surf.nby = ((slice + 1) * 64) / surf.nbx;
+	surf.nby = ((uint64_t)(slice + 1) * 64) / surf.nbx;
 	surf.mode = G_028040_ARRAY_MODE(track->db_z_info);
 	surf.format = G_028040_FORMAT(track->db_z_info);
 	surf.tsplit = G_028040_TILE_SPLIT(track->db_z_info);
@@ -705,13 +707,13 @@
 		return r;
 	}
 
-	offset = track->db_z_read_offset << 8;
+	offset = (unsigned long)track->db_z_read_offset << 8;
 	if (offset & (surf.base_align - 1)) {
 		dev_warn(p->dev, "%s:%d stencil read bo base %ld not aligned with %ld\n",
 			 __func__, __LINE__, offset, surf.base_align);
 		return -EINVAL;
 	}
-	offset += surf.layer_size * mslice;
+	offset += (unsigned long)surf.layer_size * mslice;
 	if (offset > radeon_bo_size(track->db_z_read_bo)) {
 		dev_warn(p->dev, "%s:%d depth read bo too small (layer size %d, "
 			 "offset %ld, max layer %d, bo size %ld)\n",
@@ -721,13 +723,13 @@
 		return -EINVAL;
 	}
 
-	offset = track->db_z_write_offset << 8;
+	offset = (unsigned long)track->db_z_write_offset << 8;
 	if (offset & (surf.base_align - 1)) {
 		dev_warn(p->dev, "%s:%d stencil write bo base %ld not aligned with %ld\n",
 			 __func__, __LINE__, offset, surf.base_align);
 		return -EINVAL;
 	}
-	offset += surf.layer_size * mslice;
+	offset += (unsigned long)surf.layer_size * mslice;
 	if (offset > radeon_bo_size(track->db_z_write_bo)) {
 		dev_warn(p->dev, "%s:%d depth write bo too small (layer size %d, "
 			 "offset %ld, max layer %d, bo size %ld)\n",
@@ -784,8 +786,8 @@
 	surf.bankh = G_03001C_BANK_HEIGHT(texdw[7]);
 	surf.mtilea = G_03001C_MACRO_TILE_ASPECT(texdw[7]);
 	surf.nsamples = 1;
-	toffset = texdw[2] << 8;
-	moffset = texdw[3] << 8;
+	toffset = (unsigned long)texdw[2] << 8;
+	moffset = (unsigned long)texdw[3] << 8;
 
 	if (!r600_fmt_is_valid_texture(surf.format, p->family)) {
 		dev_warn(p->dev, "%s:%d texture invalid format %d\n",
@@ -843,9 +845,9 @@
 		return -EINVAL;
 	}
 	if (dim == SQ_TEX_DIM_3D) {
-		toffset += surf.layer_size * depth;
+		toffset += (unsigned long)surf.layer_size * depth;
 	} else {
-		toffset += surf.layer_size * mslice;
+		toffset += (unsigned long)surf.layer_size * mslice;
 	}
 	if (toffset > radeon_bo_size(texture)) {
 		dev_warn(p->dev, "%s:%d texture bo too small (layer size %d, "
@@ -903,9 +905,9 @@
 		}
 
 		if (dim == SQ_TEX_DIM_3D) {
-			moffset += surf.layer_size * d;
+			moffset += (unsigned long)surf.layer_size * d;
 		} else {
-			moffset += surf.layer_size * mslice;
+			moffset += (unsigned long)surf.layer_size * mslice;
 		}
 		if (moffset > radeon_bo_size(mipmap)) {
 			dev_warn(p->dev, "%s:%d mipmap [%d] bo too small (layer size %d, "
@@ -945,8 +947,8 @@
 		for (i = 0; i < 4; i++) {
 			if (buffer_mask & (1 << i)) {
 				if (track->vgt_strmout_bo[i]) {
-					u64 offset = (u64)track->vgt_strmout_bo_offset[i] +
-							(u64)track->vgt_strmout_size[i];
+					u64 offset = ((u64)track->vgt_strmout_bo_offset[i] << 8) +
+						(u64)track->vgt_strmout_size[i] * 4;
 					if (offset > radeon_bo_size(track->vgt_strmout_bo[i])) {
 						DRM_ERROR("streamout %d bo too small: 0x%llx, 0x%lx\n",
 							  i, offset,
@@ -1275,7 +1277,7 @@
 			return -EINVAL;
 		}
 		tmp = (reg - VGT_STRMOUT_BUFFER_BASE_0) / 16;
-		track->vgt_strmout_bo_offset[tmp] = radeon_get_ib_value(p, idx) << 8;
+		track->vgt_strmout_bo_offset[tmp] = radeon_get_ib_value(p, idx);
 		ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff);
 		track->vgt_strmout_bo[tmp] = reloc->robj;
 		track->streamout_dirty = true;
@@ -1286,7 +1288,7 @@
 	case VGT_STRMOUT_BUFFER_SIZE_3:
 		tmp = (reg - VGT_STRMOUT_BUFFER_SIZE_0) / 16;
 		/* size in register is DWs, convert to bytes */
-		track->vgt_strmout_size[tmp] = radeon_get_ib_value(p, idx) * 4;
+		track->vgt_strmout_size[tmp] = radeon_get_ib_value(p, idx);
 		track->streamout_dirty = true;
 		break;
 	case CP_COHER_BASE: