mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-08 03:40:35 +09:00
Merge branch 'linux-linaro-lsk-v4.9-android' into amlogic-4.9-dev
This commit is contained in:
71
Documentation/ABI/testing/sysfs-class-dual-role-usb
Normal file
71
Documentation/ABI/testing/sysfs-class-dual-role-usb
Normal file
@@ -0,0 +1,71 @@
|
||||
What: /sys/class/dual_role_usb/.../
|
||||
Date: June 2015
|
||||
Contact: Badhri Jagan Sridharan<badhri@google.com>
|
||||
Description:
|
||||
Provide a generic interface to monitor and change
|
||||
the state of dual role usb ports. The name here
|
||||
refers to the name mentioned in the
|
||||
dual_role_phy_desc that is passed while registering
|
||||
the dual_role_phy_intstance through
|
||||
devm_dual_role_instance_register.
|
||||
|
||||
What: /sys/class/dual_role_usb/.../supported_modes
|
||||
Date: June 2015
|
||||
Contact: Badhri Jagan Sridharan<badhri@google.com>
|
||||
Description:
|
||||
This is a static node, once initialized this
|
||||
is not expected to change during runtime. "dfp"
|
||||
refers to "downstream facing port" i.e. port can
|
||||
only act as host. "ufp" refers to "upstream
|
||||
facing port" i.e. port can only act as device.
|
||||
"dfp ufp" refers to "dual role port" i.e. the port
|
||||
can either be a host port or a device port.
|
||||
|
||||
What: /sys/class/dual_role_usb/.../mode
|
||||
Date: June 2015
|
||||
Contact: Badhri Jagan Sridharan<badhri@google.com>
|
||||
Description:
|
||||
The mode node refers to the current mode in which the
|
||||
port is operating. "dfp" for host ports. "ufp" for device
|
||||
ports and "none" when cable is not connected.
|
||||
|
||||
On devices where the USB mode is software-controllable,
|
||||
userspace can change the mode by writing "dfp" or "ufp".
|
||||
On devices where the USB mode is fixed in hardware,
|
||||
this attribute is read-only.
|
||||
|
||||
What: /sys/class/dual_role_usb/.../power_role
|
||||
Date: June 2015
|
||||
Contact: Badhri Jagan Sridharan<badhri@google.com>
|
||||
Description:
|
||||
The power_role node mentions whether the port
|
||||
is "sink"ing or "source"ing power. "none" if
|
||||
they are not connected.
|
||||
|
||||
On devices implementing USB Power Delivery,
|
||||
userspace can control the power role by writing "sink" or
|
||||
"source". On devices without USB-PD, this attribute is
|
||||
read-only.
|
||||
|
||||
What: /sys/class/dual_role_usb/.../data_role
|
||||
Date: June 2015
|
||||
Contact: Badhri Jagan Sridharan<badhri@google.com>
|
||||
Description:
|
||||
The data_role node mentions whether the port
|
||||
is acting as "host" or "device" for USB data connection.
|
||||
"none" if there is no active data link.
|
||||
|
||||
On devices implementing USB Power Delivery, userspace
|
||||
can control the data role by writing "host" or "device".
|
||||
On devices without USB-PD, this attribute is read-only
|
||||
|
||||
What: /sys/class/dual_role_usb/.../powers_vconn
|
||||
Date: June 2015
|
||||
Contact: Badhri Jagan Sridharan<badhri@google.com>
|
||||
Description:
|
||||
The powers_vconn node mentions whether the port
|
||||
is supplying power for VCONN pin.
|
||||
|
||||
On devices with software control of VCONN,
|
||||
userspace can disable the power supply to VCONN by writing "n",
|
||||
or enable the power supply by writing "y".
|
||||
16
Documentation/ABI/testing/sysfs-kernel-wakeup_reasons
Normal file
16
Documentation/ABI/testing/sysfs-kernel-wakeup_reasons
Normal file
@@ -0,0 +1,16 @@
|
||||
What: /sys/kernel/wakeup_reasons/last_resume_reason
|
||||
Date: February 2014
|
||||
Contact: Ruchi Kandoi <kandoiruchi@google.com>
|
||||
Description:
|
||||
The /sys/kernel/wakeup_reasons/last_resume_reason is
|
||||
used to report wakeup reasons after system exited suspend.
|
||||
|
||||
What: /sys/kernel/wakeup_reasons/last_suspend_time
|
||||
Date: March 2015
|
||||
Contact: jinqian <jinqian@google.com>
|
||||
Description:
|
||||
The /sys/kernel/wakeup_reasons/last_suspend_time is
|
||||
used to report time spent in last suspend cycle. It contains
|
||||
two numbers (in seconds) separated by space. First number is
|
||||
the time spent in suspend and resume processes. Second number
|
||||
is the time spent in sleep state.
|
||||
121
Documentation/android.txt
Normal file
121
Documentation/android.txt
Normal file
@@ -0,0 +1,121 @@
|
||||
=============
|
||||
A N D R O I D
|
||||
=============
|
||||
|
||||
Copyright (C) 2009 Google, Inc.
|
||||
Written by Mike Chan <mike@android.com>
|
||||
|
||||
CONTENTS:
|
||||
---------
|
||||
|
||||
1. Android
|
||||
1.1 Required enabled config options
|
||||
1.2 Required disabled config options
|
||||
1.3 Recommended enabled config options
|
||||
2. Contact
|
||||
|
||||
|
||||
1. Android
|
||||
==========
|
||||
|
||||
Android (www.android.com) is an open source operating system for mobile devices.
|
||||
This document describes configurations needed to run the Android framework on
|
||||
top of the Linux kernel.
|
||||
|
||||
To see a working defconfig look at msm_defconfig or goldfish_defconfig
|
||||
which can be found at http://android.git.kernel.org in kernel/common.git
|
||||
and kernel/msm.git
|
||||
|
||||
|
||||
1.1 Required enabled config options
|
||||
-----------------------------------
|
||||
After building a standard defconfig, ensure that these options are enabled in
|
||||
your .config or defconfig if they are not already. Based off the msm_defconfig.
|
||||
You should keep the rest of the default options enabled in the defconfig
|
||||
unless you know what you are doing.
|
||||
|
||||
ANDROID_PARANOID_NETWORK
|
||||
ASHMEM
|
||||
CONFIG_FB_MODE_HELPERS
|
||||
CONFIG_FONT_8x16
|
||||
CONFIG_FONT_8x8
|
||||
CONFIG_YAFFS_SHORT_NAMES_IN_RAM
|
||||
DAB
|
||||
EARLYSUSPEND
|
||||
FB
|
||||
FB_CFB_COPYAREA
|
||||
FB_CFB_FILLRECT
|
||||
FB_CFB_IMAGEBLIT
|
||||
FB_DEFERRED_IO
|
||||
FB_TILEBLITTING
|
||||
HIGH_RES_TIMERS
|
||||
INOTIFY
|
||||
INOTIFY_USER
|
||||
INPUT_EVDEV
|
||||
INPUT_GPIO
|
||||
INPUT_MISC
|
||||
LEDS_CLASS
|
||||
LEDS_GPIO
|
||||
LOCK_KERNEL
|
||||
LkOGGER
|
||||
LOW_MEMORY_KILLER
|
||||
MISC_DEVICES
|
||||
NEW_LEDS
|
||||
NO_HZ
|
||||
POWER_SUPPLY
|
||||
PREEMPT
|
||||
RAMFS
|
||||
RTC_CLASS
|
||||
RTC_LIB
|
||||
SWITCH
|
||||
SWITCH_GPIO
|
||||
TMPFS
|
||||
UID_STAT
|
||||
UID16
|
||||
USB_FUNCTION
|
||||
USB_FUNCTION_ADB
|
||||
USER_WAKELOCK
|
||||
VIDEO_OUTPUT_CONTROL
|
||||
WAKELOCK
|
||||
YAFFS_AUTO_YAFFS2
|
||||
YAFFS_FS
|
||||
YAFFS_YAFFS1
|
||||
YAFFS_YAFFS2
|
||||
|
||||
|
||||
1.2 Required disabled config options
|
||||
------------------------------------
|
||||
CONFIG_YAFFS_DISABLE_LAZY_LOAD
|
||||
DNOTIFY
|
||||
|
||||
|
||||
1.3 Recommended enabled config options
|
||||
------------------------------
|
||||
ANDROID_PMEM
|
||||
PSTORE_CONSOLE
|
||||
PSTORE_RAM
|
||||
SCHEDSTATS
|
||||
DEBUG_PREEMPT
|
||||
DEBUG_MUTEXES
|
||||
DEBUG_SPINLOCK_SLEEP
|
||||
DEBUG_INFO
|
||||
FRAME_POINTER
|
||||
CPU_FREQ
|
||||
CPU_FREQ_TABLE
|
||||
CPU_FREQ_DEFAULT_GOV_ONDEMAND
|
||||
CPU_FREQ_GOV_ONDEMAND
|
||||
CRC_CCITT
|
||||
EMBEDDED
|
||||
INPUT_TOUCHSCREEN
|
||||
I2C
|
||||
I2C_BOARDINFO
|
||||
LOG_BUF_SHIFT=17
|
||||
SERIAL_CORE
|
||||
SERIAL_CORE_CONSOLE
|
||||
|
||||
|
||||
2. Contact
|
||||
==========
|
||||
website: http://android.git.kernel.org
|
||||
|
||||
mailing-lists: android-kernel@googlegroups.com
|
||||
@@ -30,3 +30,9 @@ switching-sched.txt
|
||||
- Switching I/O schedulers at runtime
|
||||
writeback_cache_control.txt
|
||||
- Control of volatile write back caches
|
||||
mmc-max-speed.txt
|
||||
- eMMC layer speed simulation, related to /sys/block/mmcblk*/
|
||||
attributes:
|
||||
max_read_speed
|
||||
max_write_speed
|
||||
cache_size
|
||||
|
||||
38
Documentation/block/mmc-max-speed.txt
Normal file
38
Documentation/block/mmc-max-speed.txt
Normal file
@@ -0,0 +1,38 @@
|
||||
eMMC Block layer simulation speed controls in /sys/block/mmcblk*/
|
||||
===============================================
|
||||
|
||||
Turned on with CONFIG_MMC_SIMULATE_MAX_SPEED which enables MMC device speed
|
||||
limiting. Used to test and simulate the behavior of the system when
|
||||
confronted with a slow MMC.
|
||||
|
||||
Enables max_read_speed, max_write_speed and cache_size attributes and module
|
||||
default parameters to control the write or read maximum KB/second speed
|
||||
behaviors.
|
||||
|
||||
NB: There is room for improving the algorithm for aspects tied directly to
|
||||
eMMC specific behavior. For instance, wear leveling and stalls from an
|
||||
exhausted erase pool. We would expect that if there was a need to provide
|
||||
similar speed simulation controls to other types of block devices, aspects of
|
||||
their behavior are modelled separately (e.g. head seek times, heat assist,
|
||||
shingling and rotational latency).
|
||||
|
||||
/sys/block/mmcblk0/max_read_speed:
|
||||
|
||||
Number of KB/second reads allowed to the block device. Used to test and
|
||||
simulate the behavior of the system when confronted with a slow reading MMC.
|
||||
Set to 0 or "off" to place no speed limit.
|
||||
|
||||
/sys/block/mmcblk0/max_write_speed:
|
||||
|
||||
Number of KB/second writes allowed to the block device. Used to test and
|
||||
simulate the behavior of the system when confronted with a slow writing MMC.
|
||||
Set to 0 or "off" to place no speed limit.
|
||||
|
||||
/sys/block/mmcblk0/cache_size:
|
||||
|
||||
Number of MB of high speed memory or high speed SLC cache expected on the
|
||||
eMMC device being simulated. Used to help simulate the write-back behavior
|
||||
more accurately. The assumption is the cache has no delay, but draws down
|
||||
in the background to the MLC/TLC primary store at the max_write_speed rate.
|
||||
Any write speed delays will show up when the cache is full, or when an I/O
|
||||
request to flush is issued.
|
||||
@@ -28,6 +28,7 @@ Contents:
|
||||
2.3 Userspace
|
||||
2.4 Ondemand
|
||||
2.5 Conservative
|
||||
2.6 Interactive
|
||||
|
||||
3. The Governor Interface in the CPUfreq Core
|
||||
|
||||
@@ -218,6 +219,91 @@ a decision on when to decrease the frequency while running in any
|
||||
speed. Load for frequency increase is still evaluated every
|
||||
sampling rate.
|
||||
|
||||
2.6 Interactive
|
||||
---------------
|
||||
|
||||
The CPUfreq governor "interactive" is designed for latency-sensitive,
|
||||
interactive workloads. This governor sets the CPU speed depending on
|
||||
usage, similar to "ondemand" and "conservative" governors, but with a
|
||||
different set of configurable behaviors.
|
||||
|
||||
The tunable values for this governor are:
|
||||
|
||||
above_hispeed_delay: When speed is at or above hispeed_freq, wait for
|
||||
this long before raising speed in response to continued high load.
|
||||
The format is a single delay value, optionally followed by pairs of
|
||||
CPU speeds and the delay to use at or above those speeds. Colons can
|
||||
be used between the speeds and associated delays for readability. For
|
||||
example:
|
||||
|
||||
80000 1300000:200000 1500000:40000
|
||||
|
||||
uses delay 80000 uS until CPU speed 1.3 GHz, at which speed delay
|
||||
200000 uS is used until speed 1.5 GHz, at which speed (and above)
|
||||
delay 40000 uS is used. If speeds are specified these must appear in
|
||||
ascending order. Default is 20000 uS.
|
||||
|
||||
boost: If non-zero, immediately boost speed of all CPUs to at least
|
||||
hispeed_freq until zero is written to this attribute. If zero, allow
|
||||
CPU speeds to drop below hispeed_freq according to load as usual.
|
||||
Default is zero.
|
||||
|
||||
boostpulse: On each write, immediately boost speed of all CPUs to
|
||||
hispeed_freq for at least the period of time specified by
|
||||
boostpulse_duration, after which speeds are allowed to drop below
|
||||
hispeed_freq according to load as usual. Its a write-only file.
|
||||
|
||||
boostpulse_duration: Length of time to hold CPU speed at hispeed_freq
|
||||
on a write to boostpulse, before allowing speed to drop according to
|
||||
load as usual. Default is 80000 uS.
|
||||
|
||||
go_hispeed_load: The CPU load at which to ramp to hispeed_freq.
|
||||
Default is 99%.
|
||||
|
||||
hispeed_freq: An intermediate "high speed" at which to initially ramp
|
||||
when CPU load hits the value specified in go_hispeed_load. If load
|
||||
stays high for the amount of time specified in above_hispeed_delay,
|
||||
then speed may be bumped higher. Default is the maximum speed allowed
|
||||
by the policy at governor initialization time.
|
||||
|
||||
io_is_busy: If set, the governor accounts IO time as CPU busy time.
|
||||
|
||||
min_sample_time: The minimum amount of time to spend at the current
|
||||
frequency before ramping down. Default is 80000 uS.
|
||||
|
||||
target_loads: CPU load values used to adjust speed to influence the
|
||||
current CPU load toward that value. In general, the lower the target
|
||||
load, the more often the governor will raise CPU speeds to bring load
|
||||
below the target. The format is a single target load, optionally
|
||||
followed by pairs of CPU speeds and CPU loads to target at or above
|
||||
those speeds. Colons can be used between the speeds and associated
|
||||
target loads for readability. For example:
|
||||
|
||||
85 1000000:90 1700000:99
|
||||
|
||||
targets CPU load 85% below speed 1GHz, 90% at or above 1GHz, until
|
||||
1.7GHz and above, at which load 99% is targeted. If speeds are
|
||||
specified these must appear in ascending order. Higher target load
|
||||
values are typically specified for higher speeds, that is, target load
|
||||
values also usually appear in an ascending order. The default is
|
||||
target load 90% for all speeds.
|
||||
|
||||
timer_rate: Sample rate for reevaluating CPU load when the CPU is not
|
||||
idle. A deferrable timer is used, such that the CPU will not be woken
|
||||
from idle to service this timer until something else needs to run.
|
||||
(The maximum time to allow deferring this timer when not running at
|
||||
minimum speed is configurable via timer_slack.) Default is 20000 uS.
|
||||
|
||||
timer_slack: Maximum additional time to defer handling the governor
|
||||
sampling timer beyond timer_rate when running at speeds above the
|
||||
minimum. For platforms that consume additional power at idle when
|
||||
CPUs are running at speeds greater than minimum, this places an upper
|
||||
bound on how long the timer will be deferred prior to re-evaluating
|
||||
load and dropping speed. For example, if timer_rate is 20000uS and
|
||||
timer_slack is 10000uS then timers will be deferred for up to 30msec
|
||||
when not at lowest speed. A value of -1 means defer timers
|
||||
indefinitely at all speeds. Default is 80000 uS.
|
||||
|
||||
3. The Governor Interface in the CPUfreq Core
|
||||
=============================================
|
||||
|
||||
|
||||
42
Documentation/device-mapper/boot.txt
Normal file
42
Documentation/device-mapper/boot.txt
Normal file
@@ -0,0 +1,42 @@
|
||||
Boot time creation of mapped devices
|
||||
===================================
|
||||
|
||||
It is possible to configure a device mapper device to act as the root
|
||||
device for your system in two ways.
|
||||
|
||||
The first is to build an initial ramdisk which boots to a minimal
|
||||
userspace which configures the device, then pivot_root(8) in to it.
|
||||
|
||||
For simple device mapper configurations, it is possible to boot directly
|
||||
using the following kernel command line:
|
||||
|
||||
dm="<name> <uuid> <ro>,table line 1,...,table line n"
|
||||
|
||||
name = the name to associate with the device
|
||||
after boot, udev, if used, will use that name to label
|
||||
the device node.
|
||||
uuid = may be 'none' or the UUID desired for the device.
|
||||
ro = may be "ro" or "rw". If "ro", the device and device table will be
|
||||
marked read-only.
|
||||
|
||||
Each table line may be as normal when using the dmsetup tool except for
|
||||
two variations:
|
||||
1. Any use of commas will be interpreted as a newline
|
||||
2. Quotation marks cannot be escaped and cannot be used without
|
||||
terminating the dm= argument.
|
||||
|
||||
Unless renamed by udev, the device node created will be dm-0 as the
|
||||
first minor number for the device-mapper is used during early creation.
|
||||
|
||||
Example
|
||||
=======
|
||||
|
||||
- Booting to a linear array made up of user-mode linux block devices:
|
||||
|
||||
dm="lroot none 0, 0 4096 linear 98:16 0, 4096 4096 linear 98:32 0" \
|
||||
root=/dev/dm-0
|
||||
|
||||
Will boot to a rw dm-linear target of 8192 sectors split across two
|
||||
block devices identified by their major:minor numbers. After boot, udev
|
||||
will rename this target to /dev/mapper/lroot (depending on the rules).
|
||||
No uuid was assigned.
|
||||
@@ -77,7 +77,7 @@ Examples:
|
||||
clks: ccm@53f80000{
|
||||
compatible = "fsl,imx31-ccm";
|
||||
reg = <0x53f80000 0x4000>;
|
||||
interrupts = <0 31 0x04 0 53 0x04>;
|
||||
interrupts = <31>, <53>;
|
||||
#clock-cells = <1>;
|
||||
};
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ Required properties:
|
||||
defined below.
|
||||
|
||||
Optional regulator properties:
|
||||
- ti,regulator-step-size-25mv : This is applicable for buck[1,2,6], set this
|
||||
- ti,regulator-step-size-25mv : This is applicable for buck[1-6], set this
|
||||
if the regulator is factory set with a 25mv
|
||||
step voltage mapping.
|
||||
- ti,regulator-decay : This is applicable for buck[1-6], set this if
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
Memory bandwidth and frequency state tracking
|
||||
|
||||
Required properties:
|
||||
- compatible : should be:
|
||||
"memory-state-time"
|
||||
- freq-tbl: Should contain entries with each frequency in Hz.
|
||||
- bw-buckets: Should contain upper-bound limits for each bandwidth bucket in Mbps.
|
||||
Must match the framework power_profile.xml for the device.
|
||||
@@ -392,6 +392,8 @@ is not associated with a file:
|
||||
[stack] = the stack of the main process
|
||||
[vdso] = the "virtual dynamic shared object",
|
||||
the kernel system call handler
|
||||
[anon:<name>] = an anonymous mapping that has been
|
||||
named by userspace
|
||||
|
||||
or if empty, the mapping is anonymous.
|
||||
|
||||
@@ -419,6 +421,7 @@ KernelPageSize: 4 kB
|
||||
MMUPageSize: 4 kB
|
||||
Locked: 0 kB
|
||||
VmFlags: rd ex mr mw me dw
|
||||
Name: name from userspace
|
||||
|
||||
the first of these lines shows the same information as is displayed for the
|
||||
mapping in /proc/PID/maps. The remaining lines show the size of the mapping
|
||||
@@ -486,6 +489,9 @@ Note that there is no guarantee that every flag and associated mnemonic will
|
||||
be present in all further kernel releases. Things get changed, the flags may
|
||||
be vanished or the reverse -- new added.
|
||||
|
||||
The "Name" field will only be present on a mapping that has been named by
|
||||
userspace, and will show the name passed in by userspace.
|
||||
|
||||
This file is only present if the CONFIG_MMU kernel configuration option is
|
||||
enabled.
|
||||
|
||||
|
||||
@@ -87,6 +87,7 @@ parameter is applicable:
|
||||
BLACKFIN Blackfin architecture is enabled.
|
||||
CLK Common clock infrastructure is enabled.
|
||||
CMA Contiguous Memory Area support is enabled.
|
||||
DM Device mapper support is enabled.
|
||||
DRM Direct Rendering Management support is enabled.
|
||||
DYNAMIC_DEBUG Build in debug messages and enable them at runtime
|
||||
EDD BIOS Enhanced Disk Drive Services (EDD) is enabled
|
||||
@@ -1025,6 +1026,11 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
|
||||
|
||||
dis_ucode_ldr [X86] Disable the microcode loader.
|
||||
|
||||
dm= [DM] Allows early creation of a device-mapper device.
|
||||
See Documentation/device-mapper/boot.txt.
|
||||
|
||||
dmasound= [HW,OSS] Sound subsystem buff
|
||||
|
||||
dma_debug=off If the kernel is compiled with DMA_API_DEBUG support,
|
||||
this option disables the debugging code at boot.
|
||||
|
||||
@@ -1391,6 +1397,10 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
|
||||
When zero, profiling data is discarded and associated
|
||||
debugfs files are removed at module unload time.
|
||||
|
||||
goldfish [X86] Enable the goldfish android emulator platform.
|
||||
Don't use this when you are not running on the
|
||||
android emulator
|
||||
|
||||
gpt [EFI] Forces disk with valid GPT signature but
|
||||
invalid Protective MBR to be treated as GPT. If the
|
||||
primary GPT is corrupted, it enables the backup/alternate
|
||||
@@ -3998,10 +4008,11 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
|
||||
it if 0 is given (See Documentation/cgroup-v1/memory.txt)
|
||||
|
||||
swiotlb= [ARM,IA-64,PPC,MIPS,X86]
|
||||
Format: { <int> | force }
|
||||
Format: { <int> | force | noforce }
|
||||
<int> -- Number of I/O TLB slabs
|
||||
force -- force using of bounce buffers even if they
|
||||
wouldn't be automatically used by the kernel
|
||||
noforce -- Never use bounce buffers (for debugging)
|
||||
|
||||
switches= [HW,M68k]
|
||||
|
||||
|
||||
@@ -211,7 +211,13 @@ Colorspace sRGB (V4L2_COLORSPACE_SRGB)
|
||||
The :ref:`srgb` standard defines the colorspace used by most webcams
|
||||
and computer graphics. The default transfer function is
|
||||
``V4L2_XFER_FUNC_SRGB``. The default Y'CbCr encoding is
|
||||
``V4L2_YCBCR_ENC_601``. The default Y'CbCr quantization is full range.
|
||||
``V4L2_YCBCR_ENC_601``. The default Y'CbCr quantization is limited range.
|
||||
|
||||
Note that the :ref:`sycc` standard specifies full range quantization,
|
||||
however all current capture hardware supported by the kernel convert
|
||||
R'G'B' to limited range Y'CbCr. So choosing full range as the default
|
||||
would break how applications interpret the quantization range.
|
||||
|
||||
The chromaticities of the primary colors and the white reference are:
|
||||
|
||||
|
||||
@@ -276,7 +282,7 @@ the following ``V4L2_YCBCR_ENC_601`` encoding as defined by :ref:`sycc`:
|
||||
|
||||
Y' is clamped to the range [0…1] and Cb and Cr are clamped to the range
|
||||
[-0.5…0.5]. This transform is identical to one defined in SMPTE
|
||||
170M/BT.601. The Y'CbCr quantization is full range.
|
||||
170M/BT.601. The Y'CbCr quantization is limited range.
|
||||
|
||||
|
||||
.. _col-adobergb:
|
||||
@@ -288,10 +294,15 @@ The :ref:`adobergb` standard defines the colorspace used by computer
|
||||
graphics that use the AdobeRGB colorspace. This is also known as the
|
||||
:ref:`oprgb` standard. The default transfer function is
|
||||
``V4L2_XFER_FUNC_ADOBERGB``. The default Y'CbCr encoding is
|
||||
``V4L2_YCBCR_ENC_601``. The default Y'CbCr quantization is full
|
||||
range. The chromaticities of the primary colors and the white reference
|
||||
are:
|
||||
``V4L2_YCBCR_ENC_601``. The default Y'CbCr quantization is limited
|
||||
range.
|
||||
|
||||
Note that the :ref:`oprgb` standard specifies full range quantization,
|
||||
however all current capture hardware supported by the kernel convert
|
||||
R'G'B' to limited range Y'CbCr. So choosing full range as the default
|
||||
would break how applications interpret the quantization range.
|
||||
|
||||
The chromaticities of the primary colors and the white reference are:
|
||||
|
||||
|
||||
.. tabularcolumns:: |p{4.4cm}|p{4.4cm}|p{8.7cm}|
|
||||
@@ -344,7 +355,7 @@ the following ``V4L2_YCBCR_ENC_601`` encoding:
|
||||
|
||||
Y' is clamped to the range [0…1] and Cb and Cr are clamped to the range
|
||||
[-0.5…0.5]. This transform is identical to one defined in SMPTE
|
||||
170M/BT.601. The Y'CbCr quantization is full range.
|
||||
170M/BT.601. The Y'CbCr quantization is limited range.
|
||||
|
||||
|
||||
.. _col-bt2020:
|
||||
|
||||
@@ -603,6 +603,16 @@ tcp_fastopen - INTEGER
|
||||
Note that that additional client or server features are only
|
||||
effective if the basic support (0x1 and 0x2) are enabled respectively.
|
||||
|
||||
tcp_fwmark_accept - BOOLEAN
|
||||
If set, incoming connections to listening sockets that do not have a
|
||||
socket mark will set the mark of the accepting socket to the fwmark of
|
||||
the incoming SYN packet. This will cause all packets on that connection
|
||||
(starting from the first SYNACK) to be sent with that fwmark. The
|
||||
listening socket's mark is unchanged. Listening sockets that already
|
||||
have a fwmark set via setsockopt(SOL_SOCKET, SO_MARK, ...) are
|
||||
unaffected.
|
||||
Default: 0
|
||||
|
||||
tcp_syn_retries - INTEGER
|
||||
Number of times initial SYNs for an active TCP connection attempt
|
||||
will be retransmitted. Should not be higher than 127. Default value
|
||||
|
||||
362
Documentation/scheduler/sched-energy.txt
Normal file
362
Documentation/scheduler/sched-energy.txt
Normal file
@@ -0,0 +1,362 @@
|
||||
Energy cost model for energy-aware scheduling (EXPERIMENTAL)
|
||||
|
||||
Introduction
|
||||
=============
|
||||
|
||||
The basic energy model uses platform energy data stored in sched_group_energy
|
||||
data structures attached to the sched_groups in the sched_domain hierarchy. The
|
||||
energy cost model offers two functions that can be used to guide scheduling
|
||||
decisions:
|
||||
|
||||
1. static unsigned int sched_group_energy(struct energy_env *eenv)
|
||||
2. static int energy_diff(struct energy_env *eenv)
|
||||
|
||||
sched_group_energy() estimates the energy consumed by all cpus in a specific
|
||||
sched_group including any shared resources owned exclusively by this group of
|
||||
cpus. Resources shared with other cpus are excluded (e.g. later level caches).
|
||||
|
||||
energy_diff() estimates the total energy impact of a utilization change. That
|
||||
is, adding, removing, or migrating utilization (tasks).
|
||||
|
||||
Both functions use a struct energy_env to specify the scenario to be evaluated:
|
||||
|
||||
struct energy_env {
|
||||
struct sched_group *sg_top;
|
||||
struct sched_group *sg_cap;
|
||||
int cap_idx;
|
||||
int util_delta;
|
||||
int src_cpu;
|
||||
int dst_cpu;
|
||||
int energy;
|
||||
};
|
||||
|
||||
sg_top: sched_group to be evaluated. Not used by energy_diff().
|
||||
|
||||
sg_cap: sched_group covering the cpus in the same frequency domain. Set by
|
||||
sched_group_energy().
|
||||
|
||||
cap_idx: Capacity state to be used for energy calculations. Set by
|
||||
find_new_capacity().
|
||||
|
||||
util_delta: Amount of utilization to be added, removed, or migrated.
|
||||
|
||||
src_cpu: Source cpu from where 'util_delta' utilization is removed. Should be
|
||||
-1 if no source (e.g. task wake-up).
|
||||
|
||||
dst_cpu: Destination cpu where 'util_delta' utilization is added. Should be -1
|
||||
if utilization is removed (e.g. terminating tasks).
|
||||
|
||||
energy: Result of sched_group_energy().
|
||||
|
||||
The metric used to represent utilization is the actual per-entity running time
|
||||
averaged over time using a geometric series. Very similar to the existing
|
||||
per-entity load-tracking, but _not_ scaled by task priority and capped by the
|
||||
capacity of the cpu. The latter property does mean that utilization may
|
||||
underestimate the compute requirements for task on fully/over utilized cpus.
|
||||
The greatest potential for energy savings without affecting performance too much
|
||||
is scenarios where the system isn't fully utilized. If the system is deemed
|
||||
fully utilized load-balancing should be done with task load (includes task
|
||||
priority) instead in the interest of fairness and performance.
|
||||
|
||||
|
||||
Background and Terminology
|
||||
===========================
|
||||
|
||||
To make it clear from the start:
|
||||
|
||||
energy = [joule] (resource like a battery on powered devices)
|
||||
power = energy/time = [joule/second] = [watt]
|
||||
|
||||
The goal of energy-aware scheduling is to minimize energy, while still getting
|
||||
the job done. That is, we want to maximize:
|
||||
|
||||
performance [inst/s]
|
||||
--------------------
|
||||
power [W]
|
||||
|
||||
which is equivalent to minimizing:
|
||||
|
||||
energy [J]
|
||||
-----------
|
||||
instruction
|
||||
|
||||
while still getting 'good' performance. It is essentially an alternative
|
||||
optimization objective to the current performance-only objective for the
|
||||
scheduler. This alternative considers two objectives: energy-efficiency and
|
||||
performance. Hence, there needs to be a user controllable knob to switch the
|
||||
objective. Since it is early days, this is currently a sched_feature
|
||||
(ENERGY_AWARE).
|
||||
|
||||
The idea behind introducing an energy cost model is to allow the scheduler to
|
||||
evaluate the implications of its decisions rather than applying energy-saving
|
||||
techniques blindly that may only have positive effects on some platforms. At
|
||||
the same time, the energy cost model must be as simple as possible to minimize
|
||||
the scheduler latency impact.
|
||||
|
||||
Platform topology
|
||||
------------------
|
||||
|
||||
The system topology (cpus, caches, and NUMA information, not peripherals) is
|
||||
represented in the scheduler by the sched_domain hierarchy which has
|
||||
sched_groups attached at each level that covers one or more cpus (see
|
||||
sched-domains.txt for more details). To add energy awareness to the scheduler
|
||||
we need to consider power and frequency domains.
|
||||
|
||||
Power domain:
|
||||
|
||||
A power domain is a part of the system that can be powered on/off
|
||||
independently. Power domains are typically organized in a hierarchy where you
|
||||
may be able to power down just a cpu or a group of cpus along with any
|
||||
associated resources (e.g. shared caches). Powering up a cpu means that all
|
||||
power domains it is a part of in the hierarchy must be powered up. Hence, it is
|
||||
more expensive to power up the first cpu that belongs to a higher level power
|
||||
domain than powering up additional cpus in the same high level domain. Two
|
||||
level power domain hierarchy example:
|
||||
|
||||
Power source
|
||||
+-------------------------------+----...
|
||||
per group PD G G
|
||||
| +----------+ |
|
||||
+--------+-------| Shared | (other groups)
|
||||
per-cpu PD G G | resource |
|
||||
| | +----------+
|
||||
+-------+ +-------+
|
||||
| CPU 0 | | CPU 1 |
|
||||
+-------+ +-------+
|
||||
|
||||
Frequency domain:
|
||||
|
||||
Frequency domains (P-states) typically cover the same group of cpus as one of
|
||||
the power domain levels. That is, there might be several smaller power domains
|
||||
sharing the same frequency (P-state) or there might be a power domain spanning
|
||||
multiple frequency domains.
|
||||
|
||||
From a scheduling point of view there is no need to know the actual frequencies
|
||||
[Hz]. All the scheduler cares about is the compute capacity available at the
|
||||
current state (P-state) the cpu is in and any other available states. For that
|
||||
reason, and to also factor in any cpu micro-architecture differences, compute
|
||||
capacity scaling states are called 'capacity states' in this document. For SMP
|
||||
systems this is equivalent to P-states. For mixed micro-architecture systems
|
||||
(like ARM big.LITTLE) it is P-states scaled according to the micro-architecture
|
||||
performance relative to the other cpus in the system.
|
||||
|
||||
Energy modelling:
|
||||
------------------
|
||||
|
||||
Due to the hierarchical nature of the power domains, the most obvious way to
|
||||
model energy costs is therefore to associate power and energy costs with
|
||||
domains (groups of cpus). Energy costs of shared resources are associated with
|
||||
the group of cpus that share the resources, only the cost of powering the
|
||||
cpu itself and any private resources (e.g. private L1 caches) is associated
|
||||
with the per-cpu groups (lowest level).
|
||||
|
||||
For example, for an SMP system with per-cpu power domains and a cluster level
|
||||
(group of cpus) power domain we get the overall energy costs to be:
|
||||
|
||||
energy = energy_cluster + n * energy_cpu
|
||||
|
||||
where 'n' is the number of cpus powered up and energy_cluster is the cost paid
|
||||
as soon as any cpu in the cluster is powered up.
|
||||
|
||||
The power and frequency domains can naturally be mapped onto the existing
|
||||
sched_domain hierarchy and sched_groups by adding the necessary data to the
|
||||
existing data structures.
|
||||
|
||||
The energy model considers energy consumption from two contributors (shown in
|
||||
the illustration below):
|
||||
|
||||
1. Busy energy: Energy consumed while a cpu and the higher level groups that it
|
||||
belongs to are busy running tasks. Busy energy is associated with the state of
|
||||
the cpu, not an event. The time the cpu spends in this state varies. Thus, the
|
||||
most obvious platform parameter for this contribution is busy power
|
||||
(energy/time).
|
||||
|
||||
2. Idle energy: Energy consumed while a cpu and higher level groups that it
|
||||
belongs to are idle (in a C-state). Like busy energy, idle energy is associated
|
||||
with the state of the cpu. Thus, the platform parameter for this contribution
|
||||
is idle power (energy/time).
|
||||
|
||||
Energy consumed during transitions from an idle-state (C-state) to a busy state
|
||||
(P-state) or going the other way is ignored by the model to simplify the energy
|
||||
model calculations.
|
||||
|
||||
|
||||
Power
|
||||
^
|
||||
| busy->idle idle->busy
|
||||
| transition transition
|
||||
|
|
||||
| _ __
|
||||
| / \ / \__________________
|
||||
|______________/ \ /
|
||||
| \ /
|
||||
| Busy \ Idle / Busy
|
||||
| low P-state \____________/ high P-state
|
||||
|
|
||||
+------------------------------------------------------------> time
|
||||
|
||||
Busy |--------------| |-----------------|
|
||||
|
||||
Wakeup |------| |------|
|
||||
|
||||
Idle |------------|
|
||||
|
||||
|
||||
The basic algorithm
|
||||
====================
|
||||
|
||||
The basic idea is to determine the total energy impact when utilization is
|
||||
added or removed by estimating the impact at each level in the sched_domain
|
||||
hierarchy starting from the bottom (sched_group contains just a single cpu).
|
||||
The energy cost comes from busy time (sched_group is awake because one or more
|
||||
cpus are busy) and idle time (in an idle-state). Energy model numbers account
|
||||
for energy costs associated with all cpus in the sched_group as a group.
|
||||
|
||||
for_each_domain(cpu, sd) {
|
||||
sg = sched_group_of(cpu)
|
||||
energy_before = curr_util(sg) * busy_power(sg)
|
||||
+ (1-curr_util(sg)) * idle_power(sg)
|
||||
energy_after = new_util(sg) * busy_power(sg)
|
||||
+ (1-new_util(sg)) * idle_power(sg)
|
||||
energy_diff += energy_before - energy_after
|
||||
|
||||
}
|
||||
|
||||
return energy_diff
|
||||
|
||||
{curr, new}_util: The cpu utilization at the lowest level and the overall
|
||||
non-idle time for the entire group for higher levels. Utilization is in the
|
||||
range 0.0 to 1.0 in the pseudo-code.
|
||||
|
||||
busy_power: The power consumption of the sched_group.
|
||||
|
||||
idle_power: The power consumption of the sched_group when idle.
|
||||
|
||||
Note: It is a fundamental assumption that the utilization is (roughly) scale
|
||||
invariant. Task utilization tracking factors in any frequency scaling and
|
||||
performance scaling differences due to difference cpu microarchitectures such
|
||||
that task utilization can be used across the entire system.
|
||||
|
||||
|
||||
Platform energy data
|
||||
=====================
|
||||
|
||||
struct sched_group_energy can be attached to sched_groups in the sched_domain
|
||||
hierarchy and has the following members:
|
||||
|
||||
cap_states:
|
||||
List of struct capacity_state representing the supported capacity states
|
||||
(P-states). struct capacity_state has two members: cap and power, which
|
||||
represents the compute capacity and the busy_power of the state. The
|
||||
list must be ordered by capacity low->high.
|
||||
|
||||
nr_cap_states:
|
||||
Number of capacity states in cap_states list.
|
||||
|
||||
idle_states:
|
||||
List of struct idle_state containing idle_state power cost for each
|
||||
idle-state supported by the system orderd by shallowest state first.
|
||||
All states must be included at all level in the hierarchy, i.e. a
|
||||
sched_group spanning just a single cpu must also include coupled
|
||||
idle-states (cluster states). In addition to the cpuidle idle-states,
|
||||
the list must also contain an entry for the idling using the arch
|
||||
default idle (arch_idle_cpu()). Despite this state may not be a true
|
||||
hardware idle-state it is considered the shallowest idle-state in the
|
||||
energy model and must be the first entry. cpus may enter this state
|
||||
(possibly 'active idling') if cpuidle decides not enter a cpuidle
|
||||
idle-state. Default idle may not be used when cpuidle is enabled.
|
||||
In this case, it should just be a copy of the first cpuidle idle-state.
|
||||
|
||||
nr_idle_states:
|
||||
Number of idle states in idle_states list.
|
||||
|
||||
There are no unit requirements for the energy cost data. Data can be normalized
|
||||
with any reference, however, the normalization must be consistent across all
|
||||
energy cost data. That is, one bogo-joule/watt must be the same quantity for
|
||||
data, but we don't care what it is.
|
||||
|
||||
A recipe for platform characterization
|
||||
=======================================
|
||||
|
||||
Obtaining the actual model data for a particular platform requires some way of
|
||||
measuring power/energy. There isn't a tool to help with this (yet). This
|
||||
section provides a recipe for use as reference. It covers the steps used to
|
||||
characterize the ARM TC2 development platform. This sort of measurements is
|
||||
expected to be done anyway when tuning cpuidle and cpufreq for a given
|
||||
platform.
|
||||
|
||||
The energy model needs two types of data (struct sched_group_energy holds
|
||||
these) for each sched_group where energy costs should be taken into account:
|
||||
|
||||
1. Capacity state information
|
||||
|
||||
A list containing the compute capacity and power consumption when fully
|
||||
utilized attributed to the group as a whole for each available capacity state.
|
||||
At the lowest level (group contains just a single cpu) this is the power of the
|
||||
cpu alone without including power consumed by resources shared with other cpus.
|
||||
It basically needs to fit the basic modelling approach described in "Background
|
||||
and Terminology" section:
|
||||
|
||||
energy_system = energy_shared + n * energy_cpu
|
||||
|
||||
for a system containing 'n' busy cpus. Only 'energy_cpu' should be included at
|
||||
the lowest level. 'energy_shared' is included at the next level which
|
||||
represents the group of cpus among which the resources are shared.
|
||||
|
||||
This model is, of course, a simplification of reality. Thus, power/energy
|
||||
attributions might not always exactly represent how the hardware is designed.
|
||||
Also, busy power is likely to depend on the workload. It is therefore
|
||||
recommended to use a representative mix of workloads when characterizing the
|
||||
capacity states.
|
||||
|
||||
If the group has no capacity scaling support, the list will contain a single
|
||||
state where power is the busy power attributed to the group. The capacity
|
||||
should be set to a default value (1024).
|
||||
|
||||
When frequency domains include multiple power domains, the group representing
|
||||
the frequency domain and all child groups share capacity states. This must be
|
||||
indicated by setting the SD_SHARE_CAP_STATES sched_domain flag. All groups at
|
||||
all levels that share the capacity state must have the list of capacity states
|
||||
with the power set to the contribution of the individual group.
|
||||
|
||||
2. Idle power information
|
||||
|
||||
Stored in the idle_states list. The power number is the group idle power
|
||||
consumption in each idle state as well when the group is idle but has not
|
||||
entered an idle-state ('active idle' as mentioned earlier). Due to the way the
|
||||
energy model is defined, the idle power of the deepest group idle state can
|
||||
alternatively be accounted for in the parent group busy power. In that case the
|
||||
group idle state power values are offset such that the idle power of the
|
||||
deepest state is zero. It is less intuitive, but it is easier to measure as
|
||||
idle power consumed by the group and the busy/idle power of the parent group
|
||||
cannot be distinguished without per group measurement points.
|
||||
|
||||
Measuring capacity states and idle power:
|
||||
|
||||
The capacity states' capacity and power can be estimated by running a benchmark
|
||||
workload at each available capacity state. By restricting the benchmark to run
|
||||
on subsets of cpus it is possible to extrapolate the power consumption of
|
||||
shared resources.
|
||||
|
||||
ARM TC2 has two clusters of two and three cpus respectively. Each cluster has a
|
||||
shared L2 cache. TC2 has on-chip energy counters per cluster. Running a
|
||||
benchmark workload on just one cpu in a cluster means that power is consumed in
|
||||
the cluster (higher level group) and a single cpu (lowest level group). Adding
|
||||
another benchmark task to another cpu increases the power consumption by the
|
||||
amount consumed by the additional cpu. Hence, it is possible to extrapolate the
|
||||
cluster busy power.
|
||||
|
||||
For platforms that don't have energy counters or equivalent instrumentation
|
||||
built-in, it may be possible to use an external DAQ to acquire similar data.
|
||||
|
||||
If the benchmark includes some performance score (for example sysbench cpu
|
||||
benchmark), this can be used to record the compute capacity.
|
||||
|
||||
Measuring idle power requires insight into the idle state implementation on the
|
||||
particular platform. Specifically, if the platform has coupled idle-states (or
|
||||
package states). To measure non-coupled per-cpu idle-states it is necessary to
|
||||
keep one cpu busy to keep any shared resources alive to isolate the idle power
|
||||
of the cpu from idle/busy power of the shared resources. The cpu can be tricked
|
||||
into different per-cpu idle states by disabling the other states. Based on
|
||||
various combinations of measurements with specific cpus busy and disabling
|
||||
idle-states it is possible to extrapolate the idle-state power.
|
||||
366
Documentation/scheduler/sched-tune.txt
Normal file
366
Documentation/scheduler/sched-tune.txt
Normal file
@@ -0,0 +1,366 @@
|
||||
Central, scheduler-driven, power-performance control
|
||||
(EXPERIMENTAL)
|
||||
|
||||
Abstract
|
||||
========
|
||||
|
||||
The topic of a single simple power-performance tunable, that is wholly
|
||||
scheduler centric, and has well defined and predictable properties has come up
|
||||
on several occasions in the past [1,2]. With techniques such as a scheduler
|
||||
driven DVFS [3], we now have a good framework for implementing such a tunable.
|
||||
This document describes the overall ideas behind its design and implementation.
|
||||
|
||||
|
||||
Table of Contents
|
||||
=================
|
||||
|
||||
1. Motivation
|
||||
2. Introduction
|
||||
3. Signal Boosting Strategy
|
||||
4. OPP selection using boosted CPU utilization
|
||||
5. Per task group boosting
|
||||
6. Question and Answers
|
||||
- What about "auto" mode?
|
||||
- What about boosting on a congested system?
|
||||
- How CPUs are boosted when we have tasks with multiple boost values?
|
||||
7. References
|
||||
|
||||
|
||||
1. Motivation
|
||||
=============
|
||||
|
||||
Sched-DVFS [3] is a new event-driven cpufreq governor which allows the
|
||||
scheduler to select the optimal DVFS operating point (OPP) for running a task
|
||||
allocated to a CPU. The introduction of sched-DVFS enables running workloads at
|
||||
the most energy efficient OPPs.
|
||||
|
||||
However, sometimes it may be desired to intentionally boost the performance of
|
||||
a workload even if that could imply a reasonable increase in energy
|
||||
consumption. For example, in order to reduce the response time of a task, we
|
||||
may want to run the task at a higher OPP than the one that is actually required
|
||||
by it's CPU bandwidth demand.
|
||||
|
||||
This last requirement is especially important if we consider that one of the
|
||||
main goals of the sched-DVFS component is to replace all currently available
|
||||
CPUFreq policies. Since sched-DVFS is event based, as opposed to the sampling
|
||||
driven governors we currently have, it is already more responsive at selecting
|
||||
the optimal OPP to run tasks allocated to a CPU. However, just tracking the
|
||||
actual task load demand may not be enough from a performance standpoint. For
|
||||
example, it is not possible to get behaviors similar to those provided by the
|
||||
"performance" and "interactive" CPUFreq governors.
|
||||
|
||||
This document describes an implementation of a tunable, stacked on top of the
|
||||
sched-DVFS which extends its functionality to support task performance
|
||||
boosting.
|
||||
|
||||
By "performance boosting" we mean the reduction of the time required to
|
||||
complete a task activation, i.e. the time elapsed from a task wakeup to its
|
||||
next deactivation (e.g. because it goes back to sleep or it terminates). For
|
||||
example, if we consider a simple periodic task which executes the same workload
|
||||
for 5[s] every 20[s] while running at a certain OPP, a boosted execution of
|
||||
that task must complete each of its activations in less than 5[s].
|
||||
|
||||
A previous attempt [5] to introduce such a boosting feature has not been
|
||||
successful mainly because of the complexity of the proposed solution. The
|
||||
approach described in this document exposes a single simple interface to
|
||||
user-space. This single tunable knob allows the tuning of system wide
|
||||
scheduler behaviours ranging from energy efficiency at one end through to
|
||||
incremental performance boosting at the other end. This first tunable affects
|
||||
all tasks. However, a more advanced extension of the concept is also provided
|
||||
which uses CGroups to boost the performance of only selected tasks while using
|
||||
the energy efficient default for all others.
|
||||
|
||||
The rest of this document introduces in more details the proposed solution
|
||||
which has been named SchedTune.
|
||||
|
||||
|
||||
2. Introduction
|
||||
===============
|
||||
|
||||
SchedTune exposes a simple user-space interface with a single power-performance
|
||||
tunable:
|
||||
|
||||
/proc/sys/kernel/sched_cfs_boost
|
||||
|
||||
This permits expressing a boost value as an integer in the range [0..100].
|
||||
|
||||
A value of 0 (default) configures the CFS scheduler for maximum energy
|
||||
efficiency. This means that sched-DVFS runs the tasks at the minimum OPP
|
||||
required to satisfy their workload demand.
|
||||
A value of 100 configures scheduler for maximum performance, which translates
|
||||
to the selection of the maximum OPP on that CPU.
|
||||
|
||||
The range between 0 and 100 can be set to satisfy other scenarios suitably. For
|
||||
example to satisfy interactive response or depending on other system events
|
||||
(battery level etc).
|
||||
|
||||
A CGroup based extension is also provided, which permits further user-space
|
||||
defined task classification to tune the scheduler for different goals depending
|
||||
on the specific nature of the task, e.g. background vs interactive vs
|
||||
low-priority.
|
||||
|
||||
The overall design of the SchedTune module is built on top of "Per-Entity Load
|
||||
Tracking" (PELT) signals and sched-DVFS by introducing a bias on the Operating
|
||||
Performance Point (OPP) selection.
|
||||
Each time a task is allocated on a CPU, sched-DVFS has the opportunity to tune
|
||||
the operating frequency of that CPU to better match the workload demand. The
|
||||
selection of the actual OPP being activated is influenced by the global boost
|
||||
value, or the boost value for the task CGroup when in use.
|
||||
|
||||
This simple biasing approach leverages existing frameworks, which means minimal
|
||||
modifications to the scheduler, and yet it allows to achieve a range of
|
||||
different behaviours all from a single simple tunable knob.
|
||||
The only new concept introduced is that of signal boosting.
|
||||
|
||||
|
||||
3. Signal Boosting Strategy
|
||||
===========================
|
||||
|
||||
The whole PELT machinery works based on the value of a few load tracking signals
|
||||
which basically track the CPU bandwidth requirements for tasks and the capacity
|
||||
of CPUs. The basic idea behind the SchedTune knob is to artificially inflate
|
||||
some of these load tracking signals to make a task or RQ appears more demanding
|
||||
that it actually is.
|
||||
|
||||
Which signals have to be inflated depends on the specific "consumer". However,
|
||||
independently from the specific (signal, consumer) pair, it is important to
|
||||
define a simple and possibly consistent strategy for the concept of boosting a
|
||||
signal.
|
||||
|
||||
A boosting strategy defines how the "abstract" user-space defined
|
||||
sched_cfs_boost value is translated into an internal "margin" value to be added
|
||||
to a signal to get its inflated value:
|
||||
|
||||
margin := boosting_strategy(sched_cfs_boost, signal)
|
||||
boosted_signal := signal + margin
|
||||
|
||||
Different boosting strategies were identified and analyzed before selecting the
|
||||
one found to be most effective.
|
||||
|
||||
Signal Proportional Compensation (SPC)
|
||||
--------------------------------------
|
||||
|
||||
In this boosting strategy the sched_cfs_boost value is used to compute a
|
||||
margin which is proportional to the complement of the original signal.
|
||||
When a signal has a maximum possible value, its complement is defined as
|
||||
the delta from the actual value and its possible maximum.
|
||||
|
||||
Since the tunable implementation uses signals which have SCHED_LOAD_SCALE as
|
||||
the maximum possible value, the margin becomes:
|
||||
|
||||
margin := sched_cfs_boost * (SCHED_LOAD_SCALE - signal)
|
||||
|
||||
Using this boosting strategy:
|
||||
- a 100% sched_cfs_boost means that the signal is scaled to the maximum value
|
||||
- each value in the range of sched_cfs_boost effectively inflates the signal in
|
||||
question by a quantity which is proportional to the maximum value.
|
||||
|
||||
For example, by applying the SPC boosting strategy to the selection of the OPP
|
||||
to run a task it is possible to achieve these behaviors:
|
||||
|
||||
- 0% boosting: run the task at the minimum OPP required by its workload
|
||||
- 100% boosting: run the task at the maximum OPP available for the CPU
|
||||
- 50% boosting: run at the half-way OPP between minimum and maximum
|
||||
|
||||
Which means that, at 50% boosting, a task will be scheduled to run at half of
|
||||
the maximum theoretically achievable performance on the specific target
|
||||
platform.
|
||||
|
||||
A graphical representation of an SPC boosted signal is represented in the
|
||||
following figure where:
|
||||
a) "-" represents the original signal
|
||||
b) "b" represents a 50% boosted signal
|
||||
c) "p" represents a 100% boosted signal
|
||||
|
||||
|
||||
^
|
||||
| SCHED_LOAD_SCALE
|
||||
+-----------------------------------------------------------------+
|
||||
|pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp
|
||||
|
|
||||
| boosted_signal
|
||||
| bbbbbbbbbbbbbbbbbbbbbbbb
|
||||
|
|
||||
| original signal
|
||||
| bbbbbbbbbbbbbbbbbbbbbbbb+----------------------+
|
||||
| |
|
||||
|bbbbbbbbbbbbbbbbbb |
|
||||
| |
|
||||
| |
|
||||
| |
|
||||
| +-----------------------+
|
||||
| |
|
||||
| |
|
||||
| |
|
||||
|------------------+
|
||||
|
|
||||
|
|
||||
+----------------------------------------------------------------------->
|
||||
|
||||
The plot above shows a ramped load signal (titled 'original_signal') and it's
|
||||
boosted equivalent. For each step of the original signal the boosted signal
|
||||
corresponding to a 50% boost is midway from the original signal and the upper
|
||||
bound. Boosting by 100% generates a boosted signal which is always saturated to
|
||||
the upper bound.
|
||||
|
||||
|
||||
4. OPP selection using boosted CPU utilization
|
||||
==============================================
|
||||
|
||||
It is worth calling out that the implementation does not introduce any new load
|
||||
signals. Instead, it provides an API to tune existing signals. This tuning is
|
||||
done on demand and only in scheduler code paths where it is sensible to do so.
|
||||
The new API calls are defined to return either the default signal or a boosted
|
||||
one, depending on the value of sched_cfs_boost. This is a clean an non invasive
|
||||
modification of the existing existing code paths.
|
||||
|
||||
The signal representing a CPU's utilization is boosted according to the
|
||||
previously described SPC boosting strategy. To sched-DVFS, this allows a CPU
|
||||
(ie CFS run-queue) to appear more used then it actually is.
|
||||
|
||||
Thus, with the sched_cfs_boost enabled we have the following main functions to
|
||||
get the current utilization of a CPU:
|
||||
|
||||
cpu_util()
|
||||
boosted_cpu_util()
|
||||
|
||||
The new boosted_cpu_util() is similar to the first but returns a boosted
|
||||
utilization signal which is a function of the sched_cfs_boost value.
|
||||
|
||||
This function is used in the CFS scheduler code paths where sched-DVFS needs to
|
||||
decide the OPP to run a CPU at.
|
||||
For example, this allows selecting the highest OPP for a CPU which has
|
||||
the boost value set to 100%.
|
||||
|
||||
|
||||
5. Per task group boosting
|
||||
==========================
|
||||
|
||||
The availability of a single knob which is used to boost all tasks in the
|
||||
system is certainly a simple solution but it quite likely doesn't fit many
|
||||
utilization scenarios, especially in the mobile device space.
|
||||
|
||||
For example, on battery powered devices there usually are many background
|
||||
services which are long running and need energy efficient scheduling. On the
|
||||
other hand, some applications are more performance sensitive and require an
|
||||
interactive response and/or maximum performance, regardless of the energy cost.
|
||||
To better service such scenarios, the SchedTune implementation has an extension
|
||||
that provides a more fine grained boosting interface.
|
||||
|
||||
A new CGroup controller, namely "schedtune", could be enabled which allows to
|
||||
defined and configure task groups with different boosting values.
|
||||
Tasks that require special performance can be put into separate CGroups.
|
||||
The value of the boost associated with the tasks in this group can be specified
|
||||
using a single knob exposed by the CGroup controller:
|
||||
|
||||
schedtune.boost
|
||||
|
||||
This knob allows the definition of a boost value that is to be used for
|
||||
SPC boosting of all tasks attached to this group.
|
||||
|
||||
The current schedtune controller implementation is really simple and has these
|
||||
main characteristics:
|
||||
|
||||
1) It is only possible to create 1 level depth hierarchies
|
||||
|
||||
The root control groups define the system-wide boost value to be applied
|
||||
by default to all tasks. Its direct subgroups are named "boost groups" and
|
||||
they define the boost value for specific set of tasks.
|
||||
Further nested subgroups are not allowed since they do not have a sensible
|
||||
meaning from a user-space standpoint.
|
||||
|
||||
2) It is possible to define only a limited number of "boost groups"
|
||||
|
||||
This number is defined at compile time and by default configured to 16.
|
||||
This is a design decision motivated by two main reasons:
|
||||
a) In a real system we do not expect utilization scenarios with more then few
|
||||
boost groups. For example, a reasonable collection of groups could be
|
||||
just "background", "interactive" and "performance".
|
||||
b) It simplifies the implementation considerably, especially for the code
|
||||
which has to compute the per CPU boosting once there are multiple
|
||||
RUNNABLE tasks with different boost values.
|
||||
|
||||
Such a simple design should allow servicing the main utilization scenarios identified
|
||||
so far. It provides a simple interface which can be used to manage the
|
||||
power-performance of all tasks or only selected tasks.
|
||||
Moreover, this interface can be easily integrated by user-space run-times (e.g.
|
||||
Android, ChromeOS) to implement a QoS solution for task boosting based on tasks
|
||||
classification, which has been a long standing requirement.
|
||||
|
||||
Setup and usage
|
||||
---------------
|
||||
|
||||
0. Use a kernel with CGROUP_SCHEDTUNE support enabled
|
||||
|
||||
1. Check that the "schedtune" CGroup controller is available:
|
||||
|
||||
root@linaro-nano:~# cat /proc/cgroups
|
||||
#subsys_name hierarchy num_cgroups enabled
|
||||
cpuset 0 1 1
|
||||
cpu 0 1 1
|
||||
schedtune 0 1 1
|
||||
|
||||
2. Mount a tmpfs to create the CGroups mount point (Optional)
|
||||
|
||||
root@linaro-nano:~# sudo mount -t tmpfs cgroups /sys/fs/cgroup
|
||||
|
||||
3. Mount the "schedtune" controller
|
||||
|
||||
root@linaro-nano:~# mkdir /sys/fs/cgroup/stune
|
||||
root@linaro-nano:~# sudo mount -t cgroup -o schedtune stune /sys/fs/cgroup/stune
|
||||
|
||||
4. Setup the system-wide boost value (Optional)
|
||||
|
||||
If not configured the root control group has a 0% boost value, which
|
||||
basically disables boosting for all tasks in the system thus running in
|
||||
an energy-efficient mode.
|
||||
|
||||
root@linaro-nano:~# echo $SYSBOOST > /sys/fs/cgroup/stune/schedtune.boost
|
||||
|
||||
5. Create task groups and configure their specific boost value (Optional)
|
||||
|
||||
For example here we create a "performance" boost group configure to boost
|
||||
all its tasks to 100%
|
||||
|
||||
root@linaro-nano:~# mkdir /sys/fs/cgroup/stune/performance
|
||||
root@linaro-nano:~# echo 100 > /sys/fs/cgroup/stune/performance/schedtune.boost
|
||||
|
||||
6. Move tasks into the boost group
|
||||
|
||||
For example, the following moves the tasks with PID $TASKPID (and all its
|
||||
threads) into the "performance" boost group.
|
||||
|
||||
root@linaro-nano:~# echo "TASKPID > /sys/fs/cgroup/stune/performance/cgroup.procs
|
||||
|
||||
This simple configuration allows only the threads of the $TASKPID task to run,
|
||||
when needed, at the highest OPP in the most capable CPU of the system.
|
||||
|
||||
|
||||
6. Question and Answers
|
||||
=======================
|
||||
|
||||
What about "auto" mode?
|
||||
-----------------------
|
||||
|
||||
The 'auto' mode as described in [5] can be implemented by interfacing SchedTune
|
||||
with some suitable user-space element. This element could use the exposed
|
||||
system-wide or cgroup based interface.
|
||||
|
||||
How are multiple groups of tasks with different boost values managed?
|
||||
---------------------------------------------------------------------
|
||||
|
||||
The current SchedTune implementation keeps track of the boosted RUNNABLE tasks
|
||||
on a CPU. Once sched-DVFS selects the OPP to run a CPU at, the CPU utilization
|
||||
is boosted with a value which is the maximum of the boost values of the
|
||||
currently RUNNABLE tasks in its RQ.
|
||||
|
||||
This allows sched-DVFS to boost a CPU only while there are boosted tasks ready
|
||||
to run and switch back to the energy efficient mode as soon as the last boosted
|
||||
task is dequeued.
|
||||
|
||||
|
||||
7. References
|
||||
=============
|
||||
[1] http://lwn.net/Articles/552889
|
||||
[2] http://lkml.org/lkml/2012/5/18/91
|
||||
[3] http://lkml.org/lkml/2015/6/26/620
|
||||
75
Documentation/sync.txt
Normal file
75
Documentation/sync.txt
Normal file
@@ -0,0 +1,75 @@
|
||||
Motivation:
|
||||
|
||||
In complicated DMA pipelines such as graphics (multimedia, camera, gpu, display)
|
||||
a consumer of a buffer needs to know when the producer has finished producing
|
||||
it. Likewise the producer needs to know when the consumer is finished with the
|
||||
buffer so it can reuse it. A particular buffer may be consumed by multiple
|
||||
consumers which will retain the buffer for different amounts of time. In
|
||||
addition, a consumer may consume multiple buffers atomically.
|
||||
The sync framework adds an API which allows synchronization between the
|
||||
producers and consumers in a generic way while also allowing platforms which
|
||||
have shared hardware synchronization primitives to exploit them.
|
||||
|
||||
Goals:
|
||||
* provide a generic API for expressing synchronization dependencies
|
||||
* allow drivers to exploit hardware synchronization between hardware
|
||||
blocks
|
||||
* provide a userspace API that allows a compositor to manage
|
||||
dependencies.
|
||||
* provide rich telemetry data to allow debugging slowdowns and stalls of
|
||||
the graphics pipeline.
|
||||
|
||||
Objects:
|
||||
* sync_timeline
|
||||
* sync_pt
|
||||
* sync_fence
|
||||
|
||||
sync_timeline:
|
||||
|
||||
A sync_timeline is an abstract monotonically increasing counter. In general,
|
||||
each driver/hardware block context will have one of these. They can be backed
|
||||
by the appropriate hardware or rely on the generic sw_sync implementation.
|
||||
Timelines are only ever created through their specific implementations
|
||||
(i.e. sw_sync.)
|
||||
|
||||
sync_pt:
|
||||
|
||||
A sync_pt is an abstract value which marks a point on a sync_timeline. Sync_pts
|
||||
have a single timeline parent. They have 3 states: active, signaled, and error.
|
||||
They start in active state and transition, once, to either signaled (when the
|
||||
timeline counter advances beyond the sync_pt’s value) or error state.
|
||||
|
||||
sync_fence:
|
||||
|
||||
Sync_fences are the primary primitives used by drivers to coordinate
|
||||
synchronization of their buffers. They are a collection of sync_pts which may
|
||||
or may not have the same timeline parent. A sync_pt can only exist in one fence
|
||||
and the fence's list of sync_pts is immutable once created. Fences can be
|
||||
waited on synchronously or asynchronously. Two fences can also be merged to
|
||||
create a third fence containing a copy of the two fences’ sync_pts. Fences are
|
||||
backed by file descriptors to allow userspace to coordinate the display pipeline
|
||||
dependencies.
|
||||
|
||||
Use:
|
||||
|
||||
A driver implementing sync support should have a work submission function which:
|
||||
* takes a fence argument specifying when to begin work
|
||||
* asynchronously queues that work to kick off when the fence is signaled
|
||||
* returns a fence to indicate when its work will be done.
|
||||
* signals the returned fence once the work is completed.
|
||||
|
||||
Consider an imaginary display driver that has the following API:
|
||||
/*
|
||||
* assumes buf is ready to be displayed.
|
||||
* blocks until the buffer is on screen.
|
||||
*/
|
||||
void display_buffer(struct dma_buf *buf);
|
||||
|
||||
The new API will become:
|
||||
/*
|
||||
* will display buf when fence is signaled.
|
||||
* returns immediately with a fence that will signal when buf
|
||||
* is no longer displayed.
|
||||
*/
|
||||
struct sync_fence* display_buffer(struct dma_buf *buf,
|
||||
struct sync_fence *fence);
|
||||
@@ -659,12 +659,14 @@ allowed to execute.
|
||||
perf_event_paranoid:
|
||||
|
||||
Controls use of the performance events system by unprivileged
|
||||
users (without CAP_SYS_ADMIN). The default value is 2.
|
||||
users (without CAP_SYS_ADMIN). The default value is 3 if
|
||||
CONFIG_SECURITY_PERF_EVENTS_RESTRICT is set, or 2 otherwise.
|
||||
|
||||
-1: Allow use of (almost) all events by all users
|
||||
>=0: Disallow raw tracepoint access by users without CAP_IOC_LOCK
|
||||
>=1: Disallow CPU event access by users without CAP_SYS_ADMIN
|
||||
>=2: Disallow kernel profiling by users without CAP_SYS_ADMIN
|
||||
>=3: Disallow all event access by users without CAP_SYS_ADMIN
|
||||
|
||||
==============================================================
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ cpufreq.
|
||||
|
||||
cpu_idle "state=%lu cpu_id=%lu"
|
||||
cpu_frequency "state=%lu cpu_id=%lu"
|
||||
cpu_frequency_limits "min=%lu max=%lu cpu_id=%lu"
|
||||
|
||||
A suspend event is used to indicate the system going in and out of the
|
||||
suspend mode:
|
||||
|
||||
@@ -362,6 +362,26 @@ of ftrace. Here is a list of some of the key files:
|
||||
to correlate events across hypervisor/guest if
|
||||
tb_offset is known.
|
||||
|
||||
mono: This uses the fast monotonic clock (CLOCK_MONOTONIC)
|
||||
which is monotonic and is subject to NTP rate adjustments.
|
||||
|
||||
mono_raw:
|
||||
This is the raw monotonic clock (CLOCK_MONOTONIC_RAW)
|
||||
which is montonic but is not subject to any rate adjustments
|
||||
and ticks at the same rate as the hardware clocksource.
|
||||
|
||||
boot: This is the boot clock (CLOCK_BOOTTIME) and is based on the
|
||||
fast monotonic clock, but also accounts for time spent in
|
||||
suspend. Since the clock access is designed for use in
|
||||
tracing in the suspend path, some side effects are possible
|
||||
if clock is accessed after the suspend time is accounted before
|
||||
the fast mono clock is updated. In this case, the clock update
|
||||
appears to happen slightly sooner than it normally would have.
|
||||
Also on 32-bit systems, it's possible that the 64-bit boot offset
|
||||
sees a partial update. These effects are rare and post
|
||||
processing should be able to handle them. See comments in the
|
||||
ktime_get_boot_fast_ns() function for more information.
|
||||
|
||||
To set a clock, simply echo the clock name into this file.
|
||||
|
||||
echo global > trace_clock
|
||||
@@ -2102,6 +2122,35 @@ will produce:
|
||||
1) 1.449 us | }
|
||||
|
||||
|
||||
You can disable the hierarchical function call formatting and instead print a
|
||||
flat list of function entry and return events. This uses the format described
|
||||
in the Output Formatting section and respects all the trace options that
|
||||
control that formatting. Hierarchical formatting is the default.
|
||||
|
||||
hierachical: echo nofuncgraph-flat > trace_options
|
||||
flat: echo funcgraph-flat > trace_options
|
||||
|
||||
ie:
|
||||
|
||||
# tracer: function_graph
|
||||
#
|
||||
# entries-in-buffer/entries-written: 68355/68355 #P:2
|
||||
#
|
||||
# _-----=> irqs-off
|
||||
# / _----=> need-resched
|
||||
# | / _---=> hardirq/softirq
|
||||
# || / _--=> preempt-depth
|
||||
# ||| / delay
|
||||
# TASK-PID CPU# |||| TIMESTAMP FUNCTION
|
||||
# | | | |||| | |
|
||||
sh-1806 [001] d... 198.843443: graph_ent: func=_raw_spin_lock
|
||||
sh-1806 [001] d... 198.843445: graph_ent: func=__raw_spin_lock
|
||||
sh-1806 [001] d..1 198.843447: graph_ret: func=__raw_spin_lock
|
||||
sh-1806 [001] d..1 198.843449: graph_ret: func=_raw_spin_lock
|
||||
sh-1806 [001] d..1 198.843451: graph_ent: func=_raw_spin_unlock_irqrestore
|
||||
sh-1806 [001] d... 198.843453: graph_ret: func=_raw_spin_unlock_irqrestore
|
||||
|
||||
|
||||
You might find other useful features for this tracer in the
|
||||
following "dynamic ftrace" section such as tracing only specific
|
||||
functions or tasks.
|
||||
|
||||
2
Makefile
2
Makefile
@@ -1,6 +1,6 @@
|
||||
VERSION = 4
|
||||
PATCHLEVEL = 9
|
||||
SUBLEVEL = 4
|
||||
SUBLEVEL = 13
|
||||
EXTRAVERSION =
|
||||
NAME = Roaring Lionus
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ config ARC
|
||||
select HAVE_KPROBES
|
||||
select HAVE_KRETPROBES
|
||||
select HAVE_MEMBLOCK
|
||||
select HAVE_MOD_ARCH_SPECIFIC if ARC_DW2_UNWIND
|
||||
select HAVE_MOD_ARCH_SPECIFIC
|
||||
select HAVE_OPROFILE
|
||||
select HAVE_PERF_EVENTS
|
||||
select HANDLE_DOMAIN_IRQ
|
||||
|
||||
@@ -26,7 +26,9 @@ static inline void __delay(unsigned long loops)
|
||||
" lp 1f \n"
|
||||
" nop \n"
|
||||
"1: \n"
|
||||
: : "r"(loops));
|
||||
:
|
||||
: "r"(loops)
|
||||
: "lp_count");
|
||||
}
|
||||
|
||||
extern void __bad_udelay(void);
|
||||
|
||||
@@ -14,13 +14,13 @@
|
||||
|
||||
#include <asm-generic/module.h>
|
||||
|
||||
#ifdef CONFIG_ARC_DW2_UNWIND
|
||||
struct mod_arch_specific {
|
||||
#ifdef CONFIG_ARC_DW2_UNWIND
|
||||
void *unw_info;
|
||||
int unw_sec_idx;
|
||||
#endif
|
||||
const char *secstr;
|
||||
};
|
||||
#endif
|
||||
|
||||
#define MODULE_PROC_FAMILY "ARC700"
|
||||
|
||||
|
||||
@@ -32,8 +32,8 @@ int module_frob_arch_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs,
|
||||
#ifdef CONFIG_ARC_DW2_UNWIND
|
||||
mod->arch.unw_sec_idx = 0;
|
||||
mod->arch.unw_info = NULL;
|
||||
mod->arch.secstr = secstr;
|
||||
#endif
|
||||
mod->arch.secstr = secstr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -113,8 +113,10 @@ int apply_relocate_add(Elf32_Shdr *sechdrs,
|
||||
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ARC_DW2_UNWIND
|
||||
if (strcmp(module->arch.secstr+sechdrs[tgtsec].sh_name, ".eh_frame") == 0)
|
||||
module->arch.unw_sec_idx = tgtsec;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
||||
|
||||
@@ -241,8 +241,9 @@ int misaligned_fixup(unsigned long address, struct pt_regs *regs,
|
||||
if (state.fault)
|
||||
goto fault;
|
||||
|
||||
/* clear any remanants of delay slot */
|
||||
if (delay_mode(regs)) {
|
||||
regs->ret = regs->bta;
|
||||
regs->ret = regs->bta & ~1U;
|
||||
regs->status32 &= ~STATUS_DE_MASK;
|
||||
} else {
|
||||
regs->ret += state.instr_len;
|
||||
|
||||
@@ -1836,6 +1836,15 @@ config XEN
|
||||
help
|
||||
Say Y if you want to run Linux in a Virtual Machine on Xen on ARM.
|
||||
|
||||
config ARM_FLUSH_CONSOLE_ON_RESTART
|
||||
bool "Force flush the console on restart"
|
||||
help
|
||||
If the console is locked while the system is rebooted, the messages
|
||||
in the temporary logbuffer would not have propogated to all the
|
||||
console drivers. This option forces the console lock to be
|
||||
released if it failed to be acquired, which will cause all the
|
||||
pending messages to be flushed.
|
||||
|
||||
endmenu
|
||||
|
||||
menu "Boot options"
|
||||
@@ -1864,6 +1873,21 @@ config DEPRECATED_PARAM_STRUCT
|
||||
This was deprecated in 2001 and announced to live on for 5 years.
|
||||
Some old boot loaders still use this way.
|
||||
|
||||
config BUILD_ARM_APPENDED_DTB_IMAGE
|
||||
bool "Build a concatenated zImage/dtb by default"
|
||||
depends on OF
|
||||
help
|
||||
Enabling this option will cause a concatenated zImage and list of
|
||||
DTBs to be built by default (instead of a standalone zImage.)
|
||||
The image will built in arch/arm/boot/zImage-dtb
|
||||
|
||||
config BUILD_ARM_APPENDED_DTB_IMAGE_NAMES
|
||||
string "Default dtb names"
|
||||
depends on BUILD_ARM_APPENDED_DTB_IMAGE
|
||||
help
|
||||
Space separated list of names of dtbs to append when
|
||||
building a concatenated zImage-dtb.
|
||||
|
||||
# Compressed boot loader in ROM. Yes, we really want to ask about
|
||||
# TEXT and BSS so we preserve their values in the config files.
|
||||
config ZBOOT_ROM_TEXT
|
||||
|
||||
@@ -1723,6 +1723,14 @@ config EARLY_PRINTK
|
||||
kernel low-level debugging functions. Add earlyprintk to your
|
||||
kernel parameters to enable this console.
|
||||
|
||||
config EARLY_PRINTK_DIRECT
|
||||
bool "Early printk direct"
|
||||
depends on DEBUG_LL
|
||||
help
|
||||
Say Y here if you want to have an early console using the
|
||||
kernel low-level debugging functions and EARLY_PRINTK is
|
||||
not early enough.
|
||||
|
||||
config ARM_KPROBES_TEST
|
||||
tristate "Kprobes test module"
|
||||
depends on KPROBES && MODULES
|
||||
|
||||
@@ -298,6 +298,8 @@ libs-y := arch/arm/lib/ $(libs-y)
|
||||
# Default target when executing plain make
|
||||
ifeq ($(CONFIG_XIP_KERNEL),y)
|
||||
KBUILD_IMAGE := xipImage
|
||||
else ifeq ($(CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE),y)
|
||||
KBUILD_IMAGE := zImage-dtb
|
||||
else
|
||||
KBUILD_IMAGE := zImage
|
||||
endif
|
||||
@@ -349,6 +351,9 @@ ifeq ($(CONFIG_VDSO),y)
|
||||
$(Q)$(MAKE) $(build)=arch/arm/vdso $@
|
||||
endif
|
||||
|
||||
zImage-dtb: vmlinux scripts dtbs
|
||||
$(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@
|
||||
|
||||
# We use MRPROPER_FILES and CLEAN_FILES now
|
||||
archclean:
|
||||
$(Q)$(MAKE) $(clean)=$(boot)
|
||||
|
||||
1
arch/arm/boot/.gitignore
vendored
1
arch/arm/boot/.gitignore
vendored
@@ -4,3 +4,4 @@ xipImage
|
||||
bootpImage
|
||||
uImage
|
||||
*.dtb
|
||||
zImage-dtb
|
||||
@@ -16,6 +16,7 @@ OBJCOPYFLAGS :=-O binary -R .comment -S
|
||||
ifneq ($(MACHINE),)
|
||||
include $(MACHINE)/Makefile.boot
|
||||
endif
|
||||
include $(srctree)/arch/arm/boot/dts/Makefile
|
||||
|
||||
# Note: the following conditions must always be true:
|
||||
# ZRELADDR == virt_to_phys(PAGE_OFFSET + TEXT_OFFSET)
|
||||
@@ -29,6 +30,14 @@ export ZRELADDR INITRD_PHYS PARAMS_PHYS
|
||||
|
||||
targets := Image zImage xipImage bootpImage uImage
|
||||
|
||||
DTB_NAMES := $(subst $\",,$(CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE_NAMES))
|
||||
ifneq ($(DTB_NAMES),)
|
||||
DTB_LIST := $(addsuffix .dtb,$(DTB_NAMES))
|
||||
else
|
||||
DTB_LIST := $(dtb-y)
|
||||
endif
|
||||
DTB_OBJS := $(addprefix $(obj)/dts/,$(DTB_LIST))
|
||||
|
||||
ifeq ($(CONFIG_XIP_KERNEL),y)
|
||||
|
||||
$(obj)/xipImage: vmlinux FORCE
|
||||
@@ -55,6 +64,10 @@ $(obj)/compressed/vmlinux: $(obj)/Image FORCE
|
||||
$(obj)/zImage: $(obj)/compressed/vmlinux FORCE
|
||||
$(call if_changed,objcopy)
|
||||
|
||||
$(obj)/zImage-dtb: $(obj)/zImage $(DTB_OBJS) FORCE
|
||||
$(call if_changed,cat)
|
||||
@echo ' Kernel: $@ is ready'
|
||||
|
||||
endif
|
||||
|
||||
ifneq ($(LOADADDR),)
|
||||
|
||||
@@ -781,6 +781,8 @@ __armv7_mmu_cache_on:
|
||||
bic r6, r6, #1 << 31 @ 32-bit translation system
|
||||
bic r6, r6, #(7 << 0) | (1 << 4) @ use only ttbr0
|
||||
mcrne p15, 0, r3, c2, c0, 0 @ load page table pointer
|
||||
mcrne p15, 0, r0, c8, c7, 0 @ flush I,D TLBs
|
||||
mcr p15, 0, r0, c7, c5, 4 @ ISB
|
||||
mcrne p15, 0, r1, c3, c0, 0 @ load domain access control
|
||||
mcrne p15, 0, r6, c2, c0, 2 @ load ttb control
|
||||
#endif
|
||||
|
||||
@@ -485,6 +485,7 @@ dtb-$(CONFIG_ARCH_OMAP3) += \
|
||||
am3517-evm.dtb \
|
||||
am3517_mt_ventoux.dtb \
|
||||
logicpd-torpedo-37xx-devkit.dtb \
|
||||
logicpd-som-lv-37xx-devkit.dtb \
|
||||
omap3430-sdp.dtb \
|
||||
omap3-beagle.dtb \
|
||||
omap3-beagle-xm.dtb \
|
||||
@@ -959,5 +960,15 @@ endif
|
||||
dtstree := $(srctree)/$(src)
|
||||
dtb-$(CONFIG_OF_ALL_DTBS) := $(patsubst $(dtstree)/%.dts,%.dtb, $(wildcard $(dtstree)/*.dts))
|
||||
|
||||
always := $(dtb-y)
|
||||
DTB_NAMES := $(subst $\",,$(CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE_NAMES))
|
||||
ifneq ($(DTB_NAMES),)
|
||||
DTB_LIST := $(addsuffix .dtb,$(DTB_NAMES))
|
||||
else
|
||||
DTB_LIST := $(dtb-y)
|
||||
endif
|
||||
|
||||
targets += dtbs dtbs_install
|
||||
targets += $(DTB_LIST)
|
||||
|
||||
always := $(DTB_LIST)
|
||||
clean-files := *.dtb
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
interrupt-parent = <&intc>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
chosen { };
|
||||
|
||||
aliases {
|
||||
i2c0 = &i2c0;
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
interrupt-parent = <&wakeupgen>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
chosen { };
|
||||
|
||||
memory@0 {
|
||||
device_type = "memory";
|
||||
|
||||
@@ -104,7 +104,7 @@
|
||||
reg = <0x7e104000 0x10>;
|
||||
};
|
||||
|
||||
mailbox: mailbox@7e00b800 {
|
||||
mailbox: mailbox@7e00b880 {
|
||||
compatible = "brcm,bcm2835-mbox";
|
||||
reg = <0x7e00b880 0x40>;
|
||||
interrupts = <0 1>;
|
||||
|
||||
@@ -99,6 +99,7 @@
|
||||
#size-cells = <1>;
|
||||
compatible = "m25p64";
|
||||
spi-max-frequency = <30000000>;
|
||||
m25p,fast-read;
|
||||
reg = <0>;
|
||||
partition@0 {
|
||||
label = "U-Boot-SPL";
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
interrupt-parent = <&intc>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
chosen { };
|
||||
|
||||
aliases {
|
||||
i2c0 = &i2c1;
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
interrupt-parent = <&intc>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
chosen { };
|
||||
|
||||
aliases {
|
||||
i2c0 = &i2c1;
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
compatible = "ti,dra7xx";
|
||||
interrupt-parent = <&crossbar_mpu>;
|
||||
chosen { };
|
||||
|
||||
aliases {
|
||||
i2c0 = &i2c1;
|
||||
@@ -1376,6 +1377,7 @@
|
||||
phy-names = "sata-phy";
|
||||
clocks = <&sata_ref_clk>;
|
||||
ti,hwmods = "sata";
|
||||
ports-implemented = <0x1>;
|
||||
};
|
||||
|
||||
rtc: rtc@48838000 {
|
||||
|
||||
@@ -30,11 +30,11 @@
|
||||
};
|
||||
};
|
||||
|
||||
avic: avic-interrupt-controller@60000000 {
|
||||
avic: interrupt-controller@68000000 {
|
||||
compatible = "fsl,imx31-avic", "fsl,avic";
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <1>;
|
||||
reg = <0x60000000 0x100000>;
|
||||
reg = <0x68000000 0x100000>;
|
||||
};
|
||||
|
||||
soc {
|
||||
@@ -118,13 +118,6 @@
|
||||
interrupts = <19>;
|
||||
clocks = <&clks 25>;
|
||||
};
|
||||
|
||||
clks: ccm@53f80000{
|
||||
compatible = "fsl,imx31-ccm";
|
||||
reg = <0x53f80000 0x4000>;
|
||||
interrupts = <0 31 0x04 0 53 0x04>;
|
||||
#clock-cells = <1>;
|
||||
};
|
||||
};
|
||||
|
||||
aips@53f00000 { /* AIPS2 */
|
||||
@@ -134,6 +127,13 @@
|
||||
reg = <0x53f00000 0x100000>;
|
||||
ranges;
|
||||
|
||||
clks: ccm@53f80000{
|
||||
compatible = "fsl,imx31-ccm";
|
||||
reg = <0x53f80000 0x4000>;
|
||||
interrupts = <31>, <53>;
|
||||
#clock-cells = <1>;
|
||||
};
|
||||
|
||||
gpt: timer@53f90000 {
|
||||
compatible = "fsl,imx31-gpt";
|
||||
reg = <0x53f90000 0x4000>;
|
||||
|
||||
@@ -137,7 +137,7 @@
|
||||
&gpio4 {
|
||||
gpio-ranges = <&iomuxc 5 136 1>, <&iomuxc 6 145 1>, <&iomuxc 7 150 1>,
|
||||
<&iomuxc 8 146 1>, <&iomuxc 9 151 1>, <&iomuxc 10 147 1>,
|
||||
<&iomuxc 11 151 1>, <&iomuxc 12 148 1>, <&iomuxc 13 153 1>,
|
||||
<&iomuxc 11 152 1>, <&iomuxc 12 148 1>, <&iomuxc 13 153 1>,
|
||||
<&iomuxc 14 149 1>, <&iomuxc 15 154 1>, <&iomuxc 16 39 7>,
|
||||
<&iomuxc 23 56 1>, <&iomuxc 24 61 7>, <&iomuxc 31 46 1>;
|
||||
};
|
||||
|
||||
@@ -183,7 +183,6 @@
|
||||
MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0
|
||||
MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0
|
||||
MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0
|
||||
MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0x4001b0a8
|
||||
>;
|
||||
};
|
||||
|
||||
|
||||
@@ -319,8 +319,6 @@
|
||||
compatible = "fsl,imx6q-nitrogen6_max-sgtl5000",
|
||||
"fsl,imx-audio-sgtl5000";
|
||||
model = "imx6q-nitrogen6_max-sgtl5000";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinctrl_sgtl5000>;
|
||||
ssi-controller = <&ssi1>;
|
||||
audio-codec = <&codec>;
|
||||
audio-routing =
|
||||
@@ -402,6 +400,8 @@
|
||||
|
||||
codec: sgtl5000@0a {
|
||||
compatible = "fsl,sgtl5000";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinctrl_sgtl5000>;
|
||||
reg = <0x0a>;
|
||||
clocks = <&clks IMX6QDL_CLK_CKO>;
|
||||
VDDA-supply = <®_2p5v>;
|
||||
|
||||
@@ -158,7 +158,7 @@
|
||||
&mmc1 {
|
||||
interrupts-extended = <&intc 83 &omap3_pmx_core 0x11a>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&mmc1_pins &mmc1_cd>;
|
||||
pinctrl-0 = <&mmc1_pins>;
|
||||
wp-gpios = <&gpio4 30 GPIO_ACTIVE_HIGH>; /* gpio_126 */
|
||||
cd-gpios = <&gpio4 14 IRQ_TYPE_LEVEL_LOW>; /* gpio_110 */
|
||||
vmmc-supply = <&vmmc1>;
|
||||
@@ -193,7 +193,8 @@
|
||||
OMAP3_CORE1_IOPAD(0x214a, PIN_INPUT | MUX_MODE0) /* sdmmc1_dat1.sdmmc1_dat1 */
|
||||
OMAP3_CORE1_IOPAD(0x214c, PIN_INPUT | MUX_MODE0) /* sdmmc1_dat2.sdmmc1_dat2 */
|
||||
OMAP3_CORE1_IOPAD(0x214e, PIN_INPUT | MUX_MODE0) /* sdmmc1_dat3.sdmmc1_dat3 */
|
||||
OMAP3_CORE1_IOPAD(0x2132, PIN_INPUT_PULLUP | MUX_MODE4) /* cam_strobe.gpio_126 sdmmc1_wp*/
|
||||
OMAP3_CORE1_IOPAD(0x2132, PIN_INPUT_PULLUP | MUX_MODE4) /* cam_strobe.gpio_126 */
|
||||
OMAP3_CORE1_IOPAD(0x212c, PIN_INPUT_PULLUP | MUX_MODE4) /* cam_d11.gpio_110 */
|
||||
>;
|
||||
};
|
||||
|
||||
@@ -242,12 +243,6 @@
|
||||
OMAP3_WKUP_IOPAD(0x2a16, PIN_OUTPUT | PIN_OFF_OUTPUT_LOW | MUX_MODE4) /* sys_boot6.gpio_8 */
|
||||
>;
|
||||
};
|
||||
|
||||
mmc1_cd: pinmux_mmc1_cd {
|
||||
pinctrl-single,pins = <
|
||||
OMAP3_WKUP_IOPAD(0x212c, PIN_INPUT_PULLUP | MUX_MODE4) /* cam_d11.gpio_110 */
|
||||
>;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
interrupt-parent = <&intc>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
chosen { };
|
||||
|
||||
aliases {
|
||||
serial0 = &uart1;
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
interrupt-parent = <&intc>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
chosen { };
|
||||
|
||||
aliases {
|
||||
i2c0 = &i2c1;
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
interrupt-parent = <&wakeupgen>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
chosen { };
|
||||
|
||||
aliases {
|
||||
i2c0 = &i2c1;
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
compatible = "ti,omap5";
|
||||
interrupt-parent = <&wakeupgen>;
|
||||
chosen { };
|
||||
|
||||
aliases {
|
||||
i2c0 = &i2c1;
|
||||
@@ -985,6 +986,7 @@
|
||||
phy-names = "sata-phy";
|
||||
clocks = <&sata_ref_clk>;
|
||||
ti,hwmods = "sata";
|
||||
ports-implemented = <0x1>;
|
||||
};
|
||||
|
||||
dss: dss@58000000 {
|
||||
|
||||
@@ -319,7 +319,7 @@
|
||||
"ch12";
|
||||
clocks = <&mstp5_clks R8A7794_CLK_AUDIO_DMAC0>;
|
||||
clock-names = "fck";
|
||||
power-domains = <&cpg_clocks>;
|
||||
power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
|
||||
#dma-cells = <1>;
|
||||
dma-channels = <13>;
|
||||
};
|
||||
@@ -1025,8 +1025,7 @@
|
||||
clocks = <&extal_clk &usb_extal_clk>;
|
||||
#clock-cells = <1>;
|
||||
clock-output-names = "main", "pll0", "pll1", "pll3",
|
||||
"lb", "qspi", "sdh", "sd0", "z",
|
||||
"rcan";
|
||||
"lb", "qspi", "sdh", "sd0", "rcan";
|
||||
#power-domain-cells = <0>;
|
||||
};
|
||||
/* Variable factor clocks */
|
||||
@@ -1483,7 +1482,7 @@
|
||||
"mix.0", "mix.1",
|
||||
"dvc.0", "dvc.1",
|
||||
"clk_a", "clk_b", "clk_c", "clk_i";
|
||||
power-domains = <&cpg_clocks>;
|
||||
power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
|
||||
|
||||
status = "disabled";
|
||||
|
||||
|
||||
@@ -17,3 +17,7 @@ config SHARP_PARAM
|
||||
|
||||
config SHARP_SCOOP
|
||||
bool
|
||||
|
||||
config FIQ_GLUE
|
||||
bool
|
||||
select FIQ
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
obj-y += firmware.o
|
||||
|
||||
obj-$(CONFIG_FIQ_GLUE) += fiq_glue.o fiq_glue_setup.o
|
||||
obj-$(CONFIG_ICST) += icst.o
|
||||
obj-$(CONFIG_SA1111) += sa1111.o
|
||||
obj-$(CONFIG_DMABOUNCE) += dmabounce.o
|
||||
|
||||
118
arch/arm/common/fiq_glue.S
Normal file
118
arch/arm/common/fiq_glue.S
Normal file
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Google, Inc.
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/linkage.h>
|
||||
#include <asm/assembler.h>
|
||||
|
||||
.text
|
||||
|
||||
.global fiq_glue_end
|
||||
|
||||
/* fiq stack: r0-r15,cpsr,spsr of interrupted mode */
|
||||
|
||||
ENTRY(fiq_glue)
|
||||
/* store pc, cpsr from previous mode, reserve space for spsr */
|
||||
mrs r12, spsr
|
||||
sub lr, lr, #4
|
||||
subs r10, #1
|
||||
bne nested_fiq
|
||||
|
||||
str r12, [sp, #-8]!
|
||||
str lr, [sp, #-4]!
|
||||
|
||||
/* store r8-r14 from previous mode */
|
||||
sub sp, sp, #(7 * 4)
|
||||
stmia sp, {r8-r14}^
|
||||
nop
|
||||
|
||||
/* store r0-r7 from previous mode */
|
||||
stmfd sp!, {r0-r7}
|
||||
|
||||
/* setup func(data,regs) arguments */
|
||||
mov r0, r9
|
||||
mov r1, sp
|
||||
mov r3, r8
|
||||
|
||||
mov r7, sp
|
||||
|
||||
/* Get sp and lr from non-user modes */
|
||||
and r4, r12, #MODE_MASK
|
||||
cmp r4, #USR_MODE
|
||||
beq fiq_from_usr_mode
|
||||
|
||||
mov r7, sp
|
||||
orr r4, r4, #(PSR_I_BIT | PSR_F_BIT)
|
||||
msr cpsr_c, r4
|
||||
str sp, [r7, #(4 * 13)]
|
||||
str lr, [r7, #(4 * 14)]
|
||||
mrs r5, spsr
|
||||
str r5, [r7, #(4 * 17)]
|
||||
|
||||
cmp r4, #(SVC_MODE | PSR_I_BIT | PSR_F_BIT)
|
||||
/* use fiq stack if we reenter this mode */
|
||||
subne sp, r7, #(4 * 3)
|
||||
|
||||
fiq_from_usr_mode:
|
||||
msr cpsr_c, #(SVC_MODE | PSR_I_BIT | PSR_F_BIT)
|
||||
mov r2, sp
|
||||
sub sp, r7, #12
|
||||
stmfd sp!, {r2, ip, lr}
|
||||
/* call func(data,regs) */
|
||||
blx r3
|
||||
ldmfd sp, {r2, ip, lr}
|
||||
mov sp, r2
|
||||
|
||||
/* restore/discard saved state */
|
||||
cmp r4, #USR_MODE
|
||||
beq fiq_from_usr_mode_exit
|
||||
|
||||
msr cpsr_c, r4
|
||||
ldr sp, [r7, #(4 * 13)]
|
||||
ldr lr, [r7, #(4 * 14)]
|
||||
msr spsr_cxsf, r5
|
||||
|
||||
fiq_from_usr_mode_exit:
|
||||
msr cpsr_c, #(FIQ_MODE | PSR_I_BIT | PSR_F_BIT)
|
||||
|
||||
ldmfd sp!, {r0-r7}
|
||||
ldr lr, [sp, #(4 * 7)]
|
||||
ldr r12, [sp, #(4 * 8)]
|
||||
add sp, sp, #(10 * 4)
|
||||
exit_fiq:
|
||||
msr spsr_cxsf, r12
|
||||
add r10, #1
|
||||
cmp r11, #0
|
||||
moveqs pc, lr
|
||||
bx r11 /* jump to custom fiq return function */
|
||||
|
||||
nested_fiq:
|
||||
orr r12, r12, #(PSR_F_BIT)
|
||||
b exit_fiq
|
||||
|
||||
fiq_glue_end:
|
||||
|
||||
ENTRY(fiq_glue_setup) /* func, data, sp, smc call number */
|
||||
stmfd sp!, {r4}
|
||||
mrs r4, cpsr
|
||||
msr cpsr_c, #(FIQ_MODE | PSR_I_BIT | PSR_F_BIT)
|
||||
movs r8, r0
|
||||
mov r9, r1
|
||||
mov sp, r2
|
||||
mov r11, r3
|
||||
moveq r10, #0
|
||||
movne r10, #1
|
||||
msr cpsr_c, r4
|
||||
ldmfd sp!, {r4}
|
||||
bx lr
|
||||
|
||||
147
arch/arm/common/fiq_glue_setup.c
Normal file
147
arch/arm/common/fiq_glue_setup.c
Normal file
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Google, Inc.
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/percpu.h>
|
||||
#include <linux/slab.h>
|
||||
#include <asm/fiq.h>
|
||||
#include <asm/fiq_glue.h>
|
||||
|
||||
extern unsigned char fiq_glue, fiq_glue_end;
|
||||
extern void fiq_glue_setup(void *func, void *data, void *sp,
|
||||
fiq_return_handler_t fiq_return_handler);
|
||||
|
||||
static struct fiq_handler fiq_debbuger_fiq_handler = {
|
||||
.name = "fiq_glue",
|
||||
};
|
||||
DEFINE_PER_CPU(void *, fiq_stack);
|
||||
static struct fiq_glue_handler *current_handler;
|
||||
static fiq_return_handler_t fiq_return_handler;
|
||||
static DEFINE_MUTEX(fiq_glue_lock);
|
||||
|
||||
static void fiq_glue_setup_helper(void *info)
|
||||
{
|
||||
struct fiq_glue_handler *handler = info;
|
||||
fiq_glue_setup(handler->fiq, handler,
|
||||
__get_cpu_var(fiq_stack) + THREAD_START_SP,
|
||||
fiq_return_handler);
|
||||
}
|
||||
|
||||
int fiq_glue_register_handler(struct fiq_glue_handler *handler)
|
||||
{
|
||||
int ret;
|
||||
int cpu;
|
||||
|
||||
if (!handler || !handler->fiq)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&fiq_glue_lock);
|
||||
if (fiq_stack) {
|
||||
ret = -EBUSY;
|
||||
goto err_busy;
|
||||
}
|
||||
|
||||
for_each_possible_cpu(cpu) {
|
||||
void *stack;
|
||||
stack = (void *)__get_free_pages(GFP_KERNEL, THREAD_SIZE_ORDER);
|
||||
if (WARN_ON(!stack)) {
|
||||
ret = -ENOMEM;
|
||||
goto err_alloc_fiq_stack;
|
||||
}
|
||||
per_cpu(fiq_stack, cpu) = stack;
|
||||
}
|
||||
|
||||
ret = claim_fiq(&fiq_debbuger_fiq_handler);
|
||||
if (WARN_ON(ret))
|
||||
goto err_claim_fiq;
|
||||
|
||||
current_handler = handler;
|
||||
on_each_cpu(fiq_glue_setup_helper, handler, true);
|
||||
set_fiq_handler(&fiq_glue, &fiq_glue_end - &fiq_glue);
|
||||
|
||||
mutex_unlock(&fiq_glue_lock);
|
||||
return 0;
|
||||
|
||||
err_claim_fiq:
|
||||
err_alloc_fiq_stack:
|
||||
for_each_possible_cpu(cpu) {
|
||||
__free_pages(per_cpu(fiq_stack, cpu), THREAD_SIZE_ORDER);
|
||||
per_cpu(fiq_stack, cpu) = NULL;
|
||||
}
|
||||
err_busy:
|
||||
mutex_unlock(&fiq_glue_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void fiq_glue_update_return_handler(void (*fiq_return)(void))
|
||||
{
|
||||
fiq_return_handler = fiq_return;
|
||||
if (current_handler)
|
||||
on_each_cpu(fiq_glue_setup_helper, current_handler, true);
|
||||
}
|
||||
|
||||
int fiq_glue_set_return_handler(void (*fiq_return)(void))
|
||||
{
|
||||
int ret;
|
||||
|
||||
mutex_lock(&fiq_glue_lock);
|
||||
if (fiq_return_handler) {
|
||||
ret = -EBUSY;
|
||||
goto err_busy;
|
||||
}
|
||||
fiq_glue_update_return_handler(fiq_return);
|
||||
ret = 0;
|
||||
err_busy:
|
||||
mutex_unlock(&fiq_glue_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(fiq_glue_set_return_handler);
|
||||
|
||||
int fiq_glue_clear_return_handler(void (*fiq_return)(void))
|
||||
{
|
||||
int ret;
|
||||
|
||||
mutex_lock(&fiq_glue_lock);
|
||||
if (WARN_ON(fiq_return_handler != fiq_return)) {
|
||||
ret = -EINVAL;
|
||||
goto err_inval;
|
||||
}
|
||||
fiq_glue_update_return_handler(NULL);
|
||||
ret = 0;
|
||||
err_inval:
|
||||
mutex_unlock(&fiq_glue_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(fiq_glue_clear_return_handler);
|
||||
|
||||
/**
|
||||
* fiq_glue_resume - Restore fiqs after suspend or low power idle states
|
||||
*
|
||||
* This must be called before calling local_fiq_enable after returning from a
|
||||
* power state where the fiq mode registers were lost. If a driver provided
|
||||
* a resume hook when it registered the handler it will be called.
|
||||
*/
|
||||
|
||||
void fiq_glue_resume(void)
|
||||
{
|
||||
if (!current_handler)
|
||||
return;
|
||||
fiq_glue_setup(current_handler->fiq, current_handler,
|
||||
__get_cpu_var(fiq_stack) + THREAD_START_SP,
|
||||
fiq_return_handler);
|
||||
if (current_handler->resume)
|
||||
current_handler->resume(current_handler);
|
||||
}
|
||||
|
||||
316
arch/arm/configs/ranchu_defconfig
Normal file
316
arch/arm/configs/ranchu_defconfig
Normal file
@@ -0,0 +1,316 @@
|
||||
# CONFIG_LOCALVERSION_AUTO is not set
|
||||
CONFIG_AUDIT=y
|
||||
CONFIG_NO_HZ=y
|
||||
CONFIG_HIGH_RES_TIMERS=y
|
||||
CONFIG_TASKSTATS=y
|
||||
CONFIG_TASK_DELAY_ACCT=y
|
||||
CONFIG_TASK_XACCT=y
|
||||
CONFIG_TASK_IO_ACCOUNTING=y
|
||||
CONFIG_IKCONFIG=y
|
||||
CONFIG_IKCONFIG_PROC=y
|
||||
CONFIG_LOG_BUF_SHIFT=14
|
||||
CONFIG_CGROUPS=y
|
||||
CONFIG_CGROUP_DEBUG=y
|
||||
CONFIG_CGROUP_FREEZER=y
|
||||
CONFIG_CPUSETS=y
|
||||
CONFIG_CGROUP_CPUACCT=y
|
||||
CONFIG_CGROUP_SCHED=y
|
||||
CONFIG_RT_GROUP_SCHED=y
|
||||
CONFIG_BLK_DEV_INITRD=y
|
||||
CONFIG_KALLSYMS_ALL=y
|
||||
CONFIG_EMBEDDED=y
|
||||
CONFIG_PROFILING=y
|
||||
CONFIG_OPROFILE=y
|
||||
CONFIG_ARCH_MMAP_RND_BITS=16
|
||||
# CONFIG_BLK_DEV_BSG is not set
|
||||
# CONFIG_IOSCHED_DEADLINE is not set
|
||||
# CONFIG_IOSCHED_CFQ is not set
|
||||
CONFIG_ARCH_VIRT=y
|
||||
CONFIG_ARM_KERNMEM_PERMS=y
|
||||
CONFIG_SMP=y
|
||||
CONFIG_PREEMPT=y
|
||||
CONFIG_AEABI=y
|
||||
CONFIG_HIGHMEM=y
|
||||
CONFIG_KSM=y
|
||||
CONFIG_SECCOMP=y
|
||||
CONFIG_CMDLINE="console=ttyAMA0"
|
||||
CONFIG_VFP=y
|
||||
CONFIG_NEON=y
|
||||
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
|
||||
CONFIG_PM_AUTOSLEEP=y
|
||||
CONFIG_PM_WAKELOCKS=y
|
||||
CONFIG_PM_WAKELOCKS_LIMIT=0
|
||||
# CONFIG_PM_WAKELOCKS_GC is not set
|
||||
CONFIG_PM_DEBUG=y
|
||||
CONFIG_NET=y
|
||||
CONFIG_PACKET=y
|
||||
CONFIG_UNIX=y
|
||||
CONFIG_XFRM_USER=y
|
||||
CONFIG_NET_KEY=y
|
||||
CONFIG_INET=y
|
||||
CONFIG_INET_DIAG_DESTROY=y
|
||||
CONFIG_IP_MULTICAST=y
|
||||
CONFIG_IP_ADVANCED_ROUTER=y
|
||||
CONFIG_IP_MULTIPLE_TABLES=y
|
||||
CONFIG_IP_PNP=y
|
||||
CONFIG_IP_PNP_DHCP=y
|
||||
CONFIG_IP_PNP_BOOTP=y
|
||||
CONFIG_INET_ESP=y
|
||||
# CONFIG_INET_LRO is not set
|
||||
CONFIG_IPV6_ROUTER_PREF=y
|
||||
CONFIG_IPV6_ROUTE_INFO=y
|
||||
CONFIG_IPV6_OPTIMISTIC_DAD=y
|
||||
CONFIG_INET6_AH=y
|
||||
CONFIG_INET6_ESP=y
|
||||
CONFIG_INET6_IPCOMP=y
|
||||
CONFIG_IPV6_MIP6=y
|
||||
CONFIG_IPV6_MULTIPLE_TABLES=y
|
||||
CONFIG_NETFILTER=y
|
||||
CONFIG_NF_CONNTRACK=y
|
||||
CONFIG_NF_CONNTRACK_SECMARK=y
|
||||
CONFIG_NF_CONNTRACK_EVENTS=y
|
||||
CONFIG_NF_CT_PROTO_DCCP=y
|
||||
CONFIG_NF_CT_PROTO_SCTP=y
|
||||
CONFIG_NF_CT_PROTO_UDPLITE=y
|
||||
CONFIG_NF_CONNTRACK_AMANDA=y
|
||||
CONFIG_NF_CONNTRACK_FTP=y
|
||||
CONFIG_NF_CONNTRACK_H323=y
|
||||
CONFIG_NF_CONNTRACK_IRC=y
|
||||
CONFIG_NF_CONNTRACK_NETBIOS_NS=y
|
||||
CONFIG_NF_CONNTRACK_PPTP=y
|
||||
CONFIG_NF_CONNTRACK_SANE=y
|
||||
CONFIG_NF_CONNTRACK_TFTP=y
|
||||
CONFIG_NF_CT_NETLINK=y
|
||||
CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
|
||||
CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
|
||||
CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y
|
||||
CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y
|
||||
CONFIG_NETFILTER_XT_TARGET_MARK=y
|
||||
CONFIG_NETFILTER_XT_TARGET_NFLOG=y
|
||||
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
|
||||
CONFIG_NETFILTER_XT_TARGET_TPROXY=y
|
||||
CONFIG_NETFILTER_XT_TARGET_TRACE=y
|
||||
CONFIG_NETFILTER_XT_TARGET_SECMARK=y
|
||||
CONFIG_NETFILTER_XT_TARGET_TCPMSS=y
|
||||
CONFIG_NETFILTER_XT_MATCH_COMMENT=y
|
||||
CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
|
||||
CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
|
||||
CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
|
||||
CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y
|
||||
CONFIG_NETFILTER_XT_MATCH_HELPER=y
|
||||
CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
|
||||
CONFIG_NETFILTER_XT_MATCH_LENGTH=y
|
||||
CONFIG_NETFILTER_XT_MATCH_LIMIT=y
|
||||
CONFIG_NETFILTER_XT_MATCH_MAC=y
|
||||
CONFIG_NETFILTER_XT_MATCH_MARK=y
|
||||
CONFIG_NETFILTER_XT_MATCH_POLICY=y
|
||||
CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
|
||||
CONFIG_NETFILTER_XT_MATCH_QTAGUID=y
|
||||
CONFIG_NETFILTER_XT_MATCH_QUOTA=y
|
||||
CONFIG_NETFILTER_XT_MATCH_QUOTA2=y
|
||||
CONFIG_NETFILTER_XT_MATCH_SOCKET=y
|
||||
CONFIG_NETFILTER_XT_MATCH_STATE=y
|
||||
CONFIG_NETFILTER_XT_MATCH_STATISTIC=y
|
||||
CONFIG_NETFILTER_XT_MATCH_STRING=y
|
||||
CONFIG_NETFILTER_XT_MATCH_TIME=y
|
||||
CONFIG_NETFILTER_XT_MATCH_U32=y
|
||||
CONFIG_NF_CONNTRACK_IPV4=y
|
||||
CONFIG_IP_NF_IPTABLES=y
|
||||
CONFIG_IP_NF_MATCH_AH=y
|
||||
CONFIG_IP_NF_MATCH_ECN=y
|
||||
CONFIG_IP_NF_MATCH_TTL=y
|
||||
CONFIG_IP_NF_FILTER=y
|
||||
CONFIG_IP_NF_TARGET_REJECT=y
|
||||
CONFIG_IP_NF_MANGLE=y
|
||||
CONFIG_IP_NF_RAW=y
|
||||
CONFIG_IP_NF_SECURITY=y
|
||||
CONFIG_IP_NF_ARPTABLES=y
|
||||
CONFIG_IP_NF_ARPFILTER=y
|
||||
CONFIG_IP_NF_ARP_MANGLE=y
|
||||
CONFIG_NF_CONNTRACK_IPV6=y
|
||||
CONFIG_IP6_NF_IPTABLES=y
|
||||
CONFIG_IP6_NF_FILTER=y
|
||||
CONFIG_IP6_NF_TARGET_REJECT=y
|
||||
CONFIG_IP6_NF_MANGLE=y
|
||||
CONFIG_IP6_NF_RAW=y
|
||||
CONFIG_BRIDGE=y
|
||||
CONFIG_NET_SCHED=y
|
||||
CONFIG_NET_SCH_HTB=y
|
||||
CONFIG_NET_CLS_U32=y
|
||||
CONFIG_NET_EMATCH=y
|
||||
CONFIG_NET_EMATCH_U32=y
|
||||
CONFIG_NET_CLS_ACT=y
|
||||
# CONFIG_WIRELESS is not set
|
||||
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
|
||||
CONFIG_MTD=y
|
||||
CONFIG_MTD_CMDLINE_PARTS=y
|
||||
CONFIG_MTD_BLOCK=y
|
||||
CONFIG_MTD_CFI=y
|
||||
CONFIG_MTD_CFI_INTELEXT=y
|
||||
CONFIG_MTD_CFI_AMDSTD=y
|
||||
CONFIG_BLK_DEV_LOOP=y
|
||||
CONFIG_BLK_DEV_RAM=y
|
||||
CONFIG_BLK_DEV_RAM_SIZE=8192
|
||||
CONFIG_VIRTIO_BLK=y
|
||||
CONFIG_MD=y
|
||||
CONFIG_BLK_DEV_DM=y
|
||||
CONFIG_DM_CRYPT=y
|
||||
CONFIG_DM_UEVENT=y
|
||||
CONFIG_DM_VERITY=y
|
||||
CONFIG_DM_VERITY_FEC=y
|
||||
CONFIG_NETDEVICES=y
|
||||
CONFIG_TUN=y
|
||||
CONFIG_VIRTIO_NET=y
|
||||
CONFIG_SMSC911X=y
|
||||
CONFIG_PPP=y
|
||||
CONFIG_PPP_BSDCOMP=y
|
||||
CONFIG_PPP_DEFLATE=y
|
||||
CONFIG_PPP_MPPE=y
|
||||
CONFIG_PPPOLAC=y
|
||||
CONFIG_PPPOPNS=y
|
||||
CONFIG_USB_USBNET=y
|
||||
# CONFIG_WLAN is not set
|
||||
CONFIG_INPUT_EVDEV=y
|
||||
CONFIG_INPUT_KEYRESET=y
|
||||
CONFIG_KEYBOARD_GOLDFISH_EVENTS=y
|
||||
# CONFIG_INPUT_MOUSE is not set
|
||||
CONFIG_INPUT_JOYSTICK=y
|
||||
CONFIG_JOYSTICK_XPAD=y
|
||||
CONFIG_JOYSTICK_XPAD_FF=y
|
||||
CONFIG_JOYSTICK_XPAD_LEDS=y
|
||||
CONFIG_INPUT_TABLET=y
|
||||
CONFIG_TABLET_USB_ACECAD=y
|
||||
CONFIG_TABLET_USB_AIPTEK=y
|
||||
CONFIG_TABLET_USB_GTCO=y
|
||||
CONFIG_TABLET_USB_HANWANG=y
|
||||
CONFIG_TABLET_USB_KBTAB=y
|
||||
CONFIG_INPUT_MISC=y
|
||||
CONFIG_INPUT_KEYCHORD=y
|
||||
CONFIG_INPUT_UINPUT=y
|
||||
CONFIG_INPUT_GPIO=y
|
||||
# CONFIG_SERIO_SERPORT is not set
|
||||
CONFIG_SERIO_AMBAKMI=y
|
||||
# CONFIG_VT is not set
|
||||
# CONFIG_LEGACY_PTYS is not set
|
||||
# CONFIG_DEVMEM is not set
|
||||
# CONFIG_DEVKMEM is not set
|
||||
CONFIG_SERIAL_AMBA_PL011=y
|
||||
CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
|
||||
CONFIG_VIRTIO_CONSOLE=y
|
||||
# CONFIG_HW_RANDOM is not set
|
||||
# CONFIG_HWMON is not set
|
||||
CONFIG_MEDIA_SUPPORT=y
|
||||
CONFIG_FB=y
|
||||
CONFIG_FB_GOLDFISH=y
|
||||
CONFIG_FB_SIMPLE=y
|
||||
CONFIG_BACKLIGHT_LCD_SUPPORT=y
|
||||
CONFIG_LOGO=y
|
||||
# CONFIG_LOGO_LINUX_MONO is not set
|
||||
# CONFIG_LOGO_LINUX_VGA16 is not set
|
||||
CONFIG_SOUND=y
|
||||
CONFIG_SND=y
|
||||
CONFIG_HIDRAW=y
|
||||
CONFIG_UHID=y
|
||||
CONFIG_HID_A4TECH=y
|
||||
CONFIG_HID_ACRUX=y
|
||||
CONFIG_HID_ACRUX_FF=y
|
||||
CONFIG_HID_APPLE=y
|
||||
CONFIG_HID_BELKIN=y
|
||||
CONFIG_HID_CHERRY=y
|
||||
CONFIG_HID_CHICONY=y
|
||||
CONFIG_HID_PRODIKEYS=y
|
||||
CONFIG_HID_CYPRESS=y
|
||||
CONFIG_HID_DRAGONRISE=y
|
||||
CONFIG_DRAGONRISE_FF=y
|
||||
CONFIG_HID_EMS_FF=y
|
||||
CONFIG_HID_ELECOM=y
|
||||
CONFIG_HID_EZKEY=y
|
||||
CONFIG_HID_HOLTEK=y
|
||||
CONFIG_HID_KEYTOUCH=y
|
||||
CONFIG_HID_KYE=y
|
||||
CONFIG_HID_UCLOGIC=y
|
||||
CONFIG_HID_WALTOP=y
|
||||
CONFIG_HID_GYRATION=y
|
||||
CONFIG_HID_TWINHAN=y
|
||||
CONFIG_HID_KENSINGTON=y
|
||||
CONFIG_HID_LCPOWER=y
|
||||
CONFIG_HID_LOGITECH=y
|
||||
CONFIG_HID_LOGITECH_DJ=y
|
||||
CONFIG_LOGITECH_FF=y
|
||||
CONFIG_LOGIRUMBLEPAD2_FF=y
|
||||
CONFIG_LOGIG940_FF=y
|
||||
CONFIG_HID_MAGICMOUSE=y
|
||||
CONFIG_HID_MICROSOFT=y
|
||||
CONFIG_HID_MONTEREY=y
|
||||
CONFIG_HID_MULTITOUCH=y
|
||||
CONFIG_HID_NTRIG=y
|
||||
CONFIG_HID_ORTEK=y
|
||||
CONFIG_HID_PANTHERLORD=y
|
||||
CONFIG_PANTHERLORD_FF=y
|
||||
CONFIG_HID_PETALYNX=y
|
||||
CONFIG_HID_PICOLCD=y
|
||||
CONFIG_HID_PRIMAX=y
|
||||
CONFIG_HID_ROCCAT=y
|
||||
CONFIG_HID_SAITEK=y
|
||||
CONFIG_HID_SAMSUNG=y
|
||||
CONFIG_HID_SONY=y
|
||||
CONFIG_HID_SPEEDLINK=y
|
||||
CONFIG_HID_SUNPLUS=y
|
||||
CONFIG_HID_GREENASIA=y
|
||||
CONFIG_GREENASIA_FF=y
|
||||
CONFIG_HID_SMARTJOYPLUS=y
|
||||
CONFIG_SMARTJOYPLUS_FF=y
|
||||
CONFIG_HID_TIVO=y
|
||||
CONFIG_HID_TOPSEED=y
|
||||
CONFIG_HID_THRUSTMASTER=y
|
||||
CONFIG_HID_WACOM=y
|
||||
CONFIG_HID_WIIMOTE=y
|
||||
CONFIG_HID_ZEROPLUS=y
|
||||
CONFIG_HID_ZYDACRON=y
|
||||
CONFIG_USB_HIDDEV=y
|
||||
CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
|
||||
CONFIG_USB_EHCI_HCD=y
|
||||
CONFIG_USB_OTG_WAKELOCK=y
|
||||
CONFIG_RTC_CLASS=y
|
||||
CONFIG_RTC_DRV_PL031=y
|
||||
CONFIG_VIRTIO_MMIO=y
|
||||
CONFIG_STAGING=y
|
||||
CONFIG_ASHMEM=y
|
||||
CONFIG_ANDROID_LOW_MEMORY_KILLER=y
|
||||
CONFIG_SYNC=y
|
||||
CONFIG_SW_SYNC=y
|
||||
CONFIG_SW_SYNC_USER=y
|
||||
CONFIG_ION=y
|
||||
CONFIG_GOLDFISH_AUDIO=y
|
||||
CONFIG_GOLDFISH=y
|
||||
CONFIG_GOLDFISH_PIPE=y
|
||||
CONFIG_ANDROID=y
|
||||
CONFIG_ANDROID_BINDER_IPC=y
|
||||
CONFIG_EXT4_FS=y
|
||||
CONFIG_EXT4_FS_SECURITY=y
|
||||
CONFIG_QUOTA=y
|
||||
CONFIG_FUSE_FS=y
|
||||
CONFIG_CUSE=y
|
||||
CONFIG_MSDOS_FS=y
|
||||
CONFIG_VFAT_FS=y
|
||||
CONFIG_TMPFS=y
|
||||
CONFIG_TMPFS_POSIX_ACL=y
|
||||
CONFIG_PSTORE=y
|
||||
CONFIG_PSTORE_CONSOLE=y
|
||||
CONFIG_PSTORE_RAM=y
|
||||
CONFIG_NFS_FS=y
|
||||
CONFIG_ROOT_NFS=y
|
||||
CONFIG_NLS_CODEPAGE_437=y
|
||||
CONFIG_NLS_ISO8859_1=y
|
||||
CONFIG_DEBUG_INFO=y
|
||||
CONFIG_MAGIC_SYSRQ=y
|
||||
CONFIG_DETECT_HUNG_TASK=y
|
||||
CONFIG_PANIC_TIMEOUT=5
|
||||
# CONFIG_SCHED_DEBUG is not set
|
||||
CONFIG_SCHEDSTATS=y
|
||||
CONFIG_TIMER_STATS=y
|
||||
CONFIG_ENABLE_DEFAULT_TRACERS=y
|
||||
CONFIG_SECURITY=y
|
||||
CONFIG_SECURITY_NETWORK=y
|
||||
CONFIG_SECURITY_SELINUX=y
|
||||
CONFIG_VIRTUALIZATION=y
|
||||
@@ -94,6 +94,9 @@
|
||||
#define ARM_CPU_XSCALE_ARCH_V2 0x4000
|
||||
#define ARM_CPU_XSCALE_ARCH_V3 0x6000
|
||||
|
||||
/* Qualcomm implemented cores */
|
||||
#define ARM_CPU_PART_SCORPION 0x510002d0
|
||||
|
||||
extern unsigned int processor_id;
|
||||
|
||||
#ifdef CONFIG_CPU_CP15
|
||||
|
||||
33
arch/arm/include/asm/fiq_glue.h
Normal file
33
arch/arm/include/asm/fiq_glue.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Google, Inc.
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef __ASM_FIQ_GLUE_H
|
||||
#define __ASM_FIQ_GLUE_H
|
||||
|
||||
struct fiq_glue_handler {
|
||||
void (*fiq)(struct fiq_glue_handler *h, void *regs, void *svc_sp);
|
||||
void (*resume)(struct fiq_glue_handler *h);
|
||||
};
|
||||
typedef void (*fiq_return_handler_t)(void);
|
||||
|
||||
int fiq_glue_register_handler(struct fiq_glue_handler *handler);
|
||||
int fiq_glue_set_return_handler(fiq_return_handler_t fiq_return);
|
||||
int fiq_glue_clear_return_handler(fiq_return_handler_t fiq_return);
|
||||
|
||||
#ifdef CONFIG_FIQ_GLUE
|
||||
void fiq_glue_resume(void);
|
||||
#else
|
||||
static inline void fiq_glue_resume(void) {}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#ifdef CONFIG_ARM_CPU_TOPOLOGY
|
||||
|
||||
#include <linux/cpufreq.h>
|
||||
#include <linux/cpumask.h>
|
||||
|
||||
struct cputopo_arm {
|
||||
@@ -24,6 +25,12 @@ void init_cpu_topology(void);
|
||||
void store_cpu_topology(unsigned int cpuid);
|
||||
const struct cpumask *cpu_coregroup_mask(int cpu);
|
||||
|
||||
#ifdef CONFIG_CPU_FREQ
|
||||
#define arch_scale_freq_capacity cpufreq_scale_freq_capacity
|
||||
#endif
|
||||
#define arch_scale_cpu_capacity scale_cpu_capacity
|
||||
extern unsigned long scale_cpu_capacity(struct sched_domain *sd, int cpu);
|
||||
|
||||
#else
|
||||
|
||||
static inline void init_cpu_topology(void) { }
|
||||
|
||||
@@ -1066,6 +1066,22 @@ static int __init arch_hw_breakpoint_init(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Scorpion CPUs (at least those in APQ8060) seem to set DBGPRSR.SPD
|
||||
* whenever a WFI is issued, even if the core is not powered down, in
|
||||
* violation of the architecture. When DBGPRSR.SPD is set, accesses to
|
||||
* breakpoint and watchpoint registers are treated as undefined, so
|
||||
* this results in boot time and runtime failures when these are
|
||||
* accessed and we unexpectedly take a trap.
|
||||
*
|
||||
* It's not clear if/how this can be worked around, so we blacklist
|
||||
* Scorpion CPUs to avoid these issues.
|
||||
*/
|
||||
if (read_cpuid_part() == ARM_CPU_PART_SCORPION) {
|
||||
pr_info("Scorpion CPU detected. Hardware breakpoints and watchpoints disabled\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
has_ossr = core_has_os_save_restore();
|
||||
|
||||
/* Determine how many BRPs/WRPs are available. */
|
||||
|
||||
@@ -140,6 +140,8 @@ int kgdb_arch_handle_exception(int exception_vector, int signo,
|
||||
|
||||
static int kgdb_brk_fn(struct pt_regs *regs, unsigned int instr)
|
||||
{
|
||||
if (user_mode(regs))
|
||||
return -1;
|
||||
kgdb_handle_exception(1, SIGTRAP, 0, regs);
|
||||
|
||||
return 0;
|
||||
@@ -147,6 +149,8 @@ static int kgdb_brk_fn(struct pt_regs *regs, unsigned int instr)
|
||||
|
||||
static int kgdb_compiled_brk_fn(struct pt_regs *regs, unsigned int instr)
|
||||
{
|
||||
if (user_mode(regs))
|
||||
return -1;
|
||||
compiled_break = 1;
|
||||
kgdb_handle_exception(1, SIGTRAP, 0, regs);
|
||||
|
||||
|
||||
@@ -80,6 +80,7 @@ void arch_cpu_idle_prepare(void)
|
||||
|
||||
void arch_cpu_idle_enter(void)
|
||||
{
|
||||
idle_notifier_call_chain(IDLE_START);
|
||||
ledtrig_cpu(CPU_LED_IDLE_START);
|
||||
#ifdef CONFIG_PL310_ERRATA_769419
|
||||
wmb();
|
||||
@@ -89,6 +90,78 @@ void arch_cpu_idle_enter(void)
|
||||
void arch_cpu_idle_exit(void)
|
||||
{
|
||||
ledtrig_cpu(CPU_LED_IDLE_END);
|
||||
idle_notifier_call_chain(IDLE_END);
|
||||
}
|
||||
|
||||
/*
|
||||
* dump a block of kernel memory from around the given address
|
||||
*/
|
||||
static void show_data(unsigned long addr, int nbytes, const char *name)
|
||||
{
|
||||
int i, j;
|
||||
int nlines;
|
||||
u32 *p;
|
||||
|
||||
/*
|
||||
* don't attempt to dump non-kernel addresses or
|
||||
* values that are probably just small negative numbers
|
||||
*/
|
||||
if (addr < PAGE_OFFSET || addr > -256UL)
|
||||
return;
|
||||
|
||||
printk("\n%s: %#lx:\n", name, addr);
|
||||
|
||||
/*
|
||||
* round address down to a 32 bit boundary
|
||||
* and always dump a multiple of 32 bytes
|
||||
*/
|
||||
p = (u32 *)(addr & ~(sizeof(u32) - 1));
|
||||
nbytes += (addr & (sizeof(u32) - 1));
|
||||
nlines = (nbytes + 31) / 32;
|
||||
|
||||
|
||||
for (i = 0; i < nlines; i++) {
|
||||
/*
|
||||
* just display low 16 bits of address to keep
|
||||
* each line of the dump < 80 characters
|
||||
*/
|
||||
printk("%04lx ", (unsigned long)p & 0xffff);
|
||||
for (j = 0; j < 8; j++) {
|
||||
u32 data;
|
||||
if (probe_kernel_address(p, data)) {
|
||||
printk(" ********");
|
||||
} else {
|
||||
printk(" %08x", data);
|
||||
}
|
||||
++p;
|
||||
}
|
||||
printk("\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void show_extra_register_data(struct pt_regs *regs, int nbytes)
|
||||
{
|
||||
mm_segment_t fs;
|
||||
|
||||
fs = get_fs();
|
||||
set_fs(KERNEL_DS);
|
||||
show_data(regs->ARM_pc - nbytes, nbytes * 2, "PC");
|
||||
show_data(regs->ARM_lr - nbytes, nbytes * 2, "LR");
|
||||
show_data(regs->ARM_sp - nbytes, nbytes * 2, "SP");
|
||||
show_data(regs->ARM_ip - nbytes, nbytes * 2, "IP");
|
||||
show_data(regs->ARM_fp - nbytes, nbytes * 2, "FP");
|
||||
show_data(regs->ARM_r0 - nbytes, nbytes * 2, "R0");
|
||||
show_data(regs->ARM_r1 - nbytes, nbytes * 2, "R1");
|
||||
show_data(regs->ARM_r2 - nbytes, nbytes * 2, "R2");
|
||||
show_data(regs->ARM_r3 - nbytes, nbytes * 2, "R3");
|
||||
show_data(regs->ARM_r4 - nbytes, nbytes * 2, "R4");
|
||||
show_data(regs->ARM_r5 - nbytes, nbytes * 2, "R5");
|
||||
show_data(regs->ARM_r6 - nbytes, nbytes * 2, "R6");
|
||||
show_data(regs->ARM_r7 - nbytes, nbytes * 2, "R7");
|
||||
show_data(regs->ARM_r8 - nbytes, nbytes * 2, "R8");
|
||||
show_data(regs->ARM_r9 - nbytes, nbytes * 2, "R9");
|
||||
show_data(regs->ARM_r10 - nbytes, nbytes * 2, "R10");
|
||||
set_fs(fs);
|
||||
}
|
||||
|
||||
void __show_regs(struct pt_regs *regs)
|
||||
@@ -182,6 +255,8 @@ void __show_regs(struct pt_regs *regs)
|
||||
printk("Control: %08x%s\n", ctrl, buf);
|
||||
}
|
||||
#endif
|
||||
|
||||
show_extra_register_data(regs, 128);
|
||||
}
|
||||
|
||||
void show_regs(struct pt_regs * regs)
|
||||
|
||||
@@ -600,7 +600,7 @@ static int gpr_set(struct task_struct *target,
|
||||
const void *kbuf, const void __user *ubuf)
|
||||
{
|
||||
int ret;
|
||||
struct pt_regs newregs;
|
||||
struct pt_regs newregs = *task_pt_regs(target);
|
||||
|
||||
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
|
||||
&newregs,
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#include <linux/console.h>
|
||||
#include <linux/cpu.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/reboot.h>
|
||||
@@ -122,6 +123,31 @@ void machine_power_off(void)
|
||||
pm_power_off();
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ARM_FLUSH_CONSOLE_ON_RESTART
|
||||
void arm_machine_flush_console(void)
|
||||
{
|
||||
printk("\n");
|
||||
pr_emerg("Restarting %s\n", linux_banner);
|
||||
if (console_trylock()) {
|
||||
console_unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
mdelay(50);
|
||||
|
||||
local_irq_disable();
|
||||
if (!console_trylock())
|
||||
pr_emerg("arm_restart: Console was locked! Busting\n");
|
||||
else
|
||||
pr_emerg("arm_restart: Console was locked!\n");
|
||||
console_unlock();
|
||||
}
|
||||
#else
|
||||
void arm_machine_flush_console(void)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Restart requires that the secondary CPUs stop performing any activity
|
||||
* while the primary CPU resets the system. Systems with a single CPU can
|
||||
@@ -138,6 +164,10 @@ void machine_restart(char *cmd)
|
||||
local_irq_disable();
|
||||
smp_send_stop();
|
||||
|
||||
/* Flush the console to make sure all the relevant messages make it
|
||||
* out to the console drivers */
|
||||
arm_machine_flush_console();
|
||||
|
||||
if (arm_pm_restart)
|
||||
arm_pm_restart(reboot_mode, cmd);
|
||||
else
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
*/
|
||||
#include <linux/preempt.h>
|
||||
#include <linux/smp.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
#include <asm/smp_plat.h>
|
||||
#include <asm/tlbflush.h>
|
||||
@@ -40,8 +41,11 @@ static inline void ipi_flush_tlb_mm(void *arg)
|
||||
static inline void ipi_flush_tlb_page(void *arg)
|
||||
{
|
||||
struct tlb_args *ta = (struct tlb_args *)arg;
|
||||
unsigned int __ua_flags = uaccess_save_and_enable();
|
||||
|
||||
local_flush_tlb_page(ta->ta_vma, ta->ta_start);
|
||||
|
||||
uaccess_restore(__ua_flags);
|
||||
}
|
||||
|
||||
static inline void ipi_flush_tlb_kernel_page(void *arg)
|
||||
@@ -54,8 +58,11 @@ static inline void ipi_flush_tlb_kernel_page(void *arg)
|
||||
static inline void ipi_flush_tlb_range(void *arg)
|
||||
{
|
||||
struct tlb_args *ta = (struct tlb_args *)arg;
|
||||
unsigned int __ua_flags = uaccess_save_and_enable();
|
||||
|
||||
local_flush_tlb_range(ta->ta_vma, ta->ta_start, ta->ta_end);
|
||||
|
||||
uaccess_restore(__ua_flags);
|
||||
}
|
||||
|
||||
static inline void ipi_flush_tlb_kernel_range(void *arg)
|
||||
|
||||
@@ -42,9 +42,15 @@
|
||||
*/
|
||||
static DEFINE_PER_CPU(unsigned long, cpu_scale) = SCHED_CAPACITY_SCALE;
|
||||
|
||||
unsigned long arch_scale_cpu_capacity(struct sched_domain *sd, int cpu)
|
||||
unsigned long scale_cpu_capacity(struct sched_domain *sd, int cpu)
|
||||
{
|
||||
#ifdef CONFIG_CPU_FREQ
|
||||
unsigned long max_freq_scale = cpufreq_scale_max_freq_capacity(cpu);
|
||||
|
||||
return per_cpu(cpu_scale, cpu) * max_freq_scale >> SCHED_CAPACITY_SHIFT;
|
||||
#else
|
||||
return per_cpu(cpu_scale, cpu);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void set_capacity_scale(unsigned int cpu, unsigned long capacity)
|
||||
@@ -153,6 +159,8 @@ static void __init parse_dt_topology(void)
|
||||
|
||||
}
|
||||
|
||||
static const struct sched_group_energy * const cpu_core_energy(int cpu);
|
||||
|
||||
/*
|
||||
* Look for a customed capacity of a CPU in the cpu_capacity table during the
|
||||
* boot. The update of all CPUs is in O(n^2) for heteregeneous system but the
|
||||
@@ -160,10 +168,14 @@ static void __init parse_dt_topology(void)
|
||||
*/
|
||||
static void update_cpu_capacity(unsigned int cpu)
|
||||
{
|
||||
if (!cpu_capacity(cpu))
|
||||
return;
|
||||
unsigned long capacity = SCHED_CAPACITY_SCALE;
|
||||
|
||||
set_capacity_scale(cpu, cpu_capacity(cpu) / middle_capacity);
|
||||
if (cpu_core_energy(cpu)) {
|
||||
int max_cap_idx = cpu_core_energy(cpu)->nr_cap_states - 1;
|
||||
capacity = cpu_core_energy(cpu)->cap_states[max_cap_idx].cap;
|
||||
}
|
||||
|
||||
set_capacity_scale(cpu, capacity);
|
||||
|
||||
pr_info("CPU%u: update cpu_capacity %lu\n",
|
||||
cpu, arch_scale_cpu_capacity(NULL, cpu));
|
||||
@@ -275,17 +287,138 @@ void store_cpu_topology(unsigned int cpuid)
|
||||
cpu_topology[cpuid].socket_id, mpidr);
|
||||
}
|
||||
|
||||
/*
|
||||
* ARM TC2 specific energy cost model data. There are no unit requirements for
|
||||
* the data. Data can be normalized to any reference point, but the
|
||||
* normalization must be consistent. That is, one bogo-joule/watt must be the
|
||||
* same quantity for all data, but we don't care what it is.
|
||||
*/
|
||||
static struct idle_state idle_states_cluster_a7[] = {
|
||||
{ .power = 25 }, /* arch_cpu_idle() (active idle) = WFI */
|
||||
{ .power = 25 }, /* WFI */
|
||||
{ .power = 10 }, /* cluster-sleep-l */
|
||||
};
|
||||
|
||||
static struct idle_state idle_states_cluster_a15[] = {
|
||||
{ .power = 70 }, /* arch_cpu_idle() (active idle) = WFI */
|
||||
{ .power = 70 }, /* WFI */
|
||||
{ .power = 25 }, /* cluster-sleep-b */
|
||||
};
|
||||
|
||||
static struct capacity_state cap_states_cluster_a7[] = {
|
||||
/* Cluster only power */
|
||||
{ .cap = 150, .power = 2967, }, /* 350 MHz */
|
||||
{ .cap = 172, .power = 2792, }, /* 400 MHz */
|
||||
{ .cap = 215, .power = 2810, }, /* 500 MHz */
|
||||
{ .cap = 258, .power = 2815, }, /* 600 MHz */
|
||||
{ .cap = 301, .power = 2919, }, /* 700 MHz */
|
||||
{ .cap = 344, .power = 2847, }, /* 800 MHz */
|
||||
{ .cap = 387, .power = 3917, }, /* 900 MHz */
|
||||
{ .cap = 430, .power = 4905, }, /* 1000 MHz */
|
||||
};
|
||||
|
||||
static struct capacity_state cap_states_cluster_a15[] = {
|
||||
/* Cluster only power */
|
||||
{ .cap = 426, .power = 7920, }, /* 500 MHz */
|
||||
{ .cap = 512, .power = 8165, }, /* 600 MHz */
|
||||
{ .cap = 597, .power = 8172, }, /* 700 MHz */
|
||||
{ .cap = 682, .power = 8195, }, /* 800 MHz */
|
||||
{ .cap = 768, .power = 8265, }, /* 900 MHz */
|
||||
{ .cap = 853, .power = 8446, }, /* 1000 MHz */
|
||||
{ .cap = 938, .power = 11426, }, /* 1100 MHz */
|
||||
{ .cap = 1024, .power = 15200, }, /* 1200 MHz */
|
||||
};
|
||||
|
||||
static struct sched_group_energy energy_cluster_a7 = {
|
||||
.nr_idle_states = ARRAY_SIZE(idle_states_cluster_a7),
|
||||
.idle_states = idle_states_cluster_a7,
|
||||
.nr_cap_states = ARRAY_SIZE(cap_states_cluster_a7),
|
||||
.cap_states = cap_states_cluster_a7,
|
||||
};
|
||||
|
||||
static struct sched_group_energy energy_cluster_a15 = {
|
||||
.nr_idle_states = ARRAY_SIZE(idle_states_cluster_a15),
|
||||
.idle_states = idle_states_cluster_a15,
|
||||
.nr_cap_states = ARRAY_SIZE(cap_states_cluster_a15),
|
||||
.cap_states = cap_states_cluster_a15,
|
||||
};
|
||||
|
||||
static struct idle_state idle_states_core_a7[] = {
|
||||
{ .power = 0 }, /* arch_cpu_idle (active idle) = WFI */
|
||||
{ .power = 0 }, /* WFI */
|
||||
{ .power = 0 }, /* cluster-sleep-l */
|
||||
};
|
||||
|
||||
static struct idle_state idle_states_core_a15[] = {
|
||||
{ .power = 0 }, /* arch_cpu_idle (active idle) = WFI */
|
||||
{ .power = 0 }, /* WFI */
|
||||
{ .power = 0 }, /* cluster-sleep-b */
|
||||
};
|
||||
|
||||
static struct capacity_state cap_states_core_a7[] = {
|
||||
/* Power per cpu */
|
||||
{ .cap = 150, .power = 187, }, /* 350 MHz */
|
||||
{ .cap = 172, .power = 275, }, /* 400 MHz */
|
||||
{ .cap = 215, .power = 334, }, /* 500 MHz */
|
||||
{ .cap = 258, .power = 407, }, /* 600 MHz */
|
||||
{ .cap = 301, .power = 447, }, /* 700 MHz */
|
||||
{ .cap = 344, .power = 549, }, /* 800 MHz */
|
||||
{ .cap = 387, .power = 761, }, /* 900 MHz */
|
||||
{ .cap = 430, .power = 1024, }, /* 1000 MHz */
|
||||
};
|
||||
|
||||
static struct capacity_state cap_states_core_a15[] = {
|
||||
/* Power per cpu */
|
||||
{ .cap = 426, .power = 2021, }, /* 500 MHz */
|
||||
{ .cap = 512, .power = 2312, }, /* 600 MHz */
|
||||
{ .cap = 597, .power = 2756, }, /* 700 MHz */
|
||||
{ .cap = 682, .power = 3125, }, /* 800 MHz */
|
||||
{ .cap = 768, .power = 3524, }, /* 900 MHz */
|
||||
{ .cap = 853, .power = 3846, }, /* 1000 MHz */
|
||||
{ .cap = 938, .power = 5177, }, /* 1100 MHz */
|
||||
{ .cap = 1024, .power = 6997, }, /* 1200 MHz */
|
||||
};
|
||||
|
||||
static struct sched_group_energy energy_core_a7 = {
|
||||
.nr_idle_states = ARRAY_SIZE(idle_states_core_a7),
|
||||
.idle_states = idle_states_core_a7,
|
||||
.nr_cap_states = ARRAY_SIZE(cap_states_core_a7),
|
||||
.cap_states = cap_states_core_a7,
|
||||
};
|
||||
|
||||
static struct sched_group_energy energy_core_a15 = {
|
||||
.nr_idle_states = ARRAY_SIZE(idle_states_core_a15),
|
||||
.idle_states = idle_states_core_a15,
|
||||
.nr_cap_states = ARRAY_SIZE(cap_states_core_a15),
|
||||
.cap_states = cap_states_core_a15,
|
||||
};
|
||||
|
||||
/* sd energy functions */
|
||||
static inline
|
||||
const struct sched_group_energy * const cpu_cluster_energy(int cpu)
|
||||
{
|
||||
return cpu_topology[cpu].socket_id ? &energy_cluster_a7 :
|
||||
&energy_cluster_a15;
|
||||
}
|
||||
|
||||
static inline
|
||||
const struct sched_group_energy * const cpu_core_energy(int cpu)
|
||||
{
|
||||
return cpu_topology[cpu].socket_id ? &energy_core_a7 :
|
||||
&energy_core_a15;
|
||||
}
|
||||
|
||||
static inline int cpu_corepower_flags(void)
|
||||
{
|
||||
return SD_SHARE_PKG_RESOURCES | SD_SHARE_POWERDOMAIN;
|
||||
return SD_SHARE_PKG_RESOURCES | SD_SHARE_POWERDOMAIN | \
|
||||
SD_SHARE_CAP_STATES;
|
||||
}
|
||||
|
||||
static struct sched_domain_topology_level arm_topology[] = {
|
||||
#ifdef CONFIG_SCHED_MC
|
||||
{ cpu_corepower_mask, cpu_corepower_flags, SD_INIT_NAME(GMC) },
|
||||
{ cpu_coregroup_mask, cpu_core_flags, SD_INIT_NAME(MC) },
|
||||
{ cpu_coregroup_mask, cpu_corepower_flags, cpu_core_energy, SD_INIT_NAME(MC) },
|
||||
#endif
|
||||
{ cpu_cpu_mask, SD_INIT_NAME(DIE) },
|
||||
{ cpu_cpu_mask, NULL, cpu_cluster_energy, SD_INIT_NAME(DIE) },
|
||||
{ NULL, },
|
||||
};
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@ ENTRY(__get_user_4)
|
||||
ENDPROC(__get_user_4)
|
||||
|
||||
ENTRY(__get_user_8)
|
||||
check_uaccess r0, 8, r1, r2, __get_user_bad
|
||||
check_uaccess r0, 8, r1, r2, __get_user_bad8
|
||||
#ifdef CONFIG_THUMB2_KERNEL
|
||||
5: TUSER(ldr) r2, [r0]
|
||||
6: TUSER(ldr) r3, [r0, #4]
|
||||
|
||||
@@ -134,8 +134,8 @@ bool prcmu_pending_irq(void)
|
||||
*/
|
||||
bool prcmu_is_cpu_in_wfi(int cpu)
|
||||
{
|
||||
return readl(PRCM_ARM_WFI_STANDBY) & cpu ? PRCM_ARM_WFI_STANDBY_WFI1 :
|
||||
PRCM_ARM_WFI_STANDBY_WFI0;
|
||||
return readl(PRCM_ARM_WFI_STANDBY) &
|
||||
(cpu ? PRCM_ARM_WFI_STANDBY_WFI1 : PRCM_ARM_WFI_STANDBY_WFI0);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -270,6 +270,11 @@ v6_dma_clean_range:
|
||||
* - end - virtual end address of region
|
||||
*/
|
||||
ENTRY(v6_dma_flush_range)
|
||||
#ifdef CONFIG_CACHE_FLUSH_RANGE_LIMIT
|
||||
sub r2, r1, r0
|
||||
cmp r2, #CONFIG_CACHE_FLUSH_RANGE_LIMIT
|
||||
bhi v6_dma_flush_dcache_all
|
||||
#endif
|
||||
#ifdef CONFIG_DMA_CACHE_RWFO
|
||||
ldrb r2, [r0] @ read for ownership
|
||||
strb r2, [r0] @ write for ownership
|
||||
@@ -292,6 +297,18 @@ ENTRY(v6_dma_flush_range)
|
||||
mcr p15, 0, r0, c7, c10, 4 @ drain write buffer
|
||||
ret lr
|
||||
|
||||
#ifdef CONFIG_CACHE_FLUSH_RANGE_LIMIT
|
||||
v6_dma_flush_dcache_all:
|
||||
mov r0, #0
|
||||
#ifdef HARVARD_CACHE
|
||||
mcr p15, 0, r0, c7, c14, 0 @ D cache clean+invalidate
|
||||
#else
|
||||
mcr p15, 0, r0, c7, c15, 0 @ Cache clean+invalidate
|
||||
#endif
|
||||
mcr p15, 0, r0, c7, c10, 4 @ drain write buffer
|
||||
mov pc, lr
|
||||
#endif
|
||||
|
||||
/*
|
||||
* dma_map_area(start, size, dir)
|
||||
* - start - kernel virtual start address
|
||||
|
||||
@@ -273,10 +273,10 @@ do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
|
||||
local_irq_enable();
|
||||
|
||||
/*
|
||||
* If we're in an interrupt or have no user
|
||||
* If we're in an interrupt, or have no irqs, or have no user
|
||||
* context, we must not take the fault..
|
||||
*/
|
||||
if (faulthandler_disabled() || !mm)
|
||||
if (faulthandler_disabled() || irqs_disabled() || !mm)
|
||||
goto no_context;
|
||||
|
||||
if (user_mode(regs))
|
||||
@@ -610,9 +610,9 @@ static int __init early_abort_handler(unsigned long addr, unsigned int fsr,
|
||||
|
||||
void __init early_abt_enable(void)
|
||||
{
|
||||
fsr_info[22].fn = early_abort_handler;
|
||||
fsr_info[FSR_FS_AEA].fn = early_abort_handler;
|
||||
local_abt_enable();
|
||||
fsr_info[22].fn = do_bad;
|
||||
fsr_info[FSR_FS_AEA].fn = do_bad;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_ARM_LPAE
|
||||
|
||||
@@ -11,11 +11,15 @@
|
||||
#define FSR_FS5_0 (0x3f)
|
||||
|
||||
#ifdef CONFIG_ARM_LPAE
|
||||
#define FSR_FS_AEA 17
|
||||
|
||||
static inline int fsr_fs(unsigned int fsr)
|
||||
{
|
||||
return fsr & FSR_FS5_0;
|
||||
}
|
||||
#else
|
||||
#define FSR_FS_AEA 22
|
||||
|
||||
static inline int fsr_fs(unsigned int fsr)
|
||||
{
|
||||
return (fsr & FSR_FS3_0) | (fsr & FSR_FS4) >> 6;
|
||||
|
||||
@@ -790,6 +790,14 @@ config SETEND_EMULATION
|
||||
If unsure, say Y
|
||||
endif
|
||||
|
||||
config ARM64_SW_TTBR0_PAN
|
||||
bool "Emulate Privileged Access Never using TTBR0_EL1 switching"
|
||||
help
|
||||
Enabling this option prevents the kernel from accessing
|
||||
user-space memory directly by pointing TTBR0_EL1 to a reserved
|
||||
zeroed area and reserved ASID. The user access routines
|
||||
restore the valid TTBR0_EL1 temporarily.
|
||||
|
||||
menu "ARMv8.1 architectural features"
|
||||
|
||||
config ARM64_HW_AFDBM
|
||||
@@ -949,6 +957,23 @@ config CMDLINE
|
||||
entering them here. As a minimum, you should specify the the
|
||||
root device (e.g. root=/dev/nfs).
|
||||
|
||||
choice
|
||||
prompt "Kernel command line type" if CMDLINE != ""
|
||||
default CMDLINE_FROM_BOOTLOADER
|
||||
|
||||
config CMDLINE_FROM_BOOTLOADER
|
||||
bool "Use bootloader kernel arguments if available"
|
||||
help
|
||||
Uses the command-line options passed by the boot loader. If
|
||||
the boot loader doesn't provide any, the default kernel command
|
||||
string provided in CMDLINE will be used.
|
||||
|
||||
config CMDLINE_EXTEND
|
||||
bool "Extend bootloader kernel arguments"
|
||||
help
|
||||
The command-line arguments provided by the boot loader will be
|
||||
appended to the default kernel command string.
|
||||
|
||||
config CMDLINE_FORCE
|
||||
bool "Always use the default kernel command string"
|
||||
help
|
||||
@@ -956,6 +981,7 @@ config CMDLINE_FORCE
|
||||
loader passes other arguments to the kernel.
|
||||
This is useful if you cannot or don't want to change the
|
||||
command-line options your boot loader passes to the kernel.
|
||||
endchoice
|
||||
|
||||
config EFI_STUB
|
||||
bool
|
||||
@@ -988,6 +1014,21 @@ config DMI
|
||||
However, even with this option, the resultant kernel should
|
||||
continue to boot on existing non-UEFI platforms.
|
||||
|
||||
config BUILD_ARM64_APPENDED_DTB_IMAGE
|
||||
bool "Build a concatenated Image.gz/dtb by default"
|
||||
depends on OF
|
||||
help
|
||||
Enabling this option will cause a concatenated Image.gz and list of
|
||||
DTBs to be built by default (instead of a standalone Image.gz.)
|
||||
The image will built in arch/arm64/boot/Image.gz-dtb
|
||||
|
||||
config BUILD_ARM64_APPENDED_DTB_IMAGE_NAMES
|
||||
string "Default dtb names"
|
||||
depends on BUILD_ARM64_APPENDED_DTB_IMAGE
|
||||
help
|
||||
Space separated list of names of dtbs to append when
|
||||
building a concatenated Image.gz-dtb.
|
||||
|
||||
endmenu
|
||||
|
||||
menu "Userspace binary formats"
|
||||
|
||||
@@ -40,6 +40,7 @@ endif
|
||||
KBUILD_CFLAGS += -mgeneral-regs-only $(lseinstr)
|
||||
KBUILD_CFLAGS += -fno-asynchronous-unwind-tables
|
||||
KBUILD_CFLAGS += $(call cc-option, -mpc-relative-literal-loads)
|
||||
KBUILD_CFLAGS += -fno-pic
|
||||
KBUILD_AFLAGS += $(lseinstr)
|
||||
|
||||
ifeq ($(CONFIG_CPU_BIG_ENDIAN), y)
|
||||
@@ -94,7 +95,12 @@ libs-y := arch/arm64/lib/ $(libs-y)
|
||||
core-$(CONFIG_EFI_STUB) += $(objtree)/drivers/firmware/efi/libstub/lib.a
|
||||
|
||||
# Default target when executing plain make
|
||||
ifeq ($(CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE),y)
|
||||
KBUILD_IMAGE := Image.gz-dtb
|
||||
else
|
||||
KBUILD_IMAGE := Image.gz
|
||||
endif
|
||||
|
||||
KBUILD_DTBS := dtbs
|
||||
|
||||
all: $(KBUILD_IMAGE) $(KBUILD_DTBS)
|
||||
@@ -121,6 +127,9 @@ dtbs: prepare scripts
|
||||
dtbs_install:
|
||||
$(Q)$(MAKE) $(dtbinst)=$(boot)/dts
|
||||
|
||||
Image-dtb Image.gz-dtb: vmlinux scripts dtbs
|
||||
$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
|
||||
|
||||
PHONY += vdso_install
|
||||
vdso_install:
|
||||
$(Q)$(MAKE) $(build)=arch/arm64/kernel/vdso $@
|
||||
|
||||
2
arch/arm64/boot/.gitignore
vendored
2
arch/arm64/boot/.gitignore
vendored
@@ -1,2 +1,4 @@
|
||||
Image
|
||||
Image-dtb
|
||||
Image.gz
|
||||
Image.gz-dtb
|
||||
|
||||
@@ -14,16 +14,29 @@
|
||||
# Based on the ia64 boot/Makefile.
|
||||
#
|
||||
|
||||
include $(srctree)/arch/arm64/boot/dts/Makefile
|
||||
|
||||
OBJCOPYFLAGS_Image :=-O binary -R .note -R .note.gnu.build-id -R .comment -S
|
||||
|
||||
targets := Image Image.gz
|
||||
|
||||
DTB_NAMES := $(subst $\",,$(CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE_NAMES))
|
||||
ifneq ($(DTB_NAMES),)
|
||||
DTB_LIST := $(addsuffix .dtb,$(DTB_NAMES))
|
||||
else
|
||||
DTB_LIST := $(dtb-y)
|
||||
endif
|
||||
DTB_OBJS := $(addprefix $(obj)/dts/,$(DTB_LIST))
|
||||
|
||||
$(obj)/Image: vmlinux FORCE
|
||||
$(call if_changed,objcopy)
|
||||
|
||||
$(obj)/Image.bz2: $(obj)/Image FORCE
|
||||
$(call if_changed,bzip2)
|
||||
|
||||
$(obj)/Image-dtb: $(obj)/Image $(DTB_OBJS) FORCE
|
||||
$(call if_changed,cat)
|
||||
|
||||
$(obj)/Image.gz: $(obj)/Image FORCE
|
||||
$(call if_changed,gzip)
|
||||
|
||||
@@ -36,6 +49,9 @@ $(obj)/Image.lzma: $(obj)/Image FORCE
|
||||
$(obj)/Image.lzo: $(obj)/Image FORCE
|
||||
$(call if_changed,lzo)
|
||||
|
||||
$(obj)/Image.gz-dtb: $(obj)/Image.gz $(DTB_OBJS) FORCE
|
||||
$(call if_changed,cat)
|
||||
|
||||
install:
|
||||
$(CONFIG_SHELL) $(srctree)/$(src)/install.sh $(KERNELRELEASE) \
|
||||
$(obj)/Image System.map "$(INSTALL_PATH)"
|
||||
|
||||
@@ -28,3 +28,17 @@ dtstree := $(srctree)/$(src)
|
||||
dtb-$(CONFIG_OF_ALL_DTBS) := $(patsubst $(dtstree)/%.dts,%.dtb, $(foreach d,$(dts-dirs), $(wildcard $(dtstree)/$(d)/*.dts)))
|
||||
|
||||
always := $(dtb-y)
|
||||
|
||||
targets += dtbs
|
||||
|
||||
DTB_NAMES := $(subst $\",,$(CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE_NAMES))
|
||||
ifneq ($(DTB_NAMES),)
|
||||
DTB_LIST := $(addsuffix .dtb,$(DTB_NAMES))
|
||||
else
|
||||
DTB_LIST := $(dtb-y)
|
||||
endif
|
||||
targets += $(DTB_LIST)
|
||||
|
||||
dtbs: $(addprefix $(obj)/, $(DTB_LIST))
|
||||
|
||||
clean-files := dts/*.dtb *.dtb
|
||||
|
||||
312
arch/arm64/configs/ranchu64_defconfig
Normal file
312
arch/arm64/configs/ranchu64_defconfig
Normal file
@@ -0,0 +1,312 @@
|
||||
# CONFIG_LOCALVERSION_AUTO is not set
|
||||
# CONFIG_SWAP is not set
|
||||
CONFIG_POSIX_MQUEUE=y
|
||||
CONFIG_AUDIT=y
|
||||
CONFIG_NO_HZ=y
|
||||
CONFIG_HIGH_RES_TIMERS=y
|
||||
CONFIG_BSD_PROCESS_ACCT=y
|
||||
CONFIG_BSD_PROCESS_ACCT_V3=y
|
||||
CONFIG_TASKSTATS=y
|
||||
CONFIG_TASK_DELAY_ACCT=y
|
||||
CONFIG_TASK_XACCT=y
|
||||
CONFIG_TASK_IO_ACCOUNTING=y
|
||||
CONFIG_IKCONFIG=y
|
||||
CONFIG_IKCONFIG_PROC=y
|
||||
CONFIG_LOG_BUF_SHIFT=14
|
||||
CONFIG_CGROUP_DEBUG=y
|
||||
CONFIG_CGROUP_FREEZER=y
|
||||
CONFIG_CGROUP_CPUACCT=y
|
||||
CONFIG_RT_GROUP_SCHED=y
|
||||
CONFIG_SCHED_AUTOGROUP=y
|
||||
CONFIG_BLK_DEV_INITRD=y
|
||||
CONFIG_KALLSYMS_ALL=y
|
||||
CONFIG_EMBEDDED=y
|
||||
# CONFIG_COMPAT_BRK is not set
|
||||
CONFIG_PROFILING=y
|
||||
CONFIG_ARCH_MMAP_RND_BITS=24
|
||||
CONFIG_ARCH_MMAP_RND_COMPAT_BITS=16
|
||||
# CONFIG_BLK_DEV_BSG is not set
|
||||
# CONFIG_IOSCHED_DEADLINE is not set
|
||||
CONFIG_ARCH_VEXPRESS=y
|
||||
CONFIG_NR_CPUS=4
|
||||
CONFIG_PREEMPT=y
|
||||
CONFIG_KSM=y
|
||||
CONFIG_SECCOMP=y
|
||||
CONFIG_ARMV8_DEPRECATED=y
|
||||
CONFIG_SWP_EMULATION=y
|
||||
CONFIG_CP15_BARRIER_EMULATION=y
|
||||
CONFIG_SETEND_EMULATION=y
|
||||
CONFIG_CMDLINE="console=ttyAMA0"
|
||||
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
|
||||
CONFIG_COMPAT=y
|
||||
CONFIG_PM_AUTOSLEEP=y
|
||||
CONFIG_PM_WAKELOCKS=y
|
||||
CONFIG_PM_WAKELOCKS_LIMIT=0
|
||||
# CONFIG_PM_WAKELOCKS_GC is not set
|
||||
CONFIG_PM_DEBUG=y
|
||||
CONFIG_NET=y
|
||||
CONFIG_PACKET=y
|
||||
CONFIG_UNIX=y
|
||||
CONFIG_XFRM_USER=y
|
||||
CONFIG_NET_KEY=y
|
||||
CONFIG_INET=y
|
||||
CONFIG_INET_DIAG_DESTROY=y
|
||||
CONFIG_IP_MULTICAST=y
|
||||
CONFIG_IP_ADVANCED_ROUTER=y
|
||||
CONFIG_IP_MULTIPLE_TABLES=y
|
||||
CONFIG_IP_PNP=y
|
||||
CONFIG_IP_PNP_DHCP=y
|
||||
CONFIG_IP_PNP_BOOTP=y
|
||||
CONFIG_INET_ESP=y
|
||||
# CONFIG_INET_LRO is not set
|
||||
CONFIG_IPV6_ROUTER_PREF=y
|
||||
CONFIG_IPV6_ROUTE_INFO=y
|
||||
CONFIG_IPV6_OPTIMISTIC_DAD=y
|
||||
CONFIG_INET6_AH=y
|
||||
CONFIG_INET6_ESP=y
|
||||
CONFIG_INET6_IPCOMP=y
|
||||
CONFIG_IPV6_MIP6=y
|
||||
CONFIG_IPV6_MULTIPLE_TABLES=y
|
||||
CONFIG_NETFILTER=y
|
||||
CONFIG_NF_CONNTRACK=y
|
||||
CONFIG_NF_CONNTRACK_SECMARK=y
|
||||
CONFIG_NF_CONNTRACK_EVENTS=y
|
||||
CONFIG_NF_CT_PROTO_DCCP=y
|
||||
CONFIG_NF_CT_PROTO_SCTP=y
|
||||
CONFIG_NF_CT_PROTO_UDPLITE=y
|
||||
CONFIG_NF_CONNTRACK_AMANDA=y
|
||||
CONFIG_NF_CONNTRACK_FTP=y
|
||||
CONFIG_NF_CONNTRACK_H323=y
|
||||
CONFIG_NF_CONNTRACK_IRC=y
|
||||
CONFIG_NF_CONNTRACK_NETBIOS_NS=y
|
||||
CONFIG_NF_CONNTRACK_PPTP=y
|
||||
CONFIG_NF_CONNTRACK_SANE=y
|
||||
CONFIG_NF_CONNTRACK_TFTP=y
|
||||
CONFIG_NF_CT_NETLINK=y
|
||||
CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
|
||||
CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
|
||||
CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y
|
||||
CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y
|
||||
CONFIG_NETFILTER_XT_TARGET_MARK=y
|
||||
CONFIG_NETFILTER_XT_TARGET_NFLOG=y
|
||||
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
|
||||
CONFIG_NETFILTER_XT_TARGET_TPROXY=y
|
||||
CONFIG_NETFILTER_XT_TARGET_TRACE=y
|
||||
CONFIG_NETFILTER_XT_TARGET_SECMARK=y
|
||||
CONFIG_NETFILTER_XT_TARGET_TCPMSS=y
|
||||
CONFIG_NETFILTER_XT_MATCH_COMMENT=y
|
||||
CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
|
||||
CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
|
||||
CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
|
||||
CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y
|
||||
CONFIG_NETFILTER_XT_MATCH_HELPER=y
|
||||
CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
|
||||
CONFIG_NETFILTER_XT_MATCH_LENGTH=y
|
||||
CONFIG_NETFILTER_XT_MATCH_LIMIT=y
|
||||
CONFIG_NETFILTER_XT_MATCH_MAC=y
|
||||
CONFIG_NETFILTER_XT_MATCH_MARK=y
|
||||
CONFIG_NETFILTER_XT_MATCH_POLICY=y
|
||||
CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
|
||||
CONFIG_NETFILTER_XT_MATCH_QTAGUID=y
|
||||
CONFIG_NETFILTER_XT_MATCH_QUOTA=y
|
||||
CONFIG_NETFILTER_XT_MATCH_QUOTA2=y
|
||||
CONFIG_NETFILTER_XT_MATCH_SOCKET=y
|
||||
CONFIG_NETFILTER_XT_MATCH_STATE=y
|
||||
CONFIG_NETFILTER_XT_MATCH_STATISTIC=y
|
||||
CONFIG_NETFILTER_XT_MATCH_STRING=y
|
||||
CONFIG_NETFILTER_XT_MATCH_TIME=y
|
||||
CONFIG_NETFILTER_XT_MATCH_U32=y
|
||||
CONFIG_NF_CONNTRACK_IPV4=y
|
||||
CONFIG_IP_NF_IPTABLES=y
|
||||
CONFIG_IP_NF_MATCH_AH=y
|
||||
CONFIG_IP_NF_MATCH_ECN=y
|
||||
CONFIG_IP_NF_MATCH_RPFILTER=y
|
||||
CONFIG_IP_NF_MATCH_TTL=y
|
||||
CONFIG_IP_NF_FILTER=y
|
||||
CONFIG_IP_NF_TARGET_REJECT=y
|
||||
CONFIG_IP_NF_MANGLE=y
|
||||
CONFIG_IP_NF_TARGET_ECN=y
|
||||
CONFIG_IP_NF_TARGET_TTL=y
|
||||
CONFIG_IP_NF_RAW=y
|
||||
CONFIG_IP_NF_SECURITY=y
|
||||
CONFIG_IP_NF_ARPTABLES=y
|
||||
CONFIG_IP_NF_ARPFILTER=y
|
||||
CONFIG_IP_NF_ARP_MANGLE=y
|
||||
CONFIG_NF_CONNTRACK_IPV6=y
|
||||
CONFIG_IP6_NF_IPTABLES=y
|
||||
CONFIG_IP6_NF_MATCH_AH=y
|
||||
CONFIG_IP6_NF_MATCH_EUI64=y
|
||||
CONFIG_IP6_NF_MATCH_FRAG=y
|
||||
CONFIG_IP6_NF_MATCH_OPTS=y
|
||||
CONFIG_IP6_NF_MATCH_HL=y
|
||||
CONFIG_IP6_NF_MATCH_IPV6HEADER=y
|
||||
CONFIG_IP6_NF_MATCH_MH=y
|
||||
CONFIG_IP6_NF_MATCH_RT=y
|
||||
CONFIG_IP6_NF_TARGET_HL=y
|
||||
CONFIG_IP6_NF_FILTER=y
|
||||
CONFIG_IP6_NF_TARGET_REJECT=y
|
||||
CONFIG_IP6_NF_MANGLE=y
|
||||
CONFIG_IP6_NF_RAW=y
|
||||
CONFIG_BRIDGE=y
|
||||
CONFIG_NET_SCHED=y
|
||||
CONFIG_NET_SCH_HTB=y
|
||||
CONFIG_NET_CLS_U32=y
|
||||
CONFIG_NET_EMATCH=y
|
||||
CONFIG_NET_EMATCH_U32=y
|
||||
CONFIG_NET_CLS_ACT=y
|
||||
# CONFIG_WIRELESS is not set
|
||||
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
|
||||
CONFIG_BLK_DEV_LOOP=y
|
||||
CONFIG_BLK_DEV_RAM=y
|
||||
CONFIG_BLK_DEV_RAM_SIZE=8192
|
||||
CONFIG_VIRTIO_BLK=y
|
||||
CONFIG_SCSI=y
|
||||
# CONFIG_SCSI_PROC_FS is not set
|
||||
CONFIG_BLK_DEV_SD=y
|
||||
# CONFIG_SCSI_LOWLEVEL is not set
|
||||
CONFIG_MD=y
|
||||
CONFIG_BLK_DEV_DM=y
|
||||
CONFIG_DM_CRYPT=y
|
||||
CONFIG_DM_UEVENT=y
|
||||
CONFIG_DM_VERITY=y
|
||||
CONFIG_DM_VERITY_FEC=y
|
||||
CONFIG_NETDEVICES=y
|
||||
CONFIG_TUN=y
|
||||
CONFIG_VIRTIO_NET=y
|
||||
CONFIG_SMC91X=y
|
||||
CONFIG_PPP=y
|
||||
CONFIG_PPP_BSDCOMP=y
|
||||
CONFIG_PPP_DEFLATE=y
|
||||
CONFIG_PPP_MPPE=y
|
||||
CONFIG_PPPOLAC=y
|
||||
CONFIG_PPPOPNS=y
|
||||
# CONFIG_WLAN is not set
|
||||
CONFIG_INPUT_EVDEV=y
|
||||
CONFIG_INPUT_KEYRESET=y
|
||||
CONFIG_KEYBOARD_GOLDFISH_EVENTS=y
|
||||
# CONFIG_INPUT_MOUSE is not set
|
||||
CONFIG_INPUT_JOYSTICK=y
|
||||
CONFIG_INPUT_TABLET=y
|
||||
CONFIG_INPUT_MISC=y
|
||||
CONFIG_INPUT_KEYCHORD=y
|
||||
CONFIG_INPUT_UINPUT=y
|
||||
CONFIG_INPUT_GPIO=y
|
||||
# CONFIG_SERIO_SERPORT is not set
|
||||
# CONFIG_VT is not set
|
||||
# CONFIG_LEGACY_PTYS is not set
|
||||
# CONFIG_DEVMEM is not set
|
||||
# CONFIG_DEVKMEM is not set
|
||||
CONFIG_SERIAL_AMBA_PL011=y
|
||||
CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
|
||||
CONFIG_VIRTIO_CONSOLE=y
|
||||
# CONFIG_HW_RANDOM is not set
|
||||
CONFIG_BATTERY_GOLDFISH=y
|
||||
# CONFIG_HWMON is not set
|
||||
CONFIG_MEDIA_SUPPORT=y
|
||||
CONFIG_FB=y
|
||||
CONFIG_FB_GOLDFISH=y
|
||||
CONFIG_FB_SIMPLE=y
|
||||
CONFIG_BACKLIGHT_LCD_SUPPORT=y
|
||||
CONFIG_LOGO=y
|
||||
# CONFIG_LOGO_LINUX_MONO is not set
|
||||
# CONFIG_LOGO_LINUX_VGA16 is not set
|
||||
CONFIG_SOUND=y
|
||||
CONFIG_SND=y
|
||||
CONFIG_HIDRAW=y
|
||||
CONFIG_UHID=y
|
||||
CONFIG_HID_A4TECH=y
|
||||
CONFIG_HID_ACRUX=y
|
||||
CONFIG_HID_ACRUX_FF=y
|
||||
CONFIG_HID_APPLE=y
|
||||
CONFIG_HID_BELKIN=y
|
||||
CONFIG_HID_CHERRY=y
|
||||
CONFIG_HID_CHICONY=y
|
||||
CONFIG_HID_PRODIKEYS=y
|
||||
CONFIG_HID_CYPRESS=y
|
||||
CONFIG_HID_DRAGONRISE=y
|
||||
CONFIG_DRAGONRISE_FF=y
|
||||
CONFIG_HID_EMS_FF=y
|
||||
CONFIG_HID_ELECOM=y
|
||||
CONFIG_HID_EZKEY=y
|
||||
CONFIG_HID_KEYTOUCH=y
|
||||
CONFIG_HID_KYE=y
|
||||
CONFIG_HID_WALTOP=y
|
||||
CONFIG_HID_GYRATION=y
|
||||
CONFIG_HID_TWINHAN=y
|
||||
CONFIG_HID_KENSINGTON=y
|
||||
CONFIG_HID_LCPOWER=y
|
||||
CONFIG_HID_LOGITECH=y
|
||||
CONFIG_HID_LOGITECH_DJ=y
|
||||
CONFIG_LOGITECH_FF=y
|
||||
CONFIG_LOGIRUMBLEPAD2_FF=y
|
||||
CONFIG_LOGIG940_FF=y
|
||||
CONFIG_HID_MAGICMOUSE=y
|
||||
CONFIG_HID_MICROSOFT=y
|
||||
CONFIG_HID_MONTEREY=y
|
||||
CONFIG_HID_MULTITOUCH=y
|
||||
CONFIG_HID_ORTEK=y
|
||||
CONFIG_HID_PANTHERLORD=y
|
||||
CONFIG_PANTHERLORD_FF=y
|
||||
CONFIG_HID_PETALYNX=y
|
||||
CONFIG_HID_PICOLCD=y
|
||||
CONFIG_HID_PRIMAX=y
|
||||
CONFIG_HID_SAITEK=y
|
||||
CONFIG_HID_SAMSUNG=y
|
||||
CONFIG_HID_SPEEDLINK=y
|
||||
CONFIG_HID_SUNPLUS=y
|
||||
CONFIG_HID_GREENASIA=y
|
||||
CONFIG_GREENASIA_FF=y
|
||||
CONFIG_HID_SMARTJOYPLUS=y
|
||||
CONFIG_SMARTJOYPLUS_FF=y
|
||||
CONFIG_HID_TIVO=y
|
||||
CONFIG_HID_TOPSEED=y
|
||||
CONFIG_HID_THRUSTMASTER=y
|
||||
CONFIG_HID_WACOM=y
|
||||
CONFIG_HID_WIIMOTE=y
|
||||
CONFIG_HID_ZEROPLUS=y
|
||||
CONFIG_HID_ZYDACRON=y
|
||||
# CONFIG_USB_SUPPORT is not set
|
||||
CONFIG_RTC_CLASS=y
|
||||
CONFIG_VIRTIO_MMIO=y
|
||||
CONFIG_STAGING=y
|
||||
CONFIG_ASHMEM=y
|
||||
CONFIG_ANDROID_TIMED_GPIO=y
|
||||
CONFIG_ANDROID_LOW_MEMORY_KILLER=y
|
||||
CONFIG_SYNC=y
|
||||
CONFIG_SW_SYNC=y
|
||||
CONFIG_SW_SYNC_USER=y
|
||||
CONFIG_ION=y
|
||||
CONFIG_GOLDFISH_AUDIO=y
|
||||
CONFIG_GOLDFISH=y
|
||||
CONFIG_GOLDFISH_PIPE=y
|
||||
# CONFIG_IOMMU_SUPPORT is not set
|
||||
CONFIG_ANDROID=y
|
||||
CONFIG_ANDROID_BINDER_IPC=y
|
||||
CONFIG_EXT2_FS=y
|
||||
CONFIG_EXT4_FS=y
|
||||
CONFIG_EXT4_FS_SECURITY=y
|
||||
CONFIG_QUOTA=y
|
||||
CONFIG_FUSE_FS=y
|
||||
CONFIG_CUSE=y
|
||||
CONFIG_MSDOS_FS=y
|
||||
CONFIG_VFAT_FS=y
|
||||
CONFIG_TMPFS=y
|
||||
CONFIG_TMPFS_POSIX_ACL=y
|
||||
# CONFIG_MISC_FILESYSTEMS is not set
|
||||
CONFIG_NFS_FS=y
|
||||
CONFIG_ROOT_NFS=y
|
||||
CONFIG_NLS_CODEPAGE_437=y
|
||||
CONFIG_NLS_ISO8859_1=y
|
||||
CONFIG_DEBUG_INFO=y
|
||||
CONFIG_DEBUG_FS=y
|
||||
CONFIG_MAGIC_SYSRQ=y
|
||||
CONFIG_PANIC_TIMEOUT=5
|
||||
# CONFIG_SCHED_DEBUG is not set
|
||||
CONFIG_SCHEDSTATS=y
|
||||
CONFIG_TIMER_STATS=y
|
||||
# CONFIG_FTRACE is not set
|
||||
CONFIG_ATOMIC64_SELFTEST=y
|
||||
CONFIG_DEBUG_RODATA=y
|
||||
CONFIG_SECURITY=y
|
||||
CONFIG_SECURITY_NETWORK=y
|
||||
CONFIG_SECURITY_SELINUX=y
|
||||
@@ -193,15 +193,16 @@ AES_ENTRY(aes_cbc_encrypt)
|
||||
cbz w6, .Lcbcencloop
|
||||
|
||||
ld1 {v0.16b}, [x5] /* get iv */
|
||||
enc_prepare w3, x2, x5
|
||||
enc_prepare w3, x2, x6
|
||||
|
||||
.Lcbcencloop:
|
||||
ld1 {v1.16b}, [x1], #16 /* get next pt block */
|
||||
eor v0.16b, v0.16b, v1.16b /* ..and xor with iv */
|
||||
encrypt_block v0, w3, x2, x5, w6
|
||||
encrypt_block v0, w3, x2, x6, w7
|
||||
st1 {v0.16b}, [x0], #16
|
||||
subs w4, w4, #1
|
||||
bne .Lcbcencloop
|
||||
st1 {v0.16b}, [x5] /* return iv */
|
||||
ret
|
||||
AES_ENDPROC(aes_cbc_encrypt)
|
||||
|
||||
@@ -211,7 +212,7 @@ AES_ENTRY(aes_cbc_decrypt)
|
||||
cbz w6, .LcbcdecloopNx
|
||||
|
||||
ld1 {v7.16b}, [x5] /* get iv */
|
||||
dec_prepare w3, x2, x5
|
||||
dec_prepare w3, x2, x6
|
||||
|
||||
.LcbcdecloopNx:
|
||||
#if INTERLEAVE >= 2
|
||||
@@ -248,7 +249,7 @@ AES_ENTRY(aes_cbc_decrypt)
|
||||
.Lcbcdecloop:
|
||||
ld1 {v1.16b}, [x1], #16 /* get next ct block */
|
||||
mov v0.16b, v1.16b /* ...and copy to v0 */
|
||||
decrypt_block v0, w3, x2, x5, w6
|
||||
decrypt_block v0, w3, x2, x6, w7
|
||||
eor v0.16b, v0.16b, v7.16b /* xor with iv => pt */
|
||||
mov v7.16b, v1.16b /* ct is next iv */
|
||||
st1 {v0.16b}, [x0], #16
|
||||
@@ -256,6 +257,7 @@ AES_ENTRY(aes_cbc_decrypt)
|
||||
bne .Lcbcdecloop
|
||||
.Lcbcdecout:
|
||||
FRAME_POP
|
||||
st1 {v7.16b}, [x5] /* return iv */
|
||||
ret
|
||||
AES_ENDPROC(aes_cbc_decrypt)
|
||||
|
||||
@@ -267,24 +269,15 @@ AES_ENDPROC(aes_cbc_decrypt)
|
||||
|
||||
AES_ENTRY(aes_ctr_encrypt)
|
||||
FRAME_PUSH
|
||||
cbnz w6, .Lctrfirst /* 1st time around? */
|
||||
umov x5, v4.d[1] /* keep swabbed ctr in reg */
|
||||
rev x5, x5
|
||||
#if INTERLEAVE >= 2
|
||||
cmn w5, w4 /* 32 bit overflow? */
|
||||
bcs .Lctrinc
|
||||
add x5, x5, #1 /* increment BE ctr */
|
||||
b .LctrincNx
|
||||
#else
|
||||
b .Lctrinc
|
||||
#endif
|
||||
.Lctrfirst:
|
||||
cbz w6, .Lctrnotfirst /* 1st time around? */
|
||||
enc_prepare w3, x2, x6
|
||||
ld1 {v4.16b}, [x5]
|
||||
umov x5, v4.d[1] /* keep swabbed ctr in reg */
|
||||
rev x5, x5
|
||||
|
||||
.Lctrnotfirst:
|
||||
umov x8, v4.d[1] /* keep swabbed ctr in reg */
|
||||
rev x8, x8
|
||||
#if INTERLEAVE >= 2
|
||||
cmn w5, w4 /* 32 bit overflow? */
|
||||
cmn w8, w4 /* 32 bit overflow? */
|
||||
bcs .Lctrloop
|
||||
.LctrloopNx:
|
||||
subs w4, w4, #INTERLEAVE
|
||||
@@ -292,11 +285,11 @@ AES_ENTRY(aes_ctr_encrypt)
|
||||
#if INTERLEAVE == 2
|
||||
mov v0.8b, v4.8b
|
||||
mov v1.8b, v4.8b
|
||||
rev x7, x5
|
||||
add x5, x5, #1
|
||||
rev x7, x8
|
||||
add x8, x8, #1
|
||||
ins v0.d[1], x7
|
||||
rev x7, x5
|
||||
add x5, x5, #1
|
||||
rev x7, x8
|
||||
add x8, x8, #1
|
||||
ins v1.d[1], x7
|
||||
ld1 {v2.16b-v3.16b}, [x1], #32 /* get 2 input blocks */
|
||||
do_encrypt_block2x
|
||||
@@ -305,7 +298,7 @@ AES_ENTRY(aes_ctr_encrypt)
|
||||
st1 {v0.16b-v1.16b}, [x0], #32
|
||||
#else
|
||||
ldr q8, =0x30000000200000001 /* addends 1,2,3[,0] */
|
||||
dup v7.4s, w5
|
||||
dup v7.4s, w8
|
||||
mov v0.16b, v4.16b
|
||||
add v7.4s, v7.4s, v8.4s
|
||||
mov v1.16b, v4.16b
|
||||
@@ -323,18 +316,12 @@ AES_ENTRY(aes_ctr_encrypt)
|
||||
eor v2.16b, v7.16b, v2.16b
|
||||
eor v3.16b, v5.16b, v3.16b
|
||||
st1 {v0.16b-v3.16b}, [x0], #64
|
||||
add x5, x5, #INTERLEAVE
|
||||
add x8, x8, #INTERLEAVE
|
||||
#endif
|
||||
cbz w4, .LctroutNx
|
||||
.LctrincNx:
|
||||
rev x7, x5
|
||||
rev x7, x8
|
||||
ins v4.d[1], x7
|
||||
cbz w4, .Lctrout
|
||||
b .LctrloopNx
|
||||
.LctroutNx:
|
||||
sub x5, x5, #1
|
||||
rev x7, x5
|
||||
ins v4.d[1], x7
|
||||
b .Lctrout
|
||||
.Lctr1x:
|
||||
adds w4, w4, #INTERLEAVE
|
||||
beq .Lctrout
|
||||
@@ -342,30 +329,39 @@ AES_ENTRY(aes_ctr_encrypt)
|
||||
.Lctrloop:
|
||||
mov v0.16b, v4.16b
|
||||
encrypt_block v0, w3, x2, x6, w7
|
||||
|
||||
adds x8, x8, #1 /* increment BE ctr */
|
||||
rev x7, x8
|
||||
ins v4.d[1], x7
|
||||
bcs .Lctrcarry /* overflow? */
|
||||
|
||||
.Lctrcarrydone:
|
||||
subs w4, w4, #1
|
||||
bmi .Lctrhalfblock /* blocks < 0 means 1/2 block */
|
||||
ld1 {v3.16b}, [x1], #16
|
||||
eor v3.16b, v0.16b, v3.16b
|
||||
st1 {v3.16b}, [x0], #16
|
||||
beq .Lctrout
|
||||
.Lctrinc:
|
||||
adds x5, x5, #1 /* increment BE ctr */
|
||||
rev x7, x5
|
||||
ins v4.d[1], x7
|
||||
bcc .Lctrloop /* no overflow? */
|
||||
bne .Lctrloop
|
||||
|
||||
.Lctrout:
|
||||
st1 {v4.16b}, [x5] /* return next CTR value */
|
||||
FRAME_POP
|
||||
ret
|
||||
|
||||
.Lctrhalfblock:
|
||||
ld1 {v3.8b}, [x1]
|
||||
eor v3.8b, v0.8b, v3.8b
|
||||
st1 {v3.8b}, [x0]
|
||||
FRAME_POP
|
||||
ret
|
||||
|
||||
.Lctrcarry:
|
||||
umov x7, v4.d[0] /* load upper word of ctr */
|
||||
rev x7, x7 /* ... to handle the carry */
|
||||
add x7, x7, #1
|
||||
rev x7, x7
|
||||
ins v4.d[0], x7
|
||||
b .Lctrloop
|
||||
.Lctrhalfblock:
|
||||
ld1 {v3.8b}, [x1]
|
||||
eor v3.8b, v0.8b, v3.8b
|
||||
st1 {v3.8b}, [x0]
|
||||
.Lctrout:
|
||||
FRAME_POP
|
||||
ret
|
||||
b .Lctrcarrydone
|
||||
AES_ENDPROC(aes_ctr_encrypt)
|
||||
.ltorg
|
||||
|
||||
|
||||
@@ -41,6 +41,15 @@
|
||||
msr daifclr, #2
|
||||
.endm
|
||||
|
||||
.macro save_and_disable_irq, flags
|
||||
mrs \flags, daif
|
||||
msr daifset, #2
|
||||
.endm
|
||||
|
||||
.macro restore_irq, flags
|
||||
msr daif, \flags
|
||||
.endm
|
||||
|
||||
/*
|
||||
* Enable and disable debug exceptions.
|
||||
*/
|
||||
@@ -395,4 +404,24 @@ alternative_endif
|
||||
movk \reg, :abs_g0_nc:\val
|
||||
.endm
|
||||
|
||||
/*
|
||||
* Return the current thread_info.
|
||||
*/
|
||||
.macro get_thread_info, rd
|
||||
mrs \rd, sp_el0
|
||||
.endm
|
||||
|
||||
/*
|
||||
* Errata workaround post TTBR0_EL1 update.
|
||||
*/
|
||||
.macro post_ttbr0_update_workaround
|
||||
#ifdef CONFIG_CAVIUM_ERRATUM_27456
|
||||
alternative_if ARM64_WORKAROUND_CAVIUM_27456
|
||||
ic iallu
|
||||
dsb nsh
|
||||
isb
|
||||
alternative_else_nop_endif
|
||||
#endif
|
||||
.endm
|
||||
|
||||
#endif /* __ASM_ASSEMBLER_H */
|
||||
|
||||
@@ -208,6 +208,12 @@ static inline bool system_supports_mixed_endian_el0(void)
|
||||
return id_aa64mmfr0_mixed_endian_el0(read_system_reg(SYS_ID_AA64MMFR0_EL1));
|
||||
}
|
||||
|
||||
static inline bool system_uses_ttbr0_pan(void)
|
||||
{
|
||||
return IS_ENABLED(CONFIG_ARM64_SW_TTBR0_PAN) &&
|
||||
!cpus_have_cap(ARM64_HAS_PAN);
|
||||
}
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#ifndef _ASM_EFI_H
|
||||
#define _ASM_EFI_H
|
||||
|
||||
#include <asm/cpufeature.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/mmu_context.h>
|
||||
#include <asm/neon.h>
|
||||
@@ -75,7 +76,30 @@ static inline void efifb_setup_from_dmi(struct screen_info *si, const char *opt)
|
||||
|
||||
static inline void efi_set_pgd(struct mm_struct *mm)
|
||||
{
|
||||
switch_mm(NULL, mm, NULL);
|
||||
__switch_mm(mm);
|
||||
|
||||
if (system_uses_ttbr0_pan()) {
|
||||
if (mm != current->active_mm) {
|
||||
/*
|
||||
* Update the current thread's saved ttbr0 since it is
|
||||
* restored as part of a return from exception. Set
|
||||
* the hardware TTBR0_EL1 using cpu_switch_mm()
|
||||
* directly to enable potential errata workarounds.
|
||||
*/
|
||||
update_saved_ttbr0(current, mm);
|
||||
cpu_switch_mm(mm->pgd, mm);
|
||||
} else {
|
||||
/*
|
||||
* Defer the switch to the current thread's TTBR0_EL1
|
||||
* until uaccess_enable(). Restore the current
|
||||
* thread's saved ttbr0 corresponding to its active_mm
|
||||
* (if different from init_mm).
|
||||
*/
|
||||
cpu_set_reserved_ttbr0();
|
||||
if (current->active_mm != &init_mm)
|
||||
update_saved_ttbr0(current, current->active_mm);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void efi_virtmap_load(void);
|
||||
|
||||
@@ -21,15 +21,12 @@
|
||||
#include <linux/futex.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
#include <asm/alternative.h>
|
||||
#include <asm/cpufeature.h>
|
||||
#include <asm/errno.h>
|
||||
#include <asm/sysreg.h>
|
||||
|
||||
#define __futex_atomic_op(insn, ret, oldval, uaddr, tmp, oparg) \
|
||||
do { \
|
||||
uaccess_enable(); \
|
||||
asm volatile( \
|
||||
ALTERNATIVE("nop", SET_PSTATE_PAN(0), ARM64_HAS_PAN, \
|
||||
CONFIG_ARM64_PAN) \
|
||||
" prfm pstl1strm, %2\n" \
|
||||
"1: ldxr %w1, %2\n" \
|
||||
insn "\n" \
|
||||
@@ -44,11 +41,11 @@
|
||||
" .popsection\n" \
|
||||
_ASM_EXTABLE(1b, 4b) \
|
||||
_ASM_EXTABLE(2b, 4b) \
|
||||
ALTERNATIVE("nop", SET_PSTATE_PAN(1), ARM64_HAS_PAN, \
|
||||
CONFIG_ARM64_PAN) \
|
||||
: "=&r" (ret), "=&r" (oldval), "+Q" (*uaddr), "=&r" (tmp) \
|
||||
: "r" (oparg), "Ir" (-EFAULT) \
|
||||
: "memory")
|
||||
: "memory"); \
|
||||
uaccess_disable(); \
|
||||
} while (0)
|
||||
|
||||
static inline int
|
||||
futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
|
||||
@@ -118,8 +115,8 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
|
||||
if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
|
||||
return -EFAULT;
|
||||
|
||||
uaccess_enable();
|
||||
asm volatile("// futex_atomic_cmpxchg_inatomic\n"
|
||||
ALTERNATIVE("nop", SET_PSTATE_PAN(0), ARM64_HAS_PAN, CONFIG_ARM64_PAN)
|
||||
" prfm pstl1strm, %2\n"
|
||||
"1: ldxr %w1, %2\n"
|
||||
" sub %w3, %w1, %w4\n"
|
||||
@@ -134,10 +131,10 @@ ALTERNATIVE("nop", SET_PSTATE_PAN(0), ARM64_HAS_PAN, CONFIG_ARM64_PAN)
|
||||
" .popsection\n"
|
||||
_ASM_EXTABLE(1b, 4b)
|
||||
_ASM_EXTABLE(2b, 4b)
|
||||
ALTERNATIVE("nop", SET_PSTATE_PAN(1), ARM64_HAS_PAN, CONFIG_ARM64_PAN)
|
||||
: "+r" (ret), "=&r" (val), "+Q" (*uaddr), "=&r" (tmp)
|
||||
: "r" (oldval), "r" (newval), "Ir" (-EFAULT)
|
||||
: "memory");
|
||||
uaccess_disable();
|
||||
|
||||
*uval = val;
|
||||
return ret;
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#ifndef __ASM_KERNEL_PGTABLE_H
|
||||
#define __ASM_KERNEL_PGTABLE_H
|
||||
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/sparsemem.h>
|
||||
|
||||
/*
|
||||
@@ -54,6 +55,12 @@
|
||||
#define SWAPPER_DIR_SIZE (SWAPPER_PGTABLE_LEVELS * PAGE_SIZE)
|
||||
#define IDMAP_DIR_SIZE (IDMAP_PGTABLE_LEVELS * PAGE_SIZE)
|
||||
|
||||
#ifdef CONFIG_ARM64_SW_TTBR0_PAN
|
||||
#define RESERVED_TTBR0_SIZE (PAGE_SIZE)
|
||||
#else
|
||||
#define RESERVED_TTBR0_SIZE (0)
|
||||
#endif
|
||||
|
||||
/* Initial memory map size */
|
||||
#if ARM64_SWAPPER_USES_SECTION_MAPS
|
||||
#define SWAPPER_BLOCK_SHIFT SECTION_SHIFT
|
||||
|
||||
@@ -217,7 +217,7 @@ static inline void *phys_to_virt(phys_addr_t x)
|
||||
#define _virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
|
||||
#else
|
||||
#define __virt_to_pgoff(kaddr) (((u64)(kaddr) & ~PAGE_OFFSET) / PAGE_SIZE * sizeof(struct page))
|
||||
#define __page_to_voff(page) (((u64)(page) & ~VMEMMAP_START) * PAGE_SIZE / sizeof(struct page))
|
||||
#define __page_to_voff(kaddr) (((u64)(kaddr) & ~VMEMMAP_START) * PAGE_SIZE / sizeof(struct page))
|
||||
|
||||
#define page_to_virt(page) ((void *)((__page_to_voff(page)) | PAGE_OFFSET))
|
||||
#define virt_to_page(vaddr) ((struct page *)((__virt_to_pgoff(vaddr)) | VMEMMAP_START))
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <linux/sched.h>
|
||||
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/cpufeature.h>
|
||||
#include <asm/proc-fns.h>
|
||||
#include <asm-generic/mm_hooks.h>
|
||||
#include <asm/cputype.h>
|
||||
@@ -103,7 +104,7 @@ static inline void cpu_uninstall_idmap(void)
|
||||
local_flush_tlb_all();
|
||||
cpu_set_default_tcr_t0sz();
|
||||
|
||||
if (mm != &init_mm)
|
||||
if (mm != &init_mm && !system_uses_ttbr0_pan())
|
||||
cpu_switch_mm(mm->pgd, mm);
|
||||
}
|
||||
|
||||
@@ -163,21 +164,27 @@ enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* This is the actual mm switch as far as the scheduler
|
||||
* is concerned. No registers are touched. We avoid
|
||||
* calling the CPU specific function when the mm hasn't
|
||||
* actually changed.
|
||||
*/
|
||||
static inline void
|
||||
switch_mm(struct mm_struct *prev, struct mm_struct *next,
|
||||
struct task_struct *tsk)
|
||||
#ifdef CONFIG_ARM64_SW_TTBR0_PAN
|
||||
static inline void update_saved_ttbr0(struct task_struct *tsk,
|
||||
struct mm_struct *mm)
|
||||
{
|
||||
if (system_uses_ttbr0_pan()) {
|
||||
BUG_ON(mm->pgd == swapper_pg_dir);
|
||||
task_thread_info(tsk)->ttbr0 =
|
||||
virt_to_phys(mm->pgd) | ASID(mm) << 48;
|
||||
}
|
||||
}
|
||||
#else
|
||||
static inline void update_saved_ttbr0(struct task_struct *tsk,
|
||||
struct mm_struct *mm)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline void __switch_mm(struct mm_struct *next)
|
||||
{
|
||||
unsigned int cpu = smp_processor_id();
|
||||
|
||||
if (prev == next)
|
||||
return;
|
||||
|
||||
/*
|
||||
* init_mm.pgd does not contain any user mappings and it is always
|
||||
* active for kernel addresses in TTBR1. Just set the reserved TTBR0.
|
||||
@@ -190,8 +197,26 @@ switch_mm(struct mm_struct *prev, struct mm_struct *next,
|
||||
check_and_switch_context(next, cpu);
|
||||
}
|
||||
|
||||
static inline void
|
||||
switch_mm(struct mm_struct *prev, struct mm_struct *next,
|
||||
struct task_struct *tsk)
|
||||
{
|
||||
if (prev != next)
|
||||
__switch_mm(next);
|
||||
|
||||
/*
|
||||
* Update the saved TTBR0_EL1 of the scheduled-in task as the previous
|
||||
* value may have not been initialised yet (activate_mm caller) or the
|
||||
* ASID has changed since the last run (following the context switch
|
||||
* of another thread of the same process). Avoid setting the reserved
|
||||
* TTBR0_EL1 to swapper_pg_dir (init_mm; e.g. via idle_task_exit).
|
||||
*/
|
||||
if (next != &init_mm)
|
||||
update_saved_ttbr0(tsk, next);
|
||||
}
|
||||
|
||||
#define deactivate_mm(tsk,mm) do { } while (0)
|
||||
#define activate_mm(prev,next) switch_mm(prev, next, NULL)
|
||||
#define activate_mm(prev,next) switch_mm(prev, next, current)
|
||||
|
||||
void verify_cpu_asid_bits(void);
|
||||
|
||||
|
||||
@@ -48,6 +48,9 @@ struct thread_info {
|
||||
unsigned long flags; /* low level flags */
|
||||
mm_segment_t addr_limit; /* address limit */
|
||||
struct task_struct *task; /* main task structure */
|
||||
#ifdef CONFIG_ARM64_SW_TTBR0_PAN
|
||||
u64 ttbr0; /* saved TTBR0_EL1 */
|
||||
#endif
|
||||
int preempt_count; /* 0 => preemptable, <0 => bug */
|
||||
int cpu; /* cpu */
|
||||
};
|
||||
|
||||
@@ -31,6 +31,14 @@ int pcibus_to_node(struct pci_bus *bus);
|
||||
cpumask_of_node(pcibus_to_node(bus)))
|
||||
|
||||
#endif /* CONFIG_NUMA */
|
||||
struct sched_domain;
|
||||
#ifdef CONFIG_CPU_FREQ
|
||||
#define arch_scale_freq_capacity cpufreq_scale_freq_capacity
|
||||
extern unsigned long cpufreq_scale_freq_capacity(struct sched_domain *sd, int cpu);
|
||||
extern unsigned long cpufreq_scale_max_freq_capacity(int cpu);
|
||||
#endif
|
||||
#define arch_scale_cpu_capacity scale_cpu_capacity
|
||||
extern unsigned long scale_cpu_capacity(struct sched_domain *sd, int cpu);
|
||||
|
||||
#include <asm-generic/topology.h>
|
||||
|
||||
|
||||
@@ -18,6 +18,12 @@
|
||||
#ifndef __ASM_UACCESS_H
|
||||
#define __ASM_UACCESS_H
|
||||
|
||||
#include <asm/alternative.h>
|
||||
#include <asm/kernel-pgtable.h>
|
||||
#include <asm/sysreg.h>
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
/*
|
||||
* User space memory access functions
|
||||
*/
|
||||
@@ -26,10 +32,8 @@
|
||||
#include <linux/string.h>
|
||||
#include <linux/thread_info.h>
|
||||
|
||||
#include <asm/alternative.h>
|
||||
#include <asm/cpufeature.h>
|
||||
#include <asm/ptrace.h>
|
||||
#include <asm/sysreg.h>
|
||||
#include <asm/errno.h>
|
||||
#include <asm/memory.h>
|
||||
#include <asm/compiler.h>
|
||||
@@ -119,6 +123,99 @@ static inline void set_fs(mm_segment_t fs)
|
||||
" .long (" #from " - .), (" #to " - .)\n" \
|
||||
" .popsection\n"
|
||||
|
||||
/*
|
||||
* User access enabling/disabling.
|
||||
*/
|
||||
#ifdef CONFIG_ARM64_SW_TTBR0_PAN
|
||||
static inline void __uaccess_ttbr0_disable(void)
|
||||
{
|
||||
unsigned long ttbr;
|
||||
|
||||
/* reserved_ttbr0 placed at the end of swapper_pg_dir */
|
||||
ttbr = read_sysreg(ttbr1_el1) + SWAPPER_DIR_SIZE;
|
||||
write_sysreg(ttbr, ttbr0_el1);
|
||||
isb();
|
||||
}
|
||||
|
||||
static inline void __uaccess_ttbr0_enable(void)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
/*
|
||||
* Disable interrupts to avoid preemption between reading the 'ttbr0'
|
||||
* variable and the MSR. A context switch could trigger an ASID
|
||||
* roll-over and an update of 'ttbr0'.
|
||||
*/
|
||||
local_irq_save(flags);
|
||||
write_sysreg(current_thread_info()->ttbr0, ttbr0_el1);
|
||||
isb();
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
static inline bool uaccess_ttbr0_disable(void)
|
||||
{
|
||||
if (!system_uses_ttbr0_pan())
|
||||
return false;
|
||||
__uaccess_ttbr0_disable();
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool uaccess_ttbr0_enable(void)
|
||||
{
|
||||
if (!system_uses_ttbr0_pan())
|
||||
return false;
|
||||
__uaccess_ttbr0_enable();
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
static inline bool uaccess_ttbr0_disable(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool uaccess_ttbr0_enable(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
#define __uaccess_disable(alt) \
|
||||
do { \
|
||||
if (!uaccess_ttbr0_disable()) \
|
||||
asm(ALTERNATIVE("nop", SET_PSTATE_PAN(1), alt, \
|
||||
CONFIG_ARM64_PAN)); \
|
||||
} while (0)
|
||||
|
||||
#define __uaccess_enable(alt) \
|
||||
do { \
|
||||
if (!uaccess_ttbr0_enable()) \
|
||||
asm(ALTERNATIVE("nop", SET_PSTATE_PAN(0), alt, \
|
||||
CONFIG_ARM64_PAN)); \
|
||||
} while (0)
|
||||
|
||||
static inline void uaccess_disable(void)
|
||||
{
|
||||
__uaccess_disable(ARM64_HAS_PAN);
|
||||
}
|
||||
|
||||
static inline void uaccess_enable(void)
|
||||
{
|
||||
__uaccess_enable(ARM64_HAS_PAN);
|
||||
}
|
||||
|
||||
/*
|
||||
* These functions are no-ops when UAO is present.
|
||||
*/
|
||||
static inline void uaccess_disable_not_uao(void)
|
||||
{
|
||||
__uaccess_disable(ARM64_ALT_PAN_NOT_UAO);
|
||||
}
|
||||
|
||||
static inline void uaccess_enable_not_uao(void)
|
||||
{
|
||||
__uaccess_enable(ARM64_ALT_PAN_NOT_UAO);
|
||||
}
|
||||
|
||||
/*
|
||||
* The "__xxx" versions of the user access functions do not verify the address
|
||||
* space - it must have been done previously with a separate "access_ok()"
|
||||
@@ -146,8 +243,7 @@ static inline void set_fs(mm_segment_t fs)
|
||||
do { \
|
||||
unsigned long __gu_val; \
|
||||
__chk_user_ptr(ptr); \
|
||||
asm(ALTERNATIVE("nop", SET_PSTATE_PAN(0), ARM64_ALT_PAN_NOT_UAO,\
|
||||
CONFIG_ARM64_PAN)); \
|
||||
uaccess_enable_not_uao(); \
|
||||
switch (sizeof(*(ptr))) { \
|
||||
case 1: \
|
||||
__get_user_asm("ldrb", "ldtrb", "%w", __gu_val, (ptr), \
|
||||
@@ -168,9 +264,8 @@ do { \
|
||||
default: \
|
||||
BUILD_BUG(); \
|
||||
} \
|
||||
uaccess_disable_not_uao(); \
|
||||
(x) = (__force __typeof__(*(ptr)))__gu_val; \
|
||||
asm(ALTERNATIVE("nop", SET_PSTATE_PAN(1), ARM64_ALT_PAN_NOT_UAO,\
|
||||
CONFIG_ARM64_PAN)); \
|
||||
} while (0)
|
||||
|
||||
#define __get_user(x, ptr) \
|
||||
@@ -215,8 +310,7 @@ do { \
|
||||
do { \
|
||||
__typeof__(*(ptr)) __pu_val = (x); \
|
||||
__chk_user_ptr(ptr); \
|
||||
asm(ALTERNATIVE("nop", SET_PSTATE_PAN(0), ARM64_ALT_PAN_NOT_UAO,\
|
||||
CONFIG_ARM64_PAN)); \
|
||||
uaccess_enable_not_uao(); \
|
||||
switch (sizeof(*(ptr))) { \
|
||||
case 1: \
|
||||
__put_user_asm("strb", "sttrb", "%w", __pu_val, (ptr), \
|
||||
@@ -237,8 +331,7 @@ do { \
|
||||
default: \
|
||||
BUILD_BUG(); \
|
||||
} \
|
||||
asm(ALTERNATIVE("nop", SET_PSTATE_PAN(1), ARM64_ALT_PAN_NOT_UAO,\
|
||||
CONFIG_ARM64_PAN)); \
|
||||
uaccess_disable_not_uao(); \
|
||||
} while (0)
|
||||
|
||||
#define __put_user(x, ptr) \
|
||||
@@ -331,4 +424,66 @@ extern long strncpy_from_user(char *dest, const char __user *src, long count);
|
||||
extern __must_check long strlen_user(const char __user *str);
|
||||
extern __must_check long strnlen_user(const char __user *str, long n);
|
||||
|
||||
#else /* __ASSEMBLY__ */
|
||||
|
||||
#include <asm/assembler.h>
|
||||
|
||||
/*
|
||||
* User access enabling/disabling macros.
|
||||
*/
|
||||
#ifdef CONFIG_ARM64_SW_TTBR0_PAN
|
||||
.macro __uaccess_ttbr0_disable, tmp1
|
||||
mrs \tmp1, ttbr1_el1 // swapper_pg_dir
|
||||
add \tmp1, \tmp1, #SWAPPER_DIR_SIZE // reserved_ttbr0 at the end of swapper_pg_dir
|
||||
msr ttbr0_el1, \tmp1 // set reserved TTBR0_EL1
|
||||
isb
|
||||
.endm
|
||||
|
||||
.macro __uaccess_ttbr0_enable, tmp1
|
||||
get_thread_info \tmp1
|
||||
ldr \tmp1, [\tmp1, #TSK_TI_TTBR0] // load saved TTBR0_EL1
|
||||
msr ttbr0_el1, \tmp1 // set the non-PAN TTBR0_EL1
|
||||
isb
|
||||
.endm
|
||||
|
||||
.macro uaccess_ttbr0_disable, tmp1
|
||||
alternative_if_not ARM64_HAS_PAN
|
||||
__uaccess_ttbr0_disable \tmp1
|
||||
alternative_else_nop_endif
|
||||
.endm
|
||||
|
||||
.macro uaccess_ttbr0_enable, tmp1, tmp2
|
||||
alternative_if_not ARM64_HAS_PAN
|
||||
save_and_disable_irq \tmp2 // avoid preemption
|
||||
__uaccess_ttbr0_enable \tmp1
|
||||
restore_irq \tmp2
|
||||
alternative_else_nop_endif
|
||||
.endm
|
||||
#else
|
||||
.macro uaccess_ttbr0_disable, tmp1
|
||||
.endm
|
||||
|
||||
.macro uaccess_ttbr0_enable, tmp1, tmp2
|
||||
.endm
|
||||
#endif
|
||||
|
||||
/*
|
||||
* These macros are no-ops when UAO is present.
|
||||
*/
|
||||
.macro uaccess_disable_not_uao, tmp1
|
||||
uaccess_ttbr0_disable \tmp1
|
||||
alternative_if ARM64_ALT_PAN_NOT_UAO
|
||||
SET_PSTATE_PAN(1)
|
||||
alternative_else_nop_endif
|
||||
.endm
|
||||
|
||||
.macro uaccess_enable_not_uao, tmp1, tmp2
|
||||
uaccess_ttbr0_enable \tmp1, \tmp2
|
||||
alternative_if ARM64_ALT_PAN_NOT_UAO
|
||||
SET_PSTATE_PAN(0)
|
||||
alternative_else_nop_endif
|
||||
.endm
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#endif /* __ASM_UACCESS_H */
|
||||
|
||||
@@ -77,6 +77,7 @@ struct user_fpsimd_state {
|
||||
__uint128_t vregs[32];
|
||||
__u32 fpsr;
|
||||
__u32 fpcr;
|
||||
__u32 __reserved[2];
|
||||
};
|
||||
|
||||
struct user_hwdebug_state {
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/sysctl.h>
|
||||
|
||||
#include <asm/alternative.h>
|
||||
#include <asm/cpufeature.h>
|
||||
#include <asm/insn.h>
|
||||
#include <asm/opcodes.h>
|
||||
@@ -285,10 +284,10 @@ static void __init register_insn_emulation_sysctl(struct ctl_table *table)
|
||||
#define __SWP_LL_SC_LOOPS 4
|
||||
|
||||
#define __user_swpX_asm(data, addr, res, temp, temp2, B) \
|
||||
do { \
|
||||
uaccess_enable(); \
|
||||
__asm__ __volatile__( \
|
||||
" mov %w3, %w7\n" \
|
||||
ALTERNATIVE("nop", SET_PSTATE_PAN(0), ARM64_HAS_PAN, \
|
||||
CONFIG_ARM64_PAN) \
|
||||
"0: ldxr"B" %w2, [%4]\n" \
|
||||
"1: stxr"B" %w0, %w1, [%4]\n" \
|
||||
" cbz %w0, 2f\n" \
|
||||
@@ -306,12 +305,12 @@ static void __init register_insn_emulation_sysctl(struct ctl_table *table)
|
||||
" .popsection" \
|
||||
_ASM_EXTABLE(0b, 4b) \
|
||||
_ASM_EXTABLE(1b, 4b) \
|
||||
ALTERNATIVE("nop", SET_PSTATE_PAN(1), ARM64_HAS_PAN, \
|
||||
CONFIG_ARM64_PAN) \
|
||||
: "=&r" (res), "+r" (data), "=&r" (temp), "=&r" (temp2) \
|
||||
: "r" (addr), "i" (-EAGAIN), "i" (-EFAULT), \
|
||||
"i" (__SWP_LL_SC_LOOPS) \
|
||||
: "memory")
|
||||
: "memory"); \
|
||||
uaccess_disable(); \
|
||||
} while (0)
|
||||
|
||||
#define __user_swp_asm(data, addr, res, temp, temp2) \
|
||||
__user_swpX_asm(data, addr, res, temp, temp2, "")
|
||||
|
||||
@@ -41,6 +41,9 @@ int main(void)
|
||||
DEFINE(TI_ADDR_LIMIT, offsetof(struct thread_info, addr_limit));
|
||||
DEFINE(TI_TASK, offsetof(struct thread_info, task));
|
||||
DEFINE(TI_CPU, offsetof(struct thread_info, cpu));
|
||||
#ifdef CONFIG_ARM64_SW_TTBR0_PAN
|
||||
DEFINE(TSK_TI_TTBR0, offsetof(struct thread_info, ttbr0));
|
||||
#endif
|
||||
BLANK();
|
||||
DEFINE(THREAD_CPU_CONTEXT, offsetof(struct task_struct, thread.cpu_context));
|
||||
BLANK();
|
||||
|
||||
@@ -47,6 +47,7 @@ unsigned int compat_elf_hwcap2 __read_mostly;
|
||||
#endif
|
||||
|
||||
DECLARE_BITMAP(cpu_hwcaps, ARM64_NCAPS);
|
||||
EXPORT_SYMBOL(cpu_hwcaps);
|
||||
|
||||
DEFINE_STATIC_KEY_ARRAY_FALSE(cpu_hwcap_keys, ARM64_NCAPS);
|
||||
EXPORT_SYMBOL(cpu_hwcap_keys);
|
||||
|
||||
@@ -29,7 +29,9 @@
|
||||
#include <asm/esr.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/memory.h>
|
||||
#include <asm/ptrace.h>
|
||||
#include <asm/thread_info.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/unistd.h>
|
||||
|
||||
/*
|
||||
@@ -109,6 +111,32 @@
|
||||
mrs x22, elr_el1
|
||||
mrs x23, spsr_el1
|
||||
stp lr, x21, [sp, #S_LR]
|
||||
|
||||
#ifdef CONFIG_ARM64_SW_TTBR0_PAN
|
||||
/*
|
||||
* Set the TTBR0 PAN bit in SPSR. When the exception is taken from
|
||||
* EL0, there is no need to check the state of TTBR0_EL1 since
|
||||
* accesses are always enabled.
|
||||
* Note that the meaning of this bit differs from the ARMv8.1 PAN
|
||||
* feature as all TTBR0_EL1 accesses are disabled, not just those to
|
||||
* user mappings.
|
||||
*/
|
||||
alternative_if ARM64_HAS_PAN
|
||||
b 1f // skip TTBR0 PAN
|
||||
alternative_else_nop_endif
|
||||
|
||||
.if \el != 0
|
||||
mrs x21, ttbr0_el1
|
||||
tst x21, #0xffff << 48 // Check for the reserved ASID
|
||||
orr x23, x23, #PSR_PAN_BIT // Set the emulated PAN in the saved SPSR
|
||||
b.eq 1f // TTBR0 access already disabled
|
||||
and x23, x23, #~PSR_PAN_BIT // Clear the emulated PAN in the saved SPSR
|
||||
.endif
|
||||
|
||||
__uaccess_ttbr0_disable x21
|
||||
1:
|
||||
#endif
|
||||
|
||||
stp x22, x23, [sp, #S_PC]
|
||||
|
||||
/*
|
||||
@@ -147,6 +175,40 @@
|
||||
ldp x21, x22, [sp, #S_PC] // load ELR, SPSR
|
||||
.if \el == 0
|
||||
ct_user_enter
|
||||
.endif
|
||||
|
||||
#ifdef CONFIG_ARM64_SW_TTBR0_PAN
|
||||
/*
|
||||
* Restore access to TTBR0_EL1. If returning to EL0, no need for SPSR
|
||||
* PAN bit checking.
|
||||
*/
|
||||
alternative_if ARM64_HAS_PAN
|
||||
b 2f // skip TTBR0 PAN
|
||||
alternative_else_nop_endif
|
||||
|
||||
.if \el != 0
|
||||
tbnz x22, #22, 1f // Skip re-enabling TTBR0 access if the PSR_PAN_BIT is set
|
||||
.endif
|
||||
|
||||
__uaccess_ttbr0_enable x0
|
||||
|
||||
.if \el == 0
|
||||
/*
|
||||
* Enable errata workarounds only if returning to user. The only
|
||||
* workaround currently required for TTBR0_EL1 changes are for the
|
||||
* Cavium erratum 27456 (broadcast TLBI instructions may cause I-cache
|
||||
* corruption).
|
||||
*/
|
||||
post_ttbr0_update_workaround
|
||||
.endif
|
||||
1:
|
||||
.if \el != 0
|
||||
and x22, x22, #~PSR_PAN_BIT // ARMv8.0 CPUs do not understand this bit
|
||||
.endif
|
||||
2:
|
||||
#endif
|
||||
|
||||
.if \el == 0
|
||||
ldr x23, [sp, #S_SP] // load return stack pointer
|
||||
msr sp_el0, x23
|
||||
#ifdef CONFIG_ARM64_ERRATUM_845719
|
||||
@@ -162,6 +224,7 @@ alternative_if ARM64_WORKAROUND_845719
|
||||
alternative_else_nop_endif
|
||||
#endif
|
||||
.endif
|
||||
|
||||
msr elr_el1, x21 // set up the return data
|
||||
msr spsr_el1, x22
|
||||
ldp x0, x1, [sp, #16 * 0]
|
||||
@@ -184,10 +247,6 @@ alternative_else_nop_endif
|
||||
eret // return to kernel
|
||||
.endm
|
||||
|
||||
.macro get_thread_info, rd
|
||||
mrs \rd, sp_el0
|
||||
.endm
|
||||
|
||||
.macro irq_stack_entry
|
||||
mov x19, sp // preserve the original sp
|
||||
|
||||
@@ -624,7 +683,7 @@ el0_inv:
|
||||
mov x0, sp
|
||||
mov x1, #BAD_SYNC
|
||||
mov x2, x25
|
||||
bl bad_mode
|
||||
bl bad_el0_sync
|
||||
b ret_to_user
|
||||
ENDPROC(el0_sync)
|
||||
|
||||
|
||||
@@ -326,14 +326,14 @@ __create_page_tables:
|
||||
* dirty cache lines being evicted.
|
||||
*/
|
||||
adrp x0, idmap_pg_dir
|
||||
adrp x1, swapper_pg_dir + SWAPPER_DIR_SIZE
|
||||
adrp x1, swapper_pg_dir + SWAPPER_DIR_SIZE + RESERVED_TTBR0_SIZE
|
||||
bl __inval_cache_range
|
||||
|
||||
/*
|
||||
* Clear the idmap and swapper page tables.
|
||||
*/
|
||||
adrp x0, idmap_pg_dir
|
||||
adrp x6, swapper_pg_dir + SWAPPER_DIR_SIZE
|
||||
adrp x6, swapper_pg_dir + SWAPPER_DIR_SIZE + RESERVED_TTBR0_SIZE
|
||||
1: stp xzr, xzr, [x0], #16
|
||||
stp xzr, xzr, [x0], #16
|
||||
stp xzr, xzr, [x0], #16
|
||||
@@ -412,7 +412,7 @@ __create_page_tables:
|
||||
* tables again to remove any speculatively loaded cache lines.
|
||||
*/
|
||||
adrp x0, idmap_pg_dir
|
||||
adrp x1, swapper_pg_dir + SWAPPER_DIR_SIZE
|
||||
adrp x1, swapper_pg_dir + SWAPPER_DIR_SIZE + RESERVED_TTBR0_SIZE
|
||||
dmb sy
|
||||
bl __inval_cache_range
|
||||
|
||||
|
||||
@@ -166,6 +166,70 @@ void machine_restart(char *cmd)
|
||||
while (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* dump a block of kernel memory from around the given address
|
||||
*/
|
||||
static void show_data(unsigned long addr, int nbytes, const char *name)
|
||||
{
|
||||
int i, j;
|
||||
int nlines;
|
||||
u32 *p;
|
||||
|
||||
/*
|
||||
* don't attempt to dump non-kernel addresses or
|
||||
* values that are probably just small negative numbers
|
||||
*/
|
||||
if (addr < PAGE_OFFSET || addr > -256UL)
|
||||
return;
|
||||
|
||||
printk("\n%s: %#lx:\n", name, addr);
|
||||
|
||||
/*
|
||||
* round address down to a 32 bit boundary
|
||||
* and always dump a multiple of 32 bytes
|
||||
*/
|
||||
p = (u32 *)(addr & ~(sizeof(u32) - 1));
|
||||
nbytes += (addr & (sizeof(u32) - 1));
|
||||
nlines = (nbytes + 31) / 32;
|
||||
|
||||
|
||||
for (i = 0; i < nlines; i++) {
|
||||
/*
|
||||
* just display low 16 bits of address to keep
|
||||
* each line of the dump < 80 characters
|
||||
*/
|
||||
printk("%04lx ", (unsigned long)p & 0xffff);
|
||||
for (j = 0; j < 8; j++) {
|
||||
u32 data;
|
||||
if (probe_kernel_address(p, data)) {
|
||||
printk(" ********");
|
||||
} else {
|
||||
printk(" %08x", data);
|
||||
}
|
||||
++p;
|
||||
}
|
||||
printk("\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void show_extra_register_data(struct pt_regs *regs, int nbytes)
|
||||
{
|
||||
mm_segment_t fs;
|
||||
unsigned int i;
|
||||
|
||||
fs = get_fs();
|
||||
set_fs(KERNEL_DS);
|
||||
show_data(regs->pc - nbytes, nbytes * 2, "PC");
|
||||
show_data(regs->regs[30] - nbytes, nbytes * 2, "LR");
|
||||
show_data(regs->sp - nbytes, nbytes * 2, "SP");
|
||||
for (i = 0; i < 30; i++) {
|
||||
char name[4];
|
||||
snprintf(name, sizeof(name), "X%u", i);
|
||||
show_data(regs->regs[i] - nbytes, nbytes * 2, name);
|
||||
}
|
||||
set_fs(fs);
|
||||
}
|
||||
|
||||
void __show_regs(struct pt_regs *regs)
|
||||
{
|
||||
int i, top_reg;
|
||||
@@ -201,6 +265,8 @@ void __show_regs(struct pt_regs *regs)
|
||||
|
||||
pr_cont("\n");
|
||||
}
|
||||
if (!user_mode(regs))
|
||||
show_extra_register_data(regs, 128);
|
||||
printk("\n");
|
||||
}
|
||||
|
||||
|
||||
@@ -550,6 +550,8 @@ static int hw_break_set(struct task_struct *target,
|
||||
/* (address, ctrl) registers */
|
||||
limit = regset->n * regset->size;
|
||||
while (count && offset < limit) {
|
||||
if (count < PTRACE_HBP_ADDR_SZ)
|
||||
return -EINVAL;
|
||||
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &addr,
|
||||
offset, offset + PTRACE_HBP_ADDR_SZ);
|
||||
if (ret)
|
||||
@@ -559,6 +561,8 @@ static int hw_break_set(struct task_struct *target,
|
||||
return ret;
|
||||
offset += PTRACE_HBP_ADDR_SZ;
|
||||
|
||||
if (!count)
|
||||
break;
|
||||
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &ctrl,
|
||||
offset, offset + PTRACE_HBP_CTRL_SZ);
|
||||
if (ret)
|
||||
@@ -595,7 +599,7 @@ static int gpr_set(struct task_struct *target, const struct user_regset *regset,
|
||||
const void *kbuf, const void __user *ubuf)
|
||||
{
|
||||
int ret;
|
||||
struct user_pt_regs newregs;
|
||||
struct user_pt_regs newregs = task_pt_regs(target)->user_regs;
|
||||
|
||||
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &newregs, 0, -1);
|
||||
if (ret)
|
||||
@@ -625,7 +629,8 @@ static int fpr_set(struct task_struct *target, const struct user_regset *regset,
|
||||
const void *kbuf, const void __user *ubuf)
|
||||
{
|
||||
int ret;
|
||||
struct user_fpsimd_state newstate;
|
||||
struct user_fpsimd_state newstate =
|
||||
target->thread.fpsimd_state.user_fpsimd;
|
||||
|
||||
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &newstate, 0, -1);
|
||||
if (ret)
|
||||
@@ -649,7 +654,7 @@ static int tls_set(struct task_struct *target, const struct user_regset *regset,
|
||||
const void *kbuf, const void __user *ubuf)
|
||||
{
|
||||
int ret;
|
||||
unsigned long tls;
|
||||
unsigned long tls = target->thread.tp_value;
|
||||
|
||||
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &tls, 0, -1);
|
||||
if (ret)
|
||||
@@ -675,7 +680,8 @@ static int system_call_set(struct task_struct *target,
|
||||
unsigned int pos, unsigned int count,
|
||||
const void *kbuf, const void __user *ubuf)
|
||||
{
|
||||
int syscallno, ret;
|
||||
int syscallno = task_pt_regs(target)->syscallno;
|
||||
int ret;
|
||||
|
||||
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &syscallno, 0, -1);
|
||||
if (ret)
|
||||
@@ -947,7 +953,7 @@ static int compat_tls_set(struct task_struct *target,
|
||||
const void __user *ubuf)
|
||||
{
|
||||
int ret;
|
||||
compat_ulong_t tls;
|
||||
compat_ulong_t tls = target->thread.tp_value;
|
||||
|
||||
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &tls, 0, -1);
|
||||
if (ret)
|
||||
|
||||
@@ -291,6 +291,15 @@ void __init setup_arch(char **cmdline_p)
|
||||
smp_init_cpus();
|
||||
smp_build_mpidr_hash();
|
||||
|
||||
#ifdef CONFIG_ARM64_SW_TTBR0_PAN
|
||||
/*
|
||||
* Make sure init_thread_info.ttbr0 always generates translation
|
||||
* faults in case uaccess_enable() is inadvertently called by the init
|
||||
* thread.
|
||||
*/
|
||||
init_thread_info.ttbr0 = virt_to_phys(empty_zero_page);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_VT
|
||||
#if defined(CONFIG_VGA_CONSOLE)
|
||||
conswitchp = &vga_con;
|
||||
|
||||
@@ -19,10 +19,30 @@
|
||||
#include <linux/nodemask.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/sched_energy.h>
|
||||
|
||||
#include <asm/cputype.h>
|
||||
#include <asm/topology.h>
|
||||
|
||||
static DEFINE_PER_CPU(unsigned long, cpu_scale) = SCHED_CAPACITY_SCALE;
|
||||
|
||||
unsigned long scale_cpu_capacity(struct sched_domain *sd, int cpu)
|
||||
{
|
||||
#ifdef CONFIG_CPU_FREQ
|
||||
unsigned long max_freq_scale = cpufreq_scale_max_freq_capacity(cpu);
|
||||
|
||||
return per_cpu(cpu_scale, cpu) * max_freq_scale >> SCHED_CAPACITY_SHIFT;
|
||||
#else
|
||||
return per_cpu(cpu_scale, cpu);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void set_capacity_scale(unsigned int cpu, unsigned long capacity)
|
||||
{
|
||||
per_cpu(cpu_scale, cpu) = capacity;
|
||||
}
|
||||
|
||||
static int __init get_cpu_for_node(struct device_node *node)
|
||||
{
|
||||
struct device_node *cpu_node;
|
||||
@@ -206,11 +226,67 @@ out:
|
||||
struct cpu_topology cpu_topology[NR_CPUS];
|
||||
EXPORT_SYMBOL_GPL(cpu_topology);
|
||||
|
||||
/* sd energy functions */
|
||||
static inline
|
||||
const struct sched_group_energy * const cpu_cluster_energy(int cpu)
|
||||
{
|
||||
struct sched_group_energy *sge = sge_array[cpu][SD_LEVEL1];
|
||||
|
||||
if (!sge) {
|
||||
pr_warn("Invalid sched_group_energy for Cluster%d\n", cpu);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return sge;
|
||||
}
|
||||
|
||||
static inline
|
||||
const struct sched_group_energy * const cpu_core_energy(int cpu)
|
||||
{
|
||||
struct sched_group_energy *sge = sge_array[cpu][SD_LEVEL0];
|
||||
|
||||
if (!sge) {
|
||||
pr_warn("Invalid sched_group_energy for CPU%d\n", cpu);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return sge;
|
||||
}
|
||||
|
||||
const struct cpumask *cpu_coregroup_mask(int cpu)
|
||||
{
|
||||
return &cpu_topology[cpu].core_sibling;
|
||||
}
|
||||
|
||||
static inline int cpu_corepower_flags(void)
|
||||
{
|
||||
return SD_SHARE_PKG_RESOURCES | SD_SHARE_POWERDOMAIN | \
|
||||
SD_SHARE_CAP_STATES;
|
||||
}
|
||||
|
||||
static struct sched_domain_topology_level arm64_topology[] = {
|
||||
#ifdef CONFIG_SCHED_MC
|
||||
{ cpu_coregroup_mask, cpu_corepower_flags, cpu_core_energy, SD_INIT_NAME(MC) },
|
||||
#endif
|
||||
{ cpu_cpu_mask, NULL, cpu_cluster_energy, SD_INIT_NAME(DIE) },
|
||||
{ NULL, },
|
||||
};
|
||||
|
||||
static void update_cpu_capacity(unsigned int cpu)
|
||||
{
|
||||
unsigned long capacity = SCHED_CAPACITY_SCALE;
|
||||
|
||||
if (cpu_core_energy(cpu)) {
|
||||
int max_cap_idx = cpu_core_energy(cpu)->nr_cap_states - 1;
|
||||
capacity = cpu_core_energy(cpu)->cap_states[max_cap_idx].cap;
|
||||
}
|
||||
|
||||
set_capacity_scale(cpu, capacity);
|
||||
|
||||
pr_info("CPU%d: update cpu_capacity %lu\n",
|
||||
cpu, arch_scale_cpu_capacity(NULL, cpu));
|
||||
}
|
||||
|
||||
static void update_siblings_masks(unsigned int cpuid)
|
||||
{
|
||||
struct cpu_topology *cpu_topo, *cpuid_topo = &cpu_topology[cpuid];
|
||||
@@ -272,6 +348,7 @@ void store_cpu_topology(unsigned int cpuid)
|
||||
|
||||
topology_populated:
|
||||
update_siblings_masks(cpuid);
|
||||
update_cpu_capacity(cpuid);
|
||||
}
|
||||
|
||||
static void __init reset_cpu_topology(void)
|
||||
@@ -302,4 +379,8 @@ void __init init_cpu_topology(void)
|
||||
*/
|
||||
if (of_have_populated_dt() && parse_dt_topology())
|
||||
reset_cpu_topology();
|
||||
else
|
||||
set_sched_topology(arm64_topology);
|
||||
|
||||
init_sched_energy_costs();
|
||||
}
|
||||
|
||||
@@ -435,9 +435,10 @@ int cpu_enable_cache_maint_trap(void *__unused)
|
||||
}
|
||||
|
||||
#define __user_cache_maint(insn, address, res) \
|
||||
if (untagged_addr(address) >= user_addr_max()) \
|
||||
if (untagged_addr(address) >= user_addr_max()) { \
|
||||
res = -EFAULT; \
|
||||
else \
|
||||
} else { \
|
||||
uaccess_ttbr0_enable(); \
|
||||
asm volatile ( \
|
||||
"1: " insn ", %1\n" \
|
||||
" mov %w0, #0\n" \
|
||||
@@ -449,7 +450,9 @@ int cpu_enable_cache_maint_trap(void *__unused)
|
||||
" .popsection\n" \
|
||||
_ASM_EXTABLE(1b, 3b) \
|
||||
: "=r" (res) \
|
||||
: "r" (address), "i" (-EFAULT) )
|
||||
: "r" (address), "i" (-EFAULT)); \
|
||||
uaccess_ttbr0_disable(); \
|
||||
}
|
||||
|
||||
static void user_cache_maint_handler(unsigned int esr, struct pt_regs *regs)
|
||||
{
|
||||
@@ -596,17 +599,34 @@ const char *esr_get_class_string(u32 esr)
|
||||
}
|
||||
|
||||
/*
|
||||
* bad_mode handles the impossible case in the exception vector.
|
||||
* bad_mode handles the impossible case in the exception vector. This is always
|
||||
* fatal.
|
||||
*/
|
||||
asmlinkage void bad_mode(struct pt_regs *regs, int reason, unsigned int esr)
|
||||
{
|
||||
siginfo_t info;
|
||||
void __user *pc = (void __user *)instruction_pointer(regs);
|
||||
console_verbose();
|
||||
|
||||
pr_crit("Bad mode in %s handler detected on CPU%d, code 0x%08x -- %s\n",
|
||||
handler[reason], smp_processor_id(), esr,
|
||||
esr_get_class_string(esr));
|
||||
|
||||
die("Oops - bad mode", regs, 0);
|
||||
local_irq_disable();
|
||||
panic("bad mode");
|
||||
}
|
||||
|
||||
/*
|
||||
* bad_el0_sync handles unexpected, but potentially recoverable synchronous
|
||||
* exceptions taken from EL0. Unlike bad_mode, this returns.
|
||||
*/
|
||||
asmlinkage void bad_el0_sync(struct pt_regs *regs, int reason, unsigned int esr)
|
||||
{
|
||||
siginfo_t info;
|
||||
void __user *pc = (void __user *)instruction_pointer(regs);
|
||||
console_verbose();
|
||||
|
||||
pr_crit("Bad EL0 synchronous exception detected on CPU%d, code 0x%08x -- %s\n",
|
||||
smp_processor_id(), esr, esr_get_class_string(esr));
|
||||
__show_regs(regs);
|
||||
|
||||
info.si_signo = SIGILL;
|
||||
@@ -614,7 +634,10 @@ asmlinkage void bad_mode(struct pt_regs *regs, int reason, unsigned int esr)
|
||||
info.si_code = ILL_ILLOPC;
|
||||
info.si_addr = pc;
|
||||
|
||||
arm64_notify_die("Oops - bad mode", regs, &info, 0);
|
||||
current->thread.fault_address = 0;
|
||||
current->thread.fault_code = 0;
|
||||
|
||||
force_sig_info(info.si_signo, &info, current);
|
||||
}
|
||||
|
||||
void __pte_error(const char *file, int line, unsigned long val)
|
||||
|
||||
@@ -216,6 +216,11 @@ SECTIONS
|
||||
swapper_pg_dir = .;
|
||||
. += SWAPPER_DIR_SIZE;
|
||||
|
||||
#ifdef CONFIG_ARM64_SW_TTBR0_PAN
|
||||
reserved_ttbr0 = .;
|
||||
. += RESERVED_TTBR0_SIZE;
|
||||
#endif
|
||||
|
||||
_end = .;
|
||||
|
||||
STABS_DEBUG
|
||||
|
||||
@@ -17,10 +17,7 @@
|
||||
*/
|
||||
#include <linux/linkage.h>
|
||||
|
||||
#include <asm/alternative.h>
|
||||
#include <asm/assembler.h>
|
||||
#include <asm/cpufeature.h>
|
||||
#include <asm/sysreg.h>
|
||||
#include <asm/uaccess.h>
|
||||
|
||||
.text
|
||||
|
||||
@@ -33,8 +30,7 @@
|
||||
* Alignment fixed up by hardware.
|
||||
*/
|
||||
ENTRY(__clear_user)
|
||||
ALTERNATIVE("nop", __stringify(SET_PSTATE_PAN(0)), ARM64_ALT_PAN_NOT_UAO, \
|
||||
CONFIG_ARM64_PAN)
|
||||
uaccess_enable_not_uao x2, x3
|
||||
mov x2, x1 // save the size for fixup return
|
||||
subs x1, x1, #8
|
||||
b.mi 2f
|
||||
@@ -54,8 +50,7 @@ uao_user_alternative 9f, strh, sttrh, wzr, x0, 2
|
||||
b.mi 5f
|
||||
uao_user_alternative 9f, strb, sttrb, wzr, x0, 0
|
||||
5: mov x0, #0
|
||||
ALTERNATIVE("nop", __stringify(SET_PSTATE_PAN(1)), ARM64_ALT_PAN_NOT_UAO, \
|
||||
CONFIG_ARM64_PAN)
|
||||
uaccess_disable_not_uao x2
|
||||
ret
|
||||
ENDPROC(__clear_user)
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user