Hello tech@ list!

With this diff, it becomes possible to build macppc kernel with
base-clang.  The default compiler for macppc is base-gcc.

rgc <rgci...@disroot.org> mailed the ppc@ list to report problems with
clang kernel, and got a working kernel with clang -Oz (to stop clang
inlining some functions in openfirm.c) and my modified ppc_mftb().
In this diff, I use __attribute__((noinline)) so I don't need -Oz.
I built my kernel with

# clang CC=clang COMPILER_VERSION=clang

because someone has already prepared the Makefile for macppc to pass
different flags when COMPILER_VERSION is clang.  I booted my clang
kernel and it worked well enough to build another kernel with the
same diff, but with gcc.

In the second half of the diff, I change ppc_mftb(), because
"mftb %0+1" doesn't always work in clang.  For example, clang can
put "=r"(tb) in register pair r27:r29, but 27+1 isn't 29.  I don't
know the syntax for the 2nd register of a pair, so I instead split
"=r"(tb) into 2 variables.  We use ppc_mftb() as timecounter.

(gcc and clang emit different machine code for "mftbu" and "mftb", but
both forms work for me.  "objdump -dlr obj/clock.o" ppc_mftb() would
show "mftb" from gcc or "mfspr" from clang.  Power ISA 2.03 says that
mfspr time base can't work on 601 or POWER3.  A few Old World Mac
models had PowerPC 601, but we only run on New World models.)

Is the ppc_mftb() change by itself OK to commit?

I am less sure about the first half of the diff, the noinline part.
I don't like the design of this code.  These functions call ofw_stack()
like

noinline int
OF_peer(int phandle)
{
        static struct ... args = ...;

        ofw_stack();
        args.phandle = phandle;
        if (openfirmware(&args) == -1)
                return 0;
        return args.sibling;
}

but ofw_stack() is assembly code that changes the cpu's msr, moves the
stack pointer %r1 to a different stack, copies the stack frame of
OF_peer() to this new stack, and hijacks the saved return address so
that, when OF_peer() returns, it switches back to the old stack and
restores the msr.  If clang inlines a function like OF_peer(), it no
longer has its own stack frame, so the return-hijack stops working.

We don't have retguard on powerpc, but if OF_peer() would use
retguard to protect its return address, then the return-hijack might
become impossible.

Perhaps the code should look like

        msr = do_something_to_msr();
        args.phandle = phandle;
        if (openfirmware(&args) == -1)
                ret = 0;
        else
                ret = args.sibling;
        ppc_mtmsr(msr);
        return ret;

and openfirmware() should do the stack-switching, but I have not yet
tried to make such a change.  (I suspect that we need the msr to
disable interrupts and protect the static args.)

After the diff, I put my dmesg; my iMac G3 isn't GENERIC.MP and
doesn't have radeondrm.  --George

Index: arch/macppc/macppc/openfirm.c
===================================================================
RCS file: /cvs/src/sys/arch/macppc/macppc/openfirm.c,v
retrieving revision 1.12
diff -u -p -r1.12 openfirm.c
--- arch/macppc/macppc/openfirm.c       3 Sep 2019 17:51:52 -0000       1.12
+++ arch/macppc/macppc/openfirm.c       11 Mar 2020 22:21:50 -0000
@@ -38,10 +38,13 @@
 
 #include <dev/ofw/openfirm.h>
 
+/* Callers of ofw_stack() must not be inline. */
+#define noinline __attribute__((noinline))
+
 extern void ofw_stack(void);
 extern void ofbcopy(const void *, void *, size_t);
 
-int
+noinline int
 OF_peer(int phandle)
 {
        static struct {
@@ -63,7 +66,7 @@ OF_peer(int phandle)
        return args.sibling;
 }
 
-int
+noinline int
 OF_child(int phandle)
 {
        static struct {
@@ -85,7 +88,7 @@ OF_child(int phandle)
        return args.child;
 }
 
-int
+noinline int
 OF_parent(int phandle)
 {
        static struct {
@@ -107,7 +110,7 @@ OF_parent(int phandle)
        return args.parent;
 }
 
-int
+noinline int
 OF_getproplen(int handle, char *prop)
 {
        static struct {
@@ -131,7 +134,7 @@ OF_getproplen(int handle, char *prop)
        return args.size;
 }
 
-int
+noinline int
 OF_getprop(int handle, char *prop, void *buf, int buflen)
 {
        static struct {
@@ -163,7 +166,7 @@ OF_getprop(int handle, char *prop, void 
        return args.size;
 }
 
-int
+noinline int
 OF_setprop(int handle, char *prop, const void *buf, int buflen)
 {
        static struct {
@@ -194,7 +197,7 @@ OF_setprop(int handle, char *prop, const
        return args.size;
 }
 
-int
+noinline int
 OF_nextprop(int handle, char *prop, void *nextprop)
 {
        static struct {
@@ -221,7 +224,7 @@ OF_nextprop(int handle, char *prop, void
        return args.flag;
 }
 
-int
+noinline int
 OF_interpret(char *cmd, int nreturns, ...)
 {
        va_list ap;
@@ -258,7 +261,7 @@ OF_interpret(char *cmd, int nreturns, ..
 }
 
 
-int
+noinline int
 OF_finddevice(char *name)
 {
        static struct {
@@ -281,7 +284,7 @@ OF_finddevice(char *name)
 }
 static void OF_rboot(char *bootspec);
 
-static void
+static noinline void
 OF_rboot(char *bootspec)
 {
        static struct {
@@ -312,7 +315,7 @@ OF_boot(char *bootspec)
        while(1);
 }
 
-void
+noinline void
 OF_exit(void)
 {
        static struct {
@@ -331,7 +334,7 @@ OF_exit(void)
        while (1);
 }
 
-void
+noinline void
 OF_quiesce(void)
 {
        static struct {
Index: arch/powerpc/include/cpu.h
===================================================================
RCS file: /cvs/src/sys/arch/powerpc/include/cpu.h,v
retrieving revision 1.65
diff -u -p -r1.65 cpu.h
--- arch/powerpc/include/cpu.h  23 Mar 2019 05:27:53 -0000      1.65
+++ arch/powerpc/include/cpu.h  11 Mar 2020 22:21:50 -0000
@@ -333,12 +333,11 @@ ppc_mftbl (void)
 static __inline u_int64_t
 ppc_mftb(void)
 {
-       u_long scratch;
-       u_int64_t tb;
+       u_long high, low, scratch;
 
-       __asm volatile ("1: mftbu %0; mftb %0+1; mftbu %1;"
-           " cmpw 0,%0,%1; bne 1b" : "=r"(tb), "=r"(scratch));
-       return tb;
+       __asm volatile ("1: mftbu %0; mftb %1; mftbu %2;"
+           " cmpw 0,%0,%2; bne 1b" : "=r"(high), "=r"(low), "=r"(scratch));
+       return ((u_int64_t)high << 32) | low;
 }
 
 static __inline void


[ using 1137300 bytes of bsd ELF symbol table ]
console out [ATY,Rage128k] console in [keyboard], using USB
: memaddr 94000000, size 4000000 : consaddr 94008000 : ioaddr 90020000, size 
20000: width 800 linebytes 1024 height 600 depth 8
Copyright (c) 1982, 1986, 1989, 1991, 1993
        The Regents of the University of California.  All rights reserved.
Copyright (c) 1995-2020 OpenBSD. All rights reserved.  https://www.OpenBSD.org

OpenBSD 6.6-current (GENERIC) #0: Fri Mar 13 21:18:43 EDT 2020
    r...@fishport.my.domain:/sys/arch/macppc/compile/GENERIC
real mem = 536870912 (512MB)
avail mem = 503971840 (480MB)
mpath0 at root
scsibus0 at mpath0: 256 targets
mainbus0 at root: model PowerMac2,1
cpu0 at mainbus0: 750 (Revision 0x202): 400 MHz: 512KB backside cache
mem0 at mainbus0
spdmem0 at mem0: 256MB SDRAM non-parity PC133CL2
spdmem1 at mem0: 256MB SDRAM non-parity PC133CL2
memc0 at mainbus0: uni-n rev 0x3
kiic0 at memc0 offset 0xf8001000
iic0 at kiic0
mpcpcibr0 at mainbus0 pci: uni-north
pci0 at mpcpcibr0 bus 0
pchb0 at pci0 dev 11 function 0 "Apple Uni-N AGP" rev 0x00
agp at pchb0 not configured
vgafb0 at pci0 dev 16 function 0 "ATI Rage 128" rev 0x00, mmio
wsdisplay0 at vgafb0 mux 1: console (std, vt100 emulation)
wsdisplay0: screen 1-5 added (std, vt100 emulation)
mpcpcibr1 at mainbus0 pci: uni-north
pci1 at mpcpcibr1 bus 0
macobio0 at pci1 dev 23 function 0 "Apple Keylargo" rev 0x02
openpic0 at macobio0 offset 0x40000: version 0x4614 feature 3f0302 LE
macgpio0 at macobio0 offset 0x50
macgpio1 at macgpio0: irq 47
pgs0 at macgpio0: irq 55
"escc-legacy" at macobio0 offset 0x12000 not configured
zs0 at macobio0 offset 0x13000: irq 22,50
zstty0 at zs0 channel 0
zstty1 at zs0 channel 1
awacs0 at macobio0 offset 0x14000: irq 24,9,10 speaker
audio0 at awacs0
"timer" at macobio0 offset 0x15000 not configured
adb0 at macobio0 offset 0x16000
apm0 at adb0: battery flags 0x9, 0% charged
kiic1 at macobio0 offset 0x18000
iic1 at kiic1
wdc0 at macobio0 offset 0x1f000 irq 19: DMA
wd0 at wdc0 channel 0 drive 0: <Maxtor 91020U3>
wd0: 16-sector PIO, LBA, 9736MB, 19941264 sectors
atapiscsi0 at wdc0 channel 0 drive 1
scsibus1 at atapiscsi0: 2 targets
cd0 at scsibus1 targ 0 lun 0: <MATSHITA, DVD-ROM SR-8184, AA27> removable
wd0(wdc0:0:0): using PIO mode 4, DMA mode 2, Ultra-DMA mode 2
cd0(wdc0:0:1): using PIO mode 4, DMA mode 2, Ultra-DMA mode 2
wdc1 at macobio0 offset 0x20000 irq 20: DMA
wdc2 at macobio0 offset 0x21000 irq 21: DMA
"TI TSB12LV23 FireWire" rev 0x00 at pci1 dev 18 function 0 not configured
ohci0 at pci1 dev 24 function 0 "Apple USB" rev 0x00: irq 27, version 1.0
ohci1 at pci1 dev 25 function 0 "Apple USB" rev 0x00: irq 28, version 1.0
usb0 at ohci0: USB revision 1.0
uhub0 at usb0 configuration 1 interface 0 "Apple OHCI root hub" rev 1.00/1.00 
addr 1
usb1 at ohci1: USB revision 1.0
uhub1 at usb1 configuration 1 interface 0 "Apple OHCI root hub" rev 1.00/1.00 
addr 1
mpcpcibr2 at mainbus0 pci: uni-north
pci2 at mpcpcibr2 bus 0
gem0 at pci2 dev 15 function 0 "Apple Uni-N GMAC" rev 0x00: irq 41, address 
00:0a:27:b1:66:00
bmtphy0 at gem0 phy 0: BCM5201 10/100 PHY, rev. 2
uhidev0 at uhub0 port 1 configuration 1 interface 0 "Logitech USB-PS/2 Optical 
Mouse" rev 2.00/11.10 addr 2
uhidev0: iclass 3/1
ums0 at uhidev0: 3 buttons, Z dir
wsmouse0 at ums0 mux 0
uhidev1 at uhub1 port 1 configuration 1 interface 0 "CHESEN USB Keyboard" rev 
1.10/1.10 addr 2
uhidev1: iclass 3/1
ukbd0 at uhidev1: 8 variable keys, 6 key codes, country code 33
wskbd0 at ukbd0: console keyboard, using wsdisplay0
uhidev2 at uhub1 port 1 configuration 1 interface 1 "CHESEN USB Keyboard" rev 
1.10/1.10 addr 2
uhidev2: iclass 3/0, 3 report ids
uhid0 at uhidev2 reportid 2: input=1, output=0, feature=0
uhid1 at uhidev2 reportid 3: input=3, output=0, feature=0
vscsi0 at root
scsibus2 at vscsi0: 256 targets
softraid0 at root
scsibus3 at softraid0: 256 targets
bootpath: /pci@f2000000/mac-io@17/ata-4@1f000/disk@0:/bsd
root on wd0a (c3db149b5ec148e9.a) swap on wd0b dump on wd0b

Reply via email to