diff options
Diffstat (limited to 'arch/s390')
-rw-r--r-- | arch/s390/Kconfig | 8 | ||||
-rw-r--r-- | arch/s390/include/asm/atomic.h | 7 | ||||
-rw-r--r-- | arch/s390/include/asm/kvm_host.h | 4 | ||||
-rw-r--r-- | arch/s390/include/asm/perf_counter.h | 2 | ||||
-rw-r--r-- | arch/s390/include/asm/thread_info.h | 2 | ||||
-rw-r--r-- | arch/s390/kernel/ipl.c | 15 | ||||
-rw-r--r-- | arch/s390/kvm/kvm-s390.c | 23 | ||||
-rw-r--r-- | arch/s390/kvm/priv.c | 2 | ||||
-rw-r--r-- | arch/s390/lib/Makefile | 2 | ||||
-rw-r--r-- | arch/s390/lib/delay.c | 2 | ||||
-rw-r--r-- | arch/s390/lib/ucmpdi2.c | 26 |
11 files changed, 81 insertions, 12 deletions
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index e577839f3073..2ae5d72f47ed 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig | |||
@@ -95,6 +95,11 @@ config S390 | |||
95 | select HAVE_ARCH_TRACEHOOK | 95 | select HAVE_ARCH_TRACEHOOK |
96 | select INIT_ALL_POSSIBLE | 96 | select INIT_ALL_POSSIBLE |
97 | select HAVE_PERF_COUNTERS | 97 | select HAVE_PERF_COUNTERS |
98 | select GENERIC_ATOMIC64 if !64BIT | ||
99 | |||
100 | config SCHED_OMIT_FRAME_POINTER | ||
101 | bool | ||
102 | default y | ||
98 | 103 | ||
99 | source "init/Kconfig" | 104 | source "init/Kconfig" |
100 | 105 | ||
@@ -116,6 +121,9 @@ config 32BIT | |||
116 | bool | 121 | bool |
117 | default y if !64BIT | 122 | default y if !64BIT |
118 | 123 | ||
124 | config KTIME_SCALAR | ||
125 | def_bool 32BIT | ||
126 | |||
119 | config SMP | 127 | config SMP |
120 | bool "Symmetric multi-processing support" | 128 | bool "Symmetric multi-processing support" |
121 | ---help--- | 129 | ---help--- |
diff --git a/arch/s390/include/asm/atomic.h b/arch/s390/include/asm/atomic.h index fca9dffcc669..c7d0abfb0f00 100644 --- a/arch/s390/include/asm/atomic.h +++ b/arch/s390/include/asm/atomic.h | |||
@@ -268,7 +268,12 @@ static __inline__ int atomic64_add_unless(atomic64_t *v, | |||
268 | #define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0) | 268 | #define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0) |
269 | 269 | ||
270 | #undef __CSG_LOOP | 270 | #undef __CSG_LOOP |
271 | #endif | 271 | |
272 | #else /* __s390x__ */ | ||
273 | |||
274 | #include <asm-generic/atomic64.h> | ||
275 | |||
276 | #endif /* __s390x__ */ | ||
272 | 277 | ||
273 | #define smp_mb__before_atomic_dec() smp_mb() | 278 | #define smp_mb__before_atomic_dec() smp_mb() |
274 | #define smp_mb__after_atomic_dec() smp_mb() | 279 | #define smp_mb__after_atomic_dec() smp_mb() |
diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h index a27d0d5a6f86..1cd02f6073a0 100644 --- a/arch/s390/include/asm/kvm_host.h +++ b/arch/s390/include/asm/kvm_host.h | |||
@@ -99,7 +99,9 @@ struct kvm_s390_sie_block { | |||
99 | __u8 reservedd0[48]; /* 0x00d0 */ | 99 | __u8 reservedd0[48]; /* 0x00d0 */ |
100 | __u64 gcr[16]; /* 0x0100 */ | 100 | __u64 gcr[16]; /* 0x0100 */ |
101 | __u64 gbea; /* 0x0180 */ | 101 | __u64 gbea; /* 0x0180 */ |
102 | __u8 reserved188[120]; /* 0x0188 */ | 102 | __u8 reserved188[24]; /* 0x0188 */ |
103 | __u32 fac; /* 0x01a0 */ | ||
104 | __u8 reserved1a4[92]; /* 0x01a4 */ | ||
103 | } __attribute__((packed)); | 105 | } __attribute__((packed)); |
104 | 106 | ||
105 | struct kvm_vcpu_stat { | 107 | struct kvm_vcpu_stat { |
diff --git a/arch/s390/include/asm/perf_counter.h b/arch/s390/include/asm/perf_counter.h index a7205a3828cb..7015188c2cc2 100644 --- a/arch/s390/include/asm/perf_counter.h +++ b/arch/s390/include/asm/perf_counter.h | |||
@@ -6,3 +6,5 @@ | |||
6 | 6 | ||
7 | static inline void set_perf_counter_pending(void) {} | 7 | static inline void set_perf_counter_pending(void) {} |
8 | static inline void clear_perf_counter_pending(void) {} | 8 | static inline void clear_perf_counter_pending(void) {} |
9 | |||
10 | #define PERF_COUNTER_INDEX_OFFSET 0 | ||
diff --git a/arch/s390/include/asm/thread_info.h b/arch/s390/include/asm/thread_info.h index 925bcc649035..ba1cab9fc1f9 100644 --- a/arch/s390/include/asm/thread_info.h +++ b/arch/s390/include/asm/thread_info.h | |||
@@ -61,7 +61,7 @@ struct thread_info { | |||
61 | .exec_domain = &default_exec_domain, \ | 61 | .exec_domain = &default_exec_domain, \ |
62 | .flags = 0, \ | 62 | .flags = 0, \ |
63 | .cpu = 0, \ | 63 | .cpu = 0, \ |
64 | .preempt_count = 1, \ | 64 | .preempt_count = INIT_PREEMPT_COUNT, \ |
65 | .restart_block = { \ | 65 | .restart_block = { \ |
66 | .fn = do_no_restart_syscall, \ | 66 | .fn = do_no_restart_syscall, \ |
67 | }, \ | 67 | }, \ |
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c index b8bf4b140065..371a2d88f4ac 100644 --- a/arch/s390/kernel/ipl.c +++ b/arch/s390/kernel/ipl.c | |||
@@ -70,6 +70,7 @@ struct shutdown_action { | |||
70 | char *name; | 70 | char *name; |
71 | void (*fn) (struct shutdown_trigger *trigger); | 71 | void (*fn) (struct shutdown_trigger *trigger); |
72 | int (*init) (void); | 72 | int (*init) (void); |
73 | int init_rc; | ||
73 | }; | 74 | }; |
74 | 75 | ||
75 | static char *ipl_type_str(enum ipl_type type) | 76 | static char *ipl_type_str(enum ipl_type type) |
@@ -1486,11 +1487,13 @@ static int set_trigger(const char *buf, struct shutdown_trigger *trigger, | |||
1486 | int i; | 1487 | int i; |
1487 | 1488 | ||
1488 | for (i = 0; i < SHUTDOWN_ACTIONS_COUNT; i++) { | 1489 | for (i = 0; i < SHUTDOWN_ACTIONS_COUNT; i++) { |
1489 | if (!shutdown_actions_list[i]) | ||
1490 | continue; | ||
1491 | if (sysfs_streq(buf, shutdown_actions_list[i]->name)) { | 1490 | if (sysfs_streq(buf, shutdown_actions_list[i]->name)) { |
1492 | trigger->action = shutdown_actions_list[i]; | 1491 | if (shutdown_actions_list[i]->init_rc) { |
1493 | return len; | 1492 | return shutdown_actions_list[i]->init_rc; |
1493 | } else { | ||
1494 | trigger->action = shutdown_actions_list[i]; | ||
1495 | return len; | ||
1496 | } | ||
1494 | } | 1497 | } |
1495 | } | 1498 | } |
1496 | return -EINVAL; | 1499 | return -EINVAL; |
@@ -1640,8 +1643,8 @@ static void __init shutdown_actions_init(void) | |||
1640 | for (i = 0; i < SHUTDOWN_ACTIONS_COUNT; i++) { | 1643 | for (i = 0; i < SHUTDOWN_ACTIONS_COUNT; i++) { |
1641 | if (!shutdown_actions_list[i]->init) | 1644 | if (!shutdown_actions_list[i]->init) |
1642 | continue; | 1645 | continue; |
1643 | if (shutdown_actions_list[i]->init()) | 1646 | shutdown_actions_list[i]->init_rc = |
1644 | shutdown_actions_list[i] = NULL; | 1647 | shutdown_actions_list[i]->init(); |
1645 | } | 1648 | } |
1646 | } | 1649 | } |
1647 | 1650 | ||
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index c18b21d6991c..90d9d1ba258b 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <asm/lowcore.h> | 25 | #include <asm/lowcore.h> |
26 | #include <asm/pgtable.h> | 26 | #include <asm/pgtable.h> |
27 | #include <asm/nmi.h> | 27 | #include <asm/nmi.h> |
28 | #include <asm/system.h> | ||
28 | #include "kvm-s390.h" | 29 | #include "kvm-s390.h" |
29 | #include "gaccess.h" | 30 | #include "gaccess.h" |
30 | 31 | ||
@@ -69,6 +70,7 @@ struct kvm_stats_debugfs_item debugfs_entries[] = { | |||
69 | { NULL } | 70 | { NULL } |
70 | }; | 71 | }; |
71 | 72 | ||
73 | static unsigned long long *facilities; | ||
72 | 74 | ||
73 | /* Section: not file related */ | 75 | /* Section: not file related */ |
74 | void kvm_arch_hardware_enable(void *garbage) | 76 | void kvm_arch_hardware_enable(void *garbage) |
@@ -288,6 +290,7 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu) | |||
288 | vcpu->arch.sie_block->gmsor = vcpu->kvm->arch.guest_origin; | 290 | vcpu->arch.sie_block->gmsor = vcpu->kvm->arch.guest_origin; |
289 | vcpu->arch.sie_block->ecb = 2; | 291 | vcpu->arch.sie_block->ecb = 2; |
290 | vcpu->arch.sie_block->eca = 0xC1002001U; | 292 | vcpu->arch.sie_block->eca = 0xC1002001U; |
293 | vcpu->arch.sie_block->fac = (int) (long) facilities; | ||
291 | hrtimer_init(&vcpu->arch.ckc_timer, CLOCK_REALTIME, HRTIMER_MODE_ABS); | 294 | hrtimer_init(&vcpu->arch.ckc_timer, CLOCK_REALTIME, HRTIMER_MODE_ABS); |
292 | tasklet_init(&vcpu->arch.tasklet, kvm_s390_tasklet, | 295 | tasklet_init(&vcpu->arch.tasklet, kvm_s390_tasklet, |
293 | (unsigned long) vcpu); | 296 | (unsigned long) vcpu); |
@@ -739,11 +742,29 @@ gfn_t unalias_gfn(struct kvm *kvm, gfn_t gfn) | |||
739 | 742 | ||
740 | static int __init kvm_s390_init(void) | 743 | static int __init kvm_s390_init(void) |
741 | { | 744 | { |
742 | return kvm_init(NULL, sizeof(struct kvm_vcpu), THIS_MODULE); | 745 | int ret; |
746 | ret = kvm_init(NULL, sizeof(struct kvm_vcpu), THIS_MODULE); | ||
747 | if (ret) | ||
748 | return ret; | ||
749 | |||
750 | /* | ||
751 | * guests can ask for up to 255+1 double words, we need a full page | ||
752 | * to hold the maximum amount of facilites. On the other hand, we | ||
753 | * only set facilities that are known to work in KVM. | ||
754 | */ | ||
755 | facilities = (unsigned long long *) get_zeroed_page(GFP_DMA); | ||
756 | if (!facilities) { | ||
757 | kvm_exit(); | ||
758 | return -ENOMEM; | ||
759 | } | ||
760 | stfle(facilities, 1); | ||
761 | facilities[0] &= 0xff00fff3f0700000ULL; | ||
762 | return 0; | ||
743 | } | 763 | } |
744 | 764 | ||
745 | static void __exit kvm_s390_exit(void) | 765 | static void __exit kvm_s390_exit(void) |
746 | { | 766 | { |
767 | free_page((unsigned long) facilities); | ||
747 | kvm_exit(); | 768 | kvm_exit(); |
748 | } | 769 | } |
749 | 770 | ||
diff --git a/arch/s390/kvm/priv.c b/arch/s390/kvm/priv.c index 93ecd06e1a74..d426aac8095d 100644 --- a/arch/s390/kvm/priv.c +++ b/arch/s390/kvm/priv.c | |||
@@ -158,7 +158,7 @@ static int handle_stfl(struct kvm_vcpu *vcpu) | |||
158 | 158 | ||
159 | vcpu->stat.instruction_stfl++; | 159 | vcpu->stat.instruction_stfl++; |
160 | /* only pass the facility bits, which we can handle */ | 160 | /* only pass the facility bits, which we can handle */ |
161 | facility_list &= 0xfe00fff3; | 161 | facility_list &= 0xff00fff3; |
162 | 162 | ||
163 | rc = copy_to_guest(vcpu, offsetof(struct _lowcore, stfl_fac_list), | 163 | rc = copy_to_guest(vcpu, offsetof(struct _lowcore, stfl_fac_list), |
164 | &facility_list, sizeof(facility_list)); | 164 | &facility_list, sizeof(facility_list)); |
diff --git a/arch/s390/lib/Makefile b/arch/s390/lib/Makefile index ab6735df2d21..97975ec7a274 100644 --- a/arch/s390/lib/Makefile +++ b/arch/s390/lib/Makefile | |||
@@ -3,6 +3,6 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | lib-y += delay.o string.o uaccess_std.o uaccess_pt.o | 5 | lib-y += delay.o string.o uaccess_std.o uaccess_pt.o |
6 | obj-$(CONFIG_32BIT) += div64.o qrnnd.o | 6 | obj-$(CONFIG_32BIT) += div64.o qrnnd.o ucmpdi2.o |
7 | lib-$(CONFIG_64BIT) += uaccess_mvcos.o | 7 | lib-$(CONFIG_64BIT) += uaccess_mvcos.o |
8 | lib-$(CONFIG_SMP) += spinlock.o | 8 | lib-$(CONFIG_SMP) += spinlock.o |
diff --git a/arch/s390/lib/delay.c b/arch/s390/lib/delay.c index 3f5f680726ed..97c1eca83cc2 100644 --- a/arch/s390/lib/delay.c +++ b/arch/s390/lib/delay.c | |||
@@ -36,9 +36,11 @@ static void __udelay_disabled(unsigned long usecs) | |||
36 | cr0 = (cr0_saved & 0xffff00e0) | 0x00000800; | 36 | cr0 = (cr0_saved & 0xffff00e0) | 0x00000800; |
37 | __ctl_load(cr0 , 0, 0); | 37 | __ctl_load(cr0 , 0, 0); |
38 | mask = psw_kernel_bits | PSW_MASK_WAIT | PSW_MASK_EXT; | 38 | mask = psw_kernel_bits | PSW_MASK_WAIT | PSW_MASK_EXT; |
39 | lockdep_off(); | ||
39 | trace_hardirqs_on(); | 40 | trace_hardirqs_on(); |
40 | __load_psw_mask(mask); | 41 | __load_psw_mask(mask); |
41 | local_irq_disable(); | 42 | local_irq_disable(); |
43 | lockdep_on(); | ||
42 | __ctl_load(cr0_saved, 0, 0); | 44 | __ctl_load(cr0_saved, 0, 0); |
43 | local_tick_enable(clock_saved); | 45 | local_tick_enable(clock_saved); |
44 | set_clock_comparator(S390_lowcore.clock_comparator); | 46 | set_clock_comparator(S390_lowcore.clock_comparator); |
diff --git a/arch/s390/lib/ucmpdi2.c b/arch/s390/lib/ucmpdi2.c new file mode 100644 index 000000000000..3e05ff532582 --- /dev/null +++ b/arch/s390/lib/ucmpdi2.c | |||
@@ -0,0 +1,26 @@ | |||
1 | #include <linux/module.h> | ||
2 | |||
3 | union ull_union { | ||
4 | unsigned long long ull; | ||
5 | struct { | ||
6 | unsigned int high; | ||
7 | unsigned int low; | ||
8 | } ui; | ||
9 | }; | ||
10 | |||
11 | int __ucmpdi2(unsigned long long a, unsigned long long b) | ||
12 | { | ||
13 | union ull_union au = {.ull = a}; | ||
14 | union ull_union bu = {.ull = b}; | ||
15 | |||
16 | if (au.ui.high < bu.ui.high) | ||
17 | return 0; | ||
18 | else if (au.ui.high > bu.ui.high) | ||
19 | return 2; | ||
20 | if (au.ui.low < bu.ui.low) | ||
21 | return 0; | ||
22 | else if (au.ui.low > bu.ui.low) | ||
23 | return 2; | ||
24 | return 1; | ||
25 | } | ||
26 | EXPORT_SYMBOL(__ucmpdi2); | ||