Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/sparc64/sparc64 - fix corner case bugs around the s...



details:   https://anonhg.NetBSD.org/src/rev/4f07b6e6fbb4
branches:  trunk
changeset: 749758:4f07b6e6fbb4
user:      nakayama <nakayama%NetBSD.org@localhost>
date:      Mon Dec 07 11:28:37 2009 +0000

description:
- fix corner case bugs around the segment offsets.
- make sure that on error condition we return "no valid mappings".

diffstat:

 sys/arch/sparc64/sparc64/machdep.c |  38 +++++++++++++++++++++++++++-----------
 1 files changed, 27 insertions(+), 11 deletions(-)

diffs (108 lines):

diff -r cab3a4a4a06b -r 4f07b6e6fbb4 sys/arch/sparc64/sparc64/machdep.c
--- a/sys/arch/sparc64/sparc64/machdep.c        Mon Dec 07 11:24:30 2009 +0000
+++ b/sys/arch/sparc64/sparc64/machdep.c        Mon Dec 07 11:28:37 2009 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: machdep.c,v 1.249 2009/12/02 10:18:42 nakayama Exp $ */
+/*     $NetBSD: machdep.c,v 1.250 2009/12/07 11:28:37 nakayama Exp $ */
 
 /*-
  * Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc.
@@ -71,7 +71,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.249 2009/12/02 10:18:42 nakayama Exp $");
+__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.250 2009/12/07 11:28:37 nakayama Exp $");
 
 #include "opt_ddb.h"
 #include "opt_multiprocessor.h"
@@ -1037,7 +1037,6 @@
        /*
         * We always use just one segment.
         */
-       map->dm_mapsize = buflen;
        i = 0;
        map->dm_segs[i].ds_addr = 0UL;
        map->dm_segs[i].ds_len = 0;
@@ -1049,23 +1048,24 @@
                incr = min(sgsize, incr);
 
                (void) pmap_extract(pmap_kernel(), vaddr, &pa);
-               sgsize -= incr;
-               vaddr += incr;
                if (map->dm_segs[i].ds_len == 0)
                        map->dm_segs[i].ds_addr = pa;
                if (pa == (map->dm_segs[i].ds_addr + map->dm_segs[i].ds_len)
                    && ((map->dm_segs[i].ds_len + incr) <= map->dm_maxsegsz)) {
                        /* Hey, waddyaknow, they're contiguous */
                        map->dm_segs[i].ds_len += incr;
-                       incr = PAGE_SIZE;
-                       continue;
+               } else {
+                       if (++i >= map->_dm_segcnt)
+                               return (EFBIG);
+                       map->dm_segs[i].ds_addr = pa;
+                       map->dm_segs[i].ds_len = incr;
                }
-               if (++i >= map->_dm_segcnt)
-                       return (EFBIG);
-               map->dm_segs[i].ds_addr = pa;
-               map->dm_segs[i].ds_len = incr = PAGE_SIZE;
+               sgsize -= incr;
+               vaddr += incr;
+               incr = PAGE_SIZE;
        }
        map->dm_nsegs = i + 1;
+       map->dm_mapsize = buflen;
        /* Mapping is bus dependent */
        return (0);
 }
@@ -1081,8 +1081,15 @@
        int i;
        size_t len;
 
+       /*
+        * Make sure that on error condition we return "no valid mappings".
+        */
+       map->dm_nsegs = 0;
        KASSERT(map->dm_maxsegsz <= map->_dm_maxmaxsegsz);
 
+       if (m->m_pkthdr.len > map->_dm_size)
+               return EINVAL;
+
        /* Record mbuf for *_unload */
        map->_dm_type = _DM_TYPE_MBUF;
        map->_dm_source = (void *)m;
@@ -1194,6 +1201,10 @@
        struct proc *p = uio->uio_lwp->l_proc;
        struct pmap *pm;
 
+       /*
+        * Make sure that on error condition we return "no valid mappings".
+        */
+       map->dm_nsegs = 0;
        KASSERT(map->dm_maxsegsz <= map->_dm_maxmaxsegsz);
 
        if (uio->uio_segflg == UIO_USERSPACE) {
@@ -1346,16 +1357,21 @@
 
                                if (offset < PAGE_SIZE) {
                                        start = VM_PAGE_TO_PHYS(pg) + offset;
+                                       size -= offset;
                                        if (size > len)
                                                size = len;
                                        cache_flush_phys(start, size, 0);
                                        len -= size;
+                                       if (len == 0)
+                                               goto done;
+                                       offset = 0;
                                        continue;
                                }
                                offset -= size;
                        }
                }
        }
+ done:
        if (ops & BUS_DMASYNC_POSTWRITE) {
                /* Nothing to do.  Handled by the bus controller. */
        }



Home | Main Index | Thread Index | Old Index