Merge branch 'torvalds:master' into master
This commit is contained in:
Коммит
11e4e66efd
|
@ -108,7 +108,7 @@ This bump in ABI version is at most once per kernel development cycle.
|
|||
|
||||
For example, if current state of ``libbpf.map`` is:
|
||||
|
||||
.. code-block:: c
|
||||
.. code-block:: none
|
||||
|
||||
LIBBPF_0.0.1 {
|
||||
global:
|
||||
|
@ -121,7 +121,7 @@ For example, if current state of ``libbpf.map`` is:
|
|||
, and a new symbol ``bpf_func_c`` is being introduced, then
|
||||
``libbpf.map`` should be changed like this:
|
||||
|
||||
.. code-block:: c
|
||||
.. code-block:: none
|
||||
|
||||
LIBBPF_0.0.1 {
|
||||
global:
|
||||
|
|
|
@ -152,47 +152,6 @@ allOf:
|
|||
maxItems: 1
|
||||
st,drdy-int-pin: false
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
# Two intertial interrupts i.e. accelerometer/gyro interrupts
|
||||
- st,h3lis331dl-accel
|
||||
- st,l3g4200d-gyro
|
||||
- st,l3g4is-gyro
|
||||
- st,l3gd20-gyro
|
||||
- st,l3gd20h-gyro
|
||||
- st,lis2de12
|
||||
- st,lis2dw12
|
||||
- st,lis2hh12
|
||||
- st,lis2dh12-accel
|
||||
- st,lis331dl-accel
|
||||
- st,lis331dlh-accel
|
||||
- st,lis3de
|
||||
- st,lis3dh-accel
|
||||
- st,lis3dhh
|
||||
- st,lis3mdl-magn
|
||||
- st,lng2dm-accel
|
||||
- st,lps331ap-press
|
||||
- st,lsm303agr-accel
|
||||
- st,lsm303dlh-accel
|
||||
- st,lsm303dlhc-accel
|
||||
- st,lsm303dlm-accel
|
||||
- st,lsm330-accel
|
||||
- st,lsm330-gyro
|
||||
- st,lsm330d-accel
|
||||
- st,lsm330d-gyro
|
||||
- st,lsm330dl-accel
|
||||
- st,lsm330dl-gyro
|
||||
- st,lsm330dlc-accel
|
||||
- st,lsm330dlc-gyro
|
||||
- st,lsm9ds0-gyro
|
||||
- st,lsm9ds1-magn
|
||||
then:
|
||||
properties:
|
||||
interrupts:
|
||||
maxItems: 2
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
|
|
@ -24,10 +24,10 @@ allOf:
|
|||
select:
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
- enum:
|
||||
- sifive,fu540-c000-ccache
|
||||
- sifive,fu740-c000-ccache
|
||||
contains:
|
||||
enum:
|
||||
- sifive,fu540-c000-ccache
|
||||
- sifive,fu740-c000-ccache
|
||||
|
||||
required:
|
||||
- compatible
|
||||
|
|
|
@ -18,114 +18,5 @@ real, with all the uAPI bits is:
|
|||
* Route shmem backend over to TTM SYSTEM for discrete
|
||||
* TTM purgeable object support
|
||||
* Move i915 buddy allocator over to TTM
|
||||
* MMAP ioctl mode(see `I915 MMAP`_)
|
||||
* SET/GET ioctl caching(see `I915 SET/GET CACHING`_)
|
||||
* Send RFC(with mesa-dev on cc) for final sign off on the uAPI
|
||||
* Add pciid for DG1 and turn on uAPI for real
|
||||
|
||||
New object placement and region query uAPI
|
||||
==========================================
|
||||
Starting from DG1 we need to give userspace the ability to allocate buffers from
|
||||
device local-memory. Currently the driver supports gem_create, which can place
|
||||
buffers in system memory via shmem, and the usual assortment of other
|
||||
interfaces, like dumb buffers and userptr.
|
||||
|
||||
To support this new capability, while also providing a uAPI which will work
|
||||
beyond just DG1, we propose to offer three new bits of uAPI:
|
||||
|
||||
DRM_I915_QUERY_MEMORY_REGIONS
|
||||
-----------------------------
|
||||
New query ID which allows userspace to discover the list of supported memory
|
||||
regions(like system-memory and local-memory) for a given device. We identify
|
||||
each region with a class and instance pair, which should be unique. The class
|
||||
here would be DEVICE or SYSTEM, and the instance would be zero, on platforms
|
||||
like DG1.
|
||||
|
||||
Side note: The class/instance design is borrowed from our existing engine uAPI,
|
||||
where we describe every physical engine in terms of its class, and the
|
||||
particular instance, since we can have more than one per class.
|
||||
|
||||
In the future we also want to expose more information which can further
|
||||
describe the capabilities of a region.
|
||||
|
||||
.. kernel-doc:: include/uapi/drm/i915_drm.h
|
||||
:functions: drm_i915_gem_memory_class drm_i915_gem_memory_class_instance drm_i915_memory_region_info drm_i915_query_memory_regions
|
||||
|
||||
GEM_CREATE_EXT
|
||||
--------------
|
||||
New ioctl which is basically just gem_create but now allows userspace to provide
|
||||
a chain of possible extensions. Note that if we don't provide any extensions and
|
||||
set flags=0 then we get the exact same behaviour as gem_create.
|
||||
|
||||
Side note: We also need to support PXP[1] in the near future, which is also
|
||||
applicable to integrated platforms, and adds its own gem_create_ext extension,
|
||||
which basically lets userspace mark a buffer as "protected".
|
||||
|
||||
.. kernel-doc:: include/uapi/drm/i915_drm.h
|
||||
:functions: drm_i915_gem_create_ext
|
||||
|
||||
I915_GEM_CREATE_EXT_MEMORY_REGIONS
|
||||
----------------------------------
|
||||
Implemented as an extension for gem_create_ext, we would now allow userspace to
|
||||
optionally provide an immutable list of preferred placements at creation time,
|
||||
in priority order, for a given buffer object. For the placements we expect
|
||||
them each to use the class/instance encoding, as per the output of the regions
|
||||
query. Having the list in priority order will be useful in the future when
|
||||
placing an object, say during eviction.
|
||||
|
||||
.. kernel-doc:: include/uapi/drm/i915_drm.h
|
||||
:functions: drm_i915_gem_create_ext_memory_regions
|
||||
|
||||
One fair criticism here is that this seems a little over-engineered[2]. If we
|
||||
just consider DG1 then yes, a simple gem_create.flags or something is totally
|
||||
all that's needed to tell the kernel to allocate the buffer in local-memory or
|
||||
whatever. However looking to the future we need uAPI which can also support
|
||||
upcoming Xe HP multi-tile architecture in a sane way, where there can be
|
||||
multiple local-memory instances for a given device, and so using both class and
|
||||
instance in our uAPI to describe regions is desirable, although specifically
|
||||
for DG1 it's uninteresting, since we only have a single local-memory instance.
|
||||
|
||||
Existing uAPI issues
|
||||
====================
|
||||
Some potential issues we still need to resolve.
|
||||
|
||||
I915 MMAP
|
||||
---------
|
||||
In i915 there are multiple ways to MMAP GEM object, including mapping the same
|
||||
object using different mapping types(WC vs WB), i.e multiple active mmaps per
|
||||
object. TTM expects one MMAP at most for the lifetime of the object. If it
|
||||
turns out that we have to backpedal here, there might be some potential
|
||||
userspace fallout.
|
||||
|
||||
I915 SET/GET CACHING
|
||||
--------------------
|
||||
In i915 we have set/get_caching ioctl. TTM doesn't let us to change this, but
|
||||
DG1 doesn't support non-snooped pcie transactions, so we can just always
|
||||
allocate as WB for smem-only buffers. If/when our hw gains support for
|
||||
non-snooped pcie transactions then we must fix this mode at allocation time as
|
||||
a new GEM extension.
|
||||
|
||||
This is related to the mmap problem, because in general (meaning, when we're
|
||||
not running on intel cpus) the cpu mmap must not, ever, be inconsistent with
|
||||
allocation mode.
|
||||
|
||||
Possible idea is to let the kernel picks the mmap mode for userspace from the
|
||||
following table:
|
||||
|
||||
smem-only: WB. Userspace does not need to call clflush.
|
||||
|
||||
smem+lmem: We only ever allow a single mode, so simply allocate this as uncached
|
||||
memory, and always give userspace a WC mapping. GPU still does snooped access
|
||||
here(assuming we can't turn it off like on DG1), which is a bit inefficient.
|
||||
|
||||
lmem only: always WC
|
||||
|
||||
This means on discrete you only get a single mmap mode, all others must be
|
||||
rejected. That's probably going to be a new default mode or something like
|
||||
that.
|
||||
|
||||
Links
|
||||
=====
|
||||
[1] https://patchwork.freedesktop.org/series/86798/
|
||||
|
||||
[2] https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5599#note_553791
|
||||
|
|
|
@ -17,6 +17,7 @@ Introduction
|
|||
busses/index
|
||||
i2c-topology
|
||||
muxes/i2c-mux-gpio
|
||||
i2c-sysfs
|
||||
|
||||
Writing device drivers
|
||||
======================
|
||||
|
|
|
@ -191,19 +191,9 @@ nf_flowtable_tcp_timeout - INTEGER (seconds)
|
|||
TCP connections may be offloaded from nf conntrack to nf flow table.
|
||||
Once aged, the connection is returned to nf conntrack with tcp pickup timeout.
|
||||
|
||||
nf_flowtable_tcp_pickup - INTEGER (seconds)
|
||||
default 120
|
||||
|
||||
TCP connection timeout after being aged from nf flow table offload.
|
||||
|
||||
nf_flowtable_udp_timeout - INTEGER (seconds)
|
||||
default 30
|
||||
|
||||
Control offload timeout for udp connections.
|
||||
UDP connections may be offloaded from nf conntrack to nf flow table.
|
||||
Once aged, the connection is returned to nf conntrack with udp pickup timeout.
|
||||
|
||||
nf_flowtable_udp_pickup - INTEGER (seconds)
|
||||
default 30
|
||||
|
||||
UDP connection timeout after being aged from nf flow table offload.
|
||||
|
|
|
@ -263,7 +263,7 @@ Userspace can also add file descriptors to the notifying process via
|
|||
``ioctl(SECCOMP_IOCTL_NOTIF_ADDFD)``. The ``id`` member of
|
||||
``struct seccomp_notif_addfd`` should be the same ``id`` as in
|
||||
``struct seccomp_notif``. The ``newfd_flags`` flag may be used to set flags
|
||||
like O_EXEC on the file descriptor in the notifying process. If the supervisor
|
||||
like O_CLOEXEC on the file descriptor in the notifying process. If the supervisor
|
||||
wants to inject the file descriptor with a specific number, the
|
||||
``SECCOMP_ADDFD_FLAG_SETFD`` flag can be used, and set the ``newfd`` member to
|
||||
the specific number to use. If that file descriptor is already open in the
|
||||
|
|
|
@ -25,10 +25,10 @@ On x86:
|
|||
|
||||
- vcpu->mutex is taken outside kvm->arch.hyperv.hv_lock
|
||||
|
||||
- kvm->arch.mmu_lock is an rwlock. kvm->arch.tdp_mmu_pages_lock is
|
||||
taken inside kvm->arch.mmu_lock, and cannot be taken without already
|
||||
holding kvm->arch.mmu_lock (typically with ``read_lock``, otherwise
|
||||
there's no need to take kvm->arch.tdp_mmu_pages_lock at all).
|
||||
- kvm->arch.mmu_lock is an rwlock. kvm->arch.tdp_mmu_pages_lock and
|
||||
kvm->arch.mmu_unsync_pages_lock are taken inside kvm->arch.mmu_lock, and
|
||||
cannot be taken without already holding kvm->arch.mmu_lock (typically with
|
||||
``read_lock`` for the TDP MMU, thus the need for additional spinlocks).
|
||||
|
||||
Everything else is a leaf: no other lock is taken inside the critical
|
||||
sections.
|
||||
|
|
28
MAINTAINERS
28
MAINTAINERS
|
@ -3866,6 +3866,16 @@ L: bcm-kernel-feedback-list@broadcom.com
|
|||
S: Maintained
|
||||
F: drivers/mtd/nand/raw/brcmnand/
|
||||
|
||||
BROADCOM STB PCIE DRIVER
|
||||
M: Jim Quinlan <jim2101024@gmail.com>
|
||||
M: Nicolas Saenz Julienne <nsaenz@kernel.org>
|
||||
M: Florian Fainelli <f.fainelli@gmail.com>
|
||||
M: bcm-kernel-feedback-list@broadcom.com
|
||||
L: linux-pci@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/pci/brcm,stb-pcie.yaml
|
||||
F: drivers/pci/controller/pcie-brcmstb.c
|
||||
|
||||
BROADCOM SYSTEMPORT ETHERNET DRIVER
|
||||
M: Florian Fainelli <f.fainelli@gmail.com>
|
||||
L: bcm-kernel-feedback-list@broadcom.com
|
||||
|
@ -4498,7 +4508,7 @@ L: clang-built-linux@googlegroups.com
|
|||
S: Supported
|
||||
W: https://clangbuiltlinux.github.io/
|
||||
B: https://github.com/ClangBuiltLinux/linux/issues
|
||||
C: irc://chat.freenode.net/clangbuiltlinux
|
||||
C: irc://irc.libera.chat/clangbuiltlinux
|
||||
F: Documentation/kbuild/llvm.rst
|
||||
F: include/linux/compiler-clang.h
|
||||
F: scripts/clang-tools/
|
||||
|
@ -11327,7 +11337,7 @@ W: https://linuxtv.org
|
|||
T: git git://linuxtv.org/media_tree.git
|
||||
F: drivers/media/radio/radio-maxiradio*
|
||||
|
||||
MCAB MICROCHIP CAN BUS ANALYZER TOOL DRIVER
|
||||
MCBA MICROCHIP CAN BUS ANALYZER TOOL DRIVER
|
||||
R: Yasushi SHOJI <yashi@spacecubics.com>
|
||||
L: linux-can@vger.kernel.org
|
||||
S: Maintained
|
||||
|
@ -14439,6 +14449,13 @@ S: Maintained
|
|||
F: Documentation/devicetree/bindings/pci/hisilicon-histb-pcie.txt
|
||||
F: drivers/pci/controller/dwc/pcie-histb.c
|
||||
|
||||
PCIE DRIVER FOR INTEL LGM GW SOC
|
||||
M: Rahul Tanwar <rtanwar@maxlinear.com>
|
||||
L: linux-pci@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/pci/intel-gw-pcie.yaml
|
||||
F: drivers/pci/controller/dwc/pcie-intel-gw.c
|
||||
|
||||
PCIE DRIVER FOR MEDIATEK
|
||||
M: Ryder Lee <ryder.lee@mediatek.com>
|
||||
M: Jianjun Wang <jianjun.wang@mediatek.com>
|
||||
|
@ -15812,7 +15829,7 @@ F: Documentation/devicetree/bindings/i2c/renesas,iic-emev2.yaml
|
|||
F: drivers/i2c/busses/i2c-emev2.c
|
||||
|
||||
RENESAS ETHERNET DRIVERS
|
||||
R: Sergei Shtylyov <sergei.shtylyov@gmail.com>
|
||||
R: Sergey Shtylyov <s.shtylyov@omp.ru>
|
||||
L: netdev@vger.kernel.org
|
||||
L: linux-renesas-soc@vger.kernel.org
|
||||
F: Documentation/devicetree/bindings/net/renesas,*.yaml
|
||||
|
@ -17824,7 +17841,7 @@ F: include/linux/sync_file.h
|
|||
F: include/uapi/linux/sync_file.h
|
||||
|
||||
SYNOPSYS ARC ARCHITECTURE
|
||||
M: Vineet Gupta <vgupta@synopsys.com>
|
||||
M: Vineet Gupta <vgupta@kernel.org>
|
||||
L: linux-snps-arc@lists.infradead.org
|
||||
S: Supported
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/vgupta/arc.git
|
||||
|
@ -20026,7 +20043,8 @@ F: Documentation/devicetree/bindings/extcon/wlf,arizona.yaml
|
|||
F: Documentation/devicetree/bindings/mfd/wlf,arizona.yaml
|
||||
F: Documentation/devicetree/bindings/mfd/wm831x.txt
|
||||
F: Documentation/devicetree/bindings/regulator/wlf,arizona.yaml
|
||||
F: Documentation/devicetree/bindings/sound/wlf,arizona.yaml
|
||||
F: Documentation/devicetree/bindings/sound/wlf,*.yaml
|
||||
F: Documentation/devicetree/bindings/sound/wm*
|
||||
F: Documentation/hwmon/wm83??.rst
|
||||
F: arch/arm/mach-s3c/mach-crag6410*
|
||||
F: drivers/clk/clk-wm83*.c
|
||||
|
|
2
Makefile
2
Makefile
|
@ -2,7 +2,7 @@
|
|||
VERSION = 5
|
||||
PATCHLEVEL = 14
|
||||
SUBLEVEL = 0
|
||||
EXTRAVERSION = -rc5
|
||||
EXTRAVERSION = -rc7
|
||||
NAME = Opossums on Parade
|
||||
|
||||
# *DOCUMENTATION*
|
||||
|
|
|
@ -409,7 +409,7 @@ choice
|
|||
help
|
||||
Depending on the configuration, CPU can contain DSP registers
|
||||
(ACC0_GLO, ACC0_GHI, DSP_BFLY0, DSP_CTRL, DSP_FFT_CTRL).
|
||||
Bellow is options describing how to handle these registers in
|
||||
Below are options describing how to handle these registers in
|
||||
interrupt entry / exit and in context switch.
|
||||
|
||||
config ARC_DSP_NONE
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
*/
|
||||
static inline __sum16 csum_fold(__wsum s)
|
||||
{
|
||||
unsigned r = s << 16 | s >> 16; /* ror */
|
||||
unsigned int r = s << 16 | s >> 16; /* ror */
|
||||
s = ~s;
|
||||
s -= r;
|
||||
return s >> 16;
|
||||
|
|
|
@ -123,7 +123,7 @@ static const char * const arc_pmu_ev_hw_map[] = {
|
|||
#define C(_x) PERF_COUNT_HW_CACHE_##_x
|
||||
#define CACHE_OP_UNSUPPORTED 0xffff
|
||||
|
||||
static const unsigned arc_pmu_cache_map[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
|
||||
static const unsigned int arc_pmu_cache_map[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
|
||||
[C(L1D)] = {
|
||||
[C(OP_READ)] = {
|
||||
[C(RESULT_ACCESS)] = PERF_COUNT_ARC_LDC,
|
||||
|
|
|
@ -57,23 +57,26 @@ void fpu_save_restore(struct task_struct *prev, struct task_struct *next)
|
|||
|
||||
void fpu_init_task(struct pt_regs *regs)
|
||||
{
|
||||
const unsigned int fwe = 0x80000000;
|
||||
|
||||
/* default rounding mode */
|
||||
write_aux_reg(ARC_REG_FPU_CTRL, 0x100);
|
||||
|
||||
/* set "Write enable" to allow explicit write to exception flags */
|
||||
write_aux_reg(ARC_REG_FPU_STATUS, 0x80000000);
|
||||
/* Initialize to zero: setting requires FWE be set */
|
||||
write_aux_reg(ARC_REG_FPU_STATUS, fwe);
|
||||
}
|
||||
|
||||
void fpu_save_restore(struct task_struct *prev, struct task_struct *next)
|
||||
{
|
||||
struct arc_fpu *save = &prev->thread.fpu;
|
||||
struct arc_fpu *restore = &next->thread.fpu;
|
||||
const unsigned int fwe = 0x80000000;
|
||||
|
||||
save->ctrl = read_aux_reg(ARC_REG_FPU_CTRL);
|
||||
save->status = read_aux_reg(ARC_REG_FPU_STATUS);
|
||||
|
||||
write_aux_reg(ARC_REG_FPU_CTRL, restore->ctrl);
|
||||
write_aux_reg(ARC_REG_FPU_STATUS, restore->status);
|
||||
write_aux_reg(ARC_REG_FPU_STATUS, (fwe | restore->status));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -260,7 +260,7 @@ static void init_unwind_hdr(struct unwind_table *table,
|
|||
{
|
||||
const u8 *ptr;
|
||||
unsigned long tableSize = table->size, hdrSize;
|
||||
unsigned n;
|
||||
unsigned int n;
|
||||
const u32 *fde;
|
||||
struct {
|
||||
u8 version;
|
||||
|
@ -462,7 +462,7 @@ static uleb128_t get_uleb128(const u8 **pcur, const u8 *end)
|
|||
{
|
||||
const u8 *cur = *pcur;
|
||||
uleb128_t value;
|
||||
unsigned shift;
|
||||
unsigned int shift;
|
||||
|
||||
for (shift = 0, value = 0; cur < end; shift += 7) {
|
||||
if (shift + 7 > 8 * sizeof(value)
|
||||
|
@ -483,7 +483,7 @@ static sleb128_t get_sleb128(const u8 **pcur, const u8 *end)
|
|||
{
|
||||
const u8 *cur = *pcur;
|
||||
sleb128_t value;
|
||||
unsigned shift;
|
||||
unsigned int shift;
|
||||
|
||||
for (shift = 0, value = 0; cur < end; shift += 7) {
|
||||
if (shift + 7 > 8 * sizeof(value)
|
||||
|
@ -609,7 +609,7 @@ static unsigned long read_pointer(const u8 **pLoc, const void *end,
|
|||
static signed fde_pointer_type(const u32 *cie)
|
||||
{
|
||||
const u8 *ptr = (const u8 *)(cie + 2);
|
||||
unsigned version = *ptr;
|
||||
unsigned int version = *ptr;
|
||||
|
||||
if (*++ptr) {
|
||||
const char *aug;
|
||||
|
@ -904,7 +904,7 @@ int arc_unwind(struct unwind_frame_info *frame)
|
|||
const u8 *ptr = NULL, *end = NULL;
|
||||
unsigned long pc = UNW_PC(frame) - frame->call_frame;
|
||||
unsigned long startLoc = 0, endLoc = 0, cfa;
|
||||
unsigned i;
|
||||
unsigned int i;
|
||||
signed ptrType = -1;
|
||||
uleb128_t retAddrReg = 0;
|
||||
const struct unwind_table *table;
|
||||
|
|
|
@ -88,6 +88,8 @@ SECTIONS
|
|||
CPUIDLE_TEXT
|
||||
LOCK_TEXT
|
||||
KPROBES_TEXT
|
||||
IRQENTRY_TEXT
|
||||
SOFTIRQENTRY_TEXT
|
||||
*(.fixup)
|
||||
*(.gnu.warning)
|
||||
}
|
||||
|
|
|
@ -15,8 +15,6 @@ CONFIG_SLAB=y
|
|||
CONFIG_ARCH_NOMADIK=y
|
||||
CONFIG_MACH_NOMADIK_8815NHK=y
|
||||
CONFIG_AEABI=y
|
||||
CONFIG_ZBOOT_ROM_TEXT=0x0
|
||||
CONFIG_ZBOOT_ROM_BSS=0x0
|
||||
CONFIG_MODULES=y
|
||||
CONFIG_MODULE_UNLOAD=y
|
||||
# CONFIG_BLK_DEV_BSG is not set
|
||||
|
@ -52,9 +50,9 @@ CONFIG_MTD_BLOCK=y
|
|||
CONFIG_MTD_ONENAND=y
|
||||
CONFIG_MTD_ONENAND_VERIFY_WRITE=y
|
||||
CONFIG_MTD_ONENAND_GENERIC=y
|
||||
CONFIG_MTD_NAND_ECC_SW_HAMMING_SMC=y
|
||||
CONFIG_MTD_RAW_NAND=y
|
||||
CONFIG_MTD_NAND_FSMC=y
|
||||
CONFIG_MTD_NAND_ECC_SW_HAMMING_SMC=y
|
||||
CONFIG_BLK_DEV_LOOP=y
|
||||
CONFIG_BLK_DEV_CRYPTOLOOP=y
|
||||
CONFIG_BLK_DEV_RAM=y
|
||||
|
@ -97,6 +95,7 @@ CONFIG_REGULATOR=y
|
|||
CONFIG_DRM=y
|
||||
CONFIG_DRM_PANEL_TPO_TPG110=y
|
||||
CONFIG_DRM_PL111=y
|
||||
CONFIG_FB=y
|
||||
CONFIG_BACKLIGHT_CLASS_DEVICE=y
|
||||
CONFIG_BACKLIGHT_PWM=y
|
||||
CONFIG_FRAMEBUFFER_CONSOLE=y
|
||||
|
@ -136,9 +135,8 @@ CONFIG_NLS_ISO8859_15=y
|
|||
CONFIG_CRYPTO_MD5=y
|
||||
CONFIG_CRYPTO_SHA1=y
|
||||
CONFIG_CRYPTO_DES=y
|
||||
# CONFIG_DEBUG_BUGVERBOSE is not set
|
||||
CONFIG_DEBUG_INFO=y
|
||||
# CONFIG_ENABLE_MUST_CHECK is not set
|
||||
CONFIG_DEBUG_FS=y
|
||||
# CONFIG_SCHED_DEBUG is not set
|
||||
# CONFIG_DEBUG_PREEMPT is not set
|
||||
# CONFIG_DEBUG_BUGVERBOSE is not set
|
||||
|
|
|
@ -218,30 +218,30 @@
|
|||
/*
|
||||
* PCI Control/Status Registers
|
||||
*/
|
||||
#define IXP4XX_PCI_CSR(x) ((volatile u32 *)(IXP4XX_PCI_CFG_BASE_VIRT+(x)))
|
||||
#define _IXP4XX_PCI_CSR(x) ((volatile u32 *)(IXP4XX_PCI_CFG_BASE_VIRT+(x)))
|
||||
|
||||
#define PCI_NP_AD IXP4XX_PCI_CSR(PCI_NP_AD_OFFSET)
|
||||
#define PCI_NP_CBE IXP4XX_PCI_CSR(PCI_NP_CBE_OFFSET)
|
||||
#define PCI_NP_WDATA IXP4XX_PCI_CSR(PCI_NP_WDATA_OFFSET)
|
||||
#define PCI_NP_RDATA IXP4XX_PCI_CSR(PCI_NP_RDATA_OFFSET)
|
||||
#define PCI_CRP_AD_CBE IXP4XX_PCI_CSR(PCI_CRP_AD_CBE_OFFSET)
|
||||
#define PCI_CRP_WDATA IXP4XX_PCI_CSR(PCI_CRP_WDATA_OFFSET)
|
||||
#define PCI_CRP_RDATA IXP4XX_PCI_CSR(PCI_CRP_RDATA_OFFSET)
|
||||
#define PCI_CSR IXP4XX_PCI_CSR(PCI_CSR_OFFSET)
|
||||
#define PCI_ISR IXP4XX_PCI_CSR(PCI_ISR_OFFSET)
|
||||
#define PCI_INTEN IXP4XX_PCI_CSR(PCI_INTEN_OFFSET)
|
||||
#define PCI_DMACTRL IXP4XX_PCI_CSR(PCI_DMACTRL_OFFSET)
|
||||
#define PCI_AHBMEMBASE IXP4XX_PCI_CSR(PCI_AHBMEMBASE_OFFSET)
|
||||
#define PCI_AHBIOBASE IXP4XX_PCI_CSR(PCI_AHBIOBASE_OFFSET)
|
||||
#define PCI_PCIMEMBASE IXP4XX_PCI_CSR(PCI_PCIMEMBASE_OFFSET)
|
||||
#define PCI_AHBDOORBELL IXP4XX_PCI_CSR(PCI_AHBDOORBELL_OFFSET)
|
||||
#define PCI_PCIDOORBELL IXP4XX_PCI_CSR(PCI_PCIDOORBELL_OFFSET)
|
||||
#define PCI_ATPDMA0_AHBADDR IXP4XX_PCI_CSR(PCI_ATPDMA0_AHBADDR_OFFSET)
|
||||
#define PCI_ATPDMA0_PCIADDR IXP4XX_PCI_CSR(PCI_ATPDMA0_PCIADDR_OFFSET)
|
||||
#define PCI_ATPDMA0_LENADDR IXP4XX_PCI_CSR(PCI_ATPDMA0_LENADDR_OFFSET)
|
||||
#define PCI_ATPDMA1_AHBADDR IXP4XX_PCI_CSR(PCI_ATPDMA1_AHBADDR_OFFSET)
|
||||
#define PCI_ATPDMA1_PCIADDR IXP4XX_PCI_CSR(PCI_ATPDMA1_PCIADDR_OFFSET)
|
||||
#define PCI_ATPDMA1_LENADDR IXP4XX_PCI_CSR(PCI_ATPDMA1_LENADDR_OFFSET)
|
||||
#define PCI_NP_AD _IXP4XX_PCI_CSR(PCI_NP_AD_OFFSET)
|
||||
#define PCI_NP_CBE _IXP4XX_PCI_CSR(PCI_NP_CBE_OFFSET)
|
||||
#define PCI_NP_WDATA _IXP4XX_PCI_CSR(PCI_NP_WDATA_OFFSET)
|
||||
#define PCI_NP_RDATA _IXP4XX_PCI_CSR(PCI_NP_RDATA_OFFSET)
|
||||
#define PCI_CRP_AD_CBE _IXP4XX_PCI_CSR(PCI_CRP_AD_CBE_OFFSET)
|
||||
#define PCI_CRP_WDATA _IXP4XX_PCI_CSR(PCI_CRP_WDATA_OFFSET)
|
||||
#define PCI_CRP_RDATA _IXP4XX_PCI_CSR(PCI_CRP_RDATA_OFFSET)
|
||||
#define PCI_CSR _IXP4XX_PCI_CSR(PCI_CSR_OFFSET)
|
||||
#define PCI_ISR _IXP4XX_PCI_CSR(PCI_ISR_OFFSET)
|
||||
#define PCI_INTEN _IXP4XX_PCI_CSR(PCI_INTEN_OFFSET)
|
||||
#define PCI_DMACTRL _IXP4XX_PCI_CSR(PCI_DMACTRL_OFFSET)
|
||||
#define PCI_AHBMEMBASE _IXP4XX_PCI_CSR(PCI_AHBMEMBASE_OFFSET)
|
||||
#define PCI_AHBIOBASE _IXP4XX_PCI_CSR(PCI_AHBIOBASE_OFFSET)
|
||||
#define PCI_PCIMEMBASE _IXP4XX_PCI_CSR(PCI_PCIMEMBASE_OFFSET)
|
||||
#define PCI_AHBDOORBELL _IXP4XX_PCI_CSR(PCI_AHBDOORBELL_OFFSET)
|
||||
#define PCI_PCIDOORBELL _IXP4XX_PCI_CSR(PCI_PCIDOORBELL_OFFSET)
|
||||
#define PCI_ATPDMA0_AHBADDR _IXP4XX_PCI_CSR(PCI_ATPDMA0_AHBADDR_OFFSET)
|
||||
#define PCI_ATPDMA0_PCIADDR _IXP4XX_PCI_CSR(PCI_ATPDMA0_PCIADDR_OFFSET)
|
||||
#define PCI_ATPDMA0_LENADDR _IXP4XX_PCI_CSR(PCI_ATPDMA0_LENADDR_OFFSET)
|
||||
#define PCI_ATPDMA1_AHBADDR _IXP4XX_PCI_CSR(PCI_ATPDMA1_AHBADDR_OFFSET)
|
||||
#define PCI_ATPDMA1_PCIADDR _IXP4XX_PCI_CSR(PCI_ATPDMA1_PCIADDR_OFFSET)
|
||||
#define PCI_ATPDMA1_LENADDR _IXP4XX_PCI_CSR(PCI_ATPDMA1_LENADDR_OFFSET)
|
||||
|
||||
/*
|
||||
* PCI register values and bit definitions
|
||||
|
|
|
@ -183,6 +183,8 @@ endif
|
|||
# We use MRPROPER_FILES and CLEAN_FILES now
|
||||
archclean:
|
||||
$(Q)$(MAKE) $(clean)=$(boot)
|
||||
$(Q)$(MAKE) $(clean)=arch/arm64/kernel/vdso
|
||||
$(Q)$(MAKE) $(clean)=arch/arm64/kernel/vdso32
|
||||
|
||||
ifeq ($(KBUILD_EXTMOD),)
|
||||
# We need to generate vdso-offsets.h before compiling certain files in kernel/.
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/* Copyright (c) 2015, LGE Inc. All rights reserved.
|
||||
* Copyright (c) 2016, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021, Petr Vorel <petr.vorel@gmail.com>
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
|
@ -9,6 +10,9 @@
|
|||
#include "pm8994.dtsi"
|
||||
#include "pmi8994.dtsi"
|
||||
|
||||
/* cont_splash_mem has different memory mapping */
|
||||
/delete-node/ &cont_splash_mem;
|
||||
|
||||
/ {
|
||||
model = "LG Nexus 5X";
|
||||
compatible = "lg,bullhead", "qcom,msm8992";
|
||||
|
@ -17,6 +21,9 @@
|
|||
qcom,board-id = <0xb64 0>;
|
||||
qcom,pmic-id = <0x10009 0x1000A 0x0 0x0>;
|
||||
|
||||
/* Bullhead firmware doesn't support PSCI */
|
||||
/delete-node/ psci;
|
||||
|
||||
aliases {
|
||||
serial0 = &blsp1_uart2;
|
||||
};
|
||||
|
@ -38,6 +45,11 @@
|
|||
ftrace-size = <0x10000>;
|
||||
pmsg-size = <0x20000>;
|
||||
};
|
||||
|
||||
cont_splash_mem: memory@3400000 {
|
||||
reg = <0 0x03400000 0 0x1200000>;
|
||||
no-map;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -1,12 +1,16 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/* Copyright (c) 2015, Huawei Inc. All rights reserved.
|
||||
* Copyright (c) 2016, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021, Petr Vorel <petr.vorel@gmail.com>
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
|
||||
#include "msm8994.dtsi"
|
||||
|
||||
/* Angler's firmware does not report where the memory is allocated */
|
||||
/delete-node/ &cont_splash_mem;
|
||||
|
||||
/ {
|
||||
model = "Huawei Nexus 6P";
|
||||
compatible = "huawei,angler", "qcom,msm8994";
|
||||
|
|
|
@ -200,7 +200,7 @@
|
|||
&BIG_CPU_SLEEP_1
|
||||
&CLUSTER_SLEEP_0>;
|
||||
next-level-cache = <&L2_700>;
|
||||
qcom,freq-domain = <&cpufreq_hw 1>;
|
||||
qcom,freq-domain = <&cpufreq_hw 2>;
|
||||
#cooling-cells = <2>;
|
||||
L2_700: l2-cache {
|
||||
compatible = "cache";
|
||||
|
|
|
@ -69,7 +69,7 @@
|
|||
};
|
||||
rmtfs_upper_guard: memory@f5d01000 {
|
||||
no-map;
|
||||
reg = <0 0xf5d01000 0 0x2000>;
|
||||
reg = <0 0xf5d01000 0 0x1000>;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -78,7 +78,7 @@
|
|||
*/
|
||||
removed_region: memory@88f00000 {
|
||||
no-map;
|
||||
reg = <0 0x88f00000 0 0x200000>;
|
||||
reg = <0 0x88f00000 0 0x1c00000>;
|
||||
};
|
||||
|
||||
ramoops: ramoops@ac300000 {
|
||||
|
|
|
@ -700,7 +700,7 @@
|
|||
left_spkr: wsa8810-left{
|
||||
compatible = "sdw10217211000";
|
||||
reg = <0 3>;
|
||||
powerdown-gpios = <&wcdgpio 2 GPIO_ACTIVE_HIGH>;
|
||||
powerdown-gpios = <&wcdgpio 1 GPIO_ACTIVE_HIGH>;
|
||||
#thermal-sensor-cells = <0>;
|
||||
sound-name-prefix = "SpkrLeft";
|
||||
#sound-dai-cells = <0>;
|
||||
|
@ -708,7 +708,7 @@
|
|||
|
||||
right_spkr: wsa8810-right{
|
||||
compatible = "sdw10217211000";
|
||||
powerdown-gpios = <&wcdgpio 3 GPIO_ACTIVE_HIGH>;
|
||||
powerdown-gpios = <&wcdgpio 2 GPIO_ACTIVE_HIGH>;
|
||||
reg = <0 4>;
|
||||
#thermal-sensor-cells = <0>;
|
||||
sound-name-prefix = "SpkrRight";
|
||||
|
|
|
@ -33,8 +33,7 @@
|
|||
* EL2.
|
||||
*/
|
||||
.macro __init_el2_timers
|
||||
mrs x0, cnthctl_el2
|
||||
orr x0, x0, #3 // Enable EL1 physical timers
|
||||
mov x0, #3 // Enable EL1 physical timers
|
||||
msr cnthctl_el2, x0
|
||||
msr cntvoff_el2, xzr // Clear virtual offset
|
||||
.endm
|
||||
|
|
|
@ -94,10 +94,14 @@ int kvm_vm_ioctl_enable_cap(struct kvm *kvm,
|
|||
kvm->arch.return_nisv_io_abort_to_user = true;
|
||||
break;
|
||||
case KVM_CAP_ARM_MTE:
|
||||
if (!system_supports_mte() || kvm->created_vcpus)
|
||||
return -EINVAL;
|
||||
r = 0;
|
||||
kvm->arch.mte_enabled = true;
|
||||
mutex_lock(&kvm->lock);
|
||||
if (!system_supports_mte() || kvm->created_vcpus) {
|
||||
r = -EINVAL;
|
||||
} else {
|
||||
r = 0;
|
||||
kvm->arch.mte_enabled = true;
|
||||
}
|
||||
mutex_unlock(&kvm->lock);
|
||||
break;
|
||||
default:
|
||||
r = -EINVAL;
|
||||
|
|
|
@ -193,7 +193,7 @@ static bool range_is_memory(u64 start, u64 end)
|
|||
{
|
||||
struct kvm_mem_range r1, r2;
|
||||
|
||||
if (!find_mem_range(start, &r1) || !find_mem_range(end, &r2))
|
||||
if (!find_mem_range(start, &r1) || !find_mem_range(end - 1, &r2))
|
||||
return false;
|
||||
if (r1.start != r2.start)
|
||||
return false;
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
|
||||
#include <asm/bug.h>
|
||||
#include <asm/book3s/32/mmu-hash.h>
|
||||
#include <asm/mmu.h>
|
||||
#include <asm/synch.h>
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
|
@ -28,6 +30,15 @@ static inline void kuep_lock(void)
|
|||
return;
|
||||
|
||||
update_user_segments(mfsr(0) | SR_NX);
|
||||
/*
|
||||
* This isync() shouldn't be necessary as the kernel is not excepted to
|
||||
* run any instruction in userspace soon after the update of segments,
|
||||
* but hash based cores (at least G3) seem to exhibit a random
|
||||
* behaviour when the 'isync' is not there. 603 cores don't have this
|
||||
* behaviour so don't do the 'isync' as it saves several CPU cycles.
|
||||
*/
|
||||
if (mmu_has_feature(MMU_FTR_HPTE_TABLE))
|
||||
isync(); /* Context sync required after mtsr() */
|
||||
}
|
||||
|
||||
static inline void kuep_unlock(void)
|
||||
|
@ -36,6 +47,15 @@ static inline void kuep_unlock(void)
|
|||
return;
|
||||
|
||||
update_user_segments(mfsr(0) & ~SR_NX);
|
||||
/*
|
||||
* This isync() shouldn't be necessary as a 'rfi' will soon be executed
|
||||
* to return to userspace, but hash based cores (at least G3) seem to
|
||||
* exhibit a random behaviour when the 'isync' is not there. 603 cores
|
||||
* don't have this behaviour so don't do the 'isync' as it saves several
|
||||
* CPU cycles.
|
||||
*/
|
||||
if (mmu_has_feature(MMU_FTR_HPTE_TABLE))
|
||||
isync(); /* Context sync required after mtsr() */
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PPC_KUAP
|
||||
|
|
|
@ -583,6 +583,9 @@ DECLARE_INTERRUPT_HANDLER_NMI(hmi_exception_realmode);
|
|||
|
||||
DECLARE_INTERRUPT_HANDLER_ASYNC(TAUException);
|
||||
|
||||
/* irq.c */
|
||||
DECLARE_INTERRUPT_HANDLER_ASYNC(do_IRQ);
|
||||
|
||||
void __noreturn unrecoverable_exception(struct pt_regs *regs);
|
||||
|
||||
void replay_system_reset(void);
|
||||
|
|
|
@ -52,7 +52,7 @@ extern void *mcheckirq_ctx[NR_CPUS];
|
|||
extern void *hardirq_ctx[NR_CPUS];
|
||||
extern void *softirq_ctx[NR_CPUS];
|
||||
|
||||
extern void do_IRQ(struct pt_regs *regs);
|
||||
void __do_IRQ(struct pt_regs *regs);
|
||||
extern void __init init_IRQ(void);
|
||||
extern void __do_irq(struct pt_regs *regs);
|
||||
|
||||
|
|
|
@ -70,6 +70,22 @@ struct pt_regs
|
|||
unsigned long __pad[4]; /* Maintain 16 byte interrupt stack alignment */
|
||||
};
|
||||
#endif
|
||||
#if defined(CONFIG_PPC32) && defined(CONFIG_BOOKE)
|
||||
struct { /* Must be a multiple of 16 bytes */
|
||||
unsigned long mas0;
|
||||
unsigned long mas1;
|
||||
unsigned long mas2;
|
||||
unsigned long mas3;
|
||||
unsigned long mas6;
|
||||
unsigned long mas7;
|
||||
unsigned long srr0;
|
||||
unsigned long srr1;
|
||||
unsigned long csrr0;
|
||||
unsigned long csrr1;
|
||||
unsigned long dsrr0;
|
||||
unsigned long dsrr1;
|
||||
};
|
||||
#endif
|
||||
};
|
||||
#endif
|
||||
|
||||
|
|
|
@ -309,24 +309,21 @@ int main(void)
|
|||
STACK_PT_REGS_OFFSET(STACK_REGS_IAMR, iamr);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_PPC32)
|
||||
#if defined(CONFIG_BOOKE) || defined(CONFIG_40x)
|
||||
DEFINE(EXC_LVL_SIZE, STACK_EXC_LVL_FRAME_SIZE);
|
||||
DEFINE(MAS0, STACK_INT_FRAME_SIZE+offsetof(struct exception_regs, mas0));
|
||||
#if defined(CONFIG_PPC32) && defined(CONFIG_BOOKE)
|
||||
STACK_PT_REGS_OFFSET(MAS0, mas0);
|
||||
/* we overload MMUCR for 44x on MAS0 since they are mutually exclusive */
|
||||
DEFINE(MMUCR, STACK_INT_FRAME_SIZE+offsetof(struct exception_regs, mas0));
|
||||
DEFINE(MAS1, STACK_INT_FRAME_SIZE+offsetof(struct exception_regs, mas1));
|
||||
DEFINE(MAS2, STACK_INT_FRAME_SIZE+offsetof(struct exception_regs, mas2));
|
||||
DEFINE(MAS3, STACK_INT_FRAME_SIZE+offsetof(struct exception_regs, mas3));
|
||||
DEFINE(MAS6, STACK_INT_FRAME_SIZE+offsetof(struct exception_regs, mas6));
|
||||
DEFINE(MAS7, STACK_INT_FRAME_SIZE+offsetof(struct exception_regs, mas7));
|
||||
DEFINE(_SRR0, STACK_INT_FRAME_SIZE+offsetof(struct exception_regs, srr0));
|
||||
DEFINE(_SRR1, STACK_INT_FRAME_SIZE+offsetof(struct exception_regs, srr1));
|
||||
DEFINE(_CSRR0, STACK_INT_FRAME_SIZE+offsetof(struct exception_regs, csrr0));
|
||||
DEFINE(_CSRR1, STACK_INT_FRAME_SIZE+offsetof(struct exception_regs, csrr1));
|
||||
DEFINE(_DSRR0, STACK_INT_FRAME_SIZE+offsetof(struct exception_regs, dsrr0));
|
||||
DEFINE(_DSRR1, STACK_INT_FRAME_SIZE+offsetof(struct exception_regs, dsrr1));
|
||||
#endif
|
||||
STACK_PT_REGS_OFFSET(MMUCR, mas0);
|
||||
STACK_PT_REGS_OFFSET(MAS1, mas1);
|
||||
STACK_PT_REGS_OFFSET(MAS2, mas2);
|
||||
STACK_PT_REGS_OFFSET(MAS3, mas3);
|
||||
STACK_PT_REGS_OFFSET(MAS6, mas6);
|
||||
STACK_PT_REGS_OFFSET(MAS7, mas7);
|
||||
STACK_PT_REGS_OFFSET(_SRR0, srr0);
|
||||
STACK_PT_REGS_OFFSET(_SRR1, srr1);
|
||||
STACK_PT_REGS_OFFSET(_CSRR0, csrr0);
|
||||
STACK_PT_REGS_OFFSET(_CSRR1, csrr1);
|
||||
STACK_PT_REGS_OFFSET(_DSRR0, dsrr0);
|
||||
STACK_PT_REGS_OFFSET(_DSRR1, dsrr1);
|
||||
#endif
|
||||
|
||||
/* About the CPU features table */
|
||||
|
|
|
@ -300,7 +300,7 @@ ALT_MMU_FTR_SECTION_END_IFSET(MMU_FTR_HPTE_TABLE)
|
|||
EXCEPTION_PROLOG_1
|
||||
EXCEPTION_PROLOG_2 INTERRUPT_DATA_STORAGE DataAccess handle_dar_dsisr=1
|
||||
prepare_transfer_to_handler
|
||||
lwz r5, _DSISR(r11)
|
||||
lwz r5, _DSISR(r1)
|
||||
andis. r0, r5, DSISR_DABRMATCH@h
|
||||
bne- 1f
|
||||
bl do_page_fault
|
||||
|
|
|
@ -168,20 +168,18 @@ ALT_FTR_SECTION_END_IFSET(CPU_FTR_EMB_HV)
|
|||
/* only on e500mc */
|
||||
#define DBG_STACK_BASE dbgirq_ctx
|
||||
|
||||
#define EXC_LVL_FRAME_OVERHEAD (THREAD_SIZE - INT_FRAME_SIZE - EXC_LVL_SIZE)
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
#define BOOKE_LOAD_EXC_LEVEL_STACK(level) \
|
||||
mfspr r8,SPRN_PIR; \
|
||||
slwi r8,r8,2; \
|
||||
addis r8,r8,level##_STACK_BASE@ha; \
|
||||
lwz r8,level##_STACK_BASE@l(r8); \
|
||||
addi r8,r8,EXC_LVL_FRAME_OVERHEAD;
|
||||
addi r8,r8,THREAD_SIZE - INT_FRAME_SIZE;
|
||||
#else
|
||||
#define BOOKE_LOAD_EXC_LEVEL_STACK(level) \
|
||||
lis r8,level##_STACK_BASE@ha; \
|
||||
lwz r8,level##_STACK_BASE@l(r8); \
|
||||
addi r8,r8,EXC_LVL_FRAME_OVERHEAD;
|
||||
addi r8,r8,THREAD_SIZE - INT_FRAME_SIZE;
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
@ -208,7 +206,7 @@ ALT_FTR_SECTION_END_IFSET(CPU_FTR_EMB_HV)
|
|||
mtmsr r11; \
|
||||
mfspr r11,SPRN_SPRG_THREAD; /* if from user, start at top of */\
|
||||
lwz r11, TASK_STACK - THREAD(r11); /* this thread's kernel stack */\
|
||||
addi r11,r11,EXC_LVL_FRAME_OVERHEAD; /* allocate stack frame */\
|
||||
addi r11,r11,THREAD_SIZE - INT_FRAME_SIZE; /* allocate stack frame */\
|
||||
beq 1f; \
|
||||
/* COMING FROM USER MODE */ \
|
||||
stw r9,_CCR(r11); /* save CR */\
|
||||
|
@ -516,24 +514,5 @@ label:
|
|||
bl kernel_fp_unavailable_exception; \
|
||||
b interrupt_return
|
||||
|
||||
#else /* __ASSEMBLY__ */
|
||||
struct exception_regs {
|
||||
unsigned long mas0;
|
||||
unsigned long mas1;
|
||||
unsigned long mas2;
|
||||
unsigned long mas3;
|
||||
unsigned long mas6;
|
||||
unsigned long mas7;
|
||||
unsigned long srr0;
|
||||
unsigned long srr1;
|
||||
unsigned long csrr0;
|
||||
unsigned long csrr1;
|
||||
unsigned long dsrr0;
|
||||
unsigned long dsrr1;
|
||||
};
|
||||
|
||||
/* ensure this structure is always sized to a multiple of the stack alignment */
|
||||
#define STACK_EXC_LVL_FRAME_SIZE ALIGN(sizeof (struct exception_regs), 16)
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
#endif /* __HEAD_BOOKE_H__ */
|
||||
|
|
|
@ -750,7 +750,7 @@ void __do_irq(struct pt_regs *regs)
|
|||
trace_irq_exit(regs);
|
||||
}
|
||||
|
||||
DEFINE_INTERRUPT_HANDLER_ASYNC(do_IRQ)
|
||||
void __do_IRQ(struct pt_regs *regs)
|
||||
{
|
||||
struct pt_regs *old_regs = set_irq_regs(regs);
|
||||
void *cursp, *irqsp, *sirqsp;
|
||||
|
@ -774,6 +774,11 @@ DEFINE_INTERRUPT_HANDLER_ASYNC(do_IRQ)
|
|||
set_irq_regs(old_regs);
|
||||
}
|
||||
|
||||
DEFINE_INTERRUPT_HANDLER_ASYNC(do_IRQ)
|
||||
{
|
||||
__do_IRQ(regs);
|
||||
}
|
||||
|
||||
static void *__init alloc_vm_stack(void)
|
||||
{
|
||||
return __vmalloc_node(THREAD_SIZE, THREAD_ALIGN, THREADINFO_GFP,
|
||||
|
|
|
@ -292,7 +292,8 @@ int kprobe_handler(struct pt_regs *regs)
|
|||
if (user_mode(regs))
|
||||
return 0;
|
||||
|
||||
if (!(regs->msr & MSR_IR) || !(regs->msr & MSR_DR))
|
||||
if (!IS_ENABLED(CONFIG_BOOKE) &&
|
||||
(!(regs->msr & MSR_IR) || !(regs->msr & MSR_DR)))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
|
|
|
@ -1167,7 +1167,7 @@ static int __init topology_init(void)
|
|||
* CPU. For instance, the boot cpu might never be valid
|
||||
* for hotplugging.
|
||||
*/
|
||||
if (smp_ops->cpu_offline_self)
|
||||
if (smp_ops && smp_ops->cpu_offline_self)
|
||||
c->hotpluggable = 1;
|
||||
#endif
|
||||
|
||||
|
|
|
@ -586,7 +586,7 @@ DEFINE_INTERRUPT_HANDLER_ASYNC(timer_interrupt)
|
|||
|
||||
#if defined(CONFIG_PPC32) && defined(CONFIG_PPC_PMAC)
|
||||
if (atomic_read(&ppc_n_lost_interrupts) != 0)
|
||||
do_IRQ(regs);
|
||||
__do_IRQ(regs);
|
||||
#endif
|
||||
|
||||
old_regs = set_irq_regs(regs);
|
||||
|
|
|
@ -1104,7 +1104,7 @@ DEFINE_INTERRUPT_HANDLER(RunModeException)
|
|||
_exception(SIGTRAP, regs, TRAP_UNK, 0);
|
||||
}
|
||||
|
||||
DEFINE_INTERRUPT_HANDLER(single_step_exception)
|
||||
static void __single_step_exception(struct pt_regs *regs)
|
||||
{
|
||||
clear_single_step(regs);
|
||||
clear_br_trace(regs);
|
||||
|
@ -1121,6 +1121,11 @@ DEFINE_INTERRUPT_HANDLER(single_step_exception)
|
|||
_exception(SIGTRAP, regs, TRAP_TRACE, regs->nip);
|
||||
}
|
||||
|
||||
DEFINE_INTERRUPT_HANDLER(single_step_exception)
|
||||
{
|
||||
__single_step_exception(regs);
|
||||
}
|
||||
|
||||
/*
|
||||
* After we have successfully emulated an instruction, we have to
|
||||
* check if the instruction was being single-stepped, and if so,
|
||||
|
@ -1130,7 +1135,7 @@ DEFINE_INTERRUPT_HANDLER(single_step_exception)
|
|||
static void emulate_single_step(struct pt_regs *regs)
|
||||
{
|
||||
if (single_stepping(regs))
|
||||
single_step_exception(regs);
|
||||
__single_step_exception(regs);
|
||||
}
|
||||
|
||||
static inline int __parse_fpscr(unsigned long fpscr)
|
||||
|
|
|
@ -18,16 +18,12 @@
|
|||
/*
|
||||
* Updates the attributes of a page in three steps:
|
||||
*
|
||||
* 1. invalidate the page table entry
|
||||
* 2. flush the TLB
|
||||
* 3. install the new entry with the updated attributes
|
||||
*
|
||||
* Invalidating the pte means there are situations where this will not work
|
||||
* when in theory it should.
|
||||
* For example:
|
||||
* - removing write from page whilst it is being executed
|
||||
* - setting a page read-only whilst it is being read by another CPU
|
||||
* 1. take the page_table_lock
|
||||
* 2. install the new entry with the updated attributes
|
||||
* 3. flush the TLB
|
||||
*
|
||||
* This sequence is safe against concurrent updates, and also allows updating the
|
||||
* attributes of a page currently being executed or accessed.
|
||||
*/
|
||||
static int change_page_attr(pte_t *ptep, unsigned long addr, void *data)
|
||||
{
|
||||
|
@ -36,9 +32,7 @@ static int change_page_attr(pte_t *ptep, unsigned long addr, void *data)
|
|||
|
||||
spin_lock(&init_mm.page_table_lock);
|
||||
|
||||
/* invalidate the PTE so it's safe to modify */
|
||||
pte = ptep_get_and_clear(&init_mm, addr, ptep);
|
||||
flush_tlb_kernel_range(addr, addr + PAGE_SIZE);
|
||||
pte = ptep_get(ptep);
|
||||
|
||||
/* modify the PTE bits as desired, then apply */
|
||||
switch (action) {
|
||||
|
@ -59,11 +53,14 @@ static int change_page_attr(pte_t *ptep, unsigned long addr, void *data)
|
|||
break;
|
||||
}
|
||||
|
||||
set_pte_at(&init_mm, addr, ptep, pte);
|
||||
pte_update(&init_mm, addr, ptep, ~0UL, pte_val(pte), 0);
|
||||
|
||||
/* See ptesync comment in radix__set_pte_at() */
|
||||
if (radix_enabled())
|
||||
asm volatile("ptesync": : :"memory");
|
||||
|
||||
flush_tlb_kernel_range(addr, addr + PAGE_SIZE);
|
||||
|
||||
spin_unlock(&init_mm.page_table_lock);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -539,9 +539,10 @@ static void init_cpu_char_feature_flags(struct h_cpu_char_result *result)
|
|||
* H_CPU_BEHAV_FAVOUR_SECURITY_H could be set only if
|
||||
* H_CPU_BEHAV_FAVOUR_SECURITY is.
|
||||
*/
|
||||
if (!(result->behaviour & H_CPU_BEHAV_FAVOUR_SECURITY))
|
||||
if (!(result->behaviour & H_CPU_BEHAV_FAVOUR_SECURITY)) {
|
||||
security_ftr_clear(SEC_FTR_FAVOUR_SECURITY);
|
||||
else if (result->behaviour & H_CPU_BEHAV_FAVOUR_SECURITY_H)
|
||||
pseries_security_flavor = 0;
|
||||
} else if (result->behaviour & H_CPU_BEHAV_FAVOUR_SECURITY_H)
|
||||
pseries_security_flavor = 1;
|
||||
else
|
||||
pseries_security_flavor = 2;
|
||||
|
|
|
@ -67,6 +67,7 @@ static struct irq_domain *xive_irq_domain;
|
|||
static struct xive_ipi_desc {
|
||||
unsigned int irq;
|
||||
char name[16];
|
||||
atomic_t started;
|
||||
} *xive_ipis;
|
||||
|
||||
/*
|
||||
|
@ -1120,7 +1121,7 @@ static const struct irq_domain_ops xive_ipi_irq_domain_ops = {
|
|||
.alloc = xive_ipi_irq_domain_alloc,
|
||||
};
|
||||
|
||||
static int __init xive_request_ipi(void)
|
||||
static int __init xive_init_ipis(void)
|
||||
{
|
||||
struct fwnode_handle *fwnode;
|
||||
struct irq_domain *ipi_domain;
|
||||
|
@ -1144,10 +1145,6 @@ static int __init xive_request_ipi(void)
|
|||
struct xive_ipi_desc *xid = &xive_ipis[node];
|
||||
struct xive_ipi_alloc_info info = { node };
|
||||
|
||||
/* Skip nodes without CPUs */
|
||||
if (cpumask_empty(cpumask_of_node(node)))
|
||||
continue;
|
||||
|
||||
/*
|
||||
* Map one IPI interrupt per node for all cpus of that node.
|
||||
* Since the HW interrupt number doesn't have any meaning,
|
||||
|
@ -1159,11 +1156,6 @@ static int __init xive_request_ipi(void)
|
|||
xid->irq = ret;
|
||||
|
||||
snprintf(xid->name, sizeof(xid->name), "IPI-%d", node);
|
||||
|
||||
ret = request_irq(xid->irq, xive_muxed_ipi_action,
|
||||
IRQF_PERCPU | IRQF_NO_THREAD, xid->name, NULL);
|
||||
|
||||
WARN(ret < 0, "Failed to request IPI %d: %d\n", xid->irq, ret);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
@ -1178,6 +1170,22 @@ out:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int xive_request_ipi(unsigned int cpu)
|
||||
{
|
||||
struct xive_ipi_desc *xid = &xive_ipis[early_cpu_to_node(cpu)];
|
||||
int ret;
|
||||
|
||||
if (atomic_inc_return(&xid->started) > 1)
|
||||
return 0;
|
||||
|
||||
ret = request_irq(xid->irq, xive_muxed_ipi_action,
|
||||
IRQF_PERCPU | IRQF_NO_THREAD,
|
||||
xid->name, NULL);
|
||||
|
||||
WARN(ret < 0, "Failed to request IPI %d: %d\n", xid->irq, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int xive_setup_cpu_ipi(unsigned int cpu)
|
||||
{
|
||||
unsigned int xive_ipi_irq = xive_ipi_cpu_to_irq(cpu);
|
||||
|
@ -1192,6 +1200,9 @@ static int xive_setup_cpu_ipi(unsigned int cpu)
|
|||
if (xc->hw_ipi != XIVE_BAD_IRQ)
|
||||
return 0;
|
||||
|
||||
/* Register the IPI */
|
||||
xive_request_ipi(cpu);
|
||||
|
||||
/* Grab an IPI from the backend, this will populate xc->hw_ipi */
|
||||
if (xive_ops->get_ipi(cpu, xc))
|
||||
return -EIO;
|
||||
|
@ -1231,6 +1242,8 @@ static void xive_cleanup_cpu_ipi(unsigned int cpu, struct xive_cpu *xc)
|
|||
if (xc->hw_ipi == XIVE_BAD_IRQ)
|
||||
return;
|
||||
|
||||
/* TODO: clear IPI mapping */
|
||||
|
||||
/* Mask the IPI */
|
||||
xive_do_source_set_mask(&xc->ipi_data, true);
|
||||
|
||||
|
@ -1253,7 +1266,7 @@ void __init xive_smp_probe(void)
|
|||
smp_ops->cause_ipi = xive_cause_ipi;
|
||||
|
||||
/* Register the IPI */
|
||||
xive_request_ipi();
|
||||
xive_init_ipis();
|
||||
|
||||
/* Allocate and setup IPI for the boot CPU */
|
||||
xive_setup_cpu_ipi(smp_processor_id());
|
||||
|
|
|
@ -11,7 +11,7 @@ endif
|
|||
CFLAGS_syscall_table.o += $(call cc-option,-Wno-override-init,)
|
||||
|
||||
ifdef CONFIG_KEXEC
|
||||
AFLAGS_kexec_relocate.o := -mcmodel=medany -mno-relax
|
||||
AFLAGS_kexec_relocate.o := -mcmodel=medany $(call cc-option,-mno-relax)
|
||||
endif
|
||||
|
||||
extra-y += head.o
|
||||
|
|
|
@ -229,8 +229,8 @@ static void __init init_resources(void)
|
|||
}
|
||||
|
||||
/* Clean-up any unused pre-allocated resources */
|
||||
mem_res_sz = (num_resources - res_idx + 1) * sizeof(*mem_res);
|
||||
memblock_free(__pa(mem_res), mem_res_sz);
|
||||
if (res_idx >= 0)
|
||||
memblock_free(__pa(mem_res), (res_idx + 1) * sizeof(*mem_res));
|
||||
return;
|
||||
|
||||
error:
|
||||
|
|
|
@ -197,7 +197,7 @@ static void __init setup_bootmem(void)
|
|||
* if end of dram is equal to maximum addressable memory. For 64-bit
|
||||
* kernel, this problem can't happen here as the end of the virtual
|
||||
* address space is occupied by the kernel mapping then this check must
|
||||
* be done in create_kernel_page_table.
|
||||
* be done as soon as the kernel mapping base address is determined.
|
||||
*/
|
||||
max_mapped_addr = __pa(~(ulong)0);
|
||||
if (max_mapped_addr == (phys_ram_end - 1))
|
||||
|
|
|
@ -560,9 +560,12 @@ static void zpci_cleanup_bus_resources(struct zpci_dev *zdev)
|
|||
|
||||
int pcibios_add_device(struct pci_dev *pdev)
|
||||
{
|
||||
struct zpci_dev *zdev = to_zpci(pdev);
|
||||
struct resource *res;
|
||||
int i;
|
||||
|
||||
/* The pdev has a reference to the zdev via its bus */
|
||||
zpci_zdev_get(zdev);
|
||||
if (pdev->is_physfn)
|
||||
pdev->no_vf_scan = 1;
|
||||
|
||||
|
@ -582,7 +585,10 @@ int pcibios_add_device(struct pci_dev *pdev)
|
|||
|
||||
void pcibios_release_device(struct pci_dev *pdev)
|
||||
{
|
||||
struct zpci_dev *zdev = to_zpci(pdev);
|
||||
|
||||
zpci_unmap_resources(pdev);
|
||||
zpci_zdev_put(zdev);
|
||||
}
|
||||
|
||||
int pcibios_enable_device(struct pci_dev *pdev, int mask)
|
||||
|
|
|
@ -22,6 +22,11 @@ static inline void zpci_zdev_put(struct zpci_dev *zdev)
|
|||
kref_put(&zdev->kref, zpci_release_device);
|
||||
}
|
||||
|
||||
static inline void zpci_zdev_get(struct zpci_dev *zdev)
|
||||
{
|
||||
kref_get(&zdev->kref);
|
||||
}
|
||||
|
||||
int zpci_alloc_domain(int domain);
|
||||
void zpci_free_domain(int domain);
|
||||
int zpci_setup_bus_resources(struct zpci_dev *zdev,
|
||||
|
|
|
@ -1038,6 +1038,13 @@ struct kvm_arch {
|
|||
struct list_head lpage_disallowed_mmu_pages;
|
||||
struct kvm_page_track_notifier_node mmu_sp_tracker;
|
||||
struct kvm_page_track_notifier_head track_notifier_head;
|
||||
/*
|
||||
* Protects marking pages unsync during page faults, as TDP MMU page
|
||||
* faults only take mmu_lock for read. For simplicity, the unsync
|
||||
* pages lock is always taken when marking pages unsync regardless of
|
||||
* whether mmu_lock is held for read or write.
|
||||
*/
|
||||
spinlock_t mmu_unsync_pages_lock;
|
||||
|
||||
struct list_head assigned_dev_head;
|
||||
struct iommu_domain *iommu_domain;
|
||||
|
|
|
@ -184,6 +184,8 @@ struct __attribute__ ((__packed__)) vmcb_control_area {
|
|||
#define V_IGN_TPR_SHIFT 20
|
||||
#define V_IGN_TPR_MASK (1 << V_IGN_TPR_SHIFT)
|
||||
|
||||
#define V_IRQ_INJECTION_BITS_MASK (V_IRQ_MASK | V_INTR_PRIO_MASK | V_IGN_TPR_MASK)
|
||||
|
||||
#define V_INTR_MASKING_SHIFT 24
|
||||
#define V_INTR_MASKING_MASK (1 << V_INTR_MASKING_SHIFT)
|
||||
|
||||
|
|
|
@ -1986,7 +1986,8 @@ static struct irq_chip ioapic_chip __read_mostly = {
|
|||
.irq_set_affinity = ioapic_set_affinity,
|
||||
.irq_retrigger = irq_chip_retrigger_hierarchy,
|
||||
.irq_get_irqchip_state = ioapic_irq_get_chip_state,
|
||||
.flags = IRQCHIP_SKIP_SET_WAKE,
|
||||
.flags = IRQCHIP_SKIP_SET_WAKE |
|
||||
IRQCHIP_AFFINITY_PRE_STARTUP,
|
||||
};
|
||||
|
||||
static struct irq_chip ioapic_ir_chip __read_mostly = {
|
||||
|
@ -1999,7 +2000,8 @@ static struct irq_chip ioapic_ir_chip __read_mostly = {
|
|||
.irq_set_affinity = ioapic_set_affinity,
|
||||
.irq_retrigger = irq_chip_retrigger_hierarchy,
|
||||
.irq_get_irqchip_state = ioapic_irq_get_chip_state,
|
||||
.flags = IRQCHIP_SKIP_SET_WAKE,
|
||||
.flags = IRQCHIP_SKIP_SET_WAKE |
|
||||
IRQCHIP_AFFINITY_PRE_STARTUP,
|
||||
};
|
||||
|
||||
static inline void init_IO_APIC_traps(void)
|
||||
|
|
|
@ -58,11 +58,13 @@ msi_set_affinity(struct irq_data *irqd, const struct cpumask *mask, bool force)
|
|||
* The quirk bit is not set in this case.
|
||||
* - The new vector is the same as the old vector
|
||||
* - The old vector is MANAGED_IRQ_SHUTDOWN_VECTOR (interrupt starts up)
|
||||
* - The interrupt is not yet started up
|
||||
* - The new destination CPU is the same as the old destination CPU
|
||||
*/
|
||||
if (!irqd_msi_nomask_quirk(irqd) ||
|
||||
cfg->vector == old_cfg.vector ||
|
||||
old_cfg.vector == MANAGED_IRQ_SHUTDOWN_VECTOR ||
|
||||
!irqd_is_started(irqd) ||
|
||||
cfg->dest_apicid == old_cfg.dest_apicid) {
|
||||
irq_msi_update_msg(irqd, cfg);
|
||||
return ret;
|
||||
|
@ -150,7 +152,8 @@ static struct irq_chip pci_msi_controller = {
|
|||
.irq_ack = irq_chip_ack_parent,
|
||||
.irq_retrigger = irq_chip_retrigger_hierarchy,
|
||||
.irq_set_affinity = msi_set_affinity,
|
||||
.flags = IRQCHIP_SKIP_SET_WAKE,
|
||||
.flags = IRQCHIP_SKIP_SET_WAKE |
|
||||
IRQCHIP_AFFINITY_PRE_STARTUP,
|
||||
};
|
||||
|
||||
int pci_msi_prepare(struct irq_domain *domain, struct device *dev, int nvec,
|
||||
|
@ -219,7 +222,8 @@ static struct irq_chip pci_msi_ir_controller = {
|
|||
.irq_mask = pci_msi_mask_irq,
|
||||
.irq_ack = irq_chip_ack_parent,
|
||||
.irq_retrigger = irq_chip_retrigger_hierarchy,
|
||||
.flags = IRQCHIP_SKIP_SET_WAKE,
|
||||
.flags = IRQCHIP_SKIP_SET_WAKE |
|
||||
IRQCHIP_AFFINITY_PRE_STARTUP,
|
||||
};
|
||||
|
||||
static struct msi_domain_info pci_msi_ir_domain_info = {
|
||||
|
@ -273,7 +277,8 @@ static struct irq_chip dmar_msi_controller = {
|
|||
.irq_retrigger = irq_chip_retrigger_hierarchy,
|
||||
.irq_compose_msi_msg = dmar_msi_compose_msg,
|
||||
.irq_write_msi_msg = dmar_msi_write_msg,
|
||||
.flags = IRQCHIP_SKIP_SET_WAKE,
|
||||
.flags = IRQCHIP_SKIP_SET_WAKE |
|
||||
IRQCHIP_AFFINITY_PRE_STARTUP,
|
||||
};
|
||||
|
||||
static int dmar_msi_init(struct irq_domain *domain,
|
||||
|
|
|
@ -285,15 +285,14 @@ static u64 mbm_overflow_count(u64 prev_msr, u64 cur_msr, unsigned int width)
|
|||
return chunks >>= shift;
|
||||
}
|
||||
|
||||
static int __mon_event_count(u32 rmid, struct rmid_read *rr)
|
||||
static u64 __mon_event_count(u32 rmid, struct rmid_read *rr)
|
||||
{
|
||||
struct mbm_state *m;
|
||||
u64 chunks, tval;
|
||||
|
||||
tval = __rmid_read(rmid, rr->evtid);
|
||||
if (tval & (RMID_VAL_ERROR | RMID_VAL_UNAVAIL)) {
|
||||
rr->val = tval;
|
||||
return -EINVAL;
|
||||
return tval;
|
||||
}
|
||||
switch (rr->evtid) {
|
||||
case QOS_L3_OCCUP_EVENT_ID:
|
||||
|
@ -305,12 +304,6 @@ static int __mon_event_count(u32 rmid, struct rmid_read *rr)
|
|||
case QOS_L3_MBM_LOCAL_EVENT_ID:
|
||||
m = &rr->d->mbm_local[rmid];
|
||||
break;
|
||||
default:
|
||||
/*
|
||||
* Code would never reach here because
|
||||
* an invalid event id would fail the __rmid_read.
|
||||
*/
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (rr->first) {
|
||||
|
@ -361,23 +354,29 @@ void mon_event_count(void *info)
|
|||
struct rdtgroup *rdtgrp, *entry;
|
||||
struct rmid_read *rr = info;
|
||||
struct list_head *head;
|
||||
u64 ret_val;
|
||||
|
||||
rdtgrp = rr->rgrp;
|
||||
|
||||
if (__mon_event_count(rdtgrp->mon.rmid, rr))
|
||||
return;
|
||||
ret_val = __mon_event_count(rdtgrp->mon.rmid, rr);
|
||||
|
||||
/*
|
||||
* For Ctrl groups read data from child monitor groups.
|
||||
* For Ctrl groups read data from child monitor groups and
|
||||
* add them together. Count events which are read successfully.
|
||||
* Discard the rmid_read's reporting errors.
|
||||
*/
|
||||
head = &rdtgrp->mon.crdtgrp_list;
|
||||
|
||||
if (rdtgrp->type == RDTCTRL_GROUP) {
|
||||
list_for_each_entry(entry, head, mon.crdtgrp_list) {
|
||||
if (__mon_event_count(entry->mon.rmid, rr))
|
||||
return;
|
||||
if (__mon_event_count(entry->mon.rmid, rr) == 0)
|
||||
ret_val = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Report error if none of rmid_reads are successful */
|
||||
if (ret_val)
|
||||
rr->val = ret_val;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -508,7 +508,7 @@ static struct irq_chip hpet_msi_controller __ro_after_init = {
|
|||
.irq_set_affinity = msi_domain_set_affinity,
|
||||
.irq_retrigger = irq_chip_retrigger_hierarchy,
|
||||
.irq_write_msi_msg = hpet_msi_write_msg,
|
||||
.flags = IRQCHIP_SKIP_SET_WAKE,
|
||||
.flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_AFFINITY_PRE_STARTUP,
|
||||
};
|
||||
|
||||
static int hpet_msi_init(struct irq_domain *domain,
|
||||
|
|
|
@ -208,30 +208,6 @@ static void kvm_vcpu_after_set_cpuid(struct kvm_vcpu *vcpu)
|
|||
kvm_mmu_after_set_cpuid(vcpu);
|
||||
}
|
||||
|
||||
static int is_efer_nx(void)
|
||||
{
|
||||
return host_efer & EFER_NX;
|
||||
}
|
||||
|
||||
static void cpuid_fix_nx_cap(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
int i;
|
||||
struct kvm_cpuid_entry2 *e, *entry;
|
||||
|
||||
entry = NULL;
|
||||
for (i = 0; i < vcpu->arch.cpuid_nent; ++i) {
|
||||
e = &vcpu->arch.cpuid_entries[i];
|
||||
if (e->function == 0x80000001) {
|
||||
entry = e;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (entry && cpuid_entry_has(entry, X86_FEATURE_NX) && !is_efer_nx()) {
|
||||
cpuid_entry_clear(entry, X86_FEATURE_NX);
|
||||
printk(KERN_INFO "kvm: guest NX capability removed\n");
|
||||
}
|
||||
}
|
||||
|
||||
int cpuid_query_maxphyaddr(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
struct kvm_cpuid_entry2 *best;
|
||||
|
@ -302,7 +278,6 @@ int kvm_vcpu_ioctl_set_cpuid(struct kvm_vcpu *vcpu,
|
|||
vcpu->arch.cpuid_entries = e2;
|
||||
vcpu->arch.cpuid_nent = cpuid->nent;
|
||||
|
||||
cpuid_fix_nx_cap(vcpu);
|
||||
kvm_update_cpuid_runtime(vcpu);
|
||||
kvm_vcpu_after_set_cpuid(vcpu);
|
||||
|
||||
|
@ -401,7 +376,6 @@ static __always_inline void kvm_cpu_cap_mask(enum cpuid_leafs leaf, u32 mask)
|
|||
|
||||
void kvm_set_cpu_caps(void)
|
||||
{
|
||||
unsigned int f_nx = is_efer_nx() ? F(NX) : 0;
|
||||
#ifdef CONFIG_X86_64
|
||||
unsigned int f_gbpages = F(GBPAGES);
|
||||
unsigned int f_lm = F(LM);
|
||||
|
@ -515,7 +489,7 @@ void kvm_set_cpu_caps(void)
|
|||
F(CX8) | F(APIC) | 0 /* Reserved */ | F(SYSCALL) |
|
||||
F(MTRR) | F(PGE) | F(MCA) | F(CMOV) |
|
||||
F(PAT) | F(PSE36) | 0 /* Reserved */ |
|
||||
f_nx | 0 /* Reserved */ | F(MMXEXT) | F(MMX) |
|
||||
F(NX) | 0 /* Reserved */ | F(MMXEXT) | F(MMX) |
|
||||
F(FXSR) | F(FXSR_OPT) | f_gbpages | F(RDTSCP) |
|
||||
0 /* Reserved */ | f_lm | F(3DNOWEXT) | F(3DNOW)
|
||||
);
|
||||
|
|
|
@ -1933,7 +1933,7 @@ ret_success:
|
|||
void kvm_hv_set_cpuid(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
struct kvm_cpuid_entry2 *entry;
|
||||
struct kvm_vcpu_hv *hv_vcpu = to_hv_vcpu(vcpu);
|
||||
struct kvm_vcpu_hv *hv_vcpu;
|
||||
|
||||
entry = kvm_find_cpuid_entry(vcpu, HYPERV_CPUID_INTERFACE, 0);
|
||||
if (entry && entry->eax == HYPERV_CPUID_SIGNATURE_EAX) {
|
||||
|
|
|
@ -2535,6 +2535,7 @@ static void kvm_unsync_page(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp)
|
|||
int mmu_try_to_unsync_pages(struct kvm_vcpu *vcpu, gfn_t gfn, bool can_unsync)
|
||||
{
|
||||
struct kvm_mmu_page *sp;
|
||||
bool locked = false;
|
||||
|
||||
/*
|
||||
* Force write-protection if the page is being tracked. Note, the page
|
||||
|
@ -2557,9 +2558,34 @@ int mmu_try_to_unsync_pages(struct kvm_vcpu *vcpu, gfn_t gfn, bool can_unsync)
|
|||
if (sp->unsync)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* TDP MMU page faults require an additional spinlock as they
|
||||
* run with mmu_lock held for read, not write, and the unsync
|
||||
* logic is not thread safe. Take the spinklock regardless of
|
||||
* the MMU type to avoid extra conditionals/parameters, there's
|
||||
* no meaningful penalty if mmu_lock is held for write.
|
||||
*/
|
||||
if (!locked) {
|
||||
locked = true;
|
||||
spin_lock(&vcpu->kvm->arch.mmu_unsync_pages_lock);
|
||||
|
||||
/*
|
||||
* Recheck after taking the spinlock, a different vCPU
|
||||
* may have since marked the page unsync. A false
|
||||
* positive on the unprotected check above is not
|
||||
* possible as clearing sp->unsync _must_ hold mmu_lock
|
||||
* for write, i.e. unsync cannot transition from 0->1
|
||||
* while this CPU holds mmu_lock for read (or write).
|
||||
*/
|
||||
if (READ_ONCE(sp->unsync))
|
||||
continue;
|
||||
}
|
||||
|
||||
WARN_ON(sp->role.level != PG_LEVEL_4K);
|
||||
kvm_unsync_page(vcpu, sp);
|
||||
}
|
||||
if (locked)
|
||||
spin_unlock(&vcpu->kvm->arch.mmu_unsync_pages_lock);
|
||||
|
||||
/*
|
||||
* We need to ensure that the marking of unsync pages is visible
|
||||
|
@ -5537,6 +5563,8 @@ void kvm_mmu_init_vm(struct kvm *kvm)
|
|||
{
|
||||
struct kvm_page_track_notifier_node *node = &kvm->arch.mmu_sp_tracker;
|
||||
|
||||
spin_lock_init(&kvm->arch.mmu_unsync_pages_lock);
|
||||
|
||||
if (!kvm_mmu_init_tdp_mmu(kvm))
|
||||
/*
|
||||
* No smp_load/store wrappers needed here as we are in
|
||||
|
|
|
@ -43,6 +43,7 @@ void kvm_mmu_uninit_tdp_mmu(struct kvm *kvm)
|
|||
if (!kvm->arch.tdp_mmu_enabled)
|
||||
return;
|
||||
|
||||
WARN_ON(!list_empty(&kvm->arch.tdp_mmu_pages));
|
||||
WARN_ON(!list_empty(&kvm->arch.tdp_mmu_roots));
|
||||
|
||||
/*
|
||||
|
@ -81,8 +82,6 @@ static void tdp_mmu_free_sp_rcu_callback(struct rcu_head *head)
|
|||
void kvm_tdp_mmu_put_root(struct kvm *kvm, struct kvm_mmu_page *root,
|
||||
bool shared)
|
||||
{
|
||||
gfn_t max_gfn = 1ULL << (shadow_phys_bits - PAGE_SHIFT);
|
||||
|
||||
kvm_lockdep_assert_mmu_lock_held(kvm, shared);
|
||||
|
||||
if (!refcount_dec_and_test(&root->tdp_mmu_root_count))
|
||||
|
@ -94,7 +93,7 @@ void kvm_tdp_mmu_put_root(struct kvm *kvm, struct kvm_mmu_page *root,
|
|||
list_del_rcu(&root->link);
|
||||
spin_unlock(&kvm->arch.tdp_mmu_pages_lock);
|
||||
|
||||
zap_gfn_range(kvm, root, 0, max_gfn, false, false, shared);
|
||||
zap_gfn_range(kvm, root, 0, -1ull, false, false, shared);
|
||||
|
||||
call_rcu(&root->rcu_head, tdp_mmu_free_sp_rcu_callback);
|
||||
}
|
||||
|
@ -724,13 +723,29 @@ static bool zap_gfn_range(struct kvm *kvm, struct kvm_mmu_page *root,
|
|||
gfn_t start, gfn_t end, bool can_yield, bool flush,
|
||||
bool shared)
|
||||
{
|
||||
gfn_t max_gfn_host = 1ULL << (shadow_phys_bits - PAGE_SHIFT);
|
||||
bool zap_all = (start == 0 && end >= max_gfn_host);
|
||||
struct tdp_iter iter;
|
||||
|
||||
/*
|
||||
* No need to try to step down in the iterator when zapping all SPTEs,
|
||||
* zapping the top-level non-leaf SPTEs will recurse on their children.
|
||||
*/
|
||||
int min_level = zap_all ? root->role.level : PG_LEVEL_4K;
|
||||
|
||||
/*
|
||||
* Bound the walk at host.MAXPHYADDR, guest accesses beyond that will
|
||||
* hit a #PF(RSVD) and never get to an EPT Violation/Misconfig / #NPF,
|
||||
* and so KVM will never install a SPTE for such addresses.
|
||||
*/
|
||||
end = min(end, max_gfn_host);
|
||||
|
||||
kvm_lockdep_assert_mmu_lock_held(kvm, shared);
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
tdp_root_for_each_pte(iter, root, start, end) {
|
||||
for_each_tdp_pte_min_level(iter, root->spt, root->role.level,
|
||||
min_level, start, end) {
|
||||
retry:
|
||||
if (can_yield &&
|
||||
tdp_mmu_iter_cond_resched(kvm, &iter, flush, shared)) {
|
||||
|
@ -744,9 +759,10 @@ retry:
|
|||
/*
|
||||
* If this is a non-last-level SPTE that covers a larger range
|
||||
* than should be zapped, continue, and zap the mappings at a
|
||||
* lower level.
|
||||
* lower level, except when zapping all SPTEs.
|
||||
*/
|
||||
if ((iter.gfn < start ||
|
||||
if (!zap_all &&
|
||||
(iter.gfn < start ||
|
||||
iter.gfn + KVM_PAGES_PER_HPAGE(iter.level) > end) &&
|
||||
!is_last_spte(iter.old_spte, iter.level))
|
||||
continue;
|
||||
|
@ -794,12 +810,11 @@ bool __kvm_tdp_mmu_zap_gfn_range(struct kvm *kvm, int as_id, gfn_t start,
|
|||
|
||||
void kvm_tdp_mmu_zap_all(struct kvm *kvm)
|
||||
{
|
||||
gfn_t max_gfn = 1ULL << (shadow_phys_bits - PAGE_SHIFT);
|
||||
bool flush = false;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < KVM_ADDRESS_SPACE_NUM; i++)
|
||||
flush = kvm_tdp_mmu_zap_gfn_range(kvm, i, 0, max_gfn,
|
||||
flush = kvm_tdp_mmu_zap_gfn_range(kvm, i, 0, -1ull,
|
||||
flush, false);
|
||||
|
||||
if (flush)
|
||||
|
@ -838,7 +853,6 @@ static struct kvm_mmu_page *next_invalidated_root(struct kvm *kvm,
|
|||
*/
|
||||
void kvm_tdp_mmu_zap_invalidated_roots(struct kvm *kvm)
|
||||
{
|
||||
gfn_t max_gfn = 1ULL << (shadow_phys_bits - PAGE_SHIFT);
|
||||
struct kvm_mmu_page *next_root;
|
||||
struct kvm_mmu_page *root;
|
||||
bool flush = false;
|
||||
|
@ -854,8 +868,7 @@ void kvm_tdp_mmu_zap_invalidated_roots(struct kvm *kvm)
|
|||
|
||||
rcu_read_unlock();
|
||||
|
||||
flush = zap_gfn_range(kvm, root, 0, max_gfn, true, flush,
|
||||
true);
|
||||
flush = zap_gfn_range(kvm, root, 0, -1ull, true, flush, true);
|
||||
|
||||
/*
|
||||
* Put the reference acquired in
|
||||
|
|
|
@ -158,6 +158,9 @@ void recalc_intercepts(struct vcpu_svm *svm)
|
|||
/* If SMI is not intercepted, ignore guest SMI intercept as well */
|
||||
if (!intercept_smi)
|
||||
vmcb_clr_intercept(c, INTERCEPT_SMI);
|
||||
|
||||
vmcb_set_intercept(c, INTERCEPT_VMLOAD);
|
||||
vmcb_set_intercept(c, INTERCEPT_VMSAVE);
|
||||
}
|
||||
|
||||
static void copy_vmcb_control_area(struct vmcb_control_area *dst,
|
||||
|
@ -503,7 +506,11 @@ static void nested_vmcb02_prepare_save(struct vcpu_svm *svm, struct vmcb *vmcb12
|
|||
|
||||
static void nested_vmcb02_prepare_control(struct vcpu_svm *svm)
|
||||
{
|
||||
const u32 mask = V_INTR_MASKING_MASK | V_GIF_ENABLE_MASK | V_GIF_MASK;
|
||||
const u32 int_ctl_vmcb01_bits =
|
||||
V_INTR_MASKING_MASK | V_GIF_MASK | V_GIF_ENABLE_MASK;
|
||||
|
||||
const u32 int_ctl_vmcb12_bits = V_TPR_MASK | V_IRQ_INJECTION_BITS_MASK;
|
||||
|
||||
struct kvm_vcpu *vcpu = &svm->vcpu;
|
||||
|
||||
/*
|
||||
|
@ -535,8 +542,8 @@ static void nested_vmcb02_prepare_control(struct vcpu_svm *svm)
|
|||
vcpu->arch.l1_tsc_offset + svm->nested.ctl.tsc_offset;
|
||||
|
||||
svm->vmcb->control.int_ctl =
|
||||
(svm->nested.ctl.int_ctl & ~mask) |
|
||||
(svm->vmcb01.ptr->control.int_ctl & mask);
|
||||
(svm->nested.ctl.int_ctl & int_ctl_vmcb12_bits) |
|
||||
(svm->vmcb01.ptr->control.int_ctl & int_ctl_vmcb01_bits);
|
||||
|
||||
svm->vmcb->control.virt_ext = svm->nested.ctl.virt_ext;
|
||||
svm->vmcb->control.int_vector = svm->nested.ctl.int_vector;
|
||||
|
|
|
@ -1589,17 +1589,18 @@ static void svm_set_vintr(struct vcpu_svm *svm)
|
|||
|
||||
static void svm_clear_vintr(struct vcpu_svm *svm)
|
||||
{
|
||||
const u32 mask = V_TPR_MASK | V_GIF_ENABLE_MASK | V_GIF_MASK | V_INTR_MASKING_MASK;
|
||||
svm_clr_intercept(svm, INTERCEPT_VINTR);
|
||||
|
||||
/* Drop int_ctl fields related to VINTR injection. */
|
||||
svm->vmcb->control.int_ctl &= mask;
|
||||
svm->vmcb->control.int_ctl &= ~V_IRQ_INJECTION_BITS_MASK;
|
||||
if (is_guest_mode(&svm->vcpu)) {
|
||||
svm->vmcb01.ptr->control.int_ctl &= mask;
|
||||
svm->vmcb01.ptr->control.int_ctl &= ~V_IRQ_INJECTION_BITS_MASK;
|
||||
|
||||
WARN_ON((svm->vmcb->control.int_ctl & V_TPR_MASK) !=
|
||||
(svm->nested.ctl.int_ctl & V_TPR_MASK));
|
||||
svm->vmcb->control.int_ctl |= svm->nested.ctl.int_ctl & ~mask;
|
||||
|
||||
svm->vmcb->control.int_ctl |= svm->nested.ctl.int_ctl &
|
||||
V_IRQ_INJECTION_BITS_MASK;
|
||||
}
|
||||
|
||||
vmcb_mark_dirty(svm->vmcb, VMCB_INTR);
|
||||
|
|
|
@ -330,6 +330,31 @@ void nested_vmx_free_vcpu(struct kvm_vcpu *vcpu)
|
|||
vcpu_put(vcpu);
|
||||
}
|
||||
|
||||
#define EPTP_PA_MASK GENMASK_ULL(51, 12)
|
||||
|
||||
static bool nested_ept_root_matches(hpa_t root_hpa, u64 root_eptp, u64 eptp)
|
||||
{
|
||||
return VALID_PAGE(root_hpa) &&
|
||||
((root_eptp & EPTP_PA_MASK) == (eptp & EPTP_PA_MASK));
|
||||
}
|
||||
|
||||
static void nested_ept_invalidate_addr(struct kvm_vcpu *vcpu, gpa_t eptp,
|
||||
gpa_t addr)
|
||||
{
|
||||
uint i;
|
||||
struct kvm_mmu_root_info *cached_root;
|
||||
|
||||
WARN_ON_ONCE(!mmu_is_nested(vcpu));
|
||||
|
||||
for (i = 0; i < KVM_MMU_NUM_PREV_ROOTS; i++) {
|
||||
cached_root = &vcpu->arch.mmu->prev_roots[i];
|
||||
|
||||
if (nested_ept_root_matches(cached_root->hpa, cached_root->pgd,
|
||||
eptp))
|
||||
vcpu->arch.mmu->invlpg(vcpu, addr, cached_root->hpa);
|
||||
}
|
||||
}
|
||||
|
||||
static void nested_ept_inject_page_fault(struct kvm_vcpu *vcpu,
|
||||
struct x86_exception *fault)
|
||||
{
|
||||
|
@ -342,10 +367,22 @@ static void nested_ept_inject_page_fault(struct kvm_vcpu *vcpu,
|
|||
vm_exit_reason = EXIT_REASON_PML_FULL;
|
||||
vmx->nested.pml_full = false;
|
||||
exit_qualification &= INTR_INFO_UNBLOCK_NMI;
|
||||
} else if (fault->error_code & PFERR_RSVD_MASK)
|
||||
vm_exit_reason = EXIT_REASON_EPT_MISCONFIG;
|
||||
else
|
||||
vm_exit_reason = EXIT_REASON_EPT_VIOLATION;
|
||||
} else {
|
||||
if (fault->error_code & PFERR_RSVD_MASK)
|
||||
vm_exit_reason = EXIT_REASON_EPT_MISCONFIG;
|
||||
else
|
||||
vm_exit_reason = EXIT_REASON_EPT_VIOLATION;
|
||||
|
||||
/*
|
||||
* Although the caller (kvm_inject_emulated_page_fault) would
|
||||
* have already synced the faulting address in the shadow EPT
|
||||
* tables for the current EPTP12, we also need to sync it for
|
||||
* any other cached EPTP02s based on the same EP4TA, since the
|
||||
* TLB associates mappings to the EP4TA rather than the full EPTP.
|
||||
*/
|
||||
nested_ept_invalidate_addr(vcpu, vmcs12->ept_pointer,
|
||||
fault->address);
|
||||
}
|
||||
|
||||
nested_vmx_vmexit(vcpu, vm_exit_reason, 0, exit_qualification);
|
||||
vmcs12->guest_physical_address = fault->address;
|
||||
|
@ -5325,14 +5362,6 @@ static int handle_vmptrst(struct kvm_vcpu *vcpu)
|
|||
return nested_vmx_succeed(vcpu);
|
||||
}
|
||||
|
||||
#define EPTP_PA_MASK GENMASK_ULL(51, 12)
|
||||
|
||||
static bool nested_ept_root_matches(hpa_t root_hpa, u64 root_eptp, u64 eptp)
|
||||
{
|
||||
return VALID_PAGE(root_hpa) &&
|
||||
((root_eptp & EPTP_PA_MASK) == (eptp & EPTP_PA_MASK));
|
||||
}
|
||||
|
||||
/* Emulate the INVEPT instruction */
|
||||
static int handle_invept(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
|
@ -5826,7 +5855,8 @@ static bool nested_vmx_l0_wants_exit(struct kvm_vcpu *vcpu,
|
|||
if (is_nmi(intr_info))
|
||||
return true;
|
||||
else if (is_page_fault(intr_info))
|
||||
return vcpu->arch.apf.host_apf_flags || !enable_ept;
|
||||
return vcpu->arch.apf.host_apf_flags ||
|
||||
vmx_need_pf_intercept(vcpu);
|
||||
else if (is_debug(intr_info) &&
|
||||
vcpu->guest_debug &
|
||||
(KVM_GUESTDBG_SINGLESTEP | KVM_GUESTDBG_USE_HW_BP))
|
||||
|
|
|
@ -522,7 +522,7 @@ static inline struct vmcs *alloc_vmcs(bool shadow)
|
|||
|
||||
static inline bool vmx_has_waitpkg(struct vcpu_vmx *vmx)
|
||||
{
|
||||
return vmx->secondary_exec_control &
|
||||
return secondary_exec_controls_get(vmx) &
|
||||
SECONDARY_EXEC_ENABLE_USR_WAIT_PAUSE;
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ BEGIN {
|
|||
|
||||
/^GNU objdump/ {
|
||||
verstr = ""
|
||||
gsub(/\(.*\)/, "");
|
||||
for (i = 3; i <= NF; i++)
|
||||
if (match($(i), "^[0-9]")) {
|
||||
verstr = $(i);
|
||||
|
|
|
@ -9,12 +9,6 @@ config MQ_IOSCHED_DEADLINE
|
|||
help
|
||||
MQ version of the deadline IO scheduler.
|
||||
|
||||
config MQ_IOSCHED_DEADLINE_CGROUP
|
||||
tristate
|
||||
default y
|
||||
depends on MQ_IOSCHED_DEADLINE
|
||||
depends on BLK_CGROUP
|
||||
|
||||
config MQ_IOSCHED_KYBER
|
||||
tristate "Kyber I/O scheduler"
|
||||
default y
|
||||
|
|
|
@ -22,8 +22,6 @@ obj-$(CONFIG_BLK_CGROUP_IOPRIO) += blk-ioprio.o
|
|||
obj-$(CONFIG_BLK_CGROUP_IOLATENCY) += blk-iolatency.o
|
||||
obj-$(CONFIG_BLK_CGROUP_IOCOST) += blk-iocost.o
|
||||
obj-$(CONFIG_MQ_IOSCHED_DEADLINE) += mq-deadline.o
|
||||
mq-deadline-y += mq-deadline-main.o
|
||||
mq-deadline-$(CONFIG_MQ_IOSCHED_DEADLINE_CGROUP)+= mq-deadline-cgroup.o
|
||||
obj-$(CONFIG_MQ_IOSCHED_KYBER) += kyber-iosched.o
|
||||
bfq-y := bfq-iosched.o bfq-wf2q.o bfq-cgroup.o
|
||||
obj-$(CONFIG_IOSCHED_BFQ) += bfq.o
|
||||
|
|
|
@ -790,6 +790,7 @@ static void blkcg_rstat_flush(struct cgroup_subsys_state *css, int cpu)
|
|||
struct blkcg_gq *parent = blkg->parent;
|
||||
struct blkg_iostat_set *bisc = per_cpu_ptr(blkg->iostat_cpu, cpu);
|
||||
struct blkg_iostat cur, delta;
|
||||
unsigned long flags;
|
||||
unsigned int seq;
|
||||
|
||||
/* fetch the current per-cpu values */
|
||||
|
@ -799,21 +800,21 @@ static void blkcg_rstat_flush(struct cgroup_subsys_state *css, int cpu)
|
|||
} while (u64_stats_fetch_retry(&bisc->sync, seq));
|
||||
|
||||
/* propagate percpu delta to global */
|
||||
u64_stats_update_begin(&blkg->iostat.sync);
|
||||
flags = u64_stats_update_begin_irqsave(&blkg->iostat.sync);
|
||||
blkg_iostat_set(&delta, &cur);
|
||||
blkg_iostat_sub(&delta, &bisc->last);
|
||||
blkg_iostat_add(&blkg->iostat.cur, &delta);
|
||||
blkg_iostat_add(&bisc->last, &delta);
|
||||
u64_stats_update_end(&blkg->iostat.sync);
|
||||
u64_stats_update_end_irqrestore(&blkg->iostat.sync, flags);
|
||||
|
||||
/* propagate global delta to parent (unless that's root) */
|
||||
if (parent && parent->parent) {
|
||||
u64_stats_update_begin(&parent->iostat.sync);
|
||||
flags = u64_stats_update_begin_irqsave(&parent->iostat.sync);
|
||||
blkg_iostat_set(&delta, &blkg->iostat.cur);
|
||||
blkg_iostat_sub(&delta, &blkg->iostat.last);
|
||||
blkg_iostat_add(&parent->iostat.cur, &delta);
|
||||
blkg_iostat_add(&blkg->iostat.last, &delta);
|
||||
u64_stats_update_end(&parent->iostat.sync);
|
||||
u64_stats_update_end_irqrestore(&parent->iostat.sync, flags);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -848,6 +849,7 @@ static void blkcg_fill_root_iostats(void)
|
|||
memset(&tmp, 0, sizeof(tmp));
|
||||
for_each_possible_cpu(cpu) {
|
||||
struct disk_stats *cpu_dkstats;
|
||||
unsigned long flags;
|
||||
|
||||
cpu_dkstats = per_cpu_ptr(bdev->bd_stats, cpu);
|
||||
tmp.ios[BLKG_IOSTAT_READ] +=
|
||||
|
@ -864,9 +866,9 @@ static void blkcg_fill_root_iostats(void)
|
|||
tmp.bytes[BLKG_IOSTAT_DISCARD] +=
|
||||
cpu_dkstats->sectors[STAT_DISCARD] << 9;
|
||||
|
||||
u64_stats_update_begin(&blkg->iostat.sync);
|
||||
flags = u64_stats_update_begin_irqsave(&blkg->iostat.sync);
|
||||
blkg_iostat_set(&blkg->iostat.cur, &tmp);
|
||||
u64_stats_update_end(&blkg->iostat.sync);
|
||||
u64_stats_update_end_irqrestore(&blkg->iostat.sync, flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -122,7 +122,6 @@ void blk_rq_init(struct request_queue *q, struct request *rq)
|
|||
rq->internal_tag = BLK_MQ_NO_TAG;
|
||||
rq->start_time_ns = ktime_get_ns();
|
||||
rq->part = NULL;
|
||||
refcount_set(&rq->ref, 1);
|
||||
blk_crypto_rq_set_defaults(rq);
|
||||
}
|
||||
EXPORT_SYMBOL(blk_rq_init);
|
||||
|
|
|
@ -262,6 +262,11 @@ static void flush_end_io(struct request *flush_rq, blk_status_t error)
|
|||
spin_unlock_irqrestore(&fq->mq_flush_lock, flags);
|
||||
}
|
||||
|
||||
bool is_flush_rq(struct request *rq)
|
||||
{
|
||||
return rq->end_io == flush_end_io;
|
||||
}
|
||||
|
||||
/**
|
||||
* blk_kick_flush - consider issuing flush request
|
||||
* @q: request_queue being kicked
|
||||
|
@ -329,6 +334,14 @@ static void blk_kick_flush(struct request_queue *q, struct blk_flush_queue *fq,
|
|||
flush_rq->rq_flags |= RQF_FLUSH_SEQ;
|
||||
flush_rq->rq_disk = first_rq->rq_disk;
|
||||
flush_rq->end_io = flush_end_io;
|
||||
/*
|
||||
* Order WRITE ->end_io and WRITE rq->ref, and its pair is the one
|
||||
* implied in refcount_inc_not_zero() called from
|
||||
* blk_mq_find_and_get_req(), which orders WRITE/READ flush_rq->ref
|
||||
* and READ flush_rq->end_io
|
||||
*/
|
||||
smp_wmb();
|
||||
refcount_set(&flush_rq->ref, 1);
|
||||
|
||||
blk_flush_queue_rq(flush_rq, false);
|
||||
}
|
||||
|
|
|
@ -3061,19 +3061,19 @@ static ssize_t ioc_weight_write(struct kernfs_open_file *of, char *buf,
|
|||
if (v < CGROUP_WEIGHT_MIN || v > CGROUP_WEIGHT_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock(&blkcg->lock);
|
||||
spin_lock_irq(&blkcg->lock);
|
||||
iocc->dfl_weight = v * WEIGHT_ONE;
|
||||
hlist_for_each_entry(blkg, &blkcg->blkg_list, blkcg_node) {
|
||||
struct ioc_gq *iocg = blkg_to_iocg(blkg);
|
||||
|
||||
if (iocg) {
|
||||
spin_lock_irq(&iocg->ioc->lock);
|
||||
spin_lock(&iocg->ioc->lock);
|
||||
ioc_now(iocg->ioc, &now);
|
||||
weight_updated(iocg, &now);
|
||||
spin_unlock_irq(&iocg->ioc->lock);
|
||||
spin_unlock(&iocg->ioc->lock);
|
||||
}
|
||||
}
|
||||
spin_unlock(&blkcg->lock);
|
||||
spin_unlock_irq(&blkcg->lock);
|
||||
|
||||
return nbytes;
|
||||
}
|
||||
|
|
|
@ -911,7 +911,7 @@ static bool blk_mq_req_expired(struct request *rq, unsigned long *next)
|
|||
|
||||
void blk_mq_put_rq_ref(struct request *rq)
|
||||
{
|
||||
if (is_flush_rq(rq, rq->mq_hctx))
|
||||
if (is_flush_rq(rq))
|
||||
rq->end_io(rq, 0);
|
||||
else if (refcount_dec_and_test(&rq->ref))
|
||||
__blk_mq_free_request(rq);
|
||||
|
@ -923,34 +923,14 @@ static bool blk_mq_check_expired(struct blk_mq_hw_ctx *hctx,
|
|||
unsigned long *next = priv;
|
||||
|
||||
/*
|
||||
* Just do a quick check if it is expired before locking the request in
|
||||
* so we're not unnecessarilly synchronizing across CPUs.
|
||||
*/
|
||||
if (!blk_mq_req_expired(rq, next))
|
||||
return true;
|
||||
|
||||
/*
|
||||
* We have reason to believe the request may be expired. Take a
|
||||
* reference on the request to lock this request lifetime into its
|
||||
* currently allocated context to prevent it from being reallocated in
|
||||
* the event the completion by-passes this timeout handler.
|
||||
*
|
||||
* If the reference was already released, then the driver beat the
|
||||
* timeout handler to posting a natural completion.
|
||||
*/
|
||||
if (!refcount_inc_not_zero(&rq->ref))
|
||||
return true;
|
||||
|
||||
/*
|
||||
* The request is now locked and cannot be reallocated underneath the
|
||||
* timeout handler's processing. Re-verify this exact request is truly
|
||||
* expired; if it is not expired, then the request was completed and
|
||||
* reallocated as a new request.
|
||||
* blk_mq_queue_tag_busy_iter() has locked the request, so it cannot
|
||||
* be reallocated underneath the timeout handler's processing, then
|
||||
* the expire check is reliable. If the request is not expired, then
|
||||
* it was completed and reallocated as a new request after returning
|
||||
* from blk_mq_check_expired().
|
||||
*/
|
||||
if (blk_mq_req_expired(rq, next))
|
||||
blk_mq_rq_timed_out(rq, reserved);
|
||||
|
||||
blk_mq_put_rq_ref(rq);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2994,10 +2974,12 @@ static void queue_set_hctx_shared(struct request_queue *q, bool shared)
|
|||
int i;
|
||||
|
||||
queue_for_each_hw_ctx(q, hctx, i) {
|
||||
if (shared)
|
||||
if (shared) {
|
||||
hctx->flags |= BLK_MQ_F_TAG_QUEUE_SHARED;
|
||||
else
|
||||
} else {
|
||||
blk_mq_tag_idle(hctx);
|
||||
hctx->flags &= ~BLK_MQ_F_TAG_QUEUE_SHARED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -44,11 +44,7 @@ static inline void __blk_get_queue(struct request_queue *q)
|
|||
kobject_get(&q->kobj);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
is_flush_rq(struct request *req, struct blk_mq_hw_ctx *hctx)
|
||||
{
|
||||
return hctx->fq->flush_rq == req;
|
||||
}
|
||||
bool is_flush_rq(struct request *req);
|
||||
|
||||
struct blk_flush_queue *blk_alloc_flush_queue(int node, int cmd_size,
|
||||
gfp_t flags);
|
||||
|
|
|
@ -1,126 +0,0 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
#include <linux/blk-cgroup.h>
|
||||
#include <linux/ioprio.h>
|
||||
|
||||
#include "mq-deadline-cgroup.h"
|
||||
|
||||
static struct blkcg_policy dd_blkcg_policy;
|
||||
|
||||
static struct blkcg_policy_data *dd_cpd_alloc(gfp_t gfp)
|
||||
{
|
||||
struct dd_blkcg *pd;
|
||||
|
||||
pd = kzalloc(sizeof(*pd), gfp);
|
||||
if (!pd)
|
||||
return NULL;
|
||||
pd->stats = alloc_percpu_gfp(typeof(*pd->stats),
|
||||
GFP_KERNEL | __GFP_ZERO);
|
||||
if (!pd->stats) {
|
||||
kfree(pd);
|
||||
return NULL;
|
||||
}
|
||||
return &pd->cpd;
|
||||
}
|
||||
|
||||
static void dd_cpd_free(struct blkcg_policy_data *cpd)
|
||||
{
|
||||
struct dd_blkcg *dd_blkcg = container_of(cpd, typeof(*dd_blkcg), cpd);
|
||||
|
||||
free_percpu(dd_blkcg->stats);
|
||||
kfree(dd_blkcg);
|
||||
}
|
||||
|
||||
static struct dd_blkcg *dd_blkcg_from_pd(struct blkg_policy_data *pd)
|
||||
{
|
||||
return container_of(blkcg_to_cpd(pd->blkg->blkcg, &dd_blkcg_policy),
|
||||
struct dd_blkcg, cpd);
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert an association between a block cgroup and a request queue into a
|
||||
* pointer to the mq-deadline information associated with a (blkcg, queue) pair.
|
||||
*/
|
||||
struct dd_blkcg *dd_blkcg_from_bio(struct bio *bio)
|
||||
{
|
||||
struct blkg_policy_data *pd;
|
||||
|
||||
pd = blkg_to_pd(bio->bi_blkg, &dd_blkcg_policy);
|
||||
if (!pd)
|
||||
return NULL;
|
||||
|
||||
return dd_blkcg_from_pd(pd);
|
||||
}
|
||||
|
||||
static size_t dd_pd_stat(struct blkg_policy_data *pd, char *buf, size_t size)
|
||||
{
|
||||
static const char *const prio_class_name[] = {
|
||||
[IOPRIO_CLASS_NONE] = "NONE",
|
||||
[IOPRIO_CLASS_RT] = "RT",
|
||||
[IOPRIO_CLASS_BE] = "BE",
|
||||
[IOPRIO_CLASS_IDLE] = "IDLE",
|
||||
};
|
||||
struct dd_blkcg *blkcg = dd_blkcg_from_pd(pd);
|
||||
int res = 0;
|
||||
u8 prio;
|
||||
|
||||
for (prio = 0; prio < ARRAY_SIZE(blkcg->stats->stats); prio++)
|
||||
res += scnprintf(buf + res, size - res,
|
||||
" [%s] dispatched=%u inserted=%u merged=%u",
|
||||
prio_class_name[prio],
|
||||
ddcg_sum(blkcg, dispatched, prio) +
|
||||
ddcg_sum(blkcg, merged, prio) -
|
||||
ddcg_sum(blkcg, completed, prio),
|
||||
ddcg_sum(blkcg, inserted, prio) -
|
||||
ddcg_sum(blkcg, completed, prio),
|
||||
ddcg_sum(blkcg, merged, prio));
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static struct blkg_policy_data *dd_pd_alloc(gfp_t gfp, struct request_queue *q,
|
||||
struct blkcg *blkcg)
|
||||
{
|
||||
struct dd_blkg *pd;
|
||||
|
||||
pd = kzalloc(sizeof(*pd), gfp);
|
||||
if (!pd)
|
||||
return NULL;
|
||||
return &pd->pd;
|
||||
}
|
||||
|
||||
static void dd_pd_free(struct blkg_policy_data *pd)
|
||||
{
|
||||
struct dd_blkg *dd_blkg = container_of(pd, typeof(*dd_blkg), pd);
|
||||
|
||||
kfree(dd_blkg);
|
||||
}
|
||||
|
||||
static struct blkcg_policy dd_blkcg_policy = {
|
||||
.cpd_alloc_fn = dd_cpd_alloc,
|
||||
.cpd_free_fn = dd_cpd_free,
|
||||
|
||||
.pd_alloc_fn = dd_pd_alloc,
|
||||
.pd_free_fn = dd_pd_free,
|
||||
.pd_stat_fn = dd_pd_stat,
|
||||
};
|
||||
|
||||
int dd_activate_policy(struct request_queue *q)
|
||||
{
|
||||
return blkcg_activate_policy(q, &dd_blkcg_policy);
|
||||
}
|
||||
|
||||
void dd_deactivate_policy(struct request_queue *q)
|
||||
{
|
||||
blkcg_deactivate_policy(q, &dd_blkcg_policy);
|
||||
}
|
||||
|
||||
int __init dd_blkcg_init(void)
|
||||
{
|
||||
return blkcg_policy_register(&dd_blkcg_policy);
|
||||
}
|
||||
|
||||
void __exit dd_blkcg_exit(void)
|
||||
{
|
||||
blkcg_policy_unregister(&dd_blkcg_policy);
|
||||
}
|
|
@ -1,114 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
|
||||
#if !defined(_MQ_DEADLINE_CGROUP_H_)
|
||||
#define _MQ_DEADLINE_CGROUP_H_
|
||||
|
||||
#include <linux/blk-cgroup.h>
|
||||
|
||||
struct request_queue;
|
||||
|
||||
/**
|
||||
* struct io_stats_per_prio - I/O statistics per I/O priority class.
|
||||
* @inserted: Number of inserted requests.
|
||||
* @merged: Number of merged requests.
|
||||
* @dispatched: Number of dispatched requests.
|
||||
* @completed: Number of I/O completions.
|
||||
*/
|
||||
struct io_stats_per_prio {
|
||||
local_t inserted;
|
||||
local_t merged;
|
||||
local_t dispatched;
|
||||
local_t completed;
|
||||
};
|
||||
|
||||
/* I/O statistics per I/O cgroup per I/O priority class (IOPRIO_CLASS_*). */
|
||||
struct blkcg_io_stats {
|
||||
struct io_stats_per_prio stats[4];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct dd_blkcg - Per cgroup data.
|
||||
* @cpd: blkcg_policy_data structure.
|
||||
* @stats: I/O statistics.
|
||||
*/
|
||||
struct dd_blkcg {
|
||||
struct blkcg_policy_data cpd; /* must be the first member */
|
||||
struct blkcg_io_stats __percpu *stats;
|
||||
};
|
||||
|
||||
/*
|
||||
* Count one event of type 'event_type' and with I/O priority class
|
||||
* 'prio_class'.
|
||||
*/
|
||||
#define ddcg_count(ddcg, event_type, prio_class) do { \
|
||||
if (ddcg) { \
|
||||
struct blkcg_io_stats *io_stats = get_cpu_ptr((ddcg)->stats); \
|
||||
\
|
||||
BUILD_BUG_ON(!__same_type((ddcg), struct dd_blkcg *)); \
|
||||
BUILD_BUG_ON(!__same_type((prio_class), u8)); \
|
||||
local_inc(&io_stats->stats[(prio_class)].event_type); \
|
||||
put_cpu_ptr(io_stats); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Returns the total number of ddcg_count(ddcg, event_type, prio_class) calls
|
||||
* across all CPUs. No locking or barriers since it is fine if the returned
|
||||
* sum is slightly outdated.
|
||||
*/
|
||||
#define ddcg_sum(ddcg, event_type, prio) ({ \
|
||||
unsigned int cpu; \
|
||||
u32 sum = 0; \
|
||||
\
|
||||
BUILD_BUG_ON(!__same_type((ddcg), struct dd_blkcg *)); \
|
||||
BUILD_BUG_ON(!__same_type((prio), u8)); \
|
||||
for_each_present_cpu(cpu) \
|
||||
sum += local_read(&per_cpu_ptr((ddcg)->stats, cpu)-> \
|
||||
stats[(prio)].event_type); \
|
||||
sum; \
|
||||
})
|
||||
|
||||
#ifdef CONFIG_BLK_CGROUP
|
||||
|
||||
/**
|
||||
* struct dd_blkg - Per (cgroup, request queue) data.
|
||||
* @pd: blkg_policy_data structure.
|
||||
*/
|
||||
struct dd_blkg {
|
||||
struct blkg_policy_data pd; /* must be the first member */
|
||||
};
|
||||
|
||||
struct dd_blkcg *dd_blkcg_from_bio(struct bio *bio);
|
||||
int dd_activate_policy(struct request_queue *q);
|
||||
void dd_deactivate_policy(struct request_queue *q);
|
||||
int __init dd_blkcg_init(void);
|
||||
void __exit dd_blkcg_exit(void);
|
||||
|
||||
#else /* CONFIG_BLK_CGROUP */
|
||||
|
||||
static inline struct dd_blkcg *dd_blkcg_from_bio(struct bio *bio)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline int dd_activate_policy(struct request_queue *q)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void dd_deactivate_policy(struct request_queue *q)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int dd_blkcg_init(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void dd_blkcg_exit(void)
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* CONFIG_BLK_CGROUP */
|
||||
|
||||
#endif /* _MQ_DEADLINE_CGROUP_H_ */
|
|
@ -25,7 +25,6 @@
|
|||
#include "blk-mq-debugfs.h"
|
||||
#include "blk-mq-tag.h"
|
||||
#include "blk-mq-sched.h"
|
||||
#include "mq-deadline-cgroup.h"
|
||||
|
||||
/*
|
||||
* See Documentation/block/deadline-iosched.rst
|
||||
|
@ -57,6 +56,14 @@ enum dd_prio {
|
|||
|
||||
enum { DD_PRIO_COUNT = 3 };
|
||||
|
||||
/* I/O statistics per I/O priority. */
|
||||
struct io_stats_per_prio {
|
||||
local_t inserted;
|
||||
local_t merged;
|
||||
local_t dispatched;
|
||||
local_t completed;
|
||||
};
|
||||
|
||||
/* I/O statistics for all I/O priorities (enum dd_prio). */
|
||||
struct io_stats {
|
||||
struct io_stats_per_prio stats[DD_PRIO_COUNT];
|
||||
|
@ -79,9 +86,6 @@ struct deadline_data {
|
|||
* run time data
|
||||
*/
|
||||
|
||||
/* Request queue that owns this data structure. */
|
||||
struct request_queue *queue;
|
||||
|
||||
struct dd_per_prio per_prio[DD_PRIO_COUNT];
|
||||
|
||||
/* Data direction of latest dispatched request. */
|
||||
|
@ -234,10 +238,8 @@ static void dd_merged_requests(struct request_queue *q, struct request *req,
|
|||
struct deadline_data *dd = q->elevator->elevator_data;
|
||||
const u8 ioprio_class = dd_rq_ioclass(next);
|
||||
const enum dd_prio prio = ioprio_class_to_prio[ioprio_class];
|
||||
struct dd_blkcg *blkcg = next->elv.priv[0];
|
||||
|
||||
dd_count(dd, merged, prio);
|
||||
ddcg_count(blkcg, merged, ioprio_class);
|
||||
|
||||
/*
|
||||
* if next expires before rq, assign its expire time to rq
|
||||
|
@ -375,7 +377,6 @@ static struct request *__dd_dispatch_request(struct deadline_data *dd,
|
|||
{
|
||||
struct request *rq, *next_rq;
|
||||
enum dd_data_dir data_dir;
|
||||
struct dd_blkcg *blkcg;
|
||||
enum dd_prio prio;
|
||||
u8 ioprio_class;
|
||||
|
||||
|
@ -474,8 +475,6 @@ done:
|
|||
ioprio_class = dd_rq_ioclass(rq);
|
||||
prio = ioprio_class_to_prio[ioprio_class];
|
||||
dd_count(dd, dispatched, prio);
|
||||
blkcg = rq->elv.priv[0];
|
||||
ddcg_count(blkcg, dispatched, ioprio_class);
|
||||
/*
|
||||
* If the request needs its target zone locked, do it.
|
||||
*/
|
||||
|
@ -569,8 +568,6 @@ static void dd_exit_sched(struct elevator_queue *e)
|
|||
struct deadline_data *dd = e->elevator_data;
|
||||
enum dd_prio prio;
|
||||
|
||||
dd_deactivate_policy(dd->queue);
|
||||
|
||||
for (prio = 0; prio <= DD_PRIO_MAX; prio++) {
|
||||
struct dd_per_prio *per_prio = &dd->per_prio[prio];
|
||||
|
||||
|
@ -584,7 +581,7 @@ static void dd_exit_sched(struct elevator_queue *e)
|
|||
}
|
||||
|
||||
/*
|
||||
* Initialize elevator private data (deadline_data) and associate with blkcg.
|
||||
* initialize elevator private data (deadline_data).
|
||||
*/
|
||||
static int dd_init_sched(struct request_queue *q, struct elevator_type *e)
|
||||
{
|
||||
|
@ -593,12 +590,6 @@ static int dd_init_sched(struct request_queue *q, struct elevator_type *e)
|
|||
enum dd_prio prio;
|
||||
int ret = -ENOMEM;
|
||||
|
||||
/*
|
||||
* Initialization would be very tricky if the queue is not frozen,
|
||||
* hence the warning statement below.
|
||||
*/
|
||||
WARN_ON_ONCE(!percpu_ref_is_zero(&q->q_usage_counter));
|
||||
|
||||
eq = elevator_alloc(q, e);
|
||||
if (!eq)
|
||||
return ret;
|
||||
|
@ -614,8 +605,6 @@ static int dd_init_sched(struct request_queue *q, struct elevator_type *e)
|
|||
if (!dd->stats)
|
||||
goto free_dd;
|
||||
|
||||
dd->queue = q;
|
||||
|
||||
for (prio = 0; prio <= DD_PRIO_MAX; prio++) {
|
||||
struct dd_per_prio *per_prio = &dd->per_prio[prio];
|
||||
|
||||
|
@ -635,17 +624,9 @@ static int dd_init_sched(struct request_queue *q, struct elevator_type *e)
|
|||
spin_lock_init(&dd->lock);
|
||||
spin_lock_init(&dd->zone_lock);
|
||||
|
||||
ret = dd_activate_policy(q);
|
||||
if (ret)
|
||||
goto free_stats;
|
||||
|
||||
ret = 0;
|
||||
q->elevator = eq;
|
||||
return 0;
|
||||
|
||||
free_stats:
|
||||
free_percpu(dd->stats);
|
||||
|
||||
free_dd:
|
||||
kfree(dd);
|
||||
|
||||
|
@ -718,7 +699,6 @@ static void dd_insert_request(struct blk_mq_hw_ctx *hctx, struct request *rq,
|
|||
u8 ioprio_class = IOPRIO_PRIO_CLASS(ioprio);
|
||||
struct dd_per_prio *per_prio;
|
||||
enum dd_prio prio;
|
||||
struct dd_blkcg *blkcg;
|
||||
LIST_HEAD(free);
|
||||
|
||||
lockdep_assert_held(&dd->lock);
|
||||
|
@ -729,18 +709,8 @@ static void dd_insert_request(struct blk_mq_hw_ctx *hctx, struct request *rq,
|
|||
*/
|
||||
blk_req_zone_write_unlock(rq);
|
||||
|
||||
/*
|
||||
* If a block cgroup has been associated with the submitter and if an
|
||||
* I/O priority has been set in the associated block cgroup, use the
|
||||
* lowest of the cgroup priority and the request priority for the
|
||||
* request. If no priority has been set in the request, use the cgroup
|
||||
* priority.
|
||||
*/
|
||||
prio = ioprio_class_to_prio[ioprio_class];
|
||||
dd_count(dd, inserted, prio);
|
||||
blkcg = dd_blkcg_from_bio(rq->bio);
|
||||
ddcg_count(blkcg, inserted, ioprio_class);
|
||||
rq->elv.priv[0] = blkcg;
|
||||
|
||||
if (blk_mq_sched_try_insert_merge(q, rq, &free)) {
|
||||
blk_mq_free_requests(&free);
|
||||
|
@ -789,10 +759,12 @@ static void dd_insert_requests(struct blk_mq_hw_ctx *hctx,
|
|||
spin_unlock(&dd->lock);
|
||||
}
|
||||
|
||||
/* Callback from inside blk_mq_rq_ctx_init(). */
|
||||
/*
|
||||
* Nothing to do here. This is defined only to ensure that .finish_request
|
||||
* method is called upon request completion.
|
||||
*/
|
||||
static void dd_prepare_request(struct request *rq)
|
||||
{
|
||||
rq->elv.priv[0] = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -815,13 +787,11 @@ static void dd_finish_request(struct request *rq)
|
|||
{
|
||||
struct request_queue *q = rq->q;
|
||||
struct deadline_data *dd = q->elevator->elevator_data;
|
||||
struct dd_blkcg *blkcg = rq->elv.priv[0];
|
||||
const u8 ioprio_class = dd_rq_ioclass(rq);
|
||||
const enum dd_prio prio = ioprio_class_to_prio[ioprio_class];
|
||||
struct dd_per_prio *per_prio = &dd->per_prio[prio];
|
||||
|
||||
dd_count(dd, completed, prio);
|
||||
ddcg_count(blkcg, completed, ioprio_class);
|
||||
|
||||
if (blk_queue_is_zoned(q)) {
|
||||
unsigned long flags;
|
||||
|
@ -1144,26 +1114,11 @@ MODULE_ALIAS("mq-deadline-iosched");
|
|||
|
||||
static int __init deadline_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = elv_register(&mq_deadline);
|
||||
if (ret)
|
||||
goto out;
|
||||
ret = dd_blkcg_init();
|
||||
if (ret)
|
||||
goto unreg;
|
||||
|
||||
out:
|
||||
return ret;
|
||||
|
||||
unreg:
|
||||
elv_unregister(&mq_deadline);
|
||||
goto out;
|
||||
return elv_register(&mq_deadline);
|
||||
}
|
||||
|
||||
static void __exit deadline_exit(void)
|
||||
{
|
||||
dd_blkcg_exit();
|
||||
elv_unregister(&mq_deadline);
|
||||
}
|
||||
|
|
@ -1768,7 +1768,7 @@ config CRYPTO_DRBG_HMAC
|
|||
bool
|
||||
default y
|
||||
select CRYPTO_HMAC
|
||||
select CRYPTO_SHA256
|
||||
select CRYPTO_SHA512
|
||||
|
||||
config CRYPTO_DRBG_HASH
|
||||
bool "Enable Hash DRBG"
|
||||
|
|
|
@ -3021,6 +3021,9 @@ static int acpi_nfit_register_region(struct acpi_nfit_desc *acpi_desc,
|
|||
struct acpi_nfit_memory_map *memdev = nfit_memdev->memdev;
|
||||
struct nd_mapping_desc *mapping;
|
||||
|
||||
/* range index 0 == unmapped in SPA or invalid-SPA */
|
||||
if (memdev->range_index == 0 || spa->range_index == 0)
|
||||
continue;
|
||||
if (memdev->range_index != spa->range_index)
|
||||
continue;
|
||||
if (count >= ND_MAX_MAPPINGS) {
|
||||
|
|
|
@ -292,6 +292,12 @@ void __init init_prmt(void)
|
|||
int mc = acpi_table_parse_entries(ACPI_SIG_PRMT, sizeof(struct acpi_table_prmt) +
|
||||
sizeof (struct acpi_table_prmt_header),
|
||||
0, acpi_parse_prmt, 0);
|
||||
/*
|
||||
* Return immediately if PRMT table is not present or no PRM module found.
|
||||
*/
|
||||
if (mc <= 0)
|
||||
return;
|
||||
|
||||
pr_info("PRM: found %u modules\n", mc);
|
||||
|
||||
status = acpi_install_address_space_handler(ACPI_ROOT_OBJECT,
|
||||
|
|
|
@ -452,7 +452,7 @@ int acpi_s2idle_prepare_late(void)
|
|||
if (lps0_dsm_func_mask_microsoft > 0) {
|
||||
acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_OFF,
|
||||
lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
|
||||
acpi_sleep_run_lps0_dsm(ACPI_LPS0_MS_EXIT,
|
||||
acpi_sleep_run_lps0_dsm(ACPI_LPS0_MS_ENTRY,
|
||||
lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
|
||||
acpi_sleep_run_lps0_dsm(ACPI_LPS0_ENTRY,
|
||||
lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
|
||||
|
@ -479,7 +479,7 @@ void acpi_s2idle_restore_early(void)
|
|||
if (lps0_dsm_func_mask_microsoft > 0) {
|
||||
acpi_sleep_run_lps0_dsm(ACPI_LPS0_EXIT,
|
||||
lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
|
||||
acpi_sleep_run_lps0_dsm(ACPI_LPS0_MS_ENTRY,
|
||||
acpi_sleep_run_lps0_dsm(ACPI_LPS0_MS_EXIT,
|
||||
lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
|
||||
acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_ON,
|
||||
lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
|
||||
|
|
|
@ -2837,6 +2837,7 @@ void device_initialize(struct device *dev)
|
|||
device_pm_init(dev);
|
||||
set_dev_node(dev, -1);
|
||||
#ifdef CONFIG_GENERIC_MSI_IRQ
|
||||
raw_spin_lock_init(&dev->msi_lock);
|
||||
INIT_LIST_HEAD(&dev->msi_list);
|
||||
#endif
|
||||
INIT_LIST_HEAD(&dev->links.consumers);
|
||||
|
|
|
@ -818,6 +818,10 @@ static bool nbd_clear_req(struct request *req, void *data, bool reserved)
|
|||
{
|
||||
struct nbd_cmd *cmd = blk_mq_rq_to_pdu(req);
|
||||
|
||||
/* don't abort one completed request */
|
||||
if (blk_mq_request_completed(req))
|
||||
return true;
|
||||
|
||||
mutex_lock(&cmd->lock);
|
||||
cmd->status = BLK_STS_IOERR;
|
||||
mutex_unlock(&cmd->lock);
|
||||
|
@ -2004,15 +2008,19 @@ static void nbd_disconnect_and_put(struct nbd_device *nbd)
|
|||
{
|
||||
mutex_lock(&nbd->config_lock);
|
||||
nbd_disconnect(nbd);
|
||||
nbd_clear_sock(nbd);
|
||||
mutex_unlock(&nbd->config_lock);
|
||||
sock_shutdown(nbd);
|
||||
/*
|
||||
* Make sure recv thread has finished, so it does not drop the last
|
||||
* config ref and try to destroy the workqueue from inside the work
|
||||
* queue.
|
||||
* queue. And this also ensure that we can safely call nbd_clear_que()
|
||||
* to cancel the inflight I/Os.
|
||||
*/
|
||||
if (nbd->recv_workq)
|
||||
flush_workqueue(nbd->recv_workq);
|
||||
nbd_clear_que(nbd);
|
||||
nbd->task_setup = NULL;
|
||||
mutex_unlock(&nbd->config_lock);
|
||||
|
||||
if (test_and_clear_bit(NBD_RT_HAS_CONFIG_REF,
|
||||
&nbd->config->runtime_flags))
|
||||
nbd_config_put(nbd);
|
||||
|
|
|
@ -692,6 +692,28 @@ static const struct blk_mq_ops virtio_mq_ops = {
|
|||
static unsigned int virtblk_queue_depth;
|
||||
module_param_named(queue_depth, virtblk_queue_depth, uint, 0444);
|
||||
|
||||
static int virtblk_validate(struct virtio_device *vdev)
|
||||
{
|
||||
u32 blk_size;
|
||||
|
||||
if (!vdev->config->get) {
|
||||
dev_err(&vdev->dev, "%s failure: config access disabled\n",
|
||||
__func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!virtio_has_feature(vdev, VIRTIO_BLK_F_BLK_SIZE))
|
||||
return 0;
|
||||
|
||||
blk_size = virtio_cread32(vdev,
|
||||
offsetof(struct virtio_blk_config, blk_size));
|
||||
|
||||
if (blk_size < SECTOR_SIZE || blk_size > PAGE_SIZE)
|
||||
__virtio_clear_bit(vdev, VIRTIO_BLK_F_BLK_SIZE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int virtblk_probe(struct virtio_device *vdev)
|
||||
{
|
||||
struct virtio_blk *vblk;
|
||||
|
@ -703,12 +725,6 @@ static int virtblk_probe(struct virtio_device *vdev)
|
|||
u8 physical_block_exp, alignment_offset;
|
||||
unsigned int queue_depth;
|
||||
|
||||
if (!vdev->config->get) {
|
||||
dev_err(&vdev->dev, "%s failure: config access disabled\n",
|
||||
__func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
err = ida_simple_get(&vd_index_ida, 0, minor_to_index(1 << MINORBITS),
|
||||
GFP_KERNEL);
|
||||
if (err < 0)
|
||||
|
@ -823,6 +839,14 @@ static int virtblk_probe(struct virtio_device *vdev)
|
|||
else
|
||||
blk_size = queue_logical_block_size(q);
|
||||
|
||||
if (unlikely(blk_size < SECTOR_SIZE || blk_size > PAGE_SIZE)) {
|
||||
dev_err(&vdev->dev,
|
||||
"block size is changed unexpectedly, now is %u\n",
|
||||
blk_size);
|
||||
err = -EINVAL;
|
||||
goto err_cleanup_disk;
|
||||
}
|
||||
|
||||
/* Use topology information if available */
|
||||
err = virtio_cread_feature(vdev, VIRTIO_BLK_F_TOPOLOGY,
|
||||
struct virtio_blk_config, physical_block_exp,
|
||||
|
@ -881,6 +905,8 @@ static int virtblk_probe(struct virtio_device *vdev)
|
|||
device_add_disk(&vdev->dev, vblk->disk, virtblk_attr_groups);
|
||||
return 0;
|
||||
|
||||
err_cleanup_disk:
|
||||
blk_cleanup_disk(vblk->disk);
|
||||
out_free_tags:
|
||||
blk_mq_free_tag_set(&vblk->tag_set);
|
||||
out_free_vq:
|
||||
|
@ -983,6 +1009,7 @@ static struct virtio_driver virtio_blk = {
|
|||
.driver.name = KBUILD_MODNAME,
|
||||
.driver.owner = THIS_MODULE,
|
||||
.id_table = id_table,
|
||||
.validate = virtblk_validate,
|
||||
.probe = virtblk_probe,
|
||||
.remove = virtblk_remove,
|
||||
.config_changed = virtblk_config_changed,
|
||||
|
|
|
@ -3097,8 +3097,10 @@ static int sysc_probe(struct platform_device *pdev)
|
|||
return error;
|
||||
|
||||
error = sysc_check_active_timer(ddata);
|
||||
if (error == -EBUSY)
|
||||
if (error == -ENXIO)
|
||||
ddata->reserved = true;
|
||||
else if (error)
|
||||
return error;
|
||||
|
||||
error = sysc_get_clocks(ddata);
|
||||
if (error)
|
||||
|
|
|
@ -974,6 +974,6 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
|
|||
hws[IMX6QDL_CLK_PLL3_USB_OTG]->clk);
|
||||
}
|
||||
|
||||
imx_register_uart_clocks(1);
|
||||
imx_register_uart_clocks(2);
|
||||
}
|
||||
CLK_OF_DECLARE(imx6q, "fsl,imx6q-ccm", imx6q_clocks_init);
|
||||
|
|
|
@ -357,27 +357,43 @@ static int gdsc_init(struct gdsc *sc)
|
|||
if (on < 0)
|
||||
return on;
|
||||
|
||||
/*
|
||||
* Votable GDSCs can be ON due to Vote from other masters.
|
||||
* If a Votable GDSC is ON, make sure we have a Vote.
|
||||
*/
|
||||
if ((sc->flags & VOTABLE) && on)
|
||||
if (on) {
|
||||
/* The regulator must be on, sync the kernel state */
|
||||
if (sc->rsupply) {
|
||||
ret = regulator_enable(sc->rsupply);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Votable GDSCs can be ON due to Vote from other masters.
|
||||
* If a Votable GDSC is ON, make sure we have a Vote.
|
||||
*/
|
||||
if (sc->flags & VOTABLE) {
|
||||
ret = regmap_update_bits(sc->regmap, sc->gdscr,
|
||||
SW_COLLAPSE_MASK, val);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Turn on HW trigger mode if supported */
|
||||
if (sc->flags & HW_CTRL) {
|
||||
ret = gdsc_hwctrl(sc, true);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Make sure the retain bit is set if the GDSC is already on,
|
||||
* otherwise we end up turning off the GDSC and destroying all
|
||||
* the register contents that we thought we were saving.
|
||||
*/
|
||||
if (sc->flags & RETAIN_FF_ENABLE)
|
||||
gdsc_retain_ff_on(sc);
|
||||
} else if (sc->flags & ALWAYS_ON) {
|
||||
/* If ALWAYS_ON GDSCs are not ON, turn them ON */
|
||||
gdsc_enable(&sc->pd);
|
||||
|
||||
/*
|
||||
* Make sure the retain bit is set if the GDSC is already on, otherwise
|
||||
* we end up turning off the GDSC and destroying all the register
|
||||
* contents that we thought we were saving.
|
||||
*/
|
||||
if ((sc->flags & RETAIN_FF_ENABLE) && on)
|
||||
gdsc_retain_ff_on(sc);
|
||||
|
||||
/* If ALWAYS_ON GDSCs are not ON, turn them ON */
|
||||
if (sc->flags & ALWAYS_ON) {
|
||||
if (!on)
|
||||
gdsc_enable(&sc->pd);
|
||||
on = true;
|
||||
sc->pd.flags |= GENPD_FLAG_ALWAYS_ON;
|
||||
}
|
||||
|
||||
if (on || (sc->pwrsts & PWRSTS_RET))
|
||||
|
@ -385,6 +401,8 @@ static int gdsc_init(struct gdsc *sc)
|
|||
else
|
||||
gdsc_clear_mem_on(sc);
|
||||
|
||||
if (sc->flags & ALWAYS_ON)
|
||||
sc->pd.flags |= GENPD_FLAG_ALWAYS_ON;
|
||||
if (!sc->pd.power_off)
|
||||
sc->pd.power_off = gdsc_disable;
|
||||
if (!sc->pd.power_on)
|
||||
|
|
|
@ -104,7 +104,11 @@ struct armada_37xx_dvfs {
|
|||
};
|
||||
|
||||
static struct armada_37xx_dvfs armada_37xx_dvfs[] = {
|
||||
{.cpu_freq_max = 1200*1000*1000, .divider = {1, 2, 4, 6} },
|
||||
/*
|
||||
* The cpufreq scaling for 1.2 GHz variant of the SOC is currently
|
||||
* unstable because we do not know how to configure it properly.
|
||||
*/
|
||||
/* {.cpu_freq_max = 1200*1000*1000, .divider = {1, 2, 4, 6} }, */
|
||||
{.cpu_freq_max = 1000*1000*1000, .divider = {1, 2, 4, 5} },
|
||||
{.cpu_freq_max = 800*1000*1000, .divider = {1, 2, 3, 4} },
|
||||
{.cpu_freq_max = 600*1000*1000, .divider = {2, 4, 5, 6} },
|
||||
|
|
|
@ -139,7 +139,9 @@ static const struct of_device_id blocklist[] __initconst = {
|
|||
{ .compatible = "qcom,qcs404", },
|
||||
{ .compatible = "qcom,sc7180", },
|
||||
{ .compatible = "qcom,sc7280", },
|
||||
{ .compatible = "qcom,sc8180x", },
|
||||
{ .compatible = "qcom,sdm845", },
|
||||
{ .compatible = "qcom,sm8150", },
|
||||
|
||||
{ .compatible = "st,stih407", },
|
||||
{ .compatible = "st,stih410", },
|
||||
|
|
|
@ -134,7 +134,7 @@ static int scmi_cpufreq_init(struct cpufreq_policy *policy)
|
|||
}
|
||||
|
||||
if (!zalloc_cpumask_var(&opp_shared_cpus, GFP_KERNEL))
|
||||
ret = -ENOMEM;
|
||||
return -ENOMEM;
|
||||
|
||||
/* Obtain CPUs that share SCMI performance controls */
|
||||
ret = scmi_get_sharing_cpus(cpu_dev, policy->cpus);
|
||||
|
|
|
@ -313,7 +313,7 @@ long dax_direct_access(struct dax_device *dax_dev, pgoff_t pgoff, long nr_pages,
|
|||
return -ENXIO;
|
||||
|
||||
if (nr_pages < 0)
|
||||
return nr_pages;
|
||||
return -EINVAL;
|
||||
|
||||
avail = dax_dev->ops->direct_access(dax_dev, pgoff, nr_pages,
|
||||
kaddr, pfn);
|
||||
|
|
|
@ -35,15 +35,48 @@ efi_status_t check_platform_features(void)
|
|||
}
|
||||
|
||||
/*
|
||||
* Although relocatable kernels can fix up the misalignment with respect to
|
||||
* MIN_KIMG_ALIGN, the resulting virtual text addresses are subtly out of
|
||||
* sync with those recorded in the vmlinux when kaslr is disabled but the
|
||||
* image required relocation anyway. Therefore retain 2M alignment unless
|
||||
* KASLR is in use.
|
||||
* Distro versions of GRUB may ignore the BSS allocation entirely (i.e., fail
|
||||
* to provide space, and fail to zero it). Check for this condition by double
|
||||
* checking that the first and the last byte of the image are covered by the
|
||||
* same EFI memory map entry.
|
||||
*/
|
||||
static u64 min_kimg_align(void)
|
||||
static bool check_image_region(u64 base, u64 size)
|
||||
{
|
||||
return efi_nokaslr ? MIN_KIMG_ALIGN : EFI_KIMG_ALIGN;
|
||||
unsigned long map_size, desc_size, buff_size;
|
||||
efi_memory_desc_t *memory_map;
|
||||
struct efi_boot_memmap map;
|
||||
efi_status_t status;
|
||||
bool ret = false;
|
||||
int map_offset;
|
||||
|
||||
map.map = &memory_map;
|
||||
map.map_size = &map_size;
|
||||
map.desc_size = &desc_size;
|
||||
map.desc_ver = NULL;
|
||||
map.key_ptr = NULL;
|
||||
map.buff_size = &buff_size;
|
||||
|
||||
status = efi_get_memory_map(&map);
|
||||
if (status != EFI_SUCCESS)
|
||||
return false;
|
||||
|
||||
for (map_offset = 0; map_offset < map_size; map_offset += desc_size) {
|
||||
efi_memory_desc_t *md = (void *)memory_map + map_offset;
|
||||
u64 end = md->phys_addr + md->num_pages * EFI_PAGE_SIZE;
|
||||
|
||||
/*
|
||||
* Find the region that covers base, and return whether
|
||||
* it covers base+size bytes.
|
||||
*/
|
||||
if (base >= md->phys_addr && base < end) {
|
||||
ret = (base + size) <= end;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
efi_bs_call(free_pool, memory_map);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
efi_status_t handle_kernel_image(unsigned long *image_addr,
|
||||
|
@ -56,6 +89,16 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
|
|||
unsigned long kernel_size, kernel_memsize = 0;
|
||||
u32 phys_seed = 0;
|
||||
|
||||
/*
|
||||
* Although relocatable kernels can fix up the misalignment with
|
||||
* respect to MIN_KIMG_ALIGN, the resulting virtual text addresses are
|
||||
* subtly out of sync with those recorded in the vmlinux when kaslr is
|
||||
* disabled but the image required relocation anyway. Therefore retain
|
||||
* 2M alignment if KASLR was explicitly disabled, even if it was not
|
||||
* going to be activated to begin with.
|
||||
*/
|
||||
u64 min_kimg_align = efi_nokaslr ? MIN_KIMG_ALIGN : EFI_KIMG_ALIGN;
|
||||
|
||||
if (IS_ENABLED(CONFIG_RANDOMIZE_BASE)) {
|
||||
if (!efi_nokaslr) {
|
||||
status = efi_get_random_bytes(sizeof(phys_seed),
|
||||
|
@ -76,6 +119,10 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
|
|||
if (image->image_base != _text)
|
||||
efi_err("FIRMWARE BUG: efi_loaded_image_t::image_base has bogus value\n");
|
||||
|
||||
if (!IS_ALIGNED((u64)_text, EFI_KIMG_ALIGN))
|
||||
efi_err("FIRMWARE BUG: kernel image not aligned on %ldk boundary\n",
|
||||
EFI_KIMG_ALIGN >> 10);
|
||||
|
||||
kernel_size = _edata - _text;
|
||||
kernel_memsize = kernel_size + (_end - _edata);
|
||||
*reserve_size = kernel_memsize;
|
||||
|
@ -85,14 +132,18 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
|
|||
* If KASLR is enabled, and we have some randomness available,
|
||||
* locate the kernel at a randomized offset in physical memory.
|
||||
*/
|
||||
status = efi_random_alloc(*reserve_size, min_kimg_align(),
|
||||
status = efi_random_alloc(*reserve_size, min_kimg_align,
|
||||
reserve_addr, phys_seed);
|
||||
if (status != EFI_SUCCESS)
|
||||
efi_warn("efi_random_alloc() failed: 0x%lx\n", status);
|
||||
} else {
|
||||
status = EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
if (status != EFI_SUCCESS) {
|
||||
if (IS_ALIGNED((u64)_text, min_kimg_align())) {
|
||||
if (!check_image_region((u64)_text, kernel_memsize)) {
|
||||
efi_err("FIRMWARE BUG: Image BSS overlaps adjacent EFI memory region\n");
|
||||
} else if (IS_ALIGNED((u64)_text, min_kimg_align)) {
|
||||
/*
|
||||
* Just execute from wherever we were loaded by the
|
||||
* UEFI PE/COFF loader if the alignment is suitable.
|
||||
|
@ -103,7 +154,7 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
|
|||
}
|
||||
|
||||
status = efi_allocate_pages_aligned(*reserve_size, reserve_addr,
|
||||
ULONG_MAX, min_kimg_align());
|
||||
ULONG_MAX, min_kimg_align);
|
||||
|
||||
if (status != EFI_SUCCESS) {
|
||||
efi_err("Failed to relocate kernel\n");
|
||||
|
|
|
@ -30,6 +30,8 @@ static unsigned long get_entry_num_slots(efi_memory_desc_t *md,
|
|||
|
||||
region_end = min(md->phys_addr + md->num_pages * EFI_PAGE_SIZE - 1,
|
||||
(u64)ULONG_MAX);
|
||||
if (region_end < size)
|
||||
return 0;
|
||||
|
||||
first_slot = round_up(md->phys_addr, align);
|
||||
last_slot = round_down(region_end - size + 1, align);
|
||||
|
|
|
@ -468,6 +468,46 @@ bool amdgpu_atomfirmware_dynamic_boot_config_supported(struct amdgpu_device *ade
|
|||
return (fw_cap & ATOM_FIRMWARE_CAP_DYNAMIC_BOOT_CFG_ENABLE) ? true : false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper function to query RAS EEPROM address
|
||||
*
|
||||
* @adev: amdgpu_device pointer
|
||||
*
|
||||
* Return true if vbios supports ras rom address reporting
|
||||
*/
|
||||
bool amdgpu_atomfirmware_ras_rom_addr(struct amdgpu_device *adev, uint8_t* i2c_address)
|
||||
{
|
||||
struct amdgpu_mode_info *mode_info = &adev->mode_info;
|
||||
int index;
|
||||
u16 data_offset, size;
|
||||
union firmware_info *firmware_info;
|
||||
u8 frev, crev;
|
||||
|
||||
if (i2c_address == NULL)
|
||||
return false;
|
||||
|
||||
*i2c_address = 0;
|
||||
|
||||
index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
|
||||
firmwareinfo);
|
||||
|
||||
if (amdgpu_atom_parse_data_header(adev->mode_info.atom_context,
|
||||
index, &size, &frev, &crev, &data_offset)) {
|
||||
/* support firmware_info 3.4 + */
|
||||
if ((frev == 3 && crev >=4) || (frev > 3)) {
|
||||
firmware_info = (union firmware_info *)
|
||||
(mode_info->atom_context->bios + data_offset);
|
||||
*i2c_address = firmware_info->v34.ras_rom_i2c_slave_addr;
|
||||
}
|
||||
}
|
||||
|
||||
if (*i2c_address != 0)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
union smu_info {
|
||||
struct atom_smu_info_v3_1 v31;
|
||||
};
|
||||
|
|
|
@ -36,6 +36,7 @@ int amdgpu_atomfirmware_get_clock_info(struct amdgpu_device *adev);
|
|||
int amdgpu_atomfirmware_get_gfx_info(struct amdgpu_device *adev);
|
||||
bool amdgpu_atomfirmware_mem_ecc_supported(struct amdgpu_device *adev);
|
||||
bool amdgpu_atomfirmware_sram_ecc_supported(struct amdgpu_device *adev);
|
||||
bool amdgpu_atomfirmware_ras_rom_addr(struct amdgpu_device *adev, uint8_t* i2c_address);
|
||||
bool amdgpu_atomfirmware_mem_training_supported(struct amdgpu_device *adev);
|
||||
bool amdgpu_atomfirmware_dynamic_boot_config_supported(struct amdgpu_device *adev);
|
||||
int amdgpu_atomfirmware_get_fw_reserved_fb_size(struct amdgpu_device *adev);
|
||||
|
|
|
@ -299,6 +299,9 @@ int amdgpu_discovery_reg_base_init(struct amdgpu_device *adev)
|
|||
ip->major, ip->minor,
|
||||
ip->revision);
|
||||
|
||||
if (le16_to_cpu(ip->hw_id) == VCN_HWID)
|
||||
adev->vcn.num_vcn_inst++;
|
||||
|
||||
for (k = 0; k < num_base_address; k++) {
|
||||
/*
|
||||
* convert the endianness of base addresses in place,
|
||||
|
@ -385,7 +388,7 @@ void amdgpu_discovery_harvest_ip(struct amdgpu_device *adev)
|
|||
{
|
||||
struct binary_header *bhdr;
|
||||
struct harvest_table *harvest_info;
|
||||
int i;
|
||||
int i, vcn_harvest_count = 0;
|
||||
|
||||
bhdr = (struct binary_header *)adev->mman.discovery_bin;
|
||||
harvest_info = (struct harvest_table *)(adev->mman.discovery_bin +
|
||||
|
@ -397,8 +400,7 @@ void amdgpu_discovery_harvest_ip(struct amdgpu_device *adev)
|
|||
|
||||
switch (le32_to_cpu(harvest_info->list[i].hw_id)) {
|
||||
case VCN_HWID:
|
||||
adev->harvest_ip_mask |= AMD_HARVEST_IP_VCN_MASK;
|
||||
adev->harvest_ip_mask |= AMD_HARVEST_IP_JPEG_MASK;
|
||||
vcn_harvest_count++;
|
||||
break;
|
||||
case DMU_HWID:
|
||||
adev->harvest_ip_mask |= AMD_HARVEST_IP_DMU_MASK;
|
||||
|
@ -407,6 +409,10 @@ void amdgpu_discovery_harvest_ip(struct amdgpu_device *adev)
|
|||
break;
|
||||
}
|
||||
}
|
||||
if (vcn_harvest_count == adev->vcn.num_vcn_inst) {
|
||||
adev->harvest_ip_mask |= AMD_HARVEST_IP_VCN_MASK;
|
||||
adev->harvest_ip_mask |= AMD_HARVEST_IP_JPEG_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
int amdgpu_discovery_get_gfx_info(struct amdgpu_device *adev)
|
||||
|
|
|
@ -1571,6 +1571,8 @@ static int amdgpu_pmops_runtime_suspend(struct device *dev)
|
|||
pci_ignore_hotplug(pdev);
|
||||
pci_set_power_state(pdev, PCI_D3cold);
|
||||
drm_dev->switch_power_state = DRM_SWITCH_POWER_DYNAMIC_OFF;
|
||||
} else if (amdgpu_device_supports_boco(drm_dev)) {
|
||||
/* nothing to do */
|
||||
} else if (amdgpu_device_supports_baco(drm_dev)) {
|
||||
amdgpu_device_baco_enter(drm_dev);
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "amdgpu_ras.h"
|
||||
#include <linux/bits.h>
|
||||
#include "atom.h"
|
||||
#include "amdgpu_atomfirmware.h"
|
||||
|
||||
#define EEPROM_I2C_TARGET_ADDR_VEGA20 0xA0
|
||||
#define EEPROM_I2C_TARGET_ADDR_ARCTURUS 0xA8
|
||||
|
@ -96,6 +97,9 @@ static bool __get_eeprom_i2c_addr(struct amdgpu_device *adev,
|
|||
if (!i2c_addr)
|
||||
return false;
|
||||
|
||||
if (amdgpu_atomfirmware_ras_rom_addr(adev, (uint8_t*)i2c_addr))
|
||||
return true;
|
||||
|
||||
switch (adev->asic_type) {
|
||||
case CHIP_VEGA20:
|
||||
*i2c_addr = EEPROM_I2C_TARGET_ADDR_VEGA20;
|
||||
|
|
|
@ -3026,6 +3026,14 @@ svm_range_get_attr(struct kfd_process *p, uint64_t start, uint64_t size,
|
|||
pr_debug("svms 0x%p [0x%llx 0x%llx] nattr 0x%x\n", &p->svms, start,
|
||||
start + size - 1, nattr);
|
||||
|
||||
/* Flush pending deferred work to avoid racing with deferred actions from
|
||||
* previous memory map changes (e.g. munmap). Concurrent memory map changes
|
||||
* can still race with get_attr because we don't hold the mmap lock. But that
|
||||
* would be a race condition in the application anyway, and undefined
|
||||
* behaviour is acceptable in that case.
|
||||
*/
|
||||
flush_work(&p->svms.deferred_list_work);
|
||||
|
||||
mmap_read_lock(mm);
|
||||
if (!svm_range_is_valid(mm, start, size)) {
|
||||
pr_debug("invalid range\n");
|
||||
|
|
|
@ -9605,7 +9605,12 @@ static int dm_update_crtc_state(struct amdgpu_display_manager *dm,
|
|||
} else if (amdgpu_freesync_vid_mode && aconnector &&
|
||||
is_freesync_video_mode(&new_crtc_state->mode,
|
||||
aconnector)) {
|
||||
set_freesync_fixed_config(dm_new_crtc_state);
|
||||
struct drm_display_mode *high_mode;
|
||||
|
||||
high_mode = get_highest_refresh_rate_mode(aconnector, false);
|
||||
if (!drm_mode_equal(&new_crtc_state->mode, high_mode)) {
|
||||
set_freesync_fixed_config(dm_new_crtc_state);
|
||||
}
|
||||
}
|
||||
|
||||
ret = dm_atomic_get_state(state, &dm_state);
|
||||
|
|
|
@ -584,7 +584,7 @@ static void amdgpu_dm_irq_schedule_work(struct amdgpu_device *adev,
|
|||
handler_data = container_of(handler_list->next, struct amdgpu_dm_irq_handler_data, list);
|
||||
|
||||
/*allocate a new amdgpu_dm_irq_handler_data*/
|
||||
handler_data_add = kzalloc(sizeof(*handler_data), GFP_KERNEL);
|
||||
handler_data_add = kzalloc(sizeof(*handler_data), GFP_ATOMIC);
|
||||
if (!handler_data_add) {
|
||||
DRM_ERROR("DM_IRQ: failed to allocate irq handler!\n");
|
||||
return;
|
||||
|
|
|
@ -1530,6 +1530,12 @@ void dc_z10_restore(struct dc *dc)
|
|||
if (dc->hwss.z10_restore)
|
||||
dc->hwss.z10_restore(dc);
|
||||
}
|
||||
|
||||
void dc_z10_save_init(struct dc *dc)
|
||||
{
|
||||
if (dc->hwss.z10_save_init)
|
||||
dc->hwss.z10_save_init(dc);
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
* Applies given context to HW and copy it into current context.
|
||||
|
|
|
@ -47,6 +47,9 @@ int dc_setup_system_context(struct dc *dc, struct dc_phy_addr_space_config *pa_c
|
|||
*/
|
||||
memcpy(&dc->vm_pa_config, pa_config, sizeof(struct dc_phy_addr_space_config));
|
||||
dc->vm_pa_config.valid = true;
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
dc_z10_save_init(dc);
|
||||
#endif
|
||||
}
|
||||
|
||||
return num_vmids;
|
||||
|
|
|
@ -1338,6 +1338,7 @@ void dc_hardware_release(struct dc *dc);
|
|||
bool dc_set_psr_allow_active(struct dc *dc, bool enable);
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
void dc_z10_restore(struct dc *dc);
|
||||
void dc_z10_save_init(struct dc *dc);
|
||||
#endif
|
||||
|
||||
bool dc_enable_dmub_notifications(struct dc *dc);
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче