Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 28 Feb 2014 17:16:43 -0800
From:      John-Mark Gurney <jmg@funkthat.com>
To:        Dimitry Andric <dim@freebsd.org>, Craig Butler <craig001@lerwick.hopto.org>
Cc:        rdivacky@freebsd.org, freebsd-current@freebsd.org, freebsd-sparc64@freebsd.org
Subject:   Re: HEADS UP: sparc64 backend for llvm/clang imported
Message-ID:  <20140301011643.GV47921@funkthat.com>
In-Reply-To: <F7AC069B-32B9-4F4E-BF19-EA2E6714F9C3@FreeBSD.org>
References:  <F7AC069B-32B9-4F4E-BF19-EA2E6714F9C3@FreeBSD.org>

next in thread | previous in thread | raw e-mail | index | archive | help

--wRRV7LY7NUeQGEoC
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

Dimitry Andric wrote this message on Fri, Feb 28, 2014 at 20:22 +0100:
> In r262613 I have merged the clang-sparc64 branch back to head.  This
> imports an updated sparc64 backend for llvm and clang, allowing clang to
> bootstrap itself on sparc64, and to completely build world.  To be able
> to build the GENERIC kernel, there is still one patch to be finalized,
> see below.
> 
> If you have any sparc64 hardware, and are not afraid to encounter rough
> edges, please try out building and running your system with clang.  To
> do so, update to at least r262613, and enable the following options in
> e.g. src.conf, or in your build environment:
> 
> WITH_CLANG=y
> WITH_CLANG_IS_CC=y
> WITH_LIBCPLUSPLUS=y  (optional)
> 
> Alternatively, if you would rather keep gcc as /usr/bin/cc for the
> moment, build world using just WITH_CLANG, enabling clang to be built
> (by gcc) and installed.  After installworld, you can then set CC=clang,
> CXX=clang++ and CPP=clang-cpp for building another world.
> 
> For building the sparc64 kernel, there is one open issue left, which is
> that sys/sparc64/include/pcpu.h uses global register variables, and this
> is not supported by clang.  A preliminary patch for this is attached,
> but it may or may not blow up your system, please beware!
> 
> The patch changes the pcpu and curpcb global register variables into
> inline functions, similar to what is done on other architectures.
> However, the current approach is not optimal, and the emitted code is
> slightly different from what gcc outputs.  Any improvements to this
> patch are greatly appreciated!
> 
> Last but not least, thanks go out to Roman Divacky for his work with
> llvm/clang upstream in getting the sparc64 backend into shape.

Ok, I have a new pcpu patch to try.  I have only compile tested it.

It is available here:
https://www.funkthat.com/~jmg/sparc64.pcpu.patch

I've also attached it.

Craig, do you mind testing it?

This patch also removes curpcb as it appears to not be used by any
sparc64 C code.  A GENERIC kernel compiles fine, and fxr only turns up
curpcb used in machdep code, and no references to it under sparc64.

This is not a proper solution in that
it can mean counters/stats can be copied/moved to other cpus overwriting
the previous values if a race happens...  We use
PCPU_SET(mem, PCPU_GET(mem) + val) for PCPU_ADD, not great, but it's
no worse than what we were previously using..

Until we get a proper fix which involves mapping all the cpu's PCPU
data on all CPUs, this will have to sufice..

This patch is based upon, I believe, a patch from Marius and possibly
modified by rdivacky.

Thanks for testing..

-- 
  John-Mark Gurney				Voice: +1 415 225 5579

     "All that I will do, has been done, All that I have, has not."

--wRRV7LY7NUeQGEoC
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment; filename="sparc64.pcpu.patch"

Index: pcpu.h
===================================================================
--- pcpu.h	(revision 261863)
+++ pcpu.h	(working copy)
@@ -70,11 +70,82 @@
 struct pcb;
 struct pcpu;
 
-register struct pcb *curpcb __asm__(__XSTRING(PCB_REG));
-register struct pcpu *pcpup __asm__(__XSTRING(PCPU_REG));
+/*
+ * Evaluates to the byte offset of the per-cpu variable name.
+ */
+#define	__pcpu_offset(name)						\
+	__offsetof(struct pcpu, name)
 
-#define	PCPU_GET(member)	(pcpup->pc_ ## member)
+/*
+ * Evaluates to the type of the per-cpu variable name.
+ */
+#define	__pcpu_type(name)						\
+	__typeof(((struct pcpu *)0)->name)
 
+#define	__PCPU_GET(name)	__extension__ ({			\
+	__pcpu_type(name) __res;					\
+									\
+	switch (sizeof(__res)) {					\
+	case 1:								\
+		__asm __volatile("ldub [%" __XSTRING(PCPU_REG) "+ %1], %0" \
+		: "=r" (__res) : "i" (__pcpu_offset(name)));		\
+		break;							\
+	case 2:								\
+		__asm __volatile("lduh [%" __XSTRING(PCPU_REG) "+ %1], %0"\
+		: "=r" (__res) : "i" (__pcpu_offset(name)));		\
+		break;							\
+	case 4:								\
+		__asm __volatile("ld [%" __XSTRING(PCPU_REG) "+ %1], %0"\
+		: "=r" (__res) : "i" (__pcpu_offset(name)));		\
+		break;							\
+	case 8:								\
+		__asm __volatile("ldd [%" __XSTRING(PCPU_REG) "+ %1], %0"\
+		: "=r" (__res) : "i" (__pcpu_offset(name)));		\
+		break;							\
+	default:							\
+		/* XXX - what to put here? */;				\
+	}								\
+	__res;								\
+	})
+
+#define	__PCPU_SET(name, val)	__extension__ ({			\
+	__pcpu_type(name) __val;					\
+									\
+	__val = (val);							\
+	switch (sizeof(__val)) {					\
+	case 1:								\
+		__asm __volatile("stub %0, [%" __XSTRING(PCPU_REG) "+ %1]" \
+		: : "r" (__val), "i" (__pcpu_offset(name)));		\
+		break;							\
+	case 2:								\
+		__asm __volatile("stuh %0, [%" __XSTRING(PCPU_REG) "+ %1]"\
+		: : "r" (__val), "i" (__pcpu_offset(name)));		\
+		break;							\
+	case 4:								\
+		__asm __volatile("st %0, [%" __XSTRING(PCPU_REG) "+ %1]"\
+		: : "r" (__val), "i" (__pcpu_offset(name)));		\
+		break;							\
+	case 8:								\
+		__asm __volatile("std %0, [%" __XSTRING(PCPU_REG) "+ %1]"\
+		: : "r" (__val), "i" (__pcpu_offset(name)));		\
+		break;							\
+	default:							\
+		/* XXX - what to put here? */;				\
+	}								\
+	__val;								\
+	})
+
+#define	__PCPU_PTR(name) __extension__	({				\
+	__pcpu_type(name) *__p;						\
+	struct pcpu *__pcpu;						\
+									\
+	__asm __volatile("mov %" __XSTRING(PCPU_REG) ", %0"		\
+	    : "=r" (__pcpu));						\
+	__p = &__pcpu->name;						\
+									\
+	__p;								\
+})
+
 static __inline __pure2 struct thread *
 __curthread(void)
 {
@@ -89,10 +160,11 @@
  * XXX The implementation of this operation should be made atomic
  * with respect to preemption.
  */
-#define	PCPU_ADD(member, value)	(pcpup->pc_ ## member += (value))
+#define	PCPU_GET(member)	__PCPU_GET(pc_ ## member)
+#define	PCPU_ADD(member, value)	PCPU_SET(member, PCPU_GET(member) + (value))
 #define	PCPU_INC(member)	PCPU_ADD(member, 1)
-#define	PCPU_PTR(member)	(&pcpup->pc_ ## member)
-#define	PCPU_SET(member,value)	(pcpup->pc_ ## member = (value))
+#define	PCPU_PTR(member)	__PCPU_PTR(pc_ ## member)
+#define	PCPU_SET(member,value)	__PCPU_SET(pc_ ## member, (value))
 
 #endif	/* _KERNEL */
 

--wRRV7LY7NUeQGEoC--



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