mirror of
https://github.com/hardkernel/linux.git
synced 2026-03-24 19:40:21 +09:00
Merge tag 'v6.6.103' of git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable into odroid-6.6.y
This is the 6.6.103 stable release Change-Id: I000cae00b799a6a3af191deb10b9c79c334035cd
This commit is contained in:
@@ -25,7 +25,7 @@ properties:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
minItems: 2
|
||||
maxItems: 2
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
|
||||
@@ -20,7 +20,7 @@ properties:
|
||||
maxItems: 2
|
||||
|
||||
clocks:
|
||||
minItems: 1
|
||||
maxItems: 1
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
|
||||
@@ -141,9 +141,8 @@ However, these ioctls have some limitations:
|
||||
CONFIG_PAGE_POISONING=y in your kernel config and add page_poison=1
|
||||
to your kernel command line. However, this has a performance cost.
|
||||
|
||||
- Secret keys might still exist in CPU registers, in crypto
|
||||
accelerator hardware (if used by the crypto API to implement any of
|
||||
the algorithms), or in other places not explicitly considered here.
|
||||
- Secret keys might still exist in CPU registers or in other places
|
||||
not explicitly considered here.
|
||||
|
||||
Limitations of v1 policies
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
@@ -375,9 +374,12 @@ the work is done by XChaCha12, which is much faster than AES when AES
|
||||
acceleration is unavailable. For more information about Adiantum, see
|
||||
`the Adiantum paper <https://eprint.iacr.org/2018/720.pdf>`_.
|
||||
|
||||
The (AES-128-CBC-ESSIV, AES-128-CTS-CBC) pair exists only to support
|
||||
systems whose only form of AES acceleration is an off-CPU crypto
|
||||
accelerator such as CAAM or CESA that does not support XTS.
|
||||
The (AES-128-CBC-ESSIV, AES-128-CTS-CBC) pair was added to try to
|
||||
provide a more efficient option for systems that lack AES instructions
|
||||
in the CPU but do have a non-inline crypto engine such as CAAM or CESA
|
||||
that supports AES-CBC (and not AES-XTS). This is deprecated. It has
|
||||
been shown that just doing AES on the CPU is actually faster.
|
||||
Moreover, Adiantum is faster still and is recommended on such systems.
|
||||
|
||||
The remaining mode pairs are the "national pride ciphers":
|
||||
|
||||
@@ -1231,22 +1233,13 @@ this by validating all top-level encryption policies prior to access.
|
||||
Inline encryption support
|
||||
=========================
|
||||
|
||||
By default, fscrypt uses the kernel crypto API for all cryptographic
|
||||
operations (other than HKDF, which fscrypt partially implements
|
||||
itself). The kernel crypto API supports hardware crypto accelerators,
|
||||
but only ones that work in the traditional way where all inputs and
|
||||
outputs (e.g. plaintexts and ciphertexts) are in memory. fscrypt can
|
||||
take advantage of such hardware, but the traditional acceleration
|
||||
model isn't particularly efficient and fscrypt hasn't been optimized
|
||||
for it.
|
||||
|
||||
Instead, many newer systems (especially mobile SoCs) have *inline
|
||||
encryption hardware* that can encrypt/decrypt data while it is on its
|
||||
way to/from the storage device. Linux supports inline encryption
|
||||
through a set of extensions to the block layer called *blk-crypto*.
|
||||
blk-crypto allows filesystems to attach encryption contexts to bios
|
||||
(I/O requests) to specify how the data will be encrypted or decrypted
|
||||
in-line. For more information about blk-crypto, see
|
||||
Many newer systems (especially mobile SoCs) have *inline encryption
|
||||
hardware* that can encrypt/decrypt data while it is on its way to/from
|
||||
the storage device. Linux supports inline encryption through a set of
|
||||
extensions to the block layer called *blk-crypto*. blk-crypto allows
|
||||
filesystems to attach encryption contexts to bios (I/O requests) to
|
||||
specify how the data will be encrypted or decrypted in-line. For more
|
||||
information about blk-crypto, see
|
||||
:ref:`Documentation/block/inline-encryption.rst <inline_encryption>`.
|
||||
|
||||
On supported filesystems (currently ext4 and f2fs), fscrypt can use
|
||||
|
||||
@@ -14,7 +14,7 @@ Consider this topology::
|
||||
| | | 0x70 |--CH01--> i2c client B (0x50)
|
||||
+------+ +------+
|
||||
|
||||
which corresponds to the following ASL::
|
||||
which corresponds to the following ASL (in the scope of \_SB)::
|
||||
|
||||
Device (SMB1)
|
||||
{
|
||||
@@ -24,7 +24,7 @@ which corresponds to the following ASL::
|
||||
Name (_HID, ...)
|
||||
Name (_CRS, ResourceTemplate () {
|
||||
I2cSerialBus (0x70, ControllerInitiated, I2C_SPEED,
|
||||
AddressingMode7Bit, "^SMB1", 0x00,
|
||||
AddressingMode7Bit, "\\_SB.SMB1", 0x00,
|
||||
ResourceConsumer,,)
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ which corresponds to the following ASL::
|
||||
Name (_HID, ...)
|
||||
Name (_CRS, ResourceTemplate () {
|
||||
I2cSerialBus (0x50, ControllerInitiated, I2C_SPEED,
|
||||
AddressingMode7Bit, "^CH00", 0x00,
|
||||
AddressingMode7Bit, "\\_SB.SMB1.CH00", 0x00,
|
||||
ResourceConsumer,,)
|
||||
}
|
||||
}
|
||||
@@ -52,7 +52,7 @@ which corresponds to the following ASL::
|
||||
Name (_HID, ...)
|
||||
Name (_CRS, ResourceTemplate () {
|
||||
I2cSerialBus (0x50, ControllerInitiated, I2C_SPEED,
|
||||
AddressingMode7Bit, "^CH01", 0x00,
|
||||
AddressingMode7Bit, "\\_SB.SMB1.CH01", 0x00,
|
||||
ResourceConsumer,,)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -444,6 +444,18 @@ arp_missed_max
|
||||
|
||||
The default value is 2, and the allowable range is 1 - 255.
|
||||
|
||||
coupled_control
|
||||
|
||||
Specifies whether the LACP state machine's MUX in the 802.3ad mode
|
||||
should have separate Collecting and Distributing states.
|
||||
|
||||
This is by implementing the independent control state machine per
|
||||
IEEE 802.1AX-2008 5.4.15 in addition to the existing coupled control
|
||||
state machine.
|
||||
|
||||
The default value is 1. This setting does not separate the Collecting
|
||||
and Distributing states, maintaining the bond in coupled control.
|
||||
|
||||
downdelay
|
||||
|
||||
Specifies the time, in milliseconds, to wait before disabling
|
||||
|
||||
@@ -20,6 +20,8 @@ add_addr_timeout - INTEGER (seconds)
|
||||
resent to an MPTCP peer that has not acknowledged a previous
|
||||
ADD_ADDR message.
|
||||
|
||||
Do not retransmit if set to 0.
|
||||
|
||||
The default value matches TCP_RTO_MAX. This is a per-namespace
|
||||
sysctl.
|
||||
|
||||
|
||||
@@ -398,10 +398,9 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h:
|
||||
nonzero, increment the counter and return 1; otherwise return 0 without
|
||||
changing the counter
|
||||
|
||||
`int pm_runtime_get_if_active(struct device *dev, bool ign_usage_count);`
|
||||
`int pm_runtime_get_if_active(struct device *dev);`
|
||||
- return -EINVAL if 'power.disable_depth' is nonzero; otherwise, if the
|
||||
runtime PM status is RPM_ACTIVE, and either ign_usage_count is true
|
||||
or the device's usage_count is non-zero, increment the counter and
|
||||
runtime PM status is RPM_ACTIVE, increment the counter and
|
||||
return 1; otherwise return 0 without changing the counter
|
||||
|
||||
`void pm_runtime_put_noidle(struct device *dev);`
|
||||
|
||||
4
Makefile
4
Makefile
@@ -1,7 +1,7 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
VERSION = 6
|
||||
PATCHLEVEL = 6
|
||||
SUBLEVEL = 102
|
||||
SUBLEVEL = 103
|
||||
EXTRAVERSION =
|
||||
NAME = Pinguïn Aangedreven
|
||||
|
||||
@@ -1061,7 +1061,7 @@ KBUILD_USERCFLAGS += $(filter -m32 -m64 --target=%, $(KBUILD_CPPFLAGS) $(KBUILD
|
||||
KBUILD_USERLDFLAGS += $(filter -m32 -m64 --target=%, $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS))
|
||||
|
||||
# userspace programs are linked via the compiler, use the correct linker
|
||||
ifeq ($(CONFIG_CC_IS_CLANG)$(CONFIG_LD_IS_LLD),yy)
|
||||
ifdef CONFIG_CC_IS_CLANG
|
||||
KBUILD_USERLDFLAGS += $(call cc-option, --ld-path=$(LD))
|
||||
endif
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#define arch_set_freq_scale topology_set_freq_scale
|
||||
#define arch_scale_freq_capacity topology_get_freq_scale
|
||||
#define arch_scale_freq_invariant topology_scale_freq_invariant
|
||||
#define arch_scale_freq_ref topology_get_freq_ref
|
||||
#endif
|
||||
|
||||
/* Replace task scheduler's default cpu-invariant accounting */
|
||||
|
||||
@@ -279,11 +279,6 @@ static void __init rockchip_smp_prepare_cpus(unsigned int max_cpus)
|
||||
}
|
||||
|
||||
if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9) {
|
||||
if (rockchip_smp_prepare_sram(node)) {
|
||||
of_node_put(node);
|
||||
return;
|
||||
}
|
||||
|
||||
/* enable the SCU power domain */
|
||||
pmu_set_power_domain(PMU_PWRDN_SCU, true);
|
||||
|
||||
@@ -316,11 +311,19 @@ static void __init rockchip_smp_prepare_cpus(unsigned int max_cpus)
|
||||
asm ("mrc p15, 1, %0, c9, c0, 2\n" : "=r" (l2ctlr));
|
||||
ncores = ((l2ctlr >> 24) & 0x3) + 1;
|
||||
}
|
||||
of_node_put(node);
|
||||
|
||||
/* Make sure that all cores except the first are really off */
|
||||
for (i = 1; i < ncores; i++)
|
||||
pmu_set_power_domain(0 + i, false);
|
||||
|
||||
if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9) {
|
||||
if (rockchip_smp_prepare_sram(node)) {
|
||||
of_node_put(node);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
of_node_put(node);
|
||||
}
|
||||
|
||||
static void __init rk3036_smp_prepare_cpus(unsigned int max_cpus)
|
||||
|
||||
@@ -63,7 +63,7 @@ static void __init tegra_cpu_reset_handler_enable(void)
|
||||
BUG_ON(is_enabled);
|
||||
BUG_ON(tegra_cpu_reset_handler_size > TEGRA_IRAM_RESET_HANDLER_SIZE);
|
||||
|
||||
memcpy(iram_base, (void *)__tegra_cpu_reset_handler_start,
|
||||
memcpy_toio(iram_base, (void *)__tegra_cpu_reset_handler_start,
|
||||
tegra_cpu_reset_handler_size);
|
||||
|
||||
err = call_firmware_op(set_cpu_boot_addr, 0, reset_address);
|
||||
|
||||
@@ -531,7 +531,6 @@
|
||||
clock-names = "clk_ahb", "clk_xin";
|
||||
assigned-clocks = <&k3_clks 57 6>;
|
||||
assigned-clock-parents = <&k3_clks 57 8>;
|
||||
mmc-ddr-1_8v;
|
||||
mmc-hs200-1_8v;
|
||||
ti,trm-icp = <0x2>;
|
||||
bus-width = <8>;
|
||||
|
||||
@@ -448,16 +448,16 @@
|
||||
/* Verdin I2C_2_DSI */
|
||||
pinctrl_i2c2: main-i2c2-default-pins {
|
||||
pinctrl-single,pins = <
|
||||
AM62X_IOPAD(0x00b0, PIN_INPUT, 1) /* (K22) GPMC0_CSn2.I2C2_SCL */ /* SODIMM 55 */
|
||||
AM62X_IOPAD(0x00b4, PIN_INPUT, 1) /* (K24) GPMC0_CSn3.I2C2_SDA */ /* SODIMM 53 */
|
||||
AM62X_IOPAD(0x00b0, PIN_INPUT_PULLUP, 1) /* (K22) GPMC0_CSn2.I2C2_SCL */ /* SODIMM 55 */
|
||||
AM62X_IOPAD(0x00b4, PIN_INPUT_PULLUP, 1) /* (K24) GPMC0_CSn3.I2C2_SDA */ /* SODIMM 53 */
|
||||
>;
|
||||
};
|
||||
|
||||
/* Verdin I2C_4_CSI */
|
||||
pinctrl_i2c3: main-i2c3-default-pins {
|
||||
pinctrl-single,pins = <
|
||||
AM62X_IOPAD(0x01d0, PIN_INPUT, 2) /* (A15) UART0_CTSn.I2C3_SCL */ /* SODIMM 95 */
|
||||
AM62X_IOPAD(0x01d4, PIN_INPUT, 2) /* (B15) UART0_RTSn.I2C3_SDA */ /* SODIMM 93 */
|
||||
AM62X_IOPAD(0x01d0, PIN_INPUT_PULLUP, 2) /* (A15) UART0_CTSn.I2C3_SCL */ /* SODIMM 95 */
|
||||
AM62X_IOPAD(0x01d4, PIN_INPUT_PULLUP, 2) /* (B15) UART0_RTSn.I2C3_SDA */ /* SODIMM 93 */
|
||||
>;
|
||||
};
|
||||
|
||||
@@ -729,8 +729,8 @@
|
||||
/* Verdin I2C_3_HDMI */
|
||||
pinctrl_mcu_i2c0: mcu-i2c0-default-pins {
|
||||
pinctrl-single,pins = <
|
||||
AM62X_MCU_IOPAD(0x0044, PIN_INPUT, 0) /* (A8) MCU_I2C0_SCL */ /* SODIMM 59 */
|
||||
AM62X_MCU_IOPAD(0x0048, PIN_INPUT, 0) /* (D10) MCU_I2C0_SDA */ /* SODIMM 57 */
|
||||
AM62X_MCU_IOPAD(0x0044, PIN_INPUT_PULLUP, 0) /* (A8) MCU_I2C0_SCL */ /* SODIMM 59 */
|
||||
AM62X_MCU_IOPAD(0x0048, PIN_INPUT_PULLUP, 0) /* (D10) MCU_I2C0_SDA */ /* SODIMM 57 */
|
||||
>;
|
||||
};
|
||||
|
||||
|
||||
@@ -144,8 +144,8 @@
|
||||
|
||||
main_uart1_pins_default: main-uart1-default-pins {
|
||||
pinctrl-single,pins = <
|
||||
AM62AX_IOPAD(0x01e8, PIN_INPUT, 1) /* (C17) I2C1_SCL.UART1_RXD */
|
||||
AM62AX_IOPAD(0x01ec, PIN_OUTPUT, 1) /* (E17) I2C1_SDA.UART1_TXD */
|
||||
AM62AX_IOPAD(0x01ac, PIN_INPUT, 2) /* (B21) MCASP0_AFSR.UART1_RXD */
|
||||
AM62AX_IOPAD(0x01b0, PIN_OUTPUT, 2) /* (A21) MCASP0_ACLKR.UART1_TXD */
|
||||
AM62AX_IOPAD(0x0194, PIN_INPUT, 2) /* (C19) MCASP0_AXR3.UART1_CTSn */
|
||||
AM62AX_IOPAD(0x0198, PIN_OUTPUT, 2) /* (B19) MCASP0_AXR2.UART1_RTSn */
|
||||
>;
|
||||
|
||||
@@ -8,11 +8,16 @@
|
||||
#ifndef DTS_ARM64_TI_K3_PINCTRL_H
|
||||
#define DTS_ARM64_TI_K3_PINCTRL_H
|
||||
|
||||
#define ST_EN_SHIFT (14)
|
||||
#define PULLUDEN_SHIFT (16)
|
||||
#define PULLTYPESEL_SHIFT (17)
|
||||
#define RXACTIVE_SHIFT (18)
|
||||
#define DEBOUNCE_SHIFT (11)
|
||||
|
||||
/* Schmitt trigger configuration */
|
||||
#define ST_DISABLE (0 << ST_EN_SHIFT)
|
||||
#define ST_ENABLE (1 << ST_EN_SHIFT)
|
||||
|
||||
#define PULL_DISABLE (1 << PULLUDEN_SHIFT)
|
||||
#define PULL_ENABLE (0 << PULLUDEN_SHIFT)
|
||||
|
||||
@@ -26,9 +31,13 @@
|
||||
#define PIN_OUTPUT (INPUT_DISABLE | PULL_DISABLE)
|
||||
#define PIN_OUTPUT_PULLUP (INPUT_DISABLE | PULL_UP)
|
||||
#define PIN_OUTPUT_PULLDOWN (INPUT_DISABLE | PULL_DOWN)
|
||||
#define PIN_INPUT (INPUT_EN | PULL_DISABLE)
|
||||
#define PIN_INPUT_PULLUP (INPUT_EN | PULL_UP)
|
||||
#define PIN_INPUT_PULLDOWN (INPUT_EN | PULL_DOWN)
|
||||
#define PIN_INPUT (INPUT_EN | ST_ENABLE | PULL_DISABLE)
|
||||
#define PIN_INPUT_PULLUP (INPUT_EN | ST_ENABLE | PULL_UP)
|
||||
#define PIN_INPUT_PULLDOWN (INPUT_EN | ST_ENABLE | PULL_DOWN)
|
||||
/* Input configurations with Schmitt Trigger disabled */
|
||||
#define PIN_INPUT_NOST (INPUT_EN | PULL_DISABLE)
|
||||
#define PIN_INPUT_PULLUP_NOST (INPUT_EN | PULL_UP)
|
||||
#define PIN_INPUT_PULLDOWN_NOST (INPUT_EN | PULL_DOWN)
|
||||
|
||||
#define PIN_DEBOUNCE_DISABLE (0 << DEBOUNCE_SHIFT)
|
||||
#define PIN_DEBOUNCE_CONF1 (1 << DEBOUNCE_SHIFT)
|
||||
|
||||
@@ -150,7 +150,7 @@ acpi_set_mailbox_entry(int cpu, struct acpi_madt_generic_interrupt *processor)
|
||||
{}
|
||||
#endif
|
||||
|
||||
static inline const char *acpi_get_enable_method(int cpu)
|
||||
static __always_inline const char *acpi_get_enable_method(int cpu)
|
||||
{
|
||||
if (acpi_psci_present())
|
||||
return "psci";
|
||||
|
||||
@@ -23,6 +23,7 @@ void update_freq_counters_refs(void);
|
||||
#define arch_set_freq_scale topology_set_freq_scale
|
||||
#define arch_scale_freq_capacity topology_get_freq_scale
|
||||
#define arch_scale_freq_invariant topology_scale_freq_invariant
|
||||
#define arch_scale_freq_ref topology_get_freq_ref
|
||||
|
||||
#ifdef CONFIG_ACPI_CPPC_LIB
|
||||
#define arch_init_invariance_cppc topology_init_cpu_capacity_cppc
|
||||
|
||||
@@ -1876,10 +1876,10 @@ void fpsimd_save_and_flush_cpu_state(void)
|
||||
if (!system_supports_fpsimd())
|
||||
return;
|
||||
WARN_ON(preemptible());
|
||||
__get_cpu_fpsimd_context();
|
||||
get_cpu_fpsimd_context();
|
||||
fpsimd_save();
|
||||
fpsimd_flush_cpu_state();
|
||||
__put_cpu_fpsimd_context();
|
||||
put_cpu_fpsimd_context();
|
||||
}
|
||||
|
||||
#ifdef CONFIG_KERNEL_MODE_NEON
|
||||
|
||||
@@ -82,7 +82,12 @@ int __init parse_acpi_topology(void)
|
||||
#undef pr_fmt
|
||||
#define pr_fmt(fmt) "AMU: " fmt
|
||||
|
||||
static DEFINE_PER_CPU_READ_MOSTLY(unsigned long, arch_max_freq_scale);
|
||||
/*
|
||||
* Ensure that amu_scale_freq_tick() will return SCHED_CAPACITY_SCALE until
|
||||
* the CPU capacity and its associated frequency have been correctly
|
||||
* initialized.
|
||||
*/
|
||||
static DEFINE_PER_CPU_READ_MOSTLY(unsigned long, arch_max_freq_scale) = 1UL << (2 * SCHED_CAPACITY_SHIFT);
|
||||
static DEFINE_PER_CPU(u64, arch_const_cycles_prev);
|
||||
static DEFINE_PER_CPU(u64, arch_core_cycles_prev);
|
||||
static cpumask_var_t amu_fie_cpus;
|
||||
@@ -112,14 +117,14 @@ static inline bool freq_counters_valid(int cpu)
|
||||
return true;
|
||||
}
|
||||
|
||||
static int freq_inv_set_max_ratio(int cpu, u64 max_rate, u64 ref_rate)
|
||||
void freq_inv_set_max_ratio(int cpu, u64 max_rate)
|
||||
{
|
||||
u64 ratio;
|
||||
u64 ratio, ref_rate = arch_timer_get_rate();
|
||||
|
||||
if (unlikely(!max_rate || !ref_rate)) {
|
||||
pr_debug("CPU%d: invalid maximum or reference frequency.\n",
|
||||
WARN_ONCE(1, "CPU%d: invalid maximum or reference frequency.\n",
|
||||
cpu);
|
||||
return -EINVAL;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -139,12 +144,10 @@ static int freq_inv_set_max_ratio(int cpu, u64 max_rate, u64 ref_rate)
|
||||
ratio = div64_u64(ratio, max_rate);
|
||||
if (!ratio) {
|
||||
WARN_ONCE(1, "Reference frequency too low.\n");
|
||||
return -EINVAL;
|
||||
return;
|
||||
}
|
||||
|
||||
per_cpu(arch_max_freq_scale, cpu) = (unsigned long)ratio;
|
||||
|
||||
return 0;
|
||||
WRITE_ONCE(per_cpu(arch_max_freq_scale, cpu), (unsigned long)ratio);
|
||||
}
|
||||
|
||||
static void amu_scale_freq_tick(void)
|
||||
@@ -195,10 +198,7 @@ static void amu_fie_setup(const struct cpumask *cpus)
|
||||
return;
|
||||
|
||||
for_each_cpu(cpu, cpus) {
|
||||
if (!freq_counters_valid(cpu) ||
|
||||
freq_inv_set_max_ratio(cpu,
|
||||
cpufreq_get_hw_max_freq(cpu) * 1000ULL,
|
||||
arch_timer_get_rate()))
|
||||
if (!freq_counters_valid(cpu))
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -953,6 +953,7 @@ void __noreturn panic_bad_stack(struct pt_regs *regs, unsigned long esr, unsigne
|
||||
|
||||
void __noreturn arm64_serror_panic(struct pt_regs *regs, unsigned long esr)
|
||||
{
|
||||
add_taint(TAINT_MACHINE_CHECK, LOCKDEP_STILL_OK);
|
||||
console_verbose();
|
||||
|
||||
pr_crit("SError Interrupt on CPU%d, code 0x%016lx -- %s\n",
|
||||
|
||||
@@ -753,6 +753,7 @@ static int do_sea(unsigned long far, unsigned long esr, struct pt_regs *regs)
|
||||
*/
|
||||
siaddr = untagged_addr(far);
|
||||
}
|
||||
add_taint(TAINT_MACHINE_CHECK, LOCKDEP_STILL_OK);
|
||||
arm64_notify_die(inf->name, regs, inf->sig, inf->code, siaddr, esr);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/memory_hotplug.h>
|
||||
#include <linux/seq_file.h>
|
||||
|
||||
#include <asm/ptdump.h>
|
||||
@@ -9,9 +8,7 @@ static int ptdump_show(struct seq_file *m, void *v)
|
||||
{
|
||||
struct ptdump_info *info = m->private;
|
||||
|
||||
get_online_mems();
|
||||
ptdump_walk(m, info);
|
||||
put_online_mems();
|
||||
return 0;
|
||||
}
|
||||
DEFINE_SHOW_ATTRIBUTE(ptdump);
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleloader.h>
|
||||
#include <linux/ftrace.h>
|
||||
#include <linux/sort.h>
|
||||
|
||||
Elf_Addr module_emit_got_entry(struct module *mod, Elf_Shdr *sechdrs, Elf_Addr val)
|
||||
{
|
||||
@@ -61,39 +62,38 @@ Elf_Addr module_emit_plt_entry(struct module *mod, Elf_Shdr *sechdrs, Elf_Addr v
|
||||
return (Elf_Addr)&plt[nr];
|
||||
}
|
||||
|
||||
static int is_rela_equal(const Elf_Rela *x, const Elf_Rela *y)
|
||||
#define cmp_3way(a, b) ((a) < (b) ? -1 : (a) > (b))
|
||||
|
||||
static int compare_rela(const void *x, const void *y)
|
||||
{
|
||||
return x->r_info == y->r_info && x->r_addend == y->r_addend;
|
||||
}
|
||||
int ret;
|
||||
const Elf_Rela *rela_x = x, *rela_y = y;
|
||||
|
||||
static bool duplicate_rela(const Elf_Rela *rela, int idx)
|
||||
{
|
||||
int i;
|
||||
ret = cmp_3way(rela_x->r_info, rela_y->r_info);
|
||||
if (ret == 0)
|
||||
ret = cmp_3way(rela_x->r_addend, rela_y->r_addend);
|
||||
|
||||
for (i = 0; i < idx; i++) {
|
||||
if (is_rela_equal(&rela[i], &rela[idx]))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void count_max_entries(Elf_Rela *relas, int num,
|
||||
unsigned int *plts, unsigned int *gots)
|
||||
{
|
||||
unsigned int i, type;
|
||||
unsigned int i;
|
||||
|
||||
sort(relas, num, sizeof(Elf_Rela), compare_rela, NULL);
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
type = ELF_R_TYPE(relas[i].r_info);
|
||||
switch (type) {
|
||||
if (i && !compare_rela(&relas[i-1], &relas[i]))
|
||||
continue;
|
||||
|
||||
switch (ELF_R_TYPE(relas[i].r_info)) {
|
||||
case R_LARCH_SOP_PUSH_PLT_PCREL:
|
||||
case R_LARCH_B26:
|
||||
if (!duplicate_rela(relas, i))
|
||||
(*plts)++;
|
||||
(*plts)++;
|
||||
break;
|
||||
case R_LARCH_GOT_PC_HI20:
|
||||
if (!duplicate_rela(relas, i))
|
||||
(*gots)++;
|
||||
(*gots)++;
|
||||
break;
|
||||
default:
|
||||
break; /* Do nothing. */
|
||||
|
||||
@@ -203,11 +203,9 @@ bool bpf_jit_supports_kfunc_call(void)
|
||||
return true;
|
||||
}
|
||||
|
||||
/* initialized on the first pass of build_body() */
|
||||
static int out_offset = -1;
|
||||
static int emit_bpf_tail_call(struct jit_ctx *ctx)
|
||||
static int emit_bpf_tail_call(struct jit_ctx *ctx, int insn)
|
||||
{
|
||||
int off;
|
||||
int off, tc_ninsn = 0;
|
||||
u8 tcc = tail_call_reg(ctx);
|
||||
u8 a1 = LOONGARCH_GPR_A1;
|
||||
u8 a2 = LOONGARCH_GPR_A2;
|
||||
@@ -217,7 +215,7 @@ static int emit_bpf_tail_call(struct jit_ctx *ctx)
|
||||
const int idx0 = ctx->idx;
|
||||
|
||||
#define cur_offset (ctx->idx - idx0)
|
||||
#define jmp_offset (out_offset - (cur_offset))
|
||||
#define jmp_offset (tc_ninsn - (cur_offset))
|
||||
|
||||
/*
|
||||
* a0: &ctx
|
||||
@@ -227,6 +225,7 @@ static int emit_bpf_tail_call(struct jit_ctx *ctx)
|
||||
* if (index >= array->map.max_entries)
|
||||
* goto out;
|
||||
*/
|
||||
tc_ninsn = insn ? ctx->offset[insn+1] - ctx->offset[insn] : ctx->offset[0];
|
||||
off = offsetof(struct bpf_array, map.max_entries);
|
||||
emit_insn(ctx, ldwu, t1, a1, off);
|
||||
/* bgeu $a2, $t1, jmp_offset */
|
||||
@@ -258,15 +257,6 @@ static int emit_bpf_tail_call(struct jit_ctx *ctx)
|
||||
emit_insn(ctx, ldd, t3, t2, off);
|
||||
__build_epilogue(ctx, true);
|
||||
|
||||
/* out: */
|
||||
if (out_offset == -1)
|
||||
out_offset = cur_offset;
|
||||
if (cur_offset != out_offset) {
|
||||
pr_err_once("tail_call out_offset = %d, expected %d!\n",
|
||||
cur_offset, out_offset);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
toofar:
|
||||
@@ -853,7 +843,7 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx, bool ext
|
||||
/* tail call */
|
||||
case BPF_JMP | BPF_TAIL_CALL:
|
||||
mark_tail_call(ctx);
|
||||
if (emit_bpf_tail_call(ctx) < 0)
|
||||
if (emit_bpf_tail_call(ctx, i) < 0)
|
||||
return -EINVAL;
|
||||
break;
|
||||
|
||||
@@ -1251,7 +1241,6 @@ out:
|
||||
if (tmp_blinded)
|
||||
bpf_jit_prog_release_other(prog, prog == orig_prog ? tmp : orig_prog);
|
||||
|
||||
out_offset = -1;
|
||||
|
||||
return prog;
|
||||
}
|
||||
|
||||
@@ -3404,6 +3404,7 @@ L(console_clear_loop):
|
||||
|
||||
movel %d4,%d1 /* screen height in pixels */
|
||||
divul %a0@(FONT_DESC_HEIGHT),%d1 /* d1 = max num rows */
|
||||
subql #1,%d1 /* row range is 0 to num - 1 */
|
||||
|
||||
movel %d0,%a2@(Lconsole_struct_num_columns)
|
||||
movel %d1,%a2@(Lconsole_struct_num_rows)
|
||||
@@ -3550,15 +3551,14 @@ func_start console_putc,%a0/%a1/%d0-%d7
|
||||
cmpib #10,%d7
|
||||
jne L(console_not_lf)
|
||||
movel %a0@(Lconsole_struct_cur_row),%d0
|
||||
addil #1,%d0
|
||||
movel %d0,%a0@(Lconsole_struct_cur_row)
|
||||
movel %a0@(Lconsole_struct_num_rows),%d1
|
||||
cmpl %d1,%d0
|
||||
jcs 1f
|
||||
subil #1,%d0
|
||||
movel %d0,%a0@(Lconsole_struct_cur_row)
|
||||
console_scroll
|
||||
jra L(console_exit)
|
||||
1:
|
||||
addql #1,%d0
|
||||
movel %d0,%a0@(Lconsole_struct_cur_row)
|
||||
jra L(console_exit)
|
||||
|
||||
L(console_not_lf):
|
||||
@@ -3585,12 +3585,6 @@ L(console_not_cr):
|
||||
*/
|
||||
L(console_not_home):
|
||||
movel %a0@(Lconsole_struct_cur_column),%d0
|
||||
addql #1,%a0@(Lconsole_struct_cur_column)
|
||||
movel %a0@(Lconsole_struct_num_columns),%d1
|
||||
cmpl %d1,%d0
|
||||
jcs 1f
|
||||
console_putc #'\n' /* recursion is OK! */
|
||||
1:
|
||||
movel %a0@(Lconsole_struct_cur_row),%d1
|
||||
|
||||
/*
|
||||
@@ -3637,6 +3631,23 @@ L(console_do_font_scanline):
|
||||
addq #1,%d1
|
||||
dbra %d7,L(console_read_char_scanline)
|
||||
|
||||
/*
|
||||
* Register usage in the code below:
|
||||
* a0 = pointer to console globals
|
||||
* d0 = cursor column
|
||||
* d1 = cursor column limit
|
||||
*/
|
||||
|
||||
lea %pc@(L(console_globals)),%a0
|
||||
|
||||
movel %a0@(Lconsole_struct_cur_column),%d0
|
||||
addql #1,%d0
|
||||
movel %d0,%a0@(Lconsole_struct_cur_column) /* Update cursor pos */
|
||||
movel %a0@(Lconsole_struct_num_columns),%d1
|
||||
cmpl %d1,%d0
|
||||
jcs L(console_exit)
|
||||
console_putc #'\n' /* Line wrap using tail recursion */
|
||||
|
||||
L(console_exit):
|
||||
func_return console_putc
|
||||
|
||||
|
||||
@@ -55,17 +55,13 @@
|
||||
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||
#define MSB 0
|
||||
#define LSB 3
|
||||
#define ROTx rotl
|
||||
#define ROTR(n) rotr n, 24
|
||||
#define CPU_TO_LE32(n) \
|
||||
wsbh n; \
|
||||
wsbh n, n; \
|
||||
rotr n, 16;
|
||||
#else
|
||||
#define MSB 3
|
||||
#define LSB 0
|
||||
#define ROTx rotr
|
||||
#define CPU_TO_LE32(n)
|
||||
#define ROTR(n)
|
||||
#endif
|
||||
|
||||
#define FOR_EACH_WORD(x) \
|
||||
@@ -192,10 +188,10 @@ CONCAT3(.Lchacha_mips_xor_aligned_, PLUS_ONE(x), _b: ;) \
|
||||
xor X(W), X(B); \
|
||||
xor X(Y), X(C); \
|
||||
xor X(Z), X(D); \
|
||||
rotl X(V), S; \
|
||||
rotl X(W), S; \
|
||||
rotl X(Y), S; \
|
||||
rotl X(Z), S;
|
||||
rotr X(V), 32 - S; \
|
||||
rotr X(W), 32 - S; \
|
||||
rotr X(Y), 32 - S; \
|
||||
rotr X(Z), 32 - S;
|
||||
|
||||
.text
|
||||
.set reorder
|
||||
@@ -372,21 +368,19 @@ chacha_crypt_arch:
|
||||
/* First byte */
|
||||
lbu T1, 0(IN)
|
||||
addiu $at, BYTES, 1
|
||||
CPU_TO_LE32(SAVED_X)
|
||||
ROTR(SAVED_X)
|
||||
xor T1, SAVED_X
|
||||
sb T1, 0(OUT)
|
||||
beqz $at, .Lchacha_mips_xor_done
|
||||
/* Second byte */
|
||||
lbu T1, 1(IN)
|
||||
addiu $at, BYTES, 2
|
||||
ROTx SAVED_X, 8
|
||||
rotr SAVED_X, 8
|
||||
xor T1, SAVED_X
|
||||
sb T1, 1(OUT)
|
||||
beqz $at, .Lchacha_mips_xor_done
|
||||
/* Third byte */
|
||||
lbu T1, 2(IN)
|
||||
ROTx SAVED_X, 8
|
||||
rotr SAVED_X, 8
|
||||
xor T1, SAVED_X
|
||||
sb T1, 2(OUT)
|
||||
b .Lchacha_mips_xor_done
|
||||
|
||||
@@ -119,4 +119,12 @@ void cleanup_tc(struct tc *tc);
|
||||
|
||||
int __init vpe_module_init(void);
|
||||
void __exit vpe_module_exit(void);
|
||||
|
||||
#ifdef CONFIG_MIPS_VPE_LOADER_MT
|
||||
void *vpe_alloc(void);
|
||||
int vpe_start(void *vpe, unsigned long start);
|
||||
int vpe_stop(void *vpe);
|
||||
int vpe_free(void *vpe);
|
||||
#endif /* CONFIG_MIPS_VPE_LOADER_MT */
|
||||
|
||||
#endif /* _ASM_VPE_H */
|
||||
|
||||
@@ -690,18 +690,20 @@ unsigned long mips_stack_top(void)
|
||||
}
|
||||
|
||||
/* Space for the VDSO, data page & GIC user page */
|
||||
top -= PAGE_ALIGN(current->thread.abi->vdso->size);
|
||||
top -= PAGE_SIZE;
|
||||
top -= mips_gic_present() ? PAGE_SIZE : 0;
|
||||
if (current->thread.abi) {
|
||||
top -= PAGE_ALIGN(current->thread.abi->vdso->size);
|
||||
top -= PAGE_SIZE;
|
||||
top -= mips_gic_present() ? PAGE_SIZE : 0;
|
||||
|
||||
/* Space to randomize the VDSO base */
|
||||
if (current->flags & PF_RANDOMIZE)
|
||||
top -= VDSO_RANDOMIZE_SIZE;
|
||||
}
|
||||
|
||||
/* Space for cache colour alignment */
|
||||
if (cpu_has_dc_aliases)
|
||||
top -= shm_align_mask + 1;
|
||||
|
||||
/* Space to randomize the VDSO base */
|
||||
if (current->flags & PF_RANDOMIZE)
|
||||
top -= VDSO_RANDOMIZE_SIZE;
|
||||
|
||||
return top;
|
||||
}
|
||||
|
||||
|
||||
@@ -214,19 +214,16 @@ void __init ltq_soc_init(void)
|
||||
of_node_put(np_syseth);
|
||||
of_node_put(np_sysgpe);
|
||||
|
||||
if ((request_mem_region(res_status.start, resource_size(&res_status),
|
||||
res_status.name) < 0) ||
|
||||
(request_mem_region(res_ebu.start, resource_size(&res_ebu),
|
||||
res_ebu.name) < 0) ||
|
||||
(request_mem_region(res_sys[0].start,
|
||||
resource_size(&res_sys[0]),
|
||||
res_sys[0].name) < 0) ||
|
||||
(request_mem_region(res_sys[1].start,
|
||||
resource_size(&res_sys[1]),
|
||||
res_sys[1].name) < 0) ||
|
||||
(request_mem_region(res_sys[2].start,
|
||||
resource_size(&res_sys[2]),
|
||||
res_sys[2].name) < 0))
|
||||
if ((!request_mem_region(res_status.start, resource_size(&res_status),
|
||||
res_status.name)) ||
|
||||
(!request_mem_region(res_ebu.start, resource_size(&res_ebu),
|
||||
res_ebu.name)) ||
|
||||
(!request_mem_region(res_sys[0].start, resource_size(&res_sys[0]),
|
||||
res_sys[0].name)) ||
|
||||
(!request_mem_region(res_sys[1].start, resource_size(&res_sys[1]),
|
||||
res_sys[1].name)) ||
|
||||
(!request_mem_region(res_sys[2].start, resource_size(&res_sys[2]),
|
||||
res_sys[2].name)))
|
||||
pr_err("Failed to request core resources");
|
||||
|
||||
status_membase = ioremap(res_status.start,
|
||||
|
||||
@@ -39,7 +39,9 @@ endif
|
||||
|
||||
export LD_BFD
|
||||
|
||||
# Set default 32 bits cross compilers for vdso
|
||||
# Set default 32 bits cross compilers for vdso.
|
||||
# This means that for 64BIT, both the 64-bit tools and the 32-bit tools
|
||||
# need to be in the path.
|
||||
CC_ARCHES_32 = hppa hppa2.0 hppa1.1
|
||||
CC_SUFFIXES = linux linux-gnu unknown-linux-gnu suse-linux
|
||||
CROSS32_COMPILE := $(call cc-cross-prefix, \
|
||||
@@ -139,7 +141,7 @@ palo lifimage: vmlinuz
|
||||
fi
|
||||
@if test ! -f "$(PALOCONF)"; then \
|
||||
cp $(srctree)/arch/parisc/defpalo.conf $(objtree)/palo.conf; \
|
||||
echo 'A generic palo config file ($(objree)/palo.conf) has been created for you.'; \
|
||||
echo 'A generic palo config file ($(objtree)/palo.conf) has been created for you.'; \
|
||||
echo 'You should check it and re-run "make palo".'; \
|
||||
echo 'WARNING: the "lifimage" file is now placed in this directory by default!'; \
|
||||
false; \
|
||||
|
||||
@@ -276,7 +276,7 @@ extern unsigned long *empty_zero_page;
|
||||
#define pte_none(x) (pte_val(x) == 0)
|
||||
#define pte_present(x) (pte_val(x) & _PAGE_PRESENT)
|
||||
#define pte_user(x) (pte_val(x) & _PAGE_USER)
|
||||
#define pte_clear(mm, addr, xp) set_pte(xp, __pte(0))
|
||||
#define pte_clear(mm, addr, xp) set_pte_at((mm), (addr), (xp), __pte(0))
|
||||
|
||||
#define pmd_flag(x) (pmd_val(x) & PxD_FLAG_MASK)
|
||||
#define pmd_address(x) ((unsigned long)(pmd_val(x) &~ PxD_FLAG_MASK) << PxD_VALUE_SHIFT)
|
||||
@@ -398,6 +398,7 @@ static inline void set_ptes(struct mm_struct *mm, unsigned long addr,
|
||||
}
|
||||
}
|
||||
#define set_ptes set_ptes
|
||||
#define set_pte_at(mm, addr, ptep, pte) set_ptes(mm, addr, ptep, pte, 1)
|
||||
|
||||
/* Used for deferring calls to flush_dcache_page() */
|
||||
|
||||
@@ -462,7 +463,7 @@ static inline int ptep_test_and_clear_young(struct vm_area_struct *vma, unsigned
|
||||
if (!pte_young(pte)) {
|
||||
return 0;
|
||||
}
|
||||
set_pte(ptep, pte_mkold(pte));
|
||||
set_pte_at(vma->vm_mm, addr, ptep, pte_mkold(pte));
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -472,7 +473,7 @@ pte_t ptep_clear_flush(struct vm_area_struct *vma, unsigned long addr, pte_t *pt
|
||||
struct mm_struct;
|
||||
static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
|
||||
{
|
||||
set_pte(ptep, pte_wrprotect(*ptep));
|
||||
set_pte_at(mm, addr, ptep, pte_wrprotect(*ptep));
|
||||
}
|
||||
|
||||
#define pte_same(A,B) (pte_val(A) == pte_val(B))
|
||||
|
||||
@@ -32,6 +32,34 @@
|
||||
pa; \
|
||||
})
|
||||
|
||||
/**
|
||||
* prober_user() - Probe user read access
|
||||
* @sr: Space regster.
|
||||
* @va: Virtual address.
|
||||
*
|
||||
* Return: Non-zero if address is accessible.
|
||||
*
|
||||
* Due to the way _PAGE_READ is handled in TLB entries, we need
|
||||
* a special check to determine whether a user address is accessible.
|
||||
* The ldb instruction does the initial access check. If it is
|
||||
* successful, the probe instruction checks user access rights.
|
||||
*/
|
||||
#define prober_user(sr, va) ({ \
|
||||
unsigned long read_allowed; \
|
||||
__asm__ __volatile__( \
|
||||
"copy %%r0,%0\n" \
|
||||
"8:\tldb 0(%%sr%1,%2),%%r0\n" \
|
||||
"\tproberi (%%sr%1,%2),%3,%0\n" \
|
||||
"9:\n" \
|
||||
ASM_EXCEPTIONTABLE_ENTRY(8b, 9b, \
|
||||
"or %%r0,%%r0,%%r0") \
|
||||
: "=&r" (read_allowed) \
|
||||
: "i" (sr), "r" (va), "i" (PRIV_USER) \
|
||||
: "memory" \
|
||||
); \
|
||||
read_allowed; \
|
||||
})
|
||||
|
||||
#define CR_EIEM 15 /* External Interrupt Enable Mask */
|
||||
#define CR_CR16 16 /* CR16 Interval Timer */
|
||||
#define CR_EIRR 23 /* External Interrupt Request Register */
|
||||
|
||||
@@ -42,9 +42,24 @@
|
||||
__gu_err; \
|
||||
})
|
||||
|
||||
#define __get_user(val, ptr) \
|
||||
({ \
|
||||
__get_user_internal(SR_USER, val, ptr); \
|
||||
#define __probe_user_internal(sr, error, ptr) \
|
||||
({ \
|
||||
__asm__("\tproberi (%%sr%1,%2),%3,%0\n" \
|
||||
"\tcmpiclr,= 1,%0,%0\n" \
|
||||
"\tldi %4,%0\n" \
|
||||
: "=r"(error) \
|
||||
: "i"(sr), "r"(ptr), "i"(PRIV_USER), \
|
||||
"i"(-EFAULT)); \
|
||||
})
|
||||
|
||||
#define __get_user(val, ptr) \
|
||||
({ \
|
||||
register long __gu_err; \
|
||||
\
|
||||
__gu_err = __get_user_internal(SR_USER, val, ptr); \
|
||||
if (likely(!__gu_err)) \
|
||||
__probe_user_internal(SR_USER, __gu_err, ptr); \
|
||||
__gu_err; \
|
||||
})
|
||||
|
||||
#define __get_user_asm(sr, val, ldx, ptr) \
|
||||
|
||||
@@ -425,7 +425,7 @@ static inline pte_t *get_ptep(struct mm_struct *mm, unsigned long addr)
|
||||
return ptep;
|
||||
}
|
||||
|
||||
static inline bool pte_needs_flush(pte_t pte)
|
||||
static inline bool pte_needs_cache_flush(pte_t pte)
|
||||
{
|
||||
return (pte_val(pte) & (_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_NO_CACHE))
|
||||
== (_PAGE_PRESENT | _PAGE_ACCESSED);
|
||||
@@ -630,7 +630,7 @@ static void flush_cache_page_if_present(struct vm_area_struct *vma,
|
||||
ptep = get_ptep(vma->vm_mm, vmaddr);
|
||||
if (ptep) {
|
||||
pte = ptep_get(ptep);
|
||||
needs_flush = pte_needs_flush(pte);
|
||||
needs_flush = pte_needs_cache_flush(pte);
|
||||
pte_unmap(ptep);
|
||||
}
|
||||
if (needs_flush)
|
||||
@@ -841,7 +841,7 @@ void flush_cache_vmap(unsigned long start, unsigned long end)
|
||||
}
|
||||
|
||||
vm = find_vm_area((void *)start);
|
||||
if (WARN_ON_ONCE(!vm)) {
|
||||
if (!vm) {
|
||||
flush_cache_all();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -499,6 +499,12 @@
|
||||
* this happens is quite subtle, read below */
|
||||
.macro make_insert_tlb spc,pte,prot,tmp
|
||||
space_to_prot \spc \prot /* create prot id from space */
|
||||
|
||||
#if _PAGE_SPECIAL_BIT == _PAGE_DMB_BIT
|
||||
/* need to drop DMB bit, as it's used as SPECIAL flag */
|
||||
depi 0,_PAGE_SPECIAL_BIT,1,\pte
|
||||
#endif
|
||||
|
||||
/* The following is the real subtlety. This is depositing
|
||||
* T <-> _PAGE_REFTRAP
|
||||
* D <-> _PAGE_DIRTY
|
||||
@@ -511,17 +517,18 @@
|
||||
* Finally, _PAGE_READ goes in the top bit of PL1 (so we
|
||||
* trigger an access rights trap in user space if the user
|
||||
* tries to read an unreadable page */
|
||||
#if _PAGE_SPECIAL_BIT == _PAGE_DMB_BIT
|
||||
/* need to drop DMB bit, as it's used as SPECIAL flag */
|
||||
depi 0,_PAGE_SPECIAL_BIT,1,\pte
|
||||
#endif
|
||||
depd \pte,8,7,\prot
|
||||
|
||||
/* PAGE_USER indicates the page can be read with user privileges,
|
||||
* so deposit X1|11 to PL1|PL2 (remember the upper bit of PL1
|
||||
* contains _PAGE_READ) */
|
||||
* contains _PAGE_READ). While the kernel can't directly write
|
||||
* user pages which have _PAGE_WRITE zero, it can read pages
|
||||
* which have _PAGE_READ zero (PL <= PL1). Thus, the kernel
|
||||
* exception fault handler doesn't trigger when reading pages
|
||||
* that aren't user read accessible */
|
||||
extrd,u,*= \pte,_PAGE_USER_BIT+32,1,%r0
|
||||
depdi 7,11,3,\prot
|
||||
|
||||
/* If we're a gateway page, drop PL2 back to zero for promotion
|
||||
* to kernel privilege (so we can execute the page as kernel).
|
||||
* Any privilege promotion page always denys read and write */
|
||||
|
||||
@@ -613,6 +613,9 @@ lws_compare_and_swap32:
|
||||
lws_compare_and_swap:
|
||||
/* Trigger memory reference interruptions without writing to memory */
|
||||
1: ldw 0(%r26), %r28
|
||||
proberi (%r26), PRIV_USER, %r28
|
||||
comb,=,n %r28, %r0, lws_fault /* backwards, likely not taken */
|
||||
nop
|
||||
2: stbys,e %r0, 0(%r26)
|
||||
|
||||
/* Calculate 8-bit hash index from virtual address */
|
||||
@@ -767,6 +770,9 @@ cas2_lock_start:
|
||||
copy %r26, %r28
|
||||
depi_safe 0, 31, 2, %r28
|
||||
10: ldw 0(%r28), %r1
|
||||
proberi (%r28), PRIV_USER, %r1
|
||||
comb,=,n %r1, %r0, lws_fault /* backwards, likely not taken */
|
||||
nop
|
||||
11: stbys,e %r0, 0(%r28)
|
||||
|
||||
/* Calculate 8-bit hash index from virtual address */
|
||||
@@ -951,41 +957,47 @@ atomic_xchg_begin:
|
||||
|
||||
/* 8-bit exchange */
|
||||
1: ldb 0(%r24), %r20
|
||||
proberi (%r24), PRIV_USER, %r20
|
||||
comb,=,n %r20, %r0, lws_fault /* backwards, likely not taken */
|
||||
nop
|
||||
copy %r23, %r20
|
||||
depi_safe 0, 31, 2, %r20
|
||||
b atomic_xchg_start
|
||||
2: stbys,e %r0, 0(%r20)
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
/* 16-bit exchange */
|
||||
3: ldh 0(%r24), %r20
|
||||
proberi (%r24), PRIV_USER, %r20
|
||||
comb,=,n %r20, %r0, lws_fault /* backwards, likely not taken */
|
||||
nop
|
||||
copy %r23, %r20
|
||||
depi_safe 0, 31, 2, %r20
|
||||
b atomic_xchg_start
|
||||
4: stbys,e %r0, 0(%r20)
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
/* 32-bit exchange */
|
||||
5: ldw 0(%r24), %r20
|
||||
proberi (%r24), PRIV_USER, %r20
|
||||
comb,=,n %r20, %r0, lws_fault /* backwards, likely not taken */
|
||||
nop
|
||||
b atomic_xchg_start
|
||||
6: stbys,e %r0, 0(%r23)
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
/* 64-bit exchange */
|
||||
#ifdef CONFIG_64BIT
|
||||
7: ldd 0(%r24), %r20
|
||||
proberi (%r24), PRIV_USER, %r20
|
||||
comb,=,n %r20, %r0, lws_fault /* backwards, likely not taken */
|
||||
nop
|
||||
8: stdby,e %r0, 0(%r23)
|
||||
#else
|
||||
7: ldw 0(%r24), %r20
|
||||
8: ldw 4(%r24), %r20
|
||||
proberi (%r24), PRIV_USER, %r20
|
||||
comb,=,n %r20, %r0, lws_fault /* backwards, likely not taken */
|
||||
nop
|
||||
copy %r23, %r20
|
||||
depi_safe 0, 31, 2, %r20
|
||||
9: stbys,e %r0, 0(%r20)
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/mm.h>
|
||||
|
||||
#define get_user_space() mfsp(SR_USER)
|
||||
#define get_kernel_space() SR_KERNEL
|
||||
@@ -32,9 +33,25 @@ EXPORT_SYMBOL(raw_copy_to_user);
|
||||
unsigned long raw_copy_from_user(void *dst, const void __user *src,
|
||||
unsigned long len)
|
||||
{
|
||||
unsigned long start = (unsigned long) src;
|
||||
unsigned long end = start + len;
|
||||
unsigned long newlen = len;
|
||||
|
||||
mtsp(get_user_space(), SR_TEMP1);
|
||||
mtsp(get_kernel_space(), SR_TEMP2);
|
||||
return pa_memcpy(dst, (void __force *)src, len);
|
||||
|
||||
/* Check region is user accessible */
|
||||
if (start)
|
||||
while (start < end) {
|
||||
if (!prober_user(SR_TEMP1, start)) {
|
||||
newlen = (start - (unsigned long) src);
|
||||
break;
|
||||
}
|
||||
start += PAGE_SIZE;
|
||||
/* align to page boundry which may have different permission */
|
||||
start = PAGE_ALIGN_DOWN(start);
|
||||
}
|
||||
return len - newlen + pa_memcpy(dst, (void __force *)src, newlen);
|
||||
}
|
||||
EXPORT_SYMBOL(raw_copy_from_user);
|
||||
|
||||
|
||||
@@ -363,6 +363,10 @@ bad_area:
|
||||
mmap_read_unlock(mm);
|
||||
|
||||
bad_area_nosemaphore:
|
||||
if (!user_mode(regs) && fixup_exception(regs)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (user_mode(regs)) {
|
||||
int signo, si_code;
|
||||
|
||||
|
||||
@@ -72,6 +72,7 @@ BOOTCPPFLAGS := -nostdinc $(LINUXINCLUDE)
|
||||
BOOTCPPFLAGS += -isystem $(shell $(BOOTCC) -print-file-name=include)
|
||||
|
||||
BOOTCFLAGS := $(BOOTTARGETFLAGS) \
|
||||
-std=gnu11 \
|
||||
-Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \
|
||||
-fno-strict-aliasing -O2 \
|
||||
-msoft-float -mno-altivec -mno-vsx \
|
||||
|
||||
@@ -144,9 +144,12 @@ static int hard_dma_setup(char *addr, unsigned long size, int mode, int io)
|
||||
bus_addr = 0;
|
||||
}
|
||||
|
||||
if (!bus_addr) /* need to map it */
|
||||
if (!bus_addr) { /* need to map it */
|
||||
bus_addr = dma_map_single(&isa_bridge_pcidev->dev, addr, size,
|
||||
dir);
|
||||
if (dma_mapping_error(&isa_bridge_pcidev->dev, bus_addr))
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* remember this one as prev */
|
||||
prev_addr = addr;
|
||||
|
||||
@@ -240,10 +240,8 @@ static int mpc512x_lpbfifo_kick(void)
|
||||
dma_conf.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
|
||||
|
||||
/* Make DMA channel work with LPB FIFO data register */
|
||||
if (dma_dev->device_config(lpbfifo.chan, &dma_conf)) {
|
||||
ret = -EINVAL;
|
||||
goto err_dma_prep;
|
||||
}
|
||||
if (dma_dev->device_config(lpbfifo.chan, &dma_conf))
|
||||
return -EINVAL;
|
||||
|
||||
sg_init_table(&sg, 1);
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#define arch_set_freq_scale topology_set_freq_scale
|
||||
#define arch_scale_freq_capacity topology_get_freq_scale
|
||||
#define arch_scale_freq_invariant topology_scale_freq_invariant
|
||||
#define arch_scale_freq_ref topology_get_freq_ref
|
||||
|
||||
/* Replace task scheduler's default cpu-invariant accounting */
|
||||
#define arch_scale_cpu_capacity topology_get_cpu_scale
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
* Author(s): Michael Holzheu <holzheu@linux.vnet.ibm.com>
|
||||
*/
|
||||
|
||||
#include <linux/security.h>
|
||||
#include <linux/slab.h>
|
||||
#include "hypfs.h"
|
||||
|
||||
@@ -64,24 +65,28 @@ static long dbfs_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
long rc;
|
||||
|
||||
mutex_lock(&df->lock);
|
||||
if (df->unlocked_ioctl)
|
||||
rc = df->unlocked_ioctl(file, cmd, arg);
|
||||
else
|
||||
rc = -ENOTTY;
|
||||
rc = df->unlocked_ioctl(file, cmd, arg);
|
||||
mutex_unlock(&df->lock);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static const struct file_operations dbfs_ops = {
|
||||
static const struct file_operations dbfs_ops_ioctl = {
|
||||
.read = dbfs_read,
|
||||
.llseek = no_llseek,
|
||||
.unlocked_ioctl = dbfs_ioctl,
|
||||
};
|
||||
|
||||
static const struct file_operations dbfs_ops = {
|
||||
.read = dbfs_read,
|
||||
};
|
||||
|
||||
void hypfs_dbfs_create_file(struct hypfs_dbfs_file *df)
|
||||
{
|
||||
df->dentry = debugfs_create_file(df->name, 0400, dbfs_dir, df,
|
||||
&dbfs_ops);
|
||||
const struct file_operations *fops = &dbfs_ops;
|
||||
|
||||
if (df->unlocked_ioctl && !security_locked_down(LOCKDOWN_DEBUGFS))
|
||||
fops = &dbfs_ops_ioctl;
|
||||
df->dentry = debugfs_create_file(df->name, 0400, dbfs_dir, df, fops);
|
||||
mutex_init(&df->lock);
|
||||
}
|
||||
|
||||
|
||||
@@ -192,13 +192,6 @@ static inline unsigned long get_tod_clock_fast(void)
|
||||
asm volatile("stckf %0" : "=Q" (clk) : : "cc");
|
||||
return clk;
|
||||
}
|
||||
|
||||
static inline cycles_t get_cycles(void)
|
||||
{
|
||||
return (cycles_t) get_tod_clock() >> 2;
|
||||
}
|
||||
#define get_cycles get_cycles
|
||||
|
||||
int get_phys_clock(unsigned long *clock);
|
||||
void init_cpu_timer(void);
|
||||
|
||||
@@ -226,6 +219,12 @@ static inline unsigned long get_tod_clock_monotonic(void)
|
||||
return tod;
|
||||
}
|
||||
|
||||
static inline cycles_t get_cycles(void)
|
||||
{
|
||||
return (cycles_t)get_tod_clock_monotonic() >> 2;
|
||||
}
|
||||
#define get_cycles get_cycles
|
||||
|
||||
/**
|
||||
* tod_to_ns - convert a TOD format value to nanoseconds
|
||||
* @todval: to be converted TOD format value
|
||||
|
||||
@@ -579,7 +579,7 @@ static int stp_sync_clock(void *data)
|
||||
atomic_dec(&sync->cpus);
|
||||
/* Wait for in_sync to be set. */
|
||||
while (READ_ONCE(sync->in_sync) == 0)
|
||||
__udelay(1);
|
||||
;
|
||||
}
|
||||
if (sync->in_sync != 1)
|
||||
/* Didn't work. Clear per-cpu in sync bit again. */
|
||||
|
||||
@@ -249,11 +249,9 @@ static int ptdump_show(struct seq_file *m, void *v)
|
||||
.marker = address_markers,
|
||||
};
|
||||
|
||||
get_online_mems();
|
||||
mutex_lock(&cpa_mutex);
|
||||
ptdump_walk_pgd(&st.ptdump, &init_mm, NULL);
|
||||
mutex_unlock(&cpa_mutex);
|
||||
put_online_mems();
|
||||
return 0;
|
||||
}
|
||||
DEFINE_SHOW_ATTRIBUTE(ptdump);
|
||||
|
||||
@@ -456,11 +456,6 @@ void pte_free_defer(struct mm_struct *mm, pgtable_t pgtable)
|
||||
page = virt_to_page(pgtable);
|
||||
SetPageActive(page);
|
||||
page_table_free(mm, (unsigned long *)pgtable);
|
||||
/*
|
||||
* page_table_free() does not do the pgste gmap_unlink() which
|
||||
* page_table_free_rcu() does: warn us if pgste ever reaches here.
|
||||
*/
|
||||
WARN_ON_ONCE(mm_has_pgste(mm));
|
||||
}
|
||||
#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
|
||||
|
||||
|
||||
@@ -68,7 +68,11 @@ static inline struct thread_info *current_thread_info(void)
|
||||
#define _TIF_NOTIFY_SIGNAL (1 << TIF_NOTIFY_SIGNAL)
|
||||
#define _TIF_MEMDIE (1 << TIF_MEMDIE)
|
||||
#define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT)
|
||||
#define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME)
|
||||
#define _TIF_SECCOMP (1 << TIF_SECCOMP)
|
||||
#define _TIF_SINGLESTEP (1 << TIF_SINGLESTEP)
|
||||
|
||||
#define _TIF_WORK_MASK (_TIF_NEED_RESCHED | _TIF_SIGPENDING | _TIF_NOTIFY_SIGNAL | \
|
||||
_TIF_NOTIFY_RESUME)
|
||||
|
||||
#endif
|
||||
|
||||
@@ -98,14 +98,18 @@ void *__switch_to(struct task_struct *from, struct task_struct *to)
|
||||
void interrupt_end(void)
|
||||
{
|
||||
struct pt_regs *regs = ¤t->thread.regs;
|
||||
unsigned long thread_flags;
|
||||
|
||||
if (need_resched())
|
||||
schedule();
|
||||
if (test_thread_flag(TIF_SIGPENDING) ||
|
||||
test_thread_flag(TIF_NOTIFY_SIGNAL))
|
||||
do_signal(regs);
|
||||
if (test_thread_flag(TIF_NOTIFY_RESUME))
|
||||
resume_user_mode_work(regs);
|
||||
thread_flags = read_thread_flags();
|
||||
while (thread_flags & _TIF_WORK_MASK) {
|
||||
if (thread_flags & _TIF_NEED_RESCHED)
|
||||
schedule();
|
||||
if (thread_flags & (_TIF_SIGPENDING | _TIF_NOTIFY_SIGNAL))
|
||||
do_signal(regs);
|
||||
if (thread_flags & _TIF_NOTIFY_RESUME)
|
||||
resume_user_mode_work(regs);
|
||||
thread_flags = read_thread_flags();
|
||||
}
|
||||
}
|
||||
|
||||
int get_current_pid(void)
|
||||
|
||||
@@ -48,7 +48,6 @@ KVM_X86_OP(set_idt)
|
||||
KVM_X86_OP(get_gdt)
|
||||
KVM_X86_OP(set_gdt)
|
||||
KVM_X86_OP(sync_dirty_debug_regs)
|
||||
KVM_X86_OP(set_dr6)
|
||||
KVM_X86_OP(set_dr7)
|
||||
KVM_X86_OP(cache_reg)
|
||||
KVM_X86_OP(get_rflags)
|
||||
@@ -102,7 +101,6 @@ KVM_X86_OP(write_tsc_multiplier)
|
||||
KVM_X86_OP(get_exit_info)
|
||||
KVM_X86_OP(check_intercept)
|
||||
KVM_X86_OP(handle_exit_irqoff)
|
||||
KVM_X86_OP(request_immediate_exit)
|
||||
KVM_X86_OP(sched_in)
|
||||
KVM_X86_OP_OPTIONAL(update_cpu_dirty_logging)
|
||||
KVM_X86_OP_OPTIONAL(vcpu_blocking)
|
||||
|
||||
@@ -733,6 +733,7 @@ struct kvm_vcpu_arch {
|
||||
u32 pkru;
|
||||
u32 hflags;
|
||||
u64 efer;
|
||||
u64 host_debugctl;
|
||||
u64 apic_base;
|
||||
struct kvm_lapic *apic; /* kernel irqchip context */
|
||||
bool load_eoi_exitmap_pending;
|
||||
@@ -1549,6 +1550,12 @@ static inline u16 kvm_lapic_irq_dest_mode(bool dest_mode_logical)
|
||||
return dest_mode_logical ? APIC_DEST_LOGICAL : APIC_DEST_PHYSICAL;
|
||||
}
|
||||
|
||||
enum kvm_x86_run_flags {
|
||||
KVM_RUN_FORCE_IMMEDIATE_EXIT = BIT(0),
|
||||
KVM_RUN_LOAD_GUEST_DR6 = BIT(1),
|
||||
KVM_RUN_LOAD_DEBUGCTL = BIT(2),
|
||||
};
|
||||
|
||||
struct kvm_x86_ops {
|
||||
const char *name;
|
||||
|
||||
@@ -1574,6 +1581,12 @@ struct kvm_x86_ops {
|
||||
void (*vcpu_load)(struct kvm_vcpu *vcpu, int cpu);
|
||||
void (*vcpu_put)(struct kvm_vcpu *vcpu);
|
||||
|
||||
/*
|
||||
* Mask of DEBUGCTL bits that are owned by the host, i.e. that need to
|
||||
* match the host's value even while the guest is active.
|
||||
*/
|
||||
const u64 HOST_OWNED_DEBUGCTL;
|
||||
|
||||
void (*update_exception_bitmap)(struct kvm_vcpu *vcpu);
|
||||
int (*get_msr)(struct kvm_vcpu *vcpu, struct msr_data *msr);
|
||||
int (*set_msr)(struct kvm_vcpu *vcpu, struct msr_data *msr);
|
||||
@@ -1595,7 +1608,6 @@ struct kvm_x86_ops {
|
||||
void (*get_gdt)(struct kvm_vcpu *vcpu, struct desc_ptr *dt);
|
||||
void (*set_gdt)(struct kvm_vcpu *vcpu, struct desc_ptr *dt);
|
||||
void (*sync_dirty_debug_regs)(struct kvm_vcpu *vcpu);
|
||||
void (*set_dr6)(struct kvm_vcpu *vcpu, unsigned long value);
|
||||
void (*set_dr7)(struct kvm_vcpu *vcpu, unsigned long value);
|
||||
void (*cache_reg)(struct kvm_vcpu *vcpu, enum kvm_reg reg);
|
||||
unsigned long (*get_rflags)(struct kvm_vcpu *vcpu);
|
||||
@@ -1623,7 +1635,8 @@ struct kvm_x86_ops {
|
||||
void (*flush_tlb_guest)(struct kvm_vcpu *vcpu);
|
||||
|
||||
int (*vcpu_pre_run)(struct kvm_vcpu *vcpu);
|
||||
enum exit_fastpath_completion (*vcpu_run)(struct kvm_vcpu *vcpu);
|
||||
enum exit_fastpath_completion (*vcpu_run)(struct kvm_vcpu *vcpu,
|
||||
u64 run_flags);
|
||||
int (*handle_exit)(struct kvm_vcpu *vcpu,
|
||||
enum exit_fastpath_completion exit_fastpath);
|
||||
int (*skip_emulated_instruction)(struct kvm_vcpu *vcpu);
|
||||
@@ -1657,7 +1670,7 @@ struct kvm_x86_ops {
|
||||
bool allow_apicv_in_x2apic_without_x2apic_virtualization;
|
||||
void (*refresh_apicv_exec_ctrl)(struct kvm_vcpu *vcpu);
|
||||
void (*hwapic_irr_update)(struct kvm_vcpu *vcpu, int max_irr);
|
||||
void (*hwapic_isr_update)(int isr);
|
||||
void (*hwapic_isr_update)(struct kvm_vcpu *vcpu, int isr);
|
||||
bool (*guest_apic_has_interrupt)(struct kvm_vcpu *vcpu);
|
||||
void (*load_eoi_exitmap)(struct kvm_vcpu *vcpu, u64 *eoi_exit_bitmap);
|
||||
void (*set_virtual_apic_mode)(struct kvm_vcpu *vcpu);
|
||||
@@ -1693,8 +1706,6 @@ struct kvm_x86_ops {
|
||||
struct x86_exception *exception);
|
||||
void (*handle_exit_irqoff)(struct kvm_vcpu *vcpu);
|
||||
|
||||
void (*request_immediate_exit)(struct kvm_vcpu *vcpu);
|
||||
|
||||
void (*sched_in)(struct kvm_vcpu *kvm, int cpu);
|
||||
|
||||
/*
|
||||
@@ -2180,7 +2191,6 @@ extern bool kvm_find_async_pf_gfn(struct kvm_vcpu *vcpu, gfn_t gfn);
|
||||
|
||||
int kvm_skip_emulated_instruction(struct kvm_vcpu *vcpu);
|
||||
int kvm_complete_insn_gp(struct kvm_vcpu *vcpu, int err);
|
||||
void __kvm_request_immediate_exit(struct kvm_vcpu *vcpu);
|
||||
|
||||
void __user *__x86_set_memory_region(struct kvm *kvm, int id, gpa_t gpa,
|
||||
u32 size);
|
||||
|
||||
@@ -380,6 +380,7 @@
|
||||
#define DEBUGCTLMSR_FREEZE_PERFMON_ON_PMI (1UL << 12)
|
||||
#define DEBUGCTLMSR_FREEZE_IN_SMM_BIT 14
|
||||
#define DEBUGCTLMSR_FREEZE_IN_SMM (1UL << DEBUGCTLMSR_FREEZE_IN_SMM_BIT)
|
||||
#define DEBUGCTLMSR_RTM_DEBUG BIT(15)
|
||||
|
||||
#define MSR_PEBS_FRONTEND 0x000003f7
|
||||
|
||||
|
||||
@@ -94,12 +94,13 @@ DECLARE_STATIC_CALL(xen_hypercall, xen_hypercall_func);
|
||||
#ifdef MODULE
|
||||
#define __ADDRESSABLE_xen_hypercall
|
||||
#else
|
||||
#define __ADDRESSABLE_xen_hypercall __ADDRESSABLE_ASM_STR(__SCK__xen_hypercall)
|
||||
#define __ADDRESSABLE_xen_hypercall \
|
||||
__stringify(.global STATIC_CALL_KEY(xen_hypercall);)
|
||||
#endif
|
||||
|
||||
#define __HYPERCALL \
|
||||
__ADDRESSABLE_xen_hypercall \
|
||||
"call __SCT__xen_hypercall"
|
||||
__stringify(call STATIC_CALL_TRAMP(xen_hypercall))
|
||||
|
||||
#define __HYPERCALL_ENTRY(x) "a" (x)
|
||||
|
||||
|
||||
@@ -71,10 +71,9 @@ void (*x86_return_thunk)(void) __ro_after_init = __x86_return_thunk;
|
||||
|
||||
static void __init set_return_thunk(void *thunk)
|
||||
{
|
||||
if (x86_return_thunk != __x86_return_thunk)
|
||||
pr_warn("x86/bugs: return thunk changed\n");
|
||||
|
||||
x86_return_thunk = thunk;
|
||||
|
||||
pr_info("active return thunk: %ps\n", thunk);
|
||||
}
|
||||
|
||||
/* Update SPEC_CTRL MSR and its cached copy unconditionally */
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <asm/cacheinfo.h>
|
||||
#include <asm/spec-ctrl.h>
|
||||
#include <asm/delay.h>
|
||||
#include <asm/resctrl.h>
|
||||
|
||||
#include "cpu.h"
|
||||
|
||||
@@ -240,6 +241,8 @@ static void bsp_init_hygon(struct cpuinfo_x86 *c)
|
||||
x86_amd_ls_cfg_ssbd_mask = 1ULL << 10;
|
||||
}
|
||||
}
|
||||
|
||||
resctrl_cpu_detect(c);
|
||||
}
|
||||
|
||||
static void early_init_hygon(struct cpuinfo_x86 *c)
|
||||
|
||||
@@ -1929,6 +1929,9 @@ int kvm_hv_vcpu_flush_tlb(struct kvm_vcpu *vcpu)
|
||||
if (entries[i] == KVM_HV_TLB_FLUSHALL_ENTRY)
|
||||
goto out_flush_all;
|
||||
|
||||
if (is_noncanonical_address(entries[i], vcpu))
|
||||
continue;
|
||||
|
||||
/*
|
||||
* Lower 12 bits of 'address' encode the number of additional
|
||||
* pages to flush.
|
||||
|
||||
@@ -750,7 +750,7 @@ static inline void apic_set_isr(int vec, struct kvm_lapic *apic)
|
||||
* just set SVI.
|
||||
*/
|
||||
if (unlikely(apic->apicv_active))
|
||||
static_call_cond(kvm_x86_hwapic_isr_update)(vec);
|
||||
static_call_cond(kvm_x86_hwapic_isr_update)(apic->vcpu, vec);
|
||||
else {
|
||||
++apic->isr_count;
|
||||
BUG_ON(apic->isr_count > MAX_APIC_VECTOR);
|
||||
@@ -795,7 +795,7 @@ static inline void apic_clear_isr(int vec, struct kvm_lapic *apic)
|
||||
* and must be left alone.
|
||||
*/
|
||||
if (unlikely(apic->apicv_active))
|
||||
static_call_cond(kvm_x86_hwapic_isr_update)(apic_find_highest_isr(apic));
|
||||
static_call_cond(kvm_x86_hwapic_isr_update)(apic->vcpu, apic_find_highest_isr(apic));
|
||||
else {
|
||||
--apic->isr_count;
|
||||
BUG_ON(apic->isr_count < 0);
|
||||
@@ -803,6 +803,17 @@ static inline void apic_clear_isr(int vec, struct kvm_lapic *apic)
|
||||
}
|
||||
}
|
||||
|
||||
void kvm_apic_update_hwapic_isr(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
struct kvm_lapic *apic = vcpu->arch.apic;
|
||||
|
||||
if (WARN_ON_ONCE(!lapic_in_kernel(vcpu)) || !apic->apicv_active)
|
||||
return;
|
||||
|
||||
static_call(kvm_x86_hwapic_isr_update)(vcpu, apic_find_highest_isr(apic));
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(kvm_apic_update_hwapic_isr);
|
||||
|
||||
int kvm_lapic_find_highest_irr(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
/* This may race with setting of irr in __apic_accept_irq() and
|
||||
@@ -2772,7 +2783,7 @@ void kvm_lapic_reset(struct kvm_vcpu *vcpu, bool init_event)
|
||||
if (apic->apicv_active) {
|
||||
static_call_cond(kvm_x86_apicv_post_state_restore)(vcpu);
|
||||
static_call_cond(kvm_x86_hwapic_irr_update)(vcpu, -1);
|
||||
static_call_cond(kvm_x86_hwapic_isr_update)(-1);
|
||||
static_call_cond(kvm_x86_hwapic_isr_update)(vcpu, -1);
|
||||
}
|
||||
|
||||
vcpu->arch.apic_arb_prio = 0;
|
||||
@@ -3072,7 +3083,7 @@ int kvm_apic_set_state(struct kvm_vcpu *vcpu, struct kvm_lapic_state *s)
|
||||
if (apic->apicv_active) {
|
||||
static_call_cond(kvm_x86_apicv_post_state_restore)(vcpu);
|
||||
static_call_cond(kvm_x86_hwapic_irr_update)(vcpu, apic_find_highest_irr(apic));
|
||||
static_call_cond(kvm_x86_hwapic_isr_update)(apic_find_highest_isr(apic));
|
||||
static_call_cond(kvm_x86_hwapic_isr_update)(vcpu, apic_find_highest_isr(apic));
|
||||
}
|
||||
kvm_make_request(KVM_REQ_EVENT, vcpu);
|
||||
if (ioapic_in_kernel(vcpu->kvm))
|
||||
|
||||
@@ -124,6 +124,7 @@ int kvm_set_apic_base(struct kvm_vcpu *vcpu, struct msr_data *msr_info);
|
||||
int kvm_apic_get_state(struct kvm_vcpu *vcpu, struct kvm_lapic_state *s);
|
||||
int kvm_apic_set_state(struct kvm_vcpu *vcpu, struct kvm_lapic_state *s);
|
||||
enum lapic_mode kvm_get_apic_mode(struct kvm_vcpu *vcpu);
|
||||
void kvm_apic_update_hwapic_isr(struct kvm_vcpu *vcpu);
|
||||
int kvm_lapic_find_highest_irr(struct kvm_vcpu *vcpu);
|
||||
|
||||
u64 kvm_get_lapic_tscdeadline_msr(struct kvm_vcpu *vcpu);
|
||||
|
||||
@@ -4157,6 +4157,9 @@ static int svm_vcpu_pre_run(struct kvm_vcpu *vcpu)
|
||||
|
||||
static fastpath_t svm_exit_handlers_fastpath(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
if (is_guest_mode(vcpu))
|
||||
return EXIT_FASTPATH_NONE;
|
||||
|
||||
if (to_svm(vcpu)->vmcb->control.exit_code == SVM_EXIT_MSR &&
|
||||
to_svm(vcpu)->vmcb->control.exit_info_1)
|
||||
return handle_fastpath_set_msr_irqoff(vcpu);
|
||||
@@ -4170,6 +4173,18 @@ static noinstr void svm_vcpu_enter_exit(struct kvm_vcpu *vcpu, bool spec_ctrl_in
|
||||
|
||||
guest_state_enter_irqoff();
|
||||
|
||||
/*
|
||||
* Set RFLAGS.IF prior to VMRUN, as the host's RFLAGS.IF at the time of
|
||||
* VMRUN controls whether or not physical IRQs are masked (KVM always
|
||||
* runs with V_INTR_MASKING_MASK). Toggle RFLAGS.IF here to avoid the
|
||||
* temptation to do STI+VMRUN+CLI, as AMD CPUs bleed the STI shadow
|
||||
* into guest state if delivery of an event during VMRUN triggers a
|
||||
* #VMEXIT, and the guest_state transitions already tell lockdep that
|
||||
* IRQs are being enabled/disabled. Note! GIF=0 for the entirety of
|
||||
* this path, so IRQs aren't actually unmasked while running host code.
|
||||
*/
|
||||
raw_local_irq_enable();
|
||||
|
||||
amd_clear_divider();
|
||||
|
||||
if (sev_es_guest(vcpu->kvm))
|
||||
@@ -4177,15 +4192,18 @@ static noinstr void svm_vcpu_enter_exit(struct kvm_vcpu *vcpu, bool spec_ctrl_in
|
||||
else
|
||||
__svm_vcpu_run(svm, spec_ctrl_intercepted);
|
||||
|
||||
raw_local_irq_disable();
|
||||
|
||||
guest_state_exit_irqoff();
|
||||
}
|
||||
|
||||
static __no_kcsan fastpath_t svm_vcpu_run(struct kvm_vcpu *vcpu)
|
||||
static __no_kcsan fastpath_t svm_vcpu_run(struct kvm_vcpu *vcpu, u64 run_flags)
|
||||
{
|
||||
bool force_immediate_exit = run_flags & KVM_RUN_FORCE_IMMEDIATE_EXIT;
|
||||
struct vcpu_svm *svm = to_svm(vcpu);
|
||||
bool spec_ctrl_intercepted = msr_write_intercepted(vcpu, MSR_IA32_SPEC_CTRL);
|
||||
|
||||
trace_kvm_entry(vcpu);
|
||||
trace_kvm_entry(vcpu, force_immediate_exit);
|
||||
|
||||
svm->vmcb->save.rax = vcpu->arch.regs[VCPU_REGS_RAX];
|
||||
svm->vmcb->save.rsp = vcpu->arch.regs[VCPU_REGS_RSP];
|
||||
@@ -4204,9 +4222,12 @@ static __no_kcsan fastpath_t svm_vcpu_run(struct kvm_vcpu *vcpu)
|
||||
* is enough to force an immediate vmexit.
|
||||
*/
|
||||
disable_nmi_singlestep(svm);
|
||||
smp_send_reschedule(vcpu->cpu);
|
||||
force_immediate_exit = true;
|
||||
}
|
||||
|
||||
if (force_immediate_exit)
|
||||
smp_send_reschedule(vcpu->cpu);
|
||||
|
||||
pre_svm_run(vcpu);
|
||||
|
||||
sync_lapic_to_cr8(vcpu);
|
||||
@@ -4220,10 +4241,13 @@ static __no_kcsan fastpath_t svm_vcpu_run(struct kvm_vcpu *vcpu)
|
||||
svm_hv_update_vp_id(svm->vmcb, vcpu);
|
||||
|
||||
/*
|
||||
* Run with all-zero DR6 unless needed, so that we can get the exact cause
|
||||
* of a #DB.
|
||||
* Run with all-zero DR6 unless the guest can write DR6 freely, so that
|
||||
* KVM can get the exact cause of a #DB. Note, loading guest DR6 from
|
||||
* KVM's snapshot is only necessary when DR accesses won't exit.
|
||||
*/
|
||||
if (likely(!(vcpu->arch.switch_db_regs & KVM_DEBUGREG_WONT_EXIT)))
|
||||
if (unlikely(run_flags & KVM_RUN_LOAD_GUEST_DR6))
|
||||
svm_set_dr6(vcpu, vcpu->arch.dr6);
|
||||
else if (likely(!(vcpu->arch.switch_db_regs & KVM_DEBUGREG_WONT_EXIT)))
|
||||
svm_set_dr6(vcpu, DR6_ACTIVE_LOW);
|
||||
|
||||
clgi();
|
||||
@@ -4300,9 +4324,6 @@ static __no_kcsan fastpath_t svm_vcpu_run(struct kvm_vcpu *vcpu)
|
||||
|
||||
svm_complete_interrupts(vcpu);
|
||||
|
||||
if (is_guest_mode(vcpu))
|
||||
return EXIT_FASTPATH_NONE;
|
||||
|
||||
return svm_exit_handlers_fastpath(vcpu);
|
||||
}
|
||||
|
||||
@@ -5003,7 +5024,6 @@ static struct kvm_x86_ops svm_x86_ops __initdata = {
|
||||
.set_idt = svm_set_idt,
|
||||
.get_gdt = svm_get_gdt,
|
||||
.set_gdt = svm_set_gdt,
|
||||
.set_dr6 = svm_set_dr6,
|
||||
.set_dr7 = svm_set_dr7,
|
||||
.sync_dirty_debug_regs = svm_sync_dirty_debug_regs,
|
||||
.cache_reg = svm_cache_reg,
|
||||
@@ -5060,8 +5080,6 @@ static struct kvm_x86_ops svm_x86_ops __initdata = {
|
||||
.check_intercept = svm_check_intercept,
|
||||
.handle_exit_irqoff = svm_handle_exit_irqoff,
|
||||
|
||||
.request_immediate_exit = __kvm_request_immediate_exit,
|
||||
|
||||
.sched_in = svm_sched_in,
|
||||
|
||||
.nested_ops = &svm_nested_ops,
|
||||
|
||||
@@ -171,12 +171,8 @@ SYM_FUNC_START(__svm_vcpu_run)
|
||||
VM_CLEAR_CPU_BUFFERS
|
||||
|
||||
/* Enter guest mode */
|
||||
sti
|
||||
|
||||
3: vmrun %_ASM_AX
|
||||
4:
|
||||
cli
|
||||
|
||||
/* Pop @svm to RAX while it's the only available register. */
|
||||
pop %_ASM_AX
|
||||
|
||||
@@ -341,11 +337,8 @@ SYM_FUNC_START(__svm_sev_es_vcpu_run)
|
||||
VM_CLEAR_CPU_BUFFERS
|
||||
|
||||
/* Enter guest mode */
|
||||
sti
|
||||
|
||||
1: vmrun %_ASM_AX
|
||||
|
||||
2: cli
|
||||
2:
|
||||
|
||||
/* Pop @svm to RDI, guest registers have been saved already. */
|
||||
pop %_ASM_DI
|
||||
|
||||
@@ -15,20 +15,23 @@
|
||||
* Tracepoint for guest mode entry.
|
||||
*/
|
||||
TRACE_EVENT(kvm_entry,
|
||||
TP_PROTO(struct kvm_vcpu *vcpu),
|
||||
TP_ARGS(vcpu),
|
||||
TP_PROTO(struct kvm_vcpu *vcpu, bool force_immediate_exit),
|
||||
TP_ARGS(vcpu, force_immediate_exit),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field( unsigned int, vcpu_id )
|
||||
__field( unsigned long, rip )
|
||||
__field( bool, immediate_exit )
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->vcpu_id = vcpu->vcpu_id;
|
||||
__entry->rip = kvm_rip_read(vcpu);
|
||||
__entry->immediate_exit = force_immediate_exit;
|
||||
),
|
||||
|
||||
TP_printk("vcpu %u, rip 0x%lx", __entry->vcpu_id, __entry->rip)
|
||||
TP_printk("vcpu %u, rip 0x%lx%s", __entry->vcpu_id, __entry->rip,
|
||||
__entry->immediate_exit ? "[immediate exit]" : "")
|
||||
);
|
||||
|
||||
/*
|
||||
|
||||
@@ -2564,10 +2564,11 @@ static int prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12,
|
||||
if (vmx->nested.nested_run_pending &&
|
||||
(vmcs12->vm_entry_controls & VM_ENTRY_LOAD_DEBUG_CONTROLS)) {
|
||||
kvm_set_dr(vcpu, 7, vmcs12->guest_dr7);
|
||||
vmcs_write64(GUEST_IA32_DEBUGCTL, vmcs12->guest_ia32_debugctl);
|
||||
vmx_guest_debugctl_write(vcpu, vmcs12->guest_ia32_debugctl &
|
||||
vmx_get_supported_debugctl(vcpu, false));
|
||||
} else {
|
||||
kvm_set_dr(vcpu, 7, vcpu->arch.dr7);
|
||||
vmcs_write64(GUEST_IA32_DEBUGCTL, vmx->nested.pre_vmenter_debugctl);
|
||||
vmx_guest_debugctl_write(vcpu, vmx->nested.pre_vmenter_debugctl);
|
||||
}
|
||||
if (kvm_mpx_supported() && (!vmx->nested.nested_run_pending ||
|
||||
!(vmcs12->vm_entry_controls & VM_ENTRY_LOAD_BNDCFGS)))
|
||||
@@ -3045,7 +3046,8 @@ static int nested_vmx_check_guest_state(struct kvm_vcpu *vcpu,
|
||||
return -EINVAL;
|
||||
|
||||
if ((vmcs12->vm_entry_controls & VM_ENTRY_LOAD_DEBUG_CONTROLS) &&
|
||||
CC(!kvm_dr7_valid(vmcs12->guest_dr7)))
|
||||
(CC(!kvm_dr7_valid(vmcs12->guest_dr7)) ||
|
||||
CC(!vmx_is_valid_debugctl(vcpu, vmcs12->guest_ia32_debugctl, false))))
|
||||
return -EINVAL;
|
||||
|
||||
if ((vmcs12->vm_entry_controls & VM_ENTRY_LOAD_IA32_PAT) &&
|
||||
@@ -3431,7 +3433,7 @@ enum nvmx_vmentry_status nested_vmx_enter_non_root_mode(struct kvm_vcpu *vcpu,
|
||||
|
||||
if (!vmx->nested.nested_run_pending ||
|
||||
!(vmcs12->vm_entry_controls & VM_ENTRY_LOAD_DEBUG_CONTROLS))
|
||||
vmx->nested.pre_vmenter_debugctl = vmcs_read64(GUEST_IA32_DEBUGCTL);
|
||||
vmx->nested.pre_vmenter_debugctl = vmx_guest_debugctl_read();
|
||||
if (kvm_mpx_supported() &&
|
||||
(!vmx->nested.nested_run_pending ||
|
||||
!(vmcs12->vm_entry_controls & VM_ENTRY_LOAD_BNDCFGS)))
|
||||
@@ -4435,6 +4437,12 @@ static void sync_vmcs02_to_vmcs12(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12)
|
||||
(vmcs12->vm_entry_controls & ~VM_ENTRY_IA32E_MODE) |
|
||||
(vm_entry_controls_get(to_vmx(vcpu)) & VM_ENTRY_IA32E_MODE);
|
||||
|
||||
/*
|
||||
* Note! Save DR7, but intentionally don't grab DEBUGCTL from vmcs02.
|
||||
* Writes to DEBUGCTL that aren't intercepted by L1 are immediately
|
||||
* propagated to vmcs12 (see vmx_set_msr()), as the value loaded into
|
||||
* vmcs02 doesn't strictly track vmcs12.
|
||||
*/
|
||||
if (vmcs12->vm_exit_controls & VM_EXIT_SAVE_DEBUG_CONTROLS)
|
||||
kvm_get_dr(vcpu, 7, (unsigned long *)&vmcs12->guest_dr7);
|
||||
|
||||
@@ -4625,7 +4633,7 @@ static void load_vmcs12_host_state(struct kvm_vcpu *vcpu,
|
||||
__vmx_set_segment(vcpu, &seg, VCPU_SREG_LDTR);
|
||||
|
||||
kvm_set_dr(vcpu, 7, 0x400);
|
||||
vmcs_write64(GUEST_IA32_DEBUGCTL, 0);
|
||||
vmx_guest_debugctl_write(vcpu, 0);
|
||||
|
||||
if (nested_vmx_load_msr(vcpu, vmcs12->vm_exit_msr_load_addr,
|
||||
vmcs12->vm_exit_msr_load_count))
|
||||
@@ -4680,6 +4688,9 @@ static void nested_vmx_restore_host_state(struct kvm_vcpu *vcpu)
|
||||
WARN_ON(kvm_set_dr(vcpu, 7, vmcs_readl(GUEST_DR7)));
|
||||
}
|
||||
|
||||
/* Reload DEBUGCTL to ensure vmcs01 has a fresh FREEZE_IN_SMM value. */
|
||||
vmx_reload_guest_debugctl(vcpu);
|
||||
|
||||
/*
|
||||
* Note that calling vmx_set_{efer,cr0,cr4} is important as they
|
||||
* handle a variety of side effects to KVM's software model.
|
||||
@@ -4900,6 +4911,11 @@ void nested_vmx_vmexit(struct kvm_vcpu *vcpu, u32 vm_exit_reason,
|
||||
kvm_make_request(KVM_REQ_APICV_UPDATE, vcpu);
|
||||
}
|
||||
|
||||
if (vmx->nested.update_vmcs01_hwapic_isr) {
|
||||
vmx->nested.update_vmcs01_hwapic_isr = false;
|
||||
kvm_apic_update_hwapic_isr(vcpu);
|
||||
}
|
||||
|
||||
if ((vm_exit_reason != -1) &&
|
||||
(enable_shadow_vmcs || evmptr_is_valid(vmx->nested.hv_evmcs_vmptr)))
|
||||
vmx->nested.need_vmcs12_to_shadow_sync = true;
|
||||
|
||||
@@ -633,11 +633,11 @@ static void intel_pmu_reset(struct kvm_vcpu *vcpu)
|
||||
*/
|
||||
static void intel_pmu_legacy_freezing_lbrs_on_pmi(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
u64 data = vmcs_read64(GUEST_IA32_DEBUGCTL);
|
||||
u64 data = vmx_guest_debugctl_read();
|
||||
|
||||
if (data & DEBUGCTLMSR_FREEZE_LBRS_ON_PMI) {
|
||||
data &= ~DEBUGCTLMSR_LBR;
|
||||
vmcs_write64(GUEST_IA32_DEBUGCTL, data);
|
||||
vmx_guest_debugctl_write(vcpu, data);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -707,7 +707,7 @@ void vmx_passthrough_lbr_msrs(struct kvm_vcpu *vcpu)
|
||||
|
||||
if (!lbr_desc->event) {
|
||||
vmx_disable_lbr_msrs_passthrough(vcpu);
|
||||
if (vmcs_read64(GUEST_IA32_DEBUGCTL) & DEBUGCTLMSR_LBR)
|
||||
if (vmx_guest_debugctl_read() & DEBUGCTLMSR_LBR)
|
||||
goto warn;
|
||||
if (test_bit(INTEL_PMC_IDX_FIXED_VLBR, pmu->pmc_in_use))
|
||||
goto warn;
|
||||
@@ -729,7 +729,7 @@ warn:
|
||||
|
||||
static void intel_pmu_cleanup(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
if (!(vmcs_read64(GUEST_IA32_DEBUGCTL) & DEBUGCTLMSR_LBR))
|
||||
if (!(vmx_guest_debugctl_read() & DEBUGCTLMSR_LBR))
|
||||
intel_pmu_release_guest_lbr_event(vcpu);
|
||||
}
|
||||
|
||||
|
||||
@@ -49,6 +49,8 @@
|
||||
#include <asm/spec-ctrl.h>
|
||||
#include <asm/vmx.h>
|
||||
|
||||
#include <trace/events/ipi.h>
|
||||
|
||||
#include "capabilities.h"
|
||||
#include "cpuid.h"
|
||||
#include "hyperv.h"
|
||||
@@ -1304,8 +1306,6 @@ void vmx_prepare_switch_to_guest(struct kvm_vcpu *vcpu)
|
||||
u16 fs_sel, gs_sel;
|
||||
int i;
|
||||
|
||||
vmx->req_immediate_exit = false;
|
||||
|
||||
/*
|
||||
* Note that guest MSRs to be saved/restored can also be changed
|
||||
* when guest state is loaded. This happens when guest transitions
|
||||
@@ -1499,13 +1499,9 @@ void vmx_vcpu_load_vmcs(struct kvm_vcpu *vcpu, int cpu,
|
||||
*/
|
||||
static void vmx_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
|
||||
{
|
||||
struct vcpu_vmx *vmx = to_vmx(vcpu);
|
||||
|
||||
vmx_vcpu_load_vmcs(vcpu, cpu, NULL);
|
||||
|
||||
vmx_vcpu_pi_load(vcpu, cpu);
|
||||
|
||||
vmx->host_debugctlmsr = get_debugctlmsr();
|
||||
}
|
||||
|
||||
static void vmx_vcpu_put(struct kvm_vcpu *vcpu)
|
||||
@@ -2128,7 +2124,7 @@ static int vmx_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
|
||||
msr_info->data = vmx->pt_desc.guest.addr_a[index / 2];
|
||||
break;
|
||||
case MSR_IA32_DEBUGCTLMSR:
|
||||
msr_info->data = vmcs_read64(GUEST_IA32_DEBUGCTL);
|
||||
msr_info->data = vmx_guest_debugctl_read();
|
||||
break;
|
||||
default:
|
||||
find_uret_msr:
|
||||
@@ -2153,7 +2149,7 @@ static u64 nested_vmx_truncate_sysenter_addr(struct kvm_vcpu *vcpu,
|
||||
return (unsigned long)data;
|
||||
}
|
||||
|
||||
static u64 vmx_get_supported_debugctl(struct kvm_vcpu *vcpu, bool host_initiated)
|
||||
u64 vmx_get_supported_debugctl(struct kvm_vcpu *vcpu, bool host_initiated)
|
||||
{
|
||||
u64 debugctl = 0;
|
||||
|
||||
@@ -2165,9 +2161,25 @@ static u64 vmx_get_supported_debugctl(struct kvm_vcpu *vcpu, bool host_initiated
|
||||
(host_initiated || intel_pmu_lbr_is_enabled(vcpu)))
|
||||
debugctl |= DEBUGCTLMSR_LBR | DEBUGCTLMSR_FREEZE_LBRS_ON_PMI;
|
||||
|
||||
if (boot_cpu_has(X86_FEATURE_RTM) &&
|
||||
(host_initiated || guest_cpuid_has(vcpu, X86_FEATURE_RTM)))
|
||||
debugctl |= DEBUGCTLMSR_RTM_DEBUG;
|
||||
|
||||
return debugctl;
|
||||
}
|
||||
|
||||
bool vmx_is_valid_debugctl(struct kvm_vcpu *vcpu, u64 data, bool host_initiated)
|
||||
{
|
||||
u64 invalid;
|
||||
|
||||
invalid = data & ~vmx_get_supported_debugctl(vcpu, host_initiated);
|
||||
if (invalid & (DEBUGCTLMSR_BTF | DEBUGCTLMSR_LBR)) {
|
||||
kvm_pr_unimpl_wrmsr(vcpu, MSR_IA32_DEBUGCTLMSR, data);
|
||||
invalid &= ~(DEBUGCTLMSR_BTF | DEBUGCTLMSR_LBR);
|
||||
}
|
||||
return !invalid;
|
||||
}
|
||||
|
||||
/*
|
||||
* Writes msr value into the appropriate "register".
|
||||
* Returns 0 on success, non-0 otherwise.
|
||||
@@ -2236,29 +2248,22 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
|
||||
}
|
||||
vmcs_writel(GUEST_SYSENTER_ESP, data);
|
||||
break;
|
||||
case MSR_IA32_DEBUGCTLMSR: {
|
||||
u64 invalid;
|
||||
|
||||
invalid = data & ~vmx_get_supported_debugctl(vcpu, msr_info->host_initiated);
|
||||
if (invalid & (DEBUGCTLMSR_BTF|DEBUGCTLMSR_LBR)) {
|
||||
kvm_pr_unimpl_wrmsr(vcpu, msr_index, data);
|
||||
data &= ~(DEBUGCTLMSR_BTF|DEBUGCTLMSR_LBR);
|
||||
invalid &= ~(DEBUGCTLMSR_BTF|DEBUGCTLMSR_LBR);
|
||||
}
|
||||
|
||||
if (invalid)
|
||||
case MSR_IA32_DEBUGCTLMSR:
|
||||
if (!vmx_is_valid_debugctl(vcpu, data, msr_info->host_initiated))
|
||||
return 1;
|
||||
|
||||
data &= vmx_get_supported_debugctl(vcpu, msr_info->host_initiated);
|
||||
|
||||
if (is_guest_mode(vcpu) && get_vmcs12(vcpu)->vm_exit_controls &
|
||||
VM_EXIT_SAVE_DEBUG_CONTROLS)
|
||||
get_vmcs12(vcpu)->guest_ia32_debugctl = data;
|
||||
|
||||
vmcs_write64(GUEST_IA32_DEBUGCTL, data);
|
||||
vmx_guest_debugctl_write(vcpu, data);
|
||||
|
||||
if (intel_pmu_lbr_is_enabled(vcpu) && !to_vmx(vcpu)->lbr_desc.event &&
|
||||
(data & DEBUGCTLMSR_LBR))
|
||||
intel_pmu_create_guest_lbr_event(vcpu);
|
||||
return 0;
|
||||
}
|
||||
case MSR_IA32_BNDCFGS:
|
||||
if (!kvm_mpx_supported() ||
|
||||
(!msr_info->host_initiated &&
|
||||
@@ -4822,7 +4827,8 @@ static void init_vmcs(struct vcpu_vmx *vmx)
|
||||
vmcs_write32(GUEST_SYSENTER_CS, 0);
|
||||
vmcs_writel(GUEST_SYSENTER_ESP, 0);
|
||||
vmcs_writel(GUEST_SYSENTER_EIP, 0);
|
||||
vmcs_write64(GUEST_IA32_DEBUGCTL, 0);
|
||||
|
||||
vmx_guest_debugctl_write(&vmx->vcpu, 0);
|
||||
|
||||
if (cpu_has_vmx_tpr_shadow()) {
|
||||
vmcs_write64(VIRTUAL_APIC_PAGE_ADDR, 0);
|
||||
@@ -5620,12 +5626,6 @@ static void vmx_sync_dirty_debug_regs(struct kvm_vcpu *vcpu)
|
||||
set_debugreg(DR6_RESERVED, 6);
|
||||
}
|
||||
|
||||
static void vmx_set_dr6(struct kvm_vcpu *vcpu, unsigned long val)
|
||||
{
|
||||
lockdep_assert_irqs_disabled();
|
||||
set_debugreg(vcpu->arch.dr6, 6);
|
||||
}
|
||||
|
||||
static void vmx_set_dr7(struct kvm_vcpu *vcpu, unsigned long val)
|
||||
{
|
||||
vmcs_writel(GUEST_DR7, val);
|
||||
@@ -6019,22 +6019,46 @@ static int handle_pml_full(struct kvm_vcpu *vcpu)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static fastpath_t handle_fastpath_preemption_timer(struct kvm_vcpu *vcpu)
|
||||
static fastpath_t handle_fastpath_preemption_timer(struct kvm_vcpu *vcpu,
|
||||
bool force_immediate_exit)
|
||||
{
|
||||
struct vcpu_vmx *vmx = to_vmx(vcpu);
|
||||
|
||||
if (!vmx->req_immediate_exit &&
|
||||
!unlikely(vmx->loaded_vmcs->hv_timer_soft_disabled)) {
|
||||
kvm_lapic_expired_hv_timer(vcpu);
|
||||
/*
|
||||
* In the *extremely* unlikely scenario that this is a spurious VM-Exit
|
||||
* due to the timer expiring while it was "soft" disabled, just eat the
|
||||
* exit and re-enter the guest.
|
||||
*/
|
||||
if (unlikely(vmx->loaded_vmcs->hv_timer_soft_disabled))
|
||||
return EXIT_FASTPATH_REENTER_GUEST;
|
||||
}
|
||||
|
||||
return EXIT_FASTPATH_NONE;
|
||||
/*
|
||||
* If the timer expired because KVM used it to force an immediate exit,
|
||||
* then mission accomplished.
|
||||
*/
|
||||
if (force_immediate_exit)
|
||||
return EXIT_FASTPATH_EXIT_HANDLED;
|
||||
|
||||
/*
|
||||
* If L2 is active, go down the slow path as emulating the guest timer
|
||||
* expiration likely requires synthesizing a nested VM-Exit.
|
||||
*/
|
||||
if (is_guest_mode(vcpu))
|
||||
return EXIT_FASTPATH_NONE;
|
||||
|
||||
kvm_lapic_expired_hv_timer(vcpu);
|
||||
return EXIT_FASTPATH_REENTER_GUEST;
|
||||
}
|
||||
|
||||
static int handle_preemption_timer(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
handle_fastpath_preemption_timer(vcpu);
|
||||
/*
|
||||
* This non-fastpath handler is reached if and only if the preemption
|
||||
* timer was being used to emulate a guest timer while L2 is active.
|
||||
* All other scenarios are supposed to be handled in the fastpath.
|
||||
*/
|
||||
WARN_ON_ONCE(!is_guest_mode(vcpu));
|
||||
kvm_lapic_expired_hv_timer(vcpu);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -6834,11 +6858,27 @@ out:
|
||||
kvm_release_pfn_clean(pfn);
|
||||
}
|
||||
|
||||
static void vmx_hwapic_isr_update(int max_isr)
|
||||
static void vmx_hwapic_isr_update(struct kvm_vcpu *vcpu, int max_isr)
|
||||
{
|
||||
u16 status;
|
||||
u8 old;
|
||||
|
||||
/*
|
||||
* If L2 is active, defer the SVI update until vmcs01 is loaded, as SVI
|
||||
* is only relevant for if and only if Virtual Interrupt Delivery is
|
||||
* enabled in vmcs12, and if VID is enabled then L2 EOIs affect L2's
|
||||
* vAPIC, not L1's vAPIC. KVM must update vmcs01 on the next nested
|
||||
* VM-Exit, otherwise L1 with run with a stale SVI.
|
||||
*/
|
||||
if (is_guest_mode(vcpu)) {
|
||||
/*
|
||||
* KVM is supposed to forward intercepted L2 EOIs to L1 if VID
|
||||
* is enabled in vmcs12; as above, the EOIs affect L2's vAPIC.
|
||||
*/
|
||||
to_vmx(vcpu)->nested.update_vmcs01_hwapic_isr = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (max_isr == -1)
|
||||
max_isr = 0;
|
||||
|
||||
@@ -7175,13 +7215,13 @@ static void atomic_switch_perf_msrs(struct vcpu_vmx *vmx)
|
||||
msrs[i].host, false);
|
||||
}
|
||||
|
||||
static void vmx_update_hv_timer(struct kvm_vcpu *vcpu)
|
||||
static void vmx_update_hv_timer(struct kvm_vcpu *vcpu, bool force_immediate_exit)
|
||||
{
|
||||
struct vcpu_vmx *vmx = to_vmx(vcpu);
|
||||
u64 tscl;
|
||||
u32 delta_tsc;
|
||||
|
||||
if (vmx->req_immediate_exit) {
|
||||
if (force_immediate_exit) {
|
||||
vmcs_write32(VMX_PREEMPTION_TIMER_VALUE, 0);
|
||||
vmx->loaded_vmcs->hv_timer_soft_disabled = false;
|
||||
} else if (vmx->hv_deadline_tsc != -1) {
|
||||
@@ -7234,13 +7274,22 @@ void noinstr vmx_spec_ctrl_restore_host(struct vcpu_vmx *vmx,
|
||||
barrier_nospec();
|
||||
}
|
||||
|
||||
static fastpath_t vmx_exit_handlers_fastpath(struct kvm_vcpu *vcpu)
|
||||
static fastpath_t vmx_exit_handlers_fastpath(struct kvm_vcpu *vcpu,
|
||||
bool force_immediate_exit)
|
||||
{
|
||||
/*
|
||||
* If L2 is active, some VMX preemption timer exits can be handled in
|
||||
* the fastpath even, all other exits must use the slow path.
|
||||
*/
|
||||
if (is_guest_mode(vcpu) &&
|
||||
to_vmx(vcpu)->exit_reason.basic != EXIT_REASON_PREEMPTION_TIMER)
|
||||
return EXIT_FASTPATH_NONE;
|
||||
|
||||
switch (to_vmx(vcpu)->exit_reason.basic) {
|
||||
case EXIT_REASON_MSR_WRITE:
|
||||
return handle_fastpath_set_msr_irqoff(vcpu);
|
||||
case EXIT_REASON_PREEMPTION_TIMER:
|
||||
return handle_fastpath_preemption_timer(vcpu);
|
||||
return handle_fastpath_preemption_timer(vcpu, force_immediate_exit);
|
||||
default:
|
||||
return EXIT_FASTPATH_NONE;
|
||||
}
|
||||
@@ -7300,8 +7349,9 @@ out:
|
||||
guest_state_exit_irqoff();
|
||||
}
|
||||
|
||||
static fastpath_t vmx_vcpu_run(struct kvm_vcpu *vcpu)
|
||||
static fastpath_t vmx_vcpu_run(struct kvm_vcpu *vcpu, u64 run_flags)
|
||||
{
|
||||
bool force_immediate_exit = run_flags & KVM_RUN_FORCE_IMMEDIATE_EXIT;
|
||||
struct vcpu_vmx *vmx = to_vmx(vcpu);
|
||||
unsigned long cr3, cr4;
|
||||
|
||||
@@ -7327,7 +7377,7 @@ static fastpath_t vmx_vcpu_run(struct kvm_vcpu *vcpu)
|
||||
return EXIT_FASTPATH_NONE;
|
||||
}
|
||||
|
||||
trace_kvm_entry(vcpu);
|
||||
trace_kvm_entry(vcpu, force_immediate_exit);
|
||||
|
||||
if (vmx->ple_window_dirty) {
|
||||
vmx->ple_window_dirty = false;
|
||||
@@ -7346,6 +7396,12 @@ static fastpath_t vmx_vcpu_run(struct kvm_vcpu *vcpu)
|
||||
vmcs_writel(GUEST_RIP, vcpu->arch.regs[VCPU_REGS_RIP]);
|
||||
vcpu->arch.regs_dirty = 0;
|
||||
|
||||
if (run_flags & KVM_RUN_LOAD_GUEST_DR6)
|
||||
set_debugreg(vcpu->arch.dr6, 6);
|
||||
|
||||
if (run_flags & KVM_RUN_LOAD_DEBUGCTL)
|
||||
vmx_reload_guest_debugctl(vcpu);
|
||||
|
||||
/*
|
||||
* Refresh vmcs.HOST_CR3 if necessary. This must be done immediately
|
||||
* prior to VM-Enter, as the kernel may load a new ASID (PCID) any time
|
||||
@@ -7382,7 +7438,9 @@ static fastpath_t vmx_vcpu_run(struct kvm_vcpu *vcpu)
|
||||
vmx_passthrough_lbr_msrs(vcpu);
|
||||
|
||||
if (enable_preemption_timer)
|
||||
vmx_update_hv_timer(vcpu);
|
||||
vmx_update_hv_timer(vcpu, force_immediate_exit);
|
||||
else if (force_immediate_exit)
|
||||
smp_send_reschedule(vcpu->cpu);
|
||||
|
||||
kvm_wait_lapic_expire(vcpu);
|
||||
|
||||
@@ -7398,8 +7456,8 @@ static fastpath_t vmx_vcpu_run(struct kvm_vcpu *vcpu)
|
||||
}
|
||||
|
||||
/* MSR_IA32_DEBUGCTLMSR is zeroed on vmexit. Restore it if needed */
|
||||
if (vmx->host_debugctlmsr)
|
||||
update_debugctlmsr(vmx->host_debugctlmsr);
|
||||
if (vcpu->arch.host_debugctl)
|
||||
update_debugctlmsr(vcpu->arch.host_debugctl);
|
||||
|
||||
#ifndef CONFIG_X86_64
|
||||
/*
|
||||
@@ -7446,10 +7504,7 @@ static fastpath_t vmx_vcpu_run(struct kvm_vcpu *vcpu)
|
||||
vmx_recover_nmi_blocking(vmx);
|
||||
vmx_complete_interrupts(vmx);
|
||||
|
||||
if (is_guest_mode(vcpu))
|
||||
return EXIT_FASTPATH_NONE;
|
||||
|
||||
return vmx_exit_handlers_fastpath(vcpu);
|
||||
return vmx_exit_handlers_fastpath(vcpu, force_immediate_exit);
|
||||
}
|
||||
|
||||
static void vmx_vcpu_free(struct kvm_vcpu *vcpu)
|
||||
@@ -7948,11 +8003,6 @@ static __init void vmx_set_cpu_caps(void)
|
||||
kvm_cpu_cap_check_and_set(X86_FEATURE_WAITPKG);
|
||||
}
|
||||
|
||||
static void vmx_request_immediate_exit(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
to_vmx(vcpu)->req_immediate_exit = true;
|
||||
}
|
||||
|
||||
static int vmx_check_intercept_io(struct kvm_vcpu *vcpu,
|
||||
struct x86_instruction_info *info)
|
||||
{
|
||||
@@ -8279,6 +8329,8 @@ static struct kvm_x86_ops vmx_x86_ops __initdata = {
|
||||
.vcpu_load = vmx_vcpu_load,
|
||||
.vcpu_put = vmx_vcpu_put,
|
||||
|
||||
.HOST_OWNED_DEBUGCTL = DEBUGCTLMSR_FREEZE_IN_SMM,
|
||||
|
||||
.update_exception_bitmap = vmx_update_exception_bitmap,
|
||||
.get_msr_feature = vmx_get_msr_feature,
|
||||
.get_msr = vmx_get_msr,
|
||||
@@ -8297,7 +8349,6 @@ static struct kvm_x86_ops vmx_x86_ops __initdata = {
|
||||
.set_idt = vmx_set_idt,
|
||||
.get_gdt = vmx_get_gdt,
|
||||
.set_gdt = vmx_set_gdt,
|
||||
.set_dr6 = vmx_set_dr6,
|
||||
.set_dr7 = vmx_set_dr7,
|
||||
.sync_dirty_debug_regs = vmx_sync_dirty_debug_regs,
|
||||
.cache_reg = vmx_cache_reg,
|
||||
@@ -8364,8 +8415,6 @@ static struct kvm_x86_ops vmx_x86_ops __initdata = {
|
||||
.check_intercept = vmx_check_intercept,
|
||||
.handle_exit_irqoff = vmx_handle_exit_irqoff,
|
||||
|
||||
.request_immediate_exit = vmx_request_immediate_exit,
|
||||
|
||||
.sched_in = vmx_sched_in,
|
||||
|
||||
.cpu_dirty_log_size = PML_ENTITY_NUM,
|
||||
@@ -8623,7 +8672,6 @@ static __init int hardware_setup(void)
|
||||
if (!enable_preemption_timer) {
|
||||
vmx_x86_ops.set_hv_timer = NULL;
|
||||
vmx_x86_ops.cancel_hv_timer = NULL;
|
||||
vmx_x86_ops.request_immediate_exit = __kvm_request_immediate_exit;
|
||||
}
|
||||
|
||||
kvm_caps.supported_mce_cap |= MCG_LMCE_P;
|
||||
|
||||
@@ -177,6 +177,7 @@ struct nested_vmx {
|
||||
bool reload_vmcs01_apic_access_page;
|
||||
bool update_vmcs01_cpu_dirty_logging;
|
||||
bool update_vmcs01_apicv_status;
|
||||
bool update_vmcs01_hwapic_isr;
|
||||
|
||||
/*
|
||||
* Enlightened VMCS has been enabled. It does not mean that L1 has to
|
||||
@@ -330,8 +331,6 @@ struct vcpu_vmx {
|
||||
unsigned int ple_window;
|
||||
bool ple_window_dirty;
|
||||
|
||||
bool req_immediate_exit;
|
||||
|
||||
/* Support for PML */
|
||||
#define PML_ENTITY_NUM 512
|
||||
struct page *pml_pg;
|
||||
@@ -339,8 +338,6 @@ struct vcpu_vmx {
|
||||
/* apic deadline value in host tsc */
|
||||
u64 hv_deadline_tsc;
|
||||
|
||||
unsigned long host_debugctlmsr;
|
||||
|
||||
/*
|
||||
* Only bits masked by msr_ia32_feature_control_valid_bits can be set in
|
||||
* msr_ia32_feature_control. FEAT_CTL_LOCKED is always included
|
||||
@@ -432,6 +429,32 @@ static inline void vmx_set_intercept_for_msr(struct kvm_vcpu *vcpu, u32 msr,
|
||||
|
||||
void vmx_update_cpu_dirty_logging(struct kvm_vcpu *vcpu);
|
||||
|
||||
u64 vmx_get_supported_debugctl(struct kvm_vcpu *vcpu, bool host_initiated);
|
||||
bool vmx_is_valid_debugctl(struct kvm_vcpu *vcpu, u64 data, bool host_initiated);
|
||||
|
||||
static inline void vmx_guest_debugctl_write(struct kvm_vcpu *vcpu, u64 val)
|
||||
{
|
||||
WARN_ON_ONCE(val & DEBUGCTLMSR_FREEZE_IN_SMM);
|
||||
|
||||
val |= vcpu->arch.host_debugctl & DEBUGCTLMSR_FREEZE_IN_SMM;
|
||||
vmcs_write64(GUEST_IA32_DEBUGCTL, val);
|
||||
}
|
||||
|
||||
static inline u64 vmx_guest_debugctl_read(void)
|
||||
{
|
||||
return vmcs_read64(GUEST_IA32_DEBUGCTL) & ~DEBUGCTLMSR_FREEZE_IN_SMM;
|
||||
}
|
||||
|
||||
static inline void vmx_reload_guest_debugctl(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
u64 val = vmcs_read64(GUEST_IA32_DEBUGCTL);
|
||||
|
||||
if (!((val ^ vcpu->arch.host_debugctl) & DEBUGCTLMSR_FREEZE_IN_SMM))
|
||||
return;
|
||||
|
||||
vmx_guest_debugctl_write(vcpu, val & ~DEBUGCTLMSR_FREEZE_IN_SMM);
|
||||
}
|
||||
|
||||
/*
|
||||
* Note, early Intel manuals have the write-low and read-high bitmap offsets
|
||||
* the wrong way round. The bitmaps control MSRs 0x00000000-0x00001fff and
|
||||
|
||||
@@ -10505,12 +10505,6 @@ static void kvm_vcpu_reload_apic_access_page(struct kvm_vcpu *vcpu)
|
||||
static_call_cond(kvm_x86_set_apic_access_page_addr)(vcpu);
|
||||
}
|
||||
|
||||
void __kvm_request_immediate_exit(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
smp_send_reschedule(vcpu->cpu);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__kvm_request_immediate_exit);
|
||||
|
||||
/*
|
||||
* Called within kvm->srcu read side.
|
||||
* Returns 1 to let vcpu_run() continue the guest execution loop without
|
||||
@@ -10524,6 +10518,7 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
|
||||
dm_request_for_irq_injection(vcpu) &&
|
||||
kvm_cpu_accept_dm_intr(vcpu);
|
||||
fastpath_t exit_fastpath;
|
||||
u64 run_flags, debug_ctl;
|
||||
|
||||
bool req_immediate_exit = false;
|
||||
|
||||
@@ -10756,9 +10751,10 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
|
||||
goto cancel_injection;
|
||||
}
|
||||
|
||||
run_flags = 0;
|
||||
if (req_immediate_exit) {
|
||||
run_flags |= KVM_RUN_FORCE_IMMEDIATE_EXIT;
|
||||
kvm_make_request(KVM_REQ_EVENT, vcpu);
|
||||
static_call(kvm_x86_request_immediate_exit)(vcpu);
|
||||
}
|
||||
|
||||
fpregs_assert_state_consistent();
|
||||
@@ -10776,11 +10772,23 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
|
||||
set_debugreg(vcpu->arch.eff_db[3], 3);
|
||||
/* When KVM_DEBUGREG_WONT_EXIT, dr6 is accessible in guest. */
|
||||
if (unlikely(vcpu->arch.switch_db_regs & KVM_DEBUGREG_WONT_EXIT))
|
||||
static_call(kvm_x86_set_dr6)(vcpu, vcpu->arch.dr6);
|
||||
run_flags |= KVM_RUN_LOAD_GUEST_DR6;
|
||||
} else if (unlikely(hw_breakpoint_active())) {
|
||||
set_debugreg(0, 7);
|
||||
}
|
||||
|
||||
/*
|
||||
* Refresh the host DEBUGCTL snapshot after disabling IRQs, as DEBUGCTL
|
||||
* can be modified in IRQ context, e.g. via SMP function calls. Inform
|
||||
* vendor code if any host-owned bits were changed, e.g. so that the
|
||||
* value loaded into hardware while running the guest can be updated.
|
||||
*/
|
||||
debug_ctl = get_debugctlmsr();
|
||||
if ((debug_ctl ^ vcpu->arch.host_debugctl) & kvm_x86_ops.HOST_OWNED_DEBUGCTL &&
|
||||
!vcpu->arch.guest_state_protected)
|
||||
run_flags |= KVM_RUN_LOAD_DEBUGCTL;
|
||||
vcpu->arch.host_debugctl = debug_ctl;
|
||||
|
||||
guest_timing_enter_irqoff();
|
||||
|
||||
for (;;) {
|
||||
@@ -10793,7 +10801,7 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
|
||||
WARN_ON_ONCE((kvm_vcpu_apicv_activated(vcpu) != kvm_vcpu_apicv_active(vcpu)) &&
|
||||
(kvm_get_apic_mode(vcpu) != LAPIC_MODE_DISABLED));
|
||||
|
||||
exit_fastpath = static_call(kvm_x86_vcpu_run)(vcpu);
|
||||
exit_fastpath = static_call(kvm_x86_vcpu_run)(vcpu, run_flags);
|
||||
if (likely(exit_fastpath != EXIT_FASTPATH_REENTER_GUEST))
|
||||
break;
|
||||
|
||||
@@ -10805,6 +10813,8 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
|
||||
break;
|
||||
}
|
||||
|
||||
run_flags = 0;
|
||||
|
||||
/* Note, VM-Exits that go down the "slow" path are accounted below. */
|
||||
++vcpu->stat.exits;
|
||||
}
|
||||
@@ -13256,16 +13266,22 @@ int kvm_arch_irq_bypass_add_producer(struct irq_bypass_consumer *cons,
|
||||
{
|
||||
struct kvm_kernel_irqfd *irqfd =
|
||||
container_of(cons, struct kvm_kernel_irqfd, consumer);
|
||||
struct kvm *kvm = irqfd->kvm;
|
||||
int ret;
|
||||
|
||||
irqfd->producer = prod;
|
||||
kvm_arch_start_assignment(irqfd->kvm);
|
||||
|
||||
spin_lock_irq(&kvm->irqfds.lock);
|
||||
irqfd->producer = prod;
|
||||
|
||||
ret = static_call(kvm_x86_pi_update_irte)(irqfd->kvm,
|
||||
prod->irq, irqfd->gsi, 1);
|
||||
|
||||
if (ret)
|
||||
kvm_arch_end_assignment(irqfd->kvm);
|
||||
|
||||
spin_unlock_irq(&kvm->irqfds.lock);
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -13275,9 +13291,9 @@ void kvm_arch_irq_bypass_del_producer(struct irq_bypass_consumer *cons,
|
||||
int ret;
|
||||
struct kvm_kernel_irqfd *irqfd =
|
||||
container_of(cons, struct kvm_kernel_irqfd, consumer);
|
||||
struct kvm *kvm = irqfd->kvm;
|
||||
|
||||
WARN_ON(irqfd->producer != prod);
|
||||
irqfd->producer = NULL;
|
||||
|
||||
/*
|
||||
* When producer of consumer is unregistered, we change back to
|
||||
@@ -13285,11 +13301,17 @@ void kvm_arch_irq_bypass_del_producer(struct irq_bypass_consumer *cons,
|
||||
* when the irq is masked/disabled or the consumer side (KVM
|
||||
* int this case doesn't want to receive the interrupts.
|
||||
*/
|
||||
spin_lock_irq(&kvm->irqfds.lock);
|
||||
irqfd->producer = NULL;
|
||||
|
||||
ret = static_call(kvm_x86_pi_update_irte)(irqfd->kvm, prod->irq, irqfd->gsi, 0);
|
||||
if (ret)
|
||||
printk(KERN_INFO "irq bypass consumer (token %p) unregistration"
|
||||
" fails: %d\n", irqfd->consumer.token, ret);
|
||||
|
||||
spin_unlock_irq(&kvm->irqfds.lock);
|
||||
|
||||
|
||||
kvm_arch_end_assignment(irqfd->kvm);
|
||||
}
|
||||
|
||||
|
||||
@@ -775,6 +775,15 @@ void submit_bio_noacct(struct bio *bio)
|
||||
bio_clear_polled(bio);
|
||||
|
||||
switch (bio_op(bio)) {
|
||||
case REQ_OP_READ:
|
||||
case REQ_OP_WRITE:
|
||||
break;
|
||||
case REQ_OP_FLUSH:
|
||||
/*
|
||||
* REQ_OP_FLUSH can't be submitted through bios, it is only
|
||||
* synthetized in struct request by the flush state machine.
|
||||
*/
|
||||
goto not_supported;
|
||||
case REQ_OP_DISCARD:
|
||||
if (!bdev_max_discard_sectors(bdev))
|
||||
goto not_supported;
|
||||
@@ -788,6 +797,10 @@ void submit_bio_noacct(struct bio *bio)
|
||||
if (status != BLK_STS_OK)
|
||||
goto end_io;
|
||||
break;
|
||||
case REQ_OP_WRITE_ZEROES:
|
||||
if (!q->limits.max_write_zeroes_sectors)
|
||||
goto not_supported;
|
||||
break;
|
||||
case REQ_OP_ZONE_RESET:
|
||||
case REQ_OP_ZONE_OPEN:
|
||||
case REQ_OP_ZONE_CLOSE:
|
||||
@@ -799,12 +812,15 @@ void submit_bio_noacct(struct bio *bio)
|
||||
if (!bdev_is_zoned(bio->bi_bdev) || !blk_queue_zone_resetall(q))
|
||||
goto not_supported;
|
||||
break;
|
||||
case REQ_OP_WRITE_ZEROES:
|
||||
if (!q->limits.max_write_zeroes_sectors)
|
||||
goto not_supported;
|
||||
break;
|
||||
case REQ_OP_DRV_IN:
|
||||
case REQ_OP_DRV_OUT:
|
||||
/*
|
||||
* Driver private operations are only used with passthrough
|
||||
* requests.
|
||||
*/
|
||||
fallthrough;
|
||||
default:
|
||||
break;
|
||||
goto not_supported;
|
||||
}
|
||||
|
||||
if (blk_throtl_bio(bio))
|
||||
|
||||
@@ -634,7 +634,7 @@ int blk_stack_limits(struct queue_limits *t, struct queue_limits *b,
|
||||
}
|
||||
|
||||
/* chunk_sectors a multiple of the physical block size? */
|
||||
if ((t->chunk_sectors << 9) & (t->physical_block_size - 1)) {
|
||||
if (t->chunk_sectors % (t->physical_block_size >> SECTOR_SHIFT)) {
|
||||
t->chunk_sectors = 0;
|
||||
t->misaligned = 1;
|
||||
ret = -1;
|
||||
|
||||
@@ -134,7 +134,7 @@ int jent_hash_time(void *hash_state, __u64 time, u8 *addtl,
|
||||
* Inject the data from the previous loop into the pool. This data is
|
||||
* not considered to contain any entropy, but it stirs the pool a bit.
|
||||
*/
|
||||
ret = crypto_shash_update(desc, intermediary, sizeof(intermediary));
|
||||
ret = crypto_shash_update(hash_state_desc, intermediary, sizeof(intermediary));
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
@@ -147,11 +147,12 @@ int jent_hash_time(void *hash_state, __u64 time, u8 *addtl,
|
||||
* conditioning operation to have an identical amount of input data
|
||||
* according to section 3.1.5.
|
||||
*/
|
||||
if (!stuck) {
|
||||
ret = crypto_shash_update(hash_state_desc, (u8 *)&time,
|
||||
sizeof(__u64));
|
||||
if (stuck) {
|
||||
time = 0;
|
||||
}
|
||||
|
||||
ret = crypto_shash_update(hash_state_desc, (u8 *)&time, sizeof(__u64));
|
||||
|
||||
err:
|
||||
shash_desc_zero(desc);
|
||||
memzero_explicit(intermediary, sizeof(intermediary));
|
||||
|
||||
@@ -250,7 +250,7 @@ static inline int acpi_processor_hotadd_init(struct acpi_processor *pr)
|
||||
|
||||
static int acpi_processor_get_info(struct acpi_device *device)
|
||||
{
|
||||
union acpi_object object = { 0 };
|
||||
union acpi_object object = { .processor = { 0 } };
|
||||
struct acpi_buffer buffer = { sizeof(union acpi_object), &object };
|
||||
struct acpi_processor *pr = acpi_driver_data(device);
|
||||
int device_declaration = 0;
|
||||
|
||||
@@ -715,6 +715,17 @@ static bool ghes_do_proc(struct ghes *ghes,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If no memory failure work is queued for abnormal synchronous
|
||||
* errors, do a force kill.
|
||||
*/
|
||||
if (sync && !queued) {
|
||||
dev_err(ghes->dev,
|
||||
HW_ERR GHES_PFX "%s:%d: synchronous unrecoverable error (SIGBUS)\n",
|
||||
current->comm, task_pid_nr(current));
|
||||
force_sig(SIGBUS);
|
||||
}
|
||||
|
||||
return queued;
|
||||
}
|
||||
|
||||
@@ -901,6 +912,8 @@ static void __ghes_panic(struct ghes *ghes,
|
||||
|
||||
__ghes_print_estatus(KERN_EMERG, ghes->generic, estatus);
|
||||
|
||||
add_taint(TAINT_MACHINE_CHECK, LOCKDEP_STILL_OK);
|
||||
|
||||
ghes_clear_estatus(ghes, estatus, buf_paddr, fixmap_idx);
|
||||
|
||||
if (!panic_timeout)
|
||||
|
||||
@@ -310,7 +310,7 @@ static bool applicable_image(const void *data, struct pfru_update_cap_info *cap,
|
||||
if (type == PFRU_CODE_INJECT_TYPE)
|
||||
return payload_hdr->rt_ver >= cap->code_rt_version;
|
||||
|
||||
return payload_hdr->rt_ver >= cap->drv_rt_version;
|
||||
return payload_hdr->svn_ver >= cap->drv_svn;
|
||||
}
|
||||
|
||||
static void print_update_debug_info(struct pfru_updated_result *result,
|
||||
|
||||
@@ -85,8 +85,6 @@ static u64 efi_pa_va_lookup(efi_guid_t *guid, u64 pa)
|
||||
}
|
||||
}
|
||||
|
||||
pr_warn("Failed to find VA for GUID: %pUL, PA: 0x%llx", guid, pa);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -154,13 +152,37 @@ acpi_parse_prmt(union acpi_subtable_headers *header, const unsigned long end)
|
||||
guid_copy(&th->guid, (guid_t *)handler_info->handler_guid);
|
||||
th->handler_addr =
|
||||
(void *)efi_pa_va_lookup(&th->guid, handler_info->handler_address);
|
||||
/*
|
||||
* Print a warning message if handler_addr is zero which is not expected to
|
||||
* ever happen.
|
||||
*/
|
||||
if (unlikely(!th->handler_addr))
|
||||
pr_warn("Failed to find VA of handler for GUID: %pUL, PA: 0x%llx",
|
||||
&th->guid, handler_info->handler_address);
|
||||
|
||||
th->static_data_buffer_addr =
|
||||
efi_pa_va_lookup(&th->guid, handler_info->static_data_buffer_address);
|
||||
/*
|
||||
* According to the PRM specification, static_data_buffer_address can be zero,
|
||||
* so avoid printing a warning message in that case. Otherwise, if the
|
||||
* return value of efi_pa_va_lookup() is zero, print the message.
|
||||
*/
|
||||
if (unlikely(!th->static_data_buffer_addr && handler_info->static_data_buffer_address))
|
||||
pr_warn("Failed to find VA of static data buffer for GUID: %pUL, PA: 0x%llx",
|
||||
&th->guid, handler_info->static_data_buffer_address);
|
||||
|
||||
th->acpi_param_buffer_addr =
|
||||
efi_pa_va_lookup(&th->guid, handler_info->acpi_param_buffer_address);
|
||||
|
||||
/*
|
||||
* According to the PRM specification, acpi_param_buffer_address can be zero,
|
||||
* so avoid printing a warning message in that case. Otherwise, if the
|
||||
* return value of efi_pa_va_lookup() is zero, print the message.
|
||||
*/
|
||||
if (unlikely(!th->acpi_param_buffer_addr && handler_info->acpi_param_buffer_address))
|
||||
pr_warn("Failed to find VA of acpi param buffer for GUID: %pUL, PA: 0x%llx",
|
||||
&th->guid, handler_info->acpi_param_buffer_address);
|
||||
|
||||
} while (++cur_handler < tm->handler_count && (handler_info = get_next_handler(handler_info)));
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -174,6 +174,9 @@ void acpi_processor_ppc_init(struct cpufreq_policy *policy)
|
||||
{
|
||||
unsigned int cpu;
|
||||
|
||||
if (ignore_ppc == 1)
|
||||
return;
|
||||
|
||||
for_each_cpu(cpu, policy->related_cpus) {
|
||||
struct acpi_processor *pr = per_cpu(processors, cpu);
|
||||
int ret;
|
||||
@@ -194,6 +197,14 @@ void acpi_processor_ppc_init(struct cpufreq_policy *policy)
|
||||
if (ret < 0)
|
||||
pr_err("Failed to add freq constraint for CPU%d (%d)\n",
|
||||
cpu, ret);
|
||||
|
||||
if (!pr->performance)
|
||||
continue;
|
||||
|
||||
ret = acpi_processor_get_platform_limit(pr);
|
||||
if (ret)
|
||||
pr_err("Failed to update freq constraint for CPU%d (%d)\n",
|
||||
cpu, ret);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -117,7 +117,7 @@ config SATA_AHCI
|
||||
|
||||
config SATA_MOBILE_LPM_POLICY
|
||||
int "Default SATA Link Power Management policy for low power chipsets"
|
||||
range 0 4
|
||||
range 0 5
|
||||
default 0
|
||||
depends on SATA_AHCI
|
||||
help
|
||||
@@ -126,15 +126,32 @@ config SATA_MOBILE_LPM_POLICY
|
||||
chipsets are typically found on most laptops but desktops and
|
||||
servers now also widely use chipsets supporting low power modes.
|
||||
|
||||
The value set has the following meanings:
|
||||
0 => Keep firmware settings
|
||||
1 => Maximum performance
|
||||
2 => Medium power
|
||||
3 => Medium power with Device Initiated PM enabled
|
||||
4 => Minimum power
|
||||
Each policy combines power saving states and features:
|
||||
- Partial: The Phy logic is powered but is in a reduced power
|
||||
state. The exit latency from this state is no longer than
|
||||
10us).
|
||||
- Slumber: The Phy logic is powered but is in an even lower power
|
||||
state. The exit latency from this state is potentially
|
||||
longer, but no longer than 10ms.
|
||||
- DevSleep: The Phy logic may be powered down. The exit latency from
|
||||
this state is no longer than 20 ms, unless otherwise
|
||||
specified by DETO in the device Identify Device Data log.
|
||||
- HIPM: Host Initiated Power Management (host automatically
|
||||
transitions to partial and slumber).
|
||||
- DIPM: Device Initiated Power Management (device automatically
|
||||
transitions to partial and slumber).
|
||||
|
||||
Note "Minimum power" is known to cause issues, including disk
|
||||
corruption, with some disks and should not be used.
|
||||
The possible values for the default SATA link power management
|
||||
policies are:
|
||||
0 => Keep firmware settings
|
||||
1 => No power savings (maximum performance)
|
||||
2 => HIPM (Partial)
|
||||
3 => HIPM (Partial) and DIPM (Partial and Slumber)
|
||||
4 => HIPM (Partial and DevSleep) and DIPM (Partial and Slumber)
|
||||
5 => HIPM (Slumber and DevSleep) and DIPM (Partial and Slumber)
|
||||
|
||||
Excluding the value 0, higher values represent policies with higher
|
||||
power savings.
|
||||
|
||||
config SATA_AHCI_PLATFORM
|
||||
tristate "Platform AHCI SATA support"
|
||||
|
||||
@@ -817,6 +817,11 @@ static ssize_t ata_scsi_lpm_store(struct device *device,
|
||||
|
||||
spin_lock_irqsave(ap->lock, flags);
|
||||
|
||||
if (ap->flags & ATA_FLAG_NO_LPM) {
|
||||
count = -EOPNOTSUPP;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
ata_for_each_link(link, ap, EDGE) {
|
||||
ata_for_each_dev(dev, &ap->link, ENABLED) {
|
||||
if (dev->horkage & ATA_HORKAGE_NOLPM) {
|
||||
|
||||
@@ -856,18 +856,14 @@ static void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk,
|
||||
{0xFF, 0xFF, 0xFF, 0xFF}, // END mark
|
||||
};
|
||||
static const unsigned char stat_table[][4] = {
|
||||
/* Must be first because BUSY means no other bits valid */
|
||||
{0x80, ABORTED_COMMAND, 0x47, 0x00},
|
||||
// Busy, fake parity for now
|
||||
{0x40, ILLEGAL_REQUEST, 0x21, 0x04},
|
||||
// Device ready, unaligned write command
|
||||
{0x20, HARDWARE_ERROR, 0x44, 0x00},
|
||||
// Device fault, internal target failure
|
||||
{0x08, ABORTED_COMMAND, 0x47, 0x00},
|
||||
// Timed out in xfer, fake parity for now
|
||||
{0x04, RECOVERED_ERROR, 0x11, 0x00},
|
||||
// Recovered ECC error Medium error, recovered
|
||||
{0xFF, 0xFF, 0xFF, 0xFF}, // END mark
|
||||
/* Busy: must be first because BUSY means no other bits valid */
|
||||
{ ATA_BUSY, ABORTED_COMMAND, 0x00, 0x00 },
|
||||
/* Device fault: INTERNAL TARGET FAILURE */
|
||||
{ ATA_DF, HARDWARE_ERROR, 0x44, 0x00 },
|
||||
/* Corrected data error */
|
||||
{ ATA_CORR, RECOVERED_ERROR, 0x00, 0x00 },
|
||||
|
||||
{ 0xFF, 0xFF, 0xFF, 0xFF }, /* END mark */
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -939,6 +935,8 @@ static void ata_gen_passthru_sense(struct ata_queued_cmd *qc)
|
||||
if (!(qc->flags & ATA_QCFLAG_RTF_FILLED)) {
|
||||
ata_dev_dbg(dev,
|
||||
"missing result TF: can't generate ATA PT sense data\n");
|
||||
if (qc->err_mask)
|
||||
ata_scsi_set_sense(dev, cmd, ABORTED_COMMAND, 0, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -996,8 +994,8 @@ static void ata_gen_ata_sense(struct ata_queued_cmd *qc)
|
||||
|
||||
if (!(qc->flags & ATA_QCFLAG_RTF_FILLED)) {
|
||||
ata_dev_dbg(dev,
|
||||
"missing result TF: can't generate sense data\n");
|
||||
return;
|
||||
"Missing result TF: reporting aborted command\n");
|
||||
goto aborted;
|
||||
}
|
||||
|
||||
/* Use ata_to_sense_error() to map status register bits
|
||||
@@ -1008,19 +1006,20 @@ static void ata_gen_ata_sense(struct ata_queued_cmd *qc)
|
||||
ata_to_sense_error(qc->ap->print_id, tf->status, tf->error,
|
||||
&sense_key, &asc, &ascq);
|
||||
ata_scsi_set_sense(dev, cmd, sense_key, asc, ascq);
|
||||
} else {
|
||||
/* Could not decode error */
|
||||
ata_dev_warn(dev, "could not decode error status 0x%x err_mask 0x%x\n",
|
||||
tf->status, qc->err_mask);
|
||||
ata_scsi_set_sense(dev, cmd, ABORTED_COMMAND, 0, 0);
|
||||
|
||||
block = ata_tf_read_block(&qc->result_tf, dev);
|
||||
if (block != U64_MAX)
|
||||
scsi_set_sense_information(sb, SCSI_SENSE_BUFFERSIZE,
|
||||
block);
|
||||
return;
|
||||
}
|
||||
|
||||
block = ata_tf_read_block(&qc->result_tf, dev);
|
||||
if (block == U64_MAX)
|
||||
return;
|
||||
|
||||
scsi_set_sense_information(sb, SCSI_SENSE_BUFFERSIZE, block);
|
||||
/* Could not decode error */
|
||||
ata_dev_warn(dev,
|
||||
"Could not decode error 0x%x, status 0x%x (err_mask=0x%x)\n",
|
||||
tf->error, tf->status, qc->err_mask);
|
||||
aborted:
|
||||
ata_scsi_set_sense(dev, cmd, ABORTED_COMMAND, 0, 0);
|
||||
}
|
||||
|
||||
void ata_scsi_sdev_config(struct scsi_device *sdev)
|
||||
@@ -3786,21 +3785,16 @@ static int ata_mselect_control_ata_feature(struct ata_queued_cmd *qc,
|
||||
/* Check cdl_ctrl */
|
||||
switch (buf[0] & 0x03) {
|
||||
case 0:
|
||||
/* Disable CDL if it is enabled */
|
||||
if (!(dev->flags & ATA_DFLAG_CDL_ENABLED))
|
||||
return 0;
|
||||
/* Disable CDL */
|
||||
ata_dev_dbg(dev, "Disabling CDL\n");
|
||||
cdl_action = 0;
|
||||
dev->flags &= ~ATA_DFLAG_CDL_ENABLED;
|
||||
break;
|
||||
case 0x02:
|
||||
/*
|
||||
* Enable CDL if not already enabled. Since this is mutually
|
||||
* exclusive with NCQ priority, allow this only if NCQ priority
|
||||
* is disabled.
|
||||
* Enable CDL. Since CDL is mutually exclusive with NCQ
|
||||
* priority, allow this only if NCQ priority is disabled.
|
||||
*/
|
||||
if (dev->flags & ATA_DFLAG_CDL_ENABLED)
|
||||
return 0;
|
||||
if (dev->flags & ATA_DFLAG_NCQ_PRIO_ENABLED) {
|
||||
ata_dev_err(dev,
|
||||
"NCQ priority must be disabled to enable CDL\n");
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/rcupdate.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/units.h>
|
||||
|
||||
#define CREATE_TRACE_POINTS
|
||||
#include <trace/events/thermal_pressure.h>
|
||||
@@ -26,7 +27,8 @@
|
||||
static DEFINE_PER_CPU(struct scale_freq_data __rcu *, sft_data);
|
||||
static struct cpumask scale_freq_counters_mask;
|
||||
static bool scale_freq_invariant;
|
||||
static DEFINE_PER_CPU(u32, freq_factor) = 1;
|
||||
DEFINE_PER_CPU(unsigned long, capacity_freq_ref) = 1;
|
||||
EXPORT_PER_CPU_SYMBOL_GPL(capacity_freq_ref);
|
||||
|
||||
static bool supports_scale_freq_counters(const struct cpumask *cpus)
|
||||
{
|
||||
@@ -170,9 +172,9 @@ DEFINE_PER_CPU(unsigned long, thermal_pressure);
|
||||
* operating on stale data when hot-plug is used for some CPUs. The
|
||||
* @capped_freq reflects the currently allowed max CPUs frequency due to
|
||||
* thermal capping. It might be also a boost frequency value, which is bigger
|
||||
* than the internal 'freq_factor' max frequency. In such case the pressure
|
||||
* value should simply be removed, since this is an indication that there is
|
||||
* no thermal throttling. The @capped_freq must be provided in kHz.
|
||||
* than the internal 'capacity_freq_ref' max frequency. In such case the
|
||||
* pressure value should simply be removed, since this is an indication that
|
||||
* there is no thermal throttling. The @capped_freq must be provided in kHz.
|
||||
*/
|
||||
void topology_update_thermal_pressure(const struct cpumask *cpus,
|
||||
unsigned long capped_freq)
|
||||
@@ -183,10 +185,7 @@ void topology_update_thermal_pressure(const struct cpumask *cpus,
|
||||
|
||||
cpu = cpumask_first(cpus);
|
||||
max_capacity = arch_scale_cpu_capacity(cpu);
|
||||
max_freq = per_cpu(freq_factor, cpu);
|
||||
|
||||
/* Convert to MHz scale which is used in 'freq_factor' */
|
||||
capped_freq /= 1000;
|
||||
max_freq = arch_scale_freq_ref(cpu);
|
||||
|
||||
/*
|
||||
* Handle properly the boost frequencies, which should simply clean
|
||||
@@ -279,13 +278,13 @@ void topology_normalize_cpu_scale(void)
|
||||
|
||||
capacity_scale = 1;
|
||||
for_each_possible_cpu(cpu) {
|
||||
capacity = raw_capacity[cpu] * per_cpu(freq_factor, cpu);
|
||||
capacity = raw_capacity[cpu] * per_cpu(capacity_freq_ref, cpu);
|
||||
capacity_scale = max(capacity, capacity_scale);
|
||||
}
|
||||
|
||||
pr_debug("cpu_capacity: capacity_scale=%llu\n", capacity_scale);
|
||||
for_each_possible_cpu(cpu) {
|
||||
capacity = raw_capacity[cpu] * per_cpu(freq_factor, cpu);
|
||||
capacity = raw_capacity[cpu] * per_cpu(capacity_freq_ref, cpu);
|
||||
capacity = div64_u64(capacity << SCHED_CAPACITY_SHIFT,
|
||||
capacity_scale);
|
||||
topology_set_cpu_scale(cpu, capacity);
|
||||
@@ -321,15 +320,15 @@ bool __init topology_parse_cpu_capacity(struct device_node *cpu_node, int cpu)
|
||||
cpu_node, raw_capacity[cpu]);
|
||||
|
||||
/*
|
||||
* Update freq_factor for calculating early boot cpu capacities.
|
||||
* Update capacity_freq_ref for calculating early boot CPU capacities.
|
||||
* For non-clk CPU DVFS mechanism, there's no way to get the
|
||||
* frequency value now, assuming they are running at the same
|
||||
* frequency (by keeping the initial freq_factor value).
|
||||
* frequency (by keeping the initial capacity_freq_ref value).
|
||||
*/
|
||||
cpu_clk = of_clk_get(cpu_node, 0);
|
||||
if (!PTR_ERR_OR_ZERO(cpu_clk)) {
|
||||
per_cpu(freq_factor, cpu) =
|
||||
clk_get_rate(cpu_clk) / 1000;
|
||||
per_cpu(capacity_freq_ref, cpu) =
|
||||
clk_get_rate(cpu_clk) / HZ_PER_KHZ;
|
||||
clk_put(cpu_clk);
|
||||
}
|
||||
} else {
|
||||
@@ -345,11 +344,16 @@ bool __init topology_parse_cpu_capacity(struct device_node *cpu_node, int cpu)
|
||||
return !ret;
|
||||
}
|
||||
|
||||
void __weak freq_inv_set_max_ratio(int cpu, u64 max_rate)
|
||||
{
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ACPI_CPPC_LIB
|
||||
#include <acpi/cppc_acpi.h>
|
||||
|
||||
void topology_init_cpu_capacity_cppc(void)
|
||||
{
|
||||
u64 capacity, capacity_scale = 0;
|
||||
struct cppc_perf_caps perf_caps;
|
||||
int cpu;
|
||||
|
||||
@@ -366,6 +370,10 @@ void topology_init_cpu_capacity_cppc(void)
|
||||
(perf_caps.highest_perf >= perf_caps.nominal_perf) &&
|
||||
(perf_caps.highest_perf >= perf_caps.lowest_perf)) {
|
||||
raw_capacity[cpu] = perf_caps.highest_perf;
|
||||
capacity_scale = max_t(u64, capacity_scale, raw_capacity[cpu]);
|
||||
|
||||
per_cpu(capacity_freq_ref, cpu) = cppc_perf_to_khz(&perf_caps, raw_capacity[cpu]);
|
||||
|
||||
pr_debug("cpu_capacity: CPU%d cpu_capacity=%u (raw).\n",
|
||||
cpu, raw_capacity[cpu]);
|
||||
continue;
|
||||
@@ -376,7 +384,18 @@ void topology_init_cpu_capacity_cppc(void)
|
||||
goto exit;
|
||||
}
|
||||
|
||||
topology_normalize_cpu_scale();
|
||||
for_each_possible_cpu(cpu) {
|
||||
freq_inv_set_max_ratio(cpu,
|
||||
per_cpu(capacity_freq_ref, cpu) * HZ_PER_KHZ);
|
||||
|
||||
capacity = raw_capacity[cpu];
|
||||
capacity = div64_u64(capacity << SCHED_CAPACITY_SHIFT,
|
||||
capacity_scale);
|
||||
topology_set_cpu_scale(cpu, capacity);
|
||||
pr_debug("cpu_capacity: CPU%d cpu_capacity=%lu\n",
|
||||
cpu, topology_get_cpu_scale(cpu));
|
||||
}
|
||||
|
||||
schedule_work(&update_topology_flags_work);
|
||||
pr_debug("cpu_capacity: cpu_capacity initialization done\n");
|
||||
|
||||
@@ -398,9 +417,6 @@ init_cpu_capacity_callback(struct notifier_block *nb,
|
||||
struct cpufreq_policy *policy = data;
|
||||
int cpu;
|
||||
|
||||
if (!raw_capacity)
|
||||
return 0;
|
||||
|
||||
if (val != CPUFREQ_CREATE_POLICY)
|
||||
return 0;
|
||||
|
||||
@@ -410,13 +426,18 @@ init_cpu_capacity_callback(struct notifier_block *nb,
|
||||
|
||||
cpumask_andnot(cpus_to_visit, cpus_to_visit, policy->related_cpus);
|
||||
|
||||
for_each_cpu(cpu, policy->related_cpus)
|
||||
per_cpu(freq_factor, cpu) = policy->cpuinfo.max_freq / 1000;
|
||||
for_each_cpu(cpu, policy->related_cpus) {
|
||||
per_cpu(capacity_freq_ref, cpu) = policy->cpuinfo.max_freq;
|
||||
freq_inv_set_max_ratio(cpu,
|
||||
per_cpu(capacity_freq_ref, cpu) * HZ_PER_KHZ);
|
||||
}
|
||||
|
||||
if (cpumask_empty(cpus_to_visit)) {
|
||||
topology_normalize_cpu_scale();
|
||||
schedule_work(&update_topology_flags_work);
|
||||
free_raw_capacity();
|
||||
if (raw_capacity) {
|
||||
topology_normalize_cpu_scale();
|
||||
schedule_work(&update_topology_flags_work);
|
||||
free_raw_capacity();
|
||||
}
|
||||
pr_debug("cpu_capacity: parsing done\n");
|
||||
schedule_work(&parsing_done_work);
|
||||
}
|
||||
@@ -436,7 +457,7 @@ static int __init register_cpufreq_notifier(void)
|
||||
* On ACPI-based systems skip registering cpufreq notifier as cpufreq
|
||||
* information is not needed for cpu capacity initialization.
|
||||
*/
|
||||
if (!acpi_disabled || !raw_capacity)
|
||||
if (!acpi_disabled)
|
||||
return -EINVAL;
|
||||
|
||||
if (!alloc_cpumask_var(&cpus_to_visit, GFP_KERNEL))
|
||||
|
||||
@@ -1175,16 +1175,18 @@ int __pm_runtime_resume(struct device *dev, int rpmflags)
|
||||
EXPORT_SYMBOL_GPL(__pm_runtime_resume);
|
||||
|
||||
/**
|
||||
* pm_runtime_get_if_active - Conditionally bump up device usage counter.
|
||||
* pm_runtime_get_conditional - Conditionally bump up device usage counter.
|
||||
* @dev: Device to handle.
|
||||
* @ign_usage_count: Whether or not to look at the current usage counter value.
|
||||
*
|
||||
* Return -EINVAL if runtime PM is disabled for @dev.
|
||||
*
|
||||
* Otherwise, if the runtime PM status of @dev is %RPM_ACTIVE and either
|
||||
* @ign_usage_count is %true or the runtime PM usage counter of @dev is not
|
||||
* zero, increment the usage counter of @dev and return 1. Otherwise, return 0
|
||||
* without changing the usage counter.
|
||||
* Otherwise, if its runtime PM status is %RPM_ACTIVE and (1) @ign_usage_count
|
||||
* is set, or (2) @dev is not ignoring children and its active child count is
|
||||
* nonero, or (3) the runtime PM usage counter of @dev is not zero, increment
|
||||
* the usage counter of @dev and return 1.
|
||||
*
|
||||
* Otherwise, return 0 without changing the usage counter.
|
||||
*
|
||||
* If @ign_usage_count is %true, this function can be used to prevent suspending
|
||||
* the device when its runtime PM status is %RPM_ACTIVE.
|
||||
@@ -1196,7 +1198,7 @@ EXPORT_SYMBOL_GPL(__pm_runtime_resume);
|
||||
* The caller is responsible for decrementing the runtime PM usage counter of
|
||||
* @dev after this function has returned a positive value for it.
|
||||
*/
|
||||
int pm_runtime_get_if_active(struct device *dev, bool ign_usage_count)
|
||||
static int pm_runtime_get_conditional(struct device *dev, bool ign_usage_count)
|
||||
{
|
||||
unsigned long flags;
|
||||
int retval;
|
||||
@@ -1206,7 +1208,8 @@ int pm_runtime_get_if_active(struct device *dev, bool ign_usage_count)
|
||||
retval = -EINVAL;
|
||||
} else if (dev->power.runtime_status != RPM_ACTIVE) {
|
||||
retval = 0;
|
||||
} else if (ign_usage_count) {
|
||||
} else if (ign_usage_count || (!dev->power.ignore_children &&
|
||||
atomic_read(&dev->power.child_count) > 0)) {
|
||||
retval = 1;
|
||||
atomic_inc(&dev->power.usage_count);
|
||||
} else {
|
||||
@@ -1217,8 +1220,45 @@ int pm_runtime_get_if_active(struct device *dev, bool ign_usage_count)
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* pm_runtime_get_if_active - Bump up runtime PM usage counter if the device is
|
||||
* in active state
|
||||
* @dev: Target device.
|
||||
*
|
||||
* Increment the runtime PM usage counter of @dev if its runtime PM status is
|
||||
* %RPM_ACTIVE, in which case it returns 1. If the device is in a different
|
||||
* state, 0 is returned. -EINVAL is returned if runtime PM is disabled for the
|
||||
* device, in which case also the usage_count will remain unmodified.
|
||||
*/
|
||||
int pm_runtime_get_if_active(struct device *dev)
|
||||
{
|
||||
return pm_runtime_get_conditional(dev, true);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pm_runtime_get_if_active);
|
||||
|
||||
/**
|
||||
* pm_runtime_get_if_in_use - Conditionally bump up runtime PM usage counter.
|
||||
* @dev: Target device.
|
||||
*
|
||||
* Increment the runtime PM usage counter of @dev if its runtime PM status is
|
||||
* %RPM_ACTIVE and its runtime PM usage counter is greater than 0 or it is not
|
||||
* ignoring children and its active child count is nonzero. 1 is returned in
|
||||
* this case.
|
||||
*
|
||||
* If @dev is in a different state or it is not in use (that is, its usage
|
||||
* counter is 0, or it is ignoring children, or its active child count is 0),
|
||||
* 0 is returned.
|
||||
*
|
||||
* -EINVAL is returned if runtime PM is disabled for the device, in which case
|
||||
* also the usage counter of @dev is not updated.
|
||||
*/
|
||||
int pm_runtime_get_if_in_use(struct device *dev)
|
||||
{
|
||||
return pm_runtime_get_conditional(dev, false);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pm_runtime_get_if_in_use);
|
||||
|
||||
/**
|
||||
* __pm_runtime_set_status - Set runtime PM status of a device.
|
||||
* @dev: Device to handle.
|
||||
@@ -1754,6 +1794,11 @@ void pm_runtime_reinit(struct device *dev)
|
||||
pm_runtime_put(dev->parent);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Clear power.needs_force_resume in case it has been set by
|
||||
* pm_runtime_force_suspend() invoked from a driver remove callback.
|
||||
*/
|
||||
dev->power.needs_force_resume = false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -2500,7 +2500,11 @@ static int handle_write_conflicts(struct drbd_device *device,
|
||||
peer_req->w.cb = superseded ? e_send_superseded :
|
||||
e_send_retry_write;
|
||||
list_add_tail(&peer_req->w.list, &device->done_ee);
|
||||
queue_work(connection->ack_sender, &peer_req->peer_device->send_acks_work);
|
||||
/* put is in drbd_send_acks_wf() */
|
||||
kref_get(&device->kref);
|
||||
if (!queue_work(connection->ack_sender,
|
||||
&peer_req->peer_device->send_acks_work))
|
||||
kref_put(&device->kref, drbd_destroy_device);
|
||||
|
||||
err = -ENOENT;
|
||||
goto out;
|
||||
|
||||
@@ -1472,19 +1472,36 @@ static int loop_set_dio(struct loop_device *lo, unsigned long arg)
|
||||
return error;
|
||||
}
|
||||
|
||||
static int loop_set_block_size(struct loop_device *lo, unsigned long arg)
|
||||
static int loop_set_block_size(struct loop_device *lo, blk_mode_t mode,
|
||||
struct block_device *bdev, unsigned long arg)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
if (lo->lo_state != Lo_bound)
|
||||
return -ENXIO;
|
||||
/*
|
||||
* If we don't hold exclusive handle for the device, upgrade to it
|
||||
* here to avoid changing device under exclusive owner.
|
||||
*/
|
||||
if (!(mode & BLK_OPEN_EXCL)) {
|
||||
err = bd_prepare_to_claim(bdev, loop_set_block_size, NULL);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
err = mutex_lock_killable(&lo->lo_mutex);
|
||||
if (err)
|
||||
goto abort_claim;
|
||||
|
||||
if (lo->lo_state != Lo_bound) {
|
||||
err = -ENXIO;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
err = blk_validate_block_size(arg);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (lo->lo_queue->limits.logical_block_size == arg)
|
||||
return 0;
|
||||
goto unlock;
|
||||
|
||||
sync_blockdev(lo->lo_device);
|
||||
invalidate_bdev(lo->lo_device);
|
||||
@@ -1496,6 +1513,11 @@ static int loop_set_block_size(struct loop_device *lo, unsigned long arg)
|
||||
loop_update_dio(lo);
|
||||
blk_mq_unfreeze_queue(lo->lo_queue);
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&lo->lo_mutex);
|
||||
abort_claim:
|
||||
if (!(mode & BLK_OPEN_EXCL))
|
||||
bd_abort_claiming(bdev, loop_set_block_size);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -1514,9 +1536,6 @@ static int lo_simple_ioctl(struct loop_device *lo, unsigned int cmd,
|
||||
case LOOP_SET_DIRECT_IO:
|
||||
err = loop_set_dio(lo, arg);
|
||||
break;
|
||||
case LOOP_SET_BLOCK_SIZE:
|
||||
err = loop_set_block_size(lo, arg);
|
||||
break;
|
||||
default:
|
||||
err = -EINVAL;
|
||||
}
|
||||
@@ -1571,9 +1590,12 @@ static int lo_ioctl(struct block_device *bdev, blk_mode_t mode,
|
||||
break;
|
||||
case LOOP_GET_STATUS64:
|
||||
return loop_get_status64(lo, argp);
|
||||
case LOOP_SET_BLOCK_SIZE:
|
||||
if (!(mode & BLK_OPEN_WRITE) && !capable(CAP_SYS_ADMIN))
|
||||
return -EPERM;
|
||||
return loop_set_block_size(lo, mode, bdev, arg);
|
||||
case LOOP_SET_CAPACITY:
|
||||
case LOOP_SET_DIRECT_IO:
|
||||
case LOOP_SET_BLOCK_SIZE:
|
||||
if (!(mode & BLK_OPEN_WRITE) && !capable(CAP_SYS_ADMIN))
|
||||
return -EPERM;
|
||||
fallthrough;
|
||||
|
||||
@@ -956,8 +956,10 @@ static bool vdc_port_mpgroup_check(struct vio_dev *vdev)
|
||||
dev = device_find_child(vdev->dev.parent, &port_data,
|
||||
vdc_device_probed);
|
||||
|
||||
if (dev)
|
||||
if (dev) {
|
||||
put_device(dev);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -31,8 +31,8 @@ int mhi_rddm_prepare(struct mhi_controller *mhi_cntrl,
|
||||
int ret;
|
||||
|
||||
for (i = 0; i < img_info->entries - 1; i++, mhi_buf++, bhi_vec++) {
|
||||
bhi_vec->dma_addr = mhi_buf->dma_addr;
|
||||
bhi_vec->size = mhi_buf->len;
|
||||
bhi_vec->dma_addr = cpu_to_le64(mhi_buf->dma_addr);
|
||||
bhi_vec->size = cpu_to_le64(mhi_buf->len);
|
||||
}
|
||||
|
||||
dev_dbg(dev, "BHIe programming for RDDM\n");
|
||||
@@ -375,8 +375,8 @@ static void mhi_firmware_copy(struct mhi_controller *mhi_cntrl,
|
||||
while (remainder) {
|
||||
to_cpy = min(remainder, mhi_buf->len);
|
||||
memcpy(mhi_buf->buf, buf, to_cpy);
|
||||
bhi_vec->dma_addr = mhi_buf->dma_addr;
|
||||
bhi_vec->size = to_cpy;
|
||||
bhi_vec->dma_addr = cpu_to_le64(mhi_buf->dma_addr);
|
||||
bhi_vec->size = cpu_to_le64(to_cpy);
|
||||
|
||||
buf += to_cpy;
|
||||
remainder -= to_cpy;
|
||||
|
||||
@@ -31,8 +31,8 @@ struct mhi_ctxt {
|
||||
};
|
||||
|
||||
struct bhi_vec_entry {
|
||||
u64 dma_addr;
|
||||
u64 size;
|
||||
__le64 dma_addr;
|
||||
__le64 size;
|
||||
};
|
||||
|
||||
enum mhi_ch_state_type {
|
||||
|
||||
@@ -603,7 +603,7 @@ static int parse_xfer_event(struct mhi_controller *mhi_cntrl,
|
||||
{
|
||||
dma_addr_t ptr = MHI_TRE_GET_EV_PTR(event);
|
||||
struct mhi_ring_element *local_rp, *ev_tre;
|
||||
void *dev_rp;
|
||||
void *dev_rp, *next_rp;
|
||||
struct mhi_buf_info *buf_info;
|
||||
u16 xfer_len;
|
||||
|
||||
@@ -622,6 +622,16 @@ static int parse_xfer_event(struct mhi_controller *mhi_cntrl,
|
||||
result.dir = mhi_chan->dir;
|
||||
|
||||
local_rp = tre_ring->rp;
|
||||
|
||||
next_rp = local_rp + 1;
|
||||
if (next_rp >= tre_ring->base + tre_ring->len)
|
||||
next_rp = tre_ring->base;
|
||||
if (dev_rp != next_rp && !MHI_TRE_DATA_GET_CHAIN(local_rp)) {
|
||||
dev_err(&mhi_cntrl->mhi_dev->dev,
|
||||
"Event element points to an unexpected TRE\n");
|
||||
break;
|
||||
}
|
||||
|
||||
while (local_rp != dev_rp) {
|
||||
buf_info = buf_ring->rp;
|
||||
/* If it's the last TRE, get length from the event */
|
||||
|
||||
@@ -129,8 +129,7 @@ static int cdx_rpmsg_probe(struct rpmsg_device *rpdev)
|
||||
|
||||
chinfo.src = RPMSG_ADDR_ANY;
|
||||
chinfo.dst = rpdev->dst;
|
||||
strscpy(chinfo.name, cdx_rpmsg_id_table[0].name,
|
||||
strlen(cdx_rpmsg_id_table[0].name));
|
||||
strscpy(chinfo.name, cdx_rpmsg_id_table[0].name, sizeof(chinfo.name));
|
||||
|
||||
cdx_mcdi->ept = rpmsg_create_ept(rpdev, cdx_rpmsg_cb, NULL, chinfo);
|
||||
if (!cdx_mcdi->ept) {
|
||||
|
||||
@@ -4618,10 +4618,10 @@ return_unspecified:
|
||||
* The NetFN and Command in the response is not even
|
||||
* marginally correct.
|
||||
*/
|
||||
dev_warn(intf->si_dev,
|
||||
"BMC returned incorrect response, expected netfn %x cmd %x, got netfn %x cmd %x\n",
|
||||
(msg->data[0] >> 2) | 1, msg->data[1],
|
||||
msg->rsp[0] >> 2, msg->rsp[1]);
|
||||
dev_warn_ratelimited(intf->si_dev,
|
||||
"BMC returned incorrect response, expected netfn %x cmd %x, got netfn %x cmd %x\n",
|
||||
(msg->data[0] >> 2) | 1, msg->data[1],
|
||||
msg->rsp[0] >> 2, msg->rsp[1]);
|
||||
|
||||
goto return_unspecified;
|
||||
}
|
||||
|
||||
@@ -1190,14 +1190,8 @@ static struct ipmi_smi_watcher smi_watcher = {
|
||||
.smi_gone = ipmi_smi_gone
|
||||
};
|
||||
|
||||
static int action_op(const char *inval, char *outval)
|
||||
static int action_op_set_val(const char *inval)
|
||||
{
|
||||
if (outval)
|
||||
strcpy(outval, action);
|
||||
|
||||
if (!inval)
|
||||
return 0;
|
||||
|
||||
if (strcmp(inval, "reset") == 0)
|
||||
action_val = WDOG_TIMEOUT_RESET;
|
||||
else if (strcmp(inval, "none") == 0)
|
||||
@@ -1208,18 +1202,26 @@ static int action_op(const char *inval, char *outval)
|
||||
action_val = WDOG_TIMEOUT_POWER_DOWN;
|
||||
else
|
||||
return -EINVAL;
|
||||
strcpy(action, inval);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int preaction_op(const char *inval, char *outval)
|
||||
static int action_op(const char *inval, char *outval)
|
||||
{
|
||||
int rv;
|
||||
|
||||
if (outval)
|
||||
strcpy(outval, preaction);
|
||||
strcpy(outval, action);
|
||||
|
||||
if (!inval)
|
||||
return 0;
|
||||
rv = action_op_set_val(inval);
|
||||
if (!rv)
|
||||
strcpy(action, inval);
|
||||
return rv;
|
||||
}
|
||||
|
||||
static int preaction_op_set_val(const char *inval)
|
||||
{
|
||||
if (strcmp(inval, "pre_none") == 0)
|
||||
preaction_val = WDOG_PRETIMEOUT_NONE;
|
||||
else if (strcmp(inval, "pre_smi") == 0)
|
||||
@@ -1232,18 +1234,26 @@ static int preaction_op(const char *inval, char *outval)
|
||||
preaction_val = WDOG_PRETIMEOUT_MSG_INT;
|
||||
else
|
||||
return -EINVAL;
|
||||
strcpy(preaction, inval);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int preop_op(const char *inval, char *outval)
|
||||
static int preaction_op(const char *inval, char *outval)
|
||||
{
|
||||
int rv;
|
||||
|
||||
if (outval)
|
||||
strcpy(outval, preop);
|
||||
strcpy(outval, preaction);
|
||||
|
||||
if (!inval)
|
||||
return 0;
|
||||
rv = preaction_op_set_val(inval);
|
||||
if (!rv)
|
||||
strcpy(preaction, inval);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int preop_op_set_val(const char *inval)
|
||||
{
|
||||
if (strcmp(inval, "preop_none") == 0)
|
||||
preop_val = WDOG_PREOP_NONE;
|
||||
else if (strcmp(inval, "preop_panic") == 0)
|
||||
@@ -1252,7 +1262,22 @@ static int preop_op(const char *inval, char *outval)
|
||||
preop_val = WDOG_PREOP_GIVE_DATA;
|
||||
else
|
||||
return -EINVAL;
|
||||
strcpy(preop, inval);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int preop_op(const char *inval, char *outval)
|
||||
{
|
||||
int rv;
|
||||
|
||||
if (outval)
|
||||
strcpy(outval, preop);
|
||||
|
||||
if (!inval)
|
||||
return 0;
|
||||
|
||||
rv = preop_op_set_val(inval);
|
||||
if (!rv)
|
||||
strcpy(preop, inval);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1289,18 +1314,18 @@ static int __init ipmi_wdog_init(void)
|
||||
{
|
||||
int rv;
|
||||
|
||||
if (action_op(action, NULL)) {
|
||||
if (action_op_set_val(action)) {
|
||||
action_op("reset", NULL);
|
||||
pr_info("Unknown action '%s', defaulting to reset\n", action);
|
||||
}
|
||||
|
||||
if (preaction_op(preaction, NULL)) {
|
||||
if (preaction_op_set_val(preaction)) {
|
||||
preaction_op("pre_none", NULL);
|
||||
pr_info("Unknown preaction '%s', defaulting to none\n",
|
||||
preaction);
|
||||
}
|
||||
|
||||
if (preop_op(preop, NULL)) {
|
||||
if (preop_op_set_val(preop)) {
|
||||
preop_op("preop_none", NULL);
|
||||
pr_info("Unknown preop '%s', defaulting to none\n", preop);
|
||||
}
|
||||
|
||||
@@ -314,8 +314,8 @@ static int __init misc_init(void)
|
||||
if (err)
|
||||
goto fail_remove;
|
||||
|
||||
err = -EIO;
|
||||
if (__register_chrdev(MISC_MAJOR, 0, MINORMASK + 1, "misc", &misc_fops))
|
||||
err = __register_chrdev(MISC_MAJOR, 0, MINORMASK + 1, "misc", &misc_fops);
|
||||
if (err < 0)
|
||||
goto fail_printk;
|
||||
return 0;
|
||||
|
||||
|
||||
@@ -1370,7 +1370,7 @@ static struct clk_branch gcc_xo_clk = {
|
||||
&gcc_xo_clk_src.clkr.hw,
|
||||
},
|
||||
.num_parents = 1,
|
||||
.flags = CLK_SET_RATE_PARENT,
|
||||
.flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
|
||||
.ops = &clk_branch2_ops,
|
||||
},
|
||||
},
|
||||
|
||||
@@ -51,7 +51,7 @@ static int clk_periph_determine_rate(struct clk_hw *hw,
|
||||
struct tegra_clk_periph *periph = to_clk_periph(hw);
|
||||
const struct clk_ops *div_ops = periph->div_ops;
|
||||
struct clk_hw *div_hw = &periph->divider.hw;
|
||||
unsigned long rate;
|
||||
long rate;
|
||||
|
||||
__clk_hw_set_clk(div_hw, hw);
|
||||
|
||||
@@ -59,7 +59,7 @@ static int clk_periph_determine_rate(struct clk_hw *hw,
|
||||
if (rate < 0)
|
||||
return rate;
|
||||
|
||||
req->rate = rate;
|
||||
req->rate = (unsigned long)rate;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -787,6 +787,7 @@ static int is_device_busy(struct comedi_device *dev)
|
||||
struct comedi_subdevice *s;
|
||||
int i;
|
||||
|
||||
lockdep_assert_held_write(&dev->attach_lock);
|
||||
lockdep_assert_held(&dev->mutex);
|
||||
if (!dev->attached)
|
||||
return 0;
|
||||
@@ -795,7 +796,16 @@ static int is_device_busy(struct comedi_device *dev)
|
||||
s = &dev->subdevices[i];
|
||||
if (s->busy)
|
||||
return 1;
|
||||
if (s->async && comedi_buf_is_mmapped(s))
|
||||
if (!s->async)
|
||||
continue;
|
||||
if (comedi_buf_is_mmapped(s))
|
||||
return 1;
|
||||
/*
|
||||
* There may be tasks still waiting on the subdevice's wait
|
||||
* queue, although they should already be about to be removed
|
||||
* from it since the subdevice has no active async command.
|
||||
*/
|
||||
if (wq_has_sleeper(&s->async->wait_head))
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -825,15 +835,22 @@ static int do_devconfig_ioctl(struct comedi_device *dev,
|
||||
return -EPERM;
|
||||
|
||||
if (!arg) {
|
||||
if (is_device_busy(dev))
|
||||
return -EBUSY;
|
||||
if (dev->attached) {
|
||||
struct module *driver_module = dev->driver->module;
|
||||
int rc = 0;
|
||||
|
||||
comedi_device_detach(dev);
|
||||
module_put(driver_module);
|
||||
if (dev->attached) {
|
||||
down_write(&dev->attach_lock);
|
||||
if (is_device_busy(dev)) {
|
||||
rc = -EBUSY;
|
||||
} else {
|
||||
struct module *driver_module =
|
||||
dev->driver->module;
|
||||
|
||||
comedi_device_detach_locked(dev);
|
||||
module_put(driver_module);
|
||||
}
|
||||
up_write(&dev->attach_lock);
|
||||
}
|
||||
return 0;
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (copy_from_user(&it, arg, sizeof(it)))
|
||||
@@ -1570,6 +1587,9 @@ static int do_insnlist_ioctl(struct comedi_device *dev,
|
||||
memset(&data[n], 0, (MIN_SAMPLES - n) *
|
||||
sizeof(unsigned int));
|
||||
}
|
||||
} else {
|
||||
memset(data, 0, max_t(unsigned int, n, MIN_SAMPLES) *
|
||||
sizeof(unsigned int));
|
||||
}
|
||||
ret = parse_insn(dev, insns + i, data, file);
|
||||
if (ret < 0)
|
||||
@@ -1653,6 +1673,8 @@ static int do_insn_ioctl(struct comedi_device *dev,
|
||||
memset(&data[insn->n], 0,
|
||||
(MIN_SAMPLES - insn->n) * sizeof(unsigned int));
|
||||
}
|
||||
} else {
|
||||
memset(data, 0, n_data * sizeof(unsigned int));
|
||||
}
|
||||
ret = parse_insn(dev, insn, data, file);
|
||||
if (ret < 0)
|
||||
|
||||
@@ -50,6 +50,7 @@ extern struct mutex comedi_drivers_list_lock;
|
||||
int insn_inval(struct comedi_device *dev, struct comedi_subdevice *s,
|
||||
struct comedi_insn *insn, unsigned int *data);
|
||||
|
||||
void comedi_device_detach_locked(struct comedi_device *dev);
|
||||
void comedi_device_detach(struct comedi_device *dev);
|
||||
int comedi_device_attach(struct comedi_device *dev,
|
||||
struct comedi_devconfig *it);
|
||||
|
||||
@@ -158,7 +158,7 @@ static void comedi_device_detach_cleanup(struct comedi_device *dev)
|
||||
int i;
|
||||
struct comedi_subdevice *s;
|
||||
|
||||
lockdep_assert_held(&dev->attach_lock);
|
||||
lockdep_assert_held_write(&dev->attach_lock);
|
||||
lockdep_assert_held(&dev->mutex);
|
||||
if (dev->subdevices) {
|
||||
for (i = 0; i < dev->n_subdevices; i++) {
|
||||
@@ -195,16 +195,23 @@ static void comedi_device_detach_cleanup(struct comedi_device *dev)
|
||||
comedi_clear_hw_dev(dev);
|
||||
}
|
||||
|
||||
void comedi_device_detach(struct comedi_device *dev)
|
||||
void comedi_device_detach_locked(struct comedi_device *dev)
|
||||
{
|
||||
lockdep_assert_held_write(&dev->attach_lock);
|
||||
lockdep_assert_held(&dev->mutex);
|
||||
comedi_device_cancel_all(dev);
|
||||
down_write(&dev->attach_lock);
|
||||
dev->attached = false;
|
||||
dev->detach_count++;
|
||||
if (dev->driver)
|
||||
dev->driver->detach(dev);
|
||||
comedi_device_detach_cleanup(dev);
|
||||
}
|
||||
|
||||
void comedi_device_detach(struct comedi_device *dev)
|
||||
{
|
||||
lockdep_assert_held(&dev->mutex);
|
||||
down_write(&dev->attach_lock);
|
||||
comedi_device_detach_locked(dev);
|
||||
up_write(&dev->attach_lock);
|
||||
}
|
||||
|
||||
@@ -612,11 +619,9 @@ static int insn_rw_emulate_bits(struct comedi_device *dev,
|
||||
unsigned int chan = CR_CHAN(insn->chanspec);
|
||||
unsigned int base_chan = (chan < 32) ? 0 : chan;
|
||||
unsigned int _data[2];
|
||||
unsigned int i;
|
||||
int ret;
|
||||
|
||||
if (insn->n == 0)
|
||||
return 0;
|
||||
|
||||
memset(_data, 0, sizeof(_data));
|
||||
memset(&_insn, 0, sizeof(_insn));
|
||||
_insn.insn = INSN_BITS;
|
||||
@@ -627,18 +632,21 @@ static int insn_rw_emulate_bits(struct comedi_device *dev,
|
||||
if (insn->insn == INSN_WRITE) {
|
||||
if (!(s->subdev_flags & SDF_WRITABLE))
|
||||
return -EINVAL;
|
||||
_data[0] = 1U << (chan - base_chan); /* mask */
|
||||
_data[1] = data[0] ? (1U << (chan - base_chan)) : 0; /* bits */
|
||||
_data[0] = 1U << (chan - base_chan); /* mask */
|
||||
}
|
||||
for (i = 0; i < insn->n; i++) {
|
||||
if (insn->insn == INSN_WRITE)
|
||||
_data[1] = data[i] ? _data[0] : 0; /* bits */
|
||||
|
||||
ret = s->insn_bits(dev, s, &_insn, _data);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (insn->insn == INSN_READ)
|
||||
data[i] = (_data[1] >> (chan - base_chan)) & 1;
|
||||
}
|
||||
|
||||
ret = s->insn_bits(dev, s, &_insn, _data);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (insn->insn == INSN_READ)
|
||||
data[0] = (_data[1] >> (chan - base_chan)) & 1;
|
||||
|
||||
return 1;
|
||||
return insn->n;
|
||||
}
|
||||
|
||||
static int __comedi_device_postconfig_async(struct comedi_device *dev,
|
||||
|
||||
@@ -328,7 +328,8 @@ static int pcl726_attach(struct comedi_device *dev,
|
||||
* Hook up the external trigger source interrupt only if the
|
||||
* user config option is valid and the board supports interrupts.
|
||||
*/
|
||||
if (it->options[1] && (board->irq_mask & (1 << it->options[1]))) {
|
||||
if (it->options[1] > 0 && it->options[1] < 16 &&
|
||||
(board->irq_mask & (1U << it->options[1]))) {
|
||||
ret = request_irq(it->options[1], pcl726_interrupt, 0,
|
||||
dev->board_name, dev);
|
||||
if (ret == 0) {
|
||||
|
||||
@@ -103,7 +103,7 @@ static void armada_8k_cpufreq_free_table(struct freq_table *freq_tables)
|
||||
{
|
||||
int opps_index, nb_cpus = num_possible_cpus();
|
||||
|
||||
for (opps_index = 0 ; opps_index <= nb_cpus; opps_index++) {
|
||||
for (opps_index = 0 ; opps_index < nb_cpus; opps_index++) {
|
||||
int i;
|
||||
|
||||
/* If cpu_dev is NULL then we reached the end of the array */
|
||||
|
||||
@@ -847,7 +847,7 @@ static struct freq_attr *cppc_cpufreq_attr[] = {
|
||||
};
|
||||
|
||||
static struct cpufreq_driver cppc_cpufreq_driver = {
|
||||
.flags = CPUFREQ_CONST_LOOPS,
|
||||
.flags = CPUFREQ_CONST_LOOPS | CPUFREQ_NEED_UPDATE_LIMITS,
|
||||
.verify = cppc_verify_policy,
|
||||
.target = cppc_cpufreq_set_target,
|
||||
.get = cppc_cpufreq_get_rate,
|
||||
|
||||
@@ -454,7 +454,7 @@ void cpufreq_freq_transition_end(struct cpufreq_policy *policy,
|
||||
|
||||
arch_set_freq_scale(policy->related_cpus,
|
||||
policy->cur,
|
||||
policy->cpuinfo.max_freq);
|
||||
arch_scale_freq_ref(policy->cpu));
|
||||
|
||||
spin_lock(&policy->transition_lock);
|
||||
policy->transition_ongoing = false;
|
||||
@@ -2205,7 +2205,7 @@ unsigned int cpufreq_driver_fast_switch(struct cpufreq_policy *policy,
|
||||
|
||||
policy->cur = freq;
|
||||
arch_set_freq_scale(policy->related_cpus, freq,
|
||||
policy->cpuinfo.max_freq);
|
||||
arch_scale_freq_ref(policy->cpu));
|
||||
cpufreq_stats_record_transition(policy, freq);
|
||||
|
||||
if (trace_cpu_frequency_enabled()) {
|
||||
@@ -2701,10 +2701,12 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy,
|
||||
pr_debug("starting governor %s failed\n", policy->governor->name);
|
||||
if (old_gov) {
|
||||
policy->governor = old_gov;
|
||||
if (cpufreq_init_governor(policy))
|
||||
if (cpufreq_init_governor(policy)) {
|
||||
policy->governor = NULL;
|
||||
else
|
||||
cpufreq_start_governor(policy);
|
||||
} else if (cpufreq_start_governor(policy)) {
|
||||
cpufreq_exit_governor(policy);
|
||||
policy->governor = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
|
||||
#include "gov.h"
|
||||
|
||||
#define BUCKETS 12
|
||||
#define BUCKETS 6
|
||||
#define INTERVAL_SHIFT 3
|
||||
#define INTERVALS (1UL << INTERVAL_SHIFT)
|
||||
#define RESOLUTION 1024
|
||||
@@ -31,12 +31,11 @@
|
||||
/*
|
||||
* Concepts and ideas behind the menu governor
|
||||
*
|
||||
* For the menu governor, there are 3 decision factors for picking a C
|
||||
* For the menu governor, there are 2 decision factors for picking a C
|
||||
* state:
|
||||
* 1) Energy break even point
|
||||
* 2) Performance impact
|
||||
* 3) Latency tolerance (from pmqos infrastructure)
|
||||
* These three factors are treated independently.
|
||||
* 2) Latency tolerance (from pmqos infrastructure)
|
||||
* These two factors are treated independently.
|
||||
*
|
||||
* Energy break even point
|
||||
* -----------------------
|
||||
@@ -119,19 +118,10 @@ struct menu_device {
|
||||
int interval_ptr;
|
||||
};
|
||||
|
||||
static inline int which_bucket(u64 duration_ns, unsigned int nr_iowaiters)
|
||||
static inline int which_bucket(u64 duration_ns)
|
||||
{
|
||||
int bucket = 0;
|
||||
|
||||
/*
|
||||
* We keep two groups of stats; one with no
|
||||
* IO pending, one without.
|
||||
* This allows us to calculate
|
||||
* E(duration)|iowait
|
||||
*/
|
||||
if (nr_iowaiters)
|
||||
bucket = BUCKETS/2;
|
||||
|
||||
if (duration_ns < 10ULL * NSEC_PER_USEC)
|
||||
return bucket;
|
||||
if (duration_ns < 100ULL * NSEC_PER_USEC)
|
||||
@@ -145,21 +135,16 @@ static inline int which_bucket(u64 duration_ns, unsigned int nr_iowaiters)
|
||||
return bucket + 5;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return a multiplier for the exit latency that is intended
|
||||
* to take performance requirements into account.
|
||||
* The more performance critical we estimate the system
|
||||
* to be, the higher this multiplier, and thus the higher
|
||||
* the barrier to go to an expensive C state.
|
||||
*/
|
||||
static inline int performance_multiplier(unsigned int nr_iowaiters)
|
||||
{
|
||||
/* for IO wait tasks (per cpu!) we add 10x each */
|
||||
return 1 + 10 * nr_iowaiters;
|
||||
}
|
||||
|
||||
static DEFINE_PER_CPU(struct menu_device, menu_devices);
|
||||
|
||||
static void menu_update_intervals(struct menu_device *data, unsigned int interval_us)
|
||||
{
|
||||
/* Update the repeating-pattern data. */
|
||||
data->intervals[data->interval_ptr++] = interval_us;
|
||||
if (data->interval_ptr >= INTERVALS)
|
||||
data->interval_ptr = 0;
|
||||
}
|
||||
|
||||
static void menu_update(struct cpuidle_driver *drv, struct cpuidle_device *dev);
|
||||
|
||||
/*
|
||||
@@ -276,18 +261,22 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
|
||||
struct menu_device *data = this_cpu_ptr(&menu_devices);
|
||||
s64 latency_req = cpuidle_governor_latency_req(dev->cpu);
|
||||
u64 predicted_ns;
|
||||
u64 interactivity_req;
|
||||
unsigned int nr_iowaiters;
|
||||
ktime_t delta, delta_tick;
|
||||
int i, idx;
|
||||
|
||||
if (data->needs_update) {
|
||||
menu_update(drv, dev);
|
||||
data->needs_update = 0;
|
||||
} else if (!dev->last_residency_ns) {
|
||||
/*
|
||||
* This happens when the driver rejects the previously selected
|
||||
* idle state and returns an error, so update the recent
|
||||
* intervals table to prevent invalid information from being
|
||||
* used going forward.
|
||||
*/
|
||||
menu_update_intervals(data, UINT_MAX);
|
||||
}
|
||||
|
||||
nr_iowaiters = nr_iowait_cpu(dev->cpu);
|
||||
|
||||
/* Find the shortest expected idle interval. */
|
||||
predicted_ns = get_typical_interval(data) * NSEC_PER_USEC;
|
||||
if (predicted_ns > RESIDENCY_THRESHOLD_NS) {
|
||||
@@ -301,7 +290,7 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
|
||||
}
|
||||
|
||||
data->next_timer_ns = delta;
|
||||
data->bucket = which_bucket(data->next_timer_ns, nr_iowaiters);
|
||||
data->bucket = which_bucket(data->next_timer_ns);
|
||||
|
||||
/* Round up the result for half microseconds. */
|
||||
timer_us = div_u64((RESOLUTION * DECAY * NSEC_PER_USEC) / 2 +
|
||||
@@ -319,7 +308,7 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
|
||||
*/
|
||||
data->next_timer_ns = KTIME_MAX;
|
||||
delta_tick = TICK_NSEC / 2;
|
||||
data->bucket = which_bucket(KTIME_MAX, nr_iowaiters);
|
||||
data->bucket = which_bucket(KTIME_MAX);
|
||||
}
|
||||
|
||||
if (unlikely(drv->state_count <= 1 || latency_req == 0) ||
|
||||
@@ -335,27 +324,15 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (tick_nohz_tick_stopped()) {
|
||||
/*
|
||||
* If the tick is already stopped, the cost of possible short
|
||||
* idle duration misprediction is much higher, because the CPU
|
||||
* may be stuck in a shallow idle state for a long time as a
|
||||
* result of it. In that case say we might mispredict and use
|
||||
* the known time till the closest timer event for the idle
|
||||
* state selection.
|
||||
*/
|
||||
if (predicted_ns < TICK_NSEC)
|
||||
predicted_ns = data->next_timer_ns;
|
||||
} else {
|
||||
/*
|
||||
* Use the performance multiplier and the user-configurable
|
||||
* latency_req to determine the maximum exit latency.
|
||||
*/
|
||||
interactivity_req = div64_u64(predicted_ns,
|
||||
performance_multiplier(nr_iowaiters));
|
||||
if (latency_req > interactivity_req)
|
||||
latency_req = interactivity_req;
|
||||
}
|
||||
/*
|
||||
* If the tick is already stopped, the cost of possible short idle
|
||||
* duration misprediction is much higher, because the CPU may be stuck
|
||||
* in a shallow idle state for a long time as a result of it. In that
|
||||
* case, say we might mispredict and use the known time till the closest
|
||||
* timer event for the idle state selection.
|
||||
*/
|
||||
if (tick_nohz_tick_stopped() && predicted_ns < TICK_NSEC)
|
||||
predicted_ns = data->next_timer_ns;
|
||||
|
||||
/*
|
||||
* Find the idle state with the lowest power while satisfying
|
||||
@@ -371,13 +348,15 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
|
||||
if (idx == -1)
|
||||
idx = i; /* first enabled state */
|
||||
|
||||
if (s->exit_latency_ns > latency_req)
|
||||
break;
|
||||
|
||||
if (s->target_residency_ns > predicted_ns) {
|
||||
/*
|
||||
* Use a physical idle state, not busy polling, unless
|
||||
* a timer is going to trigger soon enough.
|
||||
*/
|
||||
if ((drv->states[idx].flags & CPUIDLE_FLAG_POLLING) &&
|
||||
s->exit_latency_ns <= latency_req &&
|
||||
s->target_residency_ns <= data->next_timer_ns) {
|
||||
predicted_ns = s->target_residency_ns;
|
||||
idx = i;
|
||||
@@ -409,8 +388,6 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
|
||||
|
||||
return idx;
|
||||
}
|
||||
if (s->exit_latency_ns > latency_req)
|
||||
break;
|
||||
|
||||
idx = i;
|
||||
}
|
||||
@@ -553,10 +530,7 @@ static void menu_update(struct cpuidle_driver *drv, struct cpuidle_device *dev)
|
||||
|
||||
data->correction_factor[data->bucket] = new_factor;
|
||||
|
||||
/* update the repeating-pattern data */
|
||||
data->intervals[data->interval_ptr++] = ktime_to_us(measured_ns);
|
||||
if (data->interval_ptr >= INTERVALS)
|
||||
data->interval_ptr = 0;
|
||||
menu_update_intervals(data, ktime_to_us(measured_ns));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1482,11 +1482,13 @@ static void hpre_ecdh_cb(struct hpre_ctx *ctx, void *resp)
|
||||
if (overtime_thrhld && hpre_is_bd_timeout(req, overtime_thrhld))
|
||||
atomic64_inc(&dfx[HPRE_OVER_THRHLD_CNT].value);
|
||||
|
||||
/* Do unmap before data processing */
|
||||
hpre_ecdh_hw_data_clr_all(ctx, req, areq->dst, areq->src);
|
||||
|
||||
p = sg_virt(areq->dst);
|
||||
memmove(p, p + ctx->key_sz - curve_sz, curve_sz);
|
||||
memmove(p + curve_sz, p + areq->dst_len - curve_sz, curve_sz);
|
||||
|
||||
hpre_ecdh_hw_data_clr_all(ctx, req, areq->dst, areq->src);
|
||||
kpp_request_complete(areq, ret);
|
||||
|
||||
atomic64_inc(&dfx[HPRE_RECV_CNT].value);
|
||||
@@ -1796,9 +1798,11 @@ static void hpre_curve25519_cb(struct hpre_ctx *ctx, void *resp)
|
||||
if (overtime_thrhld && hpre_is_bd_timeout(req, overtime_thrhld))
|
||||
atomic64_inc(&dfx[HPRE_OVER_THRHLD_CNT].value);
|
||||
|
||||
/* Do unmap before data processing */
|
||||
hpre_curve25519_hw_data_clr_all(ctx, req, areq->dst, areq->src);
|
||||
|
||||
hpre_key_to_big_end(sg_virt(areq->dst), CURVE25519_KEY_SIZE);
|
||||
|
||||
hpre_curve25519_hw_data_clr_all(ctx, req, areq->dst, areq->src);
|
||||
kpp_request_complete(areq, ret);
|
||||
|
||||
atomic64_inc(&dfx[HPRE_RECV_CNT].value);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user