PERFORCE change 31868 for review

Juli Mallett jmallett at FreeBSD.org
Sun May 25 14:46:58 PDT 2003


http://perforce.freebsd.org/chv.cgi?CH=31868

Change 31868 by jmallett at jmallett_dalek on 2003/05/25 14:46:14

	o) Add END addresses for various segments.
	o) Add TBIA() wrappers.
	o) Switch to using 8K pages.
	o) Add ASID related stuff to pcpu.
	o) Fill in pmap.h with stuff Alpha pmap uses.
	o) Use a 64-bit PTE.
	o) Add a SW managed bit to the PTE.
	o) Note that we have UMA_MD_SMALL_ALLOC, which is required for
	   Alpha pmap to work properly (otherwise, need to use a custom
	   allocator for PV tables like on i386).
	o) Point kernel addresses into XKSEG.
	o) Add bogus vectors for new exception code, nuke the old ones
	   from NetBSD.  All of the TLB related exceptions will need new
	   code to use the new pmap.
	o) Use dm[ft]c0 for exception program counter.
	o) Move some calls into mips_init that are not platform-ordered.
	o) Move physsz/physmem stuff into mips_init.
	o) Remove the exception switch.
	o) Put a lightly-modified Alpha pmap in place, which will
	   obviously need a lot of hacking, etc., but this is enough of
	   a fleshed-out placeholder to get just as far as the fake
	   direct-mapped pmap got us, in real terms.  This obviously
	   is missing code to actually use the TLB and to make proper
	   use of the page tables, and is overly complex to fit what
	   PAL on Alpha uses.  That will change.  This is mostly just
	   to have something to work from.
	o) Make phys_avail really physical addresses, this is very very
	   key to having real physical vs. virtual distinctions, and it
	   being fake was just a remnant of being influenced by SPARC64,
	   and of the lazy pmap.
	o) Sneak in some cpu_intr that hands off to iointr, but this is
	   not really used.

Affected files ...

.. //depot/projects/mips/sys/mips/include/cpuregs.h#9 edit
.. //depot/projects/mips/sys/mips/include/locore.h#5 edit
.. //depot/projects/mips/sys/mips/include/param.h#10 edit
.. //depot/projects/mips/sys/mips/include/pcpu.h#4 edit
.. //depot/projects/mips/sys/mips/include/pmap.h#10 edit
.. //depot/projects/mips/sys/mips/include/pte.h#4 edit
.. //depot/projects/mips/sys/mips/include/vmparam.h#8 edit
.. //depot/projects/mips/sys/mips/mips/exception.S#2 edit
.. //depot/projects/mips/sys/mips/mips/machdep.c#27 edit
.. //depot/projects/mips/sys/mips/mips/mips_subr.S#6 edit
.. //depot/projects/mips/sys/mips/mips/pmap.c#14 edit
.. //depot/projects/mips/sys/mips/sgimips/machdep_sgimips.c#18 edit

Differences ...

==== //depot/projects/mips/sys/mips/include/cpuregs.h#9 (text+ko) ====

@@ -76,9 +76,13 @@
  */
 
 #define	MIPS_KUSEG_START		0x0
+#define	MIPS_KUSEG_END			0x000000ffffffffff
 #define	MIPS_XKSEG_START		0xc000000000000000
+#define	MIPS_XKSEG_END			0xc00000ff7fffffff
 #define	MIPS_KSEG0_START		0xffffffff80000000
+#define	MIPS_KSEG0_END			0xffffffff9fffffff
 #define	MIPS_KSEG1_START		0xffffffffa0000000
+#define	MIPS_KSEG1_END			0xffffffffbfffffff
 #define	MIPS_KSEG2_START		0xffffffffc0000000
 #define	MIPS_MAX_MEM_ADDR		0xbe000000
 #define	MIPS_RESERVED_ADDR		0xbfc80000

==== //depot/projects/mips/sys/mips/include/locore.h#5 (text+ko) ====

@@ -88,6 +88,7 @@
  */
 typedef struct  {
 	void (*setTLBpid)(int pid);
+	void (*TBIA)(int);
 	void (*TBIAP)(int);
 	void (*TBIS)(vm_paddr_t);
 	int  (*tlbUpdate)(u_int highreg, u_int lowreg);
@@ -103,6 +104,7 @@
 extern long *mips_locoresw[];
 
 #define MachSetPID		mips64_SetPID
+#define	MIPS_TBIA		mips64_TBIA
 #define MIPS_TBIAP()		mips64_TBIAP(mips_num_tlb_entries)
 #define MIPS_TBIS		mips64_TBIS
 #define MachTLBUpdate		mips64_TLBUpdate

==== //depot/projects/mips/sys/mips/include/param.h#10 (text+ko) ====

@@ -10,10 +10,10 @@
 #endif
 
 /*
- * We use a 4K page on MIPS systems.  Override PAGE_* definitions
+ * We use an 8K page on MIPS systems.  Override PAGE_* definitions
  * to compile-time constants.
  */
-#define	PAGE_SHIFT	12
+#define	PAGE_SHIFT	13
 #define	PAGE_SIZE	(1 << PAGE_SHIFT)
 #define	PAGE_MASK	(PAGE_SIZE - 1)
 
@@ -68,9 +68,9 @@
 #define ALIGNBYTES	_ALIGNBYTES
 #define ALIGN(p)	_ALIGN(p)
 
-#define	NBPG		4096		/* bytes/page */
+#define	NBPG		8192		/* bytes/page */
 #define	PGOFSET		(NBPG-1)	/* byte offset into page */
-#define	PGSHIFT		12		/* LOG2(NBPG) */
+#define	PGSHIFT		13		/* LOG2(NBPG) */
 #define	NPTEPG		(NBPG/4)
 
 #define NBSEG		0x400000	/* bytes/segment */

==== //depot/projects/mips/sys/mips/include/pcpu.h#4 (text+ko) ====

@@ -35,7 +35,8 @@
 #include <machine/cpufunc.h>
 
 #define	PCPU_MD_FIELDS							\
-	/* XXX Nothing to see here. */
+	u_char	pc_next_asid;		/* next ASID to alloc */	\
+	u_int	pc_current_asidgen;	/* ASID rollover check */
 
 #define PCPUP	(pcpup)
 

==== //depot/projects/mips/sys/mips/include/pmap.h#10 (text+ko) ====

@@ -31,22 +31,42 @@
 
 #include <machine/pte.h>
 
-struct md_page {
-};
+#ifndef	LOCORE
 
-#define	PMAP_SEGTABSIZE	512
+struct pv_entry;
 
-struct segtab {
-	union pt_entry	*seg_tab[PMAP_SEGTABSIZE];
-};
-
-struct pmap {
+typedef	struct pmap {
 	struct pmap_statistics	pm_stats;
 	int			pm_asid;
 	int			pm_asidgen;
+	int			pm_active;
+	pt_entry_t		*pm_lev1;	/* KVA of lev0map */
+	vm_object_t		pm_pteobj;	/* Container for pte's */
+	TAILQ_HEAD(,pv_entry)	pm_pvlist;	/* list of mappings in pmap */
+	struct	vm_page		*pm_ptphint;	/* pmap ptp hint */
+	LIST_ENTRY(pmap)	pm_list;	/* list of all pmaps. */
+} *pmap_t;
+
+struct md_page {
+	int pv_list_count;
+	TAILQ_HEAD(,pv_entry)	pv_list;
 };
 
-typedef	struct pmap *pmap_t;
+#define	ASID_BITS	8
+#define	ASIDGEN_BITS	(sizeof(int) * 9 - ASID_BITS)
+#define	ASIDGEN_MASK	((1 << ASIDGEN_BITS) - 1)
+
+/*
+ * For each vm_page_t, there is a list of all currently valid virtual
+ * mappings of that page.  An entry is a pv_entry_t, the list is pv_table.
+ */
+typedef struct pv_entry {
+	pmap_t		pv_pmap;	/* pmap where mapping lies */
+	vm_offset_t	pv_va;		/* virtual address for mapping */
+	TAILQ_ENTRY(pv_entry)	pv_list;
+	TAILQ_ENTRY(pv_entry)	pv_plist;
+	vm_page_t	pv_ptem;	/* VM page for pte */
+} *pv_entry_t;
 
 extern	pmap_t kernel_pmap;
 extern	vm_offset_t avail_start;
@@ -55,13 +75,41 @@
 extern	vm_size_t physsz;
 extern	vm_offset_t virtual_avail;
 extern	vm_offset_t virtual_end;
-extern	struct segtab *segbase;
 
-void pmap_bootstrap(vm_offset_t);
+void pmap_bootstrap(void);
 vm_offset_t pmap_kextract(vm_offset_t);
 vm_offset_t pmap_steal_memory(vm_size_t);
 
 #define	pmap_resident_count(pm)	((pm)->pm_stats.resident_count)
 #define	vtophys(va)	pmap_kextract((vm_offset_t)(va))
 
+#endif /*!LOCORE*/
+
+#define	NLPT			3	/* levels of page tables */
+#define MIPS_PTSHIFT		(PAGE_SHIFT-NLPT) /* bits that index within page tables */
+#define	MIPS_PGBYTES		(1 << PAGE_SHIFT)
+#define MIPS_L3SHIFT		PAGE_SHIFT
+#define MIPS_L2SHIFT		(MIPS_L3SHIFT+MIPS_PTSHIFT)
+#define MIPS_L1SHIFT		(MIPS_L2SHIFT+MIPS_PTSHIFT)
+
+/*
+ * Pte related macros
+ */
+#define VADDR(l1, l2, l3)	(((l1) << MIPS_L1SHIFT)		\
+				 + ((l2) << MIPS_L2SHIFT)	\
+				 + ((l3) << MIPS_L3SHIFT)
+
+#ifndef NKPT
+#define	NKPT			9	/* initial number of kernel page tables */
+#endif
+#define NKLEV2MAPS		255	/* max number of lev2 page tables */
+#define NKLEV3MAPS		(NKLEV2MAPS << MIPS_PTSHIFT) /* max number of lev3 page tables */
+
+#define PTLEV1I		(NPTEPG-1)	/* Lev0 entry that points to Lev0 */
+#define K0SEGLEV1I	(NPTEPG/2)
+#define K1SEGLEV1I	(K0SEGLEV1I+(NPTEPG/4))
+
+#define NUSERLEV2MAPS	(NPTEPG/2)
+#define NUSERLEV3MAPS	(NUSERLEV2MAPS << MIPS_PTSHIFT)
+
 #endif	/* !_MACHINE_PMAP_H_ */

==== //depot/projects/mips/sys/mips/include/pte.h#4 (text+ko) ====

@@ -100,10 +100,11 @@
  */
 
 #ifndef LOCORE
+#if	0/*DOCUMENTATION&OLD*/
 struct mips3_pte {
 #if BYTE_ORDER == BIG_ENDIAN
-unsigned int	pg_prot:2,		/* SW: access control */
-		pg_pfnum:24,		/* HW: core page frame number or 0 */
+unsigned int	pg_prot:3,		/* SW: access control */
+		pg_pfnum:23,		/* HW: core page frame number or 0 */
 		pg_attr:3,		/* HW: cache attribute */
 		pg_m:1,			/* HW: dirty bit */
 		pg_v:1,			/* HW: valid bit */
@@ -114,10 +115,11 @@
 		pg_v:1,			/* HW: valid bit */
 		pg_m:1,			/* HW: dirty bit */
 		pg_attr:3,		/* HW: cache attribute */
-		pg_pfnum:24,		/* HW: core page frame number or 0 */
-		pg_prot:2;		/* SW: access control */
+		pg_pfnum:23,		/* HW: core page frame number or 0 */
+		pg_prot:3;		/* SW: access control */
 #endif
 };
+#endif
 
 /*
  * Structure defining an tlb entry data set.
@@ -133,6 +135,7 @@
 
 #define MIPS3_PG_WIRED	0x80000000	/* SW */
 #define MIPS3_PG_RO	0x40000000	/* SW */
+#define	MIPS3_PG_M	0x20000000	/* SW */
 
 #define	MIPS3_PG_SVPN	0xfffff000	/* Software page no mask */
 #define	MIPS3_PG_HVPN	0xffffe000	/* Hardware page no mask */
@@ -202,10 +205,13 @@
 #ifndef LOCORE
 #include <machine/cpu.h>
 
+typedef unsigned long pt_entry_t;
+#if 0
 typedef union pt_entry {
 	unsigned int	 pt_entry;	/* for copying, etc. */
 	struct mips3_pte pt_mips3_pte;
 } pt_entry_t;
+#endif
 
 #define	mips_pg_nv_bit()	(MIPS1_PG_NV)	/* same on mips1 and mips3 */
 
@@ -227,18 +233,34 @@
 #define	mips_tlbpfn_to_paddr(x)		mips3_tlbpfn_to_paddr((vm_offset_t)(x))
 #define	mips_paddr_to_tlbpfn(x)		mips3_paddr_to_tlbpfn((x))
 
-#endif /* ! LOCORE */
+/*
+ * Address of current address space page table maps
+ */
+#ifdef _KERNEL
+/*
+ * PTmap is recursive pagemap at top of virtual address space.
+ * Within PTmap, the lev1 and lev0 page tables can be found.
+ */
+	/* lev3 page tables */
+#define	PTmap		((pt_entry_t*)VPTBASE)
+	/* lev2 page tables */
+#define	PTlev2		((pt_entry_t*)(PTmap+(PTLEV1I<<MIPS_L2SHIFT)))
+	/* lev1 page tables */
+#define	PTlev1		((pt_entry_t*)(PTlev2+(PTLEV1I<<MIPS_L2SHIFT)))
+	/* pte that maps lev1 page table */
+#define	PTlev1pte	((pt_entry_t*)(PTlev1+(PTLEV1I*sizeof(pt_entry_t))))
+#endif
 
-#if defined(_KERNEL) && !defined(LOCORE)
+#ifdef _KERNEL
 /*
- * Kernel virtual address to page table entry and visa versa.
+ * virtual address to page table entry and
+ * to physical address.
+ * Note: this work recursively, thus vtopte of a pte will give
+ * the corresponding lev1 that in turn maps it.
  */
-#define	kvtopte(va) \
-	(kptemap + (((vm_offset_t)(va) - VM_MIN_KERNEL_ADDRESS) >> PGSHIFT))
-#define	ptetokv(pte) \
-	((((pt_entry_t *)(pte) - kptemap) << PGSHIFT) + VM_MIN_KERNEL_ADDRESS)
+#define	vtopte(va)	(PTmap + (btop(va) \
+				  & ((1 << 3*MIPS_PTSHIFT)-1)))
+#endif /* _KERNEL */
 
-extern	pt_entry_t *kptemap;		/* kernel pte table */
-extern	vm_size_t kptemapsize;		/* number of pte's in Sysmap */
-#endif	/* defined(_KERNEL) && !defined(LOCORE) */
+#endif /* ! LOCORE */
 #endif /* __MIPS_PTE_H__ */

==== //depot/projects/mips/sys/mips/include/vmparam.h#8 (text+ko) ====

@@ -114,6 +114,12 @@
 #define	MAXSLP 		20
 
 /*
+ * MIPS provides a machine specific single page allocator through the use
+ * of KSEG0.
+ */
+#define UMA_MD_SMALL_ALLOC
+
+/*
  * Mach derived constants
  */
 
@@ -124,9 +130,10 @@
 #define VM_MIN_ADDRESS		((vm_offset_t)0x0000000000000000)
 #define VM_MAXUSER_ADDRESS	((vm_offset_t)0x0000010000000000)
 #define VM_MAX_ADDRESS		((vm_offset_t)0x0000010000000000)
-#define VM_MIN_KERNEL_ADDRESS	((vm_offset_t)0xFFFFFFFF80000000)
-#define VM_MAX_KERNEL_ADDRESS	((vm_offset_t)0xFFFFFFFFA0000000)
+#define VM_MIN_KERNEL_ADDRESS	((vm_offset_t)MIPS_XKSEG_START)
+#define VM_MAX_KERNEL_ADDRESS	((vm_offset_t)VPTBASE-1)
 #define	KERNBASE		(VM_MIN_KERNEL_ADDRESS)
+#define	VPTBASE			(MIPS_XKSEG_START+0xffffffff)
 
 /* virtual sizes (bytes) for various kernel submaps */
 #define	VM_KMEM_SIZE		(16*1024*1024)		/* XXX ??? */

==== //depot/projects/mips/sys/mips/mips/exception.S#2 (text+ko) ====

@@ -58,6 +58,44 @@
 	.set at
 VEND(ExceptionVector)
 
+LEAF(CacheVector)
+	.set noat
+
+	dsubu	sp, sp, TF_SIZE
+	dla	k0, 1f
+	j	exception_save_registers
+	move	k1, sp
+1:
+	/*
+	 * No turning back, and nothing we can do.  Just call into
+	 * trap and let it tell the user lovely things about how bad
+	 * their cache has been,
+	 */
+	mfc0	a1, MIPS_COP_0_CAUSE
+	dmfc0	a2, MIPS_COP_0_BAD_VADDR
+	jal	trap
+	move	a0, k1
+
+	jal	exception_restore_registers
+	daddu	sp, sp, TF_SIZE
+	eret
+	.set at
+VEND(CacheVector)
+
+LEAF(TLBMissVector)
+	.set noat
+	j ExceptionVector
+	nop
+	.set at
+VEND(TLBMissVector)
+
+LEAF(XTLBMissVector)
+	.set noat
+	j ExceptionVector
+	nop
+	.set at
+VEND(XTLBMissVector)
+
 /*
  * Restore registers from a trapframe pointed to in k1, returning to ra
  * that is passed in, and kept in k0.
@@ -91,7 +129,7 @@
 	/*
 	 * Brief interlude.
 	 */
-	mtc0	a1, MIPS_COP_0_EXC_PC
+	dmtc0	a1, MIPS_COP_0_EXC_PC
 	mthi	a0
 	mtlo	v1
 	mtc0	v0, MIPS_COP_0_STATUS
@@ -148,7 +186,7 @@
 	mfc0	v0, MIPS_COP_0_STATUS
 	mflo	v1
 	mfhi	a0
-	mfc0	a1, MIPS_COP_0_EXC_PC
+	dmfc0	a1, MIPS_COP_0_EXC_PC
 
 	sd	t0, TF_REG_T0(k1)
 	sd	t1, TF_REG_T1(k1)

==== //depot/projects/mips/sys/mips/mips/machdep.c#27 (text+ko) ====

@@ -192,13 +192,21 @@
 vm_offset_t kstack0;
 vm_paddr_t kstack0_phys;
 
+vm_size_t physsz;
+
 static void cpu_identify(void);
 void cpu_startup(void *);
 SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL);
 
+
 void
 mips_init(void)
 {
+	physmem = btoc(physsz);
+
+	mips_vector_init();
+	pmap_bootstrap();
+
 	proc_linkup(&proc0, &ksegrp0, &kse0, &thread0);
 	proc0.p_uarea = (struct user *)uarea0;
 	proc0.p_stats = &proc0.p_uarea->u_stats;
@@ -567,6 +575,7 @@
 const mips_locore_jumpvec_t mips64_locore_vec =
 {
 	mips64_SetPID,
+	mips64_TBIA,
 	mips64_TBIAP,
 	mips64_TBIS,
 	mips64_TLBUpdate,
@@ -580,50 +589,39 @@
 	extern char ExceptionVector[], ExceptionVectorEnd[];
 
 	/* TLB miss handler address and end */
-	extern char mips64_TLBMiss[], mips64_TLBMissEnd[];
-	extern char mips64_XTLBMiss[], mips64_XTLBMissEnd[];
+	extern char TLBMissVector[], TLBMissVectorEnd[];
+	extern char XTLBMissVector[], XTLBMissVectorEnd[];
 
 	/* Cache error handler */
-	extern char mips64_cache[], mips64_cacheEnd[];
+	extern char CacheVector[], CacheVectorEnd[];
 
-#if 0
-	/* MIPS32/MIPS64 interrupt exception handler */
-	extern char mips64_intr[], mips64_intrEnd[];
-#endif
-
 	/*
 	 * Copy down exception vector code.
 	 */
 
-	if (mips64_TLBMissEnd - mips64_TLBMiss > 0x80)
+	if (TLBMissVectorEnd - TLBMissVector > 0x80)
 		panic("startup: UTLB vector code too large");
-	memcpy((void *)MIPS_UTLB_MISS_EXC_VEC, mips64_TLBMiss,
-	      mips64_TLBMissEnd - mips64_TLBMiss);
+	memcpy((void *)MIPS_UTLB_MISS_EXC_VEC, TLBMissVector,
+	      TLBMissVectorEnd - TLBMissVector);
 
-	if (mips64_XTLBMissEnd - mips64_XTLBMiss > 0x80)
+	if (XTLBMissVectorEnd - XTLBMissVector > 0x80)
 		panic("startup: XTLB vector code too large");
-	memcpy((void *)MIPS3_XTLB_MISS_EXC_VEC, mips64_XTLBMiss,
-	      mips64_XTLBMissEnd - mips64_XTLBMiss);
+	memcpy((void *)MIPS3_XTLB_MISS_EXC_VEC, XTLBMissVector,
+	      XTLBMissVectorEnd - XTLBMissVector);
 
-	if (mips64_cacheEnd - mips64_cache > 0x80)
+	if (CacheVectorEnd - CacheVector > 0x80)
 		panic("startup: Cache error vector code too large");
-	memcpy((void *)MIPS3_CACHE_ERR_EXC_VEC, mips64_cache,
-	      mips64_cacheEnd - mips64_cache);
+	memcpy((void *)MIPS3_CACHE_ERR_EXC_VEC, CacheVector,
+	      CacheVectorEnd - CacheVector);
 
 	if (ExceptionVectorEnd - ExceptionVector > 0x80)
 		panic("startup: General exception vector code too large");
 	memcpy((void *)MIPS3_GEN_EXC_VEC, ExceptionVector,
 	      ExceptionVectorEnd - ExceptionVector);
 
-#if 0	/* XXX - why doesn't mipsNN_intr() work? */
-	if (mips64_intrEnd - mips64_intr > 0x80)
-		panic("startup: interrupt exception vector code too large");
-	memcpy((void *)MIPS3_INTR_EXC_VEC, mips64_intr,
-	      mips64_intrEnd - mips64_intr);
-#else
+	/* XXX do a real interrupt vector for the mips32/64? */
 	memcpy((void *)MIPS3_INTR_EXC_VEC, ExceptionVector,
 	      ExceptionVectorEnd - ExceptionVector);
-#endif
 
 	/*
 	 * Copy locore-function vector.

==== //depot/projects/mips/sys/mips/mips/mips_subr.S#6 (text+ko) ====

@@ -152,27 +152,6 @@
 #endif
 
 /*
- * VECTOR
- *	exception vector entrypoint
- *	XXX: regmask should be used to generate .mask
- */
-#define VECTOR(x, regmask)		\
-	.ent	x;		\
-	EXPORT(x);			\
-
-#ifdef __STDC__
-#define VECTOR_END(x)			\
-	EXPORT(x ## End);		\
-	END(x)
-#else
-#define VECTOR_END(x)			\
-	EXPORT(x/**/End);		\
-	END(x)
-#endif
-
-#define	_VECTOR_END(x)	VECTOR_END(x)
-
-/*
  * XXX We need a cleaner way of handling the instruction hazards of
  * the various processors.  Here are the relevant rules for the QED 52XX:
  *	tlbw[ri]	-- two integer ops beforehand
@@ -194,1258 +173,11 @@
  * for those CPU, define COP0_SYNC as sync.p
  */
 
-
-/*
- *============================================================================
- *
- *  MIPS III ISA support, part 1: locore exception vectors.
- *  The following code is copied to the vector locations to which
- *  the CPU jumps in response to an exception or a TLB miss.
- *
- *============================================================================
- */
 	.set	noreorder
 	.set	mips64
 
-/*
- * TLB handling data.   'segbase' points to the base of the segment
- * table.   this is read and written by C code in mips_machdep.c.
- *
- * XXX: use linear mapped PTs at fixed VA in kseg2 in the future?
- */
 	.text
 
-
-/*
- *----------------------------------------------------------------------------
- *
- * mips3_TLBMiss --
- *
- *	Vector code for the TLB-miss exception vector 0x80000000
- *	on an r4000.
- *
- * This code is copied to the TLB exception vector address to
- * handle TLB translation misses.
- * NOTE: This code should be relocatable and max 32 instructions!!!
- *
- * Don't check for invalid pte's here. We load them as well and
- * let the processor trap to load the correct value after service.
- *----------------------------------------------------------------------------
- */
-VECTOR(MIPSX(TLBMiss), unknown)
-	.set	noat
-	mfc0	k0, MIPS_COP_0_BAD_VADDR	#00: k0=bad address
-	lui	k1, %hi(segbase)		#01: k1=hi of segbase
-	bltz	k0, 4f				#02: k0<0 -> 4f (kernel fault)
-	srl	k0, 20				#03: k0=seg offset (almost)
-	lw	k1, %lo(segbase)(k1)		#04: k1=segment tab base
-	andi	k0, k0, 0xffc			#05: k0=seg offset (mask 0x3)
-	addu	k1, k0, k1			#06: k1=seg entry address
-	lw	k1, 0(k1)			#07: k1=seg entry
-	mfc0	k0, MIPS_COP_0_BAD_VADDR	#08: k0=bad address (again)
-	beq	k1, zero, 5f			#09: ==0 -- no page table
-	srl	k0, 10				#0a: k0=VPN (aka va>>10)
-	andi	k0, k0, 0xff8			#0b: k0=page tab offset
-	addu	k1, k1, k0			#0c: k1=pte address
-	lw	k0, 0(k1)			#0d: k0=lo0 pte
-	lw	k1, 4(k1)			#0e: k1=lo1 pte
-	sll	k0, 2				#0f: chop top 2 bits (part 1a)
-	srl	k0, 2				#10: chop top 2 bits (part 1b)
-	mtc0	k0, MIPS_COP_0_TLB_LO0		#11: lo0 is loaded
-	sll	k1, 2				#12: chop top 2 bits (part 2a)
-	srl	k1, 2				#13: chop top 2 bits (part 2b)
-	mtc0	k1, MIPS_COP_0_TLB_LO1		#14: lo1 is loaded
-	nop					#15: standard nop
-	nop					#16: extra nop for QED5230
-	tlbwr					#17: write to tlb
-	nop					#18: standard nop
-	nop					#19: needed by R4000/4400
-	nop					#1a: needed by R4000/4400
-	eret					#1b: return from exception
-4:	j MIPSX(TLBMissException)		#1c: kernel exception
-	nop					#1d: branch delay slot
-5:	j	slowfault			#1e: no page table present
-	nop					#1f: branch delay slot
-	.set	at
-_VECTOR_END(MIPSX(TLBMiss))
-
-/*
- * mips3_XTLBMiss routine
- *
- *	Vector code for the XTLB-miss exception vector 0x80000080 on an r4000.
- *
- * This code is copied to the XTLB exception vector address to
- * handle TLB translation misses while in 64-bit mode.
- * NOTE: This code should be relocatable and max 32 instructions!!!
- *
- * Note that we do not support the full size of the PTEs, relying
- * on appropriate truncation/sign extension.
- *
- * Don't check for invalid pte's here. We load them as well and
- * let the processor trap to load the correct value after service.
- */
-VECTOR(MIPSX(XTLBMiss), unknown)
-	.set	noat
-	dmfc0	k0, MIPS_COP_0_BAD_VADDR	#00: k0=bad address
-	lui	k1, %hi(segbase)		#01: k1=hi of segbase
-	bltz	k0, 4f				#02: k0<0 -> 4f (kernel fault)
-	srl	k0, 20				#03: k0=seg offset (almost)
-	lw	k1, %lo(segbase)(k1)		#04: k1=segment tab base
-	andi	k0, k0, 0xffc			#05: k0=seg offset (mask 0x3)
-	addu	k1, k0, k1			#06: k1=seg entry address
-	lw	k1, 0(k1)			#07: k1=seg entry
-	dmfc0	k0, MIPS_COP_0_BAD_VADDR	#08: k0=bad address (again)
-	beq	k1, zero, 5f			#09: ==0 -- no page table
-	srl	k0, 10				#0a: k0=VPN (aka va>>10)
-	andi	k0, k0, 0xff8			#0b: k0=page tab offset
-	addu	k1, k1, k0			#0c: k1=pte address
-	lw	k0, 0(k1)			#0d: k0=lo0 pte
-	lw	k1, 4(k1)			#0e: k1=lo1 pte
-	sll	k0, 2				#0f: chop top 2 bits (part 1a)
-	srl	k0, 2				#10: chop top 2 bits (part 1b)
-	mtc0	k0, MIPS_COP_0_TLB_LO0		#11: lo0 is loaded
-	sll	k1, 2				#12: chop top 2 bits (part 2a)
-	srl	k1, 2				#13: chop top 2 bits (part 2b)
-	mtc0	k1, MIPS_COP_0_TLB_LO1		#14: lo1 is loaded
-	nop					#15: standard nop
-	nop					#16: extra nop for QED5230
-	tlbwr					#17: write to tlb
-	nop					#18: standard nop
-	nop					#19: needed by R4000/4400
-	nop					#1a: needed by R4000/4400
-	eret					#1b: return from exception
-4:	j MIPSX(TLBMissException)		#1c: kernel exception
-	nop					#1d: branch delay slot
-5:	j	slowfault			#1e: no page table present
-	nop					#1f: branch delay slot
-	.set	at
-_VECTOR_END(MIPSX(XTLBMiss))
-
-/*
- * Vector to real handler in KSEG1.
- */
-VECTOR(MIPSX(cache), unknown)
-	la	k0, MIPSX(cacheException)
-	li	k1, MIPS_PHYS_MASK
-	and	k0, k1
-	li	k1, MIPS_KSEG1_START
-	or	k0, k1
-	j	k0
-	nop
-_VECTOR_END(MIPSX(cache))
-
-/*
- * Handle MIPS32/MIPS64 style interrupt exception vector.
- */
-VECTOR(MIPSX(intr), unknown)
-	la	k0, MIPSX(KernIntr)
-	j	k0
-	nop
-_VECTOR_END(MIPSX(intr))
-
-/*----------------------------------------------------------------------------
- *
- * slowfault --
- *
- * Alternate entry point into the mips3_UserGenException or
- * or mips3_user_Kern_exception, when the ULTB miss handler couldn't
- * find a TLB entry.
- *
- * Find out what mode we came from and call the appropriate handler.
- *
- *----------------------------------------------------------------------------
- */
-
-/*
- * We couldn't find a TLB entry.
- * Find out what mode we came from and call the appropriate handler.
- */
-slowfault:
-	.set	noat
-	mfc0	k0, MIPS_COP_0_STATUS
-	nop
-	and	k0, k0, MIPS3_SR_KSU_USER
-	bne	k0, zero, MIPSX(UserGenException)
-	nop
-	.set	at
-/*
- * Fall though ...
- */
-
-/*
- * mips3_KernGenException
- *
- * Handle an exception from kernel mode.
- * Build trapframe on stack to hold interrupted kernel context, then
- * call trap() to process the condition.
- *
- * trapframe is pointed to by the 5th arg
- * and a dummy sixth argument is used to avoid alignment problems
- *	{
- *	register_t cf_args[4 + 1];
- *	register_t cf_pad;		(for 8 word alignment)
- *	register_t cf_sp;
- *	register_t cf_ra;
- *	mips_reg_t kf_regs[17];		- trapframe begins here
- * 	mips_reg_t kf_sr;		-
- * 	mips_reg_t kf_mullo;		-
- * 	mips_reg_t kf_mulhi;		-
- * 	mips_reg_t kf_epc;		- may be changed by trap() call
- * };
- */
-NESTED_NOPROFILE(MIPSX(KernGenException), KERNFRAME_SIZ, ra)
-	.set	noat
-	.mask	0x80000000, -4
-#if defined(DDB) || defined(KGDB)
-	la	k0, kdbaux
-	REG_S	s0, SF_REG_S0(k0)
-	REG_S	s1, SF_REG_S1(k0)
-	REG_S	s2, SF_REG_S2(k0)
-	REG_S	s3, SF_REG_S3(k0)
-	REG_S	s4, SF_REG_S4(k0)
-	REG_S	s5, SF_REG_S5(k0)
-	REG_S	s6, SF_REG_S6(k0)
-	REG_S	s7, SF_REG_S7(k0)
-	REG_S	sp, SF_REG_SP(k0)
-	REG_S	s8, SF_REG_S8(k0)
-	REG_S	gp, SF_REG_RA(k0)
-#endif
-/*
- * Save the relevant kernel registers onto the stack.
- * We don't need to save s0 - s8, sp and gp because
- * the compiler does it for us.
- */
-	subu	sp, sp, KERNFRAME_SIZ
-	REG_S	AT, TF_BASE+TF_REG_AST(sp)
-	REG_S	v0, TF_BASE+TF_REG_V0(sp)
-	REG_S	v1, TF_BASE+TF_REG_V1(sp)
-	mflo	v0
-	mfhi	v1
-	REG_S	a0, TF_BASE+TF_REG_A0(sp)
-	REG_S	a1, TF_BASE+TF_REG_A1(sp)
-	REG_S	a2, TF_BASE+TF_REG_A2(sp)
-	REG_S	a3, TF_BASE+TF_REG_A3(sp)
-	mfc0	a0, MIPS_COP_0_STATUS		# 1st arg is STATUS
-	REG_S	t0, TF_BASE+TF_REG_T0(sp)
-	REG_S	t1, TF_BASE+TF_REG_T1(sp)
-	REG_S	t2, TF_BASE+TF_REG_T2(sp)
-	REG_S	t3, TF_BASE+TF_REG_T3(sp)
-	mfc0	a1, MIPS_COP_0_CAUSE		# 2nd arg is CAUSE
-	REG_S	ta0, TF_BASE+TF_REG_TA0(sp)
-	REG_S	ta1, TF_BASE+TF_REG_TA1(sp)
-	REG_S	ta2, TF_BASE+TF_REG_TA2(sp)
-	REG_S	ta3, TF_BASE+TF_REG_TA3(sp)
-	mfc0	a2, MIPS_COP_0_BAD_VADDR	# 3rd arg is fault address
-	REG_S	t8, TF_BASE+TF_REG_T8(sp)
-	REG_S	t9, TF_BASE+TF_REG_T9(sp)
-	REG_S	ra, TF_BASE+TF_REG_RA(sp)
-	REG_S	a0, TF_BASE+TF_REG_SR(sp)
-	mfc0	a3, MIPS_COP_0_EXC_PC		# 4th arg is exception PC
-	REG_S	v0, TF_BASE+TF_REG_MULLO(sp)
-	REG_S	v1, TF_BASE+TF_REG_MULHI(sp)
-	REG_S	a3, TF_BASE+TF_REG_EPC(sp)
-	addu	v0, sp, TF_BASE
-	sw	v0, KERNFRAME_ARG5(sp)		# 5th arg is p. to trapframe
-#ifdef IPL_ICU_MASK
-	.set at
-	lw	v0, md_imask
-	sw	v0, TF_BASE+TF_PPL(sp)
-	nop
-	.set noat
-#endif
-/*
- * Call the trap handler.
- */
-#if defined(DDB) || defined(DEBUG) || defined(KGDB)
-	addu	v0, sp, KERNFRAME_SIZ
-	sw	v0, KERNFRAME_SP(sp)
-#endif
-	mtc0	zero, MIPS_COP_0_STATUS		# Set kernel no error level
-	COP0_SYNC
-	nop
-	nop
-	nop
-	PRINTF("OMG\n");
-	jal	trap				#
-	sw	a3, KERNFRAME_RA(sp)		# for debugging
-
-/*
- * Restore registers and return from the exception.
- */
-	mtc0	zero, MIPS_COP_0_STATUS		# Make sure int disabled
-	COP0_SYNC
-	nop					# 3 nop delay
-	nop
-	nop
-#ifdef IPL_ICU_MASK
-	.set at
-	lw	a0, TF_BASE+TF_PPL(sp)
-	sw	a0, md_imask
-	jal	md_imask_update
-	nop
-	.set noat
-#endif
-	REG_L	a0, TF_BASE+TF_REG_SR(sp)	# ??? why differs ???
-	REG_L	t0, TF_BASE+TF_REG_MULLO(sp)
-	REG_L	t1, TF_BASE+TF_REG_MULHI(sp)
-	REG_L	k0, TF_BASE+TF_REG_EPC(sp)	# might be changed inside trap
-	mtc0	a0, MIPS_COP_0_STATUS		# restore the SR, disable intrs
-	COP0_SYNC
-	mtlo	t0
-	mthi	t1
-	_MTC0	k0, MIPS_COP_0_EXC_PC		# set return address
-	COP0_SYNC
-	REG_L	AT, TF_BASE+TF_REG_AST(sp)
-	REG_L	v0, TF_BASE+TF_REG_V0(sp)
-	REG_L	v1, TF_BASE+TF_REG_V1(sp)
-	REG_L	a0, TF_BASE+TF_REG_A0(sp)
-	REG_L	a1, TF_BASE+TF_REG_A1(sp)
-	REG_L	a2, TF_BASE+TF_REG_A2(sp)
-	REG_L	a3, TF_BASE+TF_REG_A3(sp)
-	REG_L	t0, TF_BASE+TF_REG_T0(sp)
-	REG_L	t1, TF_BASE+TF_REG_T1(sp)
-	REG_L	t2, TF_BASE+TF_REG_T2(sp)
-	REG_L	t3, TF_BASE+TF_REG_T3(sp)
-	REG_L	ta0, TF_BASE+TF_REG_TA0(sp)
-	REG_L	ta1, TF_BASE+TF_REG_TA1(sp)
-	REG_L	ta2, TF_BASE+TF_REG_TA2(sp)
-	REG_L	ta3, TF_BASE+TF_REG_TA3(sp)
-	REG_L	t8, TF_BASE+TF_REG_T8(sp)
-	REG_L	t9, TF_BASE+TF_REG_T9(sp)
-	REG_L	ra, TF_BASE+TF_REG_RA(sp)
-	addu	sp, sp, KERNFRAME_SIZ
-#ifdef DDBnotyet
-	la	k0, kdbaux
-	REG_L	s0, SF_REG_S0(k0)
-	REG_L	s1, SF_REG_S1(k0)
-	REG_L	s2, SF_REG_S2(k0)
-	REG_L	s3, SF_REG_S3(k0)
-	REG_L	s4, SF_REG_S4(k0)
-	REG_L	s5, SF_REG_S5(k0)
-	REG_L	s6, SF_REG_S6(k0)
-	REG_L	s7, SF_REG_S7(k0)
-	REG_L	sp, SF_REG_SP(k0)
-	REG_L	s8, SF_REG_S8(k0)
-	REG_L	gp, SF_REG_RA(k0)
-#endif
-	eret					# return to interrupted point
-	.set	at
-END(MIPSX(KernGenException))
-
-/*
- * mipsN_UserGenException
- *
- * Handle an exception from user mode.
- * Save user context atop the kernel stack, then call trap() to process
- * the condition.  The context can be manipulated alternatively via
- * curlwp->p_md.md_regs.
- */
-NESTED_NOPROFILE(MIPSX(UserGenException), CALLFRAME_SIZ, ra)
-	.set	noat
-	.mask	0x80000000, -4
-/*
- * Save all of the registers except for the kernel temporaries in u_pcb.
- */
- 	ld	k1, pcpup
-	ld	k1, PC_CURPCB(k1)
-	#nop					# -slip-
-	addu	k1, k1, USPACE - FRAME_SIZ
-	REG_S	AT, FRAME_AST(k1)
-	REG_S	v0, FRAME_V0(k1)
-	REG_S	v1, FRAME_V1(k1)
-	mflo	v0
-	REG_S	a0, FRAME_A0(k1)
-	REG_S	a1, FRAME_A1(k1)
-	REG_S	a2, FRAME_A2(k1)
-	REG_S	a3, FRAME_A3(k1)
-	mfhi	v1
-	REG_S	t0, FRAME_T0(k1)
-	REG_S	t1, FRAME_T1(k1)
-	REG_S	t2, FRAME_T2(k1)
-	REG_S	t3, FRAME_T3(k1)
-	mfc0	a0, MIPS_COP_0_STATUS		# 1st arg is STATUS
-	REG_S	ta0, FRAME_TA0(k1)
-	REG_S	ta1, FRAME_TA1(k1)
-	REG_S	ta2, FRAME_TA2(k1)
-	REG_S	ta3, FRAME_TA3(k1)
-	mfc0	a1, MIPS_COP_0_CAUSE		# 2nd arg is CAUSE
-	REG_S	s0, FRAME_S0(k1)
-	REG_S	s1, FRAME_S1(k1)
-	REG_S	s2, FRAME_S2(k1)
-	REG_S	s3, FRAME_S3(k1)
-	_MFC0	a2, MIPS_COP_0_BAD_VADDR	# 3rd arg is fault address
-	REG_S	s4, FRAME_S4(k1)
-	REG_S	s5, FRAME_S5(k1)
-	REG_S	s6, FRAME_S6(k1)
-	REG_S	s7, FRAME_S7(k1)
-	_MFC0	a3, MIPS_COP_0_EXC_PC		# 4th arg is exception PC
-	REG_S	t8, FRAME_T8(k1)
-	REG_S	t9, FRAME_T9(k1)
-	REG_S	gp, FRAME_GP(k1)
-	REG_S	sp, FRAME_SP(k1)
-	REG_S	s8, FRAME_S8(k1)
-	REG_S	ra, FRAME_RA(k1)
-	REG_S	a0, FRAME_SR(k1)
-	REG_S	v0, FRAME_MULLO(k1)
-	REG_S	v1, FRAME_MULHI(k1)
-	REG_S	a3, FRAME_EPC(k1)
-#ifdef IPL_ICU_MASK
-	.set at
-	lw	t0, md_imask
-	sw	t0, FRAME_PPL(k1)
-	.set noat
-#endif
-	addu	sp, k1, -CALLFRAME_SIZ	# switch to kernel SP
-#ifdef __GP_SUPPORT__
-	la	gp, _gp		# switch to kernel GP
-#endif
-/*
- * Turn off fpu and enter kernel mode
- */
-	.set	at
-	and	t0, a0, ~(MIPS_SR_COP_1_BIT | MIPS_SR_EXL | MIPS_SR_KSU_MASK | MIPS_SR_INT_IE)
-	.set	noat
-/*
- * Call the trap handler.
- */
-	mtc0	t0, MIPS_COP_0_STATUS
-	COP0_SYNC
-	jal	trap
-	sw	a3, CALLFRAME_SIZ-4(sp)		# for debugging
-/*
- * Check pending asynchronous traps.
- */
- 	ld	t0, pcpup
- 	ld	t0, PC_CURTHREAD(t0)
-	lw	t0, TD_FLAGS(t0)
-	and	t0, TDF_ASTPENDING
-	beq	t0, zero, 1f
-	nop
-/*
- * We have pending asynchronous traps; all the state is already saved.
- */
-	jal	ast
-	lw	a0, CALLFRAME_SIZ + FRAME_EPC(sp)
-1:
-/*
- * Restore user registers and return.
- * First disable interrupts and set exception level.
- */
-	mtc0	zero, MIPS_COP_0_STATUS		# disable interrupt
-	COP0_SYNC
-	nop					# 3 clock delay before
-	nop					# exceptions blocked
-	nop					# for R4X
-	li	v0, MIPS_SR_EXL
-	mtc0	v0, MIPS_COP_0_STATUS		# set exception level
-	COP0_SYNC
-	nop					# 3 nop delay
-	nop
-	nop

>>> TRUNCATED FOR MAIL (1000 lines) <<<


More information about the p4-projects mailing list