mirror of
https://github.com/Fishwaldo/linux-bl808.git
synced 2025-03-28 18:05:00 +00:00
Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
Move the bpf verifier trace check into the new switch statement in HEAD. Resolve the overlapping changes in hinic, where bug fixes overlap the addition of VF support. Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
da07f52d3c
342 changed files with 3468 additions and 1533 deletions
|
@ -112,6 +112,20 @@ used when printing stack backtraces. The specifier takes into
|
||||||
consideration the effect of compiler optimisations which may occur
|
consideration the effect of compiler optimisations which may occur
|
||||||
when tail-calls are used and marked with the noreturn GCC attribute.
|
when tail-calls are used and marked with the noreturn GCC attribute.
|
||||||
|
|
||||||
|
Probed Pointers from BPF / tracing
|
||||||
|
----------------------------------
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
%pks kernel string
|
||||||
|
%pus user string
|
||||||
|
|
||||||
|
The ``k`` and ``u`` specifiers are used for printing prior probed memory from
|
||||||
|
either kernel memory (k) or user memory (u). The subsequent ``s`` specifier
|
||||||
|
results in printing a string. For direct use in regular vsnprintf() the (k)
|
||||||
|
and (u) annotation is ignored, however, when used out of BPF's bpf_trace_printk(),
|
||||||
|
for example, it reads the memory it is pointing to without faulting.
|
||||||
|
|
||||||
Kernel Pointers
|
Kernel Pointers
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
|
|
|
@ -28,3 +28,5 @@ KVM
|
||||||
arm/index
|
arm/index
|
||||||
|
|
||||||
devices/index
|
devices/index
|
||||||
|
|
||||||
|
running-nested-guests
|
||||||
|
|
276
Documentation/virt/kvm/running-nested-guests.rst
Normal file
276
Documentation/virt/kvm/running-nested-guests.rst
Normal file
|
@ -0,0 +1,276 @@
|
||||||
|
==============================
|
||||||
|
Running nested guests with KVM
|
||||||
|
==============================
|
||||||
|
|
||||||
|
A nested guest is the ability to run a guest inside another guest (it
|
||||||
|
can be KVM-based or a different hypervisor). The straightforward
|
||||||
|
example is a KVM guest that in turn runs on a KVM guest (the rest of
|
||||||
|
this document is built on this example)::
|
||||||
|
|
||||||
|
.----------------. .----------------.
|
||||||
|
| | | |
|
||||||
|
| L2 | | L2 |
|
||||||
|
| (Nested Guest) | | (Nested Guest) |
|
||||||
|
| | | |
|
||||||
|
|----------------'--'----------------|
|
||||||
|
| |
|
||||||
|
| L1 (Guest Hypervisor) |
|
||||||
|
| KVM (/dev/kvm) |
|
||||||
|
| |
|
||||||
|
.------------------------------------------------------.
|
||||||
|
| L0 (Host Hypervisor) |
|
||||||
|
| KVM (/dev/kvm) |
|
||||||
|
|------------------------------------------------------|
|
||||||
|
| Hardware (with virtualization extensions) |
|
||||||
|
'------------------------------------------------------'
|
||||||
|
|
||||||
|
Terminology:
|
||||||
|
|
||||||
|
- L0 – level-0; the bare metal host, running KVM
|
||||||
|
|
||||||
|
- L1 – level-1 guest; a VM running on L0; also called the "guest
|
||||||
|
hypervisor", as it itself is capable of running KVM.
|
||||||
|
|
||||||
|
- L2 – level-2 guest; a VM running on L1, this is the "nested guest"
|
||||||
|
|
||||||
|
.. note:: The above diagram is modelled after the x86 architecture;
|
||||||
|
s390x, ppc64 and other architectures are likely to have
|
||||||
|
a different design for nesting.
|
||||||
|
|
||||||
|
For example, s390x always has an LPAR (LogicalPARtition)
|
||||||
|
hypervisor running on bare metal, adding another layer and
|
||||||
|
resulting in at least four levels in a nested setup — L0 (bare
|
||||||
|
metal, running the LPAR hypervisor), L1 (host hypervisor), L2
|
||||||
|
(guest hypervisor), L3 (nested guest).
|
||||||
|
|
||||||
|
This document will stick with the three-level terminology (L0,
|
||||||
|
L1, and L2) for all architectures; and will largely focus on
|
||||||
|
x86.
|
||||||
|
|
||||||
|
|
||||||
|
Use Cases
|
||||||
|
---------
|
||||||
|
|
||||||
|
There are several scenarios where nested KVM can be useful, to name a
|
||||||
|
few:
|
||||||
|
|
||||||
|
- As a developer, you want to test your software on different operating
|
||||||
|
systems (OSes). Instead of renting multiple VMs from a Cloud
|
||||||
|
Provider, using nested KVM lets you rent a large enough "guest
|
||||||
|
hypervisor" (level-1 guest). This in turn allows you to create
|
||||||
|
multiple nested guests (level-2 guests), running different OSes, on
|
||||||
|
which you can develop and test your software.
|
||||||
|
|
||||||
|
- Live migration of "guest hypervisors" and their nested guests, for
|
||||||
|
load balancing, disaster recovery, etc.
|
||||||
|
|
||||||
|
- VM image creation tools (e.g. ``virt-install``, etc) often run
|
||||||
|
their own VM, and users expect these to work inside a VM.
|
||||||
|
|
||||||
|
- Some OSes use virtualization internally for security (e.g. to let
|
||||||
|
applications run safely in isolation).
|
||||||
|
|
||||||
|
|
||||||
|
Enabling "nested" (x86)
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
From Linux kernel v4.19 onwards, the ``nested`` KVM parameter is enabled
|
||||||
|
by default for Intel and AMD. (Though your Linux distribution might
|
||||||
|
override this default.)
|
||||||
|
|
||||||
|
In case you are running a Linux kernel older than v4.19, to enable
|
||||||
|
nesting, set the ``nested`` KVM module parameter to ``Y`` or ``1``. To
|
||||||
|
persist this setting across reboots, you can add it in a config file, as
|
||||||
|
shown below:
|
||||||
|
|
||||||
|
1. On the bare metal host (L0), list the kernel modules and ensure that
|
||||||
|
the KVM modules::
|
||||||
|
|
||||||
|
$ lsmod | grep -i kvm
|
||||||
|
kvm_intel 133627 0
|
||||||
|
kvm 435079 1 kvm_intel
|
||||||
|
|
||||||
|
2. Show information for ``kvm_intel`` module::
|
||||||
|
|
||||||
|
$ modinfo kvm_intel | grep -i nested
|
||||||
|
parm: nested:bool
|
||||||
|
|
||||||
|
3. For the nested KVM configuration to persist across reboots, place the
|
||||||
|
below in ``/etc/modprobed/kvm_intel.conf`` (create the file if it
|
||||||
|
doesn't exist)::
|
||||||
|
|
||||||
|
$ cat /etc/modprobe.d/kvm_intel.conf
|
||||||
|
options kvm-intel nested=y
|
||||||
|
|
||||||
|
4. Unload and re-load the KVM Intel module::
|
||||||
|
|
||||||
|
$ sudo rmmod kvm-intel
|
||||||
|
$ sudo modprobe kvm-intel
|
||||||
|
|
||||||
|
5. Verify if the ``nested`` parameter for KVM is enabled::
|
||||||
|
|
||||||
|
$ cat /sys/module/kvm_intel/parameters/nested
|
||||||
|
Y
|
||||||
|
|
||||||
|
For AMD hosts, the process is the same as above, except that the module
|
||||||
|
name is ``kvm-amd``.
|
||||||
|
|
||||||
|
|
||||||
|
Additional nested-related kernel parameters (x86)
|
||||||
|
-------------------------------------------------
|
||||||
|
|
||||||
|
If your hardware is sufficiently advanced (Intel Haswell processor or
|
||||||
|
higher, which has newer hardware virt extensions), the following
|
||||||
|
additional features will also be enabled by default: "Shadow VMCS
|
||||||
|
(Virtual Machine Control Structure)", APIC Virtualization on your bare
|
||||||
|
metal host (L0). Parameters for Intel hosts::
|
||||||
|
|
||||||
|
$ cat /sys/module/kvm_intel/parameters/enable_shadow_vmcs
|
||||||
|
Y
|
||||||
|
|
||||||
|
$ cat /sys/module/kvm_intel/parameters/enable_apicv
|
||||||
|
Y
|
||||||
|
|
||||||
|
$ cat /sys/module/kvm_intel/parameters/ept
|
||||||
|
Y
|
||||||
|
|
||||||
|
.. note:: If you suspect your L2 (i.e. nested guest) is running slower,
|
||||||
|
ensure the above are enabled (particularly
|
||||||
|
``enable_shadow_vmcs`` and ``ept``).
|
||||||
|
|
||||||
|
|
||||||
|
Starting a nested guest (x86)
|
||||||
|
-----------------------------
|
||||||
|
|
||||||
|
Once your bare metal host (L0) is configured for nesting, you should be
|
||||||
|
able to start an L1 guest with::
|
||||||
|
|
||||||
|
$ qemu-kvm -cpu host [...]
|
||||||
|
|
||||||
|
The above will pass through the host CPU's capabilities as-is to the
|
||||||
|
gues); or for better live migration compatibility, use a named CPU
|
||||||
|
model supported by QEMU. e.g.::
|
||||||
|
|
||||||
|
$ qemu-kvm -cpu Haswell-noTSX-IBRS,vmx=on
|
||||||
|
|
||||||
|
then the guest hypervisor will subsequently be capable of running a
|
||||||
|
nested guest with accelerated KVM.
|
||||||
|
|
||||||
|
|
||||||
|
Enabling "nested" (s390x)
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
1. On the host hypervisor (L0), enable the ``nested`` parameter on
|
||||||
|
s390x::
|
||||||
|
|
||||||
|
$ rmmod kvm
|
||||||
|
$ modprobe kvm nested=1
|
||||||
|
|
||||||
|
.. note:: On s390x, the kernel parameter ``hpage`` is mutually exclusive
|
||||||
|
with the ``nested`` paramter — i.e. to be able to enable
|
||||||
|
``nested``, the ``hpage`` parameter *must* be disabled.
|
||||||
|
|
||||||
|
2. The guest hypervisor (L1) must be provided with the ``sie`` CPU
|
||||||
|
feature — with QEMU, this can be done by using "host passthrough"
|
||||||
|
(via the command-line ``-cpu host``).
|
||||||
|
|
||||||
|
3. Now the KVM module can be loaded in the L1 (guest hypervisor)::
|
||||||
|
|
||||||
|
$ modprobe kvm
|
||||||
|
|
||||||
|
|
||||||
|
Live migration with nested KVM
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
Migrating an L1 guest, with a *live* nested guest in it, to another
|
||||||
|
bare metal host, works as of Linux kernel 5.3 and QEMU 4.2.0 for
|
||||||
|
Intel x86 systems, and even on older versions for s390x.
|
||||||
|
|
||||||
|
On AMD systems, once an L1 guest has started an L2 guest, the L1 guest
|
||||||
|
should no longer be migrated or saved (refer to QEMU documentation on
|
||||||
|
"savevm"/"loadvm") until the L2 guest shuts down. Attempting to migrate
|
||||||
|
or save-and-load an L1 guest while an L2 guest is running will result in
|
||||||
|
undefined behavior. You might see a ``kernel BUG!`` entry in ``dmesg``, a
|
||||||
|
kernel 'oops', or an outright kernel panic. Such a migrated or loaded L1
|
||||||
|
guest can no longer be considered stable or secure, and must be restarted.
|
||||||
|
Migrating an L1 guest merely configured to support nesting, while not
|
||||||
|
actually running L2 guests, is expected to function normally even on AMD
|
||||||
|
systems but may fail once guests are started.
|
||||||
|
|
||||||
|
Migrating an L2 guest is always expected to succeed, so all the following
|
||||||
|
scenarios should work even on AMD systems:
|
||||||
|
|
||||||
|
- Migrating a nested guest (L2) to another L1 guest on the *same* bare
|
||||||
|
metal host.
|
||||||
|
|
||||||
|
- Migrating a nested guest (L2) to another L1 guest on a *different*
|
||||||
|
bare metal host.
|
||||||
|
|
||||||
|
- Migrating a nested guest (L2) to a bare metal host.
|
||||||
|
|
||||||
|
Reporting bugs from nested setups
|
||||||
|
-----------------------------------
|
||||||
|
|
||||||
|
Debugging "nested" problems can involve sifting through log files across
|
||||||
|
L0, L1 and L2; this can result in tedious back-n-forth between the bug
|
||||||
|
reporter and the bug fixer.
|
||||||
|
|
||||||
|
- Mention that you are in a "nested" setup. If you are running any kind
|
||||||
|
of "nesting" at all, say so. Unfortunately, this needs to be called
|
||||||
|
out because when reporting bugs, people tend to forget to even
|
||||||
|
*mention* that they're using nested virtualization.
|
||||||
|
|
||||||
|
- Ensure you are actually running KVM on KVM. Sometimes people do not
|
||||||
|
have KVM enabled for their guest hypervisor (L1), which results in
|
||||||
|
them running with pure emulation or what QEMU calls it as "TCG", but
|
||||||
|
they think they're running nested KVM. Thus confusing "nested Virt"
|
||||||
|
(which could also mean, QEMU on KVM) with "nested KVM" (KVM on KVM).
|
||||||
|
|
||||||
|
Information to collect (generic)
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
The following is not an exhaustive list, but a very good starting point:
|
||||||
|
|
||||||
|
- Kernel, libvirt, and QEMU version from L0
|
||||||
|
|
||||||
|
- Kernel, libvirt and QEMU version from L1
|
||||||
|
|
||||||
|
- QEMU command-line of L1 -- when using libvirt, you'll find it here:
|
||||||
|
``/var/log/libvirt/qemu/instance.log``
|
||||||
|
|
||||||
|
- QEMU command-line of L2 -- as above, when using libvirt, get the
|
||||||
|
complete libvirt-generated QEMU command-line
|
||||||
|
|
||||||
|
- ``cat /sys/cpuinfo`` from L0
|
||||||
|
|
||||||
|
- ``cat /sys/cpuinfo`` from L1
|
||||||
|
|
||||||
|
- ``lscpu`` from L0
|
||||||
|
|
||||||
|
- ``lscpu`` from L1
|
||||||
|
|
||||||
|
- Full ``dmesg`` output from L0
|
||||||
|
|
||||||
|
- Full ``dmesg`` output from L1
|
||||||
|
|
||||||
|
x86-specific info to collect
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Both the below commands, ``x86info`` and ``dmidecode``, should be
|
||||||
|
available on most Linux distributions with the same name:
|
||||||
|
|
||||||
|
- Output of: ``x86info -a`` from L0
|
||||||
|
|
||||||
|
- Output of: ``x86info -a`` from L1
|
||||||
|
|
||||||
|
- Output of: ``dmidecode`` from L0
|
||||||
|
|
||||||
|
- Output of: ``dmidecode`` from L1
|
||||||
|
|
||||||
|
s390x-specific info to collect
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Along with the earlier mentioned generic details, the below is
|
||||||
|
also recommended:
|
||||||
|
|
||||||
|
- ``/proc/sysinfo`` from L1; this will also include the info from L0
|
19
MAINTAINERS
19
MAINTAINERS
|
@ -3936,11 +3936,9 @@ F: arch/powerpc/platforms/cell/
|
||||||
CEPH COMMON CODE (LIBCEPH)
|
CEPH COMMON CODE (LIBCEPH)
|
||||||
M: Ilya Dryomov <idryomov@gmail.com>
|
M: Ilya Dryomov <idryomov@gmail.com>
|
||||||
M: Jeff Layton <jlayton@kernel.org>
|
M: Jeff Layton <jlayton@kernel.org>
|
||||||
M: Sage Weil <sage@redhat.com>
|
|
||||||
L: ceph-devel@vger.kernel.org
|
L: ceph-devel@vger.kernel.org
|
||||||
S: Supported
|
S: Supported
|
||||||
W: http://ceph.com/
|
W: http://ceph.com/
|
||||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client.git
|
|
||||||
T: git git://github.com/ceph/ceph-client.git
|
T: git git://github.com/ceph/ceph-client.git
|
||||||
F: include/linux/ceph/
|
F: include/linux/ceph/
|
||||||
F: include/linux/crush/
|
F: include/linux/crush/
|
||||||
|
@ -3948,12 +3946,10 @@ F: net/ceph/
|
||||||
|
|
||||||
CEPH DISTRIBUTED FILE SYSTEM CLIENT (CEPH)
|
CEPH DISTRIBUTED FILE SYSTEM CLIENT (CEPH)
|
||||||
M: Jeff Layton <jlayton@kernel.org>
|
M: Jeff Layton <jlayton@kernel.org>
|
||||||
M: Sage Weil <sage@redhat.com>
|
|
||||||
M: Ilya Dryomov <idryomov@gmail.com>
|
M: Ilya Dryomov <idryomov@gmail.com>
|
||||||
L: ceph-devel@vger.kernel.org
|
L: ceph-devel@vger.kernel.org
|
||||||
S: Supported
|
S: Supported
|
||||||
W: http://ceph.com/
|
W: http://ceph.com/
|
||||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client.git
|
|
||||||
T: git git://github.com/ceph/ceph-client.git
|
T: git git://github.com/ceph/ceph-client.git
|
||||||
F: Documentation/filesystems/ceph.rst
|
F: Documentation/filesystems/ceph.rst
|
||||||
F: fs/ceph/
|
F: fs/ceph/
|
||||||
|
@ -7119,9 +7115,10 @@ F: include/uapi/asm-generic/
|
||||||
|
|
||||||
GENERIC PHY FRAMEWORK
|
GENERIC PHY FRAMEWORK
|
||||||
M: Kishon Vijay Abraham I <kishon@ti.com>
|
M: Kishon Vijay Abraham I <kishon@ti.com>
|
||||||
|
M: Vinod Koul <vkoul@kernel.org>
|
||||||
L: linux-kernel@vger.kernel.org
|
L: linux-kernel@vger.kernel.org
|
||||||
S: Supported
|
S: Supported
|
||||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/kishon/linux-phy.git
|
T: git git://git.kernel.org/pub/scm/linux/kernel/git/phy/linux-phy.git
|
||||||
F: Documentation/devicetree/bindings/phy/
|
F: Documentation/devicetree/bindings/phy/
|
||||||
F: drivers/phy/
|
F: drivers/phy/
|
||||||
F: include/linux/phy/
|
F: include/linux/phy/
|
||||||
|
@ -7746,11 +7743,6 @@ L: platform-driver-x86@vger.kernel.org
|
||||||
S: Orphan
|
S: Orphan
|
||||||
F: drivers/platform/x86/tc1100-wmi.c
|
F: drivers/platform/x86/tc1100-wmi.c
|
||||||
|
|
||||||
HP100: Driver for HP 10/100 Mbit/s Voice Grade Network Adapter Series
|
|
||||||
M: Jaroslav Kysela <perex@perex.cz>
|
|
||||||
S: Obsolete
|
|
||||||
F: drivers/staging/hp/hp100.*
|
|
||||||
|
|
||||||
HPET: High Precision Event Timers driver
|
HPET: High Precision Event Timers driver
|
||||||
M: Clemens Ladisch <clemens@ladisch.de>
|
M: Clemens Ladisch <clemens@ladisch.de>
|
||||||
S: Maintained
|
S: Maintained
|
||||||
|
@ -11718,8 +11710,9 @@ F: net/core/drop_monitor.c
|
||||||
|
|
||||||
NETWORKING DRIVERS
|
NETWORKING DRIVERS
|
||||||
M: "David S. Miller" <davem@davemloft.net>
|
M: "David S. Miller" <davem@davemloft.net>
|
||||||
|
M: Jakub Kicinski <kuba@kernel.org>
|
||||||
L: netdev@vger.kernel.org
|
L: netdev@vger.kernel.org
|
||||||
S: Odd Fixes
|
S: Maintained
|
||||||
W: http://www.linuxfoundation.org/en/Net
|
W: http://www.linuxfoundation.org/en/Net
|
||||||
Q: http://patchwork.ozlabs.org/project/netdev/list/
|
Q: http://patchwork.ozlabs.org/project/netdev/list/
|
||||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net.git
|
T: git git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net.git
|
||||||
|
@ -14102,12 +14095,10 @@ F: drivers/media/radio/radio-tea5777.c
|
||||||
|
|
||||||
RADOS BLOCK DEVICE (RBD)
|
RADOS BLOCK DEVICE (RBD)
|
||||||
M: Ilya Dryomov <idryomov@gmail.com>
|
M: Ilya Dryomov <idryomov@gmail.com>
|
||||||
M: Sage Weil <sage@redhat.com>
|
|
||||||
R: Dongsheng Yang <dongsheng.yang@easystack.cn>
|
R: Dongsheng Yang <dongsheng.yang@easystack.cn>
|
||||||
L: ceph-devel@vger.kernel.org
|
L: ceph-devel@vger.kernel.org
|
||||||
S: Supported
|
S: Supported
|
||||||
W: http://ceph.com/
|
W: http://ceph.com/
|
||||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client.git
|
|
||||||
T: git git://github.com/ceph/ceph-client.git
|
T: git git://github.com/ceph/ceph-client.git
|
||||||
F: Documentation/ABI/testing/sysfs-bus-rbd
|
F: Documentation/ABI/testing/sysfs-bus-rbd
|
||||||
F: drivers/block/rbd.c
|
F: drivers/block/rbd.c
|
||||||
|
@ -14644,6 +14635,7 @@ F: drivers/iommu/s390-iommu.c
|
||||||
|
|
||||||
S390 IUCV NETWORK LAYER
|
S390 IUCV NETWORK LAYER
|
||||||
M: Julian Wiedmann <jwi@linux.ibm.com>
|
M: Julian Wiedmann <jwi@linux.ibm.com>
|
||||||
|
M: Karsten Graul <kgraul@linux.ibm.com>
|
||||||
M: Ursula Braun <ubraun@linux.ibm.com>
|
M: Ursula Braun <ubraun@linux.ibm.com>
|
||||||
L: linux-s390@vger.kernel.org
|
L: linux-s390@vger.kernel.org
|
||||||
S: Supported
|
S: Supported
|
||||||
|
@ -14654,6 +14646,7 @@ F: net/iucv/
|
||||||
|
|
||||||
S390 NETWORK DRIVERS
|
S390 NETWORK DRIVERS
|
||||||
M: Julian Wiedmann <jwi@linux.ibm.com>
|
M: Julian Wiedmann <jwi@linux.ibm.com>
|
||||||
|
M: Karsten Graul <kgraul@linux.ibm.com>
|
||||||
M: Ursula Braun <ubraun@linux.ibm.com>
|
M: Ursula Braun <ubraun@linux.ibm.com>
|
||||||
L: linux-s390@vger.kernel.org
|
L: linux-s390@vger.kernel.org
|
||||||
S: Supported
|
S: Supported
|
||||||
|
|
17
Makefile
17
Makefile
|
@ -2,7 +2,7 @@
|
||||||
VERSION = 5
|
VERSION = 5
|
||||||
PATCHLEVEL = 7
|
PATCHLEVEL = 7
|
||||||
SUBLEVEL = 0
|
SUBLEVEL = 0
|
||||||
EXTRAVERSION = -rc4
|
EXTRAVERSION = -rc5
|
||||||
NAME = Kleptomaniac Octopus
|
NAME = Kleptomaniac Octopus
|
||||||
|
|
||||||
# *DOCUMENTATION*
|
# *DOCUMENTATION*
|
||||||
|
@ -729,10 +729,6 @@ else ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE
|
||||||
KBUILD_CFLAGS += -Os
|
KBUILD_CFLAGS += -Os
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifdef CONFIG_CC_DISABLE_WARN_MAYBE_UNINITIALIZED
|
|
||||||
KBUILD_CFLAGS += -Wno-maybe-uninitialized
|
|
||||||
endif
|
|
||||||
|
|
||||||
# Tell gcc to never replace conditional load with a non-conditional one
|
# Tell gcc to never replace conditional load with a non-conditional one
|
||||||
KBUILD_CFLAGS += $(call cc-option,--param=allow-store-data-races=0)
|
KBUILD_CFLAGS += $(call cc-option,--param=allow-store-data-races=0)
|
||||||
KBUILD_CFLAGS += $(call cc-option,-fno-allow-store-data-races)
|
KBUILD_CFLAGS += $(call cc-option,-fno-allow-store-data-races)
|
||||||
|
@ -881,6 +877,17 @@ KBUILD_CFLAGS += -Wno-pointer-sign
|
||||||
# disable stringop warnings in gcc 8+
|
# disable stringop warnings in gcc 8+
|
||||||
KBUILD_CFLAGS += $(call cc-disable-warning, stringop-truncation)
|
KBUILD_CFLAGS += $(call cc-disable-warning, stringop-truncation)
|
||||||
|
|
||||||
|
# We'll want to enable this eventually, but it's not going away for 5.7 at least
|
||||||
|
KBUILD_CFLAGS += $(call cc-disable-warning, zero-length-bounds)
|
||||||
|
KBUILD_CFLAGS += $(call cc-disable-warning, array-bounds)
|
||||||
|
KBUILD_CFLAGS += $(call cc-disable-warning, stringop-overflow)
|
||||||
|
|
||||||
|
# Another good warning that we'll want to enable eventually
|
||||||
|
KBUILD_CFLAGS += $(call cc-disable-warning, restrict)
|
||||||
|
|
||||||
|
# Enabled with W=2, disabled by default as noisy
|
||||||
|
KBUILD_CFLAGS += $(call cc-disable-warning, maybe-uninitialized)
|
||||||
|
|
||||||
# disable invalid "can't wrap" optimizations for signed / pointers
|
# disable invalid "can't wrap" optimizations for signed / pointers
|
||||||
KBUILD_CFLAGS += $(call cc-option,-fno-strict-overflow)
|
KBUILD_CFLAGS += $(call cc-option,-fno-strict-overflow)
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@ config ARM
|
||||||
select ARCH_HAS_KEEPINITRD
|
select ARCH_HAS_KEEPINITRD
|
||||||
select ARCH_HAS_KCOV
|
select ARCH_HAS_KCOV
|
||||||
select ARCH_HAS_MEMBARRIER_SYNC_CORE
|
select ARCH_HAS_MEMBARRIER_SYNC_CORE
|
||||||
|
select ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE
|
||||||
select ARCH_HAS_PTE_SPECIAL if ARM_LPAE
|
select ARCH_HAS_PTE_SPECIAL if ARM_LPAE
|
||||||
select ARCH_HAS_PHYS_TO_DMA
|
select ARCH_HAS_PHYS_TO_DMA
|
||||||
select ARCH_HAS_SETUP_DMA_OPS
|
select ARCH_HAS_SETUP_DMA_OPS
|
||||||
|
|
|
@ -147,6 +147,7 @@ CONFIG_I2C_DAVINCI=y
|
||||||
CONFIG_SPI=y
|
CONFIG_SPI=y
|
||||||
CONFIG_SPI_DAVINCI=y
|
CONFIG_SPI_DAVINCI=y
|
||||||
CONFIG_SPI_SPIDEV=y
|
CONFIG_SPI_SPIDEV=y
|
||||||
|
CONFIG_PTP_1588_CLOCK=y
|
||||||
CONFIG_PINCTRL_SINGLE=y
|
CONFIG_PINCTRL_SINGLE=y
|
||||||
CONFIG_GPIOLIB=y
|
CONFIG_GPIOLIB=y
|
||||||
CONFIG_GPIO_SYSFS=y
|
CONFIG_GPIO_SYSFS=y
|
||||||
|
|
|
@ -274,6 +274,7 @@ CONFIG_SPI_TI_QSPI=m
|
||||||
CONFIG_HSI=m
|
CONFIG_HSI=m
|
||||||
CONFIG_OMAP_SSI=m
|
CONFIG_OMAP_SSI=m
|
||||||
CONFIG_SSI_PROTOCOL=m
|
CONFIG_SSI_PROTOCOL=m
|
||||||
|
CONFIG_PTP_1588_CLOCK=y
|
||||||
CONFIG_PINCTRL_SINGLE=y
|
CONFIG_PINCTRL_SINGLE=y
|
||||||
CONFIG_DEBUG_GPIO=y
|
CONFIG_DEBUG_GPIO=y
|
||||||
CONFIG_GPIO_SYSFS=y
|
CONFIG_GPIO_SYSFS=y
|
||||||
|
|
|
@ -165,8 +165,13 @@ arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)
|
||||||
preempt_enable();
|
preempt_enable();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!ret)
|
/*
|
||||||
*oval = oldval;
|
* Store unconditionally. If ret != 0 the extra store is the least
|
||||||
|
* of the worries but GCC cannot figure out that __futex_atomic_op()
|
||||||
|
* is either setting ret to -EFAULT or storing the old value in
|
||||||
|
* oldval which results in a uninitialized warning at the call site.
|
||||||
|
*/
|
||||||
|
*oval = oldval;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ config ARM64
|
||||||
select ARCH_HAS_KCOV
|
select ARCH_HAS_KCOV
|
||||||
select ARCH_HAS_KEEPINITRD
|
select ARCH_HAS_KEEPINITRD
|
||||||
select ARCH_HAS_MEMBARRIER_SYNC_CORE
|
select ARCH_HAS_MEMBARRIER_SYNC_CORE
|
||||||
|
select ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE
|
||||||
select ARCH_HAS_PTE_DEVMAP
|
select ARCH_HAS_PTE_DEVMAP
|
||||||
select ARCH_HAS_PTE_SPECIAL
|
select ARCH_HAS_PTE_SPECIAL
|
||||||
select ARCH_HAS_SETUP_DMA_OPS
|
select ARCH_HAS_SETUP_DMA_OPS
|
||||||
|
|
|
@ -177,6 +177,7 @@ void machine_kexec(struct kimage *kimage)
|
||||||
* the offline CPUs. Therefore, we must use the __* variant here.
|
* the offline CPUs. Therefore, we must use the __* variant here.
|
||||||
*/
|
*/
|
||||||
__flush_icache_range((uintptr_t)reboot_code_buffer,
|
__flush_icache_range((uintptr_t)reboot_code_buffer,
|
||||||
|
(uintptr_t)reboot_code_buffer +
|
||||||
arm64_relocate_new_kernel_size);
|
arm64_relocate_new_kernel_size);
|
||||||
|
|
||||||
/* Flush the kimage list and its buffers. */
|
/* Flush the kimage list and its buffers. */
|
||||||
|
|
|
@ -200,6 +200,13 @@ static int set_core_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy((u32 *)regs + off, valp, KVM_REG_SIZE(reg->id));
|
memcpy((u32 *)regs + off, valp, KVM_REG_SIZE(reg->id));
|
||||||
|
|
||||||
|
if (*vcpu_cpsr(vcpu) & PSR_MODE32_BIT) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < 16; i++)
|
||||||
|
*vcpu_reg32(vcpu, i) = (u32)*vcpu_reg32(vcpu, i);
|
||||||
|
}
|
||||||
out:
|
out:
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
|
|
||||||
#define CPU_GP_REG_OFFSET(x) (CPU_GP_REGS + x)
|
#define CPU_GP_REG_OFFSET(x) (CPU_GP_REGS + x)
|
||||||
#define CPU_XREG_OFFSET(x) CPU_GP_REG_OFFSET(CPU_USER_PT_REGS + 8*x)
|
#define CPU_XREG_OFFSET(x) CPU_GP_REG_OFFSET(CPU_USER_PT_REGS + 8*x)
|
||||||
|
#define CPU_SP_EL0_OFFSET (CPU_XREG_OFFSET(30) + 8)
|
||||||
|
|
||||||
.text
|
.text
|
||||||
.pushsection .hyp.text, "ax"
|
.pushsection .hyp.text, "ax"
|
||||||
|
@ -47,6 +48,16 @@
|
||||||
ldp x29, lr, [\ctxt, #CPU_XREG_OFFSET(29)]
|
ldp x29, lr, [\ctxt, #CPU_XREG_OFFSET(29)]
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
|
.macro save_sp_el0 ctxt, tmp
|
||||||
|
mrs \tmp, sp_el0
|
||||||
|
str \tmp, [\ctxt, #CPU_SP_EL0_OFFSET]
|
||||||
|
.endm
|
||||||
|
|
||||||
|
.macro restore_sp_el0 ctxt, tmp
|
||||||
|
ldr \tmp, [\ctxt, #CPU_SP_EL0_OFFSET]
|
||||||
|
msr sp_el0, \tmp
|
||||||
|
.endm
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* u64 __guest_enter(struct kvm_vcpu *vcpu,
|
* u64 __guest_enter(struct kvm_vcpu *vcpu,
|
||||||
* struct kvm_cpu_context *host_ctxt);
|
* struct kvm_cpu_context *host_ctxt);
|
||||||
|
@ -60,6 +71,9 @@ SYM_FUNC_START(__guest_enter)
|
||||||
// Store the host regs
|
// Store the host regs
|
||||||
save_callee_saved_regs x1
|
save_callee_saved_regs x1
|
||||||
|
|
||||||
|
// Save the host's sp_el0
|
||||||
|
save_sp_el0 x1, x2
|
||||||
|
|
||||||
// Now the host state is stored if we have a pending RAS SError it must
|
// Now the host state is stored if we have a pending RAS SError it must
|
||||||
// affect the host. If any asynchronous exception is pending we defer
|
// affect the host. If any asynchronous exception is pending we defer
|
||||||
// the guest entry. The DSB isn't necessary before v8.2 as any SError
|
// the guest entry. The DSB isn't necessary before v8.2 as any SError
|
||||||
|
@ -83,6 +97,9 @@ alternative_else_nop_endif
|
||||||
// when this feature is enabled for kernel code.
|
// when this feature is enabled for kernel code.
|
||||||
ptrauth_switch_to_guest x29, x0, x1, x2
|
ptrauth_switch_to_guest x29, x0, x1, x2
|
||||||
|
|
||||||
|
// Restore the guest's sp_el0
|
||||||
|
restore_sp_el0 x29, x0
|
||||||
|
|
||||||
// Restore guest regs x0-x17
|
// Restore guest regs x0-x17
|
||||||
ldp x0, x1, [x29, #CPU_XREG_OFFSET(0)]
|
ldp x0, x1, [x29, #CPU_XREG_OFFSET(0)]
|
||||||
ldp x2, x3, [x29, #CPU_XREG_OFFSET(2)]
|
ldp x2, x3, [x29, #CPU_XREG_OFFSET(2)]
|
||||||
|
@ -130,6 +147,9 @@ SYM_INNER_LABEL(__guest_exit, SYM_L_GLOBAL)
|
||||||
// Store the guest regs x18-x29, lr
|
// Store the guest regs x18-x29, lr
|
||||||
save_callee_saved_regs x1
|
save_callee_saved_regs x1
|
||||||
|
|
||||||
|
// Store the guest's sp_el0
|
||||||
|
save_sp_el0 x1, x2
|
||||||
|
|
||||||
get_host_ctxt x2, x3
|
get_host_ctxt x2, x3
|
||||||
|
|
||||||
// Macro ptrauth_switch_to_guest format:
|
// Macro ptrauth_switch_to_guest format:
|
||||||
|
@ -139,6 +159,9 @@ SYM_INNER_LABEL(__guest_exit, SYM_L_GLOBAL)
|
||||||
// when this feature is enabled for kernel code.
|
// when this feature is enabled for kernel code.
|
||||||
ptrauth_switch_to_host x1, x2, x3, x4, x5
|
ptrauth_switch_to_host x1, x2, x3, x4, x5
|
||||||
|
|
||||||
|
// Restore the hosts's sp_el0
|
||||||
|
restore_sp_el0 x2, x3
|
||||||
|
|
||||||
// Now restore the host regs
|
// Now restore the host regs
|
||||||
restore_callee_saved_regs x2
|
restore_callee_saved_regs x2
|
||||||
|
|
||||||
|
|
|
@ -198,7 +198,6 @@ SYM_CODE_END(__hyp_panic)
|
||||||
.macro invalid_vector label, target = __hyp_panic
|
.macro invalid_vector label, target = __hyp_panic
|
||||||
.align 2
|
.align 2
|
||||||
SYM_CODE_START(\label)
|
SYM_CODE_START(\label)
|
||||||
\label:
|
|
||||||
b \target
|
b \target
|
||||||
SYM_CODE_END(\label)
|
SYM_CODE_END(\label)
|
||||||
.endm
|
.endm
|
||||||
|
|
|
@ -15,8 +15,9 @@
|
||||||
/*
|
/*
|
||||||
* Non-VHE: Both host and guest must save everything.
|
* Non-VHE: Both host and guest must save everything.
|
||||||
*
|
*
|
||||||
* VHE: Host and guest must save mdscr_el1 and sp_el0 (and the PC and pstate,
|
* VHE: Host and guest must save mdscr_el1 and sp_el0 (and the PC and
|
||||||
* which are handled as part of the el2 return state) on every switch.
|
* pstate, which are handled as part of the el2 return state) on every
|
||||||
|
* switch (sp_el0 is being dealt with in the assembly code).
|
||||||
* tpidr_el0 and tpidrro_el0 only need to be switched when going
|
* tpidr_el0 and tpidrro_el0 only need to be switched when going
|
||||||
* to host userspace or a different VCPU. EL1 registers only need to be
|
* to host userspace or a different VCPU. EL1 registers only need to be
|
||||||
* switched when potentially going to run a different VCPU. The latter two
|
* switched when potentially going to run a different VCPU. The latter two
|
||||||
|
@ -26,12 +27,6 @@
|
||||||
static void __hyp_text __sysreg_save_common_state(struct kvm_cpu_context *ctxt)
|
static void __hyp_text __sysreg_save_common_state(struct kvm_cpu_context *ctxt)
|
||||||
{
|
{
|
||||||
ctxt->sys_regs[MDSCR_EL1] = read_sysreg(mdscr_el1);
|
ctxt->sys_regs[MDSCR_EL1] = read_sysreg(mdscr_el1);
|
||||||
|
|
||||||
/*
|
|
||||||
* The host arm64 Linux uses sp_el0 to point to 'current' and it must
|
|
||||||
* therefore be saved/restored on every entry/exit to/from the guest.
|
|
||||||
*/
|
|
||||||
ctxt->gp_regs.regs.sp = read_sysreg(sp_el0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __hyp_text __sysreg_save_user_state(struct kvm_cpu_context *ctxt)
|
static void __hyp_text __sysreg_save_user_state(struct kvm_cpu_context *ctxt)
|
||||||
|
@ -99,12 +94,6 @@ NOKPROBE_SYMBOL(sysreg_save_guest_state_vhe);
|
||||||
static void __hyp_text __sysreg_restore_common_state(struct kvm_cpu_context *ctxt)
|
static void __hyp_text __sysreg_restore_common_state(struct kvm_cpu_context *ctxt)
|
||||||
{
|
{
|
||||||
write_sysreg(ctxt->sys_regs[MDSCR_EL1], mdscr_el1);
|
write_sysreg(ctxt->sys_regs[MDSCR_EL1], mdscr_el1);
|
||||||
|
|
||||||
/*
|
|
||||||
* The host arm64 Linux uses sp_el0 to point to 'current' and it must
|
|
||||||
* therefore be saved/restored on every entry/exit to/from the guest.
|
|
||||||
*/
|
|
||||||
write_sysreg(ctxt->gp_regs.regs.sp, sp_el0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __hyp_text __sysreg_restore_user_state(struct kvm_cpu_context *ctxt)
|
static void __hyp_text __sysreg_restore_user_state(struct kvm_cpu_context *ctxt)
|
||||||
|
|
|
@ -230,6 +230,8 @@ pte_t *huge_pte_alloc(struct mm_struct *mm,
|
||||||
ptep = (pte_t *)pudp;
|
ptep = (pte_t *)pudp;
|
||||||
} else if (sz == (CONT_PTE_SIZE)) {
|
} else if (sz == (CONT_PTE_SIZE)) {
|
||||||
pmdp = pmd_alloc(mm, pudp, addr);
|
pmdp = pmd_alloc(mm, pudp, addr);
|
||||||
|
if (!pmdp)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
WARN_ON(addr & (sz - 1));
|
WARN_ON(addr & (sz - 1));
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -521,6 +521,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
|
||||||
case KVM_CAP_IOEVENTFD:
|
case KVM_CAP_IOEVENTFD:
|
||||||
case KVM_CAP_DEVICE_CTRL:
|
case KVM_CAP_DEVICE_CTRL:
|
||||||
case KVM_CAP_IMMEDIATE_EXIT:
|
case KVM_CAP_IMMEDIATE_EXIT:
|
||||||
|
case KVM_CAP_SET_GUEST_DEBUG:
|
||||||
r = 1;
|
r = 1;
|
||||||
break;
|
break;
|
||||||
case KVM_CAP_PPC_GUEST_DEBUG_SSTEP:
|
case KVM_CAP_PPC_GUEST_DEBUG_SSTEP:
|
||||||
|
|
|
@ -54,7 +54,7 @@ config RISCV
|
||||||
select GENERIC_ARCH_TOPOLOGY if SMP
|
select GENERIC_ARCH_TOPOLOGY if SMP
|
||||||
select ARCH_HAS_PTE_SPECIAL
|
select ARCH_HAS_PTE_SPECIAL
|
||||||
select ARCH_HAS_MMIOWB
|
select ARCH_HAS_MMIOWB
|
||||||
select ARCH_HAS_DEBUG_VIRTUAL
|
select ARCH_HAS_DEBUG_VIRTUAL if MMU
|
||||||
select HAVE_EBPF_JIT if MMU
|
select HAVE_EBPF_JIT if MMU
|
||||||
select EDAC_SUPPORT
|
select EDAC_SUPPORT
|
||||||
select ARCH_HAS_GIGANTIC_PAGE
|
select ARCH_HAS_GIGANTIC_PAGE
|
||||||
|
@ -136,6 +136,7 @@ config ARCH_SUPPORTS_DEBUG_PAGEALLOC
|
||||||
def_bool y
|
def_bool y
|
||||||
|
|
||||||
config SYS_SUPPORTS_HUGETLBFS
|
config SYS_SUPPORTS_HUGETLBFS
|
||||||
|
depends on MMU
|
||||||
def_bool y
|
def_bool y
|
||||||
|
|
||||||
config STACKTRACE_SUPPORT
|
config STACKTRACE_SUPPORT
|
||||||
|
|
|
@ -11,14 +11,15 @@ config SOC_SIFIVE
|
||||||
This enables support for SiFive SoC platform hardware.
|
This enables support for SiFive SoC platform hardware.
|
||||||
|
|
||||||
config SOC_VIRT
|
config SOC_VIRT
|
||||||
bool "QEMU Virt Machine"
|
bool "QEMU Virt Machine"
|
||||||
select POWER_RESET_SYSCON
|
select POWER_RESET
|
||||||
select POWER_RESET_SYSCON_POWEROFF
|
select POWER_RESET_SYSCON
|
||||||
select GOLDFISH
|
select POWER_RESET_SYSCON_POWEROFF
|
||||||
select RTC_DRV_GOLDFISH
|
select GOLDFISH
|
||||||
select SIFIVE_PLIC
|
select RTC_DRV_GOLDFISH if RTC_CLASS
|
||||||
help
|
select SIFIVE_PLIC
|
||||||
This enables support for QEMU Virt Machine.
|
help
|
||||||
|
This enables support for QEMU Virt Machine.
|
||||||
|
|
||||||
config SOC_KENDRYTE
|
config SOC_KENDRYTE
|
||||||
bool "Kendryte K210 SoC"
|
bool "Kendryte K210 SoC"
|
||||||
|
|
|
@ -51,13 +51,10 @@
|
||||||
#define CAUSE_IRQ_FLAG (_AC(1, UL) << (__riscv_xlen - 1))
|
#define CAUSE_IRQ_FLAG (_AC(1, UL) << (__riscv_xlen - 1))
|
||||||
|
|
||||||
/* Interrupt causes (minus the high bit) */
|
/* Interrupt causes (minus the high bit) */
|
||||||
#define IRQ_U_SOFT 0
|
|
||||||
#define IRQ_S_SOFT 1
|
#define IRQ_S_SOFT 1
|
||||||
#define IRQ_M_SOFT 3
|
#define IRQ_M_SOFT 3
|
||||||
#define IRQ_U_TIMER 4
|
|
||||||
#define IRQ_S_TIMER 5
|
#define IRQ_S_TIMER 5
|
||||||
#define IRQ_M_TIMER 7
|
#define IRQ_M_TIMER 7
|
||||||
#define IRQ_U_EXT 8
|
|
||||||
#define IRQ_S_EXT 9
|
#define IRQ_S_EXT 9
|
||||||
#define IRQ_M_EXT 11
|
#define IRQ_M_EXT 11
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#ifndef _ASM_RISCV_HWCAP_H
|
#ifndef _ASM_RISCV_HWCAP_H
|
||||||
#define _ASM_RISCV_HWCAP_H
|
#define _ASM_RISCV_HWCAP_H
|
||||||
|
|
||||||
|
#include <linux/bits.h>
|
||||||
#include <uapi/asm/hwcap.h>
|
#include <uapi/asm/hwcap.h>
|
||||||
|
|
||||||
#ifndef __ASSEMBLY__
|
#ifndef __ASSEMBLY__
|
||||||
|
@ -22,6 +23,27 @@ enum {
|
||||||
};
|
};
|
||||||
|
|
||||||
extern unsigned long elf_hwcap;
|
extern unsigned long elf_hwcap;
|
||||||
|
|
||||||
|
#define RISCV_ISA_EXT_a ('a' - 'a')
|
||||||
|
#define RISCV_ISA_EXT_c ('c' - 'a')
|
||||||
|
#define RISCV_ISA_EXT_d ('d' - 'a')
|
||||||
|
#define RISCV_ISA_EXT_f ('f' - 'a')
|
||||||
|
#define RISCV_ISA_EXT_h ('h' - 'a')
|
||||||
|
#define RISCV_ISA_EXT_i ('i' - 'a')
|
||||||
|
#define RISCV_ISA_EXT_m ('m' - 'a')
|
||||||
|
#define RISCV_ISA_EXT_s ('s' - 'a')
|
||||||
|
#define RISCV_ISA_EXT_u ('u' - 'a')
|
||||||
|
|
||||||
|
#define RISCV_ISA_EXT_MAX 64
|
||||||
|
|
||||||
|
unsigned long riscv_isa_extension_base(const unsigned long *isa_bitmap);
|
||||||
|
|
||||||
|
#define riscv_isa_extension_mask(ext) BIT_MASK(RISCV_ISA_EXT_##ext)
|
||||||
|
|
||||||
|
bool __riscv_isa_extension_available(const unsigned long *isa_bitmap, int bit);
|
||||||
|
#define riscv_isa_extension_available(isa_bitmap, ext) \
|
||||||
|
__riscv_isa_extension_available(isa_bitmap, RISCV_ISA_EXT_##ext)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* _ASM_RISCV_HWCAP_H */
|
#endif /* _ASM_RISCV_HWCAP_H */
|
||||||
|
|
|
@ -16,6 +16,8 @@
|
||||||
|
|
||||||
#ifndef CONFIG_MMU
|
#ifndef CONFIG_MMU
|
||||||
#define pgprot_noncached(x) (x)
|
#define pgprot_noncached(x) (x)
|
||||||
|
#define pgprot_writecombine(x) (x)
|
||||||
|
#define pgprot_device(x) (x)
|
||||||
#endif /* CONFIG_MMU */
|
#endif /* CONFIG_MMU */
|
||||||
|
|
||||||
/* Generic IO read/write. These perform native-endian accesses. */
|
/* Generic IO read/write. These perform native-endian accesses. */
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
*/
|
*/
|
||||||
#define mmiowb() __asm__ __volatile__ ("fence o,w" : : : "memory");
|
#define mmiowb() __asm__ __volatile__ ("fence o,w" : : : "memory");
|
||||||
|
|
||||||
|
#include <linux/smp.h>
|
||||||
#include <asm-generic/mmiowb.h>
|
#include <asm-generic/mmiowb.h>
|
||||||
|
|
||||||
#endif /* _ASM_RISCV_MMIOWB_H */
|
#endif /* _ASM_RISCV_MMIOWB_H */
|
||||||
|
|
|
@ -12,19 +12,14 @@
|
||||||
#include <linux/ptrace.h>
|
#include <linux/ptrace.h>
|
||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
|
|
||||||
|
#ifdef CONFIG_RISCV_BASE_PMU
|
||||||
#define RISCV_BASE_COUNTERS 2
|
#define RISCV_BASE_COUNTERS 2
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The RISCV_MAX_COUNTERS parameter should be specified.
|
* The RISCV_MAX_COUNTERS parameter should be specified.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef CONFIG_RISCV_BASE_PMU
|
|
||||||
#define RISCV_MAX_COUNTERS 2
|
#define RISCV_MAX_COUNTERS 2
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef RISCV_MAX_COUNTERS
|
|
||||||
#error "Please provide a valid RISCV_MAX_COUNTERS for the PMU."
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* These are the indexes of bits in counteren register *minus* 1,
|
* These are the indexes of bits in counteren register *minus* 1,
|
||||||
|
@ -82,6 +77,7 @@ struct riscv_pmu {
|
||||||
int irq;
|
int irq;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
#ifdef CONFIG_PERF_EVENTS
|
#ifdef CONFIG_PERF_EVENTS
|
||||||
#define perf_arch_bpf_user_pt_regs(regs) (struct user_regs_struct *)regs
|
#define perf_arch_bpf_user_pt_regs(regs) (struct user_regs_struct *)regs
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -470,12 +470,15 @@ static inline int ptep_clear_flush_young(struct vm_area_struct *vma,
|
||||||
|
|
||||||
#else /* CONFIG_MMU */
|
#else /* CONFIG_MMU */
|
||||||
|
|
||||||
|
#define PAGE_SHARED __pgprot(0)
|
||||||
#define PAGE_KERNEL __pgprot(0)
|
#define PAGE_KERNEL __pgprot(0)
|
||||||
#define swapper_pg_dir NULL
|
#define swapper_pg_dir NULL
|
||||||
#define VMALLOC_START 0
|
#define VMALLOC_START 0
|
||||||
|
|
||||||
#define TASK_SIZE 0xffffffffUL
|
#define TASK_SIZE 0xffffffffUL
|
||||||
|
|
||||||
|
static inline void __kernel_map_pages(struct page *page, int numpages, int enable) {}
|
||||||
|
|
||||||
#endif /* !CONFIG_MMU */
|
#endif /* !CONFIG_MMU */
|
||||||
|
|
||||||
#define kern_addr_valid(addr) (1) /* FIXME */
|
#define kern_addr_valid(addr) (1) /* FIXME */
|
||||||
|
|
|
@ -22,14 +22,6 @@ static inline int set_memory_x(unsigned long addr, int numpages) { return 0; }
|
||||||
static inline int set_memory_nx(unsigned long addr, int numpages) { return 0; }
|
static inline int set_memory_nx(unsigned long addr, int numpages) { return 0; }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_STRICT_KERNEL_RWX
|
|
||||||
void set_kernel_text_ro(void);
|
|
||||||
void set_kernel_text_rw(void);
|
|
||||||
#else
|
|
||||||
static inline void set_kernel_text_ro(void) { }
|
|
||||||
static inline void set_kernel_text_rw(void) { }
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int set_direct_map_invalid_noflush(struct page *page);
|
int set_direct_map_invalid_noflush(struct page *page);
|
||||||
int set_direct_map_default_noflush(struct page *page);
|
int set_direct_map_default_noflush(struct page *page);
|
||||||
|
|
||||||
|
|
|
@ -43,7 +43,7 @@ obj-$(CONFIG_MODULE_SECTIONS) += module-sections.o
|
||||||
obj-$(CONFIG_FUNCTION_TRACER) += mcount.o ftrace.o
|
obj-$(CONFIG_FUNCTION_TRACER) += mcount.o ftrace.o
|
||||||
obj-$(CONFIG_DYNAMIC_FTRACE) += mcount-dyn.o
|
obj-$(CONFIG_DYNAMIC_FTRACE) += mcount-dyn.o
|
||||||
|
|
||||||
obj-$(CONFIG_PERF_EVENTS) += perf_event.o
|
obj-$(CONFIG_RISCV_BASE_PMU) += perf_event.o
|
||||||
obj-$(CONFIG_PERF_EVENTS) += perf_callchain.o
|
obj-$(CONFIG_PERF_EVENTS) += perf_callchain.o
|
||||||
obj-$(CONFIG_HAVE_PERF_REGS) += perf_regs.o
|
obj-$(CONFIG_HAVE_PERF_REGS) += perf_regs.o
|
||||||
obj-$(CONFIG_RISCV_SBI) += sbi.o
|
obj-$(CONFIG_RISCV_SBI) += sbi.o
|
||||||
|
|
|
@ -15,8 +15,8 @@
|
||||||
|
|
||||||
const struct cpu_operations *cpu_ops[NR_CPUS] __ro_after_init;
|
const struct cpu_operations *cpu_ops[NR_CPUS] __ro_after_init;
|
||||||
|
|
||||||
void *__cpu_up_stack_pointer[NR_CPUS];
|
void *__cpu_up_stack_pointer[NR_CPUS] __section(.data);
|
||||||
void *__cpu_up_task_pointer[NR_CPUS];
|
void *__cpu_up_task_pointer[NR_CPUS] __section(.data);
|
||||||
|
|
||||||
extern const struct cpu_operations cpu_ops_sbi;
|
extern const struct cpu_operations cpu_ops_sbi;
|
||||||
extern const struct cpu_operations cpu_ops_spinwait;
|
extern const struct cpu_operations cpu_ops_spinwait;
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
* Copyright (C) 2017 SiFive
|
* Copyright (C) 2017 SiFive
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <linux/bitmap.h>
|
||||||
#include <linux/of.h>
|
#include <linux/of.h>
|
||||||
#include <asm/processor.h>
|
#include <asm/processor.h>
|
||||||
#include <asm/hwcap.h>
|
#include <asm/hwcap.h>
|
||||||
|
@ -13,15 +14,57 @@
|
||||||
#include <asm/switch_to.h>
|
#include <asm/switch_to.h>
|
||||||
|
|
||||||
unsigned long elf_hwcap __read_mostly;
|
unsigned long elf_hwcap __read_mostly;
|
||||||
|
|
||||||
|
/* Host ISA bitmap */
|
||||||
|
static DECLARE_BITMAP(riscv_isa, RISCV_ISA_EXT_MAX) __read_mostly;
|
||||||
|
|
||||||
#ifdef CONFIG_FPU
|
#ifdef CONFIG_FPU
|
||||||
bool has_fpu __read_mostly;
|
bool has_fpu __read_mostly;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* riscv_isa_extension_base() - Get base extension word
|
||||||
|
*
|
||||||
|
* @isa_bitmap: ISA bitmap to use
|
||||||
|
* Return: base extension word as unsigned long value
|
||||||
|
*
|
||||||
|
* NOTE: If isa_bitmap is NULL then Host ISA bitmap will be used.
|
||||||
|
*/
|
||||||
|
unsigned long riscv_isa_extension_base(const unsigned long *isa_bitmap)
|
||||||
|
{
|
||||||
|
if (!isa_bitmap)
|
||||||
|
return riscv_isa[0];
|
||||||
|
return isa_bitmap[0];
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(riscv_isa_extension_base);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* __riscv_isa_extension_available() - Check whether given extension
|
||||||
|
* is available or not
|
||||||
|
*
|
||||||
|
* @isa_bitmap: ISA bitmap to use
|
||||||
|
* @bit: bit position of the desired extension
|
||||||
|
* Return: true or false
|
||||||
|
*
|
||||||
|
* NOTE: If isa_bitmap is NULL then Host ISA bitmap will be used.
|
||||||
|
*/
|
||||||
|
bool __riscv_isa_extension_available(const unsigned long *isa_bitmap, int bit)
|
||||||
|
{
|
||||||
|
const unsigned long *bmap = (isa_bitmap) ? isa_bitmap : riscv_isa;
|
||||||
|
|
||||||
|
if (bit >= RISCV_ISA_EXT_MAX)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return test_bit(bit, bmap) ? true : false;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(__riscv_isa_extension_available);
|
||||||
|
|
||||||
void riscv_fill_hwcap(void)
|
void riscv_fill_hwcap(void)
|
||||||
{
|
{
|
||||||
struct device_node *node;
|
struct device_node *node;
|
||||||
const char *isa;
|
const char *isa;
|
||||||
size_t i;
|
char print_str[BITS_PER_LONG + 1];
|
||||||
|
size_t i, j, isa_len;
|
||||||
static unsigned long isa2hwcap[256] = {0};
|
static unsigned long isa2hwcap[256] = {0};
|
||||||
|
|
||||||
isa2hwcap['i'] = isa2hwcap['I'] = COMPAT_HWCAP_ISA_I;
|
isa2hwcap['i'] = isa2hwcap['I'] = COMPAT_HWCAP_ISA_I;
|
||||||
|
@ -33,8 +76,11 @@ void riscv_fill_hwcap(void)
|
||||||
|
|
||||||
elf_hwcap = 0;
|
elf_hwcap = 0;
|
||||||
|
|
||||||
|
bitmap_zero(riscv_isa, RISCV_ISA_EXT_MAX);
|
||||||
|
|
||||||
for_each_of_cpu_node(node) {
|
for_each_of_cpu_node(node) {
|
||||||
unsigned long this_hwcap = 0;
|
unsigned long this_hwcap = 0;
|
||||||
|
unsigned long this_isa = 0;
|
||||||
|
|
||||||
if (riscv_of_processor_hartid(node) < 0)
|
if (riscv_of_processor_hartid(node) < 0)
|
||||||
continue;
|
continue;
|
||||||
|
@ -44,8 +90,24 @@ void riscv_fill_hwcap(void)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < strlen(isa); ++i)
|
i = 0;
|
||||||
|
isa_len = strlen(isa);
|
||||||
|
#if IS_ENABLED(CONFIG_32BIT)
|
||||||
|
if (!strncmp(isa, "rv32", 4))
|
||||||
|
i += 4;
|
||||||
|
#elif IS_ENABLED(CONFIG_64BIT)
|
||||||
|
if (!strncmp(isa, "rv64", 4))
|
||||||
|
i += 4;
|
||||||
|
#endif
|
||||||
|
for (; i < isa_len; ++i) {
|
||||||
this_hwcap |= isa2hwcap[(unsigned char)(isa[i])];
|
this_hwcap |= isa2hwcap[(unsigned char)(isa[i])];
|
||||||
|
/*
|
||||||
|
* TODO: X, Y and Z extension parsing for Host ISA
|
||||||
|
* bitmap will be added in-future.
|
||||||
|
*/
|
||||||
|
if ('a' <= isa[i] && isa[i] < 'x')
|
||||||
|
this_isa |= (1UL << (isa[i] - 'a'));
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* All "okay" hart should have same isa. Set HWCAP based on
|
* All "okay" hart should have same isa. Set HWCAP based on
|
||||||
|
@ -56,6 +118,11 @@ void riscv_fill_hwcap(void)
|
||||||
elf_hwcap &= this_hwcap;
|
elf_hwcap &= this_hwcap;
|
||||||
else
|
else
|
||||||
elf_hwcap = this_hwcap;
|
elf_hwcap = this_hwcap;
|
||||||
|
|
||||||
|
if (riscv_isa[0])
|
||||||
|
riscv_isa[0] &= this_isa;
|
||||||
|
else
|
||||||
|
riscv_isa[0] = this_isa;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We don't support systems with F but without D, so mask those out
|
/* We don't support systems with F but without D, so mask those out
|
||||||
|
@ -65,7 +132,17 @@ void riscv_fill_hwcap(void)
|
||||||
elf_hwcap &= ~COMPAT_HWCAP_ISA_F;
|
elf_hwcap &= ~COMPAT_HWCAP_ISA_F;
|
||||||
}
|
}
|
||||||
|
|
||||||
pr_info("elf_hwcap is 0x%lx\n", elf_hwcap);
|
memset(print_str, 0, sizeof(print_str));
|
||||||
|
for (i = 0, j = 0; i < BITS_PER_LONG; i++)
|
||||||
|
if (riscv_isa[0] & BIT_MASK(i))
|
||||||
|
print_str[j++] = (char)('a' + i);
|
||||||
|
pr_info("riscv: ISA extensions %s\n", print_str);
|
||||||
|
|
||||||
|
memset(print_str, 0, sizeof(print_str));
|
||||||
|
for (i = 0, j = 0; i < BITS_PER_LONG; i++)
|
||||||
|
if (elf_hwcap & BIT_MASK(i))
|
||||||
|
print_str[j++] = (char)('a' + i);
|
||||||
|
pr_info("riscv: ELF capabilities %s\n", print_str);
|
||||||
|
|
||||||
#ifdef CONFIG_FPU
|
#ifdef CONFIG_FPU
|
||||||
if (elf_hwcap & (COMPAT_HWCAP_ISA_F | COMPAT_HWCAP_ISA_D))
|
if (elf_hwcap & (COMPAT_HWCAP_ISA_F | COMPAT_HWCAP_ISA_D))
|
||||||
|
|
|
@ -147,7 +147,7 @@ static int riscv_map_hw_event(u64 config)
|
||||||
return riscv_pmu->hw_events[config];
|
return riscv_pmu->hw_events[config];
|
||||||
}
|
}
|
||||||
|
|
||||||
int riscv_map_cache_decode(u64 config, unsigned int *type,
|
static int riscv_map_cache_decode(u64 config, unsigned int *type,
|
||||||
unsigned int *op, unsigned int *result)
|
unsigned int *op, unsigned int *result)
|
||||||
{
|
{
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
@ -342,7 +342,7 @@ static void riscv_pmu_del(struct perf_event *event, int flags)
|
||||||
|
|
||||||
static DEFINE_MUTEX(pmc_reserve_mutex);
|
static DEFINE_MUTEX(pmc_reserve_mutex);
|
||||||
|
|
||||||
irqreturn_t riscv_base_pmu_handle_irq(int irq_num, void *dev)
|
static irqreturn_t riscv_base_pmu_handle_irq(int irq_num, void *dev)
|
||||||
{
|
{
|
||||||
return IRQ_NONE;
|
return IRQ_NONE;
|
||||||
}
|
}
|
||||||
|
@ -361,7 +361,7 @@ static int reserve_pmc_hardware(void)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
void release_pmc_hardware(void)
|
static void release_pmc_hardware(void)
|
||||||
{
|
{
|
||||||
mutex_lock(&pmc_reserve_mutex);
|
mutex_lock(&pmc_reserve_mutex);
|
||||||
if (riscv_pmu->irq >= 0)
|
if (riscv_pmu->irq >= 0)
|
||||||
|
@ -464,7 +464,7 @@ static const struct of_device_id riscv_pmu_of_ids[] = {
|
||||||
{ /* sentinel value */ }
|
{ /* sentinel value */ }
|
||||||
};
|
};
|
||||||
|
|
||||||
int __init init_hw_perf_events(void)
|
static int __init init_hw_perf_events(void)
|
||||||
{
|
{
|
||||||
struct device_node *node = of_find_node_by_type(NULL, "pmu");
|
struct device_node *node = of_find_node_by_type(NULL, "pmu");
|
||||||
const struct of_device_id *of_id;
|
const struct of_device_id *of_id;
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
|
|
||||||
#include <linux/cpu.h>
|
#include <linux/cpu.h>
|
||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
|
#include <linux/module.h>
|
||||||
#include <linux/profile.h>
|
#include <linux/profile.h>
|
||||||
#include <linux/smp.h>
|
#include <linux/smp.h>
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
|
@ -63,6 +64,7 @@ void riscv_cpuid_to_hartid_mask(const struct cpumask *in, struct cpumask *out)
|
||||||
for_each_cpu(cpu, in)
|
for_each_cpu(cpu, in)
|
||||||
cpumask_set_cpu(cpuid_to_hartid_map(cpu), out);
|
cpumask_set_cpu(cpuid_to_hartid_map(cpu), out);
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(riscv_cpuid_to_hartid_mask);
|
||||||
|
|
||||||
bool arch_match_cpu_phys_id(int cpu, u64 phys_id)
|
bool arch_match_cpu_phys_id(int cpu, u64 phys_id)
|
||||||
{
|
{
|
||||||
|
|
|
@ -65,7 +65,7 @@ void notrace walk_stackframe(struct task_struct *task, struct pt_regs *regs,
|
||||||
|
|
||||||
#else /* !CONFIG_FRAME_POINTER */
|
#else /* !CONFIG_FRAME_POINTER */
|
||||||
|
|
||||||
static void notrace walk_stackframe(struct task_struct *task,
|
void notrace walk_stackframe(struct task_struct *task,
|
||||||
struct pt_regs *regs, bool (*fn)(unsigned long, void *), void *arg)
|
struct pt_regs *regs, bool (*fn)(unsigned long, void *), void *arg)
|
||||||
{
|
{
|
||||||
unsigned long sp, pc;
|
unsigned long sp, pc;
|
||||||
|
|
|
@ -12,7 +12,7 @@ vdso-syms += getcpu
|
||||||
vdso-syms += flush_icache
|
vdso-syms += flush_icache
|
||||||
|
|
||||||
# Files to link into the vdso
|
# Files to link into the vdso
|
||||||
obj-vdso = $(patsubst %, %.o, $(vdso-syms))
|
obj-vdso = $(patsubst %, %.o, $(vdso-syms)) note.o
|
||||||
|
|
||||||
# Build rules
|
# Build rules
|
||||||
targets := $(obj-vdso) vdso.so vdso.so.dbg vdso.lds vdso-dummy.o
|
targets := $(obj-vdso) vdso.so vdso.so.dbg vdso.lds vdso-dummy.o
|
||||||
|
|
12
arch/riscv/kernel/vdso/note.S
Normal file
12
arch/riscv/kernel/vdso/note.S
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||||
|
/*
|
||||||
|
* This supplies .note.* sections to go into the PT_NOTE inside the vDSO text.
|
||||||
|
* Here we can supply some information useful to userland.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/elfnote.h>
|
||||||
|
#include <linux/version.h>
|
||||||
|
|
||||||
|
ELFNOTE_START(Linux, 0, "a")
|
||||||
|
.long LINUX_VERSION_CODE
|
||||||
|
ELFNOTE_END
|
|
@ -150,7 +150,8 @@ void __init setup_bootmem(void)
|
||||||
memblock_reserve(vmlinux_start, vmlinux_end - vmlinux_start);
|
memblock_reserve(vmlinux_start, vmlinux_end - vmlinux_start);
|
||||||
|
|
||||||
set_max_mapnr(PFN_DOWN(mem_size));
|
set_max_mapnr(PFN_DOWN(mem_size));
|
||||||
max_low_pfn = PFN_DOWN(memblock_end_of_DRAM());
|
max_pfn = PFN_DOWN(memblock_end_of_DRAM());
|
||||||
|
max_low_pfn = max_pfn;
|
||||||
|
|
||||||
#ifdef CONFIG_BLK_DEV_INITRD
|
#ifdef CONFIG_BLK_DEV_INITRD
|
||||||
setup_initrd();
|
setup_initrd();
|
||||||
|
@ -501,22 +502,6 @@ static inline void setup_vm_final(void)
|
||||||
#endif /* CONFIG_MMU */
|
#endif /* CONFIG_MMU */
|
||||||
|
|
||||||
#ifdef CONFIG_STRICT_KERNEL_RWX
|
#ifdef CONFIG_STRICT_KERNEL_RWX
|
||||||
void set_kernel_text_rw(void)
|
|
||||||
{
|
|
||||||
unsigned long text_start = (unsigned long)_text;
|
|
||||||
unsigned long text_end = (unsigned long)_etext;
|
|
||||||
|
|
||||||
set_memory_rw(text_start, (text_end - text_start) >> PAGE_SHIFT);
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_kernel_text_ro(void)
|
|
||||||
{
|
|
||||||
unsigned long text_start = (unsigned long)_text;
|
|
||||||
unsigned long text_end = (unsigned long)_etext;
|
|
||||||
|
|
||||||
set_memory_ro(text_start, (text_end - text_start) >> PAGE_SHIFT);
|
|
||||||
}
|
|
||||||
|
|
||||||
void mark_rodata_ro(void)
|
void mark_rodata_ro(void)
|
||||||
{
|
{
|
||||||
unsigned long text_start = (unsigned long)_text;
|
unsigned long text_start = (unsigned long)_text;
|
||||||
|
|
|
@ -545,6 +545,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
|
||||||
case KVM_CAP_S390_AIS:
|
case KVM_CAP_S390_AIS:
|
||||||
case KVM_CAP_S390_AIS_MIGRATION:
|
case KVM_CAP_S390_AIS_MIGRATION:
|
||||||
case KVM_CAP_S390_VCPU_RESETS:
|
case KVM_CAP_S390_VCPU_RESETS:
|
||||||
|
case KVM_CAP_SET_GUEST_DEBUG:
|
||||||
r = 1;
|
r = 1;
|
||||||
break;
|
break;
|
||||||
case KVM_CAP_S390_HPAGE_1M:
|
case KVM_CAP_S390_HPAGE_1M:
|
||||||
|
|
|
@ -626,10 +626,12 @@ static int handle_pqap(struct kvm_vcpu *vcpu)
|
||||||
* available for the guest are AQIC and TAPQ with the t bit set
|
* available for the guest are AQIC and TAPQ with the t bit set
|
||||||
* since we do not set IC.3 (FIII) we currently will only intercept
|
* since we do not set IC.3 (FIII) we currently will only intercept
|
||||||
* the AQIC function code.
|
* the AQIC function code.
|
||||||
|
* Note: running nested under z/VM can result in intercepts for other
|
||||||
|
* function codes, e.g. PQAP(QCI). We do not support this and bail out.
|
||||||
*/
|
*/
|
||||||
reg0 = vcpu->run->s.regs.gprs[0];
|
reg0 = vcpu->run->s.regs.gprs[0];
|
||||||
fc = (reg0 >> 24) & 0xff;
|
fc = (reg0 >> 24) & 0xff;
|
||||||
if (WARN_ON_ONCE(fc != 0x03))
|
if (fc != 0x03)
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
/* PQAP instruction is allowed for guest kernel only */
|
/* PQAP instruction is allowed for guest kernel only */
|
||||||
|
|
|
@ -68,6 +68,7 @@ config X86
|
||||||
select ARCH_HAS_KCOV if X86_64
|
select ARCH_HAS_KCOV if X86_64
|
||||||
select ARCH_HAS_MEM_ENCRYPT
|
select ARCH_HAS_MEM_ENCRYPT
|
||||||
select ARCH_HAS_MEMBARRIER_SYNC_CORE
|
select ARCH_HAS_MEMBARRIER_SYNC_CORE
|
||||||
|
select ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE
|
||||||
select ARCH_HAS_PMEM_API if X86_64
|
select ARCH_HAS_PMEM_API if X86_64
|
||||||
select ARCH_HAS_PTE_DEVMAP if X86_64
|
select ARCH_HAS_PTE_DEVMAP if X86_64
|
||||||
select ARCH_HAS_PTE_SPECIAL
|
select ARCH_HAS_PTE_SPECIAL
|
||||||
|
|
|
@ -98,13 +98,6 @@ For 32-bit we have the following conventions - kernel is built with
|
||||||
#define SIZEOF_PTREGS 21*8
|
#define SIZEOF_PTREGS 21*8
|
||||||
|
|
||||||
.macro PUSH_AND_CLEAR_REGS rdx=%rdx rax=%rax save_ret=0
|
.macro PUSH_AND_CLEAR_REGS rdx=%rdx rax=%rax save_ret=0
|
||||||
/*
|
|
||||||
* Push registers and sanitize registers of values that a
|
|
||||||
* speculation attack might otherwise want to exploit. The
|
|
||||||
* lower registers are likely clobbered well before they
|
|
||||||
* could be put to use in a speculative execution gadget.
|
|
||||||
* Interleave XOR with PUSH for better uop scheduling:
|
|
||||||
*/
|
|
||||||
.if \save_ret
|
.if \save_ret
|
||||||
pushq %rsi /* pt_regs->si */
|
pushq %rsi /* pt_regs->si */
|
||||||
movq 8(%rsp), %rsi /* temporarily store the return address in %rsi */
|
movq 8(%rsp), %rsi /* temporarily store the return address in %rsi */
|
||||||
|
@ -114,34 +107,43 @@ For 32-bit we have the following conventions - kernel is built with
|
||||||
pushq %rsi /* pt_regs->si */
|
pushq %rsi /* pt_regs->si */
|
||||||
.endif
|
.endif
|
||||||
pushq \rdx /* pt_regs->dx */
|
pushq \rdx /* pt_regs->dx */
|
||||||
xorl %edx, %edx /* nospec dx */
|
|
||||||
pushq %rcx /* pt_regs->cx */
|
pushq %rcx /* pt_regs->cx */
|
||||||
xorl %ecx, %ecx /* nospec cx */
|
|
||||||
pushq \rax /* pt_regs->ax */
|
pushq \rax /* pt_regs->ax */
|
||||||
pushq %r8 /* pt_regs->r8 */
|
pushq %r8 /* pt_regs->r8 */
|
||||||
xorl %r8d, %r8d /* nospec r8 */
|
|
||||||
pushq %r9 /* pt_regs->r9 */
|
pushq %r9 /* pt_regs->r9 */
|
||||||
xorl %r9d, %r9d /* nospec r9 */
|
|
||||||
pushq %r10 /* pt_regs->r10 */
|
pushq %r10 /* pt_regs->r10 */
|
||||||
xorl %r10d, %r10d /* nospec r10 */
|
|
||||||
pushq %r11 /* pt_regs->r11 */
|
pushq %r11 /* pt_regs->r11 */
|
||||||
xorl %r11d, %r11d /* nospec r11*/
|
|
||||||
pushq %rbx /* pt_regs->rbx */
|
pushq %rbx /* pt_regs->rbx */
|
||||||
xorl %ebx, %ebx /* nospec rbx*/
|
|
||||||
pushq %rbp /* pt_regs->rbp */
|
pushq %rbp /* pt_regs->rbp */
|
||||||
xorl %ebp, %ebp /* nospec rbp*/
|
|
||||||
pushq %r12 /* pt_regs->r12 */
|
pushq %r12 /* pt_regs->r12 */
|
||||||
xorl %r12d, %r12d /* nospec r12*/
|
|
||||||
pushq %r13 /* pt_regs->r13 */
|
pushq %r13 /* pt_regs->r13 */
|
||||||
xorl %r13d, %r13d /* nospec r13*/
|
|
||||||
pushq %r14 /* pt_regs->r14 */
|
pushq %r14 /* pt_regs->r14 */
|
||||||
xorl %r14d, %r14d /* nospec r14*/
|
|
||||||
pushq %r15 /* pt_regs->r15 */
|
pushq %r15 /* pt_regs->r15 */
|
||||||
xorl %r15d, %r15d /* nospec r15*/
|
|
||||||
UNWIND_HINT_REGS
|
UNWIND_HINT_REGS
|
||||||
|
|
||||||
.if \save_ret
|
.if \save_ret
|
||||||
pushq %rsi /* return address on top of stack */
|
pushq %rsi /* return address on top of stack */
|
||||||
.endif
|
.endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sanitize registers of values that a speculation attack might
|
||||||
|
* otherwise want to exploit. The lower registers are likely clobbered
|
||||||
|
* well before they could be put to use in a speculative execution
|
||||||
|
* gadget.
|
||||||
|
*/
|
||||||
|
xorl %edx, %edx /* nospec dx */
|
||||||
|
xorl %ecx, %ecx /* nospec cx */
|
||||||
|
xorl %r8d, %r8d /* nospec r8 */
|
||||||
|
xorl %r9d, %r9d /* nospec r9 */
|
||||||
|
xorl %r10d, %r10d /* nospec r10 */
|
||||||
|
xorl %r11d, %r11d /* nospec r11 */
|
||||||
|
xorl %ebx, %ebx /* nospec rbx */
|
||||||
|
xorl %ebp, %ebp /* nospec rbp */
|
||||||
|
xorl %r12d, %r12d /* nospec r12 */
|
||||||
|
xorl %r13d, %r13d /* nospec r13 */
|
||||||
|
xorl %r14d, %r14d /* nospec r14 */
|
||||||
|
xorl %r15d, %r15d /* nospec r15 */
|
||||||
|
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
.macro POP_REGS pop_rdi=1 skip_r11rcx=0
|
.macro POP_REGS pop_rdi=1 skip_r11rcx=0
|
||||||
|
|
|
@ -249,7 +249,6 @@ SYM_INNER_LABEL(entry_SYSCALL_64_after_hwframe, SYM_L_GLOBAL)
|
||||||
*/
|
*/
|
||||||
syscall_return_via_sysret:
|
syscall_return_via_sysret:
|
||||||
/* rcx and r11 are already restored (see code above) */
|
/* rcx and r11 are already restored (see code above) */
|
||||||
UNWIND_HINT_EMPTY
|
|
||||||
POP_REGS pop_rdi=0 skip_r11rcx=1
|
POP_REGS pop_rdi=0 skip_r11rcx=1
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -258,6 +257,7 @@ syscall_return_via_sysret:
|
||||||
*/
|
*/
|
||||||
movq %rsp, %rdi
|
movq %rsp, %rdi
|
||||||
movq PER_CPU_VAR(cpu_tss_rw + TSS_sp0), %rsp
|
movq PER_CPU_VAR(cpu_tss_rw + TSS_sp0), %rsp
|
||||||
|
UNWIND_HINT_EMPTY
|
||||||
|
|
||||||
pushq RSP-RDI(%rdi) /* RSP */
|
pushq RSP-RDI(%rdi) /* RSP */
|
||||||
pushq (%rdi) /* RDI */
|
pushq (%rdi) /* RDI */
|
||||||
|
@ -279,8 +279,7 @@ SYM_CODE_END(entry_SYSCALL_64)
|
||||||
* %rdi: prev task
|
* %rdi: prev task
|
||||||
* %rsi: next task
|
* %rsi: next task
|
||||||
*/
|
*/
|
||||||
SYM_CODE_START(__switch_to_asm)
|
SYM_FUNC_START(__switch_to_asm)
|
||||||
UNWIND_HINT_FUNC
|
|
||||||
/*
|
/*
|
||||||
* Save callee-saved registers
|
* Save callee-saved registers
|
||||||
* This must match the order in inactive_task_frame
|
* This must match the order in inactive_task_frame
|
||||||
|
@ -321,7 +320,7 @@ SYM_CODE_START(__switch_to_asm)
|
||||||
popq %rbp
|
popq %rbp
|
||||||
|
|
||||||
jmp __switch_to
|
jmp __switch_to
|
||||||
SYM_CODE_END(__switch_to_asm)
|
SYM_FUNC_END(__switch_to_asm)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A newly forked process directly context switches into this address.
|
* A newly forked process directly context switches into this address.
|
||||||
|
@ -512,7 +511,7 @@ SYM_CODE_END(spurious_entries_start)
|
||||||
* +----------------------------------------------------+
|
* +----------------------------------------------------+
|
||||||
*/
|
*/
|
||||||
SYM_CODE_START(interrupt_entry)
|
SYM_CODE_START(interrupt_entry)
|
||||||
UNWIND_HINT_FUNC
|
UNWIND_HINT_IRET_REGS offset=16
|
||||||
ASM_CLAC
|
ASM_CLAC
|
||||||
cld
|
cld
|
||||||
|
|
||||||
|
@ -544,9 +543,9 @@ SYM_CODE_START(interrupt_entry)
|
||||||
pushq 5*8(%rdi) /* regs->eflags */
|
pushq 5*8(%rdi) /* regs->eflags */
|
||||||
pushq 4*8(%rdi) /* regs->cs */
|
pushq 4*8(%rdi) /* regs->cs */
|
||||||
pushq 3*8(%rdi) /* regs->ip */
|
pushq 3*8(%rdi) /* regs->ip */
|
||||||
|
UNWIND_HINT_IRET_REGS
|
||||||
pushq 2*8(%rdi) /* regs->orig_ax */
|
pushq 2*8(%rdi) /* regs->orig_ax */
|
||||||
pushq 8(%rdi) /* return address */
|
pushq 8(%rdi) /* return address */
|
||||||
UNWIND_HINT_FUNC
|
|
||||||
|
|
||||||
movq (%rdi), %rdi
|
movq (%rdi), %rdi
|
||||||
jmp 2f
|
jmp 2f
|
||||||
|
@ -637,6 +636,7 @@ SYM_INNER_LABEL(swapgs_restore_regs_and_return_to_usermode, SYM_L_GLOBAL)
|
||||||
*/
|
*/
|
||||||
movq %rsp, %rdi
|
movq %rsp, %rdi
|
||||||
movq PER_CPU_VAR(cpu_tss_rw + TSS_sp0), %rsp
|
movq PER_CPU_VAR(cpu_tss_rw + TSS_sp0), %rsp
|
||||||
|
UNWIND_HINT_EMPTY
|
||||||
|
|
||||||
/* Copy the IRET frame to the trampoline stack. */
|
/* Copy the IRET frame to the trampoline stack. */
|
||||||
pushq 6*8(%rdi) /* SS */
|
pushq 6*8(%rdi) /* SS */
|
||||||
|
@ -1739,7 +1739,7 @@ SYM_CODE_START(rewind_stack_do_exit)
|
||||||
|
|
||||||
movq PER_CPU_VAR(cpu_current_top_of_stack), %rax
|
movq PER_CPU_VAR(cpu_current_top_of_stack), %rax
|
||||||
leaq -PTREGS_SIZE(%rax), %rsp
|
leaq -PTREGS_SIZE(%rax), %rsp
|
||||||
UNWIND_HINT_FUNC sp_offset=PTREGS_SIZE
|
UNWIND_HINT_REGS
|
||||||
|
|
||||||
call do_exit
|
call do_exit
|
||||||
SYM_CODE_END(rewind_stack_do_exit)
|
SYM_CODE_END(rewind_stack_do_exit)
|
||||||
|
|
|
@ -56,16 +56,23 @@ struct dyn_arch_ftrace {
|
||||||
|
|
||||||
#ifndef __ASSEMBLY__
|
#ifndef __ASSEMBLY__
|
||||||
|
|
||||||
|
#if defined(CONFIG_FUNCTION_TRACER) && defined(CONFIG_DYNAMIC_FTRACE)
|
||||||
|
extern void set_ftrace_ops_ro(void);
|
||||||
|
#else
|
||||||
|
static inline void set_ftrace_ops_ro(void) { }
|
||||||
|
#endif
|
||||||
|
|
||||||
#define ARCH_HAS_SYSCALL_MATCH_SYM_NAME
|
#define ARCH_HAS_SYSCALL_MATCH_SYM_NAME
|
||||||
static inline bool arch_syscall_match_sym_name(const char *sym, const char *name)
|
static inline bool arch_syscall_match_sym_name(const char *sym, const char *name)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Compare the symbol name with the system call name. Skip the
|
* Compare the symbol name with the system call name. Skip the
|
||||||
* "__x64_sys", "__ia32_sys" or simple "sys" prefix.
|
* "__x64_sys", "__ia32_sys", "__do_sys" or simple "sys" prefix.
|
||||||
*/
|
*/
|
||||||
return !strcmp(sym + 3, name + 3) ||
|
return !strcmp(sym + 3, name + 3) ||
|
||||||
(!strncmp(sym, "__x64_", 6) && !strcmp(sym + 9, name + 3)) ||
|
(!strncmp(sym, "__x64_", 6) && !strcmp(sym + 9, name + 3)) ||
|
||||||
(!strncmp(sym, "__ia32_", 7) && !strcmp(sym + 10, name + 3));
|
(!strncmp(sym, "__ia32_", 7) && !strcmp(sym + 10, name + 3)) ||
|
||||||
|
(!strncmp(sym, "__do_sys", 8) && !strcmp(sym + 8, name + 3));
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef COMPILE_OFFSETS
|
#ifndef COMPILE_OFFSETS
|
||||||
|
|
|
@ -1663,8 +1663,8 @@ void kvm_set_msi_irq(struct kvm *kvm, struct kvm_kernel_irq_routing_entry *e,
|
||||||
static inline bool kvm_irq_is_postable(struct kvm_lapic_irq *irq)
|
static inline bool kvm_irq_is_postable(struct kvm_lapic_irq *irq)
|
||||||
{
|
{
|
||||||
/* We can only post Fixed and LowPrio IRQs */
|
/* We can only post Fixed and LowPrio IRQs */
|
||||||
return (irq->delivery_mode == dest_Fixed ||
|
return (irq->delivery_mode == APIC_DM_FIXED ||
|
||||||
irq->delivery_mode == dest_LowestPrio);
|
irq->delivery_mode == APIC_DM_LOWEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void kvm_arch_vcpu_blocking(struct kvm_vcpu *vcpu)
|
static inline void kvm_arch_vcpu_blocking(struct kvm_vcpu *vcpu)
|
||||||
|
|
|
@ -19,7 +19,7 @@ struct unwind_state {
|
||||||
#if defined(CONFIG_UNWINDER_ORC)
|
#if defined(CONFIG_UNWINDER_ORC)
|
||||||
bool signal, full_regs;
|
bool signal, full_regs;
|
||||||
unsigned long sp, bp, ip;
|
unsigned long sp, bp, ip;
|
||||||
struct pt_regs *regs;
|
struct pt_regs *regs, *prev_regs;
|
||||||
#elif defined(CONFIG_UNWINDER_FRAME_POINTER)
|
#elif defined(CONFIG_UNWINDER_FRAME_POINTER)
|
||||||
bool got_irq;
|
bool got_irq;
|
||||||
unsigned long *bp, *orig_sp, ip;
|
unsigned long *bp, *orig_sp, ip;
|
||||||
|
|
|
@ -352,8 +352,6 @@ static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen)
|
||||||
* According to Intel, MFENCE can do the serialization here.
|
* According to Intel, MFENCE can do the serialization here.
|
||||||
*/
|
*/
|
||||||
asm volatile("mfence" : : : "memory");
|
asm volatile("mfence" : : : "memory");
|
||||||
|
|
||||||
printk_once(KERN_DEBUG "TSC deadline timer enabled\n");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -546,7 +544,7 @@ static struct clock_event_device lapic_clockevent = {
|
||||||
};
|
};
|
||||||
static DEFINE_PER_CPU(struct clock_event_device, lapic_events);
|
static DEFINE_PER_CPU(struct clock_event_device, lapic_events);
|
||||||
|
|
||||||
static u32 hsx_deadline_rev(void)
|
static __init u32 hsx_deadline_rev(void)
|
||||||
{
|
{
|
||||||
switch (boot_cpu_data.x86_stepping) {
|
switch (boot_cpu_data.x86_stepping) {
|
||||||
case 0x02: return 0x3a; /* EP */
|
case 0x02: return 0x3a; /* EP */
|
||||||
|
@ -556,7 +554,7 @@ static u32 hsx_deadline_rev(void)
|
||||||
return ~0U;
|
return ~0U;
|
||||||
}
|
}
|
||||||
|
|
||||||
static u32 bdx_deadline_rev(void)
|
static __init u32 bdx_deadline_rev(void)
|
||||||
{
|
{
|
||||||
switch (boot_cpu_data.x86_stepping) {
|
switch (boot_cpu_data.x86_stepping) {
|
||||||
case 0x02: return 0x00000011;
|
case 0x02: return 0x00000011;
|
||||||
|
@ -568,7 +566,7 @@ static u32 bdx_deadline_rev(void)
|
||||||
return ~0U;
|
return ~0U;
|
||||||
}
|
}
|
||||||
|
|
||||||
static u32 skx_deadline_rev(void)
|
static __init u32 skx_deadline_rev(void)
|
||||||
{
|
{
|
||||||
switch (boot_cpu_data.x86_stepping) {
|
switch (boot_cpu_data.x86_stepping) {
|
||||||
case 0x03: return 0x01000136;
|
case 0x03: return 0x01000136;
|
||||||
|
@ -581,7 +579,7 @@ static u32 skx_deadline_rev(void)
|
||||||
return ~0U;
|
return ~0U;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct x86_cpu_id deadline_match[] = {
|
static const struct x86_cpu_id deadline_match[] __initconst = {
|
||||||
X86_MATCH_INTEL_FAM6_MODEL( HASWELL_X, &hsx_deadline_rev),
|
X86_MATCH_INTEL_FAM6_MODEL( HASWELL_X, &hsx_deadline_rev),
|
||||||
X86_MATCH_INTEL_FAM6_MODEL( BROADWELL_X, 0x0b000020),
|
X86_MATCH_INTEL_FAM6_MODEL( BROADWELL_X, 0x0b000020),
|
||||||
X86_MATCH_INTEL_FAM6_MODEL( BROADWELL_D, &bdx_deadline_rev),
|
X86_MATCH_INTEL_FAM6_MODEL( BROADWELL_D, &bdx_deadline_rev),
|
||||||
|
@ -603,18 +601,19 @@ static const struct x86_cpu_id deadline_match[] = {
|
||||||
{},
|
{},
|
||||||
};
|
};
|
||||||
|
|
||||||
static void apic_check_deadline_errata(void)
|
static __init bool apic_validate_deadline_timer(void)
|
||||||
{
|
{
|
||||||
const struct x86_cpu_id *m;
|
const struct x86_cpu_id *m;
|
||||||
u32 rev;
|
u32 rev;
|
||||||
|
|
||||||
if (!boot_cpu_has(X86_FEATURE_TSC_DEADLINE_TIMER) ||
|
if (!boot_cpu_has(X86_FEATURE_TSC_DEADLINE_TIMER))
|
||||||
boot_cpu_has(X86_FEATURE_HYPERVISOR))
|
return false;
|
||||||
return;
|
if (boot_cpu_has(X86_FEATURE_HYPERVISOR))
|
||||||
|
return true;
|
||||||
|
|
||||||
m = x86_match_cpu(deadline_match);
|
m = x86_match_cpu(deadline_match);
|
||||||
if (!m)
|
if (!m)
|
||||||
return;
|
return true;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Function pointers will have the MSB set due to address layout,
|
* Function pointers will have the MSB set due to address layout,
|
||||||
|
@ -626,11 +625,12 @@ static void apic_check_deadline_errata(void)
|
||||||
rev = (u32)m->driver_data;
|
rev = (u32)m->driver_data;
|
||||||
|
|
||||||
if (boot_cpu_data.microcode >= rev)
|
if (boot_cpu_data.microcode >= rev)
|
||||||
return;
|
return true;
|
||||||
|
|
||||||
setup_clear_cpu_cap(X86_FEATURE_TSC_DEADLINE_TIMER);
|
setup_clear_cpu_cap(X86_FEATURE_TSC_DEADLINE_TIMER);
|
||||||
pr_err(FW_BUG "TSC_DEADLINE disabled due to Errata; "
|
pr_err(FW_BUG "TSC_DEADLINE disabled due to Errata; "
|
||||||
"please update microcode to version: 0x%x (or later)\n", rev);
|
"please update microcode to version: 0x%x (or later)\n", rev);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -2092,7 +2092,8 @@ void __init init_apic_mappings(void)
|
||||||
{
|
{
|
||||||
unsigned int new_apicid;
|
unsigned int new_apicid;
|
||||||
|
|
||||||
apic_check_deadline_errata();
|
if (apic_validate_deadline_timer())
|
||||||
|
pr_debug("TSC deadline timer available\n");
|
||||||
|
|
||||||
if (x2apic_mode) {
|
if (x2apic_mode) {
|
||||||
boot_cpu_physical_apicid = read_apic_id();
|
boot_cpu_physical_apicid = read_apic_id();
|
||||||
|
|
|
@ -183,7 +183,8 @@ recursion_check:
|
||||||
*/
|
*/
|
||||||
if (visit_mask) {
|
if (visit_mask) {
|
||||||
if (*visit_mask & (1UL << info->type)) {
|
if (*visit_mask & (1UL << info->type)) {
|
||||||
printk_deferred_once(KERN_WARNING "WARNING: stack recursion on stack type %d\n", info->type);
|
if (task == current)
|
||||||
|
printk_deferred_once(KERN_WARNING "WARNING: stack recursion on stack type %d\n", info->type);
|
||||||
goto unknown;
|
goto unknown;
|
||||||
}
|
}
|
||||||
*visit_mask |= 1UL << info->type;
|
*visit_mask |= 1UL << info->type;
|
||||||
|
|
|
@ -407,7 +407,8 @@ create_trampoline(struct ftrace_ops *ops, unsigned int *tramp_size)
|
||||||
|
|
||||||
set_vm_flush_reset_perms(trampoline);
|
set_vm_flush_reset_perms(trampoline);
|
||||||
|
|
||||||
set_memory_ro((unsigned long)trampoline, npages);
|
if (likely(system_state != SYSTEM_BOOTING))
|
||||||
|
set_memory_ro((unsigned long)trampoline, npages);
|
||||||
set_memory_x((unsigned long)trampoline, npages);
|
set_memory_x((unsigned long)trampoline, npages);
|
||||||
return (unsigned long)trampoline;
|
return (unsigned long)trampoline;
|
||||||
fail:
|
fail:
|
||||||
|
@ -415,6 +416,32 @@ fail:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void set_ftrace_ops_ro(void)
|
||||||
|
{
|
||||||
|
struct ftrace_ops *ops;
|
||||||
|
unsigned long start_offset;
|
||||||
|
unsigned long end_offset;
|
||||||
|
unsigned long npages;
|
||||||
|
unsigned long size;
|
||||||
|
|
||||||
|
do_for_each_ftrace_op(ops, ftrace_ops_list) {
|
||||||
|
if (!(ops->flags & FTRACE_OPS_FL_ALLOC_TRAMP))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (ops->flags & FTRACE_OPS_FL_SAVE_REGS) {
|
||||||
|
start_offset = (unsigned long)ftrace_regs_caller;
|
||||||
|
end_offset = (unsigned long)ftrace_regs_caller_end;
|
||||||
|
} else {
|
||||||
|
start_offset = (unsigned long)ftrace_caller;
|
||||||
|
end_offset = (unsigned long)ftrace_epilogue;
|
||||||
|
}
|
||||||
|
size = end_offset - start_offset;
|
||||||
|
size = size + RET_SIZE + sizeof(void *);
|
||||||
|
npages = DIV_ROUND_UP(size, PAGE_SIZE);
|
||||||
|
set_memory_ro((unsigned long)ops->trampoline, npages);
|
||||||
|
} while_for_each_ftrace_op(ops);
|
||||||
|
}
|
||||||
|
|
||||||
static unsigned long calc_trampoline_call_offset(bool save_regs)
|
static unsigned long calc_trampoline_call_offset(bool save_regs)
|
||||||
{
|
{
|
||||||
unsigned long start_offset;
|
unsigned long start_offset;
|
||||||
|
|
|
@ -344,6 +344,9 @@ bad_address:
|
||||||
if (IS_ENABLED(CONFIG_X86_32))
|
if (IS_ENABLED(CONFIG_X86_32))
|
||||||
goto the_end;
|
goto the_end;
|
||||||
|
|
||||||
|
if (state->task != current)
|
||||||
|
goto the_end;
|
||||||
|
|
||||||
if (state->regs) {
|
if (state->regs) {
|
||||||
printk_deferred_once(KERN_WARNING
|
printk_deferred_once(KERN_WARNING
|
||||||
"WARNING: kernel stack regs at %p in %s:%d has bad 'bp' value %p\n",
|
"WARNING: kernel stack regs at %p in %s:%d has bad 'bp' value %p\n",
|
||||||
|
|
|
@ -8,19 +8,21 @@
|
||||||
#include <asm/orc_lookup.h>
|
#include <asm/orc_lookup.h>
|
||||||
|
|
||||||
#define orc_warn(fmt, ...) \
|
#define orc_warn(fmt, ...) \
|
||||||
printk_deferred_once(KERN_WARNING pr_fmt("WARNING: " fmt), ##__VA_ARGS__)
|
printk_deferred_once(KERN_WARNING "WARNING: " fmt, ##__VA_ARGS__)
|
||||||
|
|
||||||
|
#define orc_warn_current(args...) \
|
||||||
|
({ \
|
||||||
|
if (state->task == current) \
|
||||||
|
orc_warn(args); \
|
||||||
|
})
|
||||||
|
|
||||||
extern int __start_orc_unwind_ip[];
|
extern int __start_orc_unwind_ip[];
|
||||||
extern int __stop_orc_unwind_ip[];
|
extern int __stop_orc_unwind_ip[];
|
||||||
extern struct orc_entry __start_orc_unwind[];
|
extern struct orc_entry __start_orc_unwind[];
|
||||||
extern struct orc_entry __stop_orc_unwind[];
|
extern struct orc_entry __stop_orc_unwind[];
|
||||||
|
|
||||||
static DEFINE_MUTEX(sort_mutex);
|
static bool orc_init __ro_after_init;
|
||||||
int *cur_orc_ip_table = __start_orc_unwind_ip;
|
static unsigned int lookup_num_blocks __ro_after_init;
|
||||||
struct orc_entry *cur_orc_table = __start_orc_unwind;
|
|
||||||
|
|
||||||
unsigned int lookup_num_blocks;
|
|
||||||
bool orc_init;
|
|
||||||
|
|
||||||
static inline unsigned long orc_ip(const int *ip)
|
static inline unsigned long orc_ip(const int *ip)
|
||||||
{
|
{
|
||||||
|
@ -142,9 +144,6 @@ static struct orc_entry *orc_find(unsigned long ip)
|
||||||
{
|
{
|
||||||
static struct orc_entry *orc;
|
static struct orc_entry *orc;
|
||||||
|
|
||||||
if (!orc_init)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if (ip == 0)
|
if (ip == 0)
|
||||||
return &null_orc_entry;
|
return &null_orc_entry;
|
||||||
|
|
||||||
|
@ -189,6 +188,10 @@ static struct orc_entry *orc_find(unsigned long ip)
|
||||||
|
|
||||||
#ifdef CONFIG_MODULES
|
#ifdef CONFIG_MODULES
|
||||||
|
|
||||||
|
static DEFINE_MUTEX(sort_mutex);
|
||||||
|
static int *cur_orc_ip_table = __start_orc_unwind_ip;
|
||||||
|
static struct orc_entry *cur_orc_table = __start_orc_unwind;
|
||||||
|
|
||||||
static void orc_sort_swap(void *_a, void *_b, int size)
|
static void orc_sort_swap(void *_a, void *_b, int size)
|
||||||
{
|
{
|
||||||
struct orc_entry *orc_a, *orc_b;
|
struct orc_entry *orc_a, *orc_b;
|
||||||
|
@ -381,9 +384,38 @@ static bool deref_stack_iret_regs(struct unwind_state *state, unsigned long addr
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If state->regs is non-NULL, and points to a full pt_regs, just get the reg
|
||||||
|
* value from state->regs.
|
||||||
|
*
|
||||||
|
* Otherwise, if state->regs just points to IRET regs, and the previous frame
|
||||||
|
* had full regs, it's safe to get the value from the previous regs. This can
|
||||||
|
* happen when early/late IRQ entry code gets interrupted by an NMI.
|
||||||
|
*/
|
||||||
|
static bool get_reg(struct unwind_state *state, unsigned int reg_off,
|
||||||
|
unsigned long *val)
|
||||||
|
{
|
||||||
|
unsigned int reg = reg_off/8;
|
||||||
|
|
||||||
|
if (!state->regs)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (state->full_regs) {
|
||||||
|
*val = ((unsigned long *)state->regs)[reg];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state->prev_regs) {
|
||||||
|
*val = ((unsigned long *)state->prev_regs)[reg];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool unwind_next_frame(struct unwind_state *state)
|
bool unwind_next_frame(struct unwind_state *state)
|
||||||
{
|
{
|
||||||
unsigned long ip_p, sp, orig_ip = state->ip, prev_sp = state->sp;
|
unsigned long ip_p, sp, tmp, orig_ip = state->ip, prev_sp = state->sp;
|
||||||
enum stack_type prev_type = state->stack_info.type;
|
enum stack_type prev_type = state->stack_info.type;
|
||||||
struct orc_entry *orc;
|
struct orc_entry *orc;
|
||||||
bool indirect = false;
|
bool indirect = false;
|
||||||
|
@ -445,43 +477,39 @@ bool unwind_next_frame(struct unwind_state *state)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ORC_REG_R10:
|
case ORC_REG_R10:
|
||||||
if (!state->regs || !state->full_regs) {
|
if (!get_reg(state, offsetof(struct pt_regs, r10), &sp)) {
|
||||||
orc_warn("missing regs for base reg R10 at ip %pB\n",
|
orc_warn_current("missing R10 value at %pB\n",
|
||||||
(void *)state->ip);
|
(void *)state->ip);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
sp = state->regs->r10;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ORC_REG_R13:
|
case ORC_REG_R13:
|
||||||
if (!state->regs || !state->full_regs) {
|
if (!get_reg(state, offsetof(struct pt_regs, r13), &sp)) {
|
||||||
orc_warn("missing regs for base reg R13 at ip %pB\n",
|
orc_warn_current("missing R13 value at %pB\n",
|
||||||
(void *)state->ip);
|
(void *)state->ip);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
sp = state->regs->r13;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ORC_REG_DI:
|
case ORC_REG_DI:
|
||||||
if (!state->regs || !state->full_regs) {
|
if (!get_reg(state, offsetof(struct pt_regs, di), &sp)) {
|
||||||
orc_warn("missing regs for base reg DI at ip %pB\n",
|
orc_warn_current("missing RDI value at %pB\n",
|
||||||
(void *)state->ip);
|
(void *)state->ip);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
sp = state->regs->di;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ORC_REG_DX:
|
case ORC_REG_DX:
|
||||||
if (!state->regs || !state->full_regs) {
|
if (!get_reg(state, offsetof(struct pt_regs, dx), &sp)) {
|
||||||
orc_warn("missing regs for base reg DX at ip %pB\n",
|
orc_warn_current("missing DX value at %pB\n",
|
||||||
(void *)state->ip);
|
(void *)state->ip);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
sp = state->regs->dx;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
orc_warn("unknown SP base reg %d for ip %pB\n",
|
orc_warn("unknown SP base reg %d at %pB\n",
|
||||||
orc->sp_reg, (void *)state->ip);
|
orc->sp_reg, (void *)state->ip);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
@ -504,44 +532,48 @@ bool unwind_next_frame(struct unwind_state *state)
|
||||||
|
|
||||||
state->sp = sp;
|
state->sp = sp;
|
||||||
state->regs = NULL;
|
state->regs = NULL;
|
||||||
|
state->prev_regs = NULL;
|
||||||
state->signal = false;
|
state->signal = false;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ORC_TYPE_REGS:
|
case ORC_TYPE_REGS:
|
||||||
if (!deref_stack_regs(state, sp, &state->ip, &state->sp)) {
|
if (!deref_stack_regs(state, sp, &state->ip, &state->sp)) {
|
||||||
orc_warn("can't dereference registers at %p for ip %pB\n",
|
orc_warn_current("can't access registers at %pB\n",
|
||||||
(void *)sp, (void *)orig_ip);
|
(void *)orig_ip);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
state->regs = (struct pt_regs *)sp;
|
state->regs = (struct pt_regs *)sp;
|
||||||
|
state->prev_regs = NULL;
|
||||||
state->full_regs = true;
|
state->full_regs = true;
|
||||||
state->signal = true;
|
state->signal = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ORC_TYPE_REGS_IRET:
|
case ORC_TYPE_REGS_IRET:
|
||||||
if (!deref_stack_iret_regs(state, sp, &state->ip, &state->sp)) {
|
if (!deref_stack_iret_regs(state, sp, &state->ip, &state->sp)) {
|
||||||
orc_warn("can't dereference iret registers at %p for ip %pB\n",
|
orc_warn_current("can't access iret registers at %pB\n",
|
||||||
(void *)sp, (void *)orig_ip);
|
(void *)orig_ip);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (state->full_regs)
|
||||||
|
state->prev_regs = state->regs;
|
||||||
state->regs = (void *)sp - IRET_FRAME_OFFSET;
|
state->regs = (void *)sp - IRET_FRAME_OFFSET;
|
||||||
state->full_regs = false;
|
state->full_regs = false;
|
||||||
state->signal = true;
|
state->signal = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
orc_warn("unknown .orc_unwind entry type %d for ip %pB\n",
|
orc_warn("unknown .orc_unwind entry type %d at %pB\n",
|
||||||
orc->type, (void *)orig_ip);
|
orc->type, (void *)orig_ip);
|
||||||
break;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Find BP: */
|
/* Find BP: */
|
||||||
switch (orc->bp_reg) {
|
switch (orc->bp_reg) {
|
||||||
case ORC_REG_UNDEFINED:
|
case ORC_REG_UNDEFINED:
|
||||||
if (state->regs && state->full_regs)
|
if (get_reg(state, offsetof(struct pt_regs, bp), &tmp))
|
||||||
state->bp = state->regs->bp;
|
state->bp = tmp;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ORC_REG_PREV_SP:
|
case ORC_REG_PREV_SP:
|
||||||
|
@ -564,8 +596,8 @@ bool unwind_next_frame(struct unwind_state *state)
|
||||||
if (state->stack_info.type == prev_type &&
|
if (state->stack_info.type == prev_type &&
|
||||||
on_stack(&state->stack_info, (void *)state->sp, sizeof(long)) &&
|
on_stack(&state->stack_info, (void *)state->sp, sizeof(long)) &&
|
||||||
state->sp <= prev_sp) {
|
state->sp <= prev_sp) {
|
||||||
orc_warn("stack going in the wrong direction? ip=%pB\n",
|
orc_warn_current("stack going in the wrong direction? at %pB\n",
|
||||||
(void *)orig_ip);
|
(void *)orig_ip);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -585,6 +617,9 @@ EXPORT_SYMBOL_GPL(unwind_next_frame);
|
||||||
void __unwind_start(struct unwind_state *state, struct task_struct *task,
|
void __unwind_start(struct unwind_state *state, struct task_struct *task,
|
||||||
struct pt_regs *regs, unsigned long *first_frame)
|
struct pt_regs *regs, unsigned long *first_frame)
|
||||||
{
|
{
|
||||||
|
if (!orc_init)
|
||||||
|
goto done;
|
||||||
|
|
||||||
memset(state, 0, sizeof(*state));
|
memset(state, 0, sizeof(*state));
|
||||||
state->task = task;
|
state->task = task;
|
||||||
|
|
||||||
|
@ -651,7 +686,7 @@ void __unwind_start(struct unwind_state *state, struct task_struct *task,
|
||||||
/* Otherwise, skip ahead to the user-specified starting frame: */
|
/* Otherwise, skip ahead to the user-specified starting frame: */
|
||||||
while (!unwind_done(state) &&
|
while (!unwind_done(state) &&
|
||||||
(!on_stack(&state->stack_info, first_frame, sizeof(long)) ||
|
(!on_stack(&state->stack_info, first_frame, sizeof(long)) ||
|
||||||
state->sp <= (unsigned long)first_frame))
|
state->sp < (unsigned long)first_frame))
|
||||||
unwind_next_frame(state);
|
unwind_next_frame(state);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -225,12 +225,12 @@ static int ioapic_set_irq(struct kvm_ioapic *ioapic, unsigned int irq,
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* AMD SVM AVIC accelerate EOI write and do not trap,
|
* AMD SVM AVIC accelerate EOI write iff the interrupt is edge
|
||||||
* in-kernel IOAPIC will not be able to receive the EOI.
|
* triggered, in which case the in-kernel IOAPIC will not be able
|
||||||
* In this case, we do lazy update of the pending EOI when
|
* to receive the EOI. In this case, we do a lazy update of the
|
||||||
* trying to set IOAPIC irq.
|
* pending EOI when trying to set IOAPIC irq.
|
||||||
*/
|
*/
|
||||||
if (kvm_apicv_activated(ioapic->kvm))
|
if (edge && kvm_apicv_activated(ioapic->kvm))
|
||||||
ioapic_lazy_update_eoi(ioapic, irq);
|
ioapic_lazy_update_eoi(ioapic, irq);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -345,7 +345,7 @@ static struct page **sev_pin_memory(struct kvm *kvm, unsigned long uaddr,
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* Pin the user virtual address. */
|
/* Pin the user virtual address. */
|
||||||
npinned = get_user_pages_fast(uaddr, npages, FOLL_WRITE, pages);
|
npinned = get_user_pages_fast(uaddr, npages, write ? FOLL_WRITE : 0, pages);
|
||||||
if (npinned != npages) {
|
if (npinned != npages) {
|
||||||
pr_err("SEV: Failure locking %lu pages.\n", npages);
|
pr_err("SEV: Failure locking %lu pages.\n", npages);
|
||||||
goto err;
|
goto err;
|
||||||
|
|
|
@ -1752,6 +1752,8 @@ static int db_interception(struct vcpu_svm *svm)
|
||||||
if (svm->vcpu.guest_debug &
|
if (svm->vcpu.guest_debug &
|
||||||
(KVM_GUESTDBG_SINGLESTEP | KVM_GUESTDBG_USE_HW_BP)) {
|
(KVM_GUESTDBG_SINGLESTEP | KVM_GUESTDBG_USE_HW_BP)) {
|
||||||
kvm_run->exit_reason = KVM_EXIT_DEBUG;
|
kvm_run->exit_reason = KVM_EXIT_DEBUG;
|
||||||
|
kvm_run->debug.arch.dr6 = svm->vmcb->save.dr6;
|
||||||
|
kvm_run->debug.arch.dr7 = svm->vmcb->save.dr7;
|
||||||
kvm_run->debug.arch.pc =
|
kvm_run->debug.arch.pc =
|
||||||
svm->vmcb->save.cs.base + svm->vmcb->save.rip;
|
svm->vmcb->save.cs.base + svm->vmcb->save.rip;
|
||||||
kvm_run->debug.arch.exception = DB_VECTOR;
|
kvm_run->debug.arch.exception = DB_VECTOR;
|
||||||
|
|
|
@ -5165,7 +5165,7 @@ static int handle_invept(struct kvm_vcpu *vcpu)
|
||||||
*/
|
*/
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
BUG_ON(1);
|
BUG();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -82,6 +82,9 @@ SYM_FUNC_START(vmx_vmexit)
|
||||||
/* IMPORTANT: Stuff the RSB immediately after VM-Exit, before RET! */
|
/* IMPORTANT: Stuff the RSB immediately after VM-Exit, before RET! */
|
||||||
FILL_RETURN_BUFFER %_ASM_AX, RSB_CLEAR_LOOPS, X86_FEATURE_RETPOLINE
|
FILL_RETURN_BUFFER %_ASM_AX, RSB_CLEAR_LOOPS, X86_FEATURE_RETPOLINE
|
||||||
|
|
||||||
|
/* Clear RFLAGS.CF and RFLAGS.ZF to preserve VM-Exit, i.e. !VM-Fail. */
|
||||||
|
or $1, %_ASM_AX
|
||||||
|
|
||||||
pop %_ASM_AX
|
pop %_ASM_AX
|
||||||
.Lvmexit_skip_rsb:
|
.Lvmexit_skip_rsb:
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -926,19 +926,6 @@ EXPORT_SYMBOL_GPL(kvm_set_xcr);
|
||||||
__reserved_bits; \
|
__reserved_bits; \
|
||||||
})
|
})
|
||||||
|
|
||||||
static u64 kvm_host_cr4_reserved_bits(struct cpuinfo_x86 *c)
|
|
||||||
{
|
|
||||||
u64 reserved_bits = __cr4_reserved_bits(cpu_has, c);
|
|
||||||
|
|
||||||
if (kvm_cpu_cap_has(X86_FEATURE_LA57))
|
|
||||||
reserved_bits &= ~X86_CR4_LA57;
|
|
||||||
|
|
||||||
if (kvm_cpu_cap_has(X86_FEATURE_UMIP))
|
|
||||||
reserved_bits &= ~X86_CR4_UMIP;
|
|
||||||
|
|
||||||
return reserved_bits;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int kvm_valid_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
|
static int kvm_valid_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
|
||||||
{
|
{
|
||||||
if (cr4 & cr4_reserved_bits)
|
if (cr4 & cr4_reserved_bits)
|
||||||
|
@ -3385,6 +3372,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
|
||||||
case KVM_CAP_GET_MSR_FEATURES:
|
case KVM_CAP_GET_MSR_FEATURES:
|
||||||
case KVM_CAP_MSR_PLATFORM_INFO:
|
case KVM_CAP_MSR_PLATFORM_INFO:
|
||||||
case KVM_CAP_EXCEPTION_PAYLOAD:
|
case KVM_CAP_EXCEPTION_PAYLOAD:
|
||||||
|
case KVM_CAP_SET_GUEST_DEBUG:
|
||||||
r = 1;
|
r = 1;
|
||||||
break;
|
break;
|
||||||
case KVM_CAP_SYNC_REGS:
|
case KVM_CAP_SYNC_REGS:
|
||||||
|
@ -9675,7 +9663,9 @@ int kvm_arch_hardware_setup(void *opaque)
|
||||||
if (!kvm_cpu_cap_has(X86_FEATURE_XSAVES))
|
if (!kvm_cpu_cap_has(X86_FEATURE_XSAVES))
|
||||||
supported_xss = 0;
|
supported_xss = 0;
|
||||||
|
|
||||||
cr4_reserved_bits = kvm_host_cr4_reserved_bits(&boot_cpu_data);
|
#define __kvm_cpu_cap_has(UNUSED_, f) kvm_cpu_cap_has(f)
|
||||||
|
cr4_reserved_bits = __cr4_reserved_bits(__kvm_cpu_cap_has, UNUSED_);
|
||||||
|
#undef __kvm_cpu_cap_has
|
||||||
|
|
||||||
if (kvm_has_tsc_control) {
|
if (kvm_has_tsc_control) {
|
||||||
/*
|
/*
|
||||||
|
@ -9707,7 +9697,8 @@ int kvm_arch_check_processor_compat(void *opaque)
|
||||||
|
|
||||||
WARN_ON(!irqs_disabled());
|
WARN_ON(!irqs_disabled());
|
||||||
|
|
||||||
if (kvm_host_cr4_reserved_bits(c) != cr4_reserved_bits)
|
if (__cr4_reserved_bits(cpu_has, c) !=
|
||||||
|
__cr4_reserved_bits(cpu_has, &boot_cpu_data))
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
||||||
return ops->check_processor_compatibility();
|
return ops->check_processor_compatibility();
|
||||||
|
|
|
@ -54,6 +54,7 @@
|
||||||
#include <asm/init.h>
|
#include <asm/init.h>
|
||||||
#include <asm/uv/uv.h>
|
#include <asm/uv/uv.h>
|
||||||
#include <asm/setup.h>
|
#include <asm/setup.h>
|
||||||
|
#include <asm/ftrace.h>
|
||||||
|
|
||||||
#include "mm_internal.h"
|
#include "mm_internal.h"
|
||||||
|
|
||||||
|
@ -1291,6 +1292,8 @@ void mark_rodata_ro(void)
|
||||||
all_end = roundup((unsigned long)_brk_end, PMD_SIZE);
|
all_end = roundup((unsigned long)_brk_end, PMD_SIZE);
|
||||||
set_memory_nx(text_end, (all_end - text_end) >> PAGE_SHIFT);
|
set_memory_nx(text_end, (all_end - text_end) >> PAGE_SHIFT);
|
||||||
|
|
||||||
|
set_ftrace_ops_ro();
|
||||||
|
|
||||||
#ifdef CONFIG_CPA_DEBUG
|
#ifdef CONFIG_CPA_DEBUG
|
||||||
printk(KERN_INFO "Testing CPA: undo %lx-%lx\n", start, end);
|
printk(KERN_INFO "Testing CPA: undo %lx-%lx\n", start, end);
|
||||||
set_memory_rw(start, (end-start) >> PAGE_SHIFT);
|
set_memory_rw(start, (end-start) >> PAGE_SHIFT);
|
||||||
|
|
|
@ -43,7 +43,8 @@ struct cpa_data {
|
||||||
unsigned long pfn;
|
unsigned long pfn;
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
unsigned int force_split : 1,
|
unsigned int force_split : 1,
|
||||||
force_static_prot : 1;
|
force_static_prot : 1,
|
||||||
|
force_flush_all : 1;
|
||||||
struct page **pages;
|
struct page **pages;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -355,10 +356,10 @@ static void cpa_flush(struct cpa_data *data, int cache)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cpa->numpages <= tlb_single_page_flush_ceiling)
|
if (cpa->force_flush_all || cpa->numpages > tlb_single_page_flush_ceiling)
|
||||||
on_each_cpu(__cpa_flush_tlb, cpa, 1);
|
|
||||||
else
|
|
||||||
flush_tlb_all();
|
flush_tlb_all();
|
||||||
|
else
|
||||||
|
on_each_cpu(__cpa_flush_tlb, cpa, 1);
|
||||||
|
|
||||||
if (!cache)
|
if (!cache)
|
||||||
return;
|
return;
|
||||||
|
@ -1598,6 +1599,8 @@ static int cpa_process_alias(struct cpa_data *cpa)
|
||||||
alias_cpa.flags &= ~(CPA_PAGES_ARRAY | CPA_ARRAY);
|
alias_cpa.flags &= ~(CPA_PAGES_ARRAY | CPA_ARRAY);
|
||||||
alias_cpa.curpage = 0;
|
alias_cpa.curpage = 0;
|
||||||
|
|
||||||
|
cpa->force_flush_all = 1;
|
||||||
|
|
||||||
ret = __change_page_attr_set_clr(&alias_cpa, 0);
|
ret = __change_page_attr_set_clr(&alias_cpa, 0);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -1618,6 +1621,7 @@ static int cpa_process_alias(struct cpa_data *cpa)
|
||||||
alias_cpa.flags &= ~(CPA_PAGES_ARRAY | CPA_ARRAY);
|
alias_cpa.flags &= ~(CPA_PAGES_ARRAY | CPA_ARRAY);
|
||||||
alias_cpa.curpage = 0;
|
alias_cpa.curpage = 0;
|
||||||
|
|
||||||
|
cpa->force_flush_all = 1;
|
||||||
/*
|
/*
|
||||||
* The high mapping range is imprecise, so ignore the
|
* The high mapping range is imprecise, so ignore the
|
||||||
* return value.
|
* return value.
|
||||||
|
|
|
@ -123,6 +123,7 @@
|
||||||
#include <linux/ioprio.h>
|
#include <linux/ioprio.h>
|
||||||
#include <linux/sbitmap.h>
|
#include <linux/sbitmap.h>
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
|
#include <linux/backing-dev.h>
|
||||||
|
|
||||||
#include "blk.h"
|
#include "blk.h"
|
||||||
#include "blk-mq.h"
|
#include "blk-mq.h"
|
||||||
|
@ -4976,8 +4977,9 @@ bfq_set_next_ioprio_data(struct bfq_queue *bfqq, struct bfq_io_cq *bic)
|
||||||
ioprio_class = IOPRIO_PRIO_CLASS(bic->ioprio);
|
ioprio_class = IOPRIO_PRIO_CLASS(bic->ioprio);
|
||||||
switch (ioprio_class) {
|
switch (ioprio_class) {
|
||||||
default:
|
default:
|
||||||
dev_err(bfqq->bfqd->queue->backing_dev_info->dev,
|
pr_err("bdi %s: bfq: bad prio class %d\n",
|
||||||
"bfq: bad prio class %d\n", ioprio_class);
|
bdi_dev_name(bfqq->bfqd->queue->backing_dev_info),
|
||||||
|
ioprio_class);
|
||||||
/* fall through */
|
/* fall through */
|
||||||
case IOPRIO_CLASS_NONE:
|
case IOPRIO_CLASS_NONE:
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -496,7 +496,7 @@ const char *blkg_dev_name(struct blkcg_gq *blkg)
|
||||||
{
|
{
|
||||||
/* some drivers (floppy) instantiate a queue w/o disk registered */
|
/* some drivers (floppy) instantiate a queue w/o disk registered */
|
||||||
if (blkg->q->backing_dev_info->dev)
|
if (blkg->q->backing_dev_info->dev)
|
||||||
return dev_name(blkg->q->backing_dev_info->dev);
|
return bdi_dev_name(blkg->q->backing_dev_info);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -466,7 +466,7 @@ struct ioc_gq {
|
||||||
*/
|
*/
|
||||||
atomic64_t vtime;
|
atomic64_t vtime;
|
||||||
atomic64_t done_vtime;
|
atomic64_t done_vtime;
|
||||||
atomic64_t abs_vdebt;
|
u64 abs_vdebt;
|
||||||
u64 last_vtime;
|
u64 last_vtime;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1142,7 +1142,7 @@ static void iocg_kick_waitq(struct ioc_gq *iocg, struct ioc_now *now)
|
||||||
struct iocg_wake_ctx ctx = { .iocg = iocg };
|
struct iocg_wake_ctx ctx = { .iocg = iocg };
|
||||||
u64 margin_ns = (u64)(ioc->period_us *
|
u64 margin_ns = (u64)(ioc->period_us *
|
||||||
WAITQ_TIMER_MARGIN_PCT / 100) * NSEC_PER_USEC;
|
WAITQ_TIMER_MARGIN_PCT / 100) * NSEC_PER_USEC;
|
||||||
u64 abs_vdebt, vdebt, vshortage, expires, oexpires;
|
u64 vdebt, vshortage, expires, oexpires;
|
||||||
s64 vbudget;
|
s64 vbudget;
|
||||||
u32 hw_inuse;
|
u32 hw_inuse;
|
||||||
|
|
||||||
|
@ -1152,18 +1152,15 @@ static void iocg_kick_waitq(struct ioc_gq *iocg, struct ioc_now *now)
|
||||||
vbudget = now->vnow - atomic64_read(&iocg->vtime);
|
vbudget = now->vnow - atomic64_read(&iocg->vtime);
|
||||||
|
|
||||||
/* pay off debt */
|
/* pay off debt */
|
||||||
abs_vdebt = atomic64_read(&iocg->abs_vdebt);
|
vdebt = abs_cost_to_cost(iocg->abs_vdebt, hw_inuse);
|
||||||
vdebt = abs_cost_to_cost(abs_vdebt, hw_inuse);
|
|
||||||
if (vdebt && vbudget > 0) {
|
if (vdebt && vbudget > 0) {
|
||||||
u64 delta = min_t(u64, vbudget, vdebt);
|
u64 delta = min_t(u64, vbudget, vdebt);
|
||||||
u64 abs_delta = min(cost_to_abs_cost(delta, hw_inuse),
|
u64 abs_delta = min(cost_to_abs_cost(delta, hw_inuse),
|
||||||
abs_vdebt);
|
iocg->abs_vdebt);
|
||||||
|
|
||||||
atomic64_add(delta, &iocg->vtime);
|
atomic64_add(delta, &iocg->vtime);
|
||||||
atomic64_add(delta, &iocg->done_vtime);
|
atomic64_add(delta, &iocg->done_vtime);
|
||||||
atomic64_sub(abs_delta, &iocg->abs_vdebt);
|
iocg->abs_vdebt -= abs_delta;
|
||||||
if (WARN_ON_ONCE(atomic64_read(&iocg->abs_vdebt) < 0))
|
|
||||||
atomic64_set(&iocg->abs_vdebt, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1219,12 +1216,18 @@ static bool iocg_kick_delay(struct ioc_gq *iocg, struct ioc_now *now, u64 cost)
|
||||||
u64 expires, oexpires;
|
u64 expires, oexpires;
|
||||||
u32 hw_inuse;
|
u32 hw_inuse;
|
||||||
|
|
||||||
|
lockdep_assert_held(&iocg->waitq.lock);
|
||||||
|
|
||||||
/* debt-adjust vtime */
|
/* debt-adjust vtime */
|
||||||
current_hweight(iocg, NULL, &hw_inuse);
|
current_hweight(iocg, NULL, &hw_inuse);
|
||||||
vtime += abs_cost_to_cost(atomic64_read(&iocg->abs_vdebt), hw_inuse);
|
vtime += abs_cost_to_cost(iocg->abs_vdebt, hw_inuse);
|
||||||
|
|
||||||
/* clear or maintain depending on the overage */
|
/*
|
||||||
if (time_before_eq64(vtime, now->vnow)) {
|
* Clear or maintain depending on the overage. Non-zero vdebt is what
|
||||||
|
* guarantees that @iocg is online and future iocg_kick_delay() will
|
||||||
|
* clear use_delay. Don't leave it on when there's no vdebt.
|
||||||
|
*/
|
||||||
|
if (!iocg->abs_vdebt || time_before_eq64(vtime, now->vnow)) {
|
||||||
blkcg_clear_delay(blkg);
|
blkcg_clear_delay(blkg);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1258,9 +1261,12 @@ static enum hrtimer_restart iocg_delay_timer_fn(struct hrtimer *timer)
|
||||||
{
|
{
|
||||||
struct ioc_gq *iocg = container_of(timer, struct ioc_gq, delay_timer);
|
struct ioc_gq *iocg = container_of(timer, struct ioc_gq, delay_timer);
|
||||||
struct ioc_now now;
|
struct ioc_now now;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&iocg->waitq.lock, flags);
|
||||||
ioc_now(iocg->ioc, &now);
|
ioc_now(iocg->ioc, &now);
|
||||||
iocg_kick_delay(iocg, &now, 0);
|
iocg_kick_delay(iocg, &now, 0);
|
||||||
|
spin_unlock_irqrestore(&iocg->waitq.lock, flags);
|
||||||
|
|
||||||
return HRTIMER_NORESTART;
|
return HRTIMER_NORESTART;
|
||||||
}
|
}
|
||||||
|
@ -1368,14 +1374,13 @@ static void ioc_timer_fn(struct timer_list *timer)
|
||||||
* should have woken up in the last period and expire idle iocgs.
|
* should have woken up in the last period and expire idle iocgs.
|
||||||
*/
|
*/
|
||||||
list_for_each_entry_safe(iocg, tiocg, &ioc->active_iocgs, active_list) {
|
list_for_each_entry_safe(iocg, tiocg, &ioc->active_iocgs, active_list) {
|
||||||
if (!waitqueue_active(&iocg->waitq) &&
|
if (!waitqueue_active(&iocg->waitq) && iocg->abs_vdebt &&
|
||||||
!atomic64_read(&iocg->abs_vdebt) && !iocg_is_idle(iocg))
|
!iocg_is_idle(iocg))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
spin_lock(&iocg->waitq.lock);
|
spin_lock(&iocg->waitq.lock);
|
||||||
|
|
||||||
if (waitqueue_active(&iocg->waitq) ||
|
if (waitqueue_active(&iocg->waitq) || iocg->abs_vdebt) {
|
||||||
atomic64_read(&iocg->abs_vdebt)) {
|
|
||||||
/* might be oversleeping vtime / hweight changes, kick */
|
/* might be oversleeping vtime / hweight changes, kick */
|
||||||
iocg_kick_waitq(iocg, &now);
|
iocg_kick_waitq(iocg, &now);
|
||||||
iocg_kick_delay(iocg, &now, 0);
|
iocg_kick_delay(iocg, &now, 0);
|
||||||
|
@ -1718,28 +1723,49 @@ static void ioc_rqos_throttle(struct rq_qos *rqos, struct bio *bio)
|
||||||
* tests are racy but the races aren't systemic - we only miss once
|
* tests are racy but the races aren't systemic - we only miss once
|
||||||
* in a while which is fine.
|
* in a while which is fine.
|
||||||
*/
|
*/
|
||||||
if (!waitqueue_active(&iocg->waitq) &&
|
if (!waitqueue_active(&iocg->waitq) && !iocg->abs_vdebt &&
|
||||||
!atomic64_read(&iocg->abs_vdebt) &&
|
|
||||||
time_before_eq64(vtime + cost, now.vnow)) {
|
time_before_eq64(vtime + cost, now.vnow)) {
|
||||||
iocg_commit_bio(iocg, bio, cost);
|
iocg_commit_bio(iocg, bio, cost);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We're over budget. If @bio has to be issued regardless,
|
* We activated above but w/o any synchronization. Deactivation is
|
||||||
* remember the abs_cost instead of advancing vtime.
|
* synchronized with waitq.lock and we won't get deactivated as long
|
||||||
* iocg_kick_waitq() will pay off the debt before waking more IOs.
|
* as we're waiting or has debt, so we're good if we're activated
|
||||||
|
* here. In the unlikely case that we aren't, just issue the IO.
|
||||||
|
*/
|
||||||
|
spin_lock_irq(&iocg->waitq.lock);
|
||||||
|
|
||||||
|
if (unlikely(list_empty(&iocg->active_list))) {
|
||||||
|
spin_unlock_irq(&iocg->waitq.lock);
|
||||||
|
iocg_commit_bio(iocg, bio, cost);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We're over budget. If @bio has to be issued regardless, remember
|
||||||
|
* the abs_cost instead of advancing vtime. iocg_kick_waitq() will pay
|
||||||
|
* off the debt before waking more IOs.
|
||||||
|
*
|
||||||
* This way, the debt is continuously paid off each period with the
|
* This way, the debt is continuously paid off each period with the
|
||||||
* actual budget available to the cgroup. If we just wound vtime,
|
* actual budget available to the cgroup. If we just wound vtime, we
|
||||||
* we would incorrectly use the current hw_inuse for the entire
|
* would incorrectly use the current hw_inuse for the entire amount
|
||||||
* amount which, for example, can lead to the cgroup staying
|
* which, for example, can lead to the cgroup staying blocked for a
|
||||||
* blocked for a long time even with substantially raised hw_inuse.
|
* long time even with substantially raised hw_inuse.
|
||||||
|
*
|
||||||
|
* An iocg with vdebt should stay online so that the timer can keep
|
||||||
|
* deducting its vdebt and [de]activate use_delay mechanism
|
||||||
|
* accordingly. We don't want to race against the timer trying to
|
||||||
|
* clear them and leave @iocg inactive w/ dangling use_delay heavily
|
||||||
|
* penalizing the cgroup and its descendants.
|
||||||
*/
|
*/
|
||||||
if (bio_issue_as_root_blkg(bio) || fatal_signal_pending(current)) {
|
if (bio_issue_as_root_blkg(bio) || fatal_signal_pending(current)) {
|
||||||
atomic64_add(abs_cost, &iocg->abs_vdebt);
|
iocg->abs_vdebt += abs_cost;
|
||||||
if (iocg_kick_delay(iocg, &now, cost))
|
if (iocg_kick_delay(iocg, &now, cost))
|
||||||
blkcg_schedule_throttle(rqos->q,
|
blkcg_schedule_throttle(rqos->q,
|
||||||
(bio->bi_opf & REQ_SWAP) == REQ_SWAP);
|
(bio->bi_opf & REQ_SWAP) == REQ_SWAP);
|
||||||
|
spin_unlock_irq(&iocg->waitq.lock);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1756,20 +1782,6 @@ static void ioc_rqos_throttle(struct rq_qos *rqos, struct bio *bio)
|
||||||
* All waiters are on iocg->waitq and the wait states are
|
* All waiters are on iocg->waitq and the wait states are
|
||||||
* synchronized using waitq.lock.
|
* synchronized using waitq.lock.
|
||||||
*/
|
*/
|
||||||
spin_lock_irq(&iocg->waitq.lock);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* We activated above but w/o any synchronization. Deactivation is
|
|
||||||
* synchronized with waitq.lock and we won't get deactivated as
|
|
||||||
* long as we're waiting, so we're good if we're activated here.
|
|
||||||
* In the unlikely case that we are deactivated, just issue the IO.
|
|
||||||
*/
|
|
||||||
if (unlikely(list_empty(&iocg->active_list))) {
|
|
||||||
spin_unlock_irq(&iocg->waitq.lock);
|
|
||||||
iocg_commit_bio(iocg, bio, cost);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
init_waitqueue_func_entry(&wait.wait, iocg_wake_fn);
|
init_waitqueue_func_entry(&wait.wait, iocg_wake_fn);
|
||||||
wait.wait.private = current;
|
wait.wait.private = current;
|
||||||
wait.bio = bio;
|
wait.bio = bio;
|
||||||
|
@ -1801,6 +1813,7 @@ static void ioc_rqos_merge(struct rq_qos *rqos, struct request *rq,
|
||||||
struct ioc_now now;
|
struct ioc_now now;
|
||||||
u32 hw_inuse;
|
u32 hw_inuse;
|
||||||
u64 abs_cost, cost;
|
u64 abs_cost, cost;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
/* bypass if disabled or for root cgroup */
|
/* bypass if disabled or for root cgroup */
|
||||||
if (!ioc->enabled || !iocg->level)
|
if (!ioc->enabled || !iocg->level)
|
||||||
|
@ -1820,15 +1833,28 @@ static void ioc_rqos_merge(struct rq_qos *rqos, struct request *rq,
|
||||||
iocg->cursor = bio_end;
|
iocg->cursor = bio_end;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Charge if there's enough vtime budget and the existing request
|
* Charge if there's enough vtime budget and the existing request has
|
||||||
* has cost assigned. Otherwise, account it as debt. See debt
|
* cost assigned.
|
||||||
* handling in ioc_rqos_throttle() for details.
|
|
||||||
*/
|
*/
|
||||||
if (rq->bio && rq->bio->bi_iocost_cost &&
|
if (rq->bio && rq->bio->bi_iocost_cost &&
|
||||||
time_before_eq64(atomic64_read(&iocg->vtime) + cost, now.vnow))
|
time_before_eq64(atomic64_read(&iocg->vtime) + cost, now.vnow)) {
|
||||||
iocg_commit_bio(iocg, bio, cost);
|
iocg_commit_bio(iocg, bio, cost);
|
||||||
else
|
return;
|
||||||
atomic64_add(abs_cost, &iocg->abs_vdebt);
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Otherwise, account it as debt if @iocg is online, which it should
|
||||||
|
* be for the vast majority of cases. See debt handling in
|
||||||
|
* ioc_rqos_throttle() for details.
|
||||||
|
*/
|
||||||
|
spin_lock_irqsave(&iocg->waitq.lock, flags);
|
||||||
|
if (likely(!list_empty(&iocg->active_list))) {
|
||||||
|
iocg->abs_vdebt += abs_cost;
|
||||||
|
iocg_kick_delay(iocg, &now, cost);
|
||||||
|
} else {
|
||||||
|
iocg_commit_bio(iocg, bio, cost);
|
||||||
|
}
|
||||||
|
spin_unlock_irqrestore(&iocg->waitq.lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ioc_rqos_done_bio(struct rq_qos *rqos, struct bio *bio)
|
static void ioc_rqos_done_bio(struct rq_qos *rqos, struct bio *bio)
|
||||||
|
@ -1998,7 +2024,6 @@ static void ioc_pd_init(struct blkg_policy_data *pd)
|
||||||
iocg->ioc = ioc;
|
iocg->ioc = ioc;
|
||||||
atomic64_set(&iocg->vtime, now.vnow);
|
atomic64_set(&iocg->vtime, now.vnow);
|
||||||
atomic64_set(&iocg->done_vtime, now.vnow);
|
atomic64_set(&iocg->done_vtime, now.vnow);
|
||||||
atomic64_set(&iocg->abs_vdebt, 0);
|
|
||||||
atomic64_set(&iocg->active_period, atomic64_read(&ioc->cur_period));
|
atomic64_set(&iocg->active_period, atomic64_read(&ioc->cur_period));
|
||||||
INIT_LIST_HEAD(&iocg->active_list);
|
INIT_LIST_HEAD(&iocg->active_list);
|
||||||
iocg->hweight_active = HWEIGHT_WHOLE;
|
iocg->hweight_active = HWEIGHT_WHOLE;
|
||||||
|
|
|
@ -287,7 +287,7 @@ static void exit_tfm(struct crypto_skcipher *tfm)
|
||||||
crypto_free_skcipher(ctx->child);
|
crypto_free_skcipher(ctx->child);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void free(struct skcipher_instance *inst)
|
static void free_inst(struct skcipher_instance *inst)
|
||||||
{
|
{
|
||||||
crypto_drop_skcipher(skcipher_instance_ctx(inst));
|
crypto_drop_skcipher(skcipher_instance_ctx(inst));
|
||||||
kfree(inst);
|
kfree(inst);
|
||||||
|
@ -400,12 +400,12 @@ static int create(struct crypto_template *tmpl, struct rtattr **tb)
|
||||||
inst->alg.encrypt = encrypt;
|
inst->alg.encrypt = encrypt;
|
||||||
inst->alg.decrypt = decrypt;
|
inst->alg.decrypt = decrypt;
|
||||||
|
|
||||||
inst->free = free;
|
inst->free = free_inst;
|
||||||
|
|
||||||
err = skcipher_register_instance(tmpl, inst);
|
err = skcipher_register_instance(tmpl, inst);
|
||||||
if (err) {
|
if (err) {
|
||||||
err_free_inst:
|
err_free_inst:
|
||||||
free(inst);
|
free_inst(inst);
|
||||||
}
|
}
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
|
@ -322,7 +322,7 @@ static void exit_tfm(struct crypto_skcipher *tfm)
|
||||||
crypto_free_cipher(ctx->tweak);
|
crypto_free_cipher(ctx->tweak);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void free(struct skcipher_instance *inst)
|
static void free_inst(struct skcipher_instance *inst)
|
||||||
{
|
{
|
||||||
crypto_drop_skcipher(skcipher_instance_ctx(inst));
|
crypto_drop_skcipher(skcipher_instance_ctx(inst));
|
||||||
kfree(inst);
|
kfree(inst);
|
||||||
|
@ -434,12 +434,12 @@ static int create(struct crypto_template *tmpl, struct rtattr **tb)
|
||||||
inst->alg.encrypt = encrypt;
|
inst->alg.encrypt = encrypt;
|
||||||
inst->alg.decrypt = decrypt;
|
inst->alg.decrypt = decrypt;
|
||||||
|
|
||||||
inst->free = free;
|
inst->free = free_inst;
|
||||||
|
|
||||||
err = skcipher_register_instance(tmpl, inst);
|
err = skcipher_register_instance(tmpl, inst);
|
||||||
if (err) {
|
if (err) {
|
||||||
err_free_inst:
|
err_free_inst:
|
||||||
free(inst);
|
free_inst(inst);
|
||||||
}
|
}
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1994,23 +1994,31 @@ void acpi_ec_set_gpe_wake_mask(u8 action)
|
||||||
acpi_set_gpe_wake_mask(NULL, first_ec->gpe, action);
|
acpi_set_gpe_wake_mask(NULL, first_ec->gpe, action);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool acpi_ec_other_gpes_active(void)
|
|
||||||
{
|
|
||||||
return acpi_any_gpe_status_set(first_ec ? first_ec->gpe : U32_MAX);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool acpi_ec_dispatch_gpe(void)
|
bool acpi_ec_dispatch_gpe(void)
|
||||||
{
|
{
|
||||||
u32 ret;
|
u32 ret;
|
||||||
|
|
||||||
if (!first_ec)
|
if (!first_ec)
|
||||||
|
return acpi_any_gpe_status_set(U32_MAX);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Report wakeup if the status bit is set for any enabled GPE other
|
||||||
|
* than the EC one.
|
||||||
|
*/
|
||||||
|
if (acpi_any_gpe_status_set(first_ec->gpe))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (ec_no_wakeup)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Dispatch the EC GPE in-band, but do not report wakeup in any case
|
||||||
|
* to allow the caller to process events properly after that.
|
||||||
|
*/
|
||||||
ret = acpi_dispatch_gpe(NULL, first_ec->gpe);
|
ret = acpi_dispatch_gpe(NULL, first_ec->gpe);
|
||||||
if (ret == ACPI_INTERRUPT_HANDLED) {
|
if (ret == ACPI_INTERRUPT_HANDLED)
|
||||||
pm_pr_dbg("EC GPE dispatched\n");
|
pm_pr_dbg("EC GPE dispatched\n");
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_PM_SLEEP */
|
#endif /* CONFIG_PM_SLEEP */
|
||||||
|
|
|
@ -202,7 +202,6 @@ void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit);
|
||||||
|
|
||||||
#ifdef CONFIG_PM_SLEEP
|
#ifdef CONFIG_PM_SLEEP
|
||||||
void acpi_ec_flush_work(void);
|
void acpi_ec_flush_work(void);
|
||||||
bool acpi_ec_other_gpes_active(void);
|
|
||||||
bool acpi_ec_dispatch_gpe(void);
|
bool acpi_ec_dispatch_gpe(void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -1013,20 +1013,10 @@ static bool acpi_s2idle_wake(void)
|
||||||
if (acpi_check_wakeup_handlers())
|
if (acpi_check_wakeup_handlers())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
/*
|
/* Check non-EC GPE wakeups and dispatch the EC GPE. */
|
||||||
* If the status bit is set for any enabled GPE other than the
|
if (acpi_ec_dispatch_gpe())
|
||||||
* EC one, the wakeup is regarded as a genuine one.
|
|
||||||
*/
|
|
||||||
if (acpi_ec_other_gpes_active())
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
/*
|
|
||||||
* If the EC GPE status bit has not been set, the wakeup is
|
|
||||||
* regarded as a spurious one.
|
|
||||||
*/
|
|
||||||
if (!acpi_ec_dispatch_gpe())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Cancel the wakeup and process all pending events in case
|
* Cancel the wakeup and process all pending events in case
|
||||||
* there are any wakeup ones in there.
|
* there are any wakeup ones in there.
|
||||||
|
|
|
@ -645,6 +645,7 @@ static void amba_device_initialize(struct amba_device *dev, const char *name)
|
||||||
dev->dev.release = amba_device_release;
|
dev->dev.release = amba_device_release;
|
||||||
dev->dev.bus = &amba_bustype;
|
dev->dev.bus = &amba_bustype;
|
||||||
dev->dev.dma_mask = &dev->dev.coherent_dma_mask;
|
dev->dev.dma_mask = &dev->dev.coherent_dma_mask;
|
||||||
|
dev->dev.dma_parms = &dev->dma_parms;
|
||||||
dev->res.name = dev_name(&dev->dev);
|
dev->res.name = dev_name(&dev->dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -256,7 +256,8 @@ static int try_to_bring_up_master(struct master *master,
|
||||||
ret = master->ops->bind(master->dev);
|
ret = master->ops->bind(master->dev);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
devres_release_group(master->dev, NULL);
|
devres_release_group(master->dev, NULL);
|
||||||
dev_info(master->dev, "master bind failed: %d\n", ret);
|
if (ret != -EPROBE_DEFER)
|
||||||
|
dev_info(master->dev, "master bind failed: %d\n", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -611,8 +612,9 @@ static int component_bind(struct component *component, struct master *master,
|
||||||
devres_release_group(component->dev, NULL);
|
devres_release_group(component->dev, NULL);
|
||||||
devres_release_group(master->dev, NULL);
|
devres_release_group(master->dev, NULL);
|
||||||
|
|
||||||
dev_err(master->dev, "failed to bind %s (ops %ps): %d\n",
|
if (ret != -EPROBE_DEFER)
|
||||||
dev_name(component->dev), component->ops, ret);
|
dev_err(master->dev, "failed to bind %s (ops %ps): %d\n",
|
||||||
|
dev_name(component->dev), component->ops, ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -2370,6 +2370,11 @@ u32 fw_devlink_get_flags(void)
|
||||||
return fw_devlink_flags;
|
return fw_devlink_flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool fw_devlink_is_permissive(void)
|
||||||
|
{
|
||||||
|
return fw_devlink_flags == DL_FLAG_SYNC_STATE_ONLY;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* device_add - add device to device hierarchy.
|
* device_add - add device to device hierarchy.
|
||||||
* @dev: device.
|
* @dev: device.
|
||||||
|
@ -2524,7 +2529,7 @@ int device_add(struct device *dev)
|
||||||
if (fw_devlink_flags && is_fwnode_dev &&
|
if (fw_devlink_flags && is_fwnode_dev &&
|
||||||
fwnode_has_op(dev->fwnode, add_links)) {
|
fwnode_has_op(dev->fwnode, add_links)) {
|
||||||
fw_ret = fwnode_call_int_op(dev->fwnode, add_links, dev);
|
fw_ret = fwnode_call_int_op(dev->fwnode, add_links, dev);
|
||||||
if (fw_ret == -ENODEV)
|
if (fw_ret == -ENODEV && !fw_devlink_is_permissive())
|
||||||
device_link_wait_for_mandatory_supplier(dev);
|
device_link_wait_for_mandatory_supplier(dev);
|
||||||
else if (fw_ret)
|
else if (fw_ret)
|
||||||
device_link_wait_for_optional_supplier(dev);
|
device_link_wait_for_optional_supplier(dev);
|
||||||
|
|
|
@ -224,17 +224,9 @@ static int deferred_devs_show(struct seq_file *s, void *data)
|
||||||
}
|
}
|
||||||
DEFINE_SHOW_ATTRIBUTE(deferred_devs);
|
DEFINE_SHOW_ATTRIBUTE(deferred_devs);
|
||||||
|
|
||||||
#ifdef CONFIG_MODULES
|
int driver_deferred_probe_timeout;
|
||||||
/*
|
|
||||||
* In the case of modules, set the default probe timeout to
|
|
||||||
* 30 seconds to give userland some time to load needed modules
|
|
||||||
*/
|
|
||||||
int driver_deferred_probe_timeout = 30;
|
|
||||||
#else
|
|
||||||
/* In the case of !modules, no probe timeout needed */
|
|
||||||
int driver_deferred_probe_timeout = -1;
|
|
||||||
#endif
|
|
||||||
EXPORT_SYMBOL_GPL(driver_deferred_probe_timeout);
|
EXPORT_SYMBOL_GPL(driver_deferred_probe_timeout);
|
||||||
|
static DECLARE_WAIT_QUEUE_HEAD(probe_timeout_waitqueue);
|
||||||
|
|
||||||
static int __init deferred_probe_timeout_setup(char *str)
|
static int __init deferred_probe_timeout_setup(char *str)
|
||||||
{
|
{
|
||||||
|
@ -266,8 +258,8 @@ int driver_deferred_probe_check_state(struct device *dev)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!driver_deferred_probe_timeout) {
|
if (!driver_deferred_probe_timeout && initcalls_done) {
|
||||||
dev_WARN(dev, "deferred probe timeout, ignoring dependency");
|
dev_warn(dev, "deferred probe timeout, ignoring dependency");
|
||||||
return -ETIMEDOUT;
|
return -ETIMEDOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -284,6 +276,7 @@ static void deferred_probe_timeout_work_func(struct work_struct *work)
|
||||||
|
|
||||||
list_for_each_entry_safe(private, p, &deferred_probe_pending_list, deferred_probe)
|
list_for_each_entry_safe(private, p, &deferred_probe_pending_list, deferred_probe)
|
||||||
dev_info(private->device, "deferred probe pending");
|
dev_info(private->device, "deferred probe pending");
|
||||||
|
wake_up(&probe_timeout_waitqueue);
|
||||||
}
|
}
|
||||||
static DECLARE_DELAYED_WORK(deferred_probe_timeout_work, deferred_probe_timeout_work_func);
|
static DECLARE_DELAYED_WORK(deferred_probe_timeout_work, deferred_probe_timeout_work_func);
|
||||||
|
|
||||||
|
@ -658,6 +651,9 @@ int driver_probe_done(void)
|
||||||
*/
|
*/
|
||||||
void wait_for_device_probe(void)
|
void wait_for_device_probe(void)
|
||||||
{
|
{
|
||||||
|
/* wait for probe timeout */
|
||||||
|
wait_event(probe_timeout_waitqueue, !driver_deferred_probe_timeout);
|
||||||
|
|
||||||
/* wait for the deferred probe workqueue to finish */
|
/* wait for the deferred probe workqueue to finish */
|
||||||
flush_work(&deferred_probe_work);
|
flush_work(&deferred_probe_work);
|
||||||
|
|
||||||
|
|
|
@ -380,6 +380,8 @@ struct platform_object {
|
||||||
*/
|
*/
|
||||||
static void setup_pdev_dma_masks(struct platform_device *pdev)
|
static void setup_pdev_dma_masks(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
|
pdev->dev.dma_parms = &pdev->dma_parms;
|
||||||
|
|
||||||
if (!pdev->dev.coherent_dma_mask)
|
if (!pdev->dev.coherent_dma_mask)
|
||||||
pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
|
pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
|
||||||
if (!pdev->dev.dma_mask) {
|
if (!pdev->dev.dma_mask) {
|
||||||
|
|
|
@ -812,10 +812,9 @@ int mhi_register_controller(struct mhi_controller *mhi_cntrl,
|
||||||
if (!mhi_cntrl)
|
if (!mhi_cntrl)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (!mhi_cntrl->runtime_get || !mhi_cntrl->runtime_put)
|
if (!mhi_cntrl->runtime_get || !mhi_cntrl->runtime_put ||
|
||||||
return -EINVAL;
|
!mhi_cntrl->status_cb || !mhi_cntrl->read_reg ||
|
||||||
|
!mhi_cntrl->write_reg)
|
||||||
if (!mhi_cntrl->status_cb || !mhi_cntrl->link_status)
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
ret = parse_config(mhi_cntrl, config);
|
ret = parse_config(mhi_cntrl, config);
|
||||||
|
|
|
@ -11,9 +11,6 @@
|
||||||
|
|
||||||
extern struct bus_type mhi_bus_type;
|
extern struct bus_type mhi_bus_type;
|
||||||
|
|
||||||
/* MHI MMIO register mapping */
|
|
||||||
#define PCI_INVALID_READ(val) (val == U32_MAX)
|
|
||||||
|
|
||||||
#define MHIREGLEN (0x0)
|
#define MHIREGLEN (0x0)
|
||||||
#define MHIREGLEN_MHIREGLEN_MASK (0xFFFFFFFF)
|
#define MHIREGLEN_MHIREGLEN_MASK (0xFFFFFFFF)
|
||||||
#define MHIREGLEN_MHIREGLEN_SHIFT (0)
|
#define MHIREGLEN_MHIREGLEN_SHIFT (0)
|
||||||
|
|
|
@ -18,16 +18,7 @@
|
||||||
int __must_check mhi_read_reg(struct mhi_controller *mhi_cntrl,
|
int __must_check mhi_read_reg(struct mhi_controller *mhi_cntrl,
|
||||||
void __iomem *base, u32 offset, u32 *out)
|
void __iomem *base, u32 offset, u32 *out)
|
||||||
{
|
{
|
||||||
u32 tmp = readl(base + offset);
|
return mhi_cntrl->read_reg(mhi_cntrl, base + offset, out);
|
||||||
|
|
||||||
/* If there is any unexpected value, query the link status */
|
|
||||||
if (PCI_INVALID_READ(tmp) &&
|
|
||||||
mhi_cntrl->link_status(mhi_cntrl))
|
|
||||||
return -EIO;
|
|
||||||
|
|
||||||
*out = tmp;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int __must_check mhi_read_reg_field(struct mhi_controller *mhi_cntrl,
|
int __must_check mhi_read_reg_field(struct mhi_controller *mhi_cntrl,
|
||||||
|
@ -49,7 +40,7 @@ int __must_check mhi_read_reg_field(struct mhi_controller *mhi_cntrl,
|
||||||
void mhi_write_reg(struct mhi_controller *mhi_cntrl, void __iomem *base,
|
void mhi_write_reg(struct mhi_controller *mhi_cntrl, void __iomem *base,
|
||||||
u32 offset, u32 val)
|
u32 offset, u32 val)
|
||||||
{
|
{
|
||||||
writel(val, base + offset);
|
mhi_cntrl->write_reg(mhi_cntrl, base + offset, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mhi_write_reg_field(struct mhi_controller *mhi_cntrl, void __iomem *base,
|
void mhi_write_reg_field(struct mhi_controller *mhi_cntrl, void __iomem *base,
|
||||||
|
@ -294,7 +285,7 @@ void mhi_create_devices(struct mhi_controller *mhi_cntrl)
|
||||||
!(mhi_chan->ee_mask & BIT(mhi_cntrl->ee)))
|
!(mhi_chan->ee_mask & BIT(mhi_cntrl->ee)))
|
||||||
continue;
|
continue;
|
||||||
mhi_dev = mhi_alloc_device(mhi_cntrl);
|
mhi_dev = mhi_alloc_device(mhi_cntrl);
|
||||||
if (!mhi_dev)
|
if (IS_ERR(mhi_dev))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
mhi_dev->dev_type = MHI_DEVICE_XFER;
|
mhi_dev->dev_type = MHI_DEVICE_XFER;
|
||||||
|
@ -336,7 +327,8 @@ void mhi_create_devices(struct mhi_controller *mhi_cntrl)
|
||||||
|
|
||||||
/* Channel name is same for both UL and DL */
|
/* Channel name is same for both UL and DL */
|
||||||
mhi_dev->chan_name = mhi_chan->name;
|
mhi_dev->chan_name = mhi_chan->name;
|
||||||
dev_set_name(&mhi_dev->dev, "%04x_%s", mhi_chan->chan,
|
dev_set_name(&mhi_dev->dev, "%s_%s",
|
||||||
|
dev_name(mhi_cntrl->cntrl_dev),
|
||||||
mhi_dev->chan_name);
|
mhi_dev->chan_name);
|
||||||
|
|
||||||
/* Init wakeup source if available */
|
/* Init wakeup source if available */
|
||||||
|
|
|
@ -902,7 +902,11 @@ int mhi_sync_power_up(struct mhi_controller *mhi_cntrl)
|
||||||
MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state),
|
MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state),
|
||||||
msecs_to_jiffies(mhi_cntrl->timeout_ms));
|
msecs_to_jiffies(mhi_cntrl->timeout_ms));
|
||||||
|
|
||||||
return (MHI_IN_MISSION_MODE(mhi_cntrl->ee)) ? 0 : -EIO;
|
ret = (MHI_IN_MISSION_MODE(mhi_cntrl->ee)) ? 0 : -ETIMEDOUT;
|
||||||
|
if (ret)
|
||||||
|
mhi_power_down(mhi_cntrl, false);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(mhi_sync_power_up);
|
EXPORT_SYMBOL(mhi_sync_power_up);
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
int efi_tpm_final_log_size;
|
int efi_tpm_final_log_size;
|
||||||
EXPORT_SYMBOL(efi_tpm_final_log_size);
|
EXPORT_SYMBOL(efi_tpm_final_log_size);
|
||||||
|
|
||||||
static int tpm2_calc_event_log_size(void *data, int count, void *size_info)
|
static int __init tpm2_calc_event_log_size(void *data, int count, void *size_info)
|
||||||
{
|
{
|
||||||
struct tcg_pcr_event2_head *header;
|
struct tcg_pcr_event2_head *header;
|
||||||
int event_size, size = 0;
|
int event_size, size = 0;
|
||||||
|
|
|
@ -531,7 +531,7 @@ static int pca953x_gpio_set_config(struct gpio_chip *gc, unsigned int offset,
|
||||||
{
|
{
|
||||||
struct pca953x_chip *chip = gpiochip_get_data(gc);
|
struct pca953x_chip *chip = gpiochip_get_data(gc);
|
||||||
|
|
||||||
switch (config) {
|
switch (pinconf_to_config_param(config)) {
|
||||||
case PIN_CONFIG_BIAS_PULL_UP:
|
case PIN_CONFIG_BIAS_PULL_UP:
|
||||||
case PIN_CONFIG_BIAS_PULL_DOWN:
|
case PIN_CONFIG_BIAS_PULL_DOWN:
|
||||||
return pca953x_gpio_set_pull_up_down(chip, offset, config);
|
return pca953x_gpio_set_pull_up_down(chip, offset, config);
|
||||||
|
|
|
@ -368,6 +368,7 @@ static void tegra_gpio_irq_shutdown(struct irq_data *d)
|
||||||
struct tegra_gpio_info *tgi = bank->tgi;
|
struct tegra_gpio_info *tgi = bank->tgi;
|
||||||
unsigned int gpio = d->hwirq;
|
unsigned int gpio = d->hwirq;
|
||||||
|
|
||||||
|
tegra_gpio_irq_mask(d);
|
||||||
gpiochip_unlock_as_irq(&tgi->gc, gpio);
|
gpiochip_unlock_as_irq(&tgi->gc, gpio);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1158,8 +1158,19 @@ static void gpio_desc_to_lineinfo(struct gpio_desc *desc,
|
||||||
struct gpioline_info *info)
|
struct gpioline_info *info)
|
||||||
{
|
{
|
||||||
struct gpio_chip *gc = desc->gdev->chip;
|
struct gpio_chip *gc = desc->gdev->chip;
|
||||||
|
bool ok_for_pinctrl;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This function takes a mutex so we must check this before taking
|
||||||
|
* the spinlock.
|
||||||
|
*
|
||||||
|
* FIXME: find a non-racy way to retrieve this information. Maybe a
|
||||||
|
* lock common to both frameworks?
|
||||||
|
*/
|
||||||
|
ok_for_pinctrl =
|
||||||
|
pinctrl_gpio_can_use_line(gc->base + info->line_offset);
|
||||||
|
|
||||||
spin_lock_irqsave(&gpio_lock, flags);
|
spin_lock_irqsave(&gpio_lock, flags);
|
||||||
|
|
||||||
if (desc->name) {
|
if (desc->name) {
|
||||||
|
@ -1186,7 +1197,7 @@ static void gpio_desc_to_lineinfo(struct gpio_desc *desc,
|
||||||
test_bit(FLAG_USED_AS_IRQ, &desc->flags) ||
|
test_bit(FLAG_USED_AS_IRQ, &desc->flags) ||
|
||||||
test_bit(FLAG_EXPORT, &desc->flags) ||
|
test_bit(FLAG_EXPORT, &desc->flags) ||
|
||||||
test_bit(FLAG_SYSFS, &desc->flags) ||
|
test_bit(FLAG_SYSFS, &desc->flags) ||
|
||||||
!pinctrl_gpio_can_use_line(gc->base + info->line_offset))
|
!ok_for_pinctrl)
|
||||||
info->flags |= GPIOLINE_FLAG_KERNEL;
|
info->flags |= GPIOLINE_FLAG_KERNEL;
|
||||||
if (test_bit(FLAG_IS_OUT, &desc->flags))
|
if (test_bit(FLAG_IS_OUT, &desc->flags))
|
||||||
info->flags |= GPIOLINE_FLAG_IS_OUT;
|
info->flags |= GPIOLINE_FLAG_IS_OUT;
|
||||||
|
@ -1227,6 +1238,7 @@ static long gpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
||||||
void __user *ip = (void __user *)arg;
|
void __user *ip = (void __user *)arg;
|
||||||
struct gpio_desc *desc;
|
struct gpio_desc *desc;
|
||||||
__u32 offset;
|
__u32 offset;
|
||||||
|
int hwgpio;
|
||||||
|
|
||||||
/* We fail any subsequent ioctl():s when the chip is gone */
|
/* We fail any subsequent ioctl():s when the chip is gone */
|
||||||
if (!gc)
|
if (!gc)
|
||||||
|
@ -1259,13 +1271,19 @@ static long gpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
||||||
if (IS_ERR(desc))
|
if (IS_ERR(desc))
|
||||||
return PTR_ERR(desc);
|
return PTR_ERR(desc);
|
||||||
|
|
||||||
|
hwgpio = gpio_chip_hwgpio(desc);
|
||||||
|
|
||||||
|
if (cmd == GPIO_GET_LINEINFO_WATCH_IOCTL &&
|
||||||
|
test_bit(hwgpio, priv->watched_lines))
|
||||||
|
return -EBUSY;
|
||||||
|
|
||||||
gpio_desc_to_lineinfo(desc, &lineinfo);
|
gpio_desc_to_lineinfo(desc, &lineinfo);
|
||||||
|
|
||||||
if (copy_to_user(ip, &lineinfo, sizeof(lineinfo)))
|
if (copy_to_user(ip, &lineinfo, sizeof(lineinfo)))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
if (cmd == GPIO_GET_LINEINFO_WATCH_IOCTL)
|
if (cmd == GPIO_GET_LINEINFO_WATCH_IOCTL)
|
||||||
set_bit(gpio_chip_hwgpio(desc), priv->watched_lines);
|
set_bit(hwgpio, priv->watched_lines);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
} else if (cmd == GPIO_GET_LINEHANDLE_IOCTL) {
|
} else if (cmd == GPIO_GET_LINEHANDLE_IOCTL) {
|
||||||
|
@ -1280,7 +1298,12 @@ static long gpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
||||||
if (IS_ERR(desc))
|
if (IS_ERR(desc))
|
||||||
return PTR_ERR(desc);
|
return PTR_ERR(desc);
|
||||||
|
|
||||||
clear_bit(gpio_chip_hwgpio(desc), priv->watched_lines);
|
hwgpio = gpio_chip_hwgpio(desc);
|
||||||
|
|
||||||
|
if (!test_bit(hwgpio, priv->watched_lines))
|
||||||
|
return -EBUSY;
|
||||||
|
|
||||||
|
clear_bit(hwgpio, priv->watched_lines);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -5289,8 +5312,9 @@ static int __init gpiolib_dev_init(void)
|
||||||
gpiolib_initialized = true;
|
gpiolib_initialized = true;
|
||||||
gpiochip_setup_devs();
|
gpiochip_setup_devs();
|
||||||
|
|
||||||
if (IS_ENABLED(CONFIG_OF_DYNAMIC))
|
#if IS_ENABLED(CONFIG_OF_DYNAMIC) && IS_ENABLED(CONFIG_OF_GPIO)
|
||||||
WARN_ON(of_reconfig_notifier_register(&gpio_of_notifier));
|
WARN_ON(of_reconfig_notifier_register(&gpio_of_notifier));
|
||||||
|
#endif /* CONFIG_OF_DYNAMIC && CONFIG_OF_GPIO */
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -945,6 +945,7 @@ struct amdgpu_device {
|
||||||
|
|
||||||
/* s3/s4 mask */
|
/* s3/s4 mask */
|
||||||
bool in_suspend;
|
bool in_suspend;
|
||||||
|
bool in_hibernate;
|
||||||
|
|
||||||
/* record last mm index being written through WREG32*/
|
/* record last mm index being written through WREG32*/
|
||||||
unsigned long last_mm_index;
|
unsigned long last_mm_index;
|
||||||
|
|
|
@ -1343,7 +1343,7 @@ int amdgpu_amdkfd_gpuvm_free_memory_of_gpu(
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Free the BO*/
|
/* Free the BO*/
|
||||||
amdgpu_bo_unref(&mem->bo);
|
drm_gem_object_put_unlocked(&mem->bo->tbo.base);
|
||||||
mutex_destroy(&mem->lock);
|
mutex_destroy(&mem->lock);
|
||||||
kfree(mem);
|
kfree(mem);
|
||||||
|
|
||||||
|
@ -1688,7 +1688,8 @@ int amdgpu_amdkfd_gpuvm_import_dmabuf(struct kgd_dev *kgd,
|
||||||
| KFD_IOC_ALLOC_MEM_FLAGS_WRITABLE
|
| KFD_IOC_ALLOC_MEM_FLAGS_WRITABLE
|
||||||
| KFD_IOC_ALLOC_MEM_FLAGS_EXECUTABLE;
|
| KFD_IOC_ALLOC_MEM_FLAGS_EXECUTABLE;
|
||||||
|
|
||||||
(*mem)->bo = amdgpu_bo_ref(bo);
|
drm_gem_object_get(&bo->tbo.base);
|
||||||
|
(*mem)->bo = bo;
|
||||||
(*mem)->va = va;
|
(*mem)->va = va;
|
||||||
(*mem)->domain = (bo->preferred_domains & AMDGPU_GEM_DOMAIN_VRAM) ?
|
(*mem)->domain = (bo->preferred_domains & AMDGPU_GEM_DOMAIN_VRAM) ?
|
||||||
AMDGPU_GEM_DOMAIN_VRAM : AMDGPU_GEM_DOMAIN_GTT;
|
AMDGPU_GEM_DOMAIN_VRAM : AMDGPU_GEM_DOMAIN_GTT;
|
||||||
|
|
|
@ -3372,15 +3372,12 @@ int amdgpu_device_suspend(struct drm_device *dev, bool fbcon)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
amdgpu_device_set_pg_state(adev, AMD_PG_STATE_UNGATE);
|
|
||||||
amdgpu_device_set_cg_state(adev, AMD_CG_STATE_UNGATE);
|
|
||||||
|
|
||||||
amdgpu_amdkfd_suspend(adev, !fbcon);
|
|
||||||
|
|
||||||
amdgpu_ras_suspend(adev);
|
amdgpu_ras_suspend(adev);
|
||||||
|
|
||||||
r = amdgpu_device_ip_suspend_phase1(adev);
|
r = amdgpu_device_ip_suspend_phase1(adev);
|
||||||
|
|
||||||
|
amdgpu_amdkfd_suspend(adev, !fbcon);
|
||||||
|
|
||||||
/* evict vram memory */
|
/* evict vram memory */
|
||||||
amdgpu_bo_evict_vram(adev);
|
amdgpu_bo_evict_vram(adev);
|
||||||
|
|
||||||
|
|
|
@ -1181,7 +1181,9 @@ static int amdgpu_pmops_freeze(struct device *dev)
|
||||||
struct amdgpu_device *adev = drm_dev->dev_private;
|
struct amdgpu_device *adev = drm_dev->dev_private;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
adev->in_hibernate = true;
|
||||||
r = amdgpu_device_suspend(drm_dev, true);
|
r = amdgpu_device_suspend(drm_dev, true);
|
||||||
|
adev->in_hibernate = false;
|
||||||
if (r)
|
if (r)
|
||||||
return r;
|
return r;
|
||||||
return amdgpu_asic_reset(adev);
|
return amdgpu_asic_reset(adev);
|
||||||
|
|
|
@ -133,8 +133,7 @@ static int amdgpufb_create_pinned_object(struct amdgpu_fbdev *rfbdev,
|
||||||
u32 cpp;
|
u32 cpp;
|
||||||
u64 flags = AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED |
|
u64 flags = AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED |
|
||||||
AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS |
|
AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS |
|
||||||
AMDGPU_GEM_CREATE_VRAM_CLEARED |
|
AMDGPU_GEM_CREATE_VRAM_CLEARED;
|
||||||
AMDGPU_GEM_CREATE_CPU_GTT_USWC;
|
|
||||||
|
|
||||||
info = drm_get_format_info(adev->ddev, mode_cmd);
|
info = drm_get_format_info(adev->ddev, mode_cmd);
|
||||||
cpp = info->cpp[0];
|
cpp = info->cpp[0];
|
||||||
|
|
|
@ -4273,7 +4273,7 @@ static int gfx_v10_0_update_gfx_clock_gating(struct amdgpu_device *adev,
|
||||||
/* === CGCG /CGLS for GFX 3D Only === */
|
/* === CGCG /CGLS for GFX 3D Only === */
|
||||||
gfx_v10_0_update_3d_clock_gating(adev, enable);
|
gfx_v10_0_update_3d_clock_gating(adev, enable);
|
||||||
/* === MGCG + MGLS === */
|
/* === MGCG + MGLS === */
|
||||||
/* gfx_v10_0_update_medium_grain_clock_gating(adev, enable); */
|
gfx_v10_0_update_medium_grain_clock_gating(adev, enable);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (adev->cg_flags &
|
if (adev->cg_flags &
|
||||||
|
@ -4353,11 +4353,7 @@ static int gfx_v10_0_set_powergating_state(void *handle,
|
||||||
switch (adev->asic_type) {
|
switch (adev->asic_type) {
|
||||||
case CHIP_NAVI10:
|
case CHIP_NAVI10:
|
||||||
case CHIP_NAVI14:
|
case CHIP_NAVI14:
|
||||||
if (!enable) {
|
amdgpu_gfx_off_ctrl(adev, enable);
|
||||||
amdgpu_gfx_off_ctrl(adev, false);
|
|
||||||
cancel_delayed_work_sync(&adev->gfx.gfx_off_delay_work);
|
|
||||||
} else
|
|
||||||
amdgpu_gfx_off_ctrl(adev, true);
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -4918,6 +4914,19 @@ static void gfx_v10_0_ring_emit_reg_write_reg_wait(struct amdgpu_ring *ring,
|
||||||
ref, mask);
|
ref, mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void gfx_v10_0_ring_soft_recovery(struct amdgpu_ring *ring,
|
||||||
|
unsigned vmid)
|
||||||
|
{
|
||||||
|
struct amdgpu_device *adev = ring->adev;
|
||||||
|
uint32_t value = 0;
|
||||||
|
|
||||||
|
value = REG_SET_FIELD(value, SQ_CMD, CMD, 0x03);
|
||||||
|
value = REG_SET_FIELD(value, SQ_CMD, MODE, 0x01);
|
||||||
|
value = REG_SET_FIELD(value, SQ_CMD, CHECK_VMID, 1);
|
||||||
|
value = REG_SET_FIELD(value, SQ_CMD, VM_ID, vmid);
|
||||||
|
WREG32_SOC15(GC, 0, mmSQ_CMD, value);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gfx_v10_0_set_gfx_eop_interrupt_state(struct amdgpu_device *adev,
|
gfx_v10_0_set_gfx_eop_interrupt_state(struct amdgpu_device *adev,
|
||||||
uint32_t me, uint32_t pipe,
|
uint32_t me, uint32_t pipe,
|
||||||
|
@ -5309,6 +5318,7 @@ static const struct amdgpu_ring_funcs gfx_v10_0_ring_funcs_gfx = {
|
||||||
.emit_wreg = gfx_v10_0_ring_emit_wreg,
|
.emit_wreg = gfx_v10_0_ring_emit_wreg,
|
||||||
.emit_reg_wait = gfx_v10_0_ring_emit_reg_wait,
|
.emit_reg_wait = gfx_v10_0_ring_emit_reg_wait,
|
||||||
.emit_reg_write_reg_wait = gfx_v10_0_ring_emit_reg_write_reg_wait,
|
.emit_reg_write_reg_wait = gfx_v10_0_ring_emit_reg_write_reg_wait,
|
||||||
|
.soft_recovery = gfx_v10_0_ring_soft_recovery,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct amdgpu_ring_funcs gfx_v10_0_ring_funcs_compute = {
|
static const struct amdgpu_ring_funcs gfx_v10_0_ring_funcs_compute = {
|
||||||
|
|
|
@ -1236,6 +1236,8 @@ static const struct amdgpu_gfxoff_quirk amdgpu_gfxoff_quirk_list[] = {
|
||||||
{ 0x1002, 0x15dd, 0x1002, 0x15dd, 0xc8 },
|
{ 0x1002, 0x15dd, 0x1002, 0x15dd, 0xc8 },
|
||||||
/* https://bugzilla.kernel.org/show_bug.cgi?id=207171 */
|
/* https://bugzilla.kernel.org/show_bug.cgi?id=207171 */
|
||||||
{ 0x1002, 0x15dd, 0x103c, 0x83e7, 0xd3 },
|
{ 0x1002, 0x15dd, 0x103c, 0x83e7, 0xd3 },
|
||||||
|
/* GFXOFF is unstable on C6 parts with a VBIOS 113-RAVEN-114 */
|
||||||
|
{ 0x1002, 0x15dd, 0x1002, 0x15dd, 0xc6 },
|
||||||
{ 0, 0, 0, 0, 0 },
|
{ 0, 0, 0, 0, 0 },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -5025,10 +5027,9 @@ static int gfx_v9_0_set_powergating_state(void *handle,
|
||||||
switch (adev->asic_type) {
|
switch (adev->asic_type) {
|
||||||
case CHIP_RAVEN:
|
case CHIP_RAVEN:
|
||||||
case CHIP_RENOIR:
|
case CHIP_RENOIR:
|
||||||
if (!enable) {
|
if (!enable)
|
||||||
amdgpu_gfx_off_ctrl(adev, false);
|
amdgpu_gfx_off_ctrl(adev, false);
|
||||||
cancel_delayed_work_sync(&adev->gfx.gfx_off_delay_work);
|
|
||||||
}
|
|
||||||
if (adev->pg_flags & AMD_PG_SUPPORT_RLC_SMU_HS) {
|
if (adev->pg_flags & AMD_PG_SUPPORT_RLC_SMU_HS) {
|
||||||
gfx_v9_0_enable_sck_slow_down_on_power_up(adev, true);
|
gfx_v9_0_enable_sck_slow_down_on_power_up(adev, true);
|
||||||
gfx_v9_0_enable_sck_slow_down_on_power_down(adev, true);
|
gfx_v9_0_enable_sck_slow_down_on_power_down(adev, true);
|
||||||
|
@ -5052,12 +5053,7 @@ static int gfx_v9_0_set_powergating_state(void *handle,
|
||||||
amdgpu_gfx_off_ctrl(adev, true);
|
amdgpu_gfx_off_ctrl(adev, true);
|
||||||
break;
|
break;
|
||||||
case CHIP_VEGA12:
|
case CHIP_VEGA12:
|
||||||
if (!enable) {
|
amdgpu_gfx_off_ctrl(adev, enable);
|
||||||
amdgpu_gfx_off_ctrl(adev, false);
|
|
||||||
cancel_delayed_work_sync(&adev->gfx.gfx_off_delay_work);
|
|
||||||
} else {
|
|
||||||
amdgpu_gfx_off_ctrl(adev, true);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -441,7 +441,7 @@ static void dm_vupdate_high_irq(void *interrupt_params)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* dm_crtc_high_irq() - Handles CRTC interrupt
|
* dm_crtc_high_irq() - Handles CRTC interrupt
|
||||||
* @interrupt_params: ignored
|
* @interrupt_params: used for determining the CRTC instance
|
||||||
*
|
*
|
||||||
* Handles the CRTC/VSYNC interrupt by notfying DRM's VBLANK
|
* Handles the CRTC/VSYNC interrupt by notfying DRM's VBLANK
|
||||||
* event handler.
|
* event handler.
|
||||||
|
@ -455,70 +455,6 @@ static void dm_crtc_high_irq(void *interrupt_params)
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
acrtc = get_crtc_by_otg_inst(adev, irq_params->irq_src - IRQ_TYPE_VBLANK);
|
acrtc = get_crtc_by_otg_inst(adev, irq_params->irq_src - IRQ_TYPE_VBLANK);
|
||||||
|
|
||||||
if (acrtc) {
|
|
||||||
acrtc_state = to_dm_crtc_state(acrtc->base.state);
|
|
||||||
|
|
||||||
DRM_DEBUG_VBL("crtc:%d, vupdate-vrr:%d\n",
|
|
||||||
acrtc->crtc_id,
|
|
||||||
amdgpu_dm_vrr_active(acrtc_state));
|
|
||||||
|
|
||||||
/* Core vblank handling at start of front-porch is only possible
|
|
||||||
* in non-vrr mode, as only there vblank timestamping will give
|
|
||||||
* valid results while done in front-porch. Otherwise defer it
|
|
||||||
* to dm_vupdate_high_irq after end of front-porch.
|
|
||||||
*/
|
|
||||||
if (!amdgpu_dm_vrr_active(acrtc_state))
|
|
||||||
drm_crtc_handle_vblank(&acrtc->base);
|
|
||||||
|
|
||||||
/* Following stuff must happen at start of vblank, for crc
|
|
||||||
* computation and below-the-range btr support in vrr mode.
|
|
||||||
*/
|
|
||||||
amdgpu_dm_crtc_handle_crc_irq(&acrtc->base);
|
|
||||||
|
|
||||||
if (acrtc_state->stream && adev->family >= AMDGPU_FAMILY_AI &&
|
|
||||||
acrtc_state->vrr_params.supported &&
|
|
||||||
acrtc_state->freesync_config.state == VRR_STATE_ACTIVE_VARIABLE) {
|
|
||||||
spin_lock_irqsave(&adev->ddev->event_lock, flags);
|
|
||||||
mod_freesync_handle_v_update(
|
|
||||||
adev->dm.freesync_module,
|
|
||||||
acrtc_state->stream,
|
|
||||||
&acrtc_state->vrr_params);
|
|
||||||
|
|
||||||
dc_stream_adjust_vmin_vmax(
|
|
||||||
adev->dm.dc,
|
|
||||||
acrtc_state->stream,
|
|
||||||
&acrtc_state->vrr_params.adjust);
|
|
||||||
spin_unlock_irqrestore(&adev->ddev->event_lock, flags);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
|
||||||
/**
|
|
||||||
* dm_dcn_crtc_high_irq() - Handles VStartup interrupt for DCN generation ASICs
|
|
||||||
* @interrupt params - interrupt parameters
|
|
||||||
*
|
|
||||||
* Notify DRM's vblank event handler at VSTARTUP
|
|
||||||
*
|
|
||||||
* Unlike DCE hardware, we trigger the handler at VSTARTUP. at which:
|
|
||||||
* * We are close enough to VUPDATE - the point of no return for hw
|
|
||||||
* * We are in the fixed portion of variable front porch when vrr is enabled
|
|
||||||
* * We are before VUPDATE, where double-buffered vrr registers are swapped
|
|
||||||
*
|
|
||||||
* It is therefore the correct place to signal vblank, send user flip events,
|
|
||||||
* and update VRR.
|
|
||||||
*/
|
|
||||||
static void dm_dcn_crtc_high_irq(void *interrupt_params)
|
|
||||||
{
|
|
||||||
struct common_irq_params *irq_params = interrupt_params;
|
|
||||||
struct amdgpu_device *adev = irq_params->adev;
|
|
||||||
struct amdgpu_crtc *acrtc;
|
|
||||||
struct dm_crtc_state *acrtc_state;
|
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
acrtc = get_crtc_by_otg_inst(adev, irq_params->irq_src - IRQ_TYPE_VBLANK);
|
|
||||||
|
|
||||||
if (!acrtc)
|
if (!acrtc)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -528,22 +464,35 @@ static void dm_dcn_crtc_high_irq(void *interrupt_params)
|
||||||
amdgpu_dm_vrr_active(acrtc_state),
|
amdgpu_dm_vrr_active(acrtc_state),
|
||||||
acrtc_state->active_planes);
|
acrtc_state->active_planes);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Core vblank handling at start of front-porch is only possible
|
||||||
|
* in non-vrr mode, as only there vblank timestamping will give
|
||||||
|
* valid results while done in front-porch. Otherwise defer it
|
||||||
|
* to dm_vupdate_high_irq after end of front-porch.
|
||||||
|
*/
|
||||||
|
if (!amdgpu_dm_vrr_active(acrtc_state))
|
||||||
|
drm_crtc_handle_vblank(&acrtc->base);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Following stuff must happen at start of vblank, for crc
|
||||||
|
* computation and below-the-range btr support in vrr mode.
|
||||||
|
*/
|
||||||
amdgpu_dm_crtc_handle_crc_irq(&acrtc->base);
|
amdgpu_dm_crtc_handle_crc_irq(&acrtc->base);
|
||||||
drm_crtc_handle_vblank(&acrtc->base);
|
|
||||||
|
/* BTR updates need to happen before VUPDATE on Vega and above. */
|
||||||
|
if (adev->family < AMDGPU_FAMILY_AI)
|
||||||
|
return;
|
||||||
|
|
||||||
spin_lock_irqsave(&adev->ddev->event_lock, flags);
|
spin_lock_irqsave(&adev->ddev->event_lock, flags);
|
||||||
|
|
||||||
if (acrtc_state->vrr_params.supported &&
|
if (acrtc_state->stream && acrtc_state->vrr_params.supported &&
|
||||||
acrtc_state->freesync_config.state == VRR_STATE_ACTIVE_VARIABLE) {
|
acrtc_state->freesync_config.state == VRR_STATE_ACTIVE_VARIABLE) {
|
||||||
mod_freesync_handle_v_update(
|
mod_freesync_handle_v_update(adev->dm.freesync_module,
|
||||||
adev->dm.freesync_module,
|
acrtc_state->stream,
|
||||||
acrtc_state->stream,
|
&acrtc_state->vrr_params);
|
||||||
&acrtc_state->vrr_params);
|
|
||||||
|
|
||||||
dc_stream_adjust_vmin_vmax(
|
dc_stream_adjust_vmin_vmax(adev->dm.dc, acrtc_state->stream,
|
||||||
adev->dm.dc,
|
&acrtc_state->vrr_params.adjust);
|
||||||
acrtc_state->stream,
|
|
||||||
&acrtc_state->vrr_params.adjust);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -556,7 +505,8 @@ static void dm_dcn_crtc_high_irq(void *interrupt_params)
|
||||||
* avoid race conditions between flip programming and completion,
|
* avoid race conditions between flip programming and completion,
|
||||||
* which could cause too early flip completion events.
|
* which could cause too early flip completion events.
|
||||||
*/
|
*/
|
||||||
if (acrtc->pflip_status == AMDGPU_FLIP_SUBMITTED &&
|
if (adev->family >= AMDGPU_FAMILY_RV &&
|
||||||
|
acrtc->pflip_status == AMDGPU_FLIP_SUBMITTED &&
|
||||||
acrtc_state->active_planes == 0) {
|
acrtc_state->active_planes == 0) {
|
||||||
if (acrtc->event) {
|
if (acrtc->event) {
|
||||||
drm_crtc_send_vblank_event(&acrtc->base, acrtc->event);
|
drm_crtc_send_vblank_event(&acrtc->base, acrtc->event);
|
||||||
|
@ -568,7 +518,6 @@ static void dm_dcn_crtc_high_irq(void *interrupt_params)
|
||||||
|
|
||||||
spin_unlock_irqrestore(&adev->ddev->event_lock, flags);
|
spin_unlock_irqrestore(&adev->ddev->event_lock, flags);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
static int dm_set_clockgating_state(void *handle,
|
static int dm_set_clockgating_state(void *handle,
|
||||||
enum amd_clockgating_state state)
|
enum amd_clockgating_state state)
|
||||||
|
@ -2008,17 +1957,22 @@ void amdgpu_dm_update_connector_after_detect(
|
||||||
dc_sink_retain(aconnector->dc_sink);
|
dc_sink_retain(aconnector->dc_sink);
|
||||||
if (sink->dc_edid.length == 0) {
|
if (sink->dc_edid.length == 0) {
|
||||||
aconnector->edid = NULL;
|
aconnector->edid = NULL;
|
||||||
drm_dp_cec_unset_edid(&aconnector->dm_dp_aux.aux);
|
if (aconnector->dc_link->aux_mode) {
|
||||||
|
drm_dp_cec_unset_edid(
|
||||||
|
&aconnector->dm_dp_aux.aux);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
aconnector->edid =
|
aconnector->edid =
|
||||||
(struct edid *) sink->dc_edid.raw_edid;
|
(struct edid *)sink->dc_edid.raw_edid;
|
||||||
|
|
||||||
|
|
||||||
drm_connector_update_edid_property(connector,
|
drm_connector_update_edid_property(connector,
|
||||||
aconnector->edid);
|
aconnector->edid);
|
||||||
drm_dp_cec_set_edid(&aconnector->dm_dp_aux.aux,
|
|
||||||
aconnector->edid);
|
if (aconnector->dc_link->aux_mode)
|
||||||
|
drm_dp_cec_set_edid(&aconnector->dm_dp_aux.aux,
|
||||||
|
aconnector->edid);
|
||||||
}
|
}
|
||||||
|
|
||||||
amdgpu_dm_update_freesync_caps(connector, aconnector->edid);
|
amdgpu_dm_update_freesync_caps(connector, aconnector->edid);
|
||||||
update_connector_ext_caps(aconnector);
|
update_connector_ext_caps(aconnector);
|
||||||
} else {
|
} else {
|
||||||
|
@ -2440,8 +2394,36 @@ static int dcn10_register_irq_handlers(struct amdgpu_device *adev)
|
||||||
c_irq_params->adev = adev;
|
c_irq_params->adev = adev;
|
||||||
c_irq_params->irq_src = int_params.irq_source;
|
c_irq_params->irq_src = int_params.irq_source;
|
||||||
|
|
||||||
|
amdgpu_dm_irq_register_interrupt(
|
||||||
|
adev, &int_params, dm_crtc_high_irq, c_irq_params);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Use VUPDATE_NO_LOCK interrupt on DCN, which seems to correspond to
|
||||||
|
* the regular VUPDATE interrupt on DCE. We want DC_IRQ_SOURCE_VUPDATEx
|
||||||
|
* to trigger at end of each vblank, regardless of state of the lock,
|
||||||
|
* matching DCE behaviour.
|
||||||
|
*/
|
||||||
|
for (i = DCN_1_0__SRCID__OTG0_IHC_V_UPDATE_NO_LOCK_INTERRUPT;
|
||||||
|
i <= DCN_1_0__SRCID__OTG0_IHC_V_UPDATE_NO_LOCK_INTERRUPT + adev->mode_info.num_crtc - 1;
|
||||||
|
i++) {
|
||||||
|
r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_DCE, i, &adev->vupdate_irq);
|
||||||
|
|
||||||
|
if (r) {
|
||||||
|
DRM_ERROR("Failed to add vupdate irq id!\n");
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
int_params.int_context = INTERRUPT_HIGH_IRQ_CONTEXT;
|
||||||
|
int_params.irq_source =
|
||||||
|
dc_interrupt_to_irq_source(dc, i, 0);
|
||||||
|
|
||||||
|
c_irq_params = &adev->dm.vupdate_params[int_params.irq_source - DC_IRQ_SOURCE_VUPDATE1];
|
||||||
|
|
||||||
|
c_irq_params->adev = adev;
|
||||||
|
c_irq_params->irq_src = int_params.irq_source;
|
||||||
|
|
||||||
amdgpu_dm_irq_register_interrupt(adev, &int_params,
|
amdgpu_dm_irq_register_interrupt(adev, &int_params,
|
||||||
dm_dcn_crtc_high_irq, c_irq_params);
|
dm_vupdate_high_irq, c_irq_params);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Use GRPH_PFLIP interrupt */
|
/* Use GRPH_PFLIP interrupt */
|
||||||
|
@ -4448,10 +4430,6 @@ static inline int dm_set_vupdate_irq(struct drm_crtc *crtc, bool enable)
|
||||||
struct amdgpu_device *adev = crtc->dev->dev_private;
|
struct amdgpu_device *adev = crtc->dev->dev_private;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
/* Do not set vupdate for DCN hardware */
|
|
||||||
if (adev->family > AMDGPU_FAMILY_AI)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
irq_source = IRQ_TYPE_VUPDATE + acrtc->otg_inst;
|
irq_source = IRQ_TYPE_VUPDATE + acrtc->otg_inst;
|
||||||
|
|
||||||
rc = dc_interrupt_set(adev->dm.dc, irq_source, enable) ? 0 : -EBUSY;
|
rc = dc_interrupt_set(adev->dm.dc, irq_source, enable) ? 0 : -EBUSY;
|
||||||
|
@ -7877,6 +7855,7 @@ static int dm_update_plane_state(struct dc *dc,
|
||||||
struct drm_crtc_state *old_crtc_state, *new_crtc_state;
|
struct drm_crtc_state *old_crtc_state, *new_crtc_state;
|
||||||
struct dm_crtc_state *dm_new_crtc_state, *dm_old_crtc_state;
|
struct dm_crtc_state *dm_new_crtc_state, *dm_old_crtc_state;
|
||||||
struct dm_plane_state *dm_new_plane_state, *dm_old_plane_state;
|
struct dm_plane_state *dm_new_plane_state, *dm_old_plane_state;
|
||||||
|
struct amdgpu_crtc *new_acrtc;
|
||||||
bool needs_reset;
|
bool needs_reset;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
|
@ -7886,9 +7865,30 @@ static int dm_update_plane_state(struct dc *dc,
|
||||||
dm_new_plane_state = to_dm_plane_state(new_plane_state);
|
dm_new_plane_state = to_dm_plane_state(new_plane_state);
|
||||||
dm_old_plane_state = to_dm_plane_state(old_plane_state);
|
dm_old_plane_state = to_dm_plane_state(old_plane_state);
|
||||||
|
|
||||||
/*TODO Implement atomic check for cursor plane */
|
/*TODO Implement better atomic check for cursor plane */
|
||||||
if (plane->type == DRM_PLANE_TYPE_CURSOR)
|
if (plane->type == DRM_PLANE_TYPE_CURSOR) {
|
||||||
|
if (!enable || !new_plane_crtc ||
|
||||||
|
drm_atomic_plane_disabling(plane->state, new_plane_state))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
new_acrtc = to_amdgpu_crtc(new_plane_crtc);
|
||||||
|
|
||||||
|
if ((new_plane_state->crtc_w > new_acrtc->max_cursor_width) ||
|
||||||
|
(new_plane_state->crtc_h > new_acrtc->max_cursor_height)) {
|
||||||
|
DRM_DEBUG_ATOMIC("Bad cursor size %d x %d\n",
|
||||||
|
new_plane_state->crtc_w, new_plane_state->crtc_h);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (new_plane_state->crtc_x <= -new_acrtc->max_cursor_width ||
|
||||||
|
new_plane_state->crtc_y <= -new_acrtc->max_cursor_height) {
|
||||||
|
DRM_DEBUG_ATOMIC("Bad cursor position %d, %d\n",
|
||||||
|
new_plane_state->crtc_x, new_plane_state->crtc_y);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
needs_reset = should_reset_plane(state, plane, old_plane_state,
|
needs_reset = should_reset_plane(state, plane, old_plane_state,
|
||||||
new_plane_state);
|
new_plane_state);
|
||||||
|
|
|
@ -398,15 +398,15 @@ static void update_config(void *handle, struct cp_psp_stream_config *config)
|
||||||
struct mod_hdcp_display *display = &hdcp_work[link_index].display;
|
struct mod_hdcp_display *display = &hdcp_work[link_index].display;
|
||||||
struct mod_hdcp_link *link = &hdcp_work[link_index].link;
|
struct mod_hdcp_link *link = &hdcp_work[link_index].link;
|
||||||
|
|
||||||
memset(display, 0, sizeof(*display));
|
|
||||||
memset(link, 0, sizeof(*link));
|
|
||||||
|
|
||||||
display->index = aconnector->base.index;
|
|
||||||
|
|
||||||
if (config->dpms_off) {
|
if (config->dpms_off) {
|
||||||
hdcp_remove_display(hdcp_work, link_index, aconnector);
|
hdcp_remove_display(hdcp_work, link_index, aconnector);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
memset(display, 0, sizeof(*display));
|
||||||
|
memset(link, 0, sizeof(*link));
|
||||||
|
|
||||||
|
display->index = aconnector->base.index;
|
||||||
display->state = MOD_HDCP_DISPLAY_ACTIVE;
|
display->state = MOD_HDCP_DISPLAY_ACTIVE;
|
||||||
|
|
||||||
if (aconnector->dc_sink != NULL)
|
if (aconnector->dc_sink != NULL)
|
||||||
|
|
|
@ -834,11 +834,10 @@ static void disable_dangling_plane(struct dc *dc, struct dc_state *context)
|
||||||
static void wait_for_no_pipes_pending(struct dc *dc, struct dc_state *context)
|
static void wait_for_no_pipes_pending(struct dc *dc, struct dc_state *context)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int count = 0;
|
|
||||||
struct pipe_ctx *pipe;
|
|
||||||
PERF_TRACE();
|
PERF_TRACE();
|
||||||
for (i = 0; i < MAX_PIPES; i++) {
|
for (i = 0; i < MAX_PIPES; i++) {
|
||||||
pipe = &context->res_ctx.pipe_ctx[i];
|
int count = 0;
|
||||||
|
struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
|
||||||
|
|
||||||
if (!pipe->plane_state)
|
if (!pipe->plane_state)
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -3068,25 +3068,32 @@ validate_out:
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
bool dcn20_validate_bandwidth(struct dc *dc, struct dc_state *context,
|
* This must be noinline to ensure anything that deals with FP registers
|
||||||
bool fast_validate)
|
* is contained within this call; previously our compiling with hard-float
|
||||||
|
* would result in fp instructions being emitted outside of the boundaries
|
||||||
|
* of the DC_FP_START/END macros, which makes sense as the compiler has no
|
||||||
|
* idea about what is wrapped and what is not
|
||||||
|
*
|
||||||
|
* This is largely just a workaround to avoid breakage introduced with 5.6,
|
||||||
|
* ideally all fp-using code should be moved into its own file, only that
|
||||||
|
* should be compiled with hard-float, and all code exported from there
|
||||||
|
* should be strictly wrapped with DC_FP_START/END
|
||||||
|
*/
|
||||||
|
static noinline bool dcn20_validate_bandwidth_fp(struct dc *dc,
|
||||||
|
struct dc_state *context, bool fast_validate)
|
||||||
{
|
{
|
||||||
bool voltage_supported = false;
|
bool voltage_supported = false;
|
||||||
bool full_pstate_supported = false;
|
bool full_pstate_supported = false;
|
||||||
bool dummy_pstate_supported = false;
|
bool dummy_pstate_supported = false;
|
||||||
double p_state_latency_us;
|
double p_state_latency_us;
|
||||||
|
|
||||||
DC_FP_START();
|
|
||||||
p_state_latency_us = context->bw_ctx.dml.soc.dram_clock_change_latency_us;
|
p_state_latency_us = context->bw_ctx.dml.soc.dram_clock_change_latency_us;
|
||||||
context->bw_ctx.dml.soc.disable_dram_clock_change_vactive_support =
|
context->bw_ctx.dml.soc.disable_dram_clock_change_vactive_support =
|
||||||
dc->debug.disable_dram_clock_change_vactive_support;
|
dc->debug.disable_dram_clock_change_vactive_support;
|
||||||
|
|
||||||
if (fast_validate) {
|
if (fast_validate) {
|
||||||
voltage_supported = dcn20_validate_bandwidth_internal(dc, context, true);
|
return dcn20_validate_bandwidth_internal(dc, context, true);
|
||||||
|
|
||||||
DC_FP_END();
|
|
||||||
return voltage_supported;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Best case, we support full UCLK switch latency
|
// Best case, we support full UCLK switch latency
|
||||||
|
@ -3115,7 +3122,15 @@ bool dcn20_validate_bandwidth(struct dc *dc, struct dc_state *context,
|
||||||
|
|
||||||
restore_dml_state:
|
restore_dml_state:
|
||||||
context->bw_ctx.dml.soc.dram_clock_change_latency_us = p_state_latency_us;
|
context->bw_ctx.dml.soc.dram_clock_change_latency_us = p_state_latency_us;
|
||||||
|
return voltage_supported;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool dcn20_validate_bandwidth(struct dc *dc, struct dc_state *context,
|
||||||
|
bool fast_validate)
|
||||||
|
{
|
||||||
|
bool voltage_supported = false;
|
||||||
|
DC_FP_START();
|
||||||
|
voltage_supported = dcn20_validate_bandwidth_fp(dc, context, fast_validate);
|
||||||
DC_FP_END();
|
DC_FP_END();
|
||||||
return voltage_supported;
|
return voltage_supported;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1200,7 +1200,7 @@ static void dml_rq_dlg_get_dlg_params(
|
||||||
min_hratio_fact_l = 1.0;
|
min_hratio_fact_l = 1.0;
|
||||||
min_hratio_fact_c = 1.0;
|
min_hratio_fact_c = 1.0;
|
||||||
|
|
||||||
if (htaps_l <= 1)
|
if (hratio_l <= 1)
|
||||||
min_hratio_fact_l = 2.0;
|
min_hratio_fact_l = 2.0;
|
||||||
else if (htaps_l <= 6) {
|
else if (htaps_l <= 6) {
|
||||||
if ((hratio_l * 2.0) > 4.0)
|
if ((hratio_l * 2.0) > 4.0)
|
||||||
|
@ -1216,7 +1216,7 @@ static void dml_rq_dlg_get_dlg_params(
|
||||||
|
|
||||||
hscale_pixel_rate_l = min_hratio_fact_l * dppclk_freq_in_mhz;
|
hscale_pixel_rate_l = min_hratio_fact_l * dppclk_freq_in_mhz;
|
||||||
|
|
||||||
if (htaps_c <= 1)
|
if (hratio_c <= 1)
|
||||||
min_hratio_fact_c = 2.0;
|
min_hratio_fact_c = 2.0;
|
||||||
else if (htaps_c <= 6) {
|
else if (htaps_c <= 6) {
|
||||||
if ((hratio_c * 2.0) > 4.0)
|
if ((hratio_c * 2.0) > 4.0)
|
||||||
|
@ -1522,8 +1522,8 @@ static void dml_rq_dlg_get_dlg_params(
|
||||||
|
|
||||||
disp_dlg_regs->refcyc_per_vm_group_vblank = get_refcyc_per_vm_group_vblank(mode_lib, e2e_pipe_param, num_pipes, pipe_idx) * refclk_freq_in_mhz;
|
disp_dlg_regs->refcyc_per_vm_group_vblank = get_refcyc_per_vm_group_vblank(mode_lib, e2e_pipe_param, num_pipes, pipe_idx) * refclk_freq_in_mhz;
|
||||||
disp_dlg_regs->refcyc_per_vm_group_flip = get_refcyc_per_vm_group_flip(mode_lib, e2e_pipe_param, num_pipes, pipe_idx) * refclk_freq_in_mhz;
|
disp_dlg_regs->refcyc_per_vm_group_flip = get_refcyc_per_vm_group_flip(mode_lib, e2e_pipe_param, num_pipes, pipe_idx) * refclk_freq_in_mhz;
|
||||||
disp_dlg_regs->refcyc_per_vm_req_vblank = get_refcyc_per_vm_req_vblank(mode_lib, e2e_pipe_param, num_pipes, pipe_idx) * refclk_freq_in_mhz;
|
disp_dlg_regs->refcyc_per_vm_req_vblank = get_refcyc_per_vm_req_vblank(mode_lib, e2e_pipe_param, num_pipes, pipe_idx) * refclk_freq_in_mhz * dml_pow(2, 10);
|
||||||
disp_dlg_regs->refcyc_per_vm_req_flip = get_refcyc_per_vm_req_flip(mode_lib, e2e_pipe_param, num_pipes, pipe_idx) * refclk_freq_in_mhz;
|
disp_dlg_regs->refcyc_per_vm_req_flip = get_refcyc_per_vm_req_flip(mode_lib, e2e_pipe_param, num_pipes, pipe_idx) * refclk_freq_in_mhz * dml_pow(2, 10);
|
||||||
|
|
||||||
// Clamp to max for now
|
// Clamp to max for now
|
||||||
if (disp_dlg_regs->refcyc_per_vm_group_vblank >= (unsigned int)dml_pow(2, 23))
|
if (disp_dlg_regs->refcyc_per_vm_group_vblank >= (unsigned int)dml_pow(2, 23))
|
||||||
|
|
|
@ -108,7 +108,7 @@
|
||||||
#define ASSERT(expr) ASSERT_CRITICAL(expr)
|
#define ASSERT(expr) ASSERT_CRITICAL(expr)
|
||||||
|
|
||||||
#else
|
#else
|
||||||
#define ASSERT(expr) WARN_ON(!(expr))
|
#define ASSERT(expr) WARN_ON_ONCE(!(expr))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define BREAK_TO_DEBUGGER() ASSERT(0)
|
#define BREAK_TO_DEBUGGER() ASSERT(0)
|
||||||
|
|
|
@ -319,12 +319,12 @@ static void pp_dpm_en_umd_pstate(struct pp_hwmgr *hwmgr,
|
||||||
if (*level & profile_mode_mask) {
|
if (*level & profile_mode_mask) {
|
||||||
hwmgr->saved_dpm_level = hwmgr->dpm_level;
|
hwmgr->saved_dpm_level = hwmgr->dpm_level;
|
||||||
hwmgr->en_umd_pstate = true;
|
hwmgr->en_umd_pstate = true;
|
||||||
amdgpu_device_ip_set_clockgating_state(hwmgr->adev,
|
|
||||||
AMD_IP_BLOCK_TYPE_GFX,
|
|
||||||
AMD_CG_STATE_UNGATE);
|
|
||||||
amdgpu_device_ip_set_powergating_state(hwmgr->adev,
|
amdgpu_device_ip_set_powergating_state(hwmgr->adev,
|
||||||
AMD_IP_BLOCK_TYPE_GFX,
|
AMD_IP_BLOCK_TYPE_GFX,
|
||||||
AMD_PG_STATE_UNGATE);
|
AMD_PG_STATE_UNGATE);
|
||||||
|
amdgpu_device_ip_set_clockgating_state(hwmgr->adev,
|
||||||
|
AMD_IP_BLOCK_TYPE_GFX,
|
||||||
|
AMD_CG_STATE_UNGATE);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* exit umd pstate, restore level, enable gfx cg*/
|
/* exit umd pstate, restore level, enable gfx cg*/
|
||||||
|
|
|
@ -1476,7 +1476,7 @@ static int smu_disable_dpm(struct smu_context *smu)
|
||||||
bool use_baco = !smu->is_apu &&
|
bool use_baco = !smu->is_apu &&
|
||||||
((adev->in_gpu_reset &&
|
((adev->in_gpu_reset &&
|
||||||
(amdgpu_asic_reset_method(adev) == AMD_RESET_METHOD_BACO)) ||
|
(amdgpu_asic_reset_method(adev) == AMD_RESET_METHOD_BACO)) ||
|
||||||
(adev->in_runpm && amdgpu_asic_supports_baco(adev)));
|
((adev->in_runpm || adev->in_hibernate) && amdgpu_asic_supports_baco(adev)));
|
||||||
|
|
||||||
ret = smu_get_smc_version(smu, NULL, &smu_version);
|
ret = smu_get_smc_version(smu, NULL, &smu_version);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
|
@ -1744,12 +1744,12 @@ static int smu_enable_umd_pstate(void *handle,
|
||||||
if (*level & profile_mode_mask) {
|
if (*level & profile_mode_mask) {
|
||||||
smu_dpm_ctx->saved_dpm_level = smu_dpm_ctx->dpm_level;
|
smu_dpm_ctx->saved_dpm_level = smu_dpm_ctx->dpm_level;
|
||||||
smu_dpm_ctx->enable_umd_pstate = true;
|
smu_dpm_ctx->enable_umd_pstate = true;
|
||||||
amdgpu_device_ip_set_clockgating_state(smu->adev,
|
|
||||||
AMD_IP_BLOCK_TYPE_GFX,
|
|
||||||
AMD_CG_STATE_UNGATE);
|
|
||||||
amdgpu_device_ip_set_powergating_state(smu->adev,
|
amdgpu_device_ip_set_powergating_state(smu->adev,
|
||||||
AMD_IP_BLOCK_TYPE_GFX,
|
AMD_IP_BLOCK_TYPE_GFX,
|
||||||
AMD_PG_STATE_UNGATE);
|
AMD_PG_STATE_UNGATE);
|
||||||
|
amdgpu_device_ip_set_clockgating_state(smu->adev,
|
||||||
|
AMD_IP_BLOCK_TYPE_GFX,
|
||||||
|
AMD_CG_STATE_UNGATE);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* exit umd pstate, restore level, enable gfx cg*/
|
/* exit umd pstate, restore level, enable gfx cg*/
|
||||||
|
|
|
@ -241,8 +241,12 @@ static int drm_hdcp_request_srm(struct drm_device *drm_dev,
|
||||||
|
|
||||||
ret = request_firmware_direct(&fw, (const char *)fw_name,
|
ret = request_firmware_direct(&fw, (const char *)fw_name,
|
||||||
drm_dev->dev);
|
drm_dev->dev);
|
||||||
if (ret < 0)
|
if (ret < 0) {
|
||||||
|
*revoked_ksv_cnt = 0;
|
||||||
|
*revoked_ksv_list = NULL;
|
||||||
|
ret = 0;
|
||||||
goto exit;
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
if (fw->size && fw->data)
|
if (fw->size && fw->data)
|
||||||
ret = drm_hdcp_srm_update(fw->data, fw->size, revoked_ksv_list,
|
ret = drm_hdcp_srm_update(fw->data, fw->size, revoked_ksv_list,
|
||||||
|
@ -287,6 +291,8 @@ int drm_hdcp_check_ksvs_revoked(struct drm_device *drm_dev, u8 *ksvs,
|
||||||
|
|
||||||
ret = drm_hdcp_request_srm(drm_dev, &revoked_ksv_list,
|
ret = drm_hdcp_request_srm(drm_dev, &revoked_ksv_list,
|
||||||
&revoked_ksv_cnt);
|
&revoked_ksv_cnt);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
/* revoked_ksv_cnt will be zero when above function failed */
|
/* revoked_ksv_cnt will be zero when above function failed */
|
||||||
for (i = 0; i < revoked_ksv_cnt; i++)
|
for (i = 0; i < revoked_ksv_cnt; i++)
|
||||||
|
|
|
@ -485,8 +485,7 @@ static int intel_fbc_alloc_cfb(struct drm_i915_private *dev_priv,
|
||||||
if (!ret)
|
if (!ret)
|
||||||
goto err_llb;
|
goto err_llb;
|
||||||
else if (ret > 1) {
|
else if (ret > 1) {
|
||||||
DRM_INFO("Reducing the compressed framebuffer size. This may lead to less power savings than a non-reduced-size. Try to increase stolen memory size if available in BIOS.\n");
|
DRM_INFO_ONCE("Reducing the compressed framebuffer size. This may lead to less power savings than a non-reduced-size. Try to increase stolen memory size if available in BIOS.\n");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fbc->threshold = ret;
|
fbc->threshold = ret;
|
||||||
|
|
|
@ -368,7 +368,6 @@ static void i915_gem_object_bump_inactive_ggtt(struct drm_i915_gem_object *obj)
|
||||||
struct drm_i915_private *i915 = to_i915(obj->base.dev);
|
struct drm_i915_private *i915 = to_i915(obj->base.dev);
|
||||||
struct i915_vma *vma;
|
struct i915_vma *vma;
|
||||||
|
|
||||||
GEM_BUG_ON(!i915_gem_object_has_pinned_pages(obj));
|
|
||||||
if (!atomic_read(&obj->bind_count))
|
if (!atomic_read(&obj->bind_count))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -400,12 +399,8 @@ static void i915_gem_object_bump_inactive_ggtt(struct drm_i915_gem_object *obj)
|
||||||
void
|
void
|
||||||
i915_gem_object_unpin_from_display_plane(struct i915_vma *vma)
|
i915_gem_object_unpin_from_display_plane(struct i915_vma *vma)
|
||||||
{
|
{
|
||||||
struct drm_i915_gem_object *obj = vma->obj;
|
|
||||||
|
|
||||||
assert_object_held(obj);
|
|
||||||
|
|
||||||
/* Bump the LRU to try and avoid premature eviction whilst flipping */
|
/* Bump the LRU to try and avoid premature eviction whilst flipping */
|
||||||
i915_gem_object_bump_inactive_ggtt(obj);
|
i915_gem_object_bump_inactive_ggtt(vma->obj);
|
||||||
|
|
||||||
i915_vma_unpin(vma);
|
i915_vma_unpin(vma);
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,7 +69,13 @@ struct intel_context {
|
||||||
#define CONTEXT_NOPREEMPT 7
|
#define CONTEXT_NOPREEMPT 7
|
||||||
|
|
||||||
u32 *lrc_reg_state;
|
u32 *lrc_reg_state;
|
||||||
u64 lrc_desc;
|
union {
|
||||||
|
struct {
|
||||||
|
u32 lrca;
|
||||||
|
u32 ccid;
|
||||||
|
};
|
||||||
|
u64 desc;
|
||||||
|
} lrc;
|
||||||
u32 tag; /* cookie passed to HW to track this context on submission */
|
u32 tag; /* cookie passed to HW to track this context on submission */
|
||||||
|
|
||||||
/* Time on GPU as tracked by the hw. */
|
/* Time on GPU as tracked by the hw. */
|
||||||
|
|
|
@ -333,13 +333,4 @@ intel_engine_has_preempt_reset(const struct intel_engine_cs *engine)
|
||||||
return intel_engine_has_preemption(engine);
|
return intel_engine_has_preemption(engine);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool
|
|
||||||
intel_engine_has_timeslices(const struct intel_engine_cs *engine)
|
|
||||||
{
|
|
||||||
if (!IS_ACTIVE(CONFIG_DRM_I915_TIMESLICE_DURATION))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return intel_engine_has_semaphores(engine);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* _INTEL_RINGBUFFER_H_ */
|
#endif /* _INTEL_RINGBUFFER_H_ */
|
||||||
|
|
|
@ -1295,6 +1295,12 @@ static void intel_engine_print_registers(struct intel_engine_cs *engine,
|
||||||
|
|
||||||
if (engine->id == RENDER_CLASS && IS_GEN_RANGE(dev_priv, 4, 7))
|
if (engine->id == RENDER_CLASS && IS_GEN_RANGE(dev_priv, 4, 7))
|
||||||
drm_printf(m, "\tCCID: 0x%08x\n", ENGINE_READ(engine, CCID));
|
drm_printf(m, "\tCCID: 0x%08x\n", ENGINE_READ(engine, CCID));
|
||||||
|
if (HAS_EXECLISTS(dev_priv)) {
|
||||||
|
drm_printf(m, "\tEL_STAT_HI: 0x%08x\n",
|
||||||
|
ENGINE_READ(engine, RING_EXECLIST_STATUS_HI));
|
||||||
|
drm_printf(m, "\tEL_STAT_LO: 0x%08x\n",
|
||||||
|
ENGINE_READ(engine, RING_EXECLIST_STATUS_LO));
|
||||||
|
}
|
||||||
drm_printf(m, "\tRING_START: 0x%08x\n",
|
drm_printf(m, "\tRING_START: 0x%08x\n",
|
||||||
ENGINE_READ(engine, RING_START));
|
ENGINE_READ(engine, RING_START));
|
||||||
drm_printf(m, "\tRING_HEAD: 0x%08x\n",
|
drm_printf(m, "\tRING_HEAD: 0x%08x\n",
|
||||||
|
|
|
@ -156,6 +156,20 @@ struct intel_engine_execlists {
|
||||||
*/
|
*/
|
||||||
struct i915_priolist default_priolist;
|
struct i915_priolist default_priolist;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ccid: identifier for contexts submitted to this engine
|
||||||
|
*/
|
||||||
|
u32 ccid;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @yield: CCID at the time of the last semaphore-wait interrupt.
|
||||||
|
*
|
||||||
|
* Instead of leaving a semaphore busy-spinning on an engine, we would
|
||||||
|
* like to switch to another ready context, i.e. yielding the semaphore
|
||||||
|
* timeslice.
|
||||||
|
*/
|
||||||
|
u32 yield;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @error_interrupt: CS Master EIR
|
* @error_interrupt: CS Master EIR
|
||||||
*
|
*
|
||||||
|
@ -295,8 +309,7 @@ struct intel_engine_cs {
|
||||||
u32 context_size;
|
u32 context_size;
|
||||||
u32 mmio_base;
|
u32 mmio_base;
|
||||||
|
|
||||||
unsigned int context_tag;
|
unsigned long context_tag;
|
||||||
#define NUM_CONTEXT_TAG roundup_pow_of_two(2 * EXECLIST_MAX_PORTS)
|
|
||||||
|
|
||||||
struct rb_node uabi_node;
|
struct rb_node uabi_node;
|
||||||
|
|
||||||
|
@ -483,10 +496,11 @@ struct intel_engine_cs {
|
||||||
#define I915_ENGINE_SUPPORTS_STATS BIT(1)
|
#define I915_ENGINE_SUPPORTS_STATS BIT(1)
|
||||||
#define I915_ENGINE_HAS_PREEMPTION BIT(2)
|
#define I915_ENGINE_HAS_PREEMPTION BIT(2)
|
||||||
#define I915_ENGINE_HAS_SEMAPHORES BIT(3)
|
#define I915_ENGINE_HAS_SEMAPHORES BIT(3)
|
||||||
#define I915_ENGINE_NEEDS_BREADCRUMB_TASKLET BIT(4)
|
#define I915_ENGINE_HAS_TIMESLICES BIT(4)
|
||||||
#define I915_ENGINE_IS_VIRTUAL BIT(5)
|
#define I915_ENGINE_NEEDS_BREADCRUMB_TASKLET BIT(5)
|
||||||
#define I915_ENGINE_HAS_RELATIVE_MMIO BIT(6)
|
#define I915_ENGINE_IS_VIRTUAL BIT(6)
|
||||||
#define I915_ENGINE_REQUIRES_CMD_PARSER BIT(7)
|
#define I915_ENGINE_HAS_RELATIVE_MMIO BIT(7)
|
||||||
|
#define I915_ENGINE_REQUIRES_CMD_PARSER BIT(8)
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -584,6 +598,15 @@ intel_engine_has_semaphores(const struct intel_engine_cs *engine)
|
||||||
return engine->flags & I915_ENGINE_HAS_SEMAPHORES;
|
return engine->flags & I915_ENGINE_HAS_SEMAPHORES;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool
|
||||||
|
intel_engine_has_timeslices(const struct intel_engine_cs *engine)
|
||||||
|
{
|
||||||
|
if (!IS_ACTIVE(CONFIG_DRM_I915_TIMESLICE_DURATION))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return engine->flags & I915_ENGINE_HAS_TIMESLICES;
|
||||||
|
}
|
||||||
|
|
||||||
static inline bool
|
static inline bool
|
||||||
intel_engine_needs_breadcrumb_tasklet(const struct intel_engine_cs *engine)
|
intel_engine_needs_breadcrumb_tasklet(const struct intel_engine_cs *engine)
|
||||||
{
|
{
|
||||||
|
|
|
@ -39,6 +39,15 @@ cs_irq_handler(struct intel_engine_cs *engine, u32 iir)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (iir & GT_WAIT_SEMAPHORE_INTERRUPT) {
|
||||||
|
WRITE_ONCE(engine->execlists.yield,
|
||||||
|
ENGINE_READ_FW(engine, RING_EXECLIST_STATUS_HI));
|
||||||
|
ENGINE_TRACE(engine, "semaphore yield: %08x\n",
|
||||||
|
engine->execlists.yield);
|
||||||
|
if (del_timer(&engine->execlists.timer))
|
||||||
|
tasklet = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (iir & GT_CONTEXT_SWITCH_INTERRUPT)
|
if (iir & GT_CONTEXT_SWITCH_INTERRUPT)
|
||||||
tasklet = true;
|
tasklet = true;
|
||||||
|
|
||||||
|
@ -228,7 +237,8 @@ void gen11_gt_irq_postinstall(struct intel_gt *gt)
|
||||||
const u32 irqs =
|
const u32 irqs =
|
||||||
GT_CS_MASTER_ERROR_INTERRUPT |
|
GT_CS_MASTER_ERROR_INTERRUPT |
|
||||||
GT_RENDER_USER_INTERRUPT |
|
GT_RENDER_USER_INTERRUPT |
|
||||||
GT_CONTEXT_SWITCH_INTERRUPT;
|
GT_CONTEXT_SWITCH_INTERRUPT |
|
||||||
|
GT_WAIT_SEMAPHORE_INTERRUPT;
|
||||||
struct intel_uncore *uncore = gt->uncore;
|
struct intel_uncore *uncore = gt->uncore;
|
||||||
const u32 dmask = irqs << 16 | irqs;
|
const u32 dmask = irqs << 16 | irqs;
|
||||||
const u32 smask = irqs << 16;
|
const u32 smask = irqs << 16;
|
||||||
|
@ -366,7 +376,8 @@ void gen8_gt_irq_postinstall(struct intel_gt *gt)
|
||||||
const u32 irqs =
|
const u32 irqs =
|
||||||
GT_CS_MASTER_ERROR_INTERRUPT |
|
GT_CS_MASTER_ERROR_INTERRUPT |
|
||||||
GT_RENDER_USER_INTERRUPT |
|
GT_RENDER_USER_INTERRUPT |
|
||||||
GT_CONTEXT_SWITCH_INTERRUPT;
|
GT_CONTEXT_SWITCH_INTERRUPT |
|
||||||
|
GT_WAIT_SEMAPHORE_INTERRUPT;
|
||||||
const u32 gt_interrupts[] = {
|
const u32 gt_interrupts[] = {
|
||||||
irqs << GEN8_RCS_IRQ_SHIFT | irqs << GEN8_BCS_IRQ_SHIFT,
|
irqs << GEN8_RCS_IRQ_SHIFT | irqs << GEN8_BCS_IRQ_SHIFT,
|
||||||
irqs << GEN8_VCS0_IRQ_SHIFT | irqs << GEN8_VCS1_IRQ_SHIFT,
|
irqs << GEN8_VCS0_IRQ_SHIFT | irqs << GEN8_VCS1_IRQ_SHIFT,
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue