summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Hellstrom <unichrome@shipmail.org>2005-04-18 08:26:00 +0000
committerThomas Hellstrom <unichrome@shipmail.org>2005-04-18 08:26:00 +0000
commita08343e3e053d5ab27398013781f489cdf7f60de (patch)
treee7ec701b10c7e21e8eb02a21821a7618dc46fa38
parent10ddbc8c8c9e540cf4802cab36d0c46f0aa0b6d8 (diff)
VIA:
1) Security fix: Stopped possible MMIO access to PCI DMA area for the unichrome Pro. 2) Fixed an odd cpu usage problem by padding small AGP DMA submissions. Bumped patchlevel.
-rw-r--r--shared-core/via_dma.c30
-rw-r--r--shared-core/via_drv.h4
-rw-r--r--shared-core/via_verifier.c4
-rw-r--r--shared/via.h4
-rw-r--r--shared/via_dma.c30
-rw-r--r--shared/via_verifier.c15
6 files changed, 73 insertions, 14 deletions
diff --git a/shared-core/via_dma.c b/shared-core/via_dma.c
index 081fefc1..2347d98b 100644
--- a/shared-core/via_dma.c
+++ b/shared-core/via_dma.c
@@ -41,7 +41,7 @@
#include "via_3d_reg.h"
#define CMDBUF_ALIGNMENT_SIZE (0x100)
-#define CMDBUF_ALIGNMENT_MASK (0xff)
+#define CMDBUF_ALIGNMENT_MASK (0x0ff)
/* defines for VIA 3D registers */
#define VIA_REG_STATUS 0x400
@@ -73,6 +73,9 @@ static void via_cmdbuf_pause(drm_via_private_t * dev_priv);
static void via_cmdbuf_reset(drm_via_private_t * dev_priv);
static void via_cmdbuf_rewind(drm_via_private_t * dev_priv);
static int via_wait_idle(drm_via_private_t * dev_priv);
+static void via_pad_cache(drm_via_private_t *dev_priv, int qwords);
+
+
/*
* Free space in command buffer.
*/
@@ -250,6 +253,8 @@ int via_dma_init(DRM_IOCTL_ARGS)
return retcode;
}
+
+
static int via_dispatch_cmdbuffer(drm_device_t * dev, drm_via_cmdbuffer_t * cmd)
{
drm_via_private_t *dev_priv;
@@ -283,7 +288,8 @@ static int via_dispatch_cmdbuffer(drm_device_t * dev, drm_via_cmdbuffer_t * cmd)
return ret;
}
- vb = via_check_dma(dev_priv, cmd->size);
+
+ vb = via_check_dma(dev_priv, (cmd->size < 0x100) ? 0x102 : cmd->size);
if (vb == NULL) {
return DRM_ERR(EAGAIN);
}
@@ -291,6 +297,14 @@ static int via_dispatch_cmdbuffer(drm_device_t * dev, drm_via_cmdbuffer_t * cmd)
memcpy(vb, dev_priv->pci_buf, cmd->size);
dev_priv->dma_low += cmd->size;
+
+ /*
+ * Small submissions somehow stalls the CPU. (AGP cache effects?)
+ * pad to greater size.
+ */
+
+ if (cmd->size < 0x100)
+ via_pad_cache(dev_priv,(0x100 - cmd->size) >> 3);
via_cmdbuf_pause(dev_priv);
return 0;
@@ -384,7 +398,7 @@ int via_pci_cmdbuffer(DRM_IOCTL_ARGS)
static inline uint32_t *via_align_buffer(drm_via_private_t * dev_priv,
uint32_t * vb, int qw_count)
{
- for (; qw_count > 0; --qw_count) {
+ for (; qw_count > 0; --qw_count) {
VIA_OUT_RING_QW(HC_DUMMY, HC_DUMMY);
}
return vb;
@@ -555,6 +569,16 @@ static void via_cmdbuf_start(drm_via_private_t * dev_priv)
VIA_WRITE(VIA_REG_TRANSPACE, command | HC_HAGPCMNT_MASK);
}
+static void via_pad_cache(drm_via_private_t *dev_priv, int qwords)
+{
+ uint32_t *vb;
+
+ via_cmdbuf_wait(dev_priv, qwords + 2);
+ vb = via_get_dma(dev_priv);
+ VIA_OUT_RING_QW( HC_HEADER2, HC_ParaType_NotTex << 16);
+ via_align_buffer(dev_priv,vb,qwords);
+}
+
static inline void via_dummy_bitblt(drm_via_private_t * dev_priv)
{
uint32_t *vb = via_get_dma(dev_priv);
diff --git a/shared-core/via_drv.h b/shared-core/via_drv.h
index 353a9b9b..49a382fe 100644
--- a/shared-core/via_drv.h
+++ b/shared-core/via_drv.h
@@ -28,11 +28,11 @@
#define DRIVER_NAME "via"
#define DRIVER_DESC "VIA Unichrome / Pro"
-#define DRIVER_DATE "20050328"
+#define DRIVER_DATE "20050418"
#define DRIVER_MAJOR 2
#define DRIVER_MINOR 6
-#define DRIVER_PATCHLEVEL 0
+#define DRIVER_PATCHLEVEL 1
#include "via_verifier.h"
diff --git a/shared-core/via_verifier.c b/shared-core/via_verifier.c
index 5b1f30a7..07923b0c 100644
--- a/shared-core/via_verifier.c
+++ b/shared-core/via_verifier.c
@@ -732,6 +732,10 @@ verify_mmio_address( uint32_t address)
DRM_ERROR("Invalid VIDEO DMA command. "
"Attempt to access 3D- or command burst area.\n");
return 1;
+ } else if ((address > 0xCFF) && (address < 0x1300)) {
+ DRM_ERROR("Invalid VIDEO DMA command. "
+ "Attempt to access PCI DMA area.\n");
+ return 1;
} else if (address > 0x13FF ) {
DRM_ERROR("Invalid VIDEO DMA command. "
"Attempt to access VGA registers.\n");
diff --git a/shared/via.h b/shared/via.h
index 816880e7..fcfefae7 100644
--- a/shared/via.h
+++ b/shared/via.h
@@ -30,11 +30,11 @@
#define DRIVER_NAME "via"
#define DRIVER_DESC "VIA Unichrome / Pro"
-#define DRIVER_DATE "20050328"
+#define DRIVER_DATE "20050418"
#define DRIVER_MAJOR 2
#define DRIVER_MINOR 6
-#define DRIVER_PATCHLEVEL 0
+#define DRIVER_PATCHLEVEL 1
#define DRIVER_IOCTLS \
[DRM_IOCTL_NR(DRM_IOCTL_VIA_ALLOCMEM)] = { via_mem_alloc, 1, 0 }, \
diff --git a/shared/via_dma.c b/shared/via_dma.c
index 34ac6cc1..c6c14dc0 100644
--- a/shared/via_dma.c
+++ b/shared/via_dma.c
@@ -42,7 +42,7 @@
#include "via_3d_reg.h"
#define CMDBUF_ALIGNMENT_SIZE (0x100)
-#define CMDBUF_ALIGNMENT_MASK (0xff)
+#define CMDBUF_ALIGNMENT_MASK (0x0ff)
/* defines for VIA 3D registers */
#define VIA_REG_STATUS 0x400
@@ -74,6 +74,9 @@ static void via_cmdbuf_pause(drm_via_private_t * dev_priv);
static void via_cmdbuf_reset(drm_via_private_t * dev_priv);
static void via_cmdbuf_rewind(drm_via_private_t * dev_priv);
static int via_wait_idle(drm_via_private_t * dev_priv);
+static void via_pad_cache(drm_via_private_t *dev_priv, int qwords);
+
+
/*
* Free space in command buffer.
*/
@@ -251,6 +254,8 @@ int via_dma_init(DRM_IOCTL_ARGS)
return retcode;
}
+
+
static int via_dispatch_cmdbuffer(drm_device_t * dev, drm_via_cmdbuffer_t * cmd)
{
drm_via_private_t *dev_priv;
@@ -284,7 +289,8 @@ static int via_dispatch_cmdbuffer(drm_device_t * dev, drm_via_cmdbuffer_t * cmd)
return ret;
}
- vb = via_check_dma(dev_priv, cmd->size);
+
+ vb = via_check_dma(dev_priv, (cmd->size < 0x100) ? 0x102 : cmd->size);
if (vb == NULL) {
return DRM_ERR(EAGAIN);
}
@@ -292,6 +298,14 @@ static int via_dispatch_cmdbuffer(drm_device_t * dev, drm_via_cmdbuffer_t * cmd)
memcpy(vb, dev_priv->pci_buf, cmd->size);
dev_priv->dma_low += cmd->size;
+
+ /*
+ * Small submissions somehow stalls the CPU. (AGP cache effects?)
+ * pad to greater size.
+ */
+
+ if (cmd->size < 0x100)
+ via_pad_cache(dev_priv,(0x100 - cmd->size) >> 3);
via_cmdbuf_pause(dev_priv);
return 0;
@@ -385,7 +399,7 @@ int via_pci_cmdbuffer(DRM_IOCTL_ARGS)
static inline uint32_t *via_align_buffer(drm_via_private_t * dev_priv,
uint32_t * vb, int qw_count)
{
- for (; qw_count > 0; --qw_count) {
+ for (; qw_count > 0; --qw_count) {
VIA_OUT_RING_QW(HC_DUMMY, HC_DUMMY);
}
return vb;
@@ -556,6 +570,16 @@ static void via_cmdbuf_start(drm_via_private_t * dev_priv)
VIA_WRITE(VIA_REG_TRANSPACE, command | HC_HAGPCMNT_MASK);
}
+static void via_pad_cache(drm_via_private_t *dev_priv, int qwords)
+{
+ uint32_t *vb;
+
+ via_cmdbuf_wait(dev_priv, qwords + 2);
+ vb = via_get_dma(dev_priv);
+ VIA_OUT_RING_QW( HC_HEADER2, HC_ParaType_NotTex << 16);
+ via_align_buffer(dev_priv,vb,qwords);
+}
+
static inline void via_dummy_bitblt(drm_via_private_t * dev_priv)
{
uint32_t *vb = via_get_dma(dev_priv);
diff --git a/shared/via_verifier.c b/shared/via_verifier.c
index 742d7cea..ed14b1c6 100644
--- a/shared/via_verifier.c
+++ b/shared/via_verifier.c
@@ -28,8 +28,10 @@
* be very slow.
*/
-#include "via.h"
+
+
#include "via_3d_reg.h"
+#include "via.h"
#include "drmP.h"
#include "drm.h"
#include "via_drm.h"
@@ -693,11 +695,12 @@ via_parse_header2( drm_via_private_t *dev_priv, uint32_t const **buffer, const u
VIA_WRITE(HC_REG_TRANS_SET + HC_REG_BASE, *buf++);
switch(cmd) {
case HC_ParaType_CmdVdata:
- while ((*fire_count < dev_priv->num_fire_offsets) &&
+ while ((buf < buf_end) &&
+ (*fire_count < dev_priv->num_fire_offsets) &&
(*buf & HC_ACMD_MASK) == HC_ACMD_HCmdB ) {
while(buf <= next_fire) {
- VIA_WRITE(HC_REG_TRANS_SPACE + HC_REG_BASE + (burst & 63), *buf++);
- burst += 4;
+ VIA_WRITE(HC_REG_TRANS_SPACE + HC_REG_BASE + (burst & 63), *buf++);
+ burst += 4;
}
if ( ( buf < buf_end ) && ((*buf & HALCYON_FIREMASK) == HALCYON_FIRECMD))
buf++;
@@ -731,6 +734,10 @@ verify_mmio_address( uint32_t address)
DRM_ERROR("Invalid VIDEO DMA command. "
"Attempt to access 3D- or command burst area.\n");
return 1;
+ } else if ((address > 0xCFF) && (address < 0x1300)) {
+ DRM_ERROR("Invalid VIDEO DMA command. "
+ "Attempt to access PCI DMA area.\n");
+ return 1;
} else if (address > 0x13FF ) {
DRM_ERROR("Invalid VIDEO DMA command. "
"Attempt to access VGA registers.\n");