2
0
mirror of https://github.com/edk2-porting/linux-next.git synced 2024-12-23 20:53:53 +08:00

Merge branch 'linus' into sched/core, to pick up fixes

Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
Ingo Molnar 2020-03-06 12:49:56 +01:00
commit 1b10d388d0
265 changed files with 2972 additions and 1680 deletions

4
.gitignore vendored
View File

@ -100,6 +100,10 @@ modules.order
/include/ksym/ /include/ksym/
/arch/*/include/generated/ /arch/*/include/generated/
# Generated lkdtm tests
/tools/testing/selftests/lkdtm/*.sh
!/tools/testing/selftests/lkdtm/run.sh
# stgit generated dirs # stgit generated dirs
patches-* patches-*

View File

@ -567,6 +567,11 @@ D: Original author of Amiga FFS filesystem
S: Orlando, Florida S: Orlando, Florida
S: USA S: USA
N: Paul Burton
E: paulburton@kernel.org
W: https://pburton.com
D: MIPS maintainer 2018-2020
N: Lennert Buytenhek N: Lennert Buytenhek
E: kernel@wantstofly.org E: kernel@wantstofly.org
D: Original (2.4) rewrite of the ethernet bridging code D: Original (2.4) rewrite of the ethernet bridging code

View File

@ -62,6 +62,30 @@ Or more shorter, written as following::
In both styles, same key words are automatically merged when parsing it In both styles, same key words are automatically merged when parsing it
at boot time. So you can append similar trees or key-values. at boot time. So you can append similar trees or key-values.
Same-key Values
---------------
It is prohibited that two or more values or arrays share a same-key.
For example,::
foo = bar, baz
foo = qux # !ERROR! we can not re-define same key
If you want to append the value to existing key as an array member,
you can use ``+=`` operator. For example::
foo = bar, baz
foo += qux
In this case, the key ``foo`` has ``bar``, ``baz`` and ``qux``.
However, a sub-key and a value can not co-exist under a parent key.
For example, following config is NOT allowed.::
foo = value1
foo.bar = value2 # !ERROR! subkey "bar" and value "value1" can NOT co-exist
Comments Comments
-------- --------
@ -102,9 +126,13 @@ Boot Kernel With a Boot Config
============================== ==============================
Since the boot configuration file is loaded with initrd, it will be added Since the boot configuration file is loaded with initrd, it will be added
to the end of the initrd (initramfs) image file. The Linux kernel decodes to the end of the initrd (initramfs) image file with size, checksum and
the last part of the initrd image in memory to get the boot configuration 12-byte magic word as below.
data.
[initrd][bootconfig][size(u32)][checksum(u32)][#BOOTCONFIG\n]
The Linux kernel decodes the last part of the initrd image in memory to
get the boot configuration data.
Because of this "piggyback" method, there is no need to change or Because of this "piggyback" method, there is no need to change or
update the boot loader and the kernel image itself. update the boot loader and the kernel image itself.

View File

@ -136,6 +136,10 @@
dynamic table installation which will install SSDT dynamic table installation which will install SSDT
tables to /sys/firmware/acpi/tables/dynamic. tables to /sys/firmware/acpi/tables/dynamic.
acpi_no_watchdog [HW,ACPI,WDT]
Ignore the ACPI-based watchdog interface (WDAT) and let
a native driver control the watchdog device instead.
acpi_rsdp= [ACPI,EFI,KEXEC] acpi_rsdp= [ACPI,EFI,KEXEC]
Pass the RSDP address to the kernel, mostly used Pass the RSDP address to the kernel, mostly used
on machines running EFI runtime service to boot the on machines running EFI runtime service to boot the

View File

@ -551,6 +551,7 @@ options to your ``.config``:
Once the kernel is built and installed, a simple Once the kernel is built and installed, a simple
.. code-block:: bash .. code-block:: bash
modprobe example-test modprobe example-test
...will run the tests. ...will run the tests.

View File

@ -765,7 +765,7 @@ is not sufficient this sometimes needs to be explicit.
Example:: Example::
#arch/x86/boot/Makefile #arch/x86/boot/Makefile
subdir- := compressed/ subdir- := compressed
The above assignment instructs kbuild to descend down in the The above assignment instructs kbuild to descend down in the
directory compressed/ when "make clean" is executed. directory compressed/ when "make clean" is executed.
@ -1379,9 +1379,6 @@ See subsequent chapter for the syntax of the Kbuild file.
in arch/$(ARCH)/include/(uapi/)/asm, Kbuild will automatically generate in arch/$(ARCH)/include/(uapi/)/asm, Kbuild will automatically generate
a wrapper of the asm-generic one. a wrapper of the asm-generic one.
The convention is to list one subdir per line and
preferably in alphabetic order.
8 Kbuild Variables 8 Kbuild Variables
================== ==================

View File

@ -487,8 +487,9 @@ phy_register_fixup_for_id()::
The stubs set one of the two matching criteria, and set the other one to The stubs set one of the two matching criteria, and set the other one to
match anything. match anything.
When phy_register_fixup() or \*_for_uid()/\*_for_id() is called at module, When phy_register_fixup() or \*_for_uid()/\*_for_id() is called at module load
unregister fixup and free allocate memory are required. time, the module needs to unregister the fixup and free allocated memory when
it's unloaded.
Call one of following function before unloading module:: Call one of following function before unloading module::

View File

@ -13,7 +13,6 @@ Power Management
drivers-testing drivers-testing
energy-model energy-model
freezing-of-tasks freezing-of-tasks
interface
opp opp
pci pci
pm_qos_interface pm_qos_interface

View File

@ -30,4 +30,4 @@ if [ -n "$parallel" ] ; then
parallel="-j$parallel" parallel="-j$parallel"
fi fi
exec "$sphinx" "$parallel" "$@" exec "$sphinx" $parallel "$@"

View File

@ -4611,35 +4611,38 @@ unpins the VPA pages and releases all the device pages that are used to
track the secure pages by hypervisor. track the secure pages by hypervisor.
4.122 KVM_S390_NORMAL_RESET 4.122 KVM_S390_NORMAL_RESET
---------------------------
Capability: KVM_CAP_S390_VCPU_RESETS :Capability: KVM_CAP_S390_VCPU_RESETS
Architectures: s390 :Architectures: s390
Type: vcpu ioctl :Type: vcpu ioctl
Parameters: none :Parameters: none
Returns: 0 :Returns: 0
This ioctl resets VCPU registers and control structures according to This ioctl resets VCPU registers and control structures according to
the cpu reset definition in the POP (Principles Of Operation). the cpu reset definition in the POP (Principles Of Operation).
4.123 KVM_S390_INITIAL_RESET 4.123 KVM_S390_INITIAL_RESET
----------------------------
Capability: none :Capability: none
Architectures: s390 :Architectures: s390
Type: vcpu ioctl :Type: vcpu ioctl
Parameters: none :Parameters: none
Returns: 0 :Returns: 0
This ioctl resets VCPU registers and control structures according to This ioctl resets VCPU registers and control structures according to
the initial cpu reset definition in the POP. However, the cpu is not the initial cpu reset definition in the POP. However, the cpu is not
put into ESA mode. This reset is a superset of the normal reset. put into ESA mode. This reset is a superset of the normal reset.
4.124 KVM_S390_CLEAR_RESET 4.124 KVM_S390_CLEAR_RESET
--------------------------
Capability: KVM_CAP_S390_VCPU_RESETS :Capability: KVM_CAP_S390_VCPU_RESETS
Architectures: s390 :Architectures: s390
Type: vcpu ioctl :Type: vcpu ioctl
Parameters: none :Parameters: none
Returns: 0 :Returns: 0
This ioctl resets VCPU registers and control structures according to This ioctl resets VCPU registers and control structures according to
the clear cpu reset definition in the POP. However, the cpu is not put the clear cpu reset definition in the POP. However, the cpu is not put

View File

@ -19,7 +19,6 @@ x86-specific Documentation
tlb tlb
mtrr mtrr
pat pat
intel_mpx
intel-iommu intel-iommu
intel_txt intel_txt
amd-memory-encryption amd-memory-encryption

View File

@ -11115,14 +11115,12 @@ S: Maintained
F: drivers/usb/image/microtek.* F: drivers/usb/image/microtek.*
MIPS MIPS
M: Ralf Baechle <ralf@linux-mips.org> M: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
M: Paul Burton <paulburton@kernel.org>
L: linux-mips@vger.kernel.org L: linux-mips@vger.kernel.org
W: http://www.linux-mips.org/ W: http://www.linux-mips.org/
T: git git://git.linux-mips.org/pub/scm/ralf/linux.git
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mips/linux.git T: git git://git.kernel.org/pub/scm/linux/kernel/git/mips/linux.git
Q: http://patchwork.linux-mips.org/project/linux-mips/list/ Q: http://patchwork.linux-mips.org/project/linux-mips/list/
S: Supported S: Maintained
F: Documentation/devicetree/bindings/mips/ F: Documentation/devicetree/bindings/mips/
F: Documentation/mips/ F: Documentation/mips/
F: arch/mips/ F: arch/mips/
@ -12741,7 +12739,7 @@ M: Tom Joseph <tjoseph@cadence.com>
L: linux-pci@vger.kernel.org L: linux-pci@vger.kernel.org
S: Maintained S: Maintained
F: Documentation/devicetree/bindings/pci/cdns,*.txt F: Documentation/devicetree/bindings/pci/cdns,*.txt
F: drivers/pci/controller/pcie-cadence* F: drivers/pci/controller/cadence/
PCI DRIVER FOR FREESCALE LAYERSCAPE PCI DRIVER FOR FREESCALE LAYERSCAPE
M: Minghuan Lian <minghuan.Lian@nxp.com> M: Minghuan Lian <minghuan.Lian@nxp.com>

View File

@ -2,7 +2,7 @@
VERSION = 5 VERSION = 5
PATCHLEVEL = 6 PATCHLEVEL = 6
SUBLEVEL = 0 SUBLEVEL = 0
EXTRAVERSION = -rc3 EXTRAVERSION = -rc4
NAME = Kleptomaniac Octopus NAME = Kleptomaniac Octopus
# *DOCUMENTATION* # *DOCUMENTATION*
@ -68,6 +68,7 @@ unexport GREP_OPTIONS
# #
# If KBUILD_VERBOSE equals 0 then the above command will be hidden. # If KBUILD_VERBOSE equals 0 then the above command will be hidden.
# If KBUILD_VERBOSE equals 1 then the above command is displayed. # If KBUILD_VERBOSE equals 1 then the above command is displayed.
# If KBUILD_VERBOSE equals 2 then give the reason why each target is rebuilt.
# #
# To put more focus on warnings, be less verbose as default # To put more focus on warnings, be less verbose as default
# Use 'make V=1' to see the full commands # Use 'make V=1' to see the full commands
@ -1238,7 +1239,7 @@ ifneq ($(dtstree),)
%.dtb: include/config/kernel.release scripts_dtc %.dtb: include/config/kernel.release scripts_dtc
$(Q)$(MAKE) $(build)=$(dtstree) $(dtstree)/$@ $(Q)$(MAKE) $(build)=$(dtstree) $(dtstree)/$@
PHONY += dtbs dtbs_install dt_binding_check PHONY += dtbs dtbs_install dtbs_check
dtbs dtbs_check: include/config/kernel.release scripts_dtc dtbs dtbs_check: include/config/kernel.release scripts_dtc
$(Q)$(MAKE) $(build)=$(dtstree) $(Q)$(MAKE) $(build)=$(dtstree)
@ -1258,6 +1259,7 @@ PHONY += scripts_dtc
scripts_dtc: scripts_basic scripts_dtc: scripts_basic
$(Q)$(MAKE) $(build)=scripts/dtc $(Q)$(MAKE) $(build)=scripts/dtc
PHONY += dt_binding_check
dt_binding_check: scripts_dtc dt_binding_check: scripts_dtc
$(Q)$(MAKE) $(build)=Documentation/devicetree/bindings $(Q)$(MAKE) $(build)=Documentation/devicetree/bindings

View File

@ -392,9 +392,6 @@ static inline void kvm_arch_vcpu_put_fp(struct kvm_vcpu *vcpu) {}
static inline void kvm_vcpu_pmu_restore_guest(struct kvm_vcpu *vcpu) {} static inline void kvm_vcpu_pmu_restore_guest(struct kvm_vcpu *vcpu) {}
static inline void kvm_vcpu_pmu_restore_host(struct kvm_vcpu *vcpu) {} static inline void kvm_vcpu_pmu_restore_host(struct kvm_vcpu *vcpu) {}
static inline void kvm_arm_vhe_guest_enter(void) {}
static inline void kvm_arm_vhe_guest_exit(void) {}
#define KVM_BP_HARDEN_UNKNOWN -1 #define KVM_BP_HARDEN_UNKNOWN -1
#define KVM_BP_HARDEN_WA_NEEDED 0 #define KVM_BP_HARDEN_WA_NEEDED 0
#define KVM_BP_HARDEN_NOT_REQUIRED 1 #define KVM_BP_HARDEN_NOT_REQUIRED 1

View File

@ -32,7 +32,7 @@ static inline void gic_write_eoir(u32 irq)
isb(); isb();
} }
static inline void gic_write_dir(u32 irq) static __always_inline void gic_write_dir(u32 irq)
{ {
write_sysreg_s(irq, SYS_ICC_DIR_EL1); write_sysreg_s(irq, SYS_ICC_DIR_EL1);
isb(); isb();

View File

@ -69,7 +69,7 @@ static inline int icache_is_aliasing(void)
return test_bit(ICACHEF_ALIASING, &__icache_flags); return test_bit(ICACHEF_ALIASING, &__icache_flags);
} }
static inline int icache_is_vpipt(void) static __always_inline int icache_is_vpipt(void)
{ {
return test_bit(ICACHEF_VPIPT, &__icache_flags); return test_bit(ICACHEF_VPIPT, &__icache_flags);
} }

View File

@ -145,7 +145,7 @@ extern void copy_to_user_page(struct vm_area_struct *, struct page *,
#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1 #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1
extern void flush_dcache_page(struct page *); extern void flush_dcache_page(struct page *);
static inline void __flush_icache_all(void) static __always_inline void __flush_icache_all(void)
{ {
if (cpus_have_const_cap(ARM64_HAS_CACHE_DIC)) if (cpus_have_const_cap(ARM64_HAS_CACHE_DIC))
return; return;

View File

@ -435,13 +435,13 @@ cpuid_feature_extract_signed_field(u64 features, int field)
return cpuid_feature_extract_signed_field_width(features, field, 4); return cpuid_feature_extract_signed_field_width(features, field, 4);
} }
static inline unsigned int __attribute_const__ static __always_inline unsigned int __attribute_const__
cpuid_feature_extract_unsigned_field_width(u64 features, int field, int width) cpuid_feature_extract_unsigned_field_width(u64 features, int field, int width)
{ {
return (u64)(features << (64 - width - field)) >> (64 - width); return (u64)(features << (64 - width - field)) >> (64 - width);
} }
static inline unsigned int __attribute_const__ static __always_inline unsigned int __attribute_const__
cpuid_feature_extract_unsigned_field(u64 features, int field) cpuid_feature_extract_unsigned_field(u64 features, int field)
{ {
return cpuid_feature_extract_unsigned_field_width(features, field, 4); return cpuid_feature_extract_unsigned_field_width(features, field, 4);
@ -564,7 +564,7 @@ static inline bool system_supports_mixed_endian(void)
return val == 0x1; return val == 0x1;
} }
static inline bool system_supports_fpsimd(void) static __always_inline bool system_supports_fpsimd(void)
{ {
return !cpus_have_const_cap(ARM64_HAS_NO_FPSIMD); return !cpus_have_const_cap(ARM64_HAS_NO_FPSIMD);
} }
@ -575,13 +575,13 @@ static inline bool system_uses_ttbr0_pan(void)
!cpus_have_const_cap(ARM64_HAS_PAN); !cpus_have_const_cap(ARM64_HAS_PAN);
} }
static inline bool system_supports_sve(void) static __always_inline bool system_supports_sve(void)
{ {
return IS_ENABLED(CONFIG_ARM64_SVE) && return IS_ENABLED(CONFIG_ARM64_SVE) &&
cpus_have_const_cap(ARM64_SVE); cpus_have_const_cap(ARM64_SVE);
} }
static inline bool system_supports_cnp(void) static __always_inline bool system_supports_cnp(void)
{ {
return IS_ENABLED(CONFIG_ARM64_CNP) && return IS_ENABLED(CONFIG_ARM64_CNP) &&
cpus_have_const_cap(ARM64_HAS_CNP); cpus_have_const_cap(ARM64_HAS_CNP);

View File

@ -34,7 +34,7 @@ static inline void __raw_writew(u16 val, volatile void __iomem *addr)
} }
#define __raw_writel __raw_writel #define __raw_writel __raw_writel
static inline void __raw_writel(u32 val, volatile void __iomem *addr) static __always_inline void __raw_writel(u32 val, volatile void __iomem *addr)
{ {
asm volatile("str %w0, [%1]" : : "rZ" (val), "r" (addr)); asm volatile("str %w0, [%1]" : : "rZ" (val), "r" (addr));
} }
@ -69,7 +69,7 @@ static inline u16 __raw_readw(const volatile void __iomem *addr)
} }
#define __raw_readl __raw_readl #define __raw_readl __raw_readl
static inline u32 __raw_readl(const volatile void __iomem *addr) static __always_inline u32 __raw_readl(const volatile void __iomem *addr)
{ {
u32 val; u32 val;
asm volatile(ALTERNATIVE("ldr %w0, [%1]", asm volatile(ALTERNATIVE("ldr %w0, [%1]",

View File

@ -36,7 +36,7 @@ void kvm_inject_undef32(struct kvm_vcpu *vcpu);
void kvm_inject_dabt32(struct kvm_vcpu *vcpu, unsigned long addr); void kvm_inject_dabt32(struct kvm_vcpu *vcpu, unsigned long addr);
void kvm_inject_pabt32(struct kvm_vcpu *vcpu, unsigned long addr); void kvm_inject_pabt32(struct kvm_vcpu *vcpu, unsigned long addr);
static inline bool vcpu_el1_is_32bit(struct kvm_vcpu *vcpu) static __always_inline bool vcpu_el1_is_32bit(struct kvm_vcpu *vcpu)
{ {
return !(vcpu->arch.hcr_el2 & HCR_RW); return !(vcpu->arch.hcr_el2 & HCR_RW);
} }
@ -127,7 +127,7 @@ static inline void vcpu_set_vsesr(struct kvm_vcpu *vcpu, u64 vsesr)
vcpu->arch.vsesr_el2 = vsesr; vcpu->arch.vsesr_el2 = vsesr;
} }
static inline unsigned long *vcpu_pc(const struct kvm_vcpu *vcpu) static __always_inline unsigned long *vcpu_pc(const struct kvm_vcpu *vcpu)
{ {
return (unsigned long *)&vcpu_gp_regs(vcpu)->regs.pc; return (unsigned long *)&vcpu_gp_regs(vcpu)->regs.pc;
} }
@ -153,17 +153,17 @@ static inline void vcpu_write_elr_el1(const struct kvm_vcpu *vcpu, unsigned long
*__vcpu_elr_el1(vcpu) = v; *__vcpu_elr_el1(vcpu) = v;
} }
static inline unsigned long *vcpu_cpsr(const struct kvm_vcpu *vcpu) static __always_inline unsigned long *vcpu_cpsr(const struct kvm_vcpu *vcpu)
{ {
return (unsigned long *)&vcpu_gp_regs(vcpu)->regs.pstate; return (unsigned long *)&vcpu_gp_regs(vcpu)->regs.pstate;
} }
static inline bool vcpu_mode_is_32bit(const struct kvm_vcpu *vcpu) static __always_inline bool vcpu_mode_is_32bit(const struct kvm_vcpu *vcpu)
{ {
return !!(*vcpu_cpsr(vcpu) & PSR_MODE32_BIT); return !!(*vcpu_cpsr(vcpu) & PSR_MODE32_BIT);
} }
static inline bool kvm_condition_valid(const struct kvm_vcpu *vcpu) static __always_inline bool kvm_condition_valid(const struct kvm_vcpu *vcpu)
{ {
if (vcpu_mode_is_32bit(vcpu)) if (vcpu_mode_is_32bit(vcpu))
return kvm_condition_valid32(vcpu); return kvm_condition_valid32(vcpu);
@ -181,13 +181,13 @@ static inline void vcpu_set_thumb(struct kvm_vcpu *vcpu)
* coming from a read of ESR_EL2. Otherwise, it may give the wrong result on * coming from a read of ESR_EL2. Otherwise, it may give the wrong result on
* AArch32 with banked registers. * AArch32 with banked registers.
*/ */
static inline unsigned long vcpu_get_reg(const struct kvm_vcpu *vcpu, static __always_inline unsigned long vcpu_get_reg(const struct kvm_vcpu *vcpu,
u8 reg_num) u8 reg_num)
{ {
return (reg_num == 31) ? 0 : vcpu_gp_regs(vcpu)->regs.regs[reg_num]; return (reg_num == 31) ? 0 : vcpu_gp_regs(vcpu)->regs.regs[reg_num];
} }
static inline void vcpu_set_reg(struct kvm_vcpu *vcpu, u8 reg_num, static __always_inline void vcpu_set_reg(struct kvm_vcpu *vcpu, u8 reg_num,
unsigned long val) unsigned long val)
{ {
if (reg_num != 31) if (reg_num != 31)
@ -264,12 +264,12 @@ static inline bool vcpu_mode_priv(const struct kvm_vcpu *vcpu)
return mode != PSR_MODE_EL0t; return mode != PSR_MODE_EL0t;
} }
static inline u32 kvm_vcpu_get_hsr(const struct kvm_vcpu *vcpu) static __always_inline u32 kvm_vcpu_get_hsr(const struct kvm_vcpu *vcpu)
{ {
return vcpu->arch.fault.esr_el2; return vcpu->arch.fault.esr_el2;
} }
static inline int kvm_vcpu_get_condition(const struct kvm_vcpu *vcpu) static __always_inline int kvm_vcpu_get_condition(const struct kvm_vcpu *vcpu)
{ {
u32 esr = kvm_vcpu_get_hsr(vcpu); u32 esr = kvm_vcpu_get_hsr(vcpu);
@ -279,12 +279,12 @@ static inline int kvm_vcpu_get_condition(const struct kvm_vcpu *vcpu)
return -1; return -1;
} }
static inline unsigned long kvm_vcpu_get_hfar(const struct kvm_vcpu *vcpu) static __always_inline unsigned long kvm_vcpu_get_hfar(const struct kvm_vcpu *vcpu)
{ {
return vcpu->arch.fault.far_el2; return vcpu->arch.fault.far_el2;
} }
static inline phys_addr_t kvm_vcpu_get_fault_ipa(const struct kvm_vcpu *vcpu) static __always_inline phys_addr_t kvm_vcpu_get_fault_ipa(const struct kvm_vcpu *vcpu)
{ {
return ((phys_addr_t)vcpu->arch.fault.hpfar_el2 & HPFAR_MASK) << 8; return ((phys_addr_t)vcpu->arch.fault.hpfar_el2 & HPFAR_MASK) << 8;
} }
@ -299,7 +299,7 @@ static inline u32 kvm_vcpu_hvc_get_imm(const struct kvm_vcpu *vcpu)
return kvm_vcpu_get_hsr(vcpu) & ESR_ELx_xVC_IMM_MASK; return kvm_vcpu_get_hsr(vcpu) & ESR_ELx_xVC_IMM_MASK;
} }
static inline bool kvm_vcpu_dabt_isvalid(const struct kvm_vcpu *vcpu) static __always_inline bool kvm_vcpu_dabt_isvalid(const struct kvm_vcpu *vcpu)
{ {
return !!(kvm_vcpu_get_hsr(vcpu) & ESR_ELx_ISV); return !!(kvm_vcpu_get_hsr(vcpu) & ESR_ELx_ISV);
} }
@ -319,17 +319,17 @@ static inline bool kvm_vcpu_dabt_issf(const struct kvm_vcpu *vcpu)
return !!(kvm_vcpu_get_hsr(vcpu) & ESR_ELx_SF); return !!(kvm_vcpu_get_hsr(vcpu) & ESR_ELx_SF);
} }
static inline int kvm_vcpu_dabt_get_rd(const struct kvm_vcpu *vcpu) static __always_inline int kvm_vcpu_dabt_get_rd(const struct kvm_vcpu *vcpu)
{ {
return (kvm_vcpu_get_hsr(vcpu) & ESR_ELx_SRT_MASK) >> ESR_ELx_SRT_SHIFT; return (kvm_vcpu_get_hsr(vcpu) & ESR_ELx_SRT_MASK) >> ESR_ELx_SRT_SHIFT;
} }
static inline bool kvm_vcpu_dabt_iss1tw(const struct kvm_vcpu *vcpu) static __always_inline bool kvm_vcpu_dabt_iss1tw(const struct kvm_vcpu *vcpu)
{ {
return !!(kvm_vcpu_get_hsr(vcpu) & ESR_ELx_S1PTW); return !!(kvm_vcpu_get_hsr(vcpu) & ESR_ELx_S1PTW);
} }
static inline bool kvm_vcpu_dabt_iswrite(const struct kvm_vcpu *vcpu) static __always_inline bool kvm_vcpu_dabt_iswrite(const struct kvm_vcpu *vcpu)
{ {
return !!(kvm_vcpu_get_hsr(vcpu) & ESR_ELx_WNR) || return !!(kvm_vcpu_get_hsr(vcpu) & ESR_ELx_WNR) ||
kvm_vcpu_dabt_iss1tw(vcpu); /* AF/DBM update */ kvm_vcpu_dabt_iss1tw(vcpu); /* AF/DBM update */
@ -340,18 +340,18 @@ static inline bool kvm_vcpu_dabt_is_cm(const struct kvm_vcpu *vcpu)
return !!(kvm_vcpu_get_hsr(vcpu) & ESR_ELx_CM); return !!(kvm_vcpu_get_hsr(vcpu) & ESR_ELx_CM);
} }
static inline unsigned int kvm_vcpu_dabt_get_as(const struct kvm_vcpu *vcpu) static __always_inline unsigned int kvm_vcpu_dabt_get_as(const struct kvm_vcpu *vcpu)
{ {
return 1 << ((kvm_vcpu_get_hsr(vcpu) & ESR_ELx_SAS) >> ESR_ELx_SAS_SHIFT); return 1 << ((kvm_vcpu_get_hsr(vcpu) & ESR_ELx_SAS) >> ESR_ELx_SAS_SHIFT);
} }
/* This one is not specific to Data Abort */ /* This one is not specific to Data Abort */
static inline bool kvm_vcpu_trap_il_is32bit(const struct kvm_vcpu *vcpu) static __always_inline bool kvm_vcpu_trap_il_is32bit(const struct kvm_vcpu *vcpu)
{ {
return !!(kvm_vcpu_get_hsr(vcpu) & ESR_ELx_IL); return !!(kvm_vcpu_get_hsr(vcpu) & ESR_ELx_IL);
} }
static inline u8 kvm_vcpu_trap_get_class(const struct kvm_vcpu *vcpu) static __always_inline u8 kvm_vcpu_trap_get_class(const struct kvm_vcpu *vcpu)
{ {
return ESR_ELx_EC(kvm_vcpu_get_hsr(vcpu)); return ESR_ELx_EC(kvm_vcpu_get_hsr(vcpu));
} }
@ -361,17 +361,17 @@ static inline bool kvm_vcpu_trap_is_iabt(const struct kvm_vcpu *vcpu)
return kvm_vcpu_trap_get_class(vcpu) == ESR_ELx_EC_IABT_LOW; return kvm_vcpu_trap_get_class(vcpu) == ESR_ELx_EC_IABT_LOW;
} }
static inline u8 kvm_vcpu_trap_get_fault(const struct kvm_vcpu *vcpu) static __always_inline u8 kvm_vcpu_trap_get_fault(const struct kvm_vcpu *vcpu)
{ {
return kvm_vcpu_get_hsr(vcpu) & ESR_ELx_FSC; return kvm_vcpu_get_hsr(vcpu) & ESR_ELx_FSC;
} }
static inline u8 kvm_vcpu_trap_get_fault_type(const struct kvm_vcpu *vcpu) static __always_inline u8 kvm_vcpu_trap_get_fault_type(const struct kvm_vcpu *vcpu)
{ {
return kvm_vcpu_get_hsr(vcpu) & ESR_ELx_FSC_TYPE; return kvm_vcpu_get_hsr(vcpu) & ESR_ELx_FSC_TYPE;
} }
static inline bool kvm_vcpu_dabt_isextabt(const struct kvm_vcpu *vcpu) static __always_inline bool kvm_vcpu_dabt_isextabt(const struct kvm_vcpu *vcpu)
{ {
switch (kvm_vcpu_trap_get_fault(vcpu)) { switch (kvm_vcpu_trap_get_fault(vcpu)) {
case FSC_SEA: case FSC_SEA:
@ -390,7 +390,7 @@ static inline bool kvm_vcpu_dabt_isextabt(const struct kvm_vcpu *vcpu)
} }
} }
static inline int kvm_vcpu_sys_get_rt(struct kvm_vcpu *vcpu) static __always_inline int kvm_vcpu_sys_get_rt(struct kvm_vcpu *vcpu)
{ {
u32 esr = kvm_vcpu_get_hsr(vcpu); u32 esr = kvm_vcpu_get_hsr(vcpu);
return ESR_ELx_SYS64_ISS_RT(esr); return ESR_ELx_SYS64_ISS_RT(esr);
@ -504,7 +504,7 @@ static inline unsigned long vcpu_data_host_to_guest(struct kvm_vcpu *vcpu,
return data; /* Leave LE untouched */ return data; /* Leave LE untouched */
} }
static inline void kvm_skip_instr(struct kvm_vcpu *vcpu, bool is_wide_instr) static __always_inline void kvm_skip_instr(struct kvm_vcpu *vcpu, bool is_wide_instr)
{ {
if (vcpu_mode_is_32bit(vcpu)) if (vcpu_mode_is_32bit(vcpu))
kvm_skip_instr32(vcpu, is_wide_instr); kvm_skip_instr32(vcpu, is_wide_instr);
@ -519,7 +519,7 @@ static inline void kvm_skip_instr(struct kvm_vcpu *vcpu, bool is_wide_instr)
* Skip an instruction which has been emulated at hyp while most guest sysregs * Skip an instruction which has been emulated at hyp while most guest sysregs
* are live. * are live.
*/ */
static inline void __hyp_text __kvm_skip_instr(struct kvm_vcpu *vcpu) static __always_inline void __hyp_text __kvm_skip_instr(struct kvm_vcpu *vcpu)
{ {
*vcpu_pc(vcpu) = read_sysreg_el2(SYS_ELR); *vcpu_pc(vcpu) = read_sysreg_el2(SYS_ELR);
vcpu->arch.ctxt.gp_regs.regs.pstate = read_sysreg_el2(SYS_SPSR); vcpu->arch.ctxt.gp_regs.regs.pstate = read_sysreg_el2(SYS_SPSR);

View File

@ -626,38 +626,6 @@ static inline void kvm_set_pmu_events(u32 set, struct perf_event_attr *attr) {}
static inline void kvm_clr_pmu_events(u32 clr) {} static inline void kvm_clr_pmu_events(u32 clr) {}
#endif #endif
static inline void kvm_arm_vhe_guest_enter(void)
{
local_daif_mask();
/*
* Having IRQs masked via PMR when entering the guest means the GIC
* will not signal the CPU of interrupts of lower priority, and the
* only way to get out will be via guest exceptions.
* Naturally, we want to avoid this.
*
* local_daif_mask() already sets GIC_PRIO_PSR_I_SET, we just need a
* dsb to ensure the redistributor is forwards EL2 IRQs to the CPU.
*/
pmr_sync();
}
static inline void kvm_arm_vhe_guest_exit(void)
{
/*
* local_daif_restore() takes care to properly restore PSTATE.DAIF
* and the GIC PMR if the host is using IRQ priorities.
*/
local_daif_restore(DAIF_PROCCTX_NOIRQ);
/*
* When we exit from the guest we change a number of CPU configuration
* parameters, such as traps. Make sure these changes take effect
* before running the host or additional guests.
*/
isb();
}
#define KVM_BP_HARDEN_UNKNOWN -1 #define KVM_BP_HARDEN_UNKNOWN -1
#define KVM_BP_HARDEN_WA_NEEDED 0 #define KVM_BP_HARDEN_WA_NEEDED 0
#define KVM_BP_HARDEN_NOT_REQUIRED 1 #define KVM_BP_HARDEN_NOT_REQUIRED 1

View File

@ -47,6 +47,13 @@
#define read_sysreg_el2(r) read_sysreg_elx(r, _EL2, _EL1) #define read_sysreg_el2(r) read_sysreg_elx(r, _EL2, _EL1)
#define write_sysreg_el2(v,r) write_sysreg_elx(v, r, _EL2, _EL1) #define write_sysreg_el2(v,r) write_sysreg_elx(v, r, _EL2, _EL1)
/*
* Without an __arch_swab32(), we fall back to ___constant_swab32(), but the
* static inline can allow the compiler to out-of-line this. KVM always wants
* the macro version as its always inlined.
*/
#define __kvm_swab32(x) ___constant_swab32(x)
int __vgic_v2_perform_cpuif_access(struct kvm_vcpu *vcpu); int __vgic_v2_perform_cpuif_access(struct kvm_vcpu *vcpu);
void __vgic_v3_save_state(struct kvm_vcpu *vcpu); void __vgic_v3_save_state(struct kvm_vcpu *vcpu);

View File

@ -93,7 +93,7 @@ void kvm_update_va_mask(struct alt_instr *alt,
__le32 *origptr, __le32 *updptr, int nr_inst); __le32 *origptr, __le32 *updptr, int nr_inst);
void kvm_compute_layout(void); void kvm_compute_layout(void);
static inline unsigned long __kern_hyp_va(unsigned long v) static __always_inline unsigned long __kern_hyp_va(unsigned long v)
{ {
asm volatile(ALTERNATIVE_CB("and %0, %0, #1\n" asm volatile(ALTERNATIVE_CB("and %0, %0, #1\n"
"ror %0, %0, #1\n" "ror %0, %0, #1\n"
@ -473,6 +473,7 @@ static inline int kvm_write_guest_lock(struct kvm *kvm, gpa_t gpa,
extern void *__kvm_bp_vect_base; extern void *__kvm_bp_vect_base;
extern int __kvm_harden_el2_vector_slot; extern int __kvm_harden_el2_vector_slot;
/* This is only called on a VHE system */
static inline void *kvm_get_hyp_vector(void) static inline void *kvm_get_hyp_vector(void)
{ {
struct bp_hardening_data *data = arm64_get_bp_hardening_data(); struct bp_hardening_data *data = arm64_get_bp_hardening_data();

View File

@ -83,7 +83,7 @@ static inline bool is_kernel_in_hyp_mode(void)
return read_sysreg(CurrentEL) == CurrentEL_EL2; return read_sysreg(CurrentEL) == CurrentEL_EL2;
} }
static inline bool has_vhe(void) static __always_inline bool has_vhe(void)
{ {
if (cpus_have_const_cap(ARM64_HAS_VIRT_HOST_EXTN)) if (cpus_have_const_cap(ARM64_HAS_VIRT_HOST_EXTN))
return true; return true;

View File

@ -625,7 +625,7 @@ static void __hyp_text __pmu_switch_to_host(struct kvm_cpu_context *host_ctxt)
} }
/* Switch to the guest for VHE systems running in EL2 */ /* Switch to the guest for VHE systems running in EL2 */
int kvm_vcpu_run_vhe(struct kvm_vcpu *vcpu) static int __kvm_vcpu_run_vhe(struct kvm_vcpu *vcpu)
{ {
struct kvm_cpu_context *host_ctxt; struct kvm_cpu_context *host_ctxt;
struct kvm_cpu_context *guest_ctxt; struct kvm_cpu_context *guest_ctxt;
@ -678,7 +678,42 @@ int kvm_vcpu_run_vhe(struct kvm_vcpu *vcpu)
return exit_code; return exit_code;
} }
NOKPROBE_SYMBOL(kvm_vcpu_run_vhe); NOKPROBE_SYMBOL(__kvm_vcpu_run_vhe);
int kvm_vcpu_run_vhe(struct kvm_vcpu *vcpu)
{
int ret;
local_daif_mask();
/*
* Having IRQs masked via PMR when entering the guest means the GIC
* will not signal the CPU of interrupts of lower priority, and the
* only way to get out will be via guest exceptions.
* Naturally, we want to avoid this.
*
* local_daif_mask() already sets GIC_PRIO_PSR_I_SET, we just need a
* dsb to ensure the redistributor is forwards EL2 IRQs to the CPU.
*/
pmr_sync();
ret = __kvm_vcpu_run_vhe(vcpu);
/*
* local_daif_restore() takes care to properly restore PSTATE.DAIF
* and the GIC PMR if the host is using IRQ priorities.
*/
local_daif_restore(DAIF_PROCCTX_NOIRQ);
/*
* When we exit from the guest we change a number of CPU configuration
* parameters, such as traps. Make sure these changes take effect
* before running the host or additional guests.
*/
isb();
return ret;
}
/* Switch to the guest for legacy non-VHE systems */ /* Switch to the guest for legacy non-VHE systems */
int __hyp_text __kvm_vcpu_run_nvhe(struct kvm_vcpu *vcpu) int __hyp_text __kvm_vcpu_run_nvhe(struct kvm_vcpu *vcpu)

View File

@ -69,14 +69,14 @@ int __hyp_text __vgic_v2_perform_cpuif_access(struct kvm_vcpu *vcpu)
u32 data = vcpu_get_reg(vcpu, rd); u32 data = vcpu_get_reg(vcpu, rd);
if (__is_be(vcpu)) { if (__is_be(vcpu)) {
/* guest pre-swabbed data, undo this for writel() */ /* guest pre-swabbed data, undo this for writel() */
data = swab32(data); data = __kvm_swab32(data);
} }
writel_relaxed(data, addr); writel_relaxed(data, addr);
} else { } else {
u32 data = readl_relaxed(addr); u32 data = readl_relaxed(addr);
if (__is_be(vcpu)) { if (__is_be(vcpu)) {
/* guest expects swabbed data */ /* guest expects swabbed data */
data = swab32(data); data = __kvm_swab32(data);
} }
vcpu_set_reg(vcpu, rd, data); vcpu_set_reg(vcpu, rd, data);
} }

View File

@ -1,5 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 // SPDX-License-Identifier: GPL-2.0
#include <dt-bindings/clock/jz4740-cgu.h> #include <dt-bindings/clock/jz4740-cgu.h>
#include <dt-bindings/clock/ingenic,tcu.h>
/ { / {
#address-cells = <1>; #address-cells = <1>;
@ -45,14 +46,6 @@
#clock-cells = <1>; #clock-cells = <1>;
}; };
watchdog: watchdog@10002000 {
compatible = "ingenic,jz4740-watchdog";
reg = <0x10002000 0x10>;
clocks = <&cgu JZ4740_CLK_RTC>;
clock-names = "rtc";
};
tcu: timer@10002000 { tcu: timer@10002000 {
compatible = "ingenic,jz4740-tcu", "simple-mfd"; compatible = "ingenic,jz4740-tcu", "simple-mfd";
reg = <0x10002000 0x1000>; reg = <0x10002000 0x1000>;
@ -73,6 +66,14 @@
interrupt-parent = <&intc>; interrupt-parent = <&intc>;
interrupts = <23 22 21>; interrupts = <23 22 21>;
watchdog: watchdog@0 {
compatible = "ingenic,jz4740-watchdog";
reg = <0x0 0xc>;
clocks = <&tcu TCU_CLK_WDT>;
clock-names = "wdt";
};
}; };
rtc_dev: rtc@10003000 { rtc_dev: rtc@10003000 {

View File

@ -1,5 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 // SPDX-License-Identifier: GPL-2.0
#include <dt-bindings/clock/jz4780-cgu.h> #include <dt-bindings/clock/jz4780-cgu.h>
#include <dt-bindings/clock/ingenic,tcu.h>
#include <dt-bindings/dma/jz4780-dma.h> #include <dt-bindings/dma/jz4780-dma.h>
/ { / {
@ -67,6 +68,14 @@
interrupt-parent = <&intc>; interrupt-parent = <&intc>;
interrupts = <27 26 25>; interrupts = <27 26 25>;
watchdog: watchdog@0 {
compatible = "ingenic,jz4780-watchdog";
reg = <0x0 0xc>;
clocks = <&tcu TCU_CLK_WDT>;
clock-names = "wdt";
};
}; };
rtc_dev: rtc@10003000 { rtc_dev: rtc@10003000 {
@ -348,14 +357,6 @@
status = "disabled"; status = "disabled";
}; };
watchdog: watchdog@10002000 {
compatible = "ingenic,jz4780-watchdog";
reg = <0x10002000 0x10>;
clocks = <&cgu JZ4780_CLK_RTCLK>;
clock-names = "rtc";
};
nemc: nemc@13410000 { nemc: nemc@13410000 {
compatible = "ingenic,jz4780-nemc"; compatible = "ingenic,jz4780-nemc";
reg = <0x13410000 0x10000>; reg = <0x13410000 0x10000>;

View File

@ -1,4 +1,5 @@
// SPDX-License-Identifier: GPL-2.0 // SPDX-License-Identifier: GPL-2.0
#include <dt-bindings/clock/ingenic,tcu.h>
#include <dt-bindings/clock/x1000-cgu.h> #include <dt-bindings/clock/x1000-cgu.h>
#include <dt-bindings/dma/x1000-dma.h> #include <dt-bindings/dma/x1000-dma.h>
@ -72,7 +73,7 @@
compatible = "ingenic,x1000-watchdog", "ingenic,jz4780-watchdog"; compatible = "ingenic,x1000-watchdog", "ingenic,jz4780-watchdog";
reg = <0x0 0x10>; reg = <0x0 0x10>;
clocks = <&cgu X1000_CLK_RTCLK>; clocks = <&tcu TCU_CLK_WDT>;
clock-names = "wdt"; clock-names = "wdt";
}; };
}; };
@ -158,7 +159,6 @@
i2c0: i2c-controller@10050000 { i2c0: i2c-controller@10050000 {
compatible = "ingenic,x1000-i2c"; compatible = "ingenic,x1000-i2c";
reg = <0x10050000 0x1000>; reg = <0x10050000 0x1000>;
#address-cells = <1>; #address-cells = <1>;
#size-cells = <0>; #size-cells = <0>;
@ -173,7 +173,6 @@
i2c1: i2c-controller@10051000 { i2c1: i2c-controller@10051000 {
compatible = "ingenic,x1000-i2c"; compatible = "ingenic,x1000-i2c";
reg = <0x10051000 0x1000>; reg = <0x10051000 0x1000>;
#address-cells = <1>; #address-cells = <1>;
#size-cells = <0>; #size-cells = <0>;
@ -188,7 +187,6 @@
i2c2: i2c-controller@10052000 { i2c2: i2c-controller@10052000 {
compatible = "ingenic,x1000-i2c"; compatible = "ingenic,x1000-i2c";
reg = <0x10052000 0x1000>; reg = <0x10052000 0x1000>;
#address-cells = <1>; #address-cells = <1>;
#size-cells = <0>; #size-cells = <0>;

View File

@ -155,9 +155,11 @@
* effective barrier as noted by commit 6b07d38aaa52 ("MIPS: Octeon: Use * effective barrier as noted by commit 6b07d38aaa52 ("MIPS: Octeon: Use
* optimized memory barrier primitives."). Here we specify that the affected * optimized memory barrier primitives."). Here we specify that the affected
* sync instructions should be emitted twice. * sync instructions should be emitted twice.
* Note that this expression is evaluated by the assembler (not the compiler),
* and that the assembler evaluates '==' as 0 or -1, not 0 or 1.
*/ */
#ifdef CONFIG_CPU_CAVIUM_OCTEON #ifdef CONFIG_CPU_CAVIUM_OCTEON
# define __SYNC_rpt(type) (1 + (type == __SYNC_wmb)) # define __SYNC_rpt(type) (1 - (type == __SYNC_wmb))
#else #else
# define __SYNC_rpt(type) 1 # define __SYNC_rpt(type) 1
#endif #endif

View File

@ -134,7 +134,7 @@ void release_vpe(struct vpe *v)
{ {
list_del(&v->list); list_del(&v->list);
if (v->load_addr) if (v->load_addr)
release_progmem(v); release_progmem(v->load_addr);
kfree(v); kfree(v);
} }

View File

@ -33,6 +33,7 @@ endif
cflags-vdso := $(ccflags-vdso) \ cflags-vdso := $(ccflags-vdso) \
$(filter -W%,$(filter-out -Wa$(comma)%,$(KBUILD_CFLAGS))) \ $(filter -W%,$(filter-out -Wa$(comma)%,$(KBUILD_CFLAGS))) \
-O3 -g -fPIC -fno-strict-aliasing -fno-common -fno-builtin -G 0 \ -O3 -g -fPIC -fno-strict-aliasing -fno-common -fno-builtin -G 0 \
-mrelax-pic-calls $(call cc-option, -mexplicit-relocs) \
-fno-stack-protector -fno-jump-tables -DDISABLE_BRANCH_PROFILING \ -fno-stack-protector -fno-jump-tables -DDISABLE_BRANCH_PROFILING \
$(call cc-option, -fno-asynchronous-unwind-tables) \ $(call cc-option, -fno-asynchronous-unwind-tables) \
$(call cc-option, -fno-stack-protector) $(call cc-option, -fno-stack-protector)
@ -51,6 +52,8 @@ endif
CFLAGS_REMOVE_vgettimeofday.o = -pg CFLAGS_REMOVE_vgettimeofday.o = -pg
DISABLE_VDSO := n
# #
# For the pre-R6 code in arch/mips/vdso/vdso.h for locating # For the pre-R6 code in arch/mips/vdso/vdso.h for locating
# the base address of VDSO, the linker will emit a R_MIPS_PC32 # the base address of VDSO, the linker will emit a R_MIPS_PC32
@ -64,11 +67,24 @@ CFLAGS_REMOVE_vgettimeofday.o = -pg
ifndef CONFIG_CPU_MIPSR6 ifndef CONFIG_CPU_MIPSR6
ifeq ($(call ld-ifversion, -lt, 225000000, y),y) ifeq ($(call ld-ifversion, -lt, 225000000, y),y)
$(warning MIPS VDSO requires binutils >= 2.25) $(warning MIPS VDSO requires binutils >= 2.25)
obj-vdso-y := $(filter-out vgettimeofday.o, $(obj-vdso-y)) DISABLE_VDSO := y
ccflags-vdso += -DDISABLE_MIPS_VDSO
endif endif
endif endif
#
# GCC (at least up to version 9.2) appears to emit function calls that make use
# of the GOT when targeting microMIPS, which we can't use in the VDSO due to
# the lack of relocations. As such, we disable the VDSO for microMIPS builds.
#
ifdef CONFIG_CPU_MICROMIPS
DISABLE_VDSO := y
endif
ifeq ($(DISABLE_VDSO),y)
obj-vdso-y := $(filter-out vgettimeofday.o, $(obj-vdso-y))
ccflags-vdso += -DDISABLE_MIPS_VDSO
endif
# VDSO linker flags. # VDSO linker flags.
VDSO_LDFLAGS := \ VDSO_LDFLAGS := \
-Wl,-Bsymbolic -Wl,--no-undefined -Wl,-soname=linux-vdso.so.1 \ -Wl,-Bsymbolic -Wl,--no-undefined -Wl,-soname=linux-vdso.so.1 \
@ -81,12 +97,18 @@ GCOV_PROFILE := n
UBSAN_SANITIZE := n UBSAN_SANITIZE := n
KCOV_INSTRUMENT := n KCOV_INSTRUMENT := n
# Check that we don't have PIC 'jalr t9' calls left
quiet_cmd_vdso_mips_check = VDSOCHK $@
cmd_vdso_mips_check = if $(OBJDUMP) --disassemble $@ | egrep -h "jalr.*t9" > /dev/null; \
then (echo >&2 "$@: PIC 'jalr t9' calls are not supported"; \
rm -f $@; /bin/false); fi
# #
# Shared build commands. # Shared build commands.
# #
quiet_cmd_vdsold_and_vdso_check = LD $@ quiet_cmd_vdsold_and_vdso_check = LD $@
cmd_vdsold_and_vdso_check = $(cmd_vdsold); $(cmd_vdso_check) cmd_vdsold_and_vdso_check = $(cmd_vdsold); $(cmd_vdso_check); $(cmd_vdso_mips_check)
quiet_cmd_vdsold = VDSO $@ quiet_cmd_vdsold = VDSO $@
cmd_vdsold = $(CC) $(c_flags) $(VDSO_LDFLAGS) \ cmd_vdsold = $(CC) $(c_flags) $(VDSO_LDFLAGS) \

View File

@ -1,2 +1,4 @@
Image Image
Image.gz Image.gz
loader
loader.lds

View File

@ -72,6 +72,16 @@
#define EXC_LOAD_PAGE_FAULT 13 #define EXC_LOAD_PAGE_FAULT 13
#define EXC_STORE_PAGE_FAULT 15 #define EXC_STORE_PAGE_FAULT 15
/* PMP configuration */
#define PMP_R 0x01
#define PMP_W 0x02
#define PMP_X 0x04
#define PMP_A 0x18
#define PMP_A_TOR 0x08
#define PMP_A_NA4 0x10
#define PMP_A_NAPOT 0x18
#define PMP_L 0x80
/* symbolic CSR names: */ /* symbolic CSR names: */
#define CSR_CYCLE 0xc00 #define CSR_CYCLE 0xc00
#define CSR_TIME 0xc01 #define CSR_TIME 0xc01
@ -100,6 +110,8 @@
#define CSR_MCAUSE 0x342 #define CSR_MCAUSE 0x342
#define CSR_MTVAL 0x343 #define CSR_MTVAL 0x343
#define CSR_MIP 0x344 #define CSR_MIP 0x344
#define CSR_PMPCFG0 0x3a0
#define CSR_PMPADDR0 0x3b0
#define CSR_MHARTID 0xf14 #define CSR_MHARTID 0xf14
#ifdef CONFIG_RISCV_M_MODE #ifdef CONFIG_RISCV_M_MODE

View File

@ -58,6 +58,12 @@ _start_kernel:
/* Reset all registers except ra, a0, a1 */ /* Reset all registers except ra, a0, a1 */
call reset_regs call reset_regs
/* Setup a PMP to permit access to all of memory. */
li a0, -1
csrw CSR_PMPADDR0, a0
li a0, (PMP_A_NAPOT | PMP_R | PMP_W | PMP_X)
csrw CSR_PMPCFG0, a0
/* /*
* The hartid in a0 is expected later on, and we have no firmware * The hartid in a0 is expected later on, and we have no firmware
* to hand it to us. * to hand it to us.

View File

@ -156,6 +156,6 @@ void __init trap_init(void)
csr_write(CSR_SCRATCH, 0); csr_write(CSR_SCRATCH, 0);
/* Set the exception vector address */ /* Set the exception vector address */
csr_write(CSR_TVEC, &handle_exception); csr_write(CSR_TVEC, &handle_exception);
/* Enable all interrupts */ /* Enable interrupts */
csr_write(CSR_IE, -1); csr_write(CSR_IE, IE_SIE | IE_EIE);
} }

View File

@ -19,18 +19,20 @@ asmlinkage void __init kasan_early_init(void)
for (i = 0; i < PTRS_PER_PTE; ++i) for (i = 0; i < PTRS_PER_PTE; ++i)
set_pte(kasan_early_shadow_pte + i, set_pte(kasan_early_shadow_pte + i,
mk_pte(virt_to_page(kasan_early_shadow_page), mk_pte(virt_to_page(kasan_early_shadow_page),
PAGE_KERNEL)); PAGE_KERNEL));
for (i = 0; i < PTRS_PER_PMD; ++i) for (i = 0; i < PTRS_PER_PMD; ++i)
set_pmd(kasan_early_shadow_pmd + i, set_pmd(kasan_early_shadow_pmd + i,
pfn_pmd(PFN_DOWN(__pa((uintptr_t)kasan_early_shadow_pte)), pfn_pmd(PFN_DOWN
__pgprot(_PAGE_TABLE))); (__pa((uintptr_t) kasan_early_shadow_pte)),
__pgprot(_PAGE_TABLE)));
for (i = KASAN_SHADOW_START; i < KASAN_SHADOW_END; for (i = KASAN_SHADOW_START; i < KASAN_SHADOW_END;
i += PGDIR_SIZE, ++pgd) i += PGDIR_SIZE, ++pgd)
set_pgd(pgd, set_pgd(pgd,
pfn_pgd(PFN_DOWN(__pa(((uintptr_t)kasan_early_shadow_pmd))), pfn_pgd(PFN_DOWN
__pgprot(_PAGE_TABLE))); (__pa(((uintptr_t) kasan_early_shadow_pmd))),
__pgprot(_PAGE_TABLE)));
/* init for swapper_pg_dir */ /* init for swapper_pg_dir */
pgd = pgd_offset_k(KASAN_SHADOW_START); pgd = pgd_offset_k(KASAN_SHADOW_START);
@ -38,37 +40,43 @@ asmlinkage void __init kasan_early_init(void)
for (i = KASAN_SHADOW_START; i < KASAN_SHADOW_END; for (i = KASAN_SHADOW_START; i < KASAN_SHADOW_END;
i += PGDIR_SIZE, ++pgd) i += PGDIR_SIZE, ++pgd)
set_pgd(pgd, set_pgd(pgd,
pfn_pgd(PFN_DOWN(__pa(((uintptr_t)kasan_early_shadow_pmd))), pfn_pgd(PFN_DOWN
__pgprot(_PAGE_TABLE))); (__pa(((uintptr_t) kasan_early_shadow_pmd))),
__pgprot(_PAGE_TABLE)));
flush_tlb_all(); flush_tlb_all();
} }
static void __init populate(void *start, void *end) static void __init populate(void *start, void *end)
{ {
unsigned long i; unsigned long i, offset;
unsigned long vaddr = (unsigned long)start & PAGE_MASK; unsigned long vaddr = (unsigned long)start & PAGE_MASK;
unsigned long vend = PAGE_ALIGN((unsigned long)end); unsigned long vend = PAGE_ALIGN((unsigned long)end);
unsigned long n_pages = (vend - vaddr) / PAGE_SIZE; unsigned long n_pages = (vend - vaddr) / PAGE_SIZE;
unsigned long n_ptes =
((n_pages + PTRS_PER_PTE) & -PTRS_PER_PTE) / PTRS_PER_PTE;
unsigned long n_pmds = unsigned long n_pmds =
(n_pages % PTRS_PER_PTE) ? n_pages / PTRS_PER_PTE + 1 : ((n_ptes + PTRS_PER_PMD) & -PTRS_PER_PMD) / PTRS_PER_PMD;
n_pages / PTRS_PER_PTE;
pte_t *pte =
memblock_alloc(n_ptes * PTRS_PER_PTE * sizeof(pte_t), PAGE_SIZE);
pmd_t *pmd =
memblock_alloc(n_pmds * PTRS_PER_PMD * sizeof(pmd_t), PAGE_SIZE);
pgd_t *pgd = pgd_offset_k(vaddr); pgd_t *pgd = pgd_offset_k(vaddr);
pmd_t *pmd = memblock_alloc(n_pmds * sizeof(pmd_t), PAGE_SIZE);
pte_t *pte = memblock_alloc(n_pages * sizeof(pte_t), PAGE_SIZE);
for (i = 0; i < n_pages; i++) { for (i = 0; i < n_pages; i++) {
phys_addr_t phys = memblock_phys_alloc(PAGE_SIZE, PAGE_SIZE); phys_addr_t phys = memblock_phys_alloc(PAGE_SIZE, PAGE_SIZE);
set_pte(&pte[i], pfn_pte(PHYS_PFN(phys), PAGE_KERNEL));
set_pte(pte + i, pfn_pte(PHYS_PFN(phys), PAGE_KERNEL));
} }
for (i = 0; i < n_pmds; ++pgd, i += PTRS_PER_PMD) for (i = 0, offset = 0; i < n_ptes; i++, offset += PTRS_PER_PTE)
set_pgd(pgd, pfn_pgd(PFN_DOWN(__pa(((uintptr_t)(pmd + i)))), set_pmd(&pmd[i],
pfn_pmd(PFN_DOWN(__pa(&pte[offset])),
__pgprot(_PAGE_TABLE))); __pgprot(_PAGE_TABLE)));
for (i = 0; i < n_pages; ++pmd, i += PTRS_PER_PTE) for (i = 0, offset = 0; i < n_pmds; i++, offset += PTRS_PER_PMD)
set_pmd(pmd, pfn_pmd(PFN_DOWN(__pa((uintptr_t)(pte + i))), set_pgd(&pgd[i],
pfn_pgd(PFN_DOWN(__pa(&pmd[offset])),
__pgprot(_PAGE_TABLE))); __pgprot(_PAGE_TABLE)));
flush_tlb_all(); flush_tlb_all();
@ -81,7 +89,8 @@ void __init kasan_init(void)
unsigned long i; unsigned long i;
kasan_populate_early_shadow((void *)KASAN_SHADOW_START, kasan_populate_early_shadow((void *)KASAN_SHADOW_START,
(void *)kasan_mem_to_shadow((void *)VMALLOC_END)); (void *)kasan_mem_to_shadow((void *)
VMALLOC_END));
for_each_memblock(memory, reg) { for_each_memblock(memory, reg) {
void *start = (void *)__va(reg->base); void *start = (void *)__va(reg->base);
@ -90,14 +99,14 @@ void __init kasan_init(void)
if (start >= end) if (start >= end)
break; break;
populate(kasan_mem_to_shadow(start), populate(kasan_mem_to_shadow(start), kasan_mem_to_shadow(end));
kasan_mem_to_shadow(end));
}; };
for (i = 0; i < PTRS_PER_PTE; i++) for (i = 0; i < PTRS_PER_PTE; i++)
set_pte(&kasan_early_shadow_pte[i], set_pte(&kasan_early_shadow_pte[i],
mk_pte(virt_to_page(kasan_early_shadow_page), mk_pte(virt_to_page(kasan_early_shadow_page),
__pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_ACCESSED))); __pgprot(_PAGE_PRESENT | _PAGE_READ |
_PAGE_ACCESSED)));
memset(kasan_early_shadow_page, 0, PAGE_SIZE); memset(kasan_early_shadow_page, 0, PAGE_SIZE);
init_task.kasan_depth = 0; init_task.kasan_depth = 0;

View File

@ -19,7 +19,14 @@ struct task_struct;
void io_bitmap_share(struct task_struct *tsk); void io_bitmap_share(struct task_struct *tsk);
void io_bitmap_exit(void); void io_bitmap_exit(void);
void tss_update_io_bitmap(void); void native_tss_update_io_bitmap(void);
#ifdef CONFIG_PARAVIRT_XXL
#include <asm/paravirt.h>
#else
#define tss_update_io_bitmap native_tss_update_io_bitmap
#endif
#else #else
static inline void io_bitmap_share(struct task_struct *tsk) { } static inline void io_bitmap_share(struct task_struct *tsk) { }
static inline void io_bitmap_exit(void) { } static inline void io_bitmap_exit(void) { }

View File

@ -292,6 +292,14 @@ enum x86emul_mode {
#define X86EMUL_SMM_MASK (1 << 6) #define X86EMUL_SMM_MASK (1 << 6)
#define X86EMUL_SMM_INSIDE_NMI_MASK (1 << 7) #define X86EMUL_SMM_INSIDE_NMI_MASK (1 << 7)
/*
* fastop functions are declared as taking a never-defined fastop parameter,
* so they can't be called from C directly.
*/
struct fastop;
typedef void (*fastop_t)(struct fastop *);
struct x86_emulate_ctxt { struct x86_emulate_ctxt {
const struct x86_emulate_ops *ops; const struct x86_emulate_ops *ops;
@ -324,7 +332,10 @@ struct x86_emulate_ctxt {
struct operand src; struct operand src;
struct operand src2; struct operand src2;
struct operand dst; struct operand dst;
int (*execute)(struct x86_emulate_ctxt *ctxt); union {
int (*execute)(struct x86_emulate_ctxt *ctxt);
fastop_t fop;
};
int (*check_perm)(struct x86_emulate_ctxt *ctxt); int (*check_perm)(struct x86_emulate_ctxt *ctxt);
/* /*
* The following six fields are cleared together, * The following six fields are cleared together,

View File

@ -1122,6 +1122,7 @@ struct kvm_x86_ops {
int (*handle_exit)(struct kvm_vcpu *vcpu, int (*handle_exit)(struct kvm_vcpu *vcpu,
enum exit_fastpath_completion exit_fastpath); enum exit_fastpath_completion exit_fastpath);
int (*skip_emulated_instruction)(struct kvm_vcpu *vcpu); int (*skip_emulated_instruction)(struct kvm_vcpu *vcpu);
void (*update_emulated_instruction)(struct kvm_vcpu *vcpu);
void (*set_interrupt_shadow)(struct kvm_vcpu *vcpu, int mask); void (*set_interrupt_shadow)(struct kvm_vcpu *vcpu, int mask);
u32 (*get_interrupt_shadow)(struct kvm_vcpu *vcpu); u32 (*get_interrupt_shadow)(struct kvm_vcpu *vcpu);
void (*patch_hypercall)(struct kvm_vcpu *vcpu, void (*patch_hypercall)(struct kvm_vcpu *vcpu,
@ -1146,7 +1147,7 @@ struct kvm_x86_ops {
void (*load_eoi_exitmap)(struct kvm_vcpu *vcpu, u64 *eoi_exit_bitmap); void (*load_eoi_exitmap)(struct kvm_vcpu *vcpu, u64 *eoi_exit_bitmap);
void (*set_virtual_apic_mode)(struct kvm_vcpu *vcpu); void (*set_virtual_apic_mode)(struct kvm_vcpu *vcpu);
void (*set_apic_access_page_addr)(struct kvm_vcpu *vcpu, hpa_t hpa); void (*set_apic_access_page_addr)(struct kvm_vcpu *vcpu, hpa_t hpa);
void (*deliver_posted_interrupt)(struct kvm_vcpu *vcpu, int vector); int (*deliver_posted_interrupt)(struct kvm_vcpu *vcpu, int vector);
int (*sync_pir_to_irr)(struct kvm_vcpu *vcpu); int (*sync_pir_to_irr)(struct kvm_vcpu *vcpu);
int (*set_tss_addr)(struct kvm *kvm, unsigned int addr); int (*set_tss_addr)(struct kvm *kvm, unsigned int addr);
int (*set_identity_map_addr)(struct kvm *kvm, u64 ident_addr); int (*set_identity_map_addr)(struct kvm *kvm, u64 ident_addr);

View File

@ -295,6 +295,13 @@ static inline void write_idt_entry(gate_desc *dt, int entry, const gate_desc *g)
PVOP_VCALL3(cpu.write_idt_entry, dt, entry, g); PVOP_VCALL3(cpu.write_idt_entry, dt, entry, g);
} }
#ifdef CONFIG_X86_IOPL_IOPERM
static inline void tss_update_io_bitmap(void)
{
PVOP_VCALL0(cpu.update_io_bitmap);
}
#endif
static inline void paravirt_activate_mm(struct mm_struct *prev, static inline void paravirt_activate_mm(struct mm_struct *prev,
struct mm_struct *next) struct mm_struct *next)
{ {

View File

@ -140,6 +140,10 @@ struct pv_cpu_ops {
void (*load_sp0)(unsigned long sp0); void (*load_sp0)(unsigned long sp0);
#ifdef CONFIG_X86_IOPL_IOPERM
void (*update_io_bitmap)(void);
#endif
void (*wbinvd)(void); void (*wbinvd)(void);
/* cpuid emulation, mostly so that caps bits can be disabled */ /* cpuid emulation, mostly so that caps bits can be disabled */

View File

@ -72,7 +72,7 @@
#define SECONDARY_EXEC_MODE_BASED_EPT_EXEC VMCS_CONTROL_BIT(MODE_BASED_EPT_EXEC) #define SECONDARY_EXEC_MODE_BASED_EPT_EXEC VMCS_CONTROL_BIT(MODE_BASED_EPT_EXEC)
#define SECONDARY_EXEC_PT_USE_GPA VMCS_CONTROL_BIT(PT_USE_GPA) #define SECONDARY_EXEC_PT_USE_GPA VMCS_CONTROL_BIT(PT_USE_GPA)
#define SECONDARY_EXEC_TSC_SCALING VMCS_CONTROL_BIT(TSC_SCALING) #define SECONDARY_EXEC_TSC_SCALING VMCS_CONTROL_BIT(TSC_SCALING)
#define SECONDARY_EXEC_ENABLE_USR_WAIT_PAUSE 0x04000000 #define SECONDARY_EXEC_ENABLE_USR_WAIT_PAUSE VMCS_CONTROL_BIT(USR_WAIT_PAUSE)
#define PIN_BASED_EXT_INTR_MASK VMCS_CONTROL_BIT(INTR_EXITING) #define PIN_BASED_EXT_INTR_MASK VMCS_CONTROL_BIT(INTR_EXITING)
#define PIN_BASED_NMI_EXITING VMCS_CONTROL_BIT(NMI_EXITING) #define PIN_BASED_NMI_EXITING VMCS_CONTROL_BIT(NMI_EXITING)

View File

@ -81,6 +81,7 @@
#define VMX_FEATURE_MODE_BASED_EPT_EXEC ( 2*32+ 22) /* "ept_mode_based_exec" Enable separate EPT EXEC bits for supervisor vs. user */ #define VMX_FEATURE_MODE_BASED_EPT_EXEC ( 2*32+ 22) /* "ept_mode_based_exec" Enable separate EPT EXEC bits for supervisor vs. user */
#define VMX_FEATURE_PT_USE_GPA ( 2*32+ 24) /* "" Processor Trace logs GPAs */ #define VMX_FEATURE_PT_USE_GPA ( 2*32+ 24) /* "" Processor Trace logs GPAs */
#define VMX_FEATURE_TSC_SCALING ( 2*32+ 25) /* Scale hardware TSC when read in guest */ #define VMX_FEATURE_TSC_SCALING ( 2*32+ 25) /* Scale hardware TSC when read in guest */
#define VMX_FEATURE_USR_WAIT_PAUSE ( 2*32+ 26) /* Enable TPAUSE, UMONITOR, UMWAIT in guest */
#define VMX_FEATURE_ENCLV_EXITING ( 2*32+ 28) /* "" VM-Exit on ENCLV (leaf dependent) */ #define VMX_FEATURE_ENCLV_EXITING ( 2*32+ 28) /* "" VM-Exit on ENCLV (leaf dependent) */
#endif /* _ASM_X86_VMXFEATURES_H */ #endif /* _ASM_X86_VMXFEATURES_H */

View File

@ -390,6 +390,7 @@ struct kvm_sync_regs {
#define KVM_STATE_NESTED_GUEST_MODE 0x00000001 #define KVM_STATE_NESTED_GUEST_MODE 0x00000001
#define KVM_STATE_NESTED_RUN_PENDING 0x00000002 #define KVM_STATE_NESTED_RUN_PENDING 0x00000002
#define KVM_STATE_NESTED_EVMCS 0x00000004 #define KVM_STATE_NESTED_EVMCS 0x00000004
#define KVM_STATE_NESTED_MTF_PENDING 0x00000008
#define KVM_STATE_NESTED_SMM_GUEST_MODE 0x00000001 #define KVM_STATE_NESTED_SMM_GUEST_MODE 0x00000001
#define KVM_STATE_NESTED_SMM_VMXON 0x00000002 #define KVM_STATE_NESTED_SMM_VMXON 0x00000002

View File

@ -445,7 +445,7 @@ static __always_inline void setup_pku(struct cpuinfo_x86 *c)
* cpuid bit to be set. We need to ensure that we * cpuid bit to be set. We need to ensure that we
* update that bit in this CPU's "cpu_info". * update that bit in this CPU's "cpu_info".
*/ */
get_cpu_cap(c); set_cpu_cap(c, X86_FEATURE_OSPKE);
} }
#ifdef CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS #ifdef CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS

View File

@ -425,7 +425,29 @@ static void __init sev_map_percpu_data(void)
} }
} }
static bool pv_tlb_flush_supported(void)
{
return (kvm_para_has_feature(KVM_FEATURE_PV_TLB_FLUSH) &&
!kvm_para_has_hint(KVM_HINTS_REALTIME) &&
kvm_para_has_feature(KVM_FEATURE_STEAL_TIME));
}
static DEFINE_PER_CPU(cpumask_var_t, __pv_cpu_mask);
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
static bool pv_ipi_supported(void)
{
return kvm_para_has_feature(KVM_FEATURE_PV_SEND_IPI);
}
static bool pv_sched_yield_supported(void)
{
return (kvm_para_has_feature(KVM_FEATURE_PV_SCHED_YIELD) &&
!kvm_para_has_hint(KVM_HINTS_REALTIME) &&
kvm_para_has_feature(KVM_FEATURE_STEAL_TIME));
}
#define KVM_IPI_CLUSTER_SIZE (2 * BITS_PER_LONG) #define KVM_IPI_CLUSTER_SIZE (2 * BITS_PER_LONG)
static void __send_ipi_mask(const struct cpumask *mask, int vector) static void __send_ipi_mask(const struct cpumask *mask, int vector)
@ -490,12 +512,12 @@ static void kvm_send_ipi_mask(const struct cpumask *mask, int vector)
static void kvm_send_ipi_mask_allbutself(const struct cpumask *mask, int vector) static void kvm_send_ipi_mask_allbutself(const struct cpumask *mask, int vector)
{ {
unsigned int this_cpu = smp_processor_id(); unsigned int this_cpu = smp_processor_id();
struct cpumask new_mask; struct cpumask *new_mask = this_cpu_cpumask_var_ptr(__pv_cpu_mask);
const struct cpumask *local_mask; const struct cpumask *local_mask;
cpumask_copy(&new_mask, mask); cpumask_copy(new_mask, mask);
cpumask_clear_cpu(this_cpu, &new_mask); cpumask_clear_cpu(this_cpu, new_mask);
local_mask = &new_mask; local_mask = new_mask;
__send_ipi_mask(local_mask, vector); __send_ipi_mask(local_mask, vector);
} }
@ -575,7 +597,6 @@ static void __init kvm_apf_trap_init(void)
update_intr_gate(X86_TRAP_PF, async_page_fault); update_intr_gate(X86_TRAP_PF, async_page_fault);
} }
static DEFINE_PER_CPU(cpumask_var_t, __pv_tlb_mask);
static void kvm_flush_tlb_others(const struct cpumask *cpumask, static void kvm_flush_tlb_others(const struct cpumask *cpumask,
const struct flush_tlb_info *info) const struct flush_tlb_info *info)
@ -583,7 +604,7 @@ static void kvm_flush_tlb_others(const struct cpumask *cpumask,
u8 state; u8 state;
int cpu; int cpu;
struct kvm_steal_time *src; struct kvm_steal_time *src;
struct cpumask *flushmask = this_cpu_cpumask_var_ptr(__pv_tlb_mask); struct cpumask *flushmask = this_cpu_cpumask_var_ptr(__pv_cpu_mask);
cpumask_copy(flushmask, cpumask); cpumask_copy(flushmask, cpumask);
/* /*
@ -619,11 +640,10 @@ static void __init kvm_guest_init(void)
pv_ops.time.steal_clock = kvm_steal_clock; pv_ops.time.steal_clock = kvm_steal_clock;
} }
if (kvm_para_has_feature(KVM_FEATURE_PV_TLB_FLUSH) && if (pv_tlb_flush_supported()) {
!kvm_para_has_hint(KVM_HINTS_REALTIME) &&
kvm_para_has_feature(KVM_FEATURE_STEAL_TIME)) {
pv_ops.mmu.flush_tlb_others = kvm_flush_tlb_others; pv_ops.mmu.flush_tlb_others = kvm_flush_tlb_others;
pv_ops.mmu.tlb_remove_table = tlb_remove_table; pv_ops.mmu.tlb_remove_table = tlb_remove_table;
pr_info("KVM setup pv remote TLB flush\n");
} }
if (kvm_para_has_feature(KVM_FEATURE_PV_EOI)) if (kvm_para_has_feature(KVM_FEATURE_PV_EOI))
@ -632,9 +652,7 @@ static void __init kvm_guest_init(void)
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
smp_ops.smp_prepare_cpus = kvm_smp_prepare_cpus; smp_ops.smp_prepare_cpus = kvm_smp_prepare_cpus;
smp_ops.smp_prepare_boot_cpu = kvm_smp_prepare_boot_cpu; smp_ops.smp_prepare_boot_cpu = kvm_smp_prepare_boot_cpu;
if (kvm_para_has_feature(KVM_FEATURE_PV_SCHED_YIELD) && if (pv_sched_yield_supported()) {
!kvm_para_has_hint(KVM_HINTS_REALTIME) &&
kvm_para_has_feature(KVM_FEATURE_STEAL_TIME)) {
smp_ops.send_call_func_ipi = kvm_smp_send_call_func_ipi; smp_ops.send_call_func_ipi = kvm_smp_send_call_func_ipi;
pr_info("KVM setup pv sched yield\n"); pr_info("KVM setup pv sched yield\n");
} }
@ -700,7 +718,7 @@ static uint32_t __init kvm_detect(void)
static void __init kvm_apic_init(void) static void __init kvm_apic_init(void)
{ {
#if defined(CONFIG_SMP) #if defined(CONFIG_SMP)
if (kvm_para_has_feature(KVM_FEATURE_PV_SEND_IPI)) if (pv_ipi_supported())
kvm_setup_pv_ipi(); kvm_setup_pv_ipi();
#endif #endif
} }
@ -732,26 +750,31 @@ static __init int activate_jump_labels(void)
} }
arch_initcall(activate_jump_labels); arch_initcall(activate_jump_labels);
static __init int kvm_setup_pv_tlb_flush(void) static __init int kvm_alloc_cpumask(void)
{ {
int cpu; int cpu;
bool alloc = false;
if (!kvm_para_available() || nopv) if (!kvm_para_available() || nopv)
return 0; return 0;
if (kvm_para_has_feature(KVM_FEATURE_PV_TLB_FLUSH) && if (pv_tlb_flush_supported())
!kvm_para_has_hint(KVM_HINTS_REALTIME) && alloc = true;
kvm_para_has_feature(KVM_FEATURE_STEAL_TIME)) {
#if defined(CONFIG_SMP)
if (pv_ipi_supported())
alloc = true;
#endif
if (alloc)
for_each_possible_cpu(cpu) { for_each_possible_cpu(cpu) {
zalloc_cpumask_var_node(per_cpu_ptr(&__pv_tlb_mask, cpu), zalloc_cpumask_var_node(per_cpu_ptr(&__pv_cpu_mask, cpu),
GFP_KERNEL, cpu_to_node(cpu)); GFP_KERNEL, cpu_to_node(cpu));
} }
pr_info("KVM setup pv remote TLB flush\n");
}
return 0; return 0;
} }
arch_initcall(kvm_setup_pv_tlb_flush); arch_initcall(kvm_alloc_cpumask);
#ifdef CONFIG_PARAVIRT_SPINLOCKS #ifdef CONFIG_PARAVIRT_SPINLOCKS

View File

@ -30,6 +30,7 @@
#include <asm/timer.h> #include <asm/timer.h>
#include <asm/special_insns.h> #include <asm/special_insns.h>
#include <asm/tlb.h> #include <asm/tlb.h>
#include <asm/io_bitmap.h>
/* /*
* nop stub, which must not clobber anything *including the stack* to * nop stub, which must not clobber anything *including the stack* to
@ -341,6 +342,10 @@ struct paravirt_patch_template pv_ops = {
.cpu.iret = native_iret, .cpu.iret = native_iret,
.cpu.swapgs = native_swapgs, .cpu.swapgs = native_swapgs,
#ifdef CONFIG_X86_IOPL_IOPERM
.cpu.update_io_bitmap = native_tss_update_io_bitmap,
#endif
.cpu.start_context_switch = paravirt_nop, .cpu.start_context_switch = paravirt_nop,
.cpu.end_context_switch = paravirt_nop, .cpu.end_context_switch = paravirt_nop,

View File

@ -374,7 +374,7 @@ static void tss_copy_io_bitmap(struct tss_struct *tss, struct io_bitmap *iobm)
/** /**
* tss_update_io_bitmap - Update I/O bitmap before exiting to usermode * tss_update_io_bitmap - Update I/O bitmap before exiting to usermode
*/ */
void tss_update_io_bitmap(void) void native_tss_update_io_bitmap(void)
{ {
struct tss_struct *tss = this_cpu_ptr(&cpu_tss_rw); struct tss_struct *tss = this_cpu_ptr(&cpu_tss_rw);
struct thread_struct *t = &current->thread; struct thread_struct *t = &current->thread;

View File

@ -59,6 +59,19 @@ config KVM
If unsure, say N. If unsure, say N.
config KVM_WERROR
bool "Compile KVM with -Werror"
# KASAN may cause the build to fail due to larger frames
default y if X86_64 && !KASAN
# We use the dependency on !COMPILE_TEST to not be enabled
# blindly in allmodconfig or allyesconfig configurations
depends on (X86_64 && !KASAN) || !COMPILE_TEST
depends on EXPERT
help
Add -Werror to the build flags for (and only for) i915.ko.
If in doubt, say "N".
config KVM_INTEL config KVM_INTEL
tristate "KVM for Intel (and compatible) processors support" tristate "KVM for Intel (and compatible) processors support"
depends on KVM && IA32_FEAT_CTL depends on KVM && IA32_FEAT_CTL

View File

@ -1,6 +1,7 @@
# SPDX-License-Identifier: GPL-2.0 # SPDX-License-Identifier: GPL-2.0
ccflags-y += -Iarch/x86/kvm ccflags-y += -Iarch/x86/kvm
ccflags-$(CONFIG_KVM_WERROR) += -Werror
KVM := ../../../virt/kvm KVM := ../../../virt/kvm

View File

@ -191,25 +191,6 @@
#define NR_FASTOP (ilog2(sizeof(ulong)) + 1) #define NR_FASTOP (ilog2(sizeof(ulong)) + 1)
#define FASTOP_SIZE 8 #define FASTOP_SIZE 8
/*
* fastop functions have a special calling convention:
*
* dst: rax (in/out)
* src: rdx (in/out)
* src2: rcx (in)
* flags: rflags (in/out)
* ex: rsi (in:fastop pointer, out:zero if exception)
*
* Moreover, they are all exactly FASTOP_SIZE bytes long, so functions for
* different operand sizes can be reached by calculation, rather than a jump
* table (which would be bigger than the code).
*
* fastop functions are declared as taking a never-defined fastop parameter,
* so they can't be called from C directly.
*/
struct fastop;
struct opcode { struct opcode {
u64 flags : 56; u64 flags : 56;
u64 intercept : 8; u64 intercept : 8;
@ -311,8 +292,19 @@ static void invalidate_registers(struct x86_emulate_ctxt *ctxt)
#define ON64(x) #define ON64(x)
#endif #endif
typedef void (*fastop_t)(struct fastop *); /*
* fastop functions have a special calling convention:
*
* dst: rax (in/out)
* src: rdx (in/out)
* src2: rcx (in)
* flags: rflags (in/out)
* ex: rsi (in:fastop pointer, out:zero if exception)
*
* Moreover, they are all exactly FASTOP_SIZE bytes long, so functions for
* different operand sizes can be reached by calculation, rather than a jump
* table (which would be bigger than the code).
*/
static int fastop(struct x86_emulate_ctxt *ctxt, fastop_t fop); static int fastop(struct x86_emulate_ctxt *ctxt, fastop_t fop);
#define __FOP_FUNC(name) \ #define __FOP_FUNC(name) \
@ -5683,7 +5675,7 @@ special_insn:
if (ctxt->execute) { if (ctxt->execute) {
if (ctxt->d & Fastop) if (ctxt->d & Fastop)
rc = fastop(ctxt, (fastop_t)ctxt->execute); rc = fastop(ctxt, ctxt->fop);
else else
rc = ctxt->execute(ctxt); rc = ctxt->execute(ctxt);
if (rc != X86EMUL_CONTINUE) if (rc != X86EMUL_CONTINUE)

View File

@ -417,7 +417,7 @@ void kvm_scan_ioapic_routes(struct kvm_vcpu *vcpu,
kvm_set_msi_irq(vcpu->kvm, entry, &irq); kvm_set_msi_irq(vcpu->kvm, entry, &irq);
if (irq.level && if (irq.trig_mode &&
kvm_apic_match_dest(vcpu, NULL, APIC_DEST_NOSHORT, kvm_apic_match_dest(vcpu, NULL, APIC_DEST_NOSHORT,
irq.dest_id, irq.dest_mode)) irq.dest_id, irq.dest_mode))
__set_bit(irq.vector, ioapic_handled_vectors); __set_bit(irq.vector, ioapic_handled_vectors);

View File

@ -627,9 +627,11 @@ static inline bool pv_eoi_enabled(struct kvm_vcpu *vcpu)
static bool pv_eoi_get_pending(struct kvm_vcpu *vcpu) static bool pv_eoi_get_pending(struct kvm_vcpu *vcpu)
{ {
u8 val; u8 val;
if (pv_eoi_get_user(vcpu, &val) < 0) if (pv_eoi_get_user(vcpu, &val) < 0) {
printk(KERN_WARNING "Can't read EOI MSR value: 0x%llx\n", printk(KERN_WARNING "Can't read EOI MSR value: 0x%llx\n",
(unsigned long long)vcpu->arch.pv_eoi.msr_val); (unsigned long long)vcpu->arch.pv_eoi.msr_val);
return false;
}
return val & 0x1; return val & 0x1;
} }
@ -1046,11 +1048,8 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
apic->regs + APIC_TMR); apic->regs + APIC_TMR);
} }
if (vcpu->arch.apicv_active) if (kvm_x86_ops->deliver_posted_interrupt(vcpu, vector)) {
kvm_x86_ops->deliver_posted_interrupt(vcpu, vector);
else {
kvm_lapic_set_irr(vector, apic); kvm_lapic_set_irr(vector, apic);
kvm_make_request(KVM_REQ_EVENT, vcpu); kvm_make_request(KVM_REQ_EVENT, vcpu);
kvm_vcpu_kick(vcpu); kvm_vcpu_kick(vcpu);
} }

View File

@ -339,7 +339,7 @@ TRACE_EVENT(
/* These depend on page entry type, so compute them now. */ /* These depend on page entry type, so compute them now. */
__field(bool, r) __field(bool, r)
__field(bool, x) __field(bool, x)
__field(u8, u) __field(signed char, u)
), ),
TP_fast_assign( TP_fast_assign(

View File

@ -57,11 +57,13 @@
MODULE_AUTHOR("Qumranet"); MODULE_AUTHOR("Qumranet");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
#ifdef MODULE
static const struct x86_cpu_id svm_cpu_id[] = { static const struct x86_cpu_id svm_cpu_id[] = {
X86_FEATURE_MATCH(X86_FEATURE_SVM), X86_FEATURE_MATCH(X86_FEATURE_SVM),
{} {}
}; };
MODULE_DEVICE_TABLE(x86cpu, svm_cpu_id); MODULE_DEVICE_TABLE(x86cpu, svm_cpu_id);
#endif
#define IOPM_ALLOC_ORDER 2 #define IOPM_ALLOC_ORDER 2
#define MSRPM_ALLOC_ORDER 1 #define MSRPM_ALLOC_ORDER 1
@ -1005,33 +1007,32 @@ static void svm_cpu_uninit(int cpu)
static int svm_cpu_init(int cpu) static int svm_cpu_init(int cpu)
{ {
struct svm_cpu_data *sd; struct svm_cpu_data *sd;
int r;
sd = kzalloc(sizeof(struct svm_cpu_data), GFP_KERNEL); sd = kzalloc(sizeof(struct svm_cpu_data), GFP_KERNEL);
if (!sd) if (!sd)
return -ENOMEM; return -ENOMEM;
sd->cpu = cpu; sd->cpu = cpu;
r = -ENOMEM;
sd->save_area = alloc_page(GFP_KERNEL); sd->save_area = alloc_page(GFP_KERNEL);
if (!sd->save_area) if (!sd->save_area)
goto err_1; goto free_cpu_data;
if (svm_sev_enabled()) { if (svm_sev_enabled()) {
r = -ENOMEM;
sd->sev_vmcbs = kmalloc_array(max_sev_asid + 1, sd->sev_vmcbs = kmalloc_array(max_sev_asid + 1,
sizeof(void *), sizeof(void *),
GFP_KERNEL); GFP_KERNEL);
if (!sd->sev_vmcbs) if (!sd->sev_vmcbs)
goto err_1; goto free_save_area;
} }
per_cpu(svm_data, cpu) = sd; per_cpu(svm_data, cpu) = sd;
return 0; return 0;
err_1: free_save_area:
__free_page(sd->save_area);
free_cpu_data:
kfree(sd); kfree(sd);
return r; return -ENOMEM;
} }
@ -1350,6 +1351,24 @@ static __init void svm_adjust_mmio_mask(void)
kvm_mmu_set_mmio_spte_mask(mask, mask, PT_WRITABLE_MASK | PT_USER_MASK); kvm_mmu_set_mmio_spte_mask(mask, mask, PT_WRITABLE_MASK | PT_USER_MASK);
} }
static void svm_hardware_teardown(void)
{
int cpu;
if (svm_sev_enabled()) {
bitmap_free(sev_asid_bitmap);
bitmap_free(sev_reclaim_asid_bitmap);
sev_flush_asids();
}
for_each_possible_cpu(cpu)
svm_cpu_uninit(cpu);
__free_pages(pfn_to_page(iopm_base >> PAGE_SHIFT), IOPM_ALLOC_ORDER);
iopm_base = 0;
}
static __init int svm_hardware_setup(void) static __init int svm_hardware_setup(void)
{ {
int cpu; int cpu;
@ -1463,29 +1482,10 @@ static __init int svm_hardware_setup(void)
return 0; return 0;
err: err:
__free_pages(iopm_pages, IOPM_ALLOC_ORDER); svm_hardware_teardown();
iopm_base = 0;
return r; return r;
} }
static __exit void svm_hardware_unsetup(void)
{
int cpu;
if (svm_sev_enabled()) {
bitmap_free(sev_asid_bitmap);
bitmap_free(sev_reclaim_asid_bitmap);
sev_flush_asids();
}
for_each_possible_cpu(cpu)
svm_cpu_uninit(cpu);
__free_pages(pfn_to_page(iopm_base >> PAGE_SHIFT), IOPM_ALLOC_ORDER);
iopm_base = 0;
}
static void init_seg(struct vmcb_seg *seg) static void init_seg(struct vmcb_seg *seg)
{ {
seg->selector = 0; seg->selector = 0;
@ -2196,8 +2196,9 @@ static void svm_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event)
static int avic_init_vcpu(struct vcpu_svm *svm) static int avic_init_vcpu(struct vcpu_svm *svm)
{ {
int ret; int ret;
struct kvm_vcpu *vcpu = &svm->vcpu;
if (!kvm_vcpu_apicv_active(&svm->vcpu)) if (!avic || !irqchip_in_kernel(vcpu->kvm))
return 0; return 0;
ret = avic_init_backing_page(&svm->vcpu); ret = avic_init_backing_page(&svm->vcpu);
@ -5232,6 +5233,9 @@ static void svm_refresh_apicv_exec_ctrl(struct kvm_vcpu *vcpu)
struct vmcb *vmcb = svm->vmcb; struct vmcb *vmcb = svm->vmcb;
bool activated = kvm_vcpu_apicv_active(vcpu); bool activated = kvm_vcpu_apicv_active(vcpu);
if (!avic)
return;
if (activated) { if (activated) {
/** /**
* During AVIC temporary deactivation, guest could update * During AVIC temporary deactivation, guest could update
@ -5255,8 +5259,11 @@ static void svm_load_eoi_exitmap(struct kvm_vcpu *vcpu, u64 *eoi_exit_bitmap)
return; return;
} }
static void svm_deliver_avic_intr(struct kvm_vcpu *vcpu, int vec) static int svm_deliver_avic_intr(struct kvm_vcpu *vcpu, int vec)
{ {
if (!vcpu->arch.apicv_active)
return -1;
kvm_lapic_set_irr(vec, vcpu->arch.apic); kvm_lapic_set_irr(vec, vcpu->arch.apic);
smp_mb__after_atomic(); smp_mb__after_atomic();
@ -5268,6 +5275,8 @@ static void svm_deliver_avic_intr(struct kvm_vcpu *vcpu, int vec)
put_cpu(); put_cpu();
} else } else
kvm_vcpu_wake_up(vcpu); kvm_vcpu_wake_up(vcpu);
return 0;
} }
static bool svm_dy_apicv_has_pending_interrupt(struct kvm_vcpu *vcpu) static bool svm_dy_apicv_has_pending_interrupt(struct kvm_vcpu *vcpu)
@ -7378,7 +7387,7 @@ static struct kvm_x86_ops svm_x86_ops __ro_after_init = {
.cpu_has_kvm_support = has_svm, .cpu_has_kvm_support = has_svm,
.disabled_by_bios = is_disabled, .disabled_by_bios = is_disabled,
.hardware_setup = svm_hardware_setup, .hardware_setup = svm_hardware_setup,
.hardware_unsetup = svm_hardware_unsetup, .hardware_unsetup = svm_hardware_teardown,
.check_processor_compatibility = svm_check_processor_compat, .check_processor_compatibility = svm_check_processor_compat,
.hardware_enable = svm_hardware_enable, .hardware_enable = svm_hardware_enable,
.hardware_disable = svm_hardware_disable, .hardware_disable = svm_hardware_disable,
@ -7433,6 +7442,7 @@ static struct kvm_x86_ops svm_x86_ops __ro_after_init = {
.run = svm_vcpu_run, .run = svm_vcpu_run,
.handle_exit = handle_exit, .handle_exit = handle_exit,
.skip_emulated_instruction = skip_emulated_instruction, .skip_emulated_instruction = skip_emulated_instruction,
.update_emulated_instruction = NULL,
.set_interrupt_shadow = svm_set_interrupt_shadow, .set_interrupt_shadow = svm_set_interrupt_shadow,
.get_interrupt_shadow = svm_get_interrupt_shadow, .get_interrupt_shadow = svm_get_interrupt_shadow,
.patch_hypercall = svm_patch_hypercall, .patch_hypercall = svm_patch_hypercall,

View File

@ -12,6 +12,7 @@ extern bool __read_mostly enable_ept;
extern bool __read_mostly enable_unrestricted_guest; extern bool __read_mostly enable_unrestricted_guest;
extern bool __read_mostly enable_ept_ad_bits; extern bool __read_mostly enable_ept_ad_bits;
extern bool __read_mostly enable_pml; extern bool __read_mostly enable_pml;
extern bool __read_mostly enable_apicv;
extern int __read_mostly pt_mode; extern int __read_mostly pt_mode;
#define PT_MODE_SYSTEM 0 #define PT_MODE_SYSTEM 0

View File

@ -3161,10 +3161,10 @@ static void load_vmcs12_host_state(struct kvm_vcpu *vcpu,
* or KVM_SET_NESTED_STATE). Otherwise it's called from vmlaunch/vmresume. * or KVM_SET_NESTED_STATE). Otherwise it's called from vmlaunch/vmresume.
* *
* Returns: * Returns:
* NVMX_ENTRY_SUCCESS: Entered VMX non-root mode * NVMX_VMENTRY_SUCCESS: Entered VMX non-root mode
* NVMX_ENTRY_VMFAIL: Consistency check VMFail * NVMX_VMENTRY_VMFAIL: Consistency check VMFail
* NVMX_ENTRY_VMEXIT: Consistency check VMExit * NVMX_VMENTRY_VMEXIT: Consistency check VMExit
* NVMX_ENTRY_KVM_INTERNAL_ERROR: KVM internal error * NVMX_VMENTRY_KVM_INTERNAL_ERROR: KVM internal error
*/ */
enum nvmx_vmentry_status nested_vmx_enter_non_root_mode(struct kvm_vcpu *vcpu, enum nvmx_vmentry_status nested_vmx_enter_non_root_mode(struct kvm_vcpu *vcpu,
bool from_vmentry) bool from_vmentry)
@ -3609,8 +3609,15 @@ static int vmx_check_nested_events(struct kvm_vcpu *vcpu, bool external_intr)
unsigned long exit_qual; unsigned long exit_qual;
bool block_nested_events = bool block_nested_events =
vmx->nested.nested_run_pending || kvm_event_needs_reinjection(vcpu); vmx->nested.nested_run_pending || kvm_event_needs_reinjection(vcpu);
bool mtf_pending = vmx->nested.mtf_pending;
struct kvm_lapic *apic = vcpu->arch.apic; struct kvm_lapic *apic = vcpu->arch.apic;
/*
* Clear the MTF state. If a higher priority VM-exit is delivered first,
* this state is discarded.
*/
vmx->nested.mtf_pending = false;
if (lapic_in_kernel(vcpu) && if (lapic_in_kernel(vcpu) &&
test_bit(KVM_APIC_INIT, &apic->pending_events)) { test_bit(KVM_APIC_INIT, &apic->pending_events)) {
if (block_nested_events) if (block_nested_events)
@ -3621,8 +3628,28 @@ static int vmx_check_nested_events(struct kvm_vcpu *vcpu, bool external_intr)
return 0; return 0;
} }
/*
* Process any exceptions that are not debug traps before MTF.
*/
if (vcpu->arch.exception.pending && if (vcpu->arch.exception.pending &&
nested_vmx_check_exception(vcpu, &exit_qual)) { !vmx_pending_dbg_trap(vcpu) &&
nested_vmx_check_exception(vcpu, &exit_qual)) {
if (block_nested_events)
return -EBUSY;
nested_vmx_inject_exception_vmexit(vcpu, exit_qual);
return 0;
}
if (mtf_pending) {
if (block_nested_events)
return -EBUSY;
nested_vmx_update_pending_dbg(vcpu);
nested_vmx_vmexit(vcpu, EXIT_REASON_MONITOR_TRAP_FLAG, 0, 0);
return 0;
}
if (vcpu->arch.exception.pending &&
nested_vmx_check_exception(vcpu, &exit_qual)) {
if (block_nested_events) if (block_nested_events)
return -EBUSY; return -EBUSY;
nested_vmx_inject_exception_vmexit(vcpu, exit_qual); nested_vmx_inject_exception_vmexit(vcpu, exit_qual);
@ -5285,24 +5312,17 @@ fail:
return 1; return 1;
} }
/*
static bool nested_vmx_exit_handled_io(struct kvm_vcpu *vcpu, * Return true if an IO instruction with the specified port and size should cause
struct vmcs12 *vmcs12) * a VM-exit into L1.
*/
bool nested_vmx_check_io_bitmaps(struct kvm_vcpu *vcpu, unsigned int port,
int size)
{ {
unsigned long exit_qualification; struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
gpa_t bitmap, last_bitmap; gpa_t bitmap, last_bitmap;
unsigned int port;
int size;
u8 b; u8 b;
if (!nested_cpu_has(vmcs12, CPU_BASED_USE_IO_BITMAPS))
return nested_cpu_has(vmcs12, CPU_BASED_UNCOND_IO_EXITING);
exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
port = exit_qualification >> 16;
size = (exit_qualification & 7) + 1;
last_bitmap = (gpa_t)-1; last_bitmap = (gpa_t)-1;
b = -1; b = -1;
@ -5329,8 +5349,26 @@ static bool nested_vmx_exit_handled_io(struct kvm_vcpu *vcpu,
return false; return false;
} }
static bool nested_vmx_exit_handled_io(struct kvm_vcpu *vcpu,
struct vmcs12 *vmcs12)
{
unsigned long exit_qualification;
unsigned short port;
int size;
if (!nested_cpu_has(vmcs12, CPU_BASED_USE_IO_BITMAPS))
return nested_cpu_has(vmcs12, CPU_BASED_UNCOND_IO_EXITING);
exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
port = exit_qualification >> 16;
size = (exit_qualification & 7) + 1;
return nested_vmx_check_io_bitmaps(vcpu, port, size);
}
/* /*
* Return 1 if we should exit from L2 to L1 to handle an MSR access access, * Return 1 if we should exit from L2 to L1 to handle an MSR access,
* rather than handle it ourselves in L0. I.e., check whether L1 expressed * rather than handle it ourselves in L0. I.e., check whether L1 expressed
* disinterest in the current event (read or write a specific MSR) by using an * disinterest in the current event (read or write a specific MSR) by using an
* MSR bitmap. This may be the case even when L0 doesn't use MSR bitmaps. * MSR bitmap. This may be the case even when L0 doesn't use MSR bitmaps.
@ -5712,6 +5750,9 @@ static int vmx_get_nested_state(struct kvm_vcpu *vcpu,
if (vmx->nested.nested_run_pending) if (vmx->nested.nested_run_pending)
kvm_state.flags |= KVM_STATE_NESTED_RUN_PENDING; kvm_state.flags |= KVM_STATE_NESTED_RUN_PENDING;
if (vmx->nested.mtf_pending)
kvm_state.flags |= KVM_STATE_NESTED_MTF_PENDING;
} }
} }
@ -5892,6 +5933,9 @@ static int vmx_set_nested_state(struct kvm_vcpu *vcpu,
vmx->nested.nested_run_pending = vmx->nested.nested_run_pending =
!!(kvm_state->flags & KVM_STATE_NESTED_RUN_PENDING); !!(kvm_state->flags & KVM_STATE_NESTED_RUN_PENDING);
vmx->nested.mtf_pending =
!!(kvm_state->flags & KVM_STATE_NESTED_MTF_PENDING);
ret = -EINVAL; ret = -EINVAL;
if (nested_cpu_has_shadow_vmcs(vmcs12) && if (nested_cpu_has_shadow_vmcs(vmcs12) &&
vmcs12->vmcs_link_pointer != -1ull) { vmcs12->vmcs_link_pointer != -1ull) {
@ -5949,8 +5993,7 @@ void nested_vmx_set_vmcs_shadowing_bitmap(void)
* bit in the high half is on if the corresponding bit in the control field * bit in the high half is on if the corresponding bit in the control field
* may be on. See also vmx_control_verify(). * may be on. See also vmx_control_verify().
*/ */
void nested_vmx_setup_ctls_msrs(struct nested_vmx_msrs *msrs, u32 ept_caps, void nested_vmx_setup_ctls_msrs(struct nested_vmx_msrs *msrs, u32 ept_caps)
bool apicv)
{ {
/* /*
* Note that as a general rule, the high half of the MSRs (bits in * Note that as a general rule, the high half of the MSRs (bits in
@ -5977,7 +6020,7 @@ void nested_vmx_setup_ctls_msrs(struct nested_vmx_msrs *msrs, u32 ept_caps,
PIN_BASED_EXT_INTR_MASK | PIN_BASED_EXT_INTR_MASK |
PIN_BASED_NMI_EXITING | PIN_BASED_NMI_EXITING |
PIN_BASED_VIRTUAL_NMIS | PIN_BASED_VIRTUAL_NMIS |
(apicv ? PIN_BASED_POSTED_INTR : 0); (enable_apicv ? PIN_BASED_POSTED_INTR : 0);
msrs->pinbased_ctls_high |= msrs->pinbased_ctls_high |=
PIN_BASED_ALWAYSON_WITHOUT_TRUE_MSR | PIN_BASED_ALWAYSON_WITHOUT_TRUE_MSR |
PIN_BASED_VMX_PREEMPTION_TIMER; PIN_BASED_VMX_PREEMPTION_TIMER;

View File

@ -17,8 +17,7 @@ enum nvmx_vmentry_status {
}; };
void vmx_leave_nested(struct kvm_vcpu *vcpu); void vmx_leave_nested(struct kvm_vcpu *vcpu);
void nested_vmx_setup_ctls_msrs(struct nested_vmx_msrs *msrs, u32 ept_caps, void nested_vmx_setup_ctls_msrs(struct nested_vmx_msrs *msrs, u32 ept_caps);
bool apicv);
void nested_vmx_hardware_unsetup(void); void nested_vmx_hardware_unsetup(void);
__init int nested_vmx_hardware_setup(int (*exit_handlers[])(struct kvm_vcpu *)); __init int nested_vmx_hardware_setup(int (*exit_handlers[])(struct kvm_vcpu *));
void nested_vmx_set_vmcs_shadowing_bitmap(void); void nested_vmx_set_vmcs_shadowing_bitmap(void);
@ -34,6 +33,8 @@ int vmx_get_vmx_msr(struct nested_vmx_msrs *msrs, u32 msr_index, u64 *pdata);
int get_vmx_mem_address(struct kvm_vcpu *vcpu, unsigned long exit_qualification, int get_vmx_mem_address(struct kvm_vcpu *vcpu, unsigned long exit_qualification,
u32 vmx_instruction_info, bool wr, int len, gva_t *ret); u32 vmx_instruction_info, bool wr, int len, gva_t *ret);
void nested_vmx_pmu_entry_exit_ctls_update(struct kvm_vcpu *vcpu); void nested_vmx_pmu_entry_exit_ctls_update(struct kvm_vcpu *vcpu);
bool nested_vmx_check_io_bitmaps(struct kvm_vcpu *vcpu, unsigned int port,
int size);
static inline struct vmcs12 *get_vmcs12(struct kvm_vcpu *vcpu) static inline struct vmcs12 *get_vmcs12(struct kvm_vcpu *vcpu)
{ {
@ -175,6 +176,11 @@ static inline bool nested_cpu_has_virtual_nmis(struct vmcs12 *vmcs12)
return vmcs12->pin_based_vm_exec_control & PIN_BASED_VIRTUAL_NMIS; return vmcs12->pin_based_vm_exec_control & PIN_BASED_VIRTUAL_NMIS;
} }
static inline int nested_cpu_has_mtf(struct vmcs12 *vmcs12)
{
return nested_cpu_has(vmcs12, CPU_BASED_MONITOR_TRAP_FLAG);
}
static inline int nested_cpu_has_ept(struct vmcs12 *vmcs12) static inline int nested_cpu_has_ept(struct vmcs12 *vmcs12)
{ {
return nested_cpu_has2(vmcs12, SECONDARY_EXEC_ENABLE_EPT); return nested_cpu_has2(vmcs12, SECONDARY_EXEC_ENABLE_EPT);

View File

@ -64,11 +64,13 @@
MODULE_AUTHOR("Qumranet"); MODULE_AUTHOR("Qumranet");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
#ifdef MODULE
static const struct x86_cpu_id vmx_cpu_id[] = { static const struct x86_cpu_id vmx_cpu_id[] = {
X86_FEATURE_MATCH(X86_FEATURE_VMX), X86_FEATURE_MATCH(X86_FEATURE_VMX),
{} {}
}; };
MODULE_DEVICE_TABLE(x86cpu, vmx_cpu_id); MODULE_DEVICE_TABLE(x86cpu, vmx_cpu_id);
#endif
bool __read_mostly enable_vpid = 1; bool __read_mostly enable_vpid = 1;
module_param_named(vpid, enable_vpid, bool, 0444); module_param_named(vpid, enable_vpid, bool, 0444);
@ -95,7 +97,7 @@ module_param(emulate_invalid_guest_state, bool, S_IRUGO);
static bool __read_mostly fasteoi = 1; static bool __read_mostly fasteoi = 1;
module_param(fasteoi, bool, S_IRUGO); module_param(fasteoi, bool, S_IRUGO);
static bool __read_mostly enable_apicv = 1; bool __read_mostly enable_apicv = 1;
module_param(enable_apicv, bool, S_IRUGO); module_param(enable_apicv, bool, S_IRUGO);
/* /*
@ -1175,6 +1177,10 @@ void vmx_prepare_switch_to_guest(struct kvm_vcpu *vcpu)
vmx->guest_msrs[i].mask); vmx->guest_msrs[i].mask);
} }
if (vmx->nested.need_vmcs12_to_shadow_sync)
nested_sync_vmcs12_to_shadow(vcpu);
if (vmx->guest_state_loaded) if (vmx->guest_state_loaded)
return; return;
@ -1599,6 +1605,40 @@ static int skip_emulated_instruction(struct kvm_vcpu *vcpu)
return 1; return 1;
} }
/*
* Recognizes a pending MTF VM-exit and records the nested state for later
* delivery.
*/
static void vmx_update_emulated_instruction(struct kvm_vcpu *vcpu)
{
struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
struct vcpu_vmx *vmx = to_vmx(vcpu);
if (!is_guest_mode(vcpu))
return;
/*
* Per the SDM, MTF takes priority over debug-trap exceptions besides
* T-bit traps. As instruction emulation is completed (i.e. at the
* instruction boundary), any #DB exception pending delivery must be a
* debug-trap. Record the pending MTF state to be delivered in
* vmx_check_nested_events().
*/
if (nested_cpu_has_mtf(vmcs12) &&
(!vcpu->arch.exception.pending ||
vcpu->arch.exception.nr == DB_VECTOR))
vmx->nested.mtf_pending = true;
else
vmx->nested.mtf_pending = false;
}
static int vmx_skip_emulated_instruction(struct kvm_vcpu *vcpu)
{
vmx_update_emulated_instruction(vcpu);
return skip_emulated_instruction(vcpu);
}
static void vmx_clear_hlt(struct kvm_vcpu *vcpu) static void vmx_clear_hlt(struct kvm_vcpu *vcpu)
{ {
/* /*
@ -3818,24 +3858,29 @@ static int vmx_deliver_nested_posted_interrupt(struct kvm_vcpu *vcpu,
* 2. If target vcpu isn't running(root mode), kick it to pick up the * 2. If target vcpu isn't running(root mode), kick it to pick up the
* interrupt from PIR in next vmentry. * interrupt from PIR in next vmentry.
*/ */
static void vmx_deliver_posted_interrupt(struct kvm_vcpu *vcpu, int vector) static int vmx_deliver_posted_interrupt(struct kvm_vcpu *vcpu, int vector)
{ {
struct vcpu_vmx *vmx = to_vmx(vcpu); struct vcpu_vmx *vmx = to_vmx(vcpu);
int r; int r;
r = vmx_deliver_nested_posted_interrupt(vcpu, vector); r = vmx_deliver_nested_posted_interrupt(vcpu, vector);
if (!r) if (!r)
return; return 0;
if (!vcpu->arch.apicv_active)
return -1;
if (pi_test_and_set_pir(vector, &vmx->pi_desc)) if (pi_test_and_set_pir(vector, &vmx->pi_desc))
return; return 0;
/* If a previous notification has sent the IPI, nothing to do. */ /* If a previous notification has sent the IPI, nothing to do. */
if (pi_test_and_set_on(&vmx->pi_desc)) if (pi_test_and_set_on(&vmx->pi_desc))
return; return 0;
if (!kvm_vcpu_trigger_posted_interrupt(vcpu, false)) if (!kvm_vcpu_trigger_posted_interrupt(vcpu, false))
kvm_vcpu_kick(vcpu); kvm_vcpu_kick(vcpu);
return 0;
} }
/* /*
@ -6482,8 +6527,11 @@ static void vmx_vcpu_run(struct kvm_vcpu *vcpu)
vmcs_write32(PLE_WINDOW, vmx->ple_window); vmcs_write32(PLE_WINDOW, vmx->ple_window);
} }
if (vmx->nested.need_vmcs12_to_shadow_sync) /*
nested_sync_vmcs12_to_shadow(vcpu); * We did this in prepare_switch_to_guest, because it needs to
* be within srcu_read_lock.
*/
WARN_ON_ONCE(vmx->nested.need_vmcs12_to_shadow_sync);
if (kvm_register_is_dirty(vcpu, VCPU_REGS_RSP)) if (kvm_register_is_dirty(vcpu, VCPU_REGS_RSP))
vmcs_writel(GUEST_RSP, vcpu->arch.regs[VCPU_REGS_RSP]); vmcs_writel(GUEST_RSP, vcpu->arch.regs[VCPU_REGS_RSP]);
@ -6757,8 +6805,7 @@ static int vmx_create_vcpu(struct kvm_vcpu *vcpu)
if (nested) if (nested)
nested_vmx_setup_ctls_msrs(&vmx->nested.msrs, nested_vmx_setup_ctls_msrs(&vmx->nested.msrs,
vmx_capability.ept, vmx_capability.ept);
kvm_vcpu_apicv_active(vcpu));
else else
memset(&vmx->nested.msrs, 0, sizeof(vmx->nested.msrs)); memset(&vmx->nested.msrs, 0, sizeof(vmx->nested.msrs));
@ -6839,8 +6886,7 @@ static int __init vmx_check_processor_compat(void)
if (setup_vmcs_config(&vmcs_conf, &vmx_cap) < 0) if (setup_vmcs_config(&vmcs_conf, &vmx_cap) < 0)
return -EIO; return -EIO;
if (nested) if (nested)
nested_vmx_setup_ctls_msrs(&vmcs_conf.nested, vmx_cap.ept, nested_vmx_setup_ctls_msrs(&vmcs_conf.nested, vmx_cap.ept);
enable_apicv);
if (memcmp(&vmcs_config, &vmcs_conf, sizeof(struct vmcs_config)) != 0) { if (memcmp(&vmcs_config, &vmcs_conf, sizeof(struct vmcs_config)) != 0) {
printk(KERN_ERR "kvm: CPU %d feature inconsistency!\n", printk(KERN_ERR "kvm: CPU %d feature inconsistency!\n",
smp_processor_id()); smp_processor_id());
@ -7101,6 +7147,40 @@ static void vmx_request_immediate_exit(struct kvm_vcpu *vcpu)
to_vmx(vcpu)->req_immediate_exit = true; to_vmx(vcpu)->req_immediate_exit = true;
} }
static int vmx_check_intercept_io(struct kvm_vcpu *vcpu,
struct x86_instruction_info *info)
{
struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
unsigned short port;
bool intercept;
int size;
if (info->intercept == x86_intercept_in ||
info->intercept == x86_intercept_ins) {
port = info->src_val;
size = info->dst_bytes;
} else {
port = info->dst_val;
size = info->src_bytes;
}
/*
* If the 'use IO bitmaps' VM-execution control is 0, IO instruction
* VM-exits depend on the 'unconditional IO exiting' VM-execution
* control.
*
* Otherwise, IO instruction VM-exits are controlled by the IO bitmaps.
*/
if (!nested_cpu_has(vmcs12, CPU_BASED_USE_IO_BITMAPS))
intercept = nested_cpu_has(vmcs12,
CPU_BASED_UNCOND_IO_EXITING);
else
intercept = nested_vmx_check_io_bitmaps(vcpu, port, size);
/* FIXME: produce nested vmexit and return X86EMUL_INTERCEPTED. */
return intercept ? X86EMUL_UNHANDLEABLE : X86EMUL_CONTINUE;
}
static int vmx_check_intercept(struct kvm_vcpu *vcpu, static int vmx_check_intercept(struct kvm_vcpu *vcpu,
struct x86_instruction_info *info, struct x86_instruction_info *info,
enum x86_intercept_stage stage) enum x86_intercept_stage stage)
@ -7108,19 +7188,45 @@ static int vmx_check_intercept(struct kvm_vcpu *vcpu,
struct vmcs12 *vmcs12 = get_vmcs12(vcpu); struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
struct x86_emulate_ctxt *ctxt = &vcpu->arch.emulate_ctxt; struct x86_emulate_ctxt *ctxt = &vcpu->arch.emulate_ctxt;
switch (info->intercept) {
/* /*
* RDPID causes #UD if disabled through secondary execution controls. * RDPID causes #UD if disabled through secondary execution controls.
* Because it is marked as EmulateOnUD, we need to intercept it here. * Because it is marked as EmulateOnUD, we need to intercept it here.
*/ */
if (info->intercept == x86_intercept_rdtscp && case x86_intercept_rdtscp:
!nested_cpu_has2(vmcs12, SECONDARY_EXEC_RDTSCP)) { if (!nested_cpu_has2(vmcs12, SECONDARY_EXEC_RDTSCP)) {
ctxt->exception.vector = UD_VECTOR; ctxt->exception.vector = UD_VECTOR;
ctxt->exception.error_code_valid = false; ctxt->exception.error_code_valid = false;
return X86EMUL_PROPAGATE_FAULT; return X86EMUL_PROPAGATE_FAULT;
} }
break;
case x86_intercept_in:
case x86_intercept_ins:
case x86_intercept_out:
case x86_intercept_outs:
return vmx_check_intercept_io(vcpu, info);
case x86_intercept_lgdt:
case x86_intercept_lidt:
case x86_intercept_lldt:
case x86_intercept_ltr:
case x86_intercept_sgdt:
case x86_intercept_sidt:
case x86_intercept_sldt:
case x86_intercept_str:
if (!nested_cpu_has2(vmcs12, SECONDARY_EXEC_DESC))
return X86EMUL_CONTINUE;
/* FIXME: produce nested vmexit and return X86EMUL_INTERCEPTED. */
break;
/* TODO: check more intercepts... */ /* TODO: check more intercepts... */
return X86EMUL_CONTINUE; default:
break;
}
return X86EMUL_UNHANDLEABLE;
} }
#ifdef CONFIG_X86_64 #ifdef CONFIG_X86_64
@ -7702,7 +7808,7 @@ static __init int hardware_setup(void)
if (nested) { if (nested) {
nested_vmx_setup_ctls_msrs(&vmcs_config.nested, nested_vmx_setup_ctls_msrs(&vmcs_config.nested,
vmx_capability.ept, enable_apicv); vmx_capability.ept);
r = nested_vmx_hardware_setup(kvm_vmx_exit_handlers); r = nested_vmx_hardware_setup(kvm_vmx_exit_handlers);
if (r) if (r)
@ -7786,7 +7892,8 @@ static struct kvm_x86_ops vmx_x86_ops __ro_after_init = {
.run = vmx_vcpu_run, .run = vmx_vcpu_run,
.handle_exit = vmx_handle_exit, .handle_exit = vmx_handle_exit,
.skip_emulated_instruction = skip_emulated_instruction, .skip_emulated_instruction = vmx_skip_emulated_instruction,
.update_emulated_instruction = vmx_update_emulated_instruction,
.set_interrupt_shadow = vmx_set_interrupt_shadow, .set_interrupt_shadow = vmx_set_interrupt_shadow,
.get_interrupt_shadow = vmx_get_interrupt_shadow, .get_interrupt_shadow = vmx_get_interrupt_shadow,
.patch_hypercall = vmx_patch_hypercall, .patch_hypercall = vmx_patch_hypercall,

View File

@ -150,6 +150,9 @@ struct nested_vmx {
/* L2 must run next, and mustn't decide to exit to L1. */ /* L2 must run next, and mustn't decide to exit to L1. */
bool nested_run_pending; bool nested_run_pending;
/* Pending MTF VM-exit into L1. */
bool mtf_pending;
struct loaded_vmcs vmcs02; struct loaded_vmcs vmcs02;
/* /*

View File

@ -6891,6 +6891,8 @@ restart:
kvm_rip_write(vcpu, ctxt->eip); kvm_rip_write(vcpu, ctxt->eip);
if (r && ctxt->tf) if (r && ctxt->tf)
r = kvm_vcpu_do_singlestep(vcpu); r = kvm_vcpu_do_singlestep(vcpu);
if (kvm_x86_ops->update_emulated_instruction)
kvm_x86_ops->update_emulated_instruction(vcpu);
__kvm_set_rflags(vcpu, ctxt->eflags); __kvm_set_rflags(vcpu, ctxt->eflags);
} }
@ -7188,15 +7190,15 @@ static void kvm_timer_init(void)
if (!boot_cpu_has(X86_FEATURE_CONSTANT_TSC)) { if (!boot_cpu_has(X86_FEATURE_CONSTANT_TSC)) {
#ifdef CONFIG_CPU_FREQ #ifdef CONFIG_CPU_FREQ
struct cpufreq_policy policy; struct cpufreq_policy *policy;
int cpu; int cpu;
memset(&policy, 0, sizeof(policy));
cpu = get_cpu(); cpu = get_cpu();
cpufreq_get_policy(&policy, cpu); policy = cpufreq_cpu_get(cpu);
if (policy.cpuinfo.max_freq) if (policy && policy->cpuinfo.max_freq)
max_tsc_khz = policy.cpuinfo.max_freq; max_tsc_khz = policy->cpuinfo.max_freq;
put_cpu(); put_cpu();
cpufreq_cpu_put(policy);
#endif #endif
cpufreq_register_notifier(&kvmclock_cpufreq_notifier_block, cpufreq_register_notifier(&kvmclock_cpufreq_notifier_block,
CPUFREQ_TRANSITION_NOTIFIER); CPUFREQ_TRANSITION_NOTIFIER);
@ -7306,12 +7308,12 @@ int kvm_arch_init(void *opaque)
} }
if (!ops->cpu_has_kvm_support()) { if (!ops->cpu_has_kvm_support()) {
printk(KERN_ERR "kvm: no hardware support\n"); pr_err_ratelimited("kvm: no hardware support\n");
r = -EOPNOTSUPP; r = -EOPNOTSUPP;
goto out; goto out;
} }
if (ops->disabled_by_bios()) { if (ops->disabled_by_bios()) {
printk(KERN_ERR "kvm: disabled by bios\n"); pr_err_ratelimited("kvm: disabled by bios\n");
r = -EOPNOTSUPP; r = -EOPNOTSUPP;
goto out; goto out;
} }

View File

@ -363,13 +363,8 @@ static void ptdump_walk_pgd_level_core(struct seq_file *m,
{ {
const struct ptdump_range ptdump_ranges[] = { const struct ptdump_range ptdump_ranges[] = {
#ifdef CONFIG_X86_64 #ifdef CONFIG_X86_64
#define normalize_addr_shift (64 - (__VIRTUAL_MASK_SHIFT + 1))
#define normalize_addr(u) ((signed long)((u) << normalize_addr_shift) >> \
normalize_addr_shift)
{0, PTRS_PER_PGD * PGD_LEVEL_MULT / 2}, {0, PTRS_PER_PGD * PGD_LEVEL_MULT / 2},
{normalize_addr(PTRS_PER_PGD * PGD_LEVEL_MULT / 2), ~0UL}, {GUARD_HOLE_END_ADDR, ~0UL},
#else #else
{0, ~0UL}, {0, ~0UL},
#endif #endif

View File

@ -180,7 +180,7 @@ void efi_sync_low_kernel_mappings(void)
static inline phys_addr_t static inline phys_addr_t
virt_to_phys_or_null_size(void *va, unsigned long size) virt_to_phys_or_null_size(void *va, unsigned long size)
{ {
bool bad_size; phys_addr_t pa;
if (!va) if (!va)
return 0; return 0;
@ -188,16 +188,13 @@ virt_to_phys_or_null_size(void *va, unsigned long size)
if (virt_addr_valid(va)) if (virt_addr_valid(va))
return virt_to_phys(va); return virt_to_phys(va);
/* pa = slow_virt_to_phys(va);
* A fully aligned variable on the stack is guaranteed not to
* cross a page bounary. Try to catch strings on the stack by
* checking that 'size' is a power of two.
*/
bad_size = size > PAGE_SIZE || !is_power_of_2(size);
WARN_ON(!IS_ALIGNED((unsigned long)va, size) || bad_size); /* check if the object crosses a page boundary */
if (WARN_ON((pa ^ (pa + size - 1)) & PAGE_MASK))
return 0;
return slow_virt_to_phys(va); return pa;
} }
#define virt_to_phys_or_null(addr) \ #define virt_to_phys_or_null(addr) \
@ -568,85 +565,25 @@ efi_thunk_set_virtual_address_map(unsigned long memory_map_size,
static efi_status_t efi_thunk_get_time(efi_time_t *tm, efi_time_cap_t *tc) static efi_status_t efi_thunk_get_time(efi_time_t *tm, efi_time_cap_t *tc)
{ {
efi_status_t status; return EFI_UNSUPPORTED;
u32 phys_tm, phys_tc;
unsigned long flags;
spin_lock(&rtc_lock);
spin_lock_irqsave(&efi_runtime_lock, flags);
phys_tm = virt_to_phys_or_null(tm);
phys_tc = virt_to_phys_or_null(tc);
status = efi_thunk(get_time, phys_tm, phys_tc);
spin_unlock_irqrestore(&efi_runtime_lock, flags);
spin_unlock(&rtc_lock);
return status;
} }
static efi_status_t efi_thunk_set_time(efi_time_t *tm) static efi_status_t efi_thunk_set_time(efi_time_t *tm)
{ {
efi_status_t status; return EFI_UNSUPPORTED;
u32 phys_tm;
unsigned long flags;
spin_lock(&rtc_lock);
spin_lock_irqsave(&efi_runtime_lock, flags);
phys_tm = virt_to_phys_or_null(tm);
status = efi_thunk(set_time, phys_tm);
spin_unlock_irqrestore(&efi_runtime_lock, flags);
spin_unlock(&rtc_lock);
return status;
} }
static efi_status_t static efi_status_t
efi_thunk_get_wakeup_time(efi_bool_t *enabled, efi_bool_t *pending, efi_thunk_get_wakeup_time(efi_bool_t *enabled, efi_bool_t *pending,
efi_time_t *tm) efi_time_t *tm)
{ {
efi_status_t status; return EFI_UNSUPPORTED;
u32 phys_enabled, phys_pending, phys_tm;
unsigned long flags;
spin_lock(&rtc_lock);
spin_lock_irqsave(&efi_runtime_lock, flags);
phys_enabled = virt_to_phys_or_null(enabled);
phys_pending = virt_to_phys_or_null(pending);
phys_tm = virt_to_phys_or_null(tm);
status = efi_thunk(get_wakeup_time, phys_enabled,
phys_pending, phys_tm);
spin_unlock_irqrestore(&efi_runtime_lock, flags);
spin_unlock(&rtc_lock);
return status;
} }
static efi_status_t static efi_status_t
efi_thunk_set_wakeup_time(efi_bool_t enabled, efi_time_t *tm) efi_thunk_set_wakeup_time(efi_bool_t enabled, efi_time_t *tm)
{ {
efi_status_t status; return EFI_UNSUPPORTED;
u32 phys_tm;
unsigned long flags;
spin_lock(&rtc_lock);
spin_lock_irqsave(&efi_runtime_lock, flags);
phys_tm = virt_to_phys_or_null(tm);
status = efi_thunk(set_wakeup_time, enabled, phys_tm);
spin_unlock_irqrestore(&efi_runtime_lock, flags);
spin_unlock(&rtc_lock);
return status;
} }
static unsigned long efi_name_size(efi_char16_t *name) static unsigned long efi_name_size(efi_char16_t *name)
@ -658,6 +595,8 @@ static efi_status_t
efi_thunk_get_variable(efi_char16_t *name, efi_guid_t *vendor, efi_thunk_get_variable(efi_char16_t *name, efi_guid_t *vendor,
u32 *attr, unsigned long *data_size, void *data) u32 *attr, unsigned long *data_size, void *data)
{ {
u8 buf[24] __aligned(8);
efi_guid_t *vnd = PTR_ALIGN((efi_guid_t *)buf, sizeof(*vnd));
efi_status_t status; efi_status_t status;
u32 phys_name, phys_vendor, phys_attr; u32 phys_name, phys_vendor, phys_attr;
u32 phys_data_size, phys_data; u32 phys_data_size, phys_data;
@ -665,14 +604,19 @@ efi_thunk_get_variable(efi_char16_t *name, efi_guid_t *vendor,
spin_lock_irqsave(&efi_runtime_lock, flags); spin_lock_irqsave(&efi_runtime_lock, flags);
*vnd = *vendor;
phys_data_size = virt_to_phys_or_null(data_size); phys_data_size = virt_to_phys_or_null(data_size);
phys_vendor = virt_to_phys_or_null(vendor); phys_vendor = virt_to_phys_or_null(vnd);
phys_name = virt_to_phys_or_null_size(name, efi_name_size(name)); phys_name = virt_to_phys_or_null_size(name, efi_name_size(name));
phys_attr = virt_to_phys_or_null(attr); phys_attr = virt_to_phys_or_null(attr);
phys_data = virt_to_phys_or_null_size(data, *data_size); phys_data = virt_to_phys_or_null_size(data, *data_size);
status = efi_thunk(get_variable, phys_name, phys_vendor, if (!phys_name || (data && !phys_data))
phys_attr, phys_data_size, phys_data); status = EFI_INVALID_PARAMETER;
else
status = efi_thunk(get_variable, phys_name, phys_vendor,
phys_attr, phys_data_size, phys_data);
spin_unlock_irqrestore(&efi_runtime_lock, flags); spin_unlock_irqrestore(&efi_runtime_lock, flags);
@ -683,19 +627,25 @@ static efi_status_t
efi_thunk_set_variable(efi_char16_t *name, efi_guid_t *vendor, efi_thunk_set_variable(efi_char16_t *name, efi_guid_t *vendor,
u32 attr, unsigned long data_size, void *data) u32 attr, unsigned long data_size, void *data)
{ {
u8 buf[24] __aligned(8);
efi_guid_t *vnd = PTR_ALIGN((efi_guid_t *)buf, sizeof(*vnd));
u32 phys_name, phys_vendor, phys_data; u32 phys_name, phys_vendor, phys_data;
efi_status_t status; efi_status_t status;
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&efi_runtime_lock, flags); spin_lock_irqsave(&efi_runtime_lock, flags);
*vnd = *vendor;
phys_name = virt_to_phys_or_null_size(name, efi_name_size(name)); phys_name = virt_to_phys_or_null_size(name, efi_name_size(name));
phys_vendor = virt_to_phys_or_null(vendor); phys_vendor = virt_to_phys_or_null(vnd);
phys_data = virt_to_phys_or_null_size(data, data_size); phys_data = virt_to_phys_or_null_size(data, data_size);
/* If data_size is > sizeof(u32) we've got problems */ if (!phys_name || !phys_data)
status = efi_thunk(set_variable, phys_name, phys_vendor, status = EFI_INVALID_PARAMETER;
attr, data_size, phys_data); else
status = efi_thunk(set_variable, phys_name, phys_vendor,
attr, data_size, phys_data);
spin_unlock_irqrestore(&efi_runtime_lock, flags); spin_unlock_irqrestore(&efi_runtime_lock, flags);
@ -707,6 +657,8 @@ efi_thunk_set_variable_nonblocking(efi_char16_t *name, efi_guid_t *vendor,
u32 attr, unsigned long data_size, u32 attr, unsigned long data_size,
void *data) void *data)
{ {
u8 buf[24] __aligned(8);
efi_guid_t *vnd = PTR_ALIGN((efi_guid_t *)buf, sizeof(*vnd));
u32 phys_name, phys_vendor, phys_data; u32 phys_name, phys_vendor, phys_data;
efi_status_t status; efi_status_t status;
unsigned long flags; unsigned long flags;
@ -714,13 +666,17 @@ efi_thunk_set_variable_nonblocking(efi_char16_t *name, efi_guid_t *vendor,
if (!spin_trylock_irqsave(&efi_runtime_lock, flags)) if (!spin_trylock_irqsave(&efi_runtime_lock, flags))
return EFI_NOT_READY; return EFI_NOT_READY;
*vnd = *vendor;
phys_name = virt_to_phys_or_null_size(name, efi_name_size(name)); phys_name = virt_to_phys_or_null_size(name, efi_name_size(name));
phys_vendor = virt_to_phys_or_null(vendor); phys_vendor = virt_to_phys_or_null(vnd);
phys_data = virt_to_phys_or_null_size(data, data_size); phys_data = virt_to_phys_or_null_size(data, data_size);
/* If data_size is > sizeof(u32) we've got problems */ if (!phys_name || !phys_data)
status = efi_thunk(set_variable, phys_name, phys_vendor, status = EFI_INVALID_PARAMETER;
attr, data_size, phys_data); else
status = efi_thunk(set_variable, phys_name, phys_vendor,
attr, data_size, phys_data);
spin_unlock_irqrestore(&efi_runtime_lock, flags); spin_unlock_irqrestore(&efi_runtime_lock, flags);
@ -732,39 +688,36 @@ efi_thunk_get_next_variable(unsigned long *name_size,
efi_char16_t *name, efi_char16_t *name,
efi_guid_t *vendor) efi_guid_t *vendor)
{ {
u8 buf[24] __aligned(8);
efi_guid_t *vnd = PTR_ALIGN((efi_guid_t *)buf, sizeof(*vnd));
efi_status_t status; efi_status_t status;
u32 phys_name_size, phys_name, phys_vendor; u32 phys_name_size, phys_name, phys_vendor;
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&efi_runtime_lock, flags); spin_lock_irqsave(&efi_runtime_lock, flags);
*vnd = *vendor;
phys_name_size = virt_to_phys_or_null(name_size); phys_name_size = virt_to_phys_or_null(name_size);
phys_vendor = virt_to_phys_or_null(vendor); phys_vendor = virt_to_phys_or_null(vnd);
phys_name = virt_to_phys_or_null_size(name, *name_size); phys_name = virt_to_phys_or_null_size(name, *name_size);
status = efi_thunk(get_next_variable, phys_name_size, if (!phys_name)
phys_name, phys_vendor); status = EFI_INVALID_PARAMETER;
else
status = efi_thunk(get_next_variable, phys_name_size,
phys_name, phys_vendor);
spin_unlock_irqrestore(&efi_runtime_lock, flags); spin_unlock_irqrestore(&efi_runtime_lock, flags);
*vendor = *vnd;
return status; return status;
} }
static efi_status_t static efi_status_t
efi_thunk_get_next_high_mono_count(u32 *count) efi_thunk_get_next_high_mono_count(u32 *count)
{ {
efi_status_t status; return EFI_UNSUPPORTED;
u32 phys_count;
unsigned long flags;
spin_lock_irqsave(&efi_runtime_lock, flags);
phys_count = virt_to_phys_or_null(count);
status = efi_thunk(get_next_high_mono_count, phys_count);
spin_unlock_irqrestore(&efi_runtime_lock, flags);
return status;
} }
static void static void

View File

@ -72,6 +72,9 @@
#include <asm/mwait.h> #include <asm/mwait.h>
#include <asm/pci_x86.h> #include <asm/pci_x86.h>
#include <asm/cpu.h> #include <asm/cpu.h>
#ifdef CONFIG_X86_IOPL_IOPERM
#include <asm/io_bitmap.h>
#endif
#ifdef CONFIG_ACPI #ifdef CONFIG_ACPI
#include <linux/acpi.h> #include <linux/acpi.h>
@ -837,6 +840,25 @@ static void xen_load_sp0(unsigned long sp0)
this_cpu_write(cpu_tss_rw.x86_tss.sp0, sp0); this_cpu_write(cpu_tss_rw.x86_tss.sp0, sp0);
} }
#ifdef CONFIG_X86_IOPL_IOPERM
static void xen_update_io_bitmap(void)
{
struct physdev_set_iobitmap iobitmap;
struct tss_struct *tss = this_cpu_ptr(&cpu_tss_rw);
native_tss_update_io_bitmap();
iobitmap.bitmap = (uint8_t *)(&tss->x86_tss) +
tss->x86_tss.io_bitmap_base;
if (tss->x86_tss.io_bitmap_base == IO_BITMAP_OFFSET_INVALID)
iobitmap.nr_ports = 0;
else
iobitmap.nr_ports = IO_BITMAP_BITS;
HYPERVISOR_physdev_op(PHYSDEVOP_set_iobitmap, &iobitmap);
}
#endif
static void xen_io_delay(void) static void xen_io_delay(void)
{ {
} }
@ -1047,6 +1069,9 @@ static const struct pv_cpu_ops xen_cpu_ops __initconst = {
.write_idt_entry = xen_write_idt_entry, .write_idt_entry = xen_write_idt_entry,
.load_sp0 = xen_load_sp0, .load_sp0 = xen_load_sp0,
#ifdef CONFIG_X86_IOPL_IOPERM
.update_io_bitmap = xen_update_io_bitmap,
#endif
.io_delay = xen_io_delay, .io_delay = xen_io_delay,
/* Xen takes care of %gs when switching to usermode for us */ /* Xen takes care of %gs when switching to usermode for us */

View File

@ -412,7 +412,7 @@ void blk_insert_flush(struct request *rq)
*/ */
if ((policy & REQ_FSEQ_DATA) && if ((policy & REQ_FSEQ_DATA) &&
!(policy & (REQ_FSEQ_PREFLUSH | REQ_FSEQ_POSTFLUSH))) { !(policy & (REQ_FSEQ_PREFLUSH | REQ_FSEQ_POSTFLUSH))) {
blk_mq_request_bypass_insert(rq, false); blk_mq_request_bypass_insert(rq, false, false);
return; return;
} }

View File

@ -361,13 +361,19 @@ static bool blk_mq_sched_bypass_insert(struct blk_mq_hw_ctx *hctx,
bool has_sched, bool has_sched,
struct request *rq) struct request *rq)
{ {
/* dispatch flush rq directly */ /*
if (rq->rq_flags & RQF_FLUSH_SEQ) { * dispatch flush and passthrough rq directly
spin_lock(&hctx->lock); *
list_add(&rq->queuelist, &hctx->dispatch); * passthrough request has to be added to hctx->dispatch directly.
spin_unlock(&hctx->lock); * For some reason, device may be in one situation which can't
* handle FS request, so STS_RESOURCE is always returned and the
* FS request will be added to hctx->dispatch. However passthrough
* request may be required at that time for fixing the problem. If
* passthrough request is added to scheduler queue, there isn't any
* chance to dispatch it given we prioritize requests in hctx->dispatch.
*/
if ((rq->rq_flags & RQF_FLUSH_SEQ) || blk_rq_is_passthrough(rq))
return true; return true;
}
if (has_sched) if (has_sched)
rq->rq_flags |= RQF_SORTED; rq->rq_flags |= RQF_SORTED;
@ -391,8 +397,10 @@ void blk_mq_sched_insert_request(struct request *rq, bool at_head,
WARN_ON(e && (rq->tag != -1)); WARN_ON(e && (rq->tag != -1));
if (blk_mq_sched_bypass_insert(hctx, !!e, rq)) if (blk_mq_sched_bypass_insert(hctx, !!e, rq)) {
blk_mq_request_bypass_insert(rq, at_head, false);
goto run; goto run;
}
if (e && e->type->ops.insert_requests) { if (e && e->type->ops.insert_requests) {
LIST_HEAD(list); LIST_HEAD(list);

View File

@ -183,8 +183,8 @@ found_tag:
return tag + tag_offset; return tag + tag_offset;
} }
void blk_mq_put_tag(struct blk_mq_hw_ctx *hctx, struct blk_mq_tags *tags, void blk_mq_put_tag(struct blk_mq_tags *tags, struct blk_mq_ctx *ctx,
struct blk_mq_ctx *ctx, unsigned int tag) unsigned int tag)
{ {
if (!blk_mq_tag_is_reserved(tags, tag)) { if (!blk_mq_tag_is_reserved(tags, tag)) {
const int real_tag = tag - tags->nr_reserved_tags; const int real_tag = tag - tags->nr_reserved_tags;

View File

@ -26,8 +26,8 @@ extern struct blk_mq_tags *blk_mq_init_tags(unsigned int nr_tags, unsigned int r
extern void blk_mq_free_tags(struct blk_mq_tags *tags); extern void blk_mq_free_tags(struct blk_mq_tags *tags);
extern unsigned int blk_mq_get_tag(struct blk_mq_alloc_data *data); extern unsigned int blk_mq_get_tag(struct blk_mq_alloc_data *data);
extern void blk_mq_put_tag(struct blk_mq_hw_ctx *hctx, struct blk_mq_tags *tags, extern void blk_mq_put_tag(struct blk_mq_tags *tags, struct blk_mq_ctx *ctx,
struct blk_mq_ctx *ctx, unsigned int tag); unsigned int tag);
extern int blk_mq_tag_update_depth(struct blk_mq_hw_ctx *hctx, extern int blk_mq_tag_update_depth(struct blk_mq_hw_ctx *hctx,
struct blk_mq_tags **tags, struct blk_mq_tags **tags,
unsigned int depth, bool can_grow); unsigned int depth, bool can_grow);

View File

@ -477,9 +477,9 @@ static void __blk_mq_free_request(struct request *rq)
blk_pm_mark_last_busy(rq); blk_pm_mark_last_busy(rq);
rq->mq_hctx = NULL; rq->mq_hctx = NULL;
if (rq->tag != -1) if (rq->tag != -1)
blk_mq_put_tag(hctx, hctx->tags, ctx, rq->tag); blk_mq_put_tag(hctx->tags, ctx, rq->tag);
if (sched_tag != -1) if (sched_tag != -1)
blk_mq_put_tag(hctx, hctx->sched_tags, ctx, sched_tag); blk_mq_put_tag(hctx->sched_tags, ctx, sched_tag);
blk_mq_sched_restart(hctx); blk_mq_sched_restart(hctx);
blk_queue_exit(q); blk_queue_exit(q);
} }
@ -735,7 +735,7 @@ static void blk_mq_requeue_work(struct work_struct *work)
* merge. * merge.
*/ */
if (rq->rq_flags & RQF_DONTPREP) if (rq->rq_flags & RQF_DONTPREP)
blk_mq_request_bypass_insert(rq, false); blk_mq_request_bypass_insert(rq, false, false);
else else
blk_mq_sched_insert_request(rq, true, false, false); blk_mq_sched_insert_request(rq, true, false, false);
} }
@ -1286,7 +1286,7 @@ bool blk_mq_dispatch_rq_list(struct request_queue *q, struct list_head *list,
q->mq_ops->commit_rqs(hctx); q->mq_ops->commit_rqs(hctx);
spin_lock(&hctx->lock); spin_lock(&hctx->lock);
list_splice_init(list, &hctx->dispatch); list_splice_tail_init(list, &hctx->dispatch);
spin_unlock(&hctx->lock); spin_unlock(&hctx->lock);
/* /*
@ -1677,12 +1677,16 @@ void __blk_mq_insert_request(struct blk_mq_hw_ctx *hctx, struct request *rq,
* Should only be used carefully, when the caller knows we want to * Should only be used carefully, when the caller knows we want to
* bypass a potential IO scheduler on the target device. * bypass a potential IO scheduler on the target device.
*/ */
void blk_mq_request_bypass_insert(struct request *rq, bool run_queue) void blk_mq_request_bypass_insert(struct request *rq, bool at_head,
bool run_queue)
{ {
struct blk_mq_hw_ctx *hctx = rq->mq_hctx; struct blk_mq_hw_ctx *hctx = rq->mq_hctx;
spin_lock(&hctx->lock); spin_lock(&hctx->lock);
list_add_tail(&rq->queuelist, &hctx->dispatch); if (at_head)
list_add(&rq->queuelist, &hctx->dispatch);
else
list_add_tail(&rq->queuelist, &hctx->dispatch);
spin_unlock(&hctx->lock); spin_unlock(&hctx->lock);
if (run_queue) if (run_queue)
@ -1849,7 +1853,7 @@ insert:
if (bypass_insert) if (bypass_insert)
return BLK_STS_RESOURCE; return BLK_STS_RESOURCE;
blk_mq_request_bypass_insert(rq, run_queue); blk_mq_request_bypass_insert(rq, false, run_queue);
return BLK_STS_OK; return BLK_STS_OK;
} }
@ -1876,7 +1880,7 @@ static void blk_mq_try_issue_directly(struct blk_mq_hw_ctx *hctx,
ret = __blk_mq_try_issue_directly(hctx, rq, cookie, false, true); ret = __blk_mq_try_issue_directly(hctx, rq, cookie, false, true);
if (ret == BLK_STS_RESOURCE || ret == BLK_STS_DEV_RESOURCE) if (ret == BLK_STS_RESOURCE || ret == BLK_STS_DEV_RESOURCE)
blk_mq_request_bypass_insert(rq, true); blk_mq_request_bypass_insert(rq, false, true);
else if (ret != BLK_STS_OK) else if (ret != BLK_STS_OK)
blk_mq_end_request(rq, ret); blk_mq_end_request(rq, ret);
@ -1910,7 +1914,7 @@ void blk_mq_try_issue_list_directly(struct blk_mq_hw_ctx *hctx,
if (ret != BLK_STS_OK) { if (ret != BLK_STS_OK) {
if (ret == BLK_STS_RESOURCE || if (ret == BLK_STS_RESOURCE ||
ret == BLK_STS_DEV_RESOURCE) { ret == BLK_STS_DEV_RESOURCE) {
blk_mq_request_bypass_insert(rq, blk_mq_request_bypass_insert(rq, false,
list_empty(list)); list_empty(list));
break; break;
} }
@ -3398,7 +3402,6 @@ static void blk_mq_poll_stats_fn(struct blk_stat_callback *cb)
} }
static unsigned long blk_mq_poll_nsecs(struct request_queue *q, static unsigned long blk_mq_poll_nsecs(struct request_queue *q,
struct blk_mq_hw_ctx *hctx,
struct request *rq) struct request *rq)
{ {
unsigned long ret = 0; unsigned long ret = 0;
@ -3431,7 +3434,6 @@ static unsigned long blk_mq_poll_nsecs(struct request_queue *q,
} }
static bool blk_mq_poll_hybrid_sleep(struct request_queue *q, static bool blk_mq_poll_hybrid_sleep(struct request_queue *q,
struct blk_mq_hw_ctx *hctx,
struct request *rq) struct request *rq)
{ {
struct hrtimer_sleeper hs; struct hrtimer_sleeper hs;
@ -3451,7 +3453,7 @@ static bool blk_mq_poll_hybrid_sleep(struct request_queue *q,
if (q->poll_nsec > 0) if (q->poll_nsec > 0)
nsecs = q->poll_nsec; nsecs = q->poll_nsec;
else else
nsecs = blk_mq_poll_nsecs(q, hctx, rq); nsecs = blk_mq_poll_nsecs(q, rq);
if (!nsecs) if (!nsecs)
return false; return false;
@ -3506,7 +3508,7 @@ static bool blk_mq_poll_hybrid(struct request_queue *q,
return false; return false;
} }
return blk_mq_poll_hybrid_sleep(q, hctx, rq); return blk_mq_poll_hybrid_sleep(q, rq);
} }
/** /**

View File

@ -66,7 +66,8 @@ int blk_mq_alloc_rqs(struct blk_mq_tag_set *set, struct blk_mq_tags *tags,
*/ */
void __blk_mq_insert_request(struct blk_mq_hw_ctx *hctx, struct request *rq, void __blk_mq_insert_request(struct blk_mq_hw_ctx *hctx, struct request *rq,
bool at_head); bool at_head);
void blk_mq_request_bypass_insert(struct request *rq, bool run_queue); void blk_mq_request_bypass_insert(struct request *rq, bool at_head,
bool run_queue);
void blk_mq_insert_requests(struct blk_mq_hw_ctx *hctx, struct blk_mq_ctx *ctx, void blk_mq_insert_requests(struct blk_mq_hw_ctx *hctx, struct blk_mq_ctx *ctx,
struct list_head *list); struct list_head *list);
@ -199,7 +200,7 @@ static inline bool blk_mq_get_dispatch_budget(struct blk_mq_hw_ctx *hctx)
static inline void __blk_mq_put_driver_tag(struct blk_mq_hw_ctx *hctx, static inline void __blk_mq_put_driver_tag(struct blk_mq_hw_ctx *hctx,
struct request *rq) struct request *rq)
{ {
blk_mq_put_tag(hctx, hctx->tags, rq->mq_ctx, rq->tag); blk_mq_put_tag(hctx->tags, rq->mq_ctx, rq->tag);
rq->tag = -1; rq->tag = -1;
if (rq->rq_flags & RQF_MQ_INFLIGHT) { if (rq->rq_flags & RQF_MQ_INFLIGHT) {

View File

@ -55,12 +55,14 @@ static bool acpi_watchdog_uses_rtc(const struct acpi_table_wdat *wdat)
} }
#endif #endif
static bool acpi_no_watchdog;
static const struct acpi_table_wdat *acpi_watchdog_get_wdat(void) static const struct acpi_table_wdat *acpi_watchdog_get_wdat(void)
{ {
const struct acpi_table_wdat *wdat = NULL; const struct acpi_table_wdat *wdat = NULL;
acpi_status status; acpi_status status;
if (acpi_disabled) if (acpi_disabled || acpi_no_watchdog)
return NULL; return NULL;
status = acpi_get_table(ACPI_SIG_WDAT, 0, status = acpi_get_table(ACPI_SIG_WDAT, 0,
@ -88,6 +90,14 @@ bool acpi_has_watchdog(void)
} }
EXPORT_SYMBOL_GPL(acpi_has_watchdog); EXPORT_SYMBOL_GPL(acpi_has_watchdog);
/* ACPI watchdog can be disabled on boot command line */
static int __init disable_acpi_watchdog(char *str)
{
acpi_no_watchdog = true;
return 1;
}
__setup("acpi_no_watchdog", disable_acpi_watchdog);
void __init acpi_watchdog_init(void) void __init acpi_watchdog_init(void)
{ {
const struct acpi_wdat_entry *entries; const struct acpi_wdat_entry *entries;
@ -126,12 +136,11 @@ void __init acpi_watchdog_init(void)
gas = &entries[i].register_region; gas = &entries[i].register_region;
res.start = gas->address; res.start = gas->address;
res.end = res.start + ACPI_ACCESS_BYTE_WIDTH(gas->access_width) - 1;
if (gas->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) { if (gas->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
res.flags = IORESOURCE_MEM; res.flags = IORESOURCE_MEM;
res.end = res.start + ALIGN(gas->access_width, 4) - 1;
} else if (gas->space_id == ACPI_ADR_SPACE_SYSTEM_IO) { } else if (gas->space_id == ACPI_ADR_SPACE_SYSTEM_IO) {
res.flags = IORESOURCE_IO; res.flags = IORESOURCE_IO;
res.end = res.start + gas->access_width - 1;
} else { } else {
pr_warn("Unsupported address space: %u\n", pr_warn("Unsupported address space: %u\n",
gas->space_id); gas->space_id);

View File

@ -853,14 +853,17 @@ static void reset_fdc_info(int mode)
/* selects the fdc and drive, and enables the fdc's input/dma. */ /* selects the fdc and drive, and enables the fdc's input/dma. */
static void set_fdc(int drive) static void set_fdc(int drive)
{ {
unsigned int new_fdc = fdc;
if (drive >= 0 && drive < N_DRIVE) { if (drive >= 0 && drive < N_DRIVE) {
fdc = FDC(drive); new_fdc = FDC(drive);
current_drive = drive; current_drive = drive;
} }
if (fdc != 1 && fdc != 0) { if (new_fdc >= N_FDC) {
pr_info("bad fdc value\n"); pr_info("bad fdc value\n");
return; return;
} }
fdc = new_fdc;
set_dor(fdc, ~0, 8); set_dor(fdc, ~0, 8);
#if N_FDC > 1 #if N_FDC > 1
set_dor(1 - fdc, ~8, 0); set_dor(1 - fdc, ~8, 0);

View File

@ -14,9 +14,6 @@
#include <linux/fault-inject.h> #include <linux/fault-inject.h>
struct nullb_cmd { struct nullb_cmd {
struct list_head list;
struct llist_node ll_list;
struct __call_single_data csd;
struct request *rq; struct request *rq;
struct bio *bio; struct bio *bio;
unsigned int tag; unsigned int tag;

View File

@ -1518,8 +1518,6 @@ static int setup_commands(struct nullb_queue *nq)
for (i = 0; i < nq->queue_depth; i++) { for (i = 0; i < nq->queue_depth; i++) {
cmd = &nq->cmds[i]; cmd = &nq->cmds[i];
INIT_LIST_HEAD(&cmd->list);
cmd->ll_list.next = NULL;
cmd->tag = -1U; cmd->tag = -1U;
} }

View File

@ -276,7 +276,7 @@ static const struct block_device_operations pcd_bdops = {
.release = pcd_block_release, .release = pcd_block_release,
.ioctl = pcd_block_ioctl, .ioctl = pcd_block_ioctl,
#ifdef CONFIG_COMPAT #ifdef CONFIG_COMPAT
.ioctl = blkdev_compat_ptr_ioctl, .compat_ioctl = blkdev_compat_ptr_ioctl,
#endif #endif
.check_events = pcd_block_check_events, .check_events = pcd_block_check_events,
}; };

View File

@ -519,7 +519,7 @@ static const struct block_device_operations gdrom_bdops = {
.check_events = gdrom_bdops_check_events, .check_events = gdrom_bdops_check_events,
.ioctl = gdrom_bdops_ioctl, .ioctl = gdrom_bdops_ioctl,
#ifdef CONFIG_COMPAT #ifdef CONFIG_COMPAT
.ioctl = blkdev_compat_ptr_ioctl, .compat_ioctl = blkdev_compat_ptr_ioctl,
#endif #endif
}; };

View File

@ -1076,9 +1076,17 @@ static int cpufreq_init_policy(struct cpufreq_policy *policy)
pol = policy->last_policy; pol = policy->last_policy;
} else if (def_gov) { } else if (def_gov) {
pol = cpufreq_parse_policy(def_gov->name); pol = cpufreq_parse_policy(def_gov->name);
} else { /*
return -ENODATA; * In case the default governor is neiter "performance"
* nor "powersave", fall back to the initial policy
* value set by the driver.
*/
if (pol == CPUFREQ_POLICY_UNKNOWN)
pol = policy->policy;
} }
if (pol != CPUFREQ_POLICY_PERFORMANCE &&
pol != CPUFREQ_POLICY_POWERSAVE)
return -ENODATA;
} }
return cpufreq_set_policy(policy, gov, pol); return cpufreq_set_policy(policy, gov, pol);

View File

@ -738,7 +738,6 @@ struct devfreq *devfreq_add_device(struct device *dev,
{ {
struct devfreq *devfreq; struct devfreq *devfreq;
struct devfreq_governor *governor; struct devfreq_governor *governor;
static atomic_t devfreq_no = ATOMIC_INIT(-1);
int err = 0; int err = 0;
if (!dev || !profile || !governor_name) { if (!dev || !profile || !governor_name) {
@ -800,8 +799,7 @@ struct devfreq *devfreq_add_device(struct device *dev,
devfreq->suspend_freq = dev_pm_opp_get_suspend_opp_freq(dev); devfreq->suspend_freq = dev_pm_opp_get_suspend_opp_freq(dev);
atomic_set(&devfreq->suspend_count, 0); atomic_set(&devfreq->suspend_count, 0);
dev_set_name(&devfreq->dev, "devfreq%d", dev_set_name(&devfreq->dev, "%s", dev_name(dev));
atomic_inc_return(&devfreq_no));
err = device_register(&devfreq->dev); err = device_register(&devfreq->dev);
if (err) { if (err) {
mutex_unlock(&devfreq->lock); mutex_unlock(&devfreq->lock);

View File

@ -552,7 +552,7 @@ int __init efi_config_parse_tables(void *config_tables, int count, int sz,
seed = early_memremap(efi.rng_seed, sizeof(*seed)); seed = early_memremap(efi.rng_seed, sizeof(*seed));
if (seed != NULL) { if (seed != NULL) {
size = seed->size; size = READ_ONCE(seed->size);
early_memunmap(seed, sizeof(*seed)); early_memunmap(seed, sizeof(*seed));
} else { } else {
pr_err("Could not map UEFI random seed!\n"); pr_err("Could not map UEFI random seed!\n");
@ -562,7 +562,7 @@ int __init efi_config_parse_tables(void *config_tables, int count, int sz,
sizeof(*seed) + size); sizeof(*seed) + size);
if (seed != NULL) { if (seed != NULL) {
pr_notice("seeding entropy pool\n"); pr_notice("seeding entropy pool\n");
add_bootloader_randomness(seed->bits, seed->size); add_bootloader_randomness(seed->bits, size);
early_memunmap(seed, sizeof(*seed) + size); early_memunmap(seed, sizeof(*seed) + size);
} else { } else {
pr_err("Could not map UEFI random seed!\n"); pr_err("Could not map UEFI random seed!\n");

View File

@ -1389,7 +1389,7 @@ amdgpu_get_crtc_scanout_position(struct drm_device *dev, unsigned int pipe,
static struct drm_driver kms_driver = { static struct drm_driver kms_driver = {
.driver_features = .driver_features =
DRIVER_USE_AGP | DRIVER_ATOMIC | DRIVER_ATOMIC |
DRIVER_GEM | DRIVER_GEM |
DRIVER_RENDER | DRIVER_MODESET | DRIVER_SYNCOBJ | DRIVER_RENDER | DRIVER_MODESET | DRIVER_SYNCOBJ |
DRIVER_SYNCOBJ_TIMELINE, DRIVER_SYNCOBJ_TIMELINE,

View File

@ -195,6 +195,7 @@ struct amdgpu_gmc {
uint32_t srbm_soft_reset; uint32_t srbm_soft_reset;
bool prt_warning; bool prt_warning;
uint64_t stolen_size; uint64_t stolen_size;
uint32_t sdpif_register;
/* apertures */ /* apertures */
u64 shared_aperture_start; u64 shared_aperture_start;
u64 shared_aperture_end; u64 shared_aperture_end;

View File

@ -1271,6 +1271,19 @@ static void gmc_v9_0_init_golden_registers(struct amdgpu_device *adev)
} }
} }
/**
* gmc_v9_0_restore_registers - restores regs
*
* @adev: amdgpu_device pointer
*
* This restores register values, saved at suspend.
*/
static void gmc_v9_0_restore_registers(struct amdgpu_device *adev)
{
if (adev->asic_type == CHIP_RAVEN)
WREG32(mmDCHUBBUB_SDPIF_MMIO_CNTRL_0, adev->gmc.sdpif_register);
}
/** /**
* gmc_v9_0_gart_enable - gart enable * gmc_v9_0_gart_enable - gart enable
* *
@ -1376,6 +1389,20 @@ static int gmc_v9_0_hw_init(void *handle)
return r; return r;
} }
/**
* gmc_v9_0_save_registers - saves regs
*
* @adev: amdgpu_device pointer
*
* This saves potential register values that should be
* restored upon resume
*/
static void gmc_v9_0_save_registers(struct amdgpu_device *adev)
{
if (adev->asic_type == CHIP_RAVEN)
adev->gmc.sdpif_register = RREG32(mmDCHUBBUB_SDPIF_MMIO_CNTRL_0);
}
/** /**
* gmc_v9_0_gart_disable - gart disable * gmc_v9_0_gart_disable - gart disable
* *
@ -1412,9 +1439,16 @@ static int gmc_v9_0_hw_fini(void *handle)
static int gmc_v9_0_suspend(void *handle) static int gmc_v9_0_suspend(void *handle)
{ {
int r;
struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct amdgpu_device *adev = (struct amdgpu_device *)handle;
return gmc_v9_0_hw_fini(adev); r = gmc_v9_0_hw_fini(adev);
if (r)
return r;
gmc_v9_0_save_registers(adev);
return 0;
} }
static int gmc_v9_0_resume(void *handle) static int gmc_v9_0_resume(void *handle)
@ -1422,6 +1456,7 @@ static int gmc_v9_0_resume(void *handle)
int r; int r;
struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct amdgpu_device *adev = (struct amdgpu_device *)handle;
gmc_v9_0_restore_registers(adev);
r = gmc_v9_0_hw_init(adev); r = gmc_v9_0_hw_init(adev);
if (r) if (r)
return r; return r;

View File

@ -7376,6 +7376,8 @@
#define mmCRTC4_CRTC_DRR_CONTROL 0x0f3e #define mmCRTC4_CRTC_DRR_CONTROL 0x0f3e
#define mmCRTC4_CRTC_DRR_CONTROL_BASE_IDX 2 #define mmCRTC4_CRTC_DRR_CONTROL_BASE_IDX 2
#define mmDCHUBBUB_SDPIF_MMIO_CNTRL_0 0x395d
#define mmDCHUBBUB_SDPIF_MMIO_CNTRL_0_BASE_IDX 2
// addressBlock: dce_dc_fmt4_dispdec // addressBlock: dce_dc_fmt4_dispdec
// base address: 0x2000 // base address: 0x2000

View File

@ -978,8 +978,12 @@ int smu_v11_0_init_max_sustainable_clocks(struct smu_context *smu)
struct smu_11_0_max_sustainable_clocks *max_sustainable_clocks; struct smu_11_0_max_sustainable_clocks *max_sustainable_clocks;
int ret = 0; int ret = 0;
max_sustainable_clocks = kzalloc(sizeof(struct smu_11_0_max_sustainable_clocks), if (!smu->smu_table.max_sustainable_clocks)
max_sustainable_clocks = kzalloc(sizeof(struct smu_11_0_max_sustainable_clocks),
GFP_KERNEL); GFP_KERNEL);
else
max_sustainable_clocks = smu->smu_table.max_sustainable_clocks;
smu->smu_table.max_sustainable_clocks = (void *)max_sustainable_clocks; smu->smu_table.max_sustainable_clocks = (void *)max_sustainable_clocks;
max_sustainable_clocks->uclock = smu->smu_table.boot_values.uclk / 100; max_sustainable_clocks->uclock = smu->smu_table.boot_values.uclk / 100;

View File

@ -294,7 +294,7 @@ extra-$(CONFIG_DRM_I915_WERROR) += \
$(shell cd $(srctree)/$(src) && find * -name '*.h'))) $(shell cd $(srctree)/$(src) && find * -name '*.h')))
quiet_cmd_hdrtest = HDRTEST $(patsubst %.hdrtest,%.h,$@) quiet_cmd_hdrtest = HDRTEST $(patsubst %.hdrtest,%.h,$@)
cmd_hdrtest = $(CC) $(c_flags) -S -o /dev/null -x c /dev/null -include $<; touch $@ cmd_hdrtest = $(CC) $(filter-out $(CFLAGS_GCOV), $(c_flags)) -S -o /dev/null -x c /dev/null -include $<; touch $@
$(obj)/%.hdrtest: $(src)/%.h FORCE $(obj)/%.hdrtest: $(src)/%.h FORCE
$(call if_changed_dep,hdrtest) $(call if_changed_dep,hdrtest)

View File

@ -256,8 +256,7 @@ unsigned long i915_gem_shrink_all(struct drm_i915_private *i915)
with_intel_runtime_pm(&i915->runtime_pm, wakeref) { with_intel_runtime_pm(&i915->runtime_pm, wakeref) {
freed = i915_gem_shrink(i915, -1UL, NULL, freed = i915_gem_shrink(i915, -1UL, NULL,
I915_SHRINK_BOUND | I915_SHRINK_BOUND |
I915_SHRINK_UNBOUND | I915_SHRINK_UNBOUND);
I915_SHRINK_ACTIVE);
} }
return freed; return freed;
@ -336,7 +335,6 @@ i915_gem_shrinker_oom(struct notifier_block *nb, unsigned long event, void *ptr)
freed_pages = 0; freed_pages = 0;
with_intel_runtime_pm(&i915->runtime_pm, wakeref) with_intel_runtime_pm(&i915->runtime_pm, wakeref)
freed_pages += i915_gem_shrink(i915, -1UL, NULL, freed_pages += i915_gem_shrink(i915, -1UL, NULL,
I915_SHRINK_ACTIVE |
I915_SHRINK_BOUND | I915_SHRINK_BOUND |
I915_SHRINK_UNBOUND | I915_SHRINK_UNBOUND |
I915_SHRINK_WRITEBACK); I915_SHRINK_WRITEBACK);

View File

@ -151,12 +151,12 @@ static void dmabuf_gem_object_free(struct kref *kref)
dmabuf_obj = container_of(pos, dmabuf_obj = container_of(pos,
struct intel_vgpu_dmabuf_obj, list); struct intel_vgpu_dmabuf_obj, list);
if (dmabuf_obj == obj) { if (dmabuf_obj == obj) {
list_del(pos);
intel_gvt_hypervisor_put_vfio_device(vgpu); intel_gvt_hypervisor_put_vfio_device(vgpu);
idr_remove(&vgpu->object_idr, idr_remove(&vgpu->object_idr,
dmabuf_obj->dmabuf_id); dmabuf_obj->dmabuf_id);
kfree(dmabuf_obj->info); kfree(dmabuf_obj->info);
kfree(dmabuf_obj); kfree(dmabuf_obj);
list_del(pos);
break; break;
} }
} }

View File

@ -560,9 +560,9 @@ void intel_gvt_reset_vgpu_locked(struct intel_vgpu *vgpu, bool dmlr,
intel_vgpu_reset_mmio(vgpu, dmlr); intel_vgpu_reset_mmio(vgpu, dmlr);
populate_pvinfo_page(vgpu); populate_pvinfo_page(vgpu);
intel_vgpu_reset_display(vgpu);
if (dmlr) { if (dmlr) {
intel_vgpu_reset_display(vgpu);
intel_vgpu_reset_cfg_space(vgpu); intel_vgpu_reset_cfg_space(vgpu);
/* only reset the failsafe mode when dmlr reset */ /* only reset the failsafe mode when dmlr reset */
vgpu->failsafe = false; vgpu->failsafe = false;

View File

@ -437,7 +437,7 @@ static const struct intel_device_info snb_m_gt2_info = {
.has_rc6 = 1, \ .has_rc6 = 1, \
.has_rc6p = 1, \ .has_rc6p = 1, \
.has_rps = true, \ .has_rps = true, \
.ppgtt_type = INTEL_PPGTT_FULL, \ .ppgtt_type = INTEL_PPGTT_ALIASING, \
.ppgtt_size = 31, \ .ppgtt_size = 31, \
IVB_PIPE_OFFSETS, \ IVB_PIPE_OFFSETS, \
IVB_CURSOR_OFFSETS, \ IVB_CURSOR_OFFSETS, \
@ -494,7 +494,7 @@ static const struct intel_device_info vlv_info = {
.has_rps = true, .has_rps = true,
.display.has_gmch = 1, .display.has_gmch = 1,
.display.has_hotplug = 1, .display.has_hotplug = 1,
.ppgtt_type = INTEL_PPGTT_FULL, .ppgtt_type = INTEL_PPGTT_ALIASING,
.ppgtt_size = 31, .ppgtt_size = 31,
.has_snoop = true, .has_snoop = true,
.has_coherent_ggtt = false, .has_coherent_ggtt = false,

View File

@ -822,11 +822,6 @@ static ssize_t i915_pmu_event_show(struct device *dev,
return sprintf(buf, "config=0x%lx\n", eattr->val); return sprintf(buf, "config=0x%lx\n", eattr->val);
} }
static struct attribute_group i915_pmu_events_attr_group = {
.name = "events",
/* Patch in attrs at runtime. */
};
static ssize_t static ssize_t
i915_pmu_get_attr_cpumask(struct device *dev, i915_pmu_get_attr_cpumask(struct device *dev,
struct device_attribute *attr, struct device_attribute *attr,
@ -846,13 +841,6 @@ static const struct attribute_group i915_pmu_cpumask_attr_group = {
.attrs = i915_cpumask_attrs, .attrs = i915_cpumask_attrs,
}; };
static const struct attribute_group *i915_pmu_attr_groups[] = {
&i915_pmu_format_attr_group,
&i915_pmu_events_attr_group,
&i915_pmu_cpumask_attr_group,
NULL
};
#define __event(__config, __name, __unit) \ #define __event(__config, __name, __unit) \
{ \ { \
.config = (__config), \ .config = (__config), \
@ -1026,23 +1014,23 @@ err_alloc:
static void free_event_attributes(struct i915_pmu *pmu) static void free_event_attributes(struct i915_pmu *pmu)
{ {
struct attribute **attr_iter = i915_pmu_events_attr_group.attrs; struct attribute **attr_iter = pmu->events_attr_group.attrs;
for (; *attr_iter; attr_iter++) for (; *attr_iter; attr_iter++)
kfree((*attr_iter)->name); kfree((*attr_iter)->name);
kfree(i915_pmu_events_attr_group.attrs); kfree(pmu->events_attr_group.attrs);
kfree(pmu->i915_attr); kfree(pmu->i915_attr);
kfree(pmu->pmu_attr); kfree(pmu->pmu_attr);
i915_pmu_events_attr_group.attrs = NULL; pmu->events_attr_group.attrs = NULL;
pmu->i915_attr = NULL; pmu->i915_attr = NULL;
pmu->pmu_attr = NULL; pmu->pmu_attr = NULL;
} }
static int i915_pmu_cpu_online(unsigned int cpu, struct hlist_node *node) static int i915_pmu_cpu_online(unsigned int cpu, struct hlist_node *node)
{ {
struct i915_pmu *pmu = hlist_entry_safe(node, typeof(*pmu), node); struct i915_pmu *pmu = hlist_entry_safe(node, typeof(*pmu), cpuhp.node);
GEM_BUG_ON(!pmu->base.event_init); GEM_BUG_ON(!pmu->base.event_init);
@ -1055,7 +1043,7 @@ static int i915_pmu_cpu_online(unsigned int cpu, struct hlist_node *node)
static int i915_pmu_cpu_offline(unsigned int cpu, struct hlist_node *node) static int i915_pmu_cpu_offline(unsigned int cpu, struct hlist_node *node)
{ {
struct i915_pmu *pmu = hlist_entry_safe(node, typeof(*pmu), node); struct i915_pmu *pmu = hlist_entry_safe(node, typeof(*pmu), cpuhp.node);
unsigned int target; unsigned int target;
GEM_BUG_ON(!pmu->base.event_init); GEM_BUG_ON(!pmu->base.event_init);
@ -1072,8 +1060,6 @@ static int i915_pmu_cpu_offline(unsigned int cpu, struct hlist_node *node)
return 0; return 0;
} }
static enum cpuhp_state cpuhp_slot = CPUHP_INVALID;
static int i915_pmu_register_cpuhp_state(struct i915_pmu *pmu) static int i915_pmu_register_cpuhp_state(struct i915_pmu *pmu)
{ {
enum cpuhp_state slot; enum cpuhp_state slot;
@ -1087,21 +1073,22 @@ static int i915_pmu_register_cpuhp_state(struct i915_pmu *pmu)
return ret; return ret;
slot = ret; slot = ret;
ret = cpuhp_state_add_instance(slot, &pmu->node); ret = cpuhp_state_add_instance(slot, &pmu->cpuhp.node);
if (ret) { if (ret) {
cpuhp_remove_multi_state(slot); cpuhp_remove_multi_state(slot);
return ret; return ret;
} }
cpuhp_slot = slot; pmu->cpuhp.slot = slot;
return 0; return 0;
} }
static void i915_pmu_unregister_cpuhp_state(struct i915_pmu *pmu) static void i915_pmu_unregister_cpuhp_state(struct i915_pmu *pmu)
{ {
WARN_ON(cpuhp_slot == CPUHP_INVALID); WARN_ON(pmu->cpuhp.slot == CPUHP_INVALID);
WARN_ON(cpuhp_state_remove_instance(cpuhp_slot, &pmu->node)); WARN_ON(cpuhp_state_remove_instance(pmu->cpuhp.slot, &pmu->cpuhp.node));
cpuhp_remove_multi_state(cpuhp_slot); cpuhp_remove_multi_state(pmu->cpuhp.slot);
pmu->cpuhp.slot = CPUHP_INVALID;
} }
static bool is_igp(struct drm_i915_private *i915) static bool is_igp(struct drm_i915_private *i915)
@ -1118,6 +1105,13 @@ static bool is_igp(struct drm_i915_private *i915)
void i915_pmu_register(struct drm_i915_private *i915) void i915_pmu_register(struct drm_i915_private *i915)
{ {
struct i915_pmu *pmu = &i915->pmu; struct i915_pmu *pmu = &i915->pmu;
const struct attribute_group *attr_groups[] = {
&i915_pmu_format_attr_group,
&pmu->events_attr_group,
&i915_pmu_cpumask_attr_group,
NULL
};
int ret = -ENOMEM; int ret = -ENOMEM;
if (INTEL_GEN(i915) <= 2) { if (INTEL_GEN(i915) <= 2) {
@ -1128,6 +1122,7 @@ void i915_pmu_register(struct drm_i915_private *i915)
spin_lock_init(&pmu->lock); spin_lock_init(&pmu->lock);
hrtimer_init(&pmu->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); hrtimer_init(&pmu->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
pmu->timer.function = i915_sample; pmu->timer.function = i915_sample;
pmu->cpuhp.slot = CPUHP_INVALID;
if (!is_igp(i915)) { if (!is_igp(i915)) {
pmu->name = kasprintf(GFP_KERNEL, pmu->name = kasprintf(GFP_KERNEL,
@ -1143,11 +1138,16 @@ void i915_pmu_register(struct drm_i915_private *i915)
if (!pmu->name) if (!pmu->name)
goto err; goto err;
i915_pmu_events_attr_group.attrs = create_event_attributes(pmu); pmu->events_attr_group.name = "events";
if (!i915_pmu_events_attr_group.attrs) pmu->events_attr_group.attrs = create_event_attributes(pmu);
if (!pmu->events_attr_group.attrs)
goto err_name; goto err_name;
pmu->base.attr_groups = i915_pmu_attr_groups; pmu->base.attr_groups = kmemdup(attr_groups, sizeof(attr_groups),
GFP_KERNEL);
if (!pmu->base.attr_groups)
goto err_attr;
pmu->base.task_ctx_nr = perf_invalid_context; pmu->base.task_ctx_nr = perf_invalid_context;
pmu->base.event_init = i915_pmu_event_init; pmu->base.event_init = i915_pmu_event_init;
pmu->base.add = i915_pmu_event_add; pmu->base.add = i915_pmu_event_add;
@ -1159,7 +1159,7 @@ void i915_pmu_register(struct drm_i915_private *i915)
ret = perf_pmu_register(&pmu->base, pmu->name, -1); ret = perf_pmu_register(&pmu->base, pmu->name, -1);
if (ret) if (ret)
goto err_attr; goto err_groups;
ret = i915_pmu_register_cpuhp_state(pmu); ret = i915_pmu_register_cpuhp_state(pmu);
if (ret) if (ret)
@ -1169,6 +1169,8 @@ void i915_pmu_register(struct drm_i915_private *i915)
err_unreg: err_unreg:
perf_pmu_unregister(&pmu->base); perf_pmu_unregister(&pmu->base);
err_groups:
kfree(pmu->base.attr_groups);
err_attr: err_attr:
pmu->base.event_init = NULL; pmu->base.event_init = NULL;
free_event_attributes(pmu); free_event_attributes(pmu);
@ -1194,6 +1196,7 @@ void i915_pmu_unregister(struct drm_i915_private *i915)
perf_pmu_unregister(&pmu->base); perf_pmu_unregister(&pmu->base);
pmu->base.event_init = NULL; pmu->base.event_init = NULL;
kfree(pmu->base.attr_groups);
if (!is_igp(i915)) if (!is_igp(i915))
kfree(pmu->name); kfree(pmu->name);
free_event_attributes(pmu); free_event_attributes(pmu);

View File

@ -39,9 +39,12 @@ struct i915_pmu_sample {
struct i915_pmu { struct i915_pmu {
/** /**
* @node: List node for CPU hotplug handling. * @cpuhp: Struct used for CPU hotplug handling.
*/ */
struct hlist_node node; struct {
struct hlist_node node;
enum cpuhp_state slot;
} cpuhp;
/** /**
* @base: PMU base. * @base: PMU base.
*/ */
@ -104,6 +107,10 @@ struct i915_pmu {
* @sleep_last: Last time GT parked for RC6 estimation. * @sleep_last: Last time GT parked for RC6 estimation.
*/ */
ktime_t sleep_last; ktime_t sleep_last;
/**
* @events_attr_group: Device events attribute group.
*/
struct attribute_group events_attr_group;
/** /**
* @i915_attr: Memory block holding device attributes. * @i915_attr: Memory block holding device attributes.
*/ */

View File

@ -37,6 +37,7 @@
#include <linux/vga_switcheroo.h> #include <linux/vga_switcheroo.h>
#include <linux/mmu_notifier.h> #include <linux/mmu_notifier.h>
#include <drm/drm_agpsupport.h>
#include <drm/drm_crtc_helper.h> #include <drm/drm_crtc_helper.h>
#include <drm/drm_drv.h> #include <drm/drm_drv.h>
#include <drm/drm_fb_helper.h> #include <drm/drm_fb_helper.h>
@ -325,6 +326,7 @@ static int radeon_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *ent) const struct pci_device_id *ent)
{ {
unsigned long flags = 0; unsigned long flags = 0;
struct drm_device *dev;
int ret; int ret;
if (!ent) if (!ent)
@ -365,7 +367,44 @@ static int radeon_pci_probe(struct pci_dev *pdev,
if (ret) if (ret)
return ret; return ret;
return drm_get_pci_dev(pdev, ent, &kms_driver); dev = drm_dev_alloc(&kms_driver, &pdev->dev);
if (IS_ERR(dev))
return PTR_ERR(dev);
ret = pci_enable_device(pdev);
if (ret)
goto err_free;
dev->pdev = pdev;
#ifdef __alpha__
dev->hose = pdev->sysdata;
#endif
pci_set_drvdata(pdev, dev);
if (pci_find_capability(dev->pdev, PCI_CAP_ID_AGP))
dev->agp = drm_agp_init(dev);
if (dev->agp) {
dev->agp->agp_mtrr = arch_phys_wc_add(
dev->agp->agp_info.aper_base,
dev->agp->agp_info.aper_size *
1024 * 1024);
}
ret = drm_dev_register(dev, ent->driver_data);
if (ret)
goto err_agp;
return 0;
err_agp:
if (dev->agp)
arch_phys_wc_del(dev->agp->agp_mtrr);
kfree(dev->agp);
pci_disable_device(pdev);
err_free:
drm_dev_put(dev);
return ret;
} }
static void static void
@ -575,7 +614,7 @@ radeon_get_crtc_scanout_position(struct drm_device *dev, unsigned int pipe,
static struct drm_driver kms_driver = { static struct drm_driver kms_driver = {
.driver_features = .driver_features =
DRIVER_USE_AGP | DRIVER_GEM | DRIVER_RENDER, DRIVER_GEM | DRIVER_RENDER,
.load = radeon_driver_load_kms, .load = radeon_driver_load_kms,
.open = radeon_driver_open_kms, .open = radeon_driver_open_kms,
.postclose = radeon_driver_postclose_kms, .postclose = radeon_driver_postclose_kms,

View File

@ -32,6 +32,7 @@
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <linux/vga_switcheroo.h> #include <linux/vga_switcheroo.h>
#include <drm/drm_agpsupport.h>
#include <drm/drm_fb_helper.h> #include <drm/drm_fb_helper.h>
#include <drm/drm_file.h> #include <drm/drm_file.h>
#include <drm/drm_ioctl.h> #include <drm/drm_ioctl.h>
@ -77,6 +78,11 @@ void radeon_driver_unload_kms(struct drm_device *dev)
radeon_modeset_fini(rdev); radeon_modeset_fini(rdev);
radeon_device_fini(rdev); radeon_device_fini(rdev);
if (dev->agp)
arch_phys_wc_del(dev->agp->agp_mtrr);
kfree(dev->agp);
dev->agp = NULL;
done_free: done_free:
kfree(rdev); kfree(rdev);
dev->dev_private = NULL; dev->dev_private = NULL;

View File

@ -730,7 +730,7 @@ static int alps_input_configured(struct hid_device *hdev, struct hid_input *hi)
if (data->has_sp) { if (data->has_sp) {
input2 = input_allocate_device(); input2 = input_allocate_device();
if (!input2) { if (!input2) {
input_free_device(input2); ret = -ENOMEM;
goto exit; goto exit;
} }

View File

@ -340,7 +340,8 @@ static int apple_input_mapping(struct hid_device *hdev, struct hid_input *hi,
unsigned long **bit, int *max) unsigned long **bit, int *max)
{ {
if (usage->hid == (HID_UP_CUSTOM | 0x0003) || if (usage->hid == (HID_UP_CUSTOM | 0x0003) ||
usage->hid == (HID_UP_MSVENDOR | 0x0003)) { usage->hid == (HID_UP_MSVENDOR | 0x0003) ||
usage->hid == (HID_UP_HPVENDOR2 | 0x0003)) {
/* The fn key on Apple USB keyboards */ /* The fn key on Apple USB keyboards */
set_bit(EV_REP, hi->input->evbit); set_bit(EV_REP, hi->input->evbit);
hid_map_usage_clear(hi, usage, bit, max, EV_KEY, KEY_FN); hid_map_usage_clear(hi, usage, bit, max, EV_KEY, KEY_FN);

View File

@ -174,6 +174,7 @@ static __u8 pid0902_rdesc_fixed[] = {
struct bigben_device { struct bigben_device {
struct hid_device *hid; struct hid_device *hid;
struct hid_report *report; struct hid_report *report;
bool removed;
u8 led_state; /* LED1 = 1 .. LED4 = 8 */ u8 led_state; /* LED1 = 1 .. LED4 = 8 */
u8 right_motor_on; /* right motor off/on 0/1 */ u8 right_motor_on; /* right motor off/on 0/1 */
u8 left_motor_force; /* left motor force 0-255 */ u8 left_motor_force; /* left motor force 0-255 */
@ -190,6 +191,9 @@ static void bigben_worker(struct work_struct *work)
struct bigben_device, worker); struct bigben_device, worker);
struct hid_field *report_field = bigben->report->field[0]; struct hid_field *report_field = bigben->report->field[0];
if (bigben->removed)
return;
if (bigben->work_led) { if (bigben->work_led) {
bigben->work_led = false; bigben->work_led = false;
report_field->value[0] = 0x01; /* 1 = led message */ report_field->value[0] = 0x01; /* 1 = led message */
@ -220,10 +224,16 @@ static void bigben_worker(struct work_struct *work)
static int hid_bigben_play_effect(struct input_dev *dev, void *data, static int hid_bigben_play_effect(struct input_dev *dev, void *data,
struct ff_effect *effect) struct ff_effect *effect)
{ {
struct bigben_device *bigben = data; struct hid_device *hid = input_get_drvdata(dev);
struct bigben_device *bigben = hid_get_drvdata(hid);
u8 right_motor_on; u8 right_motor_on;
u8 left_motor_force; u8 left_motor_force;
if (!bigben) {
hid_err(hid, "no device data\n");
return 0;
}
if (effect->type != FF_RUMBLE) if (effect->type != FF_RUMBLE)
return 0; return 0;
@ -298,8 +308,8 @@ static void bigben_remove(struct hid_device *hid)
{ {
struct bigben_device *bigben = hid_get_drvdata(hid); struct bigben_device *bigben = hid_get_drvdata(hid);
bigben->removed = true;
cancel_work_sync(&bigben->worker); cancel_work_sync(&bigben->worker);
hid_hw_close(hid);
hid_hw_stop(hid); hid_hw_stop(hid);
} }
@ -319,6 +329,7 @@ static int bigben_probe(struct hid_device *hid,
return -ENOMEM; return -ENOMEM;
hid_set_drvdata(hid, bigben); hid_set_drvdata(hid, bigben);
bigben->hid = hid; bigben->hid = hid;
bigben->removed = false;
error = hid_parse(hid); error = hid_parse(hid);
if (error) { if (error) {
@ -341,10 +352,10 @@ static int bigben_probe(struct hid_device *hid,
INIT_WORK(&bigben->worker, bigben_worker); INIT_WORK(&bigben->worker, bigben_worker);
error = input_ff_create_memless(hidinput->input, bigben, error = input_ff_create_memless(hidinput->input, NULL,
hid_bigben_play_effect); hid_bigben_play_effect);
if (error) if (error)
return error; goto error_hw_stop;
name_sz = strlen(dev_name(&hid->dev)) + strlen(":red:bigben#") + 1; name_sz = strlen(dev_name(&hid->dev)) + strlen(":red:bigben#") + 1;
@ -354,8 +365,10 @@ static int bigben_probe(struct hid_device *hid,
sizeof(struct led_classdev) + name_sz, sizeof(struct led_classdev) + name_sz,
GFP_KERNEL GFP_KERNEL
); );
if (!led) if (!led) {
return -ENOMEM; error = -ENOMEM;
goto error_hw_stop;
}
name = (void *)(&led[1]); name = (void *)(&led[1]);
snprintf(name, name_sz, snprintf(name, name_sz,
"%s:red:bigben%d", "%s:red:bigben%d",
@ -369,7 +382,7 @@ static int bigben_probe(struct hid_device *hid,
bigben->leds[n] = led; bigben->leds[n] = led;
error = devm_led_classdev_register(&hid->dev, led); error = devm_led_classdev_register(&hid->dev, led);
if (error) if (error)
return error; goto error_hw_stop;
} }
/* initial state: LED1 is on, no rumble effect */ /* initial state: LED1 is on, no rumble effect */
@ -383,6 +396,10 @@ static int bigben_probe(struct hid_device *hid,
hid_info(hid, "LED and force feedback support for BigBen gamepad\n"); hid_info(hid, "LED and force feedback support for BigBen gamepad\n");
return 0; return 0;
error_hw_stop:
hid_hw_stop(hid);
return error;
} }
static __u8 *bigben_report_fixup(struct hid_device *hid, __u8 *rdesc, static __u8 *bigben_report_fixup(struct hid_device *hid, __u8 *rdesc,

View File

@ -1741,7 +1741,9 @@ int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, u32 size,
rsize = ((report->size - 1) >> 3) + 1; rsize = ((report->size - 1) >> 3) + 1;
if (rsize > HID_MAX_BUFFER_SIZE) if (report_enum->numbered && rsize >= HID_MAX_BUFFER_SIZE)
rsize = HID_MAX_BUFFER_SIZE - 1;
else if (rsize > HID_MAX_BUFFER_SIZE)
rsize = HID_MAX_BUFFER_SIZE; rsize = HID_MAX_BUFFER_SIZE;
if (csize < rsize) { if (csize < rsize) {

View File

@ -41,8 +41,9 @@ static const struct hid_device_id ite_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_ITE, USB_DEVICE_ID_ITE8595) }, { HID_USB_DEVICE(USB_VENDOR_ID_ITE, USB_DEVICE_ID_ITE8595) },
{ HID_USB_DEVICE(USB_VENDOR_ID_258A, USB_DEVICE_ID_258A_6A88) }, { HID_USB_DEVICE(USB_VENDOR_ID_258A, USB_DEVICE_ID_258A_6A88) },
/* ITE8595 USB kbd ctlr, with Synaptics touchpad connected to it. */ /* ITE8595 USB kbd ctlr, with Synaptics touchpad connected to it. */
{ HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
USB_DEVICE_ID_SYNAPTICS_ACER_SWITCH5_012) }, USB_VENDOR_ID_SYNAPTICS,
USB_DEVICE_ID_SYNAPTICS_ACER_SWITCH5_012) },
{ } { }
}; };
MODULE_DEVICE_TABLE(hid, ite_devices); MODULE_DEVICE_TABLE(hid, ite_devices);

View File

@ -1256,36 +1256,35 @@ static int hidpp20_battery_map_status_voltage(u8 data[3], int *voltage,
{ {
int status; int status;
long charge_sts = (long)data[2]; long flags = (long) data[2];
*level = POWER_SUPPLY_CAPACITY_LEVEL_UNKNOWN; if (flags & 0x80)
switch (data[2] & 0xe0) { switch (flags & 0x07) {
case 0x00: case 0:
status = POWER_SUPPLY_STATUS_CHARGING; status = POWER_SUPPLY_STATUS_CHARGING;
break; break;
case 0x20: case 1:
status = POWER_SUPPLY_STATUS_FULL; status = POWER_SUPPLY_STATUS_FULL;
*level = POWER_SUPPLY_CAPACITY_LEVEL_FULL; *level = POWER_SUPPLY_CAPACITY_LEVEL_FULL;
break; break;
case 0x40: case 2:
status = POWER_SUPPLY_STATUS_NOT_CHARGING;
break;
default:
status = POWER_SUPPLY_STATUS_UNKNOWN;
break;
}
else
status = POWER_SUPPLY_STATUS_DISCHARGING; status = POWER_SUPPLY_STATUS_DISCHARGING;
break;
case 0xe0:
status = POWER_SUPPLY_STATUS_NOT_CHARGING;
break;
default:
status = POWER_SUPPLY_STATUS_UNKNOWN;
}
*charge_type = POWER_SUPPLY_CHARGE_TYPE_STANDARD; *charge_type = POWER_SUPPLY_CHARGE_TYPE_STANDARD;
if (test_bit(3, &charge_sts)) { if (test_bit(3, &flags)) {
*charge_type = POWER_SUPPLY_CHARGE_TYPE_FAST; *charge_type = POWER_SUPPLY_CHARGE_TYPE_FAST;
} }
if (test_bit(4, &charge_sts)) { if (test_bit(4, &flags)) {
*charge_type = POWER_SUPPLY_CHARGE_TYPE_TRICKLE; *charge_type = POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
} }
if (test_bit(5, &flags)) {
if (test_bit(5, &charge_sts)) {
*level = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL; *level = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL;
} }

Some files were not shown because too many files have changed in this diff Show More