├── contrib ├── systemd │ ├── ryzen-stabilizator.target │ ├── ryzen-stabilizator@boot.service │ ├── ryzen-stabilizator@resume.service │ └── ryzen-stabilizator.service └── settings.toml.sample ├── aslr └── aslr.go ├── boosting └── boosting.go ├── README.md ├── c6 └── c6.go ├── main.go └── LICENSE /contrib/systemd/ryzen-stabilizator.target: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Ryzen Stabilizator Tabajara 3 | Requires=ryzen-stabilizator.service ryzen-stabilizator@boot.service ryzen-stabilizator@resume.service 4 | -------------------------------------------------------------------------------- /contrib/systemd/ryzen-stabilizator@boot.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Ryzen Stabilizator Tabajara - Boot 3 | PartOf=ryzen-stabilizator.target 4 | 5 | [Service] 6 | Type=simple 7 | User=root 8 | Group=root 9 | ExecStart=/usr/bin/ryzen-stabilizator --config=/etc/ryzen-stabilizator/settings.toml 10 | 11 | [Install] 12 | WantedBy=multi-user.target 13 | -------------------------------------------------------------------------------- /contrib/systemd/ryzen-stabilizator@resume.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Ryzen Stabilizator Tabajara - Resume 3 | After=suspend.target 4 | PartOf=ryzen-stabilizator.target 5 | 6 | [Service] 7 | Type=simple 8 | User=root 9 | Group=root 10 | ExecStart=/usr/bin/ryzen-stabilizator --config=/etc/ryzen-stabilizator/settings.toml 11 | 12 | [Install] 13 | WantedBy=suspend.target 14 | -------------------------------------------------------------------------------- /contrib/systemd/ryzen-stabilizator.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Ryzen Stabilizator Tabajara 3 | PartOf=ryzen-stabilizator.target 4 | 5 | [Service] 6 | Type=simple 7 | User=root 8 | Group=root 9 | ExecStart=/usr/bin/logger Ryzen Stabilizator Tabajara 10 | 11 | [Install] 12 | WantedBy=multi-user.target ryzen-stabilizator.target 13 | Also=ryzen-stabilizator@boot.service 14 | Also=ryzen-stabilizator@resume.service 15 | -------------------------------------------------------------------------------- /contrib/settings.toml.sample: -------------------------------------------------------------------------------- 1 | # Configuration file for Ryzen Stabilizator Tabajara. 2 | # 3 | # The allowed keys are `c6' to refer to the C6 C-state, `boosting', to refer 4 | # to processor boosting, `aslr', to refer to address space layout randomization 5 | # (ASLR), and `psicworkaround', to refer to the power supply idle control 6 | # workaround. The accepted values are either "enabled" or "disabled". 7 | # 8 | # If they (keys) are not mentioned, ryzen-stabilizator will not do anything with 9 | # regard to them. 10 | # 11 | # 12 | # E.g.: 13 | # 14 | # boosting = "disable" 15 | # 16 | # In the above case, we only define the `bosting' key, and hence it indicates 17 | # that we should disable processor boosting. Nothing will be done with regard to 18 | # C6 C-state, ASLR, or the power supply workaround. 19 | # 20 | # As for the power supply idle control workaround, it seems to disable just C6 21 | # c-state package, not core. So, if you disable C6 (`c6 = "disable"'), the 22 | # power supply idle workaround will show as enabled, as ryzen-stabilizator will 23 | # disable both core and package C6 24 | # 25 | # To tell ryzen-stabilizator to use this config file, you can do the following: 26 | # ryzen-stabilizator --config= 27 | # 28 | # 29 | #aslr = "disable" 30 | #c6 = "disable" 31 | #boosting = "disable" 32 | psicworkaround = "enable" 33 | 34 | # vim:set ts=2 sw=2 et: 35 | -------------------------------------------------------------------------------- /aslr/aslr.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Sergio Correia 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | package aslr 15 | 16 | import ( 17 | "io/ioutil" 18 | "strings" 19 | ) 20 | 21 | const ( 22 | aslrControlFile = "/proc/sys/kernel/randomize_va_space" 23 | ) 24 | 25 | // changeASLR receives a parameter indicating whether it should enable or 26 | // disable address space layout randomization (ASLR). 27 | func changeASLR(enable bool) error { 28 | // Following info from https://askubuntu.com/a/318476. 29 | // 0 - no randomization. Everything is static. 30 | // 1 - conservative randomization. Shared libraries, stack, mmap(), VDSO and 31 | // heap are randomized. 32 | // 2 - full randomization. In addition to elements listed in the previous 33 | // point, memory managed through brk() is also randomized. 34 | // We enable by setting full randomization (2), and disable with no 35 | // randomization (0). 36 | value := []byte("0") 37 | if enable { 38 | value = []byte("2") 39 | } 40 | return ioutil.WriteFile(aslrControlFile, value, 0644) 41 | } 42 | 43 | // Enabled returns a boolean indicating whether ASLR is enabled or not. 44 | func Enabled() (bool, error) { 45 | value, err := ioutil.ReadFile(aslrControlFile) 46 | if err != nil { 47 | return false, err 48 | } 49 | 50 | enabled := true 51 | if strings.Trim(string(value), "\n") == "0" { 52 | enabled = false 53 | } 54 | return enabled, nil 55 | } 56 | 57 | // Disabled returns a boolean indicating whether ASLR is disabled. 58 | func Disabled() (bool, error) { 59 | enabled, err := Enabled() 60 | if err != nil { 61 | return false, err 62 | } 63 | return !enabled, nil 64 | } 65 | 66 | // Enable enables ASLR. 67 | func Enable() error { 68 | // We pass `true' to enable ASLR. 69 | return changeASLR(true) 70 | } 71 | 72 | // Disable disables ASLR. 73 | func Disable() error { 74 | // We pass `false' to disable ASLR. 75 | return changeASLR(false) 76 | } 77 | -------------------------------------------------------------------------------- /boosting/boosting.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Sergio Correia 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | package boosting 15 | 16 | import ( 17 | "io/ioutil" 18 | "os" 19 | "strings" 20 | ) 21 | 22 | const ( 23 | boostingControlFile = "/sys/devices/system/cpu/cpufreq/boost" 24 | ) 25 | 26 | // changeProcessorBoosting receives a parameter indicating whether it should 27 | // enable or disable processor boosting. 28 | func changeProcessorBoosting(enable bool) error { 29 | value := []byte("0") 30 | if enable { 31 | value = []byte("1") 32 | } 33 | return ioutil.WriteFile(boostingControlFile, value, 0644) 34 | } 35 | 36 | // Available returns a boolean indicating whether we have boosting control 37 | // available or not. Disabling AMD Cool'n'Quiet, for instance, prevents cpufreq 38 | // module from loading, which in turn, makes boosting control unavailable. 39 | func Available() bool { 40 | if _, err := os.Stat(boostingControlFile); err == nil { 41 | return true 42 | } 43 | return false 44 | } 45 | 46 | // Enabled returns a boolean indicating whether processor boosting is enabled 47 | // or not. 48 | func Enabled() (bool, error) { 49 | value, err := ioutil.ReadFile(boostingControlFile) 50 | if err != nil { 51 | return false, err 52 | } 53 | 54 | enabled := true 55 | if strings.Trim(string(value), "\n") == "0" { 56 | enabled = false 57 | } 58 | return enabled, nil 59 | } 60 | 61 | // Disabled returns a boolean indicating whether processor boosting is 62 | // disabled. 63 | func Disabled() (bool, error) { 64 | enabled, err := Enabled() 65 | if err != nil { 66 | return false, err 67 | } 68 | return !enabled, nil 69 | } 70 | 71 | // Enable enables processor boosting. 72 | func Enable() error { 73 | // We pass `true' to enable boosting. 74 | return changeProcessorBoosting(true) 75 | } 76 | 77 | // Disable disables processor boosting. 78 | func Disable() error { 79 | // We pass `false' to disable boosting. 80 | return changeProcessorBoosting(false) 81 | } 82 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Ryzen Stabilizator Tabajara 2 | 3 | Simple Go program to enable/disable C6 C-state, processor boosting, address space layout randomization (ASLR) and the Power Supply Idle Control workaround on an AMD Ryzen processor, in order to help with the infamous "MCE-random-reboots-while-idle" issue. 4 | 5 | Code licensed under Apache License 2.0. 6 | 7 | ## Basic usage: 8 | 9 | ### Check status of C6 C-state, processor boosting, ASLR and Power Supply Idle Control workaround: 10 | ``` 11 | Ryzen Stabilizator Tabajara unspecified/git version 12 | Copyright (C) 2018 Sergio Correia 13 | 14 | 15 | Power Supply Idle Control workaround is ENABLED. 16 | C6 C-state is ENABLED. 17 | ASLR is ENABLED. 18 | Processor boosting is ENABLED. 19 | ``` 20 | 21 | ### Enable C6 C-state: 22 | ``` 23 | sudo ./ryzen-stabilizator --enable-c6 24 | Ryzen Stabilizator Tabajara unspecified/git version 25 | Copyright (C) 2018 Sergio Correia 26 | 27 | Enabling C6 C-state: SUCCESS 28 | 29 | Power Supply Idle Control workaround is DISABLED. 30 | C6 C-state is ENABLED. 31 | ASLR is ENABLED. 32 | Processor boosting is ENABLED. 33 | 34 | ``` 35 | 36 | ### Disable C6 C-state: 37 | ``` 38 | sudo ./ryzen-stabilizator --disable-c6 39 | Ryzen Stabilizator Tabajara unspecified/git version 40 | Copyright (C) 2018 Sergio Correia 41 | 42 | Disabling C6 C-state: SUCCESS 43 | 44 | Power Supply Idle Control workaround is ENABLED. 45 | C6 C-state is DISABLED. 46 | ASLR is ENABLED. 47 | Processor boosting is ENABLED. 48 | ``` 49 | 50 | ### Enable processor boosting: 51 | ``` 52 | sudo ./ryzen-stabilizator --enable-boosting 53 | Ryzen Stabilizator Tabajara unspecified/git version 54 | Copyright (C) 2018 Sergio Correia 55 | 56 | Enabling processor boosting: SUCCESS 57 | 58 | Power Supply Idle Control workaround is ENABLED. 59 | C6 C-state is DISABLED. 60 | ASLR is ENABLED. 61 | Processor boosting is ENABLED. 62 | ``` 63 | 64 | ### Disable processor boosting: 65 | ``` 66 | sudo ./ryzen-stabilizator --disable-boosting 67 | Ryzen Stabilizator Tabajara unspecified/git version 68 | Copyright (C) 2018 Sergio Correia 69 | 70 | Disabling processor boosting: SUCCESS 71 | 72 | Power Supply Idle Control workaround is ENABLED. 73 | C6 C-state is DISABLED. 74 | ASLR is ENABLED. 75 | Processor boosting is DISABLED. 76 | ``` 77 | 78 | ### Enable address space layout randomization (ASLR): 79 | ``` 80 | sudo ./ryzen-stabilizator --enable-aslr 81 | Ryzen Stabilizator Tabajara unspecified/git version 82 | Copyright (C) 2018 Sergio Correia 83 | 84 | Enabling address space layout randomization (ASLR): SUCCESS 85 | 86 | Power Supply Idle Control workaround is ENABLED. 87 | C6 C-state is DISABLED. 88 | ASLR is ENABLED. 89 | Processor boosting is DISABLED. 90 | ``` 91 | 92 | ### Disable address space layout randomization (ASLR): 93 | ``` 94 | sudo ./ryzen-stabilizator --disable-aslr 95 | Ryzen Stabilizator Tabajara unspecified/git version 96 | Copyright (C) 2018 Sergio Correia 97 | 98 | Disabling address space layout randomization (ASLR): SUCCESS 99 | 100 | Power Supply Idle Control workaround is ENABLED. 101 | C6 C-state is DISABLED. 102 | ASLR is DISABLED. 103 | Processor boosting is DISABLED. 104 | ``` 105 | 106 | ### Enable Power Supply Idle Control workaround: 107 | ``` 108 | sudo ./ryzen-stabilizator --enable-psicworkaround 109 | Ryzen Stabilizator Tabajara unspecified/git version 110 | Copyright (C) 2018 Sergio Correia 111 | 112 | Enabling Power Supply Idle Control workaround: SUCCESS 113 | 114 | Power Supply Idle Control workaround is ENABLED. 115 | C6 C-state is DISABLED. 116 | ASLR is DISABLED. 117 | Processor boosting is DISABLED. 118 | ``` 119 | 120 | ### Disable Power Supply Idle Control workaround: 121 | ``` 122 | sudo ./ryzen-stabilizator --disable-psicworkaround 123 | Ryzen Stabilizator Tabajara unspecified/git version 124 | Copyright (C) 2018 Sergio Correia 125 | 126 | Disabling Power Supply Idle Control Workaround: SUCCESS 127 | 128 | Power Supply Idle Control workaround is DISABLED. 129 | C6 C-state is ENABLED. 130 | ASLR is DISABLED. 131 | Processor boosting is DISABLED. 132 | ``` 133 | -------------------------------------------------------------------------------- /c6/c6.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Sergio Correia 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | package c6 15 | 16 | import ( 17 | "encoding/binary" 18 | "fmt" 19 | "os" 20 | "runtime" 21 | ) 22 | 23 | // ryzenC6MSR stores the offset and target bit of a given feature. MSR stands 24 | // for model-specific register. 25 | type ryzenC6MSR struct { 26 | offset int64 27 | bit uint64 28 | } 29 | 30 | var ( 31 | // msr has info for core and package C6, a C-state (idle power saving 32 | // state). Magic numbers for the MSR obtained from ZenStates-Linux project 33 | // available at https://github.com/r4m0n/ZenStates-Linux. 34 | msr = []ryzenC6MSR{ 35 | // C6 package. 36 | {0xC0010292, 1 << 32}, 37 | // C6 core. 38 | {0xC0010296, (1 << 22) | (1 << 14) | (1 << 6)}, 39 | } 40 | ) 41 | 42 | // readMSR reads the MSR of a given CPU at a given offset. 43 | func readMSR(offset int64, cpu int) (uint64, error) { 44 | fname := fmt.Sprintf("/dev/cpu/%d/msr", cpu) 45 | f, err := os.OpenFile(fname, os.O_RDONLY, 0666) 46 | if err != nil { 47 | return 0, err 48 | } 49 | defer f.Close() 50 | 51 | data := make([]byte, 8) 52 | if _, err = f.ReadAt(data, offset); err != nil { 53 | return 0, err 54 | } 55 | return binary.LittleEndian.Uint64(data), nil 56 | } 57 | 58 | // writeMSR writes a value to a specific CPU MSR at a given offset. 59 | func writeMSR(offset int64, cpu int, value uint64) error { 60 | fname := fmt.Sprintf("/dev/cpu/%d/msr", cpu) 61 | f, err := os.OpenFile(fname, os.O_WRONLY, 0666) 62 | if err != nil { 63 | return err 64 | } 65 | defer f.Close() 66 | 67 | data := make([]byte, 8) 68 | binary.LittleEndian.PutUint64(data, value) 69 | _, err = f.WriteAt(data, offset) 70 | return err 71 | } 72 | 73 | // changePackageC6 either enables or disables the C6 package C-state, depending 74 | // on whether the provided parameter is true or false, respectively. 75 | func changePackageC6(enable bool) error { 76 | // msr[0] is C6 Package. 77 | m := msr[0] 78 | cpus := runtime.NumCPU() 79 | value := m.bit 80 | if !enable { 81 | value = ^(m.bit) 82 | } 83 | for c := 0; c < cpus; c++ { 84 | if err := writeMSR(m.offset, c, value); err != nil { 85 | return err 86 | } 87 | } 88 | return nil 89 | } 90 | 91 | // changeC6 either enables or disables the C6 (both core and package) C-state, 92 | // depending on whether the provided parameter is true or false, respectively. 93 | func changeC6(enable bool) error { 94 | cpus := runtime.NumCPU() 95 | for _, m := range msr { 96 | value := m.bit 97 | if !enable { 98 | value = ^(m.bit) 99 | } 100 | for c := 0; c < cpus; c++ { 101 | if err := writeMSR(m.offset, c, value); err != nil { 102 | return err 103 | } 104 | } 105 | } 106 | return nil 107 | } 108 | 109 | // c6PackageEnabled returns true or false dependending on whether C6 c-state 110 | // (Package) is enabled or not, respectively. This seems to be what the 111 | // workaround labeled "Power Supply Idle Control" -- available at some 112 | // BIOS/AGESA -- seems to disable, when such option is set to "Typical Current 113 | // Idle". 114 | func c6PackageEnabled() (bool, error) { 115 | // msr[0] is C6 Package. 116 | m := msr[0] 117 | cpus := runtime.NumCPU() 118 | for c := 0; c < cpus; c++ { 119 | data, err := readMSR(m.offset, c) 120 | if err != nil { 121 | return false, err 122 | } 123 | if data&(m.bit) == m.bit { 124 | return true, nil 125 | } 126 | } 127 | return false, nil 128 | } 129 | 130 | // c6Enable returns true or false depending on whether C6 C-state is enabled or 131 | // disabled, respectively. This considers both core and package. If either of 132 | // them is enabled for any processor, it returns true. 133 | func c6Enabled() (bool, error) { 134 | cpus := runtime.NumCPU() 135 | for c := 0; c < cpus; c++ { 136 | for _, m := range msr { 137 | data, err := readMSR(m.offset, c) 138 | if err != nil { 139 | return false, err 140 | } 141 | if data&(m.bit) == m.bit { 142 | return true, nil 143 | } 144 | } 145 | } 146 | return false, nil 147 | } 148 | 149 | // Available returns a boolean indicating whether we have C6 C-state control 150 | // available or not. We require the `msr' module for it to be available. 151 | func Available() bool { 152 | if _, err := os.Stat("/dev/cpu/0/msr"); err == nil { 153 | return true 154 | } 155 | return false 156 | } 157 | 158 | // PackageEnable enables C6 C-state (Package). 159 | func PackageEnable() error { 160 | // Passing true to indicate we want C6 enabled. 161 | return changePackageC6(true) 162 | } 163 | 164 | // PackageDisable disables C6 C-state (Package). 165 | func PackageDisable() error { 166 | // Passing false to indicate we want C6 disabled. 167 | return changePackageC6(false) 168 | } 169 | 170 | // Enable enables C6 C-state. 171 | func Enable() error { 172 | // Passing true to indicate we want C6 enabled. 173 | return changeC6(true) 174 | } 175 | 176 | // Disable disables C6 C-state. 177 | func Disable() error { 178 | // Passing false to indicate we want C6 disabled. 179 | return changeC6(false) 180 | } 181 | 182 | // Enabled returns true if C6 C-state is enabled. 183 | func Enabled() (bool, error) { 184 | return c6Enabled() 185 | } 186 | 187 | // PackageEnabled returns true if C6 C-state (Package) is enabled. 188 | func PackageEnabled() (bool, error) { 189 | return c6PackageEnabled() 190 | } 191 | 192 | // Disabled returns true if C6 C-state is disabled. 193 | func Disabled() (bool, error) { 194 | enabled, err := c6Enabled() 195 | if err != nil { 196 | return false, err 197 | } 198 | return !enabled, nil 199 | } 200 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Sergio Correia 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | package main 15 | 16 | import ( 17 | "flag" 18 | "fmt" 19 | "io/ioutil" 20 | "os" 21 | "runtime" 22 | "strings" 23 | 24 | "github.com/BurntSushi/toml" 25 | "github.com/klauspost/cpuid" 26 | "github.com/qrwteyrutiyoup/ryzen-stabilizator/aslr" 27 | "github.com/qrwteyrutiyoup/ryzen-stabilizator/boosting" 28 | "github.com/qrwteyrutiyoup/ryzen-stabilizator/c6" 29 | ) 30 | 31 | const ( 32 | program = "Ryzen Stabilizator Tabajara" 33 | copyright = "Copyright (C) 2018 Sergio Correia " 34 | 35 | // The family number for Zen processors. 36 | amdZenFamily = 0x17 37 | ) 38 | 39 | var ( 40 | version = "unspecified/git version" 41 | ) 42 | 43 | // rsSettings contains definitions for C6 C-state, processor boosting, address 44 | // space layout randomization (ASLR) and power supply idle control workaround 45 | // (PSIC Workaround). All these parameters are "string" and accept as values 46 | // `enabled' and `disabled'. 47 | type rsSettings struct { 48 | C6 string `toml:"c6"` 49 | Boosting string `toml:"boosting"` 50 | ASLR string `toml:"aslr"` 51 | PSICWorkaround string `toml:"psicworkaround"` 52 | } 53 | 54 | // sanityCheck performs a few checks to be sure we should be running this 55 | // program. 56 | func sanityCheck() error { 57 | switch { 58 | // Check if we are running Linux. 59 | case runtime.GOOS != "linux": 60 | return fmt.Errorf("this program can only run under Linux") 61 | // Check if we are running on an AMD processor. 62 | case cpuid.CPU.VendorID != cpuid.AMD: 63 | return fmt.Errorf("this is not an AMD processor") 64 | // Check if it is the right family, 17h (Zen). 65 | case cpuid.CPU.Family != amdZenFamily: 66 | return fmt.Errorf("wrong family of AMD processors; expected 23 (17h), got %d", cpuid.CPU.Family) 67 | // Check if we are running as root. 68 | case os.Geteuid() != 0: 69 | return fmt.Errorf("you need to be root to use this program") 70 | } 71 | return nil 72 | } 73 | 74 | // disablePSICWorkaround disables Power Supply Idle Control workaround. 75 | func disablePSICWorkaround() { 76 | if !c6.Available() { 77 | fmt.Println("Power Supply Idle Control workaround unavailable - check if msr module loaded.") 78 | return 79 | } 80 | 81 | fmt.Printf("Disabling Power Supply Idle Control Workaround: ") 82 | err := c6.PackageEnable() 83 | if err != nil { 84 | fmt.Printf("oops: %v\n", err) 85 | return 86 | } 87 | fmt.Println("SUCCESS") 88 | } 89 | 90 | // enablePSICWorkaround enables Power Supply Idle Control workaround. 91 | func enablePSICWorkaround() { 92 | if !c6.Available() { 93 | fmt.Println("Power Supply Idle Control workaround unavailable - check if msr module loaded.") 94 | return 95 | } 96 | 97 | fmt.Printf("Enabling Power Supply Idle Control workaround: ") 98 | err := c6.PackageDisable() 99 | if err != nil { 100 | fmt.Printf("oops: %v\n", err) 101 | return 102 | } 103 | fmt.Println("SUCCESS") 104 | } 105 | 106 | // disableC6 disables C6 C-state. 107 | func disableC6() { 108 | if !c6.Available() { 109 | fmt.Println("C6 C-state control unavailable - check if msr module loaded.") 110 | return 111 | } 112 | 113 | fmt.Printf("Disabling C6 C-state: ") 114 | err := c6.Disable() 115 | if err != nil { 116 | fmt.Printf("oops: %v\n", err) 117 | return 118 | } 119 | fmt.Println("SUCCESS") 120 | } 121 | 122 | // enableC6 enables C6 C-state. 123 | func enableC6() { 124 | if !c6.Available() { 125 | fmt.Println("C6 C-state control unavailable - check if msr module loaded.") 126 | return 127 | } 128 | 129 | fmt.Printf("Enabling C6 C-state: ") 130 | err := c6.Enable() 131 | if err != nil { 132 | fmt.Printf("oops: %v\n", err) 133 | return 134 | } 135 | fmt.Println("SUCCESS") 136 | } 137 | 138 | // disableBoosting disables processor boosting. 139 | func disableBoosting() { 140 | if !boosting.Available() { 141 | fmt.Println("Processor boosting unavailable - check if AMD Cool'n'Quiet enabled and cpufreq module loaded.") 142 | return 143 | } 144 | 145 | fmt.Printf("Disabling processor boosting: ") 146 | err := boosting.Disable() 147 | if err != nil { 148 | fmt.Printf("oops: %v\n", err) 149 | return 150 | } 151 | fmt.Println("SUCCESS") 152 | } 153 | 154 | // enableBoosting enables processor boosting. 155 | func enableBoosting() { 156 | if !boosting.Available() { 157 | fmt.Println("Processor boosting unavailable - check if AMD Cool'n'Quiet enabled and cpufreq module loaded.") 158 | return 159 | } 160 | 161 | fmt.Printf("Enabling processor boosting: ") 162 | err := boosting.Enable() 163 | if err != nil { 164 | fmt.Printf("oops: %v\n", err) 165 | return 166 | } 167 | fmt.Println("SUCCESS") 168 | } 169 | 170 | // disableASLR disables address space layout randomization (ASLR). 171 | func disableASLR() { 172 | fmt.Printf("Disabling address space layout randomization (ASLR): ") 173 | err := aslr.Disable() 174 | if err != nil { 175 | fmt.Printf("oops: %v\n", err) 176 | return 177 | } 178 | fmt.Println("SUCCESS") 179 | } 180 | 181 | // enableASLR enables address space layout randomization (ASLR). 182 | func enableASLR() { 183 | fmt.Printf("Enabling address space layout randomization (ASLR): ") 184 | err := aslr.Enable() 185 | if err != nil { 186 | fmt.Printf("oops: %v\n", err) 187 | return 188 | } 189 | fmt.Println("SUCCESS") 190 | } 191 | 192 | // showStatus displays the current status, if available, of C6 C-state, 193 | // processor boosting and address space layout randomization (ASLR). 194 | func showStatus() { 195 | fmt.Println("") 196 | if c6.Available() { 197 | psStatus := "Power Supply Idle Control workaround is ENABLED." 198 | psEnabled, err := c6.PackageEnabled() 199 | if err == nil { 200 | if psEnabled { 201 | psStatus = "Power Supply Idle Control workaround is DISABLED." 202 | } 203 | } else { 204 | psStatus = fmt.Sprintf("Error while obtaining status of Power Supply Idle Control workaround: %v", err) 205 | } 206 | fmt.Println(psStatus) 207 | } 208 | 209 | if c6.Available() { 210 | c6Status := "C6 C-state is DISABLED." 211 | c6Enabled, err := c6.Enabled() 212 | if err == nil { 213 | if c6Enabled { 214 | c6Status = "C6 C-state is ENABLED." 215 | } 216 | } else { 217 | c6Status = fmt.Sprintf("Error while obtaining status of C6 C-state: %v", err) 218 | } 219 | fmt.Println(c6Status) 220 | } 221 | 222 | aslrStatus := "ASLR is DISABLED." 223 | aslrEnabled, err := aslr.Enabled() 224 | if err == nil { 225 | if aslrEnabled { 226 | aslrStatus = "ASLR is ENABLED." 227 | } 228 | } else { 229 | aslrStatus = fmt.Sprintf("Error while obtaining status of ASLR: %v", err) 230 | } 231 | fmt.Println(aslrStatus) 232 | 233 | if boosting.Available() { 234 | boostingEnabled, err := boosting.Enabled() 235 | boostingStatus := "Processor boosting is DISABLED." 236 | if err == nil { 237 | if boostingEnabled { 238 | boostingStatus = "Processor boosting is ENABLED." 239 | } 240 | } else { 241 | boostingStatus = fmt.Sprintf("Error while obtaining status of processor boosting: %v", err) 242 | } 243 | fmt.Println(boostingStatus) 244 | } 245 | } 246 | 247 | func handleConfigurationFile(configFile string) { 248 | settings := rsSettings{} 249 | 250 | // Reading and parsing the configuration file provided. 251 | buf, err := ioutil.ReadFile(configFile) 252 | if err != nil { 253 | fmt.Printf("Error: unable to read contents of config file %q: %v.\n", configFile, err) 254 | return 255 | } 256 | 257 | if _, err = toml.Decode(string(buf), &settings); err != nil { 258 | fmt.Printf("Error: problem parsing config file %q: %v.\n\n", configFile, err) 259 | return 260 | } 261 | 262 | // Now we perform the actions indicated by the config file. 263 | fmt.Printf("Config file: %q\n", configFile) 264 | switch strings.ToLower(settings.C6) { 265 | case "enable": 266 | enableC6() 267 | case "disable": 268 | disableC6() 269 | } 270 | switch strings.ToLower(settings.PSICWorkaround) { 271 | case "enable": 272 | enablePSICWorkaround() 273 | case "disable": 274 | disablePSICWorkaround() 275 | } 276 | switch strings.ToLower(settings.Boosting) { 277 | case "enable": 278 | enableBoosting() 279 | case "disable": 280 | disableBoosting() 281 | } 282 | switch strings.ToLower(settings.ASLR) { 283 | case "enable": 284 | enableASLR() 285 | case "disable": 286 | disableASLR() 287 | } 288 | 289 | // Current status of both C6 C-state and processor boosting. 290 | showStatus() 291 | } 292 | 293 | func main() { 294 | fmt.Printf("%s %s\n%s\n\n", program, version, copyright) 295 | 296 | err := sanityCheck() 297 | if err != nil { 298 | fmt.Printf("Error: %v.\n", err) 299 | return 300 | } 301 | 302 | configFilePtr := flag.String("config", "", "ryzen-stabilizator config file") 303 | enablePSICWorkaroundPtr := flag.Bool("enable-psicworkaround", false, "Enable Power Supply Idle Control Workaround") 304 | disablePSICWorkaroundPtr := flag.Bool("disable-psicworkaround", false, "Disable Power Supply Idle Control Workaround") 305 | enableC6Ptr := flag.Bool("enable-c6", false, "Enable C6 C-state") 306 | disableC6Ptr := flag.Bool("disable-c6", false, "Disable C6 C-state") 307 | enableBoostingPtr := flag.Bool("enable-boosting", false, "Enable processor boosting") 308 | disableBoostingPtr := flag.Bool("disable-boosting", false, "Disable processor boosting") 309 | enableASLRPtr := flag.Bool("enable-aslr", false, "Enable address space layout randomization (ASLR)") 310 | disableASLRPtr := flag.Bool("disable-aslr", false, "Disable address space layout randomization (ASLR)") 311 | 312 | flag.Parse() 313 | 314 | // Handle config file with associated profile. 315 | if *configFilePtr != "" { 316 | handleConfigurationFile(*configFilePtr) 317 | return 318 | } 319 | 320 | // Regular handling of command-line arguments, if we are not using config 321 | // file with predefined profiles. 322 | // C6. 323 | switch { 324 | case *disableC6Ptr: 325 | disableC6() 326 | case *enableC6Ptr: 327 | enableC6() 328 | } 329 | 330 | // Power Supply Idle Control Workaround. 331 | switch { 332 | case *disablePSICWorkaroundPtr: 333 | disablePSICWorkaround() 334 | case *enablePSICWorkaroundPtr: 335 | enablePSICWorkaround() 336 | } 337 | 338 | // Boosting. 339 | switch { 340 | case *disableBoostingPtr: 341 | disableBoosting() 342 | case *enableBoostingPtr: 343 | enableBoosting() 344 | } 345 | 346 | // ASLR. 347 | switch { 348 | case *disableASLRPtr: 349 | disableASLR() 350 | case *enableASLRPtr: 351 | enableASLR() 352 | } 353 | 354 | // Current status of both C6 C-state and processor boosting. 355 | showStatus() 356 | } 357 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | --------------------------------------------------------------------------------