Weird calculation for kernel L2 segment table

Izumi Tsutsui <[email protected]>
Newsgroups gmane.os.netbsd.ports.amiga,gmane.os.netbsd.ports.m68k,gmane.os.netbsd.ports.atari
Message-ID <[email protected]>
sys/arch/amiga/amiga/amiga_init.c (and recently sync'ed atari_init.c)
has the following calculations to get the level2 segment table
for the kernel Sysptmap:

---
		/*
		 * Kernel segment table at end of next level 2 table
		 */
		/* XXX fix calculations XXX */
		i = ((((ptsize >> PGSHIFT) + 3) & -2) - 1) * (NPTEPG / SG4_LEV3SIZE);
		sg = &((st_entry_t *)(RELOC(Sysseg_pa, u_int)))[SG4_LEV1SIZE + i];
		esg = &sg[NPTEPG / SG4_LEV3SIZE];
		sg_proto = Sysptmap_pa | SG_U | SG_RW | SG_V;
		while (sg < esg) {
			*sg++ = sg_proto;
			sg_proto += (SG4_LEV3SIZE * sizeof (st_entry_t));
		}
---

I think this could be rewritten more meaningfully as following:

---
		nl2desc = (ptsize >> PGSHIFT) * (NPTEPG / SG4_LEV3SIZE);
	:
		nl1desc = roundup(nl2desc, SG4_LEV2SIZE) / SG4_LEV2SIZE;
	:
		/*
		 * Kernel segment table at end of next level 2 table
		 */
		i = SG4_LEV1SIZE + (nl1desc * SG4_LEV2SIZE);
		sg = (st_entry_t *)RELOC(Sysseg_pa, u_int);
		sg = &sg[i + SG4_LEV2SIZE - (NPTEPG / SG4_LEV3SIZE)];
		esg = &sg[NPTEPG / SG4_LEV3SIZE];
	:
---

With a quick test program, both offset values against Sysseg_pa
look identical.

How about this patch? Comments?

---
Index: amiga/amiga/amiga_init.c
===================================================================
RCS file: /cvsroot/src/sys/arch/amiga/amiga/amiga_init.c,v
retrieving revision 1.103
diff -u -r1.103 amiga_init.c
--- amiga/amiga/amiga_init.c	31 Dec 2008 19:54:40 -0000	1.103
+++ amiga/amiga/amiga_init.c	2 Jan 2009 04:44:43 -0000
@@ -218,6 +218,9 @@
 	register pt_entry_t pg_proto, *pg, *epg;
 	vaddr_t end_loaded;
 	u_int ncd, i;
+#if defined(M68040) || defined(M68060)
+	u_int nl1desc, nl2desc;
+#endif
 	vaddr_t kva;
 	struct boot_memlist *ml;
 
@@ -432,9 +435,10 @@
 		 * pages of PTEs.  Note that we set the "used" bit
 		 * now to save the HW the expense of doing it.
 		 */
-		i = (ptsize >> PGSHIFT) * (NPTEPG / SG4_LEV3SIZE);
-		sg = &((st_entry_t *)(RELOC(Sysseg_pa, u_int)))[SG4_LEV1SIZE];
-		esg = &sg[i];
+		nl2desc = (ptsize >> PGSHIFT) * (NPTEPG / SG4_LEV3SIZE);
+		sg = (st_entry_t *)RELOC(Sysseg_pa, u_int);
+		sg = &sg[SG4_LEV1SIZE];
+		esg = &sg[nl2desc];
 		sg_proto = ptpa | SG_U | SG_RW | SG_V;
 		while (sg < esg) {
 			*sg++ = sg_proto;
@@ -443,15 +447,13 @@
 
 		/*
 		 * Initialize level 1 descriptors.  We need:
-		 *	roundup(num, SG4_LEV2SIZE) / SG4_LEVEL2SIZE
-		 * level 1 descriptors to map the 'num' level 2's.
+		 *	roundup(nl2desc, SG4_LEV2SIZE) / SG4_LEVEL2SIZE
+		 * level 1 descriptors to map the 'nl2desc' level 2's.
 		 */
-		i = roundup(i, SG4_LEV2SIZE) / SG4_LEV2SIZE;
+		nl1desc = roundup(nl2desc, SG4_LEV2SIZE) / SG4_LEV2SIZE;
 		/* Include additional level 2 table for Sysmap in protostfree */
-		RELOC(protostfree, u_int) =
-		    (-1 << (i + 2)) /* & ~(-1 << MAXKL2SIZE) */;
 		sg = (st_entry_t *)RELOC(Sysseg_pa, u_int);
-		esg = &sg[i];
+		esg = &sg[nl1desc];
 		sg_proto = (paddr_t)&sg[SG4_LEV1SIZE] | SG_U | SG_RW | SG_V;
 		while (sg < esg) {
 			*sg++ = sg_proto;
@@ -466,15 +468,17 @@
 		/*
 		 * Kernel segment table at end of next level 2 table
 		 */
-		/* XXX fix calculations XXX */
-		i = ((((ptsize >> PGSHIFT) + 3) & -2) - 1) * (NPTEPG / SG4_LEV3SIZE);
-		sg = &((st_entry_t *)(RELOC(Sysseg_pa, u_int)))[SG4_LEV1SIZE + i];
+		i = SG4_LEV1SIZE + (nl1desc * SG4_LEV2SIZE);
+		sg = (st_entry_t *)RELOC(Sysseg_pa, u_int);
+		sg = &sg[i + SG4_LEV2SIZE - (NPTEPG / SG4_LEV3SIZE)];
 		esg = &sg[NPTEPG / SG4_LEV3SIZE];
 		sg_proto = Sysptmap_pa | SG_U | SG_RW | SG_V;
 		while (sg < esg) {
 			*sg++ = sg_proto;
 			sg_proto += (SG4_LEV3SIZE * sizeof (st_entry_t));
 		}
+		RELOC(protostfree, u_int) =
+		    (-1 << (1 + nl1desc + 1)) /* & ~(-1 << MAXKL2SIZE) */;
 
 		/*
 		 * Initialize Sysptmap
Index: atari/atari/atari_init.c
===================================================================
RCS file: /cvsroot/src/sys/arch/atari/atari/atari_init.c,v
retrieving revision 1.70
diff -u -r1.70 atari_init.c
--- atari/atari/atari_init.c	2 Jan 2009 04:38:09 -0000	1.70
+++ atari/atari/atari_init.c	2 Jan 2009 04:44:43 -0000
@@ -981,7 +981,7 @@
 	paddr_t		sysptmap_pa;	/* System page table		*/
 	paddr_t		kbase;
 {
-	int		i;
+	int		nl1desc, nl2desc, i;
 	st_entry_t	sg_proto, *sg, *esg;
 	pt_entry_t	pg_proto, *pg, *epg;
 
@@ -1003,10 +1003,10 @@
 	 * pages of PTEs.  Note that we set the "used" bit
 	 * now to save the HW the expense of doing it.
 	 */
-	i   = (ptsize >> PGSHIFT) * (NPTEPG / SG4_LEV3SIZE);
+	nl2desc = (ptsize >> PGSHIFT) * (NPTEPG / SG4_LEV3SIZE);
 	sg  = (st_entry_t *)sysseg_pa;
 	sg  = &sg[SG4_LEV1SIZE];
-	esg = &sg[i];
+	esg = &sg[nl2desc];
 	sg_proto = (ptpa + kbase) /* relocated PA */ | SG_U | SG_RW | SG_V;
 	while (sg < esg) {
 		*sg++     = sg_proto;
@@ -1015,13 +1015,12 @@
 
 	/*
 	 * Initialize level 1 descriptors.  We need:
-	 *	roundup(num, SG4_LEV2SIZE) / SG4_LEVEL2SIZE
-	 * level 1 descriptors to map the 'num' level 2's.
+	 *	roundup(nl2desc, SG4_LEV2SIZE) / SG4_LEVEL2SIZE
+	 * level 1 descriptors to map the 'nl2desc' level 2's.
 	 */
-	i   = roundup(i, SG4_LEV2SIZE) / SG4_LEV2SIZE;
-	protostfree = (-1 << (i + 2)) /* & ~(-1 << MAXKL2SIZE) */;
+	nl1desc = roundup(nl2desc, SG4_LEV2SIZE) / SG4_LEV2SIZE;
 	sg  = (st_entry_t *)sysseg_pa;
-	esg = &sg[i];
+	esg = &sg[nl1desc];
 	sg_proto = ((paddr_t)&sg[SG4_LEV1SIZE] + kbase) /* relocated PA */
 	    | SG_U | SG_RW | SG_V;
 	while (sg < esg) {
@@ -1037,10 +1036,9 @@
 	/*
 	 * Kernel segment table at end of next level 2 table
 	 */
-	/* XXX fix calculations XXX */
-	i = ((((ptsize >> PGSHIFT) + 3) & -2) - 1) * (NPTEPG / SG4_LEV3SIZE);
+	i = SG4_LEV1SIZE + (nl1desc * SG4_LEV2SIZE);
 	sg  = (st_entry_t *)sysseg_pa;
-	sg  = &sg[SG4_LEV1SIZE + i];
+	sg  = &sg[i + SG4_LEV2SIZE - (NPTEPG / SG4_LEV3SIZE)];
 	esg = &sg[NPTEPG / SG4_LEV3SIZE];
 	sg_proto = (sysptmap_pa + kbase) /* relocated PA */
 	    | SG_U | SG_RW | SG_V;
@@ -1048,6 +1046,7 @@
 		*sg++ = sg_proto;
 		sg_proto += (SG4_LEV3SIZE * sizeof(st_entry_t));
 	}
+	protostfree = (-1 << (1 + nl1desc + 1)) /* & ~(-1 << MAXKL2SIZE) */;
 
 	/*
 	 * Initialize Sysptmap

---
Izumi Tsutsui
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.