-
-
Save drvink/7fc4ff8698bd1f55c56ebe40bb20c644 to your computer and use it in GitHub Desktop.
Revisions
-
glandium revised this gist
Sep 21, 2020 . 1 changed file with 18 additions and 7 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -47,12 +47,19 @@ void on_write_msr(void *data, unsigned int msr, u64 val, int failed) } } static int install_probe(void) { return !boot_cpu_has(X86_FEATURE_AMD_SSBD) && !boot_cpu_has(X86_FEATURE_VIRT_SSBD); } static int enable_zen_workaround(void) { if (install_probe()) { int ret = tracepoint_probe_register(&__tracepoint_write_msr, on_write_msr, NULL); if (ret) { pr_err("Registering tracepoint probe failed\n"); return ret; } } do_zen_workaround(set_speclockmap_disable); return 0; @@ -68,7 +75,9 @@ static int pm_notification(struct notifier_block *this, unsigned long event, voi break; case PM_HIBERNATION_PREPARE: case PM_SUSPEND_PREPARE: if (install_probe()) { tracepoint_probe_unregister(&__tracepoint_write_msr, on_write_msr, NULL); } break; } return NOTIFY_DONE; @@ -80,7 +89,7 @@ static struct notifier_block pm_notifier = { static int __init zen_workaround_init(void) { if (!boot_cpu_has(X86_FEATURE_ZEN)) { pr_err("Cannot use the Zen workaround on a non-Zen CPU\n"); return -EINVAL; } @@ -93,7 +102,9 @@ module_init(zen_workaround_init); static void __exit zen_workaround_exit(void) { unregister_pm_notifier(&pm_notifier); if (install_probe()) { tracepoint_probe_unregister(&__tracepoint_write_msr, on_write_msr, NULL); } do_zen_workaround(unset_speclockmap_disable); } module_exit(zen_workaround_exit); -
glandium revised this gist
Sep 21, 2020 . 1 changed file with 40 additions and 12 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,5 +1,6 @@ #include <linux/module.h> #include <linux/tracepoint.h> #include <linux/suspend.h> #define MODULE_NAME "zen_workaround" @@ -33,40 +34,67 @@ static void edit_ls_cfg_on_cpu(void *info) } } static void do_zen_workaround(edit_msr_func_t edit_msr) { smp_call_function(edit_ls_cfg_on_cpu, edit_msr, 1); edit_ls_cfg_on_cpu(edit_msr); } void on_write_msr(void *data, unsigned int msr, u64 val, int failed) { if (msr == MSR_AMD64_LS_CFG && !(val & SPECLOCKMAP_DISABLE)) { native_wrmsrl(MSR_AMD64_LS_CFG, set_speclockmap_disable(val)); } } static int enable_zen_workaround(void) { int ret = tracepoint_probe_register(&__tracepoint_write_msr, on_write_msr, NULL); if (ret) { pr_err("Registering tracepoint probe failed\n"); return ret; } do_zen_workaround(set_speclockmap_disable); return 0; } static int pm_notification(struct notifier_block *this, unsigned long event, void *ptr) { switch (event) { case PM_POST_SUSPEND: case PM_POST_HIBERNATION: case PM_POST_RESTORE: enable_zen_workaround(); break; case PM_HIBERNATION_PREPARE: case PM_SUSPEND_PREPARE: tracepoint_probe_unregister(&__tracepoint_write_msr, on_write_msr, NULL); break; } return NOTIFY_DONE; } static struct notifier_block pm_notifier = { .notifier_call = pm_notification, }; static int __init zen_workaround_init(void) { if (!static_cpu_has(X86_FEATURE_ZEN)) { pr_err("Cannot use the Zen workaround on a non-Zen CPU\n"); return -EINVAL; } enable_zen_workaround(); register_pm_notifier(&pm_notifier); return 0; } module_init(zen_workaround_init); static void __exit zen_workaround_exit(void) { unregister_pm_notifier(&pm_notifier); tracepoint_probe_unregister(&__tracepoint_write_msr, on_write_msr, NULL); do_zen_workaround(unset_speclockmap_disable); } module_exit(zen_workaround_exit); -
glandium revised this gist
Sep 21, 2020 . 1 changed file with 17 additions and 58 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,31 +1,16 @@ #include <linux/module.h> #include <linux/tracepoint.h> #define MODULE_NAME "zen_workaround" #define SPECLOCKMAP_DISABLE BIT_64(54) u64 set_speclockmap_disable(u64 msr) { return msr | SPECLOCKMAP_DISABLE; } u64 unset_speclockmap_disable(u64 msr) { return msr & ~SPECLOCKMAP_DISABLE; } typedef u64 (*edit_msr_func_t)(u64); @@ -50,55 +35,28 @@ static void edit_ls_cfg_on_cpu(void *info) static int do_zen_workaround(edit_msr_func_t edit_msr) { smp_call_function(edit_ls_cfg_on_cpu, edit_msr, 1); edit_ls_cfg_on_cpu(edit_msr); return 0; } void on_write_msr(void *data, unsigned int msr, u64 val, int failed) { if (msr == MSR_AMD64_LS_CFG && !(val & SPECLOCKMAP_DISABLE)) { native_wrmsrl(MSR_AMD64_LS_CFG, set_speclockmap_disable(val)); } } static int __init zen_workaround_init(void) { int ret; if (!static_cpu_has(X86_FEATURE_ZEN)) { pr_err("Cannot use the Zen workaround on a non-Zen CPU\n"); return -EINVAL; } ret = tracepoint_probe_register(&__tracepoint_write_msr, on_write_msr, NULL); if (ret) { pr_err("Registering tracepoint probe failed\n"); return ret; } return do_zen_workaround(set_speclockmap_disable); @@ -108,7 +66,8 @@ module_init(zen_workaround_init); static void __exit zen_workaround_exit(void) { do_zen_workaround(unset_speclockmap_disable); tracepoint_probe_unregister(&__tracepoint_write_msr, on_write_msr, NULL); } module_exit(zen_workaround_exit); MODULE_LICENSE("GPL"); -
glandium revised this gist
Sep 19, 2020 . 1 changed file with 2 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -50,9 +50,9 @@ static void edit_ls_cfg_on_cpu(void *info) static int do_zen_workaround(edit_msr_func_t edit_msr) { if (boot_cpu_has(X86_FEATURE_LS_CFG_SSBD)) { int ret; u64 old_value = *x86_amd_ls_cfg_base_ptr; u64 new_value = edit_msr(old_value); *kernel_set_to_readonly_ptr = 0; -
glandium revised this gist
Sep 19, 2020 . 2 changed files with 121 additions and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1 +1,7 @@ obj-m = zen_workaround.o all: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules clean: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,114 @@ #include <linux/module.h> #include <linux/kallsyms.h> #define MODULE_NAME "zen_workaround" typedef int set_memory_fn_t(unsigned long, int); unsigned long need_symbol(const char *name) { unsigned long sym = kallsyms_lookup_name(name); if (sym) { pr_info("%s is 0x%lx\n", name, sym); } else { pr_err("could not find kernel symbol %s\n", name); } return sym; } static set_memory_fn_t *set_memory_ro, *set_memory_rw; static _Atomic u64 *x86_amd_ls_cfg_base_ptr; static _Atomic int *kernel_set_to_readonly_ptr; u64 set_speclockmap_disable(u64 msr) { return msr | BIT_64(54); } u64 unset_speclockmap_disable(u64 msr) { return msr & ~BIT_64(54); } typedef u64 (*edit_msr_func_t)(u64); static void edit_ls_cfg_on_cpu(void *info) { int cpu = get_cpu(); u64 value = 0; if (!rdmsrl_safe(MSR_AMD64_LS_CFG, &value)) { edit_msr_func_t edit_msr = (edit_msr_func_t) info; u64 new_value = edit_msr(value); if (!wrmsrl_safe(MSR_AMD64_LS_CFG, new_value)) { pr_info("MSR_AMD64_LS_CFG for cpu %d was 0x%llx, setting to 0x%llx\n", cpu, value, new_value); } else { pr_err("MSR_AMD64_LS_CFG for cpu %d was 0x%llx, setting to 0x%llx failed\n", cpu, value, new_value); } } } static int do_zen_workaround(edit_msr_func_t edit_msr) { u64 old_value = *x86_amd_ls_cfg_base_ptr; if (old_value) { int ret; u64 new_value = edit_msr(old_value); *kernel_set_to_readonly_ptr = 0; ret = set_memory_rw((unsigned long)x86_amd_ls_cfg_base_ptr, 1); *kernel_set_to_readonly_ptr = 1; if (ret) { pr_err("set_memory_rw failed with %d\n", ret); return -EPERM; } *x86_amd_ls_cfg_base_ptr = new_value; pr_info("x86_amd_ls_cfg_base was 0x%llx, setting to 0x%llx\n", old_value, new_value); *kernel_set_to_readonly_ptr = 0; ret = set_memory_ro((unsigned long)x86_amd_ls_cfg_base_ptr, 1); *kernel_set_to_readonly_ptr = 1; if (ret) { pr_err("set_memory_ro failed with %d\n", ret); // Not returning early because we still presumably set x86_amd_ls_cfg_base. } } else { pr_info("x86_amd_ls_cfg_base is unused."); } smp_call_function(edit_ls_cfg_on_cpu, edit_msr, 1); edit_ls_cfg_on_cpu(edit_msr); return 0; } static int __init zen_workaround_init(void) { if (!static_cpu_has(X86_FEATURE_ZEN)) { pr_err("Cannot use the Zen workaround on a non-Zen CPU\n"); return -EINVAL; } set_memory_ro = (set_memory_fn_t*) need_symbol("set_memory_ro"); set_memory_rw = (set_memory_fn_t*) need_symbol("set_memory_rw"); x86_amd_ls_cfg_base_ptr = (_Atomic u64*) need_symbol("x86_amd_ls_cfg_base"); kernel_set_to_readonly_ptr = (_Atomic int*) need_symbol("kernel_set_to_readonly"); if (!set_memory_ro || !set_memory_rw || !x86_amd_ls_cfg_base_ptr || !kernel_set_to_readonly_ptr) { return -ENOENT; } return do_zen_workaround(set_speclockmap_disable); } module_init(zen_workaround_init); static void __exit zen_workaround_exit(void) { do_zen_workaround(unset_speclockmap_disable); } module_exit(zen_workaround_exit) MODULE_LICENSE("GPL"); -
glandium created this gist
Sep 19, 2020 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1 @@ obj-m = zen_workaround.o