Merge 'v5.18-rc1' into android-mainline
Linux 5.18-rc1 Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> Change-Id: I0de9c79540971fc875f91ff225565f2799e7355e
This commit is contained in:
@@ -278,20 +278,20 @@ appropriate parameters. In general this allows more efficient DMA
|
||||
on systems where System RAM exists above 4G _physical_ address.
|
||||
|
||||
Drivers for all PCI-X and PCIe compliant devices must call
|
||||
pci_set_dma_mask() as they are 64-bit DMA devices.
|
||||
set_dma_mask() as they are 64-bit DMA devices.
|
||||
|
||||
Similarly, drivers must also "register" this capability if the device
|
||||
can directly address "consistent memory" in System RAM above 4G physical
|
||||
address by calling pci_set_consistent_dma_mask().
|
||||
can directly address "coherent memory" in System RAM above 4G physical
|
||||
address by calling dma_set_coherent_mask().
|
||||
Again, this includes drivers for all PCI-X and PCIe compliant devices.
|
||||
Many 64-bit "PCI" devices (before PCI-X) and some PCI-X devices are
|
||||
64-bit DMA capable for payload ("streaming") data but not control
|
||||
("consistent") data.
|
||||
("coherent") data.
|
||||
|
||||
|
||||
Setup shared control data
|
||||
-------------------------
|
||||
Once the DMA masks are set, the driver can allocate "consistent" (a.k.a. shared)
|
||||
Once the DMA masks are set, the driver can allocate "coherent" (a.k.a. shared)
|
||||
memory. See Documentation/core-api/dma-api.rst for a full description of
|
||||
the DMA APIs. This section is just a reminder that it needs to be done
|
||||
before enabling DMA on the device.
|
||||
@@ -367,7 +367,7 @@ steps need to be performed:
|
||||
- Disable the device from generating IRQs
|
||||
- Release the IRQ (free_irq())
|
||||
- Stop all DMA activity
|
||||
- Release DMA buffers (both streaming and consistent)
|
||||
- Release DMA buffers (both streaming and coherent)
|
||||
- Unregister from other subsystems (e.g. scsi or netdev)
|
||||
- Disable device from responding to MMIO/IO Port addresses
|
||||
- Release MMIO/IO Port resource(s)
|
||||
@@ -420,7 +420,7 @@ Once DMA is stopped, clean up streaming DMA first.
|
||||
I.e. unmap data buffers and return buffers to "upstream"
|
||||
owners if there is one.
|
||||
|
||||
Then clean up "consistent" buffers which contain the control data.
|
||||
Then clean up "coherent" buffers which contain the control data.
|
||||
|
||||
See Documentation/core-api/dma-api.rst for details on unmapping interfaces.
|
||||
|
||||
|
||||
@@ -719,8 +719,8 @@ examples:
|
||||
reg = <0x0>;
|
||||
riscv,isa = "rv64imafdc";
|
||||
mmu-type = "riscv,sv48";
|
||||
cpu-idle-states = <&CPU_RET_0_0 &CPU_NONRET_0_0
|
||||
&CLUSTER_RET_0 &CLUSTER_NONRET_0>;
|
||||
cpu-idle-states = <&CPU_RET_0_0>, <&CPU_NONRET_0_0>,
|
||||
<&CLUSTER_RET_0>, <&CLUSTER_NONRET_0>;
|
||||
|
||||
cpu_intc0: interrupt-controller {
|
||||
#interrupt-cells = <1>;
|
||||
@@ -735,8 +735,8 @@ examples:
|
||||
reg = <0x1>;
|
||||
riscv,isa = "rv64imafdc";
|
||||
mmu-type = "riscv,sv48";
|
||||
cpu-idle-states = <&CPU_RET_0_0 &CPU_NONRET_0_0
|
||||
&CLUSTER_RET_0 &CLUSTER_NONRET_0>;
|
||||
cpu-idle-states = <&CPU_RET_0_0>, <&CPU_NONRET_0_0>,
|
||||
<&CLUSTER_RET_0>, <&CLUSTER_NONRET_0>;
|
||||
|
||||
cpu_intc1: interrupt-controller {
|
||||
#interrupt-cells = <1>;
|
||||
@@ -751,8 +751,8 @@ examples:
|
||||
reg = <0x10>;
|
||||
riscv,isa = "rv64imafdc";
|
||||
mmu-type = "riscv,sv48";
|
||||
cpu-idle-states = <&CPU_RET_1_0 &CPU_NONRET_1_0
|
||||
&CLUSTER_RET_1 &CLUSTER_NONRET_1>;
|
||||
cpu-idle-states = <&CPU_RET_1_0>, <&CPU_NONRET_1_0>,
|
||||
<&CLUSTER_RET_1>, <&CLUSTER_NONRET_1>;
|
||||
|
||||
cpu_intc10: interrupt-controller {
|
||||
#interrupt-cells = <1>;
|
||||
@@ -767,8 +767,8 @@ examples:
|
||||
reg = <0x11>;
|
||||
riscv,isa = "rv64imafdc";
|
||||
mmu-type = "riscv,sv48";
|
||||
cpu-idle-states = <&CPU_RET_1_0 &CPU_NONRET_1_0
|
||||
&CLUSTER_RET_1 &CLUSTER_NONRET_1>;
|
||||
cpu-idle-states = <&CPU_RET_1_0>, <&CPU_NONRET_1_0>,
|
||||
<&CLUSTER_RET_1>, <&CLUSTER_NONRET_1>;
|
||||
|
||||
cpu_intc11: interrupt-controller {
|
||||
#interrupt-cells = <1>;
|
||||
|
||||
@@ -101,6 +101,8 @@ properties:
|
||||
|
||||
cpu-idle-states:
|
||||
$ref: '/schemas/types.yaml#/definitions/phandle-array'
|
||||
items:
|
||||
maxItems: 1
|
||||
description: |
|
||||
List of phandles to idle state nodes supported
|
||||
by this hart (see ./idle-states.yaml).
|
||||
|
||||
@@ -82,10 +82,10 @@ Signing Update Supported.
|
||||
Pre-authentication integrity Supported.
|
||||
SMB3 encryption(CCM, GCM) Supported. (CCM and GCM128 supported, GCM256 in
|
||||
progress)
|
||||
SMB direct(RDMA) Partially Supported. SMB3 Multi-channel is
|
||||
required to connect to Windows client.
|
||||
SMB direct(RDMA) Supported.
|
||||
SMB3 Multi-channel Partially Supported. Planned to implement
|
||||
replay/retry mechanisms for future.
|
||||
Receive Side Scaling mode Supported.
|
||||
SMB3.1.1 POSIX extension Supported.
|
||||
ACLs Partially Supported. only DACLs available, SACLs
|
||||
(auditing) is planned for the future. For
|
||||
|
||||
@@ -7,7 +7,7 @@ user_events: User-based Event Tracing
|
||||
Overview
|
||||
--------
|
||||
User based trace events allow user processes to create events and trace data
|
||||
that can be viewed via existing tools, such as ftrace, perf and eBPF.
|
||||
that can be viewed via existing tools, such as ftrace and perf.
|
||||
To enable this feature, build your kernel with CONFIG_USER_EVENTS=y.
|
||||
|
||||
Programs can view status of the events via
|
||||
@@ -67,8 +67,7 @@ The command string format is as follows::
|
||||
|
||||
Supported Flags
|
||||
^^^^^^^^^^^^^^^
|
||||
**BPF_ITER** - EBPF programs attached to this event will get the raw iovec
|
||||
struct instead of any data copies for max performance.
|
||||
None yet
|
||||
|
||||
Field Format
|
||||
^^^^^^^^^^^^
|
||||
@@ -160,7 +159,7 @@ The following values are defined to aid in checking what has been attached:
|
||||
|
||||
**EVENT_STATUS_FTRACE** - Bit set if ftrace has been attached (Bit 0).
|
||||
|
||||
**EVENT_STATUS_PERF** - Bit set if perf/eBPF has been attached (Bit 1).
|
||||
**EVENT_STATUS_PERF** - Bit set if perf has been attached (Bit 1).
|
||||
|
||||
Writing Data
|
||||
------------
|
||||
@@ -204,13 +203,6 @@ It's advised for user programs to do the following::
|
||||
|
||||
**NOTE:** *The write_index is not emitted out into the trace being recorded.*
|
||||
|
||||
EBPF
|
||||
----
|
||||
EBPF programs that attach to a user-based event tracepoint are given a pointer
|
||||
to a struct user_bpf_context. The bpf context contains the data type (which can
|
||||
be a user or kernel buffer, or can be a pointer to the iovec) and the data
|
||||
length that was emitted (minus the write_index).
|
||||
|
||||
Example Code
|
||||
------------
|
||||
See sample code in samples/user_events.
|
||||
|
||||
@@ -151,12 +151,6 @@ In order to create user controlled virtual machines on S390, check
|
||||
KVM_CAP_S390_UCONTROL and use the flag KVM_VM_S390_UCONTROL as
|
||||
privileged user (CAP_SYS_ADMIN).
|
||||
|
||||
To use hardware assisted virtualization on MIPS (VZ ASE) rather than
|
||||
the default trap & emulate implementation (which changes the virtual
|
||||
memory layout to fit in user mode), check KVM_CAP_MIPS_VZ and use the
|
||||
flag KVM_VM_MIPS_VZ.
|
||||
|
||||
|
||||
On arm64, the physical address size for a VM (IPA Size limit) is limited
|
||||
to 40bits by default. The limit can be configured if the host supports the
|
||||
extension KVM_CAP_ARM_VM_IPA_SIZE. When supported, use
|
||||
@@ -4081,6 +4075,11 @@ x2APIC MSRs are always allowed, independent of the ``default_allow`` setting,
|
||||
and their behavior depends on the ``X2APIC_ENABLE`` bit of the APIC base
|
||||
register.
|
||||
|
||||
.. warning::
|
||||
MSR accesses coming from nested vmentry/vmexit are not filtered.
|
||||
This includes both writes to individual VMCS fields and reads/writes
|
||||
through the MSR lists pointed to by the VMCS.
|
||||
|
||||
If a bit is within one of the defined ranges, read and write accesses are
|
||||
guarded by the bitmap's value for the MSR index if the kind of access
|
||||
is included in the ``struct kvm_msr_filter_range`` flags. If no range
|
||||
@@ -5293,6 +5292,10 @@ type values:
|
||||
|
||||
KVM_XEN_VCPU_ATTR_TYPE_VCPU_INFO
|
||||
Sets the guest physical address of the vcpu_info for a given vCPU.
|
||||
As with the shared_info page for the VM, the corresponding page may be
|
||||
dirtied at any time if event channel interrupt delivery is enabled, so
|
||||
userspace should always assume that the page is dirty without relying
|
||||
on dirty logging.
|
||||
|
||||
KVM_XEN_VCPU_ATTR_TYPE_VCPU_TIME_INFO
|
||||
Sets the guest physical address of an additional pvclock structure
|
||||
@@ -7719,3 +7722,49 @@ only be invoked on a VM prior to the creation of VCPUs.
|
||||
At this time, KVM_PMU_CAP_DISABLE is the only capability. Setting
|
||||
this capability will disable PMU virtualization for that VM. Usermode
|
||||
should adjust CPUID leaf 0xA to reflect that the PMU is disabled.
|
||||
|
||||
9. Known KVM API problems
|
||||
=========================
|
||||
|
||||
In some cases, KVM's API has some inconsistencies or common pitfalls
|
||||
that userspace need to be aware of. This section details some of
|
||||
these issues.
|
||||
|
||||
Most of them are architecture specific, so the section is split by
|
||||
architecture.
|
||||
|
||||
9.1. x86
|
||||
--------
|
||||
|
||||
``KVM_GET_SUPPORTED_CPUID`` issues
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
In general, ``KVM_GET_SUPPORTED_CPUID`` is designed so that it is possible
|
||||
to take its result and pass it directly to ``KVM_SET_CPUID2``. This section
|
||||
documents some cases in which that requires some care.
|
||||
|
||||
Local APIC features
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
CPU[EAX=1]:ECX[21] (X2APIC) is reported by ``KVM_GET_SUPPORTED_CPUID``,
|
||||
but it can only be enabled if ``KVM_CREATE_IRQCHIP`` or
|
||||
``KVM_ENABLE_CAP(KVM_CAP_IRQCHIP_SPLIT)`` are used to enable in-kernel emulation of
|
||||
the local APIC.
|
||||
|
||||
The same is true for the ``KVM_FEATURE_PV_UNHALT`` paravirtualized feature.
|
||||
|
||||
CPU[EAX=1]:ECX[24] (TSC_DEADLINE) is not reported by ``KVM_GET_SUPPORTED_CPUID``.
|
||||
It can be enabled if ``KVM_CAP_TSC_DEADLINE_TIMER`` is present and the kernel
|
||||
has enabled in-kernel emulation of the local APIC.
|
||||
|
||||
Obsolete ioctls and capabilities
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
KVM_CAP_DISABLE_QUIRKS does not let userspace know which quirks are actually
|
||||
available. Use ``KVM_CHECK_EXTENSION(KVM_CAP_DISABLE_QUIRKS2)`` instead if
|
||||
available.
|
||||
|
||||
Ordering of KVM_GET_*/KVM_SET_* ioctls
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
TBD
|
||||
|
||||
@@ -8,25 +8,13 @@ KVM
|
||||
:maxdepth: 2
|
||||
|
||||
api
|
||||
amd-memory-encryption
|
||||
cpuid
|
||||
halt-polling
|
||||
hypercalls
|
||||
locking
|
||||
mmu
|
||||
msr
|
||||
nested-vmx
|
||||
ppc-pv
|
||||
s390-diag
|
||||
s390-pv
|
||||
s390-pv-boot
|
||||
timekeeping
|
||||
vcpu-requests
|
||||
|
||||
review-checklist
|
||||
|
||||
arm/index
|
||||
|
||||
devices/index
|
||||
|
||||
running-nested-guests
|
||||
arm/index
|
||||
s390/index
|
||||
ppc-pv
|
||||
x86/index
|
||||
|
||||
locking
|
||||
vcpu-requests
|
||||
review-checklist
|
||||
|
||||
@@ -210,32 +210,47 @@ time it will be set using the Dirty tracking mechanism described above.
|
||||
3. Reference
|
||||
------------
|
||||
|
||||
:Name: kvm_lock
|
||||
``kvm_lock``
|
||||
^^^^^^^^^^^^
|
||||
|
||||
:Type: mutex
|
||||
:Arch: any
|
||||
:Protects: - vm_list
|
||||
|
||||
:Name: kvm_count_lock
|
||||
``kvm_count_lock``
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
:Type: raw_spinlock_t
|
||||
:Arch: any
|
||||
:Protects: - hardware virtualization enable/disable
|
||||
:Comment: 'raw' because hardware enabling/disabling must be atomic /wrt
|
||||
migration.
|
||||
|
||||
:Name: kvm_arch::tsc_write_lock
|
||||
:Type: raw_spinlock
|
||||
``kvm->mn_invalidate_lock``
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
:Type: spinlock_t
|
||||
:Arch: any
|
||||
:Protects: mn_active_invalidate_count, mn_memslots_update_rcuwait
|
||||
|
||||
``kvm_arch::tsc_write_lock``
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
:Type: raw_spinlock_t
|
||||
:Arch: x86
|
||||
:Protects: - kvm_arch::{last_tsc_write,last_tsc_nsec,last_tsc_offset}
|
||||
- tsc offset in vmcb
|
||||
:Comment: 'raw' because updating the tsc offsets must not be preempted.
|
||||
|
||||
:Name: kvm->mmu_lock
|
||||
:Type: spinlock_t
|
||||
``kvm->mmu_lock``
|
||||
^^^^^^^^^^^^^^^^^
|
||||
:Type: spinlock_t or rwlock_t
|
||||
:Arch: any
|
||||
:Protects: -shadow page/shadow tlb entry
|
||||
:Comment: it is a spinlock since it is used in mmu notifier.
|
||||
|
||||
:Name: kvm->srcu
|
||||
``kvm->srcu``
|
||||
^^^^^^^^^^^^^
|
||||
:Type: srcu lock
|
||||
:Arch: any
|
||||
:Protects: - kvm->memslots
|
||||
@@ -246,10 +261,20 @@ time it will be set using the Dirty tracking mechanism described above.
|
||||
The srcu index can be stored in kvm_vcpu->srcu_idx per vcpu
|
||||
if it is needed by multiple functions.
|
||||
|
||||
:Name: blocked_vcpu_on_cpu_lock
|
||||
``kvm->slots_arch_lock``
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
:Type: mutex
|
||||
:Arch: any (only needed on x86 though)
|
||||
:Protects: any arch-specific fields of memslots that have to be modified
|
||||
in a ``kvm->srcu`` read-side critical section.
|
||||
:Comment: must be held before reading the pointer to the current memslots,
|
||||
until after all changes to the memslots are complete
|
||||
|
||||
``wakeup_vcpus_on_cpu_lock``
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
:Type: spinlock_t
|
||||
:Arch: x86
|
||||
:Protects: blocked_vcpu_on_cpu
|
||||
:Protects: wakeup_vcpus_on_cpu
|
||||
:Comment: This is a per-CPU lock and it is used for VT-d posted-interrupts.
|
||||
When VT-d posted-interrupts is supported and the VM has assigned
|
||||
devices, we put the blocked vCPU on the list blocked_vcpu_on_cpu
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
====================
|
||||
KVM for s390 systems
|
||||
====================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
s390-diag
|
||||
s390-pv
|
||||
s390-pv-boot
|
||||
@@ -135,6 +135,16 @@ KVM_REQ_UNHALT
|
||||
such as a pending signal, which does not indicate the VCPU's halt
|
||||
emulation should stop, and therefore does not make the request.
|
||||
|
||||
KVM_REQ_OUTSIDE_GUEST_MODE
|
||||
|
||||
This "request" ensures the target vCPU has exited guest mode prior to the
|
||||
sender of the request continuing on. No action needs be taken by the target,
|
||||
and so no request is actually logged for the target. This request is similar
|
||||
to a "kick", but unlike a kick it guarantees the vCPU has actually exited
|
||||
guest mode. A kick only guarantees the vCPU will exit at some point in the
|
||||
future, e.g. a previous kick may have started the process, but there's no
|
||||
guarantee the to-be-kicked vCPU has fully exited guest mode.
|
||||
|
||||
KVM_REQUEST_MASK
|
||||
----------------
|
||||
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
|
||||
=======================================
|
||||
Known limitations of CPU virtualization
|
||||
=======================================
|
||||
|
||||
Whenever perfect emulation of a CPU feature is impossible or too hard, KVM
|
||||
has to choose between not implementing the feature at all or introducing
|
||||
behavioral differences between virtual machines and bare metal systems.
|
||||
|
||||
This file documents some of the known limitations that KVM has in
|
||||
virtualizing CPU features.
|
||||
|
||||
x86
|
||||
===
|
||||
|
||||
``KVM_GET_SUPPORTED_CPUID`` issues
|
||||
----------------------------------
|
||||
|
||||
x87 features
|
||||
~~~~~~~~~~~~
|
||||
|
||||
Unlike most other CPUID feature bits, CPUID[EAX=7,ECX=0]:EBX[6]
|
||||
(FDP_EXCPTN_ONLY) and CPUID[EAX=7,ECX=0]:EBX]13] (ZERO_FCS_FDS) are
|
||||
clear if the features are present and set if the features are not present.
|
||||
|
||||
Clearing these bits in CPUID has no effect on the operation of the guest;
|
||||
if these bits are set on hardware, the features will not be present on
|
||||
any virtual machine that runs on that hardware.
|
||||
|
||||
**Workaround:** It is recommended to always set these bits in guest CPUID.
|
||||
Note however that any software (e.g ``WIN87EM.DLL``) expecting these features
|
||||
to be present likely predates these CPUID feature bits, and therefore
|
||||
doesn't know to check for them anyway.
|
||||
|
||||
Nested virtualization features
|
||||
------------------------------
|
||||
|
||||
TBD
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
===================
|
||||
KVM for x86 systems
|
||||
===================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
amd-memory-encryption
|
||||
cpuid
|
||||
errata
|
||||
halt-polling
|
||||
hypercalls
|
||||
mmu
|
||||
msr
|
||||
nested-vmx
|
||||
running-nested-guests
|
||||
timekeeping
|
||||
+7
-1
@@ -4640,6 +4640,7 @@ F: drivers/input/touchscreen/chipone_icn8505.c
|
||||
|
||||
CHROME HARDWARE PLATFORM SUPPORT
|
||||
M: Benson Leung <bleung@chromium.org>
|
||||
L: chrome-platform@lists.linux.dev
|
||||
S: Maintained
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/chrome-platform/linux.git
|
||||
F: drivers/platform/chrome/
|
||||
@@ -4648,6 +4649,7 @@ CHROMEOS EC CODEC DRIVER
|
||||
M: Cheng-Yi Chiang <cychiang@chromium.org>
|
||||
M: Tzung-Bi Shih <tzungbi@google.com>
|
||||
R: Guenter Roeck <groeck@chromium.org>
|
||||
L: chrome-platform@lists.linux.dev
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/sound/google,cros-ec-codec.yaml
|
||||
F: sound/soc/codecs/cros_ec_codec.*
|
||||
@@ -4655,6 +4657,7 @@ F: sound/soc/codecs/cros_ec_codec.*
|
||||
CHROMEOS EC SUBDRIVERS
|
||||
M: Benson Leung <bleung@chromium.org>
|
||||
R: Guenter Roeck <groeck@chromium.org>
|
||||
L: chrome-platform@lists.linux.dev
|
||||
S: Maintained
|
||||
F: drivers/power/supply/cros_usbpd-charger.c
|
||||
N: cros_ec
|
||||
@@ -4662,11 +4665,13 @@ N: cros-ec
|
||||
|
||||
CHROMEOS EC USB TYPE-C DRIVER
|
||||
M: Prashant Malani <pmalani@chromium.org>
|
||||
L: chrome-platform@lists.linux.dev
|
||||
S: Maintained
|
||||
F: drivers/platform/chrome/cros_ec_typec.c
|
||||
|
||||
CHROMEOS EC USB PD NOTIFY DRIVER
|
||||
M: Prashant Malani <pmalani@chromium.org>
|
||||
L: chrome-platform@lists.linux.dev
|
||||
S: Maintained
|
||||
F: drivers/platform/chrome/cros_usbpd_notify.c
|
||||
F: include/linux/platform_data/cros_usbpd_notify.h
|
||||
@@ -6052,6 +6057,7 @@ F: drivers/scsi/dpt/
|
||||
DRBD DRIVER
|
||||
M: Philipp Reisner <philipp.reisner@linbit.com>
|
||||
M: Lars Ellenberg <lars.ellenberg@linbit.com>
|
||||
M: Christoph Böhmwalder <christoph.boehmwalder@linbit.com>
|
||||
L: drbd-dev@lists.linbit.com
|
||||
S: Supported
|
||||
W: http://www.drbd.org
|
||||
@@ -10675,9 +10681,9 @@ F: tools/testing/selftests/
|
||||
|
||||
KERNEL SMB3 SERVER (KSMBD)
|
||||
M: Namjae Jeon <linkinjeon@kernel.org>
|
||||
M: Sergey Senozhatsky <senozhatsky@chromium.org>
|
||||
M: Steve French <sfrench@samba.org>
|
||||
M: Hyunchul Lee <hyc.lee@gmail.com>
|
||||
R: Sergey Senozhatsky <senozhatsky@chromium.org>
|
||||
L: linux-cifs@vger.kernel.org
|
||||
S: Maintained
|
||||
T: git git://git.samba.org/ksmbd.git
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
VERSION = 5
|
||||
PATCHLEVEL = 17
|
||||
PATCHLEVEL = 18
|
||||
SUBLEVEL = 0
|
||||
EXTRAVERSION =
|
||||
EXTRAVERSION = -rc1
|
||||
NAME = Superb Owl
|
||||
|
||||
# *DOCUMENTATION*
|
||||
@@ -813,10 +813,6 @@ ifdef CONFIG_CC_IS_CLANG
|
||||
KBUILD_CPPFLAGS += -Qunused-arguments
|
||||
# The kernel builds with '-std=gnu11' so use of GNU extensions is acceptable.
|
||||
KBUILD_CFLAGS += -Wno-gnu
|
||||
# CLANG uses a _MergedGlobals as optimization, but this breaks modpost, as the
|
||||
# source of a reference will be _MergedGlobals and not on of the whitelisted names.
|
||||
# See modpost pattern 2
|
||||
KBUILD_CFLAGS += -mno-global-merge
|
||||
else
|
||||
|
||||
# gcc inanely warns about local variables called 'main'
|
||||
|
||||
@@ -45,10 +45,4 @@ struct user {
|
||||
char u_comm[32]; /* user command name */
|
||||
};
|
||||
|
||||
#define NBPG PAGE_SIZE
|
||||
#define UPAGES 1
|
||||
#define HOST_TEXT_START_ADDR (u.start_code)
|
||||
#define HOST_DATA_START_ADDR (u.start_data)
|
||||
#define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * NBPG)
|
||||
|
||||
#endif /* _ALPHA_USER_H */
|
||||
|
||||
@@ -92,6 +92,8 @@ ifeq ($(CONFIG_USE_OF),y)
|
||||
OBJS += $(libfdt_objs) fdt_check_mem_start.o
|
||||
endif
|
||||
|
||||
OBJS += lib1funcs.o ashldi3.o bswapsdi2.o
|
||||
|
||||
targets := vmlinux vmlinux.lds piggy_data piggy.o \
|
||||
head.o $(OBJS)
|
||||
|
||||
@@ -126,8 +128,6 @@ endif
|
||||
# Next argument is a linker script
|
||||
LDFLAGS_vmlinux += -T
|
||||
|
||||
OBJS += lib1funcs.o ashldi3.o bswapsdi2.o
|
||||
|
||||
# We need to prevent any GOTOFF relocs being used with references
|
||||
# to symbols in the .bss section since we cannot relocate them
|
||||
# independently from the rest at run time. This can be achieved by
|
||||
|
||||
@@ -77,10 +77,6 @@ struct user{
|
||||
struct user_fp_struct * u_fp0;/* Used by gdb to help find the values for */
|
||||
/* the FP registers. */
|
||||
};
|
||||
#define NBPG PAGE_SIZE
|
||||
#define UPAGES 1
|
||||
#define HOST_TEXT_START_ADDR (u.start_code)
|
||||
#define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * NBPG)
|
||||
|
||||
/*
|
||||
* User specific VFP registers. If only VFPv2 is present, registers 16 to 31
|
||||
|
||||
@@ -1004,7 +1004,8 @@ static void __init reserve_crashkernel(void)
|
||||
total_mem = get_total_mem();
|
||||
ret = parse_crashkernel(boot_command_line, total_mem,
|
||||
&crash_size, &crash_base);
|
||||
if (ret)
|
||||
/* invalid value specified or crashkernel=0 */
|
||||
if (ret || !crash_size)
|
||||
return;
|
||||
|
||||
if (crash_base <= 0) {
|
||||
|
||||
@@ -54,17 +54,17 @@ int notrace unwind_frame(struct stackframe *frame)
|
||||
return -EINVAL;
|
||||
|
||||
frame->sp = frame->fp;
|
||||
frame->fp = *(unsigned long *)(fp);
|
||||
frame->pc = *(unsigned long *)(fp + 4);
|
||||
frame->fp = READ_ONCE_NOCHECK(*(unsigned long *)(fp));
|
||||
frame->pc = READ_ONCE_NOCHECK(*(unsigned long *)(fp + 4));
|
||||
#else
|
||||
/* check current frame pointer is within bounds */
|
||||
if (fp < low + 12 || fp > high - 4)
|
||||
return -EINVAL;
|
||||
|
||||
/* restore the registers from the stack frame */
|
||||
frame->fp = *(unsigned long *)(fp - 12);
|
||||
frame->sp = *(unsigned long *)(fp - 8);
|
||||
frame->pc = *(unsigned long *)(fp - 4);
|
||||
frame->fp = READ_ONCE_NOCHECK(*(unsigned long *)(fp - 12));
|
||||
frame->sp = READ_ONCE_NOCHECK(*(unsigned long *)(fp - 8));
|
||||
frame->pc = READ_ONCE_NOCHECK(*(unsigned long *)(fp - 4));
|
||||
#endif
|
||||
#ifdef CONFIG_KRETPROBES
|
||||
if (is_kretprobe_trampoline(frame->pc))
|
||||
|
||||
@@ -236,11 +236,11 @@ static int __init jive_mtdset(char *options)
|
||||
unsigned long set;
|
||||
|
||||
if (options == NULL || options[0] == '\0')
|
||||
return 0;
|
||||
return 1;
|
||||
|
||||
if (kstrtoul(options, 10, &set)) {
|
||||
printk(KERN_ERR "failed to parse mtdset=%s\n", options);
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
switch (set) {
|
||||
@@ -256,7 +256,7 @@ static int __init jive_mtdset(char *options)
|
||||
"using default.", set);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* parse the mtdset= option given to the kernel command line */
|
||||
|
||||
@@ -67,9 +67,5 @@ struct user {
|
||||
unsigned long magic; /* To uniquely identify a core file */
|
||||
char u_comm[32]; /* User command that was responsible */
|
||||
};
|
||||
#define NBPG PAGE_SIZE
|
||||
#define UPAGES 1
|
||||
#define HOST_TEXT_START_ADDR (u.start_code)
|
||||
#define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * NBPG)
|
||||
|
||||
#endif
|
||||
|
||||
@@ -50,10 +50,4 @@ struct user {
|
||||
char u_comm[32]; /* user command name */
|
||||
};
|
||||
|
||||
#define NBPG PAGE_SIZE
|
||||
#define UPAGES 1
|
||||
#define HOST_TEXT_START_ADDR (u.start_code)
|
||||
#define HOST_DATA_START_ADDR (u.start_data)
|
||||
#define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * NBPG)
|
||||
|
||||
#endif /* _ASM_IA64_USER_H */
|
||||
|
||||
@@ -79,9 +79,5 @@ struct user{
|
||||
unsigned long magic; /* To uniquely identify a core file */
|
||||
char u_comm[32]; /* User command that was responsible */
|
||||
};
|
||||
#define NBPG 4096
|
||||
#define UPAGES 1
|
||||
#define HOST_TEXT_START_ADDR (u.start_code)
|
||||
#define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * NBPG)
|
||||
|
||||
#endif
|
||||
|
||||
@@ -28,7 +28,7 @@ enum crc_type {
|
||||
};
|
||||
|
||||
#ifndef TOOLCHAIN_SUPPORTS_CRC
|
||||
#define _ASM_MACRO_CRC32(OP, SZ, TYPE) \
|
||||
#define _ASM_SET_CRC(OP, SZ, TYPE) \
|
||||
_ASM_MACRO_3R(OP, rt, rs, rt2, \
|
||||
".ifnc \\rt, \\rt2\n\t" \
|
||||
".error \"invalid operands \\\"" #OP " \\rt,\\rs,\\rt2\\\"\"\n\t" \
|
||||
@@ -37,30 +37,36 @@ _ASM_MACRO_3R(OP, rt, rs, rt2, \
|
||||
((SZ) << 6) | ((TYPE) << 8)) \
|
||||
_ASM_INSN32_IF_MM(0x00000030 | (__rs << 16) | (__rt << 21) | \
|
||||
((SZ) << 14) | ((TYPE) << 3)))
|
||||
_ASM_MACRO_CRC32(crc32b, 0, 0);
|
||||
_ASM_MACRO_CRC32(crc32h, 1, 0);
|
||||
_ASM_MACRO_CRC32(crc32w, 2, 0);
|
||||
_ASM_MACRO_CRC32(crc32d, 3, 0);
|
||||
_ASM_MACRO_CRC32(crc32cb, 0, 1);
|
||||
_ASM_MACRO_CRC32(crc32ch, 1, 1);
|
||||
_ASM_MACRO_CRC32(crc32cw, 2, 1);
|
||||
_ASM_MACRO_CRC32(crc32cd, 3, 1);
|
||||
#define _ASM_SET_CRC ""
|
||||
#define _ASM_UNSET_CRC(op, SZ, TYPE) ".purgem " #op "\n\t"
|
||||
#else /* !TOOLCHAIN_SUPPORTS_CRC */
|
||||
#define _ASM_SET_CRC ".set\tcrc\n\t"
|
||||
#define _ASM_SET_CRC(op, SZ, TYPE) ".set\tcrc\n\t"
|
||||
#define _ASM_UNSET_CRC(op, SZ, TYPE)
|
||||
#endif
|
||||
|
||||
#define _CRC32(crc, value, size, type) \
|
||||
do { \
|
||||
__asm__ __volatile__( \
|
||||
".set push\n\t" \
|
||||
_ASM_SET_CRC \
|
||||
#type #size " %0, %1, %0\n\t" \
|
||||
".set pop" \
|
||||
: "+r" (crc) \
|
||||
: "r" (value)); \
|
||||
#define __CRC32(crc, value, op, SZ, TYPE) \
|
||||
do { \
|
||||
__asm__ __volatile__( \
|
||||
".set push\n\t" \
|
||||
_ASM_SET_CRC(op, SZ, TYPE) \
|
||||
#op " %0, %1, %0\n\t" \
|
||||
_ASM_UNSET_CRC(op, SZ, TYPE) \
|
||||
".set pop" \
|
||||
: "+r" (crc) \
|
||||
: "r" (value)); \
|
||||
} while (0)
|
||||
|
||||
#define _CRC32_crc32b(crc, value) __CRC32(crc, value, crc32b, 0, 0)
|
||||
#define _CRC32_crc32h(crc, value) __CRC32(crc, value, crc32h, 1, 0)
|
||||
#define _CRC32_crc32w(crc, value) __CRC32(crc, value, crc32w, 2, 0)
|
||||
#define _CRC32_crc32d(crc, value) __CRC32(crc, value, crc32d, 3, 0)
|
||||
#define _CRC32_crc32cb(crc, value) __CRC32(crc, value, crc32cb, 0, 1)
|
||||
#define _CRC32_crc32ch(crc, value) __CRC32(crc, value, crc32ch, 1, 1)
|
||||
#define _CRC32_crc32cw(crc, value) __CRC32(crc, value, crc32cw, 2, 1)
|
||||
#define _CRC32_crc32cd(crc, value) __CRC32(crc, value, crc32cd, 3, 1)
|
||||
|
||||
#define _CRC32(crc, value, size, op) \
|
||||
_CRC32_##op##size(crc, value)
|
||||
|
||||
#define CRC32(crc, value, size) \
|
||||
_CRC32(crc, value, size, crc32)
|
||||
|
||||
|
||||
@@ -29,15 +29,6 @@
|
||||
#define DEV3TC 0x01003C
|
||||
#define BTCS 0x010040
|
||||
#define BTCOMPARE 0x010044
|
||||
#define GPIOBASE 0x050000
|
||||
/* Offsets relative to GPIOBASE */
|
||||
#define GPIOFUNC 0x00
|
||||
#define GPIOCFG 0x04
|
||||
#define GPIOD 0x08
|
||||
#define GPIOILEVEL 0x0C
|
||||
#define GPIOISTAT 0x10
|
||||
#define GPIONMIEN 0x14
|
||||
#define IMASK6 0x38
|
||||
#define LO_WPX (1 << 0)
|
||||
#define LO_ALE (1 << 1)
|
||||
#define LO_CLE (1 << 2)
|
||||
|
||||
@@ -167,6 +167,8 @@ static inline void clkdev_add_sys(const char *dev, unsigned int module,
|
||||
{
|
||||
struct clk *clk = kzalloc(sizeof(struct clk), GFP_KERNEL);
|
||||
|
||||
if (!clk)
|
||||
return;
|
||||
clk->cl.dev_id = dev;
|
||||
clk->cl.con_id = NULL;
|
||||
clk->cl.clk = clk;
|
||||
|
||||
@@ -122,6 +122,8 @@ static inline void clkdev_add_gptu(struct device *dev, const char *con,
|
||||
{
|
||||
struct clk *clk = kzalloc(sizeof(struct clk), GFP_KERNEL);
|
||||
|
||||
if (!clk)
|
||||
return;
|
||||
clk->cl.dev_id = dev_name(dev);
|
||||
clk->cl.con_id = con;
|
||||
clk->cl.clk = clk;
|
||||
|
||||
@@ -315,6 +315,8 @@ static void clkdev_add_pmu(const char *dev, const char *con, bool deactivate,
|
||||
{
|
||||
struct clk *clk = kzalloc(sizeof(struct clk), GFP_KERNEL);
|
||||
|
||||
if (!clk)
|
||||
return;
|
||||
clk->cl.dev_id = dev;
|
||||
clk->cl.con_id = con;
|
||||
clk->cl.clk = clk;
|
||||
@@ -338,6 +340,8 @@ static void clkdev_add_cgu(const char *dev, const char *con,
|
||||
{
|
||||
struct clk *clk = kzalloc(sizeof(struct clk), GFP_KERNEL);
|
||||
|
||||
if (!clk)
|
||||
return;
|
||||
clk->cl.dev_id = dev;
|
||||
clk->cl.con_id = con;
|
||||
clk->cl.clk = clk;
|
||||
@@ -356,24 +360,28 @@ static void clkdev_add_pci(void)
|
||||
struct clk *clk_ext = kzalloc(sizeof(struct clk), GFP_KERNEL);
|
||||
|
||||
/* main pci clock */
|
||||
clk->cl.dev_id = "17000000.pci";
|
||||
clk->cl.con_id = NULL;
|
||||
clk->cl.clk = clk;
|
||||
clk->rate = CLOCK_33M;
|
||||
clk->rates = valid_pci_rates;
|
||||
clk->enable = pci_enable;
|
||||
clk->disable = pmu_disable;
|
||||
clk->module = 0;
|
||||
clk->bits = PMU_PCI;
|
||||
clkdev_add(&clk->cl);
|
||||
if (clk) {
|
||||
clk->cl.dev_id = "17000000.pci";
|
||||
clk->cl.con_id = NULL;
|
||||
clk->cl.clk = clk;
|
||||
clk->rate = CLOCK_33M;
|
||||
clk->rates = valid_pci_rates;
|
||||
clk->enable = pci_enable;
|
||||
clk->disable = pmu_disable;
|
||||
clk->module = 0;
|
||||
clk->bits = PMU_PCI;
|
||||
clkdev_add(&clk->cl);
|
||||
}
|
||||
|
||||
/* use internal/external bus clock */
|
||||
clk_ext->cl.dev_id = "17000000.pci";
|
||||
clk_ext->cl.con_id = "external";
|
||||
clk_ext->cl.clk = clk_ext;
|
||||
clk_ext->enable = pci_ext_enable;
|
||||
clk_ext->disable = pci_ext_disable;
|
||||
clkdev_add(&clk_ext->cl);
|
||||
if (clk_ext) {
|
||||
clk_ext->cl.dev_id = "17000000.pci";
|
||||
clk_ext->cl.con_id = "external";
|
||||
clk_ext->cl.clk = clk_ext;
|
||||
clk_ext->enable = pci_ext_enable;
|
||||
clk_ext->disable = pci_ext_disable;
|
||||
clkdev_add(&clk_ext->cl);
|
||||
}
|
||||
}
|
||||
|
||||
/* xway socs can generate clocks on gpio pins */
|
||||
@@ -393,9 +401,15 @@ static void clkdev_add_clkout(void)
|
||||
char *name;
|
||||
|
||||
name = kzalloc(sizeof("clkout0"), GFP_KERNEL);
|
||||
if (!name)
|
||||
continue;
|
||||
sprintf(name, "clkout%d", i);
|
||||
|
||||
clk = kzalloc(sizeof(struct clk), GFP_KERNEL);
|
||||
if (!clk) {
|
||||
kfree(name);
|
||||
continue;
|
||||
}
|
||||
clk->cl.dev_id = "1f103000.cgu";
|
||||
clk->cl.con_id = name;
|
||||
clk->cl.clk = clk;
|
||||
|
||||
@@ -37,6 +37,16 @@
|
||||
#include <asm/mach-rc32434/rb.h>
|
||||
#include <asm/mach-rc32434/gpio.h>
|
||||
|
||||
#define GPIOBASE 0x050000
|
||||
/* Offsets relative to GPIOBASE */
|
||||
#define GPIOFUNC 0x00
|
||||
#define GPIOCFG 0x04
|
||||
#define GPIOD 0x08
|
||||
#define GPIOILEVEL 0x0C
|
||||
#define GPIOISTAT 0x10
|
||||
#define GPIONMIEN 0x14
|
||||
#define IMASK6 0x38
|
||||
|
||||
struct rb532_gpio_chip {
|
||||
struct gpio_chip chip;
|
||||
void __iomem *regbase;
|
||||
|
||||
@@ -363,6 +363,8 @@ static void ip22_check_gio(int slotno, unsigned long addr, int irq)
|
||||
printk(KERN_INFO "GIO: slot %d : %s (id %x)\n",
|
||||
slotno, name, id);
|
||||
gio_dev = kzalloc(sizeof *gio_dev, GFP_KERNEL);
|
||||
if (!gio_dev)
|
||||
return;
|
||||
gio_dev->name = name;
|
||||
gio_dev->slotno = slotno;
|
||||
gio_dev->id.id = id;
|
||||
|
||||
@@ -44,9 +44,4 @@ struct user {
|
||||
char u_comm[32]; /* user command name */
|
||||
};
|
||||
|
||||
#define NBPG PAGE_SIZE
|
||||
#define UPAGES 1
|
||||
#define HOST_TEXT_START_ADDR (u.start_code)
|
||||
#define HOST_DATA_START_ADDR (u.start_data)
|
||||
#define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * NBPG)
|
||||
#endif /* _ASM_POWERPC_USER_H */
|
||||
|
||||
@@ -67,9 +67,5 @@ struct user {
|
||||
unsigned long magic; /* To uniquely identify a core file */
|
||||
char u_comm[32]; /* User command that was responsible */
|
||||
};
|
||||
#define NBPG PAGE_SIZE
|
||||
#define UPAGES 1
|
||||
#define HOST_TEXT_START_ADDR (u.start_code)
|
||||
#define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * NBPG)
|
||||
|
||||
#endif /* _S390_USER_H */
|
||||
|
||||
@@ -3462,7 +3462,7 @@ void exit_sie(struct kvm_vcpu *vcpu)
|
||||
/* Kick a guest cpu out of SIE to process a request synchronously */
|
||||
void kvm_s390_sync_request(int req, struct kvm_vcpu *vcpu)
|
||||
{
|
||||
kvm_make_request(req, vcpu);
|
||||
__kvm_make_request(req, vcpu);
|
||||
kvm_s390_vcpu_request(vcpu);
|
||||
}
|
||||
|
||||
|
||||
@@ -52,10 +52,4 @@ struct user {
|
||||
char u_comm[32]; /* user command name */
|
||||
};
|
||||
|
||||
#define NBPG PAGE_SIZE
|
||||
#define UPAGES 1
|
||||
#define HOST_TEXT_START_ADDR (u.start_code)
|
||||
#define HOST_DATA_START_ADDR (u.start_data)
|
||||
#define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * NBPG)
|
||||
|
||||
#endif /* __ASM_SH_USER_H */
|
||||
|
||||
@@ -75,10 +75,6 @@ USER_CFLAGS = $(patsubst $(KERNEL_DEFINES),,$(patsubst -I%,,$(KBUILD_CFLAGS))) \
|
||||
-D_FILE_OFFSET_BITS=64 -idirafter $(srctree)/include \
|
||||
-idirafter $(objtree)/include -D__KERNEL__ -D__UM_HOST__
|
||||
|
||||
ifdef CONFIG_CC_IS_CLANG
|
||||
USER_CFLAGS := $(patsubst -mno-global-merge,,$(USER_CFLAGS))
|
||||
endif
|
||||
|
||||
#This will adjust *FLAGS accordingly to the platform.
|
||||
include $(srctree)/$(ARCH_DIR)/Makefile-os-$(OS)
|
||||
|
||||
|
||||
@@ -24,7 +24,6 @@ generic-y += softirq_stack.h
|
||||
generic-y += switch_to.h
|
||||
generic-y += topology.h
|
||||
generic-y += trace_clock.h
|
||||
generic-y += word-at-a-time.h
|
||||
generic-y += kprobes.h
|
||||
generic-y += mm_hooks.h
|
||||
generic-y += vga.h
|
||||
|
||||
@@ -122,7 +122,6 @@ config X86
|
||||
select ARCH_WANT_GENERAL_HUGETLB
|
||||
select ARCH_WANT_HUGE_PMD_SHARE
|
||||
select ARCH_WANT_LD_ORPHAN_WARN
|
||||
select ARCH_WANTS_RT_DELAYED_SIGNALS
|
||||
select ARCH_WANTS_THP_SWAP if X86_64
|
||||
select ARCH_HAS_PARANOID_L1D_FLUSH
|
||||
select BUILDTIME_TABLE_SORT
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
CONFIG_WERROR=y
|
||||
CONFIG_SYSVIPC=y
|
||||
CONFIG_POSIX_MQUEUE=y
|
||||
CONFIG_USELIB=y
|
||||
CONFIG_AUDIT=y
|
||||
CONFIG_NO_HZ=y
|
||||
CONFIG_HIGH_RES_TIMERS=y
|
||||
@@ -11,23 +13,30 @@ CONFIG_TASK_XACCT=y
|
||||
CONFIG_TASK_IO_ACCOUNTING=y
|
||||
CONFIG_LOG_BUF_SHIFT=18
|
||||
CONFIG_CGROUPS=y
|
||||
CONFIG_BLK_CGROUP=y
|
||||
CONFIG_CGROUP_SCHED=y
|
||||
CONFIG_CGROUP_PIDS=y
|
||||
CONFIG_CGROUP_RDMA=y
|
||||
CONFIG_CGROUP_FREEZER=y
|
||||
CONFIG_CGROUP_HUGETLB=y
|
||||
CONFIG_CPUSETS=y
|
||||
CONFIG_CGROUP_DEVICE=y
|
||||
CONFIG_CGROUP_CPUACCT=y
|
||||
CONFIG_CGROUP_PERF=y
|
||||
CONFIG_CGROUP_MISC=y
|
||||
CONFIG_CGROUP_DEBUG=y
|
||||
CONFIG_BLK_DEV_INITRD=y
|
||||
CONFIG_KALLSYMS_ALL=y
|
||||
# CONFIG_COMPAT_BRK is not set
|
||||
CONFIG_PROFILING=y
|
||||
# CONFIG_64BIT is not set
|
||||
CONFIG_SMP=y
|
||||
CONFIG_X86_GENERIC=y
|
||||
CONFIG_HPET_TIMER=y
|
||||
CONFIG_HYPERVISOR_GUEST=y
|
||||
CONFIG_PARAVIRT=y
|
||||
CONFIG_NR_CPUS=8
|
||||
CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS=y
|
||||
CONFIG_X86_REBOOTFIXUPS=y
|
||||
CONFIG_MICROCODE_AMD=y
|
||||
CONFIG_X86_MSR=y
|
||||
CONFIG_X86_CPUID=y
|
||||
CONFIG_HIGHPTE=y
|
||||
CONFIG_X86_CHECK_BIOS_CORRUPTION=y
|
||||
# CONFIG_MTRR_SANITIZER is not set
|
||||
CONFIG_EFI=y
|
||||
@@ -43,12 +52,15 @@ CONFIG_ACPI_BGRT=y
|
||||
CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y
|
||||
CONFIG_CPU_FREQ_GOV_ONDEMAND=y
|
||||
CONFIG_X86_ACPI_CPUFREQ=y
|
||||
CONFIG_EFI_VARS=y
|
||||
CONFIG_KPROBES=y
|
||||
CONFIG_JUMP_LABEL=y
|
||||
CONFIG_COMPAT_32BIT_TIME=y
|
||||
CONFIG_MODULES=y
|
||||
CONFIG_MODULE_UNLOAD=y
|
||||
CONFIG_MODULE_FORCE_UNLOAD=y
|
||||
CONFIG_BLK_CGROUP_IOLATENCY=y
|
||||
CONFIG_BLK_CGROUP_IOCOST=y
|
||||
CONFIG_BLK_CGROUP_IOPRIO=y
|
||||
CONFIG_BINFMT_MISC=y
|
||||
CONFIG_NET=y
|
||||
CONFIG_PACKET=y
|
||||
@@ -103,12 +115,16 @@ CONFIG_IP6_NF_FILTER=y
|
||||
CONFIG_IP6_NF_TARGET_REJECT=y
|
||||
CONFIG_IP6_NF_MANGLE=y
|
||||
CONFIG_NET_SCHED=y
|
||||
CONFIG_NET_CLS_CGROUP=y
|
||||
CONFIG_NET_EMATCH=y
|
||||
CONFIG_NET_CLS_ACT=y
|
||||
CONFIG_CGROUP_NET_PRIO=y
|
||||
CONFIG_CFG80211=y
|
||||
CONFIG_MAC80211=y
|
||||
CONFIG_MAC80211_LEDS=y
|
||||
CONFIG_RFKILL=y
|
||||
CONFIG_NET_9P=y
|
||||
CONFIG_NET_9P_VIRTIO=y
|
||||
CONFIG_PCI=y
|
||||
CONFIG_PCIEPORTBUS=y
|
||||
CONFIG_PCI_MSI=y
|
||||
@@ -119,13 +135,16 @@ CONFIG_DEVTMPFS=y
|
||||
CONFIG_DEVTMPFS_MOUNT=y
|
||||
CONFIG_DEBUG_DEVRES=y
|
||||
CONFIG_CONNECTOR=y
|
||||
CONFIG_EFI_VARS=y
|
||||
CONFIG_EFI_CAPSULE_LOADER=y
|
||||
CONFIG_BLK_DEV_LOOP=y
|
||||
CONFIG_VIRTIO_BLK=y
|
||||
CONFIG_BLK_DEV_SD=y
|
||||
CONFIG_BLK_DEV_SR=y
|
||||
CONFIG_CHR_DEV_SG=y
|
||||
CONFIG_SCSI_CONSTANTS=y
|
||||
CONFIG_SCSI_SPI_ATTRS=y
|
||||
# CONFIG_SCSI_LOWLEVEL is not set
|
||||
CONFIG_SCSI_VIRTIO=y
|
||||
CONFIG_ATA=y
|
||||
CONFIG_SATA_AHCI=y
|
||||
CONFIG_ATA_PIIX=y
|
||||
@@ -143,6 +162,7 @@ CONFIG_MACINTOSH_DRIVERS=y
|
||||
CONFIG_MAC_EMUMOUSEBTN=y
|
||||
CONFIG_NETDEVICES=y
|
||||
CONFIG_NETCONSOLE=y
|
||||
CONFIG_VIRTIO_NET=y
|
||||
CONFIG_BNX2=y
|
||||
CONFIG_TIGON3=y
|
||||
CONFIG_NET_TULIP=y
|
||||
@@ -170,6 +190,7 @@ CONFIG_SERIAL_8250_SHARE_IRQ=y
|
||||
CONFIG_SERIAL_8250_DETECT_IRQ=y
|
||||
CONFIG_SERIAL_8250_RSA=y
|
||||
CONFIG_SERIAL_NONSTANDARD=y
|
||||
CONFIG_VIRTIO_CONSOLE=y
|
||||
CONFIG_HW_RANDOM=y
|
||||
CONFIG_NVRAM=y
|
||||
CONFIG_HPET=y
|
||||
@@ -181,12 +202,7 @@ CONFIG_AGP_AMD64=y
|
||||
CONFIG_AGP_INTEL=y
|
||||
CONFIG_DRM=y
|
||||
CONFIG_DRM_I915=y
|
||||
CONFIG_FB_MODE_HELPERS=y
|
||||
CONFIG_FB_TILEBLITTING=y
|
||||
CONFIG_FB_EFI=y
|
||||
CONFIG_LOGO=y
|
||||
# CONFIG_LOGO_LINUX_MONO is not set
|
||||
# CONFIG_LOGO_LINUX_VGA16 is not set
|
||||
CONFIG_DRM_VIRTIO_GPU=y
|
||||
CONFIG_SOUND=y
|
||||
CONFIG_SND=y
|
||||
CONFIG_SND_HRTIMER=y
|
||||
@@ -219,6 +235,8 @@ CONFIG_USB_STORAGE=y
|
||||
CONFIG_RTC_CLASS=y
|
||||
# CONFIG_RTC_HCTOSYS is not set
|
||||
CONFIG_DMADEVICES=y
|
||||
CONFIG_VIRTIO_PCI=y
|
||||
CONFIG_VIRTIO_INPUT=y
|
||||
CONFIG_EEEPC_LAPTOP=y
|
||||
CONFIG_EXT4_FS=y
|
||||
CONFIG_EXT4_FS_POSIX_ACL=y
|
||||
@@ -240,6 +258,7 @@ CONFIG_NFS_FS=y
|
||||
CONFIG_NFS_V3_ACL=y
|
||||
CONFIG_NFS_V4=y
|
||||
CONFIG_ROOT_NFS=y
|
||||
CONFIG_9P_FS=y
|
||||
CONFIG_NLS_DEFAULT="utf8"
|
||||
CONFIG_NLS_CODEPAGE_437=y
|
||||
CONFIG_NLS_ASCII=y
|
||||
@@ -251,14 +270,15 @@ CONFIG_SECURITY_SELINUX=y
|
||||
CONFIG_SECURITY_SELINUX_BOOTPARAM=y
|
||||
CONFIG_SECURITY_SELINUX_DISABLE=y
|
||||
CONFIG_PRINTK_TIME=y
|
||||
CONFIG_FRAME_WARN=1024
|
||||
CONFIG_MAGIC_SYSRQ=y
|
||||
CONFIG_DEBUG_KERNEL=y
|
||||
CONFIG_DEBUG_STACK_USAGE=y
|
||||
CONFIG_DEBUG_STACKOVERFLOW=y
|
||||
# CONFIG_SCHED_DEBUG is not set
|
||||
CONFIG_SCHEDSTATS=y
|
||||
CONFIG_BLK_DEV_IO_TRACE=y
|
||||
CONFIG_PROVIDE_OHCI1394_DMA_INIT=y
|
||||
CONFIG_EARLY_PRINTK_DBGP=y
|
||||
CONFIG_DEBUG_BOOT_PARAMS=y
|
||||
CONFIG_KALLSYMS_ALL=y
|
||||
CONFIG_UNWINDER_FRAME_POINTER=y
|
||||
# CONFIG_64BIT is not set
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
CONFIG_WERROR=y
|
||||
CONFIG_SYSVIPC=y
|
||||
CONFIG_POSIX_MQUEUE=y
|
||||
CONFIG_AUDIT=y
|
||||
@@ -11,14 +12,25 @@ CONFIG_TASK_XACCT=y
|
||||
CONFIG_TASK_IO_ACCOUNTING=y
|
||||
CONFIG_LOG_BUF_SHIFT=18
|
||||
CONFIG_CGROUPS=y
|
||||
CONFIG_BLK_CGROUP=y
|
||||
CONFIG_CGROUP_SCHED=y
|
||||
CONFIG_CGROUP_PIDS=y
|
||||
CONFIG_CGROUP_RDMA=y
|
||||
CONFIG_CGROUP_FREEZER=y
|
||||
CONFIG_CGROUP_HUGETLB=y
|
||||
CONFIG_CPUSETS=y
|
||||
CONFIG_CGROUP_DEVICE=y
|
||||
CONFIG_CGROUP_CPUACCT=y
|
||||
CONFIG_CGROUP_PERF=y
|
||||
CONFIG_CGROUP_MISC=y
|
||||
CONFIG_CGROUP_DEBUG=y
|
||||
CONFIG_BLK_DEV_INITRD=y
|
||||
CONFIG_KALLSYMS_ALL=y
|
||||
# CONFIG_COMPAT_BRK is not set
|
||||
CONFIG_PROFILING=y
|
||||
CONFIG_SMP=y
|
||||
CONFIG_HYPERVISOR_GUEST=y
|
||||
CONFIG_PARAVIRT=y
|
||||
CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS=y
|
||||
CONFIG_MICROCODE_AMD=y
|
||||
CONFIG_X86_MSR=y
|
||||
@@ -41,12 +53,14 @@ CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y
|
||||
CONFIG_CPU_FREQ_GOV_ONDEMAND=y
|
||||
CONFIG_X86_ACPI_CPUFREQ=y
|
||||
CONFIG_IA32_EMULATION=y
|
||||
CONFIG_EFI_VARS=y
|
||||
CONFIG_KPROBES=y
|
||||
CONFIG_JUMP_LABEL=y
|
||||
CONFIG_MODULES=y
|
||||
CONFIG_MODULE_UNLOAD=y
|
||||
CONFIG_MODULE_FORCE_UNLOAD=y
|
||||
CONFIG_BLK_CGROUP_IOLATENCY=y
|
||||
CONFIG_BLK_CGROUP_IOCOST=y
|
||||
CONFIG_BLK_CGROUP_IOPRIO=y
|
||||
CONFIG_BINFMT_MISC=y
|
||||
CONFIG_NET=y
|
||||
CONFIG_PACKET=y
|
||||
@@ -101,12 +115,16 @@ CONFIG_IP6_NF_FILTER=y
|
||||
CONFIG_IP6_NF_TARGET_REJECT=y
|
||||
CONFIG_IP6_NF_MANGLE=y
|
||||
CONFIG_NET_SCHED=y
|
||||
CONFIG_NET_CLS_CGROUP=y
|
||||
CONFIG_NET_EMATCH=y
|
||||
CONFIG_NET_CLS_ACT=y
|
||||
CONFIG_CGROUP_NET_PRIO=y
|
||||
CONFIG_CFG80211=y
|
||||
CONFIG_MAC80211=y
|
||||
CONFIG_MAC80211_LEDS=y
|
||||
CONFIG_RFKILL=y
|
||||
CONFIG_NET_9P=y
|
||||
CONFIG_NET_9P_VIRTIO=y
|
||||
CONFIG_PCI=y
|
||||
CONFIG_PCIEPORTBUS=y
|
||||
CONFIG_HOTPLUG_PCI=y
|
||||
@@ -116,13 +134,15 @@ CONFIG_DEVTMPFS=y
|
||||
CONFIG_DEVTMPFS_MOUNT=y
|
||||
CONFIG_DEBUG_DEVRES=y
|
||||
CONFIG_CONNECTOR=y
|
||||
CONFIG_EFI_VARS=y
|
||||
CONFIG_BLK_DEV_LOOP=y
|
||||
CONFIG_VIRTIO_BLK=y
|
||||
CONFIG_BLK_DEV_SD=y
|
||||
CONFIG_BLK_DEV_SR=y
|
||||
CONFIG_CHR_DEV_SG=y
|
||||
CONFIG_SCSI_CONSTANTS=y
|
||||
CONFIG_SCSI_SPI_ATTRS=y
|
||||
# CONFIG_SCSI_LOWLEVEL is not set
|
||||
CONFIG_SCSI_VIRTIO=y
|
||||
CONFIG_ATA=y
|
||||
CONFIG_SATA_AHCI=y
|
||||
CONFIG_ATA_PIIX=y
|
||||
@@ -138,6 +158,7 @@ CONFIG_MACINTOSH_DRIVERS=y
|
||||
CONFIG_MAC_EMUMOUSEBTN=y
|
||||
CONFIG_NETDEVICES=y
|
||||
CONFIG_NETCONSOLE=y
|
||||
CONFIG_VIRTIO_NET=y
|
||||
CONFIG_TIGON3=y
|
||||
CONFIG_NET_TULIP=y
|
||||
CONFIG_E100=y
|
||||
@@ -162,6 +183,7 @@ CONFIG_SERIAL_8250_SHARE_IRQ=y
|
||||
CONFIG_SERIAL_8250_DETECT_IRQ=y
|
||||
CONFIG_SERIAL_8250_RSA=y
|
||||
CONFIG_SERIAL_NONSTANDARD=y
|
||||
CONFIG_VIRTIO_CONSOLE=y
|
||||
CONFIG_HW_RANDOM=y
|
||||
# CONFIG_HW_RANDOM_INTEL is not set
|
||||
# CONFIG_HW_RANDOM_AMD is not set
|
||||
@@ -175,12 +197,7 @@ CONFIG_AGP_AMD64=y
|
||||
CONFIG_AGP_INTEL=y
|
||||
CONFIG_DRM=y
|
||||
CONFIG_DRM_I915=y
|
||||
CONFIG_FB_MODE_HELPERS=y
|
||||
CONFIG_FB_TILEBLITTING=y
|
||||
CONFIG_FB_EFI=y
|
||||
CONFIG_LOGO=y
|
||||
# CONFIG_LOGO_LINUX_MONO is not set
|
||||
# CONFIG_LOGO_LINUX_VGA16 is not set
|
||||
CONFIG_DRM_VIRTIO_GPU=y
|
||||
CONFIG_SOUND=y
|
||||
CONFIG_SND=y
|
||||
CONFIG_SND_HRTIMER=y
|
||||
@@ -213,6 +230,8 @@ CONFIG_USB_STORAGE=y
|
||||
CONFIG_RTC_CLASS=y
|
||||
# CONFIG_RTC_HCTOSYS is not set
|
||||
CONFIG_DMADEVICES=y
|
||||
CONFIG_VIRTIO_PCI=y
|
||||
CONFIG_VIRTIO_INPUT=y
|
||||
CONFIG_EEEPC_LAPTOP=y
|
||||
CONFIG_AMD_IOMMU=y
|
||||
CONFIG_INTEL_IOMMU=y
|
||||
@@ -237,6 +256,7 @@ CONFIG_NFS_FS=y
|
||||
CONFIG_NFS_V3_ACL=y
|
||||
CONFIG_NFS_V4=y
|
||||
CONFIG_ROOT_NFS=y
|
||||
CONFIG_9P_FS=y
|
||||
CONFIG_NLS_DEFAULT="utf8"
|
||||
CONFIG_NLS_CODEPAGE_437=y
|
||||
CONFIG_NLS_ASCII=y
|
||||
@@ -257,4 +277,3 @@ CONFIG_BLK_DEV_IO_TRACE=y
|
||||
CONFIG_PROVIDE_OHCI1394_DMA_INIT=y
|
||||
CONFIG_EARLY_PRINTK_DBGP=y
|
||||
CONFIG_DEBUG_BOOT_PARAMS=y
|
||||
CONFIG_KALLSYMS_ALL=y
|
||||
|
||||
@@ -249,6 +249,7 @@ enum x86_intercept_stage;
|
||||
#define PFERR_SGX_BIT 15
|
||||
#define PFERR_GUEST_FINAL_BIT 32
|
||||
#define PFERR_GUEST_PAGE_BIT 33
|
||||
#define PFERR_IMPLICIT_ACCESS_BIT 48
|
||||
|
||||
#define PFERR_PRESENT_MASK (1U << PFERR_PRESENT_BIT)
|
||||
#define PFERR_WRITE_MASK (1U << PFERR_WRITE_BIT)
|
||||
@@ -259,6 +260,7 @@ enum x86_intercept_stage;
|
||||
#define PFERR_SGX_MASK (1U << PFERR_SGX_BIT)
|
||||
#define PFERR_GUEST_FINAL_MASK (1ULL << PFERR_GUEST_FINAL_BIT)
|
||||
#define PFERR_GUEST_PAGE_MASK (1ULL << PFERR_GUEST_PAGE_BIT)
|
||||
#define PFERR_IMPLICIT_ACCESS (1ULL << PFERR_IMPLICIT_ACCESS_BIT)
|
||||
|
||||
#define PFERR_NESTED_GUEST_PAGE (PFERR_GUEST_PAGE_MASK | \
|
||||
PFERR_WRITE_MASK | \
|
||||
@@ -430,7 +432,7 @@ struct kvm_mmu {
|
||||
void (*inject_page_fault)(struct kvm_vcpu *vcpu,
|
||||
struct x86_exception *fault);
|
||||
gpa_t (*gva_to_gpa)(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu,
|
||||
gpa_t gva_or_gpa, u32 access,
|
||||
gpa_t gva_or_gpa, u64 access,
|
||||
struct x86_exception *exception);
|
||||
int (*sync_page)(struct kvm_vcpu *vcpu,
|
||||
struct kvm_mmu_page *sp);
|
||||
@@ -512,6 +514,7 @@ struct kvm_pmu {
|
||||
u64 global_ctrl_mask;
|
||||
u64 global_ovf_ctrl_mask;
|
||||
u64 reserved_bits;
|
||||
u64 raw_event_mask;
|
||||
u8 version;
|
||||
struct kvm_pmc gp_counters[INTEL_PMC_MAX_GENERIC];
|
||||
struct kvm_pmc fixed_counters[KVM_PMC_MAX_FIXED];
|
||||
@@ -1040,14 +1043,16 @@ struct kvm_x86_msr_filter {
|
||||
struct msr_bitmap_range ranges[16];
|
||||
};
|
||||
|
||||
#define APICV_INHIBIT_REASON_DISABLE 0
|
||||
#define APICV_INHIBIT_REASON_HYPERV 1
|
||||
#define APICV_INHIBIT_REASON_NESTED 2
|
||||
#define APICV_INHIBIT_REASON_IRQWIN 3
|
||||
#define APICV_INHIBIT_REASON_PIT_REINJ 4
|
||||
#define APICV_INHIBIT_REASON_X2APIC 5
|
||||
#define APICV_INHIBIT_REASON_BLOCKIRQ 6
|
||||
#define APICV_INHIBIT_REASON_ABSENT 7
|
||||
enum kvm_apicv_inhibit {
|
||||
APICV_INHIBIT_REASON_DISABLE,
|
||||
APICV_INHIBIT_REASON_HYPERV,
|
||||
APICV_INHIBIT_REASON_NESTED,
|
||||
APICV_INHIBIT_REASON_IRQWIN,
|
||||
APICV_INHIBIT_REASON_PIT_REINJ,
|
||||
APICV_INHIBIT_REASON_X2APIC,
|
||||
APICV_INHIBIT_REASON_BLOCKIRQ,
|
||||
APICV_INHIBIT_REASON_ABSENT,
|
||||
};
|
||||
|
||||
struct kvm_arch {
|
||||
unsigned long n_used_mmu_pages;
|
||||
@@ -1401,7 +1406,7 @@ struct kvm_x86_ops {
|
||||
void (*enable_nmi_window)(struct kvm_vcpu *vcpu);
|
||||
void (*enable_irq_window)(struct kvm_vcpu *vcpu);
|
||||
void (*update_cr8_intercept)(struct kvm_vcpu *vcpu, int tpr, int irr);
|
||||
bool (*check_apicv_inhibit_reasons)(ulong bit);
|
||||
bool (*check_apicv_inhibit_reasons)(enum kvm_apicv_inhibit reason);
|
||||
void (*refresh_apicv_exec_ctrl)(struct kvm_vcpu *vcpu);
|
||||
void (*hwapic_irr_update)(struct kvm_vcpu *vcpu, int max_irr);
|
||||
void (*hwapic_isr_update)(struct kvm_vcpu *vcpu, int isr);
|
||||
@@ -1585,7 +1590,7 @@ void kvm_mmu_module_exit(void);
|
||||
|
||||
void kvm_mmu_destroy(struct kvm_vcpu *vcpu);
|
||||
int kvm_mmu_create(struct kvm_vcpu *vcpu);
|
||||
void kvm_mmu_init_vm(struct kvm *kvm);
|
||||
int kvm_mmu_init_vm(struct kvm *kvm);
|
||||
void kvm_mmu_uninit_vm(struct kvm *kvm);
|
||||
|
||||
void kvm_mmu_after_set_cpuid(struct kvm_vcpu *vcpu);
|
||||
@@ -1795,11 +1800,22 @@ gpa_t kvm_mmu_gva_to_gpa_system(struct kvm_vcpu *vcpu, gva_t gva,
|
||||
|
||||
bool kvm_apicv_activated(struct kvm *kvm);
|
||||
void kvm_vcpu_update_apicv(struct kvm_vcpu *vcpu);
|
||||
void kvm_request_apicv_update(struct kvm *kvm, bool activate,
|
||||
unsigned long bit);
|
||||
void __kvm_set_or_clear_apicv_inhibit(struct kvm *kvm,
|
||||
enum kvm_apicv_inhibit reason, bool set);
|
||||
void kvm_set_or_clear_apicv_inhibit(struct kvm *kvm,
|
||||
enum kvm_apicv_inhibit reason, bool set);
|
||||
|
||||
void __kvm_request_apicv_update(struct kvm *kvm, bool activate,
|
||||
unsigned long bit);
|
||||
static inline void kvm_set_apicv_inhibit(struct kvm *kvm,
|
||||
enum kvm_apicv_inhibit reason)
|
||||
{
|
||||
kvm_set_or_clear_apicv_inhibit(kvm, reason, true);
|
||||
}
|
||||
|
||||
static inline void kvm_clear_apicv_inhibit(struct kvm *kvm,
|
||||
enum kvm_apicv_inhibit reason)
|
||||
{
|
||||
kvm_set_or_clear_apicv_inhibit(kvm, reason, false);
|
||||
}
|
||||
|
||||
int kvm_emulate_hypercall(struct kvm_vcpu *vcpu);
|
||||
|
||||
|
||||
@@ -221,8 +221,14 @@ struct __attribute__ ((__packed__)) vmcb_control_area {
|
||||
#define SVM_NESTED_CTL_SEV_ES_ENABLE BIT(2)
|
||||
|
||||
|
||||
#define SVM_TSC_RATIO_RSVD 0xffffff0000000000ULL
|
||||
#define SVM_TSC_RATIO_MIN 0x0000000000000001ULL
|
||||
#define SVM_TSC_RATIO_MAX 0x000000ffffffffffULL
|
||||
#define SVM_TSC_RATIO_DEFAULT 0x0100000000ULL
|
||||
|
||||
|
||||
/* AVIC */
|
||||
#define AVIC_LOGICAL_ID_ENTRY_GUEST_PHYSICAL_ID_MASK (0xFF)
|
||||
#define AVIC_LOGICAL_ID_ENTRY_GUEST_PHYSICAL_ID_MASK (0xFFULL)
|
||||
#define AVIC_LOGICAL_ID_ENTRY_VALID_BIT 31
|
||||
#define AVIC_LOGICAL_ID_ENTRY_VALID_MASK (1 << 31)
|
||||
|
||||
@@ -230,9 +236,11 @@ struct __attribute__ ((__packed__)) vmcb_control_area {
|
||||
#define AVIC_PHYSICAL_ID_ENTRY_BACKING_PAGE_MASK (0xFFFFFFFFFFULL << 12)
|
||||
#define AVIC_PHYSICAL_ID_ENTRY_IS_RUNNING_MASK (1ULL << 62)
|
||||
#define AVIC_PHYSICAL_ID_ENTRY_VALID_MASK (1ULL << 63)
|
||||
#define AVIC_PHYSICAL_ID_TABLE_SIZE_MASK (0xFF)
|
||||
#define AVIC_PHYSICAL_ID_TABLE_SIZE_MASK (0xFFULL)
|
||||
|
||||
#define AVIC_DOORBELL_PHYSICAL_ID_MASK (0xFF)
|
||||
#define AVIC_DOORBELL_PHYSICAL_ID_MASK GENMASK_ULL(11, 0)
|
||||
|
||||
#define VMCB_AVIC_APIC_BAR_MASK 0xFFFFFFFFFF000ULL
|
||||
|
||||
#define AVIC_UNACCEL_ACCESS_WRITE_MASK 1
|
||||
#define AVIC_UNACCEL_ACCESS_OFFSET_MASK 0xFF0
|
||||
|
||||
@@ -124,9 +124,5 @@ struct user{
|
||||
char u_comm[32]; /* User command that was responsible */
|
||||
int u_debugreg[8];
|
||||
};
|
||||
#define NBPG PAGE_SIZE
|
||||
#define UPAGES 1
|
||||
#define HOST_TEXT_START_ADDR (u.start_code)
|
||||
#define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * NBPG)
|
||||
|
||||
#endif /* _ASM_X86_USER_32_H */
|
||||
|
||||
@@ -130,9 +130,5 @@ struct user {
|
||||
unsigned long error_code; /* CPU error code or 0 */
|
||||
unsigned long fault_address; /* CR3 or 0 */
|
||||
};
|
||||
#define NBPG PAGE_SIZE
|
||||
#define UPAGES 1
|
||||
#define HOST_TEXT_START_ADDR (u.start_code)
|
||||
#define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * NBPG)
|
||||
|
||||
#endif /* _ASM_X86_USER_64_H */
|
||||
|
||||
@@ -415,9 +415,6 @@ int fpu_copy_uabi_to_guest_fpstate(struct fpu_guest *gfpu, const void *buf,
|
||||
xpkru = get_xsave_addr(&kstate->regs.xsave, XFEATURE_PKRU);
|
||||
*vpkru = xpkru->pkru;
|
||||
}
|
||||
|
||||
/* Ensure that XCOMP_BV is set up for XSAVES */
|
||||
xstate_init_xcomp_bv(&kstate->regs.xsave, kstate->xfeatures);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(fpu_copy_uabi_to_guest_fpstate);
|
||||
|
||||
+68
-152
@@ -81,10 +81,10 @@ static unsigned int xstate_offsets[XFEATURE_MAX] __ro_after_init =
|
||||
{ [ 0 ... XFEATURE_MAX - 1] = -1};
|
||||
static unsigned int xstate_sizes[XFEATURE_MAX] __ro_after_init =
|
||||
{ [ 0 ... XFEATURE_MAX - 1] = -1};
|
||||
static unsigned int xstate_comp_offsets[XFEATURE_MAX] __ro_after_init =
|
||||
{ [ 0 ... XFEATURE_MAX - 1] = -1};
|
||||
static unsigned int xstate_supervisor_only_offsets[XFEATURE_MAX] __ro_after_init =
|
||||
{ [ 0 ... XFEATURE_MAX - 1] = -1};
|
||||
static unsigned int xstate_flags[XFEATURE_MAX] __ro_after_init;
|
||||
|
||||
#define XSTATE_FLAG_SUPERVISOR BIT(0)
|
||||
#define XSTATE_FLAG_ALIGNED64 BIT(1)
|
||||
|
||||
/*
|
||||
* Return whether the system supports a given xfeature.
|
||||
@@ -124,17 +124,41 @@ int cpu_has_xfeatures(u64 xfeatures_needed, const char **feature_name)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cpu_has_xfeatures);
|
||||
|
||||
static bool xfeature_is_aligned64(int xfeature_nr)
|
||||
{
|
||||
return xstate_flags[xfeature_nr] & XSTATE_FLAG_ALIGNED64;
|
||||
}
|
||||
|
||||
static bool xfeature_is_supervisor(int xfeature_nr)
|
||||
{
|
||||
/*
|
||||
* Extended State Enumeration Sub-leaves (EAX = 0DH, ECX = n, n > 1)
|
||||
* returns ECX[0] set to (1) for a supervisor state, and cleared (0)
|
||||
* for a user state.
|
||||
*/
|
||||
u32 eax, ebx, ecx, edx;
|
||||
return xstate_flags[xfeature_nr] & XSTATE_FLAG_SUPERVISOR;
|
||||
}
|
||||
|
||||
cpuid_count(XSTATE_CPUID, xfeature_nr, &eax, &ebx, &ecx, &edx);
|
||||
return ecx & 1;
|
||||
static unsigned int xfeature_get_offset(u64 xcomp_bv, int xfeature)
|
||||
{
|
||||
unsigned int offs, i;
|
||||
|
||||
/*
|
||||
* Non-compacted format and legacy features use the cached fixed
|
||||
* offsets.
|
||||
*/
|
||||
if (!cpu_feature_enabled(X86_FEATURE_XSAVES) || xfeature <= XFEATURE_SSE)
|
||||
return xstate_offsets[xfeature];
|
||||
|
||||
/*
|
||||
* Compacted format offsets depend on the actual content of the
|
||||
* compacted xsave area which is determined by the xcomp_bv header
|
||||
* field.
|
||||
*/
|
||||
offs = FXSAVE_SIZE + XSAVE_HDR_SIZE;
|
||||
for_each_extended_xfeature(i, xcomp_bv) {
|
||||
if (xfeature_is_aligned64(i))
|
||||
offs = ALIGN(offs, 64);
|
||||
if (i == xfeature)
|
||||
break;
|
||||
offs += xstate_sizes[i];
|
||||
}
|
||||
return offs;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -182,7 +206,7 @@ static bool xfeature_enabled(enum xfeature xfeature)
|
||||
* Record the offsets and sizes of various xstates contained
|
||||
* in the XSAVE state memory layout.
|
||||
*/
|
||||
static void __init setup_xstate_features(void)
|
||||
static void __init setup_xstate_cache(void)
|
||||
{
|
||||
u32 eax, ebx, ecx, edx, i;
|
||||
/* start at the beginning of the "extended state" */
|
||||
@@ -205,6 +229,7 @@ static void __init setup_xstate_features(void)
|
||||
cpuid_count(XSTATE_CPUID, i, &eax, &ebx, &ecx, &edx);
|
||||
|
||||
xstate_sizes[i] = eax;
|
||||
xstate_flags[i] = ecx;
|
||||
|
||||
/*
|
||||
* If an xfeature is supervisor state, the offset in EBX is
|
||||
@@ -263,94 +288,6 @@ static void __init print_xstate_features(void)
|
||||
WARN_ON(nr >= XFEATURE_MAX); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* We could cache this like xstate_size[], but we only use
|
||||
* it here, so it would be a waste of space.
|
||||
*/
|
||||
static int xfeature_is_aligned(int xfeature_nr)
|
||||
{
|
||||
u32 eax, ebx, ecx, edx;
|
||||
|
||||
CHECK_XFEATURE(xfeature_nr);
|
||||
|
||||
if (!xfeature_enabled(xfeature_nr)) {
|
||||
WARN_ONCE(1, "Checking alignment of disabled xfeature %d\n",
|
||||
xfeature_nr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
cpuid_count(XSTATE_CPUID, xfeature_nr, &eax, &ebx, &ecx, &edx);
|
||||
/*
|
||||
* The value returned by ECX[1] indicates the alignment
|
||||
* of state component 'i' when the compacted format
|
||||
* of the extended region of an XSAVE area is used:
|
||||
*/
|
||||
return !!(ecx & 2);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function sets up offsets and sizes of all extended states in
|
||||
* xsave area. This supports both standard format and compacted format
|
||||
* of the xsave area.
|
||||
*/
|
||||
static void __init setup_xstate_comp_offsets(void)
|
||||
{
|
||||
unsigned int next_offset;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* The FP xstates and SSE xstates are legacy states. They are always
|
||||
* in the fixed offsets in the xsave area in either compacted form
|
||||
* or standard form.
|
||||
*/
|
||||
xstate_comp_offsets[XFEATURE_FP] = 0;
|
||||
xstate_comp_offsets[XFEATURE_SSE] = offsetof(struct fxregs_state,
|
||||
xmm_space);
|
||||
|
||||
if (!cpu_feature_enabled(X86_FEATURE_XSAVES)) {
|
||||
for_each_extended_xfeature(i, fpu_kernel_cfg.max_features)
|
||||
xstate_comp_offsets[i] = xstate_offsets[i];
|
||||
return;
|
||||
}
|
||||
|
||||
next_offset = FXSAVE_SIZE + XSAVE_HDR_SIZE;
|
||||
|
||||
for_each_extended_xfeature(i, fpu_kernel_cfg.max_features) {
|
||||
if (xfeature_is_aligned(i))
|
||||
next_offset = ALIGN(next_offset, 64);
|
||||
|
||||
xstate_comp_offsets[i] = next_offset;
|
||||
next_offset += xstate_sizes[i];
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup offsets of a supervisor-state-only XSAVES buffer:
|
||||
*
|
||||
* The offsets stored in xstate_comp_offsets[] only work for one specific
|
||||
* value of the Requested Feature BitMap (RFBM). In cases where a different
|
||||
* RFBM value is used, a different set of offsets is required. This set of
|
||||
* offsets is for when RFBM=xfeatures_mask_supervisor().
|
||||
*/
|
||||
static void __init setup_supervisor_only_offsets(void)
|
||||
{
|
||||
unsigned int next_offset;
|
||||
int i;
|
||||
|
||||
next_offset = FXSAVE_SIZE + XSAVE_HDR_SIZE;
|
||||
|
||||
for_each_extended_xfeature(i, fpu_kernel_cfg.max_features) {
|
||||
if (!xfeature_is_supervisor(i))
|
||||
continue;
|
||||
|
||||
if (xfeature_is_aligned(i))
|
||||
next_offset = ALIGN(next_offset, 64);
|
||||
|
||||
xstate_supervisor_only_offsets[i] = next_offset;
|
||||
next_offset += xstate_sizes[i];
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Print out xstate component offsets and sizes
|
||||
*/
|
||||
@@ -360,7 +297,8 @@ static void __init print_xstate_offset_size(void)
|
||||
|
||||
for_each_extended_xfeature(i, fpu_kernel_cfg.max_features) {
|
||||
pr_info("x86/fpu: xstate_offset[%d]: %4d, xstate_sizes[%d]: %4d\n",
|
||||
i, xstate_comp_offsets[i], i, xstate_sizes[i]);
|
||||
i, xfeature_get_offset(fpu_kernel_cfg.max_features, i),
|
||||
i, xstate_sizes[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -419,7 +357,6 @@ static void __init setup_init_fpu_buf(void)
|
||||
if (!boot_cpu_has(X86_FEATURE_XSAVE))
|
||||
return;
|
||||
|
||||
setup_xstate_features();
|
||||
print_xstate_features();
|
||||
|
||||
xstate_init_xcomp_bv(&init_fpstate.regs.xsave, fpu_kernel_cfg.max_features);
|
||||
@@ -448,25 +385,6 @@ static void __init setup_init_fpu_buf(void)
|
||||
fxsave(&init_fpstate.regs.fxsave);
|
||||
}
|
||||
|
||||
static int xfeature_uncompacted_offset(int xfeature_nr)
|
||||
{
|
||||
u32 eax, ebx, ecx, edx;
|
||||
|
||||
/*
|
||||
* Only XSAVES supports supervisor states and it uses compacted
|
||||
* format. Checking a supervisor state's uncompacted offset is
|
||||
* an error.
|
||||
*/
|
||||
if (XFEATURE_MASK_SUPERVISOR_ALL & BIT_ULL(xfeature_nr)) {
|
||||
WARN_ONCE(1, "No fixed offset for xstate %d\n", xfeature_nr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
CHECK_XFEATURE(xfeature_nr);
|
||||
cpuid_count(XSTATE_CPUID, xfeature_nr, &eax, &ebx, &ecx, &edx);
|
||||
return ebx;
|
||||
}
|
||||
|
||||
int xfeature_size(int xfeature_nr)
|
||||
{
|
||||
u32 eax, ebx, ecx, edx;
|
||||
@@ -644,29 +562,15 @@ static bool __init check_xstate_against_struct(int nr)
|
||||
|
||||
static unsigned int xstate_calculate_size(u64 xfeatures, bool compacted)
|
||||
{
|
||||
unsigned int size = FXSAVE_SIZE + XSAVE_HDR_SIZE;
|
||||
int i;
|
||||
unsigned int topmost = fls64(xfeatures) - 1;
|
||||
unsigned int offset = xstate_offsets[topmost];
|
||||
|
||||
for_each_extended_xfeature(i, xfeatures) {
|
||||
/* Align from the end of the previous feature */
|
||||
if (xfeature_is_aligned(i))
|
||||
size = ALIGN(size, 64);
|
||||
/*
|
||||
* In compacted format the enabled features are packed,
|
||||
* i.e. disabled features do not occupy space.
|
||||
*
|
||||
* In non-compacted format the offsets are fixed and
|
||||
* disabled states still occupy space in the memory buffer.
|
||||
*/
|
||||
if (!compacted)
|
||||
size = xfeature_uncompacted_offset(i);
|
||||
/*
|
||||
* Add the feature size even for non-compacted format
|
||||
* to make the end result correct
|
||||
*/
|
||||
size += xfeature_size(i);
|
||||
}
|
||||
return size;
|
||||
if (topmost <= XFEATURE_SSE)
|
||||
return sizeof(struct xregs_state);
|
||||
|
||||
if (compacted)
|
||||
offset = xfeature_get_offset(xfeatures, topmost);
|
||||
return offset + xstate_sizes[topmost];
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -935,6 +839,10 @@ void __init fpu__init_system_xstate(unsigned int legacy_size)
|
||||
|
||||
/* Enable xstate instructions to be able to continue with initialization: */
|
||||
fpu__init_cpu_xstate();
|
||||
|
||||
/* Cache size, offset and flags for initialization */
|
||||
setup_xstate_cache();
|
||||
|
||||
err = init_xstate_size();
|
||||
if (err)
|
||||
goto out_disable;
|
||||
@@ -950,8 +858,6 @@ void __init fpu__init_system_xstate(unsigned int legacy_size)
|
||||
fpu_user_cfg.max_features);
|
||||
|
||||
setup_init_fpu_buf();
|
||||
setup_xstate_comp_offsets();
|
||||
setup_supervisor_only_offsets();
|
||||
|
||||
/*
|
||||
* Paranoia check whether something in the setup modified the
|
||||
@@ -1006,13 +912,19 @@ void fpu__resume_cpu(void)
|
||||
*/
|
||||
static void *__raw_xsave_addr(struct xregs_state *xsave, int xfeature_nr)
|
||||
{
|
||||
if (!xfeature_enabled(xfeature_nr)) {
|
||||
WARN_ON_FPU(1);
|
||||
u64 xcomp_bv = xsave->header.xcomp_bv;
|
||||
|
||||
if (WARN_ON_ONCE(!xfeature_enabled(xfeature_nr)))
|
||||
return NULL;
|
||||
|
||||
if (cpu_feature_enabled(X86_FEATURE_XSAVES)) {
|
||||
if (WARN_ON_ONCE(!(xcomp_bv & BIT_ULL(xfeature_nr))))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (void *)xsave + xstate_comp_offsets[xfeature_nr];
|
||||
return (void *)xsave + xfeature_get_offset(xcomp_bv, xfeature_nr);
|
||||
}
|
||||
|
||||
/*
|
||||
* Given the xsave area and a state inside, this function returns the
|
||||
* address of the state.
|
||||
@@ -1043,8 +955,9 @@ void *get_xsave_addr(struct xregs_state *xsave, int xfeature_nr)
|
||||
* We should not ever be requesting features that we
|
||||
* have not enabled.
|
||||
*/
|
||||
WARN_ONCE(!(fpu_kernel_cfg.max_features & BIT_ULL(xfeature_nr)),
|
||||
"get of unsupported state");
|
||||
if (WARN_ON_ONCE(!xfeature_enabled(xfeature_nr)))
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
* This assumes the last 'xsave*' instruction to
|
||||
* have requested that 'xfeature_nr' be saved.
|
||||
@@ -1625,6 +1538,9 @@ static int __xstate_request_perm(u64 permitted, u64 requested, bool guest)
|
||||
|
||||
/* Calculate the resulting kernel state size */
|
||||
mask = permitted | requested;
|
||||
/* Take supervisor states into account on the host */
|
||||
if (!guest)
|
||||
mask |= xfeatures_mask_supervisor();
|
||||
ksize = xstate_calculate_size(mask, compacted);
|
||||
|
||||
/* Calculate the resulting user state size */
|
||||
@@ -1639,7 +1555,7 @@ static int __xstate_request_perm(u64 permitted, u64 requested, bool guest)
|
||||
|
||||
perm = guest ? &fpu->guest_perm : &fpu->perm;
|
||||
/* Pairs with the READ_ONCE() in xstate_get_group_perm() */
|
||||
WRITE_ONCE(perm->__state_perm, requested);
|
||||
WRITE_ONCE(perm->__state_perm, mask);
|
||||
/* Protected by sighand lock */
|
||||
perm->__state_size = ksize;
|
||||
perm->__user_state_size = usize;
|
||||
|
||||
@@ -517,7 +517,7 @@ static void __send_ipi_mask(const struct cpumask *mask, int vector)
|
||||
} else if (apic_id < min && max - apic_id < KVM_IPI_CLUSTER_SIZE) {
|
||||
ipi_bitmap <<= min - apic_id;
|
||||
min = apic_id;
|
||||
} else if (apic_id < min + KVM_IPI_CLUSTER_SIZE) {
|
||||
} else if (apic_id > min && apic_id < min + KVM_IPI_CLUSTER_SIZE) {
|
||||
max = apic_id < max ? max : apic_id;
|
||||
} else {
|
||||
ret = kvm_hypercall4(KVM_HC_SEND_IPI, (unsigned long)ipi_bitmap,
|
||||
|
||||
@@ -3540,8 +3540,10 @@ static int em_rdpid(struct x86_emulate_ctxt *ctxt)
|
||||
{
|
||||
u64 tsc_aux = 0;
|
||||
|
||||
if (ctxt->ops->get_msr(ctxt, MSR_TSC_AUX, &tsc_aux))
|
||||
if (!ctxt->ops->guest_has_rdpid(ctxt))
|
||||
return emulate_ud(ctxt);
|
||||
|
||||
ctxt->ops->get_msr(ctxt, MSR_TSC_AUX, &tsc_aux);
|
||||
ctxt->dst.val = tsc_aux;
|
||||
return X86EMUL_CONTINUE;
|
||||
}
|
||||
@@ -3642,7 +3644,7 @@ static int em_wrmsr(struct x86_emulate_ctxt *ctxt)
|
||||
|
||||
msr_data = (u32)reg_read(ctxt, VCPU_REGS_RAX)
|
||||
| ((u64)reg_read(ctxt, VCPU_REGS_RDX) << 32);
|
||||
r = ctxt->ops->set_msr(ctxt, msr_index, msr_data);
|
||||
r = ctxt->ops->set_msr_with_filter(ctxt, msr_index, msr_data);
|
||||
|
||||
if (r == X86EMUL_IO_NEEDED)
|
||||
return r;
|
||||
@@ -3659,7 +3661,7 @@ static int em_rdmsr(struct x86_emulate_ctxt *ctxt)
|
||||
u64 msr_data;
|
||||
int r;
|
||||
|
||||
r = ctxt->ops->get_msr(ctxt, msr_index, &msr_data);
|
||||
r = ctxt->ops->get_msr_with_filter(ctxt, msr_index, &msr_data);
|
||||
|
||||
if (r == X86EMUL_IO_NEEDED)
|
||||
return r;
|
||||
|
||||
+16
-6
@@ -122,9 +122,13 @@ static void synic_update_vector(struct kvm_vcpu_hv_synic *synic,
|
||||
else
|
||||
hv->synic_auto_eoi_used--;
|
||||
|
||||
__kvm_request_apicv_update(vcpu->kvm,
|
||||
!hv->synic_auto_eoi_used,
|
||||
APICV_INHIBIT_REASON_HYPERV);
|
||||
/*
|
||||
* Inhibit APICv if any vCPU is using SynIC's AutoEOI, which relies on
|
||||
* the hypervisor to manually inject IRQs.
|
||||
*/
|
||||
__kvm_set_or_clear_apicv_inhibit(vcpu->kvm,
|
||||
APICV_INHIBIT_REASON_HYPERV,
|
||||
!!hv->synic_auto_eoi_used);
|
||||
|
||||
up_write(&vcpu->kvm->arch.apicv_update_lock);
|
||||
}
|
||||
@@ -239,7 +243,7 @@ static int synic_set_msr(struct kvm_vcpu_hv_synic *synic,
|
||||
struct kvm_vcpu *vcpu = hv_synic_to_vcpu(synic);
|
||||
int ret;
|
||||
|
||||
if (!synic->active && !host)
|
||||
if (!synic->active && (!host || data))
|
||||
return 1;
|
||||
|
||||
trace_kvm_hv_synic_set_msr(vcpu->vcpu_id, msr, data, host);
|
||||
@@ -285,6 +289,9 @@ static int synic_set_msr(struct kvm_vcpu_hv_synic *synic,
|
||||
case HV_X64_MSR_EOM: {
|
||||
int i;
|
||||
|
||||
if (!synic->active)
|
||||
break;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(synic->sint); i++)
|
||||
kvm_hv_notify_acked_sint(vcpu, i);
|
||||
break;
|
||||
@@ -449,6 +456,9 @@ static int synic_set_irq(struct kvm_vcpu_hv_synic *synic, u32 sint)
|
||||
struct kvm_lapic_irq irq;
|
||||
int ret, vector;
|
||||
|
||||
if (KVM_BUG_ON(!lapic_in_kernel(vcpu), vcpu->kvm))
|
||||
return -EINVAL;
|
||||
|
||||
if (sint >= ARRAY_SIZE(synic->sint))
|
||||
return -EINVAL;
|
||||
|
||||
@@ -661,7 +671,7 @@ static int stimer_set_config(struct kvm_vcpu_hv_stimer *stimer, u64 config,
|
||||
struct kvm_vcpu_hv *hv_vcpu = to_hv_vcpu(vcpu);
|
||||
struct kvm_vcpu_hv_synic *synic = to_hv_synic(vcpu);
|
||||
|
||||
if (!synic->active && !host)
|
||||
if (!synic->active && (!host || config))
|
||||
return 1;
|
||||
|
||||
if (unlikely(!host && hv_vcpu->enforce_cpuid && new_config.direct_mode &&
|
||||
@@ -690,7 +700,7 @@ static int stimer_set_count(struct kvm_vcpu_hv_stimer *stimer, u64 count,
|
||||
struct kvm_vcpu *vcpu = hv_stimer_to_vcpu(stimer);
|
||||
struct kvm_vcpu_hv_synic *synic = to_hv_synic(vcpu);
|
||||
|
||||
if (!synic->active && !host)
|
||||
if (!synic->active && (!host || count))
|
||||
return 1;
|
||||
|
||||
trace_kvm_hv_stimer_set_count(hv_stimer_to_vcpu(stimer)->vcpu_id,
|
||||
|
||||
@@ -305,15 +305,13 @@ void kvm_pit_set_reinject(struct kvm_pit *pit, bool reinject)
|
||||
* So, deactivate APICv when PIT is in reinject mode.
|
||||
*/
|
||||
if (reinject) {
|
||||
kvm_request_apicv_update(kvm, false,
|
||||
APICV_INHIBIT_REASON_PIT_REINJ);
|
||||
kvm_set_apicv_inhibit(kvm, APICV_INHIBIT_REASON_PIT_REINJ);
|
||||
/* The initial state is preserved while ps->reinject == 0. */
|
||||
kvm_pit_reset_reinject(pit);
|
||||
kvm_register_irq_ack_notifier(kvm, &ps->irq_ack_notifier);
|
||||
kvm_register_irq_mask_notifier(kvm, 0, &pit->mask_notifier);
|
||||
} else {
|
||||
kvm_request_apicv_update(kvm, true,
|
||||
APICV_INHIBIT_REASON_PIT_REINJ);
|
||||
kvm_clear_apicv_inhibit(kvm, APICV_INHIBIT_REASON_PIT_REINJ);
|
||||
kvm_unregister_irq_ack_notifier(kvm, &ps->irq_ack_notifier);
|
||||
kvm_unregister_irq_mask_notifier(kvm, 0, &pit->mask_notifier);
|
||||
}
|
||||
|
||||
@@ -210,6 +210,8 @@ struct x86_emulate_ops {
|
||||
int (*set_dr)(struct x86_emulate_ctxt *ctxt, int dr, ulong value);
|
||||
u64 (*get_smbase)(struct x86_emulate_ctxt *ctxt);
|
||||
void (*set_smbase)(struct x86_emulate_ctxt *ctxt, u64 smbase);
|
||||
int (*set_msr_with_filter)(struct x86_emulate_ctxt *ctxt, u32 msr_index, u64 data);
|
||||
int (*get_msr_with_filter)(struct x86_emulate_ctxt *ctxt, u32 msr_index, u64 *pdata);
|
||||
int (*set_msr)(struct x86_emulate_ctxt *ctxt, u32 msr_index, u64 data);
|
||||
int (*get_msr)(struct x86_emulate_ctxt *ctxt, u32 msr_index, u64 *pdata);
|
||||
int (*check_pmc)(struct x86_emulate_ctxt *ctxt, u32 pmc);
|
||||
@@ -226,6 +228,7 @@ struct x86_emulate_ops {
|
||||
bool (*guest_has_long_mode)(struct x86_emulate_ctxt *ctxt);
|
||||
bool (*guest_has_movbe)(struct x86_emulate_ctxt *ctxt);
|
||||
bool (*guest_has_fxsr)(struct x86_emulate_ctxt *ctxt);
|
||||
bool (*guest_has_rdpid)(struct x86_emulate_ctxt *ctxt);
|
||||
|
||||
void (*set_nmi_mask)(struct x86_emulate_ctxt *ctxt, bool masked);
|
||||
|
||||
|
||||
@@ -1024,6 +1024,10 @@ bool kvm_irq_delivery_to_apic_fast(struct kvm *kvm, struct kvm_lapic *src,
|
||||
*r = -1;
|
||||
|
||||
if (irq->shorthand == APIC_DEST_SELF) {
|
||||
if (KVM_BUG_ON(!src, kvm)) {
|
||||
*r = 0;
|
||||
return true;
|
||||
}
|
||||
*r = kvm_apic_set_irq(src->vcpu, irq, dest_map);
|
||||
return true;
|
||||
}
|
||||
|
||||
+16
-16
@@ -214,27 +214,27 @@ static inline int kvm_mmu_do_page_fault(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa,
|
||||
*/
|
||||
static inline u8 permission_fault(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu,
|
||||
unsigned pte_access, unsigned pte_pkey,
|
||||
unsigned pfec)
|
||||
u64 access)
|
||||
{
|
||||
int cpl = static_call(kvm_x86_get_cpl)(vcpu);
|
||||
/* strip nested paging fault error codes */
|
||||
unsigned int pfec = access;
|
||||
unsigned long rflags = static_call(kvm_x86_get_rflags)(vcpu);
|
||||
|
||||
/*
|
||||
* If CPL < 3, SMAP prevention are disabled if EFLAGS.AC = 1.
|
||||
* For explicit supervisor accesses, SMAP is disabled if EFLAGS.AC = 1.
|
||||
* For implicit supervisor accesses, SMAP cannot be overridden.
|
||||
*
|
||||
* If CPL = 3, SMAP applies to all supervisor-mode data accesses
|
||||
* (these are implicit supervisor accesses) regardless of the value
|
||||
* of EFLAGS.AC.
|
||||
* SMAP works on supervisor accesses only, and not_smap can
|
||||
* be set or not set when user access with neither has any bearing
|
||||
* on the result.
|
||||
*
|
||||
* This computes (cpl < 3) && (rflags & X86_EFLAGS_AC), leaving
|
||||
* the result in X86_EFLAGS_AC. We then insert it in place of
|
||||
* the PFERR_RSVD_MASK bit; this bit will always be zero in pfec,
|
||||
* but it will be one in index if SMAP checks are being overridden.
|
||||
* It is important to keep this branchless.
|
||||
* We put the SMAP checking bit in place of the PFERR_RSVD_MASK bit;
|
||||
* this bit will always be zero in pfec, but it will be one in index
|
||||
* if SMAP checks are being disabled.
|
||||
*/
|
||||
unsigned long smap = (cpl - 3) & (rflags & X86_EFLAGS_AC);
|
||||
int index = (pfec >> 1) +
|
||||
(smap >> (X86_EFLAGS_AC_BIT - PFERR_RSVD_BIT + 1));
|
||||
u64 implicit_access = access & PFERR_IMPLICIT_ACCESS;
|
||||
bool not_smap = ((rflags & X86_EFLAGS_AC) | implicit_access) == X86_EFLAGS_AC;
|
||||
int index = (pfec + (not_smap << PFERR_RSVD_BIT)) >> 1;
|
||||
bool fault = (mmu->permissions[index] >> pte_access) & 1;
|
||||
u32 errcode = PFERR_PRESENT_MASK;
|
||||
|
||||
@@ -317,12 +317,12 @@ static inline void kvm_update_page_stats(struct kvm *kvm, int level, int count)
|
||||
atomic64_add(count, &kvm->stat.pages[level - 1]);
|
||||
}
|
||||
|
||||
gpa_t translate_nested_gpa(struct kvm_vcpu *vcpu, gpa_t gpa, u32 access,
|
||||
gpa_t translate_nested_gpa(struct kvm_vcpu *vcpu, gpa_t gpa, u64 access,
|
||||
struct x86_exception *exception);
|
||||
|
||||
static inline gpa_t kvm_translate_gpa(struct kvm_vcpu *vcpu,
|
||||
struct kvm_mmu *mmu,
|
||||
gpa_t gpa, u32 access,
|
||||
gpa_t gpa, u64 access,
|
||||
struct x86_exception *exception)
|
||||
{
|
||||
if (mmu != &vcpu->arch.nested_mmu)
|
||||
|
||||
+17
-10
@@ -2696,8 +2696,8 @@ static int mmu_set_spte(struct kvm_vcpu *vcpu, struct kvm_memory_slot *slot,
|
||||
if (*sptep == spte) {
|
||||
ret = RET_PF_SPURIOUS;
|
||||
} else {
|
||||
trace_kvm_mmu_set_spte(level, gfn, sptep);
|
||||
flush |= mmu_spte_update(sptep, spte);
|
||||
trace_kvm_mmu_set_spte(level, gfn, sptep);
|
||||
}
|
||||
|
||||
if (wrprot) {
|
||||
@@ -3703,7 +3703,7 @@ void kvm_mmu_sync_prev_roots(struct kvm_vcpu *vcpu)
|
||||
}
|
||||
|
||||
static gpa_t nonpaging_gva_to_gpa(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu,
|
||||
gpa_t vaddr, u32 access,
|
||||
gpa_t vaddr, u64 access,
|
||||
struct x86_exception *exception)
|
||||
{
|
||||
if (exception)
|
||||
@@ -4591,11 +4591,11 @@ static void update_permission_bitmask(struct kvm_mmu *mmu, bool ept)
|
||||
* - X86_CR4_SMAP is set in CR4
|
||||
* - A user page is accessed
|
||||
* - The access is not a fetch
|
||||
* - Page fault in kernel mode
|
||||
* - if CPL = 3 or X86_EFLAGS_AC is clear
|
||||
* - The access is supervisor mode
|
||||
* - If implicit supervisor access or X86_EFLAGS_AC is clear
|
||||
*
|
||||
* Here, we cover the first three conditions.
|
||||
* The fourth is computed dynamically in permission_fault();
|
||||
* Here, we cover the first four conditions.
|
||||
* The fifth is computed dynamically in permission_fault();
|
||||
* PFERR_RSVD_MASK bit will be set in PFEC if the access is
|
||||
* *not* subject to SMAP restrictions.
|
||||
*/
|
||||
@@ -5768,17 +5768,24 @@ static void kvm_mmu_invalidate_zap_pages_in_memslot(struct kvm *kvm,
|
||||
kvm_mmu_zap_all_fast(kvm);
|
||||
}
|
||||
|
||||
void kvm_mmu_init_vm(struct kvm *kvm)
|
||||
int kvm_mmu_init_vm(struct kvm *kvm)
|
||||
{
|
||||
struct kvm_page_track_notifier_node *node = &kvm->arch.mmu_sp_tracker;
|
||||
int r;
|
||||
|
||||
INIT_LIST_HEAD(&kvm->arch.active_mmu_pages);
|
||||
INIT_LIST_HEAD(&kvm->arch.zapped_obsolete_pages);
|
||||
INIT_LIST_HEAD(&kvm->arch.lpage_disallowed_mmu_pages);
|
||||
spin_lock_init(&kvm->arch.mmu_unsync_pages_lock);
|
||||
|
||||
kvm_mmu_init_tdp_mmu(kvm);
|
||||
r = kvm_mmu_init_tdp_mmu(kvm);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
node->track_write = kvm_mmu_pte_write;
|
||||
node->track_flush_slot = kvm_mmu_invalidate_zap_pages_in_memslot;
|
||||
kvm_page_track_register_notifier(kvm, node);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void kvm_mmu_uninit_vm(struct kvm *kvm)
|
||||
@@ -5842,8 +5849,8 @@ void kvm_zap_gfn_range(struct kvm *kvm, gfn_t gfn_start, gfn_t gfn_end)
|
||||
|
||||
if (is_tdp_mmu_enabled(kvm)) {
|
||||
for (i = 0; i < KVM_ADDRESS_SPACE_NUM; i++)
|
||||
flush = kvm_tdp_mmu_zap_gfn_range(kvm, i, gfn_start,
|
||||
gfn_end, flush);
|
||||
flush = kvm_tdp_mmu_zap_leafs(kvm, i, gfn_start,
|
||||
gfn_end, true, flush);
|
||||
}
|
||||
|
||||
if (flush)
|
||||
|
||||
@@ -34,9 +34,8 @@
|
||||
#define PT_HAVE_ACCESSED_DIRTY(mmu) true
|
||||
#ifdef CONFIG_X86_64
|
||||
#define PT_MAX_FULL_LEVELS PT64_ROOT_MAX_LEVEL
|
||||
#define CMPXCHG cmpxchg
|
||||
#define CMPXCHG "cmpxchgq"
|
||||
#else
|
||||
#define CMPXCHG cmpxchg64
|
||||
#define PT_MAX_FULL_LEVELS 2
|
||||
#endif
|
||||
#elif PTTYPE == 32
|
||||
@@ -52,7 +51,7 @@
|
||||
#define PT_GUEST_DIRTY_SHIFT PT_DIRTY_SHIFT
|
||||
#define PT_GUEST_ACCESSED_SHIFT PT_ACCESSED_SHIFT
|
||||
#define PT_HAVE_ACCESSED_DIRTY(mmu) true
|
||||
#define CMPXCHG cmpxchg
|
||||
#define CMPXCHG "cmpxchgl"
|
||||
#elif PTTYPE == PTTYPE_EPT
|
||||
#define pt_element_t u64
|
||||
#define guest_walker guest_walkerEPT
|
||||
@@ -65,7 +64,9 @@
|
||||
#define PT_GUEST_DIRTY_SHIFT 9
|
||||
#define PT_GUEST_ACCESSED_SHIFT 8
|
||||
#define PT_HAVE_ACCESSED_DIRTY(mmu) ((mmu)->ept_ad)
|
||||
#define CMPXCHG cmpxchg64
|
||||
#ifdef CONFIG_X86_64
|
||||
#define CMPXCHG "cmpxchgq"
|
||||
#endif
|
||||
#define PT_MAX_FULL_LEVELS PT64_ROOT_MAX_LEVEL
|
||||
#else
|
||||
#error Invalid PTTYPE value
|
||||
@@ -147,43 +148,36 @@ static int FNAME(cmpxchg_gpte)(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu,
|
||||
pt_element_t __user *ptep_user, unsigned index,
|
||||
pt_element_t orig_pte, pt_element_t new_pte)
|
||||
{
|
||||
int npages;
|
||||
pt_element_t ret;
|
||||
pt_element_t *table;
|
||||
struct page *page;
|
||||
signed char r;
|
||||
|
||||
npages = get_user_pages_fast((unsigned long)ptep_user, 1, FOLL_WRITE, &page);
|
||||
if (likely(npages == 1)) {
|
||||
table = kmap_atomic(page);
|
||||
ret = CMPXCHG(&table[index], orig_pte, new_pte);
|
||||
kunmap_atomic(table);
|
||||
if (!user_access_begin(ptep_user, sizeof(pt_element_t)))
|
||||
return -EFAULT;
|
||||
|
||||
kvm_release_page_dirty(page);
|
||||
} else {
|
||||
struct vm_area_struct *vma;
|
||||
unsigned long vaddr = (unsigned long)ptep_user & PAGE_MASK;
|
||||
unsigned long pfn;
|
||||
unsigned long paddr;
|
||||
#ifdef CMPXCHG
|
||||
asm volatile("1:" LOCK_PREFIX CMPXCHG " %[new], %[ptr]\n"
|
||||
"setnz %b[r]\n"
|
||||
"2:"
|
||||
_ASM_EXTABLE_TYPE_REG(1b, 2b, EX_TYPE_EFAULT_REG, %k[r])
|
||||
: [ptr] "+m" (*ptep_user),
|
||||
[old] "+a" (orig_pte),
|
||||
[r] "=q" (r)
|
||||
: [new] "r" (new_pte)
|
||||
: "memory");
|
||||
#else
|
||||
asm volatile("1:" LOCK_PREFIX "cmpxchg8b %[ptr]\n"
|
||||
"setnz %b[r]\n"
|
||||
"2:"
|
||||
_ASM_EXTABLE_TYPE_REG(1b, 2b, EX_TYPE_EFAULT_REG, %k[r])
|
||||
: [ptr] "+m" (*ptep_user),
|
||||
[old] "+A" (orig_pte),
|
||||
[r] "=q" (r)
|
||||
: [new_lo] "b" ((u32)new_pte),
|
||||
[new_hi] "c" ((u32)(new_pte >> 32))
|
||||
: "memory");
|
||||
#endif
|
||||
|
||||
mmap_read_lock(current->mm);
|
||||
vma = find_vma_intersection(current->mm, vaddr, vaddr + PAGE_SIZE);
|
||||
if (!vma || !(vma->vm_flags & VM_PFNMAP)) {
|
||||
mmap_read_unlock(current->mm);
|
||||
return -EFAULT;
|
||||
}
|
||||
pfn = ((vaddr - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff;
|
||||
paddr = pfn << PAGE_SHIFT;
|
||||
table = memremap(paddr, PAGE_SIZE, MEMREMAP_WB);
|
||||
if (!table) {
|
||||
mmap_read_unlock(current->mm);
|
||||
return -EFAULT;
|
||||
}
|
||||
ret = CMPXCHG(&table[index], orig_pte, new_pte);
|
||||
memunmap(table);
|
||||
mmap_read_unlock(current->mm);
|
||||
}
|
||||
|
||||
return (ret != orig_pte);
|
||||
user_access_end();
|
||||
return r;
|
||||
}
|
||||
|
||||
static bool FNAME(prefetch_invalid_gpte)(struct kvm_vcpu *vcpu,
|
||||
@@ -339,7 +333,7 @@ static inline bool FNAME(is_last_gpte)(struct kvm_mmu *mmu,
|
||||
*/
|
||||
static int FNAME(walk_addr_generic)(struct guest_walker *walker,
|
||||
struct kvm_vcpu *vcpu, struct kvm_mmu *mmu,
|
||||
gpa_t addr, u32 access)
|
||||
gpa_t addr, u64 access)
|
||||
{
|
||||
int ret;
|
||||
pt_element_t pte;
|
||||
@@ -347,7 +341,7 @@ static int FNAME(walk_addr_generic)(struct guest_walker *walker,
|
||||
gfn_t table_gfn;
|
||||
u64 pt_access, pte_access;
|
||||
unsigned index, accessed_dirty, pte_pkey;
|
||||
unsigned nested_access;
|
||||
u64 nested_access;
|
||||
gpa_t pte_gpa;
|
||||
bool have_ad;
|
||||
int offset;
|
||||
@@ -540,7 +534,7 @@ error:
|
||||
}
|
||||
|
||||
static int FNAME(walk_addr)(struct guest_walker *walker,
|
||||
struct kvm_vcpu *vcpu, gpa_t addr, u32 access)
|
||||
struct kvm_vcpu *vcpu, gpa_t addr, u64 access)
|
||||
{
|
||||
return FNAME(walk_addr_generic)(walker, vcpu, vcpu->arch.mmu, addr,
|
||||
access);
|
||||
@@ -988,7 +982,7 @@ static void FNAME(invlpg)(struct kvm_vcpu *vcpu, gva_t gva, hpa_t root_hpa)
|
||||
|
||||
/* Note, @addr is a GPA when gva_to_gpa() translates an L2 GPA to an L1 GPA. */
|
||||
static gpa_t FNAME(gva_to_gpa)(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu,
|
||||
gpa_t addr, u32 access,
|
||||
gpa_t addr, u64 access,
|
||||
struct x86_exception *exception)
|
||||
{
|
||||
struct guest_walker walker;
|
||||
|
||||
+26
-46
@@ -14,21 +14,24 @@ static bool __read_mostly tdp_mmu_enabled = true;
|
||||
module_param_named(tdp_mmu, tdp_mmu_enabled, bool, 0644);
|
||||
|
||||
/* Initializes the TDP MMU for the VM, if enabled. */
|
||||
bool kvm_mmu_init_tdp_mmu(struct kvm *kvm)
|
||||
int kvm_mmu_init_tdp_mmu(struct kvm *kvm)
|
||||
{
|
||||
struct workqueue_struct *wq;
|
||||
|
||||
if (!tdp_enabled || !READ_ONCE(tdp_mmu_enabled))
|
||||
return false;
|
||||
return 0;
|
||||
|
||||
wq = alloc_workqueue("kvm", WQ_UNBOUND|WQ_MEM_RECLAIM|WQ_CPU_INTENSIVE, 0);
|
||||
if (!wq)
|
||||
return -ENOMEM;
|
||||
|
||||
/* This should not be changed for the lifetime of the VM. */
|
||||
kvm->arch.tdp_mmu_enabled = true;
|
||||
|
||||
INIT_LIST_HEAD(&kvm->arch.tdp_mmu_roots);
|
||||
spin_lock_init(&kvm->arch.tdp_mmu_pages_lock);
|
||||
INIT_LIST_HEAD(&kvm->arch.tdp_mmu_pages);
|
||||
kvm->arch.tdp_mmu_zap_wq =
|
||||
alloc_workqueue("kvm", WQ_UNBOUND|WQ_MEM_RECLAIM|WQ_CPU_INTENSIVE, 0);
|
||||
|
||||
return true;
|
||||
kvm->arch.tdp_mmu_zap_wq = wq;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Arbitrarily returns true so that this may be used in if statements. */
|
||||
@@ -906,10 +909,8 @@ bool kvm_tdp_mmu_zap_sp(struct kvm *kvm, struct kvm_mmu_page *sp)
|
||||
}
|
||||
|
||||
/*
|
||||
* Tears down the mappings for the range of gfns, [start, end), and frees the
|
||||
* non-root pages mapping GFNs strictly within that range. Returns true if
|
||||
* SPTEs have been cleared and a TLB flush is needed before releasing the
|
||||
* MMU lock.
|
||||
* Zap leafs SPTEs for the range of gfns, [start, end). Returns true if SPTEs
|
||||
* have been cleared and a TLB flush is needed before releasing the MMU lock.
|
||||
*
|
||||
* If can_yield is true, will release the MMU lock and reschedule if the
|
||||
* scheduler needs the CPU or there is contention on the MMU lock. If this
|
||||
@@ -917,42 +918,25 @@ bool kvm_tdp_mmu_zap_sp(struct kvm *kvm, struct kvm_mmu_page *sp)
|
||||
* the caller must ensure it does not supply too large a GFN range, or the
|
||||
* operation can cause a soft lockup.
|
||||
*/
|
||||
static bool zap_gfn_range(struct kvm *kvm, struct kvm_mmu_page *root,
|
||||
gfn_t start, gfn_t end, bool can_yield, bool flush)
|
||||
static bool tdp_mmu_zap_leafs(struct kvm *kvm, struct kvm_mmu_page *root,
|
||||
gfn_t start, gfn_t end, bool can_yield, bool flush)
|
||||
{
|
||||
bool zap_all = (start == 0 && end >= tdp_mmu_max_gfn_host());
|
||||
struct tdp_iter iter;
|
||||
|
||||
/*
|
||||
* No need to try to step down in the iterator when zapping all SPTEs,
|
||||
* zapping the top-level non-leaf SPTEs will recurse on their children.
|
||||
*/
|
||||
int min_level = zap_all ? root->role.level : PG_LEVEL_4K;
|
||||
|
||||
end = min(end, tdp_mmu_max_gfn_host());
|
||||
|
||||
lockdep_assert_held_write(&kvm->mmu_lock);
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
for_each_tdp_pte_min_level(iter, root, min_level, start, end) {
|
||||
for_each_tdp_pte_min_level(iter, root, PG_LEVEL_4K, start, end) {
|
||||
if (can_yield &&
|
||||
tdp_mmu_iter_cond_resched(kvm, &iter, flush, false)) {
|
||||
flush = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!is_shadow_present_pte(iter.old_spte))
|
||||
continue;
|
||||
|
||||
/*
|
||||
* If this is a non-last-level SPTE that covers a larger range
|
||||
* than should be zapped, continue, and zap the mappings at a
|
||||
* lower level, except when zapping all SPTEs.
|
||||
*/
|
||||
if (!zap_all &&
|
||||
(iter.gfn < start ||
|
||||
iter.gfn + KVM_PAGES_PER_HPAGE(iter.level) > end) &&
|
||||
if (!is_shadow_present_pte(iter.old_spte) ||
|
||||
!is_last_spte(iter.old_spte, iter.level))
|
||||
continue;
|
||||
|
||||
@@ -960,17 +944,13 @@ static bool zap_gfn_range(struct kvm *kvm, struct kvm_mmu_page *root,
|
||||
flush = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Need to flush before releasing RCU. TODO: do it only if intermediate
|
||||
* page tables were zapped; there is no need to flush under RCU protection
|
||||
* if no 'struct kvm_mmu_page' is freed.
|
||||
*/
|
||||
if (flush)
|
||||
kvm_flush_remote_tlbs_with_address(kvm, start, end - start);
|
||||
|
||||
rcu_read_unlock();
|
||||
|
||||
return false;
|
||||
/*
|
||||
* Because this flow zaps _only_ leaf SPTEs, the caller doesn't need
|
||||
* to provide RCU protection as no 'struct kvm_mmu_page' will be freed.
|
||||
*/
|
||||
return flush;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -979,13 +959,13 @@ static bool zap_gfn_range(struct kvm *kvm, struct kvm_mmu_page *root,
|
||||
* SPTEs have been cleared and a TLB flush is needed before releasing the
|
||||
* MMU lock.
|
||||
*/
|
||||
bool __kvm_tdp_mmu_zap_gfn_range(struct kvm *kvm, int as_id, gfn_t start,
|
||||
gfn_t end, bool can_yield, bool flush)
|
||||
bool kvm_tdp_mmu_zap_leafs(struct kvm *kvm, int as_id, gfn_t start, gfn_t end,
|
||||
bool can_yield, bool flush)
|
||||
{
|
||||
struct kvm_mmu_page *root;
|
||||
|
||||
for_each_tdp_mmu_root_yield_safe(kvm, root, as_id)
|
||||
flush = zap_gfn_range(kvm, root, start, end, can_yield, flush);
|
||||
flush = tdp_mmu_zap_leafs(kvm, root, start, end, can_yield, flush);
|
||||
|
||||
return flush;
|
||||
}
|
||||
@@ -1233,8 +1213,8 @@ int kvm_tdp_mmu_map(struct kvm_vcpu *vcpu, struct kvm_page_fault *fault)
|
||||
bool kvm_tdp_mmu_unmap_gfn_range(struct kvm *kvm, struct kvm_gfn_range *range,
|
||||
bool flush)
|
||||
{
|
||||
return __kvm_tdp_mmu_zap_gfn_range(kvm, range->slot->as_id, range->start,
|
||||
range->end, range->may_block, flush);
|
||||
return kvm_tdp_mmu_zap_leafs(kvm, range->slot->as_id, range->start,
|
||||
range->end, range->may_block, flush);
|
||||
}
|
||||
|
||||
typedef bool (*tdp_handler_t)(struct kvm *kvm, struct tdp_iter *iter,
|
||||
|
||||
@@ -15,14 +15,8 @@ __must_check static inline bool kvm_tdp_mmu_get_root(struct kvm_mmu_page *root)
|
||||
void kvm_tdp_mmu_put_root(struct kvm *kvm, struct kvm_mmu_page *root,
|
||||
bool shared);
|
||||
|
||||
bool __kvm_tdp_mmu_zap_gfn_range(struct kvm *kvm, int as_id, gfn_t start,
|
||||
bool kvm_tdp_mmu_zap_leafs(struct kvm *kvm, int as_id, gfn_t start,
|
||||
gfn_t end, bool can_yield, bool flush);
|
||||
static inline bool kvm_tdp_mmu_zap_gfn_range(struct kvm *kvm, int as_id,
|
||||
gfn_t start, gfn_t end, bool flush)
|
||||
{
|
||||
return __kvm_tdp_mmu_zap_gfn_range(kvm, as_id, start, end, true, flush);
|
||||
}
|
||||
|
||||
bool kvm_tdp_mmu_zap_sp(struct kvm *kvm, struct kvm_mmu_page *sp);
|
||||
void kvm_tdp_mmu_zap_all(struct kvm *kvm);
|
||||
void kvm_tdp_mmu_invalidate_all_roots(struct kvm *kvm);
|
||||
@@ -72,7 +66,7 @@ u64 *kvm_tdp_mmu_fast_pf_get_last_sptep(struct kvm_vcpu *vcpu, u64 addr,
|
||||
u64 *spte);
|
||||
|
||||
#ifdef CONFIG_X86_64
|
||||
bool kvm_mmu_init_tdp_mmu(struct kvm *kvm);
|
||||
int kvm_mmu_init_tdp_mmu(struct kvm *kvm);
|
||||
void kvm_mmu_uninit_tdp_mmu(struct kvm *kvm);
|
||||
static inline bool is_tdp_mmu_page(struct kvm_mmu_page *sp) { return sp->tdp_mmu_page; }
|
||||
|
||||
@@ -93,7 +87,7 @@ static inline bool is_tdp_mmu(struct kvm_mmu *mmu)
|
||||
return sp && is_tdp_mmu_page(sp) && sp->root_count;
|
||||
}
|
||||
#else
|
||||
static inline bool kvm_mmu_init_tdp_mmu(struct kvm *kvm) { return false; }
|
||||
static inline int kvm_mmu_init_tdp_mmu(struct kvm *kvm) { return 0; }
|
||||
static inline void kvm_mmu_uninit_tdp_mmu(struct kvm *kvm) {}
|
||||
static inline bool is_tdp_mmu_page(struct kvm_mmu_page *sp) { return false; }
|
||||
static inline bool is_tdp_mmu(struct kvm_mmu *mmu) { return false; }
|
||||
|
||||
+7
-11
@@ -96,8 +96,7 @@ static void kvm_perf_overflow(struct perf_event *perf_event,
|
||||
|
||||
static void pmc_reprogram_counter(struct kvm_pmc *pmc, u32 type,
|
||||
u64 config, bool exclude_user,
|
||||
bool exclude_kernel, bool intr,
|
||||
bool in_tx, bool in_tx_cp)
|
||||
bool exclude_kernel, bool intr)
|
||||
{
|
||||
struct perf_event *event;
|
||||
struct perf_event_attr attr = {
|
||||
@@ -116,16 +115,14 @@ static void pmc_reprogram_counter(struct kvm_pmc *pmc, u32 type,
|
||||
|
||||
attr.sample_period = get_sample_period(pmc, pmc->counter);
|
||||
|
||||
if (in_tx)
|
||||
attr.config |= HSW_IN_TX;
|
||||
if (in_tx_cp) {
|
||||
if ((attr.config & HSW_IN_TX_CHECKPOINTED) &&
|
||||
guest_cpuid_is_intel(pmc->vcpu)) {
|
||||
/*
|
||||
* HSW_IN_TX_CHECKPOINTED is not supported with nonzero
|
||||
* period. Just clear the sample period so at least
|
||||
* allocating the counter doesn't fail.
|
||||
*/
|
||||
attr.sample_period = 0;
|
||||
attr.config |= HSW_IN_TX_CHECKPOINTED;
|
||||
}
|
||||
|
||||
event = perf_event_create_kernel_counter(&attr, -1, current,
|
||||
@@ -185,6 +182,7 @@ void reprogram_gp_counter(struct kvm_pmc *pmc, u64 eventsel)
|
||||
u32 type = PERF_TYPE_RAW;
|
||||
struct kvm *kvm = pmc->vcpu->kvm;
|
||||
struct kvm_pmu_event_filter *filter;
|
||||
struct kvm_pmu *pmu = vcpu_to_pmu(pmc->vcpu);
|
||||
bool allow_event = true;
|
||||
|
||||
if (eventsel & ARCH_PERFMON_EVENTSEL_PIN_CONTROL)
|
||||
@@ -221,7 +219,7 @@ void reprogram_gp_counter(struct kvm_pmc *pmc, u64 eventsel)
|
||||
}
|
||||
|
||||
if (type == PERF_TYPE_RAW)
|
||||
config = eventsel & AMD64_RAW_EVENT_MASK;
|
||||
config = eventsel & pmu->raw_event_mask;
|
||||
|
||||
if (pmc->current_config == eventsel && pmc_resume_counter(pmc))
|
||||
return;
|
||||
@@ -232,9 +230,7 @@ void reprogram_gp_counter(struct kvm_pmc *pmc, u64 eventsel)
|
||||
pmc_reprogram_counter(pmc, type, config,
|
||||
!(eventsel & ARCH_PERFMON_EVENTSEL_USR),
|
||||
!(eventsel & ARCH_PERFMON_EVENTSEL_OS),
|
||||
eventsel & ARCH_PERFMON_EVENTSEL_INT,
|
||||
(eventsel & HSW_IN_TX),
|
||||
(eventsel & HSW_IN_TX_CHECKPOINTED));
|
||||
eventsel & ARCH_PERFMON_EVENTSEL_INT);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(reprogram_gp_counter);
|
||||
|
||||
@@ -270,7 +266,7 @@ void reprogram_fixed_counter(struct kvm_pmc *pmc, u8 ctrl, int idx)
|
||||
kvm_x86_ops.pmu_ops->pmc_perf_hw_id(pmc),
|
||||
!(en_field & 0x2), /* exclude user */
|
||||
!(en_field & 0x1), /* exclude kernel */
|
||||
pmi, false, false);
|
||||
pmi);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(reprogram_fixed_counter);
|
||||
|
||||
|
||||
+10
-4
@@ -726,7 +726,7 @@ int avic_pi_update_irte(struct kvm *kvm, unsigned int host_irq,
|
||||
{
|
||||
struct kvm_kernel_irq_routing_entry *e;
|
||||
struct kvm_irq_routing_table *irq_rt;
|
||||
int idx, ret = -EINVAL;
|
||||
int idx, ret = 0;
|
||||
|
||||
if (!kvm_arch_has_assigned_device(kvm) ||
|
||||
!irq_remapping_cap(IRQ_POSTING_CAP))
|
||||
@@ -737,7 +737,13 @@ int avic_pi_update_irte(struct kvm *kvm, unsigned int host_irq,
|
||||
|
||||
idx = srcu_read_lock(&kvm->irq_srcu);
|
||||
irq_rt = srcu_dereference(kvm->irq_routing, &kvm->irq_srcu);
|
||||
WARN_ON(guest_irq >= irq_rt->nr_rt_entries);
|
||||
|
||||
if (guest_irq >= irq_rt->nr_rt_entries ||
|
||||
hlist_empty(&irq_rt->map[guest_irq])) {
|
||||
pr_warn_once("no route for guest_irq %u/%u (broken user space?)\n",
|
||||
guest_irq, irq_rt->nr_rt_entries);
|
||||
goto out;
|
||||
}
|
||||
|
||||
hlist_for_each_entry(e, &irq_rt->map[guest_irq], link) {
|
||||
struct vcpu_data vcpu_info;
|
||||
@@ -822,7 +828,7 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool avic_check_apicv_inhibit_reasons(ulong bit)
|
||||
bool avic_check_apicv_inhibit_reasons(enum kvm_apicv_inhibit reason)
|
||||
{
|
||||
ulong supported = BIT(APICV_INHIBIT_REASON_DISABLE) |
|
||||
BIT(APICV_INHIBIT_REASON_ABSENT) |
|
||||
@@ -833,7 +839,7 @@ bool avic_check_apicv_inhibit_reasons(ulong bit)
|
||||
BIT(APICV_INHIBIT_REASON_X2APIC) |
|
||||
BIT(APICV_INHIBIT_REASON_BLOCKIRQ);
|
||||
|
||||
return supported & BIT(bit);
|
||||
return supported & BIT(reason);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -262,12 +262,10 @@ static int amd_pmu_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
|
||||
/* MSR_EVNTSELn */
|
||||
pmc = get_gp_pmc_amd(pmu, msr, PMU_TYPE_EVNTSEL);
|
||||
if (pmc) {
|
||||
if (data == pmc->eventsel)
|
||||
return 0;
|
||||
if (!(data & pmu->reserved_bits)) {
|
||||
data &= ~pmu->reserved_bits;
|
||||
if (data != pmc->eventsel)
|
||||
reprogram_gp_counter(pmc, data);
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
@@ -284,6 +282,7 @@ static void amd_pmu_refresh(struct kvm_vcpu *vcpu)
|
||||
|
||||
pmu->counter_bitmask[KVM_PMC_GP] = ((u64)1 << 48) - 1;
|
||||
pmu->reserved_bits = 0xfffffff000280000ull;
|
||||
pmu->raw_event_mask = AMD64_RAW_EVENT_MASK;
|
||||
pmu->version = 1;
|
||||
/* not applicable to AMD; but clean them to prevent any fall out */
|
||||
pmu->counter_bitmask[KVM_PMC_FIXED] = 0;
|
||||
|
||||
+11
-25
@@ -62,20 +62,8 @@ MODULE_DEVICE_TABLE(x86cpu, svm_cpu_id);
|
||||
#define SEG_TYPE_LDT 2
|
||||
#define SEG_TYPE_BUSY_TSS16 3
|
||||
|
||||
#define SVM_FEATURE_LBRV (1 << 1)
|
||||
#define SVM_FEATURE_SVML (1 << 2)
|
||||
#define SVM_FEATURE_TSC_RATE (1 << 4)
|
||||
#define SVM_FEATURE_VMCB_CLEAN (1 << 5)
|
||||
#define SVM_FEATURE_FLUSH_ASID (1 << 6)
|
||||
#define SVM_FEATURE_DECODE_ASSIST (1 << 7)
|
||||
#define SVM_FEATURE_PAUSE_FILTER (1 << 10)
|
||||
|
||||
#define DEBUGCTL_RESERVED_BITS (~(0x3fULL))
|
||||
|
||||
#define TSC_RATIO_RSVD 0xffffff0000000000ULL
|
||||
#define TSC_RATIO_MIN 0x0000000000000001ULL
|
||||
#define TSC_RATIO_MAX 0x000000ffffffffffULL
|
||||
|
||||
static bool erratum_383_found __read_mostly;
|
||||
|
||||
u32 msrpm_offsets[MSRPM_OFFSETS] __read_mostly;
|
||||
@@ -87,7 +75,6 @@ u32 msrpm_offsets[MSRPM_OFFSETS] __read_mostly;
|
||||
static uint64_t osvw_len = 4, osvw_status;
|
||||
|
||||
static DEFINE_PER_CPU(u64, current_tsc_ratio);
|
||||
#define TSC_RATIO_DEFAULT 0x0100000000ULL
|
||||
|
||||
static const struct svm_direct_access_msrs {
|
||||
u32 index; /* Index of the MSR */
|
||||
@@ -480,7 +467,7 @@ static void svm_hardware_disable(void)
|
||||
{
|
||||
/* Make sure we clean up behind us */
|
||||
if (tsc_scaling)
|
||||
wrmsrl(MSR_AMD64_TSC_RATIO, TSC_RATIO_DEFAULT);
|
||||
wrmsrl(MSR_AMD64_TSC_RATIO, SVM_TSC_RATIO_DEFAULT);
|
||||
|
||||
cpu_svm_disable();
|
||||
|
||||
@@ -526,8 +513,8 @@ static int svm_hardware_enable(void)
|
||||
* Set the default value, even if we don't use TSC scaling
|
||||
* to avoid having stale value in the msr
|
||||
*/
|
||||
wrmsrl(MSR_AMD64_TSC_RATIO, TSC_RATIO_DEFAULT);
|
||||
__this_cpu_write(current_tsc_ratio, TSC_RATIO_DEFAULT);
|
||||
wrmsrl(MSR_AMD64_TSC_RATIO, SVM_TSC_RATIO_DEFAULT);
|
||||
__this_cpu_write(current_tsc_ratio, SVM_TSC_RATIO_DEFAULT);
|
||||
}
|
||||
|
||||
|
||||
@@ -2723,7 +2710,7 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr)
|
||||
break;
|
||||
}
|
||||
|
||||
if (data & TSC_RATIO_RSVD)
|
||||
if (data & SVM_TSC_RATIO_RSVD)
|
||||
return 1;
|
||||
|
||||
svm->tsc_ratio_msr = data;
|
||||
@@ -2918,7 +2905,7 @@ static int interrupt_window_interception(struct kvm_vcpu *vcpu)
|
||||
* In this case AVIC was temporarily disabled for
|
||||
* requesting the IRQ window and we have to re-enable it.
|
||||
*/
|
||||
kvm_request_apicv_update(vcpu->kvm, true, APICV_INHIBIT_REASON_IRQWIN);
|
||||
kvm_clear_apicv_inhibit(vcpu->kvm, APICV_INHIBIT_REASON_IRQWIN);
|
||||
|
||||
++vcpu->stat.irq_window_exits;
|
||||
return 1;
|
||||
@@ -3516,7 +3503,7 @@ static void svm_enable_irq_window(struct kvm_vcpu *vcpu)
|
||||
* via AVIC. In such case, we need to temporarily disable AVIC,
|
||||
* and fallback to injecting IRQ via V_IRQ.
|
||||
*/
|
||||
kvm_request_apicv_update(vcpu->kvm, false, APICV_INHIBIT_REASON_IRQWIN);
|
||||
kvm_set_apicv_inhibit(vcpu->kvm, APICV_INHIBIT_REASON_IRQWIN);
|
||||
svm_set_vintr(svm);
|
||||
}
|
||||
}
|
||||
@@ -3948,6 +3935,7 @@ static void svm_vcpu_after_set_cpuid(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
struct vcpu_svm *svm = to_svm(vcpu);
|
||||
struct kvm_cpuid_entry2 *best;
|
||||
struct kvm *kvm = vcpu->kvm;
|
||||
|
||||
vcpu->arch.xsaves_enabled = guest_cpuid_has(vcpu, X86_FEATURE_XSAVE) &&
|
||||
boot_cpu_has(X86_FEATURE_XSAVE) &&
|
||||
@@ -3974,16 +3962,14 @@ static void svm_vcpu_after_set_cpuid(struct kvm_vcpu *vcpu)
|
||||
* is exposed to the guest, disable AVIC.
|
||||
*/
|
||||
if (guest_cpuid_has(vcpu, X86_FEATURE_X2APIC))
|
||||
kvm_request_apicv_update(vcpu->kvm, false,
|
||||
APICV_INHIBIT_REASON_X2APIC);
|
||||
kvm_set_apicv_inhibit(kvm, APICV_INHIBIT_REASON_X2APIC);
|
||||
|
||||
/*
|
||||
* Currently, AVIC does not work with nested virtualization.
|
||||
* So, we disable AVIC when cpuid for SVM is set in the L1 guest.
|
||||
*/
|
||||
if (nested && guest_cpuid_has(vcpu, X86_FEATURE_SVM))
|
||||
kvm_request_apicv_update(vcpu->kvm, false,
|
||||
APICV_INHIBIT_REASON_NESTED);
|
||||
kvm_set_apicv_inhibit(kvm, APICV_INHIBIT_REASON_NESTED);
|
||||
}
|
||||
init_vmcb_after_set_cpuid(vcpu);
|
||||
}
|
||||
@@ -4766,10 +4752,10 @@ static __init int svm_hardware_setup(void)
|
||||
} else {
|
||||
pr_info("TSC scaling supported\n");
|
||||
kvm_has_tsc_control = true;
|
||||
kvm_max_tsc_scaling_ratio = TSC_RATIO_MAX;
|
||||
kvm_tsc_scaling_ratio_frac_bits = 32;
|
||||
}
|
||||
}
|
||||
kvm_max_tsc_scaling_ratio = SVM_TSC_RATIO_MAX;
|
||||
kvm_tsc_scaling_ratio_frac_bits = 32;
|
||||
|
||||
tsc_aux_uret_slot = kvm_add_user_return_msr(MSR_TSC_AUX);
|
||||
|
||||
|
||||
+3
-12
@@ -22,6 +22,8 @@
|
||||
#include <asm/svm.h>
|
||||
#include <asm/sev-common.h>
|
||||
|
||||
#include "kvm_cache_regs.h"
|
||||
|
||||
#define __sme_page_pa(x) __sme_set(page_to_pfn(x) << PAGE_SHIFT)
|
||||
|
||||
#define IOPM_SIZE PAGE_SIZE * 3
|
||||
@@ -569,17 +571,6 @@ extern struct kvm_x86_nested_ops svm_nested_ops;
|
||||
|
||||
/* avic.c */
|
||||
|
||||
#define AVIC_LOGICAL_ID_ENTRY_GUEST_PHYSICAL_ID_MASK (0xFF)
|
||||
#define AVIC_LOGICAL_ID_ENTRY_VALID_BIT 31
|
||||
#define AVIC_LOGICAL_ID_ENTRY_VALID_MASK (1 << 31)
|
||||
|
||||
#define AVIC_PHYSICAL_ID_ENTRY_HOST_PHYSICAL_ID_MASK GENMASK_ULL(11, 0)
|
||||
#define AVIC_PHYSICAL_ID_ENTRY_BACKING_PAGE_MASK (0xFFFFFFFFFFULL << 12)
|
||||
#define AVIC_PHYSICAL_ID_ENTRY_IS_RUNNING_MASK (1ULL << 62)
|
||||
#define AVIC_PHYSICAL_ID_ENTRY_VALID_MASK (1ULL << 63)
|
||||
|
||||
#define VMCB_AVIC_APIC_BAR_MASK 0xFFFFFFFFFF000ULL
|
||||
|
||||
int avic_ga_log_notifier(u32 ga_tag);
|
||||
void avic_vm_destroy(struct kvm *kvm);
|
||||
int avic_vm_init(struct kvm *kvm);
|
||||
@@ -592,7 +583,7 @@ void __avic_vcpu_put(struct kvm_vcpu *vcpu);
|
||||
void avic_apicv_post_state_restore(struct kvm_vcpu *vcpu);
|
||||
void avic_set_virtual_apic_mode(struct kvm_vcpu *vcpu);
|
||||
void avic_refresh_apicv_exec_ctrl(struct kvm_vcpu *vcpu);
|
||||
bool avic_check_apicv_inhibit_reasons(ulong bit);
|
||||
bool avic_check_apicv_inhibit_reasons(enum kvm_apicv_inhibit reason);
|
||||
void avic_hwapic_irr_update(struct kvm_vcpu *vcpu, int max_irr);
|
||||
void avic_hwapic_isr_update(struct kvm_vcpu *vcpu, int max_isr);
|
||||
bool avic_dy_apicv_has_pending_interrupt(struct kvm_vcpu *vcpu);
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
*/
|
||||
|
||||
#include <linux/kvm_host.h>
|
||||
#include "kvm_cache_regs.h"
|
||||
|
||||
#include <asm/mshyperv.h>
|
||||
|
||||
|
||||
+12
-10
@@ -1339,23 +1339,25 @@ TRACE_EVENT(kvm_hv_stimer_cleanup,
|
||||
__entry->vcpu_id, __entry->timer_index)
|
||||
);
|
||||
|
||||
TRACE_EVENT(kvm_apicv_update_request,
|
||||
TP_PROTO(bool activate, unsigned long bit),
|
||||
TP_ARGS(activate, bit),
|
||||
TRACE_EVENT(kvm_apicv_inhibit_changed,
|
||||
TP_PROTO(int reason, bool set, unsigned long inhibits),
|
||||
TP_ARGS(reason, set, inhibits),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(bool, activate)
|
||||
__field(unsigned long, bit)
|
||||
__field(int, reason)
|
||||
__field(bool, set)
|
||||
__field(unsigned long, inhibits)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->activate = activate;
|
||||
__entry->bit = bit;
|
||||
__entry->reason = reason;
|
||||
__entry->set = set;
|
||||
__entry->inhibits = inhibits;
|
||||
),
|
||||
|
||||
TP_printk("%s bit=%lu",
|
||||
__entry->activate ? "activate" : "deactivate",
|
||||
__entry->bit)
|
||||
TP_printk("%s reason=%u, inhibits=0x%lx",
|
||||
__entry->set ? "set" : "cleared",
|
||||
__entry->reason, __entry->inhibits)
|
||||
);
|
||||
|
||||
TRACE_EVENT(kvm_apicv_accept_irq,
|
||||
|
||||
@@ -389,6 +389,7 @@ static int intel_pmu_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
|
||||
struct kvm_pmc *pmc;
|
||||
u32 msr = msr_info->index;
|
||||
u64 data = msr_info->data;
|
||||
u64 reserved_bits;
|
||||
|
||||
switch (msr) {
|
||||
case MSR_CORE_PERF_FIXED_CTR_CTRL:
|
||||
@@ -443,7 +444,11 @@ static int intel_pmu_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
|
||||
} else if ((pmc = get_gp_pmc(pmu, msr, MSR_P6_EVNTSEL0))) {
|
||||
if (data == pmc->eventsel)
|
||||
return 0;
|
||||
if (!(data & pmu->reserved_bits)) {
|
||||
reserved_bits = pmu->reserved_bits;
|
||||
if ((pmc->idx == 2) &&
|
||||
(pmu->raw_event_mask & HSW_IN_TX_CHECKPOINTED))
|
||||
reserved_bits ^= HSW_IN_TX_CHECKPOINTED;
|
||||
if (!(data & reserved_bits)) {
|
||||
reprogram_gp_counter(pmc, data);
|
||||
return 0;
|
||||
}
|
||||
@@ -485,6 +490,7 @@ static void intel_pmu_refresh(struct kvm_vcpu *vcpu)
|
||||
pmu->counter_bitmask[KVM_PMC_FIXED] = 0;
|
||||
pmu->version = 0;
|
||||
pmu->reserved_bits = 0xffffffff00200000ull;
|
||||
pmu->raw_event_mask = X86_RAW_EVENT_MASK;
|
||||
|
||||
entry = kvm_find_cpuid_entry(vcpu, 0xa, 0);
|
||||
if (!entry || !vcpu->kvm->arch.enable_pmu)
|
||||
@@ -533,8 +539,10 @@ static void intel_pmu_refresh(struct kvm_vcpu *vcpu)
|
||||
entry = kvm_find_cpuid_entry(vcpu, 7, 0);
|
||||
if (entry &&
|
||||
(boot_cpu_has(X86_FEATURE_HLE) || boot_cpu_has(X86_FEATURE_RTM)) &&
|
||||
(entry->ebx & (X86_FEATURE_HLE|X86_FEATURE_RTM)))
|
||||
pmu->reserved_bits ^= HSW_IN_TX|HSW_IN_TX_CHECKPOINTED;
|
||||
(entry->ebx & (X86_FEATURE_HLE|X86_FEATURE_RTM))) {
|
||||
pmu->reserved_bits ^= HSW_IN_TX;
|
||||
pmu->raw_event_mask |= (HSW_IN_TX|HSW_IN_TX_CHECKPOINTED);
|
||||
}
|
||||
|
||||
bitmap_set(pmu->all_valid_pmc_idx,
|
||||
0, pmu->nr_arch_gp_counters);
|
||||
|
||||
+10
-16
@@ -2866,21 +2866,17 @@ static void enter_rmode(struct kvm_vcpu *vcpu)
|
||||
int vmx_set_efer(struct kvm_vcpu *vcpu, u64 efer)
|
||||
{
|
||||
struct vcpu_vmx *vmx = to_vmx(vcpu);
|
||||
struct vmx_uret_msr *msr = vmx_find_uret_msr(vmx, MSR_EFER);
|
||||
|
||||
/* Nothing to do if hardware doesn't support EFER. */
|
||||
if (!msr)
|
||||
if (!vmx_find_uret_msr(vmx, MSR_EFER))
|
||||
return 0;
|
||||
|
||||
vcpu->arch.efer = efer;
|
||||
if (efer & EFER_LMA) {
|
||||
vm_entry_controls_setbit(to_vmx(vcpu), VM_ENTRY_IA32E_MODE);
|
||||
msr->data = efer;
|
||||
} else {
|
||||
vm_entry_controls_clearbit(to_vmx(vcpu), VM_ENTRY_IA32E_MODE);
|
||||
if (efer & EFER_LMA)
|
||||
vm_entry_controls_setbit(vmx, VM_ENTRY_IA32E_MODE);
|
||||
else
|
||||
vm_entry_controls_clearbit(vmx, VM_ENTRY_IA32E_MODE);
|
||||
|
||||
msr->data = efer & ~EFER_LME;
|
||||
}
|
||||
vmx_setup_uret_msrs(vmx);
|
||||
return 0;
|
||||
}
|
||||
@@ -2906,7 +2902,6 @@ static void enter_lmode(struct kvm_vcpu *vcpu)
|
||||
|
||||
static void exit_lmode(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
vm_entry_controls_clearbit(to_vmx(vcpu), VM_ENTRY_IA32E_MODE);
|
||||
vmx_set_efer(vcpu, vcpu->arch.efer & ~EFER_LMA);
|
||||
}
|
||||
|
||||
@@ -7705,14 +7700,14 @@ static void vmx_hardware_unsetup(void)
|
||||
free_kvm_area();
|
||||
}
|
||||
|
||||
static bool vmx_check_apicv_inhibit_reasons(ulong bit)
|
||||
static bool vmx_check_apicv_inhibit_reasons(enum kvm_apicv_inhibit reason)
|
||||
{
|
||||
ulong supported = BIT(APICV_INHIBIT_REASON_DISABLE) |
|
||||
BIT(APICV_INHIBIT_REASON_ABSENT) |
|
||||
BIT(APICV_INHIBIT_REASON_HYPERV) |
|
||||
BIT(APICV_INHIBIT_REASON_BLOCKIRQ);
|
||||
|
||||
return supported & BIT(bit);
|
||||
return supported & BIT(reason);
|
||||
}
|
||||
|
||||
static struct kvm_x86_ops vmx_x86_ops __initdata = {
|
||||
@@ -7980,12 +7975,11 @@ static __init int hardware_setup(void)
|
||||
if (!enable_apicv)
|
||||
vmx_x86_ops.sync_pir_to_irr = NULL;
|
||||
|
||||
if (cpu_has_vmx_tsc_scaling()) {
|
||||
if (cpu_has_vmx_tsc_scaling())
|
||||
kvm_has_tsc_control = true;
|
||||
kvm_max_tsc_scaling_ratio = KVM_VMX_TSC_MULTIPLIER_MAX;
|
||||
kvm_tsc_scaling_ratio_frac_bits = 48;
|
||||
}
|
||||
|
||||
kvm_max_tsc_scaling_ratio = KVM_VMX_TSC_MULTIPLIER_MAX;
|
||||
kvm_tsc_scaling_ratio_frac_bits = 48;
|
||||
kvm_has_bus_lock_exit = cpu_has_vmx_bus_lock_detection();
|
||||
|
||||
set_bit(0, vmx_vpid_bitmap); /* 0 is reserved for host */
|
||||
|
||||
+104
-57
@@ -1748,9 +1748,6 @@ static int __kvm_set_msr(struct kvm_vcpu *vcpu, u32 index, u64 data,
|
||||
{
|
||||
struct msr_data msr;
|
||||
|
||||
if (!host_initiated && !kvm_msr_allowed(vcpu, index, KVM_MSR_FILTER_WRITE))
|
||||
return KVM_MSR_RET_FILTERED;
|
||||
|
||||
switch (index) {
|
||||
case MSR_FS_BASE:
|
||||
case MSR_GS_BASE:
|
||||
@@ -1832,9 +1829,6 @@ int __kvm_get_msr(struct kvm_vcpu *vcpu, u32 index, u64 *data,
|
||||
struct msr_data msr;
|
||||
int ret;
|
||||
|
||||
if (!host_initiated && !kvm_msr_allowed(vcpu, index, KVM_MSR_FILTER_READ))
|
||||
return KVM_MSR_RET_FILTERED;
|
||||
|
||||
switch (index) {
|
||||
case MSR_TSC_AUX:
|
||||
if (!kvm_is_supported_user_return_msr(MSR_TSC_AUX))
|
||||
@@ -1871,6 +1865,20 @@ static int kvm_get_msr_ignored_check(struct kvm_vcpu *vcpu,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int kvm_get_msr_with_filter(struct kvm_vcpu *vcpu, u32 index, u64 *data)
|
||||
{
|
||||
if (!kvm_msr_allowed(vcpu, index, KVM_MSR_FILTER_READ))
|
||||
return KVM_MSR_RET_FILTERED;
|
||||
return kvm_get_msr_ignored_check(vcpu, index, data, false);
|
||||
}
|
||||
|
||||
static int kvm_set_msr_with_filter(struct kvm_vcpu *vcpu, u32 index, u64 data)
|
||||
{
|
||||
if (!kvm_msr_allowed(vcpu, index, KVM_MSR_FILTER_WRITE))
|
||||
return KVM_MSR_RET_FILTERED;
|
||||
return kvm_set_msr_ignored_check(vcpu, index, data, false);
|
||||
}
|
||||
|
||||
int kvm_get_msr(struct kvm_vcpu *vcpu, u32 index, u64 *data)
|
||||
{
|
||||
return kvm_get_msr_ignored_check(vcpu, index, data, false);
|
||||
@@ -1953,7 +1961,7 @@ int kvm_emulate_rdmsr(struct kvm_vcpu *vcpu)
|
||||
u64 data;
|
||||
int r;
|
||||
|
||||
r = kvm_get_msr(vcpu, ecx, &data);
|
||||
r = kvm_get_msr_with_filter(vcpu, ecx, &data);
|
||||
|
||||
if (!r) {
|
||||
trace_kvm_msr_read(ecx, data);
|
||||
@@ -1978,7 +1986,7 @@ int kvm_emulate_wrmsr(struct kvm_vcpu *vcpu)
|
||||
u64 data = kvm_read_edx_eax(vcpu);
|
||||
int r;
|
||||
|
||||
r = kvm_set_msr(vcpu, ecx, data);
|
||||
r = kvm_set_msr_with_filter(vcpu, ecx, data);
|
||||
|
||||
if (!r) {
|
||||
trace_kvm_msr_write(ecx, data);
|
||||
@@ -5938,7 +5946,7 @@ int kvm_vm_ioctl_enable_cap(struct kvm *kvm,
|
||||
smp_wmb();
|
||||
kvm->arch.irqchip_mode = KVM_IRQCHIP_SPLIT;
|
||||
kvm->arch.nr_reserved_ioapic_pins = cap->args[0];
|
||||
kvm_request_apicv_update(kvm, true, APICV_INHIBIT_REASON_ABSENT);
|
||||
kvm_clear_apicv_inhibit(kvm, APICV_INHIBIT_REASON_ABSENT);
|
||||
r = 0;
|
||||
split_irqchip_unlock:
|
||||
mutex_unlock(&kvm->lock);
|
||||
@@ -6335,7 +6343,7 @@ set_identity_unlock:
|
||||
/* Write kvm->irq_routing before enabling irqchip_in_kernel. */
|
||||
smp_wmb();
|
||||
kvm->arch.irqchip_mode = KVM_IRQCHIP_KERNEL;
|
||||
kvm_request_apicv_update(kvm, true, APICV_INHIBIT_REASON_ABSENT);
|
||||
kvm_clear_apicv_inhibit(kvm, APICV_INHIBIT_REASON_ABSENT);
|
||||
create_irqchip_unlock:
|
||||
mutex_unlock(&kvm->lock);
|
||||
break;
|
||||
@@ -6726,7 +6734,7 @@ void kvm_get_segment(struct kvm_vcpu *vcpu,
|
||||
static_call(kvm_x86_get_segment)(vcpu, var, seg);
|
||||
}
|
||||
|
||||
gpa_t translate_nested_gpa(struct kvm_vcpu *vcpu, gpa_t gpa, u32 access,
|
||||
gpa_t translate_nested_gpa(struct kvm_vcpu *vcpu, gpa_t gpa, u64 access,
|
||||
struct x86_exception *exception)
|
||||
{
|
||||
struct kvm_mmu *mmu = vcpu->arch.mmu;
|
||||
@@ -6746,7 +6754,7 @@ gpa_t kvm_mmu_gva_to_gpa_read(struct kvm_vcpu *vcpu, gva_t gva,
|
||||
{
|
||||
struct kvm_mmu *mmu = vcpu->arch.walk_mmu;
|
||||
|
||||
u32 access = (static_call(kvm_x86_get_cpl)(vcpu) == 3) ? PFERR_USER_MASK : 0;
|
||||
u64 access = (static_call(kvm_x86_get_cpl)(vcpu) == 3) ? PFERR_USER_MASK : 0;
|
||||
return mmu->gva_to_gpa(vcpu, mmu, gva, access, exception);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(kvm_mmu_gva_to_gpa_read);
|
||||
@@ -6756,7 +6764,7 @@ EXPORT_SYMBOL_GPL(kvm_mmu_gva_to_gpa_read);
|
||||
{
|
||||
struct kvm_mmu *mmu = vcpu->arch.walk_mmu;
|
||||
|
||||
u32 access = (static_call(kvm_x86_get_cpl)(vcpu) == 3) ? PFERR_USER_MASK : 0;
|
||||
u64 access = (static_call(kvm_x86_get_cpl)(vcpu) == 3) ? PFERR_USER_MASK : 0;
|
||||
access |= PFERR_FETCH_MASK;
|
||||
return mmu->gva_to_gpa(vcpu, mmu, gva, access, exception);
|
||||
}
|
||||
@@ -6766,7 +6774,7 @@ gpa_t kvm_mmu_gva_to_gpa_write(struct kvm_vcpu *vcpu, gva_t gva,
|
||||
{
|
||||
struct kvm_mmu *mmu = vcpu->arch.walk_mmu;
|
||||
|
||||
u32 access = (static_call(kvm_x86_get_cpl)(vcpu) == 3) ? PFERR_USER_MASK : 0;
|
||||
u64 access = (static_call(kvm_x86_get_cpl)(vcpu) == 3) ? PFERR_USER_MASK : 0;
|
||||
access |= PFERR_WRITE_MASK;
|
||||
return mmu->gva_to_gpa(vcpu, mmu, gva, access, exception);
|
||||
}
|
||||
@@ -6782,7 +6790,7 @@ gpa_t kvm_mmu_gva_to_gpa_system(struct kvm_vcpu *vcpu, gva_t gva,
|
||||
}
|
||||
|
||||
static int kvm_read_guest_virt_helper(gva_t addr, void *val, unsigned int bytes,
|
||||
struct kvm_vcpu *vcpu, u32 access,
|
||||
struct kvm_vcpu *vcpu, u64 access,
|
||||
struct x86_exception *exception)
|
||||
{
|
||||
struct kvm_mmu *mmu = vcpu->arch.walk_mmu;
|
||||
@@ -6819,7 +6827,7 @@ static int kvm_fetch_guest_virt(struct x86_emulate_ctxt *ctxt,
|
||||
{
|
||||
struct kvm_vcpu *vcpu = emul_to_vcpu(ctxt);
|
||||
struct kvm_mmu *mmu = vcpu->arch.walk_mmu;
|
||||
u32 access = (static_call(kvm_x86_get_cpl)(vcpu) == 3) ? PFERR_USER_MASK : 0;
|
||||
u64 access = (static_call(kvm_x86_get_cpl)(vcpu) == 3) ? PFERR_USER_MASK : 0;
|
||||
unsigned offset;
|
||||
int ret;
|
||||
|
||||
@@ -6844,7 +6852,7 @@ int kvm_read_guest_virt(struct kvm_vcpu *vcpu,
|
||||
gva_t addr, void *val, unsigned int bytes,
|
||||
struct x86_exception *exception)
|
||||
{
|
||||
u32 access = (static_call(kvm_x86_get_cpl)(vcpu) == 3) ? PFERR_USER_MASK : 0;
|
||||
u64 access = (static_call(kvm_x86_get_cpl)(vcpu) == 3) ? PFERR_USER_MASK : 0;
|
||||
|
||||
/*
|
||||
* FIXME: this should call handle_emulation_failure if X86EMUL_IO_NEEDED
|
||||
@@ -6863,9 +6871,11 @@ static int emulator_read_std(struct x86_emulate_ctxt *ctxt,
|
||||
struct x86_exception *exception, bool system)
|
||||
{
|
||||
struct kvm_vcpu *vcpu = emul_to_vcpu(ctxt);
|
||||
u32 access = 0;
|
||||
u64 access = 0;
|
||||
|
||||
if (!system && static_call(kvm_x86_get_cpl)(vcpu) == 3)
|
||||
if (system)
|
||||
access |= PFERR_IMPLICIT_ACCESS;
|
||||
else if (static_call(kvm_x86_get_cpl)(vcpu) == 3)
|
||||
access |= PFERR_USER_MASK;
|
||||
|
||||
return kvm_read_guest_virt_helper(addr, val, bytes, vcpu, access, exception);
|
||||
@@ -6881,7 +6891,7 @@ static int kvm_read_guest_phys_system(struct x86_emulate_ctxt *ctxt,
|
||||
}
|
||||
|
||||
static int kvm_write_guest_virt_helper(gva_t addr, void *val, unsigned int bytes,
|
||||
struct kvm_vcpu *vcpu, u32 access,
|
||||
struct kvm_vcpu *vcpu, u64 access,
|
||||
struct x86_exception *exception)
|
||||
{
|
||||
struct kvm_mmu *mmu = vcpu->arch.walk_mmu;
|
||||
@@ -6915,9 +6925,11 @@ static int emulator_write_std(struct x86_emulate_ctxt *ctxt, gva_t addr, void *v
|
||||
bool system)
|
||||
{
|
||||
struct kvm_vcpu *vcpu = emul_to_vcpu(ctxt);
|
||||
u32 access = PFERR_WRITE_MASK;
|
||||
u64 access = PFERR_WRITE_MASK;
|
||||
|
||||
if (!system && static_call(kvm_x86_get_cpl)(vcpu) == 3)
|
||||
if (system)
|
||||
access |= PFERR_IMPLICIT_ACCESS;
|
||||
else if (static_call(kvm_x86_get_cpl)(vcpu) == 3)
|
||||
access |= PFERR_USER_MASK;
|
||||
|
||||
return kvm_write_guest_virt_helper(addr, val, bytes, vcpu,
|
||||
@@ -6984,7 +6996,7 @@ static int vcpu_mmio_gva_to_gpa(struct kvm_vcpu *vcpu, unsigned long gva,
|
||||
bool write)
|
||||
{
|
||||
struct kvm_mmu *mmu = vcpu->arch.walk_mmu;
|
||||
u32 access = ((static_call(kvm_x86_get_cpl)(vcpu) == 3) ? PFERR_USER_MASK : 0)
|
||||
u64 access = ((static_call(kvm_x86_get_cpl)(vcpu) == 3) ? PFERR_USER_MASK : 0)
|
||||
| (write ? PFERR_WRITE_MASK : 0);
|
||||
|
||||
/*
|
||||
@@ -7627,13 +7639,13 @@ static void emulator_set_segment(struct x86_emulate_ctxt *ctxt, u16 selector,
|
||||
return;
|
||||
}
|
||||
|
||||
static int emulator_get_msr(struct x86_emulate_ctxt *ctxt,
|
||||
u32 msr_index, u64 *pdata)
|
||||
static int emulator_get_msr_with_filter(struct x86_emulate_ctxt *ctxt,
|
||||
u32 msr_index, u64 *pdata)
|
||||
{
|
||||
struct kvm_vcpu *vcpu = emul_to_vcpu(ctxt);
|
||||
int r;
|
||||
|
||||
r = kvm_get_msr(vcpu, msr_index, pdata);
|
||||
r = kvm_get_msr_with_filter(vcpu, msr_index, pdata);
|
||||
|
||||
if (r && kvm_msr_user_space(vcpu, msr_index, KVM_EXIT_X86_RDMSR, 0,
|
||||
complete_emulated_rdmsr, r)) {
|
||||
@@ -7644,13 +7656,13 @@ static int emulator_get_msr(struct x86_emulate_ctxt *ctxt,
|
||||
return r;
|
||||
}
|
||||
|
||||
static int emulator_set_msr(struct x86_emulate_ctxt *ctxt,
|
||||
u32 msr_index, u64 data)
|
||||
static int emulator_set_msr_with_filter(struct x86_emulate_ctxt *ctxt,
|
||||
u32 msr_index, u64 data)
|
||||
{
|
||||
struct kvm_vcpu *vcpu = emul_to_vcpu(ctxt);
|
||||
int r;
|
||||
|
||||
r = kvm_set_msr(vcpu, msr_index, data);
|
||||
r = kvm_set_msr_with_filter(vcpu, msr_index, data);
|
||||
|
||||
if (r && kvm_msr_user_space(vcpu, msr_index, KVM_EXIT_X86_WRMSR, data,
|
||||
complete_emulated_msr_access, r)) {
|
||||
@@ -7661,6 +7673,18 @@ static int emulator_set_msr(struct x86_emulate_ctxt *ctxt,
|
||||
return r;
|
||||
}
|
||||
|
||||
static int emulator_get_msr(struct x86_emulate_ctxt *ctxt,
|
||||
u32 msr_index, u64 *pdata)
|
||||
{
|
||||
return kvm_get_msr(emul_to_vcpu(ctxt), msr_index, pdata);
|
||||
}
|
||||
|
||||
static int emulator_set_msr(struct x86_emulate_ctxt *ctxt,
|
||||
u32 msr_index, u64 data)
|
||||
{
|
||||
return kvm_set_msr(emul_to_vcpu(ctxt), msr_index, data);
|
||||
}
|
||||
|
||||
static u64 emulator_get_smbase(struct x86_emulate_ctxt *ctxt)
|
||||
{
|
||||
struct kvm_vcpu *vcpu = emul_to_vcpu(ctxt);
|
||||
@@ -7724,6 +7748,11 @@ static bool emulator_guest_has_fxsr(struct x86_emulate_ctxt *ctxt)
|
||||
return guest_cpuid_has(emul_to_vcpu(ctxt), X86_FEATURE_FXSR);
|
||||
}
|
||||
|
||||
static bool emulator_guest_has_rdpid(struct x86_emulate_ctxt *ctxt)
|
||||
{
|
||||
return guest_cpuid_has(emul_to_vcpu(ctxt), X86_FEATURE_RDPID);
|
||||
}
|
||||
|
||||
static ulong emulator_read_gpr(struct x86_emulate_ctxt *ctxt, unsigned reg)
|
||||
{
|
||||
return kvm_register_read_raw(emul_to_vcpu(ctxt), reg);
|
||||
@@ -7794,6 +7823,8 @@ static const struct x86_emulate_ops emulate_ops = {
|
||||
.set_dr = emulator_set_dr,
|
||||
.get_smbase = emulator_get_smbase,
|
||||
.set_smbase = emulator_set_smbase,
|
||||
.set_msr_with_filter = emulator_set_msr_with_filter,
|
||||
.get_msr_with_filter = emulator_get_msr_with_filter,
|
||||
.set_msr = emulator_set_msr,
|
||||
.get_msr = emulator_get_msr,
|
||||
.check_pmc = emulator_check_pmc,
|
||||
@@ -7806,6 +7837,7 @@ static const struct x86_emulate_ops emulate_ops = {
|
||||
.guest_has_long_mode = emulator_guest_has_long_mode,
|
||||
.guest_has_movbe = emulator_guest_has_movbe,
|
||||
.guest_has_fxsr = emulator_guest_has_fxsr,
|
||||
.guest_has_rdpid = emulator_guest_has_rdpid,
|
||||
.set_nmi_mask = emulator_set_nmi_mask,
|
||||
.get_hflags = emulator_get_hflags,
|
||||
.exiting_smm = emulator_exiting_smm,
|
||||
@@ -9058,15 +9090,29 @@ bool kvm_apicv_activated(struct kvm *kvm)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(kvm_apicv_activated);
|
||||
|
||||
|
||||
static void set_or_clear_apicv_inhibit(unsigned long *inhibits,
|
||||
enum kvm_apicv_inhibit reason, bool set)
|
||||
{
|
||||
if (set)
|
||||
__set_bit(reason, inhibits);
|
||||
else
|
||||
__clear_bit(reason, inhibits);
|
||||
|
||||
trace_kvm_apicv_inhibit_changed(reason, set, *inhibits);
|
||||
}
|
||||
|
||||
static void kvm_apicv_init(struct kvm *kvm)
|
||||
{
|
||||
unsigned long *inhibits = &kvm->arch.apicv_inhibit_reasons;
|
||||
|
||||
init_rwsem(&kvm->arch.apicv_update_lock);
|
||||
|
||||
set_bit(APICV_INHIBIT_REASON_ABSENT,
|
||||
&kvm->arch.apicv_inhibit_reasons);
|
||||
set_or_clear_apicv_inhibit(inhibits, APICV_INHIBIT_REASON_ABSENT, true);
|
||||
|
||||
if (!enable_apicv)
|
||||
set_bit(APICV_INHIBIT_REASON_DISABLE,
|
||||
&kvm->arch.apicv_inhibit_reasons);
|
||||
set_or_clear_apicv_inhibit(inhibits,
|
||||
APICV_INHIBIT_REASON_ABSENT, true);
|
||||
}
|
||||
|
||||
static void kvm_sched_yield(struct kvm_vcpu *vcpu, unsigned long dest_id)
|
||||
@@ -9740,24 +9786,21 @@ out:
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(kvm_vcpu_update_apicv);
|
||||
|
||||
void __kvm_request_apicv_update(struct kvm *kvm, bool activate, ulong bit)
|
||||
void __kvm_set_or_clear_apicv_inhibit(struct kvm *kvm,
|
||||
enum kvm_apicv_inhibit reason, bool set)
|
||||
{
|
||||
unsigned long old, new;
|
||||
|
||||
lockdep_assert_held_write(&kvm->arch.apicv_update_lock);
|
||||
|
||||
if (!static_call(kvm_x86_check_apicv_inhibit_reasons)(bit))
|
||||
if (!static_call(kvm_x86_check_apicv_inhibit_reasons)(reason))
|
||||
return;
|
||||
|
||||
old = new = kvm->arch.apicv_inhibit_reasons;
|
||||
|
||||
if (activate)
|
||||
__clear_bit(bit, &new);
|
||||
else
|
||||
__set_bit(bit, &new);
|
||||
set_or_clear_apicv_inhibit(&new, reason, set);
|
||||
|
||||
if (!!old != !!new) {
|
||||
trace_kvm_apicv_update_request(activate, bit);
|
||||
/*
|
||||
* Kick all vCPUs before setting apicv_inhibit_reasons to avoid
|
||||
* false positives in the sanity check WARN in svm_vcpu_run().
|
||||
@@ -9776,20 +9819,22 @@ void __kvm_request_apicv_update(struct kvm *kvm, bool activate, ulong bit)
|
||||
unsigned long gfn = gpa_to_gfn(APIC_DEFAULT_PHYS_BASE);
|
||||
kvm_zap_gfn_range(kvm, gfn, gfn+1);
|
||||
}
|
||||
} else
|
||||
} else {
|
||||
kvm->arch.apicv_inhibit_reasons = new;
|
||||
}
|
||||
}
|
||||
|
||||
void kvm_request_apicv_update(struct kvm *kvm, bool activate, ulong bit)
|
||||
void kvm_set_or_clear_apicv_inhibit(struct kvm *kvm,
|
||||
enum kvm_apicv_inhibit reason, bool set)
|
||||
{
|
||||
if (!enable_apicv)
|
||||
return;
|
||||
|
||||
down_write(&kvm->arch.apicv_update_lock);
|
||||
__kvm_request_apicv_update(kvm, activate, bit);
|
||||
__kvm_set_or_clear_apicv_inhibit(kvm, reason, set);
|
||||
up_write(&kvm->arch.apicv_update_lock);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(kvm_request_apicv_update);
|
||||
EXPORT_SYMBOL_GPL(kvm_set_or_clear_apicv_inhibit);
|
||||
|
||||
static void vcpu_scan_ioapic(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
@@ -10937,7 +10982,7 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
|
||||
|
||||
static void kvm_arch_vcpu_guestdbg_update_apicv_inhibit(struct kvm *kvm)
|
||||
{
|
||||
bool inhibit = false;
|
||||
bool set = false;
|
||||
struct kvm_vcpu *vcpu;
|
||||
unsigned long i;
|
||||
|
||||
@@ -10945,11 +10990,11 @@ static void kvm_arch_vcpu_guestdbg_update_apicv_inhibit(struct kvm *kvm)
|
||||
|
||||
kvm_for_each_vcpu(i, vcpu, kvm) {
|
||||
if (vcpu->guest_debug & KVM_GUESTDBG_BLOCKIRQ) {
|
||||
inhibit = true;
|
||||
set = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
__kvm_request_apicv_update(kvm, !inhibit, APICV_INHIBIT_REASON_BLOCKIRQ);
|
||||
__kvm_set_or_clear_apicv_inhibit(kvm, APICV_INHIBIT_REASON_BLOCKIRQ, set);
|
||||
up_write(&kvm->arch.apicv_update_lock);
|
||||
}
|
||||
|
||||
@@ -11557,10 +11602,8 @@ int kvm_arch_hardware_setup(void *opaque)
|
||||
u64 max = min(0x7fffffffULL,
|
||||
__scale_tsc(kvm_max_tsc_scaling_ratio, tsc_khz));
|
||||
kvm_max_guest_tsc_khz = max;
|
||||
|
||||
kvm_default_tsc_scaling_ratio = 1ULL << kvm_tsc_scaling_ratio_frac_bits;
|
||||
}
|
||||
|
||||
kvm_default_tsc_scaling_ratio = 1ULL << kvm_tsc_scaling_ratio_frac_bits;
|
||||
kvm_init_msr_list();
|
||||
return 0;
|
||||
}
|
||||
@@ -11629,12 +11672,13 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
|
||||
|
||||
ret = kvm_page_track_init(kvm);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto out;
|
||||
|
||||
ret = kvm_mmu_init_vm(kvm);
|
||||
if (ret)
|
||||
goto out_page_track;
|
||||
|
||||
INIT_HLIST_HEAD(&kvm->arch.mask_notifier_list);
|
||||
INIT_LIST_HEAD(&kvm->arch.active_mmu_pages);
|
||||
INIT_LIST_HEAD(&kvm->arch.zapped_obsolete_pages);
|
||||
INIT_LIST_HEAD(&kvm->arch.lpage_disallowed_mmu_pages);
|
||||
INIT_LIST_HEAD(&kvm->arch.assigned_dev_head);
|
||||
atomic_set(&kvm->arch.noncoherent_dma_count, 0);
|
||||
|
||||
@@ -11666,10 +11710,14 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
|
||||
|
||||
kvm_apicv_init(kvm);
|
||||
kvm_hv_init_vm(kvm);
|
||||
kvm_mmu_init_vm(kvm);
|
||||
kvm_xen_init_vm(kvm);
|
||||
|
||||
return static_call(kvm_x86_vm_init)(kvm);
|
||||
|
||||
out_page_track:
|
||||
kvm_page_track_cleanup(kvm);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int kvm_arch_post_init_vm(struct kvm *kvm)
|
||||
@@ -12593,7 +12641,7 @@ void kvm_fixup_and_inject_pf_error(struct kvm_vcpu *vcpu, gva_t gva, u16 error_c
|
||||
{
|
||||
struct kvm_mmu *mmu = vcpu->arch.walk_mmu;
|
||||
struct x86_exception fault;
|
||||
u32 access = error_code &
|
||||
u64 access = error_code &
|
||||
(PFERR_WRITE_MASK | PFERR_FETCH_MASK | PFERR_USER_MASK);
|
||||
|
||||
if (!(error_code & PFERR_PRESENT_MASK) ||
|
||||
@@ -12933,7 +12981,6 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_pi_irte_update);
|
||||
EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_avic_unaccelerated_access);
|
||||
EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_avic_incomplete_ipi);
|
||||
EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_avic_ga_log);
|
||||
EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_apicv_update_request);
|
||||
EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_apicv_accept_irq);
|
||||
EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_vmgexit_enter);
|
||||
EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_vmgexit_exit);
|
||||
|
||||
+3
-4
@@ -39,8 +39,8 @@ static int kvm_xen_shared_info_init(struct kvm *kvm, gfn_t gfn)
|
||||
}
|
||||
|
||||
do {
|
||||
ret = kvm_gfn_to_pfn_cache_init(kvm, gpc, NULL, false, true,
|
||||
gpa, PAGE_SIZE, false);
|
||||
ret = kvm_gfn_to_pfn_cache_init(kvm, gpc, NULL, KVM_HOST_USES_PFN,
|
||||
gpa, PAGE_SIZE);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
@@ -1025,8 +1025,7 @@ static int evtchn_set_fn(struct kvm_kernel_irq_routing_entry *e, struct kvm *kvm
|
||||
break;
|
||||
|
||||
idx = srcu_read_lock(&kvm->srcu);
|
||||
rc = kvm_gfn_to_pfn_cache_refresh(kvm, gpc, gpc->gpa,
|
||||
PAGE_SIZE, false);
|
||||
rc = kvm_gfn_to_pfn_cache_refresh(kvm, gpc, gpc->gpa, PAGE_SIZE);
|
||||
srcu_read_unlock(&kvm->srcu, idx);
|
||||
} while(!rc);
|
||||
|
||||
|
||||
@@ -93,7 +93,6 @@ __wsum csum_partial(const void *buff, int len, __wsum sum)
|
||||
buff += 8;
|
||||
}
|
||||
if (len & 7) {
|
||||
#ifdef CONFIG_DCACHE_WORD_ACCESS
|
||||
unsigned int shift = (8 - (len & 7)) * 8;
|
||||
unsigned long trail;
|
||||
|
||||
@@ -103,31 +102,6 @@ __wsum csum_partial(const void *buff, int len, __wsum sum)
|
||||
"adcq $0,%[res]"
|
||||
: [res] "+r" (temp64)
|
||||
: [trail] "r" (trail));
|
||||
#else
|
||||
if (len & 4) {
|
||||
asm("addq %[val],%[res]\n\t"
|
||||
"adcq $0,%[res]"
|
||||
: [res] "+r" (temp64)
|
||||
: [val] "r" ((u64)*(u32 *)buff)
|
||||
: "memory");
|
||||
buff += 4;
|
||||
}
|
||||
if (len & 2) {
|
||||
asm("addq %[val],%[res]\n\t"
|
||||
"adcq $0,%[res]"
|
||||
: [res] "+r" (temp64)
|
||||
: [val] "r" ((u64)*(u16 *)buff)
|
||||
: "memory");
|
||||
buff += 2;
|
||||
}
|
||||
if (len & 1) {
|
||||
asm("addq %[val],%[res]\n\t"
|
||||
"adcq $0,%[res]"
|
||||
: [res] "+r" (temp64)
|
||||
: [val] "r" ((u64)*(u8 *)buff)
|
||||
: "memory");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
result = add32_with_carry(temp64 >> 32, temp64 & 0xffffffff);
|
||||
if (unlikely(odd)) {
|
||||
|
||||
+57
-8
@@ -22,7 +22,7 @@ static __always_inline void rep_movs(void *to, const void *from, size_t n)
|
||||
: "memory");
|
||||
}
|
||||
|
||||
void memcpy_fromio(void *to, const volatile void __iomem *from, size_t n)
|
||||
static void string_memcpy_fromio(void *to, const volatile void __iomem *from, size_t n)
|
||||
{
|
||||
if (unlikely(!n))
|
||||
return;
|
||||
@@ -38,9 +38,8 @@ void memcpy_fromio(void *to, const volatile void __iomem *from, size_t n)
|
||||
}
|
||||
rep_movs(to, (const void *)from, n);
|
||||
}
|
||||
EXPORT_SYMBOL(memcpy_fromio);
|
||||
|
||||
void memcpy_toio(volatile void __iomem *to, const void *from, size_t n)
|
||||
static void string_memcpy_toio(volatile void __iomem *to, const void *from, size_t n)
|
||||
{
|
||||
if (unlikely(!n))
|
||||
return;
|
||||
@@ -56,14 +55,64 @@ void memcpy_toio(volatile void __iomem *to, const void *from, size_t n)
|
||||
}
|
||||
rep_movs((void *)to, (const void *) from, n);
|
||||
}
|
||||
|
||||
static void unrolled_memcpy_fromio(void *to, const volatile void __iomem *from, size_t n)
|
||||
{
|
||||
const volatile char __iomem *in = from;
|
||||
char *out = to;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < n; ++i)
|
||||
out[i] = readb(&in[i]);
|
||||
}
|
||||
|
||||
static void unrolled_memcpy_toio(volatile void __iomem *to, const void *from, size_t n)
|
||||
{
|
||||
volatile char __iomem *out = to;
|
||||
const char *in = from;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < n; ++i)
|
||||
writeb(in[i], &out[i]);
|
||||
}
|
||||
|
||||
static void unrolled_memset_io(volatile void __iomem *a, int b, size_t c)
|
||||
{
|
||||
volatile char __iomem *mem = a;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < c; ++i)
|
||||
writeb(b, &mem[i]);
|
||||
}
|
||||
|
||||
void memcpy_fromio(void *to, const volatile void __iomem *from, size_t n)
|
||||
{
|
||||
if (cc_platform_has(CC_ATTR_GUEST_UNROLL_STRING_IO))
|
||||
unrolled_memcpy_fromio(to, from, n);
|
||||
else
|
||||
string_memcpy_fromio(to, from, n);
|
||||
}
|
||||
EXPORT_SYMBOL(memcpy_fromio);
|
||||
|
||||
void memcpy_toio(volatile void __iomem *to, const void *from, size_t n)
|
||||
{
|
||||
if (cc_platform_has(CC_ATTR_GUEST_UNROLL_STRING_IO))
|
||||
unrolled_memcpy_toio(to, from, n);
|
||||
else
|
||||
string_memcpy_toio(to, from, n);
|
||||
}
|
||||
EXPORT_SYMBOL(memcpy_toio);
|
||||
|
||||
void memset_io(volatile void __iomem *a, int b, size_t c)
|
||||
{
|
||||
/*
|
||||
* TODO: memset can mangle the IO patterns quite a bit.
|
||||
* perhaps it would be better to use a dumb one:
|
||||
*/
|
||||
memset((void *)a, b, c);
|
||||
if (cc_platform_has(CC_ATTR_GUEST_UNROLL_STRING_IO)) {
|
||||
unrolled_memset_io(a, b, c);
|
||||
} else {
|
||||
/*
|
||||
* TODO: memset can mangle the IO patterns quite a bit.
|
||||
* perhaps it would be better to use a dumb one:
|
||||
*/
|
||||
memset((void *)a, b, c);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(memset_io);
|
||||
|
||||
@@ -9,6 +9,7 @@ endmenu
|
||||
config UML_X86
|
||||
def_bool y
|
||||
select ARCH_BINFMT_ELF_EXTRA_PHDRS if X86_32
|
||||
select DCACHE_WORD_ACCESS
|
||||
|
||||
config 64BIT
|
||||
bool "64-bit kernel" if "$(SUBARCH)" = "x86"
|
||||
|
||||
+22
-10
@@ -65,19 +65,12 @@ static bool blkcg_policy_enabled(struct request_queue *q,
|
||||
return pol && test_bit(pol->plid, q->blkcg_pols);
|
||||
}
|
||||
|
||||
/**
|
||||
* blkg_free - free a blkg
|
||||
* @blkg: blkg to free
|
||||
*
|
||||
* Free @blkg which may be partially allocated.
|
||||
*/
|
||||
static void blkg_free(struct blkcg_gq *blkg)
|
||||
static void blkg_free_workfn(struct work_struct *work)
|
||||
{
|
||||
struct blkcg_gq *blkg = container_of(work, struct blkcg_gq,
|
||||
free_work);
|
||||
int i;
|
||||
|
||||
if (!blkg)
|
||||
return;
|
||||
|
||||
for (i = 0; i < BLKCG_MAX_POLS; i++)
|
||||
if (blkg->pd[i])
|
||||
blkcg_policy[i]->pd_free_fn(blkg->pd[i]);
|
||||
@@ -89,6 +82,25 @@ static void blkg_free(struct blkcg_gq *blkg)
|
||||
kfree(blkg);
|
||||
}
|
||||
|
||||
/**
|
||||
* blkg_free - free a blkg
|
||||
* @blkg: blkg to free
|
||||
*
|
||||
* Free @blkg which may be partially allocated.
|
||||
*/
|
||||
static void blkg_free(struct blkcg_gq *blkg)
|
||||
{
|
||||
if (!blkg)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Both ->pd_free_fn() and request queue's release handler may
|
||||
* sleep, so free us by scheduling one work func
|
||||
*/
|
||||
INIT_WORK(&blkg->free_work, blkg_free_workfn);
|
||||
schedule_work(&blkg->free_work);
|
||||
}
|
||||
|
||||
static void __blkg_release(struct rcu_head *rcu)
|
||||
{
|
||||
struct blkcg_gq *blkg = container_of(rcu, struct blkcg_gq, rcu_head);
|
||||
|
||||
+1
-2
@@ -280,7 +280,6 @@ int set_task_ioprio(struct task_struct *task, int ioprio)
|
||||
|
||||
task_lock(task);
|
||||
if (task->flags & PF_EXITING) {
|
||||
err = -ESRCH;
|
||||
kmem_cache_free(iocontext_cachep, ioc);
|
||||
goto out;
|
||||
}
|
||||
@@ -292,7 +291,7 @@ int set_task_ioprio(struct task_struct *task, int ioprio)
|
||||
task->io_context->ioprio = ioprio;
|
||||
out:
|
||||
task_unlock(task);
|
||||
return err;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(set_task_ioprio);
|
||||
|
||||
|
||||
+16
-9
@@ -4462,21 +4462,28 @@ static bool blk_mq_elv_switch_none(struct list_head *head,
|
||||
return true;
|
||||
}
|
||||
|
||||
static void blk_mq_elv_switch_back(struct list_head *head,
|
||||
struct request_queue *q)
|
||||
static struct blk_mq_qe_pair *blk_lookup_qe_pair(struct list_head *head,
|
||||
struct request_queue *q)
|
||||
{
|
||||
struct blk_mq_qe_pair *qe;
|
||||
struct elevator_type *t = NULL;
|
||||
|
||||
list_for_each_entry(qe, head, node)
|
||||
if (qe->q == q) {
|
||||
t = qe->type;
|
||||
break;
|
||||
}
|
||||
if (qe->q == q)
|
||||
return qe;
|
||||
|
||||
if (!t)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void blk_mq_elv_switch_back(struct list_head *head,
|
||||
struct request_queue *q)
|
||||
{
|
||||
struct blk_mq_qe_pair *qe;
|
||||
struct elevator_type *t;
|
||||
|
||||
qe = blk_lookup_qe_pair(head, q);
|
||||
if (!qe)
|
||||
return;
|
||||
|
||||
t = qe->type;
|
||||
list_del(&qe->node);
|
||||
kfree(qe);
|
||||
|
||||
|
||||
@@ -101,9 +101,6 @@ u64 wbt_default_latency_nsec(struct request_queue *);
|
||||
|
||||
#else
|
||||
|
||||
static inline void wbt_track(struct request *rq, enum wbt_flags flags)
|
||||
{
|
||||
}
|
||||
static inline int wbt_init(struct request_queue *q)
|
||||
{
|
||||
return -EINVAL;
|
||||
|
||||
+1
-1
@@ -335,7 +335,7 @@ int blk_alloc_ext_minor(void)
|
||||
{
|
||||
int idx;
|
||||
|
||||
idx = ida_alloc_range(&ext_devt_ida, 0, NR_EXT_DEVT, GFP_KERNEL);
|
||||
idx = ida_alloc_range(&ext_devt_ida, 0, NR_EXT_DEVT - 1, GFP_KERNEL);
|
||||
if (idx == -ENOSPC)
|
||||
return -EBUSY;
|
||||
return idx;
|
||||
|
||||
@@ -171,7 +171,7 @@ void tl_release(struct drbd_connection *connection, unsigned int barrier_nr,
|
||||
unsigned int set_size)
|
||||
{
|
||||
struct drbd_request *r;
|
||||
struct drbd_request *req = NULL;
|
||||
struct drbd_request *req = NULL, *tmp = NULL;
|
||||
int expect_epoch = 0;
|
||||
int expect_size = 0;
|
||||
|
||||
@@ -225,8 +225,11 @@ void tl_release(struct drbd_connection *connection, unsigned int barrier_nr,
|
||||
* to catch requests being barrier-acked "unexpectedly".
|
||||
* It usually should find the same req again, or some READ preceding it. */
|
||||
list_for_each_entry(req, &connection->transfer_log, tl_requests)
|
||||
if (req->epoch == expect_epoch)
|
||||
if (req->epoch == expect_epoch) {
|
||||
tmp = req;
|
||||
break;
|
||||
}
|
||||
req = list_prepare_entry(tmp, &connection->transfer_log, tl_requests);
|
||||
list_for_each_entry_safe_from(req, r, &connection->transfer_log, tl_requests) {
|
||||
if (req->epoch != expect_epoch)
|
||||
break;
|
||||
|
||||
@@ -180,7 +180,8 @@ void start_new_tl_epoch(struct drbd_connection *connection)
|
||||
void complete_master_bio(struct drbd_device *device,
|
||||
struct bio_and_error *m)
|
||||
{
|
||||
m->bio->bi_status = errno_to_blk_status(m->error);
|
||||
if (unlikely(m->error))
|
||||
m->bio->bi_status = errno_to_blk_status(m->error);
|
||||
bio_endio(m->bio);
|
||||
dec_ap_bio(device);
|
||||
}
|
||||
@@ -332,17 +333,21 @@ static void set_if_null_req_next(struct drbd_peer_device *peer_device, struct dr
|
||||
static void advance_conn_req_next(struct drbd_peer_device *peer_device, struct drbd_request *req)
|
||||
{
|
||||
struct drbd_connection *connection = peer_device ? peer_device->connection : NULL;
|
||||
struct drbd_request *iter = req;
|
||||
if (!connection)
|
||||
return;
|
||||
if (connection->req_next != req)
|
||||
return;
|
||||
list_for_each_entry_continue(req, &connection->transfer_log, tl_requests) {
|
||||
const unsigned s = req->rq_state;
|
||||
if (s & RQ_NET_QUEUED)
|
||||
|
||||
req = NULL;
|
||||
list_for_each_entry_continue(iter, &connection->transfer_log, tl_requests) {
|
||||
const unsigned int s = iter->rq_state;
|
||||
|
||||
if (s & RQ_NET_QUEUED) {
|
||||
req = iter;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (&req->tl_requests == &connection->transfer_log)
|
||||
req = NULL;
|
||||
connection->req_next = req;
|
||||
}
|
||||
|
||||
@@ -358,17 +363,21 @@ static void set_if_null_req_ack_pending(struct drbd_peer_device *peer_device, st
|
||||
static void advance_conn_req_ack_pending(struct drbd_peer_device *peer_device, struct drbd_request *req)
|
||||
{
|
||||
struct drbd_connection *connection = peer_device ? peer_device->connection : NULL;
|
||||
struct drbd_request *iter = req;
|
||||
if (!connection)
|
||||
return;
|
||||
if (connection->req_ack_pending != req)
|
||||
return;
|
||||
list_for_each_entry_continue(req, &connection->transfer_log, tl_requests) {
|
||||
const unsigned s = req->rq_state;
|
||||
if ((s & RQ_NET_SENT) && (s & RQ_NET_PENDING))
|
||||
|
||||
req = NULL;
|
||||
list_for_each_entry_continue(iter, &connection->transfer_log, tl_requests) {
|
||||
const unsigned int s = iter->rq_state;
|
||||
|
||||
if ((s & RQ_NET_SENT) && (s & RQ_NET_PENDING)) {
|
||||
req = iter;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (&req->tl_requests == &connection->transfer_log)
|
||||
req = NULL;
|
||||
connection->req_ack_pending = req;
|
||||
}
|
||||
|
||||
@@ -384,17 +393,21 @@ static void set_if_null_req_not_net_done(struct drbd_peer_device *peer_device, s
|
||||
static void advance_conn_req_not_net_done(struct drbd_peer_device *peer_device, struct drbd_request *req)
|
||||
{
|
||||
struct drbd_connection *connection = peer_device ? peer_device->connection : NULL;
|
||||
struct drbd_request *iter = req;
|
||||
if (!connection)
|
||||
return;
|
||||
if (connection->req_not_net_done != req)
|
||||
return;
|
||||
list_for_each_entry_continue(req, &connection->transfer_log, tl_requests) {
|
||||
const unsigned s = req->rq_state;
|
||||
if ((s & RQ_NET_SENT) && !(s & RQ_NET_DONE))
|
||||
|
||||
req = NULL;
|
||||
list_for_each_entry_continue(iter, &connection->transfer_log, tl_requests) {
|
||||
const unsigned int s = iter->rq_state;
|
||||
|
||||
if ((s & RQ_NET_SENT) && !(s & RQ_NET_DONE)) {
|
||||
req = iter;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (&req->tl_requests == &connection->transfer_log)
|
||||
req = NULL;
|
||||
connection->req_not_net_done = req;
|
||||
}
|
||||
|
||||
|
||||
@@ -1591,6 +1591,7 @@ struct compat_loop_info {
|
||||
compat_ulong_t lo_inode; /* ioctl r/o */
|
||||
compat_dev_t lo_rdevice; /* ioctl r/o */
|
||||
compat_int_t lo_offset;
|
||||
compat_int_t lo_encrypt_type; /* obsolete, ignored */
|
||||
compat_int_t lo_encrypt_key_size; /* ioctl w/o */
|
||||
compat_int_t lo_flags; /* ioctl r/o */
|
||||
char lo_name[LO_NAME_SIZE];
|
||||
|
||||
@@ -88,7 +88,7 @@ static void n64cart_submit_bio(struct bio *bio)
|
||||
{
|
||||
struct bio_vec bvec;
|
||||
struct bvec_iter iter;
|
||||
struct device *dev = bio->bi_disk->private_data;
|
||||
struct device *dev = bio->bi_bdev->bd_disk->private_data;
|
||||
u32 pos = bio->bi_iter.bi_sector << SECTOR_SHIFT;
|
||||
|
||||
bio_for_each_segment(bvec, bio, iter) {
|
||||
|
||||
@@ -931,7 +931,7 @@ static int xen_blkbk_parse_indirect(struct blkif_request *req,
|
||||
if (rc)
|
||||
goto unmap;
|
||||
|
||||
for (n = 0, i = 0; n < nseg; n++) {
|
||||
for (n = 0; n < nseg; n++) {
|
||||
uint8_t first_sect, last_sect;
|
||||
|
||||
if ((n % SEGS_PER_INDIRECT_FRAME) == 0) {
|
||||
|
||||
@@ -576,7 +576,7 @@ struct setup_rw_req {
|
||||
struct blkif_request *ring_req;
|
||||
grant_ref_t gref_head;
|
||||
unsigned int id;
|
||||
/* Only used when persistent grant is used and it's a read request */
|
||||
/* Only used when persistent grant is used and it's a write request */
|
||||
bool need_copy;
|
||||
unsigned int bvec_off;
|
||||
char *bvec_data;
|
||||
|
||||
+14
-28
@@ -2411,15 +2411,19 @@ int clk_set_rate_exclusive(struct clk *clk, unsigned long rate)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_set_rate_exclusive);
|
||||
|
||||
static int clk_set_rate_range_nolock(struct clk *clk,
|
||||
unsigned long min,
|
||||
unsigned long max)
|
||||
/**
|
||||
* clk_set_rate_range - set a rate range for a clock source
|
||||
* @clk: clock source
|
||||
* @min: desired minimum clock rate in Hz, inclusive
|
||||
* @max: desired maximum clock rate in Hz, inclusive
|
||||
*
|
||||
* Returns success (0) or negative errno.
|
||||
*/
|
||||
int clk_set_rate_range(struct clk *clk, unsigned long min, unsigned long max)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned long old_min, old_max, rate;
|
||||
|
||||
lockdep_assert_held(&prepare_lock);
|
||||
|
||||
if (!clk)
|
||||
return 0;
|
||||
|
||||
@@ -2432,6 +2436,8 @@ static int clk_set_rate_range_nolock(struct clk *clk,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
clk_prepare_lock();
|
||||
|
||||
if (clk->exclusive_count)
|
||||
clk_core_rate_unprotect(clk->core);
|
||||
|
||||
@@ -2475,28 +2481,6 @@ out:
|
||||
if (clk->exclusive_count)
|
||||
clk_core_rate_protect(clk->core);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* clk_set_rate_range - set a rate range for a clock source
|
||||
* @clk: clock source
|
||||
* @min: desired minimum clock rate in Hz, inclusive
|
||||
* @max: desired maximum clock rate in Hz, inclusive
|
||||
*
|
||||
* Return: 0 for success or negative errno on failure.
|
||||
*/
|
||||
int clk_set_rate_range(struct clk *clk, unsigned long min, unsigned long max)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!clk)
|
||||
return 0;
|
||||
|
||||
clk_prepare_lock();
|
||||
|
||||
ret = clk_set_rate_range_nolock(clk, min, max);
|
||||
|
||||
clk_prepare_unlock();
|
||||
|
||||
return ret;
|
||||
@@ -4484,7 +4468,9 @@ void __clk_put(struct clk *clk)
|
||||
}
|
||||
|
||||
hlist_del(&clk->clks_node);
|
||||
clk_set_rate_range_nolock(clk, 0, ULONG_MAX);
|
||||
if (clk->min_rate > clk->core->req_rate ||
|
||||
clk->max_rate < clk->core->req_rate)
|
||||
clk_core_set_rate_nolock(clk->core, clk->core->req_rate);
|
||||
|
||||
owner = clk->core->owner;
|
||||
kref_put(&clk->core->ref, __clk_release);
|
||||
|
||||
@@ -760,65 +760,9 @@ static void clk_range_test_multiple_set_range_rate_maximized(struct kunit *test)
|
||||
clk_put(user1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Test that if we have several subsequent calls to
|
||||
* clk_set_rate_range(), across multiple users, the core will reevaluate
|
||||
* whether a new rate is needed, including when a user drop its clock.
|
||||
*
|
||||
* With clk_dummy_maximize_rate_ops, this means that the rate will
|
||||
* trail along the maximum as it evolves.
|
||||
*/
|
||||
static void clk_range_test_multiple_set_range_rate_put_maximized(struct kunit *test)
|
||||
{
|
||||
struct clk_dummy_context *ctx = test->priv;
|
||||
struct clk_hw *hw = &ctx->hw;
|
||||
struct clk *clk = hw->clk;
|
||||
struct clk *user1, *user2;
|
||||
unsigned long rate;
|
||||
|
||||
user1 = clk_hw_get_clk(hw, NULL);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, user1);
|
||||
|
||||
user2 = clk_hw_get_clk(hw, NULL);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, user2);
|
||||
|
||||
KUNIT_ASSERT_EQ(test,
|
||||
clk_set_rate(clk, DUMMY_CLOCK_RATE_2 + 1000),
|
||||
0);
|
||||
|
||||
KUNIT_ASSERT_EQ(test,
|
||||
clk_set_rate_range(user1,
|
||||
0,
|
||||
DUMMY_CLOCK_RATE_2),
|
||||
0);
|
||||
|
||||
rate = clk_get_rate(clk);
|
||||
KUNIT_ASSERT_GT(test, rate, 0);
|
||||
KUNIT_EXPECT_EQ(test, rate, DUMMY_CLOCK_RATE_2);
|
||||
|
||||
KUNIT_ASSERT_EQ(test,
|
||||
clk_set_rate_range(user2,
|
||||
0,
|
||||
DUMMY_CLOCK_RATE_1),
|
||||
0);
|
||||
|
||||
rate = clk_get_rate(clk);
|
||||
KUNIT_ASSERT_GT(test, rate, 0);
|
||||
KUNIT_EXPECT_EQ(test, rate, DUMMY_CLOCK_RATE_1);
|
||||
|
||||
clk_put(user2);
|
||||
|
||||
rate = clk_get_rate(clk);
|
||||
KUNIT_ASSERT_GT(test, rate, 0);
|
||||
KUNIT_EXPECT_EQ(test, rate, DUMMY_CLOCK_RATE_2);
|
||||
|
||||
clk_put(user1);
|
||||
}
|
||||
|
||||
static struct kunit_case clk_range_maximize_test_cases[] = {
|
||||
KUNIT_CASE(clk_range_test_set_range_rate_maximized),
|
||||
KUNIT_CASE(clk_range_test_multiple_set_range_rate_maximized),
|
||||
KUNIT_CASE(clk_range_test_multiple_set_range_rate_put_maximized),
|
||||
{}
|
||||
};
|
||||
|
||||
@@ -933,61 +877,9 @@ static void clk_range_test_multiple_set_range_rate_minimized(struct kunit *test)
|
||||
clk_put(user1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Test that if we have several subsequent calls to
|
||||
* clk_set_rate_range(), across multiple users, the core will reevaluate
|
||||
* whether a new rate is needed, including when a user drop its clock.
|
||||
*
|
||||
* With clk_dummy_minimize_rate_ops, this means that the rate will
|
||||
* trail along the minimum as it evolves.
|
||||
*/
|
||||
static void clk_range_test_multiple_set_range_rate_put_minimized(struct kunit *test)
|
||||
{
|
||||
struct clk_dummy_context *ctx = test->priv;
|
||||
struct clk_hw *hw = &ctx->hw;
|
||||
struct clk *clk = hw->clk;
|
||||
struct clk *user1, *user2;
|
||||
unsigned long rate;
|
||||
|
||||
user1 = clk_hw_get_clk(hw, NULL);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, user1);
|
||||
|
||||
user2 = clk_hw_get_clk(hw, NULL);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, user2);
|
||||
|
||||
KUNIT_ASSERT_EQ(test,
|
||||
clk_set_rate_range(user1,
|
||||
DUMMY_CLOCK_RATE_1,
|
||||
ULONG_MAX),
|
||||
0);
|
||||
|
||||
rate = clk_get_rate(clk);
|
||||
KUNIT_ASSERT_GT(test, rate, 0);
|
||||
KUNIT_EXPECT_EQ(test, rate, DUMMY_CLOCK_RATE_1);
|
||||
|
||||
KUNIT_ASSERT_EQ(test,
|
||||
clk_set_rate_range(user2,
|
||||
DUMMY_CLOCK_RATE_2,
|
||||
ULONG_MAX),
|
||||
0);
|
||||
|
||||
rate = clk_get_rate(clk);
|
||||
KUNIT_ASSERT_GT(test, rate, 0);
|
||||
KUNIT_EXPECT_EQ(test, rate, DUMMY_CLOCK_RATE_2);
|
||||
|
||||
clk_put(user2);
|
||||
|
||||
rate = clk_get_rate(clk);
|
||||
KUNIT_ASSERT_GT(test, rate, 0);
|
||||
KUNIT_EXPECT_EQ(test, rate, DUMMY_CLOCK_RATE_1);
|
||||
|
||||
clk_put(user1);
|
||||
}
|
||||
|
||||
static struct kunit_case clk_range_minimize_test_cases[] = {
|
||||
KUNIT_CASE(clk_range_test_set_range_rate_minimized),
|
||||
KUNIT_CASE(clk_range_test_multiple_set_range_rate_minimized),
|
||||
KUNIT_CASE(clk_range_test_multiple_set_range_rate_put_minimized),
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
@@ -210,7 +210,7 @@ struct dm_table {
|
||||
#define DM_TIO_MAGIC 28714
|
||||
struct dm_target_io {
|
||||
unsigned short magic;
|
||||
unsigned short flags;
|
||||
blk_short_t flags;
|
||||
unsigned int target_bio_nr;
|
||||
struct dm_io *io;
|
||||
struct dm_target *ti;
|
||||
@@ -244,7 +244,7 @@ static inline void dm_tio_set_flag(struct dm_target_io *tio, unsigned int bit)
|
||||
#define DM_IO_MAGIC 19577
|
||||
struct dm_io {
|
||||
unsigned short magic;
|
||||
unsigned short flags;
|
||||
blk_short_t flags;
|
||||
atomic_t io_count;
|
||||
struct mapped_device *md;
|
||||
struct bio *orig_bio;
|
||||
|
||||
@@ -2472,9 +2472,11 @@ static void do_journal_write(struct dm_integrity_c *ic, unsigned write_start,
|
||||
dm_integrity_io_error(ic, "invalid sector in journal", -EIO);
|
||||
sec &= ~(sector_t)(ic->sectors_per_block - 1);
|
||||
}
|
||||
if (unlikely(sec >= ic->provided_data_sectors)) {
|
||||
journal_entry_set_unused(je);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (unlikely(sec >= ic->provided_data_sectors))
|
||||
continue;
|
||||
get_area_and_offset(ic, sec, &area, &offset);
|
||||
restore_last_bytes(ic, access_journal_data(ic, i, j), je);
|
||||
for (k = j + 1; k < ic->journal_section_entries; k++) {
|
||||
|
||||
+12
-3
@@ -891,15 +891,21 @@ static struct hash_cell *__find_device_hash_cell(struct dm_ioctl *param)
|
||||
struct hash_cell *hc = NULL;
|
||||
|
||||
if (*param->uuid) {
|
||||
if (*param->name || param->dev)
|
||||
if (*param->name || param->dev) {
|
||||
DMERR("Invalid ioctl structure: uuid %s, name %s, dev %llx",
|
||||
param->uuid, param->name, (unsigned long long)param->dev);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
hc = __get_uuid_cell(param->uuid);
|
||||
if (!hc)
|
||||
return NULL;
|
||||
} else if (*param->name) {
|
||||
if (param->dev)
|
||||
if (param->dev) {
|
||||
DMERR("Invalid ioctl structure: name %s, dev %llx",
|
||||
param->name, (unsigned long long)param->dev);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
hc = __get_name_cell(param->name);
|
||||
if (!hc)
|
||||
@@ -1851,8 +1857,11 @@ static int copy_params(struct dm_ioctl __user *user, struct dm_ioctl *param_kern
|
||||
if (copy_from_user(param_kernel, user, minimum_data_size))
|
||||
return -EFAULT;
|
||||
|
||||
if (param_kernel->data_size < minimum_data_size)
|
||||
if (param_kernel->data_size < minimum_data_size) {
|
||||
DMERR("Invalid data size in the ioctl structure: %u",
|
||||
param_kernel->data_size);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
secure_data = param_kernel->flags & DM_SECURE_DATA_FLAG;
|
||||
|
||||
|
||||
+13
-7
@@ -892,13 +892,19 @@ static void dm_io_complete(struct dm_io *io)
|
||||
if (unlikely(wq_has_sleeper(&md->wait)))
|
||||
wake_up(&md->wait);
|
||||
|
||||
if (io_error == BLK_STS_DM_REQUEUE) {
|
||||
/*
|
||||
* Upper layer won't help us poll split bio, io->orig_bio
|
||||
* may only reflect a subset of the pre-split original,
|
||||
* so clear REQ_POLLED in case of requeue
|
||||
*/
|
||||
bio->bi_opf &= ~REQ_POLLED;
|
||||
if (io_error == BLK_STS_DM_REQUEUE || io_error == BLK_STS_AGAIN) {
|
||||
if (bio->bi_opf & REQ_POLLED) {
|
||||
/*
|
||||
* Upper layer won't help us poll split bio (io->orig_bio
|
||||
* may only reflect a subset of the pre-split original)
|
||||
* so clear REQ_POLLED in case of requeue.
|
||||
*/
|
||||
bio->bi_opf &= ~REQ_POLLED;
|
||||
if (io_error == BLK_STS_AGAIN) {
|
||||
/* io_uring doesn't handle BLK_STS_AGAIN (yet) */
|
||||
queue_io(md, bio);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
+26
-12
@@ -1830,9 +1830,6 @@ static void nvme_update_disk_info(struct gendisk *disk,
|
||||
nvme_config_discard(disk, ns);
|
||||
blk_queue_max_write_zeroes_sectors(disk->queue,
|
||||
ns->ctrl->max_zeroes_sectors);
|
||||
|
||||
set_disk_ro(disk, (id->nsattr & NVME_NS_ATTR_RO) ||
|
||||
test_bit(NVME_NS_FORCE_RO, &ns->flags));
|
||||
}
|
||||
|
||||
static inline bool nvme_first_scan(struct gendisk *disk)
|
||||
@@ -1891,6 +1888,8 @@ static int nvme_update_ns_info(struct nvme_ns *ns, struct nvme_id_ns *id)
|
||||
goto out_unfreeze;
|
||||
}
|
||||
|
||||
set_disk_ro(ns->disk, (id->nsattr & NVME_NS_ATTR_RO) ||
|
||||
test_bit(NVME_NS_FORCE_RO, &ns->flags));
|
||||
set_bit(NVME_NS_READY, &ns->flags);
|
||||
blk_mq_unfreeze_queue(ns->disk->queue);
|
||||
|
||||
@@ -1903,6 +1902,9 @@ static int nvme_update_ns_info(struct nvme_ns *ns, struct nvme_id_ns *id)
|
||||
if (nvme_ns_head_multipath(ns->head)) {
|
||||
blk_mq_freeze_queue(ns->head->disk->queue);
|
||||
nvme_update_disk_info(ns->head->disk, ns, id);
|
||||
set_disk_ro(ns->head->disk,
|
||||
(id->nsattr & NVME_NS_ATTR_RO) ||
|
||||
test_bit(NVME_NS_FORCE_RO, &ns->flags));
|
||||
nvme_mpath_revalidate_paths(ns);
|
||||
blk_stack_limits(&ns->head->disk->queue->limits,
|
||||
&ns->queue->limits, 0);
|
||||
@@ -3589,15 +3591,20 @@ static const struct attribute_group *nvme_dev_attr_groups[] = {
|
||||
NULL,
|
||||
};
|
||||
|
||||
static struct nvme_ns_head *nvme_find_ns_head(struct nvme_subsystem *subsys,
|
||||
static struct nvme_ns_head *nvme_find_ns_head(struct nvme_ctrl *ctrl,
|
||||
unsigned nsid)
|
||||
{
|
||||
struct nvme_ns_head *h;
|
||||
|
||||
lockdep_assert_held(&subsys->lock);
|
||||
lockdep_assert_held(&ctrl->subsys->lock);
|
||||
|
||||
list_for_each_entry(h, &subsys->nsheads, entry) {
|
||||
if (h->ns_id != nsid)
|
||||
list_for_each_entry(h, &ctrl->subsys->nsheads, entry) {
|
||||
/*
|
||||
* Private namespaces can share NSIDs under some conditions.
|
||||
* In that case we can't use the same ns_head for namespaces
|
||||
* with the same NSID.
|
||||
*/
|
||||
if (h->ns_id != nsid || !nvme_is_unique_nsid(ctrl, h))
|
||||
continue;
|
||||
if (!list_empty(&h->list) && nvme_tryget_ns_head(h))
|
||||
return h;
|
||||
@@ -3791,7 +3798,7 @@ static int nvme_init_ns_head(struct nvme_ns *ns, unsigned nsid,
|
||||
}
|
||||
|
||||
mutex_lock(&ctrl->subsys->lock);
|
||||
head = nvme_find_ns_head(ctrl->subsys, nsid);
|
||||
head = nvme_find_ns_head(ctrl, nsid);
|
||||
if (!head) {
|
||||
ret = nvme_subsys_check_duplicate_ids(ctrl->subsys, ids);
|
||||
if (ret) {
|
||||
@@ -3988,6 +3995,16 @@ static void nvme_ns_remove(struct nvme_ns *ns)
|
||||
set_capacity(ns->disk, 0);
|
||||
nvme_fault_inject_fini(&ns->fault_inject);
|
||||
|
||||
/*
|
||||
* Ensure that !NVME_NS_READY is seen by other threads to prevent
|
||||
* this ns going back into current_path.
|
||||
*/
|
||||
synchronize_srcu(&ns->head->srcu);
|
||||
|
||||
/* wait for concurrent submissions */
|
||||
if (nvme_mpath_clear_current_path(ns))
|
||||
synchronize_srcu(&ns->head->srcu);
|
||||
|
||||
mutex_lock(&ns->ctrl->subsys->lock);
|
||||
list_del_rcu(&ns->siblings);
|
||||
if (list_empty(&ns->head->list)) {
|
||||
@@ -3999,10 +4016,6 @@ static void nvme_ns_remove(struct nvme_ns *ns)
|
||||
/* guarantee not available in head->list */
|
||||
synchronize_rcu();
|
||||
|
||||
/* wait for concurrent submissions */
|
||||
if (nvme_mpath_clear_current_path(ns))
|
||||
synchronize_srcu(&ns->head->srcu);
|
||||
|
||||
if (!nvme_ns_head_multipath(ns->head))
|
||||
nvme_cdev_del(&ns->cdev, &ns->cdev_device);
|
||||
del_gendisk(ns->disk);
|
||||
@@ -4480,6 +4493,7 @@ void nvme_start_ctrl(struct nvme_ctrl *ctrl)
|
||||
if (ctrl->queue_count > 1) {
|
||||
nvme_queue_scan(ctrl);
|
||||
nvme_start_queues(ctrl);
|
||||
nvme_mpath_update(ctrl);
|
||||
}
|
||||
|
||||
nvme_change_uevent(ctrl, "NVME_EVENT=connected");
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user