mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-01 10:45:49 +00:00
Merge remote-tracking branch 'torvalds/master' into perf/core
To pick up fixes. Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
commit
c635813fef
@ -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/
|
||||
@ -6945,7 +6955,7 @@ F: include/uapi/linux/mdio.h
|
||||
F: include/uapi/linux/mii.h
|
||||
|
||||
EXFAT FILE SYSTEM
|
||||
M: Namjae Jeon <namjae.jeon@samsung.com>
|
||||
M: Namjae Jeon <linkinjeon@kernel.org>
|
||||
M: Sungjong Seo <sj1557.seo@samsung.com>
|
||||
L: linux-fsdevel@vger.kernel.org
|
||||
S: Maintained
|
||||
@ -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
|
||||
@ -14430,6 +14440,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>
|
||||
@ -15803,7 +15820,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
|
||||
@ -20017,7 +20034,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 =
|
||||
NAME = Opossums on Parade
|
||||
|
||||
# *DOCUMENTATION*
|
||||
|
@ -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
|
||||
|
@ -160,10 +160,11 @@ extern unsigned long vectors_base;
|
||||
|
||||
/*
|
||||
* Physical start and end address of the kernel sections. These addresses are
|
||||
* 2MB-aligned to match the section mappings placed over the kernel.
|
||||
* 2MB-aligned to match the section mappings placed over the kernel. We use
|
||||
* u64 so that LPAE mappings beyond the 32bit limit will work out as well.
|
||||
*/
|
||||
extern u32 kernel_sec_start;
|
||||
extern u32 kernel_sec_end;
|
||||
extern u64 kernel_sec_start;
|
||||
extern u64 kernel_sec_end;
|
||||
|
||||
/*
|
||||
* Physical vs virtual RAM address space conversion. These are
|
||||
|
@ -49,7 +49,8 @@
|
||||
|
||||
/*
|
||||
* This needs to be assigned at runtime when the linker symbols are
|
||||
* resolved.
|
||||
* resolved. These are unsigned 64bit really, but in this assembly code
|
||||
* We store them as 32bit.
|
||||
*/
|
||||
.pushsection .data
|
||||
.align 2
|
||||
@ -57,7 +58,9 @@
|
||||
.globl kernel_sec_end
|
||||
kernel_sec_start:
|
||||
.long 0
|
||||
.long 0
|
||||
kernel_sec_end:
|
||||
.long 0
|
||||
.long 0
|
||||
.popsection
|
||||
|
||||
@ -250,7 +253,11 @@ __create_page_tables:
|
||||
add r0, r4, #KERNEL_OFFSET >> (SECTION_SHIFT - PMD_ORDER)
|
||||
ldr r6, =(_end - 1)
|
||||
adr_l r5, kernel_sec_start @ _pa(kernel_sec_start)
|
||||
str r8, [r5] @ Save physical start of kernel
|
||||
#ifdef CONFIG_CPU_ENDIAN_BE8
|
||||
str r8, [r5, #4] @ Save physical start of kernel (BE)
|
||||
#else
|
||||
str r8, [r5] @ Save physical start of kernel (LE)
|
||||
#endif
|
||||
orr r3, r8, r7 @ Add the MMU flags
|
||||
add r6, r4, r6, lsr #(SECTION_SHIFT - PMD_ORDER)
|
||||
1: str r3, [r0], #1 << PMD_ORDER
|
||||
@ -259,7 +266,11 @@ __create_page_tables:
|
||||
bls 1b
|
||||
eor r3, r3, r7 @ Remove the MMU flags
|
||||
adr_l r5, kernel_sec_end @ _pa(kernel_sec_end)
|
||||
str r3, [r5] @ Save physical end of kernel
|
||||
#ifdef CONFIG_CPU_ENDIAN_BE8
|
||||
str r3, [r5, #4] @ Save physical end of kernel (BE)
|
||||
#else
|
||||
str r3, [r5] @ Save physical end of kernel (LE)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_XIP_KERNEL
|
||||
/*
|
||||
|
@ -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
|
||||
|
@ -1608,6 +1608,13 @@ static void __init early_paging_init(const struct machine_desc *mdesc)
|
||||
if (offset == 0)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Offset the kernel section physical offsets so that the kernel
|
||||
* mapping will work out later on.
|
||||
*/
|
||||
kernel_sec_start += offset;
|
||||
kernel_sec_end += offset;
|
||||
|
||||
/*
|
||||
* Get the address of the remap function in the 1:1 identity
|
||||
* mapping setup by the early page table assembly code. We
|
||||
@ -1716,7 +1723,7 @@ void __init paging_init(const struct machine_desc *mdesc)
|
||||
{
|
||||
void *zero_page;
|
||||
|
||||
pr_debug("physical kernel sections: 0x%08x-0x%08x\n",
|
||||
pr_debug("physical kernel sections: 0x%08llx-0x%08llx\n",
|
||||
kernel_sec_start, kernel_sec_end);
|
||||
|
||||
prepare_page_table();
|
||||
|
@ -29,7 +29,7 @@ ENTRY(lpae_pgtables_remap_asm)
|
||||
ldr r6, =(_end - 1)
|
||||
add r7, r2, #0x1000
|
||||
add r6, r7, r6, lsr #SECTION_SHIFT - L2_ORDER
|
||||
add r7, r7, #PAGE_OFFSET >> (SECTION_SHIFT - L2_ORDER)
|
||||
add r7, r7, #KERNEL_OFFSET >> (SECTION_SHIFT - L2_ORDER)
|
||||
1: ldrd r4, r5, [r7]
|
||||
adds r4, r4, r0
|
||||
adc r5, r5, r1
|
||||
|
@ -156,6 +156,7 @@ config ARM64
|
||||
select HAVE_ARCH_KGDB
|
||||
select HAVE_ARCH_MMAP_RND_BITS
|
||||
select HAVE_ARCH_MMAP_RND_COMPAT_BITS if COMPAT
|
||||
select HAVE_ARCH_PFN_VALID
|
||||
select HAVE_ARCH_PREL32_RELOCATIONS
|
||||
select HAVE_ARCH_RANDOMIZE_KSTACK_OFFSET
|
||||
select HAVE_ARCH_SECCOMP_FILTER
|
||||
|
@ -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 @@ ramoops@1ff00000 {
|
||||
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 @@ CPU7: cpu@700 {
|
||||
&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_mem: memory@f5b01000 {
|
||||
};
|
||||
rmtfs_upper_guard: memory@f5d01000 {
|
||||
no-map;
|
||||
reg = <0 0xf5d01000 0 0x2000>;
|
||||
reg = <0 0xf5d01000 0 0x1000>;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -78,7 +78,7 @@ rmtfs_upper_guard: memory@f5d01000 {
|
||||
*/
|
||||
removed_region: memory@88f00000 {
|
||||
no-map;
|
||||
reg = <0 0x88f00000 0 0x200000>;
|
||||
reg = <0 0x88f00000 0 0x1c00000>;
|
||||
};
|
||||
|
||||
ramoops: ramoops@ac300000 {
|
||||
|
@ -700,7 +700,7 @@ swm: swm@c85 {
|
||||
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 @@ left_spkr: wsa8810-left{
|
||||
|
||||
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
|
||||
|
@ -41,6 +41,7 @@ void tag_clear_highpage(struct page *to);
|
||||
|
||||
typedef struct page *pgtable_t;
|
||||
|
||||
int pfn_valid(unsigned long pfn);
|
||||
int pfn_is_map_memory(unsigned long pfn);
|
||||
|
||||
#include <asm/memory.h>
|
||||
|
@ -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;
|
||||
|
@ -219,6 +219,43 @@ static void __init zone_sizes_init(unsigned long min, unsigned long max)
|
||||
free_area_init(max_zone_pfns);
|
||||
}
|
||||
|
||||
int pfn_valid(unsigned long pfn)
|
||||
{
|
||||
phys_addr_t addr = PFN_PHYS(pfn);
|
||||
struct mem_section *ms;
|
||||
|
||||
/*
|
||||
* Ensure the upper PAGE_SHIFT bits are clear in the
|
||||
* pfn. Else it might lead to false positives when
|
||||
* some of the upper bits are set, but the lower bits
|
||||
* match a valid pfn.
|
||||
*/
|
||||
if (PHYS_PFN(addr) != pfn)
|
||||
return 0;
|
||||
|
||||
if (pfn_to_section_nr(pfn) >= NR_MEM_SECTIONS)
|
||||
return 0;
|
||||
|
||||
ms = __pfn_to_section(pfn);
|
||||
if (!valid_section(ms))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* ZONE_DEVICE memory does not have the memblock entries.
|
||||
* memblock_is_map_memory() check for ZONE_DEVICE based
|
||||
* addresses will always fail. Even the normal hotplugged
|
||||
* memory will never have MEMBLOCK_NOMAP flag set in their
|
||||
* memblock entries. Skip memblock search for all non early
|
||||
* memory sections covering all of hotplug memory including
|
||||
* both normal and ZONE_DEVICE based.
|
||||
*/
|
||||
if (!early_section(ms))
|
||||
return pfn_section_valid(ms, pfn);
|
||||
|
||||
return memblock_is_memory(addr);
|
||||
}
|
||||
EXPORT_SYMBOL(pfn_valid);
|
||||
|
||||
int pfn_is_map_memory(unsigned long pfn)
|
||||
{
|
||||
phys_addr_t addr = PFN_PHYS(pfn);
|
||||
|
@ -8,19 +8,4 @@ extern void * memset(void *, int, size_t);
|
||||
#define __HAVE_ARCH_MEMCPY
|
||||
void * memcpy(void * dest,const void *src,size_t count);
|
||||
|
||||
#define __HAVE_ARCH_STRLEN
|
||||
extern size_t strlen(const char *s);
|
||||
|
||||
#define __HAVE_ARCH_STRCPY
|
||||
extern char *strcpy(char *dest, const char *src);
|
||||
|
||||
#define __HAVE_ARCH_STRNCPY
|
||||
extern char *strncpy(char *dest, const char *src, size_t count);
|
||||
|
||||
#define __HAVE_ARCH_STRCAT
|
||||
extern char *strcat(char *dest, const char *src);
|
||||
|
||||
#define __HAVE_ARCH_MEMSET
|
||||
extern void *memset(void *, int, size_t);
|
||||
|
||||
#endif
|
||||
|
@ -17,10 +17,6 @@
|
||||
|
||||
#include <linux/string.h>
|
||||
EXPORT_SYMBOL(memset);
|
||||
EXPORT_SYMBOL(strlen);
|
||||
EXPORT_SYMBOL(strcpy);
|
||||
EXPORT_SYMBOL(strncpy);
|
||||
EXPORT_SYMBOL(strcat);
|
||||
|
||||
#include <linux/atomic.h>
|
||||
EXPORT_SYMBOL(__xchg8);
|
||||
|
@ -3,7 +3,7 @@
|
||||
# Makefile for parisc-specific library files
|
||||
#
|
||||
|
||||
lib-y := lusercopy.o bitops.o checksum.o io.o memcpy.o \
|
||||
ucmpdi2.o delay.o string.o
|
||||
lib-y := lusercopy.o bitops.o checksum.o io.o memset.o memcpy.o \
|
||||
ucmpdi2.o delay.o
|
||||
|
||||
obj-y := iomap.o
|
||||
|
72
arch/parisc/lib/memset.c
Normal file
72
arch/parisc/lib/memset.c
Normal file
@ -0,0 +1,72 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
#include <linux/types.h>
|
||||
#include <asm/string.h>
|
||||
|
||||
#define OPSIZ (BITS_PER_LONG/8)
|
||||
typedef unsigned long op_t;
|
||||
|
||||
void *
|
||||
memset (void *dstpp, int sc, size_t len)
|
||||
{
|
||||
unsigned int c = sc;
|
||||
long int dstp = (long int) dstpp;
|
||||
|
||||
if (len >= 8)
|
||||
{
|
||||
size_t xlen;
|
||||
op_t cccc;
|
||||
|
||||
cccc = (unsigned char) c;
|
||||
cccc |= cccc << 8;
|
||||
cccc |= cccc << 16;
|
||||
if (OPSIZ > 4)
|
||||
/* Do the shift in two steps to avoid warning if long has 32 bits. */
|
||||
cccc |= (cccc << 16) << 16;
|
||||
|
||||
/* There are at least some bytes to set.
|
||||
No need to test for LEN == 0 in this alignment loop. */
|
||||
while (dstp % OPSIZ != 0)
|
||||
{
|
||||
((unsigned char *) dstp)[0] = c;
|
||||
dstp += 1;
|
||||
len -= 1;
|
||||
}
|
||||
|
||||
/* Write 8 `op_t' per iteration until less than 8 `op_t' remain. */
|
||||
xlen = len / (OPSIZ * 8);
|
||||
while (xlen > 0)
|
||||
{
|
||||
((op_t *) dstp)[0] = cccc;
|
||||
((op_t *) dstp)[1] = cccc;
|
||||
((op_t *) dstp)[2] = cccc;
|
||||
((op_t *) dstp)[3] = cccc;
|
||||
((op_t *) dstp)[4] = cccc;
|
||||
((op_t *) dstp)[5] = cccc;
|
||||
((op_t *) dstp)[6] = cccc;
|
||||
((op_t *) dstp)[7] = cccc;
|
||||
dstp += 8 * OPSIZ;
|
||||
xlen -= 1;
|
||||
}
|
||||
len %= OPSIZ * 8;
|
||||
|
||||
/* Write 1 `op_t' per iteration until less than OPSIZ bytes remain. */
|
||||
xlen = len / OPSIZ;
|
||||
while (xlen > 0)
|
||||
{
|
||||
((op_t *) dstp)[0] = cccc;
|
||||
dstp += OPSIZ;
|
||||
xlen -= 1;
|
||||
}
|
||||
len %= OPSIZ;
|
||||
}
|
||||
|
||||
/* Write the last few bytes. */
|
||||
while (len > 0)
|
||||
{
|
||||
((unsigned char *) dstp)[0] = c;
|
||||
dstp += 1;
|
||||
len -= 1;
|
||||
}
|
||||
|
||||
return dstpp;
|
||||
}
|
@ -1,136 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* PA-RISC assembly string functions
|
||||
*
|
||||
* Copyright (C) 2019 Helge Deller <deller@gmx.de>
|
||||
*/
|
||||
|
||||
#include <asm/assembly.h>
|
||||
#include <linux/linkage.h>
|
||||
|
||||
.section .text.hot
|
||||
.level PA_ASM_LEVEL
|
||||
|
||||
t0 = r20
|
||||
t1 = r21
|
||||
t2 = r22
|
||||
|
||||
ENTRY_CFI(strlen, frame=0,no_calls)
|
||||
or,COND(<>) arg0,r0,ret0
|
||||
b,l,n .Lstrlen_null_ptr,r0
|
||||
depwi 0,31,2,ret0
|
||||
cmpb,COND(<>) arg0,ret0,.Lstrlen_not_aligned
|
||||
ldw,ma 4(ret0),t0
|
||||
cmpib,tr 0,r0,.Lstrlen_loop
|
||||
uxor,nbz r0,t0,r0
|
||||
.Lstrlen_not_aligned:
|
||||
uaddcm arg0,ret0,t1
|
||||
shladd t1,3,r0,t1
|
||||
mtsar t1
|
||||
depwi -1,%sar,32,t0
|
||||
uxor,nbz r0,t0,r0
|
||||
.Lstrlen_loop:
|
||||
b,l,n .Lstrlen_end_loop,r0
|
||||
ldw,ma 4(ret0),t0
|
||||
cmpib,tr 0,r0,.Lstrlen_loop
|
||||
uxor,nbz r0,t0,r0
|
||||
.Lstrlen_end_loop:
|
||||
extrw,u,<> t0,7,8,r0
|
||||
addib,tr,n -3,ret0,.Lstrlen_out
|
||||
extrw,u,<> t0,15,8,r0
|
||||
addib,tr,n -2,ret0,.Lstrlen_out
|
||||
extrw,u,<> t0,23,8,r0
|
||||
addi -1,ret0,ret0
|
||||
.Lstrlen_out:
|
||||
bv r0(rp)
|
||||
uaddcm ret0,arg0,ret0
|
||||
.Lstrlen_null_ptr:
|
||||
bv,n r0(rp)
|
||||
ENDPROC_CFI(strlen)
|
||||
|
||||
|
||||
ENTRY_CFI(strcpy, frame=0,no_calls)
|
||||
ldb 0(arg1),t0
|
||||
stb t0,0(arg0)
|
||||
ldo 0(arg0),ret0
|
||||
ldo 1(arg1),t1
|
||||
cmpb,= r0,t0,2f
|
||||
ldo 1(arg0),t2
|
||||
1: ldb 0(t1),arg1
|
||||
stb arg1,0(t2)
|
||||
ldo 1(t1),t1
|
||||
cmpb,<> r0,arg1,1b
|
||||
ldo 1(t2),t2
|
||||
2: bv,n r0(rp)
|
||||
ENDPROC_CFI(strcpy)
|
||||
|
||||
|
||||
ENTRY_CFI(strncpy, frame=0,no_calls)
|
||||
ldb 0(arg1),t0
|
||||
stb t0,0(arg0)
|
||||
ldo 1(arg1),t1
|
||||
ldo 0(arg0),ret0
|
||||
cmpb,= r0,t0,2f
|
||||
ldo 1(arg0),arg1
|
||||
1: ldo -1(arg2),arg2
|
||||
cmpb,COND(=),n r0,arg2,2f
|
||||
ldb 0(t1),arg0
|
||||
stb arg0,0(arg1)
|
||||
ldo 1(t1),t1
|
||||
cmpb,<> r0,arg0,1b
|
||||
ldo 1(arg1),arg1
|
||||
2: bv,n r0(rp)
|
||||
ENDPROC_CFI(strncpy)
|
||||
|
||||
|
||||
ENTRY_CFI(strcat, frame=0,no_calls)
|
||||
ldb 0(arg0),t0
|
||||
cmpb,= t0,r0,2f
|
||||
ldo 0(arg0),ret0
|
||||
ldo 1(arg0),arg0
|
||||
1: ldb 0(arg0),t1
|
||||
cmpb,<>,n r0,t1,1b
|
||||
ldo 1(arg0),arg0
|
||||
2: ldb 0(arg1),t2
|
||||
stb t2,0(arg0)
|
||||
ldo 1(arg0),arg0
|
||||
ldb 0(arg1),t0
|
||||
cmpb,<> r0,t0,2b
|
||||
ldo 1(arg1),arg1
|
||||
bv,n r0(rp)
|
||||
ENDPROC_CFI(strcat)
|
||||
|
||||
|
||||
ENTRY_CFI(memset, frame=0,no_calls)
|
||||
copy arg0,ret0
|
||||
cmpb,COND(=) r0,arg0,4f
|
||||
copy arg0,t2
|
||||
cmpb,COND(=) r0,arg2,4f
|
||||
ldo -1(arg2),arg3
|
||||
subi -1,arg3,t0
|
||||
subi 0,t0,t1
|
||||
cmpiclr,COND(>=) 0,t1,arg2
|
||||
ldo -1(t1),arg2
|
||||
extru arg2,31,2,arg0
|
||||
2: stb arg1,0(t2)
|
||||
ldo 1(t2),t2
|
||||
addib,>= -1,arg0,2b
|
||||
ldo -1(arg3),arg3
|
||||
cmpiclr,COND(<=) 4,arg2,r0
|
||||
b,l,n 4f,r0
|
||||
#ifdef CONFIG_64BIT
|
||||
depd,* r0,63,2,arg2
|
||||
#else
|
||||
depw r0,31,2,arg2
|
||||
#endif
|
||||
ldo 1(t2),t2
|
||||
3: stb arg1,-1(t2)
|
||||
stb arg1,0(t2)
|
||||
stb arg1,1(t2)
|
||||
stb arg1,2(t2)
|
||||
addib,COND(>) -4,arg2,3b
|
||||
ldo 4(t2),t2
|
||||
4: bv,n r0(rp)
|
||||
ENDPROC_CFI(memset)
|
||||
|
||||
.end
|
@ -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 */
|
||||
|
@ -812,7 +812,6 @@ __start_interrupts:
|
||||
* syscall register convention is in Documentation/powerpc/syscall64-abi.rst
|
||||
*/
|
||||
EXC_VIRT_BEGIN(system_call_vectored, 0x3000, 0x1000)
|
||||
1:
|
||||
/* SCV 0 */
|
||||
mr r9,r13
|
||||
GET_PACA(r13)
|
||||
@ -842,10 +841,12 @@ EXC_VIRT_BEGIN(system_call_vectored, 0x3000, 0x1000)
|
||||
b system_call_vectored_sigill
|
||||
#endif
|
||||
.endr
|
||||
2:
|
||||
EXC_VIRT_END(system_call_vectored, 0x3000, 0x1000)
|
||||
|
||||
SOFT_MASK_TABLE(1b, 2b) // Treat scv vectors as soft-masked, see comment above.
|
||||
// Treat scv vectors as soft-masked, see comment above.
|
||||
// Use absolute values rather than labels here, so they don't get relocated,
|
||||
// because this code runs unrelocated.
|
||||
SOFT_MASK_TABLE(0xc000000000003000, 0xc000000000004000)
|
||||
|
||||
#ifdef CONFIG_RELOCATABLE
|
||||
TRAMP_VIRT_BEGIN(system_call_vectored_tramp)
|
||||
|
@ -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 @@ ALT_FTR_SECTION_END_IFSET(CPU_FTR_EMB_HV)
|
||||
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;
|
||||
|
@ -98,7 +98,7 @@ config PPC_BOOK3S_64
|
||||
select PPC_HAVE_PMU_SUPPORT
|
||||
select HAVE_ARCH_TRANSPARENT_HUGEPAGE
|
||||
select ARCH_ENABLE_HUGEPAGE_MIGRATION if HUGETLB_PAGE && MIGRATION
|
||||
select ARCH_ENABLE_PMD_SPLIT_PTLOCK
|
||||
select ARCH_ENABLE_SPLIT_PMD_PTLOCK
|
||||
select ARCH_ENABLE_THP_MIGRATION if TRANSPARENT_HUGEPAGE
|
||||
select ARCH_SUPPORTS_HUGETLBFS
|
||||
select ARCH_SUPPORTS_NUMA_BALANCING
|
||||
|
@ -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 @@ static int __init xive_request_ipi(void)
|
||||
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());
|
||||
|
@ -14,6 +14,10 @@ / {
|
||||
model = "Microchip PolarFire-SoC Icicle Kit";
|
||||
compatible = "microchip,mpfs-icicle-kit";
|
||||
|
||||
aliases {
|
||||
ethernet0 = &emac1;
|
||||
};
|
||||
|
||||
chosen {
|
||||
stdout-path = &serial0;
|
||||
};
|
||||
|
@ -317,7 +317,7 @@ emac1: ethernet@20112000 {
|
||||
reg = <0x0 0x20112000 0x0 0x2000>;
|
||||
interrupt-parent = <&plic>;
|
||||
interrupts = <70 71 72 73>;
|
||||
mac-address = [00 00 00 00 00 00];
|
||||
local-mac-address = [00 00 00 00 00 00];
|
||||
clocks = <&clkcfg 5>, <&clkcfg 2>;
|
||||
status = "disabled";
|
||||
clock-names = "pclk", "hclk";
|
||||
|
@ -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
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include <asm/ptrace.h>
|
||||
#include <asm/syscall.h>
|
||||
#include <asm/thread_info.h>
|
||||
#include <asm/switch_to.h>
|
||||
#include <linux/audit.h>
|
||||
#include <linux/ptrace.h>
|
||||
#include <linux/elf.h>
|
||||
@ -56,6 +57,9 @@ static int riscv_fpr_get(struct task_struct *target,
|
||||
{
|
||||
struct __riscv_d_ext_state *fstate = &target->thread.fstate;
|
||||
|
||||
if (target == current)
|
||||
fstate_save(current, task_pt_regs(current));
|
||||
|
||||
membuf_write(&to, fstate, offsetof(struct __riscv_d_ext_state, fcsr));
|
||||
membuf_store(&to, fstate->fcsr);
|
||||
return membuf_zero(&to, 4); // explicitly pad
|
||||
|
@ -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,
|
||||
|
@ -5,9 +5,8 @@
|
||||
* Early support for invoking 32-bit EFI services from a 64-bit kernel.
|
||||
*
|
||||
* Because this thunking occurs before ExitBootServices() we have to
|
||||
* restore the firmware's 32-bit GDT before we make EFI service calls,
|
||||
* since the firmware's 32-bit IDT is still currently installed and it
|
||||
* needs to be able to service interrupts.
|
||||
* restore the firmware's 32-bit GDT and IDT before we make EFI service
|
||||
* calls.
|
||||
*
|
||||
* On the plus side, we don't have to worry about mangling 64-bit
|
||||
* addresses into 32-bits because we're executing with an identity
|
||||
@ -39,7 +38,7 @@ SYM_FUNC_START(__efi64_thunk)
|
||||
/*
|
||||
* Convert x86-64 ABI params to i386 ABI
|
||||
*/
|
||||
subq $32, %rsp
|
||||
subq $64, %rsp
|
||||
movl %esi, 0x0(%rsp)
|
||||
movl %edx, 0x4(%rsp)
|
||||
movl %ecx, 0x8(%rsp)
|
||||
@ -49,14 +48,19 @@ SYM_FUNC_START(__efi64_thunk)
|
||||
leaq 0x14(%rsp), %rbx
|
||||
sgdt (%rbx)
|
||||
|
||||
addq $16, %rbx
|
||||
sidt (%rbx)
|
||||
|
||||
/*
|
||||
* Switch to gdt with 32-bit segments. This is the firmware GDT
|
||||
* that was installed when the kernel started executing. This
|
||||
* pointer was saved at the EFI stub entry point in head_64.S.
|
||||
* Switch to IDT and GDT with 32-bit segments. This is the firmware GDT
|
||||
* and IDT that was installed when the kernel started executing. The
|
||||
* pointers were saved at the EFI stub entry point in head_64.S.
|
||||
*
|
||||
* Pass the saved DS selector to the 32-bit code, and use far return to
|
||||
* restore the saved CS selector.
|
||||
*/
|
||||
leaq efi32_boot_idt(%rip), %rax
|
||||
lidt (%rax)
|
||||
leaq efi32_boot_gdt(%rip), %rax
|
||||
lgdt (%rax)
|
||||
|
||||
@ -67,7 +71,7 @@ SYM_FUNC_START(__efi64_thunk)
|
||||
pushq %rax
|
||||
lretq
|
||||
|
||||
1: addq $32, %rsp
|
||||
1: addq $64, %rsp
|
||||
movq %rdi, %rax
|
||||
|
||||
pop %rbx
|
||||
@ -128,10 +132,13 @@ SYM_FUNC_START_LOCAL(efi_enter32)
|
||||
|
||||
/*
|
||||
* Some firmware will return with interrupts enabled. Be sure to
|
||||
* disable them before we switch GDTs.
|
||||
* disable them before we switch GDTs and IDTs.
|
||||
*/
|
||||
cli
|
||||
|
||||
lidtl (%ebx)
|
||||
subl $16, %ebx
|
||||
|
||||
lgdtl (%ebx)
|
||||
|
||||
movl %cr4, %eax
|
||||
@ -166,6 +173,11 @@ SYM_DATA_START(efi32_boot_gdt)
|
||||
.quad 0
|
||||
SYM_DATA_END(efi32_boot_gdt)
|
||||
|
||||
SYM_DATA_START(efi32_boot_idt)
|
||||
.word 0
|
||||
.quad 0
|
||||
SYM_DATA_END(efi32_boot_idt)
|
||||
|
||||
SYM_DATA_START(efi32_boot_cs)
|
||||
.word 0
|
||||
SYM_DATA_END(efi32_boot_cs)
|
||||
|
@ -319,6 +319,9 @@ SYM_INNER_LABEL(efi32_pe_stub_entry, SYM_L_LOCAL)
|
||||
movw %cs, rva(efi32_boot_cs)(%ebp)
|
||||
movw %ds, rva(efi32_boot_ds)(%ebp)
|
||||
|
||||
/* Store firmware IDT descriptor */
|
||||
sidtl rva(efi32_boot_idt)(%ebp)
|
||||
|
||||
/* Disable paging */
|
||||
movl %cr0, %eax
|
||||
btrl $X86_CR0_PG_BIT, %eax
|
||||
|
@ -90,6 +90,7 @@ struct perf_ibs {
|
||||
unsigned long offset_mask[1];
|
||||
int offset_max;
|
||||
unsigned int fetch_count_reset_broken : 1;
|
||||
unsigned int fetch_ignore_if_zero_rip : 1;
|
||||
struct cpu_perf_ibs __percpu *pcpu;
|
||||
|
||||
struct attribute **format_attrs;
|
||||
@ -570,6 +571,7 @@ static struct perf_ibs perf_ibs_op = {
|
||||
.start = perf_ibs_start,
|
||||
.stop = perf_ibs_stop,
|
||||
.read = perf_ibs_read,
|
||||
.capabilities = PERF_PMU_CAP_NO_EXCLUDE,
|
||||
},
|
||||
.msr = MSR_AMD64_IBSOPCTL,
|
||||
.config_mask = IBS_OP_CONFIG_MASK,
|
||||
@ -672,6 +674,10 @@ static int perf_ibs_handle_irq(struct perf_ibs *perf_ibs, struct pt_regs *iregs)
|
||||
if (check_rip && (ibs_data.regs[2] & IBS_RIP_INVALID)) {
|
||||
regs.flags &= ~PERF_EFLAGS_EXACT;
|
||||
} else {
|
||||
/* Workaround for erratum #1197 */
|
||||
if (perf_ibs->fetch_ignore_if_zero_rip && !(ibs_data.regs[1]))
|
||||
goto out;
|
||||
|
||||
set_linear_ip(®s, ibs_data.regs[1]);
|
||||
regs.flags |= PERF_EFLAGS_EXACT;
|
||||
}
|
||||
@ -769,6 +775,9 @@ static __init void perf_event_ibs_init(void)
|
||||
if (boot_cpu_data.x86 >= 0x16 && boot_cpu_data.x86 <= 0x18)
|
||||
perf_ibs_fetch.fetch_count_reset_broken = 1;
|
||||
|
||||
if (boot_cpu_data.x86 == 0x19 && boot_cpu_data.x86_model < 0x10)
|
||||
perf_ibs_fetch.fetch_ignore_if_zero_rip = 1;
|
||||
|
||||
perf_ibs_pmu_init(&perf_ibs_fetch, "ibs_fetch");
|
||||
|
||||
if (ibs_caps & IBS_CAPS_OPCNT) {
|
||||
|
@ -213,6 +213,7 @@ static struct pmu pmu_class = {
|
||||
.stop = pmu_event_stop,
|
||||
.read = pmu_event_read,
|
||||
.capabilities = PERF_PMU_CAP_NO_EXCLUDE,
|
||||
.module = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int power_cpu_exit(unsigned int cpu)
|
||||
|
@ -62,7 +62,7 @@ static struct pt_cap_desc {
|
||||
PT_CAP(single_range_output, 0, CPUID_ECX, BIT(2)),
|
||||
PT_CAP(output_subsys, 0, CPUID_ECX, BIT(3)),
|
||||
PT_CAP(payloads_lip, 0, CPUID_ECX, BIT(31)),
|
||||
PT_CAP(num_address_ranges, 1, CPUID_EAX, 0x3),
|
||||
PT_CAP(num_address_ranges, 1, CPUID_EAX, 0x7),
|
||||
PT_CAP(mtc_periods, 1, CPUID_EAX, 0xffff0000),
|
||||
PT_CAP(cycle_thresholds, 1, CPUID_EBX, 0xffff),
|
||||
PT_CAP(psb_periods, 1, CPUID_EBX, 0xffff0000),
|
||||
|
@ -4811,7 +4811,7 @@ static void __snr_uncore_mmio_init_box(struct intel_uncore_box *box,
|
||||
return;
|
||||
|
||||
pci_read_config_dword(pdev, SNR_IMC_MMIO_BASE_OFFSET, &pci_dword);
|
||||
addr = (pci_dword & SNR_IMC_MMIO_BASE_MASK) << 23;
|
||||
addr = ((resource_size_t)pci_dword & SNR_IMC_MMIO_BASE_MASK) << 23;
|
||||
|
||||
pci_read_config_dword(pdev, mem_offset, &pci_dword);
|
||||
addr |= (pci_dword & SNR_IMC_MMIO_MEM0_MASK) << 12;
|
||||
|
@ -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:
|
||||
@ -307,10 +306,10 @@ static int __mon_event_count(u32 rmid, struct rmid_read *rr)
|
||||
break;
|
||||
default:
|
||||
/*
|
||||
* Code would never reach here because
|
||||
* an invalid event id would fail the __rmid_read.
|
||||
* Code would never reach here because an invalid
|
||||
* event id would fail the __rmid_read.
|
||||
*/
|
||||
return -EINVAL;
|
||||
return RMID_VAL_ERROR;
|
||||
}
|
||||
|
||||
if (rr->first) {
|
||||
@ -361,23 +360,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 @@ static u64 kvm_hv_send_ipi(struct kvm_vcpu *vcpu, struct kvm_hv_hcall *hc, bool
|
||||
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 @@ static bool zap_gfn_range(struct kvm *kvm, struct kvm_mmu_page *root,
|
||||
/*
|
||||
* 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
|
||||
|
@ -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,18 +25,12 @@
|
||||
#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
|
||||
*/
|
||||
static const int read_expire = HZ / 2; /* max time before a read is submitted. */
|
||||
static const int write_expire = 5 * HZ; /* ditto for writes, these limits are SOFT! */
|
||||
/*
|
||||
* Time after which to dispatch lower priority requests even if higher
|
||||
* priority requests are pending.
|
||||
*/
|
||||
static const int aging_expire = 10 * HZ;
|
||||
static const int writes_starved = 2; /* max times reads can starve a write */
|
||||
static const int fifo_batch = 16; /* # of sequential requests treated as one
|
||||
by the above parameters. For throughput. */
|
||||
@ -57,6 +51,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 +81,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. */
|
||||
@ -99,7 +98,6 @@ struct deadline_data {
|
||||
int writes_starved;
|
||||
int front_merges;
|
||||
u32 async_depth;
|
||||
int aging_expire;
|
||||
|
||||
spinlock_t lock;
|
||||
spinlock_t zone_lock;
|
||||
@ -234,10 +232,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
|
||||
@ -367,15 +363,13 @@ deadline_next_request(struct deadline_data *dd, struct dd_per_prio *per_prio,
|
||||
|
||||
/*
|
||||
* deadline_dispatch_requests selects the best request according to
|
||||
* read/write expire, fifo_batch, etc and with a start time <= @latest.
|
||||
* read/write expire, fifo_batch, etc
|
||||
*/
|
||||
static struct request *__dd_dispatch_request(struct deadline_data *dd,
|
||||
struct dd_per_prio *per_prio,
|
||||
u64 latest_start_ns)
|
||||
struct dd_per_prio *per_prio)
|
||||
{
|
||||
struct request *rq, *next_rq;
|
||||
enum dd_data_dir data_dir;
|
||||
struct dd_blkcg *blkcg;
|
||||
enum dd_prio prio;
|
||||
u8 ioprio_class;
|
||||
|
||||
@ -384,8 +378,6 @@ static struct request *__dd_dispatch_request(struct deadline_data *dd,
|
||||
if (!list_empty(&per_prio->dispatch)) {
|
||||
rq = list_first_entry(&per_prio->dispatch, struct request,
|
||||
queuelist);
|
||||
if (rq->start_time_ns > latest_start_ns)
|
||||
return NULL;
|
||||
list_del_init(&rq->queuelist);
|
||||
goto done;
|
||||
}
|
||||
@ -463,8 +455,6 @@ static struct request *__dd_dispatch_request(struct deadline_data *dd,
|
||||
dd->batching = 0;
|
||||
|
||||
dispatch_request:
|
||||
if (rq->start_time_ns > latest_start_ns)
|
||||
return NULL;
|
||||
/*
|
||||
* rq is the selected appropriate request.
|
||||
*/
|
||||
@ -474,8 +464,6 @@ static struct request *__dd_dispatch_request(struct deadline_data *dd,
|
||||
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.
|
||||
*/
|
||||
@ -495,32 +483,15 @@ static struct request *__dd_dispatch_request(struct deadline_data *dd,
|
||||
static struct request *dd_dispatch_request(struct blk_mq_hw_ctx *hctx)
|
||||
{
|
||||
struct deadline_data *dd = hctx->queue->elevator->elevator_data;
|
||||
const u64 now_ns = ktime_get_ns();
|
||||
struct request *rq = NULL;
|
||||
struct request *rq;
|
||||
enum dd_prio prio;
|
||||
|
||||
spin_lock(&dd->lock);
|
||||
/*
|
||||
* Start with dispatching requests whose deadline expired more than
|
||||
* aging_expire jiffies ago.
|
||||
*/
|
||||
for (prio = DD_BE_PRIO; prio <= DD_PRIO_MAX; prio++) {
|
||||
rq = __dd_dispatch_request(dd, &dd->per_prio[prio], now_ns -
|
||||
jiffies_to_nsecs(dd->aging_expire));
|
||||
if (rq)
|
||||
goto unlock;
|
||||
}
|
||||
/*
|
||||
* Next, dispatch requests in priority order. Ignore lower priority
|
||||
* requests if any higher priority requests are pending.
|
||||
*/
|
||||
for (prio = 0; prio <= DD_PRIO_MAX; prio++) {
|
||||
rq = __dd_dispatch_request(dd, &dd->per_prio[prio], now_ns);
|
||||
if (rq || dd_queued(dd, prio))
|
||||
rq = __dd_dispatch_request(dd, &dd->per_prio[prio]);
|
||||
if (rq)
|
||||
break;
|
||||
}
|
||||
|
||||
unlock:
|
||||
spin_unlock(&dd->lock);
|
||||
|
||||
return rq;
|
||||
@ -569,8 +540,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 +553,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 +562,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 +577,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];
|
||||
|
||||
@ -631,21 +592,12 @@ static int dd_init_sched(struct request_queue *q, struct elevator_type *e)
|
||||
dd->front_merges = 1;
|
||||
dd->last_dir = DD_WRITE;
|
||||
dd->fifo_batch = fifo_batch;
|
||||
dd->aging_expire = aging_expire;
|
||||
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 +670,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 +680,9 @@ 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;
|
||||
rq->elv.priv[0] = (void *)(uintptr_t)1;
|
||||
|
||||
if (blk_mq_sched_try_insert_merge(q, rq, &free)) {
|
||||
blk_mq_free_requests(&free);
|
||||
@ -815,13 +757,18 @@ 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);
|
||||
/*
|
||||
* The block layer core may call dd_finish_request() without having
|
||||
* called dd_insert_requests(). Hence only update statistics for
|
||||
* requests for which dd_insert_requests() has been called. See also
|
||||
* blk_mq_request_bypass_insert().
|
||||
*/
|
||||
if (rq->elv.priv[0])
|
||||
dd_count(dd, completed, prio);
|
||||
|
||||
if (blk_queue_is_zoned(q)) {
|
||||
unsigned long flags;
|
||||
@ -866,7 +813,6 @@ static ssize_t __FUNC(struct elevator_queue *e, char *page) \
|
||||
#define SHOW_JIFFIES(__FUNC, __VAR) SHOW_INT(__FUNC, jiffies_to_msecs(__VAR))
|
||||
SHOW_JIFFIES(deadline_read_expire_show, dd->fifo_expire[DD_READ]);
|
||||
SHOW_JIFFIES(deadline_write_expire_show, dd->fifo_expire[DD_WRITE]);
|
||||
SHOW_JIFFIES(deadline_aging_expire_show, dd->aging_expire);
|
||||
SHOW_INT(deadline_writes_starved_show, dd->writes_starved);
|
||||
SHOW_INT(deadline_front_merges_show, dd->front_merges);
|
||||
SHOW_INT(deadline_async_depth_show, dd->front_merges);
|
||||
@ -896,7 +842,6 @@ static ssize_t __FUNC(struct elevator_queue *e, const char *page, size_t count)
|
||||
STORE_FUNCTION(__FUNC, __PTR, MIN, MAX, msecs_to_jiffies)
|
||||
STORE_JIFFIES(deadline_read_expire_store, &dd->fifo_expire[DD_READ], 0, INT_MAX);
|
||||
STORE_JIFFIES(deadline_write_expire_store, &dd->fifo_expire[DD_WRITE], 0, INT_MAX);
|
||||
STORE_JIFFIES(deadline_aging_expire_store, &dd->aging_expire, 0, INT_MAX);
|
||||
STORE_INT(deadline_writes_starved_store, &dd->writes_starved, INT_MIN, INT_MAX);
|
||||
STORE_INT(deadline_front_merges_store, &dd->front_merges, 0, 1);
|
||||
STORE_INT(deadline_async_depth_store, &dd->front_merges, 1, INT_MAX);
|
||||
@ -915,7 +860,6 @@ static struct elv_fs_entry deadline_attrs[] = {
|
||||
DD_ATTR(front_merges),
|
||||
DD_ATTR(async_depth),
|
||||
DD_ATTR(fifo_batch),
|
||||
DD_ATTR(aging_expire),
|
||||
__ATTR_NULL
|
||||
};
|
||||
|
||||
@ -1144,26 +1088,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);
|
||||
|
@ -435,7 +435,7 @@ static void genpd_restore_performance_state(struct device *dev,
|
||||
int dev_pm_genpd_set_performance_state(struct device *dev, unsigned int state)
|
||||
{
|
||||
struct generic_pm_domain *genpd;
|
||||
int ret;
|
||||
int ret = 0;
|
||||
|
||||
genpd = dev_to_genpd_safe(dev);
|
||||
if (!genpd)
|
||||
@ -446,7 +446,13 @@ int dev_pm_genpd_set_performance_state(struct device *dev, unsigned int state)
|
||||
return -EINVAL;
|
||||
|
||||
genpd_lock(genpd);
|
||||
ret = genpd_set_performance_state(dev, state);
|
||||
if (pm_runtime_suspended(dev)) {
|
||||
dev_gpd_data(dev)->rpm_pstate = state;
|
||||
} else {
|
||||
ret = genpd_set_performance_state(dev, state);
|
||||
if (!ret)
|
||||
dev_gpd_data(dev)->rpm_pstate = 0;
|
||||
}
|
||||
genpd_unlock(genpd);
|
||||
|
||||
return ret;
|
||||
|
@ -213,7 +213,7 @@ config BLK_DEV_LOOP_MIN_COUNT
|
||||
dynamically allocated with the /dev/loop-control interface.
|
||||
|
||||
config BLK_DEV_CRYPTOLOOP
|
||||
tristate "Cryptoloop Support"
|
||||
tristate "Cryptoloop Support (DEPRECATED)"
|
||||
select CRYPTO
|
||||
select CRYPTO_CBC
|
||||
depends on BLK_DEV_LOOP
|
||||
@ -225,7 +225,7 @@ config BLK_DEV_CRYPTOLOOP
|
||||
WARNING: This device is not safe for journaled file systems like
|
||||
ext3 or Reiserfs. Please use the Device Mapper crypto module
|
||||
instead, which can be configured to be on-disk compatible with the
|
||||
cryptoloop device.
|
||||
cryptoloop device. cryptoloop support will be removed in Linux 5.16.
|
||||
|
||||
source "drivers/block/drbd/Kconfig"
|
||||
|
||||
|
@ -189,6 +189,8 @@ init_cryptoloop(void)
|
||||
|
||||
if (rc)
|
||||
printk(KERN_ERR "cryptoloop: loop_register_transfer failed\n");
|
||||
else
|
||||
pr_warn("the cryptoloop driver has been deprecated and will be removed in in Linux 5.16\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -892,7 +892,7 @@ static void pd_probe_drive(struct pd_unit *disk)
|
||||
return;
|
||||
|
||||
p = blk_mq_alloc_disk(&disk->tag_set, disk);
|
||||
if (!p) {
|
||||
if (IS_ERR(p)) {
|
||||
blk_mq_free_tag_set(&disk->tag_set);
|
||||
return;
|
||||
}
|
||||
|
@ -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,
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user