diff options
author | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2007-02-05 15:18:31 -0500 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2007-02-05 15:18:31 -0500 |
commit | 31ee4b2f40994e8b21691f85cdd4052551a789b7 (patch) | |
tree | 1bb167e720e25a2ea9a5168b21cc882f85b18fa8 | |
parent | 31cb4bd31a48f62105d037ad53192b94d4c08f53 (diff) |
[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>
-rw-r--r-- | arch/s390/Kconfig | 4 | ||||
-rw-r--r-- | arch/s390/kernel/setup.c | 1 | ||||
-rw-r--r-- | arch/s390/lib/Makefile | 2 | ||||
-rw-r--r-- | arch/s390/lib/qrnnd.S | 77 | ||||
-rw-r--r-- | arch/s390/math-emu/Makefile | 2 | ||||
-rw-r--r-- | arch/s390/math-emu/math.c | 2 | ||||
-rw-r--r-- | arch/s390/math-emu/qrnnd.S | 77 | ||||
-rw-r--r-- | drivers/s390/Makefile | 2 | ||||
-rw-r--r-- | drivers/s390/sysinfo.c | 63 | ||||
-rw-r--r-- | include/asm-s390/processor.h | 1 | ||||
-rw-r--r-- | include/asm-s390/sfp-util.h (renamed from arch/s390/math-emu/sfp-util.h) | 6 |
11 files changed, 149 insertions, 88 deletions
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index 5c7e981c115b..eaed402ad346 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig | |||
@@ -34,10 +34,6 @@ config GENERIC_HWEIGHT | |||
34 | bool | 34 | bool |
35 | default y | 35 | default y |
36 | 36 | ||
37 | config GENERIC_CALIBRATE_DELAY | ||
38 | bool | ||
39 | default y | ||
40 | |||
41 | config GENERIC_TIME | 37 | config GENERIC_TIME |
42 | def_bool y | 38 | def_bool y |
43 | 39 | ||
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index 2569aafcc543..2fa866f6f711 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c | |||
@@ -938,6 +938,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) | |||
938 | struct cpuinfo_S390 *cpuinfo; | 938 | struct cpuinfo_S390 *cpuinfo; |
939 | unsigned long n = (unsigned long) v - 1; | 939 | unsigned long n = (unsigned long) v - 1; |
940 | 940 | ||
941 | s390_adjust_jiffies(); | ||
941 | preempt_disable(); | 942 | preempt_disable(); |
942 | if (!n) { | 943 | if (!n) { |
943 | seq_printf(m, "vendor_id : IBM/S390\n" | 944 | seq_printf(m, "vendor_id : IBM/S390\n" |
diff --git a/arch/s390/lib/Makefile b/arch/s390/lib/Makefile index b5f94cf3bde8..7a44fed21b35 100644 --- a/arch/s390/lib/Makefile +++ b/arch/s390/lib/Makefile | |||
@@ -4,7 +4,7 @@ | |||
4 | 4 | ||
5 | EXTRA_AFLAGS := -traditional | 5 | EXTRA_AFLAGS := -traditional |
6 | 6 | ||
7 | lib-y += delay.o string.o uaccess_std.o uaccess_pt.o | 7 | lib-y += delay.o string.o uaccess_std.o uaccess_pt.o qrnnd.o |
8 | lib-$(CONFIG_32BIT) += div64.o | 8 | lib-$(CONFIG_32BIT) += div64.o |
9 | lib-$(CONFIG_64BIT) += uaccess_mvcos.o | 9 | lib-$(CONFIG_64BIT) += uaccess_mvcos.o |
10 | lib-$(CONFIG_SMP) += spinlock.o | 10 | lib-$(CONFIG_SMP) += spinlock.o |
diff --git a/arch/s390/lib/qrnnd.S b/arch/s390/lib/qrnnd.S new file mode 100644 index 000000000000..eb1df632e749 --- /dev/null +++ b/arch/s390/lib/qrnnd.S | |||
@@ -0,0 +1,77 @@ | |||
1 | # S/390 __udiv_qrnnd | ||
2 | |||
3 | # r2 : &__r | ||
4 | # r3 : upper half of 64 bit word n | ||
5 | # r4 : lower half of 64 bit word n | ||
6 | # r5 : divisor d | ||
7 | # the reminder r of the division is to be stored to &__r and | ||
8 | # the quotient q is to be returned | ||
9 | |||
10 | .text | ||
11 | .globl __udiv_qrnnd | ||
12 | __udiv_qrnnd: | ||
13 | st %r2,24(%r15) # store pointer to reminder for later | ||
14 | lr %r0,%r3 # reload n | ||
15 | lr %r1,%r4 | ||
16 | ltr %r2,%r5 # reload and test divisor | ||
17 | jp 5f | ||
18 | # divisor >= 0x80000000 | ||
19 | srdl %r0,2 # n/4 | ||
20 | srl %r2,1 # d/2 | ||
21 | slr %r1,%r2 # special case if last bit of d is set | ||
22 | brc 3,0f # (n/4) div (n/2) can overflow by 1 | ||
23 | ahi %r0,-1 # trick: subtract n/2, then divide | ||
24 | 0: dr %r0,%r2 # signed division | ||
25 | ahi %r1,1 # trick part 2: add 1 to the quotient | ||
26 | # now (n >> 2) = (d >> 1) * %r1 + %r0 | ||
27 | lhi %r3,1 | ||
28 | nr %r3,%r1 # test last bit of q | ||
29 | jz 1f | ||
30 | alr %r0,%r2 # add (d>>1) to r | ||
31 | 1: srl %r1,1 # q >>= 1 | ||
32 | # now (n >> 2) = (d&-2) * %r1 + %r0 | ||
33 | lhi %r3,1 | ||
34 | nr %r3,%r5 # test last bit of d | ||
35 | jz 2f | ||
36 | slr %r0,%r1 # r -= q | ||
37 | brc 3,2f # borrow ? | ||
38 | alr %r0,%r5 # r += d | ||
39 | ahi %r1,-1 | ||
40 | 2: # now (n >> 2) = d * %r1 + %r0 | ||
41 | alr %r1,%r1 # q <<= 1 | ||
42 | alr %r0,%r0 # r <<= 1 | ||
43 | brc 12,3f # overflow on r ? | ||
44 | slr %r0,%r5 # r -= d | ||
45 | ahi %r1,1 # q += 1 | ||
46 | 3: lhi %r3,2 | ||
47 | nr %r3,%r4 # test next to last bit of n | ||
48 | jz 4f | ||
49 | ahi %r0,1 # r += 1 | ||
50 | 4: clr %r0,%r5 # r >= d ? | ||
51 | jl 6f | ||
52 | slr %r0,%r5 # r -= d | ||
53 | ahi %r1,1 # q += 1 | ||
54 | # now (n >> 1) = d * %r1 + %r0 | ||
55 | j 6f | ||
56 | 5: # divisor < 0x80000000 | ||
57 | srdl %r0,1 | ||
58 | dr %r0,%r2 # signed division | ||
59 | # now (n >> 1) = d * %r1 + %r0 | ||
60 | 6: alr %r1,%r1 # q <<= 1 | ||
61 | alr %r0,%r0 # r <<= 1 | ||
62 | brc 12,7f # overflow on r ? | ||
63 | slr %r0,%r5 # r -= d | ||
64 | ahi %r1,1 # q += 1 | ||
65 | 7: lhi %r3,1 | ||
66 | nr %r3,%r4 # isolate last bit of n | ||
67 | alr %r0,%r3 # r += (n & 1) | ||
68 | clr %r0,%r5 # r >= d ? | ||
69 | jl 8f | ||
70 | slr %r0,%r5 # r -= d | ||
71 | ahi %r1,1 # q += 1 | ||
72 | 8: # now n = d * %r1 + %r0 | ||
73 | l %r2,24(%r15) | ||
74 | st %r0,0(%r2) | ||
75 | lr %r2,%r1 | ||
76 | br %r14 | ||
77 | .end __udiv_qrnnd | ||
diff --git a/arch/s390/math-emu/Makefile b/arch/s390/math-emu/Makefile index c10df144f2ab..73b3e72efc46 100644 --- a/arch/s390/math-emu/Makefile +++ b/arch/s390/math-emu/Makefile | |||
@@ -2,7 +2,7 @@ | |||
2 | # Makefile for the FPU instruction emulation. | 2 | # Makefile for the FPU instruction emulation. |
3 | # | 3 | # |
4 | 4 | ||
5 | obj-$(CONFIG_MATHEMU) := math.o qrnnd.o | 5 | obj-$(CONFIG_MATHEMU) := math.o |
6 | 6 | ||
7 | EXTRA_CFLAGS := -I$(src) -Iinclude/math-emu -w | 7 | EXTRA_CFLAGS := -I$(src) -Iinclude/math-emu -w |
8 | EXTRA_AFLAGS := -traditional | 8 | EXTRA_AFLAGS := -traditional |
diff --git a/arch/s390/math-emu/math.c b/arch/s390/math-emu/math.c index 6b9aec5a2c18..3ee78ccb617d 100644 --- a/arch/s390/math-emu/math.c +++ b/arch/s390/math-emu/math.c | |||
@@ -15,7 +15,7 @@ | |||
15 | #include <asm/uaccess.h> | 15 | #include <asm/uaccess.h> |
16 | #include <asm/lowcore.h> | 16 | #include <asm/lowcore.h> |
17 | 17 | ||
18 | #include "sfp-util.h" | 18 | #include <asm/sfp-util.h> |
19 | #include <math-emu/soft-fp.h> | 19 | #include <math-emu/soft-fp.h> |
20 | #include <math-emu/single.h> | 20 | #include <math-emu/single.h> |
21 | #include <math-emu/double.h> | 21 | #include <math-emu/double.h> |
diff --git a/arch/s390/math-emu/qrnnd.S b/arch/s390/math-emu/qrnnd.S deleted file mode 100644 index b01c2b648e22..000000000000 --- a/arch/s390/math-emu/qrnnd.S +++ /dev/null | |||
@@ -1,77 +0,0 @@ | |||
1 | # S/390 __udiv_qrnnd | ||
2 | |||
3 | # r2 : &__r | ||
4 | # r3 : upper half of 64 bit word n | ||
5 | # r4 : lower half of 64 bit word n | ||
6 | # r5 : divisor d | ||
7 | # the reminder r of the division is to be stored to &__r and | ||
8 | # the quotient q is to be returned | ||
9 | |||
10 | .text | ||
11 | .globl __udiv_qrnnd | ||
12 | __udiv_qrnnd: | ||
13 | st %r2,24(%r15) # store pointer to reminder for later | ||
14 | lr %r0,%r3 # reload n | ||
15 | lr %r1,%r4 | ||
16 | ltr %r2,%r5 # reload and test divisor | ||
17 | jp 5f | ||
18 | # divisor >= 0x80000000 | ||
19 | srdl %r0,2 # n/4 | ||
20 | srl %r2,1 # d/2 | ||
21 | slr %r1,%r2 # special case if last bit of d is set | ||
22 | brc 3,0f # (n/4) div (n/2) can overflow by 1 | ||
23 | ahi %r0,-1 # trick: subtract n/2, then divide | ||
24 | 0: dr %r0,%r2 # signed division | ||
25 | ahi %r1,1 # trick part 2: add 1 to the quotient | ||
26 | # now (n >> 2) = (d >> 1) * %r1 + %r0 | ||
27 | lhi %r3,1 | ||
28 | nr %r3,%r1 # test last bit of q | ||
29 | jz 1f | ||
30 | alr %r0,%r2 # add (d>>1) to r | ||
31 | 1: srl %r1,1 # q >>= 1 | ||
32 | # now (n >> 2) = (d&-2) * %r1 + %r0 | ||
33 | lhi %r3,1 | ||
34 | nr %r3,%r5 # test last bit of d | ||
35 | jz 2f | ||
36 | slr %r0,%r1 # r -= q | ||
37 | brc 3,2f # borrow ? | ||
38 | alr %r0,%r5 # r += d | ||
39 | ahi %r1,-1 | ||
40 | 2: # now (n >> 2) = d * %r1 + %r0 | ||
41 | alr %r1,%r1 # q <<= 1 | ||
42 | alr %r0,%r0 # r <<= 1 | ||
43 | brc 12,3f # overflow on r ? | ||
44 | slr %r0,%r5 # r -= d | ||
45 | ahi %r1,1 # q += 1 | ||
46 | 3: lhi %r3,2 | ||
47 | nr %r3,%r4 # test next to last bit of n | ||
48 | jz 4f | ||
49 | ahi %r0,1 # r += 1 | ||
50 | 4: clr %r0,%r5 # r >= d ? | ||
51 | jl 6f | ||
52 | slr %r0,%r5 # r -= d | ||
53 | ahi %r1,1 # q += 1 | ||
54 | # now (n >> 1) = d * %r1 + %r0 | ||
55 | j 6f | ||
56 | 5: # divisor < 0x80000000 | ||
57 | srdl %r0,1 | ||
58 | dr %r0,%r2 # signed division | ||
59 | # now (n >> 1) = d * %r1 + %r0 | ||
60 | 6: alr %r1,%r1 # q <<= 1 | ||
61 | alr %r0,%r0 # r <<= 1 | ||
62 | brc 12,7f # overflow on r ? | ||
63 | slr %r0,%r5 # r -= d | ||
64 | ahi %r1,1 # q += 1 | ||
65 | 7: lhi %r3,1 | ||
66 | nr %r3,%r4 # isolate last bit of n | ||
67 | alr %r0,%r3 # r += (n & 1) | ||
68 | clr %r0,%r5 # r >= d ? | ||
69 | jl 8f | ||
70 | slr %r0,%r5 # r -= d | ||
71 | ahi %r1,1 # q += 1 | ||
72 | 8: # now n = d * %r1 + %r0 | ||
73 | l %r2,24(%r15) | ||
74 | st %r0,0(%r2) | ||
75 | lr %r2,%r1 | ||
76 | br %r14 | ||
77 | .end __udiv_qrnnd | ||
diff --git a/drivers/s390/Makefile b/drivers/s390/Makefile index 9803c9352d78..5a888704a8d0 100644 --- a/drivers/s390/Makefile +++ b/drivers/s390/Makefile | |||
@@ -2,6 +2,8 @@ | |||
2 | # Makefile for the S/390 specific device drivers | 2 | # Makefile for the S/390 specific device drivers |
3 | # | 3 | # |
4 | 4 | ||
5 | CFLAGS_sysinfo.o += -Iinclude/math-emu -Iarch/s390/math-emu -w | ||
6 | |||
5 | obj-y += s390mach.o sysinfo.o s390_rdev.o | 7 | obj-y += s390mach.o sysinfo.o s390_rdev.o |
6 | obj-y += cio/ block/ char/ crypto/ net/ scsi/ | 8 | obj-y += cio/ block/ char/ crypto/ net/ scsi/ |
7 | 9 | ||
diff --git a/drivers/s390/sysinfo.c b/drivers/s390/sysinfo.c index 1e788e815ce7..090743d2f914 100644 --- a/drivers/s390/sysinfo.c +++ b/drivers/s390/sysinfo.c | |||
@@ -9,8 +9,14 @@ | |||
9 | #include <linux/mm.h> | 9 | #include <linux/mm.h> |
10 | #include <linux/proc_fs.h> | 10 | #include <linux/proc_fs.h> |
11 | #include <linux/init.h> | 11 | #include <linux/init.h> |
12 | #include <linux/delay.h> | ||
12 | #include <asm/ebcdic.h> | 13 | #include <asm/ebcdic.h> |
13 | 14 | ||
15 | /* Sigh, math-emu. Don't ask. */ | ||
16 | #include <asm/sfp-util.h> | ||
17 | #include <math-emu/soft-fp.h> | ||
18 | #include <math-emu/single.h> | ||
19 | |||
14 | struct sysinfo_1_1_1 { | 20 | struct sysinfo_1_1_1 { |
15 | char reserved_0[32]; | 21 | char reserved_0[32]; |
16 | char manufacturer[16]; | 22 | char manufacturer[16]; |
@@ -198,7 +204,7 @@ static int stsi_1_2_2(struct sysinfo_1_2_2 *info, char *page, int len) | |||
198 | * if the higher order 8 bits are not zero. Printing | 204 | * if the higher order 8 bits are not zero. Printing |
199 | * a floating point number in the kernel is a no-no, | 205 | * a floating point number in the kernel is a no-no, |
200 | * always print the number as 32 bit unsigned integer. | 206 | * always print the number as 32 bit unsigned integer. |
201 | * The user-space needs to know about the stange | 207 | * The user-space needs to know about the strange |
202 | * encoding of the alternate cpu capability. | 208 | * encoding of the alternate cpu capability. |
203 | */ | 209 | */ |
204 | len += sprintf(page + len, "Capability: %u %u\n", | 210 | len += sprintf(page + len, "Capability: %u %u\n", |
@@ -351,3 +357,58 @@ static __init int create_proc_sysinfo(void) | |||
351 | 357 | ||
352 | __initcall(create_proc_sysinfo); | 358 | __initcall(create_proc_sysinfo); |
353 | 359 | ||
360 | /* | ||
361 | * CPU capability might have changed. Therefore recalculate loops_per_jiffy. | ||
362 | */ | ||
363 | void s390_adjust_jiffies(void) | ||
364 | { | ||
365 | struct sysinfo_1_2_2 *info; | ||
366 | const unsigned int fmil = 0x4b189680; /* 1e7 as 32-bit float. */ | ||
367 | FP_DECL_S(SA); FP_DECL_S(SB); FP_DECL_S(SR); | ||
368 | FP_DECL_EX; | ||
369 | unsigned int capability; | ||
370 | |||
371 | info = (void *) get_zeroed_page(GFP_KERNEL); | ||
372 | if (!info) | ||
373 | return; | ||
374 | |||
375 | if (stsi(info, 1, 2, 2) != -ENOSYS) { | ||
376 | /* | ||
377 | * Major sigh. The cpu capability encoding is "special". | ||
378 | * If the first 9 bits of info->capability are 0 then it | ||
379 | * is a 32 bit unsigned integer in the range 0 .. 2^23. | ||
380 | * If the first 9 bits are != 0 then it is a 32 bit float. | ||
381 | * In addition a lower value indicates a proportionally | ||
382 | * higher cpu capacity. Bogomips are the other way round. | ||
383 | * To get to a halfway suitable number we divide 1e7 | ||
384 | * by the cpu capability number. Yes, that means a floating | ||
385 | * point division .. math-emu here we come :-) | ||
386 | */ | ||
387 | FP_UNPACK_SP(SA, &fmil); | ||
388 | if ((info->capability >> 23) == 0) | ||
389 | FP_FROM_INT_S(SB, info->capability, 32, int); | ||
390 | else | ||
391 | FP_UNPACK_SP(SB, &info->capability); | ||
392 | FP_DIV_S(SR, SA, SB); | ||
393 | FP_TO_INT_S(capability, SR, 32, 0); | ||
394 | } else | ||
395 | /* | ||
396 | * Really old machine without stsi block for basic | ||
397 | * cpu information. Report 42.0 bogomips. | ||
398 | */ | ||
399 | capability = 42; | ||
400 | loops_per_jiffy = capability * (500000/HZ); | ||
401 | free_page((unsigned long) info); | ||
402 | } | ||
403 | |||
404 | /* | ||
405 | * calibrate the delay loop | ||
406 | */ | ||
407 | void __init calibrate_delay(void) | ||
408 | { | ||
409 | s390_adjust_jiffies(); | ||
410 | /* Print the good old Bogomips line .. */ | ||
411 | printk(KERN_DEBUG "Calibrating delay loop (skipped)... " | ||
412 | "%lu.%02lu BogoMIPS preset\n", loops_per_jiffy/(500000/HZ), | ||
413 | (loops_per_jiffy/(5000/HZ)) % 100); | ||
414 | } | ||
diff --git a/include/asm-s390/processor.h b/include/asm-s390/processor.h index 5af853576cbd..cf71c5449240 100644 --- a/include/asm-s390/processor.h +++ b/include/asm-s390/processor.h | |||
@@ -50,6 +50,7 @@ struct cpuinfo_S390 | |||
50 | unsigned long pgtable_cache_sz; | 50 | unsigned long pgtable_cache_sz; |
51 | }; | 51 | }; |
52 | 52 | ||
53 | extern void s390_adjust_jiffies(void); | ||
53 | extern void print_cpu_info(struct cpuinfo_S390 *); | 54 | extern void print_cpu_info(struct cpuinfo_S390 *); |
54 | 55 | ||
55 | /* Lazy FPU handling on uni-processor */ | 56 | /* Lazy FPU handling on uni-processor */ |
diff --git a/arch/s390/math-emu/sfp-util.h b/include/asm-s390/sfp-util.h index 5b6ca4570ea4..8cabcd23d976 100644 --- a/arch/s390/math-emu/sfp-util.h +++ b/include/asm-s390/sfp-util.h | |||
@@ -52,12 +52,12 @@ | |||
52 | }) | 52 | }) |
53 | 53 | ||
54 | #define udiv_qrnnd(q, r, n1, n0, d) \ | 54 | #define udiv_qrnnd(q, r, n1, n0, d) \ |
55 | do { unsigned long __r; \ | 55 | do { unsigned int __r; \ |
56 | (q) = __udiv_qrnnd (&__r, (n1), (n0), (d)); \ | 56 | (q) = __udiv_qrnnd (&__r, (n1), (n0), (d)); \ |
57 | (r) = __r; \ | 57 | (r) = __r; \ |
58 | } while (0) | 58 | } while (0) |
59 | extern unsigned long __udiv_qrnnd (unsigned long *, unsigned long, | 59 | extern unsigned long __udiv_qrnnd (unsigned int *, unsigned int, |
60 | unsigned long , unsigned long); | 60 | unsigned int , unsigned int); |
61 | 61 | ||
62 | #define UDIV_NEEDS_NORMALIZATION 0 | 62 | #define UDIV_NEEDS_NORMALIZATION 0 |
63 | 63 | ||