mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-05 16:37:50 +00:00
Add a sysctl to control the split lock misery mode
-----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEV76QKkVc4xCGURexaDWVMHDJkrAFAmOXYlcACgkQaDWVMHDJ krB+IQ//fLNzHnNmTaFq3TlmF9HiJ926uCu2C3MMma0g8NlFXGLTbeI/UaaER12/ m/N4d+/WPSO1PnsMR36f10Byr8PN2fpbJHGMsHtZ4Y4MTnGycM6JxjDYeFuaSPB5 Cw2IRsO6c7X/dWEVW7hLbHhlG4MpsiX9APt2/PBGpGJm88wL1RDosMKst6430UQK 24JZtFbdyaPnUlo48ql85VkGtdgFHXRnebhM0sX95bVWdSLvNWUSpQAyETp+U9rn CH75pnoKcJspKun5FmdN2n3gix8Rumz8OZuv9e4XAfBl94H4OZ+SeRN4YbKUvzJP PtSCz7PT8VQNsJVCA58TQ+QdmhtKsT4ia0ylDvMhHiozzjUNeeS54qJQSUyPLOqK dBl4hl6BmGMMH2fAZGeoxVmVZMIdLaE0PBECjBEuPAG15IqlxQwTdSeyo0k+S0wV wYUtCqmxOItW3TA8y044zDjCcIN6wiFymBJtjKbAMxz54ONfnUqgAUluXLeE3xim 8UqL/uM869Ptu6sDO6sfROd1K8EA3KXrsmOGZV7s9hp+qGQcxsvUDhePT9EosS/G JcmYspV211FO2fTAAOiCe5SJRkoPw/lRWufjNNNWWd3mawJhDeYujZ2fQAxEThC+ Mf8FyFsbxOdbJ1UatgWs/iLOnVwMJf/E1hraq7mdRuZHbNQm7H4= =yyO+ -----END PGP SIGNATURE----- Merge tag 'x86_splitlock_for_6.2' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip Pull x86 splitlock updates from Dave Hansen: "Add a sysctl to control the split lock misery mode. This enables users to reduce the penalty inflicted on split lock users. There are some proprietary, binary-only games which became entirely unplayable with the old penalty. Anyone opting into the new mode is, of course, more exposed to the DoS nasitness inherent with split locks, but they can play their games again" * tag 'x86_splitlock_for_6.2' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86/split_lock: Add sysctl to control the misery mode
This commit is contained in:
commit
1cab145a94
2 changed files with 76 additions and 10 deletions
|
@ -1314,6 +1314,29 @@ watchdog work to be queued by the watchdog timer function, otherwise the NMI
|
||||||
watchdog — if enabled — can detect a hard lockup condition.
|
watchdog — if enabled — can detect a hard lockup condition.
|
||||||
|
|
||||||
|
|
||||||
|
split_lock_mitigate (x86 only)
|
||||||
|
==============================
|
||||||
|
|
||||||
|
On x86, each "split lock" imposes a system-wide performance penalty. On larger
|
||||||
|
systems, large numbers of split locks from unprivileged users can result in
|
||||||
|
denials of service to well-behaved and potentially more important users.
|
||||||
|
|
||||||
|
The kernel mitigates these bad users by detecting split locks and imposing
|
||||||
|
penalties: forcing them to wait and only allowing one core to execute split
|
||||||
|
locks at a time.
|
||||||
|
|
||||||
|
These mitigations can make those bad applications unbearably slow. Setting
|
||||||
|
split_lock_mitigate=0 may restore some application performance, but will also
|
||||||
|
increase system exposure to denial of service attacks from split lock users.
|
||||||
|
|
||||||
|
= ===================================================================
|
||||||
|
0 Disable the mitigation mode - just warns the split lock on kernel log
|
||||||
|
and exposes the system to denials of service from the split lockers.
|
||||||
|
1 Enable the mitigation mode (this is the default) - penalizes the split
|
||||||
|
lockers with intentional performance degradation.
|
||||||
|
= ===================================================================
|
||||||
|
|
||||||
|
|
||||||
stack_erasing
|
stack_erasing
|
||||||
=============
|
=============
|
||||||
|
|
||||||
|
|
|
@ -1034,8 +1034,32 @@ static const struct {
|
||||||
|
|
||||||
static struct ratelimit_state bld_ratelimit;
|
static struct ratelimit_state bld_ratelimit;
|
||||||
|
|
||||||
|
static unsigned int sysctl_sld_mitigate = 1;
|
||||||
static DEFINE_SEMAPHORE(buslock_sem);
|
static DEFINE_SEMAPHORE(buslock_sem);
|
||||||
|
|
||||||
|
#ifdef CONFIG_PROC_SYSCTL
|
||||||
|
static struct ctl_table sld_sysctls[] = {
|
||||||
|
{
|
||||||
|
.procname = "split_lock_mitigate",
|
||||||
|
.data = &sysctl_sld_mitigate,
|
||||||
|
.maxlen = sizeof(unsigned int),
|
||||||
|
.mode = 0644,
|
||||||
|
.proc_handler = proc_douintvec_minmax,
|
||||||
|
.extra1 = SYSCTL_ZERO,
|
||||||
|
.extra2 = SYSCTL_ONE,
|
||||||
|
},
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
static int __init sld_mitigate_sysctl_init(void)
|
||||||
|
{
|
||||||
|
register_sysctl_init("kernel", sld_sysctls);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
late_initcall(sld_mitigate_sysctl_init);
|
||||||
|
#endif
|
||||||
|
|
||||||
static inline bool match_option(const char *arg, int arglen, const char *opt)
|
static inline bool match_option(const char *arg, int arglen, const char *opt)
|
||||||
{
|
{
|
||||||
int len = strlen(opt), ratelimit;
|
int len = strlen(opt), ratelimit;
|
||||||
|
@ -1146,12 +1170,20 @@ static void split_lock_init(void)
|
||||||
split_lock_verify_msr(sld_state != sld_off);
|
split_lock_verify_msr(sld_state != sld_off);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __split_lock_reenable(struct work_struct *work)
|
static void __split_lock_reenable_unlock(struct work_struct *work)
|
||||||
{
|
{
|
||||||
sld_update_msr(true);
|
sld_update_msr(true);
|
||||||
up(&buslock_sem);
|
up(&buslock_sem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static DECLARE_DELAYED_WORK(sl_reenable_unlock, __split_lock_reenable_unlock);
|
||||||
|
|
||||||
|
static void __split_lock_reenable(struct work_struct *work)
|
||||||
|
{
|
||||||
|
sld_update_msr(true);
|
||||||
|
}
|
||||||
|
static DECLARE_DELAYED_WORK(sl_reenable, __split_lock_reenable);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If a CPU goes offline with pending delayed work to re-enable split lock
|
* If a CPU goes offline with pending delayed work to re-enable split lock
|
||||||
* detection then the delayed work will be executed on some other CPU. That
|
* detection then the delayed work will be executed on some other CPU. That
|
||||||
|
@ -1169,10 +1201,9 @@ static int splitlock_cpu_offline(unsigned int cpu)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static DECLARE_DELAYED_WORK(split_lock_reenable, __split_lock_reenable);
|
|
||||||
|
|
||||||
static void split_lock_warn(unsigned long ip)
|
static void split_lock_warn(unsigned long ip)
|
||||||
{
|
{
|
||||||
|
struct delayed_work *work;
|
||||||
int cpu;
|
int cpu;
|
||||||
|
|
||||||
if (!current->reported_split_lock)
|
if (!current->reported_split_lock)
|
||||||
|
@ -1180,14 +1211,26 @@ static void split_lock_warn(unsigned long ip)
|
||||||
current->comm, current->pid, ip);
|
current->comm, current->pid, ip);
|
||||||
current->reported_split_lock = 1;
|
current->reported_split_lock = 1;
|
||||||
|
|
||||||
/* misery factor #1, sleep 10ms before trying to execute split lock */
|
if (sysctl_sld_mitigate) {
|
||||||
|
/*
|
||||||
|
* misery factor #1:
|
||||||
|
* sleep 10ms before trying to execute split lock.
|
||||||
|
*/
|
||||||
if (msleep_interruptible(10) > 0)
|
if (msleep_interruptible(10) > 0)
|
||||||
return;
|
return;
|
||||||
/* Misery factor #2, only allow one buslocked disabled core at a time */
|
/*
|
||||||
|
* Misery factor #2:
|
||||||
|
* only allow one buslocked disabled core at a time.
|
||||||
|
*/
|
||||||
if (down_interruptible(&buslock_sem) == -EINTR)
|
if (down_interruptible(&buslock_sem) == -EINTR)
|
||||||
return;
|
return;
|
||||||
|
work = &sl_reenable_unlock;
|
||||||
|
} else {
|
||||||
|
work = &sl_reenable;
|
||||||
|
}
|
||||||
|
|
||||||
cpu = get_cpu();
|
cpu = get_cpu();
|
||||||
schedule_delayed_work_on(cpu, &split_lock_reenable, 2);
|
schedule_delayed_work_on(cpu, work, 2);
|
||||||
|
|
||||||
/* Disable split lock detection on this CPU to make progress */
|
/* Disable split lock detection on this CPU to make progress */
|
||||||
sld_update_msr(false);
|
sld_update_msr(false);
|
||||||
|
|
Loading…
Reference in a new issue