Mercurial > illumos > illumos-gate
changeset 6742:14e085c688d3
6696145 [OpenSolaris bug #1069] Panics due to memory corruption on Intel GM965 systems with heavy zfs i/o
author | ms148562 |
---|---|
date | Wed, 28 May 2008 08:03:20 -0700 |
parents | fd2d992ea0b3 |
children | 5176703cbaff |
files | usr/src/uts/common/sys/agp/agpdefs.h usr/src/uts/intel/io/agpgart/agpgart.c |
diffstat | 2 files changed, 46 insertions(+), 127 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/uts/common/sys/agp/agpdefs.h Tue May 27 23:01:20 2008 -0700 +++ b/usr/src/uts/common/sys/agp/agpdefs.h Wed May 28 08:03:20 2008 -0700 @@ -187,10 +187,10 @@ #define GTT_TABLE_VALID 0x1 #define GTT_BASE_MASK 0xfffff000 #define GTT_MB_TO_PAGES(m) ((m) << 8) -#define GTT_POINTER_MASK 0xffffffff +#define GTT_POINTER_MASK 0xffffffff00000000 /* Intel i810 register offset */ -#define I810_POINTER_MASK 0x3fffffff +#define I810_POINTER_MASK 0xffffffffc0000000 #define I810_CONF_SMRAM 0x70 /* offset in PCI config space */ #define I810_GMS_MASK 0xc0 /* smram register mask */ /* @@ -256,7 +256,7 @@ */ /* Intel agp bridge specific */ -#define AGP_INTEL_POINTER_MASK 0xffffffff +#define AGP_INTEL_POINTER_MASK 0xffffffff00000000 /* Amd64 cpu gart device reigster offset */ #define AMD64_APERTURE_CONTROL 0x90 @@ -269,7 +269,7 @@ #define AMD64_APERBASE_MASK 0x00007fff #define AMD64_GARTBASE_SHIFT 8 #define AMD64_GARTBASE_MASK 0xfffffff0 -#define AMD64_POINTER_MASK 0xffffffffff +#define AMD64_POINTER_MASK 0xffffff0000000000 #define AMD64_INVALID_CACHE 0x1 #define AMD64_GART_SHIFT 12 #define AMD64_RESERVE_SHIFT 4
--- a/usr/src/uts/intel/io/agpgart/agpgart.c Tue May 27 23:01:20 2008 -0700 +++ b/usr/src/uts/intel/io/agpgart/agpgart.c Wed May 28 08:03:20 2008 -0700 @@ -1,5 +1,5 @@ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* @@ -930,7 +930,7 @@ { uint32_t base; - ASSERT((phy_base & ~I810_POINTER_MASK) == 0); + ASSERT((phy_base & I810_POINTER_MASK) == 0); base = (uint32_t)phy_base; hdl = agp_regdev->agprd_masterhdl; @@ -943,7 +943,7 @@ uint32_t addr; addr = (uint32_t)phy_base; - ASSERT((phy_base & ~GTT_POINTER_MASK) == 0); + ASSERT((phy_base & GTT_POINTER_MASK) == 0); hdl = agp_regdev->agprd_targethdl; err = ldi_ioctl(hdl, AGP_TARGET_SET_GATTADDR, (intptr_t)&addr, FKIOCTL, kcred, 0); @@ -953,7 +953,7 @@ { uint32_t addr; - ASSERT((phy_base & ~AMD64_POINTER_MASK) == 0); + ASSERT((phy_base & AMD64_POINTER_MASK) == 0); addr = (uint32_t)((phy_base >> AMD64_GARTBASE_SHIFT) & AMD64_GARTBASE_MASK); @@ -1455,30 +1455,6 @@ } /* - * agp_dealloc_pmem() - * - * Description: - * This function deallocates memory resource for direct mapping to - * userland applications. - * - * Arguments: - * entryp key table entity pointer - * - */ -static void -agp_dealloc_pmem(keytable_ent_t *entryp) -{ - devmap_pmem_free(PMEMP(entryp->kte_memhdl)->pmem_cookie); - PMEMP(entryp->kte_memhdl)->pmem_cookie = NULL; - kmem_free(entryp->kte_memhdl, sizeof (agp_pmem_handle_t)); - entryp->kte_memhdl = NULL; - - /* free the page frame number array */ - kmem_free(entryp->kte_pfnarray, sizeof (pfn_t) * entryp->kte_pages); - entryp->kte_pfnarray = NULL; -} - -/* * agp_dealloc_mem() * * Description: @@ -1521,14 +1497,12 @@ } if (entryp->kte_refcnt) { AGPDB_PRINT2((CE_WARN, - "agp_dealloc_pmem: memory is exported to users")); + "agp_dealloc_mem: memory is exported to users")); return (-1); } switch (entryp->kte_type) { case AGP_NORMAL: - agp_dealloc_pmem(entryp); - break; case AGP_PHYSICAL: agp_dealloc_kmem(entryp); break; @@ -1601,13 +1575,15 @@ { uint64_t paddr; - paddr = pfn<<AGP_PAGE_SHIFT; + paddr = (uint64_t)pfn << AGP_PAGE_SHIFT; + AGPDB_PRINT1((CE_NOTE, "checking pfn number %lu for type %d", + pfn, arc_type)); switch (arc_type) { case ARC_INTELAGP: { /* Only support 32-bit hardware address */ - if ((paddr & ~AGP_INTEL_POINTER_MASK) != 0) { + if ((paddr & AGP_INTEL_POINTER_MASK) != 0) { AGPDB_PRINT2((CE_WARN, "INTEL AGP Hardware only support 32 bits")); return (-1); @@ -1620,7 +1596,7 @@ { uint32_t value1, value2; /* Physaddr should not exceed 40-bit */ - if ((paddr & ~AMD64_POINTER_MASK) != 0) { + if ((paddr & AMD64_POINTER_MASK) != 0) { AGPDB_PRINT2((CE_WARN, "AMD64 GART hardware only supoort 40 bits")); return (-1); @@ -1633,7 +1609,7 @@ break; } case ARC_IGD810: - if ((paddr & ~I810_POINTER_MASK) != 0) { + if ((paddr & I810_POINTER_MASK) != 0) { AGPDB_PRINT2((CE_WARN, "Intel i810 only support 30 bits")); return (-1); @@ -1641,7 +1617,7 @@ break; case ARC_IGD830: - if ((paddr & ~GTT_POINTER_MASK) != 0) { + if ((paddr & GTT_POINTER_MASK) != 0) { AGPDB_PRINT2((CE_WARN, "Intel IGD only support 32 bits")); return (-1); @@ -1979,85 +1955,11 @@ } /* - * agp_alloc_pmem() - * - * Description: - * This function allocates physical memory for direct mapping to userland - * applications. - * - * Arguments: - * softsate driver soft state pointer - * length memory size - * type AGP_NORMAL: normal agp memory, AGP_PHISYCAL: specical - * memory type for intel i810 IGD - * - * Returns: - * entryp new key table entity pointer - * NULL no key table slot available - */ -static keytable_ent_t * -agp_alloc_pmem(agpgart_softstate_t *softstate, size_t length, int type) -{ - keytable_ent_t keyentry; - keytable_ent_t *entryp; - - ASSERT(AGP_ALIGNED(length)); - bzero(&keyentry, sizeof (keytable_ent_t)); - - keyentry.kte_pages = AGP_BYTES2PAGES(length); - keyentry.kte_type = type; - - keyentry.kte_memhdl = - (agp_pmem_handle_t *)kmem_zalloc(sizeof (agp_pmem_handle_t), - KM_SLEEP); - - if (devmap_pmem_alloc(length, - PMEM_SLEEP, - &PMEMP(keyentry.kte_memhdl)->pmem_cookie) != DDI_SUCCESS) - goto err1; - - keyentry.kte_pfnarray = (pfn_t *)kmem_zalloc(sizeof (pfn_t) * - keyentry.kte_pages, KM_SLEEP); - - if (devmap_pmem_getpfns( - PMEMP(keyentry.kte_memhdl)->pmem_cookie, - 0, keyentry.kte_pages, keyentry.kte_pfnarray) != DDI_SUCCESS) { - AGPDB_PRINT2((CE_WARN, - "agp_alloc_pmem: devmap_map_getpfns failed")); - goto err2; - } - ASSERT(!agp_check_pfns(softstate->asoft_devreg.agprd_arctype, - keyentry.kte_pfnarray, keyentry.kte_pages)); - entryp = agp_fill_empty_keyent(softstate, &keyentry); - - if (!entryp) { - AGPDB_PRINT2((CE_WARN, - "agp_alloc_pmem: agp_fill_empty_keyent error")); - goto err2; - } - ASSERT((entryp->kte_key >= 0) && (entryp->kte_key < AGP_MAXKEYS)); - - return (entryp); - -err2: - kmem_free(keyentry.kte_pfnarray, sizeof (pfn_t) * keyentry.kte_pages); - keyentry.kte_pfnarray = NULL; - devmap_pmem_free(PMEMP(keyentry.kte_memhdl)->pmem_cookie); - PMEMP(keyentry.kte_memhdl)->pmem_cookie = NULL; -err1: - kmem_free(keyentry.kte_memhdl, sizeof (agp_pmem_handle_t)); - keyentry.kte_memhdl = NULL; - - return (NULL); - -} - -/* * agp_alloc_kmem() * * Description: * This function allocates physical memory for userland applications - * by ddi interfaces. This function can only be called to allocate + * by ddi interfaces. This function can also be called to allocate * small phsyical contiguous pages, usually tens of kilobytes. * * Arguments: @@ -2070,7 +1972,7 @@ * memory available */ static keytable_ent_t * -agp_alloc_kmem(agpgart_softstate_t *softstate, size_t length) +agp_alloc_kmem(agpgart_softstate_t *softstate, size_t length, int type) { keytable_ent_t keyentry; keytable_ent_t *entryp; @@ -2081,12 +1983,15 @@ bzero(&keyentry, sizeof (keytable_ent_t)); keyentry.kte_pages = AGP_BYTES2PAGES(length); - keyentry.kte_type = AGP_PHYSICAL; + keyentry.kte_type = type; /* * Set dma_attr_sgllen to assure contiguous physical pages */ - agpgart_dma_attr.dma_attr_sgllen = 1; + if (type == AGP_PHYSICAL) + agpgart_dma_attr.dma_attr_sgllen = 1; + else + agpgart_dma_attr.dma_attr_sgllen = keyentry.kte_pages; /* 4k size pages */ keyentry.kte_memhdl = kmem_zalloc(sizeof (agp_kmem_handle_t), KM_SLEEP); @@ -2132,7 +2037,8 @@ */ if ((ret != DDI_DMA_MAPPED) || - (KMEMP(keyentry.kte_memhdl)->kmem_cookies_num != 1)) { + ((agpgart_dma_attr.dma_attr_sgllen == 1) && + (KMEMP(keyentry.kte_memhdl)->kmem_cookies_num != 1))) { AGPDB_PRINT2((CE_WARN, "agp_alloc_kmem: can not alloc physical memory properly")); goto err2; @@ -2152,6 +2058,9 @@ ASSERT(!agp_check_pfns(softstate->asoft_devreg.agprd_arctype, keyentry.kte_pfnarray, keyentry.kte_pages)); + if (agp_check_pfns(softstate->asoft_devreg.agprd_arctype, + keyentry.kte_pfnarray, keyentry.kte_pages)) + goto err1; entryp = agp_fill_empty_keyent(softstate, &keyentry); if (!entryp) { AGPDB_PRINT2((CE_WARN, @@ -2199,7 +2108,7 @@ * * Returns: * NULL Invalid memory type or can not allocate memory - * Keytable entry pointer returned by agp_alloc_kmem or agp_alloc_pmem + * Keytable entry pointer returned by agp_alloc_kmem */ static keytable_ent_t * agp_alloc_mem(agpgart_softstate_t *st, size_t length, int type) @@ -2216,9 +2125,8 @@ switch (type) { case AGP_NORMAL: - return (agp_alloc_pmem(st, length, type)); case AGP_PHYSICAL: - return (agp_alloc_kmem(st, length)); + return (agp_alloc_kmem(st, length, type)); default: return (NULL); } @@ -3249,11 +3157,22 @@ switch (mementry->kte_type) { case AGP_NORMAL: - status = devmap_pmem_setup(cookie, softstate->asoft_dip, - &agp_devmap_cb, - PMEMP(mementry->kte_memhdl)->pmem_cookie, local_offset, - len, PROT_ALL, (DEVMAP_DEFAULTS|IOMEM_DATA_UC_WR_COMBINE), - &mem_dev_acc_attr); + if (PMEMP(mementry->kte_memhdl)->pmem_cookie) { + status = devmap_pmem_setup(cookie, + softstate->asoft_dip, + &agp_devmap_cb, + PMEMP(mementry->kte_memhdl)->pmem_cookie, + local_offset, + len, PROT_ALL, + (DEVMAP_DEFAULTS|IOMEM_DATA_UC_WR_COMBINE), + &mem_dev_acc_attr); + } else { + AGPDB_PRINT2((CE_WARN, + "agpgart_devmap: not a valid memory type")); + return (EINVAL); + + } + break; default: AGPDB_PRINT2((CE_WARN,