Merge remote-tracking branch 'ovl/rename2' into for-linus
This commit is contained in:
commit
3873691e5a
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
20
MAINTAINERS
20
MAINTAINERS
|
@ -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
|
||||||
|
|
2
Makefile
2
Makefile
|
@ -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*
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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" \
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
/ {
|
/ {
|
||||||
memory {
|
memory {
|
||||||
|
device_type = "memory";
|
||||||
reg = <0 0x10000000>;
|
reg = <0 0x10000000>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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";
|
||||||
|
|
|
@ -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>;
|
||||||
};
|
};
|
||||||
|
|
|
@ -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";
|
||||||
|
|
|
@ -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++) {
|
||||||
|
|
|
@ -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,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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];
|
||||||
|
|
|
@ -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))
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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]);
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
../../../../arm/boot/dts/bcm2835-rpi.dtsi
|
|
@ -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";
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#include "../../../../arm/boot/dts/bcm283x.dtsi"
|
#include "bcm283x.dtsi"
|
||||||
|
|
||||||
/ {
|
/ {
|
||||||
compatible = "brcm,bcm2836";
|
compatible = "brcm,bcm2836";
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
../../../../arm/boot/dts/bcm283x-rpi-smsc9514.dtsi
|
|
@ -0,0 +1 @@
|
||||||
|
../../../../arm/boot/dts/bcm283x.dtsi
|
|
@ -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 {
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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];
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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))
|
||||||
|
|
||||||
|
|
|
@ -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; \
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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) \
|
||||||
|
|
|
@ -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"
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
#
|
#
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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");
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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; \
|
||||||
|
|
|
@ -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. */
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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");
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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++;
|
||||||
|
|
|
@ -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" \
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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; \
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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];
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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; \
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -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"); \
|
||||||
\
|
\
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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, \
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
Loading…
Reference in New Issue