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>