Stop Dell from throttling CPU with power adapter

I've done some investigation into this and found that there's probably no good way to prevent recent Dell laptops from throttling the CPU when it doesn't detect an OEM AC adapter (or one with a broken data pin.)

Disabling SpeedStep or "additional sleep modes" or messing with the power profiles in the BIOS makes no difference. The "Intel Extreme Tuning" utility doesn't seem to support these motherboards as all overclocking options are locked out, but when a non-OEM charger is connected up it reports that CPU thermal throttling is engaged, and CPU-Z shows the FSB multiplier down to 5x and the core voltage at 0.6 volts.

My guess is that perhaps the BIOS is designed to send false motherboard temperature readings to the CPU when a non-OEM adapter is detected, causing it to throttle. It seems Dell was very serious about locking you in to OEM adapters when they designed this system.

Edit: I found a utility that will allow you to disable the unknown adapter throttling, under Windows at least (I don't know yet if the utility will work under Linux, or if there is something similar.) ThrottleStop has a checkbox called "BD PROCHOT" which causes the CPU core voltage and multiplier to reset to normal when disabled. Apparently this is a "2 way signal path to the CPU. It allows other components in a laptop like the motherboard or GPU to send a signal to the CPU which tricks the CPU into thinking it is too hot", confirming that the way this "feature" is implemented by the BIOS is through sending this signal to the CPU when an unknown AC adapter is detected.


Here's an OS-independent program you can compile with a C compiler/GCC (so long as it has an implementation of asprintf available) and set to run automatically at system startup which should disable the throttling on these Intel-based laptops, I've used this successfully on a Dell Inspiron 5558 laptop running Xubuntu with root privilege for the program, with "msrtools" installed and "modprobe msr" in the startup file prior to program execution, to allow reading and writing the MSR-registers from the user side (other OS may require different commands for "const char* cmd" to read/write to processor register location 0x1FC and will likely require root/privileged user access for the executable whatever form that may take)

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

#define BUFSIZE (64)

int get_msr_value(uint64_t* reg_value) {
  const char* cmd = "rdmsr -u 0x1FC";
  char cmd_buf[BUFSIZE];

  FILE* fp;

  if ((fp = popen(cmd, "r")) == NULL) {
    printf("Error opening pipe!\n");
    return -1;
  }

  cmd_buf[strcspn(fgets(cmd_buf, BUFSIZE, fp), "\n")] = 0;
  *reg_value = atoi(cmd_buf);

  if (pclose(fp)) {
    printf("Command not found or exited with error status\n");
    return -1;
  }

  return 0;
}

int main(void) {
  const char* cmd = "wrmsr -a 0x1FC";
  char* concat_cmd;
  int ret;
  uint64_t* reg_value = &(uint64_t){0};

  if ((ret = get_msr_value(reg_value))) {
    return ret;
  }

  printf("Old register value: %lu\n", *reg_value);

  *reg_value = *reg_value & 0xFFFFFFFE;  // clear bit 0

  printf("New register value: %lu\n", *reg_value);

  if (asprintf(&concat_cmd, "%s %i", cmd, *reg_value) == -1)
    return -1;

  printf("Executing: %s\n", concat_cmd);

  system(concat_cmd);
  free(concat_cmd);

  return 0;
}