Subject: Re: upgrade to 1.0 [non-contiguous memory diffs]
To: Tim Newsham <newsham@uhunix.uhcc.Hawaii.Edu>
From: Michael L. Hitch <osymh@gemini.oscs.montana.edu>
List: amiga-dev
Date: 08/10/1994 21:32:28
On Aug  8,  7:16pm, Tim Newsham wrote:
> 
> (btw.. can I get diffs for non-contig memory handling with the new
> kernels from someone who has already got it up and running?)
> 

  Here's a set of diffs for the non-contiguous memory support I'm
working with.  It's based on Tim's original changes, but I've done
some things differently.  Non-contiguous memory support is enabled
with the config option MEMORY_NONCONTIG.  The Zorro II memory usage
has been modified so that DMA bounce buffers can still be used.  The
flag use_z2_mem now specifies the number of MAXPHYS segments of
Zorro II memory to reserve for DMA bounce buffers.  The rest of the
Zorro II memory is then available to be used as pageable memory.
The first memory segment is the memory segment that NetBSD was loaded
into, irregardless of it's position in the memory list.  [At least
that's the way it should work.  On all my systems, the largest segment
is also the highest priority and the first entry in the memory list, so
I haven't verified that this works the way I intended it to.]

  A few comments about these diffs:

  The machdep.c changes also include some initial support for the
A4091 SCSI board.  These will need to be removed after applying the
diffs [I was too lazy to make a diff from a file without these
changes].

  The code that sets up the segments currently only allocates two
segments, and it will skip the A4000 motherboard memory.  [That's so
the second segment is allocated from the Zorro II memory, which has
a nasty little problem].

  I've had some trouble getting the Zorro II memory to work on my
A4000.  I get various panics in the pmap routines.  It works fine
if the second segment is the A4000 motherboard memory, and the
Zorro II memory works fine on my A2000/Zeus system.  I haven't had
the time to try and figure out what is going on.  [This is why the
code currently allocates two segments and skips the motherboard
segment - the diffs reflect the configuration that fails on my system.]

Michael

diff -cr /mnt/src/sys/arch/amiga/amiga/amiga_init.c /sys/arch/amiga/amiga/amiga_init.c
*** /mnt/src/sys/arch/amiga/amiga/amiga_init.c	Thu Jun 30 10:34:03 1994
--- /sys/arch/amiga/amiga/amiga_init.c	Sun Jul 31 11:38:34 1994
***************
*** 168,174 ****
  	 * Get ZorroII (16-bit) memory if there is any and it's not where the
  	 * kernel is loaded.
  	 */
! 	if (memlist->m_nseg > 0 && memlist->m_nseg < 16) {
  		struct boot_memseg *sp, *esp;
  
  		sp = memlist->m_seg;
--- 168,174 ----
  	 * Get ZorroII (16-bit) memory if there is any and it's not where the
  	 * kernel is loaded.
  	 */
! 	if (memlist->m_nseg > 0 && memlist->m_nseg < 16 && use_z2_mem) {
  		struct boot_memseg *sp, *esp;
  
  		sp = memlist->m_seg;
***************
*** 179,187 ****
  				continue;
  			if (sp->ms_start == fphystart)
  				continue;
! 			z2mem_start = sp->ms_start;
! 			NZTWOMEMPG = sp->ms_size / NBPG;
! 			z2mem_end = z2mem_start + sp->ms_size;
  			break;
  		}
  	}
--- 179,191 ----
  				continue;
  			if (sp->ms_start == fphystart)
  				continue;
! 			z2mem_end = sp->ms_start + sp->ms_size;
! 			z2mem_start = z2mem_end - MAXPHYS * use_z2_mem;
! 			NZTWOMEMPG = (z2mem_end - z2mem_start) / NBPG;
! 			if ((z2mem_end - z2mem_start) > sp->ms_size) {
! 				NZTWOMEMPG = sp->ms_size / NBPG;
! 				z2mem_start = z2mem_end - sp->ms_size;
! 			}
  			break;
  		}
  	}
diff -cr /mnt/src/sys/arch/amiga/amiga/machdep.c /sys/arch/amiga/amiga/machdep.c
*** /mnt/src/sys/arch/amiga/amiga/machdep.c	Mon Jul 18 10:49:13 1994
--- /sys/arch/amiga/amiga/machdep.c	Tue Aug  2 21:15:44 1994
***************
*** 109,117 ****
--- 109,119 ----
  #include "ser.h"
  #include "idesc.h"
  #include "ether.h"
+ #include "afsc.h"
  
  /* vm_map_t buffer_map; */
  extern vm_offset_t avail_end;
+ extern vm_offset_t avail_start;
  
  /*
   * Declare these as initialized data so we can patch them.
***************
*** 143,149 ****
  /* the following is used externally (sysctl_hw) */
  char machine[] = "amiga";
   
- 
  #ifdef COMPAT_SUNOS
  void sun_sendsig ();
  #endif
--- 145,150 ----
***************
*** 200,205 ****
--- 201,213 ----
  #endif
  	vm_offset_t minaddr, maxaddr;
  	vm_size_t size;
+ #ifdef MACHINE_NONCONTIG
+ 	extern struct {
+ 		vm_offset_t start;
+ 		vm_offset_t end;
+ 		int first_page;
+ 	} phys_segs[16];
+ #endif
  
  	/*
  	 * Initialize error message buffer (at end of core).
***************
*** 383,388 ****
--- 391,404 ----
  			printf("memory segment %d at %08lx size %08lx\n", i,
  			    memlist->m_seg[i].ms_start, 
  			    memlist->m_seg[i].ms_size);
+ #ifdef MACHINE_NONCONTIG
+ 	printf ("Physical memory segments:\n");
+ 	for (i = 0; phys_segs[i].start; ++i)
+ 		printf ("Physical segment %d at %08lx size %d pages %d\n", i,
+ 		    phys_segs[i].start,
+ 		    (phys_segs[i].end - phys_segs[i].start) / NBPG,
+ 		    phys_segs[i].first_page);
+ #endif
  	/*
  	 * Set up CPU-specific registers, cache, etc.
  	 */
***************
*** 1182,1187 ****
--- 1198,1204 ----
  {
  	printf("unexpected trap (vector offset %x) from %x\n",
  	       evec & 0xFFF, pc);
+ /*XXX*/	panic("straytrap");
  }
  
  int	*nofault;
***************
*** 1418,1423 ****
--- 1435,1444 ----
  		if (wesc_dmaintr())
  			goto intports_done;
  #endif
+ #if NAFSC > 0
+ 		if (afsc_dmaintr())
+ 			goto intports_done;
+ #endif
  #if NWSTSC > 0
  		if (wstsc_intr())
  			goto intports_done;
***************
*** 1648,1651 ****
  #endif
  	return(error);
  }
- 
--- 1669,1671 ----
diff -cr /mnt/src/sys/arch/amiga/amiga/pmap.c /sys/arch/amiga/amiga/pmap.c
*** /mnt/src/sys/arch/amiga/amiga/pmap.c	Tue Jun 21 10:20:50 1994
--- /sys/arch/amiga/amiga/pmap.c	Mon Aug  1 22:10:00 1994
***************
*** 85,90 ****
--- 85,91 ----
  #include <machine/pte.h>
  #include <machine/cpu.h>
  #include <machine/vmparam.h>
+ #include <amiga/amiga/memlist.h>
  /*
   * Allocate various and sundry SYSMAPs used in the days of old VM
   * and not yet converted.  XXX.
***************
*** 220,228 ****
--- 221,241 ----
  char		*pmap_attributes;	/* reference and modify bits */
  static int	pmap_ishift;	/* segment table index shift */
  
+ #ifdef MACHINE_NONCONTIG
+ struct physeg {
+ 	vm_offset_t start;
+ 	vm_offset_t end;
+ 	int first_page;
+ } phys_segs[16];
+ 
+ static	vm_offset_t avail_next;
+ static	vm_size_t avail_remaining;
+ #endif
+ 
  boolean_t	pmap_testbit();
  void		pmap_enter_ptpage();
  
+ #define pmap_valid_page(pa)	(pmap_initialized && pmap_page_index(pa) >= 0)
  
  /*
   * All those kernel PT submaps that BSD is so fond of
***************
*** 250,255 ****
--- 263,272 ----
  	extern vm_offset_t maxmem, physmem;
  	vm_offset_t va;
  	u_int *pte;
+ #ifdef MACHINE_NONCONTIG
+ 	int i;
+ 	struct boot_memseg *sp, *esp;
+ #endif
  
  	avail_start = firstaddr;
  	avail_end = maxmem << PGSHIFT;
***************
*** 256,261 ****
--- 273,307 ----
  
  	/* XXX: allow for msgbuf */
  	avail_end -= amiga_round_page(sizeof(struct msgbuf));
+ #ifdef MACHINE_NONCONTIG
+ 	avail_next = avail_start;
+ 	avail_remaining = (avail_end - avail_start) >> PGSHIFT;
+ 	phys_segs[0].start = avail_start;
+ 	phys_segs[0].end = avail_end;
+ 	sp = memlist->m_seg;
+ 	esp = sp + memlist->m_nseg;
+ 	i = 1;
+ 	for (; sp < esp; sp++) {
+ 		if ((sp->ms_attrib & MEMF_FAST) == 0)
+ 			continue;
+ 		if (avail_start >= sp->ms_start && avail_start <
+ 		    sp->ms_start + sp->ms_size)
+ 			continue;
+ 		/* deal with Zorro II memory stolen for DMA bounce buffers */
+ 		phys_segs[i].start = sp->ms_start;
+ 		phys_segs[i].end = sp->ms_start + sp->ms_size;
+ #if 1
+ if (phys_segs[i].end == 0x08000000) continue;	/* skip A4000 motherboard mem */
+ if (phys_segs[i].start == 0x00200000) phys_segs[i].end -= MAXPHYS;
+ #endif
+ 		phys_segs[i].first_page = phys_segs[i - 1].first_page +
+ 		    (phys_segs[i - 1].end - phys_segs[i - 1].start) / NBPG;
+ 		avail_remaining += (phys_segs[i].end - phys_segs[i].start) / NBPG;
+ 		physmem += (phys_segs[i].end - phys_segs[i].start) / NBPG;
+ 		++i;
+ 		break;		/* XXX only two segments for now */
+ 	}
+ #endif
  
  	mem_size = physmem << PGSHIFT;
  	virtual_avail = VM_MIN_KERNEL_ADDRESS + (firstaddr - loadaddr);
***************
*** 345,352 ****
--- 391,402 ----
   *	system needs to map virtual memory.
   */
  void
+ #ifdef MACHINE_NONCONTIG
+ pmap_init()
+ #else
  pmap_init(phys_start, phys_end)
  	vm_offset_t	phys_start, phys_end;
+ #endif
  {
  	extern vm_offset_t amigahwaddr;
  	extern u_int namigahwpg;
***************
*** 357,364 ****
--- 407,418 ----
  
  #ifdef DEBUG
  	if (pmapdebug & PDB_FOLLOW)
+ #ifdef MACHINE_NONCONTIG
+ 		printf("pmap_init(%x, %x)\n", avail_start, avail_end);
+ #else
  		printf("pmap_init(%x, %x)\n", phys_start, phys_end);
  #endif
+ #endif
  	/*
  	 * Now that kernel map has been allocated, we can mark as
  	 * unavailable regions which we have mapped in locore.
***************
*** 401,407 ****
--- 455,471 ----
  	 * Allocate memory for random pmap data structures.  Includes the
  	 * initial segment table, pv_head_table and pmap_attributes.
  	 */
+ #ifdef MACHINE_NONCONTIG
+ 	{
+ 		int i;
+ 		for (npg = 0, i = 0; phys_segs[i].start; ++i)
+ 			npg += atop(phys_segs[i].end - phys_segs[i].start);
+ 	}
+ 	printf ("pmap_init: avail_start %08x phys_segs[0].start %08x npg %d\n",
+ 		avail_start, phys_segs[0].start, npg);
+ #else
  	npg = atop(phys_end - phys_start);
+ #endif
  #ifdef M68040
  	if (cpu040)
  		s = (vm_size_t)AMIGA_040STSIZE * 128 + 
***************
*** 496,506 ****
--- 560,631 ----
  	/*
  	 * Now it is safe to enable pv_table recording.
  	 */
+ #ifdef MACHINE_NONCONTIG
+ 	vm_first_phys = avail_start;
+ 	vm_last_phys = avail_end;
+ #else
  	vm_first_phys = phys_start;
  	vm_last_phys = phys_end;
+ #endif
  	pmap_initialized = TRUE;
  }
  
+ #ifdef MACHINE_NONCONTIG
+ unsigned int
+ pmap_free_pages()
+ {
+ 
+ 	return avail_remaining;
+ }
+ 
+ int
+ pmap_next_page(addrp)
+ 	vm_offset_t *addrp;
+ {
+ 	static int cur_seg = 0;
+ 
+ 	if (phys_segs[cur_seg].start == 0)
+ 		return FALSE;
+ 	if (avail_next == phys_segs[cur_seg].end) {
+ 		avail_next = phys_segs[++cur_seg].start;
+ 		printf ("pmap_next_page: next %08x remain %d\n", avail_next, avail_remaining);
+ 	}
+ 
+ 	if (avail_next == 0)
+ 		return FALSE;
+ 	*addrp = avail_next;
+ 	avail_next += NBPG;
+ 	avail_remaining--;
+ 	return TRUE;
+ }
+ 
+ int
+ pmap_page_index(pa)
+ 	vm_offset_t pa;
+ {
+ 
+ 	struct physeg *sep = &phys_segs[0];
+ 
+ 	while (sep->start) {
+ 		if (pa >= sep->start && pa < sep->end)
+ 			return (amiga_btop(pa - sep->start) + sep->first_page);
+ 		++sep;
+ 	}
+ 	return -1;
+ }
+ 
+ void
+ pmap_virtual_space(startp, endp)
+ 	vm_offset_t	*startp;
+ 	vm_offset_t	*endp;
+ {
+ 	*startp = virtual_avail;
+ 	*endp = virtual_end;
+ }
+ #else
+ #define pmap_page_index(pa) ((pa) >= avail_start && (pa) < avail_end)
+ #endif	/* MACHINE_NONCONTIG */
+ 
  /*
   *	Used to map a range of physical addresses into kernel
   *	virtual address space.
***************
*** 767,773 ****
  		 * Remove from the PV table (raise IPL since we
  		 * may be called at interrupt time).
  		 */
! 		if (pa < vm_first_phys || pa >= vm_last_phys)
  			continue;
  		pv = pa_to_pvh(pa);
  		ste = (int *)0;
--- 892,898 ----
  		 * Remove from the PV table (raise IPL since we
  		 * may be called at interrupt time).
  		 */
! 		if (!pmap_valid_page(pa))
  			continue;
  		pv = pa_to_pvh(pa);
  		ste = (int *)0;
***************
*** 800,807 ****
  				pv = npv;
  			}
  #ifdef DEBUG
! 			if (npv == NULL)
  				panic("pmap_remove: PA not in pv_tab");
  #endif
  			ste = (int *)npv->pv_ptste;
  			ptpmap = npv->pv_ptpmap;
--- 925,934 ----
  				pv = npv;
  			}
  #ifdef DEBUG
! 			if (npv == NULL) {
! printf ("pmap_remove: PA %08x index %d\n", pa, pa_index(pa));
  				panic("pmap_remove: PA not in pv_tab");
+ 			}
  #endif
  			ste = (int *)npv->pv_ptste;
  			ptpmap = npv->pv_ptpmap;
***************
*** 938,944 ****
  	    prot == VM_PROT_NONE && (pmapdebug & PDB_REMOVE))
  		printf("pmap_page_protect(%x, %x)\n", pa, prot);
  #endif
! 	if (pa < vm_first_phys || pa >= vm_last_phys)
  		return;
  
  	switch (prot) {
--- 1065,1071 ----
  	    prot == VM_PROT_NONE && (pmapdebug & PDB_REMOVE))
  		printf("pmap_page_protect(%x, %x)\n", pa, prot);
  #endif
! 	if (!pmap_valid_page(pa))
  		return;
  
  	switch (prot) {
***************
*** 957,963 ****
--- 1084,1096 ----
  #ifdef DEBUG
  			if (!pmap_ste_v(pmap_ste(pv->pv_pmap,pv->pv_va)) ||
  			    pmap_pte_pa(pmap_pte(pv->pv_pmap,pv->pv_va)) != pa)
+ {
+   printf ("pmap_page_protect: va %08x, pmap_ste_v %d pmap_pte_pa %08x/%08x\n",
+     pv->pv_va, pmap_ste_v(pmap_ste(pv->pv_pmap,pv->pv_va)),
+     pmap_pte_pa(pmap_pte(pv->pv_pmap,pv->pv_va)),pa);
+   printf (" pvh %08x pv %08x pv_next %08x\n", pa_to_pvh(pa), pv, pv->pv_next);
  				panic("pmap_page_protect: bad mapping");
+ }
  #endif
  			pmap_remove(pv->pv_pmap, pv->pv_va,
  				    pv->pv_va + PAGE_SIZE);
***************
*** 1164,1170 ****
  	 * Note that we raise IPL while manipulating pv_table
  	 * since pmap_enter can be called at interrupt time.
  	 */
! 	if (pa >= vm_first_phys && pa < vm_last_phys) {
  		register pv_entry_t pv, npv;
  		int s;
  
--- 1297,1303 ----
  	 * Note that we raise IPL while manipulating pv_table
  	 * since pmap_enter can be called at interrupt time.
  	 */
! 	if (pmap_valid_page(pa)) {
  		register pv_entry_t pv, npv;
  		int s;
  
***************
*** 1622,1628 ****
  		if (!pmap_ste_v(pmap_ste(pmap, sva)))
  			return;
  		pa = pmap_pte_pa(pmap_pte(pmap, sva));
! 		if (pa < vm_first_phys || pa >= vm_last_phys)
  			return;
  		pv = pa_to_pvh(pa);
  		if (pv->pv_ptste == NULL)
--- 1755,1761 ----
  		if (!pmap_ste_v(pmap_ste(pmap, sva)))
  			return;
  		pa = pmap_pte_pa(pmap_pte(pmap, sva));
! 		if (!pmap_valid_page(pa))
  			return;
  		pv = pa_to_pvh(pa);
  		if (pv->pv_ptste == NULL)
***************
*** 1768,1774 ****
  	register int *pte;
  	int s;
  
! 	if (pa < vm_first_phys || pa >= vm_last_phys)
  		return(FALSE);
  
  	pv = pa_to_pvh(pa);
--- 1901,1907 ----
  	register int *pte;
  	int s;
  
! 	if (!pmap_valid_page(pa))
  		return(FALSE);
  
  	pv = pa_to_pvh(pa);
***************
*** 1816,1822 ****
  		printf("pmap_changebit(%x, %x, %s)\n",
  		       pa, bit, setem ? "set" : "clear");
  #endif
! 	if (pa < vm_first_phys || pa >= vm_last_phys)
  		return;
  
  	pv = pa_to_pvh(pa);
--- 1949,1955 ----
  		printf("pmap_changebit(%x, %x, %s)\n",
  		       pa, bit, setem ? "set" : "clear");
  #endif
! 	if (!pmap_valid_page(pa))
  		return;
  
  	pv = pa_to_pvh(pa);
diff -cr /mnt/src/sys/arch/amiga/include/pmap.h /sys/arch/amiga/include/pmap.h
*** /mnt/src/sys/arch/amiga/include/pmap.h	Sun Jun  5 10:15:23 1994
--- /sys/arch/amiga/include/pmap.h	Sun Jul 31 11:38:40 1994
***************
*** 95,101 ****
--- 95,105 ----
  u_int		*Sysmap;
  char		*vmmap;		/* map for mem, dumps, etc. */
  
+ #ifdef MACHINE_NONCONTIG
+ #define pa_index(pa)		pmap_page_index(pa)
+ #else
  #define pa_index(pa)		atop(pa - vm_first_phys)
+ #endif
  #define pa_to_pvh(pa)		(&pv_table[pa_index(pa)])
  #define	pmap_resident_count(pmap)	((pmap)->pm_stats.resident_count)
  #endif	KERNEL

-- 
Michael L. Hitch			INTERNET:  osymh@montana.edu
Computer Consultant
Office of Systems and Computing Services
Montana State University	Bozeman, MT	USA

------------------------------------------------------------------------------