Merge android-4.4.133 (3f51ea2
) into msm-4.4
* refs/heads/tmp-3f51ea2 Linux 4.4.133 x86/kexec: Avoid double free_page() upon do_kexec_load() failure hfsplus: stop workqueue when fill_super() failed cfg80211: limit wiphy names to 128 bytes gpio: rcar: Add Runtime PM handling for interrupts time: Fix CLOCK_MONOTONIC_RAW sub-nanosecond accounting dmaengine: ensure dmaengine helpers check valid callback scsi: zfcp: fix infinite iteration on ERP ready list scsi: sg: allocate with __GFP_ZERO in sg_build_indirect() scsi: libsas: defer ata device eh commands to libata s390: use expoline thunks in the BPF JIT s390: extend expoline to BC instructions s390: move spectre sysfs attribute code s390/kernel: use expoline for indirect branches s390/lib: use expoline for indirect branches s390: move expoline assembler macros to a header s390: add assembler macros for CPU alternatives ext2: fix a block leak tcp: purge write queue in tcp_connect_init() sock_diag: fix use-after-free read in __sk_free packet: in packet_snd start writing at link layer allocation net: test tailroom before appending to linear skb btrfs: fix reading stale metadata blocks after degraded raid1 mounts btrfs: fix crash when trying to resume balance without the resume flag Btrfs: fix xattr loss after power failure ARM: 8772/1: kprobes: Prohibit kprobes on get_user functions ARM: 8770/1: kprobes: Prohibit probing on optimized_callback ARM: 8769/1: kprobes: Fix to use get_kprobe_ctlblk after irq-disabed tick/broadcast: Use for_each_cpu() specially on UP kernels ARM: 8771/1: kprobes: Prohibit kprobes on do_undefinstr efi: Avoid potential crashes, fix the 'struct efi_pci_io_protocol_32' definition for mixed mode s390: remove indirect branch from do_softirq_own_stack s390/qdio: don't release memory in qdio_setup_irq() s390/cpum_sf: ensure sample frequency of perf event attributes is non-zero s390/qdio: fix access to uninitialized qdio_q fields mm: don't allow deferred pages with NEED_PER_CPU_KM powerpc/powernv: Fix NVRAM sleep in invalid context when crashing procfs: fix pthread cross-thread naming if !PR_DUMPABLE proc read mm's {arg,env}_{start,end} with mmap semaphore taken. tracing/x86/xen: Remove zero data size trace events trace_xen_mmu_flush_tlb{_all} cpufreq: intel_pstate: Enable HWP by default signals: avoid unnecessary taking of sighand->siglock mm: filemap: avoid unnecessary calls to lock_page when waiting for IO to complete during a read mm: filemap: remove redundant code in do_read_cache_page proc: meminfo: estimate available memory more conservatively vmscan: do not force-scan file lru if its absolute size is small powerpc: Don't preempt_disable() in show_cpuinfo() cpuidle: coupled: remove unused define cpuidle_coupled_lock powerpc/powernv: remove FW_FEATURE_OPALv3 and just use FW_FEATURE_OPAL powerpc/powernv: Remove OPALv2 firmware define and references powerpc/powernv: panic() on OPAL < V3 spi: pxa2xx: Allow 64-bit DMA ALSA: control: fix a redundant-copy issue ALSA: hda: Add Lenovo C50 All in one to the power_save blacklist ALSA: usb: mixer: volume quirk for CM102-A+/102S+ usbip: usbip_host: fix bad unlock balance during stub_probe() usbip: usbip_host: fix NULL-ptr deref and use-after-free errors usbip: usbip_host: run rebind from exit when module is removed usbip: usbip_host: delete device from busid_table after rebind usbip: usbip_host: refine probe and disconnect debug msgs to be useful kernel/exit.c: avoid undefined behaviour when calling wait4() futex: futex_wake_op, fix sign_extend32 sign bits pipe: cap initial pipe capacity according to pipe-max-size limit l2tp: revert "l2tp: fix missing print session offset info" Revert "ARM: dts: imx6qdl-wandboard: Fix audio channel swap" lockd: lost rollback of set_grace_period() in lockd_down_net() xfrm: fix xfrm_do_migrate() with AEAD e.g(AES-GCM) futex: Remove duplicated code and fix undefined behaviour futex: Remove unnecessary warning from get_futex_key arm64: Add work around for Arm Cortex-A55 Erratum 1024718 arm64: introduce mov_q macro to move a constant into a 64-bit register audit: move calcs after alloc and check when logging set loginuid ALSA: timer: Call notifier in the same spinlock sctp: delay the authentication for the duplicated cookie-echo chunk sctp: fix the issue that the cookie-ack with auth can't get processed tcp: ignore Fast Open on repair mode bonding: do not allow rlb updates to invalid mac tg3: Fix vunmap() BUG_ON() triggered from tg3_free_consistent(). sctp: use the old asoc when making the cookie-ack chunk in dupcook_d sctp: handle two v4 addrs comparison in sctp_inet6_cmp_addr r8169: fix powering up RTL8168h qmi_wwan: do not steal interfaces from class drivers openvswitch: Don't swap table in nlattr_set() after OVS_ATTR_NESTED is found net: support compat 64-bit time in {s,g}etsockopt net_sched: fq: take care of throttled flows before reuse net/mlx4_en: Verify coalescing parameters are in range net: ethernet: sun: niu set correct packet size in skb llc: better deal with too small mtu ipv4: fix memory leaks in udp_sendmsg, ping_v4_sendmsg dccp: fix tasklet usage bridge: check iface upper dev when setting master via ioctl 8139too: Use disable_irq_nosync() in rtl8139_poll_controller() BACKPORT, FROMLIST: fscrypt: add Speck128/256 support cgroup: Disable IRQs while holding css_set_lock Revert "cgroup: Disable IRQs while holding css_set_lock" cgroup: Disable IRQs while holding css_set_lock ANDROID: proc: fix undefined behavior in proc_uid_base_readdir x86: vdso: Fix leaky vdso linker with CC=clang. ANDROID: build: cuttlefish: Upgrade clang to newer version. ANDROID: build: cuttlefish: Upgrade clang to newer version. ANDROID: build: cuttlefish: Fix path to clang. UPSTREAM: dm bufio: avoid sleeping while holding the dm_bufio lock ANDROID: sdcardfs: Don't d_drop in d_revalidate Conflicts: arch/arm64/include/asm/cputype.h fs/ext4/crypto.c fs/ext4/ext4.h kernel/cgroup.c mm/vmscan.c Change-Id: Ic10c5722b6439af1cf423fd949c493f786764d7e Signed-off-by: Srinivasarao P <spathi@codeaurora.org>
This commit is contained in:
commit
9848856fe1
142 changed files with 1454 additions and 1007 deletions
2
Makefile
2
Makefile
|
@ -1,6 +1,6 @@
|
|||
VERSION = 4
|
||||
PATCHLEVEL = 4
|
||||
SUBLEVEL = 132
|
||||
SUBLEVEL = 133
|
||||
EXTRAVERSION =
|
||||
NAME = Blurry Fish Butt
|
||||
|
||||
|
|
|
@ -29,18 +29,10 @@
|
|||
: "r" (uaddr), "r"(oparg) \
|
||||
: "memory")
|
||||
|
||||
static inline int futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
|
||||
static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,
|
||||
u32 __user *uaddr)
|
||||
{
|
||||
int op = (encoded_op >> 28) & 7;
|
||||
int cmp = (encoded_op >> 24) & 15;
|
||||
int oparg = (encoded_op << 8) >> 20;
|
||||
int cmparg = (encoded_op << 20) >> 20;
|
||||
int oldval = 0, ret;
|
||||
if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
|
||||
oparg = 1 << oparg;
|
||||
|
||||
if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
|
||||
return -EFAULT;
|
||||
|
||||
pagefault_disable();
|
||||
|
||||
|
@ -66,17 +58,9 @@ static inline int futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
|
|||
|
||||
pagefault_enable();
|
||||
|
||||
if (!ret) {
|
||||
switch (cmp) {
|
||||
case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
|
||||
case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
|
||||
case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
|
||||
case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
|
||||
case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
|
||||
case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
|
||||
default: ret = -ENOSYS;
|
||||
}
|
||||
}
|
||||
if (!ret)
|
||||
*oval = oldval;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -73,20 +73,11 @@
|
|||
|
||||
#endif
|
||||
|
||||
static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
|
||||
static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,
|
||||
u32 __user *uaddr)
|
||||
{
|
||||
int op = (encoded_op >> 28) & 7;
|
||||
int cmp = (encoded_op >> 24) & 15;
|
||||
int oparg = (encoded_op << 8) >> 20;
|
||||
int cmparg = (encoded_op << 20) >> 20;
|
||||
int oldval = 0, ret;
|
||||
|
||||
if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
|
||||
oparg = 1 << oparg;
|
||||
|
||||
if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
|
||||
return -EFAULT;
|
||||
|
||||
#ifndef CONFIG_ARC_HAS_LLSC
|
||||
preempt_disable(); /* to guarantee atomic r-m-w of futex op */
|
||||
#endif
|
||||
|
@ -118,30 +109,9 @@ static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
|
|||
preempt_enable();
|
||||
#endif
|
||||
|
||||
if (!ret) {
|
||||
switch (cmp) {
|
||||
case FUTEX_OP_CMP_EQ:
|
||||
ret = (oldval == cmparg);
|
||||
break;
|
||||
case FUTEX_OP_CMP_NE:
|
||||
ret = (oldval != cmparg);
|
||||
break;
|
||||
case FUTEX_OP_CMP_LT:
|
||||
ret = (oldval < cmparg);
|
||||
break;
|
||||
case FUTEX_OP_CMP_GE:
|
||||
ret = (oldval >= cmparg);
|
||||
break;
|
||||
case FUTEX_OP_CMP_LE:
|
||||
ret = (oldval <= cmparg);
|
||||
break;
|
||||
case FUTEX_OP_CMP_GT:
|
||||
ret = (oldval > cmparg);
|
||||
break;
|
||||
default:
|
||||
ret = -ENOSYS;
|
||||
}
|
||||
}
|
||||
if (!ret)
|
||||
*oval = oldval;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -88,7 +88,6 @@
|
|||
clocks = <&clks 201>;
|
||||
VDDA-supply = <®_2p5v>;
|
||||
VDDIO-supply = <®_3p3v>;
|
||||
lrclk-strength = <3>;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -530,4 +530,14 @@ THUMB( orr \reg , \reg , #PSR_T_BIT )
|
|||
#endif
|
||||
.endm
|
||||
|
||||
#ifdef CONFIG_KPROBES
|
||||
#define _ASM_NOKPROBE(entry) \
|
||||
.pushsection "_kprobe_blacklist", "aw" ; \
|
||||
.balign 4 ; \
|
||||
.long entry; \
|
||||
.popsection
|
||||
#else
|
||||
#define _ASM_NOKPROBE(entry)
|
||||
#endif
|
||||
|
||||
#endif /* __ASM_ASSEMBLER_H__ */
|
||||
|
|
|
@ -128,20 +128,10 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
|
|||
#endif /* !SMP */
|
||||
|
||||
static inline int
|
||||
futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
|
||||
arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)
|
||||
{
|
||||
int op = (encoded_op >> 28) & 7;
|
||||
int cmp = (encoded_op >> 24) & 15;
|
||||
int oparg = (encoded_op << 8) >> 20;
|
||||
int cmparg = (encoded_op << 20) >> 20;
|
||||
int oldval = 0, ret, tmp;
|
||||
|
||||
if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
|
||||
oparg = 1 << oparg;
|
||||
|
||||
if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
|
||||
return -EFAULT;
|
||||
|
||||
#ifndef CONFIG_SMP
|
||||
preempt_disable();
|
||||
#endif
|
||||
|
@ -172,17 +162,9 @@ futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
|
|||
preempt_enable();
|
||||
#endif
|
||||
|
||||
if (!ret) {
|
||||
switch (cmp) {
|
||||
case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
|
||||
case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
|
||||
case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
|
||||
case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
|
||||
case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
|
||||
case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
|
||||
default: ret = -ENOSYS;
|
||||
}
|
||||
}
|
||||
if (!ret)
|
||||
*oval = oldval;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include <linux/uaccess.h>
|
||||
#include <linux/hardirq.h>
|
||||
#include <linux/kdebug.h>
|
||||
#include <linux/kprobes.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kexec.h>
|
||||
#include <linux/bug.h>
|
||||
|
@ -396,7 +397,8 @@ void unregister_undef_hook(struct undef_hook *hook)
|
|||
raw_spin_unlock_irqrestore(&undef_lock, flags);
|
||||
}
|
||||
|
||||
static int call_undef_hook(struct pt_regs *regs, unsigned int instr)
|
||||
static nokprobe_inline
|
||||
int call_undef_hook(struct pt_regs *regs, unsigned int instr)
|
||||
{
|
||||
struct undef_hook *hook;
|
||||
unsigned long flags;
|
||||
|
@ -469,6 +471,7 @@ die_sig:
|
|||
|
||||
arm_notify_die("Oops - undefined instruction", regs, &info, 0, 6);
|
||||
}
|
||||
NOKPROBE_SYMBOL(do_undefinstr)
|
||||
|
||||
/*
|
||||
* Handle FIQ similarly to NMI on x86 systems.
|
||||
|
|
|
@ -38,6 +38,7 @@ ENTRY(__get_user_1)
|
|||
mov r0, #0
|
||||
ret lr
|
||||
ENDPROC(__get_user_1)
|
||||
_ASM_NOKPROBE(__get_user_1)
|
||||
|
||||
ENTRY(__get_user_2)
|
||||
check_uaccess r0, 2, r1, r2, __get_user_bad
|
||||
|
@ -58,6 +59,7 @@ rb .req r0
|
|||
mov r0, #0
|
||||
ret lr
|
||||
ENDPROC(__get_user_2)
|
||||
_ASM_NOKPROBE(__get_user_2)
|
||||
|
||||
ENTRY(__get_user_4)
|
||||
check_uaccess r0, 4, r1, r2, __get_user_bad
|
||||
|
@ -65,6 +67,7 @@ ENTRY(__get_user_4)
|
|||
mov r0, #0
|
||||
ret lr
|
||||
ENDPROC(__get_user_4)
|
||||
_ASM_NOKPROBE(__get_user_4)
|
||||
|
||||
ENTRY(__get_user_8)
|
||||
check_uaccess r0, 8, r1, r2, __get_user_bad8
|
||||
|
@ -78,6 +81,7 @@ ENTRY(__get_user_8)
|
|||
mov r0, #0
|
||||
ret lr
|
||||
ENDPROC(__get_user_8)
|
||||
_ASM_NOKPROBE(__get_user_8)
|
||||
|
||||
#ifdef __ARMEB__
|
||||
ENTRY(__get_user_32t_8)
|
||||
|
@ -91,6 +95,7 @@ ENTRY(__get_user_32t_8)
|
|||
mov r0, #0
|
||||
ret lr
|
||||
ENDPROC(__get_user_32t_8)
|
||||
_ASM_NOKPROBE(__get_user_32t_8)
|
||||
|
||||
ENTRY(__get_user_64t_1)
|
||||
check_uaccess r0, 1, r1, r2, __get_user_bad8
|
||||
|
@ -98,6 +103,7 @@ ENTRY(__get_user_64t_1)
|
|||
mov r0, #0
|
||||
ret lr
|
||||
ENDPROC(__get_user_64t_1)
|
||||
_ASM_NOKPROBE(__get_user_64t_1)
|
||||
|
||||
ENTRY(__get_user_64t_2)
|
||||
check_uaccess r0, 2, r1, r2, __get_user_bad8
|
||||
|
@ -114,6 +120,7 @@ rb .req r0
|
|||
mov r0, #0
|
||||
ret lr
|
||||
ENDPROC(__get_user_64t_2)
|
||||
_ASM_NOKPROBE(__get_user_64t_2)
|
||||
|
||||
ENTRY(__get_user_64t_4)
|
||||
check_uaccess r0, 4, r1, r2, __get_user_bad8
|
||||
|
@ -121,6 +128,7 @@ ENTRY(__get_user_64t_4)
|
|||
mov r0, #0
|
||||
ret lr
|
||||
ENDPROC(__get_user_64t_4)
|
||||
_ASM_NOKPROBE(__get_user_64t_4)
|
||||
#endif
|
||||
|
||||
__get_user_bad8:
|
||||
|
@ -131,6 +139,8 @@ __get_user_bad:
|
|||
ret lr
|
||||
ENDPROC(__get_user_bad)
|
||||
ENDPROC(__get_user_bad8)
|
||||
_ASM_NOKPROBE(__get_user_bad)
|
||||
_ASM_NOKPROBE(__get_user_bad8)
|
||||
|
||||
.pushsection __ex_table, "a"
|
||||
.long 1b, __get_user_bad
|
||||
|
|
|
@ -165,13 +165,14 @@ optimized_callback(struct optimized_kprobe *op, struct pt_regs *regs)
|
|||
{
|
||||
unsigned long flags;
|
||||
struct kprobe *p = &op->kp;
|
||||
struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
|
||||
struct kprobe_ctlblk *kcb;
|
||||
|
||||
/* Save skipped registers */
|
||||
regs->ARM_pc = (unsigned long)op->kp.addr;
|
||||
regs->ARM_ORIG_r0 = ~0UL;
|
||||
|
||||
local_irq_save(flags);
|
||||
kcb = get_kprobe_ctlblk();
|
||||
|
||||
if (kprobe_running()) {
|
||||
kprobes_inc_nmissed_count(&op->kp);
|
||||
|
@ -191,6 +192,7 @@ optimized_callback(struct optimized_kprobe *op, struct pt_regs *regs)
|
|||
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
NOKPROBE_SYMBOL(optimized_callback)
|
||||
|
||||
int arch_prepare_optimized_kprobe(struct optimized_kprobe *op, struct kprobe *orig)
|
||||
{
|
||||
|
|
|
@ -465,6 +465,20 @@ config ARM64_ERRATUM_843419
|
|||
|
||||
If unsure, say Y.
|
||||
|
||||
config ARM64_ERRATUM_1024718
|
||||
bool "Cortex-A55: 1024718: Update of DBM/AP bits without break before make might result in incorrect update"
|
||||
default y
|
||||
help
|
||||
This option adds work around for Arm Cortex-A55 Erratum 1024718.
|
||||
|
||||
Affected Cortex-A55 cores (r0p0, r0p1, r1p0) could cause incorrect
|
||||
update of the hardware dirty bit when the DBM/AP bits are updated
|
||||
without a break-before-make. The work around is to disable the usage
|
||||
of hardware DBM locally on the affected cores. CPUs not affected by
|
||||
erratum will continue to use the feature.
|
||||
|
||||
If unsure, say Y.
|
||||
|
||||
config CAVIUM_ERRATUM_22375
|
||||
bool "Cavium erratum 22375, 24313"
|
||||
default y
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include <asm/cpufeature.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/pgtable-hwdef.h>
|
||||
#include <asm/cputype.h>
|
||||
#include <asm/ptrace.h>
|
||||
#include <asm/thread_info.h>
|
||||
|
||||
|
@ -410,4 +411,43 @@ alternative_endif
|
|||
mrs \rd, sp_el0
|
||||
.endm
|
||||
|
||||
/*
|
||||
* Check the MIDR_EL1 of the current CPU for a given model and a range of
|
||||
* variant/revision. See asm/cputype.h for the macros used below.
|
||||
*
|
||||
* model: MIDR_CPU_PART of CPU
|
||||
* rv_min: Minimum of MIDR_CPU_VAR_REV()
|
||||
* rv_max: Maximum of MIDR_CPU_VAR_REV()
|
||||
* res: Result register.
|
||||
* tmp1, tmp2, tmp3: Temporary registers
|
||||
*
|
||||
* Corrupts: res, tmp1, tmp2, tmp3
|
||||
* Returns: 0, if the CPU id doesn't match. Non-zero otherwise
|
||||
*/
|
||||
.macro cpu_midr_match model, rv_min, rv_max, res, tmp1, tmp2, tmp3
|
||||
mrs \res, midr_el1
|
||||
mov_q \tmp1, (MIDR_REVISION_MASK | MIDR_VARIANT_MASK)
|
||||
mov_q \tmp2, MIDR_CPU_PART_MASK
|
||||
and \tmp3, \res, \tmp2 // Extract model
|
||||
and \tmp1, \res, \tmp1 // rev & variant
|
||||
mov_q \tmp2, \model
|
||||
cmp \tmp3, \tmp2
|
||||
cset \res, eq
|
||||
cbz \res, .Ldone\@ // Model matches ?
|
||||
|
||||
.if (\rv_min != 0) // Skip min check if rv_min == 0
|
||||
mov_q \tmp3, \rv_min
|
||||
cmp \tmp1, \tmp3
|
||||
cset \res, ge
|
||||
.endif // \rv_min != 0
|
||||
/* Skip rv_max check if rv_min == rv_max && rv_min != 0 */
|
||||
.if ((\rv_min != \rv_max) || \rv_min == 0)
|
||||
mov_q \tmp2, \rv_max
|
||||
cmp \tmp1, \tmp2
|
||||
cset \tmp2, le
|
||||
and \res, \res, \tmp2
|
||||
.endif
|
||||
.Ldone\@:
|
||||
.endm
|
||||
|
||||
#endif /* __ASM_ASSEMBLER_H */
|
||||
|
|
|
@ -55,6 +55,14 @@
|
|||
#define MIDR_IMPLEMENTOR(midr) \
|
||||
(((midr) & MIDR_IMPLEMENTOR_MASK) >> MIDR_IMPLEMENTOR_SHIFT)
|
||||
|
||||
#define MIDR_CPU_VAR_REV(var, rev) \
|
||||
(((var) << MIDR_VARIANT_SHIFT) | (rev))
|
||||
|
||||
#define MIDR_CPU_PART_MASK \
|
||||
(MIDR_IMPLEMENTOR_MASK | \
|
||||
MIDR_ARCHITECTURE_MASK | \
|
||||
MIDR_PARTNUM_MASK)
|
||||
|
||||
#define MIDR_CPU_MODEL(imp, partnum) \
|
||||
(((imp) << MIDR_IMPLEMENTOR_SHIFT) | \
|
||||
(0xf << MIDR_ARCHITECTURE_SHIFT) | \
|
||||
|
@ -78,9 +86,9 @@
|
|||
|
||||
#define ARM_CPU_PART_AEM_V8 0xD0F
|
||||
#define ARM_CPU_PART_FOUNDATION 0xD00
|
||||
#define ARM_CPU_PART_CORTEX_A57 0xD07
|
||||
#define ARM_CPU_PART_CORTEX_A72 0xD08
|
||||
#define ARM_CPU_PART_CORTEX_A53 0xD03
|
||||
#define ARM_CPU_PART_CORTEX_A55 0xD05
|
||||
#define ARM_CPU_PART_CORTEX_A57 0xD07
|
||||
#define ARM_CPU_PART_CORTEX_A72 0xD08
|
||||
#define ARM_CPU_PART_CORTEX_A73 0xD09
|
||||
#define ARM_CPU_PART_CORTEX_A75 0xD0A
|
||||
|
@ -93,6 +101,7 @@
|
|||
#define CAVIUM_CPU_PART_THUNDERX 0x0A1
|
||||
|
||||
#define MIDR_CORTEX_A53 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A53)
|
||||
#define MIDR_CORTEX_A55 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A55)
|
||||
#define MIDR_CORTEX_A57 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A57)
|
||||
#define MIDR_CORTEX_A72 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A72)
|
||||
#define MIDR_CORTEX_A73 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A73)
|
||||
|
|
|
@ -48,20 +48,10 @@ do { \
|
|||
} while (0)
|
||||
|
||||
static inline int
|
||||
futex_atomic_op_inuser(unsigned int encoded_op, u32 __user *uaddr)
|
||||
arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)
|
||||
{
|
||||
int op = (encoded_op >> 28) & 7;
|
||||
int cmp = (encoded_op >> 24) & 15;
|
||||
int oparg = (int)(encoded_op << 8) >> 20;
|
||||
int cmparg = (int)(encoded_op << 20) >> 20;
|
||||
int oldval = 0, ret, tmp;
|
||||
|
||||
if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
|
||||
oparg = 1U << (oparg & 0x1f);
|
||||
|
||||
if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
|
||||
return -EFAULT;
|
||||
|
||||
pagefault_disable();
|
||||
|
||||
switch (op) {
|
||||
|
@ -91,17 +81,9 @@ futex_atomic_op_inuser(unsigned int encoded_op, u32 __user *uaddr)
|
|||
|
||||
pagefault_enable();
|
||||
|
||||
if (!ret) {
|
||||
switch (cmp) {
|
||||
case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
|
||||
case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
|
||||
case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
|
||||
case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
|
||||
case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
|
||||
case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
|
||||
default: ret = -ENOSYS;
|
||||
}
|
||||
}
|
||||
if (!ret)
|
||||
*oval = oldval;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -281,6 +281,11 @@ ENTRY(__cpu_setup)
|
|||
cbz x9, 2f
|
||||
cmp x9, #2
|
||||
b.lt 1f
|
||||
#ifdef CONFIG_ARM64_ERRATUM_1024718
|
||||
/* Disable hardware DBM on Cortex-A55 r0p0, r0p1 & r1p0 */
|
||||
cpu_midr_match MIDR_CORTEX_A55, MIDR_CPU_VAR_REV(0, 0), MIDR_CPU_VAR_REV(1, 0), x1, x2, x3, x4
|
||||
cbnz x1, 1f
|
||||
#endif
|
||||
orr x10, x10, #TCR_HD // hardware Dirty flag update
|
||||
1: orr x10, x10, #TCR_HA // hardware Access flag update
|
||||
2:
|
||||
|
|
|
@ -7,7 +7,8 @@
|
|||
#include <asm/errno.h>
|
||||
#include <asm/uaccess.h>
|
||||
|
||||
extern int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr);
|
||||
extern int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,
|
||||
u32 __user *uaddr);
|
||||
|
||||
static inline int
|
||||
futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
|
||||
|
|
|
@ -186,20 +186,10 @@ static inline int atomic_futex_op_xchg_xor(int oparg, u32 __user *uaddr, int *_o
|
|||
/*
|
||||
* do the futex operations
|
||||
*/
|
||||
int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
|
||||
int arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)
|
||||
{
|
||||
int op = (encoded_op >> 28) & 7;
|
||||
int cmp = (encoded_op >> 24) & 15;
|
||||
int oparg = (encoded_op << 8) >> 20;
|
||||
int cmparg = (encoded_op << 20) >> 20;
|
||||
int oldval = 0, ret;
|
||||
|
||||
if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
|
||||
oparg = 1 << oparg;
|
||||
|
||||
if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
|
||||
return -EFAULT;
|
||||
|
||||
pagefault_disable();
|
||||
|
||||
switch (op) {
|
||||
|
@ -225,18 +215,9 @@ int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
|
|||
|
||||
pagefault_enable();
|
||||
|
||||
if (!ret) {
|
||||
switch (cmp) {
|
||||
case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
|
||||
case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
|
||||
case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
|
||||
case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
|
||||
case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
|
||||
case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
|
||||
default: ret = -ENOSYS; break;
|
||||
}
|
||||
}
|
||||
if (!ret)
|
||||
*oval = oldval;
|
||||
|
||||
return ret;
|
||||
|
||||
} /* end futex_atomic_op_inuser() */
|
||||
} /* end arch_futex_atomic_op_inuser() */
|
||||
|
|
|
@ -31,18 +31,9 @@
|
|||
|
||||
|
||||
static inline int
|
||||
futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
|
||||
arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)
|
||||
{
|
||||
int op = (encoded_op >> 28) & 7;
|
||||
int cmp = (encoded_op >> 24) & 15;
|
||||
int oparg = (encoded_op << 8) >> 20;
|
||||
int cmparg = (encoded_op << 20) >> 20;
|
||||
int oldval = 0, ret;
|
||||
if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
|
||||
oparg = 1 << oparg;
|
||||
|
||||
if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
|
||||
return -EFAULT;
|
||||
|
||||
pagefault_disable();
|
||||
|
||||
|
@ -72,30 +63,9 @@ futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
|
|||
|
||||
pagefault_enable();
|
||||
|
||||
if (!ret) {
|
||||
switch (cmp) {
|
||||
case FUTEX_OP_CMP_EQ:
|
||||
ret = (oldval == cmparg);
|
||||
break;
|
||||
case FUTEX_OP_CMP_NE:
|
||||
ret = (oldval != cmparg);
|
||||
break;
|
||||
case FUTEX_OP_CMP_LT:
|
||||
ret = (oldval < cmparg);
|
||||
break;
|
||||
case FUTEX_OP_CMP_GE:
|
||||
ret = (oldval >= cmparg);
|
||||
break;
|
||||
case FUTEX_OP_CMP_LE:
|
||||
ret = (oldval <= cmparg);
|
||||
break;
|
||||
case FUTEX_OP_CMP_GT:
|
||||
ret = (oldval > cmparg);
|
||||
break;
|
||||
default:
|
||||
ret = -ENOSYS;
|
||||
}
|
||||
}
|
||||
if (!ret)
|
||||
*oval = oldval;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -45,18 +45,9 @@ do { \
|
|||
} while (0)
|
||||
|
||||
static inline int
|
||||
futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
|
||||
arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)
|
||||
{
|
||||
int op = (encoded_op >> 28) & 7;
|
||||
int cmp = (encoded_op >> 24) & 15;
|
||||
int oparg = (encoded_op << 8) >> 20;
|
||||
int cmparg = (encoded_op << 20) >> 20;
|
||||
int oldval = 0, ret;
|
||||
if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
|
||||
oparg = 1 << oparg;
|
||||
|
||||
if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))
|
||||
return -EFAULT;
|
||||
|
||||
pagefault_disable();
|
||||
|
||||
|
@ -84,17 +75,9 @@ futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
|
|||
|
||||
pagefault_enable();
|
||||
|
||||
if (!ret) {
|
||||
switch (cmp) {
|
||||
case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
|
||||
case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
|
||||
case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
|
||||
case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
|
||||
case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
|
||||
case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
|
||||
default: ret = -ENOSYS;
|
||||
}
|
||||
}
|
||||
if (!ret)
|
||||
*oval = oldval;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -29,18 +29,9 @@
|
|||
})
|
||||
|
||||
static inline int
|
||||
futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
|
||||
arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)
|
||||
{
|
||||
int op = (encoded_op >> 28) & 7;
|
||||
int cmp = (encoded_op >> 24) & 15;
|
||||
int oparg = (encoded_op << 8) >> 20;
|
||||
int cmparg = (encoded_op << 20) >> 20;
|
||||
int oldval = 0, ret;
|
||||
if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
|
||||
oparg = 1 << oparg;
|
||||
|
||||
if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
|
||||
return -EFAULT;
|
||||
|
||||
pagefault_disable();
|
||||
|
||||
|
@ -66,30 +57,9 @@ futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
|
|||
|
||||
pagefault_enable();
|
||||
|
||||
if (!ret) {
|
||||
switch (cmp) {
|
||||
case FUTEX_OP_CMP_EQ:
|
||||
ret = (oldval == cmparg);
|
||||
break;
|
||||
case FUTEX_OP_CMP_NE:
|
||||
ret = (oldval != cmparg);
|
||||
break;
|
||||
case FUTEX_OP_CMP_LT:
|
||||
ret = (oldval < cmparg);
|
||||
break;
|
||||
case FUTEX_OP_CMP_GE:
|
||||
ret = (oldval >= cmparg);
|
||||
break;
|
||||
case FUTEX_OP_CMP_LE:
|
||||
ret = (oldval <= cmparg);
|
||||
break;
|
||||
case FUTEX_OP_CMP_GT:
|
||||
ret = (oldval > cmparg);
|
||||
break;
|
||||
default:
|
||||
ret = -ENOSYS;
|
||||
}
|
||||
}
|
||||
if (!ret)
|
||||
*oval = oldval;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -83,18 +83,9 @@
|
|||
}
|
||||
|
||||
static inline int
|
||||
futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
|
||||
arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)
|
||||
{
|
||||
int op = (encoded_op >> 28) & 7;
|
||||
int cmp = (encoded_op >> 24) & 15;
|
||||
int oparg = (encoded_op << 8) >> 20;
|
||||
int cmparg = (encoded_op << 20) >> 20;
|
||||
int oldval = 0, ret;
|
||||
if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
|
||||
oparg = 1 << oparg;
|
||||
|
||||
if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))
|
||||
return -EFAULT;
|
||||
|
||||
pagefault_disable();
|
||||
|
||||
|
@ -125,17 +116,9 @@ futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
|
|||
|
||||
pagefault_enable();
|
||||
|
||||
if (!ret) {
|
||||
switch (cmp) {
|
||||
case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
|
||||
case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
|
||||
case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
|
||||
case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
|
||||
case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
|
||||
case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
|
||||
default: ret = -ENOSYS;
|
||||
}
|
||||
}
|
||||
if (!ret)
|
||||
*oval = oldval;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -32,20 +32,11 @@ _futex_spin_unlock_irqrestore(u32 __user *uaddr, unsigned long int *flags)
|
|||
}
|
||||
|
||||
static inline int
|
||||
futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
|
||||
arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)
|
||||
{
|
||||
unsigned long int flags;
|
||||
u32 val;
|
||||
int op = (encoded_op >> 28) & 7;
|
||||
int cmp = (encoded_op >> 24) & 15;
|
||||
int oparg = (encoded_op << 8) >> 20;
|
||||
int cmparg = (encoded_op << 20) >> 20;
|
||||
int oldval = 0, ret;
|
||||
if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
|
||||
oparg = 1 << oparg;
|
||||
|
||||
if (!access_ok(VERIFY_WRITE, uaddr, sizeof(*uaddr)))
|
||||
return -EFAULT;
|
||||
|
||||
pagefault_disable();
|
||||
|
||||
|
@ -98,17 +89,9 @@ futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
|
|||
|
||||
pagefault_enable();
|
||||
|
||||
if (!ret) {
|
||||
switch (cmp) {
|
||||
case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
|
||||
case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
|
||||
case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
|
||||
case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
|
||||
case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
|
||||
case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
|
||||
default: ret = -ENOSYS;
|
||||
}
|
||||
}
|
||||
if (!ret)
|
||||
*oval = oldval;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -47,12 +47,10 @@
|
|||
#define FW_FEATURE_VPHN ASM_CONST(0x0000000004000000)
|
||||
#define FW_FEATURE_XCMO ASM_CONST(0x0000000008000000)
|
||||
#define FW_FEATURE_OPAL ASM_CONST(0x0000000010000000)
|
||||
#define FW_FEATURE_OPALv2 ASM_CONST(0x0000000020000000)
|
||||
#define FW_FEATURE_SET_MODE ASM_CONST(0x0000000040000000)
|
||||
#define FW_FEATURE_BEST_ENERGY ASM_CONST(0x0000000080000000)
|
||||
#define FW_FEATURE_TYPE1_AFFINITY ASM_CONST(0x0000000100000000)
|
||||
#define FW_FEATURE_PRRN ASM_CONST(0x0000000200000000)
|
||||
#define FW_FEATURE_OPALv3 ASM_CONST(0x0000000400000000)
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
|
@ -70,8 +68,7 @@ enum {
|
|||
FW_FEATURE_SET_MODE | FW_FEATURE_BEST_ENERGY |
|
||||
FW_FEATURE_TYPE1_AFFINITY | FW_FEATURE_PRRN,
|
||||
FW_FEATURE_PSERIES_ALWAYS = 0,
|
||||
FW_FEATURE_POWERNV_POSSIBLE = FW_FEATURE_OPAL | FW_FEATURE_OPALv2 |
|
||||
FW_FEATURE_OPALv3,
|
||||
FW_FEATURE_POWERNV_POSSIBLE = FW_FEATURE_OPAL,
|
||||
FW_FEATURE_POWERNV_ALWAYS = 0,
|
||||
FW_FEATURE_PS3_POSSIBLE = FW_FEATURE_LPAR | FW_FEATURE_PS3_LV1,
|
||||
FW_FEATURE_PS3_ALWAYS = FW_FEATURE_LPAR | FW_FEATURE_PS3_LV1,
|
||||
|
|
|
@ -31,18 +31,10 @@
|
|||
: "b" (uaddr), "i" (-EFAULT), "r" (oparg) \
|
||||
: "cr0", "memory")
|
||||
|
||||
static inline int futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
|
||||
static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,
|
||||
u32 __user *uaddr)
|
||||
{
|
||||
int op = (encoded_op >> 28) & 7;
|
||||
int cmp = (encoded_op >> 24) & 15;
|
||||
int oparg = (encoded_op << 8) >> 20;
|
||||
int cmparg = (encoded_op << 20) >> 20;
|
||||
int oldval = 0, ret;
|
||||
if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
|
||||
oparg = 1 << oparg;
|
||||
|
||||
if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))
|
||||
return -EFAULT;
|
||||
|
||||
pagefault_disable();
|
||||
|
||||
|
@ -68,17 +60,9 @@ static inline int futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
|
|||
|
||||
pagefault_enable();
|
||||
|
||||
if (!ret) {
|
||||
switch (cmp) {
|
||||
case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
|
||||
case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
|
||||
case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
|
||||
case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
|
||||
case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
|
||||
case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
|
||||
default: ret = -ENOSYS;
|
||||
}
|
||||
}
|
||||
if (!ret)
|
||||
*oval = oldval;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -217,14 +217,6 @@ static int show_cpuinfo(struct seq_file *m, void *v)
|
|||
unsigned short maj;
|
||||
unsigned short min;
|
||||
|
||||
/* We only show online cpus: disable preempt (overzealous, I
|
||||
* knew) to prevent cpu going down. */
|
||||
preempt_disable();
|
||||
if (!cpu_online(cpu_id)) {
|
||||
preempt_enable();
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
pvr = per_cpu(cpu_pvr, cpu_id);
|
||||
#else
|
||||
|
@ -329,9 +321,6 @@ static int show_cpuinfo(struct seq_file *m, void *v)
|
|||
#ifdef CONFIG_SMP
|
||||
seq_printf(m, "\n");
|
||||
#endif
|
||||
|
||||
preempt_enable();
|
||||
|
||||
/* If this is the last cpu, print the summary */
|
||||
if (cpumask_next(cpu_id, cpu_online_mask) >= nr_cpu_ids)
|
||||
show_cpuinfo_summary(m);
|
||||
|
|
|
@ -48,8 +48,8 @@ static int pnv_eeh_init(void)
|
|||
struct pci_controller *hose;
|
||||
struct pnv_phb *phb;
|
||||
|
||||
if (!firmware_has_feature(FW_FEATURE_OPALv3)) {
|
||||
pr_warn("%s: OPALv3 is required !\n",
|
||||
if (!firmware_has_feature(FW_FEATURE_OPAL)) {
|
||||
pr_warn("%s: OPAL is required !\n",
|
||||
__func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
|
@ -242,7 +242,7 @@ static int __init pnv_init_idle_states(void)
|
|||
if (cpuidle_disable != IDLE_NO_OVERRIDE)
|
||||
goto out;
|
||||
|
||||
if (!firmware_has_feature(FW_FEATURE_OPALv3))
|
||||
if (!firmware_has_feature(FW_FEATURE_OPAL))
|
||||
goto out;
|
||||
|
||||
power_mgt = of_find_node_by_path("/ibm,opal/power-mgt");
|
||||
|
|
|
@ -44,6 +44,10 @@ static ssize_t opal_nvram_read(char *buf, size_t count, loff_t *index)
|
|||
return count;
|
||||
}
|
||||
|
||||
/*
|
||||
* This can be called in the panic path with interrupts off, so use
|
||||
* mdelay in that case.
|
||||
*/
|
||||
static ssize_t opal_nvram_write(char *buf, size_t count, loff_t *index)
|
||||
{
|
||||
s64 rc = OPAL_BUSY;
|
||||
|
@ -58,10 +62,16 @@ static ssize_t opal_nvram_write(char *buf, size_t count, loff_t *index)
|
|||
while (rc == OPAL_BUSY || rc == OPAL_BUSY_EVENT) {
|
||||
rc = opal_write_nvram(__pa(buf), count, off);
|
||||
if (rc == OPAL_BUSY_EVENT) {
|
||||
msleep(OPAL_BUSY_DELAY_MS);
|
||||
if (in_interrupt() || irqs_disabled())
|
||||
mdelay(OPAL_BUSY_DELAY_MS);
|
||||
else
|
||||
msleep(OPAL_BUSY_DELAY_MS);
|
||||
opal_poll_events(NULL);
|
||||
} else if (rc == OPAL_BUSY) {
|
||||
msleep(OPAL_BUSY_DELAY_MS);
|
||||
if (in_interrupt() || irqs_disabled())
|
||||
mdelay(OPAL_BUSY_DELAY_MS);
|
||||
else
|
||||
msleep(OPAL_BUSY_DELAY_MS);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -126,7 +126,7 @@ static const struct scom_controller opal_scom_controller = {
|
|||
|
||||
static int opal_xscom_init(void)
|
||||
{
|
||||
if (firmware_has_feature(FW_FEATURE_OPALv3))
|
||||
if (firmware_has_feature(FW_FEATURE_OPAL))
|
||||
scom_init(&opal_scom_controller);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -98,16 +98,11 @@ int __init early_init_dt_scan_opal(unsigned long node,
|
|||
pr_debug("OPAL Entry = 0x%llx (sizep=%p runtimesz=%d)\n",
|
||||
opal.size, sizep, runtimesz);
|
||||
|
||||
powerpc_firmware_features |= FW_FEATURE_OPAL;
|
||||
if (of_flat_dt_is_compatible(node, "ibm,opal-v3")) {
|
||||
powerpc_firmware_features |= FW_FEATURE_OPALv2;
|
||||
powerpc_firmware_features |= FW_FEATURE_OPALv3;
|
||||
pr_info("OPAL V3 detected !\n");
|
||||
} else if (of_flat_dt_is_compatible(node, "ibm,opal-v2")) {
|
||||
powerpc_firmware_features |= FW_FEATURE_OPALv2;
|
||||
pr_info("OPAL V2 detected !\n");
|
||||
powerpc_firmware_features |= FW_FEATURE_OPAL;
|
||||
pr_info("OPAL detected !\n");
|
||||
} else {
|
||||
pr_info("OPAL V1 detected !\n");
|
||||
panic("OPAL != V3 detected, no longer supported.\n");
|
||||
}
|
||||
|
||||
/* Reinit all cores with the right endian */
|
||||
|
@ -352,17 +347,15 @@ int opal_put_chars(uint32_t vtermno, const char *data, int total_len)
|
|||
* enough room and be done with it
|
||||
*/
|
||||
spin_lock_irqsave(&opal_write_lock, flags);
|
||||
if (firmware_has_feature(FW_FEATURE_OPALv2)) {
|
||||
rc = opal_console_write_buffer_space(vtermno, &olen);
|
||||
len = be64_to_cpu(olen);
|
||||
if (rc || len < total_len) {
|
||||
spin_unlock_irqrestore(&opal_write_lock, flags);
|
||||
/* Closed -> drop characters */
|
||||
if (rc)
|
||||
return total_len;
|
||||
opal_poll_events(NULL);
|
||||
return -EAGAIN;
|
||||
}
|
||||
rc = opal_console_write_buffer_space(vtermno, &olen);
|
||||
len = be64_to_cpu(olen);
|
||||
if (rc || len < total_len) {
|
||||
spin_unlock_irqrestore(&opal_write_lock, flags);
|
||||
/* Closed -> drop characters */
|
||||
if (rc)
|
||||
return total_len;
|
||||
opal_poll_events(NULL);
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
/* We still try to handle partial completions, though they
|
||||
|
@ -696,10 +689,7 @@ static int __init opal_init(void)
|
|||
}
|
||||
|
||||
/* Register OPAL consoles if any ports */
|
||||
if (firmware_has_feature(FW_FEATURE_OPALv2))
|
||||
consoles = of_find_node_by_path("/ibm,opal/consoles");
|
||||
else
|
||||
consoles = of_node_get(opal_node);
|
||||
consoles = of_find_node_by_path("/ibm,opal/consoles");
|
||||
if (consoles) {
|
||||
for_each_child_of_node(consoles, np) {
|
||||
if (strcmp(np->name, "serial"))
|
||||
|
|
|
@ -344,7 +344,7 @@ static void __init pnv_ioda_parse_m64_window(struct pnv_phb *phb)
|
|||
return;
|
||||
}
|
||||
|
||||
if (!firmware_has_feature(FW_FEATURE_OPALv3)) {
|
||||
if (!firmware_has_feature(FW_FEATURE_OPAL)) {
|
||||
pr_info(" Firmware too old to support M64 window\n");
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -140,12 +140,8 @@ static void pnv_show_cpuinfo(struct seq_file *m)
|
|||
if (root)
|
||||
model = of_get_property(root, "model", NULL);
|
||||
seq_printf(m, "machine\t\t: PowerNV %s\n", model);
|
||||
if (firmware_has_feature(FW_FEATURE_OPALv3))
|
||||
seq_printf(m, "firmware\t: OPAL v3\n");
|
||||
else if (firmware_has_feature(FW_FEATURE_OPALv2))
|
||||
seq_printf(m, "firmware\t: OPAL v2\n");
|
||||
else if (firmware_has_feature(FW_FEATURE_OPAL))
|
||||
seq_printf(m, "firmware\t: OPAL v1\n");
|
||||
if (firmware_has_feature(FW_FEATURE_OPAL))
|
||||
seq_printf(m, "firmware\t: OPAL\n");
|
||||
else
|
||||
seq_printf(m, "firmware\t: BML\n");
|
||||
of_node_put(root);
|
||||
|
@ -274,9 +270,9 @@ static void pnv_kexec_cpu_down(int crash_shutdown, int secondary)
|
|||
{
|
||||
xics_kexec_teardown_cpu(secondary);
|
||||
|
||||
/* On OPAL v3, we return all CPUs to firmware */
|
||||
/* On OPAL, we return all CPUs to firmware */
|
||||
|
||||
if (!firmware_has_feature(FW_FEATURE_OPALv3))
|
||||
if (!firmware_has_feature(FW_FEATURE_OPAL))
|
||||
return;
|
||||
|
||||
if (secondary) {
|
||||
|
|
|
@ -61,14 +61,15 @@ static int pnv_smp_kick_cpu(int nr)
|
|||
unsigned long start_here =
|
||||
__pa(ppc_function_entry(generic_secondary_smp_init));
|
||||
long rc;
|
||||
uint8_t status;
|
||||
|
||||
BUG_ON(nr < 0 || nr >= NR_CPUS);
|
||||
|
||||
/*
|
||||
* If we already started or OPALv2 is not supported, we just
|
||||
* If we already started or OPAL is not supported, we just
|
||||
* kick the CPU via the PACA
|
||||
*/
|
||||
if (paca[nr].cpu_start || !firmware_has_feature(FW_FEATURE_OPALv2))
|
||||
if (paca[nr].cpu_start || !firmware_has_feature(FW_FEATURE_OPAL))
|
||||
goto kick;
|
||||
|
||||
/*
|
||||
|
@ -77,55 +78,42 @@ static int pnv_smp_kick_cpu(int nr)
|
|||
* first time. OPAL v3 allows us to query OPAL to know if it
|
||||
* has the CPUs, so we do that
|
||||
*/
|
||||
if (firmware_has_feature(FW_FEATURE_OPALv3)) {
|
||||
uint8_t status;
|
||||
rc = opal_query_cpu_status(pcpu, &status);
|
||||
if (rc != OPAL_SUCCESS) {
|
||||
pr_warn("OPAL Error %ld querying CPU %d state\n", rc, nr);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
rc = opal_query_cpu_status(pcpu, &status);
|
||||
/*
|
||||
* Already started, just kick it, probably coming from
|
||||
* kexec and spinning
|
||||
*/
|
||||
if (status == OPAL_THREAD_STARTED)
|
||||
goto kick;
|
||||
|
||||
/*
|
||||
* Available/inactive, let's kick it
|
||||
*/
|
||||
if (status == OPAL_THREAD_INACTIVE) {
|
||||
pr_devel("OPAL: Starting CPU %d (HW 0x%x)...\n", nr, pcpu);
|
||||
rc = opal_start_cpu(pcpu, start_here);
|
||||
if (rc != OPAL_SUCCESS) {
|
||||
pr_warn("OPAL Error %ld querying CPU %d state\n",
|
||||
rc, nr);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/*
|
||||
* Already started, just kick it, probably coming from
|
||||
* kexec and spinning
|
||||
*/
|
||||
if (status == OPAL_THREAD_STARTED)
|
||||
goto kick;
|
||||
|
||||
/*
|
||||
* Available/inactive, let's kick it
|
||||
*/
|
||||
if (status == OPAL_THREAD_INACTIVE) {
|
||||
pr_devel("OPAL: Starting CPU %d (HW 0x%x)...\n",
|
||||
nr, pcpu);
|
||||
rc = opal_start_cpu(pcpu, start_here);
|
||||
if (rc != OPAL_SUCCESS) {
|
||||
pr_warn("OPAL Error %ld starting CPU %d\n",
|
||||
rc, nr);
|
||||
return -ENODEV;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* An unavailable CPU (or any other unknown status)
|
||||
* shouldn't be started. It should also
|
||||
* not be in the possible map but currently it can
|
||||
* happen
|
||||
*/
|
||||
pr_devel("OPAL: CPU %d (HW 0x%x) is unavailable"
|
||||
" (status %d)...\n", nr, pcpu, status);
|
||||
pr_warn("OPAL Error %ld starting CPU %d\n", rc, nr);
|
||||
return -ENODEV;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* On OPAL v2, we just kick it and hope for the best,
|
||||
* we must not test the error from opal_start_cpu() or
|
||||
* we would fail to get CPUs from kexec.
|
||||
* An unavailable CPU (or any other unknown status)
|
||||
* shouldn't be started. It should also
|
||||
* not be in the possible map but currently it can
|
||||
* happen
|
||||
*/
|
||||
opal_start_cpu(pcpu, start_here);
|
||||
pr_devel("OPAL: CPU %d (HW 0x%x) is unavailable"
|
||||
" (status %d)...\n", nr, pcpu, status);
|
||||
return -ENODEV;
|
||||
}
|
||||
kick:
|
||||
|
||||
kick:
|
||||
return smp_generic_kick_cpu(nr);
|
||||
}
|
||||
|
||||
|
|
108
arch/s390/include/asm/alternative-asm.h
Normal file
108
arch/s390/include/asm/alternative-asm.h
Normal file
|
@ -0,0 +1,108 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef _ASM_S390_ALTERNATIVE_ASM_H
|
||||
#define _ASM_S390_ALTERNATIVE_ASM_H
|
||||
|
||||
#ifdef __ASSEMBLY__
|
||||
|
||||
/*
|
||||
* Check the length of an instruction sequence. The length may not be larger
|
||||
* than 254 bytes and it has to be divisible by 2.
|
||||
*/
|
||||
.macro alt_len_check start,end
|
||||
.if ( \end - \start ) > 254
|
||||
.error "cpu alternatives does not support instructions blocks > 254 bytes\n"
|
||||
.endif
|
||||
.if ( \end - \start ) % 2
|
||||
.error "cpu alternatives instructions length is odd\n"
|
||||
.endif
|
||||
.endm
|
||||
|
||||
/*
|
||||
* Issue one struct alt_instr descriptor entry (need to put it into
|
||||
* the section .altinstructions, see below). This entry contains
|
||||
* enough information for the alternatives patching code to patch an
|
||||
* instruction. See apply_alternatives().
|
||||
*/
|
||||
.macro alt_entry orig_start, orig_end, alt_start, alt_end, feature
|
||||
.long \orig_start - .
|
||||
.long \alt_start - .
|
||||
.word \feature
|
||||
.byte \orig_end - \orig_start
|
||||
.byte \alt_end - \alt_start
|
||||
.endm
|
||||
|
||||
/*
|
||||
* Fill up @bytes with nops. The macro emits 6-byte nop instructions
|
||||
* for the bulk of the area, possibly followed by a 4-byte and/or
|
||||
* a 2-byte nop if the size of the area is not divisible by 6.
|
||||
*/
|
||||
.macro alt_pad_fill bytes
|
||||
.fill ( \bytes ) / 6, 6, 0xc0040000
|
||||
.fill ( \bytes ) % 6 / 4, 4, 0x47000000
|
||||
.fill ( \bytes ) % 6 % 4 / 2, 2, 0x0700
|
||||
.endm
|
||||
|
||||
/*
|
||||
* Fill up @bytes with nops. If the number of bytes is larger
|
||||
* than 6, emit a jg instruction to branch over all nops, then
|
||||
* fill an area of size (@bytes - 6) with nop instructions.
|
||||
*/
|
||||
.macro alt_pad bytes
|
||||
.if ( \bytes > 0 )
|
||||
.if ( \bytes > 6 )
|
||||
jg . + \bytes
|
||||
alt_pad_fill \bytes - 6
|
||||
.else
|
||||
alt_pad_fill \bytes
|
||||
.endif
|
||||
.endif
|
||||
.endm
|
||||
|
||||
/*
|
||||
* Define an alternative between two instructions. If @feature is
|
||||
* present, early code in apply_alternatives() replaces @oldinstr with
|
||||
* @newinstr. ".skip" directive takes care of proper instruction padding
|
||||
* in case @newinstr is longer than @oldinstr.
|
||||
*/
|
||||
.macro ALTERNATIVE oldinstr, newinstr, feature
|
||||
.pushsection .altinstr_replacement,"ax"
|
||||
770: \newinstr
|
||||
771: .popsection
|
||||
772: \oldinstr
|
||||
773: alt_len_check 770b, 771b
|
||||
alt_len_check 772b, 773b
|
||||
alt_pad ( ( 771b - 770b ) - ( 773b - 772b ) )
|
||||
774: .pushsection .altinstructions,"a"
|
||||
alt_entry 772b, 774b, 770b, 771b, \feature
|
||||
.popsection
|
||||
.endm
|
||||
|
||||
/*
|
||||
* Define an alternative between two instructions. If @feature is
|
||||
* present, early code in apply_alternatives() replaces @oldinstr with
|
||||
* @newinstr. ".skip" directive takes care of proper instruction padding
|
||||
* in case @newinstr is longer than @oldinstr.
|
||||
*/
|
||||
.macro ALTERNATIVE_2 oldinstr, newinstr1, feature1, newinstr2, feature2
|
||||
.pushsection .altinstr_replacement,"ax"
|
||||
770: \newinstr1
|
||||
771: \newinstr2
|
||||
772: .popsection
|
||||
773: \oldinstr
|
||||
774: alt_len_check 770b, 771b
|
||||
alt_len_check 771b, 772b
|
||||
alt_len_check 773b, 774b
|
||||
.if ( 771b - 770b > 772b - 771b )
|
||||
alt_pad ( ( 771b - 770b ) - ( 774b - 773b ) )
|
||||
.else
|
||||
alt_pad ( ( 772b - 771b ) - ( 774b - 773b ) )
|
||||
.endif
|
||||
775: .pushsection .altinstructions,"a"
|
||||
alt_entry 773b, 775b, 770b, 771b,\feature1
|
||||
alt_entry 773b, 775b, 771b, 772b,\feature2
|
||||
.popsection
|
||||
.endm
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#endif /* _ASM_S390_ALTERNATIVE_ASM_H */
|
|
@ -21,17 +21,12 @@
|
|||
: "0" (-EFAULT), "d" (oparg), "a" (uaddr), \
|
||||
"m" (*uaddr) : "cc");
|
||||
|
||||
static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
|
||||
static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,
|
||||
u32 __user *uaddr)
|
||||
{
|
||||
int op = (encoded_op >> 28) & 7;
|
||||
int cmp = (encoded_op >> 24) & 15;
|
||||
int oparg = (encoded_op << 8) >> 20;
|
||||
int cmparg = (encoded_op << 20) >> 20;
|
||||
int oldval = 0, newval, ret;
|
||||
|
||||
load_kernel_asce();
|
||||
if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
|
||||
oparg = 1 << oparg;
|
||||
|
||||
pagefault_disable();
|
||||
switch (op) {
|
||||
|
@ -60,17 +55,9 @@ static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
|
|||
}
|
||||
pagefault_enable();
|
||||
|
||||
if (!ret) {
|
||||
switch (cmp) {
|
||||
case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
|
||||
case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
|
||||
case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
|
||||
case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
|
||||
case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
|
||||
case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
|
||||
default: ret = -ENOSYS;
|
||||
}
|
||||
}
|
||||
if (!ret)
|
||||
*oval = oldval;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
182
arch/s390/include/asm/nospec-insn.h
Normal file
182
arch/s390/include/asm/nospec-insn.h
Normal file
|
@ -0,0 +1,182 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef _ASM_S390_NOSPEC_ASM_H
|
||||
#define _ASM_S390_NOSPEC_ASM_H
|
||||
|
||||
#ifdef __ASSEMBLY__
|
||||
|
||||
#ifdef CONFIG_EXPOLINE
|
||||
|
||||
/*
|
||||
* The expoline macros are used to create thunks in the same format
|
||||
* as gcc generates them. The 'comdat' section flag makes sure that
|
||||
* the various thunks are merged into a single copy.
|
||||
*/
|
||||
.macro __THUNK_PROLOG_NAME name
|
||||
.pushsection .text.\name,"axG",@progbits,\name,comdat
|
||||
.globl \name
|
||||
.hidden \name
|
||||
.type \name,@function
|
||||
\name:
|
||||
.cfi_startproc
|
||||
.endm
|
||||
|
||||
.macro __THUNK_EPILOG
|
||||
.cfi_endproc
|
||||
.popsection
|
||||
.endm
|
||||
|
||||
.macro __THUNK_PROLOG_BR r1,r2
|
||||
__THUNK_PROLOG_NAME __s390x_indirect_jump_r\r2\()use_r\r1
|
||||
.endm
|
||||
|
||||
.macro __THUNK_PROLOG_BC d0,r1,r2
|
||||
__THUNK_PROLOG_NAME __s390x_indirect_branch_\d0\()_\r2\()use_\r1
|
||||
.endm
|
||||
|
||||
.macro __THUNK_BR r1,r2
|
||||
jg __s390x_indirect_jump_r\r2\()use_r\r1
|
||||
.endm
|
||||
|
||||
.macro __THUNK_BC d0,r1,r2
|
||||
jg __s390x_indirect_branch_\d0\()_\r2\()use_\r1
|
||||
.endm
|
||||
|
||||
.macro __THUNK_BRASL r1,r2,r3
|
||||
brasl \r1,__s390x_indirect_jump_r\r3\()use_r\r2
|
||||
.endm
|
||||
|
||||
.macro __DECODE_RR expand,reg,ruse
|
||||
.set __decode_fail,1
|
||||
.irp r1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
|
||||
.ifc \reg,%r\r1
|
||||
.irp r2,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
|
||||
.ifc \ruse,%r\r2
|
||||
\expand \r1,\r2
|
||||
.set __decode_fail,0
|
||||
.endif
|
||||
.endr
|
||||
.endif
|
||||
.endr
|
||||
.if __decode_fail == 1
|
||||
.error "__DECODE_RR failed"
|
||||
.endif
|
||||
.endm
|
||||
|
||||
.macro __DECODE_RRR expand,rsave,rtarget,ruse
|
||||
.set __decode_fail,1
|
||||
.irp r1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
|
||||
.ifc \rsave,%r\r1
|
||||
.irp r2,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
|
||||
.ifc \rtarget,%r\r2
|
||||
.irp r3,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
|
||||
.ifc \ruse,%r\r3
|
||||
\expand \r1,\r2,\r3
|
||||
.set __decode_fail,0
|
||||
.endif
|
||||
.endr
|
||||
.endif
|
||||
.endr
|
||||
.endif
|
||||
.endr
|
||||
.if __decode_fail == 1
|
||||
.error "__DECODE_RRR failed"
|
||||
.endif
|
||||
.endm
|
||||
|
||||
.macro __DECODE_DRR expand,disp,reg,ruse
|
||||
.set __decode_fail,1
|
||||
.irp r1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
|
||||
.ifc \reg,%r\r1
|
||||
.irp r2,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
|
||||
.ifc \ruse,%r\r2
|
||||
\expand \disp,\r1,\r2
|
||||
.set __decode_fail,0
|
||||
.endif
|
||||
.endr
|
||||
.endif
|
||||
.endr
|
||||
.if __decode_fail == 1
|
||||
.error "__DECODE_DRR failed"
|
||||
.endif
|
||||
.endm
|
||||
|
||||
.macro __THUNK_EX_BR reg,ruse
|
||||
#ifdef CONFIG_HAVE_MARCH_Z10_FEATURES
|
||||
exrl 0,555f
|
||||
j .
|
||||
#else
|
||||
larl \ruse,555f
|
||||
ex 0,0(\ruse)
|
||||
j .
|
||||
#endif
|
||||
555: br \reg
|
||||
.endm
|
||||
|
||||
.macro __THUNK_EX_BC disp,reg,ruse
|
||||
#ifdef CONFIG_HAVE_MARCH_Z10_FEATURES
|
||||
exrl 0,556f
|
||||
j .
|
||||
#else
|
||||
larl \ruse,556f
|
||||
ex 0,0(\ruse)
|
||||
j .
|
||||
#endif
|
||||
556: b \disp(\reg)
|
||||
.endm
|
||||
|
||||
.macro GEN_BR_THUNK reg,ruse=%r1
|
||||
__DECODE_RR __THUNK_PROLOG_BR,\reg,\ruse
|
||||
__THUNK_EX_BR \reg,\ruse
|
||||
__THUNK_EPILOG
|
||||
.endm
|
||||
|
||||
.macro GEN_B_THUNK disp,reg,ruse=%r1
|
||||
__DECODE_DRR __THUNK_PROLOG_BC,\disp,\reg,\ruse
|
||||
__THUNK_EX_BC \disp,\reg,\ruse
|
||||
__THUNK_EPILOG
|
||||
.endm
|
||||
|
||||
.macro BR_EX reg,ruse=%r1
|
||||
557: __DECODE_RR __THUNK_BR,\reg,\ruse
|
||||
.pushsection .s390_indirect_branches,"a",@progbits
|
||||
.long 557b-.
|
||||
.popsection
|
||||
.endm
|
||||
|
||||
.macro B_EX disp,reg,ruse=%r1
|
||||
558: __DECODE_DRR __THUNK_BC,\disp,\reg,\ruse
|
||||
.pushsection .s390_indirect_branches,"a",@progbits
|
||||
.long 558b-.
|
||||
.popsection
|
||||
.endm
|
||||
|
||||
.macro BASR_EX rsave,rtarget,ruse=%r1
|
||||
559: __DECODE_RRR __THUNK_BRASL,\rsave,\rtarget,\ruse
|
||||
.pushsection .s390_indirect_branches,"a",@progbits
|
||||
.long 559b-.
|
||||
.popsection
|
||||
.endm
|
||||
|
||||
#else
|
||||
.macro GEN_BR_THUNK reg,ruse=%r1
|
||||
.endm
|
||||
|
||||
.macro GEN_B_THUNK disp,reg,ruse=%r1
|
||||
.endm
|
||||
|
||||
.macro BR_EX reg,ruse=%r1
|
||||
br \reg
|
||||
.endm
|
||||
|
||||
.macro B_EX disp,reg,ruse=%r1
|
||||
b \disp(\reg)
|
||||
.endm
|
||||
|
||||
.macro BASR_EX rsave,rtarget,ruse=%r1
|
||||
basr \rsave,\rtarget
|
||||
.endm
|
||||
#endif
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#endif /* _ASM_S390_NOSPEC_ASM_H */
|
|
@ -49,6 +49,7 @@ obj-y += nospec-branch.o
|
|||
|
||||
extra-y += head.o head64.o vmlinux.lds
|
||||
|
||||
obj-$(CONFIG_SYSFS) += nospec-sysfs.o
|
||||
CFLAGS_REMOVE_nospec-branch.o += $(CC_FLAGS_EXPOLINE)
|
||||
|
||||
obj-$(CONFIG_MODULES) += s390_ksyms.o module.o
|
||||
|
|
|
@ -8,18 +8,22 @@
|
|||
|
||||
#include <linux/linkage.h>
|
||||
#include <asm/asm-offsets.h>
|
||||
#include <asm/nospec-insn.h>
|
||||
#include <asm/ptrace.h>
|
||||
#include <asm/sigp.h>
|
||||
|
||||
GEN_BR_THUNK %r9
|
||||
GEN_BR_THUNK %r14
|
||||
|
||||
ENTRY(s390_base_mcck_handler)
|
||||
basr %r13,0
|
||||
0: lg %r15,__LC_PANIC_STACK # load panic stack
|
||||
aghi %r15,-STACK_FRAME_OVERHEAD
|
||||
larl %r1,s390_base_mcck_handler_fn
|
||||
lg %r1,0(%r1)
|
||||
ltgr %r1,%r1
|
||||
lg %r9,0(%r1)
|
||||
ltgr %r9,%r9
|
||||
jz 1f
|
||||
basr %r14,%r1
|
||||
BASR_EX %r14,%r9
|
||||
1: la %r1,4095
|
||||
lmg %r0,%r15,__LC_GPREGS_SAVE_AREA-4095(%r1)
|
||||
lpswe __LC_MCK_OLD_PSW
|
||||
|
@ -36,10 +40,10 @@ ENTRY(s390_base_ext_handler)
|
|||
basr %r13,0
|
||||
0: aghi %r15,-STACK_FRAME_OVERHEAD
|
||||
larl %r1,s390_base_ext_handler_fn
|
||||
lg %r1,0(%r1)
|
||||
ltgr %r1,%r1
|
||||
lg %r9,0(%r1)
|
||||
ltgr %r9,%r9
|
||||
jz 1f
|
||||
basr %r14,%r1
|
||||
BASR_EX %r14,%r9
|
||||
1: lmg %r0,%r15,__LC_SAVE_AREA_ASYNC
|
||||
ni __LC_EXT_OLD_PSW+1,0xfd # clear wait state bit
|
||||
lpswe __LC_EXT_OLD_PSW
|
||||
|
@ -56,10 +60,10 @@ ENTRY(s390_base_pgm_handler)
|
|||
basr %r13,0
|
||||
0: aghi %r15,-STACK_FRAME_OVERHEAD
|
||||
larl %r1,s390_base_pgm_handler_fn
|
||||
lg %r1,0(%r1)
|
||||
ltgr %r1,%r1
|
||||
lg %r9,0(%r1)
|
||||
ltgr %r9,%r9
|
||||
jz 1f
|
||||
basr %r14,%r1
|
||||
BASR_EX %r14,%r9
|
||||
lmg %r0,%r15,__LC_SAVE_AREA_SYNC
|
||||
lpswe __LC_PGM_OLD_PSW
|
||||
1: lpswe disabled_wait_psw-0b(%r13)
|
||||
|
@ -116,7 +120,7 @@ ENTRY(diag308_reset)
|
|||
larl %r4,.Lcontinue_psw # Restore PSW flags
|
||||
lpswe 0(%r4)
|
||||
.Lcontinue:
|
||||
br %r14
|
||||
BR_EX %r14
|
||||
.align 16
|
||||
.Lrestart_psw:
|
||||
.long 0x00080000,0x80000000 + .Lrestart_part2
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include <asm/vx-insn.h>
|
||||
#include <asm/setup.h>
|
||||
#include <asm/nmi.h>
|
||||
#include <asm/nospec-insn.h>
|
||||
|
||||
__PT_R0 = __PT_GPRS
|
||||
__PT_R1 = __PT_GPRS + 8
|
||||
|
@ -225,74 +226,16 @@ _PIF_WORK = (_PIF_PER_TRAP)
|
|||
.popsection
|
||||
.endm
|
||||
|
||||
#ifdef CONFIG_EXPOLINE
|
||||
|
||||
.macro GEN_BR_THUNK name,reg,tmp
|
||||
.section .text.\name,"axG",@progbits,\name,comdat
|
||||
.globl \name
|
||||
.hidden \name
|
||||
.type \name,@function
|
||||
\name:
|
||||
.cfi_startproc
|
||||
#ifdef CONFIG_HAVE_MARCH_Z10_FEATURES
|
||||
exrl 0,0f
|
||||
#else
|
||||
larl \tmp,0f
|
||||
ex 0,0(\tmp)
|
||||
#endif
|
||||
j .
|
||||
0: br \reg
|
||||
.cfi_endproc
|
||||
.endm
|
||||
|
||||
GEN_BR_THUNK __s390x_indirect_jump_r1use_r9,%r9,%r1
|
||||
GEN_BR_THUNK __s390x_indirect_jump_r1use_r14,%r14,%r1
|
||||
GEN_BR_THUNK __s390x_indirect_jump_r11use_r14,%r14,%r11
|
||||
|
||||
.macro BASR_R14_R9
|
||||
0: brasl %r14,__s390x_indirect_jump_r1use_r9
|
||||
.pushsection .s390_indirect_branches,"a",@progbits
|
||||
.long 0b-.
|
||||
.popsection
|
||||
.endm
|
||||
|
||||
.macro BR_R1USE_R14
|
||||
0: jg __s390x_indirect_jump_r1use_r14
|
||||
.pushsection .s390_indirect_branches,"a",@progbits
|
||||
.long 0b-.
|
||||
.popsection
|
||||
.endm
|
||||
|
||||
.macro BR_R11USE_R14
|
||||
0: jg __s390x_indirect_jump_r11use_r14
|
||||
.pushsection .s390_indirect_branches,"a",@progbits
|
||||
.long 0b-.
|
||||
.popsection
|
||||
.endm
|
||||
|
||||
#else /* CONFIG_EXPOLINE */
|
||||
|
||||
.macro BASR_R14_R9
|
||||
basr %r14,%r9
|
||||
.endm
|
||||
|
||||
.macro BR_R1USE_R14
|
||||
br %r14
|
||||
.endm
|
||||
|
||||
.macro BR_R11USE_R14
|
||||
br %r14
|
||||
.endm
|
||||
|
||||
#endif /* CONFIG_EXPOLINE */
|
||||
|
||||
GEN_BR_THUNK %r9
|
||||
GEN_BR_THUNK %r14
|
||||
GEN_BR_THUNK %r14,%r11
|
||||
|
||||
.section .kprobes.text, "ax"
|
||||
|
||||
ENTRY(__bpon)
|
||||
.globl __bpon
|
||||
BPON
|
||||
BR_R1USE_R14
|
||||
BR_EX %r14
|
||||
|
||||
/*
|
||||
* Scheduler resume function, called by switch_to
|
||||
|
@ -322,7 +265,7 @@ ENTRY(__switch_to)
|
|||
TSTMSK __LC_MACHINE_FLAGS,MACHINE_FLAG_LPP
|
||||
jz 0f
|
||||
.insn s,0xb2800000,__LC_LPP # set program parameter
|
||||
0: BR_R1USE_R14
|
||||
0: BR_EX %r14
|
||||
|
||||
.L__critical_start:
|
||||
|
||||
|
@ -388,7 +331,7 @@ sie_exit:
|
|||
xgr %r5,%r5
|
||||
lmg %r6,%r14,__SF_GPRS(%r15) # restore kernel registers
|
||||
lg %r2,__SF_EMPTY+16(%r15) # return exit reason code
|
||||
BR_R1USE_R14
|
||||
BR_EX %r14
|
||||
.Lsie_fault:
|
||||
lghi %r14,-EFAULT
|
||||
stg %r14,__SF_EMPTY+16(%r15) # set exit reason code
|
||||
|
@ -445,7 +388,7 @@ ENTRY(system_call)
|
|||
lgf %r9,0(%r8,%r10) # get system call add.
|
||||
TSTMSK __TI_flags(%r12),_TIF_TRACE
|
||||
jnz .Lsysc_tracesys
|
||||
BASR_R14_R9 # call sys_xxxx
|
||||
BASR_EX %r14,%r9 # call sys_xxxx
|
||||
stg %r2,__PT_R2(%r11) # store return value
|
||||
|
||||
.Lsysc_return:
|
||||
|
@ -585,7 +528,7 @@ ENTRY(system_call)
|
|||
lmg %r3,%r7,__PT_R3(%r11)
|
||||
stg %r7,STACK_FRAME_OVERHEAD(%r15)
|
||||
lg %r2,__PT_ORIG_GPR2(%r11)
|
||||
BASR_R14_R9 # call sys_xxx
|
||||
BASR_EX %r14,%r9 # call sys_xxx
|
||||
stg %r2,__PT_R2(%r11) # store return value
|
||||
.Lsysc_tracenogo:
|
||||
TSTMSK __TI_flags(%r12),_TIF_TRACE
|
||||
|
@ -609,7 +552,7 @@ ENTRY(ret_from_fork)
|
|||
lmg %r9,%r10,__PT_R9(%r11) # load gprs
|
||||
ENTRY(kernel_thread_starter)
|
||||
la %r2,0(%r10)
|
||||
BASR_R14_R9
|
||||
BASR_EX %r14,%r9
|
||||
j .Lsysc_tracenogo
|
||||
|
||||
/*
|
||||
|
@ -685,7 +628,7 @@ ENTRY(pgm_check_handler)
|
|||
je .Lpgm_return
|
||||
lgf %r9,0(%r10,%r1) # load address of handler routine
|
||||
lgr %r2,%r11 # pass pointer to pt_regs
|
||||
BASR_R14_R9 # branch to interrupt-handler
|
||||
BASR_EX %r14,%r9 # branch to interrupt-handler
|
||||
.Lpgm_return:
|
||||
LOCKDEP_SYS_EXIT
|
||||
tm __PT_PSW+1(%r11),0x01 # returning to user ?
|
||||
|
@ -962,7 +905,7 @@ ENTRY(psw_idle)
|
|||
stpt __TIMER_IDLE_ENTER(%r2)
|
||||
.Lpsw_idle_lpsw:
|
||||
lpswe __SF_EMPTY(%r15)
|
||||
BR_R1USE_R14
|
||||
BR_EX %r14
|
||||
.Lpsw_idle_end:
|
||||
|
||||
/*
|
||||
|
@ -1007,7 +950,7 @@ ENTRY(save_fpu_regs)
|
|||
.Lsave_fpu_regs_done:
|
||||
oi __LC_CPU_FLAGS+7,_CIF_FPU
|
||||
.Lsave_fpu_regs_exit:
|
||||
BR_R1USE_R14
|
||||
BR_EX %r14
|
||||
.Lsave_fpu_regs_end:
|
||||
|
||||
/*
|
||||
|
@ -1054,7 +997,7 @@ load_fpu_regs:
|
|||
.Lload_fpu_regs_done:
|
||||
ni __LC_CPU_FLAGS+7,255-_CIF_FPU
|
||||
.Lload_fpu_regs_exit:
|
||||
BR_R1USE_R14
|
||||
BR_EX %r14
|
||||
.Lload_fpu_regs_end:
|
||||
|
||||
.L__critical_end:
|
||||
|
@ -1227,7 +1170,7 @@ cleanup_critical:
|
|||
jl 0f
|
||||
clg %r9,BASED(.Lcleanup_table+104) # .Lload_fpu_regs_end
|
||||
jl .Lcleanup_load_fpu_regs
|
||||
0: BR_R11USE_R14
|
||||
0: BR_EX %r14
|
||||
|
||||
.align 8
|
||||
.Lcleanup_table:
|
||||
|
@ -1257,7 +1200,7 @@ cleanup_critical:
|
|||
ni __SIE_PROG0C+3(%r9),0xfe # no longer in SIE
|
||||
lctlg %c1,%c1,__LC_USER_ASCE # load primary asce
|
||||
larl %r9,sie_exit # skip forward to sie_exit
|
||||
BR_R11USE_R14
|
||||
BR_EX %r14
|
||||
#endif
|
||||
|
||||
.Lcleanup_system_call:
|
||||
|
@ -1315,7 +1258,7 @@ cleanup_critical:
|
|||
stg %r15,56(%r11) # r15 stack pointer
|
||||
# set new psw address and exit
|
||||
larl %r9,.Lsysc_do_svc
|
||||
BR_R11USE_R14
|
||||
BR_EX %r14,%r11
|
||||
.Lcleanup_system_call_insn:
|
||||
.quad system_call
|
||||
.quad .Lsysc_stmg
|
||||
|
@ -1325,7 +1268,7 @@ cleanup_critical:
|
|||
|
||||
.Lcleanup_sysc_tif:
|
||||
larl %r9,.Lsysc_tif
|
||||
BR_R11USE_R14
|
||||
BR_EX %r14,%r11
|
||||
|
||||
.Lcleanup_sysc_restore:
|
||||
# check if stpt has been executed
|
||||
|
@ -1342,14 +1285,14 @@ cleanup_critical:
|
|||
mvc 0(64,%r11),__PT_R8(%r9)
|
||||
lmg %r0,%r7,__PT_R0(%r9)
|
||||
1: lmg %r8,%r9,__LC_RETURN_PSW
|
||||
BR_R11USE_R14
|
||||
BR_EX %r14,%r11
|
||||
.Lcleanup_sysc_restore_insn:
|
||||
.quad .Lsysc_exit_timer
|
||||
.quad .Lsysc_done - 4
|
||||
|
||||
.Lcleanup_io_tif:
|
||||
larl %r9,.Lio_tif
|
||||
BR_R11USE_R14
|
||||
BR_EX %r14,%r11
|
||||
|
||||
.Lcleanup_io_restore:
|
||||
# check if stpt has been executed
|
||||
|
@ -1363,7 +1306,7 @@ cleanup_critical:
|
|||
mvc 0(64,%r11),__PT_R8(%r9)
|
||||
lmg %r0,%r7,__PT_R0(%r9)
|
||||
1: lmg %r8,%r9,__LC_RETURN_PSW
|
||||
BR_R11USE_R14
|
||||
BR_EX %r14,%r11
|
||||
.Lcleanup_io_restore_insn:
|
||||
.quad .Lio_exit_timer
|
||||
.quad .Lio_done - 4
|
||||
|
@ -1415,17 +1358,17 @@ cleanup_critical:
|
|||
# prepare return psw
|
||||
nihh %r8,0xfcfd # clear irq & wait state bits
|
||||
lg %r9,48(%r11) # return from psw_idle
|
||||
BR_R11USE_R14
|
||||
BR_EX %r14,%r11
|
||||
.Lcleanup_idle_insn:
|
||||
.quad .Lpsw_idle_lpsw
|
||||
|
||||
.Lcleanup_save_fpu_regs:
|
||||
larl %r9,save_fpu_regs
|
||||
BR_R11USE_R14
|
||||
BR_EX %r14,%r11
|
||||
|
||||
.Lcleanup_load_fpu_regs:
|
||||
larl %r9,load_fpu_regs
|
||||
BR_R11USE_R14
|
||||
BR_EX %r14,%r11
|
||||
|
||||
/*
|
||||
* Integer constants
|
||||
|
|
|
@ -173,10 +173,9 @@ void do_softirq_own_stack(void)
|
|||
new -= STACK_FRAME_OVERHEAD;
|
||||
((struct stack_frame *) new)->back_chain = old;
|
||||
asm volatile(" la 15,0(%0)\n"
|
||||
" basr 14,%2\n"
|
||||
" brasl 14,__do_softirq\n"
|
||||
" la 15,0(%1)\n"
|
||||
: : "a" (new), "a" (old),
|
||||
"a" (__do_softirq)
|
||||
: : "a" (new), "a" (old)
|
||||
: "0", "1", "2", "3", "4", "5", "14",
|
||||
"cc", "memory" );
|
||||
} else {
|
||||
|
|
|
@ -44,24 +44,6 @@ static int __init nospec_report(void)
|
|||
}
|
||||
arch_initcall(nospec_report);
|
||||
|
||||
#ifdef CONFIG_SYSFS
|
||||
ssize_t cpu_show_spectre_v1(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return sprintf(buf, "Mitigation: __user pointer sanitization\n");
|
||||
}
|
||||
|
||||
ssize_t cpu_show_spectre_v2(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
if (IS_ENABLED(CC_USING_EXPOLINE) && !nospec_disable)
|
||||
return sprintf(buf, "Mitigation: execute trampolines\n");
|
||||
if (__test_facility(82, S390_lowcore.alt_stfle_fac_list))
|
||||
return sprintf(buf, "Mitigation: limited branch prediction.\n");
|
||||
return sprintf(buf, "Vulnerable\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_EXPOLINE
|
||||
|
||||
int nospec_disable = IS_ENABLED(CONFIG_EXPOLINE_OFF);
|
||||
|
@ -112,7 +94,6 @@ static void __init_or_module __nospec_revert(s32 *start, s32 *end)
|
|||
s32 *epo;
|
||||
|
||||
/* Second part of the instruction replace is always a nop */
|
||||
memcpy(insnbuf + 2, (char[]) { 0x47, 0x00, 0x00, 0x00 }, 4);
|
||||
for (epo = start; epo < end; epo++) {
|
||||
instr = (u8 *) epo + *epo;
|
||||
if (instr[0] == 0xc0 && (instr[1] & 0x0f) == 0x04)
|
||||
|
@ -133,18 +114,34 @@ static void __init_or_module __nospec_revert(s32 *start, s32 *end)
|
|||
br = thunk + (*(int *)(thunk + 2)) * 2;
|
||||
else
|
||||
continue;
|
||||
if (br[0] != 0x07 || (br[1] & 0xf0) != 0xf0)
|
||||
/* Check for unconditional branch 0x07f? or 0x47f???? */
|
||||
if ((br[0] & 0xbf) != 0x07 || (br[1] & 0xf0) != 0xf0)
|
||||
continue;
|
||||
|
||||
memcpy(insnbuf + 2, (char[]) { 0x47, 0x00, 0x07, 0x00 }, 4);
|
||||
switch (type) {
|
||||
case BRCL_EXPOLINE:
|
||||
/* brcl to thunk, replace with br + nop */
|
||||
insnbuf[0] = br[0];
|
||||
insnbuf[1] = (instr[1] & 0xf0) | (br[1] & 0x0f);
|
||||
if (br[0] == 0x47) {
|
||||
/* brcl to b, replace with bc + nopr */
|
||||
insnbuf[2] = br[2];
|
||||
insnbuf[3] = br[3];
|
||||
} else {
|
||||
/* brcl to br, replace with bcr + nop */
|
||||
}
|
||||
break;
|
||||
case BRASL_EXPOLINE:
|
||||
/* brasl to thunk, replace with basr + nop */
|
||||
insnbuf[0] = 0x0d;
|
||||
insnbuf[1] = (instr[1] & 0xf0) | (br[1] & 0x0f);
|
||||
if (br[0] == 0x47) {
|
||||
/* brasl to b, replace with bas + nopr */
|
||||
insnbuf[0] = 0x4d;
|
||||
insnbuf[2] = br[2];
|
||||
insnbuf[3] = br[3];
|
||||
} else {
|
||||
/* brasl to br, replace with basr + nop */
|
||||
insnbuf[0] = 0x0d;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
21
arch/s390/kernel/nospec-sysfs.c
Normal file
21
arch/s390/kernel/nospec-sysfs.c
Normal file
|
@ -0,0 +1,21 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include <linux/device.h>
|
||||
#include <linux/cpu.h>
|
||||
#include <asm/facility.h>
|
||||
#include <asm/nospec-branch.h>
|
||||
|
||||
ssize_t cpu_show_spectre_v1(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return sprintf(buf, "Mitigation: __user pointer sanitization\n");
|
||||
}
|
||||
|
||||
ssize_t cpu_show_spectre_v2(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
if (IS_ENABLED(CC_USING_EXPOLINE) && !nospec_disable)
|
||||
return sprintf(buf, "Mitigation: execute trampolines\n");
|
||||
if (__test_facility(82, S390_lowcore.alt_stfle_fac_list))
|
||||
return sprintf(buf, "Mitigation: limited branch prediction\n");
|
||||
return sprintf(buf, "Vulnerable\n");
|
||||
}
|
|
@ -744,6 +744,10 @@ static int __hw_perf_event_init(struct perf_event *event)
|
|||
*/
|
||||
rate = 0;
|
||||
if (attr->freq) {
|
||||
if (!attr->sample_freq) {
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
rate = freq_to_sample_rate(&si, attr->sample_freq);
|
||||
rate = hw_limit_rate(&si, rate);
|
||||
attr->freq = 0;
|
||||
|
|
|
@ -6,8 +6,11 @@
|
|||
|
||||
#include <linux/linkage.h>
|
||||
#include <asm/asm-offsets.h>
|
||||
#include <asm/nospec-insn.h>
|
||||
#include <asm/sigp.h>
|
||||
|
||||
GEN_BR_THUNK %r14
|
||||
|
||||
#
|
||||
# store_status
|
||||
#
|
||||
|
@ -62,7 +65,7 @@ ENTRY(store_status)
|
|||
st %r3,__LC_PSW_SAVE_AREA-SAVE_AREA_BASE + 4(%r1)
|
||||
larl %r2,store_status
|
||||
stg %r2,__LC_PSW_SAVE_AREA-SAVE_AREA_BASE + 8(%r1)
|
||||
br %r14
|
||||
BR_EX %r14
|
||||
|
||||
.section .bss
|
||||
.align 8
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include <asm/ptrace.h>
|
||||
#include <asm/thread_info.h>
|
||||
#include <asm/asm-offsets.h>
|
||||
#include <asm/nospec-insn.h>
|
||||
#include <asm/sigp.h>
|
||||
|
||||
/*
|
||||
|
@ -23,6 +24,8 @@
|
|||
* (see below) in the resume process.
|
||||
* This function runs with disabled interrupts.
|
||||
*/
|
||||
GEN_BR_THUNK %r14
|
||||
|
||||
.section .text
|
||||
ENTRY(swsusp_arch_suspend)
|
||||
stmg %r6,%r15,__SF_GPRS(%r15)
|
||||
|
@ -102,7 +105,7 @@ ENTRY(swsusp_arch_suspend)
|
|||
spx 0x318(%r1)
|
||||
lmg %r6,%r15,STACK_FRAME_OVERHEAD + __SF_GPRS(%r15)
|
||||
lghi %r2,0
|
||||
br %r14
|
||||
BR_EX %r14
|
||||
|
||||
/*
|
||||
* Restore saved memory image to correct place and restore register context.
|
||||
|
@ -196,11 +199,10 @@ pgm_check_entry:
|
|||
larl %r15,init_thread_union
|
||||
ahi %r15,1<<(PAGE_SHIFT+THREAD_ORDER)
|
||||
larl %r2,.Lpanic_string
|
||||
larl %r3,_sclp_print_early
|
||||
lghi %r1,0
|
||||
sam31
|
||||
sigp %r1,%r0,SIGP_SET_ARCHITECTURE
|
||||
basr %r14,%r3
|
||||
brasl %r14,_sclp_print_early
|
||||
larl %r3,.Ldisabled_wait_31
|
||||
lpsw 0(%r3)
|
||||
4:
|
||||
|
@ -266,7 +268,7 @@ restore_registers:
|
|||
/* Return 0 */
|
||||
lmg %r6,%r15,STACK_FRAME_OVERHEAD + __SF_GPRS(%r15)
|
||||
lghi %r2,0
|
||||
br %r14
|
||||
BR_EX %r14
|
||||
|
||||
.section .data..nosave,"aw",@progbits
|
||||
.align 8
|
||||
|
|
|
@ -5,6 +5,9 @@
|
|||
*/
|
||||
|
||||
#include <linux/linkage.h>
|
||||
#include <asm/nospec-insn.h>
|
||||
|
||||
GEN_BR_THUNK %r14
|
||||
|
||||
/*
|
||||
* memset implementation
|
||||
|
@ -38,7 +41,7 @@ ENTRY(memset)
|
|||
.Lmemset_clear_rest:
|
||||
larl %r3,.Lmemset_xc
|
||||
ex %r4,0(%r3)
|
||||
br %r14
|
||||
BR_EX %r14
|
||||
.Lmemset_fill:
|
||||
stc %r3,0(%r2)
|
||||
cghi %r4,1
|
||||
|
@ -55,7 +58,7 @@ ENTRY(memset)
|
|||
.Lmemset_fill_rest:
|
||||
larl %r3,.Lmemset_mvc
|
||||
ex %r4,0(%r3)
|
||||
br %r14
|
||||
BR_EX %r14
|
||||
.Lmemset_xc:
|
||||
xc 0(1,%r1),0(%r1)
|
||||
.Lmemset_mvc:
|
||||
|
@ -77,7 +80,7 @@ ENTRY(memcpy)
|
|||
.Lmemcpy_rest:
|
||||
larl %r5,.Lmemcpy_mvc
|
||||
ex %r4,0(%r5)
|
||||
br %r14
|
||||
BR_EX %r14
|
||||
.Lmemcpy_loop:
|
||||
mvc 0(256,%r1),0(%r3)
|
||||
la %r1,256(%r1)
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
*/
|
||||
|
||||
#include <linux/linkage.h>
|
||||
#include <asm/nospec-insn.h>
|
||||
#include "bpf_jit.h"
|
||||
|
||||
/*
|
||||
|
@ -53,7 +54,7 @@ ENTRY(sk_load_##NAME##_pos); \
|
|||
clg %r3,STK_OFF_HLEN(%r15); /* Offset + SIZE > hlen? */ \
|
||||
jh sk_load_##NAME##_slow; \
|
||||
LOAD %r14,-SIZE(%r3,%r12); /* Get data from skb */ \
|
||||
b OFF_OK(%r6); /* Return */ \
|
||||
B_EX OFF_OK,%r6; /* Return */ \
|
||||
\
|
||||
sk_load_##NAME##_slow:; \
|
||||
lgr %r2,%r7; /* Arg1 = skb pointer */ \
|
||||
|
@ -63,11 +64,14 @@ sk_load_##NAME##_slow:; \
|
|||
brasl %r14,skb_copy_bits; /* Get data from skb */ \
|
||||
LOAD %r14,STK_OFF_TMP(%r15); /* Load from temp bufffer */ \
|
||||
ltgr %r2,%r2; /* Set cc to (%r2 != 0) */ \
|
||||
br %r6; /* Return */
|
||||
BR_EX %r6; /* Return */
|
||||
|
||||
sk_load_common(word, 4, llgf) /* r14 = *(u32 *) (skb->data+offset) */
|
||||
sk_load_common(half, 2, llgh) /* r14 = *(u16 *) (skb->data+offset) */
|
||||
|
||||
GEN_BR_THUNK %r6
|
||||
GEN_B_THUNK OFF_OK,%r6
|
||||
|
||||
/*
|
||||
* Load 1 byte from SKB (optimized version)
|
||||
*/
|
||||
|
@ -79,7 +83,7 @@ ENTRY(sk_load_byte_pos)
|
|||
clg %r3,STK_OFF_HLEN(%r15) # Offset >= hlen?
|
||||
jnl sk_load_byte_slow
|
||||
llgc %r14,0(%r3,%r12) # Get byte from skb
|
||||
b OFF_OK(%r6) # Return OK
|
||||
B_EX OFF_OK,%r6 # Return OK
|
||||
|
||||
sk_load_byte_slow:
|
||||
lgr %r2,%r7 # Arg1 = skb pointer
|
||||
|
@ -89,7 +93,7 @@ sk_load_byte_slow:
|
|||
brasl %r14,skb_copy_bits # Get data from skb
|
||||
llgc %r14,STK_OFF_TMP(%r15) # Load result from temp buffer
|
||||
ltgr %r2,%r2 # Set cc to (%r2 != 0)
|
||||
br %r6 # Return cc
|
||||
BR_EX %r6 # Return cc
|
||||
|
||||
#define sk_negative_common(NAME, SIZE, LOAD) \
|
||||
sk_load_##NAME##_slow_neg:; \
|
||||
|
@ -103,7 +107,7 @@ sk_load_##NAME##_slow_neg:; \
|
|||
jz bpf_error; \
|
||||
LOAD %r14,0(%r2); /* Get data from pointer */ \
|
||||
xr %r3,%r3; /* Set cc to zero */ \
|
||||
br %r6; /* Return cc */
|
||||
BR_EX %r6; /* Return cc */
|
||||
|
||||
sk_negative_common(word, 4, llgf)
|
||||
sk_negative_common(half, 2, llgh)
|
||||
|
@ -112,4 +116,4 @@ sk_negative_common(byte, 1, llgc)
|
|||
bpf_error:
|
||||
# force a return 0 from jit handler
|
||||
ltgr %r15,%r15 # Set condition code
|
||||
br %r6
|
||||
BR_EX %r6
|
||||
|
|
|
@ -24,6 +24,8 @@
|
|||
#include <linux/bpf.h>
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/dis.h>
|
||||
#include <asm/facility.h>
|
||||
#include <asm/nospec-branch.h>
|
||||
#include "bpf_jit.h"
|
||||
|
||||
int bpf_jit_enable __read_mostly;
|
||||
|
@ -41,6 +43,8 @@ struct bpf_jit {
|
|||
int base_ip; /* Base address for literal pool */
|
||||
int ret0_ip; /* Address of return 0 */
|
||||
int exit_ip; /* Address of exit */
|
||||
int r1_thunk_ip; /* Address of expoline thunk for 'br %r1' */
|
||||
int r14_thunk_ip; /* Address of expoline thunk for 'br %r14' */
|
||||
int tail_call_start; /* Tail call start offset */
|
||||
int labels[1]; /* Labels for local jumps */
|
||||
};
|
||||
|
@ -248,6 +252,19 @@ static inline void reg_set_seen(struct bpf_jit *jit, u32 b1)
|
|||
REG_SET_SEEN(b2); \
|
||||
})
|
||||
|
||||
#define EMIT6_PCREL_RILB(op, b, target) \
|
||||
({ \
|
||||
int rel = (target - jit->prg) / 2; \
|
||||
_EMIT6(op | reg_high(b) << 16 | rel >> 16, rel & 0xffff); \
|
||||
REG_SET_SEEN(b); \
|
||||
})
|
||||
|
||||
#define EMIT6_PCREL_RIL(op, target) \
|
||||
({ \
|
||||
int rel = (target - jit->prg) / 2; \
|
||||
_EMIT6(op | rel >> 16, rel & 0xffff); \
|
||||
})
|
||||
|
||||
#define _EMIT6_IMM(op, imm) \
|
||||
({ \
|
||||
unsigned int __imm = (imm); \
|
||||
|
@ -475,8 +492,45 @@ static void bpf_jit_epilogue(struct bpf_jit *jit)
|
|||
EMIT4(0xb9040000, REG_2, BPF_REG_0);
|
||||
/* Restore registers */
|
||||
save_restore_regs(jit, REGS_RESTORE);
|
||||
if (IS_ENABLED(CC_USING_EXPOLINE) && !nospec_disable) {
|
||||
jit->r14_thunk_ip = jit->prg;
|
||||
/* Generate __s390_indirect_jump_r14 thunk */
|
||||
if (test_facility(35)) {
|
||||
/* exrl %r0,.+10 */
|
||||
EMIT6_PCREL_RIL(0xc6000000, jit->prg + 10);
|
||||
} else {
|
||||
/* larl %r1,.+14 */
|
||||
EMIT6_PCREL_RILB(0xc0000000, REG_1, jit->prg + 14);
|
||||
/* ex 0,0(%r1) */
|
||||
EMIT4_DISP(0x44000000, REG_0, REG_1, 0);
|
||||
}
|
||||
/* j . */
|
||||
EMIT4_PCREL(0xa7f40000, 0);
|
||||
}
|
||||
/* br %r14 */
|
||||
_EMIT2(0x07fe);
|
||||
|
||||
if (IS_ENABLED(CC_USING_EXPOLINE) && !nospec_disable &&
|
||||
(jit->seen & SEEN_FUNC)) {
|
||||
jit->r1_thunk_ip = jit->prg;
|
||||
/* Generate __s390_indirect_jump_r1 thunk */
|
||||
if (test_facility(35)) {
|
||||
/* exrl %r0,.+10 */
|
||||
EMIT6_PCREL_RIL(0xc6000000, jit->prg + 10);
|
||||
/* j . */
|
||||
EMIT4_PCREL(0xa7f40000, 0);
|
||||
/* br %r1 */
|
||||
_EMIT2(0x07f1);
|
||||
} else {
|
||||
/* larl %r1,.+14 */
|
||||
EMIT6_PCREL_RILB(0xc0000000, REG_1, jit->prg + 14);
|
||||
/* ex 0,S390_lowcore.br_r1_tampoline */
|
||||
EMIT4_DISP(0x44000000, REG_0, REG_0,
|
||||
offsetof(struct _lowcore, br_r1_trampoline));
|
||||
/* j . */
|
||||
EMIT4_PCREL(0xa7f40000, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -980,8 +1034,13 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp, int i
|
|||
/* lg %w1,<d(imm)>(%l) */
|
||||
EMIT6_DISP_LH(0xe3000000, 0x0004, REG_W1, REG_0, REG_L,
|
||||
EMIT_CONST_U64(func));
|
||||
/* basr %r14,%w1 */
|
||||
EMIT2(0x0d00, REG_14, REG_W1);
|
||||
if (IS_ENABLED(CC_USING_EXPOLINE) && !nospec_disable) {
|
||||
/* brasl %r14,__s390_indirect_jump_r1 */
|
||||
EMIT6_PCREL_RILB(0xc0050000, REG_14, jit->r1_thunk_ip);
|
||||
} else {
|
||||
/* basr %r14,%w1 */
|
||||
EMIT2(0x0d00, REG_14, REG_W1);
|
||||
}
|
||||
/* lgr %b0,%r2: load return value into %b0 */
|
||||
EMIT4(0xb9040000, BPF_REG_0, REG_2);
|
||||
if (bpf_helper_changes_skb_data((void *)func)) {
|
||||
|
|
|
@ -10,20 +10,11 @@
|
|||
/* XXX: UP variants, fix for SH-4A and SMP.. */
|
||||
#include <asm/futex-irq.h>
|
||||
|
||||
static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
|
||||
static inline int arch_futex_atomic_op_inuser(int op, u32 oparg, int *oval,
|
||||
u32 __user *uaddr)
|
||||
{
|
||||
int op = (encoded_op >> 28) & 7;
|
||||
int cmp = (encoded_op >> 24) & 15;
|
||||
int oparg = (encoded_op << 8) >> 20;
|
||||
int cmparg = (encoded_op << 20) >> 20;
|
||||
int oldval = 0, ret;
|
||||
|
||||
if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
|
||||
oparg = 1 << oparg;
|
||||
|
||||
if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
|
||||
return -EFAULT;
|
||||
|
||||
pagefault_disable();
|
||||
|
||||
switch (op) {
|
||||
|
@ -49,17 +40,8 @@ static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
|
|||
|
||||
pagefault_enable();
|
||||
|
||||
if (!ret) {
|
||||
switch (cmp) {
|
||||
case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
|
||||
case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
|
||||
case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
|
||||
case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
|
||||
case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
|
||||
case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
|
||||
default: ret = -ENOSYS;
|
||||
}
|
||||
}
|
||||
if (!ret)
|
||||
*oval = oldval;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -29,22 +29,14 @@
|
|||
: "r" (uaddr), "r" (oparg), "i" (-EFAULT) \
|
||||
: "memory")
|
||||
|
||||
static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
|
||||
static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,
|
||||
u32 __user *uaddr)
|
||||
{
|
||||
int op = (encoded_op >> 28) & 7;
|
||||
int cmp = (encoded_op >> 24) & 15;
|
||||
int oparg = (encoded_op << 8) >> 20;
|
||||
int cmparg = (encoded_op << 20) >> 20;
|
||||
int oldval = 0, ret, tem;
|
||||
|
||||
if (unlikely(!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))))
|
||||
return -EFAULT;
|
||||
if (unlikely((((unsigned long) uaddr) & 0x3UL)))
|
||||
return -EINVAL;
|
||||
|
||||
if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
|
||||
oparg = 1 << oparg;
|
||||
|
||||
pagefault_disable();
|
||||
|
||||
switch (op) {
|
||||
|
@ -69,17 +61,9 @@ static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
|
|||
|
||||
pagefault_enable();
|
||||
|
||||
if (!ret) {
|
||||
switch (cmp) {
|
||||
case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
|
||||
case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
|
||||
case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
|
||||
case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
|
||||
case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
|
||||
case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
|
||||
default: ret = -ENOSYS;
|
||||
}
|
||||
}
|
||||
if (!ret)
|
||||
*oval = oldval;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -106,12 +106,9 @@
|
|||
lock = __atomic_hashed_lock((int __force *)uaddr)
|
||||
#endif
|
||||
|
||||
static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
|
||||
static inline int arch_futex_atomic_op_inuser(int op, u32 oparg, int *oval,
|
||||
u32 __user *uaddr)
|
||||
{
|
||||
int op = (encoded_op >> 28) & 7;
|
||||
int cmp = (encoded_op >> 24) & 15;
|
||||
int oparg = (encoded_op << 8) >> 20;
|
||||
int cmparg = (encoded_op << 20) >> 20;
|
||||
int uninitialized_var(val), ret;
|
||||
|
||||
__futex_prolog();
|
||||
|
@ -119,12 +116,6 @@ static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
|
|||
/* The 32-bit futex code makes this assumption, so validate it here. */
|
||||
BUILD_BUG_ON(sizeof(atomic_t) != sizeof(int));
|
||||
|
||||
if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
|
||||
oparg = 1 << oparg;
|
||||
|
||||
if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
|
||||
return -EFAULT;
|
||||
|
||||
pagefault_disable();
|
||||
switch (op) {
|
||||
case FUTEX_OP_SET:
|
||||
|
@ -148,30 +139,9 @@ static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
|
|||
}
|
||||
pagefault_enable();
|
||||
|
||||
if (!ret) {
|
||||
switch (cmp) {
|
||||
case FUTEX_OP_CMP_EQ:
|
||||
ret = (val == cmparg);
|
||||
break;
|
||||
case FUTEX_OP_CMP_NE:
|
||||
ret = (val != cmparg);
|
||||
break;
|
||||
case FUTEX_OP_CMP_LT:
|
||||
ret = (val < cmparg);
|
||||
break;
|
||||
case FUTEX_OP_CMP_GE:
|
||||
ret = (val >= cmparg);
|
||||
break;
|
||||
case FUTEX_OP_CMP_LE:
|
||||
ret = (val <= cmparg);
|
||||
break;
|
||||
case FUTEX_OP_CMP_GT:
|
||||
ret = (val > cmparg);
|
||||
break;
|
||||
default:
|
||||
ret = -ENOSYS;
|
||||
}
|
||||
}
|
||||
if (!ret)
|
||||
*oval = val;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -364,7 +364,8 @@ __setup_efi_pci32(efi_pci_io_protocol_32 *pci, struct pci_setup_rom **__rom)
|
|||
if (status != EFI_SUCCESS)
|
||||
goto free_struct;
|
||||
|
||||
memcpy(rom->romdata, pci->romimage, pci->romsize);
|
||||
memcpy(rom->romdata, (void *)(unsigned long)pci->romimage,
|
||||
pci->romsize);
|
||||
return status;
|
||||
|
||||
free_struct:
|
||||
|
@ -470,7 +471,8 @@ __setup_efi_pci64(efi_pci_io_protocol_64 *pci, struct pci_setup_rom **__rom)
|
|||
if (status != EFI_SUCCESS)
|
||||
goto free_struct;
|
||||
|
||||
memcpy(rom->romdata, pci->romimage, pci->romsize);
|
||||
memcpy(rom->romdata, (void *)(unsigned long)pci->romimage,
|
||||
pci->romsize);
|
||||
return status;
|
||||
|
||||
free_struct:
|
||||
|
|
|
@ -166,7 +166,8 @@ quiet_cmd_vdso = VDSO $@
|
|||
sh $(srctree)/$(src)/checkundef.sh '$(NM)' '$@'
|
||||
|
||||
VDSO_LDFLAGS = -fPIC -shared $(call cc-ldoption, -Wl$(comma)--hash-style=both) \
|
||||
$(call cc-ldoption, -Wl$(comma)--build-id) -Wl,-Bsymbolic $(LTO_CFLAGS)
|
||||
$(call cc-ldoption, -Wl$(comma)--build-id) -Wl,-Bsymbolic $(LTO_CFLAGS) \
|
||||
$(filter --target=% --gcc-toolchain=%,$(KBUILD_CFLAGS))
|
||||
GCOV_PROFILE := n
|
||||
|
||||
#
|
||||
|
|
|
@ -41,20 +41,11 @@
|
|||
"+m" (*uaddr), "=&r" (tem) \
|
||||
: "r" (oparg), "i" (-EFAULT), "1" (0))
|
||||
|
||||
static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
|
||||
static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,
|
||||
u32 __user *uaddr)
|
||||
{
|
||||
int op = (encoded_op >> 28) & 7;
|
||||
int cmp = (encoded_op >> 24) & 15;
|
||||
int oparg = (encoded_op << 8) >> 20;
|
||||
int cmparg = (encoded_op << 20) >> 20;
|
||||
int oldval = 0, ret, tem;
|
||||
|
||||
if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
|
||||
oparg = 1 << oparg;
|
||||
|
||||
if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
|
||||
return -EFAULT;
|
||||
|
||||
pagefault_disable();
|
||||
|
||||
switch (op) {
|
||||
|
@ -80,30 +71,9 @@ static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
|
|||
|
||||
pagefault_enable();
|
||||
|
||||
if (!ret) {
|
||||
switch (cmp) {
|
||||
case FUTEX_OP_CMP_EQ:
|
||||
ret = (oldval == cmparg);
|
||||
break;
|
||||
case FUTEX_OP_CMP_NE:
|
||||
ret = (oldval != cmparg);
|
||||
break;
|
||||
case FUTEX_OP_CMP_LT:
|
||||
ret = (oldval < cmparg);
|
||||
break;
|
||||
case FUTEX_OP_CMP_GE:
|
||||
ret = (oldval >= cmparg);
|
||||
break;
|
||||
case FUTEX_OP_CMP_LE:
|
||||
ret = (oldval <= cmparg);
|
||||
break;
|
||||
case FUTEX_OP_CMP_GT:
|
||||
ret = (oldval > cmparg);
|
||||
break;
|
||||
default:
|
||||
ret = -ENOSYS;
|
||||
}
|
||||
}
|
||||
if (!ret)
|
||||
*oval = oldval;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -71,12 +71,17 @@ static void load_segments(void)
|
|||
static void machine_kexec_free_page_tables(struct kimage *image)
|
||||
{
|
||||
free_page((unsigned long)image->arch.pgd);
|
||||
image->arch.pgd = NULL;
|
||||
#ifdef CONFIG_X86_PAE
|
||||
free_page((unsigned long)image->arch.pmd0);
|
||||
image->arch.pmd0 = NULL;
|
||||
free_page((unsigned long)image->arch.pmd1);
|
||||
image->arch.pmd1 = NULL;
|
||||
#endif
|
||||
free_page((unsigned long)image->arch.pte0);
|
||||
image->arch.pte0 = NULL;
|
||||
free_page((unsigned long)image->arch.pte1);
|
||||
image->arch.pte1 = NULL;
|
||||
}
|
||||
|
||||
static int machine_kexec_alloc_page_tables(struct kimage *image)
|
||||
|
@ -93,7 +98,6 @@ static int machine_kexec_alloc_page_tables(struct kimage *image)
|
|||
!image->arch.pmd0 || !image->arch.pmd1 ||
|
||||
#endif
|
||||
!image->arch.pte0 || !image->arch.pte1) {
|
||||
machine_kexec_free_page_tables(image);
|
||||
return -ENOMEM;
|
||||
}
|
||||
return 0;
|
||||
|
|
|
@ -37,8 +37,11 @@ static struct kexec_file_ops *kexec_file_loaders[] = {
|
|||
static void free_transition_pgtable(struct kimage *image)
|
||||
{
|
||||
free_page((unsigned long)image->arch.pud);
|
||||
image->arch.pud = NULL;
|
||||
free_page((unsigned long)image->arch.pmd);
|
||||
image->arch.pmd = NULL;
|
||||
free_page((unsigned long)image->arch.pte);
|
||||
image->arch.pte = NULL;
|
||||
}
|
||||
|
||||
static int init_transition_pgtable(struct kimage *image, pgd_t *pgd)
|
||||
|
@ -79,7 +82,6 @@ static int init_transition_pgtable(struct kimage *image, pgd_t *pgd)
|
|||
set_pte(pte, pfn_pte(paddr >> PAGE_SHIFT, PAGE_KERNEL_EXEC));
|
||||
return 0;
|
||||
err:
|
||||
free_transition_pgtable(image);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -1316,8 +1316,6 @@ void xen_flush_tlb_all(void)
|
|||
struct mmuext_op *op;
|
||||
struct multicall_space mcs;
|
||||
|
||||
trace_xen_mmu_flush_tlb_all(0);
|
||||
|
||||
preempt_disable();
|
||||
|
||||
mcs = xen_mc_entry(sizeof(*op));
|
||||
|
@ -1335,8 +1333,6 @@ static void xen_flush_tlb(void)
|
|||
struct mmuext_op *op;
|
||||
struct multicall_space mcs;
|
||||
|
||||
trace_xen_mmu_flush_tlb(0);
|
||||
|
||||
preempt_disable();
|
||||
|
||||
mcs = xen_mc_entry(sizeof(*op));
|
||||
|
|
|
@ -44,18 +44,10 @@
|
|||
: "r" (uaddr), "I" (-EFAULT), "r" (oparg) \
|
||||
: "memory")
|
||||
|
||||
static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
|
||||
static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,
|
||||
u32 __user *uaddr)
|
||||
{
|
||||
int op = (encoded_op >> 28) & 7;
|
||||
int cmp = (encoded_op >> 24) & 15;
|
||||
int oparg = (encoded_op << 8) >> 20;
|
||||
int cmparg = (encoded_op << 20) >> 20;
|
||||
int oldval = 0, ret;
|
||||
if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
|
||||
oparg = 1 << oparg;
|
||||
|
||||
if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
|
||||
return -EFAULT;
|
||||
|
||||
#if !XCHAL_HAVE_S32C1I
|
||||
return -ENOSYS;
|
||||
|
@ -89,19 +81,10 @@ static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
|
|||
|
||||
pagefault_enable();
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
if (!ret)
|
||||
*oval = oldval;
|
||||
|
||||
switch (cmp) {
|
||||
case FUTEX_OP_CMP_EQ: return (oldval == cmparg);
|
||||
case FUTEX_OP_CMP_NE: return (oldval != cmparg);
|
||||
case FUTEX_OP_CMP_LT: return (oldval < cmparg);
|
||||
case FUTEX_OP_CMP_GE: return (oldval >= cmparg);
|
||||
case FUTEX_OP_CMP_LE: return (oldval <= cmparg);
|
||||
case FUTEX_OP_CMP_GT: return (oldval > cmparg);
|
||||
}
|
||||
|
||||
return -ENOSYS;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int
|
||||
|
|
|
@ -6,7 +6,7 @@ DEFCONFIG=x86_64_cuttlefish_defconfig
|
|||
EXTRA_CMDS=''
|
||||
KERNEL_DIR=common
|
||||
POST_DEFCONFIG_CMDS="check_defconfig"
|
||||
CLANG_PREBUILT_BIN=prebuilts/clang/host/linux-x86/clang-4630689/bin
|
||||
CLANG_PREBUILT_BIN=prebuilts-master/clang/host/linux-x86/clang-r328903/bin
|
||||
LINUX_GCC_CROSS_COMPILE_PREBUILTS_BIN=prebuilts/gcc/linux-x86/x86/x86_64-linux-android-4.9/bin
|
||||
FILES="
|
||||
arch/x86/boot/bzImage
|
||||
|
|
|
@ -1361,6 +1361,11 @@ static inline bool intel_pstate_platform_pwr_mgmt_exists(void) { return false; }
|
|||
static inline bool intel_pstate_has_acpi_ppc(void) { return false; }
|
||||
#endif /* CONFIG_ACPI */
|
||||
|
||||
static const struct x86_cpu_id hwp_support_ids[] __initconst = {
|
||||
{ X86_VENDOR_INTEL, 6, X86_MODEL_ANY, X86_FEATURE_HWP },
|
||||
{}
|
||||
};
|
||||
|
||||
static int __init intel_pstate_init(void)
|
||||
{
|
||||
int cpu, rc = 0;
|
||||
|
@ -1370,17 +1375,16 @@ static int __init intel_pstate_init(void)
|
|||
if (no_load)
|
||||
return -ENODEV;
|
||||
|
||||
if (x86_match_cpu(hwp_support_ids) && !no_hwp) {
|
||||
copy_cpu_funcs(&core_params.funcs);
|
||||
hwp_active++;
|
||||
goto hwp_cpu_matched;
|
||||
}
|
||||
|
||||
id = x86_match_cpu(intel_pstate_cpu_ids);
|
||||
if (!id)
|
||||
return -ENODEV;
|
||||
|
||||
/*
|
||||
* The Intel pstate driver will be ignored if the platform
|
||||
* firmware has its own power management modes.
|
||||
*/
|
||||
if (intel_pstate_platform_pwr_mgmt_exists())
|
||||
return -ENODEV;
|
||||
|
||||
cpu_def = (struct cpu_defaults *)id->driver_data;
|
||||
|
||||
copy_pid_params(&cpu_def->pid_policy);
|
||||
|
@ -1389,17 +1393,20 @@ static int __init intel_pstate_init(void)
|
|||
if (intel_pstate_msrs_not_valid())
|
||||
return -ENODEV;
|
||||
|
||||
hwp_cpu_matched:
|
||||
/*
|
||||
* The Intel pstate driver will be ignored if the platform
|
||||
* firmware has its own power management modes.
|
||||
*/
|
||||
if (intel_pstate_platform_pwr_mgmt_exists())
|
||||
return -ENODEV;
|
||||
|
||||
pr_info("Intel P-state driver initializing.\n");
|
||||
|
||||
all_cpu_data = vzalloc(sizeof(void *) * num_possible_cpus());
|
||||
if (!all_cpu_data)
|
||||
return -ENOMEM;
|
||||
|
||||
if (static_cpu_has_safe(X86_FEATURE_HWP) && !no_hwp) {
|
||||
pr_info("intel_pstate: HWP enabled\n");
|
||||
hwp_active++;
|
||||
}
|
||||
|
||||
if (!hwp_active && hwp_only)
|
||||
goto out;
|
||||
|
||||
|
@ -1410,6 +1417,9 @@ static int __init intel_pstate_init(void)
|
|||
intel_pstate_debug_expose_params();
|
||||
intel_pstate_sysfs_expose_params();
|
||||
|
||||
if (hwp_active)
|
||||
pr_info("intel_pstate: HWP enabled\n");
|
||||
|
||||
return rc;
|
||||
out:
|
||||
get_online_cpus();
|
||||
|
|
|
@ -592,7 +592,7 @@ static int __init powernv_cpufreq_init(void)
|
|||
int rc = 0;
|
||||
|
||||
/* Don't probe on pseries (guest) platforms */
|
||||
if (!firmware_has_feature(FW_FEATURE_OPALv3))
|
||||
if (!firmware_has_feature(FW_FEATURE_OPAL))
|
||||
return -ENODEV;
|
||||
|
||||
/* Discover pstates from device tree and init */
|
||||
|
|
|
@ -119,7 +119,6 @@ struct cpuidle_coupled {
|
|||
|
||||
#define CPUIDLE_COUPLED_NOT_IDLE (-1)
|
||||
|
||||
static DEFINE_MUTEX(cpuidle_coupled_lock);
|
||||
static DEFINE_PER_CPU(struct call_single_data, cpuidle_coupled_poke_cb);
|
||||
|
||||
/*
|
||||
|
|
|
@ -282,7 +282,7 @@ static int powernv_idle_probe(void)
|
|||
if (cpuidle_disable != IDLE_NO_OVERRIDE)
|
||||
return -ENODEV;
|
||||
|
||||
if (firmware_has_feature(FW_FEATURE_OPALv3)) {
|
||||
if (firmware_has_feature(FW_FEATURE_OPAL)) {
|
||||
cpuidle_state_table = powernv_states;
|
||||
/* Device tree can indicate more idle states */
|
||||
max_idle_state = powernv_add_idle_states();
|
||||
|
|
|
@ -200,6 +200,48 @@ static int gpio_rcar_irq_set_wake(struct irq_data *d, unsigned int on)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void gpio_rcar_irq_bus_lock(struct irq_data *d)
|
||||
{
|
||||
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
|
||||
struct gpio_rcar_priv *p = container_of(gc, struct gpio_rcar_priv,
|
||||
gpio_chip);
|
||||
|
||||
pm_runtime_get_sync(&p->pdev->dev);
|
||||
}
|
||||
|
||||
static void gpio_rcar_irq_bus_sync_unlock(struct irq_data *d)
|
||||
{
|
||||
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
|
||||
struct gpio_rcar_priv *p = container_of(gc, struct gpio_rcar_priv,
|
||||
gpio_chip);
|
||||
|
||||
pm_runtime_put(&p->pdev->dev);
|
||||
}
|
||||
|
||||
|
||||
static int gpio_rcar_irq_request_resources(struct irq_data *d)
|
||||
{
|
||||
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
|
||||
struct gpio_rcar_priv *p = container_of(gc, struct gpio_rcar_priv,
|
||||
gpio_chip);
|
||||
int error;
|
||||
|
||||
error = pm_runtime_get_sync(&p->pdev->dev);
|
||||
if (error < 0)
|
||||
return error;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void gpio_rcar_irq_release_resources(struct irq_data *d)
|
||||
{
|
||||
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
|
||||
struct gpio_rcar_priv *p = container_of(gc, struct gpio_rcar_priv,
|
||||
gpio_chip);
|
||||
|
||||
pm_runtime_put(&p->pdev->dev);
|
||||
}
|
||||
|
||||
static irqreturn_t gpio_rcar_irq_handler(int irq, void *dev_id)
|
||||
{
|
||||
struct gpio_rcar_priv *p = dev_id;
|
||||
|
@ -460,6 +502,10 @@ static int gpio_rcar_probe(struct platform_device *pdev)
|
|||
irq_chip->irq_unmask = gpio_rcar_irq_enable;
|
||||
irq_chip->irq_set_type = gpio_rcar_irq_set_type;
|
||||
irq_chip->irq_set_wake = gpio_rcar_irq_set_wake;
|
||||
irq_chip->irq_bus_lock = gpio_rcar_irq_bus_lock;
|
||||
irq_chip->irq_bus_sync_unlock = gpio_rcar_irq_bus_sync_unlock;
|
||||
irq_chip->irq_request_resources = gpio_rcar_irq_request_resources;
|
||||
irq_chip->irq_release_resources = gpio_rcar_irq_release_resources;
|
||||
irq_chip->flags = IRQCHIP_SET_TYPE_MASKED | IRQCHIP_MASK_ON_SUSPEND;
|
||||
|
||||
ret = gpiochip_add(gpio_chip);
|
||||
|
|
|
@ -818,7 +818,8 @@ static struct dm_buffer *__alloc_buffer_wait_no_callback(struct dm_bufio_client
|
|||
* dm-bufio is resistant to allocation failures (it just keeps
|
||||
* one buffer reserved in cases all the allocations fail).
|
||||
* So set flags to not try too hard:
|
||||
* GFP_NOIO: don't recurse into the I/O layer
|
||||
* GFP_NOWAIT: don't wait; if we need to sleep we'll release our
|
||||
* mutex and wait ourselves.
|
||||
* __GFP_NORETRY: don't retry and rather return failure
|
||||
* __GFP_NOMEMALLOC: don't use emergency reserves
|
||||
* __GFP_NOWARN: don't print a warning in case of failure
|
||||
|
@ -828,7 +829,7 @@ static struct dm_buffer *__alloc_buffer_wait_no_callback(struct dm_bufio_client
|
|||
*/
|
||||
while (1) {
|
||||
if (dm_bufio_cache_size_latch != 1) {
|
||||
b = alloc_buffer(c, GFP_NOIO | __GFP_NORETRY | __GFP_NOMEMALLOC | __GFP_NOWARN);
|
||||
b = alloc_buffer(c, GFP_NOWAIT | __GFP_NORETRY | __GFP_NOMEMALLOC | __GFP_NOWARN);
|
||||
if (b)
|
||||
return b;
|
||||
}
|
||||
|
|
|
@ -453,7 +453,7 @@ static void rlb_update_client(struct rlb_client_info *client_info)
|
|||
{
|
||||
int i;
|
||||
|
||||
if (!client_info->slave)
|
||||
if (!client_info->slave || !is_valid_ether_addr(client_info->mac_dst))
|
||||
return;
|
||||
|
||||
for (i = 0; i < RLB_ARP_BURST_SIZE; i++) {
|
||||
|
|
|
@ -8722,14 +8722,15 @@ static void tg3_free_consistent(struct tg3 *tp)
|
|||
tg3_mem_rx_release(tp);
|
||||
tg3_mem_tx_release(tp);
|
||||
|
||||
/* Protect tg3_get_stats64() from reading freed tp->hw_stats. */
|
||||
tg3_full_lock(tp, 0);
|
||||
/* tp->hw_stats can be referenced safely:
|
||||
* 1. under rtnl_lock
|
||||
* 2. or under tp->lock if TG3_FLAG_INIT_COMPLETE is set.
|
||||
*/
|
||||
if (tp->hw_stats) {
|
||||
dma_free_coherent(&tp->pdev->dev, sizeof(struct tg3_hw_stats),
|
||||
tp->hw_stats, tp->stats_mapping);
|
||||
tp->hw_stats = NULL;
|
||||
}
|
||||
tg3_full_unlock(tp);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -14163,7 +14164,7 @@ static struct rtnl_link_stats64 *tg3_get_stats64(struct net_device *dev,
|
|||
struct tg3 *tp = netdev_priv(dev);
|
||||
|
||||
spin_lock_bh(&tp->lock);
|
||||
if (!tp->hw_stats) {
|
||||
if (!tp->hw_stats || !tg3_flag(tp, INIT_COMPLETE)) {
|
||||
*stats = tp->net_stats_prev;
|
||||
spin_unlock_bh(&tp->lock);
|
||||
return stats;
|
||||
|
|
|
@ -967,6 +967,22 @@ static int mlx4_en_set_coalesce(struct net_device *dev,
|
|||
if (!coal->tx_max_coalesced_frames_irq)
|
||||
return -EINVAL;
|
||||
|
||||
if (coal->tx_coalesce_usecs > MLX4_EN_MAX_COAL_TIME ||
|
||||
coal->rx_coalesce_usecs > MLX4_EN_MAX_COAL_TIME ||
|
||||
coal->rx_coalesce_usecs_low > MLX4_EN_MAX_COAL_TIME ||
|
||||
coal->rx_coalesce_usecs_high > MLX4_EN_MAX_COAL_TIME) {
|
||||
netdev_info(dev, "%s: maximum coalesce time supported is %d usecs\n",
|
||||
__func__, MLX4_EN_MAX_COAL_TIME);
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
if (coal->tx_max_coalesced_frames > MLX4_EN_MAX_COAL_PKTS ||
|
||||
coal->rx_max_coalesced_frames > MLX4_EN_MAX_COAL_PKTS) {
|
||||
netdev_info(dev, "%s: maximum coalesced frames supported is %d\n",
|
||||
__func__, MLX4_EN_MAX_COAL_PKTS);
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
priv->rx_frames = (coal->rx_max_coalesced_frames ==
|
||||
MLX4_EN_AUTO_CONF) ?
|
||||
MLX4_EN_RX_COAL_TARGET :
|
||||
|
|
|
@ -140,6 +140,9 @@ enum {
|
|||
#define MLX4_EN_TX_COAL_PKTS 16
|
||||
#define MLX4_EN_TX_COAL_TIME 0x10
|
||||
|
||||
#define MLX4_EN_MAX_COAL_PKTS U16_MAX
|
||||
#define MLX4_EN_MAX_COAL_TIME U16_MAX
|
||||
|
||||
#define MLX4_EN_RX_RATE_LOW 400000
|
||||
#define MLX4_EN_RX_COAL_TIME_LOW 0
|
||||
#define MLX4_EN_RX_RATE_HIGH 450000
|
||||
|
@ -518,8 +521,8 @@ struct mlx4_en_priv {
|
|||
u16 rx_usecs_low;
|
||||
u32 pkt_rate_high;
|
||||
u16 rx_usecs_high;
|
||||
u16 sample_interval;
|
||||
u16 adaptive_rx_coal;
|
||||
u32 sample_interval;
|
||||
u32 adaptive_rx_coal;
|
||||
u32 msg_enable;
|
||||
u32 loopback_ok;
|
||||
u32 validate_loopback;
|
||||
|
|
|
@ -2229,7 +2229,7 @@ static void rtl8139_poll_controller(struct net_device *dev)
|
|||
struct rtl8139_private *tp = netdev_priv(dev);
|
||||
const int irq = tp->pci_dev->irq;
|
||||
|
||||
disable_irq(irq);
|
||||
disable_irq_nosync(irq);
|
||||
rtl8139_interrupt(irq, dev);
|
||||
enable_irq(irq);
|
||||
}
|
||||
|
|
|
@ -4832,6 +4832,9 @@ static void rtl_pll_power_down(struct rtl8169_private *tp)
|
|||
static void rtl_pll_power_up(struct rtl8169_private *tp)
|
||||
{
|
||||
rtl_generic_op(tp, tp->pll_power_ops.up);
|
||||
|
||||
/* give MAC/PHY some time to resume */
|
||||
msleep(20);
|
||||
}
|
||||
|
||||
static void rtl_init_pll_power_ops(struct rtl8169_private *tp)
|
||||
|
|
|
@ -3442,7 +3442,7 @@ static int niu_process_rx_pkt(struct napi_struct *napi, struct niu *np,
|
|||
|
||||
len = (val & RCR_ENTRY_L2_LEN) >>
|
||||
RCR_ENTRY_L2_LEN_SHIFT;
|
||||
len -= ETH_FCS_LEN;
|
||||
append_size = len + ETH_HLEN + ETH_FCS_LEN;
|
||||
|
||||
addr = (val & RCR_ENTRY_PKT_BUF_ADDR) <<
|
||||
RCR_ENTRY_PKT_BUF_ADDR_SHIFT;
|
||||
|
@ -3452,7 +3452,6 @@ static int niu_process_rx_pkt(struct napi_struct *napi, struct niu *np,
|
|||
RCR_ENTRY_PKTBUFSZ_SHIFT];
|
||||
|
||||
off = addr & ~PAGE_MASK;
|
||||
append_size = rcr_size;
|
||||
if (num_rcr == 1) {
|
||||
int ptype;
|
||||
|
||||
|
@ -3465,7 +3464,7 @@ static int niu_process_rx_pkt(struct napi_struct *napi, struct niu *np,
|
|||
else
|
||||
skb_checksum_none_assert(skb);
|
||||
} else if (!(val & RCR_ENTRY_MULTI))
|
||||
append_size = len - skb->len;
|
||||
append_size = append_size - skb->len;
|
||||
|
||||
niu_rx_skb_append(skb, page, off, append_size, rcr_size);
|
||||
if ((page->index + rp->rbr_block_size) - rcr_size == addr) {
|
||||
|
|
|
@ -855,6 +855,18 @@ static int qmi_wwan_probe(struct usb_interface *intf,
|
|||
id->driver_info = (unsigned long)&qmi_wwan_info;
|
||||
}
|
||||
|
||||
/* There are devices where the same interface number can be
|
||||
* configured as different functions. We should only bind to
|
||||
* vendor specific functions when matching on interface number
|
||||
*/
|
||||
if (id->match_flags & USB_DEVICE_ID_MATCH_INT_NUMBER &&
|
||||
desc->bInterfaceClass != USB_CLASS_VENDOR_SPEC) {
|
||||
dev_dbg(&intf->dev,
|
||||
"Rejecting interface number match for class %02x\n",
|
||||
desc->bInterfaceClass);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* Quectel EC20 quirk where we've QMI on interface 4 instead of 0 */
|
||||
if (quectel_ec20_detected(intf) && desc->bInterfaceNumber == 0) {
|
||||
dev_dbg(&intf->dev, "Quectel EC20 quirk, skipping interface 0\n");
|
||||
|
|
|
@ -140,7 +140,7 @@ static int __qdio_allocate_qs(struct qdio_q **irq_ptr_qs, int nr_queues)
|
|||
int i;
|
||||
|
||||
for (i = 0; i < nr_queues; i++) {
|
||||
q = kmem_cache_alloc(qdio_q_cache, GFP_KERNEL);
|
||||
q = kmem_cache_zalloc(qdio_q_cache, GFP_KERNEL);
|
||||
if (!q)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -456,7 +456,6 @@ int qdio_setup_irq(struct qdio_initialize *init_data)
|
|||
{
|
||||
struct ciw *ciw;
|
||||
struct qdio_irq *irq_ptr = init_data->cdev->private->qdio_data;
|
||||
int rc;
|
||||
|
||||
memset(&irq_ptr->qib, 0, sizeof(irq_ptr->qib));
|
||||
memset(&irq_ptr->siga_flag, 0, sizeof(irq_ptr->siga_flag));
|
||||
|
@ -493,16 +492,14 @@ int qdio_setup_irq(struct qdio_initialize *init_data)
|
|||
ciw = ccw_device_get_ciw(init_data->cdev, CIW_TYPE_EQUEUE);
|
||||
if (!ciw) {
|
||||
DBF_ERROR("%4x NO EQ", irq_ptr->schid.sch_no);
|
||||
rc = -EINVAL;
|
||||
goto out_err;
|
||||
return -EINVAL;
|
||||
}
|
||||
irq_ptr->equeue = *ciw;
|
||||
|
||||
ciw = ccw_device_get_ciw(init_data->cdev, CIW_TYPE_AQUEUE);
|
||||
if (!ciw) {
|
||||
DBF_ERROR("%4x NO AQ", irq_ptr->schid.sch_no);
|
||||
rc = -EINVAL;
|
||||
goto out_err;
|
||||
return -EINVAL;
|
||||
}
|
||||
irq_ptr->aqueue = *ciw;
|
||||
|
||||
|
@ -510,9 +507,6 @@ int qdio_setup_irq(struct qdio_initialize *init_data)
|
|||
irq_ptr->orig_handler = init_data->cdev->handler;
|
||||
init_data->cdev->handler = qdio_int_handler;
|
||||
return 0;
|
||||
out_err:
|
||||
qdio_release_memory(irq_ptr);
|
||||
return rc;
|
||||
}
|
||||
|
||||
void qdio_print_subchannel_info(struct qdio_irq *irq_ptr,
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* Debug traces for zfcp.
|
||||
*
|
||||
* Copyright IBM Corp. 2002, 2017
|
||||
* Copyright IBM Corp. 2002, 2018
|
||||
*/
|
||||
|
||||
#define KMSG_COMPONENT "zfcp"
|
||||
|
@ -287,6 +287,27 @@ void zfcp_dbf_rec_trig(char *tag, struct zfcp_adapter *adapter,
|
|||
spin_unlock_irqrestore(&dbf->rec_lock, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* zfcp_dbf_rec_trig_lock - trace event related to triggered recovery with lock
|
||||
* @tag: identifier for event
|
||||
* @adapter: adapter on which the erp_action should run
|
||||
* @port: remote port involved in the erp_action
|
||||
* @sdev: scsi device involved in the erp_action
|
||||
* @want: wanted erp_action
|
||||
* @need: required erp_action
|
||||
*
|
||||
* The adapter->erp_lock must not be held.
|
||||
*/
|
||||
void zfcp_dbf_rec_trig_lock(char *tag, struct zfcp_adapter *adapter,
|
||||
struct zfcp_port *port, struct scsi_device *sdev,
|
||||
u8 want, u8 need)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
read_lock_irqsave(&adapter->erp_lock, flags);
|
||||
zfcp_dbf_rec_trig(tag, adapter, port, sdev, want, need);
|
||||
read_unlock_irqrestore(&adapter->erp_lock, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* zfcp_dbf_rec_run_lvl - trace event related to running recovery
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* External function declarations.
|
||||
*
|
||||
* Copyright IBM Corp. 2002, 2016
|
||||
* Copyright IBM Corp. 2002, 2018
|
||||
*/
|
||||
|
||||
#ifndef ZFCP_EXT_H
|
||||
|
@ -34,6 +34,9 @@ extern int zfcp_dbf_adapter_register(struct zfcp_adapter *);
|
|||
extern void zfcp_dbf_adapter_unregister(struct zfcp_adapter *);
|
||||
extern void zfcp_dbf_rec_trig(char *, struct zfcp_adapter *,
|
||||
struct zfcp_port *, struct scsi_device *, u8, u8);
|
||||
extern void zfcp_dbf_rec_trig_lock(char *tag, struct zfcp_adapter *adapter,
|
||||
struct zfcp_port *port,
|
||||
struct scsi_device *sdev, u8 want, u8 need);
|
||||
extern void zfcp_dbf_rec_run(char *, struct zfcp_erp_action *);
|
||||
extern void zfcp_dbf_rec_run_lvl(int level, char *tag,
|
||||
struct zfcp_erp_action *erp);
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* Interface to Linux SCSI midlayer.
|
||||
*
|
||||
* Copyright IBM Corp. 2002, 2017
|
||||
* Copyright IBM Corp. 2002, 2018
|
||||
*/
|
||||
|
||||
#define KMSG_COMPONENT "zfcp"
|
||||
|
@ -616,9 +616,9 @@ static void zfcp_scsi_rport_register(struct zfcp_port *port)
|
|||
ids.port_id = port->d_id;
|
||||
ids.roles = FC_RPORT_ROLE_FCP_TARGET;
|
||||
|
||||
zfcp_dbf_rec_trig("scpaddy", port->adapter, port, NULL,
|
||||
ZFCP_PSEUDO_ERP_ACTION_RPORT_ADD,
|
||||
ZFCP_PSEUDO_ERP_ACTION_RPORT_ADD);
|
||||
zfcp_dbf_rec_trig_lock("scpaddy", port->adapter, port, NULL,
|
||||
ZFCP_PSEUDO_ERP_ACTION_RPORT_ADD,
|
||||
ZFCP_PSEUDO_ERP_ACTION_RPORT_ADD);
|
||||
rport = fc_remote_port_add(port->adapter->scsi_host, 0, &ids);
|
||||
if (!rport) {
|
||||
dev_err(&port->adapter->ccw_device->dev,
|
||||
|
@ -640,9 +640,9 @@ static void zfcp_scsi_rport_block(struct zfcp_port *port)
|
|||
struct fc_rport *rport = port->rport;
|
||||
|
||||
if (rport) {
|
||||
zfcp_dbf_rec_trig("scpdely", port->adapter, port, NULL,
|
||||
ZFCP_PSEUDO_ERP_ACTION_RPORT_DEL,
|
||||
ZFCP_PSEUDO_ERP_ACTION_RPORT_DEL);
|
||||
zfcp_dbf_rec_trig_lock("scpdely", port->adapter, port, NULL,
|
||||
ZFCP_PSEUDO_ERP_ACTION_RPORT_DEL,
|
||||
ZFCP_PSEUDO_ERP_ACTION_RPORT_DEL);
|
||||
fc_remote_port_delete(rport);
|
||||
port->rport = NULL;
|
||||
}
|
||||
|
|
|
@ -222,6 +222,7 @@ out_done:
|
|||
static void sas_eh_finish_cmd(struct scsi_cmnd *cmd)
|
||||
{
|
||||
struct sas_ha_struct *sas_ha = SHOST_TO_SAS_HA(cmd->device->host);
|
||||
struct domain_device *dev = cmd_to_domain_dev(cmd);
|
||||
struct sas_task *task = TO_SAS_TASK(cmd);
|
||||
|
||||
/* At this point, we only get called following an actual abort
|
||||
|
@ -230,6 +231,14 @@ static void sas_eh_finish_cmd(struct scsi_cmnd *cmd)
|
|||
*/
|
||||
sas_end_task(cmd, task);
|
||||
|
||||
if (dev_is_sata(dev)) {
|
||||
/* defer commands to libata so that libata EH can
|
||||
* handle ata qcs correctly
|
||||
*/
|
||||
list_move_tail(&cmd->eh_entry, &sas_ha->eh_ata_q);
|
||||
return;
|
||||
}
|
||||
|
||||
/* now finish the command and move it on to the error
|
||||
* handler done list, this also takes it off the
|
||||
* error handler pending list.
|
||||
|
@ -237,22 +246,6 @@ static void sas_eh_finish_cmd(struct scsi_cmnd *cmd)
|
|||
scsi_eh_finish_cmd(cmd, &sas_ha->eh_done_q);
|
||||
}
|
||||
|
||||
static void sas_eh_defer_cmd(struct scsi_cmnd *cmd)
|
||||
{
|
||||
struct domain_device *dev = cmd_to_domain_dev(cmd);
|
||||
struct sas_ha_struct *ha = dev->port->ha;
|
||||
struct sas_task *task = TO_SAS_TASK(cmd);
|
||||
|
||||
if (!dev_is_sata(dev)) {
|
||||
sas_eh_finish_cmd(cmd);
|
||||
return;
|
||||
}
|
||||
|
||||
/* report the timeout to libata */
|
||||
sas_end_task(cmd, task);
|
||||
list_move_tail(&cmd->eh_entry, &ha->eh_ata_q);
|
||||
}
|
||||
|
||||
static void sas_scsi_clear_queue_lu(struct list_head *error_q, struct scsi_cmnd *my_cmd)
|
||||
{
|
||||
struct scsi_cmnd *cmd, *n;
|
||||
|
@ -260,7 +253,7 @@ static void sas_scsi_clear_queue_lu(struct list_head *error_q, struct scsi_cmnd
|
|||
list_for_each_entry_safe(cmd, n, error_q, eh_entry) {
|
||||
if (cmd->device->sdev_target == my_cmd->device->sdev_target &&
|
||||
cmd->device->lun == my_cmd->device->lun)
|
||||
sas_eh_defer_cmd(cmd);
|
||||
sas_eh_finish_cmd(cmd);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -622,12 +615,12 @@ static void sas_eh_handle_sas_errors(struct Scsi_Host *shost, struct list_head *
|
|||
case TASK_IS_DONE:
|
||||
SAS_DPRINTK("%s: task 0x%p is done\n", __func__,
|
||||
task);
|
||||
sas_eh_defer_cmd(cmd);
|
||||
sas_eh_finish_cmd(cmd);
|
||||
continue;
|
||||
case TASK_IS_ABORTED:
|
||||
SAS_DPRINTK("%s: task 0x%p is aborted\n",
|
||||
__func__, task);
|
||||
sas_eh_defer_cmd(cmd);
|
||||
sas_eh_finish_cmd(cmd);
|
||||
continue;
|
||||
case TASK_IS_AT_LU:
|
||||
SAS_DPRINTK("task 0x%p is at LU: lu recover\n", task);
|
||||
|
@ -638,7 +631,7 @@ static void sas_eh_handle_sas_errors(struct Scsi_Host *shost, struct list_head *
|
|||
"recovered\n",
|
||||
SAS_ADDR(task->dev),
|
||||
cmd->device->lun);
|
||||
sas_eh_defer_cmd(cmd);
|
||||
sas_eh_finish_cmd(cmd);
|
||||
sas_scsi_clear_queue_lu(work_q, cmd);
|
||||
goto Again;
|
||||
}
|
||||
|
|
|
@ -1903,7 +1903,7 @@ retry:
|
|||
num = (rem_sz > scatter_elem_sz_prev) ?
|
||||
scatter_elem_sz_prev : rem_sz;
|
||||
|
||||
schp->pages[k] = alloc_pages(gfp_mask, order);
|
||||
schp->pages[k] = alloc_pages(gfp_mask | __GFP_ZERO, order);
|
||||
if (!schp->pages[k])
|
||||
goto out;
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ struct driver_data {
|
|||
|
||||
/* SSP register addresses */
|
||||
void __iomem *ioaddr;
|
||||
u32 ssdr_physical;
|
||||
phys_addr_t ssdr_physical;
|
||||
|
||||
/* SSP masks*/
|
||||
u32 dma_cr1;
|
||||
|
|
|
@ -88,6 +88,7 @@ struct bus_id_priv {
|
|||
struct stub_device *sdev;
|
||||
struct usb_device *udev;
|
||||
char shutdown_busid;
|
||||
spinlock_t busid_lock;
|
||||
};
|
||||
|
||||
/* stub_priv is allocated from stub_priv_cache */
|
||||
|
@ -98,6 +99,7 @@ extern struct usb_device_driver stub_driver;
|
|||
|
||||
/* stub_main.c */
|
||||
struct bus_id_priv *get_busid_priv(const char *busid);
|
||||
void put_busid_priv(struct bus_id_priv *bid);
|
||||
int del_match_busid(char *busid);
|
||||
void stub_device_cleanup_urbs(struct stub_device *sdev);
|
||||
|
||||
|
|
|
@ -314,9 +314,9 @@ static int stub_probe(struct usb_device *udev)
|
|||
struct stub_device *sdev = NULL;
|
||||
const char *udev_busid = dev_name(&udev->dev);
|
||||
struct bus_id_priv *busid_priv;
|
||||
int rc;
|
||||
int rc = 0;
|
||||
|
||||
dev_dbg(&udev->dev, "Enter\n");
|
||||
dev_dbg(&udev->dev, "Enter probe\n");
|
||||
|
||||
/* check we should claim or not by busid_table */
|
||||
busid_priv = get_busid_priv(udev_busid);
|
||||
|
@ -331,13 +331,15 @@ static int stub_probe(struct usb_device *udev)
|
|||
* other matched drivers by the driver core.
|
||||
* See driver_probe_device() in driver/base/dd.c
|
||||
*/
|
||||
return -ENODEV;
|
||||
rc = -ENODEV;
|
||||
goto call_put_busid_priv;
|
||||
}
|
||||
|
||||
if (udev->descriptor.bDeviceClass == USB_CLASS_HUB) {
|
||||
dev_dbg(&udev->dev, "%s is a usb hub device... skip!\n",
|
||||
udev_busid);
|
||||
return -ENODEV;
|
||||
rc = -ENODEV;
|
||||
goto call_put_busid_priv;
|
||||
}
|
||||
|
||||
if (!strcmp(udev->bus->bus_name, "vhci_hcd")) {
|
||||
|
@ -345,13 +347,16 @@ static int stub_probe(struct usb_device *udev)
|
|||
"%s is attached on vhci_hcd... skip!\n",
|
||||
udev_busid);
|
||||
|
||||
return -ENODEV;
|
||||
rc = -ENODEV;
|
||||
goto call_put_busid_priv;
|
||||
}
|
||||
|
||||
/* ok, this is my device */
|
||||
sdev = stub_device_alloc(udev);
|
||||
if (!sdev)
|
||||
return -ENOMEM;
|
||||
if (!sdev) {
|
||||
rc = -ENOMEM;
|
||||
goto call_put_busid_priv;
|
||||
}
|
||||
|
||||
dev_info(&udev->dev,
|
||||
"usbip-host: register new device (bus %u dev %u)\n",
|
||||
|
@ -383,7 +388,9 @@ static int stub_probe(struct usb_device *udev)
|
|||
}
|
||||
busid_priv->status = STUB_BUSID_ALLOC;
|
||||
|
||||
return 0;
|
||||
rc = 0;
|
||||
goto call_put_busid_priv;
|
||||
|
||||
err_files:
|
||||
usb_hub_release_port(udev->parent, udev->portnum,
|
||||
(struct usb_dev_state *) udev);
|
||||
|
@ -394,6 +401,9 @@ err_port:
|
|||
|
||||
busid_priv->sdev = NULL;
|
||||
stub_device_free(sdev);
|
||||
|
||||
call_put_busid_priv:
|
||||
put_busid_priv(busid_priv);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -419,7 +429,7 @@ static void stub_disconnect(struct usb_device *udev)
|
|||
struct bus_id_priv *busid_priv;
|
||||
int rc;
|
||||
|
||||
dev_dbg(&udev->dev, "Enter\n");
|
||||
dev_dbg(&udev->dev, "Enter disconnect\n");
|
||||
|
||||
busid_priv = get_busid_priv(udev_busid);
|
||||
if (!busid_priv) {
|
||||
|
@ -432,7 +442,7 @@ static void stub_disconnect(struct usb_device *udev)
|
|||
/* get stub_device */
|
||||
if (!sdev) {
|
||||
dev_err(&udev->dev, "could not get device");
|
||||
return;
|
||||
goto call_put_busid_priv;
|
||||
}
|
||||
|
||||
dev_set_drvdata(&udev->dev, NULL);
|
||||
|
@ -447,12 +457,12 @@ static void stub_disconnect(struct usb_device *udev)
|
|||
(struct usb_dev_state *) udev);
|
||||
if (rc) {
|
||||
dev_dbg(&udev->dev, "unable to release port\n");
|
||||
return;
|
||||
goto call_put_busid_priv;
|
||||
}
|
||||
|
||||
/* If usb reset is called from event handler */
|
||||
if (busid_priv->sdev->ud.eh == current)
|
||||
return;
|
||||
goto call_put_busid_priv;
|
||||
|
||||
/* shutdown the current connection */
|
||||
shutdown_busid(busid_priv);
|
||||
|
@ -463,12 +473,11 @@ static void stub_disconnect(struct usb_device *udev)
|
|||
busid_priv->sdev = NULL;
|
||||
stub_device_free(sdev);
|
||||
|
||||
if (busid_priv->status == STUB_BUSID_ALLOC) {
|
||||
if (busid_priv->status == STUB_BUSID_ALLOC)
|
||||
busid_priv->status = STUB_BUSID_ADDED;
|
||||
} else {
|
||||
busid_priv->status = STUB_BUSID_OTHER;
|
||||
del_match_busid((char *)udev_busid);
|
||||
}
|
||||
|
||||
call_put_busid_priv:
|
||||
put_busid_priv(busid_priv);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#define DRIVER_DESC "USB/IP Host Driver"
|
||||
|
||||
struct kmem_cache *stub_priv_cache;
|
||||
|
||||
/*
|
||||
* busid_tables defines matching busids that usbip can grab. A user can change
|
||||
* dynamically what device is locally used and what device is exported to a
|
||||
|
@ -39,6 +40,8 @@ static spinlock_t busid_table_lock;
|
|||
|
||||
static void init_busid_table(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
/*
|
||||
* This also sets the bus_table[i].status to
|
||||
* STUB_BUSID_OTHER, which is 0.
|
||||
|
@ -46,6 +49,9 @@ static void init_busid_table(void)
|
|||
memset(busid_table, 0, sizeof(busid_table));
|
||||
|
||||
spin_lock_init(&busid_table_lock);
|
||||
|
||||
for (i = 0; i < MAX_BUSID; i++)
|
||||
spin_lock_init(&busid_table[i].busid_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -57,15 +63,20 @@ static int get_busid_idx(const char *busid)
|
|||
int i;
|
||||
int idx = -1;
|
||||
|
||||
for (i = 0; i < MAX_BUSID; i++)
|
||||
for (i = 0; i < MAX_BUSID; i++) {
|
||||
spin_lock(&busid_table[i].busid_lock);
|
||||
if (busid_table[i].name[0])
|
||||
if (!strncmp(busid_table[i].name, busid, BUSID_SIZE)) {
|
||||
idx = i;
|
||||
spin_unlock(&busid_table[i].busid_lock);
|
||||
break;
|
||||
}
|
||||
spin_unlock(&busid_table[i].busid_lock);
|
||||
}
|
||||
return idx;
|
||||
}
|
||||
|
||||
/* Returns holding busid_lock. Should call put_busid_priv() to unlock */
|
||||
struct bus_id_priv *get_busid_priv(const char *busid)
|
||||
{
|
||||
int idx;
|
||||
|
@ -73,13 +84,22 @@ struct bus_id_priv *get_busid_priv(const char *busid)
|
|||
|
||||
spin_lock(&busid_table_lock);
|
||||
idx = get_busid_idx(busid);
|
||||
if (idx >= 0)
|
||||
if (idx >= 0) {
|
||||
bid = &(busid_table[idx]);
|
||||
/* get busid_lock before returning */
|
||||
spin_lock(&bid->busid_lock);
|
||||
}
|
||||
spin_unlock(&busid_table_lock);
|
||||
|
||||
return bid;
|
||||
}
|
||||
|
||||
void put_busid_priv(struct bus_id_priv *bid)
|
||||
{
|
||||
if (bid)
|
||||
spin_unlock(&bid->busid_lock);
|
||||
}
|
||||
|
||||
static int add_match_busid(char *busid)
|
||||
{
|
||||
int i;
|
||||
|
@ -92,15 +112,19 @@ static int add_match_busid(char *busid)
|
|||
goto out;
|
||||
}
|
||||
|
||||
for (i = 0; i < MAX_BUSID; i++)
|
||||
for (i = 0; i < MAX_BUSID; i++) {
|
||||
spin_lock(&busid_table[i].busid_lock);
|
||||
if (!busid_table[i].name[0]) {
|
||||
strlcpy(busid_table[i].name, busid, BUSID_SIZE);
|
||||
if ((busid_table[i].status != STUB_BUSID_ALLOC) &&
|
||||
(busid_table[i].status != STUB_BUSID_REMOV))
|
||||
busid_table[i].status = STUB_BUSID_ADDED;
|
||||
ret = 0;
|
||||
spin_unlock(&busid_table[i].busid_lock);
|
||||
break;
|
||||
}
|
||||
spin_unlock(&busid_table[i].busid_lock);
|
||||
}
|
||||
|
||||
out:
|
||||
spin_unlock(&busid_table_lock);
|
||||
|
@ -121,6 +145,8 @@ int del_match_busid(char *busid)
|
|||
/* found */
|
||||
ret = 0;
|
||||
|
||||
spin_lock(&busid_table[idx].busid_lock);
|
||||
|
||||
if (busid_table[idx].status == STUB_BUSID_OTHER)
|
||||
memset(busid_table[idx].name, 0, BUSID_SIZE);
|
||||
|
||||
|
@ -128,6 +154,7 @@ int del_match_busid(char *busid)
|
|||
(busid_table[idx].status != STUB_BUSID_ADDED))
|
||||
busid_table[idx].status = STUB_BUSID_REMOV;
|
||||
|
||||
spin_unlock(&busid_table[idx].busid_lock);
|
||||
out:
|
||||
spin_unlock(&busid_table_lock);
|
||||
|
||||
|
@ -140,9 +167,12 @@ static ssize_t show_match_busid(struct device_driver *drv, char *buf)
|
|||
char *out = buf;
|
||||
|
||||
spin_lock(&busid_table_lock);
|
||||
for (i = 0; i < MAX_BUSID; i++)
|
||||
for (i = 0; i < MAX_BUSID; i++) {
|
||||
spin_lock(&busid_table[i].busid_lock);
|
||||
if (busid_table[i].name[0])
|
||||
out += sprintf(out, "%s ", busid_table[i].name);
|
||||
spin_unlock(&busid_table[i].busid_lock);
|
||||
}
|
||||
spin_unlock(&busid_table_lock);
|
||||
out += sprintf(out, "\n");
|
||||
|
||||
|
@ -184,6 +214,51 @@ static ssize_t store_match_busid(struct device_driver *dev, const char *buf,
|
|||
static DRIVER_ATTR(match_busid, S_IRUSR | S_IWUSR, show_match_busid,
|
||||
store_match_busid);
|
||||
|
||||
static int do_rebind(char *busid, struct bus_id_priv *busid_priv)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* device_attach() callers should hold parent lock for USB */
|
||||
if (busid_priv->udev->dev.parent)
|
||||
device_lock(busid_priv->udev->dev.parent);
|
||||
ret = device_attach(&busid_priv->udev->dev);
|
||||
if (busid_priv->udev->dev.parent)
|
||||
device_unlock(busid_priv->udev->dev.parent);
|
||||
if (ret < 0) {
|
||||
dev_err(&busid_priv->udev->dev, "rebind failed\n");
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void stub_device_rebind(void)
|
||||
{
|
||||
#if IS_MODULE(CONFIG_USBIP_HOST)
|
||||
struct bus_id_priv *busid_priv;
|
||||
int i;
|
||||
|
||||
/* update status to STUB_BUSID_OTHER so probe ignores the device */
|
||||
spin_lock(&busid_table_lock);
|
||||
for (i = 0; i < MAX_BUSID; i++) {
|
||||
if (busid_table[i].name[0] &&
|
||||
busid_table[i].shutdown_busid) {
|
||||
busid_priv = &(busid_table[i]);
|
||||
busid_priv->status = STUB_BUSID_OTHER;
|
||||
}
|
||||
}
|
||||
spin_unlock(&busid_table_lock);
|
||||
|
||||
/* now run rebind - no need to hold locks. driver files are removed */
|
||||
for (i = 0; i < MAX_BUSID; i++) {
|
||||
if (busid_table[i].name[0] &&
|
||||
busid_table[i].shutdown_busid) {
|
||||
busid_priv = &(busid_table[i]);
|
||||
do_rebind(busid_table[i].name, busid_priv);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static ssize_t rebind_store(struct device_driver *dev, const char *buf,
|
||||
size_t count)
|
||||
{
|
||||
|
@ -201,16 +276,17 @@ static ssize_t rebind_store(struct device_driver *dev, const char *buf,
|
|||
if (!bid)
|
||||
return -ENODEV;
|
||||
|
||||
/* device_attach() callers should hold parent lock for USB */
|
||||
if (bid->udev->dev.parent)
|
||||
device_lock(bid->udev->dev.parent);
|
||||
ret = device_attach(&bid->udev->dev);
|
||||
if (bid->udev->dev.parent)
|
||||
device_unlock(bid->udev->dev.parent);
|
||||
if (ret < 0) {
|
||||
dev_err(&bid->udev->dev, "rebind failed\n");
|
||||
/* mark the device for deletion so probe ignores it during rescan */
|
||||
bid->status = STUB_BUSID_OTHER;
|
||||
/* release the busid lock */
|
||||
put_busid_priv(bid);
|
||||
|
||||
ret = do_rebind((char *) buf, bid);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* delete device from busid_table */
|
||||
del_match_busid((char *) buf);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
@ -333,6 +409,9 @@ static void __exit usbip_host_exit(void)
|
|||
*/
|
||||
usb_deregister_device_driver(&stub_driver);
|
||||
|
||||
/* initiate scan to attach devices */
|
||||
stub_device_rebind();
|
||||
|
||||
kmem_cache_destroy(stub_priv_cache);
|
||||
}
|
||||
|
||||
|
|
|
@ -2497,10 +2497,8 @@ read_block_for_search(struct btrfs_trans_handle *trans,
|
|||
if (p->reada)
|
||||
reada_for_search(root, p, level, slot, key->objectid);
|
||||
|
||||
btrfs_release_path(p);
|
||||
|
||||
ret = -EAGAIN;
|
||||
tmp = read_tree_block(root, blocknr, 0);
|
||||
tmp = read_tree_block(root, blocknr, gen);
|
||||
if (!IS_ERR(tmp)) {
|
||||
/*
|
||||
* If the read above didn't mark this buffer up to date,
|
||||
|
@ -2512,6 +2510,8 @@ read_block_for_search(struct btrfs_trans_handle *trans,
|
|||
ret = -EIO;
|
||||
free_extent_buffer(tmp);
|
||||
}
|
||||
|
||||
btrfs_release_path(p);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -4568,6 +4568,7 @@ static int btrfs_log_inode(struct btrfs_trans_handle *trans,
|
|||
struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree;
|
||||
u64 logged_isize = 0;
|
||||
bool need_log_inode_item = true;
|
||||
bool xattrs_logged = false;
|
||||
|
||||
path = btrfs_alloc_path();
|
||||
if (!path)
|
||||
|
@ -4808,6 +4809,7 @@ next_slot:
|
|||
err = btrfs_log_all_xattrs(trans, root, inode, path, dst_path);
|
||||
if (err)
|
||||
goto out_unlock;
|
||||
xattrs_logged = true;
|
||||
if (max_key.type >= BTRFS_EXTENT_DATA_KEY && !fast_search) {
|
||||
btrfs_release_path(path);
|
||||
btrfs_release_path(dst_path);
|
||||
|
@ -4820,6 +4822,11 @@ log_extents:
|
|||
btrfs_release_path(dst_path);
|
||||
if (need_log_inode_item) {
|
||||
err = log_inode_item(trans, log, dst_path, inode);
|
||||
if (!err && !xattrs_logged) {
|
||||
err = btrfs_log_all_xattrs(trans, root, inode, path,
|
||||
dst_path);
|
||||
btrfs_release_path(path);
|
||||
}
|
||||
if (err)
|
||||
goto out_unlock;
|
||||
}
|
||||
|
|
|
@ -3850,6 +3850,15 @@ int btrfs_resume_balance_async(struct btrfs_fs_info *fs_info)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* A ro->rw remount sequence should continue with the paused balance
|
||||
* regardless of who pauses it, system or the user as of now, so set
|
||||
* the resume flag.
|
||||
*/
|
||||
spin_lock(&fs_info->balance_lock);
|
||||
fs_info->balance_ctl->flags |= BTRFS_BALANCE_RESUME;
|
||||
spin_unlock(&fs_info->balance_lock);
|
||||
|
||||
tsk = kthread_run(balance_kthread, fs_info, "btrfs-balance");
|
||||
return PTR_ERR_OR_ZERO(tsk);
|
||||
}
|
||||
|
|
|
@ -101,6 +101,10 @@ static inline bool fscrypt_valid_enc_modes(u32 contents_mode,
|
|||
filenames_mode == FS_ENCRYPTION_MODE_AES_256_CTS)
|
||||
return true;
|
||||
|
||||
if (contents_mode == FS_ENCRYPTION_MODE_SPECK128_256_XTS &&
|
||||
filenames_mode == FS_ENCRYPTION_MODE_SPECK128_256_CTS)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -134,6 +134,8 @@ static const struct {
|
|||
FS_AES_128_CBC_KEY_SIZE },
|
||||
[FS_ENCRYPTION_MODE_AES_128_CTS] = { "cts(cbc(aes))",
|
||||
FS_AES_128_CTS_KEY_SIZE },
|
||||
[FS_ENCRYPTION_MODE_SPECK128_256_XTS] = { "xts(speck128)", 64 },
|
||||
[FS_ENCRYPTION_MODE_SPECK128_256_CTS] = { "cts(cbc(speck128))", 32 },
|
||||
};
|
||||
|
||||
static int determine_cipher_type(struct fscrypt_info *ci, struct inode *inode,
|
||||
|
|
|
@ -1175,21 +1175,11 @@ do_indirects:
|
|||
|
||||
static void ext2_truncate_blocks(struct inode *inode, loff_t offset)
|
||||
{
|
||||
/*
|
||||
* XXX: it seems like a bug here that we don't allow
|
||||
* IS_APPEND inode to have blocks-past-i_size trimmed off.
|
||||
* review and fix this.
|
||||
*
|
||||
* Also would be nice to be able to handle IO errors and such,
|
||||
* but that's probably too much to ask.
|
||||
*/
|
||||
if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
|
||||
S_ISLNK(inode->i_mode)))
|
||||
return;
|
||||
if (ext2_inode_is_fast_symlink(inode))
|
||||
return;
|
||||
if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
|
||||
return;
|
||||
|
||||
dax_sem_down_write(EXT2_I(inode));
|
||||
__ext2_truncate_blocks(inode, offset);
|
||||
|
|
|
@ -455,10 +455,18 @@ errout:
|
|||
return err;
|
||||
}
|
||||
|
||||
bool ext4_valid_contents_enc_mode(uint32_t mode)
|
||||
bool ext4_valid_enc_modes(uint32_t contents_mode, uint32_t filenames_mode)
|
||||
{
|
||||
return (mode == EXT4_ENCRYPTION_MODE_AES_256_XTS ||
|
||||
mode == EXT4_ENCRYPTION_MODE_PRIVATE);
|
||||
if (contents_mode == EXT4_ENCRYPTION_MODE_AES_256_XTS ||
|
||||
contents_mode == EXT4_ENCRYPTION_MODE_PRIVATE) {
|
||||
return (filenames_mode == EXT4_ENCRYPTION_MODE_AES_256_CTS ||
|
||||
filenames_mode == EXT4_ENCRYPTION_MODE_AES_256_HEH);
|
||||
}
|
||||
|
||||
if (contents_mode == EXT4_ENCRYPTION_MODE_SPECK128_256_XTS)
|
||||
return filenames_mode == EXT4_ENCRYPTION_MODE_SPECK128_256_CTS;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -42,12 +42,6 @@ static void ext4_dir_crypt_complete(struct crypto_async_request *req, int res)
|
|||
complete(&ecr->completion);
|
||||
}
|
||||
|
||||
bool ext4_valid_filenames_enc_mode(uint32_t mode)
|
||||
{
|
||||
return (mode == EXT4_ENCRYPTION_MODE_AES_256_CTS ||
|
||||
mode == EXT4_ENCRYPTION_MODE_AES_256_HEH);
|
||||
}
|
||||
|
||||
static unsigned max_name_len(struct inode *inode)
|
||||
{
|
||||
return S_ISLNK(inode->i_mode) ? inode->i_sb->s_blocksize :
|
||||
|
|
|
@ -278,6 +278,12 @@ retry:
|
|||
case EXT4_ENCRYPTION_MODE_AES_256_HEH:
|
||||
cipher_str = "heh(aes)";
|
||||
break;
|
||||
case EXT4_ENCRYPTION_MODE_SPECK128_256_XTS:
|
||||
cipher_str = "xts(speck128)";
|
||||
break;
|
||||
case EXT4_ENCRYPTION_MODE_SPECK128_256_CTS:
|
||||
cipher_str = "cts(cbc(speck128))";
|
||||
break;
|
||||
default:
|
||||
printk_once(KERN_WARNING
|
||||
"ext4: unsupported key mode %d (ino %u)\n",
|
||||
|
|
|
@ -60,16 +60,12 @@ static int ext4_create_encryption_context_from_policy(
|
|||
ctx.format = EXT4_ENCRYPTION_CONTEXT_FORMAT_V1;
|
||||
memcpy(ctx.master_key_descriptor, policy->master_key_descriptor,
|
||||
EXT4_KEY_DESCRIPTOR_SIZE);
|
||||
if (!ext4_valid_contents_enc_mode(policy->contents_encryption_mode)) {
|
||||
if (!ext4_valid_enc_modes(policy->contents_encryption_mode,
|
||||
policy->filenames_encryption_mode)) {
|
||||
printk(KERN_WARNING
|
||||
"%s: Invalid contents encryption mode %d\n", __func__,
|
||||
policy->contents_encryption_mode);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (!ext4_valid_filenames_enc_mode(policy->filenames_encryption_mode)) {
|
||||
printk(KERN_WARNING
|
||||
"%s: Invalid filenames encryption mode %d\n", __func__,
|
||||
policy->filenames_encryption_mode);
|
||||
"%s: Invalid encryption modes (contents %d, filenames %d)\n",
|
||||
__func__, policy->contents_encryption_mode,
|
||||
policy->filenames_encryption_mode);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (policy->flags & ~EXT4_POLICY_FLAGS_VALID)
|
||||
|
|
|
@ -589,6 +589,8 @@ enum {
|
|||
#define EXT4_ENCRYPTION_MODE_AES_256_GCM 2
|
||||
#define EXT4_ENCRYPTION_MODE_AES_256_CBC 3
|
||||
#define EXT4_ENCRYPTION_MODE_AES_256_CTS 4
|
||||
#define EXT4_ENCRYPTION_MODE_SPECK128_256_XTS 7
|
||||
#define EXT4_ENCRYPTION_MODE_SPECK128_256_CTS 8
|
||||
#define EXT4_ENCRYPTION_MODE_PRIVATE 127
|
||||
#define EXT4_ENCRYPTION_MODE_AES_256_HEH 126
|
||||
|
||||
|
@ -2260,7 +2262,7 @@ int ext4_get_policy(struct inode *inode,
|
|||
|
||||
/* crypto.c */
|
||||
extern struct kmem_cache *ext4_crypt_info_cachep;
|
||||
bool ext4_valid_contents_enc_mode(uint32_t mode);
|
||||
bool ext4_valid_enc_modes(uint32_t contents_mode, uint32_t filenames_mode);
|
||||
uint32_t ext4_validate_encryption_key_size(uint32_t mode, uint32_t size);
|
||||
extern struct workqueue_struct *ext4_read_workqueue;
|
||||
struct ext4_crypto_ctx *ext4_get_crypto_ctx(struct inode *inode,
|
||||
|
@ -2292,7 +2294,6 @@ static inline int ext4_sb_has_crypto(struct super_block *sb)
|
|||
#endif
|
||||
|
||||
/* crypto_fname.c */
|
||||
bool ext4_valid_filenames_enc_mode(uint32_t mode);
|
||||
u32 ext4_fname_crypto_round_up(u32 size, u32 blksize);
|
||||
unsigned ext4_fname_encrypted_size(struct inode *inode, u32 ilen);
|
||||
int ext4_fname_crypto_alloc_buffer(struct inode *inode,
|
||||
|
|
|
@ -131,6 +131,10 @@ static inline int ext4_encryption_key_size(int mode)
|
|||
return EXT4_AES_256_CTS_KEY_SIZE;
|
||||
case EXT4_ENCRYPTION_MODE_AES_256_HEH:
|
||||
return EXT4_AES_256_HEH_KEY_SIZE;
|
||||
case EXT4_ENCRYPTION_MODE_SPECK128_256_XTS:
|
||||
return 64;
|
||||
case EXT4_ENCRYPTION_MODE_SPECK128_256_CTS:
|
||||
return 32;
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
|
|
|
@ -585,6 +585,7 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
|
|||
return 0;
|
||||
|
||||
out_put_hidden_dir:
|
||||
cancel_delayed_work_sync(&sbi->sync_work);
|
||||
iput(sbi->hidden_dir);
|
||||
out_put_root:
|
||||
dput(sb->s_root);
|
||||
|
|
|
@ -271,6 +271,8 @@ static void lockd_down_net(struct svc_serv *serv, struct net *net)
|
|||
if (ln->nlmsvc_users) {
|
||||
if (--ln->nlmsvc_users == 0) {
|
||||
nlm_shutdown_hosts_net(net);
|
||||
cancel_delayed_work_sync(&ln->grace_period_end);
|
||||
locks_end_grace(&ln->lockd_manager);
|
||||
svc_shutdown_net(serv, net);
|
||||
dprintk("lockd_down_net: per-net data destroyed; net=%p\n", net);
|
||||
}
|
||||
|
|
|
@ -616,6 +616,9 @@ struct pipe_inode_info *alloc_pipe_info(void)
|
|||
unsigned long pipe_bufs = PIPE_DEF_BUFFERS;
|
||||
struct user_struct *user = get_current_user();
|
||||
|
||||
if (pipe_bufs * PAGE_SIZE > pipe_max_size && !capable(CAP_SYS_RESOURCE))
|
||||
pipe_bufs = pipe_max_size >> PAGE_SHIFT;
|
||||
|
||||
if (!too_many_pipe_buffers_hard(user)) {
|
||||
if (too_many_pipe_buffers_soft(user))
|
||||
pipe_bufs = 1;
|
||||
|
|
|
@ -954,6 +954,7 @@ static ssize_t environ_read(struct file *file, char __user *buf,
|
|||
unsigned long src = *ppos;
|
||||
int ret = 0;
|
||||
struct mm_struct *mm = file->private_data;
|
||||
unsigned long env_start, env_end;
|
||||
|
||||
/* Ensure the process spawned far enough to have an environment. */
|
||||
if (!mm || !mm->env_end)
|
||||
|
@ -966,19 +967,25 @@ static ssize_t environ_read(struct file *file, char __user *buf,
|
|||
ret = 0;
|
||||
if (!atomic_inc_not_zero(&mm->mm_users))
|
||||
goto free;
|
||||
|
||||
down_read(&mm->mmap_sem);
|
||||
env_start = mm->env_start;
|
||||
env_end = mm->env_end;
|
||||
up_read(&mm->mmap_sem);
|
||||
|
||||
while (count > 0) {
|
||||
size_t this_len, max_len;
|
||||
int retval;
|
||||
|
||||
if (src >= (mm->env_end - mm->env_start))
|
||||
if (src >= (env_end - env_start))
|
||||
break;
|
||||
|
||||
this_len = mm->env_end - (mm->env_start + src);
|
||||
this_len = env_end - (env_start + src);
|
||||
|
||||
max_len = min_t(size_t, PAGE_SIZE, count);
|
||||
this_len = min(max_len, this_len);
|
||||
|
||||
retval = access_remote_vm(mm, (mm->env_start + src),
|
||||
retval = access_remote_vm(mm, (env_start + src),
|
||||
page, this_len, 0);
|
||||
|
||||
if (retval <= 0) {
|
||||
|
@ -3384,7 +3391,7 @@ int proc_pid_readdir(struct file *file, struct dir_context *ctx)
|
|||
* used for the node /proc/<pid>/task/<tid>/comm.
|
||||
* It bypasses generic permission checks in the case where a task of the same
|
||||
* task group attempts to access the node.
|
||||
* The rational behind this is that glibc and bionic access this node for
|
||||
* The rationale behind this is that glibc and bionic access this node for
|
||||
* cross thread naming (pthread_set/getname_np(!self)). However, if
|
||||
* PR_SET_DUMPABLE gets set to 0 this node among others becomes uid=0 gid=0,
|
||||
* which locks out the cross thread naming implementation.
|
||||
|
|
|
@ -57,11 +57,8 @@ static int meminfo_proc_show(struct seq_file *m, void *v)
|
|||
/*
|
||||
* Estimate the amount of memory available for userspace allocations,
|
||||
* without causing swapping.
|
||||
*
|
||||
* Free memory cannot be taken below the low watermark, before the
|
||||
* system starts swapping.
|
||||
*/
|
||||
available = i.freeram - wmark_low;
|
||||
available = i.freeram - totalreserve_pages;
|
||||
|
||||
/*
|
||||
* Not all the page cache can be freed, otherwise the system will
|
||||
|
|
|
@ -174,7 +174,7 @@ static int proc_uid_base_readdir(struct file *file, struct dir_context *ctx)
|
|||
return 0;
|
||||
|
||||
for (u = uid_base_stuff + (ctx->pos - 2);
|
||||
u <= uid_base_stuff + nents - 1; u++) {
|
||||
u < uid_base_stuff + nents; u++) {
|
||||
if (!proc_fill_cache(file, ctx, u->name, u->len,
|
||||
proc_uident_instantiate, NULL, u))
|
||||
break;
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue