Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 9 Mar 2009 15:50:47 GMT
From:      Arnar Mar Sig <antab@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 158933 for review
Message-ID:  <200903091550.n29Fol9N009785@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=158933

Change 158933 by antab@antab_farm on 2009/03/09 15:49:56

	Cleanup and bugfix in pmap and related code. PD_MASK and PT_MASK wrongly define causing overlappig in pmap_pte.
	Add updated version of cfi_disk from Sam Leffler.

Affected files ...

.. //depot/projects/avr32/src/sys/avr32/avr32/machdep.c#10 edit
.. //depot/projects/avr32/src/sys/avr32/avr32/pmap.c#13 edit
.. //depot/projects/avr32/src/sys/avr32/avr32/tlb.c#4 edit
.. //depot/projects/avr32/src/sys/avr32/include/atomic.h#6 edit
.. //depot/projects/avr32/src/sys/avr32/include/pmap.h#6 edit
.. //depot/projects/avr32/src/sys/avr32/include/pte.h#5 edit
.. //depot/projects/avr32/src/sys/avr32/include/tlb.h#4 edit
.. //depot/projects/avr32/src/sys/dev/cfi/cfi_disk.c#2 edit

Differences ...

==== //depot/projects/avr32/src/sys/avr32/avr32/machdep.c#10 (text+ko) ====

@@ -61,6 +61,7 @@
 #include <machine/cache.h>
 #include <machine/cpu.h>
 #include <machine/reg.h>
+#include <machine/reg_sys.h>
 #include <machine/pcb.h>
 #include <machine/frame.h>
 #include <machine/uboot.h>
@@ -282,8 +283,7 @@
 u_int32_t
 get_cyclecount(void)
 {
-	avr32_impl();
-	return (0);
+	return sysreg_read(COUNT);
 }
 
 int

==== //depot/projects/avr32/src/sys/avr32/avr32/pmap.c#13 (text+ko) ====

@@ -15,6 +15,7 @@
 #include <sys/sched.h>
 #include <sys/lock.h>
 #include <sys/mutex.h>
+#include <sys/sysctl.h>
 
 #include <vm/vm.h>
 #include <vm/uma.h>
@@ -31,6 +32,7 @@
 #include <machine/reg.h>
 #include <machine/reg_sys.h>
 #include <machine/trap.h>
+#include <machine/cache.h>
 #include <machine/debug.h>
 
 // antab: What does this stand for?
@@ -42,15 +44,14 @@
 static vm_page_t _pmap_allocpte(pmap_t pmap, unsigned ptepindex, int flags);
 static int page_is_managed(vm_offset_t pa);
 static void pmap_insert_entry(pmap_t pmap, vm_offset_t va, vm_page_t mpte, vm_page_t m, boolean_t wired);
-static void pmap_remove_entry(struct pmap *pmap, vm_page_t m, vm_offset_t va);
+static void pmap_remove_entry(pmap_t pmap, vm_page_t m, vm_offset_t va);
 static void free_pv_entry(pv_entry_t pv);
 static pv_entry_t get_pv_entry(void);
 static int pmap_remove_pte(struct pmap *pmap, pt_entry_t *ptq, vm_offset_t va);
 static void pmap_remove_page(struct pmap *pmap, vm_offset_t va);
 
 
-static struct pmap kernel_pmap_store;
-pmap_t kernel_pmap;						/**< Kernel pmap */
+struct pmap kernel_pmap_store;
 vm_offset_t kernel_vm_end = 0;
 vm_offset_t virtual_avail;      /* VA of first avail page (after kernel bss) */
 vm_offset_t virtual_end;        /* VA of last avail page (end of kernel AS) */
@@ -61,8 +62,18 @@
 static uma_zone_t pvzone;
 static struct vm_object pvzone_obj;
 static int pv_entry_count = 0, pv_entry_max = 0, pv_entry_high_water = 0;
+static int shpgperproc = PMAP_SHPGPERPROC;
 
+/**
+ * Sysctl for tuneing
+ */
+// i386 and amd64 are using _vm_pmap but i cant find the declare for it..
+SYSCTL_INT(_vm, OID_AUTO, pv_entry_max, CTLFLAG_RD, &pv_entry_max, 0,
+	"Max number of PV entries");
+SYSCTL_INT(_vm, OID_AUTO, shpgperproc, CTLFLAG_RD, &shpgperproc, 0,
+	"Page share factor per proc");
 
+
 pt_entry_t
 *pmap_pte(pmap_t pmap, vm_offset_t va)
 {
@@ -86,7 +97,6 @@
 	virtual_end = VM_MAX_KERNEL_ADDRESS;
 
 	/* Setup kernel pmap */
-	kernel_pmap = &kernel_pmap_store;
 	PMAP_LOCK_INIT(kernel_pmap);
 	kernel_pmap->pm_active = ~0;
 	kernel_pmap->pm_asid = 0;
@@ -137,10 +147,19 @@
 void
 pmap_init(void)
 {
+	/*
+	 * Initialize the address space (zone) for the pv entries.  Set a
+	 * high water mark so that the system can recover from excessive
+	 * numbers of pv entries.
+	 */
 	pvzone = uma_zcreate("PV_ENTRY", sizeof(struct pv_entry), NULL, NULL,
 		NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_VM | UMA_ZONE_NOFREE);
-	pv_entry_max = PMAP_SHPGPERPROC * maxproc + cnt.v_page_count;
+
+	TUNABLE_INT_FETCH("vm.pmap.shpgperproc", &shpgperproc);
+	TUNABLE_INT_FETCH("vm.pmap.pv_entries", &pv_entry_max);
+	pv_entry_max = shpgperproc * maxproc + cnt.v_page_count;
 	pv_entry_high_water = 9 * (pv_entry_max / 10);
+
 	uma_zone_set_obj(pvzone, &pvzone_obj, pv_entry_max);
 }
 
@@ -200,13 +219,16 @@
 void
 pmap_activate(struct thread *td)
 {
-        struct proc *p;
-	pmap_t pmap;
+	pmap_t pmap, oldpmap;
+
+	pmap = vmspace_pmap(td->td_proc->p_vmspace);
+	oldpmap = PCPU_GET(curpmap);
 
-	p = td->td_proc;
-        pmap = vmspace_pmap(p->p_vmspace);
+	oldpmap->pm_active = 0;
+	pmap->pm_active = 1;
 
-        pmap_asid_alloc(pmap);
+	pmap_asid_alloc(pmap);
+	/* XXX: Set tlbear here? */
 	PCPU_SET(curpmap, pmap);
 }
 
@@ -220,10 +242,28 @@
 void
 pmap_clear_modify(vm_page_t m)
 {
+	pv_entry_t pv;
+	pt_entry_t *pte;
+
+	if (m->flags & PG_FICTITIOUS) {
+                return;
+	}
+
 	mtx_assert(&vm_page_queue_mtx, MA_OWNED);
 	if (m->md.pv_flags & PV_TABLE_MOD) {
-		avr32_impl();
-		//pmap_changebit(m, PTE_M, FALSE);	TODO
+		panic("Need to look more into this");
+		/*
+		 * Loop over all current mappings
+		 */
+		TAILQ_FOREACH(pv, &m->md.pv_list, pv_list) {
+			PMAP_LOCK(pv->pv_pmap);
+
+			pte = pmap_pte(pv->pv_pmap, pv->pv_va);
+			KASSERT((pte != NULL || pte != 0), ("Mapped page not found"));
+			*pte &= ~PTE_DIRTY;
+
+			PMAP_UNLOCK(pv->pv_pmap);
+		}
 		m->md.pv_flags &= ~PV_TABLE_MOD;
 	}
 }
@@ -291,6 +331,8 @@
 		return (AVR32_P1_TO_PHYS(va));
 	else if ((va & AVR32_SEG_MASK) == AVR32_SEG_P2)
 		return (AVR32_P2_TO_PHYS(va));
+	else if ((va & AVR32_SEG_MASK) == AVR32_SEG_P4)
+		return (AVR32_P2_TO_PHYS(va));
 
 	return (pmap_extract(kernel_pmap, va));
 }
@@ -413,6 +455,7 @@
 	vm_page_lock_queues();
 	PMAP_LOCK(pmap);
 
+	va &= ~PAGE_MASK;
 	mpte = NULL;
 	if (va < VM_MAXUSER_ADDRESS) {
 		mpte = pmap_allocpte(pmap, va, M_WAITOK);
@@ -491,13 +534,14 @@
 update:
 	newpte = 0;
 	pfn_set(newpte, pa);
-	if (access & VM_PROT_READ) {
+	if (prot & VM_PROT_READ) {
 		newpte |= PTE_PERM_READ;
 	}
-	if (access & VM_PROT_WRITE) {
+	if (prot & VM_PROT_WRITE) {
 		newpte |= PTE_PERM_WRITE;
+		vm_page_flag_set(m, PG_WRITEABLE);
 	}
-	if (access & VM_PROT_EXECUTE) {
+	if (prot & VM_PROT_EXECUTE) {
 		newpte |= PTE_PERM_EXECUTE;
 	}
 
@@ -530,6 +574,17 @@
 	}
 	tlb_update_entry(pmap, va, newpte);
 
+	/*
+	 * XXX: Sync I & D caches for executable pages.  Do this only if the the
+	 * target pmap belongs to the current process.  Otherwise, an
+	 * unresolvable TLB miss may occur.
+	 */
+	if (pmap == kernel_pmap && (pmap == &curproc->p_vmspace->vm_pmap) &&
+		(prot & VM_PROT_EXECUTE)) {
+		avr32_icache_sync_range(va, PAGE_SIZE);
+		avr32_dcache_wbinv_range(va, PAGE_SIZE);
+	}
+
 	vm_page_unlock_queues();
 	PMAP_UNLOCK(pmap);
 }
@@ -653,8 +708,9 @@
 	vm_offset_t va;
 	pt_entry_t *pte;
 
-	if ((m->flags & PG_WRITEABLE) == 0)
-	return;
+	if ((m->flags & PG_WRITEABLE) == 0) {
+		return;
+	}
 
 	/*
 	 * Loop over all current mappings setting/clearing as appropos.
@@ -881,11 +937,11 @@
 		page->wire_count++;
 	} else {
 		page = _pmap_allocpte(pmap, pdindex, flags);
-		if (!page && flags & M_WAITOK) {
+		if (page == NULL && flags & M_WAITOK) {
 			goto retry;
 		}
 	}
-	return page;
+	return (page);
 }
 
 static int
@@ -922,7 +978,7 @@
 }
 
 static void
-pmap_remove_entry(struct pmap *pmap, vm_page_t m, vm_offset_t va)
+pmap_remove_entry(pmap_t pmap, vm_page_t m, vm_offset_t va)
 {
 	pv_entry_t pv;
 
@@ -1005,9 +1061,9 @@
 		for (p = 0; p < 1024; p++) {
 			ent = base + p;
 			if (*ent) {
-				printf("0x%x -> 0x%x\n",
+				printf("0x%08x -> 0x%08x (flags 0x%08x)\n",
 					(i << PD_SHIFT) | (p << PT_SHIFT),
-					*ent);
+					*ent & ~PAGE_MASK, *ent & PAGE_MASK);
 			}
 		}
 	}

==== //depot/projects/avr32/src/sys/avr32/avr32/tlb.c#4 (text+ko) ====

@@ -98,6 +98,19 @@
 	}
 }
 
+void
+tlb_invalidate_range(pmap_t pmap, vm_offset_t start_va, vm_offset_t end_va)
+{
+	/*
+	 * Look more into this. Maybe its batter to loop thru the tlb
+	 * and invalidate entries that are within start_va and end_va,
+	 * instead of trying to invalidate every page between them.
+	 */
+	for (; start_va < end_va; start_va += PAGE_SIZE) {
+		tlb_remove_entry(pmap, start_va);
+	}
+}
+
 static void
 tlb_dump_entry(uint32_t index, uint32_t tlbehi, uint32_t tlbelo)
 {

==== //depot/projects/avr32/src/sys/avr32/include/atomic.h#6 (text+ko) ====

@@ -171,11 +171,21 @@
 }
 
 static __inline uint32_t
-atomic_readandclear_32(volatile u_int32_t *p)
+atomic_readandclear_32(volatile u_int32_t *address)
 {
-	avr32_impl();
-	while(1);
-	return 0;
+	uint32_t ret, tmp;
+	__asm __volatile(
+		"1:"
+		"ssrf	5\n"
+		"ld.w	%0, %3\n"
+		"mov	%2, 0\n"
+		"stcond	%1, %2\n"
+		"brne	1b\n"
+		: "=&r"(ret), "=m"(*address), "=r" (tmp)
+		: "m"(*address)
+		: "cc", "memory");
+
+	return (ret);
 }
 
 static __inline int

==== //depot/projects/avr32/src/sys/avr32/include/pmap.h#6 (text+ko) ====

@@ -134,7 +134,8 @@
 } *pmap_t;
 
 #ifdef _KERNEL
-#define pmap_kernel() kernel_pmap
+extern struct pmap	kernel_pmap_store;
+#define kernel_pmap	(&kernel_pmap_store)
 
 #define PMAP_LOCK(pmap)     mtx_lock(&(pmap)->pm_mtx)
 #define PMAP_LOCK_ASSERT(pmap, type)    mtx_assert(&(pmap)->pm_mtx, (type))
@@ -172,8 +173,6 @@
 
 #define	pmap_page_is_mapped(m)	(!TAILQ_EMPTY(&(m)->md.pv_list))
 
-//extern	struct segtab * segtab_active;
-extern	pmap_t kernel_pmap;
 extern	vm_offset_t phys_avail[];
 extern	vm_offset_t virtual_avail;
 extern	vm_offset_t virtual_end;

==== //depot/projects/avr32/src/sys/avr32/include/pte.h#5 (text+ko) ====

@@ -37,8 +37,8 @@
 typedef	uint32_t		pt_entry_t;	/* page table entry (TLBELO register) */
 #endif
 
-#define PD_MASK			0xfff00000	/* Bits used to index into page dir */
-#define PT_MASK			0x000ff000	/* Bits used to index into page table */
+#define PD_MASK			0xffe00000	/* Bits used to index into page dir */
+#define PT_MASK			0x003ff000	/* Bits used to index into page table */
 #define PD_SHIFT		22
 #define PT_SHIFT		12
 

==== //depot/projects/avr32/src/sys/avr32/include/tlb.h#4 (text+ko) ====

@@ -35,6 +35,7 @@
 void tlb_flush(void);		/* Invalid all TLB entries */
 void tlb_update_entry(pmap_t, vm_offset_t, pt_entry_t);
 void tlb_remove_entry(pmap_t, vm_offset_t);
+void tlb_invalidate_range(pmap_t, vm_offset_t, vm_offset_t);
 
 #endif /* !_MACHINE_TLB_H_ */
 

==== //depot/projects/avr32/src/sys/dev/cfi/cfi_disk.c#2 (text+ko) ====

@@ -32,10 +32,13 @@
 #include <sys/bus.h>
 #include <sys/conf.h>
 #include <sys/kernel.h>
-#include <sys/malloc.h>
+#include <sys/malloc.h>   
+#include <sys/lock.h>
+#include <sys/mutex.h>
 #include <sys/module.h>
 #include <sys/rman.h>
 #include <sys/sysctl.h>
+#include <sys/taskqueue.h>
 
 #include <machine/bus.h>
 
@@ -48,6 +51,10 @@
 	struct disk	*disk;
 	int		flags;
 #define	CFI_DISK_OPEN	0x0001
+	struct bio_queue_head bioq;	/* bio queue */
+	struct mtx	qlock;		/* bioq lock */
+	struct taskqueue *tq;		/* private task queue for i/o request */
+	struct task	iotask;		/* i/o processing */
 };
 
 #define	CFI_DISK_SECSIZE	512
@@ -56,6 +63,7 @@
 static int cfi_disk_detach(device_t);
 static int cfi_disk_open(struct disk *);
 static int cfi_disk_close(struct disk *);
+static void cfi_io_proc(void *, int);
 static void cfi_disk_strategy(struct bio *);
 static int cfi_disk_ioctl(struct disk *, u_long, void *, int, struct thread *);
 
@@ -98,6 +106,15 @@
 	sc->disk->d_drv1 = sc;
 	disk_create(sc->disk, DISK_VERSION);
 
+	mtx_init(&sc->qlock, "CFID I/O lock", NULL, MTX_DEF);
+	bioq_init(&sc->bioq);
+
+	sc->tq = taskqueue_create("cfid_taskq", M_NOWAIT,
+		taskqueue_thread_enqueue, &sc->tq);
+	taskqueue_start_threads(&sc->tq, 1, PI_DISK, "cfid taskq");
+
+	TASK_INIT(&sc->iotask, 0, cfi_io_proc, sc);
+
 	return 0;
 }
 
@@ -108,7 +125,10 @@
 
 	if (sc->flags & CFI_DISK_OPEN)
 		return EBUSY;
+	taskqueue_free(sc->tq);
+	/* XXX drain bioq */
 	disk_destroy(sc->disk);
+	mtx_destroy(&sc->qlock);
 	return 0;
 }
 
@@ -224,10 +244,34 @@
 }
 
 static void
+cfi_io_proc(void *arg, int pending)
+{
+	struct cfi_disk_softc *sc = arg;
+	struct cfi_softc *cfi = sc->parent;
+	struct bio *bp;
+
+	for (;;) {
+		mtx_lock(&sc->qlock);
+		bp = bioq_takefirst(&sc->bioq);
+		mtx_unlock(&sc->qlock);
+		if (bp == NULL)
+			break;
+
+		switch (bp->bio_cmd) {
+		case BIO_READ:
+			cfi_disk_read(cfi, bp);
+			break;
+		case BIO_WRITE:
+			cfi_disk_write(cfi, bp);
+			break;
+		}
+	}
+}
+
+static void
 cfi_disk_strategy(struct bio *bp)
 {
 	struct cfi_disk_softc *sc = bp->bio_disk->d_drv1;
-	struct cfi_softc *cfi = sc->parent;
 
 	if (sc == NULL)
 		goto invalid;
@@ -238,10 +282,12 @@
 	}
 	switch (bp->bio_cmd) {
 	case BIO_READ:
-		cfi_disk_read(cfi, bp);
-		return;
 	case BIO_WRITE:
-		cfi_disk_write(cfi, bp);
+		mtx_lock(&sc->qlock);
+		/* no value in sorting requests? */
+		bioq_insert_tail(&sc->bioq, bp);
+		mtx_unlock(&sc->qlock);
+		taskqueue_enqueue(sc->tq, &sc->iotask);
 		return;
 	}
 	/* fall thru... */
@@ -271,4 +317,3 @@
 	sizeof(struct cfi_disk_softc),
 };
 DRIVER_MODULE(cfid, cfi, cfi_disk_driver, cfi_diskclass, 0, NULL);
-



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200903091550.n29Fol9N009785>