From a08343e3e053d5ab27398013781f489cdf7f60de Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Mon, 18 Apr 2005 08:26:00 +0000 Subject: 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. --- shared/via.h | 4 ++-- shared/via_dma.c | 30 +++++++++++++++++++++++++++--- shared/via_verifier.c | 15 +++++++++++---- 3 files changed, 40 insertions(+), 9 deletions(-) (limited to 'shared') 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"); -- cgit v1.2.3