* refs/heads/tmp-59ff2e1 Linux 4.4.78 kvm: vmx: allow host to access guest MSR_IA32_BNDCFGS kvm: vmx: Check value written to IA32_BNDCFGS kvm: x86: Guest BNDCFGS requires guest MPX support kvm: vmx: Do not disable intercepts for BNDCFGS KVM: x86: disable MPX if host did not enable MPX XSAVE features tracing: Use SOFTIRQ_OFFSET for softirq dectection for more accurate results PM / QoS: return -EINVAL for bogus strings PM / wakeirq: Convert to SRCU sched/topology: Optimize build_group_mask() sched/topology: Fix overlapping sched_group_mask crypto: caam - fix signals handling crypto: sha1-ssse3 - Disable avx2 crypto: atmel - only treat EBUSY as transient if backlog crypto: talitos - Extend max key length for SHA384/512-HMAC and AEAD mm: fix overflow check in expand_upwards() tpm: Issue a TPM2_Shutdown for TPM2 devices. Add "shutdown" to "struct class". tpm: Provide strong locking for device removal tpm: Get rid of chip->pdev selftests/capabilities: Fix the test_execve test mnt: Make propagate_umount less slow for overlapping mount propagation trees mnt: In propgate_umount handle visiting mounts in any order mnt: In umount propagation reparent in a separate pass vt: fix unchecked __put_user() in tioclinux ioctls exec: Limit arg stack to at most 75% of _STK_LIM s390: reduce ELF_ET_DYN_BASE powerpc: move ELF_ET_DYN_BASE to 4GB / 4MB arm64: move ELF_ET_DYN_BASE to 4GB / 4MB arm: move ELF_ET_DYN_BASE to 4MB binfmt_elf: use ELF_ET_DYN_BASE only for PIE checkpatch: silence perl 5.26.0 unescaped left brace warnings fs/dcache.c: fix spin lockup issue on nlru->lock mm/list_lru.c: fix list_lru_count_node() to be race free kernel/extable.c: mark core_kernel_text notrace tools/lib/lockdep: Reduce MAX_LOCK_DEPTH to avoid overflowing lock_chain/: Depth parisc/mm: Ensure IRQs are off in switch_mm() parisc: DMA API: return error instead of BUG_ON for dma ops on non dma devs parisc: use compat_sys_keyctl() parisc: Report SIGSEGV instead of SIGBUS when running out of stack irqchip/gic-v3: Fix out-of-bound access in gic_set_affinity cfg80211: Check if PMKID attribute is of expected size cfg80211: Validate frequencies nested in NL80211_ATTR_SCAN_FREQUENCIES cfg80211: Define nla_policy for NL80211_ATTR_LOCAL_MESH_POWER_MODE brcmfmac: fix possible buffer overflow in brcmf_cfg80211_mgmt_tx() rds: tcp: use sock_create_lite() to create the accept socket vrf: fix bug_on triggered by rx when destroying a vrf net: ipv6: Compare lwstate in detecting duplicate nexthops ipv6: dad: don't remove dynamic addresses if link is down net: handle NAPI_GRO_FREE_STOLEN_HEAD case also in napi_frags_finish() bpf: prevent leaking pointer via xadd on unpriviledged net: prevent sign extension in dev_get_stats() tcp: reset sk_rx_dst in tcp_disconnect() net: dp83640: Avoid NULL pointer dereference. ipv6: avoid unregistering inet6_dev for loopback net/phy: micrel: configure intterupts after autoneg workaround net: sched: Fix one possible panic when no destroy callback net_sched: fix error recovery at qdisc creation ANDROID: android-verity: mark dev as rw for linear target ANDROID: sdcardfs: Remove unnecessary lock ANDROID: binder: don't check prio permissions on restore. Add BINDER_GET_NODE_DEBUG_INFO ioctl UPSTREAM: cpufreq: schedutil: Trace frequency only if it has changed UPSTREAM: cpufreq: schedutil: Avoid reducing frequency of busy CPUs prematurely UPSTREAM: cpufreq: schedutil: Refactor sugov_next_freq_shared() UPSTREAM: cpufreq: schedutil: Fix per-CPU structure initialization in sugov_start() UPSTREAM: cpufreq: schedutil: Pass sg_policy to get_next_freq() UPSTREAM: cpufreq: schedutil: move cached_raw_freq to struct sugov_policy UPSTREAM: cpufreq: schedutil: Rectify comment in sugov_irq_work() function UPSTREAM: cpufreq: schedutil: irq-work and mutex are only used in slow path UPSTREAM: cpufreq: schedutil: enable fast switch earlier UPSTREAM: cpufreq: schedutil: Avoid indented labels Linux 4.4.77 saa7134: fix warm Medion 7134 EEPROM read x86/mm/pat: Don't report PAT on CPUs that don't support it ext4: check return value of kstrtoull correctly in reserved_clusters_store staging: comedi: fix clean-up of comedi_class in comedi_init() staging: vt6556: vnt_start Fix missing call to vnt_key_init_table. tcp: fix tcp_mark_head_lost to check skb len before fragmenting md: fix super_offset endianness in super_1_rdev_size_change md: fix incorrect use of lexx_to_cpu in does_sb_need_changing perf tools: Use readdir() instead of deprecated readdir_r() again perf tests: Remove wrong semicolon in while loop in CQM test perf trace: Do not process PERF_RECORD_LOST twice perf dwarf: Guard !x86_64 definitions under #ifdef else clause perf pmu: Fix misleadingly indented assignment (whitespace) perf annotate browser: Fix behaviour of Shift-Tab with nothing focussed perf tools: Remove duplicate const qualifier perf script: Use readdir() instead of deprecated readdir_r() perf thread_map: Use readdir() instead of deprecated readdir_r() perf tools: Use readdir() instead of deprecated readdir_r() perf bench numa: Avoid possible truncation when using snprintf() perf tests: Avoid possible truncation with dirent->d_name + snprintf perf scripting perl: Fix compile error with some perl5 versions perf thread_map: Correctly size buffer used with dirent->dt_name perf intel-pt: Use __fallthrough perf top: Use __fallthrough tools strfilter: Use __fallthrough tools string: Use __fallthrough in perf_atoll() tools include: Add a __fallthrough statement mqueue: fix a use-after-free in sys_mq_notify() RDMA/uverbs: Check port number supplied by user verbs cmds KEYS: Fix an error code in request_master_key() ath10k: override CE5 config for QCA9377 x86/uaccess: Optimize copy_user_enhanced_fast_string() for short strings x86/tools: Fix gcc-7 warning in relocs.c gfs2: Fix glock rhashtable rcu bug USB: serial: qcserial: new Sierra Wireless EM7305 device ID USB: serial: option: add two Longcheer device ids pinctrl: sh-pfc: Update info pointer after SoC-specific init pinctrl: mxs: atomically switch mux and drive strength config pinctrl: sunxi: Fix SPDIF function name for A83T pinctrl: meson: meson8b: fix the NAND DQS pins pinctrl: sh-pfc: r8a7791: Fix SCIF2 pinmux data sysctl: report EINVAL if value is larger than UINT_MAX for proc_douintvec sysctl: don't print negative flag for proc_douintvec mac80211_hwsim: Replace bogus hrtimer clockid usb: Fix typo in the definition of Endpoint[out]Request usb: usbip: set buffer pointers to NULL after free Add USB quirk for HVR-950q to avoid intermittent device resets USB: serial: cp210x: add ID for CEL EM3588 USB ZigBee stick usb: dwc3: replace %p with %pK drm/virtio: don't leak bo on drm_gem_object_init failure tracing/kprobes: Allow to create probe with a module name starting with a digit mm: fix classzone_idx underflow in shrink_zones() bgmac: reset & enable Ethernet core before using it driver core: platform: fix race condition with driver_override fs: completely ignore unknown open flags fs: add a VALID_OPEN_FLAGS ANDROID: binder: add RT inheritance flag to node. ANDROID: binder: improve priority inheritance. ANDROID: binder: add min sched_policy to node. ANDROID: binder: add support for RT prio inheritance. ANDROID: binder: push new transactions to waiting threads. ANDROID: binder: remove proc waitqueue FROMLIST: binder: remove global binder lock FROMLIST: binder: fix death race conditions FROMLIST: binder: protect against stale pointers in print_binder_transaction FROMLIST: binder: protect binder_ref with outer lock FROMLIST: binder: use inner lock to protect thread accounting FROMLIST: binder: protect transaction_stack with inner lock. FROMLIST: binder: protect proc->threads with inner_lock FROMLIST: binder: protect proc->nodes with inner lock FROMLIST: binder: add spinlock to protect binder_node FROMLIST: binder: add spinlocks to protect todo lists FROMLIST: binder: use inner lock to sync work dq and node counts FROMLIST: binder: introduce locking helper functions FROMLIST: binder: use node->tmp_refs to ensure node safety FROMLIST: binder: refactor binder ref inc/dec for thread safety FROMLIST: binder: make sure accesses to proc/thread are safe FROMLIST: binder: make sure target_node has strong ref FROMLIST: binder: guarantee txn complete / errors delivered in-order FROMLIST: binder: refactor binder_pop_transaction FROMLIST: binder: use atomic for transaction_log index FROMLIST: binder: add more debug info when allocation fails. FROMLIST: binder: protect against two threads freeing buffer FROMLIST: binder: remove dead code in binder_get_ref_for_node FROMLIST: binder: don't modify thread->looper from other threads FROMLIST: binder: avoid race conditions when enqueuing txn FROMLIST: binder: refactor queue management in binder_thread_read FROMLIST: binder: add log information for binder transaction failures FROMLIST: binder: make binder_last_id an atomic FROMLIST: binder: change binder_stats to atomics FROMLIST: binder: add protection for non-perf cases FROMLIST: binder: remove binder_debug_no_lock mechanism FROMLIST: binder: move binder_alloc to separate file FROMLIST: binder: separate out binder_alloc functions FROMLIST: binder: remove unneeded cleanup code FROMLIST: binder: separate binder allocator structure from binder proc FROMLIST: binder: Use wake up hint for synchronous transactions. Revert "android: binder: move global binder state into context struct." sched: walt: fix window misalignment when HZ=300 ANDROID: android-base.cfg: remove CONFIG_CGROUP_DEBUG ANDROID: sdcardfs: use mount_nodev and fix a issue in sdcardfs_kill_sb Conflicts: drivers/android/binder.c drivers/net/wireless/ath/ath10k/pci.c Change-Id: Ic6f82c2ec9929733a16a03bb3b745187e002f4f6 Signed-off-by: Blagovest Kolenichev <bkolenichev@codeaurora.org>
347 lines
8.6 KiB
C
347 lines
8.6 KiB
C
/*
|
|
* This file is subject to the terms and conditions of the GNU General Public
|
|
* License. See the file "COPYING" in the main directory of this archive
|
|
* for more details.
|
|
*
|
|
*
|
|
* Copyright (C) 1995, 1996, 1997, 1998 by Ralf Baechle
|
|
* Copyright 1999 SuSE GmbH (Philipp Rumpf, prumpf@tux.org)
|
|
* Copyright 1999 Hewlett Packard Co.
|
|
*
|
|
*/
|
|
|
|
#include <linux/mm.h>
|
|
#include <linux/ptrace.h>
|
|
#include <linux/sched.h>
|
|
#include <linux/interrupt.h>
|
|
#include <linux/module.h>
|
|
#include <linux/uaccess.h>
|
|
|
|
#include <asm/traps.h>
|
|
|
|
/* Various important other fields */
|
|
#define bit22set(x) (x & 0x00000200)
|
|
#define bits23_25set(x) (x & 0x000001c0)
|
|
#define isGraphicsFlushRead(x) ((x & 0xfc003fdf) == 0x04001a80)
|
|
/* extended opcode is 0x6a */
|
|
|
|
#define BITSSET 0x1c0 /* for identifying LDCW */
|
|
|
|
|
|
DEFINE_PER_CPU(struct exception_data, exception_data);
|
|
|
|
int show_unhandled_signals = 1;
|
|
|
|
/*
|
|
* parisc_acctyp(unsigned int inst) --
|
|
* Given a PA-RISC memory access instruction, determine if the
|
|
* the instruction would perform a memory read or memory write
|
|
* operation.
|
|
*
|
|
* This function assumes that the given instruction is a memory access
|
|
* instruction (i.e. you should really only call it if you know that
|
|
* the instruction has generated some sort of a memory access fault).
|
|
*
|
|
* Returns:
|
|
* VM_READ if read operation
|
|
* VM_WRITE if write operation
|
|
* VM_EXEC if execute operation
|
|
*/
|
|
static unsigned long
|
|
parisc_acctyp(unsigned long code, unsigned int inst)
|
|
{
|
|
if (code == 6 || code == 16)
|
|
return VM_EXEC;
|
|
|
|
switch (inst & 0xf0000000) {
|
|
case 0x40000000: /* load */
|
|
case 0x50000000: /* new load */
|
|
return VM_READ;
|
|
|
|
case 0x60000000: /* store */
|
|
case 0x70000000: /* new store */
|
|
return VM_WRITE;
|
|
|
|
case 0x20000000: /* coproc */
|
|
case 0x30000000: /* coproc2 */
|
|
if (bit22set(inst))
|
|
return VM_WRITE;
|
|
|
|
case 0x0: /* indexed/memory management */
|
|
if (bit22set(inst)) {
|
|
/*
|
|
* Check for the 'Graphics Flush Read' instruction.
|
|
* It resembles an FDC instruction, except for bits
|
|
* 20 and 21. Any combination other than zero will
|
|
* utilize the block mover functionality on some
|
|
* older PA-RISC platforms. The case where a block
|
|
* move is performed from VM to graphics IO space
|
|
* should be treated as a READ.
|
|
*
|
|
* The significance of bits 20,21 in the FDC
|
|
* instruction is:
|
|
*
|
|
* 00 Flush data cache (normal instruction behavior)
|
|
* 01 Graphics flush write (IO space -> VM)
|
|
* 10 Graphics flush read (VM -> IO space)
|
|
* 11 Graphics flush read/write (VM <-> IO space)
|
|
*/
|
|
if (isGraphicsFlushRead(inst))
|
|
return VM_READ;
|
|
return VM_WRITE;
|
|
} else {
|
|
/*
|
|
* Check for LDCWX and LDCWS (semaphore instructions).
|
|
* If bits 23 through 25 are all 1's it is one of
|
|
* the above two instructions and is a write.
|
|
*
|
|
* Note: With the limited bits we are looking at,
|
|
* this will also catch PROBEW and PROBEWI. However,
|
|
* these should never get in here because they don't
|
|
* generate exceptions of the type:
|
|
* Data TLB miss fault/data page fault
|
|
* Data memory protection trap
|
|
*/
|
|
if (bits23_25set(inst) == BITSSET)
|
|
return VM_WRITE;
|
|
}
|
|
return VM_READ; /* Default */
|
|
}
|
|
return VM_READ; /* Default */
|
|
}
|
|
|
|
#undef bit22set
|
|
#undef bits23_25set
|
|
#undef isGraphicsFlushRead
|
|
#undef BITSSET
|
|
|
|
|
|
#if 0
|
|
/* This is the treewalk to find a vma which is the highest that has
|
|
* a start < addr. We're using find_vma_prev instead right now, but
|
|
* we might want to use this at some point in the future. Probably
|
|
* not, but I want it committed to CVS so I don't lose it :-)
|
|
*/
|
|
while (tree != vm_avl_empty) {
|
|
if (tree->vm_start > addr) {
|
|
tree = tree->vm_avl_left;
|
|
} else {
|
|
prev = tree;
|
|
if (prev->vm_next == NULL)
|
|
break;
|
|
if (prev->vm_next->vm_start > addr)
|
|
break;
|
|
tree = tree->vm_avl_right;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
int fixup_exception(struct pt_regs *regs)
|
|
{
|
|
const struct exception_table_entry *fix;
|
|
|
|
fix = search_exception_tables(regs->iaoq[0]);
|
|
if (fix) {
|
|
struct exception_data *d;
|
|
d = this_cpu_ptr(&exception_data);
|
|
d->fault_ip = regs->iaoq[0];
|
|
d->fault_gp = regs->gr[27];
|
|
d->fault_space = regs->isr;
|
|
d->fault_addr = regs->ior;
|
|
|
|
regs->iaoq[0] = (unsigned long)&fix->fixup + fix->fixup;
|
|
regs->iaoq[0] &= ~3;
|
|
/*
|
|
* NOTE: In some cases the faulting instruction
|
|
* may be in the delay slot of a branch. We
|
|
* don't want to take the branch, so we don't
|
|
* increment iaoq[1], instead we set it to be
|
|
* iaoq[0]+4, and clear the B bit in the PSW
|
|
*/
|
|
regs->iaoq[1] = regs->iaoq[0] + 4;
|
|
regs->gr[0] &= ~PSW_B; /* IPSW in gr[0] */
|
|
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* Print out info about fatal segfaults, if the show_unhandled_signals
|
|
* sysctl is set:
|
|
*/
|
|
static inline void
|
|
show_signal_msg(struct pt_regs *regs, unsigned long code,
|
|
unsigned long address, struct task_struct *tsk,
|
|
struct vm_area_struct *vma)
|
|
{
|
|
if (!unhandled_signal(tsk, SIGSEGV))
|
|
return;
|
|
|
|
if (!printk_ratelimit())
|
|
return;
|
|
|
|
pr_warn("\n");
|
|
pr_warn("do_page_fault() command='%s' type=%lu address=0x%08lx",
|
|
tsk->comm, code, address);
|
|
print_vma_addr(KERN_CONT " in ", regs->iaoq[0]);
|
|
if (vma)
|
|
pr_warn(" vm_start = 0x%08lx, vm_end = 0x%08lx\n",
|
|
vma->vm_start, vma->vm_end);
|
|
|
|
show_regs(regs);
|
|
}
|
|
|
|
void do_page_fault(struct pt_regs *regs, unsigned long code,
|
|
unsigned long address)
|
|
{
|
|
struct vm_area_struct *vma, *prev_vma;
|
|
struct task_struct *tsk;
|
|
struct mm_struct *mm;
|
|
unsigned long acc_type;
|
|
int fault;
|
|
unsigned int flags;
|
|
|
|
if (faulthandler_disabled())
|
|
goto no_context;
|
|
|
|
tsk = current;
|
|
mm = tsk->mm;
|
|
if (!mm)
|
|
goto no_context;
|
|
|
|
flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
|
|
if (user_mode(regs))
|
|
flags |= FAULT_FLAG_USER;
|
|
|
|
acc_type = parisc_acctyp(code, regs->iir);
|
|
if (acc_type & VM_WRITE)
|
|
flags |= FAULT_FLAG_WRITE;
|
|
retry:
|
|
down_read(&mm->mmap_sem);
|
|
vma = find_vma_prev(mm, address, &prev_vma);
|
|
if (!vma || address < vma->vm_start)
|
|
goto check_expansion;
|
|
/*
|
|
* Ok, we have a good vm_area for this memory access. We still need to
|
|
* check the access permissions.
|
|
*/
|
|
|
|
good_area:
|
|
|
|
if ((vma->vm_flags & acc_type) != acc_type)
|
|
goto bad_area;
|
|
|
|
/*
|
|
* If for any reason at all we couldn't handle the fault, make
|
|
* sure we exit gracefully rather than endlessly redo the
|
|
* fault.
|
|
*/
|
|
|
|
fault = handle_mm_fault(mm, vma, address, flags);
|
|
|
|
if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current))
|
|
return;
|
|
|
|
if (unlikely(fault & VM_FAULT_ERROR)) {
|
|
/*
|
|
* We hit a shared mapping outside of the file, or some
|
|
* other thing happened to us that made us unable to
|
|
* handle the page fault gracefully.
|
|
*/
|
|
if (fault & VM_FAULT_OOM)
|
|
goto out_of_memory;
|
|
else if (fault & VM_FAULT_SIGSEGV)
|
|
goto bad_area;
|
|
else if (fault & VM_FAULT_SIGBUS)
|
|
goto bad_area;
|
|
BUG();
|
|
}
|
|
if (flags & FAULT_FLAG_ALLOW_RETRY) {
|
|
if (fault & VM_FAULT_MAJOR)
|
|
current->maj_flt++;
|
|
else
|
|
current->min_flt++;
|
|
if (fault & VM_FAULT_RETRY) {
|
|
flags &= ~FAULT_FLAG_ALLOW_RETRY;
|
|
|
|
/*
|
|
* No need to up_read(&mm->mmap_sem) as we would
|
|
* have already released it in __lock_page_or_retry
|
|
* in mm/filemap.c.
|
|
*/
|
|
|
|
goto retry;
|
|
}
|
|
}
|
|
up_read(&mm->mmap_sem);
|
|
return;
|
|
|
|
check_expansion:
|
|
vma = prev_vma;
|
|
if (vma && (expand_stack(vma, address) == 0))
|
|
goto good_area;
|
|
|
|
/*
|
|
* Something tried to access memory that isn't in our memory map..
|
|
*/
|
|
bad_area:
|
|
up_read(&mm->mmap_sem);
|
|
|
|
if (user_mode(regs)) {
|
|
struct siginfo si;
|
|
|
|
show_signal_msg(regs, code, address, tsk, vma);
|
|
|
|
switch (code) {
|
|
case 15: /* Data TLB miss fault/Data page fault */
|
|
/* send SIGSEGV when outside of vma */
|
|
if (!vma ||
|
|
address < vma->vm_start || address >= vma->vm_end) {
|
|
si.si_signo = SIGSEGV;
|
|
si.si_code = SEGV_MAPERR;
|
|
break;
|
|
}
|
|
|
|
/* send SIGSEGV for wrong permissions */
|
|
if ((vma->vm_flags & acc_type) != acc_type) {
|
|
si.si_signo = SIGSEGV;
|
|
si.si_code = SEGV_ACCERR;
|
|
break;
|
|
}
|
|
|
|
/* probably address is outside of mapped file */
|
|
/* fall through */
|
|
case 17: /* NA data TLB miss / page fault */
|
|
case 18: /* Unaligned access - PCXS only */
|
|
si.si_signo = SIGBUS;
|
|
si.si_code = (code == 18) ? BUS_ADRALN : BUS_ADRERR;
|
|
break;
|
|
case 16: /* Non-access instruction TLB miss fault */
|
|
case 26: /* PCXL: Data memory access rights trap */
|
|
default:
|
|
si.si_signo = SIGSEGV;
|
|
si.si_code = (code == 26) ? SEGV_ACCERR : SEGV_MAPERR;
|
|
break;
|
|
}
|
|
si.si_errno = 0;
|
|
si.si_addr = (void __user *) address;
|
|
force_sig_info(si.si_signo, &si, current);
|
|
return;
|
|
}
|
|
|
|
no_context:
|
|
|
|
if (!user_mode(regs) && fixup_exception(regs)) {
|
|
return;
|
|
}
|
|
|
|
parisc_terminate("Bad Address (null pointer deref?)", regs, code, address);
|
|
|
|
out_of_memory:
|
|
up_read(&mm->mmap_sem);
|
|
if (!user_mode(regs))
|
|
goto no_context;
|
|
pagefault_out_of_memory();
|
|
}
|