* [PATCH v5 10/18] kvm/x86: Emulate MSR IA32_CORE_CAPABILITY
From: Fenghua Yu @ 2019-03-12 23:00 UTC (permalink / raw)
To: Thomas Gleixner, Ingo Molnar, H Peter Anvin, Dave Hansen,
Paolo Bonzini, Ashok Raj, Peter Zijlstra, Xiaoyao Li ,
Michael Chan, Ravi V Shankar
Cc: linux-kernel, x86, linux-wireless, netdev, kvm, Xiaoyao Li,
Fenghua Yu
In-Reply-To: <1552431636-31511-1-git-send-email-fenghua.yu@intel.com>
From: Xiaoyao Li <xiaoyao.li@linux.intel.com>
MSR IA32_CORE_CAPABILITY is a feature-enumerating MSR, bit 5 of which
reports the capability of enabling detection of split locks (will be
supported on future processors based on Tremont microarchitecture and
later).
CPUID.(EAX=7H,ECX=0):EDX[30] will enumerate the presence of the
IA32_CORE_CAPABILITY MSR.
Please check the latest Intel 64 and IA-32 Architectures Software
Developer's Manual for more detailed information on the MSR and
the split lock bit.
Since MSR_IA32_CORE_CAPABILITY is a feature-enumerating MSR, we can
emulate it in software regardless of host's capability. What we need to
do is to set the right value of it to report the capability of guest.
In this patch we just set the guest's core_capability as 0, because we
haven't added support of the features it indicates to guest. It's for
bisectability.
Signed-off-by: Xiaoyao Li <xiaoyao.li@linux.intel.com>
Signed-off-by: Fenghua Yu <fenghua.yu@intel.com>
---
arch/x86/include/asm/kvm_host.h | 2 ++
arch/x86/kvm/cpuid.c | 6 ++++++
arch/x86/kvm/x86.c | 24 ++++++++++++++++++++++++
3 files changed, 32 insertions(+)
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 180373360e34..2c53df4a5a2a 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -570,6 +570,7 @@ struct kvm_vcpu_arch {
bool tpr_access_reporting;
u64 ia32_xss;
u64 microcode_version;
+ u64 core_capability;
/*
* Paging state of the vcpu
@@ -1527,6 +1528,7 @@ int kvm_pv_send_ipi(struct kvm *kvm, unsigned long ipi_bitmap_low,
unsigned long icr, int op_64_bit);
u64 kvm_get_arch_capabilities(void);
+u64 kvm_get_core_capability(void);
void kvm_define_shared_msr(unsigned index, u32 msr);
int kvm_set_shared_msr(unsigned index, u64 val, u64 mask);
diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c
index c07958b59f50..b7fb1822a1e5 100644
--- a/arch/x86/kvm/cpuid.c
+++ b/arch/x86/kvm/cpuid.c
@@ -505,6 +505,12 @@ static inline int __do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
* if the host doesn't support it.
*/
entry->edx |= F(ARCH_CAPABILITIES);
+ /*
+ * Since we emulate MSR IA32_CORE_CAPABILITY in
+ * software, we can always enable it for guest
+ * regardless of host's capability.
+ */
+ entry->edx |= F(CORE_CAPABILITY);
} else {
entry->ebx = 0;
entry->ecx = 0;
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 941f932373d0..e20cbb8c2b74 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -1158,6 +1158,7 @@ static u32 emulated_msrs[] = {
MSR_IA32_TSC_ADJUST,
MSR_IA32_TSCDEADLINE,
+ MSR_IA32_CORE_CAPABILITY,
MSR_IA32_MISC_ENABLE,
MSR_IA32_MCG_STATUS,
MSR_IA32_MCG_CTL,
@@ -1197,6 +1198,7 @@ static u32 msr_based_features[] = {
MSR_F10H_DECFG,
MSR_IA32_UCODE_REV,
+ MSR_IA32_CORE_CAPABILITY,
MSR_IA32_ARCH_CAPABILITIES,
};
@@ -1224,9 +1226,18 @@ u64 kvm_get_arch_capabilities(void)
}
EXPORT_SYMBOL_GPL(kvm_get_arch_capabilities);
+u64 kvm_get_core_capability(void)
+{
+ return 0;
+}
+EXPORT_SYMBOL_GPL(kvm_get_core_capability);
+
static int kvm_get_msr_feature(struct kvm_msr_entry *msr)
{
switch (msr->index) {
+ case MSR_IA32_CORE_CAPABILITY:
+ msr->data = kvm_get_core_capability();
+ break;
case MSR_IA32_ARCH_CAPABILITIES:
msr->data = kvm_get_arch_capabilities();
break;
@@ -2445,6 +2456,12 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
break;
case MSR_EFER:
return set_efer(vcpu, data);
+ case MSR_IA32_CORE_CAPABILITY:
+ if (!msr_info->host_initiated)
+ return 1;
+
+ vcpu->arch.core_capability = data;
+ break;
case MSR_K7_HWCR:
data &= ~(u64)0x40; /* ignore flush filter disable */
data &= ~(u64)0x100; /* ignore ignne emulation enable */
@@ -2750,6 +2767,12 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
case MSR_IA32_TSC:
msr_info->data = kvm_scale_tsc(vcpu, rdtsc()) + vcpu->arch.tsc_offset;
break;
+ case MSR_IA32_CORE_CAPABILITY:
+ if (!msr_info->host_initiated &&
+ !guest_cpuid_has(vcpu, X86_FEATURE_CORE_CAPABILITY))
+ return 1;
+ msr_info->data = vcpu->arch.core_capability;
+ break;
case MSR_MTRRcap:
case 0x200 ... 0x2ff:
return kvm_mtrr_get_msr(vcpu, msr_info->index, &msr_info->data);
@@ -8725,6 +8748,7 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm,
int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
{
+ vcpu->arch.core_capability = kvm_get_core_capability();
vcpu->arch.msr_platform_info = MSR_PLATFORM_INFO_CPUID_FAULT;
kvm_vcpu_mtrr_init(vcpu);
vcpu_load(vcpu);
--
2.19.1
^ permalink raw reply related
* [PATCH v5 11/18] kvm/vmx: Emulate MSR TEST_CTL
From: Fenghua Yu @ 2019-03-12 23:00 UTC (permalink / raw)
To: Thomas Gleixner, Ingo Molnar, H Peter Anvin, Dave Hansen,
Paolo Bonzini, Ashok Raj, Peter Zijlstra, Xiaoyao Li ,
Michael Chan, Ravi V Shankar
Cc: linux-kernel, x86, linux-wireless, netdev, kvm, Xiaoyao Li,
Fenghua Yu
In-Reply-To: <1552431636-31511-1-git-send-email-fenghua.yu@intel.com>
From: Xiaoyao Li <xiaoyao.li@linux.intel.com>
A control bit (bit 29) in TEST_CTL MSR 0x33 will be introduced in
future x86 processors. When bit 29 is set, the processor causes #AC
exception for split locked accesses at all CPL.
Please check the latest Intel 64 and IA-32 Architectures Software
Developer's Manual for more detailed information on the MSR and
the split lock bit.
This patch emulate MSR TEST_CTL with vmx->msr_test_ctl and does the
following:
1. As we emulate MSR TEST_CTL of guest, we should enable the related bits
in CORE_CAPABILITY to corretly report this feature to guest.
2. Differentiate MSR TEST_CTL between host and guest.
Signed-off-by: Xiaoyao Li <xiaoyao.li@linux.intel.com>
Signed-off-by: Fenghua Yu <fenghua.yu@intel.com>
---
arch/x86/kvm/vmx/vmx.c | 35 +++++++++++++++++++++++++++++++++++
arch/x86/kvm/vmx/vmx.h | 1 +
arch/x86/kvm/x86.c | 17 ++++++++++++++++-
3 files changed, 52 insertions(+), 1 deletion(-)
diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
index 30a6bcd735ec..270c6566fd5a 100644
--- a/arch/x86/kvm/vmx/vmx.c
+++ b/arch/x86/kvm/vmx/vmx.c
@@ -1659,6 +1659,12 @@ static int vmx_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
u32 index;
switch (msr_info->index) {
+ case MSR_TEST_CTL:
+ if (!msr_info->host_initiated &&
+ !(vcpu->arch.core_capability & CORE_CAP_SPLIT_LOCK_DETECT))
+ return 1;
+ msr_info->data = vmx->msr_test_ctl;
+ break;
#ifdef CONFIG_X86_64
case MSR_FS_BASE:
msr_info->data = vmcs_readl(GUEST_FS_BASE);
@@ -1799,6 +1805,14 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
u32 index;
switch (msr_index) {
+ case MSR_TEST_CTL:
+ if (!(vcpu->arch.core_capability & CORE_CAP_SPLIT_LOCK_DETECT))
+ return 1;
+
+ if (data & ~TEST_CTL_ENABLE_SPLIT_LOCK_DETECT)
+ return 1;
+ vmx->msr_test_ctl = data;
+ break;
case MSR_EFER:
ret = kvm_set_msr_common(vcpu, msr_info);
break;
@@ -4085,6 +4099,9 @@ static void vmx_vcpu_setup(struct vcpu_vmx *vmx)
vmx->arch_capabilities = kvm_get_arch_capabilities();
+ /* disable AC split lock by default */
+ vmx->msr_test_ctl = 0;
+
vm_exit_controls_init(vmx, vmx_vmexit_ctrl());
/* 22.2.1, 20.8.1 */
@@ -4122,6 +4139,7 @@ static void vmx_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event)
vmx->rmode.vm86_active = 0;
vmx->spec_ctrl = 0;
+ vmx->msr_test_ctl = 0;
vcpu->arch.microcode_version = 0x100000000ULL;
vmx->vcpu.arch.regs[VCPU_REGS_RDX] = get_rdx_init_val();
@@ -6321,6 +6339,21 @@ static void atomic_switch_perf_msrs(struct vcpu_vmx *vmx)
msrs[i].host, false);
}
+static void atomic_switch_msr_test_ctl(struct vcpu_vmx *vmx)
+{
+ u64 host_msr_test_ctl;
+
+ /* if TEST_CTL MSR doesn't exist on the hardware, we do nothing */
+ if (rdmsrl_safe(MSR_TEST_CTL, &host_msr_test_ctl))
+ return;
+
+ if (host_msr_test_ctl == vmx->msr_test_ctl)
+ clear_atomic_switch_msr(vmx, MSR_TEST_CTL);
+ else
+ add_atomic_switch_msr(vmx, MSR_TEST_CTL, vmx->msr_test_ctl,
+ host_msr_test_ctl, false);
+}
+
static void vmx_arm_hv_timer(struct vcpu_vmx *vmx, u32 val)
{
vmcs_write32(VMX_PREEMPTION_TIMER_VALUE, val);
@@ -6562,6 +6595,8 @@ static void vmx_vcpu_run(struct kvm_vcpu *vcpu)
atomic_switch_perf_msrs(vmx);
+ atomic_switch_msr_test_ctl(vmx);
+
vmx_update_hv_timer(vcpu);
/*
diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h
index 0ac0a64c7790..8549cba0fb75 100644
--- a/arch/x86/kvm/vmx/vmx.h
+++ b/arch/x86/kvm/vmx/vmx.h
@@ -191,6 +191,7 @@ struct vcpu_vmx {
u64 msr_guest_kernel_gs_base;
#endif
+ u64 msr_test_ctl;
u64 arch_capabilities;
u64 spec_ctrl;
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index e20cbb8c2b74..ad1df965574e 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -1228,7 +1228,22 @@ EXPORT_SYMBOL_GPL(kvm_get_arch_capabilities);
u64 kvm_get_core_capability(void)
{
- return 0;
+ u64 data;
+
+ rdmsrl_safe(MSR_IA32_CORE_CAPABILITY, &data);
+
+ /* mask non-virtualizable functions */
+ data &= CORE_CAP_SPLIT_LOCK_DETECT;
+
+ /*
+ * There will be a list of FMS values that have split lock detection
+ * but lack the CORE CAPABILITY MSR. In this case, we can set
+ * CORE_CAP_SPLIT_LOCK_DETECT since we emulate MSR CORE_CAPABILITY.
+ */
+ if (boot_cpu_has(X86_FEATURE_SPLIT_LOCK_DETECT))
+ data |= CORE_CAP_SPLIT_LOCK_DETECT;
+
+ return data;
}
EXPORT_SYMBOL_GPL(kvm_get_core_capability);
--
2.19.1
^ permalink raw reply related
* [PATCH v5 03/18] wlcore: simplify/fix/optimize reg_ch_conf_pending operations
From: Fenghua Yu @ 2019-03-12 23:00 UTC (permalink / raw)
To: Thomas Gleixner, Ingo Molnar, H Peter Anvin, Dave Hansen,
Paolo Bonzini, Ashok Raj, Peter Zijlstra, Xiaoyao Li ,
Michael Chan, Ravi V Shankar
Cc: linux-kernel, x86, linux-wireless, netdev, kvm, Fenghua Yu
In-Reply-To: <1552431636-31511-1-git-send-email-fenghua.yu@intel.com>
From: Paolo Bonzini <pbonzini@redhat.com>
Bitmaps are defined on unsigned longs, so the usage of u32[2] in the
wlcore driver is incorrect. As noted by Peter Zijlstra, casting arrays
to a bitmap is incorrect for big-endian architectures.
When looking at it I observed that:
- operations on reg_ch_conf_pending is always under the wl_lock mutex,
so set_bit is overkill
- the only case where reg_ch_conf_pending is accessed a u32 at a time is
unnecessary too.
This patch cleans up everything in this area, and changes tmp_ch_bitmap
to have the proper alignment.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Fenghua Yu <fenghua.yu@intel.com>
---
drivers/net/wireless/ti/wlcore/cmd.c | 15 ++++++---------
drivers/net/wireless/ti/wlcore/wlcore.h | 4 ++--
2 files changed, 8 insertions(+), 11 deletions(-)
diff --git a/drivers/net/wireless/ti/wlcore/cmd.c b/drivers/net/wireless/ti/wlcore/cmd.c
index 348be0aed97e..3b9266989afe 100644
--- a/drivers/net/wireless/ti/wlcore/cmd.c
+++ b/drivers/net/wireless/ti/wlcore/cmd.c
@@ -1700,14 +1700,14 @@ void wlcore_set_pending_regdomain_ch(struct wl1271 *wl, u16 channel,
ch_bit_idx = wlcore_get_reg_conf_ch_idx(band, channel);
if (ch_bit_idx >= 0 && ch_bit_idx <= WL1271_MAX_CHANNELS)
- set_bit(ch_bit_idx, (long *)wl->reg_ch_conf_pending);
+ __set_bit_le(ch_bit_idx, (long *)wl->reg_ch_conf_pending);
}
int wlcore_cmd_regdomain_config_locked(struct wl1271 *wl)
{
struct wl12xx_cmd_regdomain_dfs_config *cmd = NULL;
int ret = 0, i, b, ch_bit_idx;
- u32 tmp_ch_bitmap[2];
+ u32 tmp_ch_bitmap[2] __aligned(sizeof(unsigned long));
struct wiphy *wiphy = wl->hw->wiphy;
struct ieee80211_supported_band *band;
bool timeout = false;
@@ -1717,7 +1717,7 @@ int wlcore_cmd_regdomain_config_locked(struct wl1271 *wl)
wl1271_debug(DEBUG_CMD, "cmd reg domain config");
- memset(tmp_ch_bitmap, 0, sizeof(tmp_ch_bitmap));
+ memcpy(tmp_ch_bitmap, wl->reg_ch_conf_pending, sizeof(tmp_ch_bitmap));
for (b = NL80211_BAND_2GHZ; b <= NL80211_BAND_5GHZ; b++) {
band = wiphy->bands[b];
@@ -1738,13 +1738,10 @@ int wlcore_cmd_regdomain_config_locked(struct wl1271 *wl)
if (ch_bit_idx < 0)
continue;
- set_bit(ch_bit_idx, (long *)tmp_ch_bitmap);
+ __set_bit_le(ch_bit_idx, (long *)tmp_ch_bitmap);
}
}
- tmp_ch_bitmap[0] |= wl->reg_ch_conf_pending[0];
- tmp_ch_bitmap[1] |= wl->reg_ch_conf_pending[1];
-
if (!memcmp(tmp_ch_bitmap, wl->reg_ch_conf_last, sizeof(tmp_ch_bitmap)))
goto out;
@@ -1754,8 +1751,8 @@ int wlcore_cmd_regdomain_config_locked(struct wl1271 *wl)
goto out;
}
- cmd->ch_bit_map1 = cpu_to_le32(tmp_ch_bitmap[0]);
- cmd->ch_bit_map2 = cpu_to_le32(tmp_ch_bitmap[1]);
+ cmd->ch_bit_map1 = tmp_ch_bitmap[0];
+ cmd->ch_bit_map2 = tmp_ch_bitmap[1];
cmd->dfs_region = wl->dfs_region;
wl1271_debug(DEBUG_CMD,
diff --git a/drivers/net/wireless/ti/wlcore/wlcore.h b/drivers/net/wireless/ti/wlcore/wlcore.h
index dd14850b0603..870eea3e7a27 100644
--- a/drivers/net/wireless/ti/wlcore/wlcore.h
+++ b/drivers/net/wireless/ti/wlcore/wlcore.h
@@ -320,9 +320,9 @@ struct wl1271 {
bool watchdog_recovery;
/* Reg domain last configuration */
- u32 reg_ch_conf_last[2] __aligned(8);
+ DECLARE_BITMAP(reg_ch_conf_last, 64);
/* Reg domain pending configuration */
- u32 reg_ch_conf_pending[2];
+ DECLARE_BITMAP(reg_ch_conf_pending, 64);
/* Pointer that holds DMA-friendly block for the mailbox */
void *mbox;
--
2.19.1
^ permalink raw reply related
* [PATCH v5 08/18] x86/split_lock: Define MSR TEST_CTL register
From: Fenghua Yu @ 2019-03-12 23:00 UTC (permalink / raw)
To: Thomas Gleixner, Ingo Molnar, H Peter Anvin, Dave Hansen,
Paolo Bonzini, Ashok Raj, Peter Zijlstra, Xiaoyao Li ,
Michael Chan, Ravi V Shankar
Cc: linux-kernel, x86, linux-wireless, netdev, kvm, Fenghua Yu
In-Reply-To: <1552431636-31511-1-git-send-email-fenghua.yu@intel.com>
Setting bit 29 in MSR TEST_CTL register 0x33 enables split lock issue
detection and clearing the bit disables split lock issue detection.
Define the MSR and the bit. The definitions will be used in enabling or
disabling split lock detection.
Signed-off-by: Fenghua Yu <fenghua.yu@intel.com>
---
arch/x86/include/asm/msr-index.h | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
index f65ef6f783d2..25fa808de9e2 100644
--- a/arch/x86/include/asm/msr-index.h
+++ b/arch/x86/include/asm/msr-index.h
@@ -39,6 +39,10 @@
/* Intel MSRs. Some also available on other CPUs */
+#define MSR_TEST_CTL 0x00000033
+#define TEST_CTL_ENABLE_SPLIT_LOCK_DETECT_SHIFT 29
+#define TEST_CTL_ENABLE_SPLIT_LOCK_DETECT BIT(29)
+
#define MSR_IA32_SPEC_CTRL 0x00000048 /* Speculation Control */
#define SPEC_CTRL_IBRS (1 << 0) /* Indirect Branch Restricted Speculation */
#define SPEC_CTRL_STIBP_SHIFT 1 /* Single Thread Indirect Branch Predictor (STIBP) bit */
--
2.19.1
^ permalink raw reply related
* [PATCH v5 14/18] x86/clearcpuid: Support multiple clearcpuid options
From: Fenghua Yu @ 2019-03-12 23:00 UTC (permalink / raw)
To: Thomas Gleixner, Ingo Molnar, H Peter Anvin, Dave Hansen,
Paolo Bonzini, Ashok Raj, Peter Zijlstra, Xiaoyao Li ,
Michael Chan, Ravi V Shankar
Cc: linux-kernel, x86, linux-wireless, netdev, kvm, Fenghua Yu
In-Reply-To: <1552431636-31511-1-git-send-email-fenghua.yu@intel.com>
Currently only one kernel option "clearcpuid=" can be picked up by
kernel during boot time.
In some cases, user may want to clear a few cpu caps. This may be
useful to replace endless (new) kernel options like nosmep, nosmap,
etc.
We add support of multiple clearcpuid options to allow user to clear
multiple cpu caps.
Signed-off-by: Fenghua Yu <fenghua.yu@intel.com>
---
arch/x86/include/asm/cmdline.h | 3 +++
arch/x86/kernel/fpu/init.c | 30 ++++++++++++++++++++----------
arch/x86/lib/cmdline.c | 17 +++++++++++++++--
3 files changed, 38 insertions(+), 12 deletions(-)
diff --git a/arch/x86/include/asm/cmdline.h b/arch/x86/include/asm/cmdline.h
index 6faaf27e8899..059e29558bb3 100644
--- a/arch/x86/include/asm/cmdline.h
+++ b/arch/x86/include/asm/cmdline.h
@@ -5,5 +5,8 @@
int cmdline_find_option_bool(const char *cmdline_ptr, const char *option);
int cmdline_find_option(const char *cmdline_ptr, const char *option,
char *buffer, int bufsize);
+int cmdline_find_option_in_range(const char *cmdline_ptr, int cmdline_size,
+ const char *option, char *buffer, int bufsize,
+ char **arg_pos);
#endif /* _ASM_X86_CMDLINE_H */
diff --git a/arch/x86/kernel/fpu/init.c b/arch/x86/kernel/fpu/init.c
index 6abd83572b01..88bbba7ee96a 100644
--- a/arch/x86/kernel/fpu/init.c
+++ b/arch/x86/kernel/fpu/init.c
@@ -243,16 +243,31 @@ static void __init fpu__init_system_ctx_switch(void)
WARN_ON_FPU(current->thread.fpu.initialized);
}
+static void __init clear_cpuid(void)
+{
+ char arg[32], *argptr, *option_pos, clearcpuid_option[] = "clearcpuid";
+ int bit, cmdline_size;
+
+ /* Find each option in boot_command_line and clear specified cpu cap. */
+ cmdline_size = COMMAND_LINE_SIZE;
+ while (cmdline_find_option_in_range(boot_command_line, cmdline_size,
+ clearcpuid_option, arg,
+ sizeof(arg), &option_pos) >= 0) {
+ /* Chang command line range for next search. */
+ cmdline_size = option_pos - boot_command_line + 1;
+ argptr = arg;
+ if (get_option(&argptr, &bit) &&
+ bit >= 0 && bit < NCAPINTS * 32)
+ setup_clear_cpu_cap(bit);
+ }
+}
+
/*
* We parse fpu parameters early because fpu__init_system() is executed
* before parse_early_param().
*/
static void __init fpu__init_parse_early_param(void)
{
- char arg[32];
- char *argptr = arg;
- int bit;
-
if (cmdline_find_option_bool(boot_command_line, "no387"))
setup_clear_cpu_cap(X86_FEATURE_FPU);
@@ -271,12 +286,7 @@ static void __init fpu__init_parse_early_param(void)
if (cmdline_find_option_bool(boot_command_line, "noxsaves"))
setup_clear_cpu_cap(X86_FEATURE_XSAVES);
- if (cmdline_find_option(boot_command_line, "clearcpuid", arg,
- sizeof(arg)) &&
- get_option(&argptr, &bit) &&
- bit >= 0 &&
- bit < NCAPINTS * 32)
- setup_clear_cpu_cap(bit);
+ clear_cpuid();
}
/*
diff --git a/arch/x86/lib/cmdline.c b/arch/x86/lib/cmdline.c
index 3261abb21ef4..9cf1a0773877 100644
--- a/arch/x86/lib/cmdline.c
+++ b/arch/x86/lib/cmdline.c
@@ -114,13 +114,15 @@ __cmdline_find_option_bool(const char *cmdline, int max_cmdline_size,
* @option: option string to look for
* @buffer: memory buffer to return the option argument
* @bufsize: size of the supplied memory buffer
+ * @option_pos: pointer to the option if found
*
* Returns the length of the argument (regardless of if it was
* truncated to fit in the buffer), or -1 on not found.
*/
static int
__cmdline_find_option(const char *cmdline, int max_cmdline_size,
- const char *option, char *buffer, int bufsize)
+ const char *option, char *buffer, int bufsize,
+ char **arg_pos)
{
char c;
int pos = 0, len = -1;
@@ -164,6 +166,9 @@ __cmdline_find_option(const char *cmdline, int max_cmdline_size,
len = 0;
bufptr = buffer;
state = st_bufcpy;
+ if (arg_pos)
+ *arg_pos = (char *)cmdline -
+ strlen(option) - 1;
break;
} else if (c == *opptr++) {
/*
@@ -211,5 +216,13 @@ int cmdline_find_option(const char *cmdline, const char *option, char *buffer,
int bufsize)
{
return __cmdline_find_option(cmdline, COMMAND_LINE_SIZE, option,
- buffer, bufsize);
+ buffer, bufsize, NULL);
+}
+
+int cmdline_find_option_in_range(const char *cmdline, int cmdline_size,
+ char *option, char *buffer, int bufsize,
+ char **arg_pos)
+{
+ return __cmdline_find_option(cmdline, cmdline_size, option, buffer,
+ bufsize, arg_pos);
}
--
2.19.1
^ permalink raw reply related
* [PATCH v5 04/18] x86/split_lock: Align x86_capability to unsigned long to avoid split locked access
From: Fenghua Yu @ 2019-03-12 23:00 UTC (permalink / raw)
To: Thomas Gleixner, Ingo Molnar, H Peter Anvin, Dave Hansen,
Paolo Bonzini, Ashok Raj, Peter Zijlstra, Xiaoyao Li ,
Michael Chan, Ravi V Shankar
Cc: linux-kernel, x86, linux-wireless, netdev, kvm, Fenghua Yu
In-Reply-To: <1552431636-31511-1-git-send-email-fenghua.yu@intel.com>
set_cpu_cap() calls locked BTS and clear_cpu_cap() calls locked BTR to
operate on bitmap defined in x86_capability.
Locked BTS/BTR accesses a single unsigned long location. In 64-bit mode,
the location is at:
base address of x86_capability + (bit offset in x86_capability % 64) * 8
Since base address of x86_capability may not aligned to unsigned long,
the single unsigned long location may cross two cache lines and
accessing the location by locked BTS/BTR introductions will trigger #AC.
To fix the split lock issue, align x86_capability to unsigned long so that
the location will be always within one cache line.
Changing x86_capability[]'s type to unsigned long may also fix the issue
because x86_capability[] will be naturally aligned to unsigned long. But
this needs additional code changes. So we choose the simpler solution
by enforcing alignment using __aligned(unsigned long).
Signed-off-by: Fenghua Yu <fenghua.yu@intel.com>
---
arch/x86/include/asm/processor.h | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
index 2bb3a648fc12..b92296595fbe 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -93,7 +93,9 @@ struct cpuinfo_x86 {
__u32 extended_cpuid_level;
/* Maximum supported CPUID level, -1=no CPUID: */
int cpuid_level;
- __u32 x86_capability[NCAPINTS + NBUGINTS];
+ /* Unsigned long alignment to avoid split lock in atomic bitmap ops */
+ __u32 x86_capability[NCAPINTS + NBUGINTS]
+ __aligned(sizeof(unsigned long));
char x86_vendor_id[16];
char x86_model_id[64];
/* in KB - valid for CPUS which support this call: */
--
2.19.1
^ permalink raw reply related
* [PATCH v5 06/18] x86/msr-index: Define IA32_CORE_CAPABILITY MSR and #AC exception for split lock bit
From: Fenghua Yu @ 2019-03-12 23:00 UTC (permalink / raw)
To: Thomas Gleixner, Ingo Molnar, H Peter Anvin, Dave Hansen,
Paolo Bonzini, Ashok Raj, Peter Zijlstra, Xiaoyao Li ,
Michael Chan, Ravi V Shankar
Cc: linux-kernel, x86, linux-wireless, netdev, kvm, Fenghua Yu
In-Reply-To: <1552431636-31511-1-git-send-email-fenghua.yu@intel.com>
A new IA32_CORE_CAPABILITY MSR (0xCF) is defined. Each bit in
the MSR enumerates a model specific feature. Currently bit 5 enumerates
#AC exception for split locked accesses. When bit 5 is 1, split locked
accesses will generate #AC exception. When bit 5 is 0, split locked
accesses will not generate #AC exception.
Please check the latest Intel Architecture Instruction Set Extensions
and Future Features Programming Reference for more detailed information
on the MSR and the split lock bit.
Signed-off-by: Fenghua Yu <fenghua.yu@intel.com>
---
arch/x86/include/asm/msr-index.h | 3 +++
1 file changed, 3 insertions(+)
diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
index ca5bc0eacb95..f65ef6f783d2 100644
--- a/arch/x86/include/asm/msr-index.h
+++ b/arch/x86/include/asm/msr-index.h
@@ -59,6 +59,9 @@
#define MSR_PLATFORM_INFO_CPUID_FAULT_BIT 31
#define MSR_PLATFORM_INFO_CPUID_FAULT BIT_ULL(MSR_PLATFORM_INFO_CPUID_FAULT_BIT)
+#define MSR_IA32_CORE_CAPABILITY 0x000000cf
+#define CORE_CAP_SPLIT_LOCK_DETECT BIT(5) /* Detect split lock */
+
#define MSR_PKG_CST_CONFIG_CONTROL 0x000000e2
#define NHM_C3_AUTO_DEMOTE (1UL << 25)
#define NHM_C1_AUTO_DEMOTE (1UL << 26)
--
2.19.1
^ permalink raw reply related
* [PATCH v5 05/18] x86/cpufeatures: Enumerate IA32_CORE_CAPABILITIES MSR
From: Fenghua Yu @ 2019-03-12 23:00 UTC (permalink / raw)
To: Thomas Gleixner, Ingo Molnar, H Peter Anvin, Dave Hansen,
Paolo Bonzini, Ashok Raj, Peter Zijlstra, Xiaoyao Li ,
Michael Chan, Ravi V Shankar
Cc: linux-kernel, x86, linux-wireless, netdev, kvm, Fenghua Yu
In-Reply-To: <1552431636-31511-1-git-send-email-fenghua.yu@intel.com>
MSR register IA32_CORE_CAPABILITIES (0xCF) contains bits that enumerate
some model specific features.
The MSR 0xCF itself is enumerated by CPUID.(EAX=0x7,ECX=0):EDX[30].
When this bit is 1, the MSR 0xCF exists.
Detailed information for the CPUID bit and the MSR can be found in the
latest Intel Architecture Instruction Set Extensions and Future Features
Programming Reference.
Signed-off-by: Fenghua Yu <fenghua.yu@intel.com>
---
arch/x86/include/asm/cpufeatures.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h
index 981ff9479648..65b6af6cdc19 100644
--- a/arch/x86/include/asm/cpufeatures.h
+++ b/arch/x86/include/asm/cpufeatures.h
@@ -350,6 +350,7 @@
#define X86_FEATURE_INTEL_STIBP (18*32+27) /* "" Single Thread Indirect Branch Predictors */
#define X86_FEATURE_FLUSH_L1D (18*32+28) /* Flush L1D cache */
#define X86_FEATURE_ARCH_CAPABILITIES (18*32+29) /* IA32_ARCH_CAPABILITIES MSR (Intel) */
+#define X86_FEATURE_CORE_CAPABILITY (18*32+30) /* IA32_CORE_CAPABILITY MSR */
#define X86_FEATURE_SPEC_CTRL_SSBD (18*32+31) /* "" Speculative Store Bypass Disable */
/*
--
2.19.1
^ permalink raw reply related
* [PATCH v5 15/18] x86/clearcpuid: Support feature flag string in kernel option clearcpuid
From: Fenghua Yu @ 2019-03-12 23:00 UTC (permalink / raw)
To: Thomas Gleixner, Ingo Molnar, H Peter Anvin, Dave Hansen,
Paolo Bonzini, Ashok Raj, Peter Zijlstra, Xiaoyao Li ,
Michael Chan, Ravi V Shankar
Cc: linux-kernel, x86, linux-wireless, netdev, kvm, Fenghua Yu
In-Reply-To: <1552431636-31511-1-git-send-email-fenghua.yu@intel.com>
The kernel option clearcpuid currently only takes feature bit which
can be changed from kernel to kernel.
Extend clearcpuid to use cap flag string, which is defined in
x86_cap_flags[] and won't be changed from kernel to kernel.
And user can easily get the cap flag string from /proc/cpuinfo.
Signed-off-by: Fenghua Yu <fenghua.yu@intel.com>
---
arch/x86/include/asm/cpufeature.h | 1 +
arch/x86/kernel/cpu/cpuid-deps.c | 26 ++++++++++++++++++++++++++
arch/x86/kernel/fpu/init.c | 3 ++-
3 files changed, 29 insertions(+), 1 deletion(-)
diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h
index ce95b8cbd229..6792088525e3 100644
--- a/arch/x86/include/asm/cpufeature.h
+++ b/arch/x86/include/asm/cpufeature.h
@@ -132,6 +132,7 @@ extern const char * const x86_bug_flags[NBUGINTS*32];
extern void setup_clear_cpu_cap(unsigned int bit);
extern void clear_cpu_cap(struct cpuinfo_x86 *c, unsigned int bit);
+bool find_cpu_cap(char *cap_flag, unsigned int *pfeature);
#define setup_force_cpu_cap(bit) do { \
set_cpu_cap(&boot_cpu_data, bit); \
diff --git a/arch/x86/kernel/cpu/cpuid-deps.c b/arch/x86/kernel/cpu/cpuid-deps.c
index 3d633f67fbd7..1a71434f7b46 100644
--- a/arch/x86/kernel/cpu/cpuid-deps.c
+++ b/arch/x86/kernel/cpu/cpuid-deps.c
@@ -120,3 +120,29 @@ void setup_clear_cpu_cap(unsigned int feature)
{
do_clear_cpu_cap(NULL, feature);
}
+
+/**
+ * find_cpu_cap - Given a cap flag string, find its corresponding feature bit.
+ * @cap_flag: cap flag string as defined in x86_cap_flags[]
+ * @pfeature: feature bit
+ *
+ * Return: true if the feature is found. false if not found
+ */
+bool find_cpu_cap(char *cap_flag, unsigned int *pfeature)
+{
+#ifdef CONFIG_X86_FEATURE_NAMES
+ unsigned int feature;
+
+ for (feature = 0; feature < NCAPINTS * 32; feature++) {
+ if (!x86_cap_flags[feature])
+ continue;
+
+ if (strcmp(cap_flag, x86_cap_flags[feature]) == 0) {
+ *pfeature = feature;
+
+ return true;
+ }
+ }
+#endif
+ return false;
+}
diff --git a/arch/x86/kernel/fpu/init.c b/arch/x86/kernel/fpu/init.c
index 88bbba7ee96a..99b895eea166 100644
--- a/arch/x86/kernel/fpu/init.c
+++ b/arch/x86/kernel/fpu/init.c
@@ -256,7 +256,8 @@ static void __init clear_cpuid(void)
/* Chang command line range for next search. */
cmdline_size = option_pos - boot_command_line + 1;
argptr = arg;
- if (get_option(&argptr, &bit) &&
+ /* cpu cap can be specified by either feature bit or string */
+ if ((get_option(&argptr, &bit) || find_cpu_cap(arg, &bit)) &&
bit >= 0 && bit < NCAPINTS * 32)
setup_clear_cpu_cap(bit);
}
--
2.19.1
^ permalink raw reply related
* [PATCH v5 07/18] x86/split_lock: Enumerate #AC for split lock by MSR IA32_CORE_CAPABILITY
From: Fenghua Yu @ 2019-03-12 23:00 UTC (permalink / raw)
To: Thomas Gleixner, Ingo Molnar, H Peter Anvin, Dave Hansen,
Paolo Bonzini, Ashok Raj, Peter Zijlstra, Xiaoyao Li ,
Michael Chan, Ravi V Shankar
Cc: linux-kernel, x86, linux-wireless, netdev, kvm, Fenghua Yu
In-Reply-To: <1552431636-31511-1-git-send-email-fenghua.yu@intel.com>
Bits in MSR IA32_CORE_CAPABILITY enumerate features that are not
enumerated through CPUID. Currently bit 5 is defined to enumerate
feature of #AC for split lock accesses. All other bits are reserved now.
When the bit 5 is 1, the feature is supported and feature bit
X86_FEATURE_SPLIT_LOCK_DETECT is set. Otherwise, the feature is not
available.
The MSR IA32_CORE_CAPABILITY itself is enumerated by
CPUID.(EAX=0x7,ECX=0):EDX[30].
Signed-off-by: Fenghua Yu <fenghua.yu@intel.com>
---
arch/x86/include/asm/cpu.h | 5 ++
arch/x86/include/asm/cpufeatures.h | 1 +
arch/x86/kernel/cpu/common.c | 2 +
arch/x86/kernel/cpu/cpuid-deps.c | 79 +++++++++++++++---------------
arch/x86/kernel/cpu/intel.c | 22 +++++++++
5 files changed, 70 insertions(+), 39 deletions(-)
diff --git a/arch/x86/include/asm/cpu.h b/arch/x86/include/asm/cpu.h
index adc6cc86b062..4e03f53fc079 100644
--- a/arch/x86/include/asm/cpu.h
+++ b/arch/x86/include/asm/cpu.h
@@ -40,4 +40,9 @@ int mwait_usable(const struct cpuinfo_x86 *);
unsigned int x86_family(unsigned int sig);
unsigned int x86_model(unsigned int sig);
unsigned int x86_stepping(unsigned int sig);
+#ifdef CONFIG_CPU_SUP_INTEL
+void __init cpu_set_core_cap_bits(struct cpuinfo_x86 *c);
+#else
+static inline void __init cpu_set_core_cap_bits(struct cpuinfo_x86 *c) {}
+#endif
#endif /* _ASM_X86_CPU_H */
diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h
index 65b6af6cdc19..661719cbf458 100644
--- a/arch/x86/include/asm/cpufeatures.h
+++ b/arch/x86/include/asm/cpufeatures.h
@@ -221,6 +221,7 @@
#define X86_FEATURE_ZEN ( 7*32+28) /* "" CPU is AMD family 0x17 (Zen) */
#define X86_FEATURE_L1TF_PTEINV ( 7*32+29) /* "" L1TF workaround PTE inversion */
#define X86_FEATURE_IBRS_ENHANCED ( 7*32+30) /* Enhanced IBRS */
+#define X86_FEATURE_SPLIT_LOCK_DETECT ( 7*32+31) /* #AC for split lock */
/* Virtualization flags: Linux defined, word 8 */
#define X86_FEATURE_TPR_SHADOW ( 8*32+ 0) /* Intel TPR Shadow */
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 51ab37ba5f64..16b091bb62bd 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -1105,6 +1105,8 @@ static void __init early_identify_cpu(struct cpuinfo_x86 *c)
cpu_set_bug_bits(c);
+ cpu_set_core_cap_bits(c);
+
fpu__init_system(c);
#ifdef CONFIG_X86_32
diff --git a/arch/x86/kernel/cpu/cpuid-deps.c b/arch/x86/kernel/cpu/cpuid-deps.c
index 2c0bd38a44ab..3d633f67fbd7 100644
--- a/arch/x86/kernel/cpu/cpuid-deps.c
+++ b/arch/x86/kernel/cpu/cpuid-deps.c
@@ -20,45 +20,46 @@ struct cpuid_dep {
* but it's difficult to tell that to the init reference checker.
*/
static const struct cpuid_dep cpuid_deps[] = {
- { X86_FEATURE_XSAVEOPT, X86_FEATURE_XSAVE },
- { X86_FEATURE_XSAVEC, X86_FEATURE_XSAVE },
- { X86_FEATURE_XSAVES, X86_FEATURE_XSAVE },
- { X86_FEATURE_AVX, X86_FEATURE_XSAVE },
- { X86_FEATURE_PKU, X86_FEATURE_XSAVE },
- { X86_FEATURE_MPX, X86_FEATURE_XSAVE },
- { X86_FEATURE_XGETBV1, X86_FEATURE_XSAVE },
- { X86_FEATURE_FXSR_OPT, X86_FEATURE_FXSR },
- { X86_FEATURE_XMM, X86_FEATURE_FXSR },
- { X86_FEATURE_XMM2, X86_FEATURE_XMM },
- { X86_FEATURE_XMM3, X86_FEATURE_XMM2 },
- { X86_FEATURE_XMM4_1, X86_FEATURE_XMM2 },
- { X86_FEATURE_XMM4_2, X86_FEATURE_XMM2 },
- { X86_FEATURE_XMM3, X86_FEATURE_XMM2 },
- { X86_FEATURE_PCLMULQDQ, X86_FEATURE_XMM2 },
- { X86_FEATURE_SSSE3, X86_FEATURE_XMM2, },
- { X86_FEATURE_F16C, X86_FEATURE_XMM2, },
- { X86_FEATURE_AES, X86_FEATURE_XMM2 },
- { X86_FEATURE_SHA_NI, X86_FEATURE_XMM2 },
- { X86_FEATURE_FMA, X86_FEATURE_AVX },
- { X86_FEATURE_AVX2, X86_FEATURE_AVX, },
- { X86_FEATURE_AVX512F, X86_FEATURE_AVX, },
- { X86_FEATURE_AVX512IFMA, X86_FEATURE_AVX512F },
- { X86_FEATURE_AVX512PF, X86_FEATURE_AVX512F },
- { X86_FEATURE_AVX512ER, X86_FEATURE_AVX512F },
- { X86_FEATURE_AVX512CD, X86_FEATURE_AVX512F },
- { X86_FEATURE_AVX512DQ, X86_FEATURE_AVX512F },
- { X86_FEATURE_AVX512BW, X86_FEATURE_AVX512F },
- { X86_FEATURE_AVX512VL, X86_FEATURE_AVX512F },
- { X86_FEATURE_AVX512VBMI, X86_FEATURE_AVX512F },
- { X86_FEATURE_AVX512_VBMI2, X86_FEATURE_AVX512VL },
- { X86_FEATURE_GFNI, X86_FEATURE_AVX512VL },
- { X86_FEATURE_VAES, X86_FEATURE_AVX512VL },
- { X86_FEATURE_VPCLMULQDQ, X86_FEATURE_AVX512VL },
- { X86_FEATURE_AVX512_VNNI, X86_FEATURE_AVX512VL },
- { X86_FEATURE_AVX512_BITALG, X86_FEATURE_AVX512VL },
- { X86_FEATURE_AVX512_4VNNIW, X86_FEATURE_AVX512F },
- { X86_FEATURE_AVX512_4FMAPS, X86_FEATURE_AVX512F },
- { X86_FEATURE_AVX512_VPOPCNTDQ, X86_FEATURE_AVX512F },
+ { X86_FEATURE_XSAVEOPT, X86_FEATURE_XSAVE },
+ { X86_FEATURE_XSAVEC, X86_FEATURE_XSAVE },
+ { X86_FEATURE_XSAVES, X86_FEATURE_XSAVE },
+ { X86_FEATURE_AVX, X86_FEATURE_XSAVE },
+ { X86_FEATURE_PKU, X86_FEATURE_XSAVE },
+ { X86_FEATURE_MPX, X86_FEATURE_XSAVE },
+ { X86_FEATURE_XGETBV1, X86_FEATURE_XSAVE },
+ { X86_FEATURE_FXSR_OPT, X86_FEATURE_FXSR },
+ { X86_FEATURE_XMM, X86_FEATURE_FXSR },
+ { X86_FEATURE_XMM2, X86_FEATURE_XMM },
+ { X86_FEATURE_XMM3, X86_FEATURE_XMM2 },
+ { X86_FEATURE_XMM4_1, X86_FEATURE_XMM2 },
+ { X86_FEATURE_XMM4_2, X86_FEATURE_XMM2 },
+ { X86_FEATURE_XMM3, X86_FEATURE_XMM2 },
+ { X86_FEATURE_PCLMULQDQ, X86_FEATURE_XMM2 },
+ { X86_FEATURE_SSSE3, X86_FEATURE_XMM2, },
+ { X86_FEATURE_F16C, X86_FEATURE_XMM2, },
+ { X86_FEATURE_AES, X86_FEATURE_XMM2 },
+ { X86_FEATURE_SHA_NI, X86_FEATURE_XMM2 },
+ { X86_FEATURE_FMA, X86_FEATURE_AVX },
+ { X86_FEATURE_AVX2, X86_FEATURE_AVX, },
+ { X86_FEATURE_AVX512F, X86_FEATURE_AVX, },
+ { X86_FEATURE_AVX512IFMA, X86_FEATURE_AVX512F },
+ { X86_FEATURE_AVX512PF, X86_FEATURE_AVX512F },
+ { X86_FEATURE_AVX512ER, X86_FEATURE_AVX512F },
+ { X86_FEATURE_AVX512CD, X86_FEATURE_AVX512F },
+ { X86_FEATURE_AVX512DQ, X86_FEATURE_AVX512F },
+ { X86_FEATURE_AVX512BW, X86_FEATURE_AVX512F },
+ { X86_FEATURE_AVX512VL, X86_FEATURE_AVX512F },
+ { X86_FEATURE_AVX512VBMI, X86_FEATURE_AVX512F },
+ { X86_FEATURE_AVX512_VBMI2, X86_FEATURE_AVX512VL },
+ { X86_FEATURE_GFNI, X86_FEATURE_AVX512VL },
+ { X86_FEATURE_VAES, X86_FEATURE_AVX512VL },
+ { X86_FEATURE_VPCLMULQDQ, X86_FEATURE_AVX512VL },
+ { X86_FEATURE_AVX512_VNNI, X86_FEATURE_AVX512VL },
+ { X86_FEATURE_AVX512_BITALG, X86_FEATURE_AVX512VL },
+ { X86_FEATURE_AVX512_4VNNIW, X86_FEATURE_AVX512F },
+ { X86_FEATURE_AVX512_4FMAPS, X86_FEATURE_AVX512F },
+ { X86_FEATURE_AVX512_VPOPCNTDQ, X86_FEATURE_AVX512F },
+ { X86_FEATURE_SPLIT_LOCK_DETECT, X86_FEATURE_CORE_CAPABILITY},
{}
};
diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c
index fc3c07fe7df5..889390d51c17 100644
--- a/arch/x86/kernel/cpu/intel.c
+++ b/arch/x86/kernel/cpu/intel.c
@@ -1029,3 +1029,25 @@ static const struct cpu_dev intel_cpu_dev = {
cpu_dev_register(intel_cpu_dev);
+/**
+ * set_cpu_core_cap_bits - enumerate features supported in IA32_CORE_CAPABILITY
+ * @c: pointer to cpuinfo_x86
+ *
+ * Return: void
+ */
+void __init cpu_set_core_cap_bits(struct cpuinfo_x86 *c)
+{
+ u64 ia32_core_cap = 0;
+
+ if (!cpu_has(c, X86_FEATURE_CORE_CAPABILITY))
+ return;
+
+ /*
+ * If MSR_IA32_CORE_CAPABILITY exists, enumerate features that are
+ * reported in the MSR.
+ */
+ rdmsrl(MSR_IA32_CORE_CAPABILITY, ia32_core_cap);
+
+ if (ia32_core_cap & CORE_CAP_SPLIT_LOCK_DETECT)
+ setup_force_cpu_cap(X86_FEATURE_SPLIT_LOCK_DETECT);
+}
--
2.19.1
^ permalink raw reply related
* [PATCH v5 12/18] x86/split_lock: Enable #AC for split lock by default
From: Fenghua Yu @ 2019-03-12 23:00 UTC (permalink / raw)
To: Thomas Gleixner, Ingo Molnar, H Peter Anvin, Dave Hansen,
Paolo Bonzini, Ashok Raj, Peter Zijlstra, Xiaoyao Li ,
Michael Chan, Ravi V Shankar
Cc: linux-kernel, x86, linux-wireless, netdev, kvm, Fenghua Yu
In-Reply-To: <1552431636-31511-1-git-send-email-fenghua.yu@intel.com>
Split locked access locks bus and degradates overall memory access
performance. When split lock detection feature is enumerated, we want to
enable the feature by default to find any split lock issue and then fix
the issue.
Signed-off-by: Fenghua Yu <fenghua.yu@intel.com>
---
arch/x86/kernel/cpu/intel.c | 34 +++++++++++++++++++++++++++++++++-
1 file changed, 33 insertions(+), 1 deletion(-)
diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c
index 889390d51c17..561f7d50246a 100644
--- a/arch/x86/kernel/cpu/intel.c
+++ b/arch/x86/kernel/cpu/intel.c
@@ -31,6 +31,11 @@
#include <asm/apic.h>
#endif
+#define DISABLE_SPLIT_LOCK_DETECT 0
+#define ENABLE_SPLIT_LOCK_DETECT 1
+
+static int split_lock_detect_val;
+
/*
* Just in case our CPU detection goes bad, or you have a weird system,
* allow a way to override the automatic disabling of MPX.
@@ -161,10 +166,35 @@ static bool bad_spectre_microcode(struct cpuinfo_x86 *c)
return false;
}
+static u32 new_sp_test_ctl_val(u32 test_ctl_val)
+{
+ /* Change the split lock setting. */
+ if (split_lock_detect_val == DISABLE_SPLIT_LOCK_DETECT)
+ test_ctl_val &= ~TEST_CTL_ENABLE_SPLIT_LOCK_DETECT;
+ else
+ test_ctl_val |= TEST_CTL_ENABLE_SPLIT_LOCK_DETECT;
+
+ return test_ctl_val;
+}
+
+static void init_split_lock_detect(struct cpuinfo_x86 *c)
+{
+ if (cpu_has(c, X86_FEATURE_SPLIT_LOCK_DETECT)) {
+ u32 l, h;
+
+ rdmsr(MSR_TEST_CTL, l, h);
+ l = new_sp_test_ctl_val(l);
+ wrmsr(MSR_TEST_CTL, l, h);
+ pr_info_once("#AC for split lock is enabled\n");
+ }
+}
+
static void early_init_intel(struct cpuinfo_x86 *c)
{
u64 misc_enable;
+ init_split_lock_detect(c);
+
/* Unmask CPUID levels if masked: */
if (c->x86 > 6 || (c->x86 == 6 && c->x86_model >= 0xd)) {
if (msr_clear_bit(MSR_IA32_MISC_ENABLE,
@@ -1048,6 +1078,8 @@ void __init cpu_set_core_cap_bits(struct cpuinfo_x86 *c)
*/
rdmsrl(MSR_IA32_CORE_CAPABILITY, ia32_core_cap);
- if (ia32_core_cap & CORE_CAP_SPLIT_LOCK_DETECT)
+ if (ia32_core_cap & CORE_CAP_SPLIT_LOCK_DETECT) {
setup_force_cpu_cap(X86_FEATURE_SPLIT_LOCK_DETECT);
+ split_lock_detect_val = 1;
+ }
}
--
2.19.1
^ permalink raw reply related
* [PATCH v5 17/18] x86/clearcpuid: Clear CPUID bit in CPUID faulting
From: Fenghua Yu @ 2019-03-12 23:00 UTC (permalink / raw)
To: Thomas Gleixner, Ingo Molnar, H Peter Anvin, Dave Hansen,
Paolo Bonzini, Ashok Raj, Peter Zijlstra, Xiaoyao Li ,
Michael Chan, Ravi V Shankar
Cc: linux-kernel, x86, linux-wireless, netdev, kvm, Fenghua Yu
In-Reply-To: <1552431636-31511-1-git-send-email-fenghua.yu@intel.com>
From: Peter Zijlstra <peterz@infradead.org>
After kernel clears a CPUID bit through clearcpuid or other kernel options,
CPUID instruction executed from user space should see the same value for
the bit. The CPUID faulting handler returns the cleared bit to user.
Signed-off-by: Peter Zijlstra <peterz@infradead.org>
Signed-off-by: Fenghua Yu <fenghua.yu@intel.com>
---
arch/x86/include/asm/cpufeature.h | 4 +++
arch/x86/kernel/cpu/common.c | 2 ++
arch/x86/kernel/cpu/cpuid-deps.c | 52 ++++++++++++++++++++++++++++
arch/x86/kernel/cpu/intel.c | 56 +++++++++++++++++++++++++++++--
arch/x86/kernel/cpu/scattered.c | 17 ++++++++++
arch/x86/kernel/process.c | 3 ++
arch/x86/kernel/traps.c | 11 ++++++
7 files changed, 142 insertions(+), 3 deletions(-)
diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h
index 6792088525e3..c4ac787d9b85 100644
--- a/arch/x86/include/asm/cpufeature.h
+++ b/arch/x86/include/asm/cpufeature.h
@@ -227,5 +227,9 @@ static __always_inline __pure bool _static_cpu_has(u16 bit)
#define CPU_FEATURE_TYPEVAL boot_cpu_data.x86_vendor, boot_cpu_data.x86, \
boot_cpu_data.x86_model
+extern int cpuid_fault;
+u32 scattered_cpuid_mask(u32 leaf, u32 count, enum cpuid_regs_idx reg);
+u32 cpuid_cap_mask(u32 leaf, u32 count, enum cpuid_regs_idx reg);
+
#endif /* defined(__KERNEL__) && !defined(__ASSEMBLY__) */
#endif /* _ASM_X86_CPUFEATURE_H */
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 546f92aa61ca..02ea518580fa 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -1503,6 +1503,8 @@ void print_cpu_info(struct cpuinfo_x86 *c)
pr_cont(")\n");
}
+int cpuid_fault;
+
/*
* clearcpuid= was already parsed in fpu__init_parse_early_param.
* But we need to keep a dummy __setup around otherwise it would
diff --git a/arch/x86/kernel/cpu/cpuid-deps.c b/arch/x86/kernel/cpu/cpuid-deps.c
index 1a71434f7b46..d42aa4fa3021 100644
--- a/arch/x86/kernel/cpu/cpuid-deps.c
+++ b/arch/x86/kernel/cpu/cpuid-deps.c
@@ -113,9 +113,61 @@ static void do_clear_cpu_cap(struct cpuinfo_x86 *c, unsigned int feature)
void clear_cpu_cap(struct cpuinfo_x86 *c, unsigned int feature)
{
+ if (boot_cpu_has(feature))
+ cpuid_fault = 1;
do_clear_cpu_cap(c, feature);
}
+u32 cpuid_cap_mask(u32 leaf, u32 count, enum cpuid_regs_idx reg)
+{
+ switch (leaf) {
+ case 0x1:
+ if (reg == CPUID_EDX)
+ return ~cpu_caps_cleared[CPUID_1_EDX];
+ if (reg == CPUID_ECX)
+ return ~cpu_caps_cleared[CPUID_1_ECX];
+ break;
+
+ case 0x6:
+ if (reg == CPUID_EAX)
+ return ~cpu_caps_cleared[CPUID_6_EAX];
+ break;
+
+ case 0x7:
+ if (reg == CPUID_EDX)
+ return ~cpu_caps_cleared[CPUID_7_EDX];
+ if (reg == CPUID_ECX)
+ return ~cpu_caps_cleared[CPUID_7_ECX];
+ if (reg == CPUID_EBX && count == 0)
+ return ~cpu_caps_cleared[CPUID_7_0_EBX];
+ break;
+
+ case 0xD:
+ if (reg == CPUID_EAX)
+ return ~cpu_caps_cleared[CPUID_D_1_EAX];
+ break;
+
+ case 0xF:
+ if (reg == CPUID_EDX) {
+ if (count == 0)
+ return ~cpu_caps_cleared[CPUID_F_0_EDX];
+ if (count == 1)
+ return ~cpu_caps_cleared[CPUID_F_0_EDX];
+ }
+ break;
+
+ case 0x80000007:
+ if (reg == CPUID_EDX) {
+ if (test_bit(X86_FEATURE_CONSTANT_TSC,
+ (unsigned long *)cpu_caps_cleared))
+ return ~(1 << 8);
+ }
+ break;
+ }
+
+ return scattered_cpuid_mask(leaf, count, reg);
+}
+
void setup_clear_cpu_cap(unsigned int feature)
{
do_clear_cpu_cap(NULL, feature);
diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c
index 1b25ff8c75eb..13044b3f426d 100644
--- a/arch/x86/kernel/cpu/intel.c
+++ b/arch/x86/kernel/cpu/intel.c
@@ -19,6 +19,9 @@
#include <asm/microcode_intel.h>
#include <asm/hwcap2.h>
#include <asm/elf.h>
+#include <asm/insn.h>
+#include <asm/insn-eval.h>
+#include <asm/inat.h>
#ifdef CONFIG_X86_64
#include <linux/topology.h>
@@ -657,13 +660,60 @@ static void intel_bsp_resume(struct cpuinfo_x86 *c)
init_intel_energy_perf(c);
}
+bool fixup_cpuid_exception(struct pt_regs *regs)
+{
+ unsigned int leaf, count, eax, ebx, ecx, edx;
+ unsigned long seg_base = 0;
+ unsigned char buf[2];
+ int not_copied;
+
+ if (!cpuid_fault)
+ return false;
+
+ if (test_thread_flag(TIF_NOCPUID))
+ return false;
+
+ if (!user_64bit_mode(regs))
+ seg_base = insn_get_seg_base(regs, INAT_SEG_REG_CS);
+
+ if (seg_base == -1L)
+ return false;
+
+ not_copied = copy_from_user(buf, (void __user *)(seg_base + regs->ip),
+ sizeof(buf));
+ if (not_copied)
+ return false;
+
+ if (buf[0] != 0x0F || buf[1] != 0xA2) /* CPUID - OF A2 */
+ return false;
+
+ leaf = regs->ax;
+ count = regs->cx;
+
+ cpuid_count(leaf, count, &eax, &ebx, &ecx, &edx);
+
+ regs->ip += 2;
+ regs->ax = eax & cpuid_cap_mask(leaf, count, CPUID_EAX);
+ regs->bx = ebx & cpuid_cap_mask(leaf, count, CPUID_EBX);
+ regs->cx = ecx & cpuid_cap_mask(leaf, count, CPUID_ECX);
+ regs->dx = edx & cpuid_cap_mask(leaf, count, CPUID_EDX);
+
+ return true;
+}
+
static void init_cpuid_fault(struct cpuinfo_x86 *c)
{
u64 msr;
- if (!rdmsrl_safe(MSR_PLATFORM_INFO, &msr)) {
- if (msr & MSR_PLATFORM_INFO_CPUID_FAULT)
- set_cpu_cap(c, X86_FEATURE_CPUID_FAULT);
+ if (rdmsrl_safe(MSR_PLATFORM_INFO, &msr))
+ return;
+
+ if (msr & MSR_PLATFORM_INFO_CPUID_FAULT) {
+ set_cpu_cap(c, X86_FEATURE_CPUID_FAULT);
+ if (cpuid_fault) {
+ this_cpu_or(msr_misc_features_shadow,
+ MSR_MISC_FEATURES_ENABLES_CPUID_FAULT);
+ }
}
}
diff --git a/arch/x86/kernel/cpu/scattered.c b/arch/x86/kernel/cpu/scattered.c
index 94aa1c72ca98..353756c27096 100644
--- a/arch/x86/kernel/cpu/scattered.c
+++ b/arch/x86/kernel/cpu/scattered.c
@@ -62,3 +62,20 @@ void init_scattered_cpuid_features(struct cpuinfo_x86 *c)
set_cpu_cap(c, cb->feature);
}
}
+
+u32 scattered_cpuid_mask(u32 leaf, u32 count, enum cpuid_regs_idx reg)
+{
+ const struct cpuid_bit *cb;
+ u32 mask = ~0U;
+
+ for (cb = cpuid_bits; cb->feature; cb++) {
+ if (cb->level == leaf && cb->sub_leaf == count &&
+ cb->reg == reg) {
+ if (test_bit(cb->feature,
+ (unsigned long *)cpu_caps_cleared))
+ mask &= ~BIT(cb->bit);
+ }
+ }
+
+ return mask;
+}
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
index 58ac7be52c7a..2b1dfd7ae65d 100644
--- a/arch/x86/kernel/process.c
+++ b/arch/x86/kernel/process.c
@@ -196,6 +196,9 @@ static void set_cpuid_faulting(bool on)
{
u64 msrval;
+ if (cpuid_fault)
+ return;
+
msrval = this_cpu_read(msr_misc_features_shadow);
msrval &= ~MSR_MISC_FEATURES_ENABLES_CPUID_FAULT;
msrval |= (on << MSR_MISC_FEATURES_ENABLES_CPUID_FAULT_BIT);
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
index 69b6233e783e..36b2c87a2bce 100644
--- a/arch/x86/kernel/traps.c
+++ b/arch/x86/kernel/traps.c
@@ -549,6 +549,12 @@ dotraplinkage void do_bounds(struct pt_regs *regs, long error_code)
do_trap(X86_TRAP_BR, SIGSEGV, "bounds", regs, error_code, 0, NULL);
}
+#ifdef CONFIG_CPU_SUP_INTEL
+extern bool fixup_cpuid_exception(struct pt_regs *regs);
+#else
+static inline bool fixup_cpuid_exception(struct pt_regs *regs) { return false; }
+#endif
+
dotraplinkage void
do_general_protection(struct pt_regs *regs, long error_code)
{
@@ -563,6 +569,11 @@ do_general_protection(struct pt_regs *regs, long error_code)
return;
}
+ if (static_cpu_has(X86_FEATURE_CPUID_FAULT)) {
+ if (user_mode(regs) && fixup_cpuid_exception(regs))
+ return;
+ }
+
if (v8086_mode(regs)) {
local_irq_enable();
handle_vm86_fault((struct kernel_vm86_regs *) regs, error_code);
--
2.19.1
^ permalink raw reply related
* [PATCH v5 18/18] Change document for kernel option clearcpuid
From: Fenghua Yu @ 2019-03-12 23:00 UTC (permalink / raw)
To: Thomas Gleixner, Ingo Molnar, H Peter Anvin, Dave Hansen,
Paolo Bonzini, Ashok Raj, Peter Zijlstra, Xiaoyao Li ,
Michael Chan, Ravi V Shankar
Cc: linux-kernel, x86, linux-wireless, netdev, kvm, Fenghua Yu
In-Reply-To: <1552431636-31511-1-git-send-email-fenghua.yu@intel.com>
Since kernel option clearcpuid now supports multiple options and CPU
capability flags, the document needs to be changed.
Signed-off-by: Fenghua Yu <fenghua.yu@intel.com>
---
Documentation/admin-guide/kernel-parameters.txt | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index 2b8ee90bb644..7e65ae67d573 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -563,10 +563,12 @@
loops can be debugged more effectively on production
systems.
- clearcpuid=BITNUM [X86]
+ clearcpuid=BITNUM | FLAG [X86]
Disable CPUID feature X for the kernel. See
arch/x86/include/asm/cpufeatures.h for the valid bit
- numbers. Note the Linux specific bits are not necessarily
+ numbers or /proc/cpuinfo for valid CPU flags.
+ Multiple options can be used to disable a few features.
+ Note the Linux specific bits are not necessarily
stable over kernel options, but the vendor specific
ones should be.
Also note that user programs calling CPUID directly
--
2.19.1
^ permalink raw reply related
* [PATCH v5 13/18] x86/split_lock: Add a sysfs interface to allow user to enable or disable split lock detection on all CPUs during run time
From: Fenghua Yu @ 2019-03-12 23:00 UTC (permalink / raw)
To: Thomas Gleixner, Ingo Molnar, H Peter Anvin, Dave Hansen,
Paolo Bonzini, Ashok Raj, Peter Zijlstra, Xiaoyao Li ,
Michael Chan, Ravi V Shankar
Cc: linux-kernel, x86, linux-wireless, netdev, kvm, Fenghua Yu
In-Reply-To: <1552431636-31511-1-git-send-email-fenghua.yu@intel.com>
The interface /sys/device/system/cpu/split_lock_detect is added
to allow user to control split lock detection and show current split
lock detection setting.
Writing 1 to the file enables split lock detection and writing 0
disables split lock detection. Split lock detection is enabled or
disabled on all CPUs.
Reading the file shows current global split lock detection setting:
disabled when 0 and enabled when 1.
Please note the interface only shows global setting. During run time,
split lock detection on one CPU may be disabled if split lock
in kernel code happens on the CPU. The interface doesn't show split
lock detection status on individual CPU. User can run rdmsr on 0x33
to check split lock detection on each CPU.
Signed-off-by: Fenghua Yu <fenghua.yu@intel.com>
---
arch/x86/kernel/cpu/intel.c | 67 +++++++++++++++++++++++++++++++++++++
1 file changed, 67 insertions(+)
diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c
index 561f7d50246a..1b25ff8c75eb 100644
--- a/arch/x86/kernel/cpu/intel.c
+++ b/arch/x86/kernel/cpu/intel.c
@@ -34,6 +34,7 @@
#define DISABLE_SPLIT_LOCK_DETECT 0
#define ENABLE_SPLIT_LOCK_DETECT 1
+static DEFINE_MUTEX(split_lock_detect_mutex);
static int split_lock_detect_val;
/*
@@ -1083,3 +1084,69 @@ void __init cpu_set_core_cap_bits(struct cpuinfo_x86 *c)
split_lock_detect_val = 1;
}
}
+
+static ssize_t
+split_lock_detect_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ return sprintf(buf, "%u\n", READ_ONCE(split_lock_detect_val));
+}
+
+static ssize_t
+split_lock_detect_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ u32 val, l, h;
+ int cpu, ret;
+
+ ret = kstrtou32(buf, 10, &val);
+ if (ret)
+ return ret;
+
+ if (val != DISABLE_SPLIT_LOCK_DETECT && val != ENABLE_SPLIT_LOCK_DETECT)
+ return -EINVAL;
+
+ /*
+ * Since split lock could be disabled by kernel #AC handler or user
+ * may directly change bit 29 in MSR_TEST_CTL, split lock setting on
+ * each CPU may be different from global setting split_lock_detect_val
+ * by now. Update MSR on each CPU, so all of CPUs will have same split
+ * lock setting.
+ */
+ mutex_lock(&split_lock_detect_mutex);
+
+ WRITE_ONCE(split_lock_detect_val, val);
+
+ /*
+ * Get MSR_TEST_CTL on this CPU, assuming all CPUs have same value
+ * in the MSR except split lock detection bit (bit 29).
+ */
+ rdmsr(MSR_TEST_CTL, l, h);
+ l = new_sp_test_ctl_val(l);
+ /* Update the split lock detection setting on all online CPUs. */
+ for_each_online_cpu(cpu)
+ wrmsr_on_cpu(cpu, MSR_TEST_CTL, l, h);
+
+ mutex_unlock(&split_lock_detect_mutex);
+
+ return count;
+}
+
+static DEVICE_ATTR_RW(split_lock_detect);
+
+static int __init split_lock_init(void)
+{
+ int ret;
+
+ if (!boot_cpu_has(X86_FEATURE_SPLIT_LOCK_DETECT))
+ return -ENODEV;
+
+ ret = device_create_file(cpu_subsys.dev_root,
+ &dev_attr_split_lock_detect);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+subsys_initcall(split_lock_init);
--
2.19.1
^ permalink raw reply related
* [PATCH v5 09/18] x86/split_lock: Handle #AC exception for split lock
From: Fenghua Yu @ 2019-03-12 23:00 UTC (permalink / raw)
To: Thomas Gleixner, Ingo Molnar, H Peter Anvin, Dave Hansen,
Paolo Bonzini, Ashok Raj, Peter Zijlstra, Xiaoyao Li ,
Michael Chan, Ravi V Shankar
Cc: linux-kernel, x86, linux-wireless, netdev, kvm, Fenghua Yu
In-Reply-To: <1552431636-31511-1-git-send-email-fenghua.yu@intel.com>
There may be different considerations on how to handle #AC for split lock,
e.g. how to handle system hang caused by split lock issue in firmware,
how to emulate faulting instruction, etc. We use a simple method to
handle user and kernel split lock and may extend the method in the future.
When #AC exception for split lock is triggered from user process, the
process is killed by SIGBUS. To execute the process properly, user
application developer needs to fix the split lock issue.
When #AC exception for split lock is triggered from a kernel instruction,
disable #AC for split lock on local CPU and warn the split lock issue.
After the exception, the faulting instruction will be executed and kernel
execution continues. #AC for split lock is only disabled on the local CPU
not globally. It will be re-enabled if the CPU is offline and then online.
Kernel developer should check the warning, which contains helpful faulting
address, context, and callstack info, and fix the split lock issue
one by one. Then further split lock may be captured and fixed.
After bit 29 in MSR_TEST_CTL is set as one in kernel, firmware inherits
the setting when firmware is executed in S4, S5, run time services, SMI,
etc. Split lock issue in firmware triggers #AC and may hang the system
depending on how firmware handles the #AC. It's up to firmware developer
to fix the split lock issues in firmware.
Signed-off-by: Fenghua Yu <fenghua.yu@intel.com>
---
arch/x86/kernel/traps.c | 31 +++++++++++++++++++++++++++++++
1 file changed, 31 insertions(+)
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
index d26f9e9c3d83..69b6233e783e 100644
--- a/arch/x86/kernel/traps.c
+++ b/arch/x86/kernel/traps.c
@@ -61,6 +61,7 @@
#include <asm/mpx.h>
#include <asm/vm86.h>
#include <asm/umip.h>
+#include <asm/cpu.h>
#ifdef CONFIG_X86_64
#include <asm/x86_init.h>
@@ -293,7 +294,37 @@ DO_ERROR(X86_TRAP_OLD_MF, SIGFPE, 0, NULL, "coprocessor segment overru
DO_ERROR(X86_TRAP_TS, SIGSEGV, 0, NULL, "invalid TSS", invalid_TSS)
DO_ERROR(X86_TRAP_NP, SIGBUS, 0, NULL, "segment not present", segment_not_present)
DO_ERROR(X86_TRAP_SS, SIGBUS, 0, NULL, "stack segment", stack_segment)
+#ifndef CONFIG_CPU_SUP_INTEL
DO_ERROR(X86_TRAP_AC, SIGBUS, BUS_ADRALN, NULL, "alignment check", alignment_check)
+#else
+dotraplinkage void do_alignment_check(struct pt_regs *regs, long error_code)
+{
+ unsigned int trapnr = X86_TRAP_AC;
+ char str[] = "alignment check";
+ int signr = SIGBUS;
+
+ RCU_LOCKDEP_WARN(!rcu_is_watching(), "entry code didn't wake RCU");
+
+ if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) !=
+ NOTIFY_STOP) {
+ cond_local_irq_enable(regs);
+ if (!user_mode(regs)) {
+ /*
+ * Only split lock can generate #AC from kernel. Warn
+ * and disable #AC for split lock on current CPU.
+ */
+ msr_clear_bit(MSR_TEST_CTL,
+ TEST_CTL_ENABLE_SPLIT_LOCK_DETECT_SHIFT);
+ WARN_ONCE(1, "A split lock issue is detected.\n");
+
+ return;
+ }
+ /* Handle #AC generated from user code. */
+ do_trap(X86_TRAP_AC, SIGBUS, "alignment check", regs,
+ error_code, BUS_ADRALN, NULL);
+ }
+}
+#endif
#undef IP
#ifdef CONFIG_VMAP_STACK
--
2.19.1
^ permalink raw reply related
* [PATCH v5 16/18] x86/clearcpuid: Apply cleared feature bits that are forced set before
From: Fenghua Yu @ 2019-03-12 23:00 UTC (permalink / raw)
To: Thomas Gleixner, Ingo Molnar, H Peter Anvin, Dave Hansen,
Paolo Bonzini, Ashok Raj, Peter Zijlstra, Xiaoyao Li ,
Michael Chan, Ravi V Shankar
Cc: linux-kernel, x86, linux-wireless, netdev, kvm, Fenghua Yu
In-Reply-To: <1552431636-31511-1-git-send-email-fenghua.yu@intel.com>
Some CPU feature bits are forced set and stored in cpuinfo_x86 before
handling clearcpuid options. To clear those bits from cpuinfo_x86,
apply_forced_cap() is called after handling the options.
Please note, apply_forced_cap() is called twice on boot CPU. But this code
is simple and there is no functionality issue.
Signed-off-by: Fenghua Yu <fenghua.yu@intel.com>
---
arch/x86/include/asm/cpu.h | 2 ++
arch/x86/kernel/cpu/common.c | 5 +++--
arch/x86/kernel/fpu/init.c | 2 ++
3 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/arch/x86/include/asm/cpu.h b/arch/x86/include/asm/cpu.h
index 4e03f53fc079..bfa5ac6b7502 100644
--- a/arch/x86/include/asm/cpu.h
+++ b/arch/x86/include/asm/cpu.h
@@ -26,6 +26,8 @@ struct x86_cpu {
struct cpu cpu;
};
+void apply_forced_caps(struct cpuinfo_x86 *c);
+
#ifdef CONFIG_HOTPLUG_CPU
extern int arch_register_cpu(int num);
extern void arch_unregister_cpu(int);
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 16b091bb62bd..546f92aa61ca 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -758,13 +758,14 @@ void cpu_detect(struct cpuinfo_x86 *c)
}
}
-static void apply_forced_caps(struct cpuinfo_x86 *c)
+void apply_forced_caps(struct cpuinfo_x86 *c)
{
int i;
for (i = 0; i < NCAPINTS + NBUGINTS; i++) {
- c->x86_capability[i] &= ~cpu_caps_cleared[i];
+ /* Bits may be cleared after they are set. */
c->x86_capability[i] |= cpu_caps_set[i];
+ c->x86_capability[i] &= ~cpu_caps_cleared[i];
}
}
diff --git a/arch/x86/kernel/fpu/init.c b/arch/x86/kernel/fpu/init.c
index 99b895eea166..9c2801b605e3 100644
--- a/arch/x86/kernel/fpu/init.c
+++ b/arch/x86/kernel/fpu/init.c
@@ -5,6 +5,7 @@
#include <asm/tlbflush.h>
#include <asm/setup.h>
#include <asm/cmdline.h>
+#include <asm/cpu.h>
#include <linux/sched.h>
#include <linux/sched/task.h>
@@ -261,6 +262,7 @@ static void __init clear_cpuid(void)
bit >= 0 && bit < NCAPINTS * 32)
setup_clear_cpu_cap(bit);
}
+ apply_forced_caps(&boot_cpu_data);
}
/*
--
2.19.1
^ permalink raw reply related
* [PATCH v5 01/18] x86/common: Align cpu_caps_cleared and cpu_caps_set to unsigned long
From: Fenghua Yu @ 2019-03-12 23:00 UTC (permalink / raw)
To: Thomas Gleixner, Ingo Molnar, H Peter Anvin, Dave Hansen,
Paolo Bonzini, Ashok Raj, Peter Zijlstra, Xiaoyao Li ,
Michael Chan, Ravi V Shankar
Cc: linux-kernel, x86, linux-wireless, netdev, kvm, Fenghua Yu
In-Reply-To: <1552431636-31511-1-git-send-email-fenghua.yu@intel.com>
cpu_caps_cleared and cpu_caps_set may not be aligned to unsigned long.
Atomic operations (i.e. set_bit and clear_bit) on the bitmaps may access
two cache lines (a.k.a. split lock) and lock bus to block all memory
accesses from other processors to ensure atomicity.
To avoid the overall performance degradation from the bus locking, align
the two variables to unsigned long.
Defining the variables as unsigned long may also fix the issue because
they are naturally aligned to unsigned long. But that needs additional
code changes. Adding __aligned(unsigned long) are simpler fixes.
Signed-off-by: Fenghua Yu <fenghua.yu@intel.com>
---
arch/x86/kernel/cpu/common.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index cb28e98a0659..51ab37ba5f64 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -488,8 +488,9 @@ static const char *table_lookup_model(struct cpuinfo_x86 *c)
return NULL; /* Not found */
}
-__u32 cpu_caps_cleared[NCAPINTS + NBUGINTS];
-__u32 cpu_caps_set[NCAPINTS + NBUGINTS];
+/* Unsigned long alignment to avoid split lock in atomic bitmap ops */
+__u32 cpu_caps_cleared[NCAPINTS + NBUGINTS] __aligned(sizeof(unsigned long));
+__u32 cpu_caps_set[NCAPINTS + NBUGINTS] __aligned(sizeof(unsigned long));
void load_percpu_segment(int cpu)
{
--
2.19.1
^ permalink raw reply related
* Re: [linuxwifi] [RFC] iwlwifi: enable TX AMPDU for some iwldvm
From: Kevin Locke @ 2019-03-12 21:44 UTC (permalink / raw)
To: Grumbach, Emmanuel; +Cc: linuxwifi, linux-wireless, Coelho, Luciano
In-Reply-To: <58bd45ab11912eef5c809427449a31800ecdbf53.camel@intel.com>
On Tue, 2019-03-12 at 20:48 +0000, Grumbach, Emmanuel wrote:
> On Tue, 2019-03-12 at 14:31 -0600, Kevin Locke wrote:
>> On Tue, 2019-03-12 at 19:47 +0000, Grumbach, Emmanuel wrote:
>>> We had issues with reclaim path upon BACK. This is of course a
>>> firmware problem...
>>
>> Does that suggest the issue may have been fixed by a firmware update?
>> For reference, I'm currently using "firmware version 9.221.4.1 build
>> 25532" from the firmware-iwlwifi Debian package (version 20190114-1).
>>
>> If it would be helpful, I could attempt to bisect the firmware
>> revisions to find the one that fixed it (assuming I can reproduce the
>> issue with a previous firmware version).
>
> Well.. Sorry, I wasn't very "technical".
> So the problem was really that we stopped getting BACK notifications
> from the firmware and that caused a reclaim stall which in turn was
> caught by a Tx queue stuck timer firing in the driver.
> I was never able to reproduce this. What I can do is to enable A-MPDU
> on my old system that has this same device, just to see what happens.
Thanks for the additional details and for offering to try it out, that
would be great!
> While chasing this bug, I even found another one which bought me a few
> moments of fame:
>
> commit d6ee27eb13beab94056e0de52d81220058ca2297
> Author: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
> Date: Wed Jun 6 09:13:36 2012 +0200
>
> iwlwifi: don't mess up the SCD when removing a key
>
> and in the commit message of that very commit:
>
> This doesn't seem to fix the higher queues that get stuck
> from time to time.
>
> There were no new versions of the firmware released since then.
> I tried to skim through bugzilla, but couldn't find the bugs I was
> handling then.
Ah. You are right about the firmware version. I should have checked.
I see what you mean. I found several reports for TX queue stuck
issues in Bugzilla. Perhaps this is one (or one of its many dups):
https://bugzilla.kernel.org/show_bug.cgi?id=56581
Let me know if there is anything I can do to help search or test.
Thanks again,
Kevin
^ permalink raw reply
* [RFC 2/2] ath10k: Support rx-sw-crypt of PMF blockack frames.
From: greearb @ 2019-03-12 21:28 UTC (permalink / raw)
To: linux-wireless; +Cc: Ben Greear
In-Reply-To: <20190312212830.9813-1-greearb@candelatech.com>
From: Ben Greear <greearb@candelatech.com>
In rx-sw-crypt mode, the firmware cannot decrypt any frames, including
blockack action frames when using PMF. So, pass them up to the mac80211
stack so it can decrypt them and pass them back down so we can send the
decrypted frame back to the firmware for re-insertion.
Signed-off-by: Ben Greear <greearb@candelatech.com>
---
drivers/net/wireless/ath/ath10k/core.c | 1 +
drivers/net/wireless/ath/ath10k/core.h | 4 +++
drivers/net/wireless/ath/ath10k/mac.c | 27 ++++++++++++++++
drivers/net/wireless/ath/ath10k/wmi.c | 45 ++++++++++++++++++++++++--
drivers/net/wireless/ath/ath10k/wmi.h | 10 ++++++
5 files changed, 85 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index 929e0c059adc..75968d86e8bc 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -624,6 +624,7 @@ static const char *const ath10k_core_fw_feature_str[] = {
[ATH10K_FW_FEATURE_CT_STA] = "CT-STA",
[ATH10K_FW_FEATURE_TXRATE2_CT] = "txrate2-CT",
[ATH10K_FW_FEATURE_BEACON_TX_CB_CT] = "beacon-cb-CT",
+ [ATH10K_FW_FEATURE_CONSUME_BLOCK_ACK_CT] = "wmi-block-ack-CT",
};
static unsigned int ath10k_core_get_fw_feature_str(char *buf,
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index a70771170007..4dada2e6e9d1 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -950,6 +950,10 @@ enum ath10k_fw_features {
*/
ATH10K_FW_FEATURE_BEACON_TX_CB_CT = 50,
+ ATH10K_FW_FEATURE_RESERVED_CT = 51, /* reserved by out-of-tree feature */
+
+ ATH10K_FW_FEATURE_CONSUME_BLOCK_ACK_CT = 52, /* firmware can accept decrypted rx block-ack over WMI */
+
/* keep last */
ATH10K_FW_FEATURE_COUNT,
};
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 02a8efa2e783..0cca9f83f7e5 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -4990,6 +4990,32 @@ static int ath10k_start_scan(struct ath10k *ar,
/* mac80211 callbacks */
/**********************/
+static int ath10k_mac_consume_block_ack(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct sk_buff *skb)
+{
+ struct ath10k *ar = hw->priv;
+ struct ieee80211_mgmt *mgmt = (void *)skb->data;
+ struct ath10k_vif *arvif = (void *)vif->drv_priv;
+
+ /*ath10k_warn(ar, "mac-consume-ba called.\n");*/
+ if (!(test_bit(ATH10K_FW_FEATURE_CT_RXSWCRYPT,
+ ar->running_fw->fw_file.fw_features) &&
+ ar->request_nohwcrypt))
+ return -EINVAL; /* Not running swcrypt, don't need this */
+
+ if (ieee80211_is_action(mgmt->frame_control) &&
+ mgmt->u.action.category == WLAN_CATEGORY_BACK) {
+ int rv = ath10k_wmi_consume_block_ack(ar, arvif, skb);
+ if (rv) {
+ ath10k_warn(ar, "consume-block-ack failed: %d\n", rv);
+ }
+ return rv;
+ }
+ return -EINVAL;
+}
+
+
static void ath10k_mac_op_tx(struct ieee80211_hw *hw,
struct ieee80211_tx_control *control,
struct sk_buff *skb)
@@ -8958,6 +8984,7 @@ static const struct ieee80211_ops ath10k_ops = {
#ifdef CONFIG_MAC80211_DEBUGFS
.sta_add_debugfs = ath10k_sta_add_debugfs,
#endif
+ .consume_block_ack = ath10k_mac_consume_block_ack,
};
#define CHAN2G(_channel, _freq, _flags) { \
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index bebddf0effdf..59b0e0ead66a 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -656,6 +656,7 @@ static struct wmi_cmd_map wmi_10_4_cmd_map = {
.sta_keepalive_cmd = WMI_CMD_UNSUPPORTED,
.echo_cmdid = WMI_10_4_ECHO_CMDID,
.pdev_utf_cmdid = WMI_10_4_PDEV_UTF_CMDID,
+ .pdev_consume_block_ack_cmdid = WMI_10_4_PDEV_CONSUME_BLOCK_ACK_CMDID_CT,
.dbglog_cfg_cmdid = WMI_10_4_DBGLOG_CFG_CMDID,
.pdev_qvit_cmdid = WMI_10_4_PDEV_QVIT_CMDID,
.pdev_ftm_intg_cmdid = WMI_CMD_UNSUPPORTED,
@@ -1662,6 +1663,40 @@ static const struct wmi_peer_flags_map wmi_10_2_peer_flags_map = {
.bw160 = WMI_10_2_PEER_160MHZ,
};
+int ath10k_wmi_consume_block_ack(struct ath10k *ar, struct ath10k_vif *arvif, struct sk_buff *ba_skb)
+{
+ struct wmi_pdev_consume_block_ack *cmd;
+ int cmd_id = ar->wmi.cmd->pdev_consume_block_ack_cmdid;
+ struct sk_buff *wskb;
+ int ba_skb_len = ba_skb->len;
+ if (ba_skb_len > 200)
+ ba_skb_len = 200;
+
+ /*ath10k_warn(ar, "wmi consume block ack, vdev: %d peer: %d ba_skb->len: %d (%d)\n",
+ arvif->vdev_id, arvif->peer_id, ba_skb->len, ba_skb_len);*/
+
+ if ((cmd_id == WMI_CMD_UNSUPPORTED) ||
+ (! test_bit(ATH10K_FW_FEATURE_CONSUME_BLOCK_ACK_CT,
+ ar->running_fw->fw_file.fw_features)))
+ return -EOPNOTSUPP;
+
+ wskb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd) + round_up(ba_skb_len, 4));
+ if (!wskb)
+ return -ENOMEM;
+
+ cmd = (struct wmi_pdev_consume_block_ack *)wskb->data;
+ cmd->vdev_id = __cpu_to_le32(arvif->vdev_id);
+ cmd->skb_len = __cpu_to_le16(ba_skb_len);
+ cmd->flags = __cpu_to_le16(0);
+
+ memcpy(cmd->skb_data, ba_skb->data, ba_skb_len);
+
+ ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi consume block ack, vdev: %d peer: %d ba_skb->len: %d (%d)\n",
+ arvif->vdev_id, arvif->peer_id, ba_skb->len, ba_skb_len);
+
+ return ath10k_wmi_cmd_send(ar, wskb, cmd_id);
+}
+
static bool ath10k_ok_skip_ch_reservation(struct ath10k *ar, u32 vdev_id)
{
struct ath10k_vif *arvif;
@@ -2412,6 +2447,12 @@ static int ath10k_wmi_10_4_op_pull_mgmt_rx_ev(struct ath10k *ar,
static bool ath10k_wmi_rx_is_decrypted(struct ath10k *ar,
struct ieee80211_hdr *hdr)
{
+ /* If using rx-sw-crypt, it is not decrypted */
+ if (test_bit(ATH10K_FW_FEATURE_CT_RXSWCRYPT,
+ ar->running_fw->fw_file.fw_features) &&
+ ar->request_nohwcrypt)
+ return false;
+
if (!ieee80211_has_protected(hdr->frame_control))
return false;
@@ -2604,9 +2645,9 @@ int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb)
ath10k_mac_handle_beacon(ar, skb);
ath10k_dbg(ar, ATH10K_DBG_MGMT,
- "event mgmt rx skb %pK len %d ftype %02x stype %02x\n",
+ "event mgmt rx skb %pK len %d ftype %02x stype %02x decrypted: %d\n",
skb, skb->len,
- fc & IEEE80211_FCTL_FTYPE, fc & IEEE80211_FCTL_STYPE);
+ fc & IEEE80211_FCTL_FTYPE, fc & IEEE80211_FCTL_STYPE, ath10k_wmi_rx_is_decrypted(ar, hdr));
ath10k_dbg(ar, ATH10K_DBG_MGMT,
"event mgmt rx freq %d band %d snr %d chains: 0x%x(%d %d %d %d), rate_idx %d\n",
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h
index b8d908ab4709..106ebbdff196 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.h
+++ b/drivers/net/wireless/ath/ath10k/wmi.h
@@ -906,6 +906,7 @@ struct wmi_cmd_map {
u32 sta_keepalive_cmd;
u32 echo_cmdid;
u32 pdev_utf_cmdid;
+ u32 pdev_consume_block_ack_cmdid;
u32 dbglog_cfg_cmdid;
u32 pdev_qvit_cmdid;
u32 pdev_ftm_intg_cmdid;
@@ -1879,6 +1880,7 @@ enum wmi_10_4_cmd_id {
WMI_10_4_PDEV_SET_BRIDGE_MACADDR_CMDID,
WMI_10_4_ATF_GROUP_WMM_AC_CONFIG_REQUEST_CMDID,
WMI_10_4_RADAR_FOUND_CMDID,
+ WMI_10_4_PDEV_CONSUME_BLOCK_ACK_CMDID_CT = WMI_10_4_END_CMDID - 102, /* CT Specific Command ID */
WMI_10_4_PDEV_UTF_CMDID = WMI_10_4_END_CMDID - 1,
};
@@ -6657,6 +6659,13 @@ struct wmi_10_1_peer_assoc_complete_cmd_ct {
struct wmi_ct_assoc_overrides overrides;
} __packed;
+struct wmi_pdev_consume_block_ack {
+ __le32 vdev_id;
+ __le16 flags; /* currently unused, must be set to zero */
+ __le16 skb_len;
+ unsigned char skb_data[0]; /* skb contents are copied here, 200 bytes or less */
+};
+
#define WMI_PEER_ASSOC_INFO0_MAX_MCS_IDX_LSB 0
#define WMI_PEER_ASSOC_INFO0_MAX_MCS_IDX_MASK 0x0f
#define WMI_PEER_ASSOC_INFO0_MAX_NSS_LSB 4
@@ -7657,6 +7666,7 @@ void ath10k_wmi_tpc_config_get_rate_code(u8 *rate_code, u16 *pream_table,
u32 num_tx_chain);
void ath10k_wmi_event_tpc_final_table(struct ath10k *ar, struct sk_buff *skb);
void ath10k_wmi_stop_scan_work(struct work_struct *work);
+int ath10k_wmi_consume_block_ack(struct ath10k *ar, struct ath10k_vif *arvif, struct sk_buff *skb);
#ifdef CONFIG_ATH10K_DEBUGFS
/* TODO: Should really enable this all the time, not just when DEBUGFS is enabled. --Ben */
--
2.20.1
^ permalink raw reply related
* [RFC 1/2] mac80211: Support decrypting action frames for reinsertion into the driver.
From: greearb @ 2019-03-12 21:28 UTC (permalink / raw)
To: linux-wireless; +Cc: Ben Greear
From: Ben Greear <greearb@candelatech.com>
Some drivers, like ath10k-ct support rxswcrypt, but the firmware needs to
handle at least part of the blockack logic internally. Since firmware cannot
decode the frame in rxswcrypt mode, this patch adds a way for the driver to
request to be delivered the decrypted blockack action frames. The
driver can then re-insert the decrypted frame for proper handling.
Signed-off-by: Ben Greear <greearb@candelatech.com>
---
include/net/mac80211.h | 10 ++++++++++
net/mac80211/driver-ops.c | 9 +++++++++
net/mac80211/driver-ops.h | 3 +++
net/mac80211/iface.c | 7 +++++++
4 files changed, 29 insertions(+)
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 393501666820..0a49f683de57 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -3631,6 +3631,14 @@ enum ieee80211_reconfig_type {
* skb is always a real frame, head may or may not be an A-MSDU.
* @get_ftm_responder_stats: Retrieve FTM responder statistics, if available.
* Statistics should be cumulative, currently no way to reset is provided.
+ * @consume_block_ack: Offer block-ack management frames back to driver to see
+ * if it wishes to consume it. This can be useful for when firmware wants
+ * to handle block-ack logic itself, but PMF is used and the firmware
+ * cannot actually decode the block-ack frames itself. So, firmware can
+ * pass the encoded block-ack up the stack, and receive it through this
+ * callback. If return value is zero, the mac80211 stack will not further
+ * process the skb. skb will be freed by calling code, so driver must
+ * make a copy of anything it needs in the skb before returning.
*/
struct ieee80211_ops {
void (*tx)(struct ieee80211_hw *hw,
@@ -3917,6 +3925,8 @@ struct ieee80211_ops {
void (*del_nan_func)(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
u8 instance_id);
+ int (*consume_block_ack)(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif, struct sk_buff* skb);
bool (*can_aggregate_in_amsdu)(struct ieee80211_hw *hw,
struct sk_buff *head,
struct sk_buff *skb);
diff --git a/net/mac80211/driver-ops.c b/net/mac80211/driver-ops.c
index bb886e7db47f..0dc3b9606e01 100644
--- a/net/mac80211/driver-ops.c
+++ b/net/mac80211/driver-ops.c
@@ -52,6 +52,15 @@ void drv_stop(struct ieee80211_local *local)
local->started = false;
}
+int drv_consume_block_ack(struct ieee80211_local *local,
+ struct ieee80211_sub_if_data *sdata, struct sk_buff *skb)
+{
+ /*pr_warn("consume-block-ack: %p\n", local->ops->consume_block_ack);*/
+ if (local->ops->consume_block_ack)
+ return local->ops->consume_block_ack(&local->hw, &sdata->vif, skb);
+ return -EINVAL;
+}
+
int drv_add_interface(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata)
{
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index e019199f6f7b..de2ca3cd16e7 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -153,6 +153,9 @@ static inline void drv_set_wakeup(struct ieee80211_local *local,
}
#endif
+int drv_consume_block_ack(struct ieee80211_local *local,
+ struct ieee80211_sub_if_data *sdata, struct sk_buff *skb);
+
int drv_add_interface(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata);
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 03764e58db4c..0add6c47b8e3 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -1304,6 +1304,11 @@ static void ieee80211_iface_work(struct work_struct *work)
if (ieee80211_is_action(mgmt->frame_control) &&
mgmt->u.action.category == WLAN_CATEGORY_BACK) {
int len = skb->len;
+ int barv = drv_consume_block_ack(local, sdata, skb);
+
+ /*pr_err("called drv_consume_blockack, rv: %d\n", barv);*/
+ if (barv == 0)
+ goto done_skb_free;
mutex_lock(&local->sta_mtx);
sta = sta_info_get_bss(sdata, mgmt->sa);
@@ -1404,6 +1409,8 @@ static void ieee80211_iface_work(struct work_struct *work)
break;
}
+ done_skb_free:
+
kfree_skb(skb);
}
--
2.20.1
^ permalink raw reply related
* Re: [linuxwifi] [RFC] iwlwifi: enable TX AMPDU for some iwldvm
From: Grumbach, Emmanuel @ 2019-03-12 20:48 UTC (permalink / raw)
To: kevin@kevinlocke.name
Cc: linuxwifi, linux-wireless@vger.kernel.org, Coelho, Luciano
In-Reply-To: <20190312203101.GA19902@kevinolos>
On Tue, 2019-03-12 at 14:31 -0600, Kevin Locke wrote:
> Thanks Luca and Emmanuel,
>
> On Tue, 2019-03-12 at 19:47 +0000, Grumbach, Emmanuel wrote:
> > On Tue, 2019-03-12 at 21:38 +0200, Luciano Coelho wrote:
> > > If this feature was explicitly disabled, it certainly means that
> > > something was causing problems with it, so I'd be wary to enable
> > > it
> > > for all DVM devices.
> > >
> > > I guess we could enable it by default for devices that work fine,
> > > but
> > > we would have to run it in real life for a lot longer with a lot
> > > more
> > > different APs to be sure it won't cause any problems.
>
> Makes sense to me. I can start testing with available APs. Let me
> know if there is anything specific I should look for or catalog
> beyond
> latency, packet drop rates, and bandwidth.
>
> > > Emmanuel, do you happen to remember what was the issue, so Kevin
> > > could test that specific scenario with this specific NIC?
> >
> > long long nights of despair.
> >
> > We had issues with reclaim path upon BACK. This is of course a
> > firmware
> > problem...
>
> Does that suggest the issue may have been fixed by a firmware update?
> For reference, I'm currently using "firmware version 9.221.4.1 build
> 25532" from the firmware-iwlwifi Debian package (version 20190114-1).
>
> If it would be helpful, I could attempt to bisect the firmware
> revisions to find the one that fixed it (assuming I can reproduce the
> issue with a previous firmware version).
Well.. Sorry, I wasn't very "technical".
So the problem was really that we stopped getting BACK notifications
from the firmware and that caused a reclaim stall which in turn was
caught by a Tx queue stuck timer firing in the driver.
I was never able to reproduce this. What I can do is to enable A-MPDU
on my old system that has this same device, just to see what happens.
While chasing this bug, I even found another one which bought me a few
moments of fame:
commit d6ee27eb13beab94056e0de52d81220058ca2297
Author: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Date: Wed Jun 6 09:13:36 2012 +0200
iwlwifi: don't mess up the SCD when removing a key
and in the commit message of that very commit:
This doesn't seem to fix the higher queues that get stuck
from time to time.
There were no new versions of the firmware released since then.
I tried to skim through bugzilla, but couldn't find the bugs I was
handling then.
>
> Thanks again,
> Kevin
^ permalink raw reply
* Re: [linuxwifi] [RFC] iwlwifi: enable TX AMPDU for some iwldvm
From: Kevin Locke @ 2019-03-12 20:31 UTC (permalink / raw)
To: Grumbach, Emmanuel; +Cc: linuxwifi, linux-wireless, Coelho, Luciano
In-Reply-To: <1b6eaef941d3bc887a9fbedea47c2677e5511cdd.camel@intel.com>
Thanks Luca and Emmanuel,
On Tue, 2019-03-12 at 19:47 +0000, Grumbach, Emmanuel wrote:
> On Tue, 2019-03-12 at 21:38 +0200, Luciano Coelho wrote:
>> If this feature was explicitly disabled, it certainly means that
>> something was causing problems with it, so I'd be wary to enable it
>> for all DVM devices.
>>
>> I guess we could enable it by default for devices that work fine, but
>> we would have to run it in real life for a lot longer with a lot more
>> different APs to be sure it won't cause any problems.
Makes sense to me. I can start testing with available APs. Let me
know if there is anything specific I should look for or catalog beyond
latency, packet drop rates, and bandwidth.
>> Emmanuel, do you happen to remember what was the issue, so Kevin
>> could test that specific scenario with this specific NIC?
>
> long long nights of despair.
>
> We had issues with reclaim path upon BACK. This is of course a firmware
> problem...
Does that suggest the issue may have been fixed by a firmware update?
For reference, I'm currently using "firmware version 9.221.4.1 build
25532" from the firmware-iwlwifi Debian package (version 20190114-1).
If it would be helpful, I could attempt to bisect the firmware
revisions to find the one that fixed it (assuming I can reproduce the
issue with a previous firmware version).
Thanks again,
Kevin
^ permalink raw reply
* Re: [linuxwifi] [RFC] iwlwifi: enable TX AMPDU for some iwldvm
From: Grumbach, Emmanuel @ 2019-03-12 19:47 UTC (permalink / raw)
To: linuxwifi, linux-wireless@vger.kernel.org, kevin@kevinlocke.name,
Coelho, Luciano
In-Reply-To: <0f9132187a5567fa94e396ed317efbae1aa4de14.camel@intel.com>
On Tue, 2019-03-12 at 21:38 +0200, Luciano Coelho wrote:
> Hi Kevin,
>
> Johannes (johill) is also in this list. :)
>
> If this feature was explicitly disabled, it certainly means that
> something was causing problems with it, so I'd be wary to enable it
> for
> all DVM devices.
>
> I guess we could enable it by default for devices that work fine, but
> we would have to run it in real life for a lot longer with a lot more
> different APs to be sure it won't cause any problems.
>
> Emmanuel, do you happen to remember what was the issue, so Kevin
> could
> test that specific scenario with this specific NIC?
long long nights of despair.
We had issues with reclaim path upon BACK. This is of course a firmware
problem...
>
> Kevin, meanwhile you could add the option to your default module
> configuration so it would be used by default on your machine.
>
> --
> Cheers,
> Luca.
>
>
> On Tue, 2019-03-12 at 11:12 -0600, Kevin Locke wrote:
> > Hi Wireless Developers,
> >
> > I have a Lenovo ThinkPad T430 (2342-CTO) with an Intel Centrino
> > Ultimate-N 6300 (8086:4238) wireless card. With the help of
> > Reventlov
> > and johill on #linux-wireless, we discovered that enabling TX
> > AMPDU,
> > by passing module option 11n_disable=8 (IWL_ENABLE_HT_TXAGG) to
> > iwlwifi, increased TCP throughput significantly:
> >
> > With an ASUS RT-ACRH13 AP and `iperf3 -s` running on a server with
> > a
> > 1Gbps wired connection, `iperf3 -R -c` on the ThinkPad increased
> > from
> > 63.2 to 104 Mbits/sec (using MCS 15 40MHz short GI). With a
> > Buffalo
> > WZR-600DHP running OpenWRT, `iperf3 -R -c` increased from 63.2 to
> > 76.9.
> >
> > TX AMPDU was disabled by default for all iwldvm cards in
> > 205e2210daa9
> > because "iwldvm don't handle well TX AMPDU". However, I have been
> > using this configuration for >2 weeks without any issues or
> > measurable
> > change in ping times to the AP. Are there any other potential
> > side-effects I can check?
> >
> > Would it be possible to enable TX AMPDU by default for at least
> > some
> > of these cards? If so, what additional information would be
> > required?
> >
> > Thanks for considering,
> > Kevin
> > -------------------------------------
> > linuxwifi@eclists.intel.com
> > https://eclists.intel.com/sympa/info/linuxwifi
> > Unsubscribe by sending email to sympa@eclists.intel.com with
> > subject
> > "Unsubscribe linuxwifi"
>
>
^ permalink raw reply
* Re: [linuxwifi] [RFC] iwlwifi: enable TX AMPDU for some iwldvm
From: Luciano Coelho @ 2019-03-12 19:38 UTC (permalink / raw)
To: Kevin Locke, linuxwifi, linux-wireless; +Cc: Emmanuel Grumbach
In-Reply-To: <20190312171205.GA12792@kevinolos>
Hi Kevin,
Johannes (johill) is also in this list. :)
If this feature was explicitly disabled, it certainly means that
something was causing problems with it, so I'd be wary to enable it for
all DVM devices.
I guess we could enable it by default for devices that work fine, but
we would have to run it in real life for a lot longer with a lot more
different APs to be sure it won't cause any problems.
Emmanuel, do you happen to remember what was the issue, so Kevin could
test that specific scenario with this specific NIC?
Kevin, meanwhile you could add the option to your default module
configuration so it would be used by default on your machine.
--
Cheers,
Luca.
On Tue, 2019-03-12 at 11:12 -0600, Kevin Locke wrote:
> Hi Wireless Developers,
>
> I have a Lenovo ThinkPad T430 (2342-CTO) with an Intel Centrino
> Ultimate-N 6300 (8086:4238) wireless card. With the help of
> Reventlov
> and johill on #linux-wireless, we discovered that enabling TX AMPDU,
> by passing module option 11n_disable=8 (IWL_ENABLE_HT_TXAGG) to
> iwlwifi, increased TCP throughput significantly:
>
> With an ASUS RT-ACRH13 AP and `iperf3 -s` running on a server with a
> 1Gbps wired connection, `iperf3 -R -c` on the ThinkPad increased from
> 63.2 to 104 Mbits/sec (using MCS 15 40MHz short GI). With a Buffalo
> WZR-600DHP running OpenWRT, `iperf3 -R -c` increased from 63.2 to
> 76.9.
>
> TX AMPDU was disabled by default for all iwldvm cards in 205e2210daa9
> because "iwldvm don't handle well TX AMPDU". However, I have been
> using this configuration for >2 weeks without any issues or
> measurable
> change in ping times to the AP. Are there any other potential
> side-effects I can check?
>
> Would it be possible to enable TX AMPDU by default for at least some
> of these cards? If so, what additional information would be
> required?
>
> Thanks for considering,
> Kevin
> -------------------------------------
> linuxwifi@eclists.intel.com
> https://eclists.intel.com/sympa/info/linuxwifi
> Unsubscribe by sending email to sympa@eclists.intel.com with subject
> "Unsubscribe linuxwifi"
^ permalink raw reply
* [PATCH 2/2] rt2x00: enable experimental MFP with HW crypt
From: Tomislav Požega @ 2019-03-12 19:11 UTC (permalink / raw)
To: linux-wireless; +Cc: kvalo, sgruszka, daniel, Tomislav Po�ega
In-Reply-To: <1552417902-11040-1-git-send-email-pozega.tomislav@gmail.com>
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=UTF-8, Size: 1885 bytes --]
MFP can work with enabled HW crypt engine, but in this case
available bandwidth is reduced at least when connecting to
Archer C7 (QCA9558). Enable the feature for known to work chipsets-
MT7620, RT3070 and RT5390. Userspace setting for ieee80211w should
default to 0 in order to prevent unintentional bandwidth drop.
Signed-off-by: Tomislav Po¸ega <pozega.tomislav@gmail.com>
---
drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 11 +++++++----
1 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
index a03b528..bb8204d 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
@@ -9326,6 +9326,13 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
ieee80211_hw_set(rt2x00dev->hw, SIGNAL_DBM);
ieee80211_hw_set(rt2x00dev->hw, SUPPORTS_PS);
+ /* Experimental: Set MFP with HW crypto enabled. */
+ if (rt2x00_rt(rt2x00dev, RT3070) || rt2x00_rt(rt2x00dev, RT5390) ||
+ rt2x00_rt(rt2x00dev, RT6352))
+ ieee80211_hw_set(rt2x00dev->hw, MFP_CAPABLE);
+ else /* Set MFP if HW crypto is disabled. */
+ if (rt2800_hwcrypt_disabled(rt2x00dev))
+ ieee80211_hw_set(rt2x00dev->hw, MFP_CAPABLE);
/*
* Don't set IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING for USB devices
* unless we are capable of sending the buffered frames out after the
@@ -9336,10 +9343,6 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
if (!rt2x00_is_usb(rt2x00dev))
ieee80211_hw_set(rt2x00dev->hw, HOST_BROADCAST_PS_BUFFERING);
- /* Set MFP if HW crypto is disabled. */
- if (rt2800_hwcrypt_disabled(rt2x00dev))
- ieee80211_hw_set(rt2x00dev->hw, MFP_CAPABLE);
-
SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev);
SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,
rt2800_eeprom_addr(rt2x00dev,
--
1.7.0.4
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox