From 65eb9cbb289c7465cb19a772986ccaf87bf02f3e Mon Sep 17 00:00:00 2001
From: Zach Hilman <zachhilman@gmail.com>
Date: Fri, 28 Jun 2019 22:43:51 -0400
Subject: [PATCH 1/6] apm: Add Controller class to manage speed data and
 application

---
 src/core/CMakeLists.txt                 |  2 +
 src/core/hle/service/apm/controller.cpp | 68 ++++++++++++++++++++++++
 src/core/hle/service/apm/controller.h   | 70 +++++++++++++++++++++++++
 3 files changed, 140 insertions(+)
 create mode 100644 src/core/hle/service/apm/controller.cpp
 create mode 100644 src/core/hle/service/apm/controller.h

diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index d65659b44e..0a922430fd 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -207,6 +207,8 @@ add_library(core STATIC
     hle/service/aoc/aoc_u.h
     hle/service/apm/apm.cpp
     hle/service/apm/apm.h
+    hle/service/apm/controller.cpp
+    hle/service/apm/controller.h
     hle/service/apm/interface.cpp
     hle/service/apm/interface.h
     hle/service/audio/audctl.cpp
diff --git a/src/core/hle/service/apm/controller.cpp b/src/core/hle/service/apm/controller.cpp
new file mode 100644
index 0000000000..4376612ebe
--- /dev/null
+++ b/src/core/hle/service/apm/controller.cpp
@@ -0,0 +1,68 @@
+// Copyright 2019 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "common/logging/log.h"
+#include "core/core_timing.h"
+#include "core/hle/service/apm/controller.h"
+#include "core/settings.h"
+
+namespace Service::APM {
+
+constexpr PerformanceConfiguration DEFAULT_PERFORMANCE_CONFIGURATION =
+    PerformanceConfiguration::Config7;
+
+Controller::Controller(Core::Timing::CoreTiming& core_timing)
+    : core_timing(core_timing), configs{
+                                    {PerformanceMode::Handheld, DEFAULT_PERFORMANCE_CONFIGURATION},
+                                    {PerformanceMode::Docked, DEFAULT_PERFORMANCE_CONFIGURATION},
+                                } {}
+
+Controller::~Controller() = default;
+
+void Controller::SetPerformanceConfiguration(PerformanceMode mode,
+                                             PerformanceConfiguration config) {
+    static const std::map<PerformanceConfiguration, u32> PCONFIG_TO_SPEED_MAP{
+        {PerformanceConfiguration::Config1, 1020},  {PerformanceConfiguration::Config2, 1020},
+        {PerformanceConfiguration::Config3, 1224},  {PerformanceConfiguration::Config4, 1020},
+        {PerformanceConfiguration::Config5, 1020},  {PerformanceConfiguration::Config6, 1224},
+        {PerformanceConfiguration::Config7, 1020},  {PerformanceConfiguration::Config8, 1020},
+        {PerformanceConfiguration::Config9, 1020},  {PerformanceConfiguration::Config10, 1020},
+        {PerformanceConfiguration::Config11, 1020}, {PerformanceConfiguration::Config12, 1020},
+        {PerformanceConfiguration::Config13, 1785}, {PerformanceConfiguration::Config14, 1785},
+        {PerformanceConfiguration::Config15, 1020}, {PerformanceConfiguration::Config16, 1020},
+    };
+
+    SetClockSpeed(PCONFIG_TO_SPEED_MAP.find(config)->second);
+    configs.insert_or_assign(mode, config);
+}
+
+void Controller::SetFromCpuBoostMode(CpuBoostMode mode) {
+    constexpr std::array<PerformanceConfiguration, 3> BOOST_MODE_TO_CONFIG_MAP{{
+        PerformanceConfiguration::Config7,
+        PerformanceConfiguration::Config13,
+        PerformanceConfiguration::Config15,
+    }};
+
+    SetPerformanceConfiguration(PerformanceMode::Docked,
+                                BOOST_MODE_TO_CONFIG_MAP.at(static_cast<u32>(mode)));
+}
+
+PerformanceMode Controller::GetCurrentPerformanceMode() {
+    return Settings::values.use_docked_mode ? PerformanceMode::Docked : PerformanceMode::Handheld;
+}
+
+PerformanceConfiguration Controller::GetCurrentPerformanceConfiguration(PerformanceMode mode) {
+    if (configs.find(mode) == configs.end()) {
+        configs.insert_or_assign(mode, DEFAULT_PERFORMANCE_CONFIGURATION);
+    }
+
+    return configs[mode];
+}
+
+void Controller::SetClockSpeed(u32 mhz) {
+    LOG_INFO(Service_APM, "called, mhz={:08X}", mhz);
+    // TODO(DarkLordZach): Actually signal core_timing to change clock speed.
+}
+
+} // namespace Service::APM
diff --git a/src/core/hle/service/apm/controller.h b/src/core/hle/service/apm/controller.h
new file mode 100644
index 0000000000..8ac80eaea1
--- /dev/null
+++ b/src/core/hle/service/apm/controller.h
@@ -0,0 +1,70 @@
+// Copyright 2019 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <map>
+#include "common/common_types.h"
+
+namespace Core::Timing {
+class CoreTiming;
+}
+
+namespace Service::APM {
+
+enum class PerformanceConfiguration : u32 {
+    Config1 = 0x00010000,
+    Config2 = 0x00010001,
+    Config3 = 0x00010002,
+    Config4 = 0x00020000,
+    Config5 = 0x00020001,
+    Config6 = 0x00020002,
+    Config7 = 0x00020003,
+    Config8 = 0x00020004,
+    Config9 = 0x00020005,
+    Config10 = 0x00020006,
+    Config11 = 0x92220007,
+    Config12 = 0x92220008,
+    Config13 = 0x92220009,
+    Config14 = 0x9222000A,
+    Config15 = 0x9222000B,
+    Config16 = 0x9222000C,
+};
+
+enum class CpuBoostMode : u32 {
+    Disabled = 0,
+    Full = 1,    // CPU + GPU -> Config 13, 14, 15, or 16
+    Partial = 2, // GPU Only -> Config 15 or 16
+};
+
+enum class PerformanceMode : u8 {
+    Handheld = 0,
+    Docked = 1,
+};
+
+// Class to manage the state and change of the emulated system performance.
+// Specifically, this deals with PerformanceMode, which corresponds to the system being docked or
+// undocked, and PerformanceConfig which specifies the exact CPU, GPU, and Memory clocks to operate
+// at. Additionally, this manages 'Boost Mode', which allows games to temporarily overclock the
+// system during times of high load -- this simply maps to different PerformanceConfigs to use.
+class Controller {
+public:
+    Controller(Core::Timing::CoreTiming& core_timing);
+    ~Controller();
+
+    void SetPerformanceConfiguration(PerformanceMode mode, PerformanceConfiguration config);
+    void SetFromCpuBoostMode(CpuBoostMode mode);
+
+    PerformanceMode GetCurrentPerformanceMode();
+    PerformanceConfiguration GetCurrentPerformanceConfiguration(PerformanceMode mode);
+
+private:
+    void SetClockSpeed(u32 mhz);
+
+    std::map<PerformanceMode, PerformanceConfiguration> configs;
+
+    Core::Timing::CoreTiming& core_timing;
+};
+
+} // namespace Service::APM

From 9175b00e7dba90e05ad2d9ae2a81644791da5998 Mon Sep 17 00:00:00 2001
From: Zach Hilman <zachhilman@gmail.com>
Date: Fri, 28 Jun 2019 22:44:30 -0400
Subject: [PATCH 2/6] apm: Add apm:am service 8.0.0+ identical version of apm

---
 src/core/hle/service/apm/apm.cpp | 13 ++++++++-----
 src/core/hle/service/apm/apm.h   |  7 +------
 2 files changed, 9 insertions(+), 11 deletions(-)

diff --git a/src/core/hle/service/apm/apm.cpp b/src/core/hle/service/apm/apm.cpp
index f3c09bbb1a..85bbf59887 100644
--- a/src/core/hle/service/apm/apm.cpp
+++ b/src/core/hle/service/apm/apm.cpp
@@ -2,7 +2,6 @@
 // Licensed under GPLv2 or any later version
 // Refer to the license.txt file included.
 
-#include "common/logging/log.h"
 #include "core/hle/ipc_helpers.h"
 #include "core/hle/service/apm/apm.h"
 #include "core/hle/service/apm/interface.h"
@@ -12,11 +11,15 @@ namespace Service::APM {
 Module::Module() = default;
 Module::~Module() = default;
 
-void InstallInterfaces(SM::ServiceManager& service_manager) {
+void InstallInterfaces(Core::System& system) {
     auto module_ = std::make_shared<Module>();
-    std::make_shared<APM>(module_, "apm")->InstallAsService(service_manager);
-    std::make_shared<APM>(module_, "apm:p")->InstallAsService(service_manager);
-    std::make_shared<APM_Sys>()->InstallAsService(service_manager);
+    std::make_shared<APM>(module_, system.GetAPMController(), "apm")
+        ->InstallAsService(system.ServiceManager());
+    std::make_shared<APM>(module_, system.GetAPMController(), "apm:p")
+        ->InstallAsService(system.ServiceManager());
+    std::make_shared<APM>(module_, system.GetAPMController(), "apm:am")
+        ->InstallAsService(system.ServiceManager());
+    std::make_shared<APM_Sys>(system.GetAPMController())->InstallAsService(system.ServiceManager());
 }
 
 } // namespace Service::APM
diff --git a/src/core/hle/service/apm/apm.h b/src/core/hle/service/apm/apm.h
index 4d7d5bb7c3..cf4c2bb111 100644
--- a/src/core/hle/service/apm/apm.h
+++ b/src/core/hle/service/apm/apm.h
@@ -8,11 +8,6 @@
 
 namespace Service::APM {
 
-enum class PerformanceMode : u8 {
-    Handheld = 0,
-    Docked = 1,
-};
-
 class Module final {
 public:
     Module();
@@ -20,6 +15,6 @@ public:
 };
 
 /// Registers all AM services with the specified service manager.
-void InstallInterfaces(SM::ServiceManager& service_manager);
+void InstallInterfaces(Core::System& system);
 
 } // namespace Service::APM

From 1c6e6305eab7a6e98a73d9ba5cdb880ac74d9116 Mon Sep 17 00:00:00 2001
From: Zach Hilman <zachhilman@gmail.com>
Date: Fri, 28 Jun 2019 22:45:31 -0400
Subject: [PATCH 3/6] apm: Add getters for performance config and mode

---
 src/core/hle/service/apm/interface.cpp | 70 ++++++++++++++------------
 src/core/hle/service/apm/interface.h   | 12 ++++-
 2 files changed, 49 insertions(+), 33 deletions(-)

diff --git a/src/core/hle/service/apm/interface.cpp b/src/core/hle/service/apm/interface.cpp
index d058c0245a..b2241366f5 100644
--- a/src/core/hle/service/apm/interface.cpp
+++ b/src/core/hle/service/apm/interface.cpp
@@ -5,43 +5,32 @@
 #include "common/logging/log.h"
 #include "core/hle/ipc_helpers.h"
 #include "core/hle/service/apm/apm.h"
+#include "core/hle/service/apm/controller.h"
 #include "core/hle/service/apm/interface.h"
 
 namespace Service::APM {
 
 class ISession final : public ServiceFramework<ISession> {
 public:
-    ISession() : ServiceFramework("ISession") {
+    ISession(Controller& controller) : ServiceFramework("ISession"), controller(controller) {
         static const FunctionInfo functions[] = {
             {0, &ISession::SetPerformanceConfiguration, "SetPerformanceConfiguration"},
             {1, &ISession::GetPerformanceConfiguration, "GetPerformanceConfiguration"},
+            {2, nullptr, "SetCpuOverclockEnabled"},
         };
         RegisterHandlers(functions);
     }
 
 private:
-    enum class PerformanceConfiguration : u32 {
-        Config1 = 0x00010000,
-        Config2 = 0x00010001,
-        Config3 = 0x00010002,
-        Config4 = 0x00020000,
-        Config5 = 0x00020001,
-        Config6 = 0x00020002,
-        Config7 = 0x00020003,
-        Config8 = 0x00020004,
-        Config9 = 0x00020005,
-        Config10 = 0x00020006,
-        Config11 = 0x92220007,
-        Config12 = 0x92220008,
-    };
-
     void SetPerformanceConfiguration(Kernel::HLERequestContext& ctx) {
         IPC::RequestParser rp{ctx};
 
-        auto mode = static_cast<PerformanceMode>(rp.Pop<u32>());
-        u32 config = rp.Pop<u32>();
-        LOG_WARNING(Service_APM, "(STUBBED) called mode={} config={}", static_cast<u32>(mode),
-                    config);
+        const auto mode = rp.PopEnum<PerformanceMode>();
+        const auto config = rp.PopEnum<PerformanceConfiguration>();
+        LOG_DEBUG(Service_APM, "called mode={} config={}", static_cast<u32>(mode),
+                  static_cast<u32>(config));
+
+        controller.SetPerformanceConfiguration(mode, config);
 
         IPC::ResponseBuilder rb{ctx, 2};
         rb.Push(RESULT_SUCCESS);
@@ -50,20 +39,23 @@ private:
     void GetPerformanceConfiguration(Kernel::HLERequestContext& ctx) {
         IPC::RequestParser rp{ctx};
 
-        auto mode = static_cast<PerformanceMode>(rp.Pop<u32>());
-        LOG_WARNING(Service_APM, "(STUBBED) called mode={}", static_cast<u32>(mode));
+        const auto mode = rp.PopEnum<PerformanceMode>();
+        LOG_DEBUG(Service_APM, "called mode={}", static_cast<u32>(mode));
 
         IPC::ResponseBuilder rb{ctx, 3};
         rb.Push(RESULT_SUCCESS);
-        rb.Push<u32>(static_cast<u32>(PerformanceConfiguration::Config1));
+        rb.PushEnum(controller.GetCurrentPerformanceConfiguration(mode));
     }
+
+    Controller& controller;
 };
 
-APM::APM(std::shared_ptr<Module> apm, const char* name)
-    : ServiceFramework(name), apm(std::move(apm)) {
+APM::APM(std::shared_ptr<Module> apm, Controller& controller, const char* name)
+    : ServiceFramework(name), apm(std::move(apm)), controller(controller) {
     static const FunctionInfo functions[] = {
         {0, &APM::OpenSession, "OpenSession"},
-        {1, nullptr, "GetPerformanceMode"},
+        {1, &APM::GetPerformanceMode, "GetPerformanceMode"},
+        {6, nullptr, "IsCpuOverclockEnabled"},
     };
     RegisterHandlers(functions);
 }
@@ -75,10 +67,17 @@ void APM::OpenSession(Kernel::HLERequestContext& ctx) {
 
     IPC::ResponseBuilder rb{ctx, 2, 0, 1};
     rb.Push(RESULT_SUCCESS);
-    rb.PushIpcInterface<ISession>();
+    rb.PushIpcInterface<ISession>(controller);
 }
 
-APM_Sys::APM_Sys() : ServiceFramework{"apm:sys"} {
+void APM::GetPerformanceMode(Kernel::HLERequestContext& ctx) {
+    LOG_DEBUG(Service_APM, "called");
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.PushEnum(controller.GetCurrentPerformanceMode());
+}
+
+APM_Sys::APM_Sys(Controller& controller) : ServiceFramework{"apm:sys"}, controller(controller) {
     // clang-format off
     static const FunctionInfo functions[] = {
         {0, nullptr, "RequestPerformanceMode"},
@@ -87,8 +86,8 @@ APM_Sys::APM_Sys() : ServiceFramework{"apm:sys"} {
         {3, nullptr, "GetLastThrottlingState"},
         {4, nullptr, "ClearLastThrottlingState"},
         {5, nullptr, "LoadAndApplySettings"},
-        {6, nullptr, "SetCpuBoostMode"},
-        {7, nullptr, "GetCurrentPerformanceConfiguration"},
+        {6, &APM_Sys::SetCpuBoostMode, "SetCpuBoostMode"},
+        {7, &APM_Sys::GetCurrentPerformanceConfiguration, "GetCurrentPerformanceConfiguration"},
     };
     // clang-format on
 
@@ -102,7 +101,16 @@ void APM_Sys::GetPerformanceEvent(Kernel::HLERequestContext& ctx) {
 
     IPC::ResponseBuilder rb{ctx, 2, 0, 1};
     rb.Push(RESULT_SUCCESS);
-    rb.PushIpcInterface<ISession>();
+    rb.PushIpcInterface<ISession>(controller);
+}
+
+void APM_Sys::GetCurrentPerformanceConfiguration(Kernel::HLERequestContext& ctx) {
+    LOG_DEBUG(Service_APM, "called");
+
+    IPC::ResponseBuilder rb{ctx, 3};
+    rb.Push(RESULT_SUCCESS);
+    rb.PushEnum(
+        controller.GetCurrentPerformanceConfiguration(controller.GetCurrentPerformanceMode()));
 }
 
 } // namespace Service::APM
diff --git a/src/core/hle/service/apm/interface.h b/src/core/hle/service/apm/interface.h
index 773541aa4b..6d5fdf8ef2 100644
--- a/src/core/hle/service/apm/interface.h
+++ b/src/core/hle/service/apm/interface.h
@@ -8,24 +8,32 @@
 
 namespace Service::APM {
 
+class Controller;
+class Module;
+
 class APM final : public ServiceFramework<APM> {
 public:
-    explicit APM(std::shared_ptr<Module> apm, const char* name);
+    explicit APM(std::shared_ptr<Module> apm, Controller& controller, const char* name);
     ~APM() override;
 
 private:
     void OpenSession(Kernel::HLERequestContext& ctx);
+    void GetPerformanceMode(Kernel::HLERequestContext& ctx);
 
     std::shared_ptr<Module> apm;
+    Controller& controller;
 };
 
 class APM_Sys final : public ServiceFramework<APM_Sys> {
 public:
-    explicit APM_Sys();
+    explicit APM_Sys(Controller& controller);
     ~APM_Sys() override;
 
 private:
     void GetPerformanceEvent(Kernel::HLERequestContext& ctx);
+    void GetCurrentPerformanceConfiguration(Kernel::HLERequestContext& ctx);
+
+    Controller& controller;
 };
 
 } // namespace Service::APM

From e52306ca6086ca017b86d2ed98d6015592b00549 Mon Sep 17 00:00:00 2001
From: Zach Hilman <zachhilman@gmail.com>
Date: Fri, 28 Jun 2019 22:46:00 -0400
Subject: [PATCH 4/6] apm: Implement SetCpuBoostMode

---
 src/core/hle/service/apm/interface.cpp | 12 ++++++++++++
 src/core/hle/service/apm/interface.h   |  2 ++
 2 files changed, 14 insertions(+)

diff --git a/src/core/hle/service/apm/interface.cpp b/src/core/hle/service/apm/interface.cpp
index b2241366f5..06f0f8edd7 100644
--- a/src/core/hle/service/apm/interface.cpp
+++ b/src/core/hle/service/apm/interface.cpp
@@ -104,6 +104,18 @@ void APM_Sys::GetPerformanceEvent(Kernel::HLERequestContext& ctx) {
     rb.PushIpcInterface<ISession>(controller);
 }
 
+void APM_Sys::SetCpuBoostMode(Kernel::HLERequestContext& ctx) {
+    IPC::RequestParser rp{ctx};
+    const auto mode = rp.PopEnum<CpuBoostMode>();
+
+    LOG_DEBUG(Service_APM, "called, mode={:08X}", static_cast<u32>(mode));
+
+    controller.SetFromCpuBoostMode(mode);
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(RESULT_SUCCESS);
+}
+
 void APM_Sys::GetCurrentPerformanceConfiguration(Kernel::HLERequestContext& ctx) {
     LOG_DEBUG(Service_APM, "called");
 
diff --git a/src/core/hle/service/apm/interface.h b/src/core/hle/service/apm/interface.h
index 6d5fdf8ef2..de1b894379 100644
--- a/src/core/hle/service/apm/interface.h
+++ b/src/core/hle/service/apm/interface.h
@@ -29,6 +29,8 @@ public:
     explicit APM_Sys(Controller& controller);
     ~APM_Sys() override;
 
+    void SetCpuBoostMode(Kernel::HLERequestContext& ctx);
+
 private:
     void GetPerformanceEvent(Kernel::HLERequestContext& ctx);
     void GetCurrentPerformanceConfiguration(Kernel::HLERequestContext& ctx);

From e2ad3e1fb0771a5280601dbcb9bafe9ebe323492 Mon Sep 17 00:00:00 2001
From: Zach Hilman <zachhilman@gmail.com>
Date: Fri, 28 Jun 2019 22:46:31 -0400
Subject: [PATCH 5/6] core: Keep instance of APM Controller

---
 src/core/core.cpp | 12 ++++++++++++
 src/core/core.h   |  8 ++++++++
 2 files changed, 20 insertions(+)

diff --git a/src/core/core.cpp b/src/core/core.cpp
index df26eb109b..fa6fc357d1 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -25,6 +25,7 @@
 #include "core/hle/kernel/scheduler.h"
 #include "core/hle/kernel/thread.h"
 #include "core/hle/service/am/applets/applets.h"
+#include "core/hle/service/apm/controller.h"
 #include "core/hle/service/glue/manager.h"
 #include "core/hle/service/service.h"
 #include "core/hle/service/sm/sm.h"
@@ -304,6 +305,9 @@ struct System::Impl {
     /// Frontend applets
     Service::AM::Applets::AppletManager applet_manager;
 
+    /// APM (Performance) services
+    Service::APM::Controller apm_controller{core_timing};
+
     /// Glue services
     Service::Glue::ARPManager arp_manager;
 
@@ -566,6 +570,14 @@ const Service::Glue::ARPManager& System::GetARPManager() const {
     return impl->arp_manager;
 }
 
+Service::APM::Controller& System::GetAPMController() {
+    return impl->apm_controller;
+}
+
+const Service::APM::Controller& System::GetAPMController() const {
+    return impl->apm_controller;
+}
+
 System::ResultStatus System::Init(Frontend::EmuWindow& emu_window) {
     return impl->Init(*this, emu_window);
 }
diff --git a/src/core/core.h b/src/core/core.h
index 70adb7af96..11e73278ef 100644
--- a/src/core/core.h
+++ b/src/core/core.h
@@ -43,6 +43,10 @@ struct AppletFrontendSet;
 class AppletManager;
 } // namespace AM::Applets
 
+namespace APM {
+class Controller;
+}
+
 namespace Glue {
 class ARPManager;
 }
@@ -296,6 +300,10 @@ public:
 
     const Service::Glue::ARPManager& GetARPManager() const;
 
+    Service::APM::Controller& GetAPMController();
+
+    const Service::APM::Controller& GetAPMController() const;
+
 private:
     System();
 

From 7e5d7773cc6f6eb7e08dd092bdeef1431c19e6c6 Mon Sep 17 00:00:00 2001
From: Zach Hilman <zachhilman@gmail.com>
Date: Fri, 28 Jun 2019 22:46:51 -0400
Subject: [PATCH 6/6] am: Implement SetCpuBoostMode in terms of APM

---
 src/core/hle/service/am/am.cpp        | 26 ++++++++++++++++++--------
 src/core/hle/service/am/am.h          |  5 ++++-
 src/core/hle/service/am/applet_ae.cpp |  4 ++--
 src/core/hle/service/am/applet_oe.cpp |  2 +-
 src/core/hle/service/service.cpp      |  2 +-
 5 files changed, 26 insertions(+), 13 deletions(-)

diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp
index 33cebb48b8..4b5baf2837 100644
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -29,7 +29,8 @@
 #include "core/hle/service/am/omm.h"
 #include "core/hle/service/am/spsm.h"
 #include "core/hle/service/am/tcap.h"
-#include "core/hle/service/apm/apm.h"
+#include "core/hle/service/apm/controller.h"
+#include "core/hle/service/apm/interface.h"
 #include "core/hle/service/filesystem/filesystem.h"
 #include "core/hle/service/ns/ns.h"
 #include "core/hle/service/nvflinger/nvflinger.h"
@@ -508,8 +509,9 @@ void AppletMessageQueue::OperationModeChanged() {
     on_operation_mode_changed.writable->Signal();
 }
 
-ICommonStateGetter::ICommonStateGetter(std::shared_ptr<AppletMessageQueue> msg_queue)
-    : ServiceFramework("ICommonStateGetter"), msg_queue(std::move(msg_queue)) {
+ICommonStateGetter::ICommonStateGetter(Core::System& system,
+                                       std::shared_ptr<AppletMessageQueue> msg_queue)
+    : ServiceFramework("ICommonStateGetter"), system(system), msg_queue(std::move(msg_queue)) {
     // clang-format off
     static const FunctionInfo functions[] = {
         {0, &ICommonStateGetter::GetEventHandle, "GetEventHandle"},
@@ -542,7 +544,7 @@ ICommonStateGetter::ICommonStateGetter(std::shared_ptr<AppletMessageQueue> msg_q
         {63, nullptr, "GetHdcpAuthenticationStateChangeEvent"},
         {64, nullptr, "SetTvPowerStateMatchingMode"},
         {65, nullptr, "GetApplicationIdByContentActionName"},
-        {66, nullptr, "SetCpuBoostMode"},
+        {66, &ICommonStateGetter::SetCpuBoostMode, "SetCpuBoostMode"},
         {80, nullptr, "PerformSystemButtonPressingIfInFocus"},
         {90, nullptr, "SetPerformanceConfigurationChangedNotification"},
         {91, nullptr, "GetCurrentPerformanceConfiguration"},
@@ -623,6 +625,16 @@ void ICommonStateGetter::GetDefaultDisplayResolution(Kernel::HLERequestContext&
     }
 }
 
+void ICommonStateGetter::SetCpuBoostMode(Kernel::HLERequestContext& ctx) {
+    LOG_DEBUG(Service_AM, "called, forwarding to APM:SYS");
+
+    const auto& sm = system.ServiceManager();
+    const auto apm_sys = sm.GetService<APM::APM_Sys>("apm:sys");
+    ASSERT(apm_sys != nullptr);
+
+    apm_sys->SetCpuBoostMode(ctx);
+}
+
 IStorage::IStorage(std::vector<u8> buffer)
     : ServiceFramework("IStorage"), buffer(std::move(buffer)) {
     // clang-format off
@@ -651,13 +663,11 @@ void ICommonStateGetter::GetOperationMode(Kernel::HLERequestContext& ctx) {
 }
 
 void ICommonStateGetter::GetPerformanceMode(Kernel::HLERequestContext& ctx) {
-    const bool use_docked_mode{Settings::values.use_docked_mode};
-    LOG_DEBUG(Service_AM, "called, use_docked_mode={}", use_docked_mode);
+    LOG_DEBUG(Service_AM, "called");
 
     IPC::ResponseBuilder rb{ctx, 3};
     rb.Push(RESULT_SUCCESS);
-    rb.Push(static_cast<u32>(use_docked_mode ? APM::PerformanceMode::Docked
-                                             : APM::PerformanceMode::Handheld));
+    rb.PushEnum(system.GetAPMController().GetCurrentPerformanceMode());
 }
 
 class ILibraryAppletAccessor final : public ServiceFramework<ILibraryAppletAccessor> {
diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h
index 4ea609d23b..88d1ba27cc 100644
--- a/src/core/hle/service/am/am.h
+++ b/src/core/hle/service/am/am.h
@@ -145,7 +145,8 @@ private:
 
 class ICommonStateGetter final : public ServiceFramework<ICommonStateGetter> {
 public:
-    explicit ICommonStateGetter(std::shared_ptr<AppletMessageQueue> msg_queue);
+    explicit ICommonStateGetter(Core::System& system,
+                                std::shared_ptr<AppletMessageQueue> msg_queue);
     ~ICommonStateGetter() override;
 
 private:
@@ -167,7 +168,9 @@ private:
     void GetPerformanceMode(Kernel::HLERequestContext& ctx);
     void GetBootMode(Kernel::HLERequestContext& ctx);
     void GetDefaultDisplayResolution(Kernel::HLERequestContext& ctx);
+    void SetCpuBoostMode(Kernel::HLERequestContext& ctx);
 
+    Core::System& system;
     std::shared_ptr<AppletMessageQueue> msg_queue;
 };
 
diff --git a/src/core/hle/service/am/applet_ae.cpp b/src/core/hle/service/am/applet_ae.cpp
index fe5beb8f9a..a34368c8b9 100644
--- a/src/core/hle/service/am/applet_ae.cpp
+++ b/src/core/hle/service/am/applet_ae.cpp
@@ -42,7 +42,7 @@ private:
 
         IPC::ResponseBuilder rb{ctx, 2, 0, 1};
         rb.Push(RESULT_SUCCESS);
-        rb.PushIpcInterface<ICommonStateGetter>(msg_queue);
+        rb.PushIpcInterface<ICommonStateGetter>(system, msg_queue);
     }
 
     void GetSelfController(Kernel::HLERequestContext& ctx) {
@@ -146,7 +146,7 @@ private:
 
         IPC::ResponseBuilder rb{ctx, 2, 0, 1};
         rb.Push(RESULT_SUCCESS);
-        rb.PushIpcInterface<ICommonStateGetter>(msg_queue);
+        rb.PushIpcInterface<ICommonStateGetter>(system, msg_queue);
     }
 
     void GetSelfController(Kernel::HLERequestContext& ctx) {
diff --git a/src/core/hle/service/am/applet_oe.cpp b/src/core/hle/service/am/applet_oe.cpp
index 6e255fe95b..5d53ef113b 100644
--- a/src/core/hle/service/am/applet_oe.cpp
+++ b/src/core/hle/service/am/applet_oe.cpp
@@ -80,7 +80,7 @@ private:
 
         IPC::ResponseBuilder rb{ctx, 2, 0, 1};
         rb.Push(RESULT_SUCCESS);
-        rb.PushIpcInterface<ICommonStateGetter>(msg_queue);
+        rb.PushIpcInterface<ICommonStateGetter>(system, msg_queue);
     }
 
     void GetLibraryAppletCreator(Kernel::HLERequestContext& ctx) {
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp
index ec9d755b73..e441b3730d 100644
--- a/src/core/hle/service/service.cpp
+++ b/src/core/hle/service/service.cpp
@@ -206,7 +206,7 @@ void Init(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system,
     Account::InstallInterfaces(system);
     AM::InstallInterfaces(*sm, nv_flinger, system);
     AOC::InstallInterfaces(*sm);
-    APM::InstallInterfaces(*sm);
+    APM::InstallInterfaces(system);
     Audio::InstallInterfaces(*sm);
     BCAT::InstallInterfaces(*sm);
     BPC::InstallInterfaces(*sm);