Merge remote-tracking branch 'ovl/rename2' into for-linus

This commit is contained in:
Al Viro 2016-10-10 23:02:51 -04:00
commit 3873691e5a
483 changed files with 4393 additions and 2750 deletions

View File

@ -13,6 +13,7 @@ Required properties:
- touchscreen-size-y : See touchscreen.txt - touchscreen-size-y : See touchscreen.txt
Optional properties: Optional properties:
- firmware-name : File basename (string) for board specific firmware
- touchscreen-inverted-x : See touchscreen.txt - touchscreen-inverted-x : See touchscreen.txt
- touchscreen-inverted-y : See touchscreen.txt - touchscreen-inverted-y : See touchscreen.txt
- touchscreen-swapped-x-y : See touchscreen.txt - touchscreen-swapped-x-y : See touchscreen.txt

View File

@ -10,7 +10,7 @@ Required properties:
subsystem (mmcss) inside the FlashSS (available in STiH407 SoC subsystem (mmcss) inside the FlashSS (available in STiH407 SoC
family). family).
- clock-names: Should be "mmc". - clock-names: Should be "mmc" and "icn". (NB: The latter is not compulsory)
See: Documentation/devicetree/bindings/resource-names.txt See: Documentation/devicetree/bindings/resource-names.txt
- clocks: Phandle to the clock. - clocks: Phandle to the clock.
See: Documentation/devicetree/bindings/clock/clock-bindings.txt See: Documentation/devicetree/bindings/clock/clock-bindings.txt

View File

@ -51,8 +51,6 @@ prototypes:
int (*rmdir) (struct inode *,struct dentry *); int (*rmdir) (struct inode *,struct dentry *);
int (*mknod) (struct inode *,struct dentry *,umode_t,dev_t); int (*mknod) (struct inode *,struct dentry *,umode_t,dev_t);
int (*rename) (struct inode *, struct dentry *, int (*rename) (struct inode *, struct dentry *,
struct inode *, struct dentry *);
int (*rename2) (struct inode *, struct dentry *,
struct inode *, struct dentry *, unsigned int); struct inode *, struct dentry *, unsigned int);
int (*readlink) (struct dentry *, char __user *,int); int (*readlink) (struct dentry *, char __user *,int);
const char *(*get_link) (struct dentry *, struct inode *, void **); const char *(*get_link) (struct dentry *, struct inode *, void **);
@ -83,8 +81,7 @@ symlink: yes
mkdir: yes mkdir: yes
unlink: yes (both) unlink: yes (both)
rmdir: yes (both) (see below) rmdir: yes (both) (see below)
rename: yes (all) (see below) rename: yes (all) (see below)
rename2: yes (all) (see below)
readlink: no readlink: no
get_link: no get_link: no
setattr: yes setattr: yes
@ -102,8 +99,7 @@ tmpfile: no
Additionally, ->rmdir(), ->unlink() and ->rename() have ->i_mutex on Additionally, ->rmdir(), ->unlink() and ->rename() have ->i_mutex on
victim. victim.
cross-directory ->rename() and rename2() has (per-superblock) cross-directory ->rename() has (per-superblock) ->s_vfs_rename_sem.
->s_vfs_rename_sem.
See Documentation/filesystems/directory-locking for more detailed discussion See Documentation/filesystems/directory-locking for more detailed discussion
of the locking scheme for directory operations. of the locking scheme for directory operations.

View File

@ -19,7 +19,7 @@ locks victim and calls the method. Locks are exclusive.
4) rename() that is _not_ cross-directory. Locking rules: caller locks 4) rename() that is _not_ cross-directory. Locking rules: caller locks
the parent and finds source and target. In case of exchange (with the parent and finds source and target. In case of exchange (with
RENAME_EXCHANGE in rename2() flags argument) lock both. In any case, RENAME_EXCHANGE in flags argument) lock both. In any case,
if the target already exists, lock it. If the source is a non-directory, if the target already exists, lock it. If the source is a non-directory,
lock it. If we need to lock both, lock them in inode pointer order. lock it. If we need to lock both, lock them in inode pointer order.
Then call the method. All locks are exclusive. Then call the method. All locks are exclusive.

View File

@ -592,3 +592,7 @@ in your dentry operations instead.
work just as well; if it's something more complicated, use dentry->d_parent. work just as well; if it's something more complicated, use dentry->d_parent.
Just be careful not to assume that fetching it more than once will yield Just be careful not to assume that fetching it more than once will yield
the same value - in RCU mode it could change under you. the same value - in RCU mode it could change under you.
--
[mandatory]
->rename() has an added flags argument. Any flags not handled by the
filesystem should result in EINVAL being returned.

View File

@ -346,8 +346,6 @@ struct inode_operations {
int (*rmdir) (struct inode *,struct dentry *); int (*rmdir) (struct inode *,struct dentry *);
int (*mknod) (struct inode *,struct dentry *,umode_t,dev_t); int (*mknod) (struct inode *,struct dentry *,umode_t,dev_t);
int (*rename) (struct inode *, struct dentry *, int (*rename) (struct inode *, struct dentry *,
struct inode *, struct dentry *);
int (*rename2) (struct inode *, struct dentry *,
struct inode *, struct dentry *, unsigned int); struct inode *, struct dentry *, unsigned int);
int (*readlink) (struct dentry *, char __user *,int); int (*readlink) (struct dentry *, char __user *,int);
const char *(*get_link) (struct dentry *, struct inode *, const char *(*get_link) (struct dentry *, struct inode *,
@ -416,11 +414,8 @@ otherwise noted.
rename: called by the rename(2) system call to rename the object to rename: called by the rename(2) system call to rename the object to
have the parent and name given by the second inode and dentry. have the parent and name given by the second inode and dentry.
rename2: this has an additional flags argument compared to rename. The filesystem must return -EINVAL for any unsupported or
If no flags are supported by the filesystem then this method unknown flags. Currently the following flags are implemented:
need not be implemented. If some flags are supported then the
filesystem must return -EINVAL for any unsupported or unknown
flags. Currently the following flags are implemented:
(1) RENAME_NOREPLACE: this flag indicates that if the target (1) RENAME_NOREPLACE: this flag indicates that if the target
of the rename exists the rename should fail with -EEXIST of the rename exists the rename should fail with -EEXIST
instead of replacing the target. The VFS already checks for instead of replacing the target. The VFS already checks for

View File

@ -144,7 +144,7 @@ logical address types are already defined will return with error ``EBUSY``.
- ``flags`` - ``flags``
- Flags. No flags are defined yet, so set this to 0. - Flags. See :ref:`cec-log-addrs-flags` for a list of available flags.
- .. row 7 - .. row 7
@ -201,6 +201,25 @@ logical address types are already defined will return with error ``EBUSY``.
give the CEC framework more information about the device type, even give the CEC framework more information about the device type, even
though the framework won't use it directly in the CEC message. though the framework won't use it directly in the CEC message.
.. _cec-log-addrs-flags:
.. flat-table:: Flags for struct cec_log_addrs
:header-rows: 0
:stub-columns: 0
:widths: 3 1 4
- .. _`CEC-LOG-ADDRS-FL-ALLOW-UNREG-FALLBACK`:
- ``CEC_LOG_ADDRS_FL_ALLOW_UNREG_FALLBACK``
- 1
- By default if no logical address of the requested type can be claimed, then
it will go back to the unconfigured state. If this flag is set, then it will
fallback to the Unregistered logical address. Note that if the Unregistered
logical address was explicitly requested, then this flag has no effect.
.. _cec-versions: .. _cec-versions:
.. flat-table:: CEC Versions .. flat-table:: CEC Versions

View File

@ -64,7 +64,8 @@ it is guaranteed that the state did change in between the two events.
- ``phys_addr`` - ``phys_addr``
- The current physical address. - The current physical address. This is ``CEC_PHYS_ADDR_INVALID`` if no
valid physical address is set.
- .. row 2 - .. row 2
@ -72,7 +73,10 @@ it is guaranteed that the state did change in between the two events.
- ``log_addr_mask`` - ``log_addr_mask``
- The current set of claimed logical addresses. - The current set of claimed logical addresses. This is 0 if no logical
addresses are claimed or if ``phys_addr`` is ``CEC_PHYS_ADDR_INVALID``.
If bit 15 is set (``1 << CEC_LOG_ADDR_UNREGISTERED``) then this device
has the unregistered logical address. In that case all other bits are 0.

View File

@ -1625,6 +1625,7 @@ N: rockchip
ARM/SAMSUNG EXYNOS ARM ARCHITECTURES ARM/SAMSUNG EXYNOS ARM ARCHITECTURES
M: Kukjin Kim <kgene@kernel.org> M: Kukjin Kim <kgene@kernel.org>
M: Krzysztof Kozlowski <krzk@kernel.org> M: Krzysztof Kozlowski <krzk@kernel.org>
R: Javier Martinez Canillas <javier@osg.samsung.com>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
L: linux-samsung-soc@vger.kernel.org (moderated for non-subscribers) L: linux-samsung-soc@vger.kernel.org (moderated for non-subscribers)
S: Maintained S: Maintained
@ -2485,7 +2486,7 @@ F: include/net/bluetooth/
BONDING DRIVER BONDING DRIVER
M: Jay Vosburgh <j.vosburgh@gmail.com> M: Jay Vosburgh <j.vosburgh@gmail.com>
M: Veaceslav Falico <vfalico@gmail.com> M: Veaceslav Falico <vfalico@gmail.com>
M: Andy Gospodarek <gospo@cumulusnetworks.com> M: Andy Gospodarek <andy@greyhouse.net>
L: netdev@vger.kernel.org L: netdev@vger.kernel.org
W: http://sourceforge.net/projects/bonding/ W: http://sourceforge.net/projects/bonding/
S: Supported S: Supported
@ -2500,7 +2501,7 @@ S: Supported
F: kernel/bpf/ F: kernel/bpf/
BROADCOM B44 10/100 ETHERNET DRIVER BROADCOM B44 10/100 ETHERNET DRIVER
M: Gary Zambrano <zambrano@broadcom.com> M: Michael Chan <michael.chan@broadcom.com>
L: netdev@vger.kernel.org L: netdev@vger.kernel.org
S: Supported S: Supported
F: drivers/net/ethernet/broadcom/b44.* F: drivers/net/ethernet/broadcom/b44.*
@ -3269,7 +3270,7 @@ S: Maintained
F: drivers/net/wan/cosa* F: drivers/net/wan/cosa*
CPMAC ETHERNET DRIVER CPMAC ETHERNET DRIVER
M: Florian Fainelli <florian@openwrt.org> M: Florian Fainelli <f.fainelli@gmail.com>
L: netdev@vger.kernel.org L: netdev@vger.kernel.org
S: Maintained S: Maintained
F: drivers/net/ethernet/ti/cpmac.c F: drivers/net/ethernet/ti/cpmac.c
@ -6102,7 +6103,7 @@ S: Supported
F: drivers/cpufreq/intel_pstate.c F: drivers/cpufreq/intel_pstate.c
INTEL FRAMEBUFFER DRIVER (excluding 810 and 815) INTEL FRAMEBUFFER DRIVER (excluding 810 and 815)
M: Maik Broemme <mbroemme@plusserver.de> M: Maik Broemme <mbroemme@libmpq.org>
L: linux-fbdev@vger.kernel.org L: linux-fbdev@vger.kernel.org
S: Maintained S: Maintained
F: Documentation/fb/intelfb.txt F: Documentation/fb/intelfb.txt
@ -8160,6 +8161,15 @@ S: Maintained
W: https://fedorahosted.org/dropwatch/ W: https://fedorahosted.org/dropwatch/
F: net/core/drop_monitor.c F: net/core/drop_monitor.c
NETWORKING [DSA]
M: Andrew Lunn <andrew@lunn.ch>
M: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
M: Florian Fainelli <f.fainelli@gmail.com>
S: Maintained
F: net/dsa/
F: include/net/dsa.h
F: drivers/net/dsa/
NETWORKING [GENERAL] NETWORKING [GENERAL]
M: "David S. Miller" <davem@davemloft.net> M: "David S. Miller" <davem@davemloft.net>
L: netdev@vger.kernel.org L: netdev@vger.kernel.org
@ -12568,7 +12578,7 @@ F: include/linux/if_*vlan.h
F: net/8021q/ F: net/8021q/
VLYNQ BUS VLYNQ BUS
M: Florian Fainelli <florian@openwrt.org> M: Florian Fainelli <f.fainelli@gmail.com>
L: openwrt-devel@lists.openwrt.org (subscribers-only) L: openwrt-devel@lists.openwrt.org (subscribers-only)
S: Maintained S: Maintained
F: drivers/vlynq/vlynq.c F: drivers/vlynq/vlynq.c

View File

@ -1,7 +1,7 @@
VERSION = 4 VERSION = 4
PATCHLEVEL = 8 PATCHLEVEL = 8
SUBLEVEL = 0 SUBLEVEL = 0
EXTRAVERSION = -rc6 EXTRAVERSION = -rc8
NAME = Psychotic Stoned Sheep NAME = Psychotic Stoned Sheep
# *DOCUMENTATION* # *DOCUMENTATION*

View File

@ -371,14 +371,6 @@ __copy_tofrom_user_nocheck(void *to, const void *from, long len)
return __cu_len; return __cu_len;
} }
extern inline long
__copy_tofrom_user(void *to, const void *from, long len, const void __user *validate)
{
if (__access_ok((unsigned long)validate, len, get_fs()))
len = __copy_tofrom_user_nocheck(to, from, len);
return len;
}
#define __copy_to_user(to, from, n) \ #define __copy_to_user(to, from, n) \
({ \ ({ \
__chk_user_ptr(to); \ __chk_user_ptr(to); \
@ -393,17 +385,22 @@ __copy_tofrom_user(void *to, const void *from, long len, const void __user *vali
#define __copy_to_user_inatomic __copy_to_user #define __copy_to_user_inatomic __copy_to_user
#define __copy_from_user_inatomic __copy_from_user #define __copy_from_user_inatomic __copy_from_user
extern inline long extern inline long
copy_to_user(void __user *to, const void *from, long n) copy_to_user(void __user *to, const void *from, long n)
{ {
return __copy_tofrom_user((__force void *)to, from, n, to); if (likely(__access_ok((unsigned long)to, n, get_fs())))
n = __copy_tofrom_user_nocheck((__force void *)to, from, n);
return n;
} }
extern inline long extern inline long
copy_from_user(void *to, const void __user *from, long n) copy_from_user(void *to, const void __user *from, long n)
{ {
return __copy_tofrom_user(to, (__force void *)from, n, from); if (likely(__access_ok((unsigned long)from, n, get_fs())))
n = __copy_tofrom_user_nocheck(to, (__force void *)from, n);
else
memset(to, 0, n);
return n;
} }
extern void __do_clear_user(void); extern void __do_clear_user(void);

View File

@ -83,7 +83,10 @@
"2: ;nop\n" \ "2: ;nop\n" \
" .section .fixup, \"ax\"\n" \ " .section .fixup, \"ax\"\n" \
" .align 4\n" \ " .align 4\n" \
"3: mov %0, %3\n" \ "3: # return -EFAULT\n" \
" mov %0, %3\n" \
" # zero out dst ptr\n" \
" mov %1, 0\n" \
" j 2b\n" \ " j 2b\n" \
" .previous\n" \ " .previous\n" \
" .section __ex_table, \"a\"\n" \ " .section __ex_table, \"a\"\n" \
@ -101,7 +104,11 @@
"2: ;nop\n" \ "2: ;nop\n" \
" .section .fixup, \"ax\"\n" \ " .section .fixup, \"ax\"\n" \
" .align 4\n" \ " .align 4\n" \
"3: mov %0, %3\n" \ "3: # return -EFAULT\n" \
" mov %0, %3\n" \
" # zero out dst ptr\n" \
" mov %1, 0\n" \
" mov %R1, 0\n" \
" j 2b\n" \ " j 2b\n" \
" .previous\n" \ " .previous\n" \
" .section __ex_table, \"a\"\n" \ " .section __ex_table, \"a\"\n" \

View File

@ -2,6 +2,7 @@
/ { / {
memory { memory {
device_type = "memory";
reg = <0 0x10000000>; reg = <0 0x10000000>;
}; };

View File

@ -2,7 +2,6 @@
#include <dt-bindings/clock/bcm2835.h> #include <dt-bindings/clock/bcm2835.h>
#include <dt-bindings/clock/bcm2835-aux.h> #include <dt-bindings/clock/bcm2835-aux.h>
#include <dt-bindings/gpio/gpio.h> #include <dt-bindings/gpio/gpio.h>
#include "skeleton.dtsi"
/* This include file covers the common peripherals and configuration between /* This include file covers the common peripherals and configuration between
* bcm2835 and bcm2836 implementations, leaving the CPU configuration to * bcm2835 and bcm2836 implementations, leaving the CPU configuration to
@ -13,6 +12,8 @@
compatible = "brcm,bcm2835"; compatible = "brcm,bcm2835";
model = "BCM2835"; model = "BCM2835";
interrupt-parent = <&intc>; interrupt-parent = <&intc>;
#address-cells = <1>;
#size-cells = <1>;
chosen { chosen {
bootargs = "earlyprintk console=ttyAMA0"; bootargs = "earlyprintk console=ttyAMA0";

View File

@ -550,8 +550,9 @@
interrupt-names = "mmcirq"; interrupt-names = "mmcirq";
pinctrl-names = "default"; pinctrl-names = "default";
pinctrl-0 = <&pinctrl_mmc0>; pinctrl-0 = <&pinctrl_mmc0>;
clock-names = "mmc"; clock-names = "mmc", "icn";
clocks = <&clk_s_c0_flexgen CLK_MMC_0>; clocks = <&clk_s_c0_flexgen CLK_MMC_0>,
<&clk_s_c0_flexgen CLK_RX_ICN_HVA>;
bus-width = <8>; bus-width = <8>;
non-removable; non-removable;
}; };
@ -565,8 +566,9 @@
interrupt-names = "mmcirq"; interrupt-names = "mmcirq";
pinctrl-names = "default"; pinctrl-names = "default";
pinctrl-0 = <&pinctrl_sd1>; pinctrl-0 = <&pinctrl_sd1>;
clock-names = "mmc"; clock-names = "mmc", "icn";
clocks = <&clk_s_c0_flexgen CLK_MMC_1>; clocks = <&clk_s_c0_flexgen CLK_MMC_1>,
<&clk_s_c0_flexgen CLK_RX_ICN_HVA>;
resets = <&softreset STIH407_MMC1_SOFTRESET>; resets = <&softreset STIH407_MMC1_SOFTRESET>;
bus-width = <4>; bus-width = <4>;
}; };

View File

@ -41,7 +41,8 @@
compatible = "st,st-ohci-300x"; compatible = "st,st-ohci-300x";
reg = <0x9a03c00 0x100>; reg = <0x9a03c00 0x100>;
interrupts = <GIC_SPI 180 IRQ_TYPE_NONE>; interrupts = <GIC_SPI 180 IRQ_TYPE_NONE>;
clocks = <&clk_s_c0_flexgen CLK_TX_ICN_DISP_0>; clocks = <&clk_s_c0_flexgen CLK_TX_ICN_DISP_0>,
<&clk_s_c0_flexgen CLK_RX_ICN_DISP_0>;
resets = <&powerdown STIH407_USB2_PORT0_POWERDOWN>, resets = <&powerdown STIH407_USB2_PORT0_POWERDOWN>,
<&softreset STIH407_USB2_PORT0_SOFTRESET>; <&softreset STIH407_USB2_PORT0_SOFTRESET>;
reset-names = "power", "softreset"; reset-names = "power", "softreset";
@ -57,7 +58,8 @@
interrupts = <GIC_SPI 151 IRQ_TYPE_NONE>; interrupts = <GIC_SPI 151 IRQ_TYPE_NONE>;
pinctrl-names = "default"; pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usb0>; pinctrl-0 = <&pinctrl_usb0>;
clocks = <&clk_s_c0_flexgen CLK_TX_ICN_DISP_0>; clocks = <&clk_s_c0_flexgen CLK_TX_ICN_DISP_0>,
<&clk_s_c0_flexgen CLK_RX_ICN_DISP_0>;
resets = <&powerdown STIH407_USB2_PORT0_POWERDOWN>, resets = <&powerdown STIH407_USB2_PORT0_POWERDOWN>,
<&softreset STIH407_USB2_PORT0_SOFTRESET>; <&softreset STIH407_USB2_PORT0_SOFTRESET>;
reset-names = "power", "softreset"; reset-names = "power", "softreset";
@ -71,7 +73,8 @@
compatible = "st,st-ohci-300x"; compatible = "st,st-ohci-300x";
reg = <0x9a83c00 0x100>; reg = <0x9a83c00 0x100>;
interrupts = <GIC_SPI 181 IRQ_TYPE_NONE>; interrupts = <GIC_SPI 181 IRQ_TYPE_NONE>;
clocks = <&clk_s_c0_flexgen CLK_TX_ICN_DISP_0>; clocks = <&clk_s_c0_flexgen CLK_TX_ICN_DISP_0>,
<&clk_s_c0_flexgen CLK_RX_ICN_DISP_0>;
resets = <&powerdown STIH407_USB2_PORT1_POWERDOWN>, resets = <&powerdown STIH407_USB2_PORT1_POWERDOWN>,
<&softreset STIH407_USB2_PORT1_SOFTRESET>; <&softreset STIH407_USB2_PORT1_SOFTRESET>;
reset-names = "power", "softreset"; reset-names = "power", "softreset";
@ -87,7 +90,8 @@
interrupts = <GIC_SPI 153 IRQ_TYPE_NONE>; interrupts = <GIC_SPI 153 IRQ_TYPE_NONE>;
pinctrl-names = "default"; pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usb1>; pinctrl-0 = <&pinctrl_usb1>;
clocks = <&clk_s_c0_flexgen CLK_TX_ICN_DISP_0>; clocks = <&clk_s_c0_flexgen CLK_TX_ICN_DISP_0>,
<&clk_s_c0_flexgen CLK_RX_ICN_DISP_0>;
resets = <&powerdown STIH407_USB2_PORT1_POWERDOWN>, resets = <&powerdown STIH407_USB2_PORT1_POWERDOWN>,
<&softreset STIH407_USB2_PORT1_SOFTRESET>; <&softreset STIH407_USB2_PORT1_SOFTRESET>;
reset-names = "power", "softreset"; reset-names = "power", "softreset";

View File

@ -140,7 +140,7 @@ static struct locomo_dev_info locomo_devices[] = {
static void locomo_handler(struct irq_desc *desc) static void locomo_handler(struct irq_desc *desc)
{ {
struct locomo *lchip = irq_desc_get_chip_data(desc); struct locomo *lchip = irq_desc_get_handler_data(desc);
int req, i; int req, i;
/* Acknowledge the parent IRQ */ /* Acknowledge the parent IRQ */
@ -200,8 +200,7 @@ static void locomo_setup_irq(struct locomo *lchip)
* Install handler for IRQ_LOCOMO_HW. * Install handler for IRQ_LOCOMO_HW.
*/ */
irq_set_irq_type(lchip->irq, IRQ_TYPE_EDGE_FALLING); irq_set_irq_type(lchip->irq, IRQ_TYPE_EDGE_FALLING);
irq_set_chip_data(lchip->irq, lchip); irq_set_chained_handler_and_data(lchip->irq, locomo_handler, lchip);
irq_set_chained_handler(lchip->irq, locomo_handler);
/* Install handlers for IRQ_LOCOMO_* */ /* Install handlers for IRQ_LOCOMO_* */
for ( ; irq <= lchip->irq_base + 3; irq++) { for ( ; irq <= lchip->irq_base + 3; irq++) {

View File

@ -472,8 +472,8 @@ static int sa1111_setup_irq(struct sa1111 *sachip, unsigned irq_base)
* specifies that S0ReadyInt and S1ReadyInt should be '1'. * specifies that S0ReadyInt and S1ReadyInt should be '1'.
*/ */
sa1111_writel(0, irqbase + SA1111_INTPOL0); sa1111_writel(0, irqbase + SA1111_INTPOL0);
sa1111_writel(SA1111_IRQMASK_HI(IRQ_S0_READY_NINT) | sa1111_writel(BIT(IRQ_S0_READY_NINT & 31) |
SA1111_IRQMASK_HI(IRQ_S1_READY_NINT), BIT(IRQ_S1_READY_NINT & 31),
irqbase + SA1111_INTPOL1); irqbase + SA1111_INTPOL1);
/* clear all IRQs */ /* clear all IRQs */
@ -754,7 +754,7 @@ static int __sa1111_probe(struct device *me, struct resource *mem, int irq)
if (sachip->irq != NO_IRQ) { if (sachip->irq != NO_IRQ) {
ret = sa1111_setup_irq(sachip, pd->irq_base); ret = sa1111_setup_irq(sachip, pd->irq_base);
if (ret) if (ret)
goto err_unmap; goto err_clk;
} }
#ifdef CONFIG_ARCH_SA1100 #ifdef CONFIG_ARCH_SA1100
@ -799,6 +799,8 @@ static int __sa1111_probe(struct device *me, struct resource *mem, int irq)
return 0; return 0;
err_clk:
clk_disable(sachip->clk);
err_unmap: err_unmap:
iounmap(sachip->base); iounmap(sachip->base);
err_clk_unprep: err_clk_unprep:
@ -869,9 +871,9 @@ struct sa1111_save_data {
#ifdef CONFIG_PM #ifdef CONFIG_PM
static int sa1111_suspend(struct platform_device *dev, pm_message_t state) static int sa1111_suspend_noirq(struct device *dev)
{ {
struct sa1111 *sachip = platform_get_drvdata(dev); struct sa1111 *sachip = dev_get_drvdata(dev);
struct sa1111_save_data *save; struct sa1111_save_data *save;
unsigned long flags; unsigned long flags;
unsigned int val; unsigned int val;
@ -934,9 +936,9 @@ static int sa1111_suspend(struct platform_device *dev, pm_message_t state)
* restored by their respective drivers, and must be called * restored by their respective drivers, and must be called
* via LDM after this function. * via LDM after this function.
*/ */
static int sa1111_resume(struct platform_device *dev) static int sa1111_resume_noirq(struct device *dev)
{ {
struct sa1111 *sachip = platform_get_drvdata(dev); struct sa1111 *sachip = dev_get_drvdata(dev);
struct sa1111_save_data *save; struct sa1111_save_data *save;
unsigned long flags, id; unsigned long flags, id;
void __iomem *base; void __iomem *base;
@ -952,7 +954,7 @@ static int sa1111_resume(struct platform_device *dev)
id = sa1111_readl(sachip->base + SA1111_SKID); id = sa1111_readl(sachip->base + SA1111_SKID);
if ((id & SKID_ID_MASK) != SKID_SA1111_ID) { if ((id & SKID_ID_MASK) != SKID_SA1111_ID) {
__sa1111_remove(sachip); __sa1111_remove(sachip);
platform_set_drvdata(dev, NULL); dev_set_drvdata(dev, NULL);
kfree(save); kfree(save);
return 0; return 0;
} }
@ -1003,8 +1005,8 @@ static int sa1111_resume(struct platform_device *dev)
} }
#else #else
#define sa1111_suspend NULL #define sa1111_suspend_noirq NULL
#define sa1111_resume NULL #define sa1111_resume_noirq NULL
#endif #endif
static int sa1111_probe(struct platform_device *pdev) static int sa1111_probe(struct platform_device *pdev)
@ -1017,7 +1019,7 @@ static int sa1111_probe(struct platform_device *pdev)
return -EINVAL; return -EINVAL;
irq = platform_get_irq(pdev, 0); irq = platform_get_irq(pdev, 0);
if (irq < 0) if (irq < 0)
return -ENXIO; return irq;
return __sa1111_probe(&pdev->dev, mem, irq); return __sa1111_probe(&pdev->dev, mem, irq);
} }
@ -1038,6 +1040,11 @@ static int sa1111_remove(struct platform_device *pdev)
return 0; return 0;
} }
static struct dev_pm_ops sa1111_pm_ops = {
.suspend_noirq = sa1111_suspend_noirq,
.resume_noirq = sa1111_resume_noirq,
};
/* /*
* Not sure if this should be on the system bus or not yet. * Not sure if this should be on the system bus or not yet.
* We really want some way to register a system device at * We really want some way to register a system device at
@ -1050,10 +1057,9 @@ static int sa1111_remove(struct platform_device *pdev)
static struct platform_driver sa1111_device_driver = { static struct platform_driver sa1111_device_driver = {
.probe = sa1111_probe, .probe = sa1111_probe,
.remove = sa1111_remove, .remove = sa1111_remove,
.suspend = sa1111_suspend,
.resume = sa1111_resume,
.driver = { .driver = {
.name = "sa1111", .name = "sa1111",
.pm = &sa1111_pm_ops,
}, },
}; };

View File

@ -161,6 +161,7 @@ CONFIG_USB_MON=y
CONFIG_USB_XHCI_HCD=y CONFIG_USB_XHCI_HCD=y
CONFIG_USB_STORAGE=y CONFIG_USB_STORAGE=y
CONFIG_USB_DWC3=y CONFIG_USB_DWC3=y
CONFIG_NOP_USB_XCEIV=y
CONFIG_KEYSTONE_USB_PHY=y CONFIG_KEYSTONE_USB_PHY=y
CONFIG_NEW_LEDS=y CONFIG_NEW_LEDS=y
CONFIG_LEDS_CLASS=y CONFIG_LEDS_CLASS=y

View File

@ -781,7 +781,7 @@ CONFIG_MXS_DMA=y
CONFIG_DMA_BCM2835=y CONFIG_DMA_BCM2835=y
CONFIG_DMA_OMAP=y CONFIG_DMA_OMAP=y
CONFIG_QCOM_BAM_DMA=y CONFIG_QCOM_BAM_DMA=y
CONFIG_XILINX_VDMA=y CONFIG_XILINX_DMA=y
CONFIG_DMA_SUN6I=y CONFIG_DMA_SUN6I=y
CONFIG_STAGING=y CONFIG_STAGING=y
CONFIG_SENSORS_ISL29018=y CONFIG_SENSORS_ISL29018=y

View File

@ -284,7 +284,7 @@ static int ctr_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
err = blkcipher_walk_done(desc, &walk, err = blkcipher_walk_done(desc, &walk,
walk.nbytes % AES_BLOCK_SIZE); walk.nbytes % AES_BLOCK_SIZE);
} }
if (nbytes) { if (walk.nbytes % AES_BLOCK_SIZE) {
u8 *tdst = walk.dst.virt.addr + blocks * AES_BLOCK_SIZE; u8 *tdst = walk.dst.virt.addr + blocks * AES_BLOCK_SIZE;
u8 *tsrc = walk.src.virt.addr + blocks * AES_BLOCK_SIZE; u8 *tsrc = walk.src.virt.addr + blocks * AES_BLOCK_SIZE;
u8 __aligned(8) tail[AES_BLOCK_SIZE]; u8 __aligned(8) tail[AES_BLOCK_SIZE];

View File

@ -47,6 +47,7 @@
#define PMD_SECT_WB (PMD_SECT_CACHEABLE | PMD_SECT_BUFFERABLE) #define PMD_SECT_WB (PMD_SECT_CACHEABLE | PMD_SECT_BUFFERABLE)
#define PMD_SECT_MINICACHE (PMD_SECT_TEX(1) | PMD_SECT_CACHEABLE) #define PMD_SECT_MINICACHE (PMD_SECT_TEX(1) | PMD_SECT_CACHEABLE)
#define PMD_SECT_WBWA (PMD_SECT_TEX(1) | PMD_SECT_CACHEABLE | PMD_SECT_BUFFERABLE) #define PMD_SECT_WBWA (PMD_SECT_TEX(1) | PMD_SECT_CACHEABLE | PMD_SECT_BUFFERABLE)
#define PMD_SECT_CACHE_MASK (PMD_SECT_TEX(1) | PMD_SECT_CACHEABLE | PMD_SECT_BUFFERABLE)
#define PMD_SECT_NONSHARED_DEV (PMD_SECT_TEX(2)) #define PMD_SECT_NONSHARED_DEV (PMD_SECT_TEX(2))
/* /*

View File

@ -62,6 +62,7 @@
#define PMD_SECT_WT (_AT(pmdval_t, 2) << 2) /* normal inner write-through */ #define PMD_SECT_WT (_AT(pmdval_t, 2) << 2) /* normal inner write-through */
#define PMD_SECT_WB (_AT(pmdval_t, 3) << 2) /* normal inner write-back */ #define PMD_SECT_WB (_AT(pmdval_t, 3) << 2) /* normal inner write-back */
#define PMD_SECT_WBWA (_AT(pmdval_t, 7) << 2) /* normal inner write-alloc */ #define PMD_SECT_WBWA (_AT(pmdval_t, 7) << 2) /* normal inner write-alloc */
#define PMD_SECT_CACHE_MASK (_AT(pmdval_t, 7) << 2)
/* /*
* + Level 3 descriptor (PTE) * + Level 3 descriptor (PTE)

View File

@ -158,8 +158,6 @@ void kvm_arch_destroy_vm(struct kvm *kvm)
{ {
int i; int i;
kvm_free_stage2_pgd(kvm);
for (i = 0; i < KVM_MAX_VCPUS; ++i) { for (i = 0; i < KVM_MAX_VCPUS; ++i) {
if (kvm->vcpus[i]) { if (kvm->vcpus[i]) {
kvm_arch_vcpu_free(kvm->vcpus[i]); kvm_arch_vcpu_free(kvm->vcpus[i]);

View File

@ -1714,7 +1714,8 @@ int kvm_mmu_init(void)
kern_hyp_va(PAGE_OFFSET), kern_hyp_va(~0UL)); kern_hyp_va(PAGE_OFFSET), kern_hyp_va(~0UL));
if (hyp_idmap_start >= kern_hyp_va(PAGE_OFFSET) && if (hyp_idmap_start >= kern_hyp_va(PAGE_OFFSET) &&
hyp_idmap_start < kern_hyp_va(~0UL)) { hyp_idmap_start < kern_hyp_va(~0UL) &&
hyp_idmap_start != (unsigned long)__hyp_idmap_text_start) {
/* /*
* The idmap page is intersecting with the VA space, * The idmap page is intersecting with the VA space,
* it is not safe to continue further. * it is not safe to continue further.
@ -1893,6 +1894,7 @@ void kvm_arch_memslots_updated(struct kvm *kvm, struct kvm_memslots *slots)
void kvm_arch_flush_shadow_all(struct kvm *kvm) void kvm_arch_flush_shadow_all(struct kvm *kvm)
{ {
kvm_free_stage2_pgd(kvm);
} }
void kvm_arch_flush_shadow_memslot(struct kvm *kvm, void kvm_arch_flush_shadow_memslot(struct kvm *kvm,

View File

@ -255,6 +255,12 @@ static int __init exynos_pmu_irq_init(struct device_node *node,
return -ENOMEM; return -ENOMEM;
} }
/*
* Clear the OF_POPULATED flag set in of_irq_init so that
* later the Exynos PMU platform device won't be skipped.
*/
of_node_clear_flag(node, OF_POPULATED);
return 0; return 0;
} }

View File

@ -137,6 +137,18 @@ static struct pxa2xx_udc_mach_info udc_info __initdata = {
// no D+ pullup; lubbock can't connect/disconnect in software // no D+ pullup; lubbock can't connect/disconnect in software
}; };
static void lubbock_init_pcmcia(void)
{
struct clk *clk;
/* Add an alias for the SA1111 PCMCIA clock */
clk = clk_get_sys("pxa2xx-pcmcia", NULL);
if (!IS_ERR(clk)) {
clkdev_create(clk, NULL, "1800");
clk_put(clk);
}
}
static struct resource sa1111_resources[] = { static struct resource sa1111_resources[] = {
[0] = { [0] = {
.start = 0x10000000, .start = 0x10000000,
@ -467,6 +479,8 @@ static void __init lubbock_init(void)
pxa_set_btuart_info(NULL); pxa_set_btuart_info(NULL);
pxa_set_stuart_info(NULL); pxa_set_stuart_info(NULL);
lubbock_init_pcmcia();
clk_add_alias("SA1111_CLK", NULL, "GPIO11_CLK", NULL); clk_add_alias("SA1111_CLK", NULL, "GPIO11_CLK", NULL);
pxa_set_udc_info(&udc_info); pxa_set_udc_info(&udc_info);
pxa_set_fb_info(NULL, &sharp_lm8v31); pxa_set_fb_info(NULL, &sharp_lm8v31);

View File

@ -41,40 +41,27 @@
#define REGULATOR_IRQ_MASK BIT(2) /* IRQ2, active low */ #define REGULATOR_IRQ_MASK BIT(2) /* IRQ2, active low */
/* start of DA9210 System Control and Event Registers */
#define DA9210_REG_MASK_A 0x54
static void __iomem *irqc; static void __iomem *irqc;
static const u8 da9063_mask_regs[] = { /* first byte sets the memory pointer, following are consecutive reg values */
DA9063_REG_IRQ_MASK_A, static u8 da9063_irq_clr[] = { DA9063_REG_IRQ_MASK_A, 0xff, 0xff, 0xff, 0xff };
DA9063_REG_IRQ_MASK_B, static u8 da9210_irq_clr[] = { DA9210_REG_MASK_A, 0xff, 0xff };
DA9063_REG_IRQ_MASK_C,
DA9063_REG_IRQ_MASK_D, static struct i2c_msg da9xxx_msgs[2] = {
{
.addr = 0x58,
.len = ARRAY_SIZE(da9063_irq_clr),
.buf = da9063_irq_clr,
}, {
.addr = 0x68,
.len = ARRAY_SIZE(da9210_irq_clr),
.buf = da9210_irq_clr,
},
}; };
/* DA9210 System Control and Event Registers */
#define DA9210_REG_MASK_A 0x54
#define DA9210_REG_MASK_B 0x55
static const u8 da9210_mask_regs[] = {
DA9210_REG_MASK_A,
DA9210_REG_MASK_B,
};
static void da9xxx_mask_irqs(struct i2c_client *client, const u8 regs[],
unsigned int nregs)
{
unsigned int i;
dev_info(&client->dev, "Masking %s interrupt sources\n", client->name);
for (i = 0; i < nregs; i++) {
int error = i2c_smbus_write_byte_data(client, regs[i], ~0);
if (error) {
dev_err(&client->dev, "i2c error %d\n", error);
return;
}
}
}
static int regulator_quirk_notify(struct notifier_block *nb, static int regulator_quirk_notify(struct notifier_block *nb,
unsigned long action, void *data) unsigned long action, void *data)
{ {
@ -93,12 +80,15 @@ static int regulator_quirk_notify(struct notifier_block *nb,
client = to_i2c_client(dev); client = to_i2c_client(dev);
dev_dbg(dev, "Detected %s\n", client->name); dev_dbg(dev, "Detected %s\n", client->name);
if ((client->addr == 0x58 && !strcmp(client->name, "da9063"))) if ((client->addr == 0x58 && !strcmp(client->name, "da9063")) ||
da9xxx_mask_irqs(client, da9063_mask_regs, (client->addr == 0x68 && !strcmp(client->name, "da9210"))) {
ARRAY_SIZE(da9063_mask_regs)); int ret;
else if (client->addr == 0x68 && !strcmp(client->name, "da9210"))
da9xxx_mask_irqs(client, da9210_mask_regs, dev_info(&client->dev, "clearing da9063/da9210 interrupts\n");
ARRAY_SIZE(da9210_mask_regs)); ret = i2c_transfer(client->adapter, da9xxx_msgs, ARRAY_SIZE(da9xxx_msgs));
if (ret != ARRAY_SIZE(da9xxx_msgs))
dev_err(&client->dev, "i2c error %d\n", ret);
}
mon = ioread32(irqc + IRQC_MONITOR); mon = ioread32(irqc + IRQC_MONITOR);
if (mon & REGULATOR_IRQ_MASK) if (mon & REGULATOR_IRQ_MASK)

View File

@ -137,7 +137,7 @@ void __init init_default_cache_policy(unsigned long pmd)
initial_pmd_value = pmd; initial_pmd_value = pmd;
pmd &= PMD_SECT_TEX(1) | PMD_SECT_BUFFERABLE | PMD_SECT_CACHEABLE; pmd &= PMD_SECT_CACHE_MASK;
for (i = 0; i < ARRAY_SIZE(cache_policies); i++) for (i = 0; i < ARRAY_SIZE(cache_policies); i++)
if (cache_policies[i].pmd == pmd) { if (cache_policies[i].pmd == pmd) {

View File

@ -170,9 +170,6 @@ static int xen_starting_cpu(unsigned int cpu)
pr_info("Xen: initializing cpu%d\n", cpu); pr_info("Xen: initializing cpu%d\n", cpu);
vcpup = per_cpu_ptr(xen_vcpu_info, cpu); vcpup = per_cpu_ptr(xen_vcpu_info, cpu);
/* Direct vCPU id mapping for ARM guests. */
per_cpu(xen_vcpu_id, cpu) = cpu;
info.mfn = virt_to_gfn(vcpup); info.mfn = virt_to_gfn(vcpup);
info.offset = xen_offset_in_page(vcpup); info.offset = xen_offset_in_page(vcpup);
@ -330,6 +327,7 @@ static int __init xen_guest_init(void)
{ {
struct xen_add_to_physmap xatp; struct xen_add_to_physmap xatp;
struct shared_info *shared_info_page = NULL; struct shared_info *shared_info_page = NULL;
int cpu;
if (!xen_domain()) if (!xen_domain())
return 0; return 0;
@ -380,7 +378,8 @@ static int __init xen_guest_init(void)
return -ENOMEM; return -ENOMEM;
/* Direct vCPU id mapping for ARM guests. */ /* Direct vCPU id mapping for ARM guests. */
per_cpu(xen_vcpu_id, 0) = 0; for_each_possible_cpu(cpu)
per_cpu(xen_vcpu_id, cpu) = cpu;
xen_auto_xlat_grant_frames.count = gnttab_max_grant_frames(); xen_auto_xlat_grant_frames.count = gnttab_max_grant_frames();
if (xen_xlate_map_ballooned_pages(&xen_auto_xlat_grant_frames.pfn, if (xen_xlate_map_ballooned_pages(&xen_auto_xlat_grant_frames.pfn,

View File

@ -255,10 +255,10 @@
/* Local timer */ /* Local timer */
timer { timer {
compatible = "arm,armv8-timer"; compatible = "arm,armv8-timer";
interrupts = <1 13 0xf01>, interrupts = <1 13 0xf08>,
<1 14 0xf01>, <1 14 0xf08>,
<1 11 0xf01>, <1 11 0xf08>,
<1 10 0xf01>; <1 10 0xf08>;
}; };
timer0: timer0@ffc03000 { timer0: timer0@ffc03000 {

View File

@ -102,13 +102,13 @@
timer { timer {
compatible = "arm,armv8-timer"; compatible = "arm,armv8-timer";
interrupts = <GIC_PPI 13 interrupts = <GIC_PPI 13
(GIC_CPU_MASK_RAW(0xff) | IRQ_TYPE_EDGE_RISING)>, (GIC_CPU_MASK_RAW(0xff) | IRQ_TYPE_LEVEL_LOW)>,
<GIC_PPI 14 <GIC_PPI 14
(GIC_CPU_MASK_RAW(0xff) | IRQ_TYPE_EDGE_RISING)>, (GIC_CPU_MASK_RAW(0xff) | IRQ_TYPE_LEVEL_LOW)>,
<GIC_PPI 11 <GIC_PPI 11
(GIC_CPU_MASK_RAW(0xff) | IRQ_TYPE_EDGE_RISING)>, (GIC_CPU_MASK_RAW(0xff) | IRQ_TYPE_LEVEL_LOW)>,
<GIC_PPI 10 <GIC_PPI 10
(GIC_CPU_MASK_RAW(0xff) | IRQ_TYPE_EDGE_RISING)>; (GIC_CPU_MASK_RAW(0xff) | IRQ_TYPE_LEVEL_LOW)>;
}; };
xtal: xtal-clk { xtal: xtal-clk {

View File

@ -110,10 +110,10 @@
timer { timer {
compatible = "arm,armv8-timer"; compatible = "arm,armv8-timer";
interrupts = <1 0 0xff01>, /* Secure Phys IRQ */ interrupts = <1 0 0xff08>, /* Secure Phys IRQ */
<1 13 0xff01>, /* Non-secure Phys IRQ */ <1 13 0xff08>, /* Non-secure Phys IRQ */
<1 14 0xff01>, /* Virt IRQ */ <1 14 0xff08>, /* Virt IRQ */
<1 15 0xff01>; /* Hyp IRQ */ <1 15 0xff08>; /* Hyp IRQ */
clock-frequency = <50000000>; clock-frequency = <50000000>;
}; };

View File

@ -0,0 +1 @@
../../../../arm/boot/dts/bcm2835-rpi.dtsi

View File

@ -1,7 +1,7 @@
/dts-v1/; /dts-v1/;
#include "bcm2837.dtsi" #include "bcm2837.dtsi"
#include "../../../../arm/boot/dts/bcm2835-rpi.dtsi" #include "bcm2835-rpi.dtsi"
#include "../../../../arm/boot/dts/bcm283x-rpi-smsc9514.dtsi" #include "bcm283x-rpi-smsc9514.dtsi"
/ { / {
compatible = "raspberrypi,3-model-b", "brcm,bcm2837"; compatible = "raspberrypi,3-model-b", "brcm,bcm2837";

View File

@ -1,4 +1,4 @@
#include "../../../../arm/boot/dts/bcm283x.dtsi" #include "bcm283x.dtsi"
/ { / {
compatible = "brcm,bcm2836"; compatible = "brcm,bcm2836";

View File

@ -0,0 +1 @@
../../../../arm/boot/dts/bcm283x-rpi-smsc9514.dtsi

View File

@ -0,0 +1 @@
../../../../arm/boot/dts/bcm283x.dtsi

View File

@ -88,13 +88,13 @@
timer { timer {
compatible = "arm,armv8-timer"; compatible = "arm,armv8-timer";
interrupts = <GIC_PPI 13 (GIC_CPU_MASK_RAW(0xff) | interrupts = <GIC_PPI 13 (GIC_CPU_MASK_RAW(0xff) |
IRQ_TYPE_EDGE_RISING)>, IRQ_TYPE_LEVEL_LOW)>,
<GIC_PPI 14 (GIC_CPU_MASK_RAW(0xff) | <GIC_PPI 14 (GIC_CPU_MASK_RAW(0xff) |
IRQ_TYPE_EDGE_RISING)>, IRQ_TYPE_LEVEL_LOW)>,
<GIC_PPI 11 (GIC_CPU_MASK_RAW(0xff) | <GIC_PPI 11 (GIC_CPU_MASK_RAW(0xff) |
IRQ_TYPE_EDGE_RISING)>, IRQ_TYPE_LEVEL_LOW)>,
<GIC_PPI 10 (GIC_CPU_MASK_RAW(0xff) | <GIC_PPI 10 (GIC_CPU_MASK_RAW(0xff) |
IRQ_TYPE_EDGE_RISING)>; IRQ_TYPE_LEVEL_LOW)>;
}; };
pmu { pmu {

View File

@ -354,10 +354,10 @@
timer { timer {
compatible = "arm,armv8-timer"; compatible = "arm,armv8-timer";
interrupts = <1 13 0xff01>, interrupts = <1 13 4>,
<1 14 0xff01>, <1 14 4>,
<1 11 0xff01>, <1 11 4>,
<1 10 0xff01>; <1 10 4>;
}; };
pmu { pmu {

View File

@ -473,10 +473,10 @@
timer { timer {
compatible = "arm,armv8-timer"; compatible = "arm,armv8-timer";
interrupts = <1 13 0xff01>, interrupts = <1 13 0xff08>,
<1 14 0xff01>, <1 14 0xff08>,
<1 11 0xff01>, <1 11 0xff08>,
<1 10 0xff01>; <1 10 0xff08>;
}; };
pmu_system_controller: system-controller@105c0000 { pmu_system_controller: system-controller@105c0000 {

View File

@ -119,10 +119,10 @@
timer { timer {
compatible = "arm,armv8-timer"; compatible = "arm,armv8-timer";
interrupts = <1 13 0x1>, /* Physical Secure PPI */ interrupts = <1 13 0xf08>, /* Physical Secure PPI */
<1 14 0x1>, /* Physical Non-Secure PPI */ <1 14 0xf08>, /* Physical Non-Secure PPI */
<1 11 0x1>, /* Virtual PPI */ <1 11 0xf08>, /* Virtual PPI */
<1 10 0x1>; /* Hypervisor PPI */ <1 10 0xf08>; /* Hypervisor PPI */
}; };
pmu { pmu {

View File

@ -191,10 +191,10 @@
timer { timer {
compatible = "arm,armv8-timer"; compatible = "arm,armv8-timer";
interrupts = <1 13 0x8>, /* Physical Secure PPI, active-low */ interrupts = <1 13 4>, /* Physical Secure PPI, active-low */
<1 14 0x8>, /* Physical Non-Secure PPI, active-low */ <1 14 4>, /* Physical Non-Secure PPI, active-low */
<1 11 0x8>, /* Virtual PPI, active-low */ <1 11 4>, /* Virtual PPI, active-low */
<1 10 0x8>; /* Hypervisor PPI, active-low */ <1 10 4>; /* Hypervisor PPI, active-low */
}; };
pmu { pmu {

View File

@ -122,10 +122,10 @@
timer { timer {
compatible = "arm,armv8-timer"; compatible = "arm,armv8-timer";
interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_EDGE_RISING)>, interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
<GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_EDGE_RISING)>, <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
<GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_EDGE_RISING)>, <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
<GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_EDGE_RISING)>; <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>;
}; };
odmi: odmi@300000 { odmi: odmi@300000 {

View File

@ -129,10 +129,10 @@
timer { timer {
compatible = "arm,armv8-timer"; compatible = "arm,armv8-timer";
interrupts = <1 13 0xf01>, interrupts = <1 13 4>,
<1 14 0xf01>, <1 14 4>,
<1 11 0xf01>, <1 11 4>,
<1 10 0xf01>; <1 10 4>;
}; };
soc { soc {

View File

@ -65,10 +65,10 @@
timer { timer {
compatible = "arm,armv8-timer"; compatible = "arm,armv8-timer";
interrupt-parent = <&gic>; interrupt-parent = <&gic>;
interrupts = <1 13 0xf01>, interrupts = <1 13 0xf08>,
<1 14 0xf01>, <1 14 0xf08>,
<1 11 0xf01>, <1 11 0xf08>,
<1 10 0xf01>; <1 10 0xf08>;
}; };
amba_apu { amba_apu {

View File

@ -216,7 +216,7 @@ static int ctr_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
err = blkcipher_walk_done(desc, &walk, err = blkcipher_walk_done(desc, &walk,
walk.nbytes % AES_BLOCK_SIZE); walk.nbytes % AES_BLOCK_SIZE);
} }
if (nbytes) { if (walk.nbytes % AES_BLOCK_SIZE) {
u8 *tdst = walk.dst.virt.addr + blocks * AES_BLOCK_SIZE; u8 *tdst = walk.dst.virt.addr + blocks * AES_BLOCK_SIZE;
u8 *tsrc = walk.src.virt.addr + blocks * AES_BLOCK_SIZE; u8 *tsrc = walk.src.virt.addr + blocks * AES_BLOCK_SIZE;
u8 __aligned(8) tail[AES_BLOCK_SIZE]; u8 __aligned(8) tail[AES_BLOCK_SIZE];

View File

@ -61,8 +61,6 @@
#define AARCH64_BREAK_KGDB_DYN_DBG \ #define AARCH64_BREAK_KGDB_DYN_DBG \
(AARCH64_BREAK_MON | (KGDB_DYN_DBG_BRK_IMM << 5)) (AARCH64_BREAK_MON | (KGDB_DYN_DBG_BRK_IMM << 5))
#define KGDB_DYN_BRK_INS_BYTE(x) \
((AARCH64_BREAK_KGDB_DYN_DBG >> (8 * (x))) & 0xff)
#define CACHE_FLUSH_IS_SAFE 1 #define CACHE_FLUSH_IS_SAFE 1

View File

@ -19,10 +19,13 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <linux/bug.h>
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/kdebug.h> #include <linux/kdebug.h>
#include <linux/kgdb.h> #include <linux/kgdb.h>
#include <linux/kprobes.h> #include <linux/kprobes.h>
#include <asm/debug-monitors.h>
#include <asm/insn.h>
#include <asm/traps.h> #include <asm/traps.h>
struct dbg_reg_def_t dbg_reg_def[DBG_MAX_REG_NUM] = { struct dbg_reg_def_t dbg_reg_def[DBG_MAX_REG_NUM] = {
@ -338,15 +341,24 @@ void kgdb_arch_exit(void)
unregister_die_notifier(&kgdb_notifier); unregister_die_notifier(&kgdb_notifier);
} }
/* struct kgdb_arch arch_kgdb_ops;
* ARM instructions are always in LE.
* Break instruction is encoded in LE format int kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt)
*/ {
struct kgdb_arch arch_kgdb_ops = { int err;
.gdb_bpt_instr = {
KGDB_DYN_BRK_INS_BYTE(0), BUILD_BUG_ON(AARCH64_INSN_SIZE != BREAK_INSTR_SIZE);
KGDB_DYN_BRK_INS_BYTE(1),
KGDB_DYN_BRK_INS_BYTE(2), err = aarch64_insn_read((void *)bpt->bpt_addr, (u32 *)bpt->saved_instr);
KGDB_DYN_BRK_INS_BYTE(3), if (err)
} return err;
};
return aarch64_insn_write((void *)bpt->bpt_addr,
(u32)AARCH64_BREAK_KGDB_DYN_DBG);
}
int kgdb_arch_remove_breakpoint(struct kgdb_bkpt *bpt)
{
return aarch64_insn_write((void *)bpt->bpt_addr,
*(u32 *)bpt->saved_instr);
}

View File

@ -201,12 +201,6 @@ int __cpu_up(unsigned int cpu, struct task_struct *idle)
return ret; return ret;
} }
static void smp_store_cpu_info(unsigned int cpuid)
{
store_cpu_topology(cpuid);
numa_store_cpu_info(cpuid);
}
/* /*
* This is the secondary CPU boot entry. We're using this CPUs * This is the secondary CPU boot entry. We're using this CPUs
* idle thread stack, but a set of temporary page tables. * idle thread stack, but a set of temporary page tables.
@ -254,7 +248,7 @@ asmlinkage void secondary_start_kernel(void)
*/ */
notify_cpu_starting(cpu); notify_cpu_starting(cpu);
smp_store_cpu_info(cpu); store_cpu_topology(cpu);
/* /*
* OK, now it's safe to let the boot CPU continue. Wait for * OK, now it's safe to let the boot CPU continue. Wait for
@ -689,10 +683,13 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
{ {
int err; int err;
unsigned int cpu; unsigned int cpu;
unsigned int this_cpu;
init_cpu_topology(); init_cpu_topology();
smp_store_cpu_info(smp_processor_id()); this_cpu = smp_processor_id();
store_cpu_topology(this_cpu);
numa_store_cpu_info(this_cpu);
/* /*
* If UP is mandated by "nosmp" (which implies "maxcpus=0"), don't set * If UP is mandated by "nosmp" (which implies "maxcpus=0"), don't set
@ -719,6 +716,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
continue; continue;
set_cpu_present(cpu, true); set_cpu_present(cpu, true);
numa_store_cpu_info(cpu);
} }
} }

View File

@ -74,7 +74,7 @@ extern __kernel_size_t __copy_user(void *to, const void *from,
extern __kernel_size_t copy_to_user(void __user *to, const void *from, extern __kernel_size_t copy_to_user(void __user *to, const void *from,
__kernel_size_t n); __kernel_size_t n);
extern __kernel_size_t copy_from_user(void *to, const void __user *from, extern __kernel_size_t ___copy_from_user(void *to, const void __user *from,
__kernel_size_t n); __kernel_size_t n);
static inline __kernel_size_t __copy_to_user(void __user *to, const void *from, static inline __kernel_size_t __copy_to_user(void __user *to, const void *from,
@ -88,6 +88,15 @@ static inline __kernel_size_t __copy_from_user(void *to,
{ {
return __copy_user(to, (const void __force *)from, n); return __copy_user(to, (const void __force *)from, n);
} }
static inline __kernel_size_t copy_from_user(void *to,
const void __user *from,
__kernel_size_t n)
{
size_t res = ___copy_from_user(to, from, n);
if (unlikely(res))
memset(to + (n - res), 0, res);
return res;
}
#define __copy_to_user_inatomic __copy_to_user #define __copy_to_user_inatomic __copy_to_user
#define __copy_from_user_inatomic __copy_from_user #define __copy_from_user_inatomic __copy_from_user

View File

@ -36,7 +36,7 @@ EXPORT_SYMBOL(copy_page);
/* /*
* Userspace access stuff. * Userspace access stuff.
*/ */
EXPORT_SYMBOL(copy_from_user); EXPORT_SYMBOL(___copy_from_user);
EXPORT_SYMBOL(copy_to_user); EXPORT_SYMBOL(copy_to_user);
EXPORT_SYMBOL(__copy_user); EXPORT_SYMBOL(__copy_user);
EXPORT_SYMBOL(strncpy_from_user); EXPORT_SYMBOL(strncpy_from_user);

View File

@ -23,13 +23,13 @@
*/ */
.text .text
.align 1 .align 1
.global copy_from_user .global ___copy_from_user
.type copy_from_user, @function .type ___copy_from_user, @function
copy_from_user: ___copy_from_user:
branch_if_kernel r8, __copy_user branch_if_kernel r8, __copy_user
ret_if_privileged r8, r11, r10, r10 ret_if_privileged r8, r11, r10, r10
rjmp __copy_user rjmp __copy_user
.size copy_from_user, . - copy_from_user .size ___copy_from_user, . - ___copy_from_user
.global copy_to_user .global copy_to_user
.type copy_to_user, @function .type copy_to_user, @function

View File

@ -171,11 +171,12 @@ static inline int bad_user_access_length(void)
static inline unsigned long __must_check static inline unsigned long __must_check
copy_from_user(void *to, const void __user *from, unsigned long n) copy_from_user(void *to, const void __user *from, unsigned long n)
{ {
if (access_ok(VERIFY_READ, from, n)) if (likely(access_ok(VERIFY_READ, from, n))) {
memcpy(to, (const void __force *)from, n); memcpy(to, (const void __force *)from, n);
else return 0;
return n; }
return 0; memset(to, 0, n);
return n;
} }
static inline unsigned long __must_check static inline unsigned long __must_check

View File

@ -194,30 +194,6 @@ extern unsigned long __copy_user(void __user *to, const void *from, unsigned lon
extern unsigned long __copy_user_zeroing(void *to, const void __user *from, unsigned long n); extern unsigned long __copy_user_zeroing(void *to, const void __user *from, unsigned long n);
extern unsigned long __do_clear_user(void __user *to, unsigned long n); extern unsigned long __do_clear_user(void __user *to, unsigned long n);
static inline unsigned long
__generic_copy_to_user(void __user *to, const void *from, unsigned long n)
{
if (access_ok(VERIFY_WRITE, to, n))
return __copy_user(to, from, n);
return n;
}
static inline unsigned long
__generic_copy_from_user(void *to, const void __user *from, unsigned long n)
{
if (access_ok(VERIFY_READ, from, n))
return __copy_user_zeroing(to, from, n);
return n;
}
static inline unsigned long
__generic_clear_user(void __user *to, unsigned long n)
{
if (access_ok(VERIFY_WRITE, to, n))
return __do_clear_user(to, n);
return n;
}
static inline long static inline long
__strncpy_from_user(char *dst, const char __user *src, long count) __strncpy_from_user(char *dst, const char __user *src, long count)
{ {
@ -282,7 +258,7 @@ __constant_copy_from_user(void *to, const void __user *from, unsigned long n)
else if (n == 24) else if (n == 24)
__asm_copy_from_user_24(to, from, ret); __asm_copy_from_user_24(to, from, ret);
else else
ret = __generic_copy_from_user(to, from, n); ret = __copy_user_zeroing(to, from, n);
return ret; return ret;
} }
@ -333,7 +309,7 @@ __constant_copy_to_user(void __user *to, const void *from, unsigned long n)
else if (n == 24) else if (n == 24)
__asm_copy_to_user_24(to, from, ret); __asm_copy_to_user_24(to, from, ret);
else else
ret = __generic_copy_to_user(to, from, n); ret = __copy_user(to, from, n);
return ret; return ret;
} }
@ -366,26 +342,43 @@ __constant_clear_user(void __user *to, unsigned long n)
else if (n == 24) else if (n == 24)
__asm_clear_24(to, ret); __asm_clear_24(to, ret);
else else
ret = __generic_clear_user(to, n); ret = __do_clear_user(to, n);
return ret; return ret;
} }
#define clear_user(to, n) \ static inline size_t clear_user(void __user *to, size_t n)
(__builtin_constant_p(n) ? \ {
__constant_clear_user(to, n) : \ if (unlikely(!access_ok(VERIFY_WRITE, to, n)))
__generic_clear_user(to, n)) return n;
if (__builtin_constant_p(n))
return __constant_clear_user(to, n);
else
return __do_clear_user(to, n);
}
#define copy_from_user(to, from, n) \ static inline size_t copy_from_user(void *to, const void __user *from, size_t n)
(__builtin_constant_p(n) ? \ {
__constant_copy_from_user(to, from, n) : \ if (unlikely(!access_ok(VERIFY_READ, from, n))) {
__generic_copy_from_user(to, from, n)) memset(to, 0, n);
return n;
}
if (__builtin_constant_p(n))
return __constant_copy_from_user(to, from, n);
else
return __copy_user_zeroing(to, from, n);
}
#define copy_to_user(to, from, n) \ static inline size_t copy_to_user(void __user *to, const void *from, size_t n)
(__builtin_constant_p(n) ? \ {
__constant_copy_to_user(to, from, n) : \ if (unlikely(!access_ok(VERIFY_WRITE, to, n)))
__generic_copy_to_user(to, from, n)) return n;
if (__builtin_constant_p(n))
return __constant_copy_to_user(to, from, n);
else
return __copy_user(to, from, n);
}
/* We let the __ versions of copy_from/to_user inline, because they're often /* We let the __ versions of copy_from/to_user inline, because they're often
* used in fast paths and have only a small space overhead. * used in fast paths and have only a small space overhead.

View File

@ -263,19 +263,25 @@ do { \
extern long __memset_user(void *dst, unsigned long count); extern long __memset_user(void *dst, unsigned long count);
extern long __memcpy_user(void *dst, const void *src, unsigned long count); extern long __memcpy_user(void *dst, const void *src, unsigned long count);
#define clear_user(dst,count) __memset_user(____force(dst), (count)) #define __clear_user(dst,count) __memset_user(____force(dst), (count))
#define __copy_from_user_inatomic(to, from, n) __memcpy_user((to), ____force(from), (n)) #define __copy_from_user_inatomic(to, from, n) __memcpy_user((to), ____force(from), (n))
#define __copy_to_user_inatomic(to, from, n) __memcpy_user(____force(to), (from), (n)) #define __copy_to_user_inatomic(to, from, n) __memcpy_user(____force(to), (from), (n))
#else #else
#define clear_user(dst,count) (memset(____force(dst), 0, (count)), 0) #define __clear_user(dst,count) (memset(____force(dst), 0, (count)), 0)
#define __copy_from_user_inatomic(to, from, n) (memcpy((to), ____force(from), (n)), 0) #define __copy_from_user_inatomic(to, from, n) (memcpy((to), ____force(from), (n)), 0)
#define __copy_to_user_inatomic(to, from, n) (memcpy(____force(to), (from), (n)), 0) #define __copy_to_user_inatomic(to, from, n) (memcpy(____force(to), (from), (n)), 0)
#endif #endif
#define __clear_user clear_user static inline unsigned long __must_check
clear_user(void __user *to, unsigned long n)
{
if (likely(__access_ok(to, n)))
n = __clear_user(to, n);
return n;
}
static inline unsigned long __must_check static inline unsigned long __must_check
__copy_to_user(void __user *to, const void *from, unsigned long n) __copy_to_user(void __user *to, const void *from, unsigned long n)

View File

@ -103,7 +103,8 @@ static inline long hexagon_strncpy_from_user(char *dst, const char __user *src,
{ {
long res = __strnlen_user(src, n); long res = __strnlen_user(src, n);
/* return from strnlen can't be zero -- that would be rubbish. */ if (unlikely(!res))
return -EFAULT;
if (res > n) { if (res > n) {
copy_from_user(dst, src, n); copy_from_user(dst, src, n);

View File

@ -269,19 +269,16 @@ __copy_from_user (void *to, const void __user *from, unsigned long count)
__cu_len; \ __cu_len; \
}) })
#define copy_from_user(to, from, n) \ static inline unsigned long
({ \ copy_from_user(void *to, const void __user *from, unsigned long n)
void *__cu_to = (to); \ {
const void __user *__cu_from = (from); \ check_object_size(to, n, false);
long __cu_len = (n); \ if (likely(__access_ok(from, n, get_fs())))
\ n = __copy_user((__force void __user *) to, from, n);
__chk_user_ptr(__cu_from); \ else
if (__access_ok(__cu_from, __cu_len, get_fs())) { \ memset(to, 0, n);
check_object_size(__cu_to, __cu_len, false); \ return n;
__cu_len = __copy_user((__force void __user *) __cu_to, __cu_from, __cu_len); \ }
} \
__cu_len; \
})
#define __copy_in_user(to, from, size) __copy_user((to), (from), (size)) #define __copy_in_user(to, from, size) __copy_user((to), (from), (size))

View File

@ -219,7 +219,7 @@ extern int fixup_exception(struct pt_regs *regs);
#define __get_user_nocheck(x, ptr, size) \ #define __get_user_nocheck(x, ptr, size) \
({ \ ({ \
long __gu_err = 0; \ long __gu_err = 0; \
unsigned long __gu_val; \ unsigned long __gu_val = 0; \
might_fault(); \ might_fault(); \
__get_user_size(__gu_val, (ptr), (size), __gu_err); \ __get_user_size(__gu_val, (ptr), (size), __gu_err); \
(x) = (__force __typeof__(*(ptr)))__gu_val; \ (x) = (__force __typeof__(*(ptr)))__gu_val; \

View File

@ -204,8 +204,9 @@ extern unsigned long __must_check __copy_user_zeroing(void *to,
static inline unsigned long static inline unsigned long
copy_from_user(void *to, const void __user *from, unsigned long n) copy_from_user(void *to, const void __user *from, unsigned long n)
{ {
if (access_ok(VERIFY_READ, from, n)) if (likely(access_ok(VERIFY_READ, from, n)))
return __copy_user_zeroing(to, from, n); return __copy_user_zeroing(to, from, n);
memset(to, 0, n);
return n; return n;
} }

View File

@ -227,7 +227,7 @@ extern long __user_bad(void);
#define __get_user(x, ptr) \ #define __get_user(x, ptr) \
({ \ ({ \
unsigned long __gu_val; \ unsigned long __gu_val = 0; \
/*unsigned long __gu_ptr = (unsigned long)(ptr);*/ \ /*unsigned long __gu_ptr = (unsigned long)(ptr);*/ \
long __gu_err; \ long __gu_err; \
switch (sizeof(*(ptr))) { \ switch (sizeof(*(ptr))) { \
@ -373,10 +373,13 @@ extern long __user_bad(void);
static inline long copy_from_user(void *to, static inline long copy_from_user(void *to,
const void __user *from, unsigned long n) const void __user *from, unsigned long n)
{ {
unsigned long res = n;
might_fault(); might_fault();
if (access_ok(VERIFY_READ, from, n)) if (likely(access_ok(VERIFY_READ, from, n)))
return __copy_from_user(to, from, n); res = __copy_from_user(to, from, n);
return n; if (unlikely(res))
memset(to + (n - res), 0, res);
return res;
} }
#define __copy_to_user(to, from, n) \ #define __copy_to_user(to, from, n) \

View File

@ -65,6 +65,7 @@ config MIPS
select ARCH_CLOCKSOURCE_DATA select ARCH_CLOCKSOURCE_DATA
select HANDLE_DOMAIN_IRQ select HANDLE_DOMAIN_IRQ
select HAVE_EXIT_THREAD select HAVE_EXIT_THREAD
select HAVE_REGS_AND_STACK_ACCESS_API
menu "Machine selection" menu "Machine selection"

View File

@ -113,42 +113,6 @@ config SPINLOCK_TEST
help help
Add several files to the debugfs to test spinlock speed. Add several files to the debugfs to test spinlock speed.
if CPU_MIPSR6
choice
prompt "Compact branch policy"
default MIPS_COMPACT_BRANCHES_OPTIMAL
config MIPS_COMPACT_BRANCHES_NEVER
bool "Never (force delay slot branches)"
help
Pass the -mcompact-branches=never flag to the compiler in order to
force it to always emit branches with delay slots, and make no use
of the compact branch instructions introduced by MIPSr6. This is
useful if you suspect there may be an issue with compact branches in
either the compiler or the CPU.
config MIPS_COMPACT_BRANCHES_OPTIMAL
bool "Optimal (use where beneficial)"
help
Pass the -mcompact-branches=optimal flag to the compiler in order for
it to make use of compact branch instructions where it deems them
beneficial, and use branches with delay slots elsewhere. This is the
default compiler behaviour, and should be used unless you have a
reason to choose otherwise.
config MIPS_COMPACT_BRANCHES_ALWAYS
bool "Always (force compact branches)"
help
Pass the -mcompact-branches=always flag to the compiler in order to
force it to always emit compact branches, making no use of branch
instructions with delay slots. This can result in more compact code
which may be beneficial in some scenarios.
endchoice
endif # CPU_MIPSR6
config SCACHE_DEBUGFS config SCACHE_DEBUGFS
bool "L2 cache debugfs entries" bool "L2 cache debugfs entries"
depends on DEBUG_FS depends on DEBUG_FS

View File

@ -203,10 +203,6 @@ endif
toolchain-virt := $(call cc-option-yn,$(mips-cflags) -mvirt) toolchain-virt := $(call cc-option-yn,$(mips-cflags) -mvirt)
cflags-$(toolchain-virt) += -DTOOLCHAIN_SUPPORTS_VIRT cflags-$(toolchain-virt) += -DTOOLCHAIN_SUPPORTS_VIRT
cflags-$(CONFIG_MIPS_COMPACT_BRANCHES_NEVER) += -mcompact-branches=never
cflags-$(CONFIG_MIPS_COMPACT_BRANCHES_OPTIMAL) += -mcompact-branches=optimal
cflags-$(CONFIG_MIPS_COMPACT_BRANCHES_ALWAYS) += -mcompact-branches=always
# #
# Firmware support # Firmware support
# #

View File

@ -96,7 +96,7 @@ static struct clk * __init ath79_reg_ffclk(const char *name,
struct clk *clk; struct clk *clk;
clk = clk_register_fixed_factor(NULL, name, parent_name, 0, mult, div); clk = clk_register_fixed_factor(NULL, name, parent_name, 0, mult, div);
if (!clk) if (IS_ERR(clk))
panic("failed to allocate %s clock structure", name); panic("failed to allocate %s clock structure", name);
return clk; return clk;

View File

@ -1059,7 +1059,7 @@ static int __init octeon_publish_devices(void)
{ {
return of_platform_bus_probe(NULL, octeon_ids, NULL); return of_platform_bus_probe(NULL, octeon_ids, NULL);
} }
device_initcall(octeon_publish_devices); arch_initcall(octeon_publish_devices);
MODULE_AUTHOR("David Daney <ddaney@caviumnetworks.com>"); MODULE_AUTHOR("David Daney <ddaney@caviumnetworks.com>");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");

View File

@ -157,6 +157,7 @@
ldc1 $f28, THREAD_FPR28(\thread) ldc1 $f28, THREAD_FPR28(\thread)
ldc1 $f30, THREAD_FPR30(\thread) ldc1 $f30, THREAD_FPR30(\thread)
ctc1 \tmp, fcr31 ctc1 \tmp, fcr31
.set pop
.endm .endm
.macro fpu_restore_16odd thread .macro fpu_restore_16odd thread

View File

@ -15,8 +15,8 @@
static inline bool __should_swizzle_bits(volatile void *a) static inline bool __should_swizzle_bits(volatile void *a)
{ {
extern const bool octeon_should_swizzle_table[]; extern const bool octeon_should_swizzle_table[];
u64 did = ((u64)(uintptr_t)a >> 40) & 0xff;
unsigned long did = ((unsigned long)a >> 40) & 0xff;
return octeon_should_swizzle_table[did]; return octeon_should_swizzle_table[did];
} }
@ -29,7 +29,7 @@ static inline bool __should_swizzle_bits(volatile void *a)
#define __should_swizzle_bits(a) false #define __should_swizzle_bits(a) false
static inline bool __should_swizzle_addr(unsigned long p) static inline bool __should_swizzle_addr(u64 p)
{ {
/* boot bus? */ /* boot bus? */
return ((p >> 40) & 0xff) == 0; return ((p >> 40) & 0xff) == 0;

View File

@ -11,11 +11,13 @@
#define CP0_EBASE $15, 1 #define CP0_EBASE $15, 1
.macro kernel_entry_setup .macro kernel_entry_setup
#ifdef CONFIG_SMP
mfc0 t0, CP0_EBASE mfc0 t0, CP0_EBASE
andi t0, t0, 0x3ff # CPUNum andi t0, t0, 0x3ff # CPUNum
beqz t0, 1f beqz t0, 1f
# CPUs other than zero goto smp_bootstrap # CPUs other than zero goto smp_bootstrap
j smp_bootstrap j smp_bootstrap
#endif /* CONFIG_SMP */
1: 1:
.endm .endm

View File

@ -14,6 +14,7 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/thread_info.h> #include <linux/thread_info.h>
#include <linux/string.h>
#include <asm/asm-eva.h> #include <asm/asm-eva.h>
/* /*
@ -1170,6 +1171,8 @@ extern size_t __copy_in_user_eva(void *__to, const void *__from, size_t __n);
__cu_len = __invoke_copy_from_user(__cu_to, \ __cu_len = __invoke_copy_from_user(__cu_to, \
__cu_from, \ __cu_from, \
__cu_len); \ __cu_len); \
} else { \
memset(__cu_to, 0, __cu_len); \
} \ } \
} \ } \
__cu_len; \ __cu_len; \

View File

@ -1164,7 +1164,9 @@ fpu_emul:
regs->regs[31] = r31; regs->regs[31] = r31;
regs->cp0_epc = epc; regs->cp0_epc = epc;
if (!used_math()) { /* First time FPU user. */ if (!used_math()) { /* First time FPU user. */
preempt_disable();
err = init_fpu(); err = init_fpu();
preempt_enable();
set_used_math(); set_used_math();
} }
lose_fpu(1); /* Save FPU state for the emulator. */ lose_fpu(1); /* Save FPU state for the emulator. */

View File

@ -605,14 +605,14 @@ int mips_set_process_fp_mode(struct task_struct *task, unsigned int value)
return -EOPNOTSUPP; return -EOPNOTSUPP;
/* Avoid inadvertently triggering emulation */ /* Avoid inadvertently triggering emulation */
if ((value & PR_FP_MODE_FR) && cpu_has_fpu && if ((value & PR_FP_MODE_FR) && raw_cpu_has_fpu &&
!(current_cpu_data.fpu_id & MIPS_FPIR_F64)) !(raw_current_cpu_data.fpu_id & MIPS_FPIR_F64))
return -EOPNOTSUPP; return -EOPNOTSUPP;
if ((value & PR_FP_MODE_FRE) && cpu_has_fpu && !cpu_has_fre) if ((value & PR_FP_MODE_FRE) && raw_cpu_has_fpu && !cpu_has_fre)
return -EOPNOTSUPP; return -EOPNOTSUPP;
/* FR = 0 not supported in MIPS R6 */ /* FR = 0 not supported in MIPS R6 */
if (!(value & PR_FP_MODE_FR) && cpu_has_fpu && cpu_has_mips_r6) if (!(value & PR_FP_MODE_FR) && raw_cpu_has_fpu && cpu_has_mips_r6)
return -EOPNOTSUPP; return -EOPNOTSUPP;
/* Proceed with the mode switch */ /* Proceed with the mode switch */

View File

@ -87,6 +87,13 @@ void __init add_memory_region(phys_addr_t start, phys_addr_t size, long type)
int x = boot_mem_map.nr_map; int x = boot_mem_map.nr_map;
int i; int i;
/*
* If the region reaches the top of the physical address space, adjust
* the size slightly so that (start + size) doesn't overflow
*/
if (start + size - 1 == (phys_addr_t)ULLONG_MAX)
--size;
/* Sanity check */ /* Sanity check */
if (start + size < start) { if (start + size < start) {
pr_warn("Trying to add an invalid memory region, skipped\n"); pr_warn("Trying to add an invalid memory region, skipped\n");

View File

@ -322,6 +322,9 @@ asmlinkage void start_secondary(void)
cpumask_set_cpu(cpu, &cpu_coherent_mask); cpumask_set_cpu(cpu, &cpu_coherent_mask);
notify_cpu_starting(cpu); notify_cpu_starting(cpu);
cpumask_set_cpu(cpu, &cpu_callin_map);
synchronise_count_slave(cpu);
set_cpu_online(cpu, true); set_cpu_online(cpu, true);
set_cpu_sibling_map(cpu); set_cpu_sibling_map(cpu);
@ -329,10 +332,6 @@ asmlinkage void start_secondary(void)
calculate_cpu_foreign_map(); calculate_cpu_foreign_map();
cpumask_set_cpu(cpu, &cpu_callin_map);
synchronise_count_slave(cpu);
/* /*
* irq will be enabled in ->smp_finish(), enabling it too early * irq will be enabled in ->smp_finish(), enabling it too early
* is dangerous. * is dangerous.

View File

@ -222,7 +222,7 @@ int arch_uprobe_exception_notify(struct notifier_block *self,
return NOTIFY_DONE; return NOTIFY_DONE;
switch (val) { switch (val) {
case DIE_BREAK: case DIE_UPROBE:
if (uprobe_pre_sstep_notifier(regs)) if (uprobe_pre_sstep_notifier(regs))
return NOTIFY_STOP; return NOTIFY_STOP;
break; break;

View File

@ -39,16 +39,16 @@ static struct vm_special_mapping vdso_vvar_mapping = {
static void __init init_vdso_image(struct mips_vdso_image *image) static void __init init_vdso_image(struct mips_vdso_image *image)
{ {
unsigned long num_pages, i; unsigned long num_pages, i;
unsigned long data_pfn;
BUG_ON(!PAGE_ALIGNED(image->data)); BUG_ON(!PAGE_ALIGNED(image->data));
BUG_ON(!PAGE_ALIGNED(image->size)); BUG_ON(!PAGE_ALIGNED(image->size));
num_pages = image->size / PAGE_SIZE; num_pages = image->size / PAGE_SIZE;
for (i = 0; i < num_pages; i++) { data_pfn = __phys_to_pfn(__pa_symbol(image->data));
image->mapping.pages[i] = for (i = 0; i < num_pages; i++)
virt_to_page(image->data + (i * PAGE_SIZE)); image->mapping.pages[i] = pfn_to_page(data_pfn + i);
}
} }
static int __init init_vdso(void) static int __init init_vdso(void)

View File

@ -298,5 +298,6 @@ bool do_dsemulret(struct pt_regs *xcp)
/* Set EPC to return to post-branch instruction */ /* Set EPC to return to post-branch instruction */
xcp->cp0_epc = current->thread.bd_emu_cont_pc; xcp->cp0_epc = current->thread.bd_emu_cont_pc;
pr_debug("dsemulret to 0x%08lx\n", xcp->cp0_epc); pr_debug("dsemulret to 0x%08lx\n", xcp->cp0_epc);
MIPS_FPU_EMU_INC_STATS(ds_emul);
return true; return true;
} }

View File

@ -800,7 +800,7 @@ static void r4k_flush_icache_range(unsigned long start, unsigned long end)
* If address-based cache ops don't require an SMP call, then * If address-based cache ops don't require an SMP call, then
* use them exclusively for small flushes. * use them exclusively for small flushes.
*/ */
size = start - end; size = end - start;
cache_size = icache_size; cache_size = icache_size;
if (!cpu_has_ic_fills_f_dc) { if (!cpu_has_ic_fills_f_dc) {
size *= 2; size *= 2;

View File

@ -261,7 +261,6 @@ unsigned __weak platform_maar_init(unsigned num_pairs)
{ {
struct maar_config cfg[BOOT_MEM_MAP_MAX]; struct maar_config cfg[BOOT_MEM_MAP_MAX];
unsigned i, num_configured, num_cfg = 0; unsigned i, num_configured, num_cfg = 0;
phys_addr_t skip;
for (i = 0; i < boot_mem_map.nr_map; i++) { for (i = 0; i < boot_mem_map.nr_map; i++) {
switch (boot_mem_map.map[i].type) { switch (boot_mem_map.map[i].type) {
@ -272,14 +271,14 @@ unsigned __weak platform_maar_init(unsigned num_pairs)
continue; continue;
} }
skip = 0x10000 - (boot_mem_map.map[i].addr & 0xffff); /* Round lower up */
cfg[num_cfg].lower = boot_mem_map.map[i].addr; cfg[num_cfg].lower = boot_mem_map.map[i].addr;
cfg[num_cfg].lower += skip; cfg[num_cfg].lower = (cfg[num_cfg].lower + 0xffff) & ~0xffff;
cfg[num_cfg].upper = cfg[num_cfg].lower; /* Round upper down */
cfg[num_cfg].upper += boot_mem_map.map[i].size - 1; cfg[num_cfg].upper = boot_mem_map.map[i].addr +
cfg[num_cfg].upper -= skip; boot_mem_map.map[i].size;
cfg[num_cfg].upper = (cfg[num_cfg].upper & ~0xffff) - 1;
cfg[num_cfg].attrs = MIPS_MAAR_S; cfg[num_cfg].attrs = MIPS_MAAR_S;
num_cfg++; num_cfg++;

View File

@ -166,6 +166,7 @@ struct __large_struct { unsigned long buf[100]; };
"2:\n" \ "2:\n" \
" .section .fixup,\"ax\"\n" \ " .section .fixup,\"ax\"\n" \
"3:\n\t" \ "3:\n\t" \
" mov 0,%1\n" \
" mov %3,%0\n" \ " mov %3,%0\n" \
" jmp 2b\n" \ " jmp 2b\n" \
" .previous\n" \ " .previous\n" \

View File

@ -9,7 +9,7 @@
* as published by the Free Software Foundation; either version * as published by the Free Software Foundation; either version
* 2 of the Licence, or (at your option) any later version. * 2 of the Licence, or (at your option) any later version.
*/ */
#include <asm/uaccess.h> #include <linux/uaccess.h>
unsigned long unsigned long
__generic_copy_to_user(void *to, const void *from, unsigned long n) __generic_copy_to_user(void *to, const void *from, unsigned long n)
@ -24,6 +24,8 @@ __generic_copy_from_user(void *to, const void *from, unsigned long n)
{ {
if (access_ok(VERIFY_READ, from, n)) if (access_ok(VERIFY_READ, from, n))
__copy_user_zeroing(to, from, n); __copy_user_zeroing(to, from, n);
else
memset(to, 0, n);
return n; return n;
} }

View File

@ -102,9 +102,12 @@ extern long __copy_to_user(void __user *to, const void *from, unsigned long n);
static inline long copy_from_user(void *to, const void __user *from, static inline long copy_from_user(void *to, const void __user *from,
unsigned long n) unsigned long n)
{ {
if (!access_ok(VERIFY_READ, from, n)) unsigned long res = n;
return n; if (access_ok(VERIFY_READ, from, n))
return __copy_from_user(to, from, n); res = __copy_from_user(to, from, n);
if (unlikely(res))
memset(to + (n - res), 0, res);
return res;
} }
static inline long copy_to_user(void __user *to, const void *from, static inline long copy_to_user(void __user *to, const void *from,
@ -139,7 +142,7 @@ extern long strnlen_user(const char __user *s, long n);
#define __get_user_unknown(val, size, ptr, err) do { \ #define __get_user_unknown(val, size, ptr, err) do { \
err = 0; \ err = 0; \
if (copy_from_user(&(val), ptr, size)) { \ if (__copy_from_user(&(val), ptr, size)) { \
err = -EFAULT; \ err = -EFAULT; \
} \ } \
} while (0) } while (0)
@ -166,7 +169,7 @@ do { \
({ \ ({ \
long __gu_err = -EFAULT; \ long __gu_err = -EFAULT; \
const __typeof__(*(ptr)) __user *__gu_ptr = (ptr); \ const __typeof__(*(ptr)) __user *__gu_ptr = (ptr); \
unsigned long __gu_val; \ unsigned long __gu_val = 0; \
__get_user_common(__gu_val, sizeof(*(ptr)), __gu_ptr, __gu_err);\ __get_user_common(__gu_val, sizeof(*(ptr)), __gu_ptr, __gu_err);\
(x) = (__force __typeof__(x))__gu_val; \ (x) = (__force __typeof__(x))__gu_val; \
__gu_err; \ __gu_err; \

View File

@ -273,28 +273,20 @@ __copy_tofrom_user(void *to, const void *from, unsigned long size);
static inline unsigned long static inline unsigned long
copy_from_user(void *to, const void *from, unsigned long n) copy_from_user(void *to, const void *from, unsigned long n)
{ {
unsigned long over; unsigned long res = n;
if (access_ok(VERIFY_READ, from, n)) if (likely(access_ok(VERIFY_READ, from, n)))
return __copy_tofrom_user(to, from, n); res = __copy_tofrom_user(to, from, n);
if ((unsigned long)from < TASK_SIZE) { if (unlikely(res))
over = (unsigned long)from + n - TASK_SIZE; memset(to + (n - res), 0, res);
return __copy_tofrom_user(to, from, n - over) + over; return res;
}
return n;
} }
static inline unsigned long static inline unsigned long
copy_to_user(void *to, const void *from, unsigned long n) copy_to_user(void *to, const void *from, unsigned long n)
{ {
unsigned long over; if (likely(access_ok(VERIFY_WRITE, to, n)))
n = __copy_tofrom_user(to, from, n);
if (access_ok(VERIFY_WRITE, to, n))
return __copy_tofrom_user(to, from, n);
if ((unsigned long)to < TASK_SIZE) {
over = (unsigned long)to + n - TASK_SIZE;
return __copy_tofrom_user(to, from, n - over) + over;
}
return n; return n;
} }
@ -303,13 +295,8 @@ extern unsigned long __clear_user(void *addr, unsigned long size);
static inline __must_check unsigned long static inline __must_check unsigned long
clear_user(void *addr, unsigned long size) clear_user(void *addr, unsigned long size)
{ {
if (likely(access_ok(VERIFY_WRITE, addr, size)))
if (access_ok(VERIFY_WRITE, addr, size)) size = __clear_user(addr, size);
return __clear_user(addr, size);
if ((unsigned long)addr < TASK_SIZE) {
unsigned long over = (unsigned long)addr + size - TASK_SIZE;
return __clear_user(addr, size - over) + over;
}
return size; return size;
} }

View File

@ -10,6 +10,7 @@
#include <asm-generic/uaccess-unaligned.h> #include <asm-generic/uaccess-unaligned.h>
#include <linux/bug.h> #include <linux/bug.h>
#include <linux/string.h>
#define VERIFY_READ 0 #define VERIFY_READ 0
#define VERIFY_WRITE 1 #define VERIFY_WRITE 1
@ -221,7 +222,7 @@ static inline unsigned long __must_check copy_from_user(void *to,
unsigned long n) unsigned long n)
{ {
int sz = __compiletime_object_size(to); int sz = __compiletime_object_size(to);
int ret = -EFAULT; unsigned long ret = n;
if (likely(sz == -1 || sz >= n)) if (likely(sz == -1 || sz >= n))
ret = __copy_from_user(to, from, n); ret = __copy_from_user(to, from, n);
@ -230,6 +231,8 @@ static inline unsigned long __must_check copy_from_user(void *to,
else else
__bad_copy_user(); __bad_copy_user();
if (unlikely(ret))
memset(to + (n - ret), 0, ret);
return ret; return ret;
} }

View File

@ -15,7 +15,7 @@ static inline bool early_cpu_has_feature(unsigned long feature)
#ifdef CONFIG_JUMP_LABEL_FEATURE_CHECKS #ifdef CONFIG_JUMP_LABEL_FEATURE_CHECKS
#include <linux/jump_label.h> #include <linux/jump_label.h>
#define NUM_CPU_FTR_KEYS 64 #define NUM_CPU_FTR_KEYS BITS_PER_LONG
extern struct static_key_true cpu_feature_keys[NUM_CPU_FTR_KEYS]; extern struct static_key_true cpu_feature_keys[NUM_CPU_FTR_KEYS];

View File

@ -308,36 +308,21 @@ extern unsigned long __copy_tofrom_user(void __user *to,
static inline unsigned long copy_from_user(void *to, static inline unsigned long copy_from_user(void *to,
const void __user *from, unsigned long n) const void __user *from, unsigned long n)
{ {
unsigned long over; if (likely(access_ok(VERIFY_READ, from, n))) {
if (access_ok(VERIFY_READ, from, n)) {
check_object_size(to, n, false); check_object_size(to, n, false);
return __copy_tofrom_user((__force void __user *)to, from, n); return __copy_tofrom_user((__force void __user *)to, from, n);
} }
if ((unsigned long)from < TASK_SIZE) { memset(to, 0, n);
over = (unsigned long)from + n - TASK_SIZE;
check_object_size(to, n - over, false);
return __copy_tofrom_user((__force void __user *)to, from,
n - over) + over;
}
return n; return n;
} }
static inline unsigned long copy_to_user(void __user *to, static inline unsigned long copy_to_user(void __user *to,
const void *from, unsigned long n) const void *from, unsigned long n)
{ {
unsigned long over;
if (access_ok(VERIFY_WRITE, to, n)) { if (access_ok(VERIFY_WRITE, to, n)) {
check_object_size(from, n, true); check_object_size(from, n, true);
return __copy_tofrom_user(to, (__force void __user *)from, n); return __copy_tofrom_user(to, (__force void __user *)from, n);
} }
if ((unsigned long)to < TASK_SIZE) {
over = (unsigned long)to + n - TASK_SIZE;
check_object_size(from, n - over, true);
return __copy_tofrom_user(to, (__force void __user *)from,
n - over) + over;
}
return n; return n;
} }
@ -434,10 +419,6 @@ static inline unsigned long clear_user(void __user *addr, unsigned long size)
might_fault(); might_fault();
if (likely(access_ok(VERIFY_WRITE, addr, size))) if (likely(access_ok(VERIFY_WRITE, addr, size)))
return __clear_user(addr, size); return __clear_user(addr, size);
if ((unsigned long)addr < TASK_SIZE) {
unsigned long over = (unsigned long)addr + size - TASK_SIZE;
return __clear_user(addr, size - over) + over;
}
return size; return size;
} }

View File

@ -411,7 +411,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300)
* *
* r13 - PACA * r13 - PACA
* cr3 - gt if waking up with partial/complete hypervisor state loss * cr3 - gt if waking up with partial/complete hypervisor state loss
* cr4 - eq if waking up from complete hypervisor state loss. * cr4 - gt or eq if waking up from complete hypervisor state loss.
*/ */
_GLOBAL(pnv_wakeup_tb_loss) _GLOBAL(pnv_wakeup_tb_loss)
ld r1,PACAR1(r13) ld r1,PACAR1(r13)
@ -453,7 +453,7 @@ lwarx_loop2:
* At this stage * At this stage
* cr2 - eq if first thread to wakeup in core * cr2 - eq if first thread to wakeup in core
* cr3- gt if waking up with partial/complete hypervisor state loss * cr3- gt if waking up with partial/complete hypervisor state loss
* cr4 - eq if waking up from complete hypervisor state loss. * cr4 - gt or eq if waking up from complete hypervisor state loss.
*/ */
ori r15,r15,PNV_CORE_IDLE_LOCK_BIT ori r15,r15,PNV_CORE_IDLE_LOCK_BIT
@ -481,7 +481,7 @@ first_thread_in_subcore:
* If waking up from sleep, subcore state is not lost. Hence * If waking up from sleep, subcore state is not lost. Hence
* skip subcore state restore * skip subcore state restore
*/ */
bne cr4,subcore_state_restored blt cr4,subcore_state_restored
/* Restore per-subcore state */ /* Restore per-subcore state */
ld r4,_SDR1(r1) ld r4,_SDR1(r1)
@ -526,7 +526,7 @@ timebase_resync:
* If waking up from sleep, per core state is not lost, skip to * If waking up from sleep, per core state is not lost, skip to
* clear_lock. * clear_lock.
*/ */
bne cr4,clear_lock blt cr4,clear_lock
/* /*
* First thread in the core to wake up and its waking up with * First thread in the core to wake up and its waking up with
@ -557,7 +557,7 @@ common_exit:
* If waking up from sleep, hypervisor state is not lost. Hence * If waking up from sleep, hypervisor state is not lost. Hence
* skip hypervisor state restore. * skip hypervisor state restore.
*/ */
bne cr4,hypervisor_state_restored blt cr4,hypervisor_state_restored
/* Waking up from winkle */ /* Waking up from winkle */

View File

@ -124,6 +124,13 @@ static inline bool pnv_pci_is_m64(struct pnv_phb *phb, struct resource *r)
r->start < (phb->ioda.m64_base + phb->ioda.m64_size)); r->start < (phb->ioda.m64_base + phb->ioda.m64_size));
} }
static inline bool pnv_pci_is_m64_flags(unsigned long resource_flags)
{
unsigned long flags = (IORESOURCE_MEM_64 | IORESOURCE_PREFETCH);
return (resource_flags & flags) == flags;
}
static struct pnv_ioda_pe *pnv_ioda_init_pe(struct pnv_phb *phb, int pe_no) static struct pnv_ioda_pe *pnv_ioda_init_pe(struct pnv_phb *phb, int pe_no)
{ {
phb->ioda.pe_array[pe_no].phb = phb; phb->ioda.pe_array[pe_no].phb = phb;
@ -2217,7 +2224,7 @@ static long pnv_pci_ioda2_set_window(struct iommu_table_group *table_group,
pnv_pci_link_table_and_group(phb->hose->node, num, pnv_pci_link_table_and_group(phb->hose->node, num,
tbl, &pe->table_group); tbl, &pe->table_group);
pnv_pci_phb3_tce_invalidate_pe(pe); pnv_pci_ioda2_tce_invalidate_pe(pe);
return 0; return 0;
} }
@ -2355,7 +2362,7 @@ static long pnv_pci_ioda2_unset_window(struct iommu_table_group *table_group,
if (ret) if (ret)
pe_warn(pe, "Unmapping failed, ret = %ld\n", ret); pe_warn(pe, "Unmapping failed, ret = %ld\n", ret);
else else
pnv_pci_phb3_tce_invalidate_pe(pe); pnv_pci_ioda2_tce_invalidate_pe(pe);
pnv_pci_unlink_table_and_group(table_group->tables[num], table_group); pnv_pci_unlink_table_and_group(table_group->tables[num], table_group);
@ -2871,7 +2878,7 @@ static void pnv_pci_ioda_fixup_iov_resources(struct pci_dev *pdev)
res = &pdev->resource[i + PCI_IOV_RESOURCES]; res = &pdev->resource[i + PCI_IOV_RESOURCES];
if (!res->flags || res->parent) if (!res->flags || res->parent)
continue; continue;
if (!pnv_pci_is_m64(phb, res)) { if (!pnv_pci_is_m64_flags(res->flags)) {
dev_warn(&pdev->dev, "Don't support SR-IOV with" dev_warn(&pdev->dev, "Don't support SR-IOV with"
" non M64 VF BAR%d: %pR. \n", " non M64 VF BAR%d: %pR. \n",
i, res); i, res);
@ -3096,7 +3103,7 @@ static resource_size_t pnv_pci_window_alignment(struct pci_bus *bus,
* alignment for any 64-bit resource, PCIe doesn't care and * alignment for any 64-bit resource, PCIe doesn't care and
* bridges only do 64-bit prefetchable anyway. * bridges only do 64-bit prefetchable anyway.
*/ */
if (phb->ioda.m64_segsize && (type & IORESOURCE_MEM_64)) if (phb->ioda.m64_segsize && pnv_pci_is_m64_flags(type))
return phb->ioda.m64_segsize; return phb->ioda.m64_segsize;
if (type & IORESOURCE_MEM) if (type & IORESOURCE_MEM)
return phb->ioda.m32_segsize; return phb->ioda.m32_segsize;
@ -3426,7 +3433,17 @@ static void pnv_ioda_release_pe(struct pnv_ioda_pe *pe)
} }
} }
pnv_ioda_free_pe(pe); /*
* The PE for root bus can be removed because of hotplug in EEH
* recovery for fenced PHB error. We need to mark the PE dead so
* that it can be populated again in PCI hot add path. The PE
* shouldn't be destroyed as it's the global reserved resource.
*/
if (phb->ioda.root_pe_populated &&
phb->ioda.root_pe_idx == pe->pe_number)
phb->ioda.root_pe_populated = false;
else
pnv_ioda_free_pe(pe);
} }
static void pnv_pci_release_device(struct pci_dev *pdev) static void pnv_pci_release_device(struct pci_dev *pdev)
@ -3442,7 +3459,17 @@ static void pnv_pci_release_device(struct pci_dev *pdev)
if (!pdn || pdn->pe_number == IODA_INVALID_PE) if (!pdn || pdn->pe_number == IODA_INVALID_PE)
return; return;
/*
* PCI hotplug can happen as part of EEH error recovery. The @pdn
* isn't removed and added afterwards in this scenario. We should
* set the PE number in @pdn to an invalid one. Otherwise, the PE's
* device count is decreased on removing devices while failing to
* be increased on adding devices. It leads to unbalanced PE's device
* count and eventually make normal PCI hotplug path broken.
*/
pe = &phb->ioda.pe_array[pdn->pe_number]; pe = &phb->ioda.pe_array[pdn->pe_number];
pdn->pe_number = IODA_INVALID_PE;
WARN_ON(--pe->device_count < 0); WARN_ON(--pe->device_count < 0);
if (pe->device_count == 0) if (pe->device_count == 0)
pnv_ioda_release_pe(pe); pnv_ioda_release_pe(pe);

View File

@ -266,28 +266,28 @@ int __put_user_bad(void) __attribute__((noreturn));
__chk_user_ptr(ptr); \ __chk_user_ptr(ptr); \
switch (sizeof(*(ptr))) { \ switch (sizeof(*(ptr))) { \
case 1: { \ case 1: { \
unsigned char __x; \ unsigned char __x = 0; \
__gu_err = __get_user_fn(&__x, ptr, \ __gu_err = __get_user_fn(&__x, ptr, \
sizeof(*(ptr))); \ sizeof(*(ptr))); \
(x) = *(__force __typeof__(*(ptr)) *) &__x; \ (x) = *(__force __typeof__(*(ptr)) *) &__x; \
break; \ break; \
}; \ }; \
case 2: { \ case 2: { \
unsigned short __x; \ unsigned short __x = 0; \
__gu_err = __get_user_fn(&__x, ptr, \ __gu_err = __get_user_fn(&__x, ptr, \
sizeof(*(ptr))); \ sizeof(*(ptr))); \
(x) = *(__force __typeof__(*(ptr)) *) &__x; \ (x) = *(__force __typeof__(*(ptr)) *) &__x; \
break; \ break; \
}; \ }; \
case 4: { \ case 4: { \
unsigned int __x; \ unsigned int __x = 0; \
__gu_err = __get_user_fn(&__x, ptr, \ __gu_err = __get_user_fn(&__x, ptr, \
sizeof(*(ptr))); \ sizeof(*(ptr))); \
(x) = *(__force __typeof__(*(ptr)) *) &__x; \ (x) = *(__force __typeof__(*(ptr)) *) &__x; \
break; \ break; \
}; \ }; \
case 8: { \ case 8: { \
unsigned long long __x; \ unsigned long long __x = 0; \
__gu_err = __get_user_fn(&__x, ptr, \ __gu_err = __get_user_fn(&__x, ptr, \
sizeof(*(ptr))); \ sizeof(*(ptr))); \
(x) = *(__force __typeof__(*(ptr)) *) &__x; \ (x) = *(__force __typeof__(*(ptr)) *) &__x; \

View File

@ -2231,9 +2231,10 @@ int kvm_arch_vcpu_ioctl_set_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
return -EINVAL; return -EINVAL;
current->thread.fpu.fpc = fpu->fpc; current->thread.fpu.fpc = fpu->fpc;
if (MACHINE_HAS_VX) if (MACHINE_HAS_VX)
convert_fp_to_vx(current->thread.fpu.vxrs, (freg_t *)fpu->fprs); convert_fp_to_vx((__vector128 *) vcpu->run->s.regs.vrs,
(freg_t *) fpu->fprs);
else else
memcpy(current->thread.fpu.fprs, &fpu->fprs, sizeof(fpu->fprs)); memcpy(vcpu->run->s.regs.fprs, &fpu->fprs, sizeof(fpu->fprs));
return 0; return 0;
} }
@ -2242,9 +2243,10 @@ int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
/* make sure we have the latest values */ /* make sure we have the latest values */
save_fpu_regs(); save_fpu_regs();
if (MACHINE_HAS_VX) if (MACHINE_HAS_VX)
convert_vx_to_fp((freg_t *)fpu->fprs, current->thread.fpu.vxrs); convert_vx_to_fp((freg_t *) fpu->fprs,
(__vector128 *) vcpu->run->s.regs.vrs);
else else
memcpy(fpu->fprs, current->thread.fpu.fprs, sizeof(fpu->fprs)); memcpy(fpu->fprs, vcpu->run->s.regs.fprs, sizeof(fpu->fprs));
fpu->fpc = current->thread.fpu.fpc; fpu->fpc = current->thread.fpu.fpc;
return 0; return 0;
} }

View File

@ -584,7 +584,7 @@ static int pin_blocks(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page)
/* Validity 0x0044 will be checked by SIE */ /* Validity 0x0044 will be checked by SIE */
if (rc) if (rc)
goto unpin; goto unpin;
scb_s->gvrd = hpa; scb_s->riccbd = hpa;
} }
return 0; return 0;
unpin: unpin:

View File

@ -163,7 +163,7 @@ do { \
__get_user_asm(val, "lw", ptr); \ __get_user_asm(val, "lw", ptr); \
break; \ break; \
case 8: \ case 8: \
if ((copy_from_user((void *)&val, ptr, 8)) == 0) \ if (__copy_from_user((void *)&val, ptr, 8) == 0) \
__gu_err = 0; \ __gu_err = 0; \
else \ else \
__gu_err = -EFAULT; \ __gu_err = -EFAULT; \
@ -188,6 +188,8 @@ do { \
\ \
if (likely(access_ok(VERIFY_READ, __gu_ptr, size))) \ if (likely(access_ok(VERIFY_READ, __gu_ptr, size))) \
__get_user_common((x), size, __gu_ptr); \ __get_user_common((x), size, __gu_ptr); \
else \
(x) = 0; \
\ \
__gu_err; \ __gu_err; \
}) })
@ -201,6 +203,7 @@ do { \
"2:\n" \ "2:\n" \
".section .fixup,\"ax\"\n" \ ".section .fixup,\"ax\"\n" \
"3:li %0, %4\n" \ "3:li %0, %4\n" \
"li %1, 0\n" \
"j 2b\n" \ "j 2b\n" \
".previous\n" \ ".previous\n" \
".section __ex_table,\"a\"\n" \ ".section __ex_table,\"a\"\n" \
@ -298,35 +301,34 @@ extern int __copy_tofrom_user(void *to, const void *from, unsigned long len);
static inline unsigned long static inline unsigned long
copy_from_user(void *to, const void *from, unsigned long len) copy_from_user(void *to, const void *from, unsigned long len)
{ {
unsigned long over; unsigned long res = len;
if (access_ok(VERIFY_READ, from, len)) if (likely(access_ok(VERIFY_READ, from, len)))
return __copy_tofrom_user(to, from, len); res = __copy_tofrom_user(to, from, len);
if ((unsigned long)from < TASK_SIZE) { if (unlikely(res))
over = (unsigned long)from + len - TASK_SIZE; memset(to + (len - res), 0, res);
return __copy_tofrom_user(to, from, len - over) + over;
} return res;
return len;
} }
static inline unsigned long static inline unsigned long
copy_to_user(void *to, const void *from, unsigned long len) copy_to_user(void *to, const void *from, unsigned long len)
{ {
unsigned long over; if (likely(access_ok(VERIFY_WRITE, to, len)))
len = __copy_tofrom_user(to, from, len);
if (access_ok(VERIFY_WRITE, to, len))
return __copy_tofrom_user(to, from, len);
if ((unsigned long)to < TASK_SIZE) {
over = (unsigned long)to + len - TASK_SIZE;
return __copy_tofrom_user(to, from, len - over) + over;
}
return len; return len;
} }
#define __copy_from_user(to, from, len) \ static inline unsigned long
__copy_tofrom_user((to), (from), (len)) __copy_from_user(void *to, const void *from, unsigned long len)
{
unsigned long left = __copy_tofrom_user(to, from, len);
if (unlikely(left))
memset(to + (len - left), 0, left);
return left;
}
#define __copy_to_user(to, from, len) \ #define __copy_to_user(to, from, len) \
__copy_tofrom_user((to), (from), (len)) __copy_tofrom_user((to), (from), (len))
@ -340,17 +342,17 @@ __copy_to_user_inatomic(void *to, const void *from, unsigned long len)
static inline unsigned long static inline unsigned long
__copy_from_user_inatomic(void *to, const void *from, unsigned long len) __copy_from_user_inatomic(void *to, const void *from, unsigned long len)
{ {
return __copy_from_user(to, from, len); return __copy_tofrom_user(to, from, len);
} }
#define __copy_in_user(to, from, len) __copy_from_user(to, from, len) #define __copy_in_user(to, from, len) __copy_tofrom_user(to, from, len)
static inline unsigned long static inline unsigned long
copy_in_user(void *to, const void *from, unsigned long len) copy_in_user(void *to, const void *from, unsigned long len)
{ {
if (access_ok(VERIFY_READ, from, len) && if (access_ok(VERIFY_READ, from, len) &&
access_ok(VERFITY_WRITE, to, len)) access_ok(VERFITY_WRITE, to, len))
return copy_from_user(to, from, len); return __copy_tofrom_user(to, from, len);
} }
/* /*

View File

@ -60,7 +60,7 @@ static inline int atomic_fetch_##op(int i, atomic_t *v) \
" movco.l %0, @%3 \n" \ " movco.l %0, @%3 \n" \
" bf 1b \n" \ " bf 1b \n" \
" synco \n" \ " synco \n" \
: "=&z" (temp), "=&z" (res) \ : "=&z" (temp), "=&r" (res) \
: "r" (i), "r" (&v->counter) \ : "r" (i), "r" (&v->counter) \
: "t"); \ : "t"); \
\ \

View File

@ -151,7 +151,10 @@ copy_from_user(void *to, const void __user *from, unsigned long n)
__kernel_size_t __copy_size = (__kernel_size_t) n; __kernel_size_t __copy_size = (__kernel_size_t) n;
if (__copy_size && __access_ok(__copy_from, __copy_size)) if (__copy_size && __access_ok(__copy_from, __copy_size))
return __copy_user(to, from, __copy_size); __copy_size = __copy_user(to, from, __copy_size);
if (unlikely(__copy_size))
memset(to + (n - __copy_size), 0, __copy_size);
return __copy_size; return __copy_size;
} }

View File

@ -24,6 +24,7 @@
#define __get_user_size(x,ptr,size,retval) \ #define __get_user_size(x,ptr,size,retval) \
do { \ do { \
retval = 0; \ retval = 0; \
x = 0; \
switch (size) { \ switch (size) { \
case 1: \ case 1: \
retval = __get_user_asm_b((void *)&x, \ retval = __get_user_asm_b((void *)&x, \

View File

@ -266,8 +266,10 @@ static inline unsigned long copy_from_user(void *to, const void __user *from, un
if (n && __access_ok((unsigned long) from, n)) { if (n && __access_ok((unsigned long) from, n)) {
check_object_size(to, n, false); check_object_size(to, n, false);
return __copy_user((__force void __user *) to, from, n); return __copy_user((__force void __user *) to, from, n);
} else } else {
memset(to, 0, n);
return n; return n;
}
} }
static inline unsigned long __copy_from_user(void *to, const void __user *from, unsigned long n) static inline unsigned long __copy_from_user(void *to, const void __user *from, unsigned long n)

View File

@ -1004,79 +1004,87 @@ static efi_status_t alloc_e820ext(u32 nr_desc, struct setup_data **e820ext,
return status; return status;
} }
struct exit_boot_struct {
struct boot_params *boot_params;
struct efi_info *efi;
struct setup_data *e820ext;
__u32 e820ext_size;
bool is64;
};
static efi_status_t exit_boot_func(efi_system_table_t *sys_table_arg,
struct efi_boot_memmap *map,
void *priv)
{
static bool first = true;
const char *signature;
__u32 nr_desc;
efi_status_t status;
struct exit_boot_struct *p = priv;
if (first) {
nr_desc = *map->buff_size / *map->desc_size;
if (nr_desc > ARRAY_SIZE(p->boot_params->e820_map)) {
u32 nr_e820ext = nr_desc -
ARRAY_SIZE(p->boot_params->e820_map);
status = alloc_e820ext(nr_e820ext, &p->e820ext,
&p->e820ext_size);
if (status != EFI_SUCCESS)
return status;
}
first = false;
}
signature = p->is64 ? EFI64_LOADER_SIGNATURE : EFI32_LOADER_SIGNATURE;
memcpy(&p->efi->efi_loader_signature, signature, sizeof(__u32));
p->efi->efi_systab = (unsigned long)sys_table_arg;
p->efi->efi_memdesc_size = *map->desc_size;
p->efi->efi_memdesc_version = *map->desc_ver;
p->efi->efi_memmap = (unsigned long)*map->map;
p->efi->efi_memmap_size = *map->map_size;
#ifdef CONFIG_X86_64
p->efi->efi_systab_hi = (unsigned long)sys_table_arg >> 32;
p->efi->efi_memmap_hi = (unsigned long)*map->map >> 32;
#endif
return EFI_SUCCESS;
}
static efi_status_t exit_boot(struct boot_params *boot_params, static efi_status_t exit_boot(struct boot_params *boot_params,
void *handle, bool is64) void *handle, bool is64)
{ {
struct efi_info *efi = &boot_params->efi_info; unsigned long map_sz, key, desc_size, buff_size;
unsigned long map_sz, key, desc_size;
efi_memory_desc_t *mem_map; efi_memory_desc_t *mem_map;
struct setup_data *e820ext; struct setup_data *e820ext;
const char *signature;
__u32 e820ext_size; __u32 e820ext_size;
__u32 nr_desc, prev_nr_desc;
efi_status_t status; efi_status_t status;
__u32 desc_version; __u32 desc_version;
bool called_exit = false; struct efi_boot_memmap map;
u8 nr_entries; struct exit_boot_struct priv;
int i;
nr_desc = 0; map.map = &mem_map;
e820ext = NULL; map.map_size = &map_sz;
e820ext_size = 0; map.desc_size = &desc_size;
map.desc_ver = &desc_version;
get_map: map.key_ptr = &key;
status = efi_get_memory_map(sys_table, &mem_map, &map_sz, &desc_size, map.buff_size = &buff_size;
&desc_version, &key); priv.boot_params = boot_params;
priv.efi = &boot_params->efi_info;
priv.e820ext = NULL;
priv.e820ext_size = 0;
priv.is64 = is64;
/* Might as well exit boot services now */
status = efi_exit_boot_services(sys_table, handle, &map, &priv,
exit_boot_func);
if (status != EFI_SUCCESS) if (status != EFI_SUCCESS)
return status; return status;
prev_nr_desc = nr_desc; e820ext = priv.e820ext;
nr_desc = map_sz / desc_size; e820ext_size = priv.e820ext_size;
if (nr_desc > prev_nr_desc &&
nr_desc > ARRAY_SIZE(boot_params->e820_map)) {
u32 nr_e820ext = nr_desc - ARRAY_SIZE(boot_params->e820_map);
status = alloc_e820ext(nr_e820ext, &e820ext, &e820ext_size);
if (status != EFI_SUCCESS)
goto free_mem_map;
efi_call_early(free_pool, mem_map);
goto get_map; /* Allocated memory, get map again */
}
signature = is64 ? EFI64_LOADER_SIGNATURE : EFI32_LOADER_SIGNATURE;
memcpy(&efi->efi_loader_signature, signature, sizeof(__u32));
efi->efi_systab = (unsigned long)sys_table;
efi->efi_memdesc_size = desc_size;
efi->efi_memdesc_version = desc_version;
efi->efi_memmap = (unsigned long)mem_map;
efi->efi_memmap_size = map_sz;
#ifdef CONFIG_X86_64
efi->efi_systab_hi = (unsigned long)sys_table >> 32;
efi->efi_memmap_hi = (unsigned long)mem_map >> 32;
#endif
/* Might as well exit boot services now */
status = efi_call_early(exit_boot_services, handle, key);
if (status != EFI_SUCCESS) {
/*
* ExitBootServices() will fail if any of the event
* handlers change the memory map. In which case, we
* must be prepared to retry, but only once so that
* we're guaranteed to exit on repeated failures instead
* of spinning forever.
*/
if (called_exit)
goto free_mem_map;
called_exit = true;
efi_call_early(free_pool, mem_map);
goto get_map;
}
/* Historic? */ /* Historic? */
boot_params->alt_mem_k = 32 * 1024; boot_params->alt_mem_k = 32 * 1024;
@ -1085,10 +1093,6 @@ get_map:
return status; return status;
return EFI_SUCCESS; return EFI_SUCCESS;
free_mem_map:
efi_call_early(free_pool, mem_map);
return status;
} }
/* /*

View File

@ -119,8 +119,8 @@ static const u64 amd_perfmon_event_map[PERF_COUNT_HW_MAX] =
{ {
[PERF_COUNT_HW_CPU_CYCLES] = 0x0076, [PERF_COUNT_HW_CPU_CYCLES] = 0x0076,
[PERF_COUNT_HW_INSTRUCTIONS] = 0x00c0, [PERF_COUNT_HW_INSTRUCTIONS] = 0x00c0,
[PERF_COUNT_HW_CACHE_REFERENCES] = 0x0080, [PERF_COUNT_HW_CACHE_REFERENCES] = 0x077d,
[PERF_COUNT_HW_CACHE_MISSES] = 0x0081, [PERF_COUNT_HW_CACHE_MISSES] = 0x077e,
[PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = 0x00c2, [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = 0x00c2,
[PERF_COUNT_HW_BRANCH_MISSES] = 0x00c3, [PERF_COUNT_HW_BRANCH_MISSES] = 0x00c3,
[PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = 0x00d0, /* "Decoder empty" event */ [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = 0x00d0, /* "Decoder empty" event */

View File

@ -29,6 +29,8 @@
#define COUNTER_SHIFT 16 #define COUNTER_SHIFT 16
static HLIST_HEAD(uncore_unused_list);
struct amd_uncore { struct amd_uncore {
int id; int id;
int refcnt; int refcnt;
@ -39,7 +41,7 @@ struct amd_uncore {
cpumask_t *active_mask; cpumask_t *active_mask;
struct pmu *pmu; struct pmu *pmu;
struct perf_event *events[MAX_COUNTERS]; struct perf_event *events[MAX_COUNTERS];
struct amd_uncore *free_when_cpu_online; struct hlist_node node;
}; };
static struct amd_uncore * __percpu *amd_uncore_nb; static struct amd_uncore * __percpu *amd_uncore_nb;
@ -306,6 +308,7 @@ static int amd_uncore_cpu_up_prepare(unsigned int cpu)
uncore_nb->msr_base = MSR_F15H_NB_PERF_CTL; uncore_nb->msr_base = MSR_F15H_NB_PERF_CTL;
uncore_nb->active_mask = &amd_nb_active_mask; uncore_nb->active_mask = &amd_nb_active_mask;
uncore_nb->pmu = &amd_nb_pmu; uncore_nb->pmu = &amd_nb_pmu;
uncore_nb->id = -1;
*per_cpu_ptr(amd_uncore_nb, cpu) = uncore_nb; *per_cpu_ptr(amd_uncore_nb, cpu) = uncore_nb;
} }
@ -319,6 +322,7 @@ static int amd_uncore_cpu_up_prepare(unsigned int cpu)
uncore_l2->msr_base = MSR_F16H_L2I_PERF_CTL; uncore_l2->msr_base = MSR_F16H_L2I_PERF_CTL;
uncore_l2->active_mask = &amd_l2_active_mask; uncore_l2->active_mask = &amd_l2_active_mask;
uncore_l2->pmu = &amd_l2_pmu; uncore_l2->pmu = &amd_l2_pmu;
uncore_l2->id = -1;
*per_cpu_ptr(amd_uncore_l2, cpu) = uncore_l2; *per_cpu_ptr(amd_uncore_l2, cpu) = uncore_l2;
} }
@ -348,7 +352,7 @@ amd_uncore_find_online_sibling(struct amd_uncore *this,
continue; continue;
if (this->id == that->id) { if (this->id == that->id) {
that->free_when_cpu_online = this; hlist_add_head(&this->node, &uncore_unused_list);
this = that; this = that;
break; break;
} }
@ -388,13 +392,23 @@ static int amd_uncore_cpu_starting(unsigned int cpu)
return 0; return 0;
} }
static void uncore_clean_online(void)
{
struct amd_uncore *uncore;
struct hlist_node *n;
hlist_for_each_entry_safe(uncore, n, &uncore_unused_list, node) {
hlist_del(&uncore->node);
kfree(uncore);
}
}
static void uncore_online(unsigned int cpu, static void uncore_online(unsigned int cpu,
struct amd_uncore * __percpu *uncores) struct amd_uncore * __percpu *uncores)
{ {
struct amd_uncore *uncore = *per_cpu_ptr(uncores, cpu); struct amd_uncore *uncore = *per_cpu_ptr(uncores, cpu);
kfree(uncore->free_when_cpu_online); uncore_clean_online();
uncore->free_when_cpu_online = NULL;
if (cpu == uncore->cpu) if (cpu == uncore->cpu)
cpumask_set_cpu(cpu, uncore->active_mask); cpumask_set_cpu(cpu, uncore->active_mask);

View File

@ -31,7 +31,17 @@
struct bts_ctx { struct bts_ctx {
struct perf_output_handle handle; struct perf_output_handle handle;
struct debug_store ds_back; struct debug_store ds_back;
int started; int state;
};
/* BTS context states: */
enum {
/* no ongoing AUX transactions */
BTS_STATE_STOPPED = 0,
/* AUX transaction is on, BTS tracing is disabled */
BTS_STATE_INACTIVE,
/* AUX transaction is on, BTS tracing is running */
BTS_STATE_ACTIVE,
}; };
static DEFINE_PER_CPU(struct bts_ctx, bts_ctx); static DEFINE_PER_CPU(struct bts_ctx, bts_ctx);
@ -204,6 +214,15 @@ static void bts_update(struct bts_ctx *bts)
static int static int
bts_buffer_reset(struct bts_buffer *buf, struct perf_output_handle *handle); bts_buffer_reset(struct bts_buffer *buf, struct perf_output_handle *handle);
/*
* Ordering PMU callbacks wrt themselves and the PMI is done by means
* of bts::state, which:
* - is set when bts::handle::event is valid, that is, between
* perf_aux_output_begin() and perf_aux_output_end();
* - is zero otherwise;
* - is ordered against bts::handle::event with a compiler barrier.
*/
static void __bts_event_start(struct perf_event *event) static void __bts_event_start(struct perf_event *event)
{ {
struct bts_ctx *bts = this_cpu_ptr(&bts_ctx); struct bts_ctx *bts = this_cpu_ptr(&bts_ctx);
@ -221,10 +240,13 @@ static void __bts_event_start(struct perf_event *event)
/* /*
* local barrier to make sure that ds configuration made it * local barrier to make sure that ds configuration made it
* before we enable BTS * before we enable BTS and bts::state goes ACTIVE
*/ */
wmb(); wmb();
/* INACTIVE/STOPPED -> ACTIVE */
WRITE_ONCE(bts->state, BTS_STATE_ACTIVE);
intel_pmu_enable_bts(config); intel_pmu_enable_bts(config);
} }
@ -251,9 +273,6 @@ static void bts_event_start(struct perf_event *event, int flags)
__bts_event_start(event); __bts_event_start(event);
/* PMI handler: this counter is running and likely generating PMIs */
ACCESS_ONCE(bts->started) = 1;
return; return;
fail_end_stop: fail_end_stop:
@ -263,30 +282,34 @@ fail_stop:
event->hw.state = PERF_HES_STOPPED; event->hw.state = PERF_HES_STOPPED;
} }
static void __bts_event_stop(struct perf_event *event) static void __bts_event_stop(struct perf_event *event, int state)
{ {
struct bts_ctx *bts = this_cpu_ptr(&bts_ctx);
/* ACTIVE -> INACTIVE(PMI)/STOPPED(->stop()) */
WRITE_ONCE(bts->state, state);
/* /*
* No extra synchronization is mandated by the documentation to have * No extra synchronization is mandated by the documentation to have
* BTS data stores globally visible. * BTS data stores globally visible.
*/ */
intel_pmu_disable_bts(); intel_pmu_disable_bts();
if (event->hw.state & PERF_HES_STOPPED)
return;
ACCESS_ONCE(event->hw.state) |= PERF_HES_STOPPED;
} }
static void bts_event_stop(struct perf_event *event, int flags) static void bts_event_stop(struct perf_event *event, int flags)
{ {
struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events); struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
struct bts_ctx *bts = this_cpu_ptr(&bts_ctx); struct bts_ctx *bts = this_cpu_ptr(&bts_ctx);
struct bts_buffer *buf = perf_get_aux(&bts->handle); struct bts_buffer *buf = NULL;
int state = READ_ONCE(bts->state);
/* PMI handler: don't restart this counter */ if (state == BTS_STATE_ACTIVE)
ACCESS_ONCE(bts->started) = 0; __bts_event_stop(event, BTS_STATE_STOPPED);
__bts_event_stop(event); if (state != BTS_STATE_STOPPED)
buf = perf_get_aux(&bts->handle);
event->hw.state |= PERF_HES_STOPPED;
if (flags & PERF_EF_UPDATE) { if (flags & PERF_EF_UPDATE) {
bts_update(bts); bts_update(bts);
@ -296,6 +319,7 @@ static void bts_event_stop(struct perf_event *event, int flags)
bts->handle.head = bts->handle.head =
local_xchg(&buf->data_size, local_xchg(&buf->data_size,
buf->nr_pages << PAGE_SHIFT); buf->nr_pages << PAGE_SHIFT);
perf_aux_output_end(&bts->handle, local_xchg(&buf->data_size, 0), perf_aux_output_end(&bts->handle, local_xchg(&buf->data_size, 0),
!!local_xchg(&buf->lost, 0)); !!local_xchg(&buf->lost, 0));
} }
@ -310,8 +334,20 @@ static void bts_event_stop(struct perf_event *event, int flags)
void intel_bts_enable_local(void) void intel_bts_enable_local(void)
{ {
struct bts_ctx *bts = this_cpu_ptr(&bts_ctx); struct bts_ctx *bts = this_cpu_ptr(&bts_ctx);
int state = READ_ONCE(bts->state);
if (bts->handle.event && bts->started) /*
* Here we transition from INACTIVE to ACTIVE;
* if we instead are STOPPED from the interrupt handler,
* stay that way. Can't be ACTIVE here though.
*/
if (WARN_ON_ONCE(state == BTS_STATE_ACTIVE))
return;
if (state == BTS_STATE_STOPPED)
return;
if (bts->handle.event)
__bts_event_start(bts->handle.event); __bts_event_start(bts->handle.event);
} }
@ -319,8 +355,15 @@ void intel_bts_disable_local(void)
{ {
struct bts_ctx *bts = this_cpu_ptr(&bts_ctx); struct bts_ctx *bts = this_cpu_ptr(&bts_ctx);
/*
* Here we transition from ACTIVE to INACTIVE;
* do nothing for STOPPED or INACTIVE.
*/
if (READ_ONCE(bts->state) != BTS_STATE_ACTIVE)
return;
if (bts->handle.event) if (bts->handle.event)
__bts_event_stop(bts->handle.event); __bts_event_stop(bts->handle.event, BTS_STATE_INACTIVE);
} }
static int static int
@ -335,8 +378,6 @@ bts_buffer_reset(struct bts_buffer *buf, struct perf_output_handle *handle)
return 0; return 0;
head = handle->head & ((buf->nr_pages << PAGE_SHIFT) - 1); head = handle->head & ((buf->nr_pages << PAGE_SHIFT) - 1);
if (WARN_ON_ONCE(head != local_read(&buf->head)))
return -EINVAL;
phys = &buf->buf[buf->cur_buf]; phys = &buf->buf[buf->cur_buf];
space = phys->offset + phys->displacement + phys->size - head; space = phys->offset + phys->displacement + phys->size - head;
@ -403,22 +444,37 @@ bts_buffer_reset(struct bts_buffer *buf, struct perf_output_handle *handle)
int intel_bts_interrupt(void) int intel_bts_interrupt(void)
{ {
struct debug_store *ds = this_cpu_ptr(&cpu_hw_events)->ds;
struct bts_ctx *bts = this_cpu_ptr(&bts_ctx); struct bts_ctx *bts = this_cpu_ptr(&bts_ctx);
struct perf_event *event = bts->handle.event; struct perf_event *event = bts->handle.event;
struct bts_buffer *buf; struct bts_buffer *buf;
s64 old_head; s64 old_head;
int err; int err = -ENOSPC, handled = 0;
if (!event || !bts->started) /*
return 0; * The only surefire way of knowing if this NMI is ours is by checking
* the write ptr against the PMI threshold.
*/
if (ds && (ds->bts_index >= ds->bts_interrupt_threshold))
handled = 1;
/*
* this is wrapped in intel_bts_enable_local/intel_bts_disable_local,
* so we can only be INACTIVE or STOPPED
*/
if (READ_ONCE(bts->state) == BTS_STATE_STOPPED)
return handled;
buf = perf_get_aux(&bts->handle); buf = perf_get_aux(&bts->handle);
if (!buf)
return handled;
/* /*
* Skip snapshot counters: they don't use the interrupt, but * Skip snapshot counters: they don't use the interrupt, but
* there's no other way of telling, because the pointer will * there's no other way of telling, because the pointer will
* keep moving * keep moving
*/ */
if (!buf || buf->snapshot) if (buf->snapshot)
return 0; return 0;
old_head = local_read(&buf->head); old_head = local_read(&buf->head);
@ -426,18 +482,27 @@ int intel_bts_interrupt(void)
/* no new data */ /* no new data */
if (old_head == local_read(&buf->head)) if (old_head == local_read(&buf->head))
return 0; return handled;
perf_aux_output_end(&bts->handle, local_xchg(&buf->data_size, 0), perf_aux_output_end(&bts->handle, local_xchg(&buf->data_size, 0),
!!local_xchg(&buf->lost, 0)); !!local_xchg(&buf->lost, 0));
buf = perf_aux_output_begin(&bts->handle, event); buf = perf_aux_output_begin(&bts->handle, event);
if (!buf) if (buf)
return 1; err = bts_buffer_reset(buf, &bts->handle);
err = bts_buffer_reset(buf, &bts->handle); if (err) {
if (err) WRITE_ONCE(bts->state, BTS_STATE_STOPPED);
perf_aux_output_end(&bts->handle, 0, false);
if (buf) {
/*
* BTS_STATE_STOPPED should be visible before
* cleared handle::event
*/
barrier();
perf_aux_output_end(&bts->handle, 0, false);
}
}
return 1; return 1;
} }
@ -519,7 +584,8 @@ static __init int bts_init(void)
if (!boot_cpu_has(X86_FEATURE_DTES64) || !x86_pmu.bts) if (!boot_cpu_has(X86_FEATURE_DTES64) || !x86_pmu.bts)
return -ENODEV; return -ENODEV;
bts_pmu.capabilities = PERF_PMU_CAP_AUX_NO_SG | PERF_PMU_CAP_ITRACE; bts_pmu.capabilities = PERF_PMU_CAP_AUX_NO_SG | PERF_PMU_CAP_ITRACE |
PERF_PMU_CAP_EXCLUSIVE;
bts_pmu.task_ctx_nr = perf_sw_context; bts_pmu.task_ctx_nr = perf_sw_context;
bts_pmu.event_init = bts_event_init; bts_pmu.event_init = bts_event_init;
bts_pmu.add = bts_event_add; bts_pmu.add = bts_event_add;

Some files were not shown because too many files have changed in this diff Show More