mirror of
https://github.com/torvalds/linux.git
synced 2024-12-14 07:02:23 +00:00
Merge branch 'x86/core' into x86/build, to avoid conflicts
Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
commit
bce6824cc8
@ -15,7 +15,8 @@ than x86. Check the v86d documentation for a list of currently supported
|
||||
arches.
|
||||
|
||||
v86d source code can be downloaded from the following website:
|
||||
http://dev.gentoo.org/~spock/projects/uvesafb
|
||||
|
||||
https://github.com/mjanusz/v86d
|
||||
|
||||
Please refer to the v86d documentation for detailed configuration and
|
||||
installation instructions.
|
||||
@ -177,7 +178,7 @@ from the Video BIOS if you set pixclock to 0 in fb_var_screeninfo.
|
||||
|
||||
--
|
||||
Michal Januszewski <spock@gentoo.org>
|
||||
Last updated: 2009-03-30
|
||||
Last updated: 2017-10-10
|
||||
|
||||
Documentation of the uvesafb options is loosely based on vesafb.txt.
|
||||
|
||||
|
@ -1251,7 +1251,7 @@ N: meson
|
||||
|
||||
ARM/Annapurna Labs ALPINE ARCHITECTURE
|
||||
M: Tsahee Zidenberg <tsahee@annapurnalabs.com>
|
||||
M: Antoine Tenart <antoine.tenart@free-electrons.com>
|
||||
M: Antoine Tenart <antoine.tenart@bootlin.com>
|
||||
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
||||
S: Maintained
|
||||
F: arch/arm/mach-alpine/
|
||||
@ -15395,7 +15395,7 @@ S: Maintained
|
||||
UVESAFB DRIVER
|
||||
M: Michal Januszewski <spock@gentoo.org>
|
||||
L: linux-fbdev@vger.kernel.org
|
||||
W: http://dev.gentoo.org/~spock/projects/uvesafb/
|
||||
W: https://github.com/mjanusz/v86d
|
||||
S: Maintained
|
||||
F: Documentation/fb/uvesafb.txt
|
||||
F: drivers/video/fbdev/uvesafb.*
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "sama5d2-pinfunc.h"
|
||||
#include <dt-bindings/mfd/atmel-flexcom.h>
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/pinctrl/at91.h>
|
||||
|
||||
/ {
|
||||
model = "Atmel SAMA5D2 PTC EK";
|
||||
@ -299,6 +300,7 @@
|
||||
<PIN_PA30__NWE_NANDWE>,
|
||||
<PIN_PB2__NRD_NANDOE>;
|
||||
bias-pull-up;
|
||||
atmel,drive-strength = <ATMEL_PIO_DRVSTR_ME>;
|
||||
};
|
||||
|
||||
ale_cle_rdy_cs {
|
||||
|
@ -106,21 +106,23 @@
|
||||
global_timer: timer@1e200 {
|
||||
compatible = "arm,cortex-a9-global-timer";
|
||||
reg = <0x1e200 0x20>;
|
||||
interrupts = <GIC_PPI 11 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupts = <GIC_PPI 11 IRQ_TYPE_EDGE_RISING>;
|
||||
clocks = <&axi_clk>;
|
||||
};
|
||||
|
||||
local_timer: local-timer@1e600 {
|
||||
compatible = "arm,cortex-a9-twd-timer";
|
||||
reg = <0x1e600 0x20>;
|
||||
interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(2) |
|
||||
IRQ_TYPE_EDGE_RISING)>;
|
||||
clocks = <&axi_clk>;
|
||||
};
|
||||
|
||||
twd_watchdog: watchdog@1e620 {
|
||||
compatible = "arm,cortex-a9-twd-wdt";
|
||||
reg = <0x1e620 0x20>;
|
||||
interrupts = <GIC_PPI 14 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupts = <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(2) |
|
||||
IRQ_TYPE_LEVEL_HIGH)>;
|
||||
};
|
||||
|
||||
armpll: armpll {
|
||||
@ -158,7 +160,7 @@
|
||||
serial0: serial@600 {
|
||||
compatible = "brcm,bcm6345-uart";
|
||||
reg = <0x600 0x1b>;
|
||||
interrupts = <GIC_SPI 32 0>;
|
||||
interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&periph_clk>;
|
||||
clock-names = "periph";
|
||||
status = "disabled";
|
||||
@ -167,7 +169,7 @@
|
||||
serial1: serial@620 {
|
||||
compatible = "brcm,bcm6345-uart";
|
||||
reg = <0x620 0x1b>;
|
||||
interrupts = <GIC_SPI 33 0>;
|
||||
interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&periph_clk>;
|
||||
clock-names = "periph";
|
||||
status = "disabled";
|
||||
@ -180,7 +182,7 @@
|
||||
reg = <0x2000 0x600>, <0xf0 0x10>;
|
||||
reg-names = "nand", "nand-int-base";
|
||||
status = "disabled";
|
||||
interrupts = <GIC_SPI 38 0>;
|
||||
interrupts = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-names = "nand";
|
||||
};
|
||||
|
||||
|
@ -1078,8 +1078,8 @@
|
||||
interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&rcc SPI6_K>;
|
||||
resets = <&rcc SPI6_R>;
|
||||
dmas = <&mdma1 34 0x0 0x40008 0x0 0x0 0>,
|
||||
<&mdma1 35 0x0 0x40002 0x0 0x0 0>;
|
||||
dmas = <&mdma1 34 0x0 0x40008 0x0 0x0>,
|
||||
<&mdma1 35 0x0 0x40002 0x0 0x0>;
|
||||
dma-names = "rx", "tx";
|
||||
status = "disabled";
|
||||
};
|
||||
|
@ -800,8 +800,7 @@
|
||||
};
|
||||
|
||||
hdmi_phy: hdmi-phy@1ef0000 {
|
||||
compatible = "allwinner,sun8i-r40-hdmi-phy",
|
||||
"allwinner,sun50i-a64-hdmi-phy";
|
||||
compatible = "allwinner,sun8i-r40-hdmi-phy";
|
||||
reg = <0x01ef0000 0x10000>;
|
||||
clocks = <&ccu CLK_BUS_HDMI1>, <&ccu CLK_HDMI_SLOW>,
|
||||
<&ccu 7>, <&ccu 16>;
|
||||
|
@ -57,6 +57,45 @@ static u64 core_reg_offset_from_id(u64 id)
|
||||
return id & ~(KVM_REG_ARCH_MASK | KVM_REG_SIZE_MASK | KVM_REG_ARM_CORE);
|
||||
}
|
||||
|
||||
static int validate_core_offset(const struct kvm_one_reg *reg)
|
||||
{
|
||||
u64 off = core_reg_offset_from_id(reg->id);
|
||||
int size;
|
||||
|
||||
switch (off) {
|
||||
case KVM_REG_ARM_CORE_REG(regs.regs[0]) ...
|
||||
KVM_REG_ARM_CORE_REG(regs.regs[30]):
|
||||
case KVM_REG_ARM_CORE_REG(regs.sp):
|
||||
case KVM_REG_ARM_CORE_REG(regs.pc):
|
||||
case KVM_REG_ARM_CORE_REG(regs.pstate):
|
||||
case KVM_REG_ARM_CORE_REG(sp_el1):
|
||||
case KVM_REG_ARM_CORE_REG(elr_el1):
|
||||
case KVM_REG_ARM_CORE_REG(spsr[0]) ...
|
||||
KVM_REG_ARM_CORE_REG(spsr[KVM_NR_SPSR - 1]):
|
||||
size = sizeof(__u64);
|
||||
break;
|
||||
|
||||
case KVM_REG_ARM_CORE_REG(fp_regs.vregs[0]) ...
|
||||
KVM_REG_ARM_CORE_REG(fp_regs.vregs[31]):
|
||||
size = sizeof(__uint128_t);
|
||||
break;
|
||||
|
||||
case KVM_REG_ARM_CORE_REG(fp_regs.fpsr):
|
||||
case KVM_REG_ARM_CORE_REG(fp_regs.fpcr):
|
||||
size = sizeof(__u32);
|
||||
break;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (KVM_REG_SIZE(reg->id) == size &&
|
||||
IS_ALIGNED(off, size / sizeof(__u32)))
|
||||
return 0;
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int get_core_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
|
||||
{
|
||||
/*
|
||||
@ -76,6 +115,9 @@ static int get_core_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
|
||||
(off + (KVM_REG_SIZE(reg->id) / sizeof(__u32))) >= nr_regs)
|
||||
return -ENOENT;
|
||||
|
||||
if (validate_core_offset(reg))
|
||||
return -EINVAL;
|
||||
|
||||
if (copy_to_user(uaddr, ((u32 *)regs) + off, KVM_REG_SIZE(reg->id)))
|
||||
return -EFAULT;
|
||||
|
||||
@ -98,6 +140,9 @@ static int set_core_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
|
||||
(off + (KVM_REG_SIZE(reg->id) / sizeof(__u32))) >= nr_regs)
|
||||
return -ENOENT;
|
||||
|
||||
if (validate_core_offset(reg))
|
||||
return -EINVAL;
|
||||
|
||||
if (KVM_REG_SIZE(reg->id) > sizeof(tmp))
|
||||
return -EINVAL;
|
||||
|
||||
@ -107,17 +152,25 @@ static int set_core_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
|
||||
}
|
||||
|
||||
if (off == KVM_REG_ARM_CORE_REG(regs.pstate)) {
|
||||
u32 mode = (*(u32 *)valp) & PSR_AA32_MODE_MASK;
|
||||
u64 mode = (*(u64 *)valp) & PSR_AA32_MODE_MASK;
|
||||
switch (mode) {
|
||||
case PSR_AA32_MODE_USR:
|
||||
if (!system_supports_32bit_el0())
|
||||
return -EINVAL;
|
||||
break;
|
||||
case PSR_AA32_MODE_FIQ:
|
||||
case PSR_AA32_MODE_IRQ:
|
||||
case PSR_AA32_MODE_SVC:
|
||||
case PSR_AA32_MODE_ABT:
|
||||
case PSR_AA32_MODE_UND:
|
||||
if (!vcpu_el1_is_32bit(vcpu))
|
||||
return -EINVAL;
|
||||
break;
|
||||
case PSR_MODE_EL0t:
|
||||
case PSR_MODE_EL1t:
|
||||
case PSR_MODE_EL1h:
|
||||
if (vcpu_el1_is_32bit(vcpu))
|
||||
return -EINVAL;
|
||||
break;
|
||||
default:
|
||||
err = -EINVAL;
|
||||
|
@ -117,11 +117,14 @@ static pte_t get_clear_flush(struct mm_struct *mm,
|
||||
|
||||
/*
|
||||
* If HW_AFDBM is enabled, then the HW could turn on
|
||||
* the dirty bit for any page in the set, so check
|
||||
* them all. All hugetlb entries are already young.
|
||||
* the dirty or accessed bit for any page in the set,
|
||||
* so check them all.
|
||||
*/
|
||||
if (pte_dirty(pte))
|
||||
orig_pte = pte_mkdirty(orig_pte);
|
||||
|
||||
if (pte_young(pte))
|
||||
orig_pte = pte_mkyoung(orig_pte);
|
||||
}
|
||||
|
||||
if (valid) {
|
||||
@ -320,11 +323,40 @@ pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
|
||||
return get_clear_flush(mm, addr, ptep, pgsize, ncontig);
|
||||
}
|
||||
|
||||
/*
|
||||
* huge_ptep_set_access_flags will update access flags (dirty, accesssed)
|
||||
* and write permission.
|
||||
*
|
||||
* For a contiguous huge pte range we need to check whether or not write
|
||||
* permission has to change only on the first pte in the set. Then for
|
||||
* all the contiguous ptes we need to check whether or not there is a
|
||||
* discrepancy between dirty or young.
|
||||
*/
|
||||
static int __cont_access_flags_changed(pte_t *ptep, pte_t pte, int ncontig)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (pte_write(pte) != pte_write(huge_ptep_get(ptep)))
|
||||
return 1;
|
||||
|
||||
for (i = 0; i < ncontig; i++) {
|
||||
pte_t orig_pte = huge_ptep_get(ptep + i);
|
||||
|
||||
if (pte_dirty(pte) != pte_dirty(orig_pte))
|
||||
return 1;
|
||||
|
||||
if (pte_young(pte) != pte_young(orig_pte))
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int huge_ptep_set_access_flags(struct vm_area_struct *vma,
|
||||
unsigned long addr, pte_t *ptep,
|
||||
pte_t pte, int dirty)
|
||||
{
|
||||
int ncontig, i, changed = 0;
|
||||
int ncontig, i;
|
||||
size_t pgsize = 0;
|
||||
unsigned long pfn = pte_pfn(pte), dpfn;
|
||||
pgprot_t hugeprot;
|
||||
@ -336,19 +368,23 @@ int huge_ptep_set_access_flags(struct vm_area_struct *vma,
|
||||
ncontig = find_num_contig(vma->vm_mm, addr, ptep, &pgsize);
|
||||
dpfn = pgsize >> PAGE_SHIFT;
|
||||
|
||||
orig_pte = get_clear_flush(vma->vm_mm, addr, ptep, pgsize, ncontig);
|
||||
if (!pte_same(orig_pte, pte))
|
||||
changed = 1;
|
||||
if (!__cont_access_flags_changed(ptep, pte, ncontig))
|
||||
return 0;
|
||||
|
||||
/* Make sure we don't lose the dirty state */
|
||||
orig_pte = get_clear_flush(vma->vm_mm, addr, ptep, pgsize, ncontig);
|
||||
|
||||
/* Make sure we don't lose the dirty or young state */
|
||||
if (pte_dirty(orig_pte))
|
||||
pte = pte_mkdirty(pte);
|
||||
|
||||
if (pte_young(orig_pte))
|
||||
pte = pte_mkyoung(pte);
|
||||
|
||||
hugeprot = pte_pgprot(pte);
|
||||
for (i = 0; i < ncontig; i++, ptep++, addr += pgsize, pfn += dpfn)
|
||||
set_pte_at(vma->vm_mm, addr, ptep, pfn_pte(pfn, hugeprot));
|
||||
|
||||
return changed;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void huge_ptep_set_wrprotect(struct mm_struct *mm,
|
||||
|
@ -130,6 +130,9 @@
|
||||
# define _ASM_EXTABLE(from, to) \
|
||||
_ASM_EXTABLE_HANDLE(from, to, ex_handler_default)
|
||||
|
||||
# define _ASM_EXTABLE_UA(from, to) \
|
||||
_ASM_EXTABLE_HANDLE(from, to, ex_handler_uaccess)
|
||||
|
||||
# define _ASM_EXTABLE_FAULT(from, to) \
|
||||
_ASM_EXTABLE_HANDLE(from, to, ex_handler_fault)
|
||||
|
||||
@ -165,8 +168,8 @@
|
||||
jmp copy_user_handle_tail
|
||||
.previous
|
||||
|
||||
_ASM_EXTABLE(100b,103b)
|
||||
_ASM_EXTABLE(101b,103b)
|
||||
_ASM_EXTABLE_UA(100b, 103b)
|
||||
_ASM_EXTABLE_UA(101b, 103b)
|
||||
.endm
|
||||
|
||||
#else
|
||||
@ -182,6 +185,9 @@
|
||||
# define _ASM_EXTABLE(from, to) \
|
||||
_ASM_EXTABLE_HANDLE(from, to, ex_handler_default)
|
||||
|
||||
# define _ASM_EXTABLE_UA(from, to) \
|
||||
_ASM_EXTABLE_HANDLE(from, to, ex_handler_uaccess)
|
||||
|
||||
# define _ASM_EXTABLE_FAULT(from, to) \
|
||||
_ASM_EXTABLE_HANDLE(from, to, ex_handler_fault)
|
||||
|
||||
|
@ -29,7 +29,8 @@ struct pt_regs;
|
||||
(b)->handler = (tmp).handler - (delta); \
|
||||
} while (0)
|
||||
|
||||
extern int fixup_exception(struct pt_regs *regs, int trapnr);
|
||||
extern int fixup_exception(struct pt_regs *regs, int trapnr,
|
||||
unsigned long error_code, unsigned long fault_addr);
|
||||
extern int fixup_bug(struct pt_regs *regs, int trapnr);
|
||||
extern bool ex_has_fault_handler(unsigned long ip);
|
||||
extern void early_fixup_exception(struct pt_regs *regs, int trapnr);
|
||||
|
@ -226,7 +226,7 @@ static inline void copy_fxregs_to_kernel(struct fpu *fpu)
|
||||
"3: movl $-2,%[err]\n\t" \
|
||||
"jmp 2b\n\t" \
|
||||
".popsection\n\t" \
|
||||
_ASM_EXTABLE(1b, 3b) \
|
||||
_ASM_EXTABLE_UA(1b, 3b) \
|
||||
: [err] "=r" (err) \
|
||||
: "D" (st), "m" (*st), "a" (lmask), "d" (hmask) \
|
||||
: "memory")
|
||||
|
@ -20,7 +20,7 @@
|
||||
"3:\tmov\t%3, %1\n" \
|
||||
"\tjmp\t2b\n" \
|
||||
"\t.previous\n" \
|
||||
_ASM_EXTABLE(1b, 3b) \
|
||||
_ASM_EXTABLE_UA(1b, 3b) \
|
||||
: "=r" (oldval), "=r" (ret), "+m" (*uaddr) \
|
||||
: "i" (-EFAULT), "0" (oparg), "1" (0))
|
||||
|
||||
@ -36,8 +36,8 @@
|
||||
"4:\tmov\t%5, %1\n" \
|
||||
"\tjmp\t3b\n" \
|
||||
"\t.previous\n" \
|
||||
_ASM_EXTABLE(1b, 4b) \
|
||||
_ASM_EXTABLE(2b, 4b) \
|
||||
_ASM_EXTABLE_UA(1b, 4b) \
|
||||
_ASM_EXTABLE_UA(2b, 4b) \
|
||||
: "=&a" (oldval), "=&r" (ret), \
|
||||
"+m" (*uaddr), "=&r" (tem) \
|
||||
: "r" (oparg), "i" (-EFAULT), "1" (0))
|
||||
|
@ -37,8 +37,10 @@ struct pt_regs {
|
||||
unsigned short __esh;
|
||||
unsigned short fs;
|
||||
unsigned short __fsh;
|
||||
/* On interrupt, gs and __gsh store the vector number. */
|
||||
unsigned short gs;
|
||||
unsigned short __gsh;
|
||||
/* On interrupt, this is the error code. */
|
||||
unsigned long orig_ax;
|
||||
unsigned long ip;
|
||||
unsigned short cs;
|
||||
|
@ -198,8 +198,8 @@ __typeof__(__builtin_choose_expr(sizeof(x) > sizeof(0UL), 0ULL, 0UL))
|
||||
"4: movl %3,%0\n" \
|
||||
" jmp 3b\n" \
|
||||
".previous\n" \
|
||||
_ASM_EXTABLE(1b, 4b) \
|
||||
_ASM_EXTABLE(2b, 4b) \
|
||||
_ASM_EXTABLE_UA(1b, 4b) \
|
||||
_ASM_EXTABLE_UA(2b, 4b) \
|
||||
: "=r" (err) \
|
||||
: "A" (x), "r" (addr), "i" (errret), "0" (err))
|
||||
|
||||
@ -340,8 +340,8 @@ do { \
|
||||
" xorl %%edx,%%edx\n" \
|
||||
" jmp 3b\n" \
|
||||
".previous\n" \
|
||||
_ASM_EXTABLE(1b, 4b) \
|
||||
_ASM_EXTABLE(2b, 4b) \
|
||||
_ASM_EXTABLE_UA(1b, 4b) \
|
||||
_ASM_EXTABLE_UA(2b, 4b) \
|
||||
: "=r" (retval), "=&A"(x) \
|
||||
: "m" (__m(__ptr)), "m" __m(((u32 __user *)(__ptr)) + 1), \
|
||||
"i" (errret), "0" (retval)); \
|
||||
@ -386,7 +386,7 @@ do { \
|
||||
" xor"itype" %"rtype"1,%"rtype"1\n" \
|
||||
" jmp 2b\n" \
|
||||
".previous\n" \
|
||||
_ASM_EXTABLE(1b, 3b) \
|
||||
_ASM_EXTABLE_UA(1b, 3b) \
|
||||
: "=r" (err), ltype(x) \
|
||||
: "m" (__m(addr)), "i" (errret), "0" (err))
|
||||
|
||||
@ -398,7 +398,7 @@ do { \
|
||||
"3: mov %3,%0\n" \
|
||||
" jmp 2b\n" \
|
||||
".previous\n" \
|
||||
_ASM_EXTABLE(1b, 3b) \
|
||||
_ASM_EXTABLE_UA(1b, 3b) \
|
||||
: "=r" (err), ltype(x) \
|
||||
: "m" (__m(addr)), "i" (errret), "0" (err))
|
||||
|
||||
@ -474,7 +474,7 @@ struct __large_struct { unsigned long buf[100]; };
|
||||
"3: mov %3,%0\n" \
|
||||
" jmp 2b\n" \
|
||||
".previous\n" \
|
||||
_ASM_EXTABLE(1b, 3b) \
|
||||
_ASM_EXTABLE_UA(1b, 3b) \
|
||||
: "=r"(err) \
|
||||
: ltype(x), "m" (__m(addr)), "i" (errret), "0" (err))
|
||||
|
||||
@ -602,7 +602,7 @@ extern void __cmpxchg_wrong_size(void)
|
||||
"3:\tmov %3, %0\n" \
|
||||
"\tjmp 2b\n" \
|
||||
"\t.previous\n" \
|
||||
_ASM_EXTABLE(1b, 3b) \
|
||||
_ASM_EXTABLE_UA(1b, 3b) \
|
||||
: "+r" (__ret), "=a" (__old), "+m" (*(ptr)) \
|
||||
: "i" (-EFAULT), "q" (__new), "1" (__old) \
|
||||
: "memory" \
|
||||
@ -618,7 +618,7 @@ extern void __cmpxchg_wrong_size(void)
|
||||
"3:\tmov %3, %0\n" \
|
||||
"\tjmp 2b\n" \
|
||||
"\t.previous\n" \
|
||||
_ASM_EXTABLE(1b, 3b) \
|
||||
_ASM_EXTABLE_UA(1b, 3b) \
|
||||
: "+r" (__ret), "=a" (__old), "+m" (*(ptr)) \
|
||||
: "i" (-EFAULT), "r" (__new), "1" (__old) \
|
||||
: "memory" \
|
||||
@ -634,7 +634,7 @@ extern void __cmpxchg_wrong_size(void)
|
||||
"3:\tmov %3, %0\n" \
|
||||
"\tjmp 2b\n" \
|
||||
"\t.previous\n" \
|
||||
_ASM_EXTABLE(1b, 3b) \
|
||||
_ASM_EXTABLE_UA(1b, 3b) \
|
||||
: "+r" (__ret), "=a" (__old), "+m" (*(ptr)) \
|
||||
: "i" (-EFAULT), "r" (__new), "1" (__old) \
|
||||
: "memory" \
|
||||
@ -653,7 +653,7 @@ extern void __cmpxchg_wrong_size(void)
|
||||
"3:\tmov %3, %0\n" \
|
||||
"\tjmp 2b\n" \
|
||||
"\t.previous\n" \
|
||||
_ASM_EXTABLE(1b, 3b) \
|
||||
_ASM_EXTABLE_UA(1b, 3b) \
|
||||
: "+r" (__ret), "=a" (__old), "+m" (*(ptr)) \
|
||||
: "i" (-EFAULT), "r" (__new), "1" (__old) \
|
||||
: "memory" \
|
||||
|
@ -1315,7 +1315,7 @@ void do_machine_check(struct pt_regs *regs, long error_code)
|
||||
local_irq_disable();
|
||||
ist_end_non_atomic();
|
||||
} else {
|
||||
if (!fixup_exception(regs, X86_TRAP_MC))
|
||||
if (!fixup_exception(regs, X86_TRAP_MC, error_code, 0))
|
||||
mce_panic("Failed kernel mode recovery", &m, NULL);
|
||||
}
|
||||
|
||||
|
@ -1020,50 +1020,12 @@ int kprobe_fault_handler(struct pt_regs *regs, int trapnr)
|
||||
*/
|
||||
if (cur->fault_handler && cur->fault_handler(cur, regs, trapnr))
|
||||
return 1;
|
||||
|
||||
/*
|
||||
* In case the user-specified fault handler returned
|
||||
* zero, try to fix up.
|
||||
*/
|
||||
if (fixup_exception(regs, trapnr))
|
||||
return 1;
|
||||
|
||||
/*
|
||||
* fixup routine could not handle it,
|
||||
* Let do_page_fault() fix it.
|
||||
*/
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
NOKPROBE_SYMBOL(kprobe_fault_handler);
|
||||
|
||||
/*
|
||||
* Wrapper routine for handling exceptions.
|
||||
*/
|
||||
int kprobe_exceptions_notify(struct notifier_block *self, unsigned long val,
|
||||
void *data)
|
||||
{
|
||||
struct die_args *args = data;
|
||||
int ret = NOTIFY_DONE;
|
||||
|
||||
if (args->regs && user_mode(args->regs))
|
||||
return ret;
|
||||
|
||||
if (val == DIE_GPF) {
|
||||
/*
|
||||
* To be potentially processing a kprobe fault and to
|
||||
* trust the result from kprobe_running(), we have
|
||||
* be non-preemptible.
|
||||
*/
|
||||
if (!preemptible() && kprobe_running() &&
|
||||
kprobe_fault_handler(args->regs, args->trapnr))
|
||||
ret = NOTIFY_STOP;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
NOKPROBE_SYMBOL(kprobe_exceptions_notify);
|
||||
|
||||
bool arch_within_kprobe_blacklist(unsigned long addr)
|
||||
{
|
||||
bool is_in_entry_trampoline_section = false;
|
||||
|
@ -206,7 +206,7 @@ do_trap_no_signal(struct task_struct *tsk, int trapnr, char *str,
|
||||
}
|
||||
|
||||
if (!user_mode(regs)) {
|
||||
if (fixup_exception(regs, trapnr))
|
||||
if (fixup_exception(regs, trapnr, error_code, 0))
|
||||
return 0;
|
||||
|
||||
tsk->thread.error_code = error_code;
|
||||
@ -551,11 +551,21 @@ do_general_protection(struct pt_regs *regs, long error_code)
|
||||
|
||||
tsk = current;
|
||||
if (!user_mode(regs)) {
|
||||
if (fixup_exception(regs, X86_TRAP_GP))
|
||||
if (fixup_exception(regs, X86_TRAP_GP, error_code, 0))
|
||||
return;
|
||||
|
||||
tsk->thread.error_code = error_code;
|
||||
tsk->thread.trap_nr = X86_TRAP_GP;
|
||||
|
||||
/*
|
||||
* To be potentially processing a kprobe fault and to
|
||||
* trust the result from kprobe_running(), we have to
|
||||
* be non-preemptible.
|
||||
*/
|
||||
if (!preemptible() && kprobe_running() &&
|
||||
kprobe_fault_handler(regs, X86_TRAP_GP))
|
||||
return;
|
||||
|
||||
if (notify_die(DIE_GPF, "general protection fault", regs, error_code,
|
||||
X86_TRAP_GP, SIGSEGV) != NOTIFY_STOP)
|
||||
die("general protection fault", regs, error_code);
|
||||
@ -838,7 +848,7 @@ static void math_error(struct pt_regs *regs, int error_code, int trapnr)
|
||||
cond_local_irq_enable(regs);
|
||||
|
||||
if (!user_mode(regs)) {
|
||||
if (fixup_exception(regs, trapnr))
|
||||
if (fixup_exception(regs, trapnr, error_code, 0))
|
||||
return;
|
||||
|
||||
task->thread.error_code = error_code;
|
||||
|
@ -273,11 +273,11 @@ unsigned int csum_partial_copy_generic (const char *src, char *dst,
|
||||
|
||||
#define SRC(y...) \
|
||||
9999: y; \
|
||||
_ASM_EXTABLE(9999b, 6001f)
|
||||
_ASM_EXTABLE_UA(9999b, 6001f)
|
||||
|
||||
#define DST(y...) \
|
||||
9999: y; \
|
||||
_ASM_EXTABLE(9999b, 6002f)
|
||||
_ASM_EXTABLE_UA(9999b, 6002f)
|
||||
|
||||
#ifndef CONFIG_X86_USE_PPRO_CHECKSUM
|
||||
|
||||
|
@ -92,26 +92,26 @@ ENTRY(copy_user_generic_unrolled)
|
||||
60: jmp copy_user_handle_tail /* ecx is zerorest also */
|
||||
.previous
|
||||
|
||||
_ASM_EXTABLE(1b,30b)
|
||||
_ASM_EXTABLE(2b,30b)
|
||||
_ASM_EXTABLE(3b,30b)
|
||||
_ASM_EXTABLE(4b,30b)
|
||||
_ASM_EXTABLE(5b,30b)
|
||||
_ASM_EXTABLE(6b,30b)
|
||||
_ASM_EXTABLE(7b,30b)
|
||||
_ASM_EXTABLE(8b,30b)
|
||||
_ASM_EXTABLE(9b,30b)
|
||||
_ASM_EXTABLE(10b,30b)
|
||||
_ASM_EXTABLE(11b,30b)
|
||||
_ASM_EXTABLE(12b,30b)
|
||||
_ASM_EXTABLE(13b,30b)
|
||||
_ASM_EXTABLE(14b,30b)
|
||||
_ASM_EXTABLE(15b,30b)
|
||||
_ASM_EXTABLE(16b,30b)
|
||||
_ASM_EXTABLE(18b,40b)
|
||||
_ASM_EXTABLE(19b,40b)
|
||||
_ASM_EXTABLE(21b,50b)
|
||||
_ASM_EXTABLE(22b,50b)
|
||||
_ASM_EXTABLE_UA(1b, 30b)
|
||||
_ASM_EXTABLE_UA(2b, 30b)
|
||||
_ASM_EXTABLE_UA(3b, 30b)
|
||||
_ASM_EXTABLE_UA(4b, 30b)
|
||||
_ASM_EXTABLE_UA(5b, 30b)
|
||||
_ASM_EXTABLE_UA(6b, 30b)
|
||||
_ASM_EXTABLE_UA(7b, 30b)
|
||||
_ASM_EXTABLE_UA(8b, 30b)
|
||||
_ASM_EXTABLE_UA(9b, 30b)
|
||||
_ASM_EXTABLE_UA(10b, 30b)
|
||||
_ASM_EXTABLE_UA(11b, 30b)
|
||||
_ASM_EXTABLE_UA(12b, 30b)
|
||||
_ASM_EXTABLE_UA(13b, 30b)
|
||||
_ASM_EXTABLE_UA(14b, 30b)
|
||||
_ASM_EXTABLE_UA(15b, 30b)
|
||||
_ASM_EXTABLE_UA(16b, 30b)
|
||||
_ASM_EXTABLE_UA(18b, 40b)
|
||||
_ASM_EXTABLE_UA(19b, 40b)
|
||||
_ASM_EXTABLE_UA(21b, 50b)
|
||||
_ASM_EXTABLE_UA(22b, 50b)
|
||||
ENDPROC(copy_user_generic_unrolled)
|
||||
EXPORT_SYMBOL(copy_user_generic_unrolled)
|
||||
|
||||
@ -156,8 +156,8 @@ ENTRY(copy_user_generic_string)
|
||||
jmp copy_user_handle_tail
|
||||
.previous
|
||||
|
||||
_ASM_EXTABLE(1b,11b)
|
||||
_ASM_EXTABLE(3b,12b)
|
||||
_ASM_EXTABLE_UA(1b, 11b)
|
||||
_ASM_EXTABLE_UA(3b, 12b)
|
||||
ENDPROC(copy_user_generic_string)
|
||||
EXPORT_SYMBOL(copy_user_generic_string)
|
||||
|
||||
@ -189,7 +189,7 @@ ENTRY(copy_user_enhanced_fast_string)
|
||||
jmp copy_user_handle_tail
|
||||
.previous
|
||||
|
||||
_ASM_EXTABLE(1b,12b)
|
||||
_ASM_EXTABLE_UA(1b, 12b)
|
||||
ENDPROC(copy_user_enhanced_fast_string)
|
||||
EXPORT_SYMBOL(copy_user_enhanced_fast_string)
|
||||
|
||||
@ -319,27 +319,27 @@ ENTRY(__copy_user_nocache)
|
||||
jmp copy_user_handle_tail
|
||||
.previous
|
||||
|
||||
_ASM_EXTABLE(1b,.L_fixup_4x8b_copy)
|
||||
_ASM_EXTABLE(2b,.L_fixup_4x8b_copy)
|
||||
_ASM_EXTABLE(3b,.L_fixup_4x8b_copy)
|
||||
_ASM_EXTABLE(4b,.L_fixup_4x8b_copy)
|
||||
_ASM_EXTABLE(5b,.L_fixup_4x8b_copy)
|
||||
_ASM_EXTABLE(6b,.L_fixup_4x8b_copy)
|
||||
_ASM_EXTABLE(7b,.L_fixup_4x8b_copy)
|
||||
_ASM_EXTABLE(8b,.L_fixup_4x8b_copy)
|
||||
_ASM_EXTABLE(9b,.L_fixup_4x8b_copy)
|
||||
_ASM_EXTABLE(10b,.L_fixup_4x8b_copy)
|
||||
_ASM_EXTABLE(11b,.L_fixup_4x8b_copy)
|
||||
_ASM_EXTABLE(12b,.L_fixup_4x8b_copy)
|
||||
_ASM_EXTABLE(13b,.L_fixup_4x8b_copy)
|
||||
_ASM_EXTABLE(14b,.L_fixup_4x8b_copy)
|
||||
_ASM_EXTABLE(15b,.L_fixup_4x8b_copy)
|
||||
_ASM_EXTABLE(16b,.L_fixup_4x8b_copy)
|
||||
_ASM_EXTABLE(20b,.L_fixup_8b_copy)
|
||||
_ASM_EXTABLE(21b,.L_fixup_8b_copy)
|
||||
_ASM_EXTABLE(30b,.L_fixup_4b_copy)
|
||||
_ASM_EXTABLE(31b,.L_fixup_4b_copy)
|
||||
_ASM_EXTABLE(40b,.L_fixup_1b_copy)
|
||||
_ASM_EXTABLE(41b,.L_fixup_1b_copy)
|
||||
_ASM_EXTABLE_UA(1b, .L_fixup_4x8b_copy)
|
||||
_ASM_EXTABLE_UA(2b, .L_fixup_4x8b_copy)
|
||||
_ASM_EXTABLE_UA(3b, .L_fixup_4x8b_copy)
|
||||
_ASM_EXTABLE_UA(4b, .L_fixup_4x8b_copy)
|
||||
_ASM_EXTABLE_UA(5b, .L_fixup_4x8b_copy)
|
||||
_ASM_EXTABLE_UA(6b, .L_fixup_4x8b_copy)
|
||||
_ASM_EXTABLE_UA(7b, .L_fixup_4x8b_copy)
|
||||
_ASM_EXTABLE_UA(8b, .L_fixup_4x8b_copy)
|
||||
_ASM_EXTABLE_UA(9b, .L_fixup_4x8b_copy)
|
||||
_ASM_EXTABLE_UA(10b, .L_fixup_4x8b_copy)
|
||||
_ASM_EXTABLE_UA(11b, .L_fixup_4x8b_copy)
|
||||
_ASM_EXTABLE_UA(12b, .L_fixup_4x8b_copy)
|
||||
_ASM_EXTABLE_UA(13b, .L_fixup_4x8b_copy)
|
||||
_ASM_EXTABLE_UA(14b, .L_fixup_4x8b_copy)
|
||||
_ASM_EXTABLE_UA(15b, .L_fixup_4x8b_copy)
|
||||
_ASM_EXTABLE_UA(16b, .L_fixup_4x8b_copy)
|
||||
_ASM_EXTABLE_UA(20b, .L_fixup_8b_copy)
|
||||
_ASM_EXTABLE_UA(21b, .L_fixup_8b_copy)
|
||||
_ASM_EXTABLE_UA(30b, .L_fixup_4b_copy)
|
||||
_ASM_EXTABLE_UA(31b, .L_fixup_4b_copy)
|
||||
_ASM_EXTABLE_UA(40b, .L_fixup_1b_copy)
|
||||
_ASM_EXTABLE_UA(41b, .L_fixup_1b_copy)
|
||||
ENDPROC(__copy_user_nocache)
|
||||
EXPORT_SYMBOL(__copy_user_nocache)
|
||||
|
@ -31,14 +31,18 @@
|
||||
|
||||
.macro source
|
||||
10:
|
||||
_ASM_EXTABLE(10b, .Lbad_source)
|
||||
_ASM_EXTABLE_UA(10b, .Lbad_source)
|
||||
.endm
|
||||
|
||||
.macro dest
|
||||
20:
|
||||
_ASM_EXTABLE(20b, .Lbad_dest)
|
||||
_ASM_EXTABLE_UA(20b, .Lbad_dest)
|
||||
.endm
|
||||
|
||||
/*
|
||||
* No _ASM_EXTABLE_UA; this is used for intentional prefetch on a
|
||||
* potentially unmapped kernel address.
|
||||
*/
|
||||
.macro ignore L=.Lignore
|
||||
30:
|
||||
_ASM_EXTABLE(30b, \L)
|
||||
|
@ -132,12 +132,12 @@ bad_get_user_8:
|
||||
END(bad_get_user_8)
|
||||
#endif
|
||||
|
||||
_ASM_EXTABLE(1b,bad_get_user)
|
||||
_ASM_EXTABLE(2b,bad_get_user)
|
||||
_ASM_EXTABLE(3b,bad_get_user)
|
||||
_ASM_EXTABLE_UA(1b, bad_get_user)
|
||||
_ASM_EXTABLE_UA(2b, bad_get_user)
|
||||
_ASM_EXTABLE_UA(3b, bad_get_user)
|
||||
#ifdef CONFIG_X86_64
|
||||
_ASM_EXTABLE(4b,bad_get_user)
|
||||
_ASM_EXTABLE_UA(4b, bad_get_user)
|
||||
#else
|
||||
_ASM_EXTABLE(4b,bad_get_user_8)
|
||||
_ASM_EXTABLE(5b,bad_get_user_8)
|
||||
_ASM_EXTABLE_UA(4b, bad_get_user_8)
|
||||
_ASM_EXTABLE_UA(5b, bad_get_user_8)
|
||||
#endif
|
||||
|
@ -94,10 +94,10 @@ bad_put_user:
|
||||
EXIT
|
||||
END(bad_put_user)
|
||||
|
||||
_ASM_EXTABLE(1b,bad_put_user)
|
||||
_ASM_EXTABLE(2b,bad_put_user)
|
||||
_ASM_EXTABLE(3b,bad_put_user)
|
||||
_ASM_EXTABLE(4b,bad_put_user)
|
||||
_ASM_EXTABLE_UA(1b, bad_put_user)
|
||||
_ASM_EXTABLE_UA(2b, bad_put_user)
|
||||
_ASM_EXTABLE_UA(3b, bad_put_user)
|
||||
_ASM_EXTABLE_UA(4b, bad_put_user)
|
||||
#ifdef CONFIG_X86_32
|
||||
_ASM_EXTABLE(5b,bad_put_user)
|
||||
_ASM_EXTABLE_UA(5b, bad_put_user)
|
||||
#endif
|
||||
|
@ -47,8 +47,8 @@ do { \
|
||||
"3: lea 0(%2,%0,4),%0\n" \
|
||||
" jmp 2b\n" \
|
||||
".previous\n" \
|
||||
_ASM_EXTABLE(0b,3b) \
|
||||
_ASM_EXTABLE(1b,2b) \
|
||||
_ASM_EXTABLE_UA(0b, 3b) \
|
||||
_ASM_EXTABLE_UA(1b, 2b) \
|
||||
: "=&c"(size), "=&D" (__d0) \
|
||||
: "r"(size & 3), "0"(size / 4), "1"(addr), "a"(0)); \
|
||||
} while (0)
|
||||
@ -153,44 +153,44 @@ __copy_user_intel(void __user *to, const void *from, unsigned long size)
|
||||
"101: lea 0(%%eax,%0,4),%0\n"
|
||||
" jmp 100b\n"
|
||||
".previous\n"
|
||||
_ASM_EXTABLE(1b,100b)
|
||||
_ASM_EXTABLE(2b,100b)
|
||||
_ASM_EXTABLE(3b,100b)
|
||||
_ASM_EXTABLE(4b,100b)
|
||||
_ASM_EXTABLE(5b,100b)
|
||||
_ASM_EXTABLE(6b,100b)
|
||||
_ASM_EXTABLE(7b,100b)
|
||||
_ASM_EXTABLE(8b,100b)
|
||||
_ASM_EXTABLE(9b,100b)
|
||||
_ASM_EXTABLE(10b,100b)
|
||||
_ASM_EXTABLE(11b,100b)
|
||||
_ASM_EXTABLE(12b,100b)
|
||||
_ASM_EXTABLE(13b,100b)
|
||||
_ASM_EXTABLE(14b,100b)
|
||||
_ASM_EXTABLE(15b,100b)
|
||||
_ASM_EXTABLE(16b,100b)
|
||||
_ASM_EXTABLE(17b,100b)
|
||||
_ASM_EXTABLE(18b,100b)
|
||||
_ASM_EXTABLE(19b,100b)
|
||||
_ASM_EXTABLE(20b,100b)
|
||||
_ASM_EXTABLE(21b,100b)
|
||||
_ASM_EXTABLE(22b,100b)
|
||||
_ASM_EXTABLE(23b,100b)
|
||||
_ASM_EXTABLE(24b,100b)
|
||||
_ASM_EXTABLE(25b,100b)
|
||||
_ASM_EXTABLE(26b,100b)
|
||||
_ASM_EXTABLE(27b,100b)
|
||||
_ASM_EXTABLE(28b,100b)
|
||||
_ASM_EXTABLE(29b,100b)
|
||||
_ASM_EXTABLE(30b,100b)
|
||||
_ASM_EXTABLE(31b,100b)
|
||||
_ASM_EXTABLE(32b,100b)
|
||||
_ASM_EXTABLE(33b,100b)
|
||||
_ASM_EXTABLE(34b,100b)
|
||||
_ASM_EXTABLE(35b,100b)
|
||||
_ASM_EXTABLE(36b,100b)
|
||||
_ASM_EXTABLE(37b,100b)
|
||||
_ASM_EXTABLE(99b,101b)
|
||||
_ASM_EXTABLE_UA(1b, 100b)
|
||||
_ASM_EXTABLE_UA(2b, 100b)
|
||||
_ASM_EXTABLE_UA(3b, 100b)
|
||||
_ASM_EXTABLE_UA(4b, 100b)
|
||||
_ASM_EXTABLE_UA(5b, 100b)
|
||||
_ASM_EXTABLE_UA(6b, 100b)
|
||||
_ASM_EXTABLE_UA(7b, 100b)
|
||||
_ASM_EXTABLE_UA(8b, 100b)
|
||||
_ASM_EXTABLE_UA(9b, 100b)
|
||||
_ASM_EXTABLE_UA(10b, 100b)
|
||||
_ASM_EXTABLE_UA(11b, 100b)
|
||||
_ASM_EXTABLE_UA(12b, 100b)
|
||||
_ASM_EXTABLE_UA(13b, 100b)
|
||||
_ASM_EXTABLE_UA(14b, 100b)
|
||||
_ASM_EXTABLE_UA(15b, 100b)
|
||||
_ASM_EXTABLE_UA(16b, 100b)
|
||||
_ASM_EXTABLE_UA(17b, 100b)
|
||||
_ASM_EXTABLE_UA(18b, 100b)
|
||||
_ASM_EXTABLE_UA(19b, 100b)
|
||||
_ASM_EXTABLE_UA(20b, 100b)
|
||||
_ASM_EXTABLE_UA(21b, 100b)
|
||||
_ASM_EXTABLE_UA(22b, 100b)
|
||||
_ASM_EXTABLE_UA(23b, 100b)
|
||||
_ASM_EXTABLE_UA(24b, 100b)
|
||||
_ASM_EXTABLE_UA(25b, 100b)
|
||||
_ASM_EXTABLE_UA(26b, 100b)
|
||||
_ASM_EXTABLE_UA(27b, 100b)
|
||||
_ASM_EXTABLE_UA(28b, 100b)
|
||||
_ASM_EXTABLE_UA(29b, 100b)
|
||||
_ASM_EXTABLE_UA(30b, 100b)
|
||||
_ASM_EXTABLE_UA(31b, 100b)
|
||||
_ASM_EXTABLE_UA(32b, 100b)
|
||||
_ASM_EXTABLE_UA(33b, 100b)
|
||||
_ASM_EXTABLE_UA(34b, 100b)
|
||||
_ASM_EXTABLE_UA(35b, 100b)
|
||||
_ASM_EXTABLE_UA(36b, 100b)
|
||||
_ASM_EXTABLE_UA(37b, 100b)
|
||||
_ASM_EXTABLE_UA(99b, 101b)
|
||||
: "=&c"(size), "=&D" (d0), "=&S" (d1)
|
||||
: "1"(to), "2"(from), "0"(size)
|
||||
: "eax", "edx", "memory");
|
||||
@ -259,26 +259,26 @@ static unsigned long __copy_user_intel_nocache(void *to,
|
||||
"9: lea 0(%%eax,%0,4),%0\n"
|
||||
"16: jmp 8b\n"
|
||||
".previous\n"
|
||||
_ASM_EXTABLE(0b,16b)
|
||||
_ASM_EXTABLE(1b,16b)
|
||||
_ASM_EXTABLE(2b,16b)
|
||||
_ASM_EXTABLE(21b,16b)
|
||||
_ASM_EXTABLE(3b,16b)
|
||||
_ASM_EXTABLE(31b,16b)
|
||||
_ASM_EXTABLE(4b,16b)
|
||||
_ASM_EXTABLE(41b,16b)
|
||||
_ASM_EXTABLE(10b,16b)
|
||||
_ASM_EXTABLE(51b,16b)
|
||||
_ASM_EXTABLE(11b,16b)
|
||||
_ASM_EXTABLE(61b,16b)
|
||||
_ASM_EXTABLE(12b,16b)
|
||||
_ASM_EXTABLE(71b,16b)
|
||||
_ASM_EXTABLE(13b,16b)
|
||||
_ASM_EXTABLE(81b,16b)
|
||||
_ASM_EXTABLE(14b,16b)
|
||||
_ASM_EXTABLE(91b,16b)
|
||||
_ASM_EXTABLE(6b,9b)
|
||||
_ASM_EXTABLE(7b,16b)
|
||||
_ASM_EXTABLE_UA(0b, 16b)
|
||||
_ASM_EXTABLE_UA(1b, 16b)
|
||||
_ASM_EXTABLE_UA(2b, 16b)
|
||||
_ASM_EXTABLE_UA(21b, 16b)
|
||||
_ASM_EXTABLE_UA(3b, 16b)
|
||||
_ASM_EXTABLE_UA(31b, 16b)
|
||||
_ASM_EXTABLE_UA(4b, 16b)
|
||||
_ASM_EXTABLE_UA(41b, 16b)
|
||||
_ASM_EXTABLE_UA(10b, 16b)
|
||||
_ASM_EXTABLE_UA(51b, 16b)
|
||||
_ASM_EXTABLE_UA(11b, 16b)
|
||||
_ASM_EXTABLE_UA(61b, 16b)
|
||||
_ASM_EXTABLE_UA(12b, 16b)
|
||||
_ASM_EXTABLE_UA(71b, 16b)
|
||||
_ASM_EXTABLE_UA(13b, 16b)
|
||||
_ASM_EXTABLE_UA(81b, 16b)
|
||||
_ASM_EXTABLE_UA(14b, 16b)
|
||||
_ASM_EXTABLE_UA(91b, 16b)
|
||||
_ASM_EXTABLE_UA(6b, 9b)
|
||||
_ASM_EXTABLE_UA(7b, 16b)
|
||||
: "=&c"(size), "=&D" (d0), "=&S" (d1)
|
||||
: "1"(to), "2"(from), "0"(size)
|
||||
: "eax", "edx", "memory");
|
||||
@ -321,9 +321,9 @@ do { \
|
||||
"3: lea 0(%3,%0,4),%0\n" \
|
||||
" jmp 2b\n" \
|
||||
".previous\n" \
|
||||
_ASM_EXTABLE(4b,5b) \
|
||||
_ASM_EXTABLE(0b,3b) \
|
||||
_ASM_EXTABLE(1b,2b) \
|
||||
_ASM_EXTABLE_UA(4b, 5b) \
|
||||
_ASM_EXTABLE_UA(0b, 3b) \
|
||||
_ASM_EXTABLE_UA(1b, 2b) \
|
||||
: "=&c"(size), "=&D" (__d0), "=&S" (__d1), "=r"(__d2) \
|
||||
: "3"(size), "0"(size), "1"(to), "2"(from) \
|
||||
: "memory"); \
|
||||
|
@ -37,8 +37,8 @@ unsigned long __clear_user(void __user *addr, unsigned long size)
|
||||
"3: lea 0(%[size1],%[size8],8),%[size8]\n"
|
||||
" jmp 2b\n"
|
||||
".previous\n"
|
||||
_ASM_EXTABLE(0b,3b)
|
||||
_ASM_EXTABLE(1b,2b)
|
||||
_ASM_EXTABLE_UA(0b, 3b)
|
||||
_ASM_EXTABLE_UA(1b, 2b)
|
||||
: [size8] "=&c"(size), [dst] "=&D" (__d0)
|
||||
: [size1] "r"(size & 7), "[size8]" (size / 8), "[dst]"(addr));
|
||||
clac();
|
||||
|
@ -8,7 +8,8 @@
|
||||
#include <asm/kdebug.h>
|
||||
|
||||
typedef bool (*ex_handler_t)(const struct exception_table_entry *,
|
||||
struct pt_regs *, int);
|
||||
struct pt_regs *, int, unsigned long,
|
||||
unsigned long);
|
||||
|
||||
static inline unsigned long
|
||||
ex_fixup_addr(const struct exception_table_entry *x)
|
||||
@ -22,7 +23,9 @@ ex_fixup_handler(const struct exception_table_entry *x)
|
||||
}
|
||||
|
||||
__visible bool ex_handler_default(const struct exception_table_entry *fixup,
|
||||
struct pt_regs *regs, int trapnr)
|
||||
struct pt_regs *regs, int trapnr,
|
||||
unsigned long error_code,
|
||||
unsigned long fault_addr)
|
||||
{
|
||||
regs->ip = ex_fixup_addr(fixup);
|
||||
return true;
|
||||
@ -30,7 +33,9 @@ __visible bool ex_handler_default(const struct exception_table_entry *fixup,
|
||||
EXPORT_SYMBOL(ex_handler_default);
|
||||
|
||||
__visible bool ex_handler_fault(const struct exception_table_entry *fixup,
|
||||
struct pt_regs *regs, int trapnr)
|
||||
struct pt_regs *regs, int trapnr,
|
||||
unsigned long error_code,
|
||||
unsigned long fault_addr)
|
||||
{
|
||||
regs->ip = ex_fixup_addr(fixup);
|
||||
regs->ax = trapnr;
|
||||
@ -43,7 +48,9 @@ EXPORT_SYMBOL_GPL(ex_handler_fault);
|
||||
* result of a refcount inc/dec/add/sub.
|
||||
*/
|
||||
__visible bool ex_handler_refcount(const struct exception_table_entry *fixup,
|
||||
struct pt_regs *regs, int trapnr)
|
||||
struct pt_regs *regs, int trapnr,
|
||||
unsigned long error_code,
|
||||
unsigned long fault_addr)
|
||||
{
|
||||
/* First unconditionally saturate the refcount. */
|
||||
*(int *)regs->cx = INT_MIN / 2;
|
||||
@ -96,7 +103,9 @@ EXPORT_SYMBOL(ex_handler_refcount);
|
||||
* out all the FPU registers) if we can't restore from the task's FPU state.
|
||||
*/
|
||||
__visible bool ex_handler_fprestore(const struct exception_table_entry *fixup,
|
||||
struct pt_regs *regs, int trapnr)
|
||||
struct pt_regs *regs, int trapnr,
|
||||
unsigned long error_code,
|
||||
unsigned long fault_addr)
|
||||
{
|
||||
regs->ip = ex_fixup_addr(fixup);
|
||||
|
||||
@ -108,9 +117,79 @@ __visible bool ex_handler_fprestore(const struct exception_table_entry *fixup,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ex_handler_fprestore);
|
||||
|
||||
__visible bool ex_handler_ext(const struct exception_table_entry *fixup,
|
||||
struct pt_regs *regs, int trapnr)
|
||||
/* Helper to check whether a uaccess fault indicates a kernel bug. */
|
||||
static bool bogus_uaccess(struct pt_regs *regs, int trapnr,
|
||||
unsigned long fault_addr)
|
||||
{
|
||||
/* This is the normal case: #PF with a fault address in userspace. */
|
||||
if (trapnr == X86_TRAP_PF && fault_addr < TASK_SIZE_MAX)
|
||||
return false;
|
||||
|
||||
/*
|
||||
* This code can be reached for machine checks, but only if the #MC
|
||||
* handler has already decided that it looks like a candidate for fixup.
|
||||
* This e.g. happens when attempting to access userspace memory which
|
||||
* the CPU can't access because of uncorrectable bad memory.
|
||||
*/
|
||||
if (trapnr == X86_TRAP_MC)
|
||||
return false;
|
||||
|
||||
/*
|
||||
* There are two remaining exception types we might encounter here:
|
||||
* - #PF for faulting accesses to kernel addresses
|
||||
* - #GP for faulting accesses to noncanonical addresses
|
||||
* Complain about anything else.
|
||||
*/
|
||||
if (trapnr != X86_TRAP_PF && trapnr != X86_TRAP_GP) {
|
||||
WARN(1, "unexpected trap %d in uaccess\n", trapnr);
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is a faulting memory access in kernel space, on a kernel
|
||||
* address, in a usercopy function. This can e.g. be caused by improper
|
||||
* use of helpers like __put_user and by improper attempts to access
|
||||
* userspace addresses in KERNEL_DS regions.
|
||||
* The one (semi-)legitimate exception are probe_kernel_{read,write}(),
|
||||
* which can be invoked from places like kgdb, /dev/mem (for reading)
|
||||
* and privileged BPF code (for reading).
|
||||
* The probe_kernel_*() functions set the kernel_uaccess_faults_ok flag
|
||||
* to tell us that faulting on kernel addresses, and even noncanonical
|
||||
* addresses, in a userspace accessor does not necessarily imply a
|
||||
* kernel bug, root might just be doing weird stuff.
|
||||
*/
|
||||
if (current->kernel_uaccess_faults_ok)
|
||||
return false;
|
||||
|
||||
/* This is bad. Refuse the fixup so that we go into die(). */
|
||||
if (trapnr == X86_TRAP_PF) {
|
||||
pr_emerg("BUG: pagefault on kernel address 0x%lx in non-whitelisted uaccess\n",
|
||||
fault_addr);
|
||||
} else {
|
||||
pr_emerg("BUG: GPF in non-whitelisted uaccess (non-canonical address?)\n");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
__visible bool ex_handler_uaccess(const struct exception_table_entry *fixup,
|
||||
struct pt_regs *regs, int trapnr,
|
||||
unsigned long error_code,
|
||||
unsigned long fault_addr)
|
||||
{
|
||||
if (bogus_uaccess(regs, trapnr, fault_addr))
|
||||
return false;
|
||||
regs->ip = ex_fixup_addr(fixup);
|
||||
return true;
|
||||
}
|
||||
EXPORT_SYMBOL(ex_handler_uaccess);
|
||||
|
||||
__visible bool ex_handler_ext(const struct exception_table_entry *fixup,
|
||||
struct pt_regs *regs, int trapnr,
|
||||
unsigned long error_code,
|
||||
unsigned long fault_addr)
|
||||
{
|
||||
if (bogus_uaccess(regs, trapnr, fault_addr))
|
||||
return false;
|
||||
/* Special hack for uaccess_err */
|
||||
current->thread.uaccess_err = 1;
|
||||
regs->ip = ex_fixup_addr(fixup);
|
||||
@ -119,7 +198,9 @@ __visible bool ex_handler_ext(const struct exception_table_entry *fixup,
|
||||
EXPORT_SYMBOL(ex_handler_ext);
|
||||
|
||||
__visible bool ex_handler_rdmsr_unsafe(const struct exception_table_entry *fixup,
|
||||
struct pt_regs *regs, int trapnr)
|
||||
struct pt_regs *regs, int trapnr,
|
||||
unsigned long error_code,
|
||||
unsigned long fault_addr)
|
||||
{
|
||||
if (pr_warn_once("unchecked MSR access error: RDMSR from 0x%x at rIP: 0x%lx (%pF)\n",
|
||||
(unsigned int)regs->cx, regs->ip, (void *)regs->ip))
|
||||
@ -134,7 +215,9 @@ __visible bool ex_handler_rdmsr_unsafe(const struct exception_table_entry *fixup
|
||||
EXPORT_SYMBOL(ex_handler_rdmsr_unsafe);
|
||||
|
||||
__visible bool ex_handler_wrmsr_unsafe(const struct exception_table_entry *fixup,
|
||||
struct pt_regs *regs, int trapnr)
|
||||
struct pt_regs *regs, int trapnr,
|
||||
unsigned long error_code,
|
||||
unsigned long fault_addr)
|
||||
{
|
||||
if (pr_warn_once("unchecked MSR access error: WRMSR to 0x%x (tried to write 0x%08x%08x) at rIP: 0x%lx (%pF)\n",
|
||||
(unsigned int)regs->cx, (unsigned int)regs->dx,
|
||||
@ -148,12 +231,14 @@ __visible bool ex_handler_wrmsr_unsafe(const struct exception_table_entry *fixup
|
||||
EXPORT_SYMBOL(ex_handler_wrmsr_unsafe);
|
||||
|
||||
__visible bool ex_handler_clear_fs(const struct exception_table_entry *fixup,
|
||||
struct pt_regs *regs, int trapnr)
|
||||
struct pt_regs *regs, int trapnr,
|
||||
unsigned long error_code,
|
||||
unsigned long fault_addr)
|
||||
{
|
||||
if (static_cpu_has(X86_BUG_NULL_SEG))
|
||||
asm volatile ("mov %0, %%fs" : : "rm" (__USER_DS));
|
||||
asm volatile ("mov %0, %%fs" : : "rm" (0));
|
||||
return ex_handler_default(fixup, regs, trapnr);
|
||||
return ex_handler_default(fixup, regs, trapnr, error_code, fault_addr);
|
||||
}
|
||||
EXPORT_SYMBOL(ex_handler_clear_fs);
|
||||
|
||||
@ -170,7 +255,8 @@ __visible bool ex_has_fault_handler(unsigned long ip)
|
||||
return handler == ex_handler_fault;
|
||||
}
|
||||
|
||||
int fixup_exception(struct pt_regs *regs, int trapnr)
|
||||
int fixup_exception(struct pt_regs *regs, int trapnr, unsigned long error_code,
|
||||
unsigned long fault_addr)
|
||||
{
|
||||
const struct exception_table_entry *e;
|
||||
ex_handler_t handler;
|
||||
@ -194,7 +280,7 @@ int fixup_exception(struct pt_regs *regs, int trapnr)
|
||||
return 0;
|
||||
|
||||
handler = ex_fixup_handler(e);
|
||||
return handler(e, regs, trapnr);
|
||||
return handler(e, regs, trapnr, error_code, fault_addr);
|
||||
}
|
||||
|
||||
extern unsigned int early_recursion_flag;
|
||||
@ -230,9 +316,9 @@ void __init early_fixup_exception(struct pt_regs *regs, int trapnr)
|
||||
* result in a hard-to-debug panic.
|
||||
*
|
||||
* Keep in mind that not all vectors actually get here. Early
|
||||
* fage faults, for example, are special.
|
||||
* page faults, for example, are special.
|
||||
*/
|
||||
if (fixup_exception(regs, trapnr))
|
||||
if (fixup_exception(regs, trapnr, regs->orig_ax, 0))
|
||||
return;
|
||||
|
||||
if (fixup_bug(regs, trapnr))
|
||||
|
@ -44,17 +44,19 @@ kmmio_fault(struct pt_regs *regs, unsigned long addr)
|
||||
|
||||
static nokprobe_inline int kprobes_fault(struct pt_regs *regs)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
/* kprobe_running() needs smp_processor_id() */
|
||||
if (kprobes_built_in() && !user_mode(regs)) {
|
||||
preempt_disable();
|
||||
if (kprobe_running() && kprobe_fault_handler(regs, 14))
|
||||
ret = 1;
|
||||
preempt_enable();
|
||||
}
|
||||
|
||||
return ret;
|
||||
if (!kprobes_built_in())
|
||||
return 0;
|
||||
if (user_mode(regs))
|
||||
return 0;
|
||||
/*
|
||||
* To be potentially processing a kprobe fault and to be allowed to call
|
||||
* kprobe_running(), we have to be non-preemptible.
|
||||
*/
|
||||
if (preemptible())
|
||||
return 0;
|
||||
if (!kprobe_running())
|
||||
return 0;
|
||||
return kprobe_fault_handler(regs, X86_TRAP_PF);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -709,7 +711,7 @@ no_context(struct pt_regs *regs, unsigned long error_code,
|
||||
int sig;
|
||||
|
||||
/* Are we prepared to handle this kernel fault? */
|
||||
if (fixup_exception(regs, X86_TRAP_PF)) {
|
||||
if (fixup_exception(regs, X86_TRAP_PF, error_code, address)) {
|
||||
/*
|
||||
* Any interrupt that takes a fault gets the fixup. This makes
|
||||
* the below recursive fault logic only apply to a faults from
|
||||
|
@ -183,6 +183,7 @@ static const struct crashtype crashtypes[] = {
|
||||
CRASHTYPE(USERCOPY_STACK_FRAME_FROM),
|
||||
CRASHTYPE(USERCOPY_STACK_BEYOND),
|
||||
CRASHTYPE(USERCOPY_KERNEL),
|
||||
CRASHTYPE(USERCOPY_KERNEL_DS),
|
||||
};
|
||||
|
||||
|
||||
|
@ -82,5 +82,6 @@ void lkdtm_USERCOPY_STACK_FRAME_TO(void);
|
||||
void lkdtm_USERCOPY_STACK_FRAME_FROM(void);
|
||||
void lkdtm_USERCOPY_STACK_BEYOND(void);
|
||||
void lkdtm_USERCOPY_KERNEL(void);
|
||||
void lkdtm_USERCOPY_KERNEL_DS(void);
|
||||
|
||||
#endif
|
||||
|
@ -322,6 +322,19 @@ free_user:
|
||||
vm_munmap(user_addr, PAGE_SIZE);
|
||||
}
|
||||
|
||||
void lkdtm_USERCOPY_KERNEL_DS(void)
|
||||
{
|
||||
char __user *user_ptr = (char __user *)ERR_PTR(-EINVAL);
|
||||
mm_segment_t old_fs = get_fs();
|
||||
char buf[10] = {0};
|
||||
|
||||
pr_info("attempting copy_to_user on unmapped kernel address\n");
|
||||
set_fs(KERNEL_DS);
|
||||
if (copy_to_user(user_ptr, buf, sizeof(buf)))
|
||||
pr_info("copy_to_user un unmapped kernel address failed\n");
|
||||
set_fs(old_fs);
|
||||
}
|
||||
|
||||
void __init lkdtm_usercopy_init(void)
|
||||
{
|
||||
/* Prepare cache that lacks SLAB_USERCOPY flag. */
|
||||
|
@ -235,7 +235,7 @@ int mmc_of_parse(struct mmc_host *host)
|
||||
host->caps |= MMC_CAP_NEEDS_POLL;
|
||||
|
||||
ret = mmc_gpiod_request_cd(host, "cd", 0, true,
|
||||
cd_debounce_delay_ms,
|
||||
cd_debounce_delay_ms * 1000,
|
||||
&cd_gpio_invert);
|
||||
if (!ret)
|
||||
dev_info(host->parent, "Got CD GPIO\n");
|
||||
|
@ -271,7 +271,7 @@ int mmc_gpiod_request_cd(struct mmc_host *host, const char *con_id,
|
||||
if (debounce) {
|
||||
ret = gpiod_set_debounce(desc, debounce);
|
||||
if (ret < 0)
|
||||
ctx->cd_debounce_delay_ms = debounce;
|
||||
ctx->cd_debounce_delay_ms = debounce / 1000;
|
||||
}
|
||||
|
||||
if (gpio_invert)
|
||||
|
@ -498,7 +498,8 @@ static const struct soc_device_attribute gen3_soc_whitelist[] = {
|
||||
|
||||
static int renesas_sdhi_sys_dmac_probe(struct platform_device *pdev)
|
||||
{
|
||||
if (of_device_get_match_data(&pdev->dev) == &of_rcar_gen3_compatible &&
|
||||
if ((of_device_get_match_data(&pdev->dev) == &of_rcar_gen3_compatible ||
|
||||
of_device_get_match_data(&pdev->dev) == &of_rcar_r8a7795_compatible) &&
|
||||
!soc_device_match(gen3_soc_whitelist))
|
||||
return -ENODEV;
|
||||
|
||||
|
@ -2729,6 +2729,9 @@ static int qman_alloc_range(struct gen_pool *p, u32 *result, u32 cnt)
|
||||
{
|
||||
unsigned long addr;
|
||||
|
||||
if (!p)
|
||||
return -ENODEV;
|
||||
|
||||
addr = gen_pool_alloc(p, cnt);
|
||||
if (!addr)
|
||||
return -ENOMEM;
|
||||
|
@ -626,7 +626,7 @@ static u32 ucc_get_tdm_sync_shift(enum comm_dir mode, u32 tdm_num)
|
||||
{
|
||||
u32 shift;
|
||||
|
||||
shift = (mode == COMM_DIR_RX) ? RX_SYNC_SHIFT_BASE : RX_SYNC_SHIFT_BASE;
|
||||
shift = (mode == COMM_DIR_RX) ? RX_SYNC_SHIFT_BASE : TX_SYNC_SHIFT_BASE;
|
||||
shift -= tdm_num * 2;
|
||||
|
||||
return shift;
|
||||
|
@ -42,6 +42,7 @@ struct bmp_dib_header {
|
||||
u32 colors_important;
|
||||
} __packed;
|
||||
|
||||
static bool use_bgrt = true;
|
||||
static bool request_mem_succeeded = false;
|
||||
static u64 mem_flags = EFI_MEMORY_WC | EFI_MEMORY_UC;
|
||||
|
||||
@ -160,6 +161,9 @@ static void efifb_show_boot_graphics(struct fb_info *info)
|
||||
void *bgrt_image = NULL;
|
||||
u8 *dst = info->screen_base;
|
||||
|
||||
if (!use_bgrt)
|
||||
return;
|
||||
|
||||
if (!bgrt_tab.image_address) {
|
||||
pr_info("efifb: No BGRT, not showing boot graphics\n");
|
||||
return;
|
||||
@ -290,6 +294,8 @@ static int efifb_setup(char *options)
|
||||
screen_info.lfb_width = simple_strtoul(this_opt+6, NULL, 0);
|
||||
else if (!strcmp(this_opt, "nowc"))
|
||||
mem_flags &= ~EFI_MEMORY_WC;
|
||||
else if (!strcmp(this_opt, "nobgrt"))
|
||||
use_bgrt = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -496,6 +496,9 @@ static int omapfb_memory_read(struct fb_info *fbi,
|
||||
if (!access_ok(VERIFY_WRITE, mr->buffer, mr->buffer_size))
|
||||
return -EFAULT;
|
||||
|
||||
if (mr->w > 4096 || mr->h > 4096)
|
||||
return -EINVAL;
|
||||
|
||||
if (mr->w * mr->h * 3 > mr->buffer_size)
|
||||
return -EINVAL;
|
||||
|
||||
@ -509,7 +512,7 @@ static int omapfb_memory_read(struct fb_info *fbi,
|
||||
mr->x, mr->y, mr->w, mr->h);
|
||||
|
||||
if (r > 0) {
|
||||
if (copy_to_user(mr->buffer, buf, mr->buffer_size))
|
||||
if (copy_to_user(mr->buffer, buf, r))
|
||||
r = -EFAULT;
|
||||
}
|
||||
|
||||
|
@ -712,7 +712,7 @@ static int pxa168fb_probe(struct platform_device *pdev)
|
||||
/*
|
||||
* enable controller clock
|
||||
*/
|
||||
clk_enable(fbi->clk);
|
||||
clk_prepare_enable(fbi->clk);
|
||||
|
||||
pxa168fb_set_par(info);
|
||||
|
||||
@ -767,7 +767,7 @@ static int pxa168fb_probe(struct platform_device *pdev)
|
||||
failed_free_cmap:
|
||||
fb_dealloc_cmap(&info->cmap);
|
||||
failed_free_clk:
|
||||
clk_disable(fbi->clk);
|
||||
clk_disable_unprepare(fbi->clk);
|
||||
failed_free_fbmem:
|
||||
dma_free_coherent(fbi->dev, info->fix.smem_len,
|
||||
info->screen_base, fbi->fb_start_dma);
|
||||
@ -807,7 +807,7 @@ static int pxa168fb_remove(struct platform_device *pdev)
|
||||
dma_free_wc(fbi->dev, PAGE_ALIGN(info->fix.smem_len),
|
||||
info->screen_base, info->fix.smem_start);
|
||||
|
||||
clk_disable(fbi->clk);
|
||||
clk_disable_unprepare(fbi->clk);
|
||||
|
||||
framebuffer_release(info);
|
||||
|
||||
|
@ -1157,7 +1157,7 @@ static int __init stifb_init_fb(struct sti_struct *sti, int bpp_pref)
|
||||
dev_name);
|
||||
goto out_err0;
|
||||
}
|
||||
/* fall though */
|
||||
/* fall through */
|
||||
case S9000_ID_ARTIST:
|
||||
case S9000_ID_HCRX:
|
||||
case S9000_ID_TIMBER:
|
||||
|
@ -2642,6 +2642,7 @@ static long exact_copy_from_user(void *to, const void __user * from,
|
||||
if (!access_ok(VERIFY_READ, from, n))
|
||||
return n;
|
||||
|
||||
current->kernel_uaccess_faults_ok++;
|
||||
while (n) {
|
||||
if (__get_user(c, f)) {
|
||||
memset(t, 0, n);
|
||||
@ -2651,6 +2652,7 @@ static long exact_copy_from_user(void *to, const void __user * from,
|
||||
f++;
|
||||
n--;
|
||||
}
|
||||
current->kernel_uaccess_faults_ok--;
|
||||
return n;
|
||||
}
|
||||
|
||||
|
@ -898,8 +898,22 @@ static struct platform_driver ramoops_driver = {
|
||||
},
|
||||
};
|
||||
|
||||
static void ramoops_register_dummy(void)
|
||||
static inline void ramoops_unregister_dummy(void)
|
||||
{
|
||||
platform_device_unregister(dummy);
|
||||
dummy = NULL;
|
||||
|
||||
kfree(dummy_data);
|
||||
dummy_data = NULL;
|
||||
}
|
||||
|
||||
static void __init ramoops_register_dummy(void)
|
||||
{
|
||||
/*
|
||||
* Prepare a dummy platform data structure to carry the module
|
||||
* parameters. If mem_size isn't set, then there are no module
|
||||
* parameters, and we can skip this.
|
||||
*/
|
||||
if (!mem_size)
|
||||
return;
|
||||
|
||||
@ -932,21 +946,28 @@ static void ramoops_register_dummy(void)
|
||||
if (IS_ERR(dummy)) {
|
||||
pr_info("could not create platform device: %ld\n",
|
||||
PTR_ERR(dummy));
|
||||
dummy = NULL;
|
||||
ramoops_unregister_dummy();
|
||||
}
|
||||
}
|
||||
|
||||
static int __init ramoops_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ramoops_register_dummy();
|
||||
return platform_driver_register(&ramoops_driver);
|
||||
ret = platform_driver_register(&ramoops_driver);
|
||||
if (ret != 0)
|
||||
ramoops_unregister_dummy();
|
||||
|
||||
return ret;
|
||||
}
|
||||
late_initcall(ramoops_init);
|
||||
|
||||
static void __exit ramoops_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&ramoops_driver);
|
||||
platform_device_unregister(dummy);
|
||||
kfree(dummy_data);
|
||||
ramoops_unregister_dummy();
|
||||
}
|
||||
module_exit(ramoops_exit);
|
||||
|
||||
|
@ -739,6 +739,12 @@ struct task_struct {
|
||||
unsigned use_memdelay:1;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* May usercopy functions fault on kernel addresses?
|
||||
* This is not just a single bit because this can potentially nest.
|
||||
*/
|
||||
unsigned int kernel_uaccess_faults_ok;
|
||||
|
||||
unsigned long atomic_flags; /* Flags requiring atomic access. */
|
||||
|
||||
struct restart_block restart_block;
|
||||
|
@ -30,8 +30,10 @@ long __probe_kernel_read(void *dst, const void *src, size_t size)
|
||||
|
||||
set_fs(KERNEL_DS);
|
||||
pagefault_disable();
|
||||
current->kernel_uaccess_faults_ok++;
|
||||
ret = __copy_from_user_inatomic(dst,
|
||||
(__force const void __user *)src, size);
|
||||
current->kernel_uaccess_faults_ok--;
|
||||
pagefault_enable();
|
||||
set_fs(old_fs);
|
||||
|
||||
@ -58,7 +60,9 @@ long __probe_kernel_write(void *dst, const void *src, size_t size)
|
||||
|
||||
set_fs(KERNEL_DS);
|
||||
pagefault_disable();
|
||||
current->kernel_uaccess_faults_ok++;
|
||||
ret = __copy_to_user_inatomic((__force void __user *)dst, src, size);
|
||||
current->kernel_uaccess_faults_ok--;
|
||||
pagefault_enable();
|
||||
set_fs(old_fs);
|
||||
|
||||
@ -94,11 +98,13 @@ long strncpy_from_unsafe(char *dst, const void *unsafe_addr, long count)
|
||||
|
||||
set_fs(KERNEL_DS);
|
||||
pagefault_disable();
|
||||
current->kernel_uaccess_faults_ok++;
|
||||
|
||||
do {
|
||||
ret = __get_user(*dst++, (const char __user __force *)src++);
|
||||
} while (dst[-1] && ret == 0 && src - unsafe_addr < count);
|
||||
|
||||
current->kernel_uaccess_faults_ok--;
|
||||
dst[-1] = '\0';
|
||||
pagefault_enable();
|
||||
set_fs(old_fs);
|
||||
|
Loading…
Reference in New Issue
Block a user