Skip to content

Commit

Permalink
[S390] Calibrate delay and bogomips.
Browse files Browse the repository at this point in the history
Preset the bogomips number to the cpu capacity value reported by
store system information in SYSIB 1.2.2. This value is constant
for a particular machine model and can be used to determine
relative performance differences between machines.

Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
  • Loading branch information
Martin Schwidefsky committed Feb 5, 2007
1 parent 31cb4bd commit 31ee4b2
Show file tree
Hide file tree
Showing 11 changed files with 149 additions and 88 deletions.
4 changes: 0 additions & 4 deletions arch/s390/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,6 @@ config GENERIC_HWEIGHT
bool
default y

config GENERIC_CALIBRATE_DELAY
bool
default y

config GENERIC_TIME
def_bool y

Expand Down
1 change: 1 addition & 0 deletions arch/s390/kernel/setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -938,6 +938,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
struct cpuinfo_S390 *cpuinfo;
unsigned long n = (unsigned long) v - 1;

s390_adjust_jiffies();
preempt_disable();
if (!n) {
seq_printf(m, "vendor_id : IBM/S390\n"
Expand Down
2 changes: 1 addition & 1 deletion arch/s390/lib/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

EXTRA_AFLAGS := -traditional

lib-y += delay.o string.o uaccess_std.o uaccess_pt.o
lib-y += delay.o string.o uaccess_std.o uaccess_pt.o qrnnd.o
lib-$(CONFIG_32BIT) += div64.o
lib-$(CONFIG_64BIT) += uaccess_mvcos.o
lib-$(CONFIG_SMP) += spinlock.o
77 changes: 77 additions & 0 deletions arch/s390/lib/qrnnd.S
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# S/390 __udiv_qrnnd

# r2 : &__r
# r3 : upper half of 64 bit word n
# r4 : lower half of 64 bit word n
# r5 : divisor d
# the reminder r of the division is to be stored to &__r and
# the quotient q is to be returned

.text
.globl __udiv_qrnnd
__udiv_qrnnd:
st %r2,24(%r15) # store pointer to reminder for later
lr %r0,%r3 # reload n
lr %r1,%r4
ltr %r2,%r5 # reload and test divisor
jp 5f
# divisor >= 0x80000000
srdl %r0,2 # n/4
srl %r2,1 # d/2
slr %r1,%r2 # special case if last bit of d is set
brc 3,0f # (n/4) div (n/2) can overflow by 1
ahi %r0,-1 # trick: subtract n/2, then divide
0: dr %r0,%r2 # signed division
ahi %r1,1 # trick part 2: add 1 to the quotient
# now (n >> 2) = (d >> 1) * %r1 + %r0
lhi %r3,1
nr %r3,%r1 # test last bit of q
jz 1f
alr %r0,%r2 # add (d>>1) to r
1: srl %r1,1 # q >>= 1
# now (n >> 2) = (d&-2) * %r1 + %r0
lhi %r3,1
nr %r3,%r5 # test last bit of d
jz 2f
slr %r0,%r1 # r -= q
brc 3,2f # borrow ?
alr %r0,%r5 # r += d
ahi %r1,-1
2: # now (n >> 2) = d * %r1 + %r0
alr %r1,%r1 # q <<= 1
alr %r0,%r0 # r <<= 1
brc 12,3f # overflow on r ?
slr %r0,%r5 # r -= d
ahi %r1,1 # q += 1
3: lhi %r3,2
nr %r3,%r4 # test next to last bit of n
jz 4f
ahi %r0,1 # r += 1
4: clr %r0,%r5 # r >= d ?
jl 6f
slr %r0,%r5 # r -= d
ahi %r1,1 # q += 1
# now (n >> 1) = d * %r1 + %r0
j 6f
5: # divisor < 0x80000000
srdl %r0,1
dr %r0,%r2 # signed division
# now (n >> 1) = d * %r1 + %r0
6: alr %r1,%r1 # q <<= 1
alr %r0,%r0 # r <<= 1
brc 12,7f # overflow on r ?
slr %r0,%r5 # r -= d
ahi %r1,1 # q += 1
7: lhi %r3,1
nr %r3,%r4 # isolate last bit of n
alr %r0,%r3 # r += (n & 1)
clr %r0,%r5 # r >= d ?
jl 8f
slr %r0,%r5 # r -= d
ahi %r1,1 # q += 1
8: # now n = d * %r1 + %r0
l %r2,24(%r15)
st %r0,0(%r2)
lr %r2,%r1
br %r14
.end __udiv_qrnnd
2 changes: 1 addition & 1 deletion arch/s390/math-emu/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# Makefile for the FPU instruction emulation.
#

obj-$(CONFIG_MATHEMU) := math.o qrnnd.o
obj-$(CONFIG_MATHEMU) := math.o

EXTRA_CFLAGS := -I$(src) -Iinclude/math-emu -w
EXTRA_AFLAGS := -traditional
2 changes: 1 addition & 1 deletion arch/s390/math-emu/math.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
#include <asm/uaccess.h>
#include <asm/lowcore.h>

#include "sfp-util.h"
#include <asm/sfp-util.h>
#include <math-emu/soft-fp.h>
#include <math-emu/single.h>
#include <math-emu/double.h>
Expand Down
77 changes: 0 additions & 77 deletions arch/s390/math-emu/qrnnd.S

This file was deleted.

2 changes: 2 additions & 0 deletions drivers/s390/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
# Makefile for the S/390 specific device drivers
#

CFLAGS_sysinfo.o += -Iinclude/math-emu -Iarch/s390/math-emu -w

obj-y += s390mach.o sysinfo.o s390_rdev.o
obj-y += cio/ block/ char/ crypto/ net/ scsi/

Expand Down
63 changes: 62 additions & 1 deletion drivers/s390/sysinfo.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,14 @@
#include <linux/mm.h>
#include <linux/proc_fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <asm/ebcdic.h>

/* Sigh, math-emu. Don't ask. */
#include <asm/sfp-util.h>
#include <math-emu/soft-fp.h>
#include <math-emu/single.h>

struct sysinfo_1_1_1 {
char reserved_0[32];
char manufacturer[16];
Expand Down Expand Up @@ -198,7 +204,7 @@ static int stsi_1_2_2(struct sysinfo_1_2_2 *info, char *page, int len)
* if the higher order 8 bits are not zero. Printing
* a floating point number in the kernel is a no-no,
* always print the number as 32 bit unsigned integer.
* The user-space needs to know about the stange
* The user-space needs to know about the strange
* encoding of the alternate cpu capability.
*/
len += sprintf(page + len, "Capability: %u %u\n",
Expand Down Expand Up @@ -351,3 +357,58 @@ static __init int create_proc_sysinfo(void)

__initcall(create_proc_sysinfo);

/*
* CPU capability might have changed. Therefore recalculate loops_per_jiffy.
*/
void s390_adjust_jiffies(void)
{
struct sysinfo_1_2_2 *info;
const unsigned int fmil = 0x4b189680; /* 1e7 as 32-bit float. */
FP_DECL_S(SA); FP_DECL_S(SB); FP_DECL_S(SR);
FP_DECL_EX;
unsigned int capability;

info = (void *) get_zeroed_page(GFP_KERNEL);
if (!info)
return;

if (stsi(info, 1, 2, 2) != -ENOSYS) {
/*
* Major sigh. The cpu capability encoding is "special".
* If the first 9 bits of info->capability are 0 then it
* is a 32 bit unsigned integer in the range 0 .. 2^23.
* If the first 9 bits are != 0 then it is a 32 bit float.
* In addition a lower value indicates a proportionally
* higher cpu capacity. Bogomips are the other way round.
* To get to a halfway suitable number we divide 1e7
* by the cpu capability number. Yes, that means a floating
* point division .. math-emu here we come :-)
*/
FP_UNPACK_SP(SA, &fmil);
if ((info->capability >> 23) == 0)
FP_FROM_INT_S(SB, info->capability, 32, int);
else
FP_UNPACK_SP(SB, &info->capability);
FP_DIV_S(SR, SA, SB);
FP_TO_INT_S(capability, SR, 32, 0);
} else
/*
* Really old machine without stsi block for basic
* cpu information. Report 42.0 bogomips.
*/
capability = 42;
loops_per_jiffy = capability * (500000/HZ);
free_page((unsigned long) info);
}

/*
* calibrate the delay loop
*/
void __init calibrate_delay(void)
{
s390_adjust_jiffies();
/* Print the good old Bogomips line .. */
printk(KERN_DEBUG "Calibrating delay loop (skipped)... "
"%lu.%02lu BogoMIPS preset\n", loops_per_jiffy/(500000/HZ),
(loops_per_jiffy/(5000/HZ)) % 100);
}
1 change: 1 addition & 0 deletions include/asm-s390/processor.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ struct cpuinfo_S390
unsigned long pgtable_cache_sz;
};

extern void s390_adjust_jiffies(void);
extern void print_cpu_info(struct cpuinfo_S390 *);

/* Lazy FPU handling on uni-processor */
Expand Down
6 changes: 3 additions & 3 deletions arch/s390/math-emu/sfp-util.h → include/asm-s390/sfp-util.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,12 @@
})

#define udiv_qrnnd(q, r, n1, n0, d) \
do { unsigned long __r; \
do { unsigned int __r; \
(q) = __udiv_qrnnd (&__r, (n1), (n0), (d)); \
(r) = __r; \
} while (0)
extern unsigned long __udiv_qrnnd (unsigned long *, unsigned long,
unsigned long , unsigned long);
extern unsigned long __udiv_qrnnd (unsigned int *, unsigned int,
unsigned int , unsigned int);

#define UDIV_NEEDS_NORMALIZATION 0

Expand Down

0 comments on commit 31ee4b2

Please sign in to comment.