svn commit: r204778 - head/sys/mips/cavium

Juli Mallett jmallett at FreeBSD.org
Fri Mar 5 22:48:35 UTC 2010


Author: jmallett
Date: Fri Mar  5 22:48:34 2010
New Revision: 204778
URL: http://svn.freebsd.org/changeset/base/204778

Log:
  o) Simplify the implementation of bus read/write functions, and eliminate some
     redundant implementations.
  o) Use ABI, not ISA, to determine address length.
  o) Disable and restore interrupts around any operation that uses all 64 bits of
     a register.  In kernels using the O32 ABI, the upper 32 bits of those
     registers is likely to be corrupted by an interrupt.
  
  Sponsored by:	Packet Forensics

Modified:
  head/sys/mips/cavium/octeon_pcmap_regs.h

Modified: head/sys/mips/cavium/octeon_pcmap_regs.h
==============================================================================
--- head/sys/mips/cavium/octeon_pcmap_regs.h	Fri Mar  5 22:46:11 2010	(r204777)
+++ head/sys/mips/cavium/octeon_pcmap_regs.h	Fri Mar  5 22:48:34 2010	(r204778)
@@ -90,350 +90,228 @@ extern struct pcpu *cpuid_to_pcpu[];
 #define OCTEON_SYNCW	__asm __volatile (".word  0x10f" : : )
 #define OCTEON_SYNCWS	__asm __volatile (".word  0x14f" : : )
 
-#if defined(__mips_n32) || defined(__mips_n64)
+#if defined(__mips_n64)
+#define	oct_write64(a, v)	(*(volatile uint64_t *)(a) = (uint64_t)(v))
+#define	oct_write8_x8(a, v)	(*(volatile uint8_t *)(a) = (uint8_t)(v))
+
+#define	OCT_READ(n, t)							\
+static inline t oct_read ## n(uintptr_t a)				\
+{									\
+	volatile t *p = (volatile t *)a;				\
+	return (*p);							\
+}
+
+OCT_READ(8, uint8_t);
+OCT_READ(16, uint16_t);
+OCT_READ(32, uint32_t);
+OCT_READ(64, uint64_t);
 
+#elif defined(__mips_n32) || defined(__mips_o32)
+#if defined(__mips_n32)
 static inline void oct_write64 (uint64_t csr_addr, uint64_t val64)
 {
-    uint64_t *ptr = (uint64_t *) csr_addr;
-    *ptr = val64;
-}
-
-static inline void oct_write64_int64 (uint64_t csr_addr, int64_t val64i)
-{
-    int64_t *ptr = (int64_t *) csr_addr;
-    *ptr = val64i;
+    __asm __volatile (
+	    ".set push\n"
+            ".set mips64\n"
+            "sd     %0, 0(%1)\n"
+            ".set pop\n"
+            :
+	    : "r"(val64), "r"(csr_addr));
 }
 
 static inline void oct_write8_x8 (uint64_t csr_addr, uint8_t val8)
 {
-    uint64_t *ptr = (uint64_t *) csr_addr;
-    *ptr = (uint64_t) val8;
-}
+    __asm __volatile (
+	    ".set push\n"
+            ".set mips64\n"
+            "sb    %0, 0(%1)\n"
+            ".set pop\n"
+            :
+	    : "r"(val8), "r"(csr_addr));
+}
+
+#define	OCT_READ(n, t, insn)						\
+static inline t oct_read ## n(uint64_t a)				\
+{									\
+    uint64_t tmp;							\
+									\
+    __asm __volatile (							\
+	".set push\n"							\
+        ".set mips64\n"							\
+        insn "\t%0, 0(%1)\n"						\
+        ".set pop\n"							\
+        : "=r"(tmp)							\
+        : "r"(a));							\
+    return ((t)tmp);							\
+}
+
+OCT_READ(8, uint8_t, "lb");
+OCT_READ(16, uint16_t, "lh");
+OCT_READ(32, uint32_t, "lw");
+OCT_READ(64, uint64_t, "ld");
+#else
 
-static inline void oct_write8 (uint64_t csr_addr, uint8_t val8)
+/*
+ * XXX
+ * Add o32 variants that load the address into a register and the result out
+ * of a register properly, and simply disable interrupts before and after and
+ * hope that we don't need to refill or modify the TLB to access the address.
+ * I'd be a lot happier if csr_addr were a physical address and we mapped it
+ * into XKPHYS here so that we could guarantee that interrupts were the only
+ * kind of exception we needed to worry about.
+ *
+ * Also, some of this inline assembly is needlessly verbose.  Oh, well.
+ */
+static inline void oct_write64 (uint64_t csr_addr, uint64_t val64)
 {
-    oct_write64(csr_addr, (uint64_t) val8);
-}
+	uint32_t csr_addrh = csr_addr >> 32;
+	uint32_t csr_addrl = csr_addr;
+	uint32_t valh = val64 >> 32;
+	uint32_t vall = val64;
+	uint32_t tmp1;
+	uint32_t tmp2;
+	uint32_t tmp3;
+	register_t sr;
 
-static inline void oct_write16 (uint64_t csr_addr, uint16_t val16)
-{
-    oct_write64(csr_addr, (uint64_t) val16);
-}
+	sr = intr_disable();
 
-static inline void oct_write32 (uint64_t csr_addr, uint32_t val32)
-{
-    oct_write64(csr_addr, (uint64_t) val32);
-}
+	__asm __volatile (
+	    ".set push\n"
+            ".set mips64\n"
+	    ".set noreorder\n"
+	    ".set noat\n"
+	    "dsll   %0, %3, 32\n"
+	    "dsll   %1, %5, 32\n"
+	    "dsll   %2, %4, 32\n"
+	    "dsrl   %2, %2, 32\n"
+	    "or     %0, %0, %2\n"
+	    "dsll   %2, %6, 32\n"
+	    "dsrl   %2, %2, 32\n"
+	    "or     %1, %1, %2\n"
+	    "sd     %0, 0(%1)\n"
+            ".set pop\n"
+	    : "=&r" (tmp1), "=&r" (tmp2), "=&r" (tmp3)
+	    : "r" (valh), "r" (vall), "r" (csr_addrh), "r" (csr_addrl));
 
-static inline uint8_t oct_read8 (uint64_t csr_addr)
-{
-    uint8_t *ptr = (uint8_t *) csr_addr;
-    return (*ptr);
+	intr_restore(sr);
 }
 
-static inline uint8_t oct_read16 (uint64_t csr_addr)
+static inline void oct_write8_x8 (uint64_t csr_addr, uint8_t val8)
 {
-    uint16_t *ptr = (uint16_t *) csr_addr;
-    return (*ptr);
-}
+	uint32_t csr_addrh = csr_addr >> 32;
+	uint32_t csr_addrl = csr_addr;
+	uint32_t tmp1;
+	uint32_t tmp2;
+	register_t sr;
 
+	sr = intr_disable();
 
-static inline uint32_t oct_read32 (uint64_t csr_addr)
-{
-    uint32_t *ptr = (uint32_t *) csr_addr;
-    return (*ptr);
-}
+	__asm __volatile (
+	    ".set push\n"
+            ".set mips64\n"
+	    ".set noreorder\n"
+	    ".set noat\n"
+	    "dsll   %0, %3, 32\n"
+	    "dsll   %1, %4, 32\n"
+	    "dsrl   %1, %1, 32\n"
+	    "or     %0, %0, %1\n"
+	    "sb     %2, 0(%0)\n"
+            ".set pop\n"
+	    : "=&r" (tmp1), "=&r" (tmp2)
+	    : "r" (val8), "r" (csr_addrh), "r" (csr_addrl));
+
+	intr_restore(sr);
+}
+
+#define	OCT_READ(n, t, insn)						\
+static inline t oct_read ## n(uint64_t csr_addr)			\
+{									\
+	uint32_t csr_addrh = csr_addr >> 32;				\
+	uint32_t csr_addrl = csr_addr;					\
+	uint32_t tmp1, tmp2;						\
+	register_t sr;							\
+									\
+	sr = intr_disable();						\
+									\
+	__asm __volatile (						\
+	    ".set push\n"						\
+            ".set mips64\n"						\
+	    ".set noreorder\n"						\
+	    ".set noat\n"						\
+	    "dsll   %1, %2, 32\n"					\
+	    "dsll   %0, %3, 32\n"					\
+	    "dsrl   %0, %0, 32\n"					\
+	    "or     %1, %1, %0\n"					\
+	    "lb     %1, 0(%1)\n"					\
+	    ".set pop\n"						\
+	    : "=&r" (tmp1), "=&r" (tmp2)				\
+	    : "r" (csr_addrh), "r" (csr_addrl));			\
+									\
+	intr_restore(sr);						\
+									\
+	return ((t)tmp2);						\
+}
+
+OCT_READ(8, uint8_t, "lb");
+OCT_READ(16, uint16_t, "lh");
+OCT_READ(32, uint32_t, "lw");
 
 static inline uint64_t oct_read64 (uint64_t csr_addr)
 {
-    uint64_t *ptr = (uint64_t *) csr_addr;
-    return (*ptr);
-}
-
-static inline int32_t oct_readint32 (uint64_t csr_addr)
-{
-    int32_t *ptr = (int32_t *) csr_addr;
-    return (*ptr);
-}
-
-
-
-#else
-
-
-/*  ABI o32 */
+	uint32_t csr_addrh = csr_addr >> 32;
+	uint32_t csr_addrl = csr_addr;
+	uint32_t valh;
+	uint32_t vall;
+	register_t sr;
 
+	sr = intr_disable();
 
-/*
- * Read/write functions
- */
-static inline void oct_write64 (uint64_t csr_addr, uint64_t val64)
-{
-    uint32_t csr_addrh = csr_addr >> 32;
-    uint32_t csr_addrl = csr_addr;
-    uint32_t valh = (uint64_t)val64 >> 32;
-    uint32_t vall = val64;
-    uint32_t tmp1;
-    uint32_t tmp2;
-    uint32_t tmp3;
-
-    __asm __volatile (
+	__asm __volatile (
+	    ".set push\n"
             ".set mips64\n"
-            "dsll   %0, %3, 32\n"
-            "dsll   %1, %5, 32\n"
-            "dsll   %2, %4, 32\n"
-            "dsrl   %2, %2, 32\n"
-            "or     %0, %0, %2\n"
-            "dsll   %2, %6, 32\n"
-            "dsrl   %2, %2, 32\n"
-            "or     %1, %1, %2\n"
-            "sd     %0, 0(%1)\n"
-            ".set mips0\n"
-            : "=&r" (tmp1), "=&r" (tmp2), "=&r" (tmp3)
-            : "r" (valh), "r" (vall),
-              "r" (csr_addrh), "r" (csr_addrl)
-        );
-}
-
-static inline void oct_write64_int64 (uint64_t csr_addr, int64_t val64i)
-{
-    uint32_t csr_addrh = csr_addr >> 32;
-    uint32_t csr_addrl = csr_addr;
-    int32_t valh = (uint64_t)val64i >> 32;
-    int32_t vall = val64i;
-    uint32_t tmp1;
-    uint32_t tmp2;
-    uint32_t tmp3;
+	    ".set noreorder\n"
+	    ".set noat\n"
+	    "dsll   %0, %2, 32\n"
+	    "dsll   %1, %3, 32\n"
+	    "dsrl   %1, %1, 32\n"
+	    "or     %0, %0, %1\n"
+	    "ld     %1, 0(%0)\n"
+	    "dsrl   %0, %1, 32\n"
+	    "dsll   %1, %1, 32\n"
+	    "dsrl   %1, %1, 32\n"
+	    ".set pop\n"
+	    : "=&r" (valh), "=&r" (vall)
+	    : "r" (csr_addrh), "r" (csr_addrl));
 
-    __asm __volatile (
-            ".set mips64\n"
-            "dsll   %0, %3, 32\n"
-            "dsll   %1, %5, 32\n"
-            "dsll   %2, %4, 32\n"
-            "dsrl   %2, %2, 32\n"
-            "or     %0, %0, %2\n"
-            "dsll   %2, %6, 32\n"
-            "dsrl   %2, %2, 32\n"
-            "or     %1, %1, %2\n"
-            "sd     %0, 0(%1)\n"
-            ".set mips0\n"
-            : "=&r" (tmp1), "=&r" (tmp2), "=&r" (tmp3)
-            : "r" (valh), "r" (vall),
-              "r" (csr_addrh), "r" (csr_addrl)
-        );
-}
+	intr_restore(sr);
 
+	return ((uint64_t)valh << 32) | vall;
+}
+#endif
 
-/*
- * oct_write8_x8
- *
- * 8 bit data write into IO Space. Written using an 8 bit bus io transaction
- */
-static inline void oct_write8_x8 (uint64_t csr_addr, uint8_t val8)
-{
-    uint32_t csr_addrh = csr_addr>>32;
-    uint32_t csr_addrl = csr_addr;
-    uint32_t tmp1;
-    uint32_t tmp2;
+#endif
 
-    __asm __volatile (
-        ".set mips64\n"
-        "dsll   %0, %3, 32\n"
-        "dsll   %1, %4, 32\n"
-        "dsrl   %1, %1, 32\n"
-        "or     %0, %0, %1\n"
-        "sb     %2, 0(%0)\n"
-	".set mips0\n"
-        : "=&r" (tmp1), "=&r" (tmp2)
-        : "r" (val8), "r" (csr_addrh), "r" (csr_addrl) );
-}
+#define	oct_write64_int64(a, v)	(oct_write64(a, (int64_t)(v)))
 
 /*
- * oct_write8
- *
- * 8 bit data write into IO Space. Written using a 64 bit bus io transaction
+ * Most write bus transactions are actually 64-bit on Octeon.
  */
 static inline void oct_write8 (uint64_t csr_addr, uint8_t val8)
 {
-#if 1
     oct_write64(csr_addr, (uint64_t) val8);
-#else
-
-    uint32_t csr_addrh = csr_addr>>32;
-    uint32_t csr_addrl = csr_addr;
-    uint32_t tmp1;
-    uint32_t tmp2;
-
-    __asm __volatile (
-        ".set mips64\n"
-        "dsll   %0, %3, 32\n"
-        "dsll   %1, %4, 32\n"
-        "dsrl   %1, %1, 32\n"
-        "or     %0, %0, %1\n"
-        "sb     %2, 0(%0)\n"
-        ".set mips0\n"
-        : "=&r" (tmp1), "=&r" (tmp2)
-        : "r" (val8), "r" (csr_addrh), "r" (csr_addrl) );
-#endif
 }
 
 static inline void oct_write16 (uint64_t csr_addr, uint16_t val16)
 {
-#if 1
     oct_write64(csr_addr, (uint64_t) val16);
-
-#else
-    uint32_t csr_addrh = csr_addr>>32;
-    uint32_t csr_addrl = csr_addr;
-    uint32_t tmp1;
-    uint32_t tmp2;
-
-    __asm __volatile (
-        ".set mips64\n"
-        "dsll   %0, %3, 32\n"
-        "dsll   %1, %4, 32\n"
-        "dsrl   %1, %1, 32\n"
-        "or     %0, %0, %1\n"
-        "sh     %2, 0(%0)\n"
-	".set mips0\n"
-        : "=&r" (tmp1), "=&r" (tmp2)
-        : "r" (val16), "r" (csr_addrh), "r" (csr_addrl) );
-#endif
 }
 
 static inline void oct_write32 (uint64_t csr_addr, uint32_t val32)
 {
-#if 1
     oct_write64(csr_addr, (uint64_t) val32);
-#else
-
-    uint32_t csr_addrh = csr_addr>>32;
-    uint32_t csr_addrl = csr_addr;
-    uint32_t tmp1;
-    uint32_t tmp2;
-
-    __asm __volatile (
-        ".set mips64\n"
-        "dsll   %0, %3, 32\n"
-        "dsll   %1, %4, 32\n"
-        "dsrl   %1, %1, 32\n"
-        "or     %0, %0, %1\n"
-        "sw     %2, 0(%0)\n"
-	".set mips0\n"
-        : "=&r" (tmp1), "=&r" (tmp2)
-        : "r" (val32), "r" (csr_addrh), "r" (csr_addrl) );
-#endif
 }
 
-
-
-static inline uint8_t oct_read8 (uint64_t csr_addr)
-{
-    uint32_t csr_addrh = csr_addr>>32;
-    uint32_t csr_addrl = csr_addr;
-    uint32_t tmp1, tmp2;
-
-    __asm __volatile (
-        ".set mips64\n"
-        "dsll   %1, %2, 32\n"
-        "dsll   %0, %3, 32\n"
-        "dsrl   %0, %0, 32\n"
-        "or     %1, %1, %0\n"
-        "lb     %1, 0(%1)\n"
-        ".set mips0\n"
-        : "=&r" (tmp1), "=&r" (tmp2)
-        : "r" (csr_addrh), "r" (csr_addrl) );
-    return ((uint8_t) tmp2);
-}
-
-static inline uint8_t oct_read16 (uint64_t csr_addr)
-{
-    uint32_t csr_addrh = csr_addr>>32;
-    uint32_t csr_addrl = csr_addr;
-    uint32_t tmp1, tmp2;
-
-    __asm __volatile (
-        ".set mips64\n"
-        "dsll   %1, %2, 32\n"
-        "dsll   %0, %3, 32\n"
-        "dsrl   %0, %0, 32\n"
-        "or     %1, %1, %0\n"
-        "lh     %1, 0(%1)\n"
-        ".set mips0\n"
-        : "=&r" (tmp1), "=&r" (tmp2)
-        : "r" (csr_addrh), "r" (csr_addrl) );
-    return ((uint16_t) tmp2);
-}
-
-
-static inline uint32_t oct_read32 (uint64_t csr_addr)
-{
-    uint32_t csr_addrh = csr_addr>>32;
-    uint32_t csr_addrl = csr_addr;
-    uint32_t val32;
-    uint32_t tmp;
-
-    __asm __volatile (
-        ".set mips64\n"
-        "dsll   %0, %2, 32\n"
-        "dsll   %1, %3, 32\n"
-        "dsrl   %1, %1, 32\n"
-        "or     %0, %0, %1\n"
-        "lw    %0, 0(%0)\n"
-        ".set mips0\n"
-        : "=&r" (val32), "=&r" (tmp)
-        : "r" (csr_addrh), "r" (csr_addrl) );
-    return (val32);
-}
-
-
-static inline uint64_t oct_read64 (uint64_t csr_addr)
-{
-    uint32_t csr_addrh = csr_addr >> 32;
-    uint32_t csr_addrl = csr_addr;
-    uint32_t valh;
-    uint32_t vall;
-
-    __asm __volatile (
-        ".set mips64\n"
-        "dsll   %0, %2, 32\n"
-        "dsll   %1, %3, 32\n"
-        "dsrl   %1, %1, 32\n"
-        "or     %0, %0, %1\n"
-        "ld     %1, 0(%0)\n"
-        "dsrl   %0, %1, 32\n"
-        "dsll   %1, %1, 32\n"
-        "dsrl   %1, %1, 32\n"
-        ".set mips0\n"
-        : "=&r" (valh), "=&r" (vall)
-        : "r" (csr_addrh), "r" (csr_addrl)
-        );
-    return ((uint64_t)valh << 32) | vall;
-}
-
-
-static inline int32_t oct_readint32 (uint64_t csr_addr)
-{
-    uint32_t csr_addrh = csr_addr>>32;
-    uint32_t csr_addrl = csr_addr;
-    int32_t val32;
-    uint32_t tmp;
-
-    __asm __volatile (
-        ".set mips64\n"
-        "dsll   %0, %2, 32\n"
-        "dsll   %1, %3, 32\n"
-        "dsrl   %1, %1, 32\n"
-        "or     %0, %0, %1\n"
-        "lw    %0, 0(%0)\n"
-        : "=&r" (val32), "=&r" (tmp)
-        : "r" (csr_addrh), "r" (csr_addrl) );
-    return (val32);
-}
-
-
-#endif
-
+#define	oct_readint32(a)	((int32_t)oct_read32((a)))
 
 #define OCTEON_HW_BASE		((volatile uint64_t *) 0L)
 #define OCTEON_REG_OFFSET	(-4 * 1024ll)  /* local scratchpad reg base */
@@ -589,7 +467,7 @@ typedef enum {
 
 /*  PTR_SIZE == sizeof(uint32_t)  */
 
-#ifdef ISA_MIPS32
+#if defined(__mips_n32) || defined(__mips_o32)
 #define mipsx_addr_size				uint32_t	// u_int64
 #define MIPSX_ADDR_SIZE_KSEGX_BIT_SHIFT		30		// 62
 #define MIPSX_ADDR_SIZE_KSEGX_MASK_REMOVED	0x1fffffff	// 0x1fffffff


More information about the svn-src-head mailing list