aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/include
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390/include')
-rw-r--r--arch/s390/include/asm/ap.h21
-rw-r--r--arch/s390/include/asm/ctlreg.h24
-rw-r--r--arch/s390/include/asm/facility.h6
-rw-r--r--arch/s390/include/asm/fpu/api.h35
-rw-r--r--arch/s390/include/asm/fpu/internal.h10
-rw-r--r--arch/s390/include/asm/irq_work.h2
-rw-r--r--arch/s390/include/asm/jump_label.h4
-rw-r--r--arch/s390/include/asm/kvm_host.h2
-rw-r--r--arch/s390/include/asm/pci_io.h32
-rw-r--r--arch/s390/include/asm/pgtable.h1
-rw-r--r--arch/s390/include/asm/processor.h34
-rw-r--r--arch/s390/include/asm/setup.h2
-rw-r--r--arch/s390/include/asm/sysinfo.h4
13 files changed, 113 insertions, 64 deletions
diff --git a/arch/s390/include/asm/ap.h b/arch/s390/include/asm/ap.h
index 40c2b82f083a..43ac4a64f49b 100644
--- a/arch/s390/include/asm/ap.h
+++ b/arch/s390/include/asm/ap.h
@@ -88,7 +88,7 @@ static inline bool ap_instructions_available(void)
}
/* TAPQ register GR2 response struct */
-struct ap_tapq_gr2 {
+struct ap_tapq_hwinfo {
union {
unsigned long value;
struct {
@@ -96,11 +96,13 @@ struct ap_tapq_gr2 {
unsigned int apinfo : 32; /* ap type, ... */
};
struct {
- unsigned int s : 1; /* APSC */
- unsigned int m : 1; /* AP4KM */
- unsigned int c : 1; /* AP4KC */
- unsigned int mode : 3;
- unsigned int n : 1; /* APXA */
+ unsigned int apsc : 1; /* APSC */
+ unsigned int mex4k : 1; /* AP4KM */
+ unsigned int crt4k : 1; /* AP4KC */
+ unsigned int cca : 1; /* D */
+ unsigned int accel : 1; /* A */
+ unsigned int ep11 : 1; /* X */
+ unsigned int apxa : 1; /* APXA */
unsigned int : 1;
unsigned int class : 8;
unsigned int bs : 2; /* SE bind/assoc */
@@ -126,11 +128,12 @@ struct ap_tapq_gr2 {
/**
* ap_tapq(): Test adjunct processor queue.
* @qid: The AP queue number
- * @info: Pointer to queue descriptor
+ * @info: Pointer to tapq hwinfo struct
*
* Returns AP queue status structure.
*/
-static inline struct ap_queue_status ap_tapq(ap_qid_t qid, struct ap_tapq_gr2 *info)
+static inline struct ap_queue_status ap_tapq(ap_qid_t qid,
+ struct ap_tapq_hwinfo *info)
{
union ap_queue_status_reg reg1;
unsigned long reg2;
@@ -158,7 +161,7 @@ static inline struct ap_queue_status ap_tapq(ap_qid_t qid, struct ap_tapq_gr2 *i
* Returns AP queue status structure.
*/
static inline struct ap_queue_status ap_test_queue(ap_qid_t qid, int tbit,
- struct ap_tapq_gr2 *info)
+ struct ap_tapq_hwinfo *info)
{
if (tbit)
qid |= 1UL << 23; /* set T bit*/
diff --git a/arch/s390/include/asm/ctlreg.h b/arch/s390/include/asm/ctlreg.h
index 6d4b85f2b541..72a9556d04f3 100644
--- a/arch/s390/include/asm/ctlreg.h
+++ b/arch/s390/include/asm/ctlreg.h
@@ -141,22 +141,26 @@ static __always_inline void local_ctl_store(unsigned int cr, struct ctlreg *reg)
: [cr] "i" (cr));
}
-static __always_inline void local_ctl_set_bit(unsigned int cr, unsigned int bit)
+static __always_inline struct ctlreg local_ctl_set_bit(unsigned int cr, unsigned int bit)
{
- struct ctlreg reg;
+ struct ctlreg new, old;
- local_ctl_store(cr, &reg);
- reg.val |= 1UL << bit;
- local_ctl_load(cr, &reg);
+ local_ctl_store(cr, &old);
+ new = old;
+ new.val |= 1UL << bit;
+ local_ctl_load(cr, &new);
+ return old;
}
-static __always_inline void local_ctl_clear_bit(unsigned int cr, unsigned int bit)
+static __always_inline struct ctlreg local_ctl_clear_bit(unsigned int cr, unsigned int bit)
{
- struct ctlreg reg;
+ struct ctlreg new, old;
- local_ctl_store(cr, &reg);
- reg.val &= ~(1UL << bit);
- local_ctl_load(cr, &reg);
+ local_ctl_store(cr, &old);
+ new = old;
+ new.val &= ~(1UL << bit);
+ local_ctl_load(cr, &new);
+ return old;
}
struct lowcore;
diff --git a/arch/s390/include/asm/facility.h b/arch/s390/include/asm/facility.h
index 94b6919026df..796007125dff 100644
--- a/arch/s390/include/asm/facility.h
+++ b/arch/s390/include/asm/facility.h
@@ -111,4 +111,10 @@ static inline void stfle(u64 *stfle_fac_list, int size)
preempt_enable();
}
+/**
+ * stfle_size - Actual size of the facility list as specified by stfle
+ * (number of double words)
+ */
+unsigned int stfle_size(void);
+
#endif /* __ASM_FACILITY_H */
diff --git a/arch/s390/include/asm/fpu/api.h b/arch/s390/include/asm/fpu/api.h
index 9acf48e53a87..d6ca8bc6ca68 100644
--- a/arch/s390/include/asm/fpu/api.h
+++ b/arch/s390/include/asm/fpu/api.h
@@ -46,26 +46,33 @@
#include <linux/preempt.h>
#include <asm/asm-extable.h>
+#include <asm/fpu/internal.h>
void save_fpu_regs(void);
void load_fpu_regs(void);
void __load_fpu_regs(void);
-static inline int test_fp_ctl(u32 fpc)
+/**
+ * sfpc_safe - Set floating point control register safely.
+ * @fpc: new value for floating point control register
+ *
+ * Set floating point control register. This may lead to an exception,
+ * since a saved value may have been modified by user space (ptrace,
+ * signal return, kvm registers) to an invalid value. In such a case
+ * set the floating point control register to zero.
+ */
+static inline void sfpc_safe(u32 fpc)
{
- u32 orig_fpc;
- int rc;
-
- asm volatile(
- " efpc %1\n"
- " sfpc %2\n"
- "0: sfpc %1\n"
- " la %0,0\n"
- "1:\n"
- EX_TABLE(0b,1b)
- : "=d" (rc), "=&d" (orig_fpc)
- : "d" (fpc), "0" (-EINVAL));
- return rc;
+ asm volatile("\n"
+ "0: sfpc %[fpc]\n"
+ "1: nopr %%r7\n"
+ ".pushsection .fixup, \"ax\"\n"
+ "2: lghi %[fpc],0\n"
+ " jg 0b\n"
+ ".popsection\n"
+ EX_TABLE(1b, 2b)
+ : [fpc] "+d" (fpc)
+ : : "memory");
}
#define KERNEL_FPC 1
diff --git a/arch/s390/include/asm/fpu/internal.h b/arch/s390/include/asm/fpu/internal.h
index 8634581b9011..d511c4cf5afb 100644
--- a/arch/s390/include/asm/fpu/internal.h
+++ b/arch/s390/include/asm/fpu/internal.h
@@ -10,8 +10,14 @@
#define _ASM_S390_FPU_INTERNAL_H
#include <linux/string.h>
+#include <asm/facility.h>
#include <asm/fpu/types.h>
+static inline bool cpu_has_vx(void)
+{
+ return likely(test_facility(129));
+}
+
static inline void save_vx_regs(__vector128 *vxrs)
{
asm volatile(
@@ -41,7 +47,7 @@ static inline void fpregs_store(_s390_fp_regs *fpregs, struct fpu *fpu)
{
fpregs->pad = 0;
fpregs->fpc = fpu->fpc;
- if (MACHINE_HAS_VX)
+ if (cpu_has_vx())
convert_vx_to_fp((freg_t *)&fpregs->fprs, fpu->vxrs);
else
memcpy((freg_t *)&fpregs->fprs, fpu->fprs,
@@ -51,7 +57,7 @@ static inline void fpregs_store(_s390_fp_regs *fpregs, struct fpu *fpu)
static inline void fpregs_load(_s390_fp_regs *fpregs, struct fpu *fpu)
{
fpu->fpc = fpregs->fpc;
- if (MACHINE_HAS_VX)
+ if (cpu_has_vx())
convert_fp_to_vx(fpu->vxrs, (freg_t *)&fpregs->fprs);
else
memcpy(fpu->fprs, (freg_t *)&fpregs->fprs,
diff --git a/arch/s390/include/asm/irq_work.h b/arch/s390/include/asm/irq_work.h
index 603783766d0a..f00c9f610d5a 100644
--- a/arch/s390/include/asm/irq_work.h
+++ b/arch/s390/include/asm/irq_work.h
@@ -7,6 +7,4 @@ static inline bool arch_irq_work_has_interrupt(void)
return true;
}
-void arch_irq_work_raise(void);
-
#endif /* _ASM_S390_IRQ_WORK_H */
diff --git a/arch/s390/include/asm/jump_label.h b/arch/s390/include/asm/jump_label.h
index 895f774bbcc5..bf78cf381dfc 100644
--- a/arch/s390/include/asm/jump_label.h
+++ b/arch/s390/include/asm/jump_label.h
@@ -25,7 +25,7 @@
*/
static __always_inline bool arch_static_branch(struct static_key *key, bool branch)
{
- asm_volatile_goto("0: brcl 0,%l[label]\n"
+ asm goto("0: brcl 0,%l[label]\n"
".pushsection __jump_table,\"aw\"\n"
".balign 8\n"
".long 0b-.,%l[label]-.\n"
@@ -39,7 +39,7 @@ label:
static __always_inline bool arch_static_branch_jump(struct static_key *key, bool branch)
{
- asm_volatile_goto("0: brcl 15,%l[label]\n"
+ asm goto("0: brcl 15,%l[label]\n"
".pushsection __jump_table,\"aw\"\n"
".balign 8\n"
".long 0b-.,%l[label]-.\n"
diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h
index 67a298b6cf6e..52664105a473 100644
--- a/arch/s390/include/asm/kvm_host.h
+++ b/arch/s390/include/asm/kvm_host.h
@@ -818,7 +818,7 @@ struct s390_io_adapter {
struct kvm_s390_cpu_model {
/* facility mask supported by kvm & hosting machine */
- __u64 fac_mask[S390_ARCH_FAC_LIST_SIZE_U64];
+ __u64 fac_mask[S390_ARCH_FAC_MASK_SIZE_U64];
struct kvm_s390_vm_cpu_subfunc subfuncs;
/* facility list requested by guest (in dma page) */
__u64 *fac_list;
diff --git a/arch/s390/include/asm/pci_io.h b/arch/s390/include/asm/pci_io.h
index 287bb88f7698..2686bee800e3 100644
--- a/arch/s390/include/asm/pci_io.h
+++ b/arch/s390/include/asm/pci_io.h
@@ -11,6 +11,8 @@
/* I/O size constraints */
#define ZPCI_MAX_READ_SIZE 8
#define ZPCI_MAX_WRITE_SIZE 128
+#define ZPCI_BOUNDARY_SIZE (1 << 12)
+#define ZPCI_BOUNDARY_MASK (ZPCI_BOUNDARY_SIZE - 1)
/* I/O Map */
#define ZPCI_IOMAP_SHIFT 48
@@ -125,16 +127,18 @@ out:
int zpci_write_block(volatile void __iomem *dst, const void *src,
unsigned long len);
-static inline u8 zpci_get_max_write_size(u64 src, u64 dst, int len, int max)
+static inline int zpci_get_max_io_size(u64 src, u64 dst, int len, int max)
{
- int count = len > max ? max : len, size = 1;
+ int offset = dst & ZPCI_BOUNDARY_MASK;
+ int size;
- while (!(src & 0x1) && !(dst & 0x1) && ((size << 1) <= count)) {
- dst = dst >> 1;
- src = src >> 1;
- size = size << 1;
- }
- return size;
+ size = min3(len, ZPCI_BOUNDARY_SIZE - offset, max);
+ if (IS_ALIGNED(src, 8) && IS_ALIGNED(dst, 8) && IS_ALIGNED(size, 8))
+ return size;
+
+ if (size >= 8)
+ return 8;
+ return rounddown_pow_of_two(size);
}
static inline int zpci_memcpy_fromio(void *dst,
@@ -144,9 +148,9 @@ static inline int zpci_memcpy_fromio(void *dst,
int size, rc = 0;
while (n > 0) {
- size = zpci_get_max_write_size((u64 __force) src,
- (u64) dst, n,
- ZPCI_MAX_READ_SIZE);
+ size = zpci_get_max_io_size((u64 __force) src,
+ (u64) dst, n,
+ ZPCI_MAX_READ_SIZE);
rc = zpci_read_single(dst, src, size);
if (rc)
break;
@@ -166,9 +170,9 @@ static inline int zpci_memcpy_toio(volatile void __iomem *dst,
return -EINVAL;
while (n > 0) {
- size = zpci_get_max_write_size((u64 __force) dst,
- (u64) src, n,
- ZPCI_MAX_WRITE_SIZE);
+ size = zpci_get_max_io_size((u64 __force) dst,
+ (u64) src, n,
+ ZPCI_MAX_WRITE_SIZE);
if (size > 8) /* main path */
rc = zpci_write_block(dst, src, size);
else
diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h
index 601e87fa8a9a..1299b56e43f6 100644
--- a/arch/s390/include/asm/pgtable.h
+++ b/arch/s390/include/asm/pgtable.h
@@ -770,6 +770,7 @@ static inline int pud_write(pud_t pud)
return (pud_val(pud) & _REGION3_ENTRY_WRITE) != 0;
}
+#define pmd_dirty pmd_dirty
static inline int pmd_dirty(pmd_t pmd)
{
return (pmd_val(pmd) & _SEGMENT_ENTRY_DIRTY) != 0;
diff --git a/arch/s390/include/asm/processor.h b/arch/s390/include/asm/processor.h
index c15eadbb9983..c0b6e74d899a 100644
--- a/arch/s390/include/asm/processor.h
+++ b/arch/s390/include/asm/processor.h
@@ -184,11 +184,7 @@ struct thread_struct {
struct gs_cb *gs_cb; /* Current guarded storage cb */
struct gs_cb *gs_bc_cb; /* Broadcast guarded storage cb */
struct pgm_tdb trap_tdb; /* Transaction abort diagnose block */
- /*
- * Warning: 'fpu' is dynamically-sized. It *MUST* be at
- * the end.
- */
- struct fpu fpu; /* FP and VX register save area */
+ struct fpu fpu; /* FP and VX register save area */
};
/* Flag to disable transactions. */
@@ -331,14 +327,36 @@ static inline unsigned long __extract_psw(void)
return (((unsigned long) reg1) << 32) | ((unsigned long) reg2);
}
-static inline void local_mcck_enable(void)
+static inline unsigned long __local_mcck_save(void)
{
- __load_psw_mask(__extract_psw() | PSW_MASK_MCHECK);
+ unsigned long mask = __extract_psw();
+
+ __load_psw_mask(mask & ~PSW_MASK_MCHECK);
+ return mask & PSW_MASK_MCHECK;
+}
+
+#define local_mcck_save(mflags) \
+do { \
+ typecheck(unsigned long, mflags); \
+ mflags = __local_mcck_save(); \
+} while (0)
+
+static inline void local_mcck_restore(unsigned long mflags)
+{
+ unsigned long mask = __extract_psw();
+
+ mask &= ~PSW_MASK_MCHECK;
+ __load_psw_mask(mask | mflags);
}
static inline void local_mcck_disable(void)
{
- __load_psw_mask(__extract_psw() & ~PSW_MASK_MCHECK);
+ __local_mcck_save();
+}
+
+static inline void local_mcck_enable(void)
+{
+ __load_psw_mask(__extract_psw() | PSW_MASK_MCHECK);
}
/*
diff --git a/arch/s390/include/asm/setup.h b/arch/s390/include/asm/setup.h
index df316436d2e1..03bcaa8effb2 100644
--- a/arch/s390/include/asm/setup.h
+++ b/arch/s390/include/asm/setup.h
@@ -28,7 +28,6 @@
#define MACHINE_FLAG_TOPOLOGY BIT(10)
#define MACHINE_FLAG_TE BIT(11)
#define MACHINE_FLAG_TLB_LC BIT(12)
-#define MACHINE_FLAG_VX BIT(13)
#define MACHINE_FLAG_TLB_GUEST BIT(14)
#define MACHINE_FLAG_NX BIT(15)
#define MACHINE_FLAG_GS BIT(16)
@@ -90,7 +89,6 @@ extern unsigned long mio_wb_bit_mask;
#define MACHINE_HAS_TOPOLOGY (S390_lowcore.machine_flags & MACHINE_FLAG_TOPOLOGY)
#define MACHINE_HAS_TE (S390_lowcore.machine_flags & MACHINE_FLAG_TE)
#define MACHINE_HAS_TLB_LC (S390_lowcore.machine_flags & MACHINE_FLAG_TLB_LC)
-#define MACHINE_HAS_VX (S390_lowcore.machine_flags & MACHINE_FLAG_VX)
#define MACHINE_HAS_TLB_GUEST (S390_lowcore.machine_flags & MACHINE_FLAG_TLB_GUEST)
#define MACHINE_HAS_NX (S390_lowcore.machine_flags & MACHINE_FLAG_NX)
#define MACHINE_HAS_GS (S390_lowcore.machine_flags & MACHINE_FLAG_GS)
diff --git a/arch/s390/include/asm/sysinfo.h b/arch/s390/include/asm/sysinfo.h
index ab1c6316055c..edca5a751df4 100644
--- a/arch/s390/include/asm/sysinfo.h
+++ b/arch/s390/include/asm/sysinfo.h
@@ -40,6 +40,10 @@ struct sysinfo_1_1_1 {
unsigned int ncr;
unsigned int npr;
unsigned int ntr;
+ char reserved_3[4];
+ char model_var_cap[16];
+ unsigned int model_var_cap_rating;
+ unsigned int nvr;
};
struct sysinfo_1_2_1 {