Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux
Pull s390 updates from Martin Schwidefsky: "There are a couple of new things for s390 with this merge request: - a new scheduling domain "drawer" is added to reflect the unusual topology found on z13 machines. Performance tests showed up to 8 percent gain with the additional domain. - the new crc-32 checksum crypto module uses the vector-galois-field multiply and sum SIMD instruction to speed up crc-32 and crc-32c. - proper __ro_after_init support, this requires RO_AFTER_INIT_DATA in the generic vmlinux.lds linker script definitions. - kcov instrumentation support. A prerequisite for that is the inline assembly basic block cleanup, which is the reason for the net/iucv/iucv.c change. - support for 2GB pages is added to the hugetlbfs backend. Then there are two removals: - the oprofile hardware sampling support is dead code and is removed. The oprofile user space uses the perf interface nowadays. - the ETR clock synchronization is removed, this has been superseeded be the STP clock synchronization. And it always has been "interesting" code.. And the usual bug fixes and cleanups" * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux: (82 commits) s390/pci: Delete an unnecessary check before the function call "pci_dev_put" s390/smp: clean up a condition s390/cio/chp : Remove deprecated create_singlethread_workqueue s390/chsc: improve channel path descriptor determination s390/chsc: sanitize fmt check for chp_desc determination s390/cio: make fmt1 channel path descriptor optional s390/chsc: fix ioctl CHSC_INFO_CU command s390/cio/device_ops: fix kernel doc s390/cio: allow to reset channel measurement block s390/console: Make preferred console handling more consistent s390/mm: fix gmap tlb flush issues s390/mm: add support for 2GB hugepages s390: have unique symbol for __switch_to address s390/cpuinfo: show maximum thread id s390/ptrace: clarify bits in the per_struct s390: stack address vs thread_info s390: remove pointless load within __switch_to s390: enable kcov support s390/cpumf: use basic block for ecctr inline assembly s390/hypfs: use basic block for diag inline assembly ...
This commit is contained in:
@@ -13,9 +13,6 @@
|
||||
#define L1_CACHE_SHIFT 8
|
||||
#define NET_SKB_PAD 32
|
||||
|
||||
#define __read_mostly __attribute__((__section__(".data..read_mostly")))
|
||||
|
||||
/* Read-only memory is marked before mark_rodata_ro() is called. */
|
||||
#define __ro_after_init __read_mostly
|
||||
#define __read_mostly __section(.data..read_mostly)
|
||||
|
||||
#endif
|
||||
|
@@ -320,7 +320,7 @@ struct cio_iplinfo {
|
||||
extern int cio_get_iplinfo(struct cio_iplinfo *iplinfo);
|
||||
|
||||
/* Function from drivers/s390/cio/chsc.c */
|
||||
int chsc_sstpc(void *page, unsigned int op, u16 ctrl);
|
||||
int chsc_sstpc(void *page, unsigned int op, u16 ctrl, u64 *clock_delta);
|
||||
int chsc_sstpi(void *page, void *result, size_t size);
|
||||
|
||||
#endif
|
||||
|
@@ -169,16 +169,27 @@ static inline int lcctl(u64 ctl)
|
||||
}
|
||||
|
||||
/* Extract CPU counter */
|
||||
static inline int ecctr(u64 ctr, u64 *val)
|
||||
static inline int __ecctr(u64 ctr, u64 *content)
|
||||
{
|
||||
register u64 content asm("4") = 0;
|
||||
register u64 _content asm("4") = 0;
|
||||
int cc;
|
||||
|
||||
asm volatile (
|
||||
" .insn rre,0xb2e40000,%0,%2\n"
|
||||
" ipm %1\n"
|
||||
" srl %1,28\n"
|
||||
: "=d" (content), "=d" (cc) : "d" (ctr) : "cc");
|
||||
: "=d" (_content), "=d" (cc) : "d" (ctr) : "cc");
|
||||
*content = _content;
|
||||
return cc;
|
||||
}
|
||||
|
||||
/* Extract CPU counter */
|
||||
static inline int ecctr(u64 ctr, u64 *val)
|
||||
{
|
||||
u64 content;
|
||||
int cc;
|
||||
|
||||
cc = __ecctr(ctr, &content);
|
||||
if (!cc)
|
||||
*val = content;
|
||||
return cc;
|
||||
|
@@ -49,7 +49,7 @@ static inline void diag10_range(unsigned long start_pfn, unsigned long num_pfn)
|
||||
diag_stat_inc(DIAG_STAT_X010);
|
||||
asm volatile(
|
||||
"0: diag %0,%1,0x10\n"
|
||||
"1:\n"
|
||||
"1: nopr %%r7\n"
|
||||
EX_TABLE(0b, 1b)
|
||||
EX_TABLE(1b, 1b)
|
||||
: : "a" (start_addr), "a" (end_addr));
|
||||
|
@@ -1,261 +0,0 @@
|
||||
/*
|
||||
* Copyright IBM Corp. 2006
|
||||
* Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
|
||||
*/
|
||||
#ifndef __S390_ETR_H
|
||||
#define __S390_ETR_H
|
||||
|
||||
/* ETR attachment control register */
|
||||
struct etr_eacr {
|
||||
unsigned int e0 : 1; /* port 0 stepping control */
|
||||
unsigned int e1 : 1; /* port 1 stepping control */
|
||||
unsigned int _pad0 : 5; /* must be 00100 */
|
||||
unsigned int dp : 1; /* data port control */
|
||||
unsigned int p0 : 1; /* port 0 change recognition control */
|
||||
unsigned int p1 : 1; /* port 1 change recognition control */
|
||||
unsigned int _pad1 : 3; /* must be 000 */
|
||||
unsigned int ea : 1; /* ETR alert control */
|
||||
unsigned int es : 1; /* ETR sync check control */
|
||||
unsigned int sl : 1; /* switch to local control */
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* Port state returned by steai */
|
||||
enum etr_psc {
|
||||
etr_psc_operational = 0,
|
||||
etr_psc_semi_operational = 1,
|
||||
etr_psc_protocol_error = 4,
|
||||
etr_psc_no_symbols = 8,
|
||||
etr_psc_no_signal = 12,
|
||||
etr_psc_pps_mode = 13
|
||||
};
|
||||
|
||||
/* Logical port state returned by stetr */
|
||||
enum etr_lpsc {
|
||||
etr_lpsc_operational_step = 0,
|
||||
etr_lpsc_operational_alt = 1,
|
||||
etr_lpsc_semi_operational = 2,
|
||||
etr_lpsc_protocol_error = 4,
|
||||
etr_lpsc_no_symbol_sync = 8,
|
||||
etr_lpsc_no_signal = 12,
|
||||
etr_lpsc_pps_mode = 13
|
||||
};
|
||||
|
||||
/* ETR status words */
|
||||
struct etr_esw {
|
||||
struct etr_eacr eacr; /* attachment control register */
|
||||
unsigned int y : 1; /* stepping mode */
|
||||
unsigned int _pad0 : 5; /* must be 00000 */
|
||||
unsigned int p : 1; /* stepping port number */
|
||||
unsigned int q : 1; /* data port number */
|
||||
unsigned int psc0 : 4; /* port 0 state code */
|
||||
unsigned int psc1 : 4; /* port 1 state code */
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* Second level data register status word */
|
||||
struct etr_slsw {
|
||||
unsigned int vv1 : 1; /* copy of validity bit data frame 1 */
|
||||
unsigned int vv2 : 1; /* copy of validity bit data frame 2 */
|
||||
unsigned int vv3 : 1; /* copy of validity bit data frame 3 */
|
||||
unsigned int vv4 : 1; /* copy of validity bit data frame 4 */
|
||||
unsigned int _pad0 : 19; /* must by all zeroes */
|
||||
unsigned int n : 1; /* EAF port number */
|
||||
unsigned int v1 : 1; /* validity bit ETR data frame 1 */
|
||||
unsigned int v2 : 1; /* validity bit ETR data frame 2 */
|
||||
unsigned int v3 : 1; /* validity bit ETR data frame 3 */
|
||||
unsigned int v4 : 1; /* validity bit ETR data frame 4 */
|
||||
unsigned int _pad1 : 4; /* must be 0000 */
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* ETR data frames */
|
||||
struct etr_edf1 {
|
||||
unsigned int u : 1; /* untuned bit */
|
||||
unsigned int _pad0 : 1; /* must be 0 */
|
||||
unsigned int r : 1; /* service request bit */
|
||||
unsigned int _pad1 : 4; /* must be 0000 */
|
||||
unsigned int a : 1; /* time adjustment bit */
|
||||
unsigned int net_id : 8; /* ETR network id */
|
||||
unsigned int etr_id : 8; /* id of ETR which sends data frames */
|
||||
unsigned int etr_pn : 8; /* port number of ETR output port */
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct etr_edf2 {
|
||||
unsigned int etv : 32; /* Upper 32 bits of TOD. */
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct etr_edf3 {
|
||||
unsigned int rc : 8; /* failure reason code */
|
||||
unsigned int _pad0 : 3; /* must be 000 */
|
||||
unsigned int c : 1; /* ETR coupled bit */
|
||||
unsigned int tc : 4; /* ETR type code */
|
||||
unsigned int blto : 8; /* biased local time offset */
|
||||
/* (blto - 128) * 15 = minutes */
|
||||
unsigned int buo : 8; /* biased utc offset */
|
||||
/* (buo - 128) = leap seconds */
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct etr_edf4 {
|
||||
unsigned int ed : 8; /* ETS device dependent data */
|
||||
unsigned int _pad0 : 1; /* must be 0 */
|
||||
unsigned int buc : 5; /* biased ut1 correction */
|
||||
/* (buc - 16) * 0.1 seconds */
|
||||
unsigned int em : 6; /* ETS error magnitude */
|
||||
unsigned int dc : 6; /* ETS drift code */
|
||||
unsigned int sc : 6; /* ETS steering code */
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/*
|
||||
* ETR attachment information block, two formats
|
||||
* format 1 has 4 reserved words with a size of 64 bytes
|
||||
* format 2 has 16 reserved words with a size of 96 bytes
|
||||
*/
|
||||
struct etr_aib {
|
||||
struct etr_esw esw;
|
||||
struct etr_slsw slsw;
|
||||
unsigned long long tsp;
|
||||
struct etr_edf1 edf1;
|
||||
struct etr_edf2 edf2;
|
||||
struct etr_edf3 edf3;
|
||||
struct etr_edf4 edf4;
|
||||
unsigned int reserved[16];
|
||||
} __attribute__ ((packed,aligned(8)));
|
||||
|
||||
/* ETR interruption parameter */
|
||||
struct etr_irq_parm {
|
||||
unsigned int _pad0 : 8;
|
||||
unsigned int pc0 : 1; /* port 0 state change */
|
||||
unsigned int pc1 : 1; /* port 1 state change */
|
||||
unsigned int _pad1 : 3;
|
||||
unsigned int eai : 1; /* ETR alert indication */
|
||||
unsigned int _pad2 : 18;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* Query TOD offset result */
|
||||
struct etr_ptff_qto {
|
||||
unsigned long long physical_clock;
|
||||
unsigned long long tod_offset;
|
||||
unsigned long long logical_tod_offset;
|
||||
unsigned long long tod_epoch_difference;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* Inline assembly helper functions */
|
||||
static inline int etr_setr(struct etr_eacr *ctrl)
|
||||
{
|
||||
int rc = -EOPNOTSUPP;
|
||||
|
||||
asm volatile(
|
||||
" .insn s,0xb2160000,%1\n"
|
||||
"0: la %0,0\n"
|
||||
"1:\n"
|
||||
EX_TABLE(0b,1b)
|
||||
: "+d" (rc) : "Q" (*ctrl));
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Stores a format 1 aib with 64 bytes */
|
||||
static inline int etr_stetr(struct etr_aib *aib)
|
||||
{
|
||||
int rc = -EOPNOTSUPP;
|
||||
|
||||
asm volatile(
|
||||
" .insn s,0xb2170000,%1\n"
|
||||
"0: la %0,0\n"
|
||||
"1:\n"
|
||||
EX_TABLE(0b,1b)
|
||||
: "+d" (rc) : "Q" (*aib));
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Stores a format 2 aib with 96 bytes for specified port */
|
||||
static inline int etr_steai(struct etr_aib *aib, unsigned int func)
|
||||
{
|
||||
register unsigned int reg0 asm("0") = func;
|
||||
int rc = -EOPNOTSUPP;
|
||||
|
||||
asm volatile(
|
||||
" .insn s,0xb2b30000,%1\n"
|
||||
"0: la %0,0\n"
|
||||
"1:\n"
|
||||
EX_TABLE(0b,1b)
|
||||
: "+d" (rc) : "Q" (*aib), "d" (reg0));
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Function codes for the steai instruction. */
|
||||
#define ETR_STEAI_STEPPING_PORT 0x10
|
||||
#define ETR_STEAI_ALTERNATE_PORT 0x11
|
||||
#define ETR_STEAI_PORT_0 0x12
|
||||
#define ETR_STEAI_PORT_1 0x13
|
||||
|
||||
static inline int etr_ptff(void *ptff_block, unsigned int func)
|
||||
{
|
||||
register unsigned int reg0 asm("0") = func;
|
||||
register unsigned long reg1 asm("1") = (unsigned long) ptff_block;
|
||||
int rc = -EOPNOTSUPP;
|
||||
|
||||
asm volatile(
|
||||
" .word 0x0104\n"
|
||||
" ipm %0\n"
|
||||
" srl %0,28\n"
|
||||
: "=d" (rc), "=m" (ptff_block)
|
||||
: "d" (reg0), "d" (reg1), "m" (ptff_block) : "cc");
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Function codes for the ptff instruction. */
|
||||
#define ETR_PTFF_QAF 0x00 /* query available functions */
|
||||
#define ETR_PTFF_QTO 0x01 /* query tod offset */
|
||||
#define ETR_PTFF_QSI 0x02 /* query steering information */
|
||||
#define ETR_PTFF_ATO 0x40 /* adjust tod offset */
|
||||
#define ETR_PTFF_STO 0x41 /* set tod offset */
|
||||
#define ETR_PTFF_SFS 0x42 /* set fine steering rate */
|
||||
#define ETR_PTFF_SGS 0x43 /* set gross steering rate */
|
||||
|
||||
/* Functions needed by the machine check handler */
|
||||
int etr_switch_to_local(void);
|
||||
int etr_sync_check(void);
|
||||
void etr_queue_work(void);
|
||||
|
||||
/* notifier for syncs */
|
||||
extern struct atomic_notifier_head s390_epoch_delta_notifier;
|
||||
|
||||
/* STP interruption parameter */
|
||||
struct stp_irq_parm {
|
||||
unsigned int _pad0 : 14;
|
||||
unsigned int tsc : 1; /* Timing status change */
|
||||
unsigned int lac : 1; /* Link availability change */
|
||||
unsigned int tcpc : 1; /* Time control parameter change */
|
||||
unsigned int _pad2 : 15;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
#define STP_OP_SYNC 1
|
||||
#define STP_OP_CTRL 3
|
||||
|
||||
struct stp_sstpi {
|
||||
unsigned int rsvd0;
|
||||
unsigned int rsvd1 : 8;
|
||||
unsigned int stratum : 8;
|
||||
unsigned int vbits : 16;
|
||||
unsigned int leaps : 16;
|
||||
unsigned int tmd : 4;
|
||||
unsigned int ctn : 4;
|
||||
unsigned int rsvd2 : 3;
|
||||
unsigned int c : 1;
|
||||
unsigned int tst : 4;
|
||||
unsigned int tzo : 16;
|
||||
unsigned int dsto : 16;
|
||||
unsigned int ctrl : 16;
|
||||
unsigned int rsvd3 : 16;
|
||||
unsigned int tto;
|
||||
unsigned int rsvd4;
|
||||
unsigned int ctnid[3];
|
||||
unsigned int rsvd5;
|
||||
unsigned int todoff[4];
|
||||
unsigned int rsvd6[48];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* Functions needed by the machine check handler */
|
||||
int stp_sync_check(void);
|
||||
int stp_island_check(void);
|
||||
void stp_queue_work(void);
|
||||
|
||||
#endif /* __S390_ETR_H */
|
@@ -6,7 +6,7 @@
|
||||
*/
|
||||
|
||||
#ifndef _ASM_S390_FCX_H
|
||||
#define _ASM_S390_FCX_H _ASM_S390_FCX_H
|
||||
#define _ASM_S390_FCX_H
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
|
@@ -1,6 +1,41 @@
|
||||
/*
|
||||
* In-kernel FPU support functions
|
||||
*
|
||||
*
|
||||
* Consider these guidelines before using in-kernel FPU functions:
|
||||
*
|
||||
* 1. Use kernel_fpu_begin() and kernel_fpu_end() to enclose all in-kernel
|
||||
* use of floating-point or vector registers and instructions.
|
||||
*
|
||||
* 2. For kernel_fpu_begin(), specify the vector register range you want to
|
||||
* use with the KERNEL_VXR_* constants. Consider these usage guidelines:
|
||||
*
|
||||
* a) If your function typically runs in process-context, use the lower
|
||||
* half of the vector registers, for example, specify KERNEL_VXR_LOW.
|
||||
* b) If your function typically runs in soft-irq or hard-irq context,
|
||||
* prefer using the upper half of the vector registers, for example,
|
||||
* specify KERNEL_VXR_HIGH.
|
||||
*
|
||||
* If you adhere to these guidelines, an interrupted process context
|
||||
* does not require to save and restore vector registers because of
|
||||
* disjoint register ranges.
|
||||
*
|
||||
* Also note that the __kernel_fpu_begin()/__kernel_fpu_end() functions
|
||||
* includes logic to save and restore up to 16 vector registers at once.
|
||||
*
|
||||
* 3. You can nest kernel_fpu_begin()/kernel_fpu_end() by using different
|
||||
* struct kernel_fpu states. Vector registers that are in use by outer
|
||||
* levels are saved and restored. You can minimize the save and restore
|
||||
* effort by choosing disjoint vector register ranges.
|
||||
*
|
||||
* 5. To use vector floating-point instructions, specify the KERNEL_FPC
|
||||
* flag to save and restore floating-point controls in addition to any
|
||||
* vector register range.
|
||||
*
|
||||
* 6. To use floating-point registers and instructions only, specify the
|
||||
* KERNEL_FPR flag. This flag triggers a save and restore of vector
|
||||
* registers V0 to V15 and floating-point controls.
|
||||
*
|
||||
* Copyright IBM Corp. 2015
|
||||
* Author(s): Hendrik Brueckner <brueckner@linux.vnet.ibm.com>
|
||||
*/
|
||||
@@ -8,6 +43,8 @@
|
||||
#ifndef _ASM_S390_FPU_API_H
|
||||
#define _ASM_S390_FPU_API_H
|
||||
|
||||
#include <linux/preempt.h>
|
||||
|
||||
void save_fpu_regs(void);
|
||||
|
||||
static inline int test_fp_ctl(u32 fpc)
|
||||
@@ -27,4 +64,42 @@ static inline int test_fp_ctl(u32 fpc)
|
||||
return rc;
|
||||
}
|
||||
|
||||
#define KERNEL_VXR_V0V7 1
|
||||
#define KERNEL_VXR_V8V15 2
|
||||
#define KERNEL_VXR_V16V23 4
|
||||
#define KERNEL_VXR_V24V31 8
|
||||
#define KERNEL_FPR 16
|
||||
#define KERNEL_FPC 256
|
||||
|
||||
#define KERNEL_VXR_LOW (KERNEL_VXR_V0V7|KERNEL_VXR_V8V15)
|
||||
#define KERNEL_VXR_MID (KERNEL_VXR_V8V15|KERNEL_VXR_V16V23)
|
||||
#define KERNEL_VXR_HIGH (KERNEL_VXR_V16V23|KERNEL_VXR_V24V31)
|
||||
|
||||
#define KERNEL_FPU_MASK (KERNEL_VXR_LOW|KERNEL_VXR_HIGH|KERNEL_FPR)
|
||||
|
||||
struct kernel_fpu;
|
||||
|
||||
/*
|
||||
* Note the functions below must be called with preemption disabled.
|
||||
* Do not enable preemption before calling __kernel_fpu_end() to prevent
|
||||
* an corruption of an existing kernel FPU state.
|
||||
*
|
||||
* Prefer using the kernel_fpu_begin()/kernel_fpu_end() pair of functions.
|
||||
*/
|
||||
void __kernel_fpu_begin(struct kernel_fpu *state, u32 flags);
|
||||
void __kernel_fpu_end(struct kernel_fpu *state);
|
||||
|
||||
|
||||
static inline void kernel_fpu_begin(struct kernel_fpu *state, u32 flags)
|
||||
{
|
||||
preempt_disable();
|
||||
__kernel_fpu_begin(state, flags);
|
||||
}
|
||||
|
||||
static inline void kernel_fpu_end(struct kernel_fpu *state)
|
||||
{
|
||||
__kernel_fpu_end(state);
|
||||
preempt_enable();
|
||||
}
|
||||
|
||||
#endif /* _ASM_S390_FPU_API_H */
|
||||
|
@@ -24,4 +24,14 @@ struct fpu {
|
||||
/* VX array structure for address operand constraints in inline assemblies */
|
||||
struct vx_array { __vector128 _[__NUM_VXRS]; };
|
||||
|
||||
/* In-kernel FPU state structure */
|
||||
struct kernel_fpu {
|
||||
u32 mask;
|
||||
u32 fpc;
|
||||
union {
|
||||
freg_t fprs[__NUM_FPRS];
|
||||
__vector128 vxrs[__NUM_VXRS];
|
||||
};
|
||||
};
|
||||
|
||||
#endif /* _ASM_S390_FPU_TYPES_H */
|
||||
|
@@ -41,7 +41,10 @@ static inline int prepare_hugepage_range(struct file *file,
|
||||
static inline void huge_pte_clear(struct mm_struct *mm, unsigned long addr,
|
||||
pte_t *ptep)
|
||||
{
|
||||
pte_val(*ptep) = _SEGMENT_ENTRY_EMPTY;
|
||||
if ((pte_val(*ptep) & _REGION_ENTRY_TYPE_MASK) == _REGION_ENTRY_TYPE_R3)
|
||||
pte_val(*ptep) = _REGION3_ENTRY_EMPTY;
|
||||
else
|
||||
pte_val(*ptep) = _SEGMENT_ENTRY_EMPTY;
|
||||
}
|
||||
|
||||
static inline void huge_ptep_clear_flush(struct vm_area_struct *vma,
|
||||
|
@@ -141,11 +141,11 @@ extern void setup_ipl(void);
|
||||
* DIAG 308 support
|
||||
*/
|
||||
enum diag308_subcode {
|
||||
DIAG308_REL_HSA = 2,
|
||||
DIAG308_IPL = 3,
|
||||
DIAG308_DUMP = 4,
|
||||
DIAG308_SET = 5,
|
||||
DIAG308_STORE = 6,
|
||||
DIAG308_REL_HSA = 2,
|
||||
DIAG308_LOAD_CLEAR = 3,
|
||||
DIAG308_LOAD_NORMAL_DUMP = 4,
|
||||
DIAG308_SET = 5,
|
||||
DIAG308_STORE = 6,
|
||||
};
|
||||
|
||||
enum diag308_ipl_type {
|
||||
|
@@ -7,11 +7,8 @@
|
||||
|
||||
#define NR_IRQS_BASE 3
|
||||
|
||||
#ifdef CONFIG_PCI_NR_MSI
|
||||
# define NR_IRQS (NR_IRQS_BASE + CONFIG_PCI_NR_MSI)
|
||||
#else
|
||||
# define NR_IRQS NR_IRQS_BASE
|
||||
#endif
|
||||
#define NR_IRQS NR_IRQS_BASE
|
||||
#define NR_IRQS_LEGACY NR_IRQS_BASE
|
||||
|
||||
/* External interruption codes */
|
||||
#define EXT_IRQ_INTERRUPT_KEY 0x0040
|
||||
|
@@ -4,6 +4,7 @@
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/stringify.h>
|
||||
|
||||
#define JUMP_LABEL_NOP_SIZE 6
|
||||
#define JUMP_LABEL_NOP_OFFSET 2
|
||||
|
@@ -43,9 +43,9 @@ typedef u16 kprobe_opcode_t;
|
||||
#define MAX_INSN_SIZE 0x0003
|
||||
#define MAX_STACK_SIZE 64
|
||||
#define MIN_STACK_SIZE(ADDR) (((MAX_STACK_SIZE) < \
|
||||
(((unsigned long)current_thread_info()) + THREAD_SIZE - (ADDR))) \
|
||||
(((unsigned long)task_stack_page(current)) + THREAD_SIZE - (ADDR))) \
|
||||
? (MAX_STACK_SIZE) \
|
||||
: (((unsigned long)current_thread_info()) + THREAD_SIZE - (ADDR)))
|
||||
: (((unsigned long)task_stack_page(current)) + THREAD_SIZE - (ADDR)))
|
||||
|
||||
#define kretprobe_blacklist_size 0
|
||||
|
||||
|
@@ -1,28 +0,0 @@
|
||||
/*
|
||||
* IEEE floating point emulation.
|
||||
*
|
||||
* S390 version
|
||||
* Copyright IBM Corp. 1999
|
||||
* Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
|
||||
*/
|
||||
|
||||
#ifndef __MATHEMU__
|
||||
#define __MATHEMU__
|
||||
|
||||
extern int math_emu_b3(__u8 *, struct pt_regs *);
|
||||
extern int math_emu_ed(__u8 *, struct pt_regs *);
|
||||
extern int math_emu_ldr(__u8 *);
|
||||
extern int math_emu_ler(__u8 *);
|
||||
extern int math_emu_std(__u8 *, struct pt_regs *);
|
||||
extern int math_emu_ld(__u8 *, struct pt_regs *);
|
||||
extern int math_emu_ste(__u8 *, struct pt_regs *);
|
||||
extern int math_emu_le(__u8 *, struct pt_regs *);
|
||||
extern int math_emu_lfpc(__u8 *, struct pt_regs *);
|
||||
extern int math_emu_stfpc(__u8 *, struct pt_regs *);
|
||||
extern int math_emu_srnm(__u8 *, struct pt_regs *);
|
||||
|
||||
#endif /* __MATHEMU__ */
|
||||
|
||||
|
||||
|
||||
|
@@ -6,7 +6,7 @@
|
||||
|
||||
typedef struct {
|
||||
cpumask_t cpu_attach_mask;
|
||||
atomic_t attach_count;
|
||||
atomic_t flush_count;
|
||||
unsigned int flush_mm;
|
||||
spinlock_t list_lock;
|
||||
struct list_head pgtable_list;
|
||||
|
@@ -19,7 +19,7 @@ static inline int init_new_context(struct task_struct *tsk,
|
||||
INIT_LIST_HEAD(&mm->context.pgtable_list);
|
||||
INIT_LIST_HEAD(&mm->context.gmap_list);
|
||||
cpumask_clear(&mm->context.cpu_attach_mask);
|
||||
atomic_set(&mm->context.attach_count, 0);
|
||||
atomic_set(&mm->context.flush_count, 0);
|
||||
mm->context.flush_mm = 0;
|
||||
#ifdef CONFIG_PGSTE
|
||||
mm->context.alloc_pgste = page_table_allocate_pgste;
|
||||
@@ -90,15 +90,12 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
|
||||
S390_lowcore.user_asce = next->context.asce;
|
||||
if (prev == next)
|
||||
return;
|
||||
if (MACHINE_HAS_TLB_LC)
|
||||
cpumask_set_cpu(cpu, &next->context.cpu_attach_mask);
|
||||
cpumask_set_cpu(cpu, &next->context.cpu_attach_mask);
|
||||
cpumask_set_cpu(cpu, mm_cpumask(next));
|
||||
/* Clear old ASCE by loading the kernel ASCE. */
|
||||
__ctl_load(S390_lowcore.kernel_asce, 1, 1);
|
||||
__ctl_load(S390_lowcore.kernel_asce, 7, 7);
|
||||
atomic_inc(&next->context.attach_count);
|
||||
atomic_dec(&prev->context.attach_count);
|
||||
if (MACHINE_HAS_TLB_LC)
|
||||
cpumask_clear_cpu(cpu, &prev->context.cpu_attach_mask);
|
||||
cpumask_clear_cpu(cpu, &prev->context.cpu_attach_mask);
|
||||
}
|
||||
|
||||
#define finish_arch_post_lock_switch finish_arch_post_lock_switch
|
||||
@@ -110,10 +107,9 @@ static inline void finish_arch_post_lock_switch(void)
|
||||
load_kernel_asce();
|
||||
if (mm) {
|
||||
preempt_disable();
|
||||
while (atomic_read(&mm->context.attach_count) >> 16)
|
||||
while (atomic_read(&mm->context.flush_count))
|
||||
cpu_relax();
|
||||
|
||||
cpumask_set_cpu(smp_processor_id(), mm_cpumask(mm));
|
||||
if (mm->context.flush_mm)
|
||||
__tlb_flush_mm(mm);
|
||||
preempt_enable();
|
||||
@@ -128,7 +124,6 @@ static inline void activate_mm(struct mm_struct *prev,
|
||||
struct mm_struct *next)
|
||||
{
|
||||
switch_mm(prev, next, current);
|
||||
cpumask_set_cpu(smp_processor_id(), mm_cpumask(next));
|
||||
set_user_asce(next);
|
||||
}
|
||||
|
||||
|
@@ -21,6 +21,7 @@
|
||||
#define HPAGE_SIZE (1UL << HPAGE_SHIFT)
|
||||
#define HPAGE_MASK (~(HPAGE_SIZE - 1))
|
||||
#define HUGETLB_PAGE_ORDER (HPAGE_SHIFT - PAGE_SHIFT)
|
||||
#define HUGE_MAX_HSTATE 2
|
||||
|
||||
#define ARCH_HAS_SETCLEAR_HUGE_PTE
|
||||
#define ARCH_HAS_HUGE_PTE_TYPE
|
||||
@@ -30,11 +31,12 @@
|
||||
#include <asm/setup.h>
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
void __storage_key_init_range(unsigned long start, unsigned long end);
|
||||
|
||||
static inline void storage_key_init_range(unsigned long start, unsigned long end)
|
||||
{
|
||||
#if PAGE_DEFAULT_KEY
|
||||
__storage_key_init_range(start, end);
|
||||
#endif
|
||||
if (PAGE_DEFAULT_KEY)
|
||||
__storage_key_init_range(start, end);
|
||||
}
|
||||
|
||||
#define clear_page(page) memset((page), 0, PAGE_SIZE)
|
||||
|
@@ -86,16 +86,4 @@ struct sf_raw_sample {
|
||||
u8 padding[]; /* Padding to next multiple of 8 */
|
||||
} __packed;
|
||||
|
||||
/* Perf hardware reserve and release functions */
|
||||
#ifdef CONFIG_PERF_EVENTS
|
||||
int perf_reserve_sampling(void);
|
||||
void perf_release_sampling(void);
|
||||
#else /* CONFIG_PERF_EVENTS */
|
||||
static inline int perf_reserve_sampling(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline void perf_release_sampling(void) {}
|
||||
#endif /* CONFIG_PERF_EVENTS */
|
||||
|
||||
#endif /* _ASM_S390_PERF_EVENT_H */
|
||||
|
@@ -28,12 +28,33 @@
|
||||
#include <linux/mm_types.h>
|
||||
#include <linux/page-flags.h>
|
||||
#include <linux/radix-tree.h>
|
||||
#include <linux/atomic.h>
|
||||
#include <asm/bug.h>
|
||||
#include <asm/page.h>
|
||||
|
||||
extern pgd_t swapper_pg_dir[] __attribute__ ((aligned (4096)));
|
||||
extern pgd_t swapper_pg_dir[];
|
||||
extern void paging_init(void);
|
||||
extern void vmem_map_init(void);
|
||||
pmd_t *vmem_pmd_alloc(void);
|
||||
pte_t *vmem_pte_alloc(void);
|
||||
|
||||
enum {
|
||||
PG_DIRECT_MAP_4K = 0,
|
||||
PG_DIRECT_MAP_1M,
|
||||
PG_DIRECT_MAP_2G,
|
||||
PG_DIRECT_MAP_MAX
|
||||
};
|
||||
|
||||
extern atomic_long_t direct_pages_count[PG_DIRECT_MAP_MAX];
|
||||
|
||||
static inline void update_page_count(int level, long count)
|
||||
{
|
||||
if (IS_ENABLED(CONFIG_PROC_FS))
|
||||
atomic_long_add(count, &direct_pages_count[level]);
|
||||
}
|
||||
|
||||
struct seq_file;
|
||||
void arch_report_meminfo(struct seq_file *m);
|
||||
|
||||
/*
|
||||
* The S390 doesn't have any external MMU info: the kernel page
|
||||
@@ -270,8 +291,23 @@ static inline int is_module_addr(void *addr)
|
||||
#define _REGION3_ENTRY (_REGION_ENTRY_TYPE_R3 | _REGION_ENTRY_LENGTH)
|
||||
#define _REGION3_ENTRY_EMPTY (_REGION_ENTRY_TYPE_R3 | _REGION_ENTRY_INVALID)
|
||||
|
||||
#define _REGION3_ENTRY_LARGE 0x400 /* RTTE-format control, large page */
|
||||
#define _REGION3_ENTRY_RO 0x200 /* page protection bit */
|
||||
#define _REGION3_ENTRY_ORIGIN_LARGE ~0x7fffffffUL /* large page address */
|
||||
#define _REGION3_ENTRY_ORIGIN ~0x7ffUL/* region third table origin */
|
||||
|
||||
#define _REGION3_ENTRY_DIRTY 0x2000 /* SW region dirty bit */
|
||||
#define _REGION3_ENTRY_YOUNG 0x1000 /* SW region young bit */
|
||||
#define _REGION3_ENTRY_LARGE 0x0400 /* RTTE-format control, large page */
|
||||
#define _REGION3_ENTRY_READ 0x0002 /* SW region read bit */
|
||||
#define _REGION3_ENTRY_WRITE 0x0001 /* SW region write bit */
|
||||
|
||||
#ifdef CONFIG_MEM_SOFT_DIRTY
|
||||
#define _REGION3_ENTRY_SOFT_DIRTY 0x4000 /* SW region soft dirty bit */
|
||||
#else
|
||||
#define _REGION3_ENTRY_SOFT_DIRTY 0x0000 /* SW region soft dirty bit */
|
||||
#endif
|
||||
|
||||
#define _REGION_ENTRY_BITS 0xfffffffffffff227UL
|
||||
#define _REGION_ENTRY_BITS_LARGE 0xffffffff8000fe27UL
|
||||
|
||||
/* Bits in the segment table entry */
|
||||
#define _SEGMENT_ENTRY_BITS 0xfffffffffffffe33UL
|
||||
@@ -297,7 +333,8 @@ static inline int is_module_addr(void *addr)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Segment table entry encoding (R = read-only, I = invalid, y = young bit):
|
||||
* Segment table and region3 table entry encoding
|
||||
* (R = read-only, I = invalid, y = young bit):
|
||||
* dy..R...I...rw
|
||||
* prot-none, clean, old 00..1...1...00
|
||||
* prot-none, clean, young 01..1...1...00
|
||||
@@ -391,6 +428,33 @@ static inline int is_module_addr(void *addr)
|
||||
_SEGMENT_ENTRY_READ)
|
||||
#define SEGMENT_WRITE __pgprot(_SEGMENT_ENTRY_READ | \
|
||||
_SEGMENT_ENTRY_WRITE)
|
||||
#define SEGMENT_KERNEL __pgprot(_SEGMENT_ENTRY | \
|
||||
_SEGMENT_ENTRY_LARGE | \
|
||||
_SEGMENT_ENTRY_READ | \
|
||||
_SEGMENT_ENTRY_WRITE | \
|
||||
_SEGMENT_ENTRY_YOUNG | \
|
||||
_SEGMENT_ENTRY_DIRTY)
|
||||
#define SEGMENT_KERNEL_RO __pgprot(_SEGMENT_ENTRY | \
|
||||
_SEGMENT_ENTRY_LARGE | \
|
||||
_SEGMENT_ENTRY_READ | \
|
||||
_SEGMENT_ENTRY_YOUNG | \
|
||||
_SEGMENT_ENTRY_PROTECT)
|
||||
|
||||
/*
|
||||
* Region3 entry (large page) protection definitions.
|
||||
*/
|
||||
|
||||
#define REGION3_KERNEL __pgprot(_REGION_ENTRY_TYPE_R3 | \
|
||||
_REGION3_ENTRY_LARGE | \
|
||||
_REGION3_ENTRY_READ | \
|
||||
_REGION3_ENTRY_WRITE | \
|
||||
_REGION3_ENTRY_YOUNG | \
|
||||
_REGION3_ENTRY_DIRTY)
|
||||
#define REGION3_KERNEL_RO __pgprot(_REGION_ENTRY_TYPE_R3 | \
|
||||
_REGION3_ENTRY_LARGE | \
|
||||
_REGION3_ENTRY_READ | \
|
||||
_REGION3_ENTRY_YOUNG | \
|
||||
_REGION_ENTRY_PROTECT)
|
||||
|
||||
static inline int mm_has_pgste(struct mm_struct *mm)
|
||||
{
|
||||
@@ -424,6 +488,53 @@ static inline int mm_use_skey(struct mm_struct *mm)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void csp(unsigned int *ptr, unsigned int old, unsigned int new)
|
||||
{
|
||||
register unsigned long reg2 asm("2") = old;
|
||||
register unsigned long reg3 asm("3") = new;
|
||||
unsigned long address = (unsigned long)ptr | 1;
|
||||
|
||||
asm volatile(
|
||||
" csp %0,%3"
|
||||
: "+d" (reg2), "+m" (*ptr)
|
||||
: "d" (reg3), "d" (address)
|
||||
: "cc");
|
||||
}
|
||||
|
||||
static inline void cspg(unsigned long *ptr, unsigned long old, unsigned long new)
|
||||
{
|
||||
register unsigned long reg2 asm("2") = old;
|
||||
register unsigned long reg3 asm("3") = new;
|
||||
unsigned long address = (unsigned long)ptr | 1;
|
||||
|
||||
asm volatile(
|
||||
" .insn rre,0xb98a0000,%0,%3"
|
||||
: "+d" (reg2), "+m" (*ptr)
|
||||
: "d" (reg3), "d" (address)
|
||||
: "cc");
|
||||
}
|
||||
|
||||
#define CRDTE_DTT_PAGE 0x00UL
|
||||
#define CRDTE_DTT_SEGMENT 0x10UL
|
||||
#define CRDTE_DTT_REGION3 0x14UL
|
||||
#define CRDTE_DTT_REGION2 0x18UL
|
||||
#define CRDTE_DTT_REGION1 0x1cUL
|
||||
|
||||
static inline void crdte(unsigned long old, unsigned long new,
|
||||
unsigned long table, unsigned long dtt,
|
||||
unsigned long address, unsigned long asce)
|
||||
{
|
||||
register unsigned long reg2 asm("2") = old;
|
||||
register unsigned long reg3 asm("3") = new;
|
||||
register unsigned long reg4 asm("4") = table | dtt;
|
||||
register unsigned long reg5 asm("5") = address;
|
||||
|
||||
asm volatile(".insn rrf,0xb98f0000,%0,%2,%4,0"
|
||||
: "+d" (reg2)
|
||||
: "d" (reg3), "d" (reg4), "d" (reg5), "a" (asce)
|
||||
: "memory", "cc");
|
||||
}
|
||||
|
||||
/*
|
||||
* pgd/pmd/pte query functions
|
||||
*/
|
||||
@@ -465,7 +576,7 @@ static inline int pud_none(pud_t pud)
|
||||
{
|
||||
if ((pud_val(pud) & _REGION_ENTRY_TYPE_MASK) < _REGION_ENTRY_TYPE_R3)
|
||||
return 0;
|
||||
return (pud_val(pud) & _REGION_ENTRY_INVALID) != 0UL;
|
||||
return pud_val(pud) == _REGION3_ENTRY_EMPTY;
|
||||
}
|
||||
|
||||
static inline int pud_large(pud_t pud)
|
||||
@@ -475,17 +586,35 @@ static inline int pud_large(pud_t pud)
|
||||
return !!(pud_val(pud) & _REGION3_ENTRY_LARGE);
|
||||
}
|
||||
|
||||
static inline unsigned long pud_pfn(pud_t pud)
|
||||
{
|
||||
unsigned long origin_mask;
|
||||
|
||||
origin_mask = _REGION3_ENTRY_ORIGIN;
|
||||
if (pud_large(pud))
|
||||
origin_mask = _REGION3_ENTRY_ORIGIN_LARGE;
|
||||
return (pud_val(pud) & origin_mask) >> PAGE_SHIFT;
|
||||
}
|
||||
|
||||
static inline int pmd_large(pmd_t pmd)
|
||||
{
|
||||
return (pmd_val(pmd) & _SEGMENT_ENTRY_LARGE) != 0;
|
||||
}
|
||||
|
||||
static inline int pmd_bad(pmd_t pmd)
|
||||
{
|
||||
if (pmd_large(pmd))
|
||||
return (pmd_val(pmd) & ~_SEGMENT_ENTRY_BITS_LARGE) != 0;
|
||||
return (pmd_val(pmd) & ~_SEGMENT_ENTRY_BITS) != 0;
|
||||
}
|
||||
|
||||
static inline int pud_bad(pud_t pud)
|
||||
{
|
||||
/*
|
||||
* With dynamic page table levels the pud can be a region table
|
||||
* entry or a segment table entry. Check for the bit that are
|
||||
* invalid for either table entry.
|
||||
*/
|
||||
unsigned long mask =
|
||||
~_SEGMENT_ENTRY_ORIGIN & ~_REGION_ENTRY_INVALID &
|
||||
~_REGION_ENTRY_TYPE_MASK & ~_REGION_ENTRY_LENGTH;
|
||||
return (pud_val(pud) & mask) != 0;
|
||||
if ((pud_val(pud) & _REGION_ENTRY_TYPE_MASK) < _REGION_ENTRY_TYPE_R3)
|
||||
return pmd_bad(__pmd(pud_val(pud)));
|
||||
if (pud_large(pud))
|
||||
return (pud_val(pud) & ~_REGION_ENTRY_BITS_LARGE) != 0;
|
||||
return (pud_val(pud) & ~_REGION_ENTRY_BITS) != 0;
|
||||
}
|
||||
|
||||
static inline int pmd_present(pmd_t pmd)
|
||||
@@ -498,11 +627,6 @@ static inline int pmd_none(pmd_t pmd)
|
||||
return pmd_val(pmd) == _SEGMENT_ENTRY_INVALID;
|
||||
}
|
||||
|
||||
static inline int pmd_large(pmd_t pmd)
|
||||
{
|
||||
return (pmd_val(pmd) & _SEGMENT_ENTRY_LARGE) != 0;
|
||||
}
|
||||
|
||||
static inline unsigned long pmd_pfn(pmd_t pmd)
|
||||
{
|
||||
unsigned long origin_mask;
|
||||
@@ -513,13 +637,6 @@ static inline unsigned long pmd_pfn(pmd_t pmd)
|
||||
return (pmd_val(pmd) & origin_mask) >> PAGE_SHIFT;
|
||||
}
|
||||
|
||||
static inline int pmd_bad(pmd_t pmd)
|
||||
{
|
||||
if (pmd_large(pmd))
|
||||
return (pmd_val(pmd) & ~_SEGMENT_ENTRY_BITS_LARGE) != 0;
|
||||
return (pmd_val(pmd) & ~_SEGMENT_ENTRY_BITS) != 0;
|
||||
}
|
||||
|
||||
#define __HAVE_ARCH_PMD_WRITE
|
||||
static inline int pmd_write(pmd_t pmd)
|
||||
{
|
||||
@@ -963,6 +1080,7 @@ static inline pmd_t *pmd_offset(pud_t *pud, unsigned long address)
|
||||
#define pte_page(x) pfn_to_page(pte_pfn(x))
|
||||
|
||||
#define pmd_page(pmd) pfn_to_page(pmd_pfn(pmd))
|
||||
#define pud_page(pud) pfn_to_page(pud_pfn(pud))
|
||||
|
||||
/* Find an entry in the lowest level page table.. */
|
||||
#define pte_offset(pmd, addr) ((pte_t *) pmd_deref(*(pmd)) + pte_index(addr))
|
||||
@@ -970,20 +1088,6 @@ static inline pmd_t *pmd_offset(pud_t *pud, unsigned long address)
|
||||
#define pte_offset_map(pmd, address) pte_offset_kernel(pmd, address)
|
||||
#define pte_unmap(pte) do { } while (0)
|
||||
|
||||
#if defined(CONFIG_TRANSPARENT_HUGEPAGE) || defined(CONFIG_HUGETLB_PAGE)
|
||||
static inline unsigned long massage_pgprot_pmd(pgprot_t pgprot)
|
||||
{
|
||||
/*
|
||||
* pgprot is PAGE_NONE, PAGE_READ, or PAGE_WRITE (see __Pxxx / __Sxxx)
|
||||
* Convert to segment table entry format.
|
||||
*/
|
||||
if (pgprot_val(pgprot) == pgprot_val(PAGE_NONE))
|
||||
return pgprot_val(SEGMENT_NONE);
|
||||
if (pgprot_val(pgprot) == pgprot_val(PAGE_READ))
|
||||
return pgprot_val(SEGMENT_READ);
|
||||
return pgprot_val(SEGMENT_WRITE);
|
||||
}
|
||||
|
||||
static inline pmd_t pmd_wrprotect(pmd_t pmd)
|
||||
{
|
||||
pmd_val(pmd) &= ~_SEGMENT_ENTRY_WRITE;
|
||||
@@ -1020,6 +1124,56 @@ static inline pmd_t pmd_mkdirty(pmd_t pmd)
|
||||
return pmd;
|
||||
}
|
||||
|
||||
static inline pud_t pud_wrprotect(pud_t pud)
|
||||
{
|
||||
pud_val(pud) &= ~_REGION3_ENTRY_WRITE;
|
||||
pud_val(pud) |= _REGION_ENTRY_PROTECT;
|
||||
return pud;
|
||||
}
|
||||
|
||||
static inline pud_t pud_mkwrite(pud_t pud)
|
||||
{
|
||||
pud_val(pud) |= _REGION3_ENTRY_WRITE;
|
||||
if (pud_large(pud) && !(pud_val(pud) & _REGION3_ENTRY_DIRTY))
|
||||
return pud;
|
||||
pud_val(pud) &= ~_REGION_ENTRY_PROTECT;
|
||||
return pud;
|
||||
}
|
||||
|
||||
static inline pud_t pud_mkclean(pud_t pud)
|
||||
{
|
||||
if (pud_large(pud)) {
|
||||
pud_val(pud) &= ~_REGION3_ENTRY_DIRTY;
|
||||
pud_val(pud) |= _REGION_ENTRY_PROTECT;
|
||||
}
|
||||
return pud;
|
||||
}
|
||||
|
||||
static inline pud_t pud_mkdirty(pud_t pud)
|
||||
{
|
||||
if (pud_large(pud)) {
|
||||
pud_val(pud) |= _REGION3_ENTRY_DIRTY |
|
||||
_REGION3_ENTRY_SOFT_DIRTY;
|
||||
if (pud_val(pud) & _REGION3_ENTRY_WRITE)
|
||||
pud_val(pud) &= ~_REGION_ENTRY_PROTECT;
|
||||
}
|
||||
return pud;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_TRANSPARENT_HUGEPAGE) || defined(CONFIG_HUGETLB_PAGE)
|
||||
static inline unsigned long massage_pgprot_pmd(pgprot_t pgprot)
|
||||
{
|
||||
/*
|
||||
* pgprot is PAGE_NONE, PAGE_READ, or PAGE_WRITE (see __Pxxx / __Sxxx)
|
||||
* Convert to segment table entry format.
|
||||
*/
|
||||
if (pgprot_val(pgprot) == pgprot_val(PAGE_NONE))
|
||||
return pgprot_val(SEGMENT_NONE);
|
||||
if (pgprot_val(pgprot) == pgprot_val(PAGE_READ))
|
||||
return pgprot_val(SEGMENT_READ);
|
||||
return pgprot_val(SEGMENT_WRITE);
|
||||
}
|
||||
|
||||
static inline pmd_t pmd_mkyoung(pmd_t pmd)
|
||||
{
|
||||
if (pmd_large(pmd)) {
|
||||
@@ -1068,15 +1222,8 @@ static inline pmd_t mk_pmd_phys(unsigned long physpage, pgprot_t pgprot)
|
||||
|
||||
static inline void __pmdp_csp(pmd_t *pmdp)
|
||||
{
|
||||
register unsigned long reg2 asm("2") = pmd_val(*pmdp);
|
||||
register unsigned long reg3 asm("3") = pmd_val(*pmdp) |
|
||||
_SEGMENT_ENTRY_INVALID;
|
||||
register unsigned long reg4 asm("4") = ((unsigned long) pmdp) + 5;
|
||||
|
||||
asm volatile(
|
||||
" csp %1,%3"
|
||||
: "=m" (*pmdp)
|
||||
: "d" (reg2), "d" (reg3), "d" (reg4), "m" (*pmdp) : "cc");
|
||||
csp((unsigned int *)pmdp + 1, pmd_val(*pmdp),
|
||||
pmd_val(*pmdp) | _SEGMENT_ENTRY_INVALID);
|
||||
}
|
||||
|
||||
static inline void __pmdp_idte(unsigned long address, pmd_t *pmdp)
|
||||
@@ -1091,6 +1238,19 @@ static inline void __pmdp_idte(unsigned long address, pmd_t *pmdp)
|
||||
: "cc" );
|
||||
}
|
||||
|
||||
static inline void __pudp_idte(unsigned long address, pud_t *pudp)
|
||||
{
|
||||
unsigned long r3o;
|
||||
|
||||
r3o = (unsigned long) pudp - pud_index(address) * sizeof(pud_t);
|
||||
r3o |= _ASCE_TYPE_REGION3;
|
||||
asm volatile(
|
||||
" .insn rrf,0xb98e0000,%2,%3,0,0"
|
||||
: "=m" (*pudp)
|
||||
: "m" (*pudp), "a" (r3o), "a" ((address & PUD_MASK))
|
||||
: "cc");
|
||||
}
|
||||
|
||||
static inline void __pmdp_idte_local(unsigned long address, pmd_t *pmdp)
|
||||
{
|
||||
unsigned long sto;
|
||||
@@ -1103,8 +1263,22 @@ static inline void __pmdp_idte_local(unsigned long address, pmd_t *pmdp)
|
||||
: "cc" );
|
||||
}
|
||||
|
||||
static inline void __pudp_idte_local(unsigned long address, pud_t *pudp)
|
||||
{
|
||||
unsigned long r3o;
|
||||
|
||||
r3o = (unsigned long) pudp - pud_index(address) * sizeof(pud_t);
|
||||
r3o |= _ASCE_TYPE_REGION3;
|
||||
asm volatile(
|
||||
" .insn rrf,0xb98e0000,%2,%3,0,1"
|
||||
: "=m" (*pudp)
|
||||
: "m" (*pudp), "a" (r3o), "a" ((address & PUD_MASK))
|
||||
: "cc");
|
||||
}
|
||||
|
||||
pmd_t pmdp_xchg_direct(struct mm_struct *, unsigned long, pmd_t *, pmd_t);
|
||||
pmd_t pmdp_xchg_lazy(struct mm_struct *, unsigned long, pmd_t *, pmd_t);
|
||||
pud_t pudp_xchg_direct(struct mm_struct *, unsigned long, pud_t *, pud_t);
|
||||
|
||||
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
|
||||
|
||||
|
@@ -77,7 +77,10 @@ static inline void get_cpu_id(struct cpuid *ptr)
|
||||
asm volatile("stidp %0" : "=Q" (*ptr));
|
||||
}
|
||||
|
||||
extern void s390_adjust_jiffies(void);
|
||||
void s390_adjust_jiffies(void);
|
||||
void s390_update_cpu_mhz(void);
|
||||
void cpu_detect_mhz_feature(void);
|
||||
|
||||
extern const struct seq_operations cpuinfo_op;
|
||||
extern int sysctl_ieee_emulation_warnings;
|
||||
extern void execve_tail(void);
|
||||
@@ -233,6 +236,18 @@ void cpu_relax(void);
|
||||
|
||||
#define cpu_relax_lowlatency() barrier()
|
||||
|
||||
#define ECAG_CACHE_ATTRIBUTE 0
|
||||
#define ECAG_CPU_ATTRIBUTE 1
|
||||
|
||||
static inline unsigned long __ecag(unsigned int asi, unsigned char parm)
|
||||
{
|
||||
unsigned long val;
|
||||
|
||||
asm volatile(".insn rsy,0xeb000000004c,%0,0,0(%1)" /* ecag */
|
||||
: "=d" (val) : "a" (asi << 8 | parm));
|
||||
return val;
|
||||
}
|
||||
|
||||
static inline void psw_set_key(unsigned int key)
|
||||
{
|
||||
asm volatile("spka 0(%0)" : : "d" (key));
|
||||
|
@@ -4,5 +4,6 @@
|
||||
#include <asm-generic/sections.h>
|
||||
|
||||
extern char _eshared[], _ehead[];
|
||||
extern char __start_ro_after_init[], __end_ro_after_init[];
|
||||
|
||||
#endif
|
||||
|
@@ -86,9 +86,13 @@ extern char vmpoff_cmd[];
|
||||
#define CONSOLE_IS_SCLP (console_mode == 1)
|
||||
#define CONSOLE_IS_3215 (console_mode == 2)
|
||||
#define CONSOLE_IS_3270 (console_mode == 3)
|
||||
#define CONSOLE_IS_VT220 (console_mode == 4)
|
||||
#define CONSOLE_IS_HVC (console_mode == 5)
|
||||
#define SET_CONSOLE_SCLP do { console_mode = 1; } while (0)
|
||||
#define SET_CONSOLE_3215 do { console_mode = 2; } while (0)
|
||||
#define SET_CONSOLE_3270 do { console_mode = 3; } while (0)
|
||||
#define SET_CONSOLE_VT220 do { console_mode = 4; } while (0)
|
||||
#define SET_CONSOLE_HVC do { console_mode = 5; } while (0)
|
||||
|
||||
#define NSS_NAME_SIZE 8
|
||||
extern char kernel_nss_name[];
|
||||
|
@@ -1,142 +0,0 @@
|
||||
/* Machine-dependent software floating-point definitions.
|
||||
S/390 kernel version.
|
||||
Copyright (C) 1997,1998,1999 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Richard Henderson (rth@cygnus.com),
|
||||
Jakub Jelinek (jj@ultra.linux.cz),
|
||||
David S. Miller (davem@redhat.com) and
|
||||
Peter Maydell (pmaydell@chiark.greenend.org.uk).
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with the GNU C Library; see the file COPYING.LIB. If
|
||||
not, write to the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#ifndef _SFP_MACHINE_H
|
||||
#define _SFP_MACHINE_H
|
||||
|
||||
|
||||
#define _FP_W_TYPE_SIZE 32
|
||||
#define _FP_W_TYPE unsigned int
|
||||
#define _FP_WS_TYPE signed int
|
||||
#define _FP_I_TYPE int
|
||||
|
||||
#define _FP_MUL_MEAT_S(R,X,Y) \
|
||||
_FP_MUL_MEAT_1_wide(_FP_WFRACBITS_S,R,X,Y,umul_ppmm)
|
||||
#define _FP_MUL_MEAT_D(R,X,Y) \
|
||||
_FP_MUL_MEAT_2_wide(_FP_WFRACBITS_D,R,X,Y,umul_ppmm)
|
||||
#define _FP_MUL_MEAT_Q(R,X,Y) \
|
||||
_FP_MUL_MEAT_4_wide(_FP_WFRACBITS_Q,R,X,Y,umul_ppmm)
|
||||
|
||||
#define _FP_DIV_MEAT_S(R,X,Y) _FP_DIV_MEAT_1_udiv(S,R,X,Y)
|
||||
#define _FP_DIV_MEAT_D(R,X,Y) _FP_DIV_MEAT_2_udiv(D,R,X,Y)
|
||||
#define _FP_DIV_MEAT_Q(R,X,Y) _FP_DIV_MEAT_4_udiv(Q,R,X,Y)
|
||||
|
||||
#define _FP_NANFRAC_S ((_FP_QNANBIT_S << 1) - 1)
|
||||
#define _FP_NANFRAC_D ((_FP_QNANBIT_D << 1) - 1), -1
|
||||
#define _FP_NANFRAC_Q ((_FP_QNANBIT_Q << 1) - 1), -1, -1, -1
|
||||
#define _FP_NANSIGN_S 0
|
||||
#define _FP_NANSIGN_D 0
|
||||
#define _FP_NANSIGN_Q 0
|
||||
|
||||
#define _FP_KEEPNANFRACP 1
|
||||
|
||||
/*
|
||||
* If one NaN is signaling and the other is not,
|
||||
* we choose that one, otherwise we choose X.
|
||||
*/
|
||||
#define _FP_CHOOSENAN(fs, wc, R, X, Y, OP) \
|
||||
do { \
|
||||
if ((_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs) \
|
||||
&& !(_FP_FRAC_HIGH_RAW_##fs(Y) & _FP_QNANBIT_##fs)) \
|
||||
{ \
|
||||
R##_s = Y##_s; \
|
||||
_FP_FRAC_COPY_##wc(R,Y); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
R##_s = X##_s; \
|
||||
_FP_FRAC_COPY_##wc(R,X); \
|
||||
} \
|
||||
R##_c = FP_CLS_NAN; \
|
||||
} while (0)
|
||||
|
||||
/* Some assembly to speed things up. */
|
||||
#define __FP_FRAC_ADD_3(r2,r1,r0,x2,x1,x0,y2,y1,y0) ({ \
|
||||
unsigned int __r2 = (x2) + (y2); \
|
||||
unsigned int __r1 = (x1); \
|
||||
unsigned int __r0 = (x0); \
|
||||
asm volatile( \
|
||||
" alr %2,%3\n" \
|
||||
" brc 12,0f\n" \
|
||||
" lhi 0,1\n" \
|
||||
" alr %1,0\n" \
|
||||
" brc 12,0f\n" \
|
||||
" alr %0,0\n" \
|
||||
"0:" \
|
||||
: "+&d" (__r2), "+&d" (__r1), "+&d" (__r0) \
|
||||
: "d" (y0), "i" (1) : "cc", "0" ); \
|
||||
asm volatile( \
|
||||
" alr %1,%2\n" \
|
||||
" brc 12,0f\n" \
|
||||
" ahi %0,1\n" \
|
||||
"0:" \
|
||||
: "+&d" (__r2), "+&d" (__r1) \
|
||||
: "d" (y1) : "cc"); \
|
||||
(r2) = __r2; \
|
||||
(r1) = __r1; \
|
||||
(r0) = __r0; \
|
||||
})
|
||||
|
||||
#define __FP_FRAC_SUB_3(r2,r1,r0,x2,x1,x0,y2,y1,y0) ({ \
|
||||
unsigned int __r2 = (x2) - (y2); \
|
||||
unsigned int __r1 = (x1); \
|
||||
unsigned int __r0 = (x0); \
|
||||
asm volatile( \
|
||||
" slr %2,%3\n" \
|
||||
" brc 3,0f\n" \
|
||||
" lhi 0,1\n" \
|
||||
" slr %1,0\n" \
|
||||
" brc 3,0f\n" \
|
||||
" slr %0,0\n" \
|
||||
"0:" \
|
||||
: "+&d" (__r2), "+&d" (__r1), "+&d" (__r0) \
|
||||
: "d" (y0) : "cc", "0"); \
|
||||
asm volatile( \
|
||||
" slr %1,%2\n" \
|
||||
" brc 3,0f\n" \
|
||||
" ahi %0,-1\n" \
|
||||
"0:" \
|
||||
: "+&d" (__r2), "+&d" (__r1) \
|
||||
: "d" (y1) : "cc"); \
|
||||
(r2) = __r2; \
|
||||
(r1) = __r1; \
|
||||
(r0) = __r0; \
|
||||
})
|
||||
|
||||
#define __FP_FRAC_DEC_3(x2,x1,x0,y2,y1,y0) __FP_FRAC_SUB_3(x2,x1,x0,x2,x1,x0,y2,y1,y0)
|
||||
|
||||
/* Obtain the current rounding mode. */
|
||||
#define FP_ROUNDMODE mode
|
||||
|
||||
/* Exception flags. */
|
||||
#define FP_EX_INVALID 0x800000
|
||||
#define FP_EX_DIVZERO 0x400000
|
||||
#define FP_EX_OVERFLOW 0x200000
|
||||
#define FP_EX_UNDERFLOW 0x100000
|
||||
#define FP_EX_INEXACT 0x080000
|
||||
|
||||
/* We write the results always */
|
||||
#define FP_INHIBIT_RESULTS 0
|
||||
|
||||
#endif
|
@@ -1,67 +0,0 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/types.h>
|
||||
#include <asm/byteorder.h>
|
||||
|
||||
#define add_ssaaaa(sh, sl, ah, al, bh, bl) ({ \
|
||||
unsigned int __sh = (ah); \
|
||||
unsigned int __sl = (al); \
|
||||
asm volatile( \
|
||||
" alr %1,%3\n" \
|
||||
" brc 12,0f\n" \
|
||||
" ahi %0,1\n" \
|
||||
"0: alr %0,%2" \
|
||||
: "+&d" (__sh), "+d" (__sl) \
|
||||
: "d" (bh), "d" (bl) : "cc"); \
|
||||
(sh) = __sh; \
|
||||
(sl) = __sl; \
|
||||
})
|
||||
|
||||
#define sub_ddmmss(sh, sl, ah, al, bh, bl) ({ \
|
||||
unsigned int __sh = (ah); \
|
||||
unsigned int __sl = (al); \
|
||||
asm volatile( \
|
||||
" slr %1,%3\n" \
|
||||
" brc 3,0f\n" \
|
||||
" ahi %0,-1\n" \
|
||||
"0: slr %0,%2" \
|
||||
: "+&d" (__sh), "+d" (__sl) \
|
||||
: "d" (bh), "d" (bl) : "cc"); \
|
||||
(sh) = __sh; \
|
||||
(sl) = __sl; \
|
||||
})
|
||||
|
||||
/* a umul b = a mul b + (a>=2<<31) ? b<<32:0 + (b>=2<<31) ? a<<32:0 */
|
||||
#define umul_ppmm(wh, wl, u, v) ({ \
|
||||
unsigned int __wh = u; \
|
||||
unsigned int __wl = v; \
|
||||
asm volatile( \
|
||||
" ltr 1,%0\n" \
|
||||
" mr 0,%1\n" \
|
||||
" jnm 0f\n" \
|
||||
" alr 0,%1\n" \
|
||||
"0: ltr %1,%1\n" \
|
||||
" jnm 1f\n" \
|
||||
" alr 0,%0\n" \
|
||||
"1: lr %0,0\n" \
|
||||
" lr %1,1\n" \
|
||||
: "+d" (__wh), "+d" (__wl) \
|
||||
: : "0", "1", "cc"); \
|
||||
wh = __wh; \
|
||||
wl = __wl; \
|
||||
})
|
||||
|
||||
#define udiv_qrnnd(q, r, n1, n0, d) \
|
||||
do { unsigned long __n; \
|
||||
unsigned int __r, __d; \
|
||||
__n = ((unsigned long)(n1) << 32) + n0; \
|
||||
__d = (d); \
|
||||
(q) = __n / __d; \
|
||||
(r) = __n % __d; \
|
||||
} while (0)
|
||||
|
||||
#define UDIV_NEEDS_NORMALIZATION 0
|
||||
|
||||
#define abort() BUG()
|
||||
|
||||
#define __BYTE_ORDER __BIG_ENDIAN
|
@@ -37,8 +37,8 @@
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
static inline int __pcpu_sigp(u16 addr, u8 order, unsigned long parm,
|
||||
u32 *status)
|
||||
static inline int ____pcpu_sigp(u16 addr, u8 order, unsigned long parm,
|
||||
u32 *status)
|
||||
{
|
||||
register unsigned long reg1 asm ("1") = parm;
|
||||
int cc;
|
||||
@@ -48,8 +48,19 @@ static inline int __pcpu_sigp(u16 addr, u8 order, unsigned long parm,
|
||||
" ipm %0\n"
|
||||
" srl %0,28\n"
|
||||
: "=d" (cc), "+d" (reg1) : "d" (addr), "a" (order) : "cc");
|
||||
*status = reg1;
|
||||
return cc;
|
||||
}
|
||||
|
||||
static inline int __pcpu_sigp(u16 addr, u8 order, unsigned long parm,
|
||||
u32 *status)
|
||||
{
|
||||
u32 _status;
|
||||
int cc;
|
||||
|
||||
cc = ____pcpu_sigp(addr, order, parm, &_status);
|
||||
if (status && cc == 1)
|
||||
*status = reg1;
|
||||
*status = _status;
|
||||
return cc;
|
||||
}
|
||||
|
||||
|
51
arch/s390/include/asm/stp.h
Normal file
51
arch/s390/include/asm/stp.h
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright IBM Corp. 2006
|
||||
* Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
|
||||
*/
|
||||
#ifndef __S390_STP_H
|
||||
#define __S390_STP_H
|
||||
|
||||
/* notifier for syncs */
|
||||
extern struct atomic_notifier_head s390_epoch_delta_notifier;
|
||||
|
||||
/* STP interruption parameter */
|
||||
struct stp_irq_parm {
|
||||
unsigned int _pad0 : 14;
|
||||
unsigned int tsc : 1; /* Timing status change */
|
||||
unsigned int lac : 1; /* Link availability change */
|
||||
unsigned int tcpc : 1; /* Time control parameter change */
|
||||
unsigned int _pad2 : 15;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
#define STP_OP_SYNC 1
|
||||
#define STP_OP_CTRL 3
|
||||
|
||||
struct stp_sstpi {
|
||||
unsigned int rsvd0;
|
||||
unsigned int rsvd1 : 8;
|
||||
unsigned int stratum : 8;
|
||||
unsigned int vbits : 16;
|
||||
unsigned int leaps : 16;
|
||||
unsigned int tmd : 4;
|
||||
unsigned int ctn : 4;
|
||||
unsigned int rsvd2 : 3;
|
||||
unsigned int c : 1;
|
||||
unsigned int tst : 4;
|
||||
unsigned int tzo : 16;
|
||||
unsigned int dsto : 16;
|
||||
unsigned int ctrl : 16;
|
||||
unsigned int rsvd3 : 16;
|
||||
unsigned int tto;
|
||||
unsigned int rsvd4;
|
||||
unsigned int ctnid[3];
|
||||
unsigned int rsvd5;
|
||||
unsigned int todoff[4];
|
||||
unsigned int rsvd6[48];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* Functions needed by the machine check handler */
|
||||
int stp_sync_check(void);
|
||||
int stp_island_check(void);
|
||||
void stp_queue_work(void);
|
||||
|
||||
#endif /* __S390_STP_H */
|
@@ -52,6 +52,70 @@ static inline void store_clock_comparator(__u64 *time)
|
||||
|
||||
void clock_comparator_work(void);
|
||||
|
||||
void __init ptff_init(void);
|
||||
|
||||
extern unsigned char ptff_function_mask[16];
|
||||
extern unsigned long lpar_offset;
|
||||
extern unsigned long initial_leap_seconds;
|
||||
|
||||
/* Function codes for the ptff instruction. */
|
||||
#define PTFF_QAF 0x00 /* query available functions */
|
||||
#define PTFF_QTO 0x01 /* query tod offset */
|
||||
#define PTFF_QSI 0x02 /* query steering information */
|
||||
#define PTFF_QUI 0x04 /* query UTC information */
|
||||
#define PTFF_ATO 0x40 /* adjust tod offset */
|
||||
#define PTFF_STO 0x41 /* set tod offset */
|
||||
#define PTFF_SFS 0x42 /* set fine steering rate */
|
||||
#define PTFF_SGS 0x43 /* set gross steering rate */
|
||||
|
||||
/* Query TOD offset result */
|
||||
struct ptff_qto {
|
||||
unsigned long long physical_clock;
|
||||
unsigned long long tod_offset;
|
||||
unsigned long long logical_tod_offset;
|
||||
unsigned long long tod_epoch_difference;
|
||||
} __packed;
|
||||
|
||||
static inline int ptff_query(unsigned int nr)
|
||||
{
|
||||
unsigned char *ptr;
|
||||
|
||||
ptr = ptff_function_mask + (nr >> 3);
|
||||
return (*ptr & (0x80 >> (nr & 7))) != 0;
|
||||
}
|
||||
|
||||
/* Query UTC information result */
|
||||
struct ptff_qui {
|
||||
unsigned int tm : 2;
|
||||
unsigned int ts : 2;
|
||||
unsigned int : 28;
|
||||
unsigned int pad_0x04;
|
||||
unsigned long leap_event;
|
||||
short old_leap;
|
||||
short new_leap;
|
||||
unsigned int pad_0x14;
|
||||
unsigned long prt[5];
|
||||
unsigned long cst[3];
|
||||
unsigned int skew;
|
||||
unsigned int pad_0x5c[41];
|
||||
} __packed;
|
||||
|
||||
static inline int ptff(void *ptff_block, size_t len, unsigned int func)
|
||||
{
|
||||
typedef struct { char _[len]; } addrtype;
|
||||
register unsigned int reg0 asm("0") = func;
|
||||
register unsigned long reg1 asm("1") = (unsigned long) ptff_block;
|
||||
int rc;
|
||||
|
||||
asm volatile(
|
||||
" .word 0x0104\n"
|
||||
" ipm %0\n"
|
||||
" srl %0,28\n"
|
||||
: "=d" (rc), "+m" (*(addrtype *) ptff_block)
|
||||
: "d" (reg0), "d" (reg1) : "cc");
|
||||
return rc;
|
||||
}
|
||||
|
||||
static inline unsigned long long local_tick_disable(void)
|
||||
{
|
||||
unsigned long long old;
|
||||
@@ -105,7 +169,7 @@ static inline cycles_t get_cycles(void)
|
||||
return (cycles_t) get_tod_clock() >> 2;
|
||||
}
|
||||
|
||||
int get_sync_clock(unsigned long long *clock);
|
||||
int get_phys_clock(unsigned long long *clock);
|
||||
void init_cpu_timer(void);
|
||||
unsigned long long monotonic_clock(void);
|
||||
|
||||
|
@@ -5,6 +5,7 @@
|
||||
#include <linux/sched.h>
|
||||
#include <asm/processor.h>
|
||||
#include <asm/pgalloc.h>
|
||||
#include <asm/pgtable.h>
|
||||
|
||||
/*
|
||||
* Flush all TLB entries on the local CPU.
|
||||
@@ -44,17 +45,9 @@ void smp_ptlb_all(void);
|
||||
*/
|
||||
static inline void __tlb_flush_global(void)
|
||||
{
|
||||
register unsigned long reg2 asm("2");
|
||||
register unsigned long reg3 asm("3");
|
||||
register unsigned long reg4 asm("4");
|
||||
long dummy;
|
||||
unsigned int dummy = 0;
|
||||
|
||||
dummy = 0;
|
||||
reg2 = reg3 = 0;
|
||||
reg4 = ((unsigned long) &dummy) + 1;
|
||||
asm volatile(
|
||||
" csp %0,%2"
|
||||
: : "d" (reg2), "d" (reg3), "d" (reg4), "m" (dummy) : "cc" );
|
||||
csp(&dummy, 0, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -64,7 +57,7 @@ static inline void __tlb_flush_global(void)
|
||||
static inline void __tlb_flush_full(struct mm_struct *mm)
|
||||
{
|
||||
preempt_disable();
|
||||
atomic_add(0x10000, &mm->context.attach_count);
|
||||
atomic_inc(&mm->context.flush_count);
|
||||
if (cpumask_equal(mm_cpumask(mm), cpumask_of(smp_processor_id()))) {
|
||||
/* Local TLB flush */
|
||||
__tlb_flush_local();
|
||||
@@ -76,21 +69,19 @@ static inline void __tlb_flush_full(struct mm_struct *mm)
|
||||
cpumask_copy(mm_cpumask(mm),
|
||||
&mm->context.cpu_attach_mask);
|
||||
}
|
||||
atomic_sub(0x10000, &mm->context.attach_count);
|
||||
atomic_dec(&mm->context.flush_count);
|
||||
preempt_enable();
|
||||
}
|
||||
|
||||
/*
|
||||
* Flush TLB entries for a specific ASCE on all CPUs.
|
||||
* Flush TLB entries for a specific ASCE on all CPUs. Should never be used
|
||||
* when more than one asce (e.g. gmap) ran on this mm.
|
||||
*/
|
||||
static inline void __tlb_flush_asce(struct mm_struct *mm, unsigned long asce)
|
||||
{
|
||||
int active, count;
|
||||
|
||||
preempt_disable();
|
||||
active = (mm == current->active_mm) ? 1 : 0;
|
||||
count = atomic_add_return(0x10000, &mm->context.attach_count);
|
||||
if (MACHINE_HAS_TLB_LC && (count & 0xffff) <= active &&
|
||||
atomic_inc(&mm->context.flush_count);
|
||||
if (MACHINE_HAS_TLB_LC &&
|
||||
cpumask_equal(mm_cpumask(mm), cpumask_of(smp_processor_id()))) {
|
||||
__tlb_flush_idte_local(asce);
|
||||
} else {
|
||||
@@ -103,7 +94,7 @@ static inline void __tlb_flush_asce(struct mm_struct *mm, unsigned long asce)
|
||||
cpumask_copy(mm_cpumask(mm),
|
||||
&mm->context.cpu_attach_mask);
|
||||
}
|
||||
atomic_sub(0x10000, &mm->context.attach_count);
|
||||
atomic_dec(&mm->context.flush_count);
|
||||
preempt_enable();
|
||||
}
|
||||
|
||||
|
@@ -14,10 +14,12 @@ struct cpu_topology_s390 {
|
||||
unsigned short core_id;
|
||||
unsigned short socket_id;
|
||||
unsigned short book_id;
|
||||
unsigned short drawer_id;
|
||||
unsigned short node_id;
|
||||
cpumask_t thread_mask;
|
||||
cpumask_t core_mask;
|
||||
cpumask_t book_mask;
|
||||
cpumask_t drawer_mask;
|
||||
};
|
||||
|
||||
DECLARE_PER_CPU(struct cpu_topology_s390, cpu_topology);
|
||||
@@ -30,6 +32,8 @@ DECLARE_PER_CPU(struct cpu_topology_s390, cpu_topology);
|
||||
#define topology_core_cpumask(cpu) (&per_cpu(cpu_topology, cpu).core_mask)
|
||||
#define topology_book_id(cpu) (per_cpu(cpu_topology, cpu).book_id)
|
||||
#define topology_book_cpumask(cpu) (&per_cpu(cpu_topology, cpu).book_mask)
|
||||
#define topology_drawer_id(cpu) (per_cpu(cpu_topology, cpu).drawer_id)
|
||||
#define topology_drawer_cpumask(cpu) (&per_cpu(cpu_topology, cpu).drawer_mask)
|
||||
|
||||
#define mc_capable() 1
|
||||
|
||||
|
@@ -151,8 +151,65 @@ unsigned long __must_check __copy_to_user(void __user *to, const void *from,
|
||||
__rc; \
|
||||
})
|
||||
|
||||
#define __put_user_fn(x, ptr, size) __put_get_user_asm(ptr, x, size, 0x810000UL)
|
||||
#define __get_user_fn(x, ptr, size) __put_get_user_asm(x, ptr, size, 0x81UL)
|
||||
static inline int __put_user_fn(void *x, void __user *ptr, unsigned long size)
|
||||
{
|
||||
unsigned long spec = 0x810000UL;
|
||||
int rc;
|
||||
|
||||
switch (size) {
|
||||
case 1:
|
||||
rc = __put_get_user_asm((unsigned char __user *)ptr,
|
||||
(unsigned char *)x,
|
||||
size, spec);
|
||||
break;
|
||||
case 2:
|
||||
rc = __put_get_user_asm((unsigned short __user *)ptr,
|
||||
(unsigned short *)x,
|
||||
size, spec);
|
||||
break;
|
||||
case 4:
|
||||
rc = __put_get_user_asm((unsigned int __user *)ptr,
|
||||
(unsigned int *)x,
|
||||
size, spec);
|
||||
break;
|
||||
case 8:
|
||||
rc = __put_get_user_asm((unsigned long __user *)ptr,
|
||||
(unsigned long *)x,
|
||||
size, spec);
|
||||
break;
|
||||
};
|
||||
return rc;
|
||||
}
|
||||
|
||||
static inline int __get_user_fn(void *x, const void __user *ptr, unsigned long size)
|
||||
{
|
||||
unsigned long spec = 0x81UL;
|
||||
int rc;
|
||||
|
||||
switch (size) {
|
||||
case 1:
|
||||
rc = __put_get_user_asm((unsigned char *)x,
|
||||
(unsigned char __user *)ptr,
|
||||
size, spec);
|
||||
break;
|
||||
case 2:
|
||||
rc = __put_get_user_asm((unsigned short *)x,
|
||||
(unsigned short __user *)ptr,
|
||||
size, spec);
|
||||
break;
|
||||
case 4:
|
||||
rc = __put_get_user_asm((unsigned int *)x,
|
||||
(unsigned int __user *)ptr,
|
||||
size, spec);
|
||||
break;
|
||||
case 8:
|
||||
rc = __put_get_user_asm((unsigned long *)x,
|
||||
(unsigned long __user *)ptr,
|
||||
size, spec);
|
||||
break;
|
||||
};
|
||||
return rc;
|
||||
}
|
||||
|
||||
#else /* CONFIG_HAVE_MARCH_Z10_FEATURES */
|
||||
|
||||
@@ -191,7 +248,7 @@ static inline int __get_user_fn(void *x, const void __user *ptr, unsigned long s
|
||||
__put_user_bad(); \
|
||||
break; \
|
||||
} \
|
||||
__pu_err; \
|
||||
__builtin_expect(__pu_err, 0); \
|
||||
})
|
||||
|
||||
#define put_user(x, ptr) \
|
||||
@@ -240,7 +297,7 @@ int __put_user_bad(void) __attribute__((noreturn));
|
||||
__get_user_bad(); \
|
||||
break; \
|
||||
} \
|
||||
__gu_err; \
|
||||
__builtin_expect(__gu_err, 0); \
|
||||
})
|
||||
|
||||
#define get_user(x, ptr) \
|
||||
|
Reference in New Issue
Block a user