mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-12-29 09:16:33 +00:00
Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
This commit is contained in:
commit
edf45f007a
4
.mailmap
4
.mailmap
@ -391,6 +391,10 @@ Uwe Kleine-König <ukleinek@strlen.de>
|
||||
Uwe Kleine-König <ukl@pengutronix.de>
|
||||
Uwe Kleine-König <Uwe.Kleine-Koenig@digi.com>
|
||||
Valdis Kletnieks <Valdis.Kletnieks@vt.edu>
|
||||
Vasily Averin <vasily.averin@linux.dev> <vvs@virtuozzo.com>
|
||||
Vasily Averin <vasily.averin@linux.dev> <vvs@openvz.org>
|
||||
Vasily Averin <vasily.averin@linux.dev> <vvs@parallels.com>
|
||||
Vasily Averin <vasily.averin@linux.dev> <vvs@sw.ru>
|
||||
Vinod Koul <vkoul@kernel.org> <vinod.koul@intel.com>
|
||||
Vinod Koul <vkoul@kernel.org> <vinod.koul@linux.intel.com>
|
||||
Vinod Koul <vkoul@kernel.org> <vkoul@infradead.org>
|
||||
|
@ -116,7 +116,7 @@ Description:
|
||||
<value>[ForceIf:<attribute>=<value>]
|
||||
<value>[ForceIfNot:<attribute>=<value>]
|
||||
|
||||
For example:
|
||||
For example::
|
||||
|
||||
LegacyOrom/dell_value_modifier has value:
|
||||
Disabled[ForceIf:SecureBoot=Enabled]
|
||||
@ -212,7 +212,7 @@ Description:
|
||||
the next boot.
|
||||
|
||||
Lenovo specific class extensions
|
||||
------------------------------
|
||||
--------------------------------
|
||||
|
||||
On Lenovo systems the following additional settings are available:
|
||||
|
||||
@ -246,9 +246,7 @@ Description:
|
||||
that is being referenced (e.g hdd0, hdd1 etc)
|
||||
This attribute defaults to device 0.
|
||||
|
||||
certificate:
|
||||
signature:
|
||||
save_signature:
|
||||
certificate, signature, save_signature:
|
||||
These attributes are used for certificate based authentication. This is
|
||||
used in conjunction with a signing server as an alternative to password
|
||||
based authentication.
|
||||
@ -257,22 +255,27 @@ Description:
|
||||
The attributes can be displayed to check the stored value.
|
||||
|
||||
Some usage examples:
|
||||
Installing a certificate to enable feature:
|
||||
echo <supervisor password > authentication/Admin/current_password
|
||||
echo <signed certificate> > authentication/Admin/certificate
|
||||
|
||||
Updating the installed certificate:
|
||||
echo <signature> > authentication/Admin/signature
|
||||
echo <signed certificate> > authentication/Admin/certificate
|
||||
Installing a certificate to enable feature::
|
||||
|
||||
Removing the installed certificate:
|
||||
echo <signature> > authentication/Admin/signature
|
||||
echo '' > authentication/Admin/certificate
|
||||
echo "supervisor password" > authentication/Admin/current_password
|
||||
echo "signed certificate" > authentication/Admin/certificate
|
||||
|
||||
Changing a BIOS setting:
|
||||
echo <signature> > authentication/Admin/signature
|
||||
echo <save signature> > authentication/Admin/save_signature
|
||||
echo Enable > attribute/PasswordBeep/current_value
|
||||
Updating the installed certificate::
|
||||
|
||||
echo "signature" > authentication/Admin/signature
|
||||
echo "signed certificate" > authentication/Admin/certificate
|
||||
|
||||
Removing the installed certificate::
|
||||
|
||||
echo "signature" > authentication/Admin/signature
|
||||
echo "" > authentication/Admin/certificate
|
||||
|
||||
Changing a BIOS setting::
|
||||
|
||||
echo "signature" > authentication/Admin/signature
|
||||
echo "save signature" > authentication/Admin/save_signature
|
||||
echo Enable > attribute/PasswordBeep/current_value
|
||||
|
||||
You cannot enable certificate authentication if a supervisor password
|
||||
has not been set.
|
||||
@ -288,9 +291,10 @@ Description:
|
||||
certificate_to_password:
|
||||
Write only attribute used to switch from certificate based authentication
|
||||
back to password based.
|
||||
Usage:
|
||||
echo <signature> > authentication/Admin/signature
|
||||
echo <password> > authentication/Admin/certificate_to_password
|
||||
Usage::
|
||||
|
||||
echo "signature" > authentication/Admin/signature
|
||||
echo "password" > authentication/Admin/certificate_to_password
|
||||
|
||||
|
||||
What: /sys/class/firmware-attributes/*/attributes/pending_reboot
|
||||
@ -345,7 +349,7 @@ Description:
|
||||
|
||||
# echo "factory" > /sys/class/firmware-attributes/*/device/attributes/reset_bios
|
||||
# cat /sys/class/firmware-attributes/*/device/attributes/reset_bios
|
||||
# builtinsafe lastknowngood [factory] custom
|
||||
builtinsafe lastknowngood [factory] custom
|
||||
|
||||
Note that any changes to this attribute requires a reboot
|
||||
for changes to take effect.
|
||||
|
@ -13,17 +13,19 @@ Description:
|
||||
Should the operation fail, one of the following error codes
|
||||
may be returned:
|
||||
|
||||
========== =====
|
||||
Error Code Cause
|
||||
---------- -----
|
||||
EIO General mailbox failure. Log may indicate cause.
|
||||
EBUSY Mailbox is owned by another agent.
|
||||
EPERM SDSI capability is not enabled in hardware.
|
||||
EPROTO Failure in mailbox protocol detected by driver.
|
||||
========== =====
|
||||
EIO General mailbox failure. Log may indicate cause.
|
||||
EBUSY Mailbox is owned by another agent.
|
||||
EPERM SDSI capability is not enabled in hardware.
|
||||
EPROTO Failure in mailbox protocol detected by driver.
|
||||
See log for details.
|
||||
EOVERFLOW For provision commands, the size of the data
|
||||
EOVERFLOW For provision commands, the size of the data
|
||||
exceeds what may be written.
|
||||
ESPIPE Seeking is not allowed.
|
||||
ETIMEDOUT Failure to complete mailbox transaction in time.
|
||||
ESPIPE Seeking is not allowed.
|
||||
ETIMEDOUT Failure to complete mailbox transaction in time.
|
||||
========== =====
|
||||
|
||||
What: /sys/bus/auxiliary/devices/intel_vsec.sdsi.X/guid
|
||||
Date: Feb 2022
|
||||
|
@ -41,13 +41,18 @@ or ``VFAT_FS``. To run ``FAT_KUNIT_TEST``, the ``.kunitconfig`` has:
|
||||
CONFIG_MSDOS_FS=y
|
||||
CONFIG_FAT_KUNIT_TEST=y
|
||||
|
||||
1. A good starting point for the ``.kunitconfig``, is the KUnit default
|
||||
config. Run the command:
|
||||
1. A good starting point for the ``.kunitconfig`` is the KUnit default config.
|
||||
You can generate it by running:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
cd $PATH_TO_LINUX_REPO
|
||||
cp tools/testing/kunit/configs/default.config .kunitconfig
|
||||
tools/testing/kunit/kunit.py config
|
||||
cat .kunit/.kunitconfig
|
||||
|
||||
.. note ::
|
||||
``.kunitconfig`` lives in the ``--build_dir`` used by kunit.py, which is
|
||||
``.kunit`` by default.
|
||||
|
||||
.. note ::
|
||||
You may want to remove CONFIG_KUNIT_ALL_TESTS from the ``.kunitconfig`` as
|
||||
|
@ -51,7 +51,6 @@ properties:
|
||||
Video port for MIPI DPI output (panel or connector).
|
||||
|
||||
required:
|
||||
- port@0
|
||||
- port@1
|
||||
|
||||
required:
|
||||
|
@ -39,7 +39,6 @@ properties:
|
||||
Video port for MIPI DPI output (panel or connector).
|
||||
|
||||
required:
|
||||
- port@0
|
||||
- port@1
|
||||
|
||||
required:
|
||||
|
@ -83,6 +83,8 @@ properties:
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- width-mm
|
||||
- height-mm
|
||||
- panel-timing
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
@ -13,9 +13,6 @@ description: |
|
||||
This describes the devicetree bindings for AVE ethernet controller
|
||||
implemented on Socionext UniPhier SoCs.
|
||||
|
||||
allOf:
|
||||
- $ref: ethernet-controller.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
@ -44,25 +41,13 @@ properties:
|
||||
minItems: 1
|
||||
maxItems: 4
|
||||
|
||||
clock-names:
|
||||
oneOf:
|
||||
- items: # for Pro4
|
||||
- const: gio
|
||||
- const: ether
|
||||
- const: ether-gb
|
||||
- const: ether-phy
|
||||
- const: ether # for others
|
||||
clock-names: true
|
||||
|
||||
resets:
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
|
||||
reset-names:
|
||||
oneOf:
|
||||
- items: # for Pro4
|
||||
- const: gio
|
||||
- const: ether
|
||||
- const: ether # for others
|
||||
reset-names: true
|
||||
|
||||
socionext,syscon-phy-mode:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle-array
|
||||
@ -78,6 +63,42 @@ properties:
|
||||
$ref: mdio.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
allOf:
|
||||
- $ref: ethernet-controller.yaml#
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: socionext,uniphier-pro4-ave4
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
minItems: 4
|
||||
maxItems: 4
|
||||
clock-names:
|
||||
items:
|
||||
- const: gio
|
||||
- const: ether
|
||||
- const: ether-gb
|
||||
- const: ether-phy
|
||||
resets:
|
||||
minItems: 2
|
||||
maxItems: 2
|
||||
reset-names:
|
||||
items:
|
||||
- const: gio
|
||||
- const: ether
|
||||
else:
|
||||
properties:
|
||||
clocks:
|
||||
maxItems: 1
|
||||
clock-names:
|
||||
const: ether
|
||||
resets:
|
||||
maxItems: 1
|
||||
reset-names:
|
||||
const: ether
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
@ -90,7 +111,7 @@ required:
|
||||
- reset-names
|
||||
- mdio
|
||||
|
||||
additionalProperties: false
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
|
@ -185,6 +185,12 @@ DMA Fence Chain
|
||||
.. kernel-doc:: include/linux/dma-fence-chain.h
|
||||
:internal:
|
||||
|
||||
DMA Fence unwrap
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
.. kernel-doc:: include/linux/dma-fence-unwrap.h
|
||||
:internal:
|
||||
|
||||
DMA Fence uABI/Sync File
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
@ -73,7 +73,7 @@ busy.
|
||||
If successful, the cache backend can then start setting up the cache. In the
|
||||
event that the initialisation fails, the cache backend should call::
|
||||
|
||||
void fscache_relinquish_cookie(struct fscache_cache *cache);
|
||||
void fscache_relinquish_cache(struct fscache_cache *cache);
|
||||
|
||||
to reset and discard the cookie.
|
||||
|
||||
@ -110,9 +110,9 @@ to withdraw them, calling::
|
||||
|
||||
on the cookie that each object belongs to. This schedules the specified cookie
|
||||
for withdrawal. This gets offloaded to a workqueue. The cache backend can
|
||||
test for completion by calling::
|
||||
wait for completion by calling::
|
||||
|
||||
bool fscache_are_objects_withdrawn(struct fscache_cookie *cache);
|
||||
void fscache_wait_for_objects(struct fscache_cache *cache);
|
||||
|
||||
Once all the cookies are withdrawn, a cache backend can withdraw all the
|
||||
volumes, calling::
|
||||
@ -125,7 +125,7 @@ outstanding accesses on the volume to complete before returning.
|
||||
When the the cache is completely withdrawn, fscache should be notified by
|
||||
calling::
|
||||
|
||||
void fscache_cache_relinquish(struct fscache_cache *cache);
|
||||
void fscache_relinquish_cache(struct fscache_cache *cache);
|
||||
|
||||
to clear fields in the cookie and discard the caller's ref on it.
|
||||
|
||||
|
@ -404,22 +404,21 @@ schedule a write of that region::
|
||||
And if an error occurs before that point is reached, the marks can be removed
|
||||
by calling::
|
||||
|
||||
void fscache_clear_page_bits(struct fscache_cookie *cookie,
|
||||
struct address_space *mapping,
|
||||
void fscache_clear_page_bits(struct address_space *mapping,
|
||||
loff_t start, size_t len,
|
||||
bool caching)
|
||||
|
||||
In both of these functions, the cookie representing the cache object to be
|
||||
written to and a pointer to the mapping to which the source pages are attached
|
||||
are passed in; start and len indicate the size of the region that's going to be
|
||||
written (it doesn't have to align to page boundaries necessarily, but it does
|
||||
have to align to DIO boundaries on the backing filesystem). The caching
|
||||
parameter indicates if caching should be skipped, and if false, the functions
|
||||
do nothing.
|
||||
In these functions, a pointer to the mapping to which the source pages are
|
||||
attached is passed in and start and len indicate the size of the region that's
|
||||
going to be written (it doesn't have to align to page boundaries necessarily,
|
||||
but it does have to align to DIO boundaries on the backing filesystem). The
|
||||
caching parameter indicates if caching should be skipped, and if false, the
|
||||
functions do nothing.
|
||||
|
||||
The write function takes some additional parameters: i_size indicates the size
|
||||
of the netfs file and term_func indicates an optional completion function, to
|
||||
which term_func_priv will be passed, along with the error or amount written.
|
||||
The write function takes some additional parameters: the cookie representing
|
||||
the cache object to be written to, i_size indicates the size of the netfs file
|
||||
and term_func indicates an optional completion function, to which
|
||||
term_func_priv will be passed, along with the error or amount written.
|
||||
|
||||
Note that the write function will always run asynchronously and will unmark all
|
||||
the pages upon completion before calling term_func.
|
||||
|
@ -894,7 +894,7 @@ xmit_hash_policy
|
||||
Uses XOR of hardware MAC addresses and packet type ID
|
||||
field to generate the hash. The formula is
|
||||
|
||||
hash = source MAC XOR destination MAC XOR packet type ID
|
||||
hash = source MAC[5] XOR destination MAC[5] XOR packet type ID
|
||||
slave number = hash modulo slave count
|
||||
|
||||
This algorithm will place all traffic to a particular
|
||||
@ -910,7 +910,7 @@ xmit_hash_policy
|
||||
Uses XOR of hardware MAC addresses and IP addresses to
|
||||
generate the hash. The formula is
|
||||
|
||||
hash = source MAC XOR destination MAC XOR packet type ID
|
||||
hash = source MAC[5] XOR destination MAC[5] XOR packet type ID
|
||||
hash = hash XOR source IP XOR destination IP
|
||||
hash = hash XOR (hash RSHIFT 16)
|
||||
hash = hash XOR (hash RSHIFT 8)
|
||||
|
@ -6190,6 +6190,7 @@ Valid values for 'type' are:
|
||||
unsigned long args[6];
|
||||
unsigned long ret[2];
|
||||
} riscv_sbi;
|
||||
|
||||
If exit reason is KVM_EXIT_RISCV_SBI then it indicates that the VCPU has
|
||||
done a SBI call which is not handled by KVM RISC-V kernel module. The details
|
||||
of the SBI call are available in 'riscv_sbi' member of kvm_run structure. The
|
||||
|
@ -1,3 +1,5 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
=================
|
||||
KVM VCPU Requests
|
||||
=================
|
||||
|
@ -1,3 +1,5 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
======================================
|
||||
Secure Encrypted Virtualization (SEV)
|
||||
======================================
|
||||
|
@ -1,3 +1,4 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
=======================================
|
||||
Known limitations of CPU virtualization
|
||||
@ -36,4 +37,3 @@ Nested virtualization features
|
||||
------------------------------
|
||||
|
||||
TBD
|
||||
|
||||
|
@ -1,3 +1,5 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
==============================
|
||||
Running nested guests with KVM
|
||||
==============================
|
||||
|
25
MAINTAINERS
25
MAINTAINERS
@ -201,6 +201,7 @@ F: include/net/ieee80211_radiotap.h
|
||||
F: include/net/iw_handler.h
|
||||
F: include/net/wext.h
|
||||
F: include/uapi/linux/nl80211.h
|
||||
F: include/uapi/linux/wireless.h
|
||||
F: net/wireless/
|
||||
|
||||
8169 10/100/1000 GIGABIT ETHERNET DRIVER
|
||||
@ -4791,6 +4792,7 @@ F: .clang-format
|
||||
CLANG/LLVM BUILD SUPPORT
|
||||
M: Nathan Chancellor <nathan@kernel.org>
|
||||
M: Nick Desaulniers <ndesaulniers@google.com>
|
||||
R: Tom Rix <trix@redhat.com>
|
||||
L: llvm@lists.linux.dev
|
||||
S: Supported
|
||||
W: https://clangbuiltlinux.github.io/
|
||||
@ -5715,7 +5717,7 @@ W: http://lanana.org/docs/device-list/index.html
|
||||
|
||||
DEVICE RESOURCE MANAGEMENT HELPERS
|
||||
M: Hans de Goede <hdegoede@redhat.com>
|
||||
R: Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>
|
||||
R: Matti Vaittinen <mazziesaccount@gmail.com>
|
||||
S: Maintained
|
||||
F: include/linux/devm-helpers.h
|
||||
|
||||
@ -8675,7 +8677,6 @@ F: include/linux/cciss*.h
|
||||
F: include/uapi/linux/cciss*.h
|
||||
|
||||
HFI1 DRIVER
|
||||
M: Mike Marciniszyn <mike.marciniszyn@cornelisnetworks.com>
|
||||
M: Dennis Dalessandro <dennis.dalessandro@cornelisnetworks.com>
|
||||
L: linux-rdma@vger.kernel.org
|
||||
S: Supported
|
||||
@ -9598,6 +9599,7 @@ F: drivers/iio/pressure/dps310.c
|
||||
|
||||
INFINIBAND SUBSYSTEM
|
||||
M: Jason Gunthorpe <jgg@nvidia.com>
|
||||
M: Leon Romanovsky <leonro@nvidia.com>
|
||||
L: linux-rdma@vger.kernel.org
|
||||
S: Supported
|
||||
W: https://github.com/linux-rdma/rdma-core
|
||||
@ -11208,7 +11210,7 @@ F: scripts/spdxcheck.py
|
||||
|
||||
LINEAR RANGES HELPERS
|
||||
M: Mark Brown <broonie@kernel.org>
|
||||
R: Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>
|
||||
R: Matti Vaittinen <mazziesaccount@gmail.com>
|
||||
F: lib/linear_ranges.c
|
||||
F: lib/test_linear_ranges.c
|
||||
F: include/linux/linear_range.h
|
||||
@ -12408,7 +12410,7 @@ F: drivers/mmc/host/mtk-sd.c
|
||||
|
||||
MEDIATEK MT76 WIRELESS LAN DRIVER
|
||||
M: Felix Fietkau <nbd@nbd.name>
|
||||
M: Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
|
||||
M: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
M: Ryder Lee <ryder.lee@mediatek.com>
|
||||
R: Shayne Chen <shayne.chen@mediatek.com>
|
||||
R: Sean Wang <sean.wang@mediatek.com>
|
||||
@ -14663,7 +14665,6 @@ F: drivers/rtc/rtc-optee.c
|
||||
|
||||
OPA-VNIC DRIVER
|
||||
M: Dennis Dalessandro <dennis.dalessandro@cornelisnetworks.com>
|
||||
M: Mike Marciniszyn <mike.marciniszyn@cornelisnetworks.com>
|
||||
L: linux-rdma@vger.kernel.org
|
||||
S: Supported
|
||||
F: drivers/infiniband/ulp/opa_vnic
|
||||
@ -16105,7 +16106,6 @@ F: include/uapi/linux/qemu_fw_cfg.h
|
||||
|
||||
QIB DRIVER
|
||||
M: Dennis Dalessandro <dennis.dalessandro@cornelisnetworks.com>
|
||||
M: Mike Marciniszyn <mike.marciniszyn@cornelisnetworks.com>
|
||||
L: linux-rdma@vger.kernel.org
|
||||
S: Supported
|
||||
F: drivers/infiniband/hw/qib/
|
||||
@ -16623,7 +16623,6 @@ F: drivers/net/ethernet/rdc/r6040.c
|
||||
|
||||
RDMAVT - RDMA verbs software
|
||||
M: Dennis Dalessandro <dennis.dalessandro@cornelisnetworks.com>
|
||||
M: Mike Marciniszyn <mike.marciniszyn@cornelisnetworks.com>
|
||||
L: linux-rdma@vger.kernel.org
|
||||
S: Supported
|
||||
F: drivers/infiniband/sw/rdmavt
|
||||
@ -17018,8 +17017,7 @@ S: Odd Fixes
|
||||
F: drivers/tty/serial/rp2.*
|
||||
|
||||
ROHM BD99954 CHARGER IC
|
||||
R: Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>
|
||||
L: linux-power@fi.rohmeurope.com
|
||||
R: Matti Vaittinen <mazziesaccount@gmail.com>
|
||||
S: Supported
|
||||
F: drivers/power/supply/bd99954-charger.c
|
||||
F: drivers/power/supply/bd99954-charger.h
|
||||
@ -17042,8 +17040,7 @@ F: drivers/regulator/bd9571mwv-regulator.c
|
||||
F: include/linux/mfd/bd9571mwv.h
|
||||
|
||||
ROHM POWER MANAGEMENT IC DEVICE DRIVERS
|
||||
R: Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>
|
||||
L: linux-power@fi.rohmeurope.com
|
||||
R: Matti Vaittinen <mazziesaccount@gmail.com>
|
||||
S: Supported
|
||||
F: drivers/clk/clk-bd718x7.c
|
||||
F: drivers/gpio/gpio-bd71815.c
|
||||
@ -21125,7 +21122,7 @@ F: include/linux/regulator/
|
||||
K: regulator_get_optional
|
||||
|
||||
VOLTAGE AND CURRENT REGULATOR IRQ HELPERS
|
||||
R: Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>
|
||||
R: Matti Vaittinen <mazziesaccount@gmail.com>
|
||||
F: drivers/regulator/irq_helpers.c
|
||||
|
||||
VRF
|
||||
@ -21238,10 +21235,8 @@ S: Maintained
|
||||
F: drivers/hid/hid-wiimote*
|
||||
|
||||
WILOCITY WIL6210 WIRELESS DRIVER
|
||||
M: Maya Erez <merez@codeaurora.org>
|
||||
L: linux-wireless@vger.kernel.org
|
||||
L: wil6210@qti.qualcomm.com
|
||||
S: Supported
|
||||
S: Orphan
|
||||
W: https://wireless.wiki.kernel.org/en/users/Drivers/wil6210
|
||||
F: drivers/net/wireless/ath/wil6210/
|
||||
|
||||
|
2
Makefile
2
Makefile
@ -2,7 +2,7 @@
|
||||
VERSION = 5
|
||||
PATCHLEVEL = 18
|
||||
SUBLEVEL = 0
|
||||
EXTRAVERSION = -rc1
|
||||
EXTRAVERSION = -rc2
|
||||
NAME = Superb Owl
|
||||
|
||||
# *DOCUMENTATION*
|
||||
|
@ -75,6 +75,7 @@
|
||||
#define ARM_CPU_PART_CORTEX_A77 0xD0D
|
||||
#define ARM_CPU_PART_NEOVERSE_V1 0xD40
|
||||
#define ARM_CPU_PART_CORTEX_A78 0xD41
|
||||
#define ARM_CPU_PART_CORTEX_A78AE 0xD42
|
||||
#define ARM_CPU_PART_CORTEX_X1 0xD44
|
||||
#define ARM_CPU_PART_CORTEX_A510 0xD46
|
||||
#define ARM_CPU_PART_CORTEX_A710 0xD47
|
||||
@ -130,6 +131,7 @@
|
||||
#define MIDR_CORTEX_A77 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A77)
|
||||
#define MIDR_NEOVERSE_V1 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_V1)
|
||||
#define MIDR_CORTEX_A78 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A78)
|
||||
#define MIDR_CORTEX_A78AE MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A78AE)
|
||||
#define MIDR_CORTEX_X1 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X1)
|
||||
#define MIDR_CORTEX_A510 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A510)
|
||||
#define MIDR_CORTEX_A710 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A710)
|
||||
|
@ -107,7 +107,7 @@
|
||||
isb // Make sure SRE is now set
|
||||
mrs_s x0, SYS_ICC_SRE_EL2 // Read SRE back,
|
||||
tbz x0, #0, .Lskip_gicv3_\@ // and check that it sticks
|
||||
msr_s SYS_ICH_HCR_EL2, xzr // Reset ICC_HCR_EL2 to defaults
|
||||
msr_s SYS_ICH_HCR_EL2, xzr // Reset ICH_HCR_EL2 to defaults
|
||||
.Lskip_gicv3_\@:
|
||||
.endm
|
||||
|
||||
|
@ -43,10 +43,22 @@ void kvm_inject_pabt(struct kvm_vcpu *vcpu, unsigned long addr);
|
||||
|
||||
void kvm_vcpu_wfi(struct kvm_vcpu *vcpu);
|
||||
|
||||
#if defined(__KVM_VHE_HYPERVISOR__) || defined(__KVM_NVHE_HYPERVISOR__)
|
||||
static __always_inline bool vcpu_el1_is_32bit(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
return !(vcpu->arch.hcr_el2 & HCR_RW);
|
||||
}
|
||||
#else
|
||||
static __always_inline bool vcpu_el1_is_32bit(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
struct kvm *kvm = vcpu->kvm;
|
||||
|
||||
WARN_ON_ONCE(!test_bit(KVM_ARCH_FLAG_REG_WIDTH_CONFIGURED,
|
||||
&kvm->arch.flags));
|
||||
|
||||
return test_bit(KVM_ARCH_FLAG_EL1_32BIT, &kvm->arch.flags);
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline void vcpu_reset_hcr(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
@ -72,15 +84,14 @@ static inline void vcpu_reset_hcr(struct kvm_vcpu *vcpu)
|
||||
vcpu->arch.hcr_el2 |= HCR_TVM;
|
||||
}
|
||||
|
||||
if (test_bit(KVM_ARM_VCPU_EL1_32BIT, vcpu->arch.features))
|
||||
if (vcpu_el1_is_32bit(vcpu))
|
||||
vcpu->arch.hcr_el2 &= ~HCR_RW;
|
||||
|
||||
/*
|
||||
* TID3: trap feature register accesses that we virtualise.
|
||||
* For now this is conditional, since no AArch32 feature regs
|
||||
* are currently virtualised.
|
||||
*/
|
||||
if (!vcpu_el1_is_32bit(vcpu))
|
||||
else
|
||||
/*
|
||||
* TID3: trap feature register accesses that we virtualise.
|
||||
* For now this is conditional, since no AArch32 feature regs
|
||||
* are currently virtualised.
|
||||
*/
|
||||
vcpu->arch.hcr_el2 |= HCR_TID3;
|
||||
|
||||
if (cpus_have_const_cap(ARM64_MISMATCHED_CACHE_TYPE) ||
|
||||
|
@ -127,6 +127,16 @@ struct kvm_arch {
|
||||
#define KVM_ARCH_FLAG_MTE_ENABLED 1
|
||||
/* At least one vCPU has ran in the VM */
|
||||
#define KVM_ARCH_FLAG_HAS_RAN_ONCE 2
|
||||
/*
|
||||
* The following two bits are used to indicate the guest's EL1
|
||||
* register width configuration. A value of KVM_ARCH_FLAG_EL1_32BIT
|
||||
* bit is valid only when KVM_ARCH_FLAG_REG_WIDTH_CONFIGURED is set.
|
||||
* Otherwise, the guest's EL1 register width has not yet been
|
||||
* determined yet.
|
||||
*/
|
||||
#define KVM_ARCH_FLAG_REG_WIDTH_CONFIGURED 3
|
||||
#define KVM_ARCH_FLAG_EL1_32BIT 4
|
||||
|
||||
unsigned long flags;
|
||||
|
||||
/*
|
||||
|
@ -42,7 +42,7 @@ bool alternative_is_applied(u16 cpufeature)
|
||||
/*
|
||||
* Check if the target PC is within an alternative block.
|
||||
*/
|
||||
static bool branch_insn_requires_update(struct alt_instr *alt, unsigned long pc)
|
||||
static __always_inline bool branch_insn_requires_update(struct alt_instr *alt, unsigned long pc)
|
||||
{
|
||||
unsigned long replptr = (unsigned long)ALT_REPL_PTR(alt);
|
||||
return !(pc >= replptr && pc <= (replptr + alt->alt_len));
|
||||
@ -50,7 +50,7 @@ static bool branch_insn_requires_update(struct alt_instr *alt, unsigned long pc)
|
||||
|
||||
#define align_down(x, a) ((unsigned long)(x) & ~(((unsigned long)(a)) - 1))
|
||||
|
||||
static u32 get_alt_insn(struct alt_instr *alt, __le32 *insnptr, __le32 *altinsnptr)
|
||||
static __always_inline u32 get_alt_insn(struct alt_instr *alt, __le32 *insnptr, __le32 *altinsnptr)
|
||||
{
|
||||
u32 insn;
|
||||
|
||||
@ -95,7 +95,7 @@ static u32 get_alt_insn(struct alt_instr *alt, __le32 *insnptr, __le32 *altinsnp
|
||||
return insn;
|
||||
}
|
||||
|
||||
static void patch_alternative(struct alt_instr *alt,
|
||||
static noinstr void patch_alternative(struct alt_instr *alt,
|
||||
__le32 *origptr, __le32 *updptr, int nr_inst)
|
||||
{
|
||||
__le32 *replptr;
|
||||
|
@ -8,16 +8,9 @@
|
||||
#include <asm/cpufeature.h>
|
||||
#include <asm/mte.h>
|
||||
|
||||
#ifndef VMA_ITERATOR
|
||||
#define VMA_ITERATOR(name, mm, addr) \
|
||||
struct mm_struct *name = mm
|
||||
#define for_each_vma(vmi, vma) \
|
||||
for (vma = vmi->mmap; vma; vma = vma->vm_next)
|
||||
#endif
|
||||
|
||||
#define for_each_mte_vma(vmi, vma) \
|
||||
#define for_each_mte_vma(tsk, vma) \
|
||||
if (system_supports_mte()) \
|
||||
for_each_vma(vmi, vma) \
|
||||
for (vma = tsk->mm->mmap; vma; vma = vma->vm_next) \
|
||||
if (vma->vm_flags & VM_MTE)
|
||||
|
||||
static unsigned long mte_vma_tag_dump_size(struct vm_area_struct *vma)
|
||||
@ -32,10 +25,11 @@ static unsigned long mte_vma_tag_dump_size(struct vm_area_struct *vma)
|
||||
static int mte_dump_tag_range(struct coredump_params *cprm,
|
||||
unsigned long start, unsigned long end)
|
||||
{
|
||||
int ret = 1;
|
||||
unsigned long addr;
|
||||
void *tags = NULL;
|
||||
|
||||
for (addr = start; addr < end; addr += PAGE_SIZE) {
|
||||
char tags[MTE_PAGE_TAG_STORAGE];
|
||||
struct page *page = get_dump_page(addr);
|
||||
|
||||
/*
|
||||
@ -59,22 +53,36 @@ static int mte_dump_tag_range(struct coredump_params *cprm,
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!tags) {
|
||||
tags = mte_allocate_tag_storage();
|
||||
if (!tags) {
|
||||
put_page(page);
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mte_save_page_tags(page_address(page), tags);
|
||||
put_page(page);
|
||||
if (!dump_emit(cprm, tags, MTE_PAGE_TAG_STORAGE))
|
||||
return 0;
|
||||
if (!dump_emit(cprm, tags, MTE_PAGE_TAG_STORAGE)) {
|
||||
mte_free_tag_storage(tags);
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
if (tags)
|
||||
mte_free_tag_storage(tags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
Elf_Half elf_core_extra_phdrs(void)
|
||||
{
|
||||
struct vm_area_struct *vma;
|
||||
int vma_count = 0;
|
||||
VMA_ITERATOR(vmi, current->mm, 0);
|
||||
|
||||
for_each_mte_vma(vmi, vma)
|
||||
for_each_mte_vma(current, vma)
|
||||
vma_count++;
|
||||
|
||||
return vma_count;
|
||||
@ -83,9 +91,8 @@ Elf_Half elf_core_extra_phdrs(void)
|
||||
int elf_core_write_extra_phdrs(struct coredump_params *cprm, loff_t offset)
|
||||
{
|
||||
struct vm_area_struct *vma;
|
||||
VMA_ITERATOR(vmi, current->mm, 0);
|
||||
|
||||
for_each_mte_vma(vmi, vma) {
|
||||
for_each_mte_vma(current, vma) {
|
||||
struct elf_phdr phdr;
|
||||
|
||||
phdr.p_type = PT_ARM_MEMTAG_MTE;
|
||||
@ -109,9 +116,8 @@ size_t elf_core_extra_data_size(void)
|
||||
{
|
||||
struct vm_area_struct *vma;
|
||||
size_t data_size = 0;
|
||||
VMA_ITERATOR(vmi, current->mm, 0);
|
||||
|
||||
for_each_mte_vma(vmi, vma)
|
||||
for_each_mte_vma(current, vma)
|
||||
data_size += mte_vma_tag_dump_size(vma);
|
||||
|
||||
return data_size;
|
||||
@ -120,9 +126,8 @@ size_t elf_core_extra_data_size(void)
|
||||
int elf_core_write_extra_data(struct coredump_params *cprm)
|
||||
{
|
||||
struct vm_area_struct *vma;
|
||||
VMA_ITERATOR(vmi, current->mm, 0);
|
||||
|
||||
for_each_mte_vma(vmi, vma) {
|
||||
for_each_mte_vma(current, vma) {
|
||||
if (vma->vm_flags & VM_DONTDUMP)
|
||||
continue;
|
||||
|
||||
|
@ -701,7 +701,7 @@ NOKPROBE_SYMBOL(breakpoint_handler);
|
||||
* addresses. There is no straight-forward way, short of disassembling the
|
||||
* offending instruction, to map that address back to the watchpoint. This
|
||||
* function computes the distance of the memory access from the watchpoint as a
|
||||
* heuristic for the likelyhood that a given access triggered the watchpoint.
|
||||
* heuristic for the likelihood that a given access triggered the watchpoint.
|
||||
*
|
||||
* See Section D2.10.5 "Determining the memory location that caused a Watchpoint
|
||||
* exception" of ARMv8 Architecture Reference Manual for details.
|
||||
|
@ -220,7 +220,7 @@ static unsigned int count_plts(Elf64_Sym *syms, Elf64_Rela *rela, int num,
|
||||
* increasing the section's alignment so that the
|
||||
* resulting address of this instruction is guaranteed
|
||||
* to equal the offset in that particular bit (as well
|
||||
* as all less signficant bits). This ensures that the
|
||||
* as all less significant bits). This ensures that the
|
||||
* address modulo 4 KB != 0xfff8 or 0xfffc (which would
|
||||
* have all ones in bits [11:3])
|
||||
*/
|
||||
|
@ -117,8 +117,8 @@ static int __kprobes aarch64_insn_patch_text_cb(void *arg)
|
||||
int i, ret = 0;
|
||||
struct aarch64_insn_patch *pp = arg;
|
||||
|
||||
/* The first CPU becomes master */
|
||||
if (atomic_inc_return(&pp->cpu_count) == 1) {
|
||||
/* The last CPU becomes master */
|
||||
if (atomic_inc_return(&pp->cpu_count) == num_online_cpus()) {
|
||||
for (i = 0; ret == 0 && i < pp->insn_cnt; i++)
|
||||
ret = aarch64_insn_patch_text_nosync(pp->text_addrs[i],
|
||||
pp->new_insns[i]);
|
||||
|
@ -853,6 +853,7 @@ u8 spectre_bhb_loop_affected(int scope)
|
||||
if (scope == SCOPE_LOCAL_CPU) {
|
||||
static const struct midr_range spectre_bhb_k32_list[] = {
|
||||
MIDR_ALL_VERSIONS(MIDR_CORTEX_A78),
|
||||
MIDR_ALL_VERSIONS(MIDR_CORTEX_A78AE),
|
||||
MIDR_ALL_VERSIONS(MIDR_CORTEX_A78C),
|
||||
MIDR_ALL_VERSIONS(MIDR_CORTEX_X1),
|
||||
MIDR_ALL_VERSIONS(MIDR_CORTEX_A710),
|
||||
|
@ -234,6 +234,7 @@ asmlinkage notrace void secondary_start_kernel(void)
|
||||
* Log the CPU info before it is marked online and might get read.
|
||||
*/
|
||||
cpuinfo_store_cpu();
|
||||
store_cpu_topology(cpu);
|
||||
|
||||
/*
|
||||
* Enable GIC and timers.
|
||||
@ -242,7 +243,6 @@ asmlinkage notrace void secondary_start_kernel(void)
|
||||
|
||||
ipi_setup(cpu);
|
||||
|
||||
store_cpu_topology(cpu);
|
||||
numa_add_cpu(cpu);
|
||||
|
||||
/*
|
||||
|
@ -140,7 +140,7 @@ int cpu_suspend(unsigned long arg, int (*fn)(unsigned long))
|
||||
/*
|
||||
* Restore pstate flags. OS lock and mdscr have been already
|
||||
* restored, so from this point onwards, debugging is fully
|
||||
* renabled if it was enabled when core started shutdown.
|
||||
* reenabled if it was enabled when core started shutdown.
|
||||
*/
|
||||
local_daif_restore(flags);
|
||||
|
||||
|
@ -1079,7 +1079,7 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
|
||||
gfn_t gfn;
|
||||
kvm_pfn_t pfn;
|
||||
bool logging_active = memslot_is_logging(memslot);
|
||||
bool logging_perm_fault = false;
|
||||
bool use_read_lock = false;
|
||||
unsigned long fault_level = kvm_vcpu_trap_get_fault_level(vcpu);
|
||||
unsigned long vma_pagesize, fault_granule;
|
||||
enum kvm_pgtable_prot prot = KVM_PGTABLE_PROT_R;
|
||||
@ -1114,7 +1114,8 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
|
||||
if (logging_active) {
|
||||
force_pte = true;
|
||||
vma_shift = PAGE_SHIFT;
|
||||
logging_perm_fault = (fault_status == FSC_PERM && write_fault);
|
||||
use_read_lock = (fault_status == FSC_PERM && write_fault &&
|
||||
fault_granule == PAGE_SIZE);
|
||||
} else {
|
||||
vma_shift = get_vma_page_shift(vma, hva);
|
||||
}
|
||||
@ -1218,7 +1219,7 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
|
||||
* logging dirty logging, only acquire read lock for permission
|
||||
* relaxation.
|
||||
*/
|
||||
if (logging_perm_fault)
|
||||
if (use_read_lock)
|
||||
read_lock(&kvm->mmu_lock);
|
||||
else
|
||||
write_lock(&kvm->mmu_lock);
|
||||
@ -1268,6 +1269,8 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
|
||||
if (fault_status == FSC_PERM && vma_pagesize == fault_granule) {
|
||||
ret = kvm_pgtable_stage2_relax_perms(pgt, fault_ipa, prot);
|
||||
} else {
|
||||
WARN_ONCE(use_read_lock, "Attempted stage-2 map outside of write lock\n");
|
||||
|
||||
ret = kvm_pgtable_stage2_map(pgt, fault_ipa, vma_pagesize,
|
||||
__pfn_to_phys(pfn), prot,
|
||||
memcache);
|
||||
@ -1280,7 +1283,7 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
|
||||
}
|
||||
|
||||
out_unlock:
|
||||
if (logging_perm_fault)
|
||||
if (use_read_lock)
|
||||
read_unlock(&kvm->mmu_lock);
|
||||
else
|
||||
write_unlock(&kvm->mmu_lock);
|
||||
|
@ -215,15 +215,11 @@ static void kvm_psci_narrow_to_32bit(struct kvm_vcpu *vcpu)
|
||||
|
||||
static unsigned long kvm_psci_check_allowed_function(struct kvm_vcpu *vcpu, u32 fn)
|
||||
{
|
||||
switch(fn) {
|
||||
case PSCI_0_2_FN64_CPU_SUSPEND:
|
||||
case PSCI_0_2_FN64_CPU_ON:
|
||||
case PSCI_0_2_FN64_AFFINITY_INFO:
|
||||
/* Disallow these functions for 32bit guests */
|
||||
if (vcpu_mode_is_32bit(vcpu))
|
||||
return PSCI_RET_NOT_SUPPORTED;
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* Prevent 32 bit guests from calling 64 bit PSCI functions.
|
||||
*/
|
||||
if ((fn & PSCI_0_2_64BIT) && vcpu_mode_is_32bit(vcpu))
|
||||
return PSCI_RET_NOT_SUPPORTED;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -235,10 +231,6 @@ static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu)
|
||||
unsigned long val;
|
||||
int ret = 1;
|
||||
|
||||
val = kvm_psci_check_allowed_function(vcpu, psci_fn);
|
||||
if (val)
|
||||
goto out;
|
||||
|
||||
switch (psci_fn) {
|
||||
case PSCI_0_2_FN_PSCI_VERSION:
|
||||
/*
|
||||
@ -306,7 +298,6 @@ static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu)
|
||||
break;
|
||||
}
|
||||
|
||||
out:
|
||||
smccc_set_retval(vcpu, val, 0, 0, 0);
|
||||
return ret;
|
||||
}
|
||||
@ -318,9 +309,6 @@ static int kvm_psci_1_x_call(struct kvm_vcpu *vcpu, u32 minor)
|
||||
unsigned long val;
|
||||
int ret = 1;
|
||||
|
||||
if (minor > 1)
|
||||
return -EINVAL;
|
||||
|
||||
switch(psci_fn) {
|
||||
case PSCI_0_2_FN_PSCI_VERSION:
|
||||
val = minor == 0 ? KVM_ARM_PSCI_1_0 : KVM_ARM_PSCI_1_1;
|
||||
@ -426,6 +414,15 @@ static int kvm_psci_0_1_call(struct kvm_vcpu *vcpu)
|
||||
*/
|
||||
int kvm_psci_call(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
u32 psci_fn = smccc_get_function(vcpu);
|
||||
unsigned long val;
|
||||
|
||||
val = kvm_psci_check_allowed_function(vcpu, psci_fn);
|
||||
if (val) {
|
||||
smccc_set_retval(vcpu, val, 0, 0, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
switch (kvm_psci_version(vcpu)) {
|
||||
case KVM_ARM_PSCI_1_1:
|
||||
return kvm_psci_1_x_call(vcpu, 1);
|
||||
|
@ -181,27 +181,51 @@ static int kvm_vcpu_enable_ptrauth(struct kvm_vcpu *vcpu)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool vcpu_allowed_register_width(struct kvm_vcpu *vcpu)
|
||||
/**
|
||||
* kvm_set_vm_width() - set the register width for the guest
|
||||
* @vcpu: Pointer to the vcpu being configured
|
||||
*
|
||||
* Set both KVM_ARCH_FLAG_EL1_32BIT and KVM_ARCH_FLAG_REG_WIDTH_CONFIGURED
|
||||
* in the VM flags based on the vcpu's requested register width, the HW
|
||||
* capabilities and other options (such as MTE).
|
||||
* When REG_WIDTH_CONFIGURED is already set, the vcpu settings must be
|
||||
* consistent with the value of the FLAG_EL1_32BIT bit in the flags.
|
||||
*
|
||||
* Return: 0 on success, negative error code on failure.
|
||||
*/
|
||||
static int kvm_set_vm_width(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
struct kvm_vcpu *tmp;
|
||||
struct kvm *kvm = vcpu->kvm;
|
||||
bool is32bit;
|
||||
unsigned long i;
|
||||
|
||||
is32bit = vcpu_has_feature(vcpu, KVM_ARM_VCPU_EL1_32BIT);
|
||||
if (!cpus_have_const_cap(ARM64_HAS_32BIT_EL1) && is32bit)
|
||||
return false;
|
||||
|
||||
/* MTE is incompatible with AArch32 */
|
||||
if (kvm_has_mte(vcpu->kvm) && is32bit)
|
||||
return false;
|
||||
lockdep_assert_held(&kvm->lock);
|
||||
|
||||
/* Check that the vcpus are either all 32bit or all 64bit */
|
||||
kvm_for_each_vcpu(i, tmp, vcpu->kvm) {
|
||||
if (vcpu_has_feature(tmp, KVM_ARM_VCPU_EL1_32BIT) != is32bit)
|
||||
return false;
|
||||
if (test_bit(KVM_ARCH_FLAG_REG_WIDTH_CONFIGURED, &kvm->arch.flags)) {
|
||||
/*
|
||||
* The guest's register width is already configured.
|
||||
* Make sure that the vcpu is consistent with it.
|
||||
*/
|
||||
if (is32bit == test_bit(KVM_ARCH_FLAG_EL1_32BIT, &kvm->arch.flags))
|
||||
return 0;
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return true;
|
||||
if (!cpus_have_const_cap(ARM64_HAS_32BIT_EL1) && is32bit)
|
||||
return -EINVAL;
|
||||
|
||||
/* MTE is incompatible with AArch32 */
|
||||
if (kvm_has_mte(kvm) && is32bit)
|
||||
return -EINVAL;
|
||||
|
||||
if (is32bit)
|
||||
set_bit(KVM_ARCH_FLAG_EL1_32BIT, &kvm->arch.flags);
|
||||
|
||||
set_bit(KVM_ARCH_FLAG_REG_WIDTH_CONFIGURED, &kvm->arch.flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -230,10 +254,16 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu)
|
||||
u32 pstate;
|
||||
|
||||
mutex_lock(&vcpu->kvm->lock);
|
||||
reset_state = vcpu->arch.reset_state;
|
||||
WRITE_ONCE(vcpu->arch.reset_state.reset, false);
|
||||
ret = kvm_set_vm_width(vcpu);
|
||||
if (!ret) {
|
||||
reset_state = vcpu->arch.reset_state;
|
||||
WRITE_ONCE(vcpu->arch.reset_state.reset, false);
|
||||
}
|
||||
mutex_unlock(&vcpu->kvm->lock);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Reset PMU outside of the non-preemptible section */
|
||||
kvm_pmu_vcpu_reset(vcpu);
|
||||
|
||||
@ -260,14 +290,9 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu)
|
||||
}
|
||||
}
|
||||
|
||||
if (!vcpu_allowed_register_width(vcpu)) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
switch (vcpu->arch.target) {
|
||||
default:
|
||||
if (test_bit(KVM_ARM_VCPU_EL1_32BIT, vcpu->arch.features)) {
|
||||
if (vcpu_el1_is_32bit(vcpu)) {
|
||||
pstate = VCPU_RESET_PSTATE_SVC;
|
||||
} else {
|
||||
pstate = VCPU_RESET_PSTATE_EL1;
|
||||
|
@ -82,7 +82,7 @@ static bool end_of_vgic(struct vgic_state_iter *iter)
|
||||
|
||||
static void *vgic_debug_start(struct seq_file *s, loff_t *pos)
|
||||
{
|
||||
struct kvm *kvm = (struct kvm *)s->private;
|
||||
struct kvm *kvm = s->private;
|
||||
struct vgic_state_iter *iter;
|
||||
|
||||
mutex_lock(&kvm->lock);
|
||||
@ -110,7 +110,7 @@ static void *vgic_debug_start(struct seq_file *s, loff_t *pos)
|
||||
|
||||
static void *vgic_debug_next(struct seq_file *s, void *v, loff_t *pos)
|
||||
{
|
||||
struct kvm *kvm = (struct kvm *)s->private;
|
||||
struct kvm *kvm = s->private;
|
||||
struct vgic_state_iter *iter = kvm->arch.vgic.iter;
|
||||
|
||||
++*pos;
|
||||
@ -122,7 +122,7 @@ static void *vgic_debug_next(struct seq_file *s, void *v, loff_t *pos)
|
||||
|
||||
static void vgic_debug_stop(struct seq_file *s, void *v)
|
||||
{
|
||||
struct kvm *kvm = (struct kvm *)s->private;
|
||||
struct kvm *kvm = s->private;
|
||||
struct vgic_state_iter *iter;
|
||||
|
||||
/*
|
||||
@ -229,8 +229,8 @@ static void print_irq_state(struct seq_file *s, struct vgic_irq *irq,
|
||||
|
||||
static int vgic_debug_show(struct seq_file *s, void *v)
|
||||
{
|
||||
struct kvm *kvm = (struct kvm *)s->private;
|
||||
struct vgic_state_iter *iter = (struct vgic_state_iter *)v;
|
||||
struct kvm *kvm = s->private;
|
||||
struct vgic_state_iter *iter = v;
|
||||
struct vgic_irq *irq;
|
||||
struct kvm_vcpu *vcpu = NULL;
|
||||
unsigned long flags;
|
||||
|
@ -2143,7 +2143,7 @@ static int vgic_its_save_ite(struct vgic_its *its, struct its_device *dev,
|
||||
static int vgic_its_restore_ite(struct vgic_its *its, u32 event_id,
|
||||
void *ptr, void *opaque)
|
||||
{
|
||||
struct its_device *dev = (struct its_device *)opaque;
|
||||
struct its_device *dev = opaque;
|
||||
struct its_collection *collection;
|
||||
struct kvm *kvm = its->dev->kvm;
|
||||
struct kvm_vcpu *vcpu = NULL;
|
||||
|
@ -73,7 +73,7 @@ EXPORT_SYMBOL(memstart_addr);
|
||||
* In this scheme a comparatively quicker boot is observed.
|
||||
*
|
||||
* If ZONE_DMA configs are defined, crash kernel memory reservation
|
||||
* is delayed until DMA zone memory range size initilazation performed in
|
||||
* is delayed until DMA zone memory range size initialization performed in
|
||||
* zone_sizes_init(). The defer is necessary to steer clear of DMA zone
|
||||
* memory range to avoid overlap allocation. So crash kernel memory boundaries
|
||||
* are not known when mapping all bank memory ranges, which otherwise means
|
||||
@ -81,7 +81,7 @@ EXPORT_SYMBOL(memstart_addr);
|
||||
* so page-granularity mappings are created for the entire memory range.
|
||||
* Hence a slightly slower boot is observed.
|
||||
*
|
||||
* Note: Page-granularity mapppings are necessary for crash kernel memory
|
||||
* Note: Page-granularity mappings are necessary for crash kernel memory
|
||||
* range for shrinking its size via /sys/kernel/kexec_crash_size interface.
|
||||
*/
|
||||
#if IS_ENABLED(CONFIG_ZONE_DMA) || IS_ENABLED(CONFIG_ZONE_DMA32)
|
||||
|
@ -16,18 +16,6 @@
|
||||
#include <asm/ppc-opcode.h>
|
||||
#include <asm/pte-walk.h>
|
||||
|
||||
#ifdef CONFIG_PPC_PSERIES
|
||||
static inline bool kvmhv_on_pseries(void)
|
||||
{
|
||||
return !cpu_has_feature(CPU_FTR_HVMODE);
|
||||
}
|
||||
#else
|
||||
static inline bool kvmhv_on_pseries(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Structure for a nested guest, that is, for a guest that is managed by
|
||||
* one of our guests.
|
||||
|
@ -586,6 +586,18 @@ static inline bool kvm_hv_mode_active(void) { return false; }
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PPC_PSERIES
|
||||
static inline bool kvmhv_on_pseries(void)
|
||||
{
|
||||
return !cpu_has_feature(CPU_FTR_HVMODE);
|
||||
}
|
||||
#else
|
||||
static inline bool kvmhv_on_pseries(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_KVM_XICS
|
||||
static inline int kvmppc_xics_enabled(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
|
@ -132,7 +132,11 @@ static inline bool pfn_valid(unsigned long pfn)
|
||||
#define virt_to_page(kaddr) pfn_to_page(virt_to_pfn(kaddr))
|
||||
#define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT)
|
||||
|
||||
#define virt_addr_valid(kaddr) pfn_valid(virt_to_pfn(kaddr))
|
||||
#define virt_addr_valid(vaddr) ({ \
|
||||
unsigned long _addr = (unsigned long)vaddr; \
|
||||
_addr >= PAGE_OFFSET && _addr < (unsigned long)high_memory && \
|
||||
pfn_valid(virt_to_pfn(_addr)); \
|
||||
})
|
||||
|
||||
/*
|
||||
* On Book-E parts we need __va to parse the device tree and we can't
|
||||
|
@ -28,11 +28,13 @@ void setup_panic(void);
|
||||
#define ARCH_PANIC_TIMEOUT 180
|
||||
|
||||
#ifdef CONFIG_PPC_PSERIES
|
||||
extern bool pseries_reloc_on_exception(void);
|
||||
extern bool pseries_enable_reloc_on_exc(void);
|
||||
extern void pseries_disable_reloc_on_exc(void);
|
||||
extern void pseries_big_endian_exceptions(void);
|
||||
void __init pseries_little_endian_exceptions(void);
|
||||
#else
|
||||
static inline bool pseries_reloc_on_exception(void) { return false; }
|
||||
static inline bool pseries_enable_reloc_on_exc(void) { return false; }
|
||||
static inline void pseries_disable_reloc_on_exc(void) {}
|
||||
static inline void pseries_big_endian_exceptions(void) {}
|
||||
|
@ -24,5 +24,6 @@
|
||||
|
||||
#define ARCH_DEFINE_STATIC_CALL_TRAMP(name, func) __PPC_SCT(name, "b " #func)
|
||||
#define ARCH_DEFINE_STATIC_CALL_NULL_TRAMP(name) __PPC_SCT(name, "blr")
|
||||
#define ARCH_DEFINE_STATIC_CALL_RET0_TRAMP(name) __PPC_SCT(name, "b .+20")
|
||||
|
||||
#endif /* _ASM_POWERPC_STATIC_CALL_H */
|
||||
|
@ -809,6 +809,10 @@ __start_interrupts:
|
||||
* - MSR_EE|MSR_RI is clear (no reentrant exceptions)
|
||||
* - Standard kernel environment is set up (stack, paca, etc)
|
||||
*
|
||||
* KVM:
|
||||
* These interrupts do not elevate HV 0->1, so HV is not involved. PR KVM
|
||||
* ensures that FSCR[SCV] is disabled whenever it has to force AIL off.
|
||||
*
|
||||
* Call convention:
|
||||
*
|
||||
* syscall register convention is in Documentation/powerpc/syscall64-abi.rst
|
||||
|
@ -196,6 +196,34 @@ static void __init configure_exceptions(void)
|
||||
|
||||
/* Under a PAPR hypervisor, we need hypercalls */
|
||||
if (firmware_has_feature(FW_FEATURE_SET_MODE)) {
|
||||
/*
|
||||
* - PR KVM does not support AIL mode interrupts in the host
|
||||
* while a PR guest is running.
|
||||
*
|
||||
* - SCV system call interrupt vectors are only implemented for
|
||||
* AIL mode interrupts.
|
||||
*
|
||||
* - On pseries, AIL mode can only be enabled and disabled
|
||||
* system-wide so when a PR VM is created on a pseries host,
|
||||
* all CPUs of the host are set to AIL=0 mode.
|
||||
*
|
||||
* - Therefore host CPUs must not execute scv while a PR VM
|
||||
* exists.
|
||||
*
|
||||
* - SCV support can not be disabled dynamically because the
|
||||
* feature is advertised to host userspace. Disabling the
|
||||
* facility and emulating it would be possible but is not
|
||||
* implemented.
|
||||
*
|
||||
* - So SCV support is blanket disabled if PR KVM could possibly
|
||||
* run. That is, PR support compiled in, booting on pseries
|
||||
* with hash MMU.
|
||||
*/
|
||||
if (IS_ENABLED(CONFIG_KVM_BOOK3S_PR_POSSIBLE) && !radix_enabled()) {
|
||||
init_task.thread.fscr &= ~FSCR_SCV;
|
||||
cur_cpu_spec->cpu_user_features2 &= ~PPC_FEATURE2_SCV;
|
||||
}
|
||||
|
||||
/* Enable AIL if possible */
|
||||
if (!pseries_enable_reloc_on_exc()) {
|
||||
init_task.thread.fscr &= ~FSCR_SCV;
|
||||
|
@ -112,12 +112,21 @@ config KVM_BOOK3S_64_PR
|
||||
guest in user mode (problem state) and emulating all
|
||||
privileged instructions and registers.
|
||||
|
||||
This is only available for hash MMU mode and only supports
|
||||
guests that use hash MMU mode.
|
||||
|
||||
This is not as fast as using hypervisor mode, but works on
|
||||
machines where hypervisor mode is not available or not usable,
|
||||
and can emulate processors that are different from the host
|
||||
processor, including emulating 32-bit processors on a 64-bit
|
||||
host.
|
||||
|
||||
Selecting this option will cause the SCV facility to be
|
||||
disabled when the kernel is booted on the pseries platform in
|
||||
hash MMU mode (regardless of PR VMs running). When any PR VMs
|
||||
are running, "AIL" mode is disabled which may slow interrupts
|
||||
and system calls on the host.
|
||||
|
||||
config KVM_BOOK3S_HV_EXIT_TIMING
|
||||
bool "Detailed timing for hypervisor real-mode code"
|
||||
depends on KVM_BOOK3S_HV_POSSIBLE && DEBUG_FS
|
||||
|
@ -414,10 +414,16 @@ END_FTR_SECTION_IFSET(CPU_FTR_DAWR1)
|
||||
*/
|
||||
ld r10,HSTATE_SCRATCH0(r13)
|
||||
cmpwi r10,BOOK3S_INTERRUPT_MACHINE_CHECK
|
||||
beq machine_check_common
|
||||
beq .Lcall_machine_check_common
|
||||
|
||||
cmpwi r10,BOOK3S_INTERRUPT_SYSTEM_RESET
|
||||
beq system_reset_common
|
||||
beq .Lcall_system_reset_common
|
||||
|
||||
b .
|
||||
|
||||
.Lcall_machine_check_common:
|
||||
b machine_check_common
|
||||
|
||||
.Lcall_system_reset_common:
|
||||
b system_reset_common
|
||||
#endif
|
||||
|
@ -225,6 +225,13 @@ static void kvmppc_fast_vcpu_kick_hv(struct kvm_vcpu *vcpu)
|
||||
int cpu;
|
||||
struct rcuwait *waitp;
|
||||
|
||||
/*
|
||||
* rcuwait_wake_up contains smp_mb() which orders prior stores that
|
||||
* create pending work vs below loads of cpu fields. The other side
|
||||
* is the barrier in vcpu run that orders setting the cpu fields vs
|
||||
* testing for pending work.
|
||||
*/
|
||||
|
||||
waitp = kvm_arch_vcpu_get_wait(vcpu);
|
||||
if (rcuwait_wake_up(waitp))
|
||||
++vcpu->stat.generic.halt_wakeup;
|
||||
@ -1089,7 +1096,7 @@ int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu)
|
||||
break;
|
||||
}
|
||||
tvcpu->arch.prodded = 1;
|
||||
smp_mb();
|
||||
smp_mb(); /* This orders prodded store vs ceded load */
|
||||
if (tvcpu->arch.ceded)
|
||||
kvmppc_fast_vcpu_kick_hv(tvcpu);
|
||||
break;
|
||||
@ -3766,6 +3773,14 @@ static noinline void kvmppc_run_core(struct kvmppc_vcore *vc)
|
||||
pvc = core_info.vc[sub];
|
||||
pvc->pcpu = pcpu + thr;
|
||||
for_each_runnable_thread(i, vcpu, pvc) {
|
||||
/*
|
||||
* XXX: is kvmppc_start_thread called too late here?
|
||||
* It updates vcpu->cpu and vcpu->arch.thread_cpu
|
||||
* which are used by kvmppc_fast_vcpu_kick_hv(), but
|
||||
* kick is called after new exceptions become available
|
||||
* and exceptions are checked earlier than here, by
|
||||
* kvmppc_core_prepare_to_enter.
|
||||
*/
|
||||
kvmppc_start_thread(vcpu, pvc);
|
||||
kvmppc_create_dtl_entry(vcpu, pvc);
|
||||
trace_kvm_guest_enter(vcpu);
|
||||
@ -4487,6 +4502,21 @@ int kvmhv_run_single_vcpu(struct kvm_vcpu *vcpu, u64 time_limit,
|
||||
if (need_resched() || !kvm->arch.mmu_ready)
|
||||
goto out;
|
||||
|
||||
vcpu->cpu = pcpu;
|
||||
vcpu->arch.thread_cpu = pcpu;
|
||||
vc->pcpu = pcpu;
|
||||
local_paca->kvm_hstate.kvm_vcpu = vcpu;
|
||||
local_paca->kvm_hstate.ptid = 0;
|
||||
local_paca->kvm_hstate.fake_suspend = 0;
|
||||
|
||||
/*
|
||||
* Orders set cpu/thread_cpu vs testing for pending interrupts and
|
||||
* doorbells below. The other side is when these fields are set vs
|
||||
* kvmppc_fast_vcpu_kick_hv reading the cpu/thread_cpu fields to
|
||||
* kick a vCPU to notice the pending interrupt.
|
||||
*/
|
||||
smp_mb();
|
||||
|
||||
if (!nested) {
|
||||
kvmppc_core_prepare_to_enter(vcpu);
|
||||
if (test_bit(BOOK3S_IRQPRIO_EXTERNAL,
|
||||
@ -4506,13 +4536,6 @@ int kvmhv_run_single_vcpu(struct kvm_vcpu *vcpu, u64 time_limit,
|
||||
|
||||
tb = mftb();
|
||||
|
||||
vcpu->cpu = pcpu;
|
||||
vcpu->arch.thread_cpu = pcpu;
|
||||
vc->pcpu = pcpu;
|
||||
local_paca->kvm_hstate.kvm_vcpu = vcpu;
|
||||
local_paca->kvm_hstate.ptid = 0;
|
||||
local_paca->kvm_hstate.fake_suspend = 0;
|
||||
|
||||
__kvmppc_create_dtl_entry(vcpu, pcpu, tb + vc->tb_offset, 0);
|
||||
|
||||
trace_kvm_guest_enter(vcpu);
|
||||
@ -4614,6 +4637,8 @@ int kvmhv_run_single_vcpu(struct kvm_vcpu *vcpu, u64 time_limit,
|
||||
run->exit_reason = KVM_EXIT_INTR;
|
||||
vcpu->arch.ret = -EINTR;
|
||||
out:
|
||||
vcpu->cpu = -1;
|
||||
vcpu->arch.thread_cpu = -1;
|
||||
powerpc_local_irq_pmu_restore(flags);
|
||||
preempt_enable();
|
||||
goto done;
|
||||
|
@ -137,12 +137,15 @@ static void kvmppc_core_vcpu_load_pr(struct kvm_vcpu *vcpu, int cpu)
|
||||
svcpu->slb_max = to_book3s(vcpu)->slb_shadow_max;
|
||||
svcpu->in_use = 0;
|
||||
svcpu_put(svcpu);
|
||||
#endif
|
||||
|
||||
/* Disable AIL if supported */
|
||||
if (cpu_has_feature(CPU_FTR_HVMODE) &&
|
||||
cpu_has_feature(CPU_FTR_ARCH_207S))
|
||||
mtspr(SPRN_LPCR, mfspr(SPRN_LPCR) & ~LPCR_AIL);
|
||||
if (cpu_has_feature(CPU_FTR_HVMODE)) {
|
||||
if (cpu_has_feature(CPU_FTR_ARCH_207S))
|
||||
mtspr(SPRN_LPCR, mfspr(SPRN_LPCR) & ~LPCR_AIL);
|
||||
if (cpu_has_feature(CPU_FTR_ARCH_300) && (current->thread.fscr & FSCR_SCV))
|
||||
mtspr(SPRN_FSCR, mfspr(SPRN_FSCR) & ~FSCR_SCV);
|
||||
}
|
||||
#endif
|
||||
|
||||
vcpu->cpu = smp_processor_id();
|
||||
#ifdef CONFIG_PPC_BOOK3S_32
|
||||
@ -165,6 +168,14 @@ static void kvmppc_core_vcpu_put_pr(struct kvm_vcpu *vcpu)
|
||||
memcpy(to_book3s(vcpu)->slb_shadow, svcpu->slb, sizeof(svcpu->slb));
|
||||
to_book3s(vcpu)->slb_shadow_max = svcpu->slb_max;
|
||||
svcpu_put(svcpu);
|
||||
|
||||
/* Enable AIL if supported */
|
||||
if (cpu_has_feature(CPU_FTR_HVMODE)) {
|
||||
if (cpu_has_feature(CPU_FTR_ARCH_207S))
|
||||
mtspr(SPRN_LPCR, mfspr(SPRN_LPCR) | LPCR_AIL_3);
|
||||
if (cpu_has_feature(CPU_FTR_ARCH_300) && (current->thread.fscr & FSCR_SCV))
|
||||
mtspr(SPRN_FSCR, mfspr(SPRN_FSCR) | FSCR_SCV);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (kvmppc_is_split_real(vcpu))
|
||||
@ -174,11 +185,6 @@ static void kvmppc_core_vcpu_put_pr(struct kvm_vcpu *vcpu)
|
||||
kvmppc_giveup_fac(vcpu, FSCR_TAR_LG);
|
||||
kvmppc_save_tm_pr(vcpu);
|
||||
|
||||
/* Enable AIL if supported */
|
||||
if (cpu_has_feature(CPU_FTR_HVMODE) &&
|
||||
cpu_has_feature(CPU_FTR_ARCH_207S))
|
||||
mtspr(SPRN_LPCR, mfspr(SPRN_LPCR) | LPCR_AIL_3);
|
||||
|
||||
vcpu->cpu = -1;
|
||||
}
|
||||
|
||||
@ -1037,6 +1043,8 @@ static int kvmppc_handle_fac(struct kvm_vcpu *vcpu, ulong fac)
|
||||
|
||||
void kvmppc_set_fscr(struct kvm_vcpu *vcpu, u64 fscr)
|
||||
{
|
||||
if (fscr & FSCR_SCV)
|
||||
fscr &= ~FSCR_SCV; /* SCV must not be enabled */
|
||||
if ((vcpu->arch.fscr & FSCR_TAR) && !(fscr & FSCR_TAR)) {
|
||||
/* TAR got dropped, drop it in shadow too */
|
||||
kvmppc_giveup_fac(vcpu, FSCR_TAR_LG);
|
||||
|
@ -281,6 +281,22 @@ static int kvmppc_h_pr_logical_ci_store(struct kvm_vcpu *vcpu)
|
||||
return EMULATE_DONE;
|
||||
}
|
||||
|
||||
static int kvmppc_h_pr_set_mode(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
unsigned long mflags = kvmppc_get_gpr(vcpu, 4);
|
||||
unsigned long resource = kvmppc_get_gpr(vcpu, 5);
|
||||
|
||||
if (resource == H_SET_MODE_RESOURCE_ADDR_TRANS_MODE) {
|
||||
/* KVM PR does not provide AIL!=0 to guests */
|
||||
if (mflags == 0)
|
||||
kvmppc_set_gpr(vcpu, 3, H_SUCCESS);
|
||||
else
|
||||
kvmppc_set_gpr(vcpu, 3, H_UNSUPPORTED_FLAG_START - 63);
|
||||
return EMULATE_DONE;
|
||||
}
|
||||
return EMULATE_FAIL;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SPAPR_TCE_IOMMU
|
||||
static int kvmppc_h_pr_put_tce(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
@ -384,6 +400,8 @@ int kvmppc_h_pr(struct kvm_vcpu *vcpu, unsigned long cmd)
|
||||
return kvmppc_h_pr_logical_ci_load(vcpu);
|
||||
case H_LOGICAL_CI_STORE:
|
||||
return kvmppc_h_pr_logical_ci_store(vcpu);
|
||||
case H_SET_MODE:
|
||||
return kvmppc_h_pr_set_mode(vcpu);
|
||||
case H_XIRR:
|
||||
case H_CPPR:
|
||||
case H_EOI:
|
||||
@ -421,6 +439,7 @@ int kvmppc_hcall_impl_pr(unsigned long cmd)
|
||||
case H_CEDE:
|
||||
case H_LOGICAL_CI_LOAD:
|
||||
case H_LOGICAL_CI_STORE:
|
||||
case H_SET_MODE:
|
||||
#ifdef CONFIG_KVM_XICS
|
||||
case H_XIRR:
|
||||
case H_CPPR:
|
||||
@ -447,6 +466,7 @@ static unsigned int default_hcall_list[] = {
|
||||
H_BULK_REMOVE,
|
||||
H_PUT_TCE,
|
||||
H_CEDE,
|
||||
H_SET_MODE,
|
||||
#ifdef CONFIG_KVM_XICS
|
||||
H_XIRR,
|
||||
H_CPPR,
|
||||
|
@ -705,6 +705,23 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
|
||||
r = 1;
|
||||
break;
|
||||
#endif
|
||||
case KVM_CAP_PPC_AIL_MODE_3:
|
||||
r = 0;
|
||||
/*
|
||||
* KVM PR, POWER7, and some POWER9s don't support AIL=3 mode.
|
||||
* The POWER9s can support it if the guest runs in hash mode,
|
||||
* but QEMU doesn't necessarily query the capability in time.
|
||||
*/
|
||||
if (hv_enabled) {
|
||||
if (kvmhv_on_pseries()) {
|
||||
if (pseries_reloc_on_exception())
|
||||
r = 1;
|
||||
} else if (cpu_has_feature(CPU_FTR_ARCH_207S) &&
|
||||
!cpu_has_feature(CPU_FTR_P9_RADIX_PREFETCH_BUG)) {
|
||||
r = 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
r = 0;
|
||||
break;
|
||||
|
@ -255,7 +255,7 @@ void __init mem_init(void)
|
||||
#endif
|
||||
|
||||
high_memory = (void *) __va(max_low_pfn * PAGE_SIZE);
|
||||
set_max_mapnr(max_low_pfn);
|
||||
set_max_mapnr(max_pfn);
|
||||
|
||||
kasan_late_init();
|
||||
|
||||
|
@ -1436,7 +1436,7 @@ int find_and_online_cpu_nid(int cpu)
|
||||
if (new_nid < 0 || !node_possible(new_nid))
|
||||
new_nid = first_online_node;
|
||||
|
||||
if (NODE_DATA(new_nid) == NULL) {
|
||||
if (!node_online(new_nid)) {
|
||||
#ifdef CONFIG_MEMORY_HOTPLUG
|
||||
/*
|
||||
* Need to ensure that NODE_DATA is initialized for a node from
|
||||
|
@ -353,6 +353,14 @@ static void pseries_lpar_idle(void)
|
||||
pseries_idle_epilog();
|
||||
}
|
||||
|
||||
static bool pseries_reloc_on_exception_enabled;
|
||||
|
||||
bool pseries_reloc_on_exception(void)
|
||||
{
|
||||
return pseries_reloc_on_exception_enabled;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pseries_reloc_on_exception);
|
||||
|
||||
/*
|
||||
* Enable relocation on during exceptions. This has partition wide scope and
|
||||
* may take a while to complete, if it takes longer than one second we will
|
||||
@ -377,6 +385,7 @@ bool pseries_enable_reloc_on_exc(void)
|
||||
" on exceptions: %ld\n", rc);
|
||||
return false;
|
||||
}
|
||||
pseries_reloc_on_exception_enabled = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -404,7 +413,9 @@ void pseries_disable_reloc_on_exc(void)
|
||||
break;
|
||||
mdelay(get_longbusy_msecs(rc));
|
||||
}
|
||||
if (rc != H_SUCCESS)
|
||||
if (rc == H_SUCCESS)
|
||||
pseries_reloc_on_exception_enabled = false;
|
||||
else
|
||||
pr_warn("Warning: Failed to disable relocation on exceptions: %ld\n",
|
||||
rc);
|
||||
}
|
||||
|
@ -99,6 +99,7 @@ static struct attribute *vas_def_capab_attrs[] = {
|
||||
&nr_used_credits_attribute.attr,
|
||||
NULL,
|
||||
};
|
||||
ATTRIBUTE_GROUPS(vas_def_capab);
|
||||
|
||||
static struct attribute *vas_qos_capab_attrs[] = {
|
||||
&nr_total_credits_attribute.attr,
|
||||
@ -106,6 +107,7 @@ static struct attribute *vas_qos_capab_attrs[] = {
|
||||
&update_total_credits_attribute.attr,
|
||||
NULL,
|
||||
};
|
||||
ATTRIBUTE_GROUPS(vas_qos_capab);
|
||||
|
||||
static ssize_t vas_type_show(struct kobject *kobj, struct attribute *attr,
|
||||
char *buf)
|
||||
@ -154,13 +156,13 @@ static const struct sysfs_ops vas_sysfs_ops = {
|
||||
static struct kobj_type vas_def_attr_type = {
|
||||
.release = vas_type_release,
|
||||
.sysfs_ops = &vas_sysfs_ops,
|
||||
.default_attrs = vas_def_capab_attrs,
|
||||
.default_groups = vas_def_capab_groups,
|
||||
};
|
||||
|
||||
static struct kobj_type vas_qos_attr_type = {
|
||||
.release = vas_type_release,
|
||||
.sysfs_ops = &vas_sysfs_ops,
|
||||
.default_attrs = vas_qos_capab_attrs,
|
||||
.default_groups = vas_qos_capab_groups,
|
||||
};
|
||||
|
||||
static char *vas_caps_kobj_name(struct vas_caps_entry *centry,
|
||||
|
@ -653,8 +653,6 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
|
||||
vcpu->arch.isa);
|
||||
kvm_riscv_vcpu_host_fp_restore(&vcpu->arch.host_context);
|
||||
|
||||
csr_write(CSR_HGATP, 0);
|
||||
|
||||
csr->vsstatus = csr_read(CSR_VSSTATUS);
|
||||
csr->vsie = csr_read(CSR_VSIE);
|
||||
csr->vstvec = csr_read(CSR_VSTVEC);
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include <linux/err.h>
|
||||
#include <linux/kvm_host.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <asm/hwcap.h>
|
||||
|
||||
#ifdef CONFIG_FPU
|
||||
void kvm_riscv_vcpu_fp_reset(struct kvm_vcpu *vcpu)
|
||||
|
@ -302,7 +302,7 @@ static struct extra_reg intel_spr_extra_regs[] __read_mostly = {
|
||||
INTEL_UEVENT_EXTRA_REG(0x012a, MSR_OFFCORE_RSP_0, 0x3fffffffffull, RSP_0),
|
||||
INTEL_UEVENT_EXTRA_REG(0x012b, MSR_OFFCORE_RSP_1, 0x3fffffffffull, RSP_1),
|
||||
INTEL_UEVENT_PEBS_LDLAT_EXTRA_REG(0x01cd),
|
||||
INTEL_UEVENT_EXTRA_REG(0x01c6, MSR_PEBS_FRONTEND, 0x7fff17, FE),
|
||||
INTEL_UEVENT_EXTRA_REG(0x01c6, MSR_PEBS_FRONTEND, 0x7fff1f, FE),
|
||||
INTEL_UEVENT_EXTRA_REG(0x40ad, MSR_PEBS_FRONTEND, 0x7, FE),
|
||||
INTEL_UEVENT_EXTRA_REG(0x04c2, MSR_PEBS_FRONTEND, 0x8, FE),
|
||||
EVENT_EXTRA_END
|
||||
@ -5536,7 +5536,11 @@ static void intel_pmu_check_event_constraints(struct event_constraint *event_con
|
||||
/* Disabled fixed counters which are not in CPUID */
|
||||
c->idxmsk64 &= intel_ctrl;
|
||||
|
||||
if (c->idxmsk64 != INTEL_PMC_MSK_FIXED_REF_CYCLES)
|
||||
/*
|
||||
* Don't extend the pseudo-encoding to the
|
||||
* generic counters
|
||||
*/
|
||||
if (!use_fixed_pseudo_encoding(c->code))
|
||||
c->idxmsk64 |= (1ULL << num_counters) - 1;
|
||||
}
|
||||
c->idxmsk64 &=
|
||||
@ -6212,6 +6216,7 @@ __init int intel_pmu_init(void)
|
||||
|
||||
case INTEL_FAM6_ALDERLAKE:
|
||||
case INTEL_FAM6_ALDERLAKE_L:
|
||||
case INTEL_FAM6_RAPTORLAKE:
|
||||
/*
|
||||
* Alder Lake has 2 types of CPU, core and atom.
|
||||
*
|
||||
|
@ -40,7 +40,7 @@
|
||||
* Model specific counters:
|
||||
* MSR_CORE_C1_RES: CORE C1 Residency Counter
|
||||
* perf code: 0x00
|
||||
* Available model: SLM,AMT,GLM,CNL,ICX,TNT,ADL
|
||||
* Available model: SLM,AMT,GLM,CNL,ICX,TNT,ADL,RPL
|
||||
* Scope: Core (each processor core has a MSR)
|
||||
* MSR_CORE_C3_RESIDENCY: CORE C3 Residency Counter
|
||||
* perf code: 0x01
|
||||
@ -51,49 +51,50 @@
|
||||
* perf code: 0x02
|
||||
* Available model: SLM,AMT,NHM,WSM,SNB,IVB,HSW,BDW,
|
||||
* SKL,KNL,GLM,CNL,KBL,CML,ICL,ICX,
|
||||
* TGL,TNT,RKL,ADL
|
||||
* TGL,TNT,RKL,ADL,RPL
|
||||
* Scope: Core
|
||||
* MSR_CORE_C7_RESIDENCY: CORE C7 Residency Counter
|
||||
* perf code: 0x03
|
||||
* Available model: SNB,IVB,HSW,BDW,SKL,CNL,KBL,CML,
|
||||
* ICL,TGL,RKL,ADL
|
||||
* ICL,TGL,RKL,ADL,RPL
|
||||
* Scope: Core
|
||||
* MSR_PKG_C2_RESIDENCY: Package C2 Residency Counter.
|
||||
* perf code: 0x00
|
||||
* Available model: SNB,IVB,HSW,BDW,SKL,KNL,GLM,CNL,
|
||||
* KBL,CML,ICL,ICX,TGL,TNT,RKL,ADL
|
||||
* KBL,CML,ICL,ICX,TGL,TNT,RKL,ADL,
|
||||
* RPL
|
||||
* Scope: Package (physical package)
|
||||
* MSR_PKG_C3_RESIDENCY: Package C3 Residency Counter.
|
||||
* perf code: 0x01
|
||||
* Available model: NHM,WSM,SNB,IVB,HSW,BDW,SKL,KNL,
|
||||
* GLM,CNL,KBL,CML,ICL,TGL,TNT,RKL,
|
||||
* ADL
|
||||
* ADL,RPL
|
||||
* Scope: Package (physical package)
|
||||
* MSR_PKG_C6_RESIDENCY: Package C6 Residency Counter.
|
||||
* perf code: 0x02
|
||||
* Available model: SLM,AMT,NHM,WSM,SNB,IVB,HSW,BDW,
|
||||
* SKL,KNL,GLM,CNL,KBL,CML,ICL,ICX,
|
||||
* TGL,TNT,RKL,ADL
|
||||
* TGL,TNT,RKL,ADL,RPL
|
||||
* Scope: Package (physical package)
|
||||
* MSR_PKG_C7_RESIDENCY: Package C7 Residency Counter.
|
||||
* perf code: 0x03
|
||||
* Available model: NHM,WSM,SNB,IVB,HSW,BDW,SKL,CNL,
|
||||
* KBL,CML,ICL,TGL,RKL,ADL
|
||||
* KBL,CML,ICL,TGL,RKL,ADL,RPL
|
||||
* Scope: Package (physical package)
|
||||
* MSR_PKG_C8_RESIDENCY: Package C8 Residency Counter.
|
||||
* perf code: 0x04
|
||||
* Available model: HSW ULT,KBL,CNL,CML,ICL,TGL,RKL,
|
||||
* ADL
|
||||
* ADL,RPL
|
||||
* Scope: Package (physical package)
|
||||
* MSR_PKG_C9_RESIDENCY: Package C9 Residency Counter.
|
||||
* perf code: 0x05
|
||||
* Available model: HSW ULT,KBL,CNL,CML,ICL,TGL,RKL,
|
||||
* ADL
|
||||
* ADL,RPL
|
||||
* Scope: Package (physical package)
|
||||
* MSR_PKG_C10_RESIDENCY: Package C10 Residency Counter.
|
||||
* perf code: 0x06
|
||||
* Available model: HSW ULT,KBL,GLM,CNL,CML,ICL,TGL,
|
||||
* TNT,RKL,ADL
|
||||
* TNT,RKL,ADL,RPL
|
||||
* Scope: Package (physical package)
|
||||
*
|
||||
*/
|
||||
@ -680,6 +681,7 @@ static const struct x86_cpu_id intel_cstates_match[] __initconst = {
|
||||
X86_MATCH_INTEL_FAM6_MODEL(ROCKETLAKE, &icl_cstates),
|
||||
X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE, &adl_cstates),
|
||||
X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE_L, &adl_cstates),
|
||||
X86_MATCH_INTEL_FAM6_MODEL(RAPTORLAKE, &adl_cstates),
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(x86cpu, intel_cstates_match);
|
||||
|
@ -1828,6 +1828,7 @@ static const struct x86_cpu_id intel_uncore_match[] __initconst = {
|
||||
X86_MATCH_INTEL_FAM6_MODEL(ROCKETLAKE, &rkl_uncore_init),
|
||||
X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE, &adl_uncore_init),
|
||||
X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE_L, &adl_uncore_init),
|
||||
X86_MATCH_INTEL_FAM6_MODEL(RAPTORLAKE, &adl_uncore_init),
|
||||
X86_MATCH_INTEL_FAM6_MODEL(SAPPHIRERAPIDS_X, &spr_uncore_init),
|
||||
X86_MATCH_INTEL_FAM6_MODEL(ATOM_TREMONT_D, &snr_uncore_init),
|
||||
{},
|
||||
|
@ -79,6 +79,10 @@
|
||||
#define PCI_DEVICE_ID_INTEL_ADL_14_IMC 0x4650
|
||||
#define PCI_DEVICE_ID_INTEL_ADL_15_IMC 0x4668
|
||||
#define PCI_DEVICE_ID_INTEL_ADL_16_IMC 0x4670
|
||||
#define PCI_DEVICE_ID_INTEL_RPL_1_IMC 0xA700
|
||||
#define PCI_DEVICE_ID_INTEL_RPL_2_IMC 0xA702
|
||||
#define PCI_DEVICE_ID_INTEL_RPL_3_IMC 0xA706
|
||||
#define PCI_DEVICE_ID_INTEL_RPL_4_IMC 0xA709
|
||||
|
||||
/* SNB event control */
|
||||
#define SNB_UNC_CTL_EV_SEL_MASK 0x000000ff
|
||||
@ -1406,6 +1410,22 @@ static const struct pci_device_id tgl_uncore_pci_ids[] = {
|
||||
PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ADL_16_IMC),
|
||||
.driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
|
||||
},
|
||||
{ /* IMC */
|
||||
PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_RPL_1_IMC),
|
||||
.driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
|
||||
},
|
||||
{ /* IMC */
|
||||
PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_RPL_2_IMC),
|
||||
.driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
|
||||
},
|
||||
{ /* IMC */
|
||||
PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_RPL_3_IMC),
|
||||
.driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
|
||||
},
|
||||
{ /* IMC */
|
||||
PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_RPL_4_IMC),
|
||||
.driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
|
||||
},
|
||||
{ /* end: all zeroes */ }
|
||||
};
|
||||
|
||||
|
@ -103,6 +103,7 @@ static bool test_intel(int idx, void *data)
|
||||
case INTEL_FAM6_ROCKETLAKE:
|
||||
case INTEL_FAM6_ALDERLAKE:
|
||||
case INTEL_FAM6_ALDERLAKE_L:
|
||||
case INTEL_FAM6_RAPTORLAKE:
|
||||
if (idx == PERF_MSR_SMI || idx == PERF_MSR_PPERF)
|
||||
return true;
|
||||
break;
|
||||
|
@ -154,24 +154,24 @@
|
||||
|
||||
# define DEFINE_EXTABLE_TYPE_REG \
|
||||
".macro extable_type_reg type:req reg:req\n" \
|
||||
".set found, 0\n" \
|
||||
".set regnr, 0\n" \
|
||||
".set .Lfound, 0\n" \
|
||||
".set .Lregnr, 0\n" \
|
||||
".irp rs,rax,rcx,rdx,rbx,rsp,rbp,rsi,rdi,r8,r9,r10,r11,r12,r13,r14,r15\n" \
|
||||
".ifc \\reg, %%\\rs\n" \
|
||||
".set found, found+1\n" \
|
||||
".long \\type + (regnr << 8)\n" \
|
||||
".set .Lfound, .Lfound+1\n" \
|
||||
".long \\type + (.Lregnr << 8)\n" \
|
||||
".endif\n" \
|
||||
".set regnr, regnr+1\n" \
|
||||
".set .Lregnr, .Lregnr+1\n" \
|
||||
".endr\n" \
|
||||
".set regnr, 0\n" \
|
||||
".set .Lregnr, 0\n" \
|
||||
".irp rs,eax,ecx,edx,ebx,esp,ebp,esi,edi,r8d,r9d,r10d,r11d,r12d,r13d,r14d,r15d\n" \
|
||||
".ifc \\reg, %%\\rs\n" \
|
||||
".set found, found+1\n" \
|
||||
".long \\type + (regnr << 8)\n" \
|
||||
".set .Lfound, .Lfound+1\n" \
|
||||
".long \\type + (.Lregnr << 8)\n" \
|
||||
".endif\n" \
|
||||
".set regnr, regnr+1\n" \
|
||||
".set .Lregnr, .Lregnr+1\n" \
|
||||
".endr\n" \
|
||||
".if (found != 1)\n" \
|
||||
".if (.Lfound != 1)\n" \
|
||||
".error \"extable_type_reg: bad register argument\"\n" \
|
||||
".endif\n" \
|
||||
".endm\n"
|
||||
|
@ -78,9 +78,9 @@ do { \
|
||||
*/
|
||||
#define __WARN_FLAGS(flags) \
|
||||
do { \
|
||||
__auto_type f = BUGFLAG_WARNING|(flags); \
|
||||
__auto_type __flags = BUGFLAG_WARNING|(flags); \
|
||||
instrumentation_begin(); \
|
||||
_BUG_FLAGS(ASM_UD2, f, ASM_REACHABLE); \
|
||||
_BUG_FLAGS(ASM_UD2, __flags, ASM_REACHABLE); \
|
||||
instrumentation_end(); \
|
||||
} while (0)
|
||||
|
||||
|
@ -28,15 +28,13 @@ typedef u16 compat_ipc_pid_t;
|
||||
typedef __kernel_fsid_t compat_fsid_t;
|
||||
|
||||
struct compat_stat {
|
||||
compat_dev_t st_dev;
|
||||
u16 __pad1;
|
||||
u32 st_dev;
|
||||
compat_ino_t st_ino;
|
||||
compat_mode_t st_mode;
|
||||
compat_nlink_t st_nlink;
|
||||
__compat_uid_t st_uid;
|
||||
__compat_gid_t st_gid;
|
||||
compat_dev_t st_rdev;
|
||||
u16 __pad2;
|
||||
u32 st_rdev;
|
||||
u32 st_size;
|
||||
u32 st_blksize;
|
||||
u32 st_blocks;
|
||||
|
@ -974,12 +974,10 @@ enum hv_tsc_page_status {
|
||||
HV_TSC_PAGE_UNSET = 0,
|
||||
/* TSC page MSR was written by the guest, update pending */
|
||||
HV_TSC_PAGE_GUEST_CHANGED,
|
||||
/* TSC page MSR was written by KVM userspace, update pending */
|
||||
/* TSC page update was triggered from the host side */
|
||||
HV_TSC_PAGE_HOST_CHANGED,
|
||||
/* TSC page was properly set up and is currently active */
|
||||
HV_TSC_PAGE_SET,
|
||||
/* TSC page is currently being updated and therefore is inactive */
|
||||
HV_TSC_PAGE_UPDATING,
|
||||
/* TSC page was set up with an inaccessible GPA */
|
||||
HV_TSC_PAGE_BROKEN,
|
||||
};
|
||||
@ -1052,6 +1050,7 @@ enum kvm_apicv_inhibit {
|
||||
APICV_INHIBIT_REASON_X2APIC,
|
||||
APICV_INHIBIT_REASON_BLOCKIRQ,
|
||||
APICV_INHIBIT_REASON_ABSENT,
|
||||
APICV_INHIBIT_REASON_SEV,
|
||||
};
|
||||
|
||||
struct kvm_arch {
|
||||
@ -1585,8 +1584,9 @@ static inline int kvm_arch_flush_remote_tlb(struct kvm *kvm)
|
||||
#define kvm_arch_pmi_in_guest(vcpu) \
|
||||
((vcpu) && (vcpu)->arch.handling_intr_from_guest)
|
||||
|
||||
int kvm_mmu_module_init(void);
|
||||
void kvm_mmu_module_exit(void);
|
||||
void kvm_mmu_x86_module_init(void);
|
||||
int kvm_mmu_vendor_module_init(void);
|
||||
void kvm_mmu_vendor_module_exit(void);
|
||||
|
||||
void kvm_mmu_destroy(struct kvm_vcpu *vcpu);
|
||||
int kvm_mmu_create(struct kvm_vcpu *vcpu);
|
||||
|
@ -12,14 +12,17 @@ int pci_msi_prepare(struct irq_domain *domain, struct device *dev, int nvec,
|
||||
/* Structs and defines for the X86 specific MSI message format */
|
||||
|
||||
typedef struct x86_msi_data {
|
||||
u32 vector : 8,
|
||||
delivery_mode : 3,
|
||||
dest_mode_logical : 1,
|
||||
reserved : 2,
|
||||
active_low : 1,
|
||||
is_level : 1;
|
||||
|
||||
u32 dmar_subhandle;
|
||||
union {
|
||||
struct {
|
||||
u32 vector : 8,
|
||||
delivery_mode : 3,
|
||||
dest_mode_logical : 1,
|
||||
reserved : 2,
|
||||
active_low : 1,
|
||||
is_level : 1;
|
||||
};
|
||||
u32 dmar_subhandle;
|
||||
};
|
||||
} __attribute__ ((packed)) arch_msi_msg_data_t;
|
||||
#define arch_msi_msg_data x86_msi_data
|
||||
|
||||
|
@ -38,9 +38,9 @@
|
||||
#define arch_raw_cpu_ptr(ptr) \
|
||||
({ \
|
||||
unsigned long tcp_ptr__; \
|
||||
asm volatile("add " __percpu_arg(1) ", %0" \
|
||||
: "=r" (tcp_ptr__) \
|
||||
: "m" (this_cpu_off), "0" (ptr)); \
|
||||
asm ("add " __percpu_arg(1) ", %0" \
|
||||
: "=r" (tcp_ptr__) \
|
||||
: "m" (this_cpu_off), "0" (ptr)); \
|
||||
(typeof(*(ptr)) __kernel __force *)tcp_ptr__; \
|
||||
})
|
||||
#else
|
||||
|
@ -241,6 +241,11 @@ struct x86_pmu_capability {
|
||||
#define INTEL_PMC_IDX_FIXED_SLOTS (INTEL_PMC_IDX_FIXED + 3)
|
||||
#define INTEL_PMC_MSK_FIXED_SLOTS (1ULL << INTEL_PMC_IDX_FIXED_SLOTS)
|
||||
|
||||
static inline bool use_fixed_pseudo_encoding(u64 code)
|
||||
{
|
||||
return !(code & 0xff);
|
||||
}
|
||||
|
||||
/*
|
||||
* We model BTS tracing as another fixed-mode PMC.
|
||||
*
|
||||
|
@ -38,6 +38,8 @@
|
||||
#define ARCH_DEFINE_STATIC_CALL_NULL_TRAMP(name) \
|
||||
__ARCH_DEFINE_STATIC_CALL_TRAMP(name, "ret; int3; nop; nop; nop")
|
||||
|
||||
#define ARCH_DEFINE_STATIC_CALL_RET0_TRAMP(name) \
|
||||
ARCH_DEFINE_STATIC_CALL_TRAMP(name, __static_call_return0)
|
||||
|
||||
#define ARCH_ADD_TRAMP_KEY(name) \
|
||||
asm(".pushsection .static_call_tramp_key, \"a\" \n" \
|
||||
|
@ -12,10 +12,9 @@ enum insn_type {
|
||||
};
|
||||
|
||||
/*
|
||||
* data16 data16 xorq %rax, %rax - a single 5 byte instruction that clears %rax
|
||||
* The REX.W cancels the effect of any data16.
|
||||
* cs cs cs xorl %eax, %eax - a single 5 byte instruction that clears %[er]ax
|
||||
*/
|
||||
static const u8 xor5rax[] = { 0x66, 0x66, 0x48, 0x31, 0xc0 };
|
||||
static const u8 xor5rax[] = { 0x2e, 0x2e, 0x2e, 0x31, 0xc0 };
|
||||
|
||||
static const u8 retinsn[] = { RET_INSN_OPCODE, 0xcc, 0xcc, 0xcc, 0xcc };
|
||||
|
||||
|
@ -1135,11 +1135,13 @@ void kvm_hv_setup_tsc_page(struct kvm *kvm,
|
||||
BUILD_BUG_ON(sizeof(tsc_seq) != sizeof(hv->tsc_ref.tsc_sequence));
|
||||
BUILD_BUG_ON(offsetof(struct ms_hyperv_tsc_page, tsc_sequence) != 0);
|
||||
|
||||
if (hv->hv_tsc_page_status == HV_TSC_PAGE_BROKEN ||
|
||||
hv->hv_tsc_page_status == HV_TSC_PAGE_UNSET)
|
||||
return;
|
||||
|
||||
mutex_lock(&hv->hv_lock);
|
||||
|
||||
if (hv->hv_tsc_page_status == HV_TSC_PAGE_BROKEN ||
|
||||
hv->hv_tsc_page_status == HV_TSC_PAGE_SET ||
|
||||
hv->hv_tsc_page_status == HV_TSC_PAGE_UNSET)
|
||||
goto out_unlock;
|
||||
|
||||
if (!(hv->hv_tsc_page & HV_X64_MSR_TSC_REFERENCE_ENABLE))
|
||||
goto out_unlock;
|
||||
|
||||
@ -1201,45 +1203,19 @@ void kvm_hv_setup_tsc_page(struct kvm *kvm,
|
||||
mutex_unlock(&hv->hv_lock);
|
||||
}
|
||||
|
||||
void kvm_hv_invalidate_tsc_page(struct kvm *kvm)
|
||||
void kvm_hv_request_tsc_page_update(struct kvm *kvm)
|
||||
{
|
||||
struct kvm_hv *hv = to_kvm_hv(kvm);
|
||||
u64 gfn;
|
||||
int idx;
|
||||
|
||||
if (hv->hv_tsc_page_status == HV_TSC_PAGE_BROKEN ||
|
||||
hv->hv_tsc_page_status == HV_TSC_PAGE_UNSET ||
|
||||
tsc_page_update_unsafe(hv))
|
||||
return;
|
||||
|
||||
mutex_lock(&hv->hv_lock);
|
||||
|
||||
if (!(hv->hv_tsc_page & HV_X64_MSR_TSC_REFERENCE_ENABLE))
|
||||
goto out_unlock;
|
||||
if (hv->hv_tsc_page_status == HV_TSC_PAGE_SET &&
|
||||
!tsc_page_update_unsafe(hv))
|
||||
hv->hv_tsc_page_status = HV_TSC_PAGE_HOST_CHANGED;
|
||||
|
||||
/* Preserve HV_TSC_PAGE_GUEST_CHANGED/HV_TSC_PAGE_HOST_CHANGED states */
|
||||
if (hv->hv_tsc_page_status == HV_TSC_PAGE_SET)
|
||||
hv->hv_tsc_page_status = HV_TSC_PAGE_UPDATING;
|
||||
|
||||
gfn = hv->hv_tsc_page >> HV_X64_MSR_TSC_REFERENCE_ADDRESS_SHIFT;
|
||||
|
||||
hv->tsc_ref.tsc_sequence = 0;
|
||||
|
||||
/*
|
||||
* Take the srcu lock as memslots will be accessed to check the gfn
|
||||
* cache generation against the memslots generation.
|
||||
*/
|
||||
idx = srcu_read_lock(&kvm->srcu);
|
||||
if (kvm_write_guest(kvm, gfn_to_gpa(gfn),
|
||||
&hv->tsc_ref, sizeof(hv->tsc_ref.tsc_sequence)))
|
||||
hv->hv_tsc_page_status = HV_TSC_PAGE_BROKEN;
|
||||
srcu_read_unlock(&kvm->srcu, idx);
|
||||
|
||||
out_unlock:
|
||||
mutex_unlock(&hv->hv_lock);
|
||||
}
|
||||
|
||||
|
||||
static bool hv_check_msr_access(struct kvm_vcpu_hv *hv_vcpu, u32 msr)
|
||||
{
|
||||
if (!hv_vcpu->enforce_cpuid)
|
||||
|
@ -137,7 +137,7 @@ void kvm_hv_process_stimers(struct kvm_vcpu *vcpu);
|
||||
|
||||
void kvm_hv_setup_tsc_page(struct kvm *kvm,
|
||||
struct pvclock_vcpu_time_info *hv_clock);
|
||||
void kvm_hv_invalidate_tsc_page(struct kvm *kvm);
|
||||
void kvm_hv_request_tsc_page_update(struct kvm *kvm);
|
||||
|
||||
void kvm_hv_init_vm(struct kvm *kvm);
|
||||
void kvm_hv_destroy_vm(struct kvm *kvm);
|
||||
|
@ -6237,12 +6237,24 @@ static int set_nx_huge_pages(const char *val, const struct kernel_param *kp)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int kvm_mmu_module_init(void)
|
||||
/*
|
||||
* nx_huge_pages needs to be resolved to true/false when kvm.ko is loaded, as
|
||||
* its default value of -1 is technically undefined behavior for a boolean.
|
||||
*/
|
||||
void kvm_mmu_x86_module_init(void)
|
||||
{
|
||||
int ret = -ENOMEM;
|
||||
|
||||
if (nx_huge_pages == -1)
|
||||
__set_nx_huge_pages(get_nx_auto_mode());
|
||||
}
|
||||
|
||||
/*
|
||||
* The bulk of the MMU initialization is deferred until the vendor module is
|
||||
* loaded as many of the masks/values may be modified by VMX or SVM, i.e. need
|
||||
* to be reset when a potentially different vendor module is loaded.
|
||||
*/
|
||||
int kvm_mmu_vendor_module_init(void)
|
||||
{
|
||||
int ret = -ENOMEM;
|
||||
|
||||
/*
|
||||
* MMU roles use union aliasing which is, generally speaking, an
|
||||
@ -6290,7 +6302,7 @@ void kvm_mmu_destroy(struct kvm_vcpu *vcpu)
|
||||
mmu_free_memory_caches(vcpu);
|
||||
}
|
||||
|
||||
void kvm_mmu_module_exit(void)
|
||||
void kvm_mmu_vendor_module_exit(void)
|
||||
{
|
||||
mmu_destroy_caches();
|
||||
percpu_counter_destroy(&kvm_total_used_mmu_pages);
|
||||
|
@ -51,7 +51,7 @@ void kvm_mmu_uninit_tdp_mmu(struct kvm *kvm)
|
||||
if (!kvm->arch.tdp_mmu_enabled)
|
||||
return;
|
||||
|
||||
flush_workqueue(kvm->arch.tdp_mmu_zap_wq);
|
||||
/* Also waits for any queued work items. */
|
||||
destroy_workqueue(kvm->arch.tdp_mmu_zap_wq);
|
||||
|
||||
WARN_ON(!list_empty(&kvm->arch.tdp_mmu_pages));
|
||||
|
@ -837,7 +837,8 @@ bool avic_check_apicv_inhibit_reasons(enum kvm_apicv_inhibit reason)
|
||||
BIT(APICV_INHIBIT_REASON_IRQWIN) |
|
||||
BIT(APICV_INHIBIT_REASON_PIT_REINJ) |
|
||||
BIT(APICV_INHIBIT_REASON_X2APIC) |
|
||||
BIT(APICV_INHIBIT_REASON_BLOCKIRQ);
|
||||
BIT(APICV_INHIBIT_REASON_BLOCKIRQ) |
|
||||
BIT(APICV_INHIBIT_REASON_SEV);
|
||||
|
||||
return supported & BIT(reason);
|
||||
}
|
||||
|
@ -260,6 +260,8 @@ static int sev_guest_init(struct kvm *kvm, struct kvm_sev_cmd *argp)
|
||||
INIT_LIST_HEAD(&sev->regions_list);
|
||||
INIT_LIST_HEAD(&sev->mirror_vms);
|
||||
|
||||
kvm_set_apicv_inhibit(kvm, APICV_INHIBIT_REASON_SEV);
|
||||
|
||||
return 0;
|
||||
|
||||
e_free:
|
||||
@ -465,6 +467,7 @@ static void sev_clflush_pages(struct page *pages[], unsigned long npages)
|
||||
page_virtual = kmap_atomic(pages[i]);
|
||||
clflush_cache_range(page_virtual, PAGE_SIZE);
|
||||
kunmap_atomic(page_virtual);
|
||||
cond_resched();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2901,7 +2901,7 @@ static void kvm_end_pvclock_update(struct kvm *kvm)
|
||||
|
||||
static void kvm_update_masterclock(struct kvm *kvm)
|
||||
{
|
||||
kvm_hv_invalidate_tsc_page(kvm);
|
||||
kvm_hv_request_tsc_page_update(kvm);
|
||||
kvm_start_pvclock_update(kvm);
|
||||
pvclock_update_vm_gtod_copy(kvm);
|
||||
kvm_end_pvclock_update(kvm);
|
||||
@ -3113,8 +3113,7 @@ static int kvm_guest_time_update(struct kvm_vcpu *v)
|
||||
offsetof(struct compat_vcpu_info, time));
|
||||
if (vcpu->xen.vcpu_time_info_set)
|
||||
kvm_setup_pvclock_page(v, &vcpu->xen.vcpu_time_info_cache, 0);
|
||||
if (!v->vcpu_idx)
|
||||
kvm_hv_setup_tsc_page(v->kvm, &vcpu->hv_clock);
|
||||
kvm_hv_setup_tsc_page(v->kvm, &vcpu->hv_clock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -6241,7 +6240,7 @@ static int kvm_vm_ioctl_set_clock(struct kvm *kvm, void __user *argp)
|
||||
if (data.flags & ~KVM_CLOCK_VALID_FLAGS)
|
||||
return -EINVAL;
|
||||
|
||||
kvm_hv_invalidate_tsc_page(kvm);
|
||||
kvm_hv_request_tsc_page_update(kvm);
|
||||
kvm_start_pvclock_update(kvm);
|
||||
pvclock_update_vm_gtod_copy(kvm);
|
||||
|
||||
@ -8926,7 +8925,7 @@ int kvm_arch_init(void *opaque)
|
||||
}
|
||||
kvm_nr_uret_msrs = 0;
|
||||
|
||||
r = kvm_mmu_module_init();
|
||||
r = kvm_mmu_vendor_module_init();
|
||||
if (r)
|
||||
goto out_free_percpu;
|
||||
|
||||
@ -8974,7 +8973,7 @@ void kvm_arch_exit(void)
|
||||
cancel_work_sync(&pvclock_gtod_work);
|
||||
#endif
|
||||
kvm_x86_ops.hardware_enable = NULL;
|
||||
kvm_mmu_module_exit();
|
||||
kvm_mmu_vendor_module_exit();
|
||||
free_percpu(user_return_msrs);
|
||||
kmem_cache_destroy(x86_emulator_cache);
|
||||
#ifdef CONFIG_KVM_XEN
|
||||
@ -12986,3 +12985,19 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_vmgexit_enter);
|
||||
EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_vmgexit_exit);
|
||||
EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_vmgexit_msr_protocol_enter);
|
||||
EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_vmgexit_msr_protocol_exit);
|
||||
|
||||
static int __init kvm_x86_init(void)
|
||||
{
|
||||
kvm_mmu_x86_module_init();
|
||||
return 0;
|
||||
}
|
||||
module_init(kvm_x86_init);
|
||||
|
||||
static void __exit kvm_x86_exit(void)
|
||||
{
|
||||
/*
|
||||
* If module_init() is implemented, module_exit() must also be
|
||||
* implemented to allow module unload.
|
||||
*/
|
||||
}
|
||||
module_exit(kvm_x86_exit);
|
||||
|
@ -855,13 +855,11 @@ static void flush_tlb_func(void *info)
|
||||
nr_invalidate);
|
||||
}
|
||||
|
||||
static bool tlb_is_not_lazy(int cpu)
|
||||
static bool tlb_is_not_lazy(int cpu, void *data)
|
||||
{
|
||||
return !per_cpu(cpu_tlbstate_shared.is_lazy, cpu);
|
||||
}
|
||||
|
||||
static DEFINE_PER_CPU(cpumask_t, flush_tlb_mask);
|
||||
|
||||
DEFINE_PER_CPU_SHARED_ALIGNED(struct tlb_state_shared, cpu_tlbstate_shared);
|
||||
EXPORT_PER_CPU_SYMBOL(cpu_tlbstate_shared);
|
||||
|
||||
@ -890,36 +888,11 @@ STATIC_NOPV void native_flush_tlb_multi(const struct cpumask *cpumask,
|
||||
* up on the new contents of what used to be page tables, while
|
||||
* doing a speculative memory access.
|
||||
*/
|
||||
if (info->freed_tables) {
|
||||
if (info->freed_tables)
|
||||
on_each_cpu_mask(cpumask, flush_tlb_func, (void *)info, true);
|
||||
} else {
|
||||
/*
|
||||
* Although we could have used on_each_cpu_cond_mask(),
|
||||
* open-coding it has performance advantages, as it eliminates
|
||||
* the need for indirect calls or retpolines. In addition, it
|
||||
* allows to use a designated cpumask for evaluating the
|
||||
* condition, instead of allocating one.
|
||||
*
|
||||
* This code works under the assumption that there are no nested
|
||||
* TLB flushes, an assumption that is already made in
|
||||
* flush_tlb_mm_range().
|
||||
*
|
||||
* cond_cpumask is logically a stack-local variable, but it is
|
||||
* more efficient to have it off the stack and not to allocate
|
||||
* it on demand. Preemption is disabled and this code is
|
||||
* non-reentrant.
|
||||
*/
|
||||
struct cpumask *cond_cpumask = this_cpu_ptr(&flush_tlb_mask);
|
||||
int cpu;
|
||||
|
||||
cpumask_clear(cond_cpumask);
|
||||
|
||||
for_each_cpu(cpu, cpumask) {
|
||||
if (tlb_is_not_lazy(cpu))
|
||||
__cpumask_set_cpu(cpu, cond_cpumask);
|
||||
}
|
||||
on_each_cpu_mask(cond_cpumask, flush_tlb_func, (void *)info, true);
|
||||
}
|
||||
else
|
||||
on_each_cpu_cond_mask(tlb_is_not_lazy, flush_tlb_func,
|
||||
(void *)info, 1, cpumask);
|
||||
}
|
||||
|
||||
void flush_tlb_multi(const struct cpumask *cpumask,
|
||||
|
@ -412,6 +412,7 @@ static void emit_indirect_jump(u8 **pprog, int reg, u8 *ip)
|
||||
EMIT_LFENCE();
|
||||
EMIT2(0xFF, 0xE0 + reg);
|
||||
} else if (cpu_feature_enabled(X86_FEATURE_RETPOLINE)) {
|
||||
OPTIMIZER_HIDE_VAR(reg);
|
||||
emit_jump(&prog, &__x86_indirect_thunk_array[reg], ip);
|
||||
} else
|
||||
#endif
|
||||
|
@ -570,8 +570,7 @@ static int acpi_idle_play_dead(struct cpuidle_device *dev, int index)
|
||||
{
|
||||
struct acpi_processor_cx *cx = per_cpu(acpi_cstate[index], dev->cpu);
|
||||
|
||||
if (cx->type == ACPI_STATE_C3)
|
||||
ACPI_FLUSH_CPU_CACHE();
|
||||
ACPI_FLUSH_CPU_CACHE();
|
||||
|
||||
while (1) {
|
||||
|
||||
|
@ -588,19 +588,6 @@ static struct acpi_device *handle_to_device(acpi_handle handle,
|
||||
return adev;
|
||||
}
|
||||
|
||||
int acpi_bus_get_device(acpi_handle handle, struct acpi_device **device)
|
||||
{
|
||||
if (!device)
|
||||
return -EINVAL;
|
||||
|
||||
*device = handle_to_device(handle, NULL);
|
||||
if (!*device)
|
||||
return -ENODEV;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(acpi_bus_get_device);
|
||||
|
||||
/**
|
||||
* acpi_fetch_acpi_dev - Retrieve ACPI device object.
|
||||
* @handle: ACPI handle associated with the requested ACPI device object.
|
||||
|
@ -296,6 +296,7 @@ int driver_deferred_probe_check_state(struct device *dev)
|
||||
|
||||
return -EPROBE_DEFER;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(driver_deferred_probe_check_state);
|
||||
|
||||
static void deferred_probe_timeout_work_func(struct work_struct *work)
|
||||
{
|
||||
|
@ -1638,22 +1638,22 @@ struct sib_info {
|
||||
};
|
||||
void drbd_bcast_event(struct drbd_device *device, const struct sib_info *sib);
|
||||
|
||||
extern void notify_resource_state(struct sk_buff *,
|
||||
extern int notify_resource_state(struct sk_buff *,
|
||||
unsigned int,
|
||||
struct drbd_resource *,
|
||||
struct resource_info *,
|
||||
enum drbd_notification_type);
|
||||
extern void notify_device_state(struct sk_buff *,
|
||||
extern int notify_device_state(struct sk_buff *,
|
||||
unsigned int,
|
||||
struct drbd_device *,
|
||||
struct device_info *,
|
||||
enum drbd_notification_type);
|
||||
extern void notify_connection_state(struct sk_buff *,
|
||||
extern int notify_connection_state(struct sk_buff *,
|
||||
unsigned int,
|
||||
struct drbd_connection *,
|
||||
struct connection_info *,
|
||||
enum drbd_notification_type);
|
||||
extern void notify_peer_device_state(struct sk_buff *,
|
||||
extern int notify_peer_device_state(struct sk_buff *,
|
||||
unsigned int,
|
||||
struct drbd_peer_device *,
|
||||
struct peer_device_info *,
|
||||
|
@ -2719,6 +2719,7 @@ enum drbd_ret_code drbd_create_device(struct drbd_config_context *adm_ctx, unsig
|
||||
sprintf(disk->disk_name, "drbd%d", minor);
|
||||
disk->private_data = device;
|
||||
|
||||
blk_queue_flag_set(QUEUE_FLAG_STABLE_WRITES, disk->queue);
|
||||
blk_queue_write_cache(disk->queue, true, true);
|
||||
/* Setting the max_hw_sectors to an odd value of 8kibyte here
|
||||
This triggers a max_bio_size message upon first attach or connect */
|
||||
@ -2773,12 +2774,12 @@ enum drbd_ret_code drbd_create_device(struct drbd_config_context *adm_ctx, unsig
|
||||
|
||||
if (init_submitter(device)) {
|
||||
err = ERR_NOMEM;
|
||||
goto out_idr_remove_vol;
|
||||
goto out_idr_remove_from_resource;
|
||||
}
|
||||
|
||||
err = add_disk(disk);
|
||||
if (err)
|
||||
goto out_idr_remove_vol;
|
||||
goto out_idr_remove_from_resource;
|
||||
|
||||
/* inherit the connection state */
|
||||
device->state.conn = first_connection(resource)->cstate;
|
||||
@ -2792,8 +2793,6 @@ enum drbd_ret_code drbd_create_device(struct drbd_config_context *adm_ctx, unsig
|
||||
drbd_debugfs_device_add(device);
|
||||
return NO_ERROR;
|
||||
|
||||
out_idr_remove_vol:
|
||||
idr_remove(&connection->peer_devices, vnr);
|
||||
out_idr_remove_from_resource:
|
||||
for_each_connection(connection, resource) {
|
||||
peer_device = idr_remove(&connection->peer_devices, vnr);
|
||||
|
@ -4549,7 +4549,7 @@ static int nla_put_notification_header(struct sk_buff *msg,
|
||||
return drbd_notification_header_to_skb(msg, &nh, true);
|
||||
}
|
||||
|
||||
void notify_resource_state(struct sk_buff *skb,
|
||||
int notify_resource_state(struct sk_buff *skb,
|
||||
unsigned int seq,
|
||||
struct drbd_resource *resource,
|
||||
struct resource_info *resource_info,
|
||||
@ -4591,16 +4591,17 @@ void notify_resource_state(struct sk_buff *skb,
|
||||
if (err && err != -ESRCH)
|
||||
goto failed;
|
||||
}
|
||||
return;
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
nlmsg_free(skb);
|
||||
failed:
|
||||
drbd_err(resource, "Error %d while broadcasting event. Event seq:%u\n",
|
||||
err, seq);
|
||||
return err;
|
||||
}
|
||||
|
||||
void notify_device_state(struct sk_buff *skb,
|
||||
int notify_device_state(struct sk_buff *skb,
|
||||
unsigned int seq,
|
||||
struct drbd_device *device,
|
||||
struct device_info *device_info,
|
||||
@ -4640,16 +4641,17 @@ void notify_device_state(struct sk_buff *skb,
|
||||
if (err && err != -ESRCH)
|
||||
goto failed;
|
||||
}
|
||||
return;
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
nlmsg_free(skb);
|
||||
failed:
|
||||
drbd_err(device, "Error %d while broadcasting event. Event seq:%u\n",
|
||||
err, seq);
|
||||
return err;
|
||||
}
|
||||
|
||||
void notify_connection_state(struct sk_buff *skb,
|
||||
int notify_connection_state(struct sk_buff *skb,
|
||||
unsigned int seq,
|
||||
struct drbd_connection *connection,
|
||||
struct connection_info *connection_info,
|
||||
@ -4689,16 +4691,17 @@ void notify_connection_state(struct sk_buff *skb,
|
||||
if (err && err != -ESRCH)
|
||||
goto failed;
|
||||
}
|
||||
return;
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
nlmsg_free(skb);
|
||||
failed:
|
||||
drbd_err(connection, "Error %d while broadcasting event. Event seq:%u\n",
|
||||
err, seq);
|
||||
return err;
|
||||
}
|
||||
|
||||
void notify_peer_device_state(struct sk_buff *skb,
|
||||
int notify_peer_device_state(struct sk_buff *skb,
|
||||
unsigned int seq,
|
||||
struct drbd_peer_device *peer_device,
|
||||
struct peer_device_info *peer_device_info,
|
||||
@ -4739,13 +4742,14 @@ void notify_peer_device_state(struct sk_buff *skb,
|
||||
if (err && err != -ESRCH)
|
||||
goto failed;
|
||||
}
|
||||
return;
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
nlmsg_free(skb);
|
||||
failed:
|
||||
drbd_err(peer_device, "Error %d while broadcasting event. Event seq:%u\n",
|
||||
err, seq);
|
||||
return err;
|
||||
}
|
||||
|
||||
void notify_helper(enum drbd_notification_type type,
|
||||
@ -4796,7 +4800,7 @@ void notify_helper(enum drbd_notification_type type,
|
||||
err, seq);
|
||||
}
|
||||
|
||||
static void notify_initial_state_done(struct sk_buff *skb, unsigned int seq)
|
||||
static int notify_initial_state_done(struct sk_buff *skb, unsigned int seq)
|
||||
{
|
||||
struct drbd_genlmsghdr *dh;
|
||||
int err;
|
||||
@ -4810,11 +4814,12 @@ static void notify_initial_state_done(struct sk_buff *skb, unsigned int seq)
|
||||
if (nla_put_notification_header(skb, NOTIFY_EXISTS))
|
||||
goto nla_put_failure;
|
||||
genlmsg_end(skb, dh);
|
||||
return;
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
nlmsg_free(skb);
|
||||
pr_err("Error %d sending event. Event seq:%u\n", err, seq);
|
||||
return err;
|
||||
}
|
||||
|
||||
static void free_state_changes(struct list_head *list)
|
||||
@ -4841,6 +4846,7 @@ static int get_initial_state(struct sk_buff *skb, struct netlink_callback *cb)
|
||||
unsigned int seq = cb->args[2];
|
||||
unsigned int n;
|
||||
enum drbd_notification_type flags = 0;
|
||||
int err = 0;
|
||||
|
||||
/* There is no need for taking notification_mutex here: it doesn't
|
||||
matter if the initial state events mix with later state chage
|
||||
@ -4849,32 +4855,32 @@ static int get_initial_state(struct sk_buff *skb, struct netlink_callback *cb)
|
||||
|
||||
cb->args[5]--;
|
||||
if (cb->args[5] == 1) {
|
||||
notify_initial_state_done(skb, seq);
|
||||
err = notify_initial_state_done(skb, seq);
|
||||
goto out;
|
||||
}
|
||||
n = cb->args[4]++;
|
||||
if (cb->args[4] < cb->args[3])
|
||||
flags |= NOTIFY_CONTINUES;
|
||||
if (n < 1) {
|
||||
notify_resource_state_change(skb, seq, state_change->resource,
|
||||
err = notify_resource_state_change(skb, seq, state_change->resource,
|
||||
NOTIFY_EXISTS | flags);
|
||||
goto next;
|
||||
}
|
||||
n--;
|
||||
if (n < state_change->n_connections) {
|
||||
notify_connection_state_change(skb, seq, &state_change->connections[n],
|
||||
err = notify_connection_state_change(skb, seq, &state_change->connections[n],
|
||||
NOTIFY_EXISTS | flags);
|
||||
goto next;
|
||||
}
|
||||
n -= state_change->n_connections;
|
||||
if (n < state_change->n_devices) {
|
||||
notify_device_state_change(skb, seq, &state_change->devices[n],
|
||||
err = notify_device_state_change(skb, seq, &state_change->devices[n],
|
||||
NOTIFY_EXISTS | flags);
|
||||
goto next;
|
||||
}
|
||||
n -= state_change->n_devices;
|
||||
if (n < state_change->n_devices * state_change->n_connections) {
|
||||
notify_peer_device_state_change(skb, seq, &state_change->peer_devices[n],
|
||||
err = notify_peer_device_state_change(skb, seq, &state_change->peer_devices[n],
|
||||
NOTIFY_EXISTS | flags);
|
||||
goto next;
|
||||
}
|
||||
@ -4889,7 +4895,10 @@ static int get_initial_state(struct sk_buff *skb, struct netlink_callback *cb)
|
||||
cb->args[4] = 0;
|
||||
}
|
||||
out:
|
||||
return skb->len;
|
||||
if (err)
|
||||
return err;
|
||||
else
|
||||
return skb->len;
|
||||
}
|
||||
|
||||
int drbd_adm_get_initial_state(struct sk_buff *skb, struct netlink_callback *cb)
|
||||
|
@ -1537,7 +1537,7 @@ int drbd_bitmap_io_from_worker(struct drbd_device *device,
|
||||
return rv;
|
||||
}
|
||||
|
||||
void notify_resource_state_change(struct sk_buff *skb,
|
||||
int notify_resource_state_change(struct sk_buff *skb,
|
||||
unsigned int seq,
|
||||
struct drbd_resource_state_change *resource_state_change,
|
||||
enum drbd_notification_type type)
|
||||
@ -1550,10 +1550,10 @@ void notify_resource_state_change(struct sk_buff *skb,
|
||||
.res_susp_fen = resource_state_change->susp_fen[NEW],
|
||||
};
|
||||
|
||||
notify_resource_state(skb, seq, resource, &resource_info, type);
|
||||
return notify_resource_state(skb, seq, resource, &resource_info, type);
|
||||
}
|
||||
|
||||
void notify_connection_state_change(struct sk_buff *skb,
|
||||
int notify_connection_state_change(struct sk_buff *skb,
|
||||
unsigned int seq,
|
||||
struct drbd_connection_state_change *connection_state_change,
|
||||
enum drbd_notification_type type)
|
||||
@ -1564,10 +1564,10 @@ void notify_connection_state_change(struct sk_buff *skb,
|
||||
.conn_role = connection_state_change->peer_role[NEW],
|
||||
};
|
||||
|
||||
notify_connection_state(skb, seq, connection, &connection_info, type);
|
||||
return notify_connection_state(skb, seq, connection, &connection_info, type);
|
||||
}
|
||||
|
||||
void notify_device_state_change(struct sk_buff *skb,
|
||||
int notify_device_state_change(struct sk_buff *skb,
|
||||
unsigned int seq,
|
||||
struct drbd_device_state_change *device_state_change,
|
||||
enum drbd_notification_type type)
|
||||
@ -1577,10 +1577,10 @@ void notify_device_state_change(struct sk_buff *skb,
|
||||
.dev_disk_state = device_state_change->disk_state[NEW],
|
||||
};
|
||||
|
||||
notify_device_state(skb, seq, device, &device_info, type);
|
||||
return notify_device_state(skb, seq, device, &device_info, type);
|
||||
}
|
||||
|
||||
void notify_peer_device_state_change(struct sk_buff *skb,
|
||||
int notify_peer_device_state_change(struct sk_buff *skb,
|
||||
unsigned int seq,
|
||||
struct drbd_peer_device_state_change *p,
|
||||
enum drbd_notification_type type)
|
||||
@ -1594,7 +1594,7 @@ void notify_peer_device_state_change(struct sk_buff *skb,
|
||||
.peer_resync_susp_dependency = p->resync_susp_dependency[NEW],
|
||||
};
|
||||
|
||||
notify_peer_device_state(skb, seq, peer_device, &peer_device_info, type);
|
||||
return notify_peer_device_state(skb, seq, peer_device, &peer_device_info, type);
|
||||
}
|
||||
|
||||
static void broadcast_state_change(struct drbd_state_change *state_change)
|
||||
@ -1602,7 +1602,7 @@ static void broadcast_state_change(struct drbd_state_change *state_change)
|
||||
struct drbd_resource_state_change *resource_state_change = &state_change->resource[0];
|
||||
bool resource_state_has_changed;
|
||||
unsigned int n_device, n_connection, n_peer_device, n_peer_devices;
|
||||
void (*last_func)(struct sk_buff *, unsigned int, void *,
|
||||
int (*last_func)(struct sk_buff *, unsigned int, void *,
|
||||
enum drbd_notification_type) = NULL;
|
||||
void *last_arg = NULL;
|
||||
|
||||
|
@ -44,19 +44,19 @@ extern struct drbd_state_change *remember_old_state(struct drbd_resource *, gfp_
|
||||
extern void copy_old_to_new_state_change(struct drbd_state_change *);
|
||||
extern void forget_state_change(struct drbd_state_change *);
|
||||
|
||||
extern void notify_resource_state_change(struct sk_buff *,
|
||||
extern int notify_resource_state_change(struct sk_buff *,
|
||||
unsigned int,
|
||||
struct drbd_resource_state_change *,
|
||||
enum drbd_notification_type type);
|
||||
extern void notify_connection_state_change(struct sk_buff *,
|
||||
extern int notify_connection_state_change(struct sk_buff *,
|
||||
unsigned int,
|
||||
struct drbd_connection_state_change *,
|
||||
enum drbd_notification_type type);
|
||||
extern void notify_device_state_change(struct sk_buff *,
|
||||
extern int notify_device_state_change(struct sk_buff *,
|
||||
unsigned int,
|
||||
struct drbd_device_state_change *,
|
||||
enum drbd_notification_type type);
|
||||
extern void notify_peer_device_state_change(struct sk_buff *,
|
||||
extern int notify_peer_device_state_change(struct sk_buff *,
|
||||
unsigned int,
|
||||
struct drbd_peer_device_state_change *,
|
||||
enum drbd_notification_type type);
|
||||
|
@ -1365,7 +1365,6 @@ static int cdrom_slot_status(struct cdrom_device_info *cdi, int slot)
|
||||
*/
|
||||
int cdrom_number_of_slots(struct cdrom_device_info *cdi)
|
||||
{
|
||||
int status;
|
||||
int nslots = 1;
|
||||
struct cdrom_changer_info *info;
|
||||
|
||||
@ -1377,7 +1376,7 @@ int cdrom_number_of_slots(struct cdrom_device_info *cdi)
|
||||
if (!info)
|
||||
return -ENOMEM;
|
||||
|
||||
if ((status = cdrom_read_mech_status(cdi, info)) == 0)
|
||||
if (cdrom_read_mech_status(cdi, info) == 0)
|
||||
nslots = info->hdr.nslots;
|
||||
|
||||
kfree(info);
|
||||
|
@ -436,7 +436,6 @@ static int wait_for_media_ready(struct cxl_dev_state *cxlds)
|
||||
|
||||
for (i = mbox_ready_timeout; i; i--) {
|
||||
u32 temp;
|
||||
int rc;
|
||||
|
||||
rc = pci_read_config_dword(
|
||||
pdev, d + CXL_DVSEC_RANGE_SIZE_LOW(0), &temp);
|
||||
|
@ -12,6 +12,7 @@ dmabuf_selftests-y := \
|
||||
selftest.o \
|
||||
st-dma-fence.o \
|
||||
st-dma-fence-chain.o \
|
||||
st-dma-fence-unwrap.o \
|
||||
st-dma-resv.o
|
||||
|
||||
obj-$(CONFIG_DMABUF_SELFTESTS) += dmabuf_selftests.o
|
||||
|
@ -159,6 +159,8 @@ struct dma_fence_array *dma_fence_array_create(int num_fences,
|
||||
struct dma_fence_array *array;
|
||||
size_t size = sizeof(*array);
|
||||
|
||||
WARN_ON(!num_fences || !fences);
|
||||
|
||||
/* Allocate the callback structures behind the array. */
|
||||
size += num_fences * sizeof(struct dma_fence_array_cb);
|
||||
array = kzalloc(size, GFP_KERNEL);
|
||||
@ -219,3 +221,33 @@ bool dma_fence_match_context(struct dma_fence *fence, u64 context)
|
||||
return true;
|
||||
}
|
||||
EXPORT_SYMBOL(dma_fence_match_context);
|
||||
|
||||
struct dma_fence *dma_fence_array_first(struct dma_fence *head)
|
||||
{
|
||||
struct dma_fence_array *array;
|
||||
|
||||
if (!head)
|
||||
return NULL;
|
||||
|
||||
array = to_dma_fence_array(head);
|
||||
if (!array)
|
||||
return head;
|
||||
|
||||
if (!array->num_fences)
|
||||
return NULL;
|
||||
|
||||
return array->fences[0];
|
||||
}
|
||||
EXPORT_SYMBOL(dma_fence_array_first);
|
||||
|
||||
struct dma_fence *dma_fence_array_next(struct dma_fence *head,
|
||||
unsigned int index)
|
||||
{
|
||||
struct dma_fence_array *array = to_dma_fence_array(head);
|
||||
|
||||
if (!array || index >= array->num_fences)
|
||||
return NULL;
|
||||
|
||||
return array->fences[index];
|
||||
}
|
||||
EXPORT_SYMBOL(dma_fence_array_next);
|
||||
|
@ -12,4 +12,5 @@
|
||||
selftest(sanitycheck, __sanitycheck__) /* keep first (igt selfcheck) */
|
||||
selftest(dma_fence, dma_fence)
|
||||
selftest(dma_fence_chain, dma_fence_chain)
|
||||
selftest(dma_fence_unwrap, dma_fence_unwrap)
|
||||
selftest(dma_resv, dma_resv)
|
||||
|
261
drivers/dma-buf/st-dma-fence-unwrap.c
Normal file
261
drivers/dma-buf/st-dma-fence-unwrap.c
Normal file
@ -0,0 +1,261 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
/*
|
||||
* Copyright (C) 2022 Advanced Micro Devices, Inc.
|
||||
*/
|
||||
|
||||
#include <linux/dma-fence-unwrap.h>
|
||||
#if 0
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/sched/signal.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/random.h>
|
||||
#endif
|
||||
|
||||
#include "selftest.h"
|
||||
|
||||
#define CHAIN_SZ (4 << 10)
|
||||
|
||||
static inline struct mock_fence {
|
||||
struct dma_fence base;
|
||||
spinlock_t lock;
|
||||
} *to_mock_fence(struct dma_fence *f) {
|
||||
return container_of(f, struct mock_fence, base);
|
||||
}
|
||||
|
||||
static const char *mock_name(struct dma_fence *f)
|
||||
{
|
||||
return "mock";
|
||||
}
|
||||
|
||||
static const struct dma_fence_ops mock_ops = {
|
||||
.get_driver_name = mock_name,
|
||||
.get_timeline_name = mock_name,
|
||||
};
|
||||
|
||||
static struct dma_fence *mock_fence(void)
|
||||
{
|
||||
struct mock_fence *f;
|
||||
|
||||
f = kmalloc(sizeof(*f), GFP_KERNEL);
|
||||
if (!f)
|
||||
return NULL;
|
||||
|
||||
spin_lock_init(&f->lock);
|
||||
dma_fence_init(&f->base, &mock_ops, &f->lock, 0, 0);
|
||||
|
||||
return &f->base;
|
||||
}
|
||||
|
||||
static struct dma_fence *mock_array(unsigned int num_fences, ...)
|
||||
{
|
||||
struct dma_fence_array *array;
|
||||
struct dma_fence **fences;
|
||||
va_list valist;
|
||||
int i;
|
||||
|
||||
fences = kcalloc(num_fences, sizeof(*fences), GFP_KERNEL);
|
||||
if (!fences)
|
||||
return NULL;
|
||||
|
||||
va_start(valist, num_fences);
|
||||
for (i = 0; i < num_fences; ++i)
|
||||
fences[i] = va_arg(valist, typeof(*fences));
|
||||
va_end(valist);
|
||||
|
||||
array = dma_fence_array_create(num_fences, fences,
|
||||
dma_fence_context_alloc(1),
|
||||
1, false);
|
||||
if (!array)
|
||||
goto cleanup;
|
||||
return &array->base;
|
||||
|
||||
cleanup:
|
||||
for (i = 0; i < num_fences; ++i)
|
||||
dma_fence_put(fences[i]);
|
||||
kfree(fences);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct dma_fence *mock_chain(struct dma_fence *prev,
|
||||
struct dma_fence *fence)
|
||||
{
|
||||
struct dma_fence_chain *f;
|
||||
|
||||
f = dma_fence_chain_alloc();
|
||||
if (!f) {
|
||||
dma_fence_put(prev);
|
||||
dma_fence_put(fence);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dma_fence_chain_init(f, prev, fence, 1);
|
||||
return &f->base;
|
||||
}
|
||||
|
||||
static int sanitycheck(void *arg)
|
||||
{
|
||||
struct dma_fence *f, *chain, *array;
|
||||
int err = 0;
|
||||
|
||||
f = mock_fence();
|
||||
if (!f)
|
||||
return -ENOMEM;
|
||||
|
||||
array = mock_array(1, f);
|
||||
if (!array)
|
||||
return -ENOMEM;
|
||||
|
||||
chain = mock_chain(NULL, array);
|
||||
if (!chain)
|
||||
return -ENOMEM;
|
||||
|
||||
dma_fence_signal(f);
|
||||
dma_fence_put(chain);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int unwrap_array(void *arg)
|
||||
{
|
||||
struct dma_fence *fence, *f1, *f2, *array;
|
||||
struct dma_fence_unwrap iter;
|
||||
int err = 0;
|
||||
|
||||
f1 = mock_fence();
|
||||
if (!f1)
|
||||
return -ENOMEM;
|
||||
|
||||
f2 = mock_fence();
|
||||
if (!f2) {
|
||||
dma_fence_put(f1);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
array = mock_array(2, f1, f2);
|
||||
if (!array)
|
||||
return -ENOMEM;
|
||||
|
||||
dma_fence_unwrap_for_each(fence, &iter, array) {
|
||||
if (fence == f1) {
|
||||
f1 = NULL;
|
||||
} else if (fence == f2) {
|
||||
f2 = NULL;
|
||||
} else {
|
||||
pr_err("Unexpected fence!\n");
|
||||
err = -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
if (f1 || f2) {
|
||||
pr_err("Not all fences seen!\n");
|
||||
err = -EINVAL;
|
||||
}
|
||||
|
||||
dma_fence_signal(f1);
|
||||
dma_fence_signal(f2);
|
||||
dma_fence_put(array);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int unwrap_chain(void *arg)
|
||||
{
|
||||
struct dma_fence *fence, *f1, *f2, *chain;
|
||||
struct dma_fence_unwrap iter;
|
||||
int err = 0;
|
||||
|
||||
f1 = mock_fence();
|
||||
if (!f1)
|
||||
return -ENOMEM;
|
||||
|
||||
f2 = mock_fence();
|
||||
if (!f2) {
|
||||
dma_fence_put(f1);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
chain = mock_chain(f1, f2);
|
||||
if (!chain)
|
||||
return -ENOMEM;
|
||||
|
||||
dma_fence_unwrap_for_each(fence, &iter, chain) {
|
||||
if (fence == f1) {
|
||||
f1 = NULL;
|
||||
} else if (fence == f2) {
|
||||
f2 = NULL;
|
||||
} else {
|
||||
pr_err("Unexpected fence!\n");
|
||||
err = -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
if (f1 || f2) {
|
||||
pr_err("Not all fences seen!\n");
|
||||
err = -EINVAL;
|
||||
}
|
||||
|
||||
dma_fence_signal(f1);
|
||||
dma_fence_signal(f2);
|
||||
dma_fence_put(chain);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int unwrap_chain_array(void *arg)
|
||||
{
|
||||
struct dma_fence *fence, *f1, *f2, *array, *chain;
|
||||
struct dma_fence_unwrap iter;
|
||||
int err = 0;
|
||||
|
||||
f1 = mock_fence();
|
||||
if (!f1)
|
||||
return -ENOMEM;
|
||||
|
||||
f2 = mock_fence();
|
||||
if (!f2) {
|
||||
dma_fence_put(f1);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
array = mock_array(2, f1, f2);
|
||||
if (!array)
|
||||
return -ENOMEM;
|
||||
|
||||
chain = mock_chain(NULL, array);
|
||||
if (!chain)
|
||||
return -ENOMEM;
|
||||
|
||||
dma_fence_unwrap_for_each(fence, &iter, chain) {
|
||||
if (fence == f1) {
|
||||
f1 = NULL;
|
||||
} else if (fence == f2) {
|
||||
f2 = NULL;
|
||||
} else {
|
||||
pr_err("Unexpected fence!\n");
|
||||
err = -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
if (f1 || f2) {
|
||||
pr_err("Not all fences seen!\n");
|
||||
err = -EINVAL;
|
||||
}
|
||||
|
||||
dma_fence_signal(f1);
|
||||
dma_fence_signal(f2);
|
||||
dma_fence_put(chain);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dma_fence_unwrap(void)
|
||||
{
|
||||
static const struct subtest tests[] = {
|
||||
SUBTEST(sanitycheck),
|
||||
SUBTEST(unwrap_array),
|
||||
SUBTEST(unwrap_chain),
|
||||
SUBTEST(unwrap_chain_array),
|
||||
};
|
||||
|
||||
return subtests(tests, NULL);
|
||||
}
|
@ -5,6 +5,7 @@
|
||||
* Copyright (C) 2012 Google, Inc.
|
||||
*/
|
||||
|
||||
#include <linux/dma-fence-unwrap.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/file.h>
|
||||
#include <linux/fs.h>
|
||||
@ -172,20 +173,6 @@ static int sync_file_set_fence(struct sync_file *sync_file,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct dma_fence **get_fences(struct sync_file *sync_file,
|
||||
int *num_fences)
|
||||
{
|
||||
if (dma_fence_is_array(sync_file->fence)) {
|
||||
struct dma_fence_array *array = to_dma_fence_array(sync_file->fence);
|
||||
|
||||
*num_fences = array->num_fences;
|
||||
return array->fences;
|
||||
}
|
||||
|
||||
*num_fences = 1;
|
||||
return &sync_file->fence;
|
||||
}
|
||||
|
||||
static void add_fence(struct dma_fence **fences,
|
||||
int *i, struct dma_fence *fence)
|
||||
{
|
||||
@ -210,86 +197,97 @@ static void add_fence(struct dma_fence **fences,
|
||||
static struct sync_file *sync_file_merge(const char *name, struct sync_file *a,
|
||||
struct sync_file *b)
|
||||
{
|
||||
struct dma_fence *a_fence, *b_fence, **fences;
|
||||
struct dma_fence_unwrap a_iter, b_iter;
|
||||
unsigned int index, num_fences;
|
||||
struct sync_file *sync_file;
|
||||
struct dma_fence **fences = NULL, **nfences, **a_fences, **b_fences;
|
||||
int i = 0, i_a, i_b, num_fences, a_num_fences, b_num_fences;
|
||||
|
||||
sync_file = sync_file_alloc();
|
||||
if (!sync_file)
|
||||
return NULL;
|
||||
|
||||
a_fences = get_fences(a, &a_num_fences);
|
||||
b_fences = get_fences(b, &b_num_fences);
|
||||
if (a_num_fences > INT_MAX - b_num_fences)
|
||||
goto err;
|
||||
num_fences = 0;
|
||||
dma_fence_unwrap_for_each(a_fence, &a_iter, a->fence)
|
||||
++num_fences;
|
||||
dma_fence_unwrap_for_each(b_fence, &b_iter, b->fence)
|
||||
++num_fences;
|
||||
|
||||
num_fences = a_num_fences + b_num_fences;
|
||||
if (num_fences > INT_MAX)
|
||||
goto err_free_sync_file;
|
||||
|
||||
fences = kcalloc(num_fences, sizeof(*fences), GFP_KERNEL);
|
||||
if (!fences)
|
||||
goto err;
|
||||
goto err_free_sync_file;
|
||||
|
||||
/*
|
||||
* Assume sync_file a and b are both ordered and have no
|
||||
* duplicates with the same context.
|
||||
* We can't guarantee that fences in both a and b are ordered, but it is
|
||||
* still quite likely.
|
||||
*
|
||||
* If a sync_file can only be created with sync_file_merge
|
||||
* and sync_file_create, this is a reasonable assumption.
|
||||
* So attempt to order the fences as we pass over them and merge fences
|
||||
* with the same context.
|
||||
*/
|
||||
for (i_a = i_b = 0; i_a < a_num_fences && i_b < b_num_fences; ) {
|
||||
struct dma_fence *pt_a = a_fences[i_a];
|
||||
struct dma_fence *pt_b = b_fences[i_b];
|
||||
|
||||
if (pt_a->context < pt_b->context) {
|
||||
add_fence(fences, &i, pt_a);
|
||||
index = 0;
|
||||
for (a_fence = dma_fence_unwrap_first(a->fence, &a_iter),
|
||||
b_fence = dma_fence_unwrap_first(b->fence, &b_iter);
|
||||
a_fence || b_fence; ) {
|
||||
|
||||
i_a++;
|
||||
} else if (pt_a->context > pt_b->context) {
|
||||
add_fence(fences, &i, pt_b);
|
||||
if (!b_fence) {
|
||||
add_fence(fences, &index, a_fence);
|
||||
a_fence = dma_fence_unwrap_next(&a_iter);
|
||||
|
||||
} else if (!a_fence) {
|
||||
add_fence(fences, &index, b_fence);
|
||||
b_fence = dma_fence_unwrap_next(&b_iter);
|
||||
|
||||
} else if (a_fence->context < b_fence->context) {
|
||||
add_fence(fences, &index, a_fence);
|
||||
a_fence = dma_fence_unwrap_next(&a_iter);
|
||||
|
||||
} else if (b_fence->context < a_fence->context) {
|
||||
add_fence(fences, &index, b_fence);
|
||||
b_fence = dma_fence_unwrap_next(&b_iter);
|
||||
|
||||
} else if (__dma_fence_is_later(a_fence->seqno, b_fence->seqno,
|
||||
a_fence->ops)) {
|
||||
add_fence(fences, &index, a_fence);
|
||||
a_fence = dma_fence_unwrap_next(&a_iter);
|
||||
b_fence = dma_fence_unwrap_next(&b_iter);
|
||||
|
||||
i_b++;
|
||||
} else {
|
||||
if (__dma_fence_is_later(pt_a->seqno, pt_b->seqno,
|
||||
pt_a->ops))
|
||||
add_fence(fences, &i, pt_a);
|
||||
else
|
||||
add_fence(fences, &i, pt_b);
|
||||
|
||||
i_a++;
|
||||
i_b++;
|
||||
add_fence(fences, &index, b_fence);
|
||||
a_fence = dma_fence_unwrap_next(&a_iter);
|
||||
b_fence = dma_fence_unwrap_next(&b_iter);
|
||||
}
|
||||
}
|
||||
|
||||
for (; i_a < a_num_fences; i_a++)
|
||||
add_fence(fences, &i, a_fences[i_a]);
|
||||
if (index == 0)
|
||||
fences[index++] = dma_fence_get_stub();
|
||||
|
||||
for (; i_b < b_num_fences; i_b++)
|
||||
add_fence(fences, &i, b_fences[i_b]);
|
||||
if (num_fences > index) {
|
||||
struct dma_fence **tmp;
|
||||
|
||||
if (i == 0)
|
||||
fences[i++] = dma_fence_get(a_fences[0]);
|
||||
|
||||
if (num_fences > i) {
|
||||
nfences = krealloc_array(fences, i, sizeof(*fences), GFP_KERNEL);
|
||||
if (!nfences)
|
||||
goto err;
|
||||
|
||||
fences = nfences;
|
||||
/* Keep going even when reducing the size failed */
|
||||
tmp = krealloc_array(fences, index, sizeof(*fences),
|
||||
GFP_KERNEL);
|
||||
if (tmp)
|
||||
fences = tmp;
|
||||
}
|
||||
|
||||
if (sync_file_set_fence(sync_file, fences, i) < 0)
|
||||
goto err;
|
||||
if (sync_file_set_fence(sync_file, fences, index) < 0)
|
||||
goto err_put_fences;
|
||||
|
||||
strlcpy(sync_file->user_name, name, sizeof(sync_file->user_name));
|
||||
return sync_file;
|
||||
|
||||
err:
|
||||
while (i)
|
||||
dma_fence_put(fences[--i]);
|
||||
err_put_fences:
|
||||
while (index)
|
||||
dma_fence_put(fences[--index]);
|
||||
kfree(fences);
|
||||
|
||||
err_free_sync_file:
|
||||
fput(sync_file->file);
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
static int sync_file_release(struct inode *inode, struct file *file)
|
||||
@ -398,11 +396,13 @@ static int sync_fill_fence_info(struct dma_fence *fence,
|
||||
static long sync_file_ioctl_fence_info(struct sync_file *sync_file,
|
||||
unsigned long arg)
|
||||
{
|
||||
struct sync_file_info info;
|
||||
struct sync_fence_info *fence_info = NULL;
|
||||
struct dma_fence **fences;
|
||||
struct dma_fence_unwrap iter;
|
||||
struct sync_file_info info;
|
||||
unsigned int num_fences;
|
||||
struct dma_fence *fence;
|
||||
int ret;
|
||||
__u32 size;
|
||||
int num_fences, ret, i;
|
||||
|
||||
if (copy_from_user(&info, (void __user *)arg, sizeof(info)))
|
||||
return -EFAULT;
|
||||
@ -410,7 +410,9 @@ static long sync_file_ioctl_fence_info(struct sync_file *sync_file,
|
||||
if (info.flags || info.pad)
|
||||
return -EINVAL;
|
||||
|
||||
fences = get_fences(sync_file, &num_fences);
|
||||
num_fences = 0;
|
||||
dma_fence_unwrap_for_each(fence, &iter, sync_file->fence)
|
||||
++num_fences;
|
||||
|
||||
/*
|
||||
* Passing num_fences = 0 means that userspace doesn't want to
|
||||
@ -433,8 +435,11 @@ static long sync_file_ioctl_fence_info(struct sync_file *sync_file,
|
||||
if (!fence_info)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < num_fences; i++) {
|
||||
int status = sync_fill_fence_info(fences[i], &fence_info[i]);
|
||||
num_fences = 0;
|
||||
dma_fence_unwrap_for_each(fence, &iter, sync_file->fence) {
|
||||
int status;
|
||||
|
||||
status = sync_fill_fence_info(fence, &fence_info[num_fences++]);
|
||||
info.status = info.status <= 0 ? info.status : status;
|
||||
}
|
||||
|
||||
|
@ -1404,6 +1404,16 @@ static int gpiochip_to_irq(struct gpio_chip *gc, unsigned int offset)
|
||||
{
|
||||
struct irq_domain *domain = gc->irq.domain;
|
||||
|
||||
#ifdef CONFIG_GPIOLIB_IRQCHIP
|
||||
/*
|
||||
* Avoid race condition with other code, which tries to lookup
|
||||
* an IRQ before the irqchip has been properly registered,
|
||||
* i.e. while gpiochip is still being brought up.
|
||||
*/
|
||||
if (!gc->irq.initialized)
|
||||
return -EPROBE_DEFER;
|
||||
#endif
|
||||
|
||||
if (!gpiochip_irqchip_irq_valid(gc, offset))
|
||||
return -ENXIO;
|
||||
|
||||
@ -1593,6 +1603,15 @@ static int gpiochip_add_irqchip(struct gpio_chip *gc,
|
||||
|
||||
acpi_gpiochip_request_interrupts(gc);
|
||||
|
||||
/*
|
||||
* Using barrier() here to prevent compiler from reordering
|
||||
* gc->irq.initialized before initialization of above
|
||||
* GPIO chip irq members.
|
||||
*/
|
||||
barrier();
|
||||
|
||||
gc->irq.initialized = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -119,6 +119,7 @@
|
||||
#define CONNECTOR_OBJECT_ID_eDP 0x14
|
||||
#define CONNECTOR_OBJECT_ID_MXM 0x15
|
||||
#define CONNECTOR_OBJECT_ID_LVDS_eDP 0x16
|
||||
#define CONNECTOR_OBJECT_ID_USBC 0x17
|
||||
|
||||
/* deleted */
|
||||
|
||||
|
@ -5733,7 +5733,7 @@ void amdgpu_device_flush_hdp(struct amdgpu_device *adev,
|
||||
struct amdgpu_ring *ring)
|
||||
{
|
||||
#ifdef CONFIG_X86_64
|
||||
if (adev->flags & AMD_IS_APU)
|
||||
if ((adev->flags & AMD_IS_APU) && !amdgpu_passthrough(adev))
|
||||
return;
|
||||
#endif
|
||||
if (adev->gmc.xgmi.connected_to_cpu)
|
||||
@ -5749,7 +5749,7 @@ void amdgpu_device_invalidate_hdp(struct amdgpu_device *adev,
|
||||
struct amdgpu_ring *ring)
|
||||
{
|
||||
#ifdef CONFIG_X86_64
|
||||
if (adev->flags & AMD_IS_APU)
|
||||
if ((adev->flags & AMD_IS_APU) && !amdgpu_passthrough(adev))
|
||||
return;
|
||||
#endif
|
||||
if (adev->gmc.xgmi.connected_to_cpu)
|
||||
|
@ -680,7 +680,7 @@ MODULE_PARM_DESC(sched_policy,
|
||||
* Maximum number of processes that HWS can schedule concurrently. The maximum is the
|
||||
* number of VMIDs assigned to the HWS, which is also the default.
|
||||
*/
|
||||
int hws_max_conc_proc = 8;
|
||||
int hws_max_conc_proc = -1;
|
||||
module_param(hws_max_conc_proc, int, 0444);
|
||||
MODULE_PARM_DESC(hws_max_conc_proc,
|
||||
"Max # processes HWS can execute concurrently when sched_policy=0 (0 = no concurrency, #VMIDs for KFD = Maximum(default))");
|
||||
|
@ -266,7 +266,7 @@ static int amdgpu_gfx_kiq_acquire(struct amdgpu_device *adev,
|
||||
* adev->gfx.mec.num_pipe_per_mec
|
||||
* adev->gfx.mec.num_queue_per_pipe;
|
||||
|
||||
while (queue_bit-- >= 0) {
|
||||
while (--queue_bit >= 0) {
|
||||
if (test_bit(queue_bit, adev->gfx.mec.queue_bitmap))
|
||||
continue;
|
||||
|
||||
|
@ -561,9 +561,15 @@ void amdgpu_gmc_noretry_set(struct amdgpu_device *adev)
|
||||
|
||||
switch (adev->ip_versions[GC_HWIP][0]) {
|
||||
case IP_VERSION(9, 0, 1):
|
||||
case IP_VERSION(9, 3, 0):
|
||||
case IP_VERSION(9, 4, 0):
|
||||
case IP_VERSION(9, 4, 1):
|
||||
case IP_VERSION(9, 4, 2):
|
||||
case IP_VERSION(10, 3, 3):
|
||||
case IP_VERSION(10, 3, 4):
|
||||
case IP_VERSION(10, 3, 5):
|
||||
case IP_VERSION(10, 3, 6):
|
||||
case IP_VERSION(10, 3, 7):
|
||||
/*
|
||||
* noretry = 0 will cause kfd page fault tests fail
|
||||
* for some ASICs, so set default to 1 for these ASICs.
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user