[S390] Calibrate delay and bogomips.
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>
This commit is contained in:
parent
31cb4bd31a
commit
31ee4b2f40
|
@ -34,10 +34,6 @@ config GENERIC_HWEIGHT
|
|||
bool
|
||||
default y
|
||||
|
||||
config GENERIC_CALIBRATE_DELAY
|
||||
bool
|
||||
default y
|
||||
|
||||
config GENERIC_TIME
|
||||
def_bool y
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,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
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -1,77 +0,0 @@
|
|||
# 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,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/
|
||||
|
||||
|
|
|
@ -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];
|
||||
|
@ -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",
|
||||
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
Loading…
Reference in New Issue