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 \
|
subdir-y := accounting auxdisplay blackfin connector \
|
||||||
filesystems filesystems ia64 laptops misc-devices \
|
filesystems filesystems ia64 laptops misc-devices \
|
||||||
networking pcmcia prctl ptp spi timers vDSO video4linux \
|
pcmcia prctl ptp spi timers vDSO video4linux watchdog
|
||||||
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
|
VERSION = 4
|
||||||
PATCHLEVEL = 4
|
PATCHLEVEL = 4
|
||||||
SUBLEVEL = 167
|
SUBLEVEL = 168
|
||||||
EXTRAVERSION =
|
EXTRAVERSION =
|
||||||
NAME = Blurry Fish Butt
|
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;
|
struct modem_private_data *priv = port->private_data;
|
||||||
|
|
||||||
|
if (!priv)
|
||||||
|
return;
|
||||||
|
|
||||||
if (IS_ERR(priv->regulator))
|
if (IS_ERR(priv->regulator))
|
||||||
return;
|
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
|
* to occur, WAKEUPENABLE bits must be set in the pad mux registers, and
|
||||||
* omap44xx_prm_reconfigure_io_chain() must be called. No return value.
|
* 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();
|
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),
|
(unsigned long int)(oper.indata + prev_ix),
|
||||||
noinpages,
|
noinpages,
|
||||||
0, /* read access only for in data */
|
0, /* read access only for in data */
|
||||||
0, /* no force */
|
|
||||||
inpages,
|
inpages,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
|
@ -2740,8 +2739,7 @@ static int cryptocop_ioctl_process(struct inode *inode, struct file *filp, unsig
|
||||||
current->mm,
|
current->mm,
|
||||||
(unsigned long int)oper.cipher_outdata,
|
(unsigned long int)oper.cipher_outdata,
|
||||||
nooutpages,
|
nooutpages,
|
||||||
1, /* write access for out data */
|
FOLL_WRITE, /* write access for out data */
|
||||||
0, /* no force */
|
|
||||||
outpages,
|
outpages,
|
||||||
NULL);
|
NULL);
|
||||||
up_read(¤t->mm->mmap_sem);
|
up_read(¤t->mm->mmap_sem);
|
||||||
|
|
|
@ -143,7 +143,7 @@ store_virtual_to_phys(struct device *dev, struct device_attribute *attr,
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = get_user_pages(current, current->mm, virt_addr,
|
ret = get_user_pages(current, current->mm, virt_addr,
|
||||||
1, VM_READ, 0, NULL, NULL);
|
1, FOLL_WRITE, NULL, NULL);
|
||||||
if (ret<=0) {
|
if (ret<=0) {
|
||||||
#ifdef ERR_INJ_DEBUG
|
#ifdef ERR_INJ_DEBUG
|
||||||
printk("Virtual address %lx is not existing.\n",virt_addr);
|
printk("Virtual address %lx is not existing.\n",virt_addr);
|
||||||
|
|
|
@ -303,7 +303,7 @@ slow_irqon:
|
||||||
|
|
||||||
ret = get_user_pages_unlocked(current, mm, start,
|
ret = get_user_pages_unlocked(current, mm, start,
|
||||||
(end - start) >> PAGE_SHIFT,
|
(end - start) >> PAGE_SHIFT,
|
||||||
write, 0, pages);
|
pages, write ? FOLL_WRITE : 0);
|
||||||
|
|
||||||
/* Have to be a bit careful with return values */
|
/* Have to be a bit careful with return values */
|
||||||
if (nr > 0) {
|
if (nr > 0) {
|
||||||
|
|
|
@ -344,6 +344,8 @@ static int __hw_perf_event_init(struct perf_event *event)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PERF_TYPE_HARDWARE:
|
case PERF_TYPE_HARDWARE:
|
||||||
|
if (is_sampling_event(event)) /* No sampling support */
|
||||||
|
return -ENOENT;
|
||||||
ev = attr->config;
|
ev = attr->config;
|
||||||
/* Count user space (problem-state) only */
|
/* Count user space (problem-state) only */
|
||||||
if (!attr->exclude_user && attr->exclude_kernel) {
|
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;
|
start += nr << PAGE_SHIFT;
|
||||||
pages += nr;
|
pages += nr;
|
||||||
ret = get_user_pages_unlocked(current, mm, start,
|
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 */
|
/* Have to be a bit careful with return values */
|
||||||
if (nr > 0)
|
if (nr > 0)
|
||||||
ret = (ret < 0) ? nr : ret + nr;
|
ret = (ret < 0) ? nr : ret + nr;
|
||||||
|
|
|
@ -258,7 +258,8 @@ slow_irqon:
|
||||||
pages += nr;
|
pages += nr;
|
||||||
|
|
||||||
ret = get_user_pages_unlocked(current, mm, start,
|
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 */
|
/* Have to be a bit careful with return values */
|
||||||
if (nr > 0) {
|
if (nr > 0) {
|
||||||
|
|
|
@ -250,7 +250,8 @@ slow:
|
||||||
pages += nr;
|
pages += nr;
|
||||||
|
|
||||||
ret = get_user_pages_unlocked(current, mm, start,
|
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 */
|
/* Have to be a bit careful with return values */
|
||||||
if (nr > 0) {
|
if (nr > 0) {
|
||||||
|
|
|
@ -765,7 +765,7 @@ struct kvm_x86_ops {
|
||||||
int (*hardware_setup)(void); /* __init */
|
int (*hardware_setup)(void); /* __init */
|
||||||
void (*hardware_unsetup)(void); /* __exit */
|
void (*hardware_unsetup)(void); /* __exit */
|
||||||
bool (*cpu_has_accelerated_tpr)(void);
|
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);
|
void (*cpuid_update)(struct kvm_vcpu *vcpu);
|
||||||
|
|
||||||
/* Create, but do not attach this VCPU */
|
/* Create, but do not attach this VCPU */
|
||||||
|
|
|
@ -151,6 +151,11 @@ extern int __get_user_bad(void);
|
||||||
|
|
||||||
#define __uaccess_begin() stac()
|
#define __uaccess_begin() stac()
|
||||||
#define __uaccess_end() clac()
|
#define __uaccess_end() clac()
|
||||||
|
#define __uaccess_begin_nospec() \
|
||||||
|
({ \
|
||||||
|
stac(); \
|
||||||
|
barrier_nospec(); \
|
||||||
|
})
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is a type: either unsigned long, if the argument fits into
|
* This is a type: either unsigned long, if the argument fits into
|
||||||
|
@ -436,7 +441,7 @@ do { \
|
||||||
({ \
|
({ \
|
||||||
int __gu_err; \
|
int __gu_err; \
|
||||||
unsigned long __gu_val; \
|
unsigned long __gu_val; \
|
||||||
__uaccess_begin(); \
|
__uaccess_begin_nospec(); \
|
||||||
__get_user_size(__gu_val, (ptr), (size), __gu_err, -EFAULT); \
|
__get_user_size(__gu_val, (ptr), (size), __gu_err, -EFAULT); \
|
||||||
__uaccess_end(); \
|
__uaccess_end(); \
|
||||||
(x) = (__force __typeof__(*(ptr)))__gu_val; \
|
(x) = (__force __typeof__(*(ptr)))__gu_val; \
|
||||||
|
@ -478,6 +483,10 @@ struct __large_struct { unsigned long buf[100]; };
|
||||||
__uaccess_begin(); \
|
__uaccess_begin(); \
|
||||||
barrier();
|
barrier();
|
||||||
|
|
||||||
|
#define uaccess_try_nospec do { \
|
||||||
|
current_thread_info()->uaccess_err = 0; \
|
||||||
|
__uaccess_begin_nospec(); \
|
||||||
|
|
||||||
#define uaccess_catch(err) \
|
#define uaccess_catch(err) \
|
||||||
__uaccess_end(); \
|
__uaccess_end(); \
|
||||||
(err) |= (current_thread_info()->uaccess_err ? -EFAULT : 0); \
|
(err) |= (current_thread_info()->uaccess_err ? -EFAULT : 0); \
|
||||||
|
@ -542,7 +551,7 @@ struct __large_struct { unsigned long buf[100]; };
|
||||||
* get_user_ex(...);
|
* get_user_ex(...);
|
||||||
* } get_user_catch(err)
|
* } 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_catch(err) uaccess_catch(err)
|
||||||
|
|
||||||
#define get_user_ex(x, ptr) do { \
|
#define get_user_ex(x, ptr) do { \
|
||||||
|
@ -577,7 +586,7 @@ extern void __cmpxchg_wrong_size(void)
|
||||||
__typeof__(ptr) __uval = (uval); \
|
__typeof__(ptr) __uval = (uval); \
|
||||||
__typeof__(*(ptr)) __old = (old); \
|
__typeof__(*(ptr)) __old = (old); \
|
||||||
__typeof__(*(ptr)) __new = (new); \
|
__typeof__(*(ptr)) __new = (new); \
|
||||||
__uaccess_begin(); \
|
__uaccess_begin_nospec(); \
|
||||||
switch (size) { \
|
switch (size) { \
|
||||||
case 1: \
|
case 1: \
|
||||||
{ \
|
{ \
|
||||||
|
|
|
@ -49,25 +49,25 @@ __copy_to_user_inatomic(void __user *to, const void *from, unsigned long n)
|
||||||
|
|
||||||
switch (n) {
|
switch (n) {
|
||||||
case 1:
|
case 1:
|
||||||
__uaccess_begin();
|
__uaccess_begin_nospec();
|
||||||
__put_user_size(*(u8 *)from, (u8 __user *)to,
|
__put_user_size(*(u8 *)from, (u8 __user *)to,
|
||||||
1, ret, 1);
|
1, ret, 1);
|
||||||
__uaccess_end();
|
__uaccess_end();
|
||||||
return ret;
|
return ret;
|
||||||
case 2:
|
case 2:
|
||||||
__uaccess_begin();
|
__uaccess_begin_nospec();
|
||||||
__put_user_size(*(u16 *)from, (u16 __user *)to,
|
__put_user_size(*(u16 *)from, (u16 __user *)to,
|
||||||
2, ret, 2);
|
2, ret, 2);
|
||||||
__uaccess_end();
|
__uaccess_end();
|
||||||
return ret;
|
return ret;
|
||||||
case 4:
|
case 4:
|
||||||
__uaccess_begin();
|
__uaccess_begin_nospec();
|
||||||
__put_user_size(*(u32 *)from, (u32 __user *)to,
|
__put_user_size(*(u32 *)from, (u32 __user *)to,
|
||||||
4, ret, 4);
|
4, ret, 4);
|
||||||
__uaccess_end();
|
__uaccess_end();
|
||||||
return ret;
|
return ret;
|
||||||
case 8:
|
case 8:
|
||||||
__uaccess_begin();
|
__uaccess_begin_nospec();
|
||||||
__put_user_size(*(u64 *)from, (u64 __user *)to,
|
__put_user_size(*(u64 *)from, (u64 __user *)to,
|
||||||
8, ret, 8);
|
8, ret, 8);
|
||||||
__uaccess_end();
|
__uaccess_end();
|
||||||
|
@ -112,17 +112,17 @@ __copy_from_user_inatomic(void *to, const void __user *from, unsigned long n)
|
||||||
|
|
||||||
switch (n) {
|
switch (n) {
|
||||||
case 1:
|
case 1:
|
||||||
__uaccess_begin();
|
__uaccess_begin_nospec();
|
||||||
__get_user_size(*(u8 *)to, from, 1, ret, 1);
|
__get_user_size(*(u8 *)to, from, 1, ret, 1);
|
||||||
__uaccess_end();
|
__uaccess_end();
|
||||||
return ret;
|
return ret;
|
||||||
case 2:
|
case 2:
|
||||||
__uaccess_begin();
|
__uaccess_begin_nospec();
|
||||||
__get_user_size(*(u16 *)to, from, 2, ret, 2);
|
__get_user_size(*(u16 *)to, from, 2, ret, 2);
|
||||||
__uaccess_end();
|
__uaccess_end();
|
||||||
return ret;
|
return ret;
|
||||||
case 4:
|
case 4:
|
||||||
__uaccess_begin();
|
__uaccess_begin_nospec();
|
||||||
__get_user_size(*(u32 *)to, from, 4, ret, 4);
|
__get_user_size(*(u32 *)to, from, 4, ret, 4);
|
||||||
__uaccess_end();
|
__uaccess_end();
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -164,17 +164,17 @@ __copy_from_user(void *to, const void __user *from, unsigned long n)
|
||||||
|
|
||||||
switch (n) {
|
switch (n) {
|
||||||
case 1:
|
case 1:
|
||||||
__uaccess_begin();
|
__uaccess_begin_nospec();
|
||||||
__get_user_size(*(u8 *)to, from, 1, ret, 1);
|
__get_user_size(*(u8 *)to, from, 1, ret, 1);
|
||||||
__uaccess_end();
|
__uaccess_end();
|
||||||
return ret;
|
return ret;
|
||||||
case 2:
|
case 2:
|
||||||
__uaccess_begin();
|
__uaccess_begin_nospec();
|
||||||
__get_user_size(*(u16 *)to, from, 2, ret, 2);
|
__get_user_size(*(u16 *)to, from, 2, ret, 2);
|
||||||
__uaccess_end();
|
__uaccess_end();
|
||||||
return ret;
|
return ret;
|
||||||
case 4:
|
case 4:
|
||||||
__uaccess_begin();
|
__uaccess_begin_nospec();
|
||||||
__get_user_size(*(u32 *)to, from, 4, ret, 4);
|
__get_user_size(*(u32 *)to, from, 4, ret, 4);
|
||||||
__uaccess_end();
|
__uaccess_end();
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -192,17 +192,17 @@ static __always_inline unsigned long __copy_from_user_nocache(void *to,
|
||||||
|
|
||||||
switch (n) {
|
switch (n) {
|
||||||
case 1:
|
case 1:
|
||||||
__uaccess_begin();
|
__uaccess_begin_nospec();
|
||||||
__get_user_size(*(u8 *)to, from, 1, ret, 1);
|
__get_user_size(*(u8 *)to, from, 1, ret, 1);
|
||||||
__uaccess_end();
|
__uaccess_end();
|
||||||
return ret;
|
return ret;
|
||||||
case 2:
|
case 2:
|
||||||
__uaccess_begin();
|
__uaccess_begin_nospec();
|
||||||
__get_user_size(*(u16 *)to, from, 2, ret, 2);
|
__get_user_size(*(u16 *)to, from, 2, ret, 2);
|
||||||
__uaccess_end();
|
__uaccess_end();
|
||||||
return ret;
|
return ret;
|
||||||
case 4:
|
case 4:
|
||||||
__uaccess_begin();
|
__uaccess_begin_nospec();
|
||||||
__get_user_size(*(u32 *)to, from, 4, ret, 4);
|
__get_user_size(*(u32 *)to, from, 4, ret, 4);
|
||||||
__uaccess_end();
|
__uaccess_end();
|
||||||
return ret;
|
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);
|
return copy_user_generic(dst, (__force void *)src, size);
|
||||||
switch (size) {
|
switch (size) {
|
||||||
case 1:
|
case 1:
|
||||||
__uaccess_begin();
|
__uaccess_begin_nospec();
|
||||||
__get_user_asm(*(u8 *)dst, (u8 __user *)src,
|
__get_user_asm(*(u8 *)dst, (u8 __user *)src,
|
||||||
ret, "b", "b", "=q", 1);
|
ret, "b", "b", "=q", 1);
|
||||||
__uaccess_end();
|
__uaccess_end();
|
||||||
return ret;
|
return ret;
|
||||||
case 2:
|
case 2:
|
||||||
__uaccess_begin();
|
__uaccess_begin_nospec();
|
||||||
__get_user_asm(*(u16 *)dst, (u16 __user *)src,
|
__get_user_asm(*(u16 *)dst, (u16 __user *)src,
|
||||||
ret, "w", "w", "=r", 2);
|
ret, "w", "w", "=r", 2);
|
||||||
__uaccess_end();
|
__uaccess_end();
|
||||||
return ret;
|
return ret;
|
||||||
case 4:
|
case 4:
|
||||||
__uaccess_begin();
|
__uaccess_begin_nospec();
|
||||||
__get_user_asm(*(u32 *)dst, (u32 __user *)src,
|
__get_user_asm(*(u32 *)dst, (u32 __user *)src,
|
||||||
ret, "l", "k", "=r", 4);
|
ret, "l", "k", "=r", 4);
|
||||||
__uaccess_end();
|
__uaccess_end();
|
||||||
return ret;
|
return ret;
|
||||||
case 8:
|
case 8:
|
||||||
__uaccess_begin();
|
__uaccess_begin_nospec();
|
||||||
__get_user_asm(*(u64 *)dst, (u64 __user *)src,
|
__get_user_asm(*(u64 *)dst, (u64 __user *)src,
|
||||||
ret, "q", "", "=r", 8);
|
ret, "q", "", "=r", 8);
|
||||||
__uaccess_end();
|
__uaccess_end();
|
||||||
return ret;
|
return ret;
|
||||||
case 10:
|
case 10:
|
||||||
__uaccess_begin();
|
__uaccess_begin_nospec();
|
||||||
__get_user_asm(*(u64 *)dst, (u64 __user *)src,
|
__get_user_asm(*(u64 *)dst, (u64 __user *)src,
|
||||||
ret, "q", "", "=r", 10);
|
ret, "q", "", "=r", 10);
|
||||||
if (likely(!ret))
|
if (likely(!ret))
|
||||||
|
@ -92,7 +92,7 @@ int __copy_from_user_nocheck(void *dst, const void __user *src, unsigned size)
|
||||||
__uaccess_end();
|
__uaccess_end();
|
||||||
return ret;
|
return ret;
|
||||||
case 16:
|
case 16:
|
||||||
__uaccess_begin();
|
__uaccess_begin_nospec();
|
||||||
__get_user_asm(*(u64 *)dst, (u64 __user *)src,
|
__get_user_asm(*(u64 *)dst, (u64 __user *)src,
|
||||||
ret, "q", "", "=r", 16);
|
ret, "q", "", "=r", 16);
|
||||||
if (likely(!ret))
|
if (likely(!ret))
|
||||||
|
@ -192,7 +192,7 @@ int __copy_in_user(void __user *dst, const void __user *src, unsigned size)
|
||||||
switch (size) {
|
switch (size) {
|
||||||
case 1: {
|
case 1: {
|
||||||
u8 tmp;
|
u8 tmp;
|
||||||
__uaccess_begin();
|
__uaccess_begin_nospec();
|
||||||
__get_user_asm(tmp, (u8 __user *)src,
|
__get_user_asm(tmp, (u8 __user *)src,
|
||||||
ret, "b", "b", "=q", 1);
|
ret, "b", "b", "=q", 1);
|
||||||
if (likely(!ret))
|
if (likely(!ret))
|
||||||
|
@ -203,7 +203,7 @@ int __copy_in_user(void __user *dst, const void __user *src, unsigned size)
|
||||||
}
|
}
|
||||||
case 2: {
|
case 2: {
|
||||||
u16 tmp;
|
u16 tmp;
|
||||||
__uaccess_begin();
|
__uaccess_begin_nospec();
|
||||||
__get_user_asm(tmp, (u16 __user *)src,
|
__get_user_asm(tmp, (u16 __user *)src,
|
||||||
ret, "w", "w", "=r", 2);
|
ret, "w", "w", "=r", 2);
|
||||||
if (likely(!ret))
|
if (likely(!ret))
|
||||||
|
@ -215,7 +215,7 @@ int __copy_in_user(void __user *dst, const void __user *src, unsigned size)
|
||||||
|
|
||||||
case 4: {
|
case 4: {
|
||||||
u32 tmp;
|
u32 tmp;
|
||||||
__uaccess_begin();
|
__uaccess_begin_nospec();
|
||||||
__get_user_asm(tmp, (u32 __user *)src,
|
__get_user_asm(tmp, (u32 __user *)src,
|
||||||
ret, "l", "k", "=r", 4);
|
ret, "l", "k", "=r", 4);
|
||||||
if (likely(!ret))
|
if (likely(!ret))
|
||||||
|
@ -226,7 +226,7 @@ int __copy_in_user(void __user *dst, const void __user *src, unsigned size)
|
||||||
}
|
}
|
||||||
case 8: {
|
case 8: {
|
||||||
u64 tmp;
|
u64 tmp;
|
||||||
__uaccess_begin();
|
__uaccess_begin_nospec();
|
||||||
__get_user_asm(tmp, (u64 __user *)src,
|
__get_user_asm(tmp, (u64 __user *)src,
|
||||||
ret, "q", "", "=r", 8);
|
ret, "q", "", "=r", 8);
|
||||||
if (likely(!ret))
|
if (likely(!ret))
|
||||||
|
|
|
@ -693,7 +693,8 @@ static void init_speculation_control(struct cpuinfo_x86 *c)
|
||||||
if (cpu_has(c, X86_FEATURE_INTEL_STIBP))
|
if (cpu_has(c, X86_FEATURE_INTEL_STIBP))
|
||||||
set_cpu_cap(c, X86_FEATURE_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);
|
set_cpu_cap(c, X86_FEATURE_SSBD);
|
||||||
|
|
||||||
if (cpu_has(c, X86_FEATURE_AMD_IBRS)) {
|
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) |
|
F(3DNOWPREFETCH) | F(OSVW) | 0 /* IBS */ | F(XOP) |
|
||||||
0 /* SKINIT, WDT, LWP */ | F(FMA4) | F(TBM);
|
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 */
|
/* cpuid 0xC0000001.edx */
|
||||||
const u32 kvm_supported_word5_x86_features =
|
const u32 kvm_supported_word5_x86_features =
|
||||||
F(XSTORE) | F(XSTORE_EN) | F(XCRYPT) | F(XCRYPT_EN) |
|
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 =
|
const u32 kvm_supported_word10_x86_features =
|
||||||
F(XSAVEOPT) | F(XSAVEC) | F(XGETBV1) | f_xsaves;
|
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 */
|
/* all calls to cpuid_count() should be made on the same cpu */
|
||||||
get_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);
|
cpuid_mask(&entry->ebx, 9);
|
||||||
// TSC_ADJUST is emulated
|
// TSC_ADJUST is emulated
|
||||||
entry->ebx |= F(TSC_ADJUST);
|
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->ebx = 0;
|
||||||
|
entry->edx = 0;
|
||||||
|
}
|
||||||
entry->eax = 0;
|
entry->eax = 0;
|
||||||
entry->ecx = 0;
|
entry->ecx = 0;
|
||||||
entry->edx = 0;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 9:
|
case 9:
|
||||||
|
@ -583,7 +594,21 @@ static inline int __do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
|
||||||
if (!g_phys_as)
|
if (!g_phys_as)
|
||||||
g_phys_as = phys_as;
|
g_phys_as = phys_as;
|
||||||
entry->eax = g_phys_as | (virt_as << 8);
|
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;
|
break;
|
||||||
}
|
}
|
||||||
case 0x80000019:
|
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));
|
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
|
* NRIPS is provided through cpuidfn 0x8000000a.edx bit 3
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -56,7 +56,7 @@
|
||||||
#define APIC_BUS_CYCLE_NS 1
|
#define APIC_BUS_CYCLE_NS 1
|
||||||
|
|
||||||
/* #define apic_debug(fmt,arg...) printk(KERN_WARNING fmt,##arg) */
|
/* #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
|
#define APIC_LVT_NUM 6
|
||||||
/* 14 is the version for Xeon and Pentium 8.4.8*/
|
/* 14 is the version for Xeon and Pentium 8.4.8*/
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
#include <asm/desc.h>
|
#include <asm/desc.h>
|
||||||
#include <asm/debugreg.h>
|
#include <asm/debugreg.h>
|
||||||
#include <asm/kvm_para.h>
|
#include <asm/kvm_para.h>
|
||||||
|
#include <asm/microcode.h>
|
||||||
#include <asm/spec-ctrl.h>
|
#include <asm/spec-ctrl.h>
|
||||||
|
|
||||||
#include <asm/virtext.h>
|
#include <asm/virtext.h>
|
||||||
|
@ -147,6 +148,14 @@ struct vcpu_svm {
|
||||||
u64 gs_base;
|
u64 gs_base;
|
||||||
} host;
|
} 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;
|
u32 *msrpm;
|
||||||
|
|
||||||
ulong nmi_iret_rip;
|
ulong nmi_iret_rip;
|
||||||
|
@ -182,6 +191,8 @@ static const struct svm_direct_access_msrs {
|
||||||
{ .index = MSR_CSTAR, .always = true },
|
{ .index = MSR_CSTAR, .always = true },
|
||||||
{ .index = MSR_SYSCALL_MASK, .always = true },
|
{ .index = MSR_SYSCALL_MASK, .always = true },
|
||||||
#endif
|
#endif
|
||||||
|
{ .index = MSR_IA32_SPEC_CTRL, .always = false },
|
||||||
|
{ .index = MSR_IA32_PRED_CMD, .always = false },
|
||||||
{ .index = MSR_IA32_LASTBRANCHFROMIP, .always = false },
|
{ .index = MSR_IA32_LASTBRANCHFROMIP, .always = false },
|
||||||
{ .index = MSR_IA32_LASTBRANCHTOIP, .always = false },
|
{ .index = MSR_IA32_LASTBRANCHTOIP, .always = false },
|
||||||
{ .index = MSR_IA32_LASTINTFROMIP, .always = false },
|
{ .index = MSR_IA32_LASTINTFROMIP, .always = false },
|
||||||
|
@ -411,6 +422,7 @@ struct svm_cpu_data {
|
||||||
struct kvm_ldttss_desc *tss_desc;
|
struct kvm_ldttss_desc *tss_desc;
|
||||||
|
|
||||||
struct page *save_area;
|
struct page *save_area;
|
||||||
|
struct vmcb *current_vmcb;
|
||||||
};
|
};
|
||||||
|
|
||||||
static DEFINE_PER_CPU(struct svm_cpu_data *, svm_data);
|
static DEFINE_PER_CPU(struct svm_cpu_data *, svm_data);
|
||||||
|
@ -762,6 +774,25 @@ static bool valid_msr_intercept(u32 index)
|
||||||
return false;
|
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,
|
static void set_msr_interception(u32 *msrpm, unsigned msr,
|
||||||
int read, int write)
|
int read, int write)
|
||||||
{
|
{
|
||||||
|
@ -1120,6 +1151,9 @@ static void svm_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event)
|
||||||
u32 dummy;
|
u32 dummy;
|
||||||
u32 eax = 1;
|
u32 eax = 1;
|
||||||
|
|
||||||
|
svm->spec_ctrl = 0;
|
||||||
|
svm->virt_spec_ctrl = 0;
|
||||||
|
|
||||||
if (!init_event) {
|
if (!init_event) {
|
||||||
svm->vcpu.arch.apic_base = APIC_DEFAULT_PHYS_BASE |
|
svm->vcpu.arch.apic_base = APIC_DEFAULT_PHYS_BASE |
|
||||||
MSR_IA32_APICBASE_ENABLE;
|
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);
|
__free_pages(virt_to_page(svm->nested.msrpm), MSRPM_ALLOC_ORDER);
|
||||||
kvm_vcpu_uninit(vcpu);
|
kvm_vcpu_uninit(vcpu);
|
||||||
kmem_cache_free(kvm_vcpu_cache, svm);
|
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)
|
static void svm_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
|
||||||
{
|
{
|
||||||
struct vcpu_svm *svm = to_svm(vcpu);
|
struct vcpu_svm *svm = to_svm(vcpu);
|
||||||
|
struct svm_cpu_data *sd = per_cpu(svm_data, cpu);
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (unlikely(cpu != vcpu->cpu)) {
|
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);
|
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)
|
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:
|
case MSR_VM_CR:
|
||||||
msr_info->data = svm->nested.vm_cr_msr;
|
msr_info->data = svm->nested.vm_cr_msr;
|
||||||
break;
|
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:
|
case MSR_IA32_UCODE_REV:
|
||||||
msr_info->data = 0x01000065;
|
msr_info->data = 0x01000065;
|
||||||
break;
|
break;
|
||||||
|
@ -3125,6 +3183,59 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr)
|
||||||
case MSR_IA32_TSC:
|
case MSR_IA32_TSC:
|
||||||
kvm_write_tsc(vcpu, msr);
|
kvm_write_tsc(vcpu, msr);
|
||||||
break;
|
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:
|
case MSR_STAR:
|
||||||
svm->vmcb->save.star = data;
|
svm->vmcb->save.star = data;
|
||||||
break;
|
break;
|
||||||
|
@ -3811,6 +3922,14 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu)
|
||||||
|
|
||||||
local_irq_enable();
|
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 (
|
asm volatile (
|
||||||
"push %%" _ASM_BP "; \n\t"
|
"push %%" _ASM_BP "; \n\t"
|
||||||
"mov %c[rbx](%[svm]), %%" _ASM_BX " \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
|
||||||
#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);
|
reload_tss(vcpu);
|
||||||
|
|
||||||
local_irq_disable();
|
local_irq_disable();
|
||||||
|
@ -4015,7 +4154,7 @@ static bool svm_cpu_has_accelerated_tpr(void)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool svm_has_high_real_mode_segbase(void)
|
static bool svm_has_emulated_msr(int index)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -4299,7 +4438,7 @@ static struct kvm_x86_ops svm_x86_ops = {
|
||||||
.hardware_enable = svm_hardware_enable,
|
.hardware_enable = svm_hardware_enable,
|
||||||
.hardware_disable = svm_hardware_disable,
|
.hardware_disable = svm_hardware_disable,
|
||||||
.cpu_has_accelerated_tpr = svm_cpu_has_accelerated_tpr,
|
.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_create = svm_create_vcpu,
|
||||||
.vcpu_free = svm_free_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
|
#endif
|
||||||
MSR_IA32_TSC, MSR_IA32_CR_PAT, MSR_VM_HSAVE_PA,
|
MSR_IA32_TSC, MSR_IA32_CR_PAT, MSR_VM_HSAVE_PA,
|
||||||
MSR_IA32_FEATURE_CONTROL, MSR_IA32_BNDCFGS, MSR_TSC_AUX,
|
MSR_IA32_FEATURE_CONTROL, MSR_IA32_BNDCFGS, MSR_TSC_AUX,
|
||||||
|
MSR_IA32_SPEC_CTRL, MSR_IA32_ARCH_CAPABILITIES
|
||||||
};
|
};
|
||||||
|
|
||||||
static unsigned num_msrs_to_save;
|
static unsigned num_msrs_to_save;
|
||||||
|
@ -984,6 +985,7 @@ static u32 emulated_msrs[] = {
|
||||||
MSR_IA32_MCG_STATUS,
|
MSR_IA32_MCG_STATUS,
|
||||||
MSR_IA32_MCG_CTL,
|
MSR_IA32_MCG_CTL,
|
||||||
MSR_IA32_SMBASE,
|
MSR_IA32_SMBASE,
|
||||||
|
MSR_AMD64_VIRT_SPEC_CTRL,
|
||||||
};
|
};
|
||||||
|
|
||||||
static unsigned num_emulated_msrs;
|
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
|
* fringe case that is not enabled except via specific settings
|
||||||
* of the module parameters.
|
* 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;
|
break;
|
||||||
case KVM_CAP_COALESCED_MMIO:
|
case KVM_CAP_COALESCED_MMIO:
|
||||||
r = KVM_COALESCED_MMIO_PAGE_OFFSET;
|
r = KVM_COALESCED_MMIO_PAGE_OFFSET;
|
||||||
|
@ -4072,14 +4074,8 @@ static void kvm_init_msr_list(void)
|
||||||
num_msrs_to_save = j;
|
num_msrs_to_save = j;
|
||||||
|
|
||||||
for (i = j = 0; i < ARRAY_SIZE(emulated_msrs); i++) {
|
for (i = j = 0; i < ARRAY_SIZE(emulated_msrs); i++) {
|
||||||
switch (emulated_msrs[i]) {
|
if (!kvm_x86_ops->has_emulated_msr(emulated_msrs[i]))
|
||||||
case MSR_IA32_SMBASE:
|
|
||||||
if (!kvm_x86_ops->cpu_has_high_real_mode_segbase())
|
|
||||||
continue;
|
continue;
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (j < i)
|
if (j < i)
|
||||||
emulated_msrs[j] = emulated_msrs[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 __copy_to_user_ll(void __user *to, const void *from,
|
||||||
unsigned long n)
|
unsigned long n)
|
||||||
{
|
{
|
||||||
stac();
|
__uaccess_begin_nospec();
|
||||||
if (movsl_is_ok(to, from, n))
|
if (movsl_is_ok(to, from, n))
|
||||||
__copy_user(to, from, n);
|
__copy_user(to, from, n);
|
||||||
else
|
else
|
||||||
n = __copy_user_intel(to, from, n);
|
n = __copy_user_intel(to, from, n);
|
||||||
clac();
|
__uaccess_end();
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(__copy_to_user_ll);
|
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 __copy_from_user_ll(void *to, const void __user *from,
|
||||||
unsigned long n)
|
unsigned long n)
|
||||||
{
|
{
|
||||||
stac();
|
__uaccess_begin_nospec();
|
||||||
if (movsl_is_ok(to, from, n))
|
if (movsl_is_ok(to, from, n))
|
||||||
__copy_user_zeroing(to, from, n);
|
__copy_user_zeroing(to, from, n);
|
||||||
else
|
else
|
||||||
n = __copy_user_zeroing_intel(to, from, n);
|
n = __copy_user_zeroing_intel(to, from, n);
|
||||||
clac();
|
__uaccess_end();
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(__copy_from_user_ll);
|
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 __copy_from_user_ll_nozero(void *to, const void __user *from,
|
||||||
unsigned long n)
|
unsigned long n)
|
||||||
{
|
{
|
||||||
stac();
|
__uaccess_begin_nospec();
|
||||||
if (movsl_is_ok(to, from, n))
|
if (movsl_is_ok(to, from, n))
|
||||||
__copy_user(to, from, n);
|
__copy_user(to, from, n);
|
||||||
else
|
else
|
||||||
n = __copy_user_intel((void __user *)to,
|
n = __copy_user_intel((void __user *)to,
|
||||||
(const void *)from, n);
|
(const void *)from, n);
|
||||||
clac();
|
__uaccess_end();
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(__copy_from_user_ll_nozero);
|
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 __copy_from_user_ll_nocache(void *to, const void __user *from,
|
||||||
unsigned long n)
|
unsigned long n)
|
||||||
{
|
{
|
||||||
stac();
|
__uaccess_begin_nospec();
|
||||||
#ifdef CONFIG_X86_INTEL_USERCOPY
|
#ifdef CONFIG_X86_INTEL_USERCOPY
|
||||||
if (n > 64 && cpu_has_xmm2)
|
if (n > 64 && cpu_has_xmm2)
|
||||||
n = __copy_user_zeroing_intel_nocache(to, from, n);
|
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
|
#else
|
||||||
__copy_user_zeroing(to, from, n);
|
__copy_user_zeroing(to, from, n);
|
||||||
#endif
|
#endif
|
||||||
clac();
|
__uaccess_end();
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(__copy_from_user_ll_nocache);
|
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 __copy_from_user_ll_nocache_nozero(void *to, const void __user *from,
|
||||||
unsigned long n)
|
unsigned long n)
|
||||||
{
|
{
|
||||||
stac();
|
__uaccess_begin_nospec();
|
||||||
#ifdef CONFIG_X86_INTEL_USERCOPY
|
#ifdef CONFIG_X86_INTEL_USERCOPY
|
||||||
if (n > 64 && cpu_has_xmm2)
|
if (n > 64 && cpu_has_xmm2)
|
||||||
n = __copy_user_intel_nocache(to, from, n);
|
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
|
#else
|
||||||
__copy_user(to, from, n);
|
__copy_user(to, from, n);
|
||||||
#endif
|
#endif
|
||||||
clac();
|
__uaccess_end();
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(__copy_from_user_ll_nocache_nozero);
|
EXPORT_SYMBOL(__copy_from_user_ll_nocache_nozero);
|
||||||
|
|
|
@ -388,7 +388,7 @@ slow_irqon:
|
||||||
|
|
||||||
ret = get_user_pages_unlocked(current, mm, start,
|
ret = get_user_pages_unlocked(current, mm, start,
|
||||||
(end - start) >> PAGE_SHIFT,
|
(end - start) >> PAGE_SHIFT,
|
||||||
write, 0, pages);
|
pages, write ? FOLL_WRITE : 0);
|
||||||
|
|
||||||
/* Have to be a bit careful with return values */
|
/* Have to be a bit careful with return values */
|
||||||
if (nr > 0) {
|
if (nr > 0) {
|
||||||
|
|
|
@ -536,10 +536,9 @@ static int mpx_resolve_fault(long __user *addr, int write)
|
||||||
{
|
{
|
||||||
long gup_ret;
|
long gup_ret;
|
||||||
int nr_pages = 1;
|
int nr_pages = 1;
|
||||||
int force = 0;
|
|
||||||
|
|
||||||
gup_ret = get_user_pages(current, current->mm, (unsigned long)addr,
|
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.
|
* get_user_pages() returns number of pages gotten.
|
||||||
* 0 means we failed to fault in and get anything,
|
* 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 r;
|
||||||
|
|
||||||
int write = !(gtt->userflags & AMDGPU_GEM_USERPTR_READONLY);
|
int write = !(gtt->userflags & AMDGPU_GEM_USERPTR_READONLY);
|
||||||
|
unsigned int flags = 0;
|
||||||
enum dma_data_direction direction = write ?
|
enum dma_data_direction direction = write ?
|
||||||
DMA_BIDIRECTIONAL : DMA_TO_DEVICE;
|
DMA_BIDIRECTIONAL : DMA_TO_DEVICE;
|
||||||
|
|
||||||
|
if (write)
|
||||||
|
flags |= FOLL_WRITE;
|
||||||
|
|
||||||
if (current->mm != gtt->usermm)
|
if (current->mm != gtt->usermm)
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
|
|
||||||
|
@ -519,7 +523,7 @@ static int amdgpu_ttm_tt_pin_userptr(struct ttm_tt *ttm)
|
||||||
struct page **pages = ttm->pages + pinned;
|
struct page **pages = ttm->pages + pinned;
|
||||||
|
|
||||||
r = get_user_pages(current, current->mm, userptr, num_pages,
|
r = get_user_pages(current, current->mm, userptr, num_pages,
|
||||||
write, 0, pages, NULL);
|
flags, pages, NULL);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
goto release_pages;
|
goto release_pages;
|
||||||
|
|
||||||
|
|
|
@ -968,9 +968,21 @@ static int get_clock(void *i2c_priv)
|
||||||
{
|
{
|
||||||
struct ast_i2c_chan *i2c = i2c_priv;
|
struct ast_i2c_chan *i2c = i2c_priv;
|
||||||
struct ast_private *ast = i2c->dev->dev_private;
|
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;
|
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_i2c_chan *i2c = i2c_priv;
|
||||||
struct ast_private *ast = i2c->dev->dev_private;
|
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;
|
return val & 1 ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -993,7 +1017,7 @@ static void set_clock(void *i2c_priv, int clock)
|
||||||
|
|
||||||
for (i = 0; i < 0x10000; i++) {
|
for (i = 0; i < 0x10000; i++) {
|
||||||
ujcrb7 = ((clock & 0x01) ? 0 : 1);
|
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);
|
jtemp = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x01);
|
||||||
if (ujcrb7 == jtemp)
|
if (ujcrb7 == jtemp)
|
||||||
break;
|
break;
|
||||||
|
@ -1009,7 +1033,7 @@ static void set_data(void *i2c_priv, int data)
|
||||||
|
|
||||||
for (i = 0; i < 0x10000; i++) {
|
for (i = 0; i < 0x10000; i++) {
|
||||||
ujcrb7 = ((data & 0x01) ? 0 : 1) << 2;
|
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);
|
jtemp = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x04);
|
||||||
if (ujcrb7 == jtemp)
|
if (ujcrb7 == jtemp)
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -471,7 +471,8 @@ static dma_addr_t *g2d_userptr_get_dma_addr(struct drm_device *drm_dev,
|
||||||
goto err_free;
|
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) {
|
if (ret != npages) {
|
||||||
DRM_ERROR("failed to get user pages from userptr.\n");
|
DRM_ERROR("failed to get user pages from userptr.\n");
|
||||||
if (ret < 0)
|
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 *));
|
pvec = drm_malloc_ab(npages, sizeof(struct page *));
|
||||||
if (pvec != NULL) {
|
if (pvec != NULL) {
|
||||||
struct mm_struct *mm = obj->userptr.mm->mm;
|
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);
|
down_read(&mm->mmap_sem);
|
||||||
while (pinned < npages) {
|
while (pinned < npages) {
|
||||||
ret = get_user_pages(work->task, mm,
|
ret = get_user_pages(work->task, mm,
|
||||||
obj->userptr.ptr + pinned * PAGE_SIZE,
|
obj->userptr.ptr + pinned * PAGE_SIZE,
|
||||||
npages - pinned,
|
npages - pinned,
|
||||||
!obj->userptr.read_only, 0,
|
flags,
|
||||||
pvec + pinned, NULL);
|
pvec + pinned, NULL);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -557,7 +557,7 @@ static int radeon_ttm_tt_pin_userptr(struct ttm_tt *ttm)
|
||||||
struct page **pages = ttm->pages + pinned;
|
struct page **pages = ttm->pages + pinned;
|
||||||
|
|
||||||
r = get_user_pages(current, current->mm, userptr, num_pages,
|
r = get_user_pages(current, current->mm, userptr, num_pages,
|
||||||
write, 0, pages, NULL);
|
write ? FOLL_WRITE : 0, pages, NULL);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
goto release_pages;
|
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,
|
ret = get_user_pages(current, current->mm,
|
||||||
(unsigned long)xfer->mem_addr,
|
(unsigned long)xfer->mem_addr,
|
||||||
vsg->num_pages,
|
vsg->num_pages,
|
||||||
(vsg->direction == DMA_FROM_DEVICE),
|
(vsg->direction == DMA_FROM_DEVICE) ? FOLL_WRITE : 0,
|
||||||
0, vsg->pages, NULL);
|
vsg->pages, NULL);
|
||||||
|
|
||||||
up_read(¤t->mm->mmap_sem);
|
up_read(¤t->mm->mmap_sem);
|
||||||
if (ret != vsg->num_pages) {
|
if (ret != vsg->num_pages) {
|
||||||
|
|
|
@ -273,7 +273,7 @@ static int ina2xx_get_value(struct ina2xx_data *data, u8 reg,
|
||||||
break;
|
break;
|
||||||
case INA2XX_CURRENT:
|
case INA2XX_CURRENT:
|
||||||
/* signed register, result in mA */
|
/* signed register, result in mA */
|
||||||
val = regval * data->current_lsb_uA;
|
val = (s16)regval * data->current_lsb_uA;
|
||||||
val = DIV_ROUND_CLOSEST(val, 1000);
|
val = DIV_ROUND_CLOSEST(val, 1000);
|
||||||
break;
|
break;
|
||||||
case INA2XX_CALIBRATION:
|
case INA2XX_CALIBRATION:
|
||||||
|
|
|
@ -1691,7 +1691,7 @@ store_sf_setup(struct device *dev, struct device_attribute *attr,
|
||||||
* somewhere else in the code
|
* somewhere else in the code
|
||||||
*/
|
*/
|
||||||
#define SENSOR_ATTR_TEMP(index) { \
|
#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), \
|
show_temp_mode, store_temp_mode, NOT_USED, index - 1), \
|
||||||
SENSOR_ATTR_2(temp##index##_input, S_IRUGO, show_temp, \
|
SENSOR_ATTR_2(temp##index##_input, S_IRUGO, show_temp, \
|
||||||
NULL, TEMP_READ, index - 1), \
|
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);
|
DEFINE_DMA_ATTRS(attrs);
|
||||||
struct scatterlist *sg, *sg_list_start;
|
struct scatterlist *sg, *sg_list_start;
|
||||||
int need_release = 0;
|
int need_release = 0;
|
||||||
|
unsigned int gup_flags = FOLL_WRITE;
|
||||||
|
|
||||||
if (dmasync)
|
if (dmasync)
|
||||||
dma_set_attr(DMA_ATTR_WRITE_BARRIER, &attrs);
|
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)
|
if (ret)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
if (!umem->writable)
|
||||||
|
gup_flags |= FOLL_FORCE;
|
||||||
|
|
||||||
need_release = 1;
|
need_release = 1;
|
||||||
sg_list_start = umem->sg_head.sgl;
|
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,
|
ret = get_user_pages(current, current->mm, cur_base,
|
||||||
min_t(unsigned long, npages,
|
min_t(unsigned long, npages,
|
||||||
PAGE_SIZE / sizeof (struct page *)),
|
PAGE_SIZE / sizeof (struct page *)),
|
||||||
1, !umem->writable, page_list, vma_list);
|
gup_flags, page_list, vma_list);
|
||||||
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
|
@ -527,6 +527,7 @@ int ib_umem_odp_map_dma_pages(struct ib_umem *umem, u64 user_virt, u64 bcnt,
|
||||||
u64 off;
|
u64 off;
|
||||||
int j, k, ret = 0, start_idx, npages = 0;
|
int j, k, ret = 0, start_idx, npages = 0;
|
||||||
u64 base_virt_addr;
|
u64 base_virt_addr;
|
||||||
|
unsigned int flags = 0;
|
||||||
|
|
||||||
if (access_mask == 0)
|
if (access_mask == 0)
|
||||||
return -EINVAL;
|
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;
|
goto out_put_task;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (access_mask & ODP_WRITE_ALLOWED_BIT)
|
||||||
|
flags |= FOLL_WRITE;
|
||||||
|
|
||||||
start_idx = (user_virt - ib_umem_start(umem)) >> PAGE_SHIFT;
|
start_idx = (user_virt - ib_umem_start(umem)) >> PAGE_SHIFT;
|
||||||
k = start_idx;
|
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,
|
npages = get_user_pages(owning_process, owning_mm, user_virt,
|
||||||
gup_num_pages,
|
gup_num_pages,
|
||||||
access_mask & ODP_WRITE_ALLOWED_BIT, 0,
|
flags, local_page_list, NULL);
|
||||||
local_page_list, NULL);
|
|
||||||
up_read(&owning_mm->mmap_sem);
|
up_read(&owning_mm->mmap_sem);
|
||||||
|
|
||||||
if (npages < 0)
|
if (npages < 0)
|
||||||
|
|
|
@ -472,8 +472,8 @@ int mthca_map_user_db(struct mthca_dev *dev, struct mthca_uar *uar,
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = get_user_pages(current, current->mm, uaddr & PAGE_MASK, 1, 1, 0,
|
ret = get_user_pages(current, current->mm, uaddr & PAGE_MASK, 1,
|
||||||
pages, NULL);
|
FOLL_WRITE, pages, NULL);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto out;
|
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) {
|
for (got = 0; got < num_pages; got += ret) {
|
||||||
ret = get_user_pages(current, current->mm,
|
ret = get_user_pages(current, current->mm,
|
||||||
start_page + got * PAGE_SIZE,
|
start_page + got * PAGE_SIZE,
|
||||||
num_pages - got, 1, 1,
|
num_pages - got,
|
||||||
|
FOLL_WRITE | FOLL_FORCE,
|
||||||
p + got, NULL);
|
p + got, NULL);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto bail_release;
|
goto bail_release;
|
||||||
|
|
|
@ -113,6 +113,7 @@ static int usnic_uiom_get_pages(unsigned long addr, size_t size, int writable,
|
||||||
int flags;
|
int flags;
|
||||||
dma_addr_t pa;
|
dma_addr_t pa;
|
||||||
DEFINE_DMA_ATTRS(attrs);
|
DEFINE_DMA_ATTRS(attrs);
|
||||||
|
unsigned int gup_flags;
|
||||||
|
|
||||||
if (dmasync)
|
if (dmasync)
|
||||||
dma_set_attr(DMA_ATTR_WRITE_BARRIER, &attrs);
|
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 = IOMMU_READ | IOMMU_CACHE;
|
||||||
flags |= (writable) ? IOMMU_WRITE : 0;
|
flags |= (writable) ? IOMMU_WRITE : 0;
|
||||||
|
gup_flags = FOLL_WRITE;
|
||||||
|
gup_flags |= (writable) ? 0 : FOLL_FORCE;
|
||||||
cur_base = addr & PAGE_MASK;
|
cur_base = addr & PAGE_MASK;
|
||||||
ret = 0;
|
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,
|
ret = get_user_pages(current, current->mm, cur_base,
|
||||||
min_t(unsigned long, npages,
|
min_t(unsigned long, npages,
|
||||||
PAGE_SIZE / sizeof(struct page *)),
|
PAGE_SIZE / sizeof(struct page *)),
|
||||||
1, !writable, page_list, NULL);
|
gup_flags, page_list, NULL);
|
||||||
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto out;
|
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)
|
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,
|
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,
|
static int cxd2841er_write_reg(struct cxd2841er_priv *priv,
|
||||||
u8 addr, u8 reg, u8 val)
|
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,
|
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)
|
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)
|
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)
|
static inline int itd1000_write_reg(struct itd1000_state *state, u8 r, u8 v)
|
||||||
{
|
{
|
||||||
int ret = itd1000_write_regs(state, r, &v, 1);
|
u8 tmp = v; /* see gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 */
|
||||||
state->shadow[r] = v;
|
int ret = itd1000_write_regs(state, r, &tmp, 1);
|
||||||
|
state->shadow[r] = tmp;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -142,7 +142,10 @@ static inline int mt312_readreg(struct mt312_state *state,
|
||||||
static inline int mt312_writereg(struct mt312_state *state,
|
static inline int mt312_writereg(struct mt312_state *state,
|
||||||
const enum mt312_reg_addr reg, const u8 val)
|
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)
|
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)
|
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)
|
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)) {
|
if (unlikely(reg >= STB6100_NUMREGS)) {
|
||||||
dprintk(verbose, FE_ERROR, 1, "Invalid register offset 0x%x", reg);
|
dprintk(verbose, FE_ERROR, 1, "Invalid register offset 0x%x", reg);
|
||||||
return -EREMOTEIO;
|
return -EREMOTEIO;
|
||||||
}
|
}
|
||||||
data = (data & stb6100_template[reg].mask) | stb6100_template[reg].set;
|
tmp = (tmp & stb6100_template[reg].mask) | stb6100_template[reg].set;
|
||||||
return stb6100_write_reg_range(state, &data, reg, 1);
|
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)
|
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)
|
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)
|
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)
|
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)
|
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)
|
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 enum zl10039_reg_addr reg,
|
||||||
const u8 val)
|
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)
|
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 */
|
/* Get user pages for DMA Xfer */
|
||||||
err = get_user_pages_unlocked(current, current->mm,
|
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) {
|
if (user_dma.page_count != err) {
|
||||||
IVTV_DEBUG_WARN("failed to map user pages, returned %d instead of %d\n",
|
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 */
|
/* Get user pages for DMA Xfer */
|
||||||
y_pages = get_user_pages_unlocked(current, current->mm,
|
y_pages = get_user_pages_unlocked(current, current->mm,
|
||||||
y_dma.uaddr, y_dma.page_count, 0, 1,
|
y_dma.uaddr, y_dma.page_count,
|
||||||
&dma->map[0]);
|
&dma->map[0], FOLL_FORCE);
|
||||||
uv_pages = 0; /* silence gcc. value is set and consumed only if: */
|
uv_pages = 0; /* silence gcc. value is set and consumed only if: */
|
||||||
if (y_pages == y_dma.page_count) {
|
if (y_pages == y_dma.page_count) {
|
||||||
uv_pages = get_user_pages_unlocked(current, current->mm,
|
uv_pages = get_user_pages_unlocked(current, current->mm,
|
||||||
uv_dma.uaddr, uv_dma.page_count, 0, 1,
|
uv_dma.uaddr, uv_dma.page_count,
|
||||||
&dma->map[y_pages]);
|
&dma->map[y_pages], FOLL_FORCE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (y_pages != y_dma.page_count || uv_pages != uv_dma.page_count) {
|
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)
|
if (!vec)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
ret = get_vaddr_frames(virtp, 1, true, false, vec);
|
ret = get_vaddr_frames(virtp, 1, FOLL_WRITE, vec);
|
||||||
if (ret != 1) {
|
if (ret != 1) {
|
||||||
frame_vector_destroy(vec);
|
frame_vector_destroy(vec);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
|
@ -156,6 +156,7 @@ static int videobuf_dma_init_user_locked(struct videobuf_dmabuf *dma,
|
||||||
{
|
{
|
||||||
unsigned long first, last;
|
unsigned long first, last;
|
||||||
int err, rw = 0;
|
int err, rw = 0;
|
||||||
|
unsigned int flags = FOLL_FORCE;
|
||||||
|
|
||||||
dma->direction = direction;
|
dma->direction = direction;
|
||||||
switch (dma->direction) {
|
switch (dma->direction) {
|
||||||
|
@ -178,13 +179,15 @@ static int videobuf_dma_init_user_locked(struct videobuf_dmabuf *dma,
|
||||||
if (NULL == dma->pages)
|
if (NULL == dma->pages)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
if (rw == READ)
|
||||||
|
flags |= FOLL_WRITE;
|
||||||
|
|
||||||
dprintk(1, "init user [0x%lx+0x%lx => %d pages]\n",
|
dprintk(1, "init user [0x%lx+0x%lx => %d pages]\n",
|
||||||
data, size, dma->nr_pages);
|
data, size, dma->nr_pages);
|
||||||
|
|
||||||
err = get_user_pages(current, current->mm,
|
err = get_user_pages(current, current->mm,
|
||||||
data & PAGE_MASK, dma->nr_pages,
|
data & PAGE_MASK, dma->nr_pages,
|
||||||
rw == READ, 1, /* force */
|
flags, dma->pages, NULL);
|
||||||
dma->pages, NULL);
|
|
||||||
|
|
||||||
if (err != dma->nr_pages) {
|
if (err != dma->nr_pages) {
|
||||||
dma->nr_pages = (err >= 0) ? err : 0;
|
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 first, last;
|
||||||
unsigned long nr;
|
unsigned long nr;
|
||||||
struct frame_vector *vec;
|
struct frame_vector *vec;
|
||||||
|
unsigned int flags = FOLL_FORCE;
|
||||||
|
|
||||||
|
if (write)
|
||||||
|
flags |= FOLL_WRITE;
|
||||||
|
|
||||||
first = start >> PAGE_SHIFT;
|
first = start >> PAGE_SHIFT;
|
||||||
last = (start + length - 1) >> 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);
|
vec = frame_vector_create(nr);
|
||||||
if (!vec)
|
if (!vec)
|
||||||
return ERR_PTR(-ENOMEM);
|
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)
|
if (ret < 0)
|
||||||
goto out_destroy;
|
goto out_destroy;
|
||||||
/* We accept only complete set of PFNs */
|
/* We accept only complete set of PFNs */
|
||||||
|
|
|
@ -1398,8 +1398,7 @@ retry:
|
||||||
mm,
|
mm,
|
||||||
(u64)addr,
|
(u64)addr,
|
||||||
nr_pages,
|
nr_pages,
|
||||||
!!(prot & SCIF_PROT_WRITE),
|
(prot & SCIF_PROT_WRITE) ? FOLL_WRITE : 0,
|
||||||
0,
|
|
||||||
pinned_pages->pages,
|
pinned_pages->pages,
|
||||||
NULL);
|
NULL);
|
||||||
up_write(&mm->mmap_sem);
|
up_write(&mm->mmap_sem);
|
||||||
|
|
|
@ -199,7 +199,7 @@ static int non_atomic_pte_lookup(struct vm_area_struct *vma,
|
||||||
*pageshift = PAGE_SHIFT;
|
*pageshift = PAGE_SHIFT;
|
||||||
#endif
|
#endif
|
||||||
if (get_user_pages
|
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;
|
return -EFAULT;
|
||||||
*paddr = page_to_phys(page);
|
*paddr = page_to_phys(page);
|
||||||
put_page(page);
|
put_page(page);
|
||||||
|
|
|
@ -1090,6 +1090,9 @@ static void nic_remove(struct pci_dev *pdev)
|
||||||
{
|
{
|
||||||
struct nicpf *nic = pci_get_drvdata(pdev);
|
struct nicpf *nic = pci_get_drvdata(pdev);
|
||||||
|
|
||||||
|
if (!nic)
|
||||||
|
return;
|
||||||
|
|
||||||
if (nic->flags & NIC_SRIOV_ENABLED)
|
if (nic->flags & NIC_SRIOV_ENABLED)
|
||||||
pci_disable_sriov(pdev);
|
pci_disable_sriov(pdev);
|
||||||
|
|
||||||
|
|
|
@ -919,10 +919,8 @@ static int hip04_mac_probe(struct platform_device *pdev)
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = register_netdev(ndev);
|
ret = register_netdev(ndev);
|
||||||
if (ret) {
|
if (ret)
|
||||||
free_netdev(ndev);
|
|
||||||
goto alloc_fail;
|
goto alloc_fail;
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|
|
@ -1429,7 +1429,9 @@ static s32 ixgbe_get_link_capabilities_X550em(struct ixgbe_hw *hw,
|
||||||
*autoneg = false;
|
*autoneg = false;
|
||||||
|
|
||||||
if (hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core0 ||
|
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;
|
*speed = IXGBE_LINK_SPEED_1GB_FULL;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -578,6 +578,7 @@ static irqreturn_t cp_interrupt (int irq, void *dev_instance)
|
||||||
struct cp_private *cp;
|
struct cp_private *cp;
|
||||||
int handled = 0;
|
int handled = 0;
|
||||||
u16 status;
|
u16 status;
|
||||||
|
u16 mask;
|
||||||
|
|
||||||
if (unlikely(dev == NULL))
|
if (unlikely(dev == NULL))
|
||||||
return IRQ_NONE;
|
return IRQ_NONE;
|
||||||
|
@ -585,6 +586,10 @@ static irqreturn_t cp_interrupt (int irq, void *dev_instance)
|
||||||
|
|
||||||
spin_lock(&cp->lock);
|
spin_lock(&cp->lock);
|
||||||
|
|
||||||
|
mask = cpr16(IntrMask);
|
||||||
|
if (!mask)
|
||||||
|
goto out_unlock;
|
||||||
|
|
||||||
status = cpr16(IntrStatus);
|
status = cpr16(IntrStatus);
|
||||||
if (!status || (status == 0xFFFF))
|
if (!status || (status == 0xFFFF))
|
||||||
goto out_unlock;
|
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,
|
static int rocker_tlv_put_u8(struct rocker_desc_info *desc_info,
|
||||||
int attrtype, u8 value)
|
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,
|
static int rocker_tlv_put_u16(struct rocker_desc_info *desc_info,
|
||||||
int attrtype, u16 value)
|
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,
|
static int rocker_tlv_put_be16(struct rocker_desc_info *desc_info,
|
||||||
int attrtype, __be16 value)
|
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,
|
static int rocker_tlv_put_u32(struct rocker_desc_info *desc_info,
|
||||||
int attrtype, u32 value)
|
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,
|
static int rocker_tlv_put_be32(struct rocker_desc_info *desc_info,
|
||||||
int attrtype, __be32 value)
|
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,
|
static int rocker_tlv_put_u64(struct rocker_desc_info *desc_info,
|
||||||
int attrtype, u64 value)
|
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 *
|
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)
|
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) {
|
switch (max_speed) {
|
||||||
default:
|
case SPEED_10:
|
||||||
return -ENOTSUPP;
|
phydev->supported &= ~PHY_100BT_FEATURES;
|
||||||
case SPEED_1000:
|
|
||||||
phydev->supported |= PHY_1000BT_FEATURES;
|
|
||||||
/* fall through */
|
/* fall through */
|
||||||
case SPEED_100:
|
case SPEED_100:
|
||||||
phydev->supported |= PHY_100BT_FEATURES;
|
phydev->supported &= ~PHY_1000BT_FEATURES;
|
||||||
/* fall through */
|
break;
|
||||||
case SPEED_10:
|
case SPEED_1000:
|
||||||
phydev->supported |= PHY_10BT_FEATURES;
|
break;
|
||||||
|
default:
|
||||||
|
return -ENOTSUPP;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -1472,9 +1472,9 @@ static void tun_setup(struct net_device *dev)
|
||||||
*/
|
*/
|
||||||
static int tun_validate(struct nlattr *tb[], struct nlattr *data[])
|
static int tun_validate(struct nlattr *tb[], struct nlattr *data[])
|
||||||
{
|
{
|
||||||
if (!data)
|
/* NL_SET_ERR_MSG(extack,
|
||||||
return 0;
|
"tun/tap creation via rtnetlink is not supported."); */
|
||||||
return -EINVAL;
|
return -EOPNOTSUPP;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct rtnl_link_ops tun_link_ops __read_mostly = {
|
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;
|
int rc;
|
||||||
u16 len = sizeof(struct wmi_set_appie_cmd) + ie_len;
|
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) {
|
if (!cmd) {
|
||||||
rc = -ENOMEM;
|
rc = -ENOMEM;
|
||||||
goto out;
|
goto out;
|
||||||
|
|
|
@ -187,30 +187,25 @@ int sr_do_ioctl(Scsi_CD *cd, struct packet_command *cgc)
|
||||||
struct scsi_device *SDev;
|
struct scsi_device *SDev;
|
||||||
struct scsi_sense_hdr sshdr;
|
struct scsi_sense_hdr sshdr;
|
||||||
int result, err = 0, retries = 0;
|
int result, err = 0, retries = 0;
|
||||||
struct request_sense *sense = cgc->sense;
|
unsigned char sense_buffer[SCSI_SENSE_BUFFERSIZE];
|
||||||
|
|
||||||
SDev = cd->device;
|
SDev = cd->device;
|
||||||
|
|
||||||
if (!sense) {
|
|
||||||
sense = kmalloc(SCSI_SENSE_BUFFERSIZE, GFP_KERNEL);
|
|
||||||
if (!sense) {
|
|
||||||
err = -ENOMEM;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
retry:
|
retry:
|
||||||
if (!scsi_block_when_processing_errors(SDev)) {
|
if (!scsi_block_when_processing_errors(SDev)) {
|
||||||
err = -ENODEV;
|
err = -ENODEV;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(sense, 0, sizeof(*sense));
|
memset(sense_buffer, 0, sizeof(sense_buffer));
|
||||||
result = scsi_execute(SDev, cgc->cmd, cgc->data_direction,
|
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);
|
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. */
|
/* Minimal error checking. Ignore cases we know about, and report the rest. */
|
||||||
if (driver_byte(result) != 0) {
|
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 */
|
/* Wake up a process waiting for device */
|
||||||
out:
|
out:
|
||||||
if (!cgc->sense)
|
|
||||||
kfree(sense);
|
|
||||||
cgc->stat = err;
|
cgc->stat = err;
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4821,9 +4821,8 @@ static int sgl_map_user_pages(struct st_buffer *STbp,
|
||||||
current->mm,
|
current->mm,
|
||||||
uaddr,
|
uaddr,
|
||||||
nr_pages,
|
nr_pages,
|
||||||
rw == READ,
|
pages,
|
||||||
0, /* don't force */
|
rw == READ ? FOLL_WRITE : 0); /* don't force */
|
||||||
pages);
|
|
||||||
|
|
||||||
/* Errors and no page mapped should return here */
|
/* Errors and no page mapped should return here */
|
||||||
if (res < nr_pages)
|
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) {
|
for (got = 0; got < num_pages; got += ret) {
|
||||||
ret = get_user_pages(current, current->mm,
|
ret = get_user_pages(current, current->mm,
|
||||||
start_page + got * PAGE_SIZE,
|
start_page + got * PAGE_SIZE,
|
||||||
num_pages - got, 1, 1,
|
num_pages - got, FOLL_WRITE | FOLL_FORCE,
|
||||||
p + got, NULL);
|
p + got, NULL);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto bail_release;
|
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) {
|
for (got = 0; got < num_pages; got += ret) {
|
||||||
ret = get_user_pages(current, current->mm,
|
ret = get_user_pages(current, current->mm,
|
||||||
start_page + got * PAGE_SIZE,
|
start_page + got * PAGE_SIZE,
|
||||||
num_pages - got, 1, 1,
|
num_pages - got, FOLL_WRITE | FOLL_FORCE,
|
||||||
p + got, NULL);
|
p + got, NULL);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto bail_release;
|
goto bail_release;
|
||||||
|
|
|
@ -387,7 +387,7 @@ static ssize_t synth_store(struct kobject *kobj, struct kobj_attribute *attr,
|
||||||
len = strlen(buf);
|
len = strlen(buf);
|
||||||
if (len < 2 || len > 9)
|
if (len < 2 || len > 9)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
strncpy(new_synth_name, buf, len);
|
memcpy(new_synth_name, buf, len);
|
||||||
if (new_synth_name[len - 1] == '\n')
|
if (new_synth_name[len - 1] == '\n')
|
||||||
len--;
|
len--;
|
||||||
new_synth_name[len] = '\0';
|
new_synth_name[len] = '\0';
|
||||||
|
@ -514,7 +514,7 @@ static ssize_t punc_store(struct kobject *kobj, struct kobj_attribute *attr,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
strncpy(punc_buf, buf, x);
|
memcpy(punc_buf, buf, x);
|
||||||
|
|
||||||
while (x && punc_buf[x - 1] == '\n')
|
while (x && punc_buf[x - 1] == '\n')
|
||||||
x--;
|
x--;
|
||||||
|
|
|
@ -2037,6 +2037,7 @@ static inline int machine_without_vbus_sense(void)
|
||||||
{
|
{
|
||||||
return machine_is_omap_innovator()
|
return machine_is_omap_innovator()
|
||||||
|| machine_is_omap_osk()
|
|| machine_is_omap_osk()
|
||||||
|
|| machine_is_omap_palmte()
|
||||||
|| machine_is_sx1()
|
|| machine_is_sx1()
|
||||||
/* No known omap7xx boards with vbus sense */
|
/* No known omap7xx boards with vbus sense */
|
||||||
|| cpu_is_omap7xx();
|
|| cpu_is_omap7xx();
|
||||||
|
@ -2045,7 +2046,7 @@ static inline int machine_without_vbus_sense(void)
|
||||||
static int omap_udc_start(struct usb_gadget *g,
|
static int omap_udc_start(struct usb_gadget *g,
|
||||||
struct usb_gadget_driver *driver)
|
struct usb_gadget_driver *driver)
|
||||||
{
|
{
|
||||||
int status = -ENODEV;
|
int status;
|
||||||
struct omap_ep *ep;
|
struct omap_ep *ep;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
|
@ -2083,6 +2084,7 @@ static int omap_udc_start(struct usb_gadget *g,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
status = 0;
|
||||||
if (can_pullup(udc))
|
if (can_pullup(udc))
|
||||||
pullup_enable(udc);
|
pullup_enable(udc);
|
||||||
else
|
else
|
||||||
|
@ -2612,9 +2614,22 @@ omap_ep_setup(char *name, u8 addr, u8 type,
|
||||||
|
|
||||||
static void omap_udc_release(struct device *dev)
|
static void omap_udc_release(struct device *dev)
|
||||||
{
|
{
|
||||||
|
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);
|
complete(udc->done);
|
||||||
kfree(udc);
|
kfree(udc);
|
||||||
udc = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -2886,8 +2901,8 @@ bad_on_1710:
|
||||||
udc->clr_halt = UDC_RESET_EP;
|
udc->clr_halt = UDC_RESET_EP;
|
||||||
|
|
||||||
/* USB general purpose IRQ: ep0, state changes, dma, etc */
|
/* USB general purpose IRQ: ep0, state changes, dma, etc */
|
||||||
status = request_irq(pdev->resource[1].start, omap_udc_irq,
|
status = devm_request_irq(&pdev->dev, pdev->resource[1].start,
|
||||||
0, driver_name, udc);
|
omap_udc_irq, 0, driver_name, udc);
|
||||||
if (status != 0) {
|
if (status != 0) {
|
||||||
ERR("can't get irq %d, err %d\n",
|
ERR("can't get irq %d, err %d\n",
|
||||||
(int) pdev->resource[1].start, status);
|
(int) pdev->resource[1].start, status);
|
||||||
|
@ -2895,20 +2910,20 @@ bad_on_1710:
|
||||||
}
|
}
|
||||||
|
|
||||||
/* USB "non-iso" IRQ (PIO for all but ep0) */
|
/* USB "non-iso" IRQ (PIO for all but ep0) */
|
||||||
status = request_irq(pdev->resource[2].start, omap_udc_pio_irq,
|
status = devm_request_irq(&pdev->dev, pdev->resource[2].start,
|
||||||
0, "omap_udc pio", udc);
|
omap_udc_pio_irq, 0, "omap_udc pio", udc);
|
||||||
if (status != 0) {
|
if (status != 0) {
|
||||||
ERR("can't get irq %d, err %d\n",
|
ERR("can't get irq %d, err %d\n",
|
||||||
(int) pdev->resource[2].start, status);
|
(int) pdev->resource[2].start, status);
|
||||||
goto cleanup2;
|
goto cleanup1;
|
||||||
}
|
}
|
||||||
#ifdef USE_ISO
|
#ifdef USE_ISO
|
||||||
status = request_irq(pdev->resource[3].start, omap_udc_iso_irq,
|
status = devm_request_irq(&pdev->dev, pdev->resource[3].start,
|
||||||
0, "omap_udc iso", udc);
|
omap_udc_iso_irq, 0, "omap_udc iso", udc);
|
||||||
if (status != 0) {
|
if (status != 0) {
|
||||||
ERR("can't get irq %d, err %d\n",
|
ERR("can't get irq %d, err %d\n",
|
||||||
(int) pdev->resource[3].start, status);
|
(int) pdev->resource[3].start, status);
|
||||||
goto cleanup3;
|
goto cleanup1;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (cpu_is_omap16xx() || cpu_is_omap7xx()) {
|
if (cpu_is_omap16xx() || cpu_is_omap7xx()) {
|
||||||
|
@ -2919,23 +2934,8 @@ bad_on_1710:
|
||||||
}
|
}
|
||||||
|
|
||||||
create_proc_file();
|
create_proc_file();
|
||||||
status = usb_add_gadget_udc_release(&pdev->dev, &udc->gadget,
|
return usb_add_gadget_udc_release(&pdev->dev, &udc->gadget,
|
||||||
omap_udc_release);
|
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);
|
|
||||||
|
|
||||||
cleanup1:
|
cleanup1:
|
||||||
kfree(udc);
|
kfree(udc);
|
||||||
|
@ -2962,42 +2962,15 @@ static int omap_udc_remove(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
DECLARE_COMPLETION_ONSTACK(done);
|
DECLARE_COMPLETION_ONSTACK(done);
|
||||||
|
|
||||||
if (!udc)
|
|
||||||
return -ENODEV;
|
|
||||||
|
|
||||||
usb_del_gadget_udc(&udc->gadget);
|
|
||||||
if (udc->driver)
|
|
||||||
return -EBUSY;
|
|
||||||
|
|
||||||
udc->done = &done;
|
udc->done = &done;
|
||||||
|
|
||||||
pullup_disable(udc);
|
usb_del_gadget_udc(&udc->gadget);
|
||||||
if (!IS_ERR_OR_NULL(udc->transceiver)) {
|
|
||||||
usb_put_phy(udc->transceiver);
|
|
||||||
udc->transceiver = NULL;
|
|
||||||
}
|
|
||||||
omap_writew(0, UDC_SYSCON1);
|
|
||||||
|
|
||||||
remove_proc_file();
|
wait_for_completion(&done);
|
||||||
|
|
||||||
#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);
|
|
||||||
}
|
|
||||||
|
|
||||||
release_mem_region(pdev->resource[0].start,
|
release_mem_region(pdev->resource[0].start,
|
||||||
pdev->resource[0].end - pdev->resource[0].start + 1);
|
pdev->resource[0].end - pdev->resource[0].start + 1);
|
||||||
|
|
||||||
wait_for_completion(&done);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -372,7 +372,7 @@ static int Ti3026_init(struct matrox_fb_info *minfo, struct my_timming *m)
|
||||||
|
|
||||||
DBG(__func__)
|
DBG(__func__)
|
||||||
|
|
||||||
memcpy(hw->DACreg, MGADACbpp32, sizeof(hw->DACreg));
|
memcpy(hw->DACreg, MGADACbpp32, sizeof(MGADACbpp32));
|
||||||
switch (minfo->fbcon.var.bits_per_pixel) {
|
switch (minfo->fbcon.var.bits_per_pixel) {
|
||||||
case 4: hw->DACreg[POS3026_XLATCHCTRL] = TVP3026_XLATCHCTRL_16_1; /* or _8_1, they are same */
|
case 4: hw->DACreg[POS3026_XLATCHCTRL] = TVP3026_XLATCHCTRL_16_1; /* or _8_1, they are same */
|
||||||
hw->DACreg[POS3026_XTRUECOLORCTRL] = TVP3026_XTRUECOLORCTRL_PSEUDOCOLOR;
|
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;
|
return -ENOMEM;
|
||||||
|
|
||||||
ret = get_user_pages_unlocked(current, current->mm, (unsigned long)buf,
|
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) {
|
if (ret < nr_pages) {
|
||||||
nr_pages = ret;
|
nr_pages = ret;
|
||||||
|
|
|
@ -246,8 +246,8 @@ static long ioctl_memcpy(struct fsl_hv_ioctl_memcpy __user *p)
|
||||||
down_read(¤t->mm->mmap_sem);
|
down_read(¤t->mm->mmap_sem);
|
||||||
num_pinned = get_user_pages(current, current->mm,
|
num_pinned = get_user_pages(current, current->mm,
|
||||||
param.local_vaddr - lb_offset, num_pages,
|
param.local_vaddr - lb_offset, num_pages,
|
||||||
(param.source == -1) ? READ : WRITE,
|
(param.source == -1) ? 0 : FOLL_WRITE,
|
||||||
0, pages, NULL);
|
pages, NULL);
|
||||||
up_read(¤t->mm->mmap_sem);
|
up_read(¤t->mm->mmap_sem);
|
||||||
|
|
||||||
if (num_pinned != num_pages) {
|
if (num_pinned != num_pages) {
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
#include <asm/xen/hypervisor.h>
|
#include <asm/xen/hypervisor.h>
|
||||||
|
|
||||||
#include <xen/xen.h>
|
#include <xen/xen.h>
|
||||||
|
#include <xen/xen-ops.h>
|
||||||
#include <xen/page.h>
|
#include <xen/page.h>
|
||||||
#include <xen/interface/xen.h>
|
#include <xen/interface/xen.h>
|
||||||
#include <xen/interface/memory.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);
|
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)
|
struct list_head *stack)
|
||||||
{
|
{
|
||||||
if (list_empty(&moves->list)) {
|
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_add_tail(&moves->list, stack);
|
||||||
list_splice_tail(&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)
|
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;
|
return 0;
|
||||||
|
|
||||||
INIT_LIST_HEAD(&stack);
|
INIT_LIST_HEAD(&stack);
|
||||||
tail_append_pending_moves(pm, &stack);
|
tail_append_pending_moves(sctx, pm, &stack);
|
||||||
|
|
||||||
while (!list_empty(&stack)) {
|
while (!list_empty(&stack)) {
|
||||||
pm = list_first_entry(&stack, struct pending_dir_move, list);
|
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;
|
goto out;
|
||||||
pm = get_pending_dir_moves(sctx, parent_ino);
|
pm = get_pending_dir_moves(sctx, parent_ino);
|
||||||
if (pm)
|
if (pm)
|
||||||
tail_append_pending_moves(pm, &stack);
|
tail_append_pending_moves(sctx, pm, &stack);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|
|
@ -963,11 +963,8 @@ error:
|
||||||
void cachefiles_uncache_page(struct fscache_object *_object, struct page *page)
|
void cachefiles_uncache_page(struct fscache_object *_object, struct page *page)
|
||||||
{
|
{
|
||||||
struct cachefiles_object *object;
|
struct cachefiles_object *object;
|
||||||
struct cachefiles_cache *cache;
|
|
||||||
|
|
||||||
object = container_of(_object, struct cachefiles_object, fscache);
|
object = container_of(_object, struct cachefiles_object, fscache);
|
||||||
cache = container_of(object->fscache.cache,
|
|
||||||
struct cachefiles_cache, cache);
|
|
||||||
|
|
||||||
_enter("%p,{%lu}", object, page->index);
|
_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;
|
struct page *page;
|
||||||
int ret;
|
int ret;
|
||||||
|
unsigned int gup_flags = FOLL_FORCE;
|
||||||
|
|
||||||
#ifdef CONFIG_STACK_GROWSUP
|
#ifdef CONFIG_STACK_GROWSUP
|
||||||
if (write) {
|
if (write) {
|
||||||
|
@ -199,8 +200,12 @@ static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
#endif
|
#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)
|
if (ret <= 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
|
|
@ -76,7 +76,7 @@ static bool dentry_connected(struct dentry *dentry)
|
||||||
struct dentry *parent = dget_parent(dentry);
|
struct dentry *parent = dget_parent(dentry);
|
||||||
|
|
||||||
dput(dentry);
|
dput(dentry);
|
||||||
if (IS_ROOT(dentry)) {
|
if (dentry == parent) {
|
||||||
dput(parent);
|
dput(parent);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -715,6 +715,9 @@ static const struct fscache_state *fscache_drop_object(struct fscache_object *ob
|
||||||
|
|
||||||
if (awaken)
|
if (awaken)
|
||||||
wake_up_bit(&cookie->flags, FSCACHE_COOKIE_INVALIDATING);
|
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
|
/* Prevent a race with our last child, which has to signal EV_CLEARED
|
||||||
* before dropping our spinlock.
|
* before dropping our spinlock.
|
||||||
|
|
|
@ -328,13 +328,14 @@ void hfs_bmap_free(struct hfs_bnode *node)
|
||||||
|
|
||||||
nidx -= len * 8;
|
nidx -= len * 8;
|
||||||
i = node->next;
|
i = node->next;
|
||||||
hfs_bnode_put(node);
|
|
||||||
if (!i) {
|
if (!i) {
|
||||||
/* panic */;
|
/* panic */;
|
||||||
pr_crit("unable to free bnode %u. bmap not found!\n",
|
pr_crit("unable to free bnode %u. bmap not found!\n",
|
||||||
node->this);
|
node->this);
|
||||||
|
hfs_bnode_put(node);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
hfs_bnode_put(node);
|
||||||
node = hfs_bnode_find(tree, i);
|
node = hfs_bnode_find(tree, i);
|
||||||
if (IS_ERR(node))
|
if (IS_ERR(node))
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -453,14 +453,15 @@ void hfs_bmap_free(struct hfs_bnode *node)
|
||||||
|
|
||||||
nidx -= len * 8;
|
nidx -= len * 8;
|
||||||
i = node->next;
|
i = node->next;
|
||||||
hfs_bnode_put(node);
|
|
||||||
if (!i) {
|
if (!i) {
|
||||||
/* panic */;
|
/* panic */;
|
||||||
pr_crit("unable to free bnode %u. "
|
pr_crit("unable to free bnode %u. "
|
||||||
"bmap not found!\n",
|
"bmap not found!\n",
|
||||||
node->this);
|
node->this);
|
||||||
|
hfs_bnode_put(node);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
hfs_bnode_put(node);
|
||||||
node = hfs_bnode_find(tree, i);
|
node = hfs_bnode_find(tree, i);
|
||||||
if (IS_ERR(node))
|
if (IS_ERR(node))
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -118,6 +118,16 @@ static void huge_pagevec_release(struct pagevec *pvec)
|
||||||
pagevec_reinit(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)
|
static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma)
|
||||||
{
|
{
|
||||||
struct inode *inode = file_inode(file);
|
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_flags |= VM_HUGETLB | VM_DONTEXPAND;
|
||||||
vma->vm_ops = &hugetlb_vm_ops;
|
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))
|
if (vma->vm_pgoff & (~huge_page_mask(h) >> PAGE_SHIFT))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
vma_len = (loff_t)(vma->vm_end - vma->vm_start);
|
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);
|
mutex_lock(&inode->i_mutex);
|
||||||
file_accessed(file);
|
file_accessed(file);
|
||||||
|
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
len = vma_len + ((loff_t)vma->vm_pgoff << PAGE_SHIFT);
|
|
||||||
|
|
||||||
if (hugetlb_reserve_pages(inode,
|
if (hugetlb_reserve_pages(inode,
|
||||||
vma->vm_pgoff >> huge_page_order(h),
|
vma->vm_pgoff >> huge_page_order(h),
|
||||||
len >> huge_page_shift(h), vma,
|
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;
|
ret = 0;
|
||||||
if (vma->vm_flags & VM_WRITE && inode->i_size < len)
|
if (vma->vm_flags & VM_WRITE && inode->i_size < len)
|
||||||
inode->i_size = len;
|
i_size_write(inode, len);
|
||||||
out:
|
out:
|
||||||
mutex_unlock(&inode->i_mutex);
|
mutex_unlock(&inode->i_mutex);
|
||||||
|
|
||||||
|
|
|
@ -125,10 +125,10 @@ check_err:
|
||||||
|
|
||||||
check_gen:
|
check_gen:
|
||||||
if (handle->ih_generation != inode->i_generation) {
|
if (handle->ih_generation != inode->i_generation) {
|
||||||
iput(inode);
|
|
||||||
trace_ocfs2_get_dentry_generation((unsigned long long)blkno,
|
trace_ocfs2_get_dentry_generation((unsigned long long)blkno,
|
||||||
handle->ih_generation,
|
handle->ih_generation,
|
||||||
inode->i_generation);
|
inode->i_generation);
|
||||||
|
iput(inode);
|
||||||
result = ERR_PTR(-ESTALE);
|
result = ERR_PTR(-ESTALE);
|
||||||
goto bail;
|
goto bail;
|
||||||
}
|
}
|
||||||
|
|
|
@ -156,18 +156,14 @@ out:
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* lock allocators, and reserving appropriate number of bits for
|
* lock allocator, and reserve appropriate number of bits for
|
||||||
* meta blocks and data clusters.
|
* meta blocks.
|
||||||
*
|
|
||||||
* in some cases, we don't need to reserve clusters, just let data_ac
|
|
||||||
* be NULL.
|
|
||||||
*/
|
*/
|
||||||
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,
|
struct ocfs2_extent_tree *et,
|
||||||
u32 clusters_to_move,
|
u32 clusters_to_move,
|
||||||
u32 extents_to_split,
|
u32 extents_to_split,
|
||||||
struct ocfs2_alloc_context **meta_ac,
|
struct ocfs2_alloc_context **meta_ac,
|
||||||
struct ocfs2_alloc_context **data_ac,
|
|
||||||
int extra_blocks,
|
int extra_blocks,
|
||||||
int *credits)
|
int *credits)
|
||||||
{
|
{
|
||||||
|
@ -192,13 +188,6 @@ static int ocfs2_lock_allocators_move_extents(struct inode *inode,
|
||||||
goto out;
|
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);
|
*credits += ocfs2_calc_extend_credits(osb->sb, et->et_root_el);
|
||||||
|
|
||||||
|
@ -260,9 +249,9 @@ static int ocfs2_defrag_extent(struct ocfs2_move_extents_context *context,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = ocfs2_lock_allocators_move_extents(inode, &context->et, *len, 1,
|
ret = ocfs2_lock_meta_allocator_move_extents(inode, &context->et,
|
||||||
|
*len, 1,
|
||||||
&context->meta_ac,
|
&context->meta_ac,
|
||||||
&context->data_ac,
|
|
||||||
extra_blocks, &credits);
|
extra_blocks, &credits);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
mlog_errno(ret);
|
mlog_errno(ret);
|
||||||
|
@ -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);
|
handle = ocfs2_start_trans(osb, credits);
|
||||||
if (IS_ERR(handle)) {
|
if (IS_ERR(handle)) {
|
||||||
ret = PTR_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,
|
ret = ocfs2_lock_meta_allocator_move_extents(inode, &context->et,
|
||||||
|
len, 1,
|
||||||
&context->meta_ac,
|
&context->meta_ac,
|
||||||
NULL, extra_blocks, &credits);
|
extra_blocks, &credits);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
mlog_errno(ret);
|
mlog_errno(ret);
|
||||||
goto out;
|
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
|
* Inherently racy -- command line shares address space
|
||||||
* with code and data.
|
* 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)
|
if (rv <= 0)
|
||||||
goto out_free_page;
|
goto out_free_page;
|
||||||
|
|
||||||
|
@ -273,7 +273,7 @@ static ssize_t proc_pid_cmdline_read(struct file *file, char __user *buf,
|
||||||
int nr_read;
|
int nr_read;
|
||||||
|
|
||||||
_count = min3(count, len, PAGE_SIZE);
|
_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)
|
if (nr_read < 0)
|
||||||
rv = nr_read;
|
rv = nr_read;
|
||||||
if (nr_read <= 0)
|
if (nr_read <= 0)
|
||||||
|
@ -308,7 +308,7 @@ static ssize_t proc_pid_cmdline_read(struct file *file, char __user *buf,
|
||||||
bool final;
|
bool final;
|
||||||
|
|
||||||
_count = min3(count, len, PAGE_SIZE);
|
_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)
|
if (nr_read < 0)
|
||||||
rv = nr_read;
|
rv = nr_read;
|
||||||
if (nr_read <= 0)
|
if (nr_read <= 0)
|
||||||
|
@ -357,7 +357,7 @@ skip_argv:
|
||||||
bool final;
|
bool final;
|
||||||
|
|
||||||
_count = min3(count, len, PAGE_SIZE);
|
_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)
|
if (nr_read < 0)
|
||||||
rv = nr_read;
|
rv = nr_read;
|
||||||
if (nr_read <= 0)
|
if (nr_read <= 0)
|
||||||
|
@ -869,6 +869,7 @@ static ssize_t mem_rw(struct file *file, char __user *buf,
|
||||||
unsigned long addr = *ppos;
|
unsigned long addr = *ppos;
|
||||||
ssize_t copied;
|
ssize_t copied;
|
||||||
char *page;
|
char *page;
|
||||||
|
unsigned int flags;
|
||||||
|
|
||||||
if (!mm)
|
if (!mm)
|
||||||
return 0;
|
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))
|
if (!atomic_inc_not_zero(&mm->mm_users))
|
||||||
goto free;
|
goto free;
|
||||||
|
|
||||||
|
/* Maybe we should limit FOLL_FORCE to actual ptrace users? */
|
||||||
|
flags = FOLL_FORCE;
|
||||||
|
if (write)
|
||||||
|
flags |= FOLL_WRITE;
|
||||||
|
|
||||||
while (count > 0) {
|
while (count > 0) {
|
||||||
int this_len = min_t(int, count, PAGE_SIZE);
|
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;
|
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 (!this_len) {
|
||||||
if (!copied)
|
if (!copied)
|
||||||
copied = -EIO;
|
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);
|
max_len = min_t(size_t, PAGE_SIZE, count);
|
||||||
this_len = min(max_len, this_len);
|
this_len = min(max_len, this_len);
|
||||||
|
|
||||||
retval = access_remote_vm(mm, (env_start + src),
|
retval = access_remote_vm(mm, (env_start + src), page, this_len, FOLL_ANON);
|
||||||
page, this_len, 0);
|
|
||||||
|
|
||||||
if (retval <= 0) {
|
if (retval <= 0) {
|
||||||
ret = retval;
|
ret = retval;
|
||||||
|
|
|
@ -141,7 +141,7 @@ static void seq_print_vma_name(struct seq_file *m, struct vm_area_struct *vma)
|
||||||
struct page *page;
|
struct page *page;
|
||||||
|
|
||||||
pages_pinned = get_user_pages(current, mm, page_start_vaddr,
|
pages_pinned = get_user_pages(current, mm, page_start_vaddr,
|
||||||
1, 0, 0, &page, NULL);
|
1, 0, &page, NULL);
|
||||||
if (pages_pinned < 1) {
|
if (pages_pinned < 1) {
|
||||||
seq_puts(m, "<fault>]");
|
seq_puts(m, "<fault>]");
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -392,8 +392,8 @@ static void pstore_console_write(struct console *con, const char *s, unsigned c)
|
||||||
} else {
|
} else {
|
||||||
spin_lock_irqsave(&psinfo->buf_lock, flags);
|
spin_lock_irqsave(&psinfo->buf_lock, flags);
|
||||||
}
|
}
|
||||||
memcpy(psinfo->buf, s, c);
|
psinfo->write_buf(PSTORE_TYPE_CONSOLE, 0, &id, 0,
|
||||||
psinfo->write(PSTORE_TYPE_CONSOLE, 0, &id, 0, 0, 0, c, psinfo);
|
s, 0, c, psinfo);
|
||||||
spin_unlock_irqrestore(&psinfo->buf_lock, flags);
|
spin_unlock_irqrestore(&psinfo->buf_lock, flags);
|
||||||
s += c;
|
s += c;
|
||||||
c = e - s;
|
c = e - s;
|
||||||
|
|
|
@ -275,7 +275,7 @@ static int __sysv_write_inode(struct inode *inode, int wait)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
brelse(bh);
|
brelse(bh);
|
||||||
return 0;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
int sysv_write_inode(struct inode *inode, struct writeback_control *wbc)
|
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_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,
|
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,
|
long __get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
|
||||||
unsigned long start, unsigned long nr_pages,
|
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);
|
struct vm_area_struct **vmas, int *nonblocking);
|
||||||
long get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
|
long get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
|
||||||
unsigned long start, unsigned long nr_pages,
|
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);
|
struct vm_area_struct **vmas);
|
||||||
long get_user_pages_locked(struct task_struct *tsk, struct mm_struct *mm,
|
long get_user_pages_locked(struct task_struct *tsk, struct mm_struct *mm,
|
||||||
unsigned long start, unsigned long nr_pages,
|
unsigned long start, unsigned long nr_pages,
|
||||||
int write, int force, struct page **pages,
|
unsigned int gup_flags, struct page **pages, int *locked);
|
||||||
int *locked);
|
|
||||||
long __get_user_pages_unlocked(struct task_struct *tsk, struct mm_struct *mm,
|
long __get_user_pages_unlocked(struct task_struct *tsk, struct mm_struct *mm,
|
||||||
unsigned long start, unsigned long nr_pages,
|
unsigned long start, unsigned long nr_pages,
|
||||||
int write, int force, struct page **pages,
|
struct page **pages, unsigned int gup_flags);
|
||||||
unsigned int gup_flags);
|
|
||||||
long get_user_pages_unlocked(struct task_struct *tsk, struct mm_struct *mm,
|
long get_user_pages_unlocked(struct task_struct *tsk, struct mm_struct *mm,
|
||||||
unsigned long start, unsigned long nr_pages,
|
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,
|
int get_user_pages_fast(unsigned long start, int nr_pages, int write,
|
||||||
struct page **pages);
|
struct page **pages);
|
||||||
|
|
||||||
|
@ -1245,7 +1243,7 @@ struct frame_vector {
|
||||||
struct frame_vector *frame_vector_create(unsigned int nr_frames);
|
struct frame_vector *frame_vector_create(unsigned int nr_frames);
|
||||||
void frame_vector_destroy(struct frame_vector *vec);
|
void frame_vector_destroy(struct frame_vector *vec);
|
||||||
int get_vaddr_frames(unsigned long start, unsigned int nr_pfns,
|
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);
|
void put_vaddr_frames(struct frame_vector *vec);
|
||||||
int frame_vector_to_pages(struct frame_vector *vec);
|
int frame_vector_to_pages(struct frame_vector *vec);
|
||||||
void frame_vector_to_pfns(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_TRIED 0x800 /* a retry, previous pass started an IO */
|
||||||
#define FOLL_MLOCK 0x1000 /* lock present pages */
|
#define FOLL_MLOCK 0x1000 /* lock present pages */
|
||||||
#define FOLL_COW 0x4000 /* internal GUP flag */
|
#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,
|
typedef int (*pte_fn_t)(pte_t *pte, pgtable_t token, unsigned long addr,
|
||||||
void *data);
|
void *data);
|
||||||
|
|
|
@ -65,8 +65,8 @@ struct k_itimer {
|
||||||
spinlock_t it_lock;
|
spinlock_t it_lock;
|
||||||
clockid_t it_clock; /* which timer type */
|
clockid_t it_clock; /* which timer type */
|
||||||
timer_t it_id; /* timer id */
|
timer_t it_id; /* timer id */
|
||||||
int it_overrun; /* overrun on pending signal */
|
s64 it_overrun; /* overrun on pending signal */
|
||||||
int it_overrun_last; /* overrun on last delivered signal */
|
s64 it_overrun_last; /* overrun on last delivered signal */
|
||||||
int it_requeue_pending; /* waiting to requeue this timer */
|
int it_requeue_pending; /* waiting to requeue this timer */
|
||||||
#define REQUEUE_PENDING 1
|
#define REQUEUE_PENDING 1
|
||||||
int it_sigev_notify; /* notify word of sigevent struct */
|
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)
|
static inline int neigh_hh_output(const struct hh_cache *hh, struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
|
unsigned int hh_alen = 0;
|
||||||
unsigned int seq;
|
unsigned int seq;
|
||||||
int hh_len;
|
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);
|
seq = read_seqbegin(&hh->hh_lock);
|
||||||
hh_len = hh->hh_len;
|
hh_len = hh->hh_len;
|
||||||
if (likely(hh_len <= HH_DATA_MOD)) {
|
if (likely(hh_len <= HH_DATA_MOD)) {
|
||||||
/* this is inlined by gcc */
|
hh_alen = HH_DATA_MOD;
|
||||||
memcpy(skb->data - HH_DATA_MOD, hh->hh_data, HH_DATA_MOD);
|
|
||||||
} else {
|
|
||||||
int hh_alen = HH_DATA_ALIGN(hh_len);
|
|
||||||
|
|
||||||
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));
|
} 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);
|
return dev_queue_xmit(skb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -100,7 +100,7 @@ struct snd_pcm_ops {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define SNDRV_PCM_IOCTL1_RESET 0
|
#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_CHANNEL_INFO 2
|
||||||
#define SNDRV_PCM_IOCTL1_GSTATE 3
|
#define SNDRV_PCM_IOCTL1_GSTATE 3
|
||||||
#define SNDRV_PCM_IOCTL1_FIFO_SIZE 4
|
#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 */
|
enum bpf_reg_type ptr_type; /* pointer type for load/store insns */
|
||||||
struct bpf_map *map_ptr; /* pointer for call insn into lookup_elem */
|
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 */
|
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,
|
/* check_stack_read/write functions track spill/fill of registers,
|
||||||
* stack boundary and alignment are checked in check_mem_access()
|
* stack boundary and alignment are checked in check_mem_access()
|
||||||
*/
|
*/
|
||||||
static int check_stack_write(struct verifier_state *state, int off, int size,
|
static int check_stack_write(struct verifier_env *env,
|
||||||
int value_regno)
|
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,
|
/* 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
|
* 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 */
|
/* save register state */
|
||||||
state->spilled_regs[(MAX_BPF_STACK + off) / BPF_REG_SIZE] =
|
state->spilled_regs[spi] = state->regs[value_regno];
|
||||||
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;
|
state->stack_slot_type[MAX_BPF_STACK + off + i] = STACK_SPILL;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
/* regular write of data into stack */
|
/* regular write of data into stack */
|
||||||
state->spilled_regs[(MAX_BPF_STACK + off) / BPF_REG_SIZE] =
|
state->spilled_regs[spi] = (struct reg_state) {};
|
||||||
(struct reg_state) {};
|
|
||||||
|
|
||||||
for (i = 0; i < size; i++)
|
for (i = 0; i < size; i++)
|
||||||
state->stack_slot_type[MAX_BPF_STACK + off + i] = STACK_MISC;
|
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==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
|
* 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 bpf_size, enum bpf_access_type t,
|
||||||
int value_regno)
|
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");
|
verbose("attempt to corrupt spilled pointer on stack\n");
|
||||||
return -EACCES;
|
return -EACCES;
|
||||||
}
|
}
|
||||||
err = check_stack_write(state, off, size, value_regno);
|
err = check_stack_write(env, state, off, size,
|
||||||
|
value_regno, insn_idx);
|
||||||
} else {
|
} else {
|
||||||
err = check_stack_read(state, off, size, value_regno);
|
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;
|
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;
|
struct reg_state *regs = env->cur_state.regs;
|
||||||
int err;
|
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 */
|
/* 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);
|
BPF_SIZE(insn->code), BPF_READ, -1);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
/* check whether atomic_add can write into the same memory */
|
/* 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);
|
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,
|
/* check that memory (src_reg + off) is readable,
|
||||||
* the state of dst_reg will be updated by this func
|
* 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,
|
BPF_SIZE(insn->code), BPF_READ,
|
||||||
insn->dst_reg);
|
insn->dst_reg);
|
||||||
if (err)
|
if (err)
|
||||||
return 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++;
|
insn_idx++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -1876,7 +1902,7 @@ static int do_check(struct verifier_env *env)
|
||||||
enum bpf_reg_type *prev_dst_type, dst_reg_type;
|
enum bpf_reg_type *prev_dst_type, dst_reg_type;
|
||||||
|
|
||||||
if (BPF_MODE(insn->code) == BPF_XADD) {
|
if (BPF_MODE(insn->code) == BPF_XADD) {
|
||||||
err = check_xadd(env, insn);
|
err = check_xadd(env, insn_idx, insn);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
insn_idx++;
|
insn_idx++;
|
||||||
|
@ -1895,7 +1921,7 @@ static int do_check(struct verifier_env *env)
|
||||||
dst_reg_type = regs[insn->dst_reg].type;
|
dst_reg_type = regs[insn->dst_reg].type;
|
||||||
|
|
||||||
/* check that memory (dst_reg + off) is writeable */
|
/* 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,
|
BPF_SIZE(insn->code), BPF_WRITE,
|
||||||
insn->src_reg);
|
insn->src_reg);
|
||||||
if (err)
|
if (err)
|
||||||
|
@ -1930,7 +1956,7 @@ static int do_check(struct verifier_env *env)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check that memory (dst_reg + off) is writeable */
|
/* 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,
|
BPF_SIZE(insn->code), BPF_WRITE,
|
||||||
-1);
|
-1);
|
||||||
if (err)
|
if (err)
|
||||||
|
@ -2220,13 +2246,43 @@ static int convert_ctx_accesses(struct verifier_env *env)
|
||||||
for (i = 0; i < insn_cnt; i++, insn++) {
|
for (i = 0; i < insn_cnt; i++, insn++) {
|
||||||
u32 cnt;
|
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;
|
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;
|
type = BPF_WRITE;
|
||||||
else
|
else
|
||||||
continue;
|
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)
|
if (env->insn_aux_data[i + delta].ptr_type != PTR_TO_CTX)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
|
@ -299,7 +299,7 @@ int uprobe_write_opcode(struct mm_struct *mm, unsigned long vaddr,
|
||||||
|
|
||||||
retry:
|
retry:
|
||||||
/* Read the page with vaddr into memory */
|
/* 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)
|
if (ret <= 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
@ -1700,7 +1700,7 @@ static int is_trap_at_addr(struct mm_struct *mm, unsigned long vaddr)
|
||||||
if (likely(result == 0))
|
if (likely(result == 0))
|
||||||
goto out;
|
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)
|
if (result < 0)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
|
|
|
@ -103,7 +103,7 @@ static void bump_cpu_timer(struct k_itimer *timer,
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
timer->it.cpu.expires += incr;
|
timer->it.cpu.expires += incr;
|
||||||
timer->it_overrun += 1 << i;
|
timer->it_overrun += 1LL << i;
|
||||||
delta -= incr;
|
delta -= incr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -355,6 +355,17 @@ static __init int init_posix_timers(void)
|
||||||
|
|
||||||
__initcall(init_posix_timers);
|
__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)
|
static void schedule_next_timer(struct k_itimer *timr)
|
||||||
{
|
{
|
||||||
struct hrtimer *timer = &timr->it.real.timer;
|
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)
|
if (timr->it.real.interval.tv64 == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
timr->it_overrun += (unsigned int) hrtimer_forward(timer,
|
timr->it_overrun += hrtimer_forward(timer, timer->base->get_time(),
|
||||||
timer->base->get_time(),
|
|
||||||
timr->it.real.interval);
|
timr->it.real.interval);
|
||||||
|
|
||||||
timr->it_overrun_last = timr->it_overrun;
|
timr->it_overrun_last = timr->it_overrun;
|
||||||
timr->it_overrun = -1;
|
timr->it_overrun = -1LL;
|
||||||
++timr->it_requeue_pending;
|
++timr->it_requeue_pending;
|
||||||
hrtimer_restart(timer);
|
hrtimer_restart(timer);
|
||||||
}
|
}
|
||||||
|
@ -396,7 +406,7 @@ void do_schedule_next_timer(struct siginfo *info)
|
||||||
else
|
else
|
||||||
schedule_next_timer(timr);
|
schedule_next_timer(timr);
|
||||||
|
|
||||||
info->si_overrun += timr->it_overrun_last;
|
info->si_overrun = timer_overrun_to_int(timr, info->si_overrun);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (timr)
|
if (timr)
|
||||||
|
@ -491,8 +501,7 @@ static enum hrtimer_restart posix_timer_fn(struct hrtimer *timer)
|
||||||
now = ktime_add(now, kj);
|
now = ktime_add(now, kj);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
timr->it_overrun += (unsigned int)
|
timr->it_overrun += hrtimer_forward(timer, now,
|
||||||
hrtimer_forward(timer, now,
|
|
||||||
timr->it.real.interval);
|
timr->it.real.interval);
|
||||||
ret = HRTIMER_RESTART;
|
ret = HRTIMER_RESTART;
|
||||||
++timr->it_requeue_pending;
|
++timr->it_requeue_pending;
|
||||||
|
@ -633,7 +642,7 @@ SYSCALL_DEFINE3(timer_create, const clockid_t, which_clock,
|
||||||
it_id_set = IT_ID_SET;
|
it_id_set = IT_ID_SET;
|
||||||
new_timer->it_id = (timer_t) new_timer_id;
|
new_timer->it_id = (timer_t) new_timer_id;
|
||||||
new_timer->it_clock = which_clock;
|
new_timer->it_clock = which_clock;
|
||||||
new_timer->it_overrun = -1;
|
new_timer->it_overrun = -1LL;
|
||||||
|
|
||||||
if (timer_event_spec) {
|
if (timer_event_spec) {
|
||||||
if (copy_from_user(&event, timer_event_spec, sizeof (event))) {
|
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 ||
|
if (iv.tv64 && (timr->it_requeue_pending & REQUEUE_PENDING ||
|
||||||
timr->it_sigev_notify == SIGEV_NONE))
|
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);
|
remaining = __hrtimer_expires_remaining_adjusted(timer, now);
|
||||||
/* Return 0 only, when the timer is expired and not pending */
|
/* 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)
|
if (!timr)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
overrun = timr->it_overrun_last;
|
overrun = timer_overrun_to_int(timr, 0);
|
||||||
unlock_timer(timr, flags);
|
unlock_timer(timr, flags);
|
||||||
|
|
||||||
return overrun;
|
return overrun;
|
||||||
|
|
|
@ -119,11 +119,13 @@ static u64 bpf_trace_printk(u64 r1, u64 fmt_size, u64 r3, u64 r4, u64 r5)
|
||||||
i++;
|
i++;
|
||||||
} else if (fmt[i] == 'p' || fmt[i] == 's') {
|
} else if (fmt[i] == 'p' || fmt[i] == 's') {
|
||||||
mod[fmt_cnt]++;
|
mod[fmt_cnt]++;
|
||||||
i++;
|
/* disallow any further format extensions */
|
||||||
if (!isspace(fmt[i]) && !ispunct(fmt[i]) && fmt[i] != 0)
|
if (fmt[i + 1] != 0 &&
|
||||||
|
!isspace(fmt[i + 1]) &&
|
||||||
|
!ispunct(fmt[i + 1]))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
fmt_cnt++;
|
fmt_cnt++;
|
||||||
if (fmt[i - 1] == 's') {
|
if (fmt[i] == 's') {
|
||||||
if (str_seen)
|
if (str_seen)
|
||||||
/* allow only one '%s' per fmt string */
|
/* allow only one '%s' per fmt string */
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
|
@ -1088,7 +1088,8 @@ void __init debug_objects_mem_init(void)
|
||||||
|
|
||||||
obj_cache = kmem_cache_create("debug_objects_cache",
|
obj_cache = kmem_cache_create("debug_objects_cache",
|
||||||
sizeof (struct debug_obj), 0,
|
sizeof (struct debug_obj), 0,
|
||||||
SLAB_DEBUG_OBJECTS, NULL);
|
SLAB_DEBUG_OBJECTS | SLAB_NOLEAKTRACE,
|
||||||
|
NULL);
|
||||||
|
|
||||||
if (!obj_cache || debug_objects_replace_static_objects()) {
|
if (!obj_cache || debug_objects_replace_static_objects()) {
|
||||||
debug_objects_enabled = 0;
|
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