[patch 08/16] Bogomips calculation for 64 bit.



From: Martin Schwidefsky <schwidefsky@xxxxxxxxxx>

The bogomips calculation triggered via reading from /proc/cpuinfo
can return incorrect values if the qrnnd assembly is called with a
pointer in %r2 with any of the upper 32 bits set.
Fix this by using 64 bit division / remainder operation provided by
gcc instead of calling the assembly.

Signed-off-by: Martin Schwidefsky <schwidefsky@xxxxxxxxxx>
---

arch/s390/lib/Makefile | 4 ++--
include/asm-s390/sfp-machine.h | 6 +++---
include/asm-s390/sfp-util.h | 11 +++++++++++
3 files changed, 16 insertions(+), 5 deletions(-)

Index: quilt-2.6/arch/s390/lib/Makefile
===================================================================
--- quilt-2.6.orig/arch/s390/lib/Makefile
+++ quilt-2.6/arch/s390/lib/Makefile
@@ -4,7 +4,7 @@

EXTRA_AFLAGS := -traditional

-lib-y += delay.o string.o uaccess_std.o uaccess_pt.o qrnnd.o
-obj-$(CONFIG_32BIT) += div64.o
+lib-y += delay.o string.o uaccess_std.o uaccess_pt.o
+obj-$(CONFIG_32BIT) += div64.o qrnnd.o
lib-$(CONFIG_64BIT) += uaccess_mvcos.o
lib-$(CONFIG_SMP) += spinlock.o
Index: quilt-2.6/include/asm-s390/sfp-machine.h
===================================================================
--- quilt-2.6.orig/include/asm-s390/sfp-machine.h
+++ quilt-2.6/include/asm-s390/sfp-machine.h
@@ -27,9 +27,9 @@


#define _FP_W_TYPE_SIZE 32
-#define _FP_W_TYPE unsigned long
-#define _FP_WS_TYPE signed long
-#define _FP_I_TYPE long
+#define _FP_W_TYPE unsigned int
+#define _FP_WS_TYPE signed int
+#define _FP_I_TYPE int

#define _FP_MUL_MEAT_S(R,X,Y) \
_FP_MUL_MEAT_1_wide(_FP_WFRACBITS_S,R,X,Y,umul_ppmm)
Index: quilt-2.6/include/asm-s390/sfp-util.h
===================================================================
--- quilt-2.6.orig/include/asm-s390/sfp-util.h
+++ quilt-2.6/include/asm-s390/sfp-util.h
@@ -51,6 +51,16 @@
wl = __wl; \
})

+#ifdef __s390x__
+#define udiv_qrnnd(q, r, n1, n0, d) \
+ do { unsigned long __n; \
+ unsigned int __r, __d; \
+ __n = ((unsigned long)(n1) << 32) + n0; \
+ __d = (d); \
+ (q) = __n / __d; \
+ (r) = __n % __d; \
+ } while (0)
+#else
#define udiv_qrnnd(q, r, n1, n0, d) \
do { unsigned int __r; \
(q) = __udiv_qrnnd (&__r, (n1), (n0), (d)); \
@@ -58,6 +68,7 @@
} while (0)
extern unsigned long __udiv_qrnnd (unsigned int *, unsigned int,
unsigned int , unsigned int);
+#endif

#define UDIV_NEEDS_NORMALIZATION 0


--
blue skies,
Martin.

"Reality continues to ruin my life." - Calvin.

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/



Relevant Pages

  • Re: mb-gcc producing incorrect code ???
    ... Only if you stick to doing permitted things, and writing to an object ... of one size and reading it via an pointer to an object of another size ... unsigned int dword; ...
    (comp.arch.fpga)
  • Re: Unions Redux
    ... pointer casting. ... union U {double a; unsigned int b;} u; ... valid and aliasing rules don't work here. ...
    (comp.lang.c)
  • Re: Initializer element not constant
    ... unsigned int, which I assume is 32 bits, would cause a nasty run-time ... problem, since first if any of the upper 32 bits of the pointer are 1, ... an object of this type with static storage duration you are trying to ... So your compiler, with one set of options, is quite free to reject ...
    (comp.lang.c)
  • Re: still nfs problems [Was: Linux 2.6.37-rc8]
    ... through both the direct and the virtual mapping. ... unsigned int npages) ... * Check if the input buffer is long enough to enable us to decode ... * If so return the current pointer without updating the current ...
    (Linux-Kernel)
  • Re: unsigned __int64 typecast bug?
    ... The typecast does the correct thing for an unsigned int, ... I don't know if the conversion sequence from 32 bit pointer to 64 bit ... The compiler will sign-extend the pointer when it is assigned ...
    (microsoft.public.vc.language)