Subject: 1.0 performance patch
To: None <port-sparc@NetBSD.ORG>
From: Paul Kranenburg <pk@cs.few.eur.nl>
List: port-sparc
Date: 03/04/1995 11:23:29
For those of you running NetBSD/sparc 1.0 I've put together a source patch to
avoid cache aliasing, This will improve performance a bit.
This is not an "official" patch; use at your own risk.
NOTE: install /usr/libexec/ld.so first, *before* booting a new kernel.
===================================================================
RCS file: /tmp/CVS/src/gnu/usr.bin/ld/rtld/rtld.c,v
retrieving revision 1.21.2.2
diff -c -r1.21.2.2 rtld.c
*** 1.21.2.2 1994/08/12 08:46:02
--- rtld.c 1995/02/10 10:59:42
***************
*** 479,485 ****
return NULL;
}
! if ((addr = mmap(0, hdr.a_text + hdr.a_data,
PROT_READ|PROT_EXEC,
MAP_COPY, fd, 0)) == (caddr_t)-1) {
(void)close(fd);
--- 479,485 ----
return NULL;
}
! if ((addr = mmap(0, hdr.a_text + hdr.a_data + hdr.a_bss,
PROT_READ|PROT_EXEC,
MAP_COPY, fd, 0)) == (caddr_t)-1) {
(void)close(fd);
===================================================================
RCS file: /tmp/CVS/src/sys/arch/sparc/include/pmap.h,v
retrieving revision 1.5.2.1
diff -c -r1.5.2.1 pmap.h
*** 1.5.2.1 1994/08/17 06:19:34
--- pmap.h 1995/02/09 20:11:33
***************
*** 152,157 ****
--- 152,158 ----
#define PMAP_ACTIVATE(pmap, pcb, iscurproc)
#define PMAP_DEACTIVATE(pmap, pcb)
+ #define PMAP_PREFER(pa, va) pmap_prefer((pa), (va))
/*
* Since PTEs also contain type bits, we have to have some way
===================================================================
RCS file: /tmp/CVS/src/sys/arch/sparc/sparc/pmap.c,v
retrieving revision 1.13.2.2
diff -c -r1.13.2.2 pmap.c
*** 1.13.2.2 1994/10/24 04:22:06
--- pmap.c 1995/02/10 11:03:05
***************
*** 2830,2835 ****
--- 2830,2872 ----
}
/*
+ * Find first virtual address >= va that doesn't cause
+ * a cache alias on physical address pa.
+ */
+ vm_offset_t
+ pmap_prefer(pa, va)
+ register vm_offset_t pa;
+ register vm_offset_t va;
+ {
+ register struct pvlist *pv;
+ register long m, d;
+
+ #if 0
+ if (cputyp == CPU_SUN4M)
+ /* does the sun4m have the cache alias problem? */
+ return va;
+
+ m = CACHE_ALIAS_DIST;
+ #endif
+ m = 0x10000;
+
+ if (!managed(pa))
+ return va;
+
+ pv = pvhead(pa);
+ if (pv->pv_pmap == NULL)
+ /* Unusable, tell caller to try another one */
+ return (vm_offset_t)-1;
+
+ d = (long)(pv->pv_va & (m - 1)) - (long)(va & (m - 1));
+ if (d < 0)
+ va += m;
+ va += d;
+
+ return va;
+ }
+
+ /*
* For /dev/mem.
*/
int
===================================================================
RCS file: /tmp/CVS/src/sys/vm/vm_mmap.c,v
retrieving revision 1.31.2.1
diff -c -r1.31.2.1 vm_mmap.c
*** 1.31.2.1 1994/09/16 19:33:27
--- vm_mmap.c 1995/02/09 20:10:38
***************
*** 724,731 ****
vm_offset_t off;
/* locate and allocate the target address space */
! rv = vm_map_find(map, NULL, (vm_offset_t)0,
! addr, size, fitit);
if (rv != KERN_SUCCESS) {
vm_object_deallocate(object);
goto out;
--- 724,772 ----
vm_offset_t off;
/* locate and allocate the target address space */
! if (fitit) {
! /*
! * We cannot call vm_map_find() because
! * a proposed address may be vetoed by
! * the pmap module.
! * So we look for space ourselves, validate
! * it and insert it into the map.
! */
! vm_map_lock(map);
! again:
! if (vm_map_findspace(map, *addr, size,
! addr) == 1) {
! rv = KERN_NO_SPACE;
! } else {
! vm_object_prefer(object, foff, addr);
! rv = vm_map_insert(map, NULL,
! (vm_offset_t)0,
! *addr, *addr+size);
! if (rv == KERN_NO_SPACE)
! /*
! * Modified address didn't fit
! * after all, the gap must
! * have been to small.
! */
! goto again;
! }
! vm_map_unlock(map);
! } else {
! rv = vm_map_find(map, NULL, (vm_offset_t)0,
! addr, size, 0);
!
! /*
! * Check against PMAP preferred address. If
! * there's a mismatch, these pages should not
! * be shared with others. <howto?>
! */
! if (rv == KERN_SUCCESS) {
! vm_offset_t paddr = *addr;
! vm_object_prefer(object, foff, &paddr);
! if (paddr != *addr)
! printf("vm_mmap: pmap botch!\n");
! }
! }
if (rv != KERN_SUCCESS) {
vm_object_deallocate(object);
goto out;
===================================================================
RCS file: /tmp/CVS/src/sys/vm/vm_object.c,v
retrieving revision 1.24.2.1
diff -c -r1.24.2.1 vm_object.c
*** 1.24.2.1 1994/10/06 05:05:13
--- vm_object.c 1995/02/09 20:08:48
***************
*** 1403,1408 ****
--- 1403,1448 ----
}
/*
+ * vm_object_prefer:
+ *
+ * Return optimal virtual address for new mapping of this object.
+ *
+ * The object must *not* be locked.
+ */
+ void
+ vm_object_prefer(object, offset, addr)
+ register vm_object_t object;
+ register vm_offset_t offset;
+ register vm_offset_t *addr;
+ {
+ register vm_page_t p;
+ register vm_offset_t paddr;
+
+ if (object == NULL)
+ return;
+
+ #ifdef PMAP_PREFER
+ vm_object_lock(object);
+ /*
+ * Look for the first page that the pmap layer has something
+ * to say about. Since an object maps a contiguous range of
+ * virutal addresses, this will determine the preferred origin
+ * of the proposed mapping.
+ */
+ for (p = object->memq.tqh_first; p != NULL; p = p->listq.tqe_next) {
+ if (p->flags & (PG_FAKE | PG_FICTITIOUS))
+ continue;
+ paddr = PMAP_PREFER(VM_PAGE_TO_PHYS(p), *addr+p->offset-offset);
+ if (paddr == (vm_offset_t)-1)
+ continue;
+ *addr = paddr - (p->offset - offset);
+ break;
+ }
+ vm_object_unlock(object);
+ #endif
+ }
+
+ /*
* vm_object_print: [ debug ]
*/
void