This is the 4.4.168 stable release
-----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEZH8oZUiU471FcZm+ONu9yGCSaT4FAlwYDToACgkQONu9yGCS aT79dhAAhjCCEjMpcWGXExuCryWYUKJGV6rI1Hk3o5+Jr6tu/dWnhCLQrrSLgyCR qbhBPW/MLpedxnoeLD0Kzo5XDvziB7dNrVgaure923N/Urst4JTH+hMBX6HHUPWY vGReKg0a6HNaKsitlTPQaZTNE0uJJ1oCO7mEWYkU571zWaiT8/MT/wo42Ruiab1/ zw4YVlb74fdZRuazAmTIdszC8MxCoqBJQuzl0UvbKcPtosPdZLywi4Rw0LQNgdcf nO/FZE9GPYPw2G/yV3XMp3qs+vVtJpZQrwrF2xHHDfe7Hosk5bB9iEcl6iSbYvyw Eir1nD8YTD438sAcLgV3EDRguhQbgBcd23YHFPuyfJrZErZnshfp63iLLYIdZ1Mn OP47nilY1/FnvxIzJFn0aHlg+9Ix9RepmPWL31xqHb6a0HuYJRJY6ciLln9v+Mld jG4TtuxlGdkQzbkiSnNVbMVcsWMwX4OHmwQLteZvlzdj5bro5ko+8SVaio5TWBRB bA9Bw82mKw3BLvlhmgM0Rg0pwJpgXl88r6o5iq2zALVPCUOdFOedoHdCiPpwO1Hl eFUY2PYx1YZk8qZXX6eh0LhoHM1Lqyd7qSjDbekKGf1oBVUlLe3umhSGivp3j2is ei1usTw3uM3n6thSeIKPn565gyr/CwXbspo3Ym/YG+719a+XwNU= =2xi1 -----END PGP SIGNATURE----- Merge 4.4.168 into android-4.4 Changes in 4.4.168 ipv6: Check available headroom in ip6_xmit() even without options net: 8139cp: fix a BUG triggered by changing mtu with network traffic net: phy: don't allow __set_phy_supported to add unsupported modes net: Prevent invalid access to skb->prev in __qdisc_drop_all rtnetlink: ndo_dflt_fdb_dump() only work for ARPHRD_ETHER devices tcp: fix NULL ref in tail loss probe tun: forbid iface creation with rtnl ops neighbour: Avoid writing before skb->head in neigh_hh_output() ARM: OMAP2+: prm44xx: Fix section annotation on omap44xx_prm_enable_io_wakeup ARM: OMAP1: ams-delta: Fix possible use of uninitialized field sysv: return 'err' instead of 0 in __sysv_write_inode s390/cpum_cf: Reject request for sampling in event initialization hwmon: (ina2xx) Fix current value calculation ASoC: dapm: Recalculate audio map forcely when card instantiated hwmon: (w83795) temp4_type has writable permission Btrfs: send, fix infinite loop due to directory rename dependencies ASoC: omap-mcpdm: Add pm_qos handling to avoid under/overruns with CPU_IDLE ASoC: omap-dmic: Add pm_qos handling to avoid overruns with CPU_IDLE exportfs: do not read dentry after free bpf: fix check of allowed specifiers in bpf_trace_printk USB: omap_udc: use devm_request_irq() USB: omap_udc: fix crashes on probe error and module removal USB: omap_udc: fix omap_udc_start() on 15xx machines USB: omap_udc: fix USB gadget functionality on Palm Tungsten E KVM: x86: fix empty-body warnings net: thunderx: fix NULL pointer dereference in nic_remove ixgbe: recognize 1000BaseLX SFP modules as 1Gbps net: hisilicon: remove unexpected free_netdev drm/ast: fixed reading monitor EDID not stable issue xen: xlate_mmu: add missing header to fix 'W=1' warning fscache: fix race between enablement and dropping of object fscache, cachefiles: remove redundant variable 'cache' ocfs2: fix deadlock caused by ocfs2_defrag_extent() hfs: do not free node before using hfsplus: do not free node before using debugobjects: avoid recursive calls with kmemleak ocfs2: fix potential use after free pstore: Convert console write to use ->write_buf ALSA: pcm: remove SNDRV_PCM_IOCTL1_INFO internal command KVM: nVMX: fix msr bitmaps to prevent L2 from accessing L0 x2APIC KVM: nVMX: mark vmcs12 pages dirty on L2 exit KVM: nVMX: Eliminate vmcs02 pool KVM: VMX: introduce alloc_loaded_vmcs KVM: VMX: make MSR bitmaps per-VCPU KVM/x86: Add IBPB support KVM/VMX: Emulate MSR_IA32_ARCH_CAPABILITIES KVM/VMX: Allow direct access to MSR_IA32_SPEC_CTRL KVM/SVM: Allow direct access to MSR_IA32_SPEC_CTRL KVM/x86: Remove indirect MSR op calls from SPEC_CTRL x86: reorganize SMAP handling in user space accesses x86: fix SMAP in 32-bit environments x86: Introduce __uaccess_begin_nospec() and uaccess_try_nospec x86/usercopy: Replace open coded stac/clac with __uaccess_{begin, end} x86/uaccess: Use __uaccess_begin_nospec() and uaccess_try_nospec x86/bugs, KVM: Support the combination of guest and host IBRS x86/KVM/VMX: Expose SPEC_CTRL Bit(2) to the guest KVM: SVM: Move spec control call after restore of GS x86/bugs, KVM: Extend speculation control for VIRT_SPEC_CTRL x86/speculation: Use synthetic bits for IBRS/IBPB/STIBP KVM: SVM: Implement VIRT_SPEC_CTRL support for SSBD bpf: support 8-byte metafield access bpf/verifier: Add spi variable to check_stack_write() bpf/verifier: Pass instruction index to check_mem_access() and check_xadd() bpf: Prevent memory disambiguation attack wil6210: missing length check in wmi_set_ie posix-timers: Sanitize overrun handling mm/hugetlb.c: don't call region_abort if region_chg fails hugetlbfs: fix offset overflow in hugetlbfs mmap hugetlbfs: check for pgoff value overflow hugetlbfs: fix bug in pgoff overflow checking swiotlb: clean up reporting sr: pass down correctly sized SCSI sense buffer mm: remove write/force parameters from __get_user_pages_locked() mm: remove write/force parameters from __get_user_pages_unlocked() mm/nommu.c: Switch __get_user_pages_unlocked() to use __get_user_pages() mm: replace get_user_pages_unlocked() write/force parameters with gup_flags mm: replace get_user_pages_locked() write/force parameters with gup_flags mm: replace get_vaddr_frames() write/force parameters with gup_flags mm: replace get_user_pages() write/force parameters with gup_flags mm: replace __access_remote_vm() write parameter with gup_flags mm: replace access_remote_vm() write parameter with gup_flags proc: don't use FOLL_FORCE for reading cmdline and environment proc: do not access cmdline nor environ from file-backed areas media: dvb-frontends: fix i2c access helpers for KASAN matroxfb: fix size of memcpy staging: speakup: Replace strncpy with memcpy rocker: fix rocker_tlv_put_* functions for KASAN selftests: Move networking/timestamping from Documentation Linux 4.4.168 Change-Id: I71a633f645fada4b473abcff660a9ada3103592b Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
commit
66a37fc02d
127 changed files with 1334 additions and 771 deletions
|
@ -1,4 +1,3 @@
|
|||
subdir-y := accounting auxdisplay blackfin connector \
|
||||
filesystems filesystems ia64 laptops misc-devices \
|
||||
networking pcmcia prctl ptp spi timers vDSO video4linux \
|
||||
watchdog
|
||||
pcmcia prctl ptp spi timers vDSO video4linux watchdog
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
subdir-y := timestamping
|
|
@ -1,14 +0,0 @@
|
|||
# To compile, from the source root
|
||||
#
|
||||
# make headers_install
|
||||
# make M=documentation
|
||||
|
||||
# List of programs to build
|
||||
hostprogs-y := hwtstamp_config timestamping txtimestamp
|
||||
|
||||
# Tell kbuild to always build the programs
|
||||
always := $(hostprogs-y)
|
||||
|
||||
HOSTCFLAGS_timestamping.o += -I$(objtree)/usr/include
|
||||
HOSTCFLAGS_txtimestamp.o += -I$(objtree)/usr/include
|
||||
HOSTCFLAGS_hwtstamp_config.o += -I$(objtree)/usr/include
|
2
Makefile
2
Makefile
|
@ -1,6 +1,6 @@
|
|||
VERSION = 4
|
||||
PATCHLEVEL = 4
|
||||
SUBLEVEL = 167
|
||||
SUBLEVEL = 168
|
||||
EXTRAVERSION =
|
||||
NAME = Blurry Fish Butt
|
||||
|
||||
|
|
|
@ -511,6 +511,9 @@ static void modem_pm(struct uart_port *port, unsigned int state, unsigned old)
|
|||
{
|
||||
struct modem_private_data *priv = port->private_data;
|
||||
|
||||
if (!priv)
|
||||
return;
|
||||
|
||||
if (IS_ERR(priv->regulator))
|
||||
return;
|
||||
|
||||
|
|
|
@ -344,7 +344,7 @@ static void omap44xx_prm_reconfigure_io_chain(void)
|
|||
* to occur, WAKEUPENABLE bits must be set in the pad mux registers, and
|
||||
* omap44xx_prm_reconfigure_io_chain() must be called. No return value.
|
||||
*/
|
||||
static void __init omap44xx_prm_enable_io_wakeup(void)
|
||||
static void omap44xx_prm_enable_io_wakeup(void)
|
||||
{
|
||||
s32 inst = omap4_prmst_get_prm_dev_inst();
|
||||
|
||||
|
|
|
@ -2724,7 +2724,6 @@ static int cryptocop_ioctl_process(struct inode *inode, struct file *filp, unsig
|
|||
(unsigned long int)(oper.indata + prev_ix),
|
||||
noinpages,
|
||||
0, /* read access only for in data */
|
||||
0, /* no force */
|
||||
inpages,
|
||||
NULL);
|
||||
|
||||
|
@ -2740,8 +2739,7 @@ static int cryptocop_ioctl_process(struct inode *inode, struct file *filp, unsig
|
|||
current->mm,
|
||||
(unsigned long int)oper.cipher_outdata,
|
||||
nooutpages,
|
||||
1, /* write access for out data */
|
||||
0, /* no force */
|
||||
FOLL_WRITE, /* write access for out data */
|
||||
outpages,
|
||||
NULL);
|
||||
up_read(¤t->mm->mmap_sem);
|
||||
|
|
|
@ -143,7 +143,7 @@ store_virtual_to_phys(struct device *dev, struct device_attribute *attr,
|
|||
int ret;
|
||||
|
||||
ret = get_user_pages(current, current->mm, virt_addr,
|
||||
1, VM_READ, 0, NULL, NULL);
|
||||
1, FOLL_WRITE, NULL, NULL);
|
||||
if (ret<=0) {
|
||||
#ifdef ERR_INJ_DEBUG
|
||||
printk("Virtual address %lx is not existing.\n",virt_addr);
|
||||
|
|
|
@ -303,7 +303,7 @@ slow_irqon:
|
|||
|
||||
ret = get_user_pages_unlocked(current, mm, start,
|
||||
(end - start) >> PAGE_SHIFT,
|
||||
write, 0, pages);
|
||||
pages, write ? FOLL_WRITE : 0);
|
||||
|
||||
/* Have to be a bit careful with return values */
|
||||
if (nr > 0) {
|
||||
|
|
|
@ -344,6 +344,8 @@ static int __hw_perf_event_init(struct perf_event *event)
|
|||
break;
|
||||
|
||||
case PERF_TYPE_HARDWARE:
|
||||
if (is_sampling_event(event)) /* No sampling support */
|
||||
return -ENOENT;
|
||||
ev = attr->config;
|
||||
/* Count user space (problem-state) only */
|
||||
if (!attr->exclude_user && attr->exclude_kernel) {
|
||||
|
|
|
@ -242,7 +242,7 @@ int get_user_pages_fast(unsigned long start, int nr_pages, int write,
|
|||
start += nr << PAGE_SHIFT;
|
||||
pages += nr;
|
||||
ret = get_user_pages_unlocked(current, mm, start,
|
||||
nr_pages - nr, write, 0, pages);
|
||||
nr_pages - nr, pages, write ? FOLL_WRITE : 0);
|
||||
/* Have to be a bit careful with return values */
|
||||
if (nr > 0)
|
||||
ret = (ret < 0) ? nr : ret + nr;
|
||||
|
|
|
@ -258,7 +258,8 @@ slow_irqon:
|
|||
pages += nr;
|
||||
|
||||
ret = get_user_pages_unlocked(current, mm, start,
|
||||
(end - start) >> PAGE_SHIFT, write, 0, pages);
|
||||
(end - start) >> PAGE_SHIFT, pages,
|
||||
write ? FOLL_WRITE : 0);
|
||||
|
||||
/* Have to be a bit careful with return values */
|
||||
if (nr > 0) {
|
||||
|
|
|
@ -250,7 +250,8 @@ slow:
|
|||
pages += nr;
|
||||
|
||||
ret = get_user_pages_unlocked(current, mm, start,
|
||||
(end - start) >> PAGE_SHIFT, write, 0, pages);
|
||||
(end - start) >> PAGE_SHIFT, pages,
|
||||
write ? FOLL_WRITE : 0);
|
||||
|
||||
/* Have to be a bit careful with return values */
|
||||
if (nr > 0) {
|
||||
|
|
|
@ -765,7 +765,7 @@ struct kvm_x86_ops {
|
|||
int (*hardware_setup)(void); /* __init */
|
||||
void (*hardware_unsetup)(void); /* __exit */
|
||||
bool (*cpu_has_accelerated_tpr)(void);
|
||||
bool (*cpu_has_high_real_mode_segbase)(void);
|
||||
bool (*has_emulated_msr)(int index);
|
||||
void (*cpuid_update)(struct kvm_vcpu *vcpu);
|
||||
|
||||
/* Create, but do not attach this VCPU */
|
||||
|
|
|
@ -151,6 +151,11 @@ extern int __get_user_bad(void);
|
|||
|
||||
#define __uaccess_begin() stac()
|
||||
#define __uaccess_end() clac()
|
||||
#define __uaccess_begin_nospec() \
|
||||
({ \
|
||||
stac(); \
|
||||
barrier_nospec(); \
|
||||
})
|
||||
|
||||
/*
|
||||
* This is a type: either unsigned long, if the argument fits into
|
||||
|
@ -436,7 +441,7 @@ do { \
|
|||
({ \
|
||||
int __gu_err; \
|
||||
unsigned long __gu_val; \
|
||||
__uaccess_begin(); \
|
||||
__uaccess_begin_nospec(); \
|
||||
__get_user_size(__gu_val, (ptr), (size), __gu_err, -EFAULT); \
|
||||
__uaccess_end(); \
|
||||
(x) = (__force __typeof__(*(ptr)))__gu_val; \
|
||||
|
@ -478,6 +483,10 @@ struct __large_struct { unsigned long buf[100]; };
|
|||
__uaccess_begin(); \
|
||||
barrier();
|
||||
|
||||
#define uaccess_try_nospec do { \
|
||||
current_thread_info()->uaccess_err = 0; \
|
||||
__uaccess_begin_nospec(); \
|
||||
|
||||
#define uaccess_catch(err) \
|
||||
__uaccess_end(); \
|
||||
(err) |= (current_thread_info()->uaccess_err ? -EFAULT : 0); \
|
||||
|
@ -542,7 +551,7 @@ struct __large_struct { unsigned long buf[100]; };
|
|||
* get_user_ex(...);
|
||||
* } get_user_catch(err)
|
||||
*/
|
||||
#define get_user_try uaccess_try
|
||||
#define get_user_try uaccess_try_nospec
|
||||
#define get_user_catch(err) uaccess_catch(err)
|
||||
|
||||
#define get_user_ex(x, ptr) do { \
|
||||
|
@ -577,7 +586,7 @@ extern void __cmpxchg_wrong_size(void)
|
|||
__typeof__(ptr) __uval = (uval); \
|
||||
__typeof__(*(ptr)) __old = (old); \
|
||||
__typeof__(*(ptr)) __new = (new); \
|
||||
__uaccess_begin(); \
|
||||
__uaccess_begin_nospec(); \
|
||||
switch (size) { \
|
||||
case 1: \
|
||||
{ \
|
||||
|
|
|
@ -49,25 +49,25 @@ __copy_to_user_inatomic(void __user *to, const void *from, unsigned long n)
|
|||
|
||||
switch (n) {
|
||||
case 1:
|
||||
__uaccess_begin();
|
||||
__uaccess_begin_nospec();
|
||||
__put_user_size(*(u8 *)from, (u8 __user *)to,
|
||||
1, ret, 1);
|
||||
__uaccess_end();
|
||||
return ret;
|
||||
case 2:
|
||||
__uaccess_begin();
|
||||
__uaccess_begin_nospec();
|
||||
__put_user_size(*(u16 *)from, (u16 __user *)to,
|
||||
2, ret, 2);
|
||||
__uaccess_end();
|
||||
return ret;
|
||||
case 4:
|
||||
__uaccess_begin();
|
||||
__uaccess_begin_nospec();
|
||||
__put_user_size(*(u32 *)from, (u32 __user *)to,
|
||||
4, ret, 4);
|
||||
__uaccess_end();
|
||||
return ret;
|
||||
case 8:
|
||||
__uaccess_begin();
|
||||
__uaccess_begin_nospec();
|
||||
__put_user_size(*(u64 *)from, (u64 __user *)to,
|
||||
8, ret, 8);
|
||||
__uaccess_end();
|
||||
|
@ -112,17 +112,17 @@ __copy_from_user_inatomic(void *to, const void __user *from, unsigned long n)
|
|||
|
||||
switch (n) {
|
||||
case 1:
|
||||
__uaccess_begin();
|
||||
__uaccess_begin_nospec();
|
||||
__get_user_size(*(u8 *)to, from, 1, ret, 1);
|
||||
__uaccess_end();
|
||||
return ret;
|
||||
case 2:
|
||||
__uaccess_begin();
|
||||
__uaccess_begin_nospec();
|
||||
__get_user_size(*(u16 *)to, from, 2, ret, 2);
|
||||
__uaccess_end();
|
||||
return ret;
|
||||
case 4:
|
||||
__uaccess_begin();
|
||||
__uaccess_begin_nospec();
|
||||
__get_user_size(*(u32 *)to, from, 4, ret, 4);
|
||||
__uaccess_end();
|
||||
return ret;
|
||||
|
@ -164,17 +164,17 @@ __copy_from_user(void *to, const void __user *from, unsigned long n)
|
|||
|
||||
switch (n) {
|
||||
case 1:
|
||||
__uaccess_begin();
|
||||
__uaccess_begin_nospec();
|
||||
__get_user_size(*(u8 *)to, from, 1, ret, 1);
|
||||
__uaccess_end();
|
||||
return ret;
|
||||
case 2:
|
||||
__uaccess_begin();
|
||||
__uaccess_begin_nospec();
|
||||
__get_user_size(*(u16 *)to, from, 2, ret, 2);
|
||||
__uaccess_end();
|
||||
return ret;
|
||||
case 4:
|
||||
__uaccess_begin();
|
||||
__uaccess_begin_nospec();
|
||||
__get_user_size(*(u32 *)to, from, 4, ret, 4);
|
||||
__uaccess_end();
|
||||
return ret;
|
||||
|
@ -192,17 +192,17 @@ static __always_inline unsigned long __copy_from_user_nocache(void *to,
|
|||
|
||||
switch (n) {
|
||||
case 1:
|
||||
__uaccess_begin();
|
||||
__uaccess_begin_nospec();
|
||||
__get_user_size(*(u8 *)to, from, 1, ret, 1);
|
||||
__uaccess_end();
|
||||
return ret;
|
||||
case 2:
|
||||
__uaccess_begin();
|
||||
__uaccess_begin_nospec();
|
||||
__get_user_size(*(u16 *)to, from, 2, ret, 2);
|
||||
__uaccess_end();
|
||||
return ret;
|
||||
case 4:
|
||||
__uaccess_begin();
|
||||
__uaccess_begin_nospec();
|
||||
__get_user_size(*(u32 *)to, from, 4, ret, 4);
|
||||
__uaccess_end();
|
||||
return ret;
|
||||
|
|
|
@ -58,31 +58,31 @@ int __copy_from_user_nocheck(void *dst, const void __user *src, unsigned size)
|
|||
return copy_user_generic(dst, (__force void *)src, size);
|
||||
switch (size) {
|
||||
case 1:
|
||||
__uaccess_begin();
|
||||
__uaccess_begin_nospec();
|
||||
__get_user_asm(*(u8 *)dst, (u8 __user *)src,
|
||||
ret, "b", "b", "=q", 1);
|
||||
__uaccess_end();
|
||||
return ret;
|
||||
case 2:
|
||||
__uaccess_begin();
|
||||
__uaccess_begin_nospec();
|
||||
__get_user_asm(*(u16 *)dst, (u16 __user *)src,
|
||||
ret, "w", "w", "=r", 2);
|
||||
__uaccess_end();
|
||||
return ret;
|
||||
case 4:
|
||||
__uaccess_begin();
|
||||
__uaccess_begin_nospec();
|
||||
__get_user_asm(*(u32 *)dst, (u32 __user *)src,
|
||||
ret, "l", "k", "=r", 4);
|
||||
__uaccess_end();
|
||||
return ret;
|
||||
case 8:
|
||||
__uaccess_begin();
|
||||
__uaccess_begin_nospec();
|
||||
__get_user_asm(*(u64 *)dst, (u64 __user *)src,
|
||||
ret, "q", "", "=r", 8);
|
||||
__uaccess_end();
|
||||
return ret;
|
||||
case 10:
|
||||
__uaccess_begin();
|
||||
__uaccess_begin_nospec();
|
||||
__get_user_asm(*(u64 *)dst, (u64 __user *)src,
|
||||
ret, "q", "", "=r", 10);
|
||||
if (likely(!ret))
|
||||
|
@ -92,7 +92,7 @@ int __copy_from_user_nocheck(void *dst, const void __user *src, unsigned size)
|
|||
__uaccess_end();
|
||||
return ret;
|
||||
case 16:
|
||||
__uaccess_begin();
|
||||
__uaccess_begin_nospec();
|
||||
__get_user_asm(*(u64 *)dst, (u64 __user *)src,
|
||||
ret, "q", "", "=r", 16);
|
||||
if (likely(!ret))
|
||||
|
@ -192,7 +192,7 @@ int __copy_in_user(void __user *dst, const void __user *src, unsigned size)
|
|||
switch (size) {
|
||||
case 1: {
|
||||
u8 tmp;
|
||||
__uaccess_begin();
|
||||
__uaccess_begin_nospec();
|
||||
__get_user_asm(tmp, (u8 __user *)src,
|
||||
ret, "b", "b", "=q", 1);
|
||||
if (likely(!ret))
|
||||
|
@ -203,7 +203,7 @@ int __copy_in_user(void __user *dst, const void __user *src, unsigned size)
|
|||
}
|
||||
case 2: {
|
||||
u16 tmp;
|
||||
__uaccess_begin();
|
||||
__uaccess_begin_nospec();
|
||||
__get_user_asm(tmp, (u16 __user *)src,
|
||||
ret, "w", "w", "=r", 2);
|
||||
if (likely(!ret))
|
||||
|
@ -215,7 +215,7 @@ int __copy_in_user(void __user *dst, const void __user *src, unsigned size)
|
|||
|
||||
case 4: {
|
||||
u32 tmp;
|
||||
__uaccess_begin();
|
||||
__uaccess_begin_nospec();
|
||||
__get_user_asm(tmp, (u32 __user *)src,
|
||||
ret, "l", "k", "=r", 4);
|
||||
if (likely(!ret))
|
||||
|
@ -226,7 +226,7 @@ int __copy_in_user(void __user *dst, const void __user *src, unsigned size)
|
|||
}
|
||||
case 8: {
|
||||
u64 tmp;
|
||||
__uaccess_begin();
|
||||
__uaccess_begin_nospec();
|
||||
__get_user_asm(tmp, (u64 __user *)src,
|
||||
ret, "q", "", "=r", 8);
|
||||
if (likely(!ret))
|
||||
|
|
|
@ -693,7 +693,8 @@ static void init_speculation_control(struct cpuinfo_x86 *c)
|
|||
if (cpu_has(c, X86_FEATURE_INTEL_STIBP))
|
||||
set_cpu_cap(c, X86_FEATURE_STIBP);
|
||||
|
||||
if (cpu_has(c, X86_FEATURE_SPEC_CTRL_SSBD))
|
||||
if (cpu_has(c, X86_FEATURE_SPEC_CTRL_SSBD) ||
|
||||
cpu_has(c, X86_FEATURE_VIRT_SSBD))
|
||||
set_cpu_cap(c, X86_FEATURE_SSBD);
|
||||
|
||||
if (cpu_has(c, X86_FEATURE_AMD_IBRS)) {
|
||||
|
|
|
@ -341,6 +341,10 @@ static inline int __do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
|
|||
F(3DNOWPREFETCH) | F(OSVW) | 0 /* IBS */ | F(XOP) |
|
||||
0 /* SKINIT, WDT, LWP */ | F(FMA4) | F(TBM);
|
||||
|
||||
/* cpuid 0x80000008.ebx */
|
||||
const u32 kvm_cpuid_8000_0008_ebx_x86_features =
|
||||
F(AMD_IBPB) | F(AMD_IBRS) | F(VIRT_SSBD);
|
||||
|
||||
/* cpuid 0xC0000001.edx */
|
||||
const u32 kvm_supported_word5_x86_features =
|
||||
F(XSTORE) | F(XSTORE_EN) | F(XCRYPT) | F(XCRYPT_EN) |
|
||||
|
@ -358,6 +362,10 @@ static inline int __do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
|
|||
const u32 kvm_supported_word10_x86_features =
|
||||
F(XSAVEOPT) | F(XSAVEC) | F(XGETBV1) | f_xsaves;
|
||||
|
||||
/* cpuid 7.0.edx*/
|
||||
const u32 kvm_cpuid_7_0_edx_x86_features =
|
||||
F(SPEC_CTRL) | F(SPEC_CTRL_SSBD) | F(ARCH_CAPABILITIES);
|
||||
|
||||
/* all calls to cpuid_count() should be made on the same cpu */
|
||||
get_cpu();
|
||||
|
||||
|
@ -435,11 +443,14 @@ static inline int __do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
|
|||
cpuid_mask(&entry->ebx, 9);
|
||||
// TSC_ADJUST is emulated
|
||||
entry->ebx |= F(TSC_ADJUST);
|
||||
} else
|
||||
entry->edx &= kvm_cpuid_7_0_edx_x86_features;
|
||||
cpuid_mask(&entry->edx, CPUID_7_EDX);
|
||||
} else {
|
||||
entry->ebx = 0;
|
||||
entry->edx = 0;
|
||||
}
|
||||
entry->eax = 0;
|
||||
entry->ecx = 0;
|
||||
entry->edx = 0;
|
||||
break;
|
||||
}
|
||||
case 9:
|
||||
|
@ -583,7 +594,21 @@ static inline int __do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
|
|||
if (!g_phys_as)
|
||||
g_phys_as = phys_as;
|
||||
entry->eax = g_phys_as | (virt_as << 8);
|
||||
entry->ebx = entry->edx = 0;
|
||||
entry->edx = 0;
|
||||
/*
|
||||
* IBRS, IBPB and VIRT_SSBD aren't necessarily present in
|
||||
* hardware cpuid
|
||||
*/
|
||||
if (boot_cpu_has(X86_FEATURE_AMD_IBPB))
|
||||
entry->ebx |= F(AMD_IBPB);
|
||||
if (boot_cpu_has(X86_FEATURE_AMD_IBRS))
|
||||
entry->ebx |= F(AMD_IBRS);
|
||||
if (boot_cpu_has(X86_FEATURE_VIRT_SSBD))
|
||||
entry->ebx |= F(VIRT_SSBD);
|
||||
entry->ebx &= kvm_cpuid_8000_0008_ebx_x86_features;
|
||||
cpuid_mask(&entry->ebx, CPUID_8000_0008_EBX);
|
||||
if (boot_cpu_has(X86_FEATURE_LS_CFG_SSBD))
|
||||
entry->ebx |= F(VIRT_SSBD);
|
||||
break;
|
||||
}
|
||||
case 0x80000019:
|
||||
|
|
|
@ -159,6 +159,46 @@ static inline bool guest_cpuid_has_rdtscp(struct kvm_vcpu *vcpu)
|
|||
return best && (best->edx & bit(X86_FEATURE_RDTSCP));
|
||||
}
|
||||
|
||||
static inline bool guest_cpuid_has_ibpb(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
struct kvm_cpuid_entry2 *best;
|
||||
|
||||
best = kvm_find_cpuid_entry(vcpu, 0x80000008, 0);
|
||||
if (best && (best->ebx & bit(X86_FEATURE_AMD_IBPB)))
|
||||
return true;
|
||||
best = kvm_find_cpuid_entry(vcpu, 7, 0);
|
||||
return best && (best->edx & bit(X86_FEATURE_SPEC_CTRL));
|
||||
}
|
||||
|
||||
static inline bool guest_cpuid_has_spec_ctrl(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
struct kvm_cpuid_entry2 *best;
|
||||
|
||||
best = kvm_find_cpuid_entry(vcpu, 0x80000008, 0);
|
||||
if (best && (best->ebx & bit(X86_FEATURE_AMD_IBRS)))
|
||||
return true;
|
||||
best = kvm_find_cpuid_entry(vcpu, 7, 0);
|
||||
return best && (best->edx & (bit(X86_FEATURE_SPEC_CTRL) | bit(X86_FEATURE_SPEC_CTRL_SSBD)));
|
||||
}
|
||||
|
||||
static inline bool guest_cpuid_has_arch_capabilities(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
struct kvm_cpuid_entry2 *best;
|
||||
|
||||
best = kvm_find_cpuid_entry(vcpu, 7, 0);
|
||||
return best && (best->edx & bit(X86_FEATURE_ARCH_CAPABILITIES));
|
||||
}
|
||||
|
||||
static inline bool guest_cpuid_has_virt_ssbd(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
struct kvm_cpuid_entry2 *best;
|
||||
|
||||
best = kvm_find_cpuid_entry(vcpu, 0x80000008, 0);
|
||||
return best && (best->ebx & bit(X86_FEATURE_VIRT_SSBD));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* NRIPS is provided through cpuidfn 0x8000000a.edx bit 3
|
||||
*/
|
||||
|
|
|
@ -56,7 +56,7 @@
|
|||
#define APIC_BUS_CYCLE_NS 1
|
||||
|
||||
/* #define apic_debug(fmt,arg...) printk(KERN_WARNING fmt,##arg) */
|
||||
#define apic_debug(fmt, arg...)
|
||||
#define apic_debug(fmt, arg...) do {} while (0)
|
||||
|
||||
#define APIC_LVT_NUM 6
|
||||
/* 14 is the version for Xeon and Pentium 8.4.8*/
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include <asm/desc.h>
|
||||
#include <asm/debugreg.h>
|
||||
#include <asm/kvm_para.h>
|
||||
#include <asm/microcode.h>
|
||||
#include <asm/spec-ctrl.h>
|
||||
|
||||
#include <asm/virtext.h>
|
||||
|
@ -147,6 +148,14 @@ struct vcpu_svm {
|
|||
u64 gs_base;
|
||||
} host;
|
||||
|
||||
u64 spec_ctrl;
|
||||
/*
|
||||
* Contains guest-controlled bits of VIRT_SPEC_CTRL, which will be
|
||||
* translated into the appropriate L2_CFG bits on the host to
|
||||
* perform speculative control.
|
||||
*/
|
||||
u64 virt_spec_ctrl;
|
||||
|
||||
u32 *msrpm;
|
||||
|
||||
ulong nmi_iret_rip;
|
||||
|
@ -182,6 +191,8 @@ static const struct svm_direct_access_msrs {
|
|||
{ .index = MSR_CSTAR, .always = true },
|
||||
{ .index = MSR_SYSCALL_MASK, .always = true },
|
||||
#endif
|
||||
{ .index = MSR_IA32_SPEC_CTRL, .always = false },
|
||||
{ .index = MSR_IA32_PRED_CMD, .always = false },
|
||||
{ .index = MSR_IA32_LASTBRANCHFROMIP, .always = false },
|
||||
{ .index = MSR_IA32_LASTBRANCHTOIP, .always = false },
|
||||
{ .index = MSR_IA32_LASTINTFROMIP, .always = false },
|
||||
|
@ -411,6 +422,7 @@ struct svm_cpu_data {
|
|||
struct kvm_ldttss_desc *tss_desc;
|
||||
|
||||
struct page *save_area;
|
||||
struct vmcb *current_vmcb;
|
||||
};
|
||||
|
||||
static DEFINE_PER_CPU(struct svm_cpu_data *, svm_data);
|
||||
|
@ -762,6 +774,25 @@ static bool valid_msr_intercept(u32 index)
|
|||
return false;
|
||||
}
|
||||
|
||||
static bool msr_write_intercepted(struct kvm_vcpu *vcpu, unsigned msr)
|
||||
{
|
||||
u8 bit_write;
|
||||
unsigned long tmp;
|
||||
u32 offset;
|
||||
u32 *msrpm;
|
||||
|
||||
msrpm = is_guest_mode(vcpu) ? to_svm(vcpu)->nested.msrpm:
|
||||
to_svm(vcpu)->msrpm;
|
||||
|
||||
offset = svm_msrpm_offset(msr);
|
||||
bit_write = 2 * (msr & 0x0f) + 1;
|
||||
tmp = msrpm[offset];
|
||||
|
||||
BUG_ON(offset == MSR_INVALID);
|
||||
|
||||
return !!test_bit(bit_write, &tmp);
|
||||
}
|
||||
|
||||
static void set_msr_interception(u32 *msrpm, unsigned msr,
|
||||
int read, int write)
|
||||
{
|
||||
|
@ -1120,6 +1151,9 @@ static void svm_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event)
|
|||
u32 dummy;
|
||||
u32 eax = 1;
|
||||
|
||||
svm->spec_ctrl = 0;
|
||||
svm->virt_spec_ctrl = 0;
|
||||
|
||||
if (!init_event) {
|
||||
svm->vcpu.arch.apic_base = APIC_DEFAULT_PHYS_BASE |
|
||||
MSR_IA32_APICBASE_ENABLE;
|
||||
|
@ -1210,11 +1244,17 @@ static void svm_free_vcpu(struct kvm_vcpu *vcpu)
|
|||
__free_pages(virt_to_page(svm->nested.msrpm), MSRPM_ALLOC_ORDER);
|
||||
kvm_vcpu_uninit(vcpu);
|
||||
kmem_cache_free(kvm_vcpu_cache, svm);
|
||||
/*
|
||||
* The vmcb page can be recycled, causing a false negative in
|
||||
* svm_vcpu_load(). So do a full IBPB now.
|
||||
*/
|
||||
indirect_branch_prediction_barrier();
|
||||
}
|
||||
|
||||
static void svm_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
|
||||
{
|
||||
struct vcpu_svm *svm = to_svm(vcpu);
|
||||
struct svm_cpu_data *sd = per_cpu(svm_data, cpu);
|
||||
int i;
|
||||
|
||||
if (unlikely(cpu != vcpu->cpu)) {
|
||||
|
@ -1239,6 +1279,10 @@ static void svm_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
|
|||
wrmsrl(MSR_AMD64_TSC_RATIO, tsc_ratio);
|
||||
}
|
||||
}
|
||||
if (sd->current_vmcb != svm->vmcb) {
|
||||
sd->current_vmcb = svm->vmcb;
|
||||
indirect_branch_prediction_barrier();
|
||||
}
|
||||
}
|
||||
|
||||
static void svm_vcpu_put(struct kvm_vcpu *vcpu)
|
||||
|
@ -3051,6 +3095,20 @@ static int svm_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
|
|||
case MSR_VM_CR:
|
||||
msr_info->data = svm->nested.vm_cr_msr;
|
||||
break;
|
||||
case MSR_IA32_SPEC_CTRL:
|
||||
if (!msr_info->host_initiated &&
|
||||
!guest_cpuid_has_spec_ctrl(vcpu))
|
||||
return 1;
|
||||
|
||||
msr_info->data = svm->spec_ctrl;
|
||||
break;
|
||||
case MSR_AMD64_VIRT_SPEC_CTRL:
|
||||
if (!msr_info->host_initiated &&
|
||||
!guest_cpuid_has_virt_ssbd(vcpu))
|
||||
return 1;
|
||||
|
||||
msr_info->data = svm->virt_spec_ctrl;
|
||||
break;
|
||||
case MSR_IA32_UCODE_REV:
|
||||
msr_info->data = 0x01000065;
|
||||
break;
|
||||
|
@ -3125,6 +3183,59 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr)
|
|||
case MSR_IA32_TSC:
|
||||
kvm_write_tsc(vcpu, msr);
|
||||
break;
|
||||
case MSR_IA32_SPEC_CTRL:
|
||||
if (!msr->host_initiated &&
|
||||
!guest_cpuid_has_spec_ctrl(vcpu))
|
||||
return 1;
|
||||
|
||||
/* The STIBP bit doesn't fault even if it's not advertised */
|
||||
if (data & ~(SPEC_CTRL_IBRS | SPEC_CTRL_STIBP))
|
||||
return 1;
|
||||
|
||||
svm->spec_ctrl = data;
|
||||
|
||||
if (!data)
|
||||
break;
|
||||
|
||||
/*
|
||||
* For non-nested:
|
||||
* When it's written (to non-zero) for the first time, pass
|
||||
* it through.
|
||||
*
|
||||
* For nested:
|
||||
* The handling of the MSR bitmap for L2 guests is done in
|
||||
* nested_svm_vmrun_msrpm.
|
||||
* We update the L1 MSR bit as well since it will end up
|
||||
* touching the MSR anyway now.
|
||||
*/
|
||||
set_msr_interception(svm->msrpm, MSR_IA32_SPEC_CTRL, 1, 1);
|
||||
break;
|
||||
case MSR_IA32_PRED_CMD:
|
||||
if (!msr->host_initiated &&
|
||||
!guest_cpuid_has_ibpb(vcpu))
|
||||
return 1;
|
||||
|
||||
if (data & ~PRED_CMD_IBPB)
|
||||
return 1;
|
||||
|
||||
if (!data)
|
||||
break;
|
||||
|
||||
wrmsrl(MSR_IA32_PRED_CMD, PRED_CMD_IBPB);
|
||||
if (is_guest_mode(vcpu))
|
||||
break;
|
||||
set_msr_interception(svm->msrpm, MSR_IA32_PRED_CMD, 0, 1);
|
||||
break;
|
||||
case MSR_AMD64_VIRT_SPEC_CTRL:
|
||||
if (!msr->host_initiated &&
|
||||
!guest_cpuid_has_virt_ssbd(vcpu))
|
||||
return 1;
|
||||
|
||||
if (data & ~SPEC_CTRL_SSBD)
|
||||
return 1;
|
||||
|
||||
svm->virt_spec_ctrl = data;
|
||||
break;
|
||||
case MSR_STAR:
|
||||
svm->vmcb->save.star = data;
|
||||
break;
|
||||
|
@ -3811,6 +3922,14 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu)
|
|||
|
||||
local_irq_enable();
|
||||
|
||||
/*
|
||||
* If this vCPU has touched SPEC_CTRL, restore the guest's value if
|
||||
* it's non-zero. Since vmentry is serialising on affected CPUs, there
|
||||
* is no need to worry about the conditional branch over the wrmsr
|
||||
* being speculatively taken.
|
||||
*/
|
||||
x86_spec_ctrl_set_guest(svm->spec_ctrl, svm->virt_spec_ctrl);
|
||||
|
||||
asm volatile (
|
||||
"push %%" _ASM_BP "; \n\t"
|
||||
"mov %c[rbx](%[svm]), %%" _ASM_BX " \n\t"
|
||||
|
@ -3915,6 +4034,26 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu)
|
|||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* We do not use IBRS in the kernel. If this vCPU has used the
|
||||
* SPEC_CTRL MSR it may have left it on; save the value and
|
||||
* turn it off. This is much more efficient than blindly adding
|
||||
* it to the atomic save/restore list. Especially as the former
|
||||
* (Saving guest MSRs on vmexit) doesn't even exist in KVM.
|
||||
*
|
||||
* For non-nested case:
|
||||
* If the L01 MSR bitmap does not intercept the MSR, then we need to
|
||||
* save it.
|
||||
*
|
||||
* For nested case:
|
||||
* If the L02 MSR bitmap does not intercept the MSR, then we need to
|
||||
* save it.
|
||||
*/
|
||||
if (!msr_write_intercepted(vcpu, MSR_IA32_SPEC_CTRL))
|
||||
svm->spec_ctrl = native_read_msr(MSR_IA32_SPEC_CTRL);
|
||||
|
||||
x86_spec_ctrl_restore_host(svm->spec_ctrl, svm->virt_spec_ctrl);
|
||||
|
||||
reload_tss(vcpu);
|
||||
|
||||
local_irq_disable();
|
||||
|
@ -4015,7 +4154,7 @@ static bool svm_cpu_has_accelerated_tpr(void)
|
|||
return false;
|
||||
}
|
||||
|
||||
static bool svm_has_high_real_mode_segbase(void)
|
||||
static bool svm_has_emulated_msr(int index)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
@ -4299,7 +4438,7 @@ static struct kvm_x86_ops svm_x86_ops = {
|
|||
.hardware_enable = svm_hardware_enable,
|
||||
.hardware_disable = svm_hardware_disable,
|
||||
.cpu_has_accelerated_tpr = svm_cpu_has_accelerated_tpr,
|
||||
.cpu_has_high_real_mode_segbase = svm_has_high_real_mode_segbase,
|
||||
.has_emulated_msr = svm_has_emulated_msr,
|
||||
|
||||
.vcpu_create = svm_create_vcpu,
|
||||
.vcpu_free = svm_free_vcpu,
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -961,6 +961,7 @@ static u32 msrs_to_save[] = {
|
|||
#endif
|
||||
MSR_IA32_TSC, MSR_IA32_CR_PAT, MSR_VM_HSAVE_PA,
|
||||
MSR_IA32_FEATURE_CONTROL, MSR_IA32_BNDCFGS, MSR_TSC_AUX,
|
||||
MSR_IA32_SPEC_CTRL, MSR_IA32_ARCH_CAPABILITIES
|
||||
};
|
||||
|
||||
static unsigned num_msrs_to_save;
|
||||
|
@ -984,6 +985,7 @@ static u32 emulated_msrs[] = {
|
|||
MSR_IA32_MCG_STATUS,
|
||||
MSR_IA32_MCG_CTL,
|
||||
MSR_IA32_SMBASE,
|
||||
MSR_AMD64_VIRT_SPEC_CTRL,
|
||||
};
|
||||
|
||||
static unsigned num_emulated_msrs;
|
||||
|
@ -2583,7 +2585,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
|
|||
* fringe case that is not enabled except via specific settings
|
||||
* of the module parameters.
|
||||
*/
|
||||
r = kvm_x86_ops->cpu_has_high_real_mode_segbase();
|
||||
r = kvm_x86_ops->has_emulated_msr(MSR_IA32_SMBASE);
|
||||
break;
|
||||
case KVM_CAP_COALESCED_MMIO:
|
||||
r = KVM_COALESCED_MMIO_PAGE_OFFSET;
|
||||
|
@ -4072,14 +4074,8 @@ static void kvm_init_msr_list(void)
|
|||
num_msrs_to_save = j;
|
||||
|
||||
for (i = j = 0; i < ARRAY_SIZE(emulated_msrs); i++) {
|
||||
switch (emulated_msrs[i]) {
|
||||
case MSR_IA32_SMBASE:
|
||||
if (!kvm_x86_ops->cpu_has_high_real_mode_segbase())
|
||||
continue;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (!kvm_x86_ops->has_emulated_msr(emulated_msrs[i]))
|
||||
continue;
|
||||
|
||||
if (j < i)
|
||||
emulated_msrs[j] = emulated_msrs[i];
|
||||
|
|
|
@ -570,12 +570,12 @@ do { \
|
|||
unsigned long __copy_to_user_ll(void __user *to, const void *from,
|
||||
unsigned long n)
|
||||
{
|
||||
stac();
|
||||
__uaccess_begin_nospec();
|
||||
if (movsl_is_ok(to, from, n))
|
||||
__copy_user(to, from, n);
|
||||
else
|
||||
n = __copy_user_intel(to, from, n);
|
||||
clac();
|
||||
__uaccess_end();
|
||||
return n;
|
||||
}
|
||||
EXPORT_SYMBOL(__copy_to_user_ll);
|
||||
|
@ -583,12 +583,12 @@ EXPORT_SYMBOL(__copy_to_user_ll);
|
|||
unsigned long __copy_from_user_ll(void *to, const void __user *from,
|
||||
unsigned long n)
|
||||
{
|
||||
stac();
|
||||
__uaccess_begin_nospec();
|
||||
if (movsl_is_ok(to, from, n))
|
||||
__copy_user_zeroing(to, from, n);
|
||||
else
|
||||
n = __copy_user_zeroing_intel(to, from, n);
|
||||
clac();
|
||||
__uaccess_end();
|
||||
return n;
|
||||
}
|
||||
EXPORT_SYMBOL(__copy_from_user_ll);
|
||||
|
@ -596,13 +596,13 @@ EXPORT_SYMBOL(__copy_from_user_ll);
|
|||
unsigned long __copy_from_user_ll_nozero(void *to, const void __user *from,
|
||||
unsigned long n)
|
||||
{
|
||||
stac();
|
||||
__uaccess_begin_nospec();
|
||||
if (movsl_is_ok(to, from, n))
|
||||
__copy_user(to, from, n);
|
||||
else
|
||||
n = __copy_user_intel((void __user *)to,
|
||||
(const void *)from, n);
|
||||
clac();
|
||||
__uaccess_end();
|
||||
return n;
|
||||
}
|
||||
EXPORT_SYMBOL(__copy_from_user_ll_nozero);
|
||||
|
@ -610,7 +610,7 @@ EXPORT_SYMBOL(__copy_from_user_ll_nozero);
|
|||
unsigned long __copy_from_user_ll_nocache(void *to, const void __user *from,
|
||||
unsigned long n)
|
||||
{
|
||||
stac();
|
||||
__uaccess_begin_nospec();
|
||||
#ifdef CONFIG_X86_INTEL_USERCOPY
|
||||
if (n > 64 && cpu_has_xmm2)
|
||||
n = __copy_user_zeroing_intel_nocache(to, from, n);
|
||||
|
@ -619,7 +619,7 @@ unsigned long __copy_from_user_ll_nocache(void *to, const void __user *from,
|
|||
#else
|
||||
__copy_user_zeroing(to, from, n);
|
||||
#endif
|
||||
clac();
|
||||
__uaccess_end();
|
||||
return n;
|
||||
}
|
||||
EXPORT_SYMBOL(__copy_from_user_ll_nocache);
|
||||
|
@ -627,7 +627,7 @@ EXPORT_SYMBOL(__copy_from_user_ll_nocache);
|
|||
unsigned long __copy_from_user_ll_nocache_nozero(void *to, const void __user *from,
|
||||
unsigned long n)
|
||||
{
|
||||
stac();
|
||||
__uaccess_begin_nospec();
|
||||
#ifdef CONFIG_X86_INTEL_USERCOPY
|
||||
if (n > 64 && cpu_has_xmm2)
|
||||
n = __copy_user_intel_nocache(to, from, n);
|
||||
|
@ -636,7 +636,7 @@ unsigned long __copy_from_user_ll_nocache_nozero(void *to, const void __user *fr
|
|||
#else
|
||||
__copy_user(to, from, n);
|
||||
#endif
|
||||
clac();
|
||||
__uaccess_end();
|
||||
return n;
|
||||
}
|
||||
EXPORT_SYMBOL(__copy_from_user_ll_nocache_nozero);
|
||||
|
|
|
@ -388,7 +388,7 @@ slow_irqon:
|
|||
|
||||
ret = get_user_pages_unlocked(current, mm, start,
|
||||
(end - start) >> PAGE_SHIFT,
|
||||
write, 0, pages);
|
||||
pages, write ? FOLL_WRITE : 0);
|
||||
|
||||
/* Have to be a bit careful with return values */
|
||||
if (nr > 0) {
|
||||
|
|
|
@ -536,10 +536,9 @@ static int mpx_resolve_fault(long __user *addr, int write)
|
|||
{
|
||||
long gup_ret;
|
||||
int nr_pages = 1;
|
||||
int force = 0;
|
||||
|
||||
gup_ret = get_user_pages(current, current->mm, (unsigned long)addr,
|
||||
nr_pages, write, force, NULL, NULL);
|
||||
nr_pages, write ? FOLL_WRITE : 0, NULL, NULL);
|
||||
/*
|
||||
* get_user_pages() returns number of pages gotten.
|
||||
* 0 means we failed to fault in and get anything,
|
||||
|
|
|
@ -496,9 +496,13 @@ static int amdgpu_ttm_tt_pin_userptr(struct ttm_tt *ttm)
|
|||
int r;
|
||||
|
||||
int write = !(gtt->userflags & AMDGPU_GEM_USERPTR_READONLY);
|
||||
unsigned int flags = 0;
|
||||
enum dma_data_direction direction = write ?
|
||||
DMA_BIDIRECTIONAL : DMA_TO_DEVICE;
|
||||
|
||||
if (write)
|
||||
flags |= FOLL_WRITE;
|
||||
|
||||
if (current->mm != gtt->usermm)
|
||||
return -EPERM;
|
||||
|
||||
|
@ -519,7 +523,7 @@ static int amdgpu_ttm_tt_pin_userptr(struct ttm_tt *ttm)
|
|||
struct page **pages = ttm->pages + pinned;
|
||||
|
||||
r = get_user_pages(current, current->mm, userptr, num_pages,
|
||||
write, 0, pages, NULL);
|
||||
flags, pages, NULL);
|
||||
if (r < 0)
|
||||
goto release_pages;
|
||||
|
||||
|
|
|
@ -968,9 +968,21 @@ static int get_clock(void *i2c_priv)
|
|||
{
|
||||
struct ast_i2c_chan *i2c = i2c_priv;
|
||||
struct ast_private *ast = i2c->dev->dev_private;
|
||||
uint32_t val;
|
||||
uint32_t val, val2, count, pass;
|
||||
|
||||
count = 0;
|
||||
pass = 0;
|
||||
val = (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x10) >> 4) & 0x01;
|
||||
do {
|
||||
val2 = (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x10) >> 4) & 0x01;
|
||||
if (val == val2) {
|
||||
pass++;
|
||||
} else {
|
||||
pass = 0;
|
||||
val = (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x10) >> 4) & 0x01;
|
||||
}
|
||||
} while ((pass < 5) && (count++ < 0x10000));
|
||||
|
||||
val = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x10) >> 4;
|
||||
return val & 1 ? 1 : 0;
|
||||
}
|
||||
|
||||
|
@ -978,9 +990,21 @@ static int get_data(void *i2c_priv)
|
|||
{
|
||||
struct ast_i2c_chan *i2c = i2c_priv;
|
||||
struct ast_private *ast = i2c->dev->dev_private;
|
||||
uint32_t val;
|
||||
uint32_t val, val2, count, pass;
|
||||
|
||||
count = 0;
|
||||
pass = 0;
|
||||
val = (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x20) >> 5) & 0x01;
|
||||
do {
|
||||
val2 = (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x20) >> 5) & 0x01;
|
||||
if (val == val2) {
|
||||
pass++;
|
||||
} else {
|
||||
pass = 0;
|
||||
val = (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x20) >> 5) & 0x01;
|
||||
}
|
||||
} while ((pass < 5) && (count++ < 0x10000));
|
||||
|
||||
val = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x20) >> 5;
|
||||
return val & 1 ? 1 : 0;
|
||||
}
|
||||
|
||||
|
@ -993,7 +1017,7 @@ static void set_clock(void *i2c_priv, int clock)
|
|||
|
||||
for (i = 0; i < 0x10000; i++) {
|
||||
ujcrb7 = ((clock & 0x01) ? 0 : 1);
|
||||
ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0xfe, ujcrb7);
|
||||
ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0xf4, ujcrb7);
|
||||
jtemp = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x01);
|
||||
if (ujcrb7 == jtemp)
|
||||
break;
|
||||
|
@ -1009,7 +1033,7 @@ static void set_data(void *i2c_priv, int data)
|
|||
|
||||
for (i = 0; i < 0x10000; i++) {
|
||||
ujcrb7 = ((data & 0x01) ? 0 : 1) << 2;
|
||||
ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0xfb, ujcrb7);
|
||||
ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0xf1, ujcrb7);
|
||||
jtemp = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x04);
|
||||
if (ujcrb7 == jtemp)
|
||||
break;
|
||||
|
|
|
@ -471,7 +471,8 @@ static dma_addr_t *g2d_userptr_get_dma_addr(struct drm_device *drm_dev,
|
|||
goto err_free;
|
||||
}
|
||||
|
||||
ret = get_vaddr_frames(start, npages, true, true, g2d_userptr->vec);
|
||||
ret = get_vaddr_frames(start, npages, FOLL_FORCE | FOLL_WRITE,
|
||||
g2d_userptr->vec);
|
||||
if (ret != npages) {
|
||||
DRM_ERROR("failed to get user pages from userptr.\n");
|
||||
if (ret < 0)
|
||||
|
|
|
@ -581,13 +581,17 @@ __i915_gem_userptr_get_pages_worker(struct work_struct *_work)
|
|||
pvec = drm_malloc_ab(npages, sizeof(struct page *));
|
||||
if (pvec != NULL) {
|
||||
struct mm_struct *mm = obj->userptr.mm->mm;
|
||||
unsigned int flags = 0;
|
||||
|
||||
if (!obj->userptr.read_only)
|
||||
flags |= FOLL_WRITE;
|
||||
|
||||
down_read(&mm->mmap_sem);
|
||||
while (pinned < npages) {
|
||||
ret = get_user_pages(work->task, mm,
|
||||
obj->userptr.ptr + pinned * PAGE_SIZE,
|
||||
npages - pinned,
|
||||
!obj->userptr.read_only, 0,
|
||||
flags,
|
||||
pvec + pinned, NULL);
|
||||
if (ret < 0)
|
||||
break;
|
||||
|
|
|
@ -557,7 +557,7 @@ static int radeon_ttm_tt_pin_userptr(struct ttm_tt *ttm)
|
|||
struct page **pages = ttm->pages + pinned;
|
||||
|
||||
r = get_user_pages(current, current->mm, userptr, num_pages,
|
||||
write, 0, pages, NULL);
|
||||
write ? FOLL_WRITE : 0, pages, NULL);
|
||||
if (r < 0)
|
||||
goto release_pages;
|
||||
|
||||
|
|
|
@ -242,8 +242,8 @@ via_lock_all_dma_pages(drm_via_sg_info_t *vsg, drm_via_dmablit_t *xfer)
|
|||
ret = get_user_pages(current, current->mm,
|
||||
(unsigned long)xfer->mem_addr,
|
||||
vsg->num_pages,
|
||||
(vsg->direction == DMA_FROM_DEVICE),
|
||||
0, vsg->pages, NULL);
|
||||
(vsg->direction == DMA_FROM_DEVICE) ? FOLL_WRITE : 0,
|
||||
vsg->pages, NULL);
|
||||
|
||||
up_read(¤t->mm->mmap_sem);
|
||||
if (ret != vsg->num_pages) {
|
||||
|
|
|
@ -273,7 +273,7 @@ static int ina2xx_get_value(struct ina2xx_data *data, u8 reg,
|
|||
break;
|
||||
case INA2XX_CURRENT:
|
||||
/* signed register, result in mA */
|
||||
val = regval * data->current_lsb_uA;
|
||||
val = (s16)regval * data->current_lsb_uA;
|
||||
val = DIV_ROUND_CLOSEST(val, 1000);
|
||||
break;
|
||||
case INA2XX_CALIBRATION:
|
||||
|
|
|
@ -1691,7 +1691,7 @@ store_sf_setup(struct device *dev, struct device_attribute *attr,
|
|||
* somewhere else in the code
|
||||
*/
|
||||
#define SENSOR_ATTR_TEMP(index) { \
|
||||
SENSOR_ATTR_2(temp##index##_type, S_IRUGO | (index < 4 ? S_IWUSR : 0), \
|
||||
SENSOR_ATTR_2(temp##index##_type, S_IRUGO | (index < 5 ? S_IWUSR : 0), \
|
||||
show_temp_mode, store_temp_mode, NOT_USED, index - 1), \
|
||||
SENSOR_ATTR_2(temp##index##_input, S_IRUGO, show_temp, \
|
||||
NULL, TEMP_READ, index - 1), \
|
||||
|
|
|
@ -95,6 +95,7 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr,
|
|||
DEFINE_DMA_ATTRS(attrs);
|
||||
struct scatterlist *sg, *sg_list_start;
|
||||
int need_release = 0;
|
||||
unsigned int gup_flags = FOLL_WRITE;
|
||||
|
||||
if (dmasync)
|
||||
dma_set_attr(DMA_ATTR_WRITE_BARRIER, &attrs);
|
||||
|
@ -177,6 +178,9 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr,
|
|||
if (ret)
|
||||
goto out;
|
||||
|
||||
if (!umem->writable)
|
||||
gup_flags |= FOLL_FORCE;
|
||||
|
||||
need_release = 1;
|
||||
sg_list_start = umem->sg_head.sgl;
|
||||
|
||||
|
@ -184,7 +188,7 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr,
|
|||
ret = get_user_pages(current, current->mm, cur_base,
|
||||
min_t(unsigned long, npages,
|
||||
PAGE_SIZE / sizeof (struct page *)),
|
||||
1, !umem->writable, page_list, vma_list);
|
||||
gup_flags, page_list, vma_list);
|
||||
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
|
|
@ -527,6 +527,7 @@ int ib_umem_odp_map_dma_pages(struct ib_umem *umem, u64 user_virt, u64 bcnt,
|
|||
u64 off;
|
||||
int j, k, ret = 0, start_idx, npages = 0;
|
||||
u64 base_virt_addr;
|
||||
unsigned int flags = 0;
|
||||
|
||||
if (access_mask == 0)
|
||||
return -EINVAL;
|
||||
|
@ -556,6 +557,9 @@ int ib_umem_odp_map_dma_pages(struct ib_umem *umem, u64 user_virt, u64 bcnt,
|
|||
goto out_put_task;
|
||||
}
|
||||
|
||||
if (access_mask & ODP_WRITE_ALLOWED_BIT)
|
||||
flags |= FOLL_WRITE;
|
||||
|
||||
start_idx = (user_virt - ib_umem_start(umem)) >> PAGE_SHIFT;
|
||||
k = start_idx;
|
||||
|
||||
|
@ -574,8 +578,7 @@ int ib_umem_odp_map_dma_pages(struct ib_umem *umem, u64 user_virt, u64 bcnt,
|
|||
*/
|
||||
npages = get_user_pages(owning_process, owning_mm, user_virt,
|
||||
gup_num_pages,
|
||||
access_mask & ODP_WRITE_ALLOWED_BIT, 0,
|
||||
local_page_list, NULL);
|
||||
flags, local_page_list, NULL);
|
||||
up_read(&owning_mm->mmap_sem);
|
||||
|
||||
if (npages < 0)
|
||||
|
|
|
@ -472,8 +472,8 @@ int mthca_map_user_db(struct mthca_dev *dev, struct mthca_uar *uar,
|
|||
goto out;
|
||||
}
|
||||
|
||||
ret = get_user_pages(current, current->mm, uaddr & PAGE_MASK, 1, 1, 0,
|
||||
pages, NULL);
|
||||
ret = get_user_pages(current, current->mm, uaddr & PAGE_MASK, 1,
|
||||
FOLL_WRITE, pages, NULL);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
|
|
|
@ -68,7 +68,8 @@ static int __qib_get_user_pages(unsigned long start_page, size_t num_pages,
|
|||
for (got = 0; got < num_pages; got += ret) {
|
||||
ret = get_user_pages(current, current->mm,
|
||||
start_page + got * PAGE_SIZE,
|
||||
num_pages - got, 1, 1,
|
||||
num_pages - got,
|
||||
FOLL_WRITE | FOLL_FORCE,
|
||||
p + got, NULL);
|
||||
if (ret < 0)
|
||||
goto bail_release;
|
||||
|
|
|
@ -113,6 +113,7 @@ static int usnic_uiom_get_pages(unsigned long addr, size_t size, int writable,
|
|||
int flags;
|
||||
dma_addr_t pa;
|
||||
DEFINE_DMA_ATTRS(attrs);
|
||||
unsigned int gup_flags;
|
||||
|
||||
if (dmasync)
|
||||
dma_set_attr(DMA_ATTR_WRITE_BARRIER, &attrs);
|
||||
|
@ -140,6 +141,8 @@ static int usnic_uiom_get_pages(unsigned long addr, size_t size, int writable,
|
|||
|
||||
flags = IOMMU_READ | IOMMU_CACHE;
|
||||
flags |= (writable) ? IOMMU_WRITE : 0;
|
||||
gup_flags = FOLL_WRITE;
|
||||
gup_flags |= (writable) ? 0 : FOLL_FORCE;
|
||||
cur_base = addr & PAGE_MASK;
|
||||
ret = 0;
|
||||
|
||||
|
@ -147,7 +150,7 @@ static int usnic_uiom_get_pages(unsigned long addr, size_t size, int writable,
|
|||
ret = get_user_pages(current, current->mm, cur_base,
|
||||
min_t(unsigned long, npages,
|
||||
PAGE_SIZE / sizeof(struct page *)),
|
||||
1, !writable, page_list, NULL);
|
||||
gup_flags, page_list, NULL);
|
||||
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
|
|
@ -155,7 +155,9 @@ static int ascot2e_write_regs(struct ascot2e_priv *priv,
|
|||
|
||||
static int ascot2e_write_reg(struct ascot2e_priv *priv, u8 reg, u8 val)
|
||||
{
|
||||
return ascot2e_write_regs(priv, reg, &val, 1);
|
||||
u8 tmp = val; /* see gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 */
|
||||
|
||||
return ascot2e_write_regs(priv, reg, &tmp, 1);
|
||||
}
|
||||
|
||||
static int ascot2e_read_regs(struct ascot2e_priv *priv,
|
||||
|
|
|
@ -241,7 +241,9 @@ static int cxd2841er_write_regs(struct cxd2841er_priv *priv,
|
|||
static int cxd2841er_write_reg(struct cxd2841er_priv *priv,
|
||||
u8 addr, u8 reg, u8 val)
|
||||
{
|
||||
return cxd2841er_write_regs(priv, addr, reg, &val, 1);
|
||||
u8 tmp = val; /* see gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 */
|
||||
|
||||
return cxd2841er_write_regs(priv, addr, reg, &tmp, 1);
|
||||
}
|
||||
|
||||
static int cxd2841er_read_regs(struct cxd2841er_priv *priv,
|
||||
|
|
|
@ -89,7 +89,9 @@ static int horus3a_write_regs(struct horus3a_priv *priv,
|
|||
|
||||
static int horus3a_write_reg(struct horus3a_priv *priv, u8 reg, u8 val)
|
||||
{
|
||||
return horus3a_write_regs(priv, reg, &val, 1);
|
||||
u8 tmp = val; /* see gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 */
|
||||
|
||||
return horus3a_write_regs(priv, reg, &tmp, 1);
|
||||
}
|
||||
|
||||
static int horus3a_enter_power_save(struct horus3a_priv *priv)
|
||||
|
|
|
@ -99,8 +99,9 @@ static int itd1000_read_reg(struct itd1000_state *state, u8 reg)
|
|||
|
||||
static inline int itd1000_write_reg(struct itd1000_state *state, u8 r, u8 v)
|
||||
{
|
||||
int ret = itd1000_write_regs(state, r, &v, 1);
|
||||
state->shadow[r] = v;
|
||||
u8 tmp = v; /* see gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 */
|
||||
int ret = itd1000_write_regs(state, r, &tmp, 1);
|
||||
state->shadow[r] = tmp;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -142,7 +142,10 @@ static inline int mt312_readreg(struct mt312_state *state,
|
|||
static inline int mt312_writereg(struct mt312_state *state,
|
||||
const enum mt312_reg_addr reg, const u8 val)
|
||||
{
|
||||
return mt312_write(state, reg, &val, 1);
|
||||
u8 tmp = val; /* see gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 */
|
||||
|
||||
|
||||
return mt312_write(state, reg, &tmp, 1);
|
||||
}
|
||||
|
||||
static inline u32 mt312_div(u32 a, u32 b)
|
||||
|
|
|
@ -552,7 +552,8 @@ int stb0899_write_regs(struct stb0899_state *state, unsigned int reg, u8 *data,
|
|||
|
||||
int stb0899_write_reg(struct stb0899_state *state, unsigned int reg, u8 data)
|
||||
{
|
||||
return stb0899_write_regs(state, reg, &data, 1);
|
||||
u8 tmp = data;
|
||||
return stb0899_write_regs(state, reg, &tmp, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -226,12 +226,14 @@ static int stb6100_write_reg_range(struct stb6100_state *state, u8 buf[], int st
|
|||
|
||||
static int stb6100_write_reg(struct stb6100_state *state, u8 reg, u8 data)
|
||||
{
|
||||
u8 tmp = data; /* see gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 */
|
||||
|
||||
if (unlikely(reg >= STB6100_NUMREGS)) {
|
||||
dprintk(verbose, FE_ERROR, 1, "Invalid register offset 0x%x", reg);
|
||||
return -EREMOTEIO;
|
||||
}
|
||||
data = (data & stb6100_template[reg].mask) | stb6100_template[reg].set;
|
||||
return stb6100_write_reg_range(state, &data, reg, 1);
|
||||
tmp = (tmp & stb6100_template[reg].mask) | stb6100_template[reg].set;
|
||||
return stb6100_write_reg_range(state, &tmp, reg, 1);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -804,7 +804,9 @@ int stv0367_writeregs(struct stv0367_state *state, u16 reg, u8 *data, int len)
|
|||
|
||||
static int stv0367_writereg(struct stv0367_state *state, u16 reg, u8 data)
|
||||
{
|
||||
return stv0367_writeregs(state, reg, &data, 1);
|
||||
u8 tmp = data; /* see gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 */
|
||||
|
||||
return stv0367_writeregs(state, reg, &tmp, 1);
|
||||
}
|
||||
|
||||
static u8 stv0367_readreg(struct stv0367_state *state, u16 reg)
|
||||
|
|
|
@ -761,7 +761,9 @@ static int stv090x_write_regs(struct stv090x_state *state, unsigned int reg, u8
|
|||
|
||||
static int stv090x_write_reg(struct stv090x_state *state, unsigned int reg, u8 data)
|
||||
{
|
||||
return stv090x_write_regs(state, reg, &data, 1);
|
||||
u8 tmp = data; /* see gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 */
|
||||
|
||||
return stv090x_write_regs(state, reg, &tmp, 1);
|
||||
}
|
||||
|
||||
static int stv090x_i2c_gate_ctrl(struct stv090x_state *state, int enable)
|
||||
|
|
|
@ -97,7 +97,9 @@ static int stv6110x_write_regs(struct stv6110x_state *stv6110x, int start, u8 da
|
|||
|
||||
static int stv6110x_write_reg(struct stv6110x_state *stv6110x, u8 reg, u8 data)
|
||||
{
|
||||
return stv6110x_write_regs(stv6110x, reg, &data, 1);
|
||||
u8 tmp = data; /* see gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 */
|
||||
|
||||
return stv6110x_write_regs(stv6110x, reg, &tmp, 1);
|
||||
}
|
||||
|
||||
static int stv6110x_init(struct dvb_frontend *fe)
|
||||
|
|
|
@ -138,7 +138,9 @@ static inline int zl10039_writereg(struct zl10039_state *state,
|
|||
const enum zl10039_reg_addr reg,
|
||||
const u8 val)
|
||||
{
|
||||
return zl10039_write(state, reg, &val, 1);
|
||||
const u8 tmp = val; /* see gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 */
|
||||
|
||||
return zl10039_write(state, reg, &tmp, 1);
|
||||
}
|
||||
|
||||
static int zl10039_init(struct dvb_frontend *fe)
|
||||
|
|
|
@ -125,7 +125,8 @@ int ivtv_udma_setup(struct ivtv *itv, unsigned long ivtv_dest_addr,
|
|||
|
||||
/* Get user pages for DMA Xfer */
|
||||
err = get_user_pages_unlocked(current, current->mm,
|
||||
user_dma.uaddr, user_dma.page_count, 0, 1, dma->map);
|
||||
user_dma.uaddr, user_dma.page_count, dma->map,
|
||||
FOLL_FORCE);
|
||||
|
||||
if (user_dma.page_count != err) {
|
||||
IVTV_DEBUG_WARN("failed to map user pages, returned %d instead of %d\n",
|
||||
|
|
|
@ -76,13 +76,13 @@ static int ivtv_yuv_prep_user_dma(struct ivtv *itv, struct ivtv_user_dma *dma,
|
|||
|
||||
/* Get user pages for DMA Xfer */
|
||||
y_pages = get_user_pages_unlocked(current, current->mm,
|
||||
y_dma.uaddr, y_dma.page_count, 0, 1,
|
||||
&dma->map[0]);
|
||||
y_dma.uaddr, y_dma.page_count,
|
||||
&dma->map[0], FOLL_FORCE);
|
||||
uv_pages = 0; /* silence gcc. value is set and consumed only if: */
|
||||
if (y_pages == y_dma.page_count) {
|
||||
uv_pages = get_user_pages_unlocked(current, current->mm,
|
||||
uv_dma.uaddr, uv_dma.page_count, 0, 1,
|
||||
&dma->map[y_pages]);
|
||||
uv_dma.uaddr, uv_dma.page_count,
|
||||
&dma->map[y_pages], FOLL_FORCE);
|
||||
}
|
||||
|
||||
if (y_pages != y_dma.page_count || uv_pages != uv_dma.page_count) {
|
||||
|
|
|
@ -214,7 +214,7 @@ static int omap_vout_get_userptr(struct videobuf_buffer *vb, u32 virtp,
|
|||
if (!vec)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = get_vaddr_frames(virtp, 1, true, false, vec);
|
||||
ret = get_vaddr_frames(virtp, 1, FOLL_WRITE, vec);
|
||||
if (ret != 1) {
|
||||
frame_vector_destroy(vec);
|
||||
return -EINVAL;
|
||||
|
|
|
@ -156,6 +156,7 @@ static int videobuf_dma_init_user_locked(struct videobuf_dmabuf *dma,
|
|||
{
|
||||
unsigned long first, last;
|
||||
int err, rw = 0;
|
||||
unsigned int flags = FOLL_FORCE;
|
||||
|
||||
dma->direction = direction;
|
||||
switch (dma->direction) {
|
||||
|
@ -178,13 +179,15 @@ static int videobuf_dma_init_user_locked(struct videobuf_dmabuf *dma,
|
|||
if (NULL == dma->pages)
|
||||
return -ENOMEM;
|
||||
|
||||
if (rw == READ)
|
||||
flags |= FOLL_WRITE;
|
||||
|
||||
dprintk(1, "init user [0x%lx+0x%lx => %d pages]\n",
|
||||
data, size, dma->nr_pages);
|
||||
|
||||
err = get_user_pages(current, current->mm,
|
||||
data & PAGE_MASK, dma->nr_pages,
|
||||
rw == READ, 1, /* force */
|
||||
dma->pages, NULL);
|
||||
flags, dma->pages, NULL);
|
||||
|
||||
if (err != dma->nr_pages) {
|
||||
dma->nr_pages = (err >= 0) ? err : 0;
|
||||
|
|
|
@ -42,6 +42,10 @@ struct frame_vector *vb2_create_framevec(unsigned long start,
|
|||
unsigned long first, last;
|
||||
unsigned long nr;
|
||||
struct frame_vector *vec;
|
||||
unsigned int flags = FOLL_FORCE;
|
||||
|
||||
if (write)
|
||||
flags |= FOLL_WRITE;
|
||||
|
||||
first = start >> PAGE_SHIFT;
|
||||
last = (start + length - 1) >> PAGE_SHIFT;
|
||||
|
@ -49,7 +53,7 @@ struct frame_vector *vb2_create_framevec(unsigned long start,
|
|||
vec = frame_vector_create(nr);
|
||||
if (!vec)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
ret = get_vaddr_frames(start & PAGE_MASK, nr, write, true, vec);
|
||||
ret = get_vaddr_frames(start & PAGE_MASK, nr, flags, vec);
|
||||
if (ret < 0)
|
||||
goto out_destroy;
|
||||
/* We accept only complete set of PFNs */
|
||||
|
|
|
@ -1398,8 +1398,7 @@ retry:
|
|||
mm,
|
||||
(u64)addr,
|
||||
nr_pages,
|
||||
!!(prot & SCIF_PROT_WRITE),
|
||||
0,
|
||||
(prot & SCIF_PROT_WRITE) ? FOLL_WRITE : 0,
|
||||
pinned_pages->pages,
|
||||
NULL);
|
||||
up_write(&mm->mmap_sem);
|
||||
|
|
|
@ -199,7 +199,7 @@ static int non_atomic_pte_lookup(struct vm_area_struct *vma,
|
|||
*pageshift = PAGE_SHIFT;
|
||||
#endif
|
||||
if (get_user_pages
|
||||
(current, current->mm, vaddr, 1, write, 0, &page, NULL) <= 0)
|
||||
(current, current->mm, vaddr, 1, write ? FOLL_WRITE : 0, &page, NULL) <= 0)
|
||||
return -EFAULT;
|
||||
*paddr = page_to_phys(page);
|
||||
put_page(page);
|
||||
|
|
|
@ -1090,6 +1090,9 @@ static void nic_remove(struct pci_dev *pdev)
|
|||
{
|
||||
struct nicpf *nic = pci_get_drvdata(pdev);
|
||||
|
||||
if (!nic)
|
||||
return;
|
||||
|
||||
if (nic->flags & NIC_SRIOV_ENABLED)
|
||||
pci_disable_sriov(pdev);
|
||||
|
||||
|
|
|
@ -919,10 +919,8 @@ static int hip04_mac_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
ret = register_netdev(ndev);
|
||||
if (ret) {
|
||||
free_netdev(ndev);
|
||||
if (ret)
|
||||
goto alloc_fail;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
|
|
|
@ -1429,7 +1429,9 @@ static s32 ixgbe_get_link_capabilities_X550em(struct ixgbe_hw *hw,
|
|||
*autoneg = false;
|
||||
|
||||
if (hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core0 ||
|
||||
hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core1) {
|
||||
hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core1 ||
|
||||
hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core0 ||
|
||||
hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core1) {
|
||||
*speed = IXGBE_LINK_SPEED_1GB_FULL;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -578,6 +578,7 @@ static irqreturn_t cp_interrupt (int irq, void *dev_instance)
|
|||
struct cp_private *cp;
|
||||
int handled = 0;
|
||||
u16 status;
|
||||
u16 mask;
|
||||
|
||||
if (unlikely(dev == NULL))
|
||||
return IRQ_NONE;
|
||||
|
@ -585,6 +586,10 @@ static irqreturn_t cp_interrupt (int irq, void *dev_instance)
|
|||
|
||||
spin_lock(&cp->lock);
|
||||
|
||||
mask = cpr16(IntrMask);
|
||||
if (!mask)
|
||||
goto out_unlock;
|
||||
|
||||
status = cpr16(IntrStatus);
|
||||
if (!status || (status == 0xFFFF))
|
||||
goto out_unlock;
|
||||
|
|
|
@ -821,37 +821,49 @@ static int rocker_tlv_put(struct rocker_desc_info *desc_info,
|
|||
static int rocker_tlv_put_u8(struct rocker_desc_info *desc_info,
|
||||
int attrtype, u8 value)
|
||||
{
|
||||
return rocker_tlv_put(desc_info, attrtype, sizeof(u8), &value);
|
||||
u8 tmp = value; /* work around GCC PR81715 */
|
||||
|
||||
return rocker_tlv_put(desc_info, attrtype, sizeof(u8), &tmp);
|
||||
}
|
||||
|
||||
static int rocker_tlv_put_u16(struct rocker_desc_info *desc_info,
|
||||
int attrtype, u16 value)
|
||||
{
|
||||
return rocker_tlv_put(desc_info, attrtype, sizeof(u16), &value);
|
||||
u16 tmp = value;
|
||||
|
||||
return rocker_tlv_put(desc_info, attrtype, sizeof(u16), &tmp);
|
||||
}
|
||||
|
||||
static int rocker_tlv_put_be16(struct rocker_desc_info *desc_info,
|
||||
int attrtype, __be16 value)
|
||||
{
|
||||
return rocker_tlv_put(desc_info, attrtype, sizeof(__be16), &value);
|
||||
__be16 tmp = value;
|
||||
|
||||
return rocker_tlv_put(desc_info, attrtype, sizeof(__be16), &tmp);
|
||||
}
|
||||
|
||||
static int rocker_tlv_put_u32(struct rocker_desc_info *desc_info,
|
||||
int attrtype, u32 value)
|
||||
{
|
||||
return rocker_tlv_put(desc_info, attrtype, sizeof(u32), &value);
|
||||
u32 tmp = value;
|
||||
|
||||
return rocker_tlv_put(desc_info, attrtype, sizeof(u32), &tmp);
|
||||
}
|
||||
|
||||
static int rocker_tlv_put_be32(struct rocker_desc_info *desc_info,
|
||||
int attrtype, __be32 value)
|
||||
{
|
||||
return rocker_tlv_put(desc_info, attrtype, sizeof(__be32), &value);
|
||||
__be32 tmp = value;
|
||||
|
||||
return rocker_tlv_put(desc_info, attrtype, sizeof(__be32), &tmp);
|
||||
}
|
||||
|
||||
static int rocker_tlv_put_u64(struct rocker_desc_info *desc_info,
|
||||
int attrtype, u64 value)
|
||||
{
|
||||
return rocker_tlv_put(desc_info, attrtype, sizeof(u64), &value);
|
||||
u64 tmp = value;
|
||||
|
||||
return rocker_tlv_put(desc_info, attrtype, sizeof(u64), &tmp);
|
||||
}
|
||||
|
||||
static struct rocker_tlv *
|
||||
|
|
|
@ -1265,20 +1265,17 @@ static int gen10g_resume(struct phy_device *phydev)
|
|||
|
||||
static int __set_phy_supported(struct phy_device *phydev, u32 max_speed)
|
||||
{
|
||||
phydev->supported &= ~(PHY_1000BT_FEATURES | PHY_100BT_FEATURES |
|
||||
PHY_10BT_FEATURES);
|
||||
|
||||
switch (max_speed) {
|
||||
default:
|
||||
return -ENOTSUPP;
|
||||
case SPEED_1000:
|
||||
phydev->supported |= PHY_1000BT_FEATURES;
|
||||
case SPEED_10:
|
||||
phydev->supported &= ~PHY_100BT_FEATURES;
|
||||
/* fall through */
|
||||
case SPEED_100:
|
||||
phydev->supported |= PHY_100BT_FEATURES;
|
||||
/* fall through */
|
||||
case SPEED_10:
|
||||
phydev->supported |= PHY_10BT_FEATURES;
|
||||
phydev->supported &= ~PHY_1000BT_FEATURES;
|
||||
break;
|
||||
case SPEED_1000:
|
||||
break;
|
||||
default:
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -1472,9 +1472,9 @@ static void tun_setup(struct net_device *dev)
|
|||
*/
|
||||
static int tun_validate(struct nlattr *tb[], struct nlattr *data[])
|
||||
{
|
||||
if (!data)
|
||||
return 0;
|
||||
return -EINVAL;
|
||||
/* NL_SET_ERR_MSG(extack,
|
||||
"tun/tap creation via rtnetlink is not supported."); */
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static struct rtnl_link_ops tun_link_ops __read_mostly = {
|
||||
|
|
|
@ -1035,8 +1035,14 @@ int wmi_set_ie(struct wil6210_priv *wil, u8 type, u16 ie_len, const void *ie)
|
|||
};
|
||||
int rc;
|
||||
u16 len = sizeof(struct wmi_set_appie_cmd) + ie_len;
|
||||
struct wmi_set_appie_cmd *cmd = kzalloc(len, GFP_KERNEL);
|
||||
struct wmi_set_appie_cmd *cmd;
|
||||
|
||||
if (len < ie_len) {
|
||||
rc = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
cmd = kzalloc(len, GFP_KERNEL);
|
||||
if (!cmd) {
|
||||
rc = -ENOMEM;
|
||||
goto out;
|
||||
|
|
|
@ -187,30 +187,25 @@ int sr_do_ioctl(Scsi_CD *cd, struct packet_command *cgc)
|
|||
struct scsi_device *SDev;
|
||||
struct scsi_sense_hdr sshdr;
|
||||
int result, err = 0, retries = 0;
|
||||
struct request_sense *sense = cgc->sense;
|
||||
unsigned char sense_buffer[SCSI_SENSE_BUFFERSIZE];
|
||||
|
||||
SDev = cd->device;
|
||||
|
||||
if (!sense) {
|
||||
sense = kmalloc(SCSI_SENSE_BUFFERSIZE, GFP_KERNEL);
|
||||
if (!sense) {
|
||||
err = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
retry:
|
||||
if (!scsi_block_when_processing_errors(SDev)) {
|
||||
err = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
|
||||
memset(sense, 0, sizeof(*sense));
|
||||
memset(sense_buffer, 0, sizeof(sense_buffer));
|
||||
result = scsi_execute(SDev, cgc->cmd, cgc->data_direction,
|
||||
cgc->buffer, cgc->buflen, (char *)sense,
|
||||
cgc->buffer, cgc->buflen, sense_buffer,
|
||||
cgc->timeout, IOCTL_RETRIES, 0, NULL);
|
||||
|
||||
scsi_normalize_sense((char *)sense, sizeof(*sense), &sshdr);
|
||||
scsi_normalize_sense(sense_buffer, sizeof(sense_buffer), &sshdr);
|
||||
|
||||
if (cgc->sense)
|
||||
memcpy(cgc->sense, sense_buffer, sizeof(*cgc->sense));
|
||||
|
||||
/* Minimal error checking. Ignore cases we know about, and report the rest. */
|
||||
if (driver_byte(result) != 0) {
|
||||
|
@ -261,8 +256,6 @@ int sr_do_ioctl(Scsi_CD *cd, struct packet_command *cgc)
|
|||
|
||||
/* Wake up a process waiting for device */
|
||||
out:
|
||||
if (!cgc->sense)
|
||||
kfree(sense);
|
||||
cgc->stat = err;
|
||||
return err;
|
||||
}
|
||||
|
|
|
@ -4821,9 +4821,8 @@ static int sgl_map_user_pages(struct st_buffer *STbp,
|
|||
current->mm,
|
||||
uaddr,
|
||||
nr_pages,
|
||||
rw == READ,
|
||||
0, /* don't force */
|
||||
pages);
|
||||
pages,
|
||||
rw == READ ? FOLL_WRITE : 0); /* don't force */
|
||||
|
||||
/* Errors and no page mapped should return here */
|
||||
if (res < nr_pages)
|
||||
|
|
|
@ -85,7 +85,7 @@ static int __hfi1_get_user_pages(unsigned long start_page, size_t num_pages,
|
|||
for (got = 0; got < num_pages; got += ret) {
|
||||
ret = get_user_pages(current, current->mm,
|
||||
start_page + got * PAGE_SIZE,
|
||||
num_pages - got, 1, 1,
|
||||
num_pages - got, FOLL_WRITE | FOLL_FORCE,
|
||||
p + got, NULL);
|
||||
if (ret < 0)
|
||||
goto bail_release;
|
||||
|
|
|
@ -72,7 +72,7 @@ static int __ipath_get_user_pages(unsigned long start_page, size_t num_pages,
|
|||
for (got = 0; got < num_pages; got += ret) {
|
||||
ret = get_user_pages(current, current->mm,
|
||||
start_page + got * PAGE_SIZE,
|
||||
num_pages - got, 1, 1,
|
||||
num_pages - got, FOLL_WRITE | FOLL_FORCE,
|
||||
p + got, NULL);
|
||||
if (ret < 0)
|
||||
goto bail_release;
|
||||
|
|
|
@ -387,7 +387,7 @@ static ssize_t synth_store(struct kobject *kobj, struct kobj_attribute *attr,
|
|||
len = strlen(buf);
|
||||
if (len < 2 || len > 9)
|
||||
return -EINVAL;
|
||||
strncpy(new_synth_name, buf, len);
|
||||
memcpy(new_synth_name, buf, len);
|
||||
if (new_synth_name[len - 1] == '\n')
|
||||
len--;
|
||||
new_synth_name[len] = '\0';
|
||||
|
@ -514,7 +514,7 @@ static ssize_t punc_store(struct kobject *kobj, struct kobj_attribute *attr,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
strncpy(punc_buf, buf, x);
|
||||
memcpy(punc_buf, buf, x);
|
||||
|
||||
while (x && punc_buf[x - 1] == '\n')
|
||||
x--;
|
||||
|
|
|
@ -2037,6 +2037,7 @@ static inline int machine_without_vbus_sense(void)
|
|||
{
|
||||
return machine_is_omap_innovator()
|
||||
|| machine_is_omap_osk()
|
||||
|| machine_is_omap_palmte()
|
||||
|| machine_is_sx1()
|
||||
/* No known omap7xx boards with vbus sense */
|
||||
|| cpu_is_omap7xx();
|
||||
|
@ -2045,7 +2046,7 @@ static inline int machine_without_vbus_sense(void)
|
|||
static int omap_udc_start(struct usb_gadget *g,
|
||||
struct usb_gadget_driver *driver)
|
||||
{
|
||||
int status = -ENODEV;
|
||||
int status;
|
||||
struct omap_ep *ep;
|
||||
unsigned long flags;
|
||||
|
||||
|
@ -2083,6 +2084,7 @@ static int omap_udc_start(struct usb_gadget *g,
|
|||
goto done;
|
||||
}
|
||||
} else {
|
||||
status = 0;
|
||||
if (can_pullup(udc))
|
||||
pullup_enable(udc);
|
||||
else
|
||||
|
@ -2612,9 +2614,22 @@ omap_ep_setup(char *name, u8 addr, u8 type,
|
|||
|
||||
static void omap_udc_release(struct device *dev)
|
||||
{
|
||||
complete(udc->done);
|
||||
pullup_disable(udc);
|
||||
if (!IS_ERR_OR_NULL(udc->transceiver)) {
|
||||
usb_put_phy(udc->transceiver);
|
||||
udc->transceiver = NULL;
|
||||
}
|
||||
omap_writew(0, UDC_SYSCON1);
|
||||
remove_proc_file();
|
||||
if (udc->dc_clk) {
|
||||
if (udc->clk_requested)
|
||||
omap_udc_enable_clock(0);
|
||||
clk_put(udc->hhc_clk);
|
||||
clk_put(udc->dc_clk);
|
||||
}
|
||||
if (udc->done)
|
||||
complete(udc->done);
|
||||
kfree(udc);
|
||||
udc = NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -2886,8 +2901,8 @@ bad_on_1710:
|
|||
udc->clr_halt = UDC_RESET_EP;
|
||||
|
||||
/* USB general purpose IRQ: ep0, state changes, dma, etc */
|
||||
status = request_irq(pdev->resource[1].start, omap_udc_irq,
|
||||
0, driver_name, udc);
|
||||
status = devm_request_irq(&pdev->dev, pdev->resource[1].start,
|
||||
omap_udc_irq, 0, driver_name, udc);
|
||||
if (status != 0) {
|
||||
ERR("can't get irq %d, err %d\n",
|
||||
(int) pdev->resource[1].start, status);
|
||||
|
@ -2895,20 +2910,20 @@ bad_on_1710:
|
|||
}
|
||||
|
||||
/* USB "non-iso" IRQ (PIO for all but ep0) */
|
||||
status = request_irq(pdev->resource[2].start, omap_udc_pio_irq,
|
||||
0, "omap_udc pio", udc);
|
||||
status = devm_request_irq(&pdev->dev, pdev->resource[2].start,
|
||||
omap_udc_pio_irq, 0, "omap_udc pio", udc);
|
||||
if (status != 0) {
|
||||
ERR("can't get irq %d, err %d\n",
|
||||
(int) pdev->resource[2].start, status);
|
||||
goto cleanup2;
|
||||
goto cleanup1;
|
||||
}
|
||||
#ifdef USE_ISO
|
||||
status = request_irq(pdev->resource[3].start, omap_udc_iso_irq,
|
||||
0, "omap_udc iso", udc);
|
||||
status = devm_request_irq(&pdev->dev, pdev->resource[3].start,
|
||||
omap_udc_iso_irq, 0, "omap_udc iso", udc);
|
||||
if (status != 0) {
|
||||
ERR("can't get irq %d, err %d\n",
|
||||
(int) pdev->resource[3].start, status);
|
||||
goto cleanup3;
|
||||
goto cleanup1;
|
||||
}
|
||||
#endif
|
||||
if (cpu_is_omap16xx() || cpu_is_omap7xx()) {
|
||||
|
@ -2919,23 +2934,8 @@ bad_on_1710:
|
|||
}
|
||||
|
||||
create_proc_file();
|
||||
status = usb_add_gadget_udc_release(&pdev->dev, &udc->gadget,
|
||||
omap_udc_release);
|
||||
if (status)
|
||||
goto cleanup4;
|
||||
|
||||
return 0;
|
||||
|
||||
cleanup4:
|
||||
remove_proc_file();
|
||||
|
||||
#ifdef USE_ISO
|
||||
cleanup3:
|
||||
free_irq(pdev->resource[2].start, udc);
|
||||
#endif
|
||||
|
||||
cleanup2:
|
||||
free_irq(pdev->resource[1].start, udc);
|
||||
return usb_add_gadget_udc_release(&pdev->dev, &udc->gadget,
|
||||
omap_udc_release);
|
||||
|
||||
cleanup1:
|
||||
kfree(udc);
|
||||
|
@ -2962,42 +2962,15 @@ static int omap_udc_remove(struct platform_device *pdev)
|
|||
{
|
||||
DECLARE_COMPLETION_ONSTACK(done);
|
||||
|
||||
if (!udc)
|
||||
return -ENODEV;
|
||||
|
||||
usb_del_gadget_udc(&udc->gadget);
|
||||
if (udc->driver)
|
||||
return -EBUSY;
|
||||
|
||||
udc->done = &done;
|
||||
|
||||
pullup_disable(udc);
|
||||
if (!IS_ERR_OR_NULL(udc->transceiver)) {
|
||||
usb_put_phy(udc->transceiver);
|
||||
udc->transceiver = NULL;
|
||||
}
|
||||
omap_writew(0, UDC_SYSCON1);
|
||||
usb_del_gadget_udc(&udc->gadget);
|
||||
|
||||
remove_proc_file();
|
||||
|
||||
#ifdef USE_ISO
|
||||
free_irq(pdev->resource[3].start, udc);
|
||||
#endif
|
||||
free_irq(pdev->resource[2].start, udc);
|
||||
free_irq(pdev->resource[1].start, udc);
|
||||
|
||||
if (udc->dc_clk) {
|
||||
if (udc->clk_requested)
|
||||
omap_udc_enable_clock(0);
|
||||
clk_put(udc->hhc_clk);
|
||||
clk_put(udc->dc_clk);
|
||||
}
|
||||
wait_for_completion(&done);
|
||||
|
||||
release_mem_region(pdev->resource[0].start,
|
||||
pdev->resource[0].end - pdev->resource[0].start + 1);
|
||||
|
||||
wait_for_completion(&done);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -372,7 +372,7 @@ static int Ti3026_init(struct matrox_fb_info *minfo, struct my_timming *m)
|
|||
|
||||
DBG(__func__)
|
||||
|
||||
memcpy(hw->DACreg, MGADACbpp32, sizeof(hw->DACreg));
|
||||
memcpy(hw->DACreg, MGADACbpp32, sizeof(MGADACbpp32));
|
||||
switch (minfo->fbcon.var.bits_per_pixel) {
|
||||
case 4: hw->DACreg[POS3026_XLATCHCTRL] = TVP3026_XLATCHCTRL_16_1; /* or _8_1, they are same */
|
||||
hw->DACreg[POS3026_XTRUECOLORCTRL] = TVP3026_XTRUECOLORCTRL_PSEUDOCOLOR;
|
||||
|
|
|
@ -687,7 +687,7 @@ static ssize_t pvr2fb_write(struct fb_info *info, const char *buf,
|
|||
return -ENOMEM;
|
||||
|
||||
ret = get_user_pages_unlocked(current, current->mm, (unsigned long)buf,
|
||||
nr_pages, WRITE, 0, pages);
|
||||
nr_pages, pages, FOLL_WRITE);
|
||||
|
||||
if (ret < nr_pages) {
|
||||
nr_pages = ret;
|
||||
|
|
|
@ -246,8 +246,8 @@ static long ioctl_memcpy(struct fsl_hv_ioctl_memcpy __user *p)
|
|||
down_read(¤t->mm->mmap_sem);
|
||||
num_pinned = get_user_pages(current, current->mm,
|
||||
param.local_vaddr - lb_offset, num_pages,
|
||||
(param.source == -1) ? READ : WRITE,
|
||||
0, pages, NULL);
|
||||
(param.source == -1) ? 0 : FOLL_WRITE,
|
||||
pages, NULL);
|
||||
up_read(¤t->mm->mmap_sem);
|
||||
|
||||
if (num_pinned != num_pages) {
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include <asm/xen/hypervisor.h>
|
||||
|
||||
#include <xen/xen.h>
|
||||
#include <xen/xen-ops.h>
|
||||
#include <xen/page.h>
|
||||
#include <xen/interface/xen.h>
|
||||
#include <xen/interface/memory.h>
|
||||
|
|
|
@ -3232,7 +3232,8 @@ static void free_pending_move(struct send_ctx *sctx, struct pending_dir_move *m)
|
|||
kfree(m);
|
||||
}
|
||||
|
||||
static void tail_append_pending_moves(struct pending_dir_move *moves,
|
||||
static void tail_append_pending_moves(struct send_ctx *sctx,
|
||||
struct pending_dir_move *moves,
|
||||
struct list_head *stack)
|
||||
{
|
||||
if (list_empty(&moves->list)) {
|
||||
|
@ -3243,6 +3244,10 @@ static void tail_append_pending_moves(struct pending_dir_move *moves,
|
|||
list_add_tail(&moves->list, stack);
|
||||
list_splice_tail(&list, stack);
|
||||
}
|
||||
if (!RB_EMPTY_NODE(&moves->node)) {
|
||||
rb_erase(&moves->node, &sctx->pending_dir_moves);
|
||||
RB_CLEAR_NODE(&moves->node);
|
||||
}
|
||||
}
|
||||
|
||||
static int apply_children_dir_moves(struct send_ctx *sctx)
|
||||
|
@ -3257,7 +3262,7 @@ static int apply_children_dir_moves(struct send_ctx *sctx)
|
|||
return 0;
|
||||
|
||||
INIT_LIST_HEAD(&stack);
|
||||
tail_append_pending_moves(pm, &stack);
|
||||
tail_append_pending_moves(sctx, pm, &stack);
|
||||
|
||||
while (!list_empty(&stack)) {
|
||||
pm = list_first_entry(&stack, struct pending_dir_move, list);
|
||||
|
@ -3268,7 +3273,7 @@ static int apply_children_dir_moves(struct send_ctx *sctx)
|
|||
goto out;
|
||||
pm = get_pending_dir_moves(sctx, parent_ino);
|
||||
if (pm)
|
||||
tail_append_pending_moves(pm, &stack);
|
||||
tail_append_pending_moves(sctx, pm, &stack);
|
||||
}
|
||||
return 0;
|
||||
|
||||
|
|
|
@ -963,11 +963,8 @@ error:
|
|||
void cachefiles_uncache_page(struct fscache_object *_object, struct page *page)
|
||||
{
|
||||
struct cachefiles_object *object;
|
||||
struct cachefiles_cache *cache;
|
||||
|
||||
object = container_of(_object, struct cachefiles_object, fscache);
|
||||
cache = container_of(object->fscache.cache,
|
||||
struct cachefiles_cache, cache);
|
||||
|
||||
_enter("%p,{%lu}", object, page->index);
|
||||
|
||||
|
|
|
@ -191,6 +191,7 @@ static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos,
|
|||
{
|
||||
struct page *page;
|
||||
int ret;
|
||||
unsigned int gup_flags = FOLL_FORCE;
|
||||
|
||||
#ifdef CONFIG_STACK_GROWSUP
|
||||
if (write) {
|
||||
|
@ -199,8 +200,12 @@ static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos,
|
|||
return NULL;
|
||||
}
|
||||
#endif
|
||||
ret = get_user_pages(current, bprm->mm, pos,
|
||||
1, write, 1, &page, NULL);
|
||||
|
||||
if (write)
|
||||
gup_flags |= FOLL_WRITE;
|
||||
|
||||
ret = get_user_pages(current, bprm->mm, pos, 1, gup_flags,
|
||||
&page, NULL);
|
||||
if (ret <= 0)
|
||||
return NULL;
|
||||
|
||||
|
|
|
@ -76,7 +76,7 @@ static bool dentry_connected(struct dentry *dentry)
|
|||
struct dentry *parent = dget_parent(dentry);
|
||||
|
||||
dput(dentry);
|
||||
if (IS_ROOT(dentry)) {
|
||||
if (dentry == parent) {
|
||||
dput(parent);
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -715,6 +715,9 @@ static const struct fscache_state *fscache_drop_object(struct fscache_object *ob
|
|||
|
||||
if (awaken)
|
||||
wake_up_bit(&cookie->flags, FSCACHE_COOKIE_INVALIDATING);
|
||||
if (test_and_clear_bit(FSCACHE_COOKIE_LOOKING_UP, &cookie->flags))
|
||||
wake_up_bit(&cookie->flags, FSCACHE_COOKIE_LOOKING_UP);
|
||||
|
||||
|
||||
/* Prevent a race with our last child, which has to signal EV_CLEARED
|
||||
* before dropping our spinlock.
|
||||
|
|
|
@ -328,13 +328,14 @@ void hfs_bmap_free(struct hfs_bnode *node)
|
|||
|
||||
nidx -= len * 8;
|
||||
i = node->next;
|
||||
hfs_bnode_put(node);
|
||||
if (!i) {
|
||||
/* panic */;
|
||||
pr_crit("unable to free bnode %u. bmap not found!\n",
|
||||
node->this);
|
||||
hfs_bnode_put(node);
|
||||
return;
|
||||
}
|
||||
hfs_bnode_put(node);
|
||||
node = hfs_bnode_find(tree, i);
|
||||
if (IS_ERR(node))
|
||||
return;
|
||||
|
|
|
@ -453,14 +453,15 @@ void hfs_bmap_free(struct hfs_bnode *node)
|
|||
|
||||
nidx -= len * 8;
|
||||
i = node->next;
|
||||
hfs_bnode_put(node);
|
||||
if (!i) {
|
||||
/* panic */;
|
||||
pr_crit("unable to free bnode %u. "
|
||||
"bmap not found!\n",
|
||||
node->this);
|
||||
hfs_bnode_put(node);
|
||||
return;
|
||||
}
|
||||
hfs_bnode_put(node);
|
||||
node = hfs_bnode_find(tree, i);
|
||||
if (IS_ERR(node))
|
||||
return;
|
||||
|
|
|
@ -118,6 +118,16 @@ static void huge_pagevec_release(struct pagevec *pvec)
|
|||
pagevec_reinit(pvec);
|
||||
}
|
||||
|
||||
/*
|
||||
* Mask used when checking the page offset value passed in via system
|
||||
* calls. This value will be converted to a loff_t which is signed.
|
||||
* Therefore, we want to check the upper PAGE_SHIFT + 1 bits of the
|
||||
* value. The extra bit (- 1 in the shift value) is to take the sign
|
||||
* bit into account.
|
||||
*/
|
||||
#define PGOFF_LOFFT_MAX \
|
||||
(((1UL << (PAGE_SHIFT + 1)) - 1) << (BITS_PER_LONG - (PAGE_SHIFT + 1)))
|
||||
|
||||
static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma)
|
||||
{
|
||||
struct inode *inode = file_inode(file);
|
||||
|
@ -136,17 +146,31 @@ static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma)
|
|||
vma->vm_flags |= VM_HUGETLB | VM_DONTEXPAND;
|
||||
vma->vm_ops = &hugetlb_vm_ops;
|
||||
|
||||
/*
|
||||
* page based offset in vm_pgoff could be sufficiently large to
|
||||
* overflow a loff_t when converted to byte offset. This can
|
||||
* only happen on architectures where sizeof(loff_t) ==
|
||||
* sizeof(unsigned long). So, only check in those instances.
|
||||
*/
|
||||
if (sizeof(unsigned long) == sizeof(loff_t)) {
|
||||
if (vma->vm_pgoff & PGOFF_LOFFT_MAX)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* must be huge page aligned */
|
||||
if (vma->vm_pgoff & (~huge_page_mask(h) >> PAGE_SHIFT))
|
||||
return -EINVAL;
|
||||
|
||||
vma_len = (loff_t)(vma->vm_end - vma->vm_start);
|
||||
len = vma_len + ((loff_t)vma->vm_pgoff << PAGE_SHIFT);
|
||||
/* check for overflow */
|
||||
if (len < vma_len)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&inode->i_mutex);
|
||||
file_accessed(file);
|
||||
|
||||
ret = -ENOMEM;
|
||||
len = vma_len + ((loff_t)vma->vm_pgoff << PAGE_SHIFT);
|
||||
|
||||
if (hugetlb_reserve_pages(inode,
|
||||
vma->vm_pgoff >> huge_page_order(h),
|
||||
len >> huge_page_shift(h), vma,
|
||||
|
@ -155,7 +179,7 @@ static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma)
|
|||
|
||||
ret = 0;
|
||||
if (vma->vm_flags & VM_WRITE && inode->i_size < len)
|
||||
inode->i_size = len;
|
||||
i_size_write(inode, len);
|
||||
out:
|
||||
mutex_unlock(&inode->i_mutex);
|
||||
|
||||
|
|
|
@ -125,10 +125,10 @@ check_err:
|
|||
|
||||
check_gen:
|
||||
if (handle->ih_generation != inode->i_generation) {
|
||||
iput(inode);
|
||||
trace_ocfs2_get_dentry_generation((unsigned long long)blkno,
|
||||
handle->ih_generation,
|
||||
inode->i_generation);
|
||||
iput(inode);
|
||||
result = ERR_PTR(-ESTALE);
|
||||
goto bail;
|
||||
}
|
||||
|
|
|
@ -156,18 +156,14 @@ out:
|
|||
}
|
||||
|
||||
/*
|
||||
* lock allocators, and reserving appropriate number of bits for
|
||||
* meta blocks and data clusters.
|
||||
*
|
||||
* in some cases, we don't need to reserve clusters, just let data_ac
|
||||
* be NULL.
|
||||
* lock allocator, and reserve appropriate number of bits for
|
||||
* meta blocks.
|
||||
*/
|
||||
static int ocfs2_lock_allocators_move_extents(struct inode *inode,
|
||||
static int ocfs2_lock_meta_allocator_move_extents(struct inode *inode,
|
||||
struct ocfs2_extent_tree *et,
|
||||
u32 clusters_to_move,
|
||||
u32 extents_to_split,
|
||||
struct ocfs2_alloc_context **meta_ac,
|
||||
struct ocfs2_alloc_context **data_ac,
|
||||
int extra_blocks,
|
||||
int *credits)
|
||||
{
|
||||
|
@ -192,13 +188,6 @@ static int ocfs2_lock_allocators_move_extents(struct inode *inode,
|
|||
goto out;
|
||||
}
|
||||
|
||||
if (data_ac) {
|
||||
ret = ocfs2_reserve_clusters(osb, clusters_to_move, data_ac);
|
||||
if (ret) {
|
||||
mlog_errno(ret);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
*credits += ocfs2_calc_extend_credits(osb->sb, et->et_root_el);
|
||||
|
||||
|
@ -260,10 +249,10 @@ static int ocfs2_defrag_extent(struct ocfs2_move_extents_context *context,
|
|||
}
|
||||
}
|
||||
|
||||
ret = ocfs2_lock_allocators_move_extents(inode, &context->et, *len, 1,
|
||||
&context->meta_ac,
|
||||
&context->data_ac,
|
||||
extra_blocks, &credits);
|
||||
ret = ocfs2_lock_meta_allocator_move_extents(inode, &context->et,
|
||||
*len, 1,
|
||||
&context->meta_ac,
|
||||
extra_blocks, &credits);
|
||||
if (ret) {
|
||||
mlog_errno(ret);
|
||||
goto out;
|
||||
|
@ -286,6 +275,21 @@ static int ocfs2_defrag_extent(struct ocfs2_move_extents_context *context,
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Make sure ocfs2_reserve_cluster is called after
|
||||
* __ocfs2_flush_truncate_log, otherwise, dead lock may happen.
|
||||
*
|
||||
* If ocfs2_reserve_cluster is called
|
||||
* before __ocfs2_flush_truncate_log, dead lock on global bitmap
|
||||
* may happen.
|
||||
*
|
||||
*/
|
||||
ret = ocfs2_reserve_clusters(osb, *len, &context->data_ac);
|
||||
if (ret) {
|
||||
mlog_errno(ret);
|
||||
goto out_unlock_mutex;
|
||||
}
|
||||
|
||||
handle = ocfs2_start_trans(osb, credits);
|
||||
if (IS_ERR(handle)) {
|
||||
ret = PTR_ERR(handle);
|
||||
|
@ -606,9 +610,10 @@ static int ocfs2_move_extent(struct ocfs2_move_extents_context *context,
|
|||
}
|
||||
}
|
||||
|
||||
ret = ocfs2_lock_allocators_move_extents(inode, &context->et, len, 1,
|
||||
&context->meta_ac,
|
||||
NULL, extra_blocks, &credits);
|
||||
ret = ocfs2_lock_meta_allocator_move_extents(inode, &context->et,
|
||||
len, 1,
|
||||
&context->meta_ac,
|
||||
extra_blocks, &credits);
|
||||
if (ret) {
|
||||
mlog_errno(ret);
|
||||
goto out;
|
||||
|
|
|
@ -255,7 +255,7 @@ static ssize_t proc_pid_cmdline_read(struct file *file, char __user *buf,
|
|||
* Inherently racy -- command line shares address space
|
||||
* with code and data.
|
||||
*/
|
||||
rv = access_remote_vm(mm, arg_end - 1, &c, 1, 0);
|
||||
rv = access_remote_vm(mm, arg_end - 1, &c, 1, FOLL_ANON);
|
||||
if (rv <= 0)
|
||||
goto out_free_page;
|
||||
|
||||
|
@ -273,7 +273,7 @@ static ssize_t proc_pid_cmdline_read(struct file *file, char __user *buf,
|
|||
int nr_read;
|
||||
|
||||
_count = min3(count, len, PAGE_SIZE);
|
||||
nr_read = access_remote_vm(mm, p, page, _count, 0);
|
||||
nr_read = access_remote_vm(mm, p, page, _count, FOLL_ANON);
|
||||
if (nr_read < 0)
|
||||
rv = nr_read;
|
||||
if (nr_read <= 0)
|
||||
|
@ -308,7 +308,7 @@ static ssize_t proc_pid_cmdline_read(struct file *file, char __user *buf,
|
|||
bool final;
|
||||
|
||||
_count = min3(count, len, PAGE_SIZE);
|
||||
nr_read = access_remote_vm(mm, p, page, _count, 0);
|
||||
nr_read = access_remote_vm(mm, p, page, _count, FOLL_ANON);
|
||||
if (nr_read < 0)
|
||||
rv = nr_read;
|
||||
if (nr_read <= 0)
|
||||
|
@ -357,7 +357,7 @@ skip_argv:
|
|||
bool final;
|
||||
|
||||
_count = min3(count, len, PAGE_SIZE);
|
||||
nr_read = access_remote_vm(mm, p, page, _count, 0);
|
||||
nr_read = access_remote_vm(mm, p, page, _count, FOLL_ANON);
|
||||
if (nr_read < 0)
|
||||
rv = nr_read;
|
||||
if (nr_read <= 0)
|
||||
|
@ -869,6 +869,7 @@ static ssize_t mem_rw(struct file *file, char __user *buf,
|
|||
unsigned long addr = *ppos;
|
||||
ssize_t copied;
|
||||
char *page;
|
||||
unsigned int flags;
|
||||
|
||||
if (!mm)
|
||||
return 0;
|
||||
|
@ -881,6 +882,11 @@ static ssize_t mem_rw(struct file *file, char __user *buf,
|
|||
if (!atomic_inc_not_zero(&mm->mm_users))
|
||||
goto free;
|
||||
|
||||
/* Maybe we should limit FOLL_FORCE to actual ptrace users? */
|
||||
flags = FOLL_FORCE;
|
||||
if (write)
|
||||
flags |= FOLL_WRITE;
|
||||
|
||||
while (count > 0) {
|
||||
int this_len = min_t(int, count, PAGE_SIZE);
|
||||
|
||||
|
@ -889,7 +895,7 @@ static ssize_t mem_rw(struct file *file, char __user *buf,
|
|||
break;
|
||||
}
|
||||
|
||||
this_len = access_remote_vm(mm, addr, page, this_len, write);
|
||||
this_len = access_remote_vm(mm, addr, page, this_len, flags);
|
||||
if (!this_len) {
|
||||
if (!copied)
|
||||
copied = -EIO;
|
||||
|
@ -1001,8 +1007,7 @@ static ssize_t environ_read(struct file *file, char __user *buf,
|
|||
max_len = min_t(size_t, PAGE_SIZE, count);
|
||||
this_len = min(max_len, this_len);
|
||||
|
||||
retval = access_remote_vm(mm, (env_start + src),
|
||||
page, this_len, 0);
|
||||
retval = access_remote_vm(mm, (env_start + src), page, this_len, FOLL_ANON);
|
||||
|
||||
if (retval <= 0) {
|
||||
ret = retval;
|
||||
|
|
|
@ -141,7 +141,7 @@ static void seq_print_vma_name(struct seq_file *m, struct vm_area_struct *vma)
|
|||
struct page *page;
|
||||
|
||||
pages_pinned = get_user_pages(current, mm, page_start_vaddr,
|
||||
1, 0, 0, &page, NULL);
|
||||
1, 0, &page, NULL);
|
||||
if (pages_pinned < 1) {
|
||||
seq_puts(m, "<fault>]");
|
||||
return;
|
||||
|
|
|
@ -392,8 +392,8 @@ static void pstore_console_write(struct console *con, const char *s, unsigned c)
|
|||
} else {
|
||||
spin_lock_irqsave(&psinfo->buf_lock, flags);
|
||||
}
|
||||
memcpy(psinfo->buf, s, c);
|
||||
psinfo->write(PSTORE_TYPE_CONSOLE, 0, &id, 0, 0, 0, c, psinfo);
|
||||
psinfo->write_buf(PSTORE_TYPE_CONSOLE, 0, &id, 0,
|
||||
s, 0, c, psinfo);
|
||||
spin_unlock_irqrestore(&psinfo->buf_lock, flags);
|
||||
s += c;
|
||||
c = e - s;
|
||||
|
|
|
@ -275,7 +275,7 @@ static int __sysv_write_inode(struct inode *inode, int wait)
|
|||
}
|
||||
}
|
||||
brelse(bh);
|
||||
return 0;
|
||||
return err;
|
||||
}
|
||||
|
||||
int sysv_write_inode(struct inode *inode, struct writeback_control *wbc)
|
||||
|
|
|
@ -1207,7 +1207,7 @@ static inline int fixup_user_fault(struct task_struct *tsk,
|
|||
|
||||
extern int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, int len, int write);
|
||||
extern int access_remote_vm(struct mm_struct *mm, unsigned long addr,
|
||||
void *buf, int len, int write);
|
||||
void *buf, int len, unsigned int gup_flags);
|
||||
|
||||
long __get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
|
||||
unsigned long start, unsigned long nr_pages,
|
||||
|
@ -1215,19 +1215,17 @@ long __get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
|
|||
struct vm_area_struct **vmas, int *nonblocking);
|
||||
long get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
|
||||
unsigned long start, unsigned long nr_pages,
|
||||
int write, int force, struct page **pages,
|
||||
unsigned int gup_flags, struct page **pages,
|
||||
struct vm_area_struct **vmas);
|
||||
long get_user_pages_locked(struct task_struct *tsk, struct mm_struct *mm,
|
||||
unsigned long start, unsigned long nr_pages,
|
||||
int write, int force, struct page **pages,
|
||||
int *locked);
|
||||
unsigned int gup_flags, struct page **pages, int *locked);
|
||||
long __get_user_pages_unlocked(struct task_struct *tsk, struct mm_struct *mm,
|
||||
unsigned long start, unsigned long nr_pages,
|
||||
int write, int force, struct page **pages,
|
||||
unsigned int gup_flags);
|
||||
struct page **pages, unsigned int gup_flags);
|
||||
long get_user_pages_unlocked(struct task_struct *tsk, struct mm_struct *mm,
|
||||
unsigned long start, unsigned long nr_pages,
|
||||
int write, int force, struct page **pages);
|
||||
struct page **pages, unsigned int gup_flags);
|
||||
int get_user_pages_fast(unsigned long start, int nr_pages, int write,
|
||||
struct page **pages);
|
||||
|
||||
|
@ -1245,7 +1243,7 @@ struct frame_vector {
|
|||
struct frame_vector *frame_vector_create(unsigned int nr_frames);
|
||||
void frame_vector_destroy(struct frame_vector *vec);
|
||||
int get_vaddr_frames(unsigned long start, unsigned int nr_pfns,
|
||||
bool write, bool force, struct frame_vector *vec);
|
||||
unsigned int gup_flags, struct frame_vector *vec);
|
||||
void put_vaddr_frames(struct frame_vector *vec);
|
||||
int frame_vector_to_pages(struct frame_vector *vec);
|
||||
void frame_vector_to_pfns(struct frame_vector *vec);
|
||||
|
@ -2138,6 +2136,7 @@ static inline struct page *follow_page(struct vm_area_struct *vma,
|
|||
#define FOLL_TRIED 0x800 /* a retry, previous pass started an IO */
|
||||
#define FOLL_MLOCK 0x1000 /* lock present pages */
|
||||
#define FOLL_COW 0x4000 /* internal GUP flag */
|
||||
#define FOLL_ANON 0x8000 /* don't do file mappings */
|
||||
|
||||
typedef int (*pte_fn_t)(pte_t *pte, pgtable_t token, unsigned long addr,
|
||||
void *data);
|
||||
|
|
|
@ -65,8 +65,8 @@ struct k_itimer {
|
|||
spinlock_t it_lock;
|
||||
clockid_t it_clock; /* which timer type */
|
||||
timer_t it_id; /* timer id */
|
||||
int it_overrun; /* overrun on pending signal */
|
||||
int it_overrun_last; /* overrun on last delivered signal */
|
||||
s64 it_overrun; /* overrun on pending signal */
|
||||
s64 it_overrun_last; /* overrun on last delivered signal */
|
||||
int it_requeue_pending; /* waiting to requeue this timer */
|
||||
#define REQUEUE_PENDING 1
|
||||
int it_sigev_notify; /* notify word of sigevent struct */
|
||||
|
|
|
@ -448,6 +448,7 @@ static inline int neigh_hh_bridge(struct hh_cache *hh, struct sk_buff *skb)
|
|||
|
||||
static inline int neigh_hh_output(const struct hh_cache *hh, struct sk_buff *skb)
|
||||
{
|
||||
unsigned int hh_alen = 0;
|
||||
unsigned int seq;
|
||||
int hh_len;
|
||||
|
||||
|
@ -455,16 +456,33 @@ static inline int neigh_hh_output(const struct hh_cache *hh, struct sk_buff *skb
|
|||
seq = read_seqbegin(&hh->hh_lock);
|
||||
hh_len = hh->hh_len;
|
||||
if (likely(hh_len <= HH_DATA_MOD)) {
|
||||
/* this is inlined by gcc */
|
||||
memcpy(skb->data - HH_DATA_MOD, hh->hh_data, HH_DATA_MOD);
|
||||
} else {
|
||||
int hh_alen = HH_DATA_ALIGN(hh_len);
|
||||
hh_alen = HH_DATA_MOD;
|
||||
|
||||
memcpy(skb->data - hh_alen, hh->hh_data, hh_alen);
|
||||
/* skb_push() would proceed silently if we have room for
|
||||
* the unaligned size but not for the aligned size:
|
||||
* check headroom explicitly.
|
||||
*/
|
||||
if (likely(skb_headroom(skb) >= HH_DATA_MOD)) {
|
||||
/* this is inlined by gcc */
|
||||
memcpy(skb->data - HH_DATA_MOD, hh->hh_data,
|
||||
HH_DATA_MOD);
|
||||
}
|
||||
} else {
|
||||
hh_alen = HH_DATA_ALIGN(hh_len);
|
||||
|
||||
if (likely(skb_headroom(skb) >= hh_alen)) {
|
||||
memcpy(skb->data - hh_alen, hh->hh_data,
|
||||
hh_alen);
|
||||
}
|
||||
}
|
||||
} while (read_seqretry(&hh->hh_lock, seq));
|
||||
|
||||
skb_push(skb, hh_len);
|
||||
if (WARN_ON_ONCE(skb_headroom(skb) < hh_alen)) {
|
||||
kfree_skb(skb);
|
||||
return NET_XMIT_DROP;
|
||||
}
|
||||
|
||||
__skb_push(skb, hh_len);
|
||||
return dev_queue_xmit(skb);
|
||||
}
|
||||
|
||||
|
|
|
@ -100,7 +100,7 @@ struct snd_pcm_ops {
|
|||
#endif
|
||||
|
||||
#define SNDRV_PCM_IOCTL1_RESET 0
|
||||
#define SNDRV_PCM_IOCTL1_INFO 1
|
||||
/* 1 is absent slot. */
|
||||
#define SNDRV_PCM_IOCTL1_CHANNEL_INFO 2
|
||||
#define SNDRV_PCM_IOCTL1_GSTATE 3
|
||||
#define SNDRV_PCM_IOCTL1_FIFO_SIZE 4
|
||||
|
|
|
@ -191,6 +191,7 @@ struct bpf_insn_aux_data {
|
|||
enum bpf_reg_type ptr_type; /* pointer type for load/store insns */
|
||||
struct bpf_map *map_ptr; /* pointer for call insn into lookup_elem */
|
||||
};
|
||||
int sanitize_stack_off; /* stack slot to be cleared */
|
||||
bool seen; /* this insn was processed by the verifier */
|
||||
};
|
||||
|
||||
|
@ -569,10 +570,11 @@ static bool is_spillable_regtype(enum bpf_reg_type type)
|
|||
/* check_stack_read/write functions track spill/fill of registers,
|
||||
* stack boundary and alignment are checked in check_mem_access()
|
||||
*/
|
||||
static int check_stack_write(struct verifier_state *state, int off, int size,
|
||||
int value_regno)
|
||||
static int check_stack_write(struct verifier_env *env,
|
||||
struct verifier_state *state, int off,
|
||||
int size, int value_regno, int insn_idx)
|
||||
{
|
||||
int i;
|
||||
int i, spi = (MAX_BPF_STACK + off) / BPF_REG_SIZE;
|
||||
/* caller checked that off % size == 0 and -MAX_BPF_STACK <= off < 0,
|
||||
* so it's aligned access and [off, off + size) are within stack limits
|
||||
*/
|
||||
|
@ -587,15 +589,37 @@ static int check_stack_write(struct verifier_state *state, int off, int size,
|
|||
}
|
||||
|
||||
/* save register state */
|
||||
state->spilled_regs[(MAX_BPF_STACK + off) / BPF_REG_SIZE] =
|
||||
state->regs[value_regno];
|
||||
state->spilled_regs[spi] = state->regs[value_regno];
|
||||
|
||||
for (i = 0; i < BPF_REG_SIZE; i++)
|
||||
for (i = 0; i < BPF_REG_SIZE; i++) {
|
||||
if (state->stack_slot_type[MAX_BPF_STACK + off + i] == STACK_MISC &&
|
||||
!env->allow_ptr_leaks) {
|
||||
int *poff = &env->insn_aux_data[insn_idx].sanitize_stack_off;
|
||||
int soff = (-spi - 1) * BPF_REG_SIZE;
|
||||
|
||||
/* detected reuse of integer stack slot with a pointer
|
||||
* which means either llvm is reusing stack slot or
|
||||
* an attacker is trying to exploit CVE-2018-3639
|
||||
* (speculative store bypass)
|
||||
* Have to sanitize that slot with preemptive
|
||||
* store of zero.
|
||||
*/
|
||||
if (*poff && *poff != soff) {
|
||||
/* disallow programs where single insn stores
|
||||
* into two different stack slots, since verifier
|
||||
* cannot sanitize them
|
||||
*/
|
||||
verbose("insn %d cannot access two stack slots fp%d and fp%d",
|
||||
insn_idx, *poff, soff);
|
||||
return -EINVAL;
|
||||
}
|
||||
*poff = soff;
|
||||
}
|
||||
state->stack_slot_type[MAX_BPF_STACK + off + i] = STACK_SPILL;
|
||||
}
|
||||
} else {
|
||||
/* regular write of data into stack */
|
||||
state->spilled_regs[(MAX_BPF_STACK + off) / BPF_REG_SIZE] =
|
||||
(struct reg_state) {};
|
||||
state->spilled_regs[spi] = (struct reg_state) {};
|
||||
|
||||
for (i = 0; i < size; i++)
|
||||
state->stack_slot_type[MAX_BPF_STACK + off + i] = STACK_MISC;
|
||||
|
@ -696,7 +720,7 @@ static bool is_ctx_reg(struct verifier_env *env, int regno)
|
|||
* if t==write && value_regno==-1, some unknown value is stored into memory
|
||||
* if t==read && value_regno==-1, don't care what we read from memory
|
||||
*/
|
||||
static int check_mem_access(struct verifier_env *env, u32 regno, int off,
|
||||
static int check_mem_access(struct verifier_env *env, int insn_idx, u32 regno, int off,
|
||||
int bpf_size, enum bpf_access_type t,
|
||||
int value_regno)
|
||||
{
|
||||
|
@ -748,7 +772,8 @@ static int check_mem_access(struct verifier_env *env, u32 regno, int off,
|
|||
verbose("attempt to corrupt spilled pointer on stack\n");
|
||||
return -EACCES;
|
||||
}
|
||||
err = check_stack_write(state, off, size, value_regno);
|
||||
err = check_stack_write(env, state, off, size,
|
||||
value_regno, insn_idx);
|
||||
} else {
|
||||
err = check_stack_read(state, off, size, value_regno);
|
||||
}
|
||||
|
@ -760,7 +785,7 @@ static int check_mem_access(struct verifier_env *env, u32 regno, int off,
|
|||
return err;
|
||||
}
|
||||
|
||||
static int check_xadd(struct verifier_env *env, struct bpf_insn *insn)
|
||||
static int check_xadd(struct verifier_env *env, int insn_idx, struct bpf_insn *insn)
|
||||
{
|
||||
struct reg_state *regs = env->cur_state.regs;
|
||||
int err;
|
||||
|
@ -793,13 +818,13 @@ static int check_xadd(struct verifier_env *env, struct bpf_insn *insn)
|
|||
}
|
||||
|
||||
/* check whether atomic_add can read the memory */
|
||||
err = check_mem_access(env, insn->dst_reg, insn->off,
|
||||
err = check_mem_access(env, insn_idx, insn->dst_reg, insn->off,
|
||||
BPF_SIZE(insn->code), BPF_READ, -1);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* check whether atomic_add can write into the same memory */
|
||||
return check_mem_access(env, insn->dst_reg, insn->off,
|
||||
return check_mem_access(env, insn_idx, insn->dst_reg, insn->off,
|
||||
BPF_SIZE(insn->code), BPF_WRITE, -1);
|
||||
}
|
||||
|
||||
|
@ -1838,13 +1863,14 @@ static int do_check(struct verifier_env *env)
|
|||
/* check that memory (src_reg + off) is readable,
|
||||
* the state of dst_reg will be updated by this func
|
||||
*/
|
||||
err = check_mem_access(env, insn->src_reg, insn->off,
|
||||
err = check_mem_access(env, insn_idx, insn->src_reg, insn->off,
|
||||
BPF_SIZE(insn->code), BPF_READ,
|
||||
insn->dst_reg);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (BPF_SIZE(insn->code) != BPF_W) {
|
||||
if (BPF_SIZE(insn->code) != BPF_W &&
|
||||
BPF_SIZE(insn->code) != BPF_DW) {
|
||||
insn_idx++;
|
||||
continue;
|
||||
}
|
||||
|
@ -1876,7 +1902,7 @@ static int do_check(struct verifier_env *env)
|
|||
enum bpf_reg_type *prev_dst_type, dst_reg_type;
|
||||
|
||||
if (BPF_MODE(insn->code) == BPF_XADD) {
|
||||
err = check_xadd(env, insn);
|
||||
err = check_xadd(env, insn_idx, insn);
|
||||
if (err)
|
||||
return err;
|
||||
insn_idx++;
|
||||
|
@ -1895,7 +1921,7 @@ static int do_check(struct verifier_env *env)
|
|||
dst_reg_type = regs[insn->dst_reg].type;
|
||||
|
||||
/* check that memory (dst_reg + off) is writeable */
|
||||
err = check_mem_access(env, insn->dst_reg, insn->off,
|
||||
err = check_mem_access(env, insn_idx, insn->dst_reg, insn->off,
|
||||
BPF_SIZE(insn->code), BPF_WRITE,
|
||||
insn->src_reg);
|
||||
if (err)
|
||||
|
@ -1930,7 +1956,7 @@ static int do_check(struct verifier_env *env)
|
|||
}
|
||||
|
||||
/* check that memory (dst_reg + off) is writeable */
|
||||
err = check_mem_access(env, insn->dst_reg, insn->off,
|
||||
err = check_mem_access(env, insn_idx, insn->dst_reg, insn->off,
|
||||
BPF_SIZE(insn->code), BPF_WRITE,
|
||||
-1);
|
||||
if (err)
|
||||
|
@ -2220,13 +2246,43 @@ static int convert_ctx_accesses(struct verifier_env *env)
|
|||
for (i = 0; i < insn_cnt; i++, insn++) {
|
||||
u32 cnt;
|
||||
|
||||
if (insn->code == (BPF_LDX | BPF_MEM | BPF_W))
|
||||
if (insn->code == (BPF_LDX | BPF_MEM | BPF_W) ||
|
||||
insn->code == (BPF_LDX | BPF_MEM | BPF_DW))
|
||||
type = BPF_READ;
|
||||
else if (insn->code == (BPF_STX | BPF_MEM | BPF_W))
|
||||
else if (insn->code == (BPF_STX | BPF_MEM | BPF_W) ||
|
||||
insn->code == (BPF_STX | BPF_MEM | BPF_DW))
|
||||
type = BPF_WRITE;
|
||||
else
|
||||
continue;
|
||||
|
||||
if (type == BPF_WRITE &&
|
||||
env->insn_aux_data[i + delta].sanitize_stack_off) {
|
||||
struct bpf_insn patch[] = {
|
||||
/* Sanitize suspicious stack slot with zero.
|
||||
* There are no memory dependencies for this store,
|
||||
* since it's only using frame pointer and immediate
|
||||
* constant of zero
|
||||
*/
|
||||
BPF_ST_MEM(BPF_DW, BPF_REG_FP,
|
||||
env->insn_aux_data[i + delta].sanitize_stack_off,
|
||||
0),
|
||||
/* the original STX instruction will immediately
|
||||
* overwrite the same stack slot with appropriate value
|
||||
*/
|
||||
*insn,
|
||||
};
|
||||
|
||||
cnt = ARRAY_SIZE(patch);
|
||||
new_prog = bpf_patch_insn_data(env, i + delta, patch, cnt);
|
||||
if (!new_prog)
|
||||
return -ENOMEM;
|
||||
|
||||
delta += cnt - 1;
|
||||
env->prog = new_prog;
|
||||
insn = new_prog->insnsi + i + delta;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (env->insn_aux_data[i + delta].ptr_type != PTR_TO_CTX)
|
||||
continue;
|
||||
|
||||
|
|
|
@ -299,7 +299,7 @@ int uprobe_write_opcode(struct mm_struct *mm, unsigned long vaddr,
|
|||
|
||||
retry:
|
||||
/* Read the page with vaddr into memory */
|
||||
ret = get_user_pages(NULL, mm, vaddr, 1, 0, 1, &old_page, &vma);
|
||||
ret = get_user_pages(NULL, mm, vaddr, 1, FOLL_FORCE, &old_page, &vma);
|
||||
if (ret <= 0)
|
||||
return ret;
|
||||
|
||||
|
@ -1700,7 +1700,7 @@ static int is_trap_at_addr(struct mm_struct *mm, unsigned long vaddr)
|
|||
if (likely(result == 0))
|
||||
goto out;
|
||||
|
||||
result = get_user_pages(NULL, mm, vaddr, 1, 0, 1, &page, NULL);
|
||||
result = get_user_pages(NULL, mm, vaddr, 1, FOLL_FORCE, &page, NULL);
|
||||
if (result < 0)
|
||||
return result;
|
||||
|
||||
|
|
|
@ -103,7 +103,7 @@ static void bump_cpu_timer(struct k_itimer *timer,
|
|||
continue;
|
||||
|
||||
timer->it.cpu.expires += incr;
|
||||
timer->it_overrun += 1 << i;
|
||||
timer->it_overrun += 1LL << i;
|
||||
delta -= incr;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -355,6 +355,17 @@ static __init int init_posix_timers(void)
|
|||
|
||||
__initcall(init_posix_timers);
|
||||
|
||||
/*
|
||||
* The siginfo si_overrun field and the return value of timer_getoverrun(2)
|
||||
* are of type int. Clamp the overrun value to INT_MAX
|
||||
*/
|
||||
static inline int timer_overrun_to_int(struct k_itimer *timr, int baseval)
|
||||
{
|
||||
s64 sum = timr->it_overrun_last + (s64)baseval;
|
||||
|
||||
return sum > (s64)INT_MAX ? INT_MAX : (int)sum;
|
||||
}
|
||||
|
||||
static void schedule_next_timer(struct k_itimer *timr)
|
||||
{
|
||||
struct hrtimer *timer = &timr->it.real.timer;
|
||||
|
@ -362,12 +373,11 @@ static void schedule_next_timer(struct k_itimer *timr)
|
|||
if (timr->it.real.interval.tv64 == 0)
|
||||
return;
|
||||
|
||||
timr->it_overrun += (unsigned int) hrtimer_forward(timer,
|
||||
timer->base->get_time(),
|
||||
timr->it.real.interval);
|
||||
timr->it_overrun += hrtimer_forward(timer, timer->base->get_time(),
|
||||
timr->it.real.interval);
|
||||
|
||||
timr->it_overrun_last = timr->it_overrun;
|
||||
timr->it_overrun = -1;
|
||||
timr->it_overrun = -1LL;
|
||||
++timr->it_requeue_pending;
|
||||
hrtimer_restart(timer);
|
||||
}
|
||||
|
@ -396,7 +406,7 @@ void do_schedule_next_timer(struct siginfo *info)
|
|||
else
|
||||
schedule_next_timer(timr);
|
||||
|
||||
info->si_overrun += timr->it_overrun_last;
|
||||
info->si_overrun = timer_overrun_to_int(timr, info->si_overrun);
|
||||
}
|
||||
|
||||
if (timr)
|
||||
|
@ -491,8 +501,7 @@ static enum hrtimer_restart posix_timer_fn(struct hrtimer *timer)
|
|||
now = ktime_add(now, kj);
|
||||
}
|
||||
#endif
|
||||
timr->it_overrun += (unsigned int)
|
||||
hrtimer_forward(timer, now,
|
||||
timr->it_overrun += hrtimer_forward(timer, now,
|
||||
timr->it.real.interval);
|
||||
ret = HRTIMER_RESTART;
|
||||
++timr->it_requeue_pending;
|
||||
|
@ -633,7 +642,7 @@ SYSCALL_DEFINE3(timer_create, const clockid_t, which_clock,
|
|||
it_id_set = IT_ID_SET;
|
||||
new_timer->it_id = (timer_t) new_timer_id;
|
||||
new_timer->it_clock = which_clock;
|
||||
new_timer->it_overrun = -1;
|
||||
new_timer->it_overrun = -1LL;
|
||||
|
||||
if (timer_event_spec) {
|
||||
if (copy_from_user(&event, timer_event_spec, sizeof (event))) {
|
||||
|
@ -762,7 +771,7 @@ common_timer_get(struct k_itimer *timr, struct itimerspec *cur_setting)
|
|||
*/
|
||||
if (iv.tv64 && (timr->it_requeue_pending & REQUEUE_PENDING ||
|
||||
timr->it_sigev_notify == SIGEV_NONE))
|
||||
timr->it_overrun += (unsigned int) hrtimer_forward(timer, now, iv);
|
||||
timr->it_overrun += hrtimer_forward(timer, now, iv);
|
||||
|
||||
remaining = __hrtimer_expires_remaining_adjusted(timer, now);
|
||||
/* Return 0 only, when the timer is expired and not pending */
|
||||
|
@ -824,7 +833,7 @@ SYSCALL_DEFINE1(timer_getoverrun, timer_t, timer_id)
|
|||
if (!timr)
|
||||
return -EINVAL;
|
||||
|
||||
overrun = timr->it_overrun_last;
|
||||
overrun = timer_overrun_to_int(timr, 0);
|
||||
unlock_timer(timr, flags);
|
||||
|
||||
return overrun;
|
||||
|
|
|
@ -119,11 +119,13 @@ static u64 bpf_trace_printk(u64 r1, u64 fmt_size, u64 r3, u64 r4, u64 r5)
|
|||
i++;
|
||||
} else if (fmt[i] == 'p' || fmt[i] == 's') {
|
||||
mod[fmt_cnt]++;
|
||||
i++;
|
||||
if (!isspace(fmt[i]) && !ispunct(fmt[i]) && fmt[i] != 0)
|
||||
/* disallow any further format extensions */
|
||||
if (fmt[i + 1] != 0 &&
|
||||
!isspace(fmt[i + 1]) &&
|
||||
!ispunct(fmt[i + 1]))
|
||||
return -EINVAL;
|
||||
fmt_cnt++;
|
||||
if (fmt[i - 1] == 's') {
|
||||
if (fmt[i] == 's') {
|
||||
if (str_seen)
|
||||
/* allow only one '%s' per fmt string */
|
||||
return -EINVAL;
|
||||
|
|
|
@ -1088,7 +1088,8 @@ void __init debug_objects_mem_init(void)
|
|||
|
||||
obj_cache = kmem_cache_create("debug_objects_cache",
|
||||
sizeof (struct debug_obj), 0,
|
||||
SLAB_DEBUG_OBJECTS, NULL);
|
||||
SLAB_DEBUG_OBJECTS | SLAB_NOLEAKTRACE,
|
||||
NULL);
|
||||
|
||||
if (!obj_cache || debug_objects_replace_static_objects()) {
|
||||
debug_objects_enabled = 0;
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue