IOS: Convert the IOS kernel HLE code to a class

This changes the main IOS code (roughly the equivalent of the kernel)
to a class instead of being a set of free functions + tons of static
variables.

The reason for this change is that keeping tons of static variables
like that prevents us from making an IOS instance and reusing IOS
code easily.

Converting the IOS code to a class also allows us to mostly decouple
IOS from the PPC emulation.

The more interesting changes are in Core/IOS/IOS. Everything else is
mostly just boring stuff required by this change...

* Because the devices themselves call back to the main IOS code
  for various things (getting the current version, replying to a
  request, and other syscall-like functions), just like processes in
  IOS call kernel syscalls, we have to pass a reference to the kernel
  to anything that uses IOS syscalls.

* Change DoState to save device names instead of device IDs to simplify
  AddDevice() and get rid of an ugly static count.

* Change ES_Launch's ack to be sent at IOS boot, now that we can do
  this properly.
This commit is contained in:
Léo Lam
2017-04-30 17:18:53 +02:00
parent fcc2ed4550
commit 2fc5047d26
88 changed files with 1477 additions and 1428 deletions
+1 -1
View File
@@ -27,7 +27,7 @@
#include "Core/HW/Memmap.h"
#include "Core/HW/VideoInterface.h"
#include "Core/Host.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
#include "Core/PatchEngine.h"
#include "Core/PowerPC/PPCAnalyst.h"
#include "Core/PowerPC/PPCSymbolDB.h"
+2 -2
View File
@@ -23,7 +23,7 @@
#include "Core/HW/Memmap.h"
#include "Core/IOS/ES/ES.h"
#include "Core/IOS/ES/Formats.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
#include "Core/PatchEngine.h"
#include "Core/PowerPC/PowerPC.h"
@@ -289,7 +289,7 @@ bool CBoot::SetupWiiMemory(u64 ios_title_id)
Memory::Write_U16(0x8201, 0x000030e6); // Dev console / debug capable
Memory::Write_U32(0x00000000, 0x000030f0); // Apploader
if (!IOS::HLE::Reload(ios_title_id))
if (!IOS::HLE::GetIOS()->BootIOS(ios_title_id))
{
return false;
}
+2 -2
View File
@@ -16,7 +16,7 @@
#include "Core/Boot/Boot.h"
#include "Core/IOS/ES/ES.h"
#include "Core/IOS/FS/FileIO.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
#include "Core/PatchEngine.h"
#include "DiscIO/NANDContentLoader.h"
@@ -88,7 +88,7 @@ bool CBoot::Boot_WiiWAD(const std::string& _pFilename)
return false;
IOS::HLE::Device::ES::LoadWAD(_pFilename);
if (!IOS::HLE::BootstrapPPC(ContentLoader))
if (!IOS::HLE::GetIOS()->BootstrapPPC(ContentLoader))
return false;
return true;
+2 -1
View File
@@ -147,7 +147,8 @@ set(SRCS
HW/WiiSaveCrypted.cpp
IOS/Device.cpp
IOS/DeviceStub.cpp
IOS/IPC.cpp
IOS/IOS.cpp
IOS/MemoryValues.cpp
IOS/MIOS.cpp
IOS/DI/DI.cpp
IOS/ES/ES.cpp
+4 -2
View File
@@ -50,7 +50,7 @@
#include "Core/HW/SystemTimers.h"
#include "Core/HW/VideoInterface.h"
#include "Core/HW/Wiimote.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
#include "Core/Movie.h"
#include "Core/NetPlayClient.h"
#include "Core/NetPlayProto.h"
@@ -952,7 +952,9 @@ void UpdateWantDeterminism(bool initial)
bool was_unpaused = Core::PauseAndLock(true);
s_wants_determinism = new_want_determinism;
IOS::HLE::UpdateWantDeterminism(new_want_determinism);
const auto ios = IOS::HLE::GetIOS();
if (ios)
ios->UpdateWantDeterminism(new_want_determinism);
Fifo::UpdateWantDeterminism(new_want_determinism);
// We need to clear the cache because some parts of the JIT depend on want_determinism, e.g. use
// of FMA.
+4 -2
View File
@@ -174,7 +174,8 @@
<ClCompile Include="HW\WiiSaveCrypted.cpp" />
<ClCompile Include="IOS\Device.cpp" />
<ClCompile Include="IOS\DeviceStub.cpp" />
<ClCompile Include="IOS\IPC.cpp" />
<ClCompile Include="IOS\IOS.cpp" />
<ClCompile Include="IOS\MemoryValues.cpp" />
<ClCompile Include="IOS\MIOS.cpp" />
<ClCompile Include="IOS\DI\DI.cpp" />
<ClCompile Include="IOS\ES\ES.cpp" />
@@ -431,7 +432,8 @@
<ClInclude Include="HW\WII_IPC.h" />
<ClInclude Include="IOS\Device.h" />
<ClInclude Include="IOS\DeviceStub.h" />
<ClInclude Include="IOS\IPC.h" />
<ClInclude Include="IOS\IOS.h" />
<ClInclude Include="IOS\MemoryValues.h" />
<ClInclude Include="IOS\MIOS.h" />
<ClInclude Include="IOS\DI\DI.h" />
<ClInclude Include="IOS\ES\ES.h" />
+8 -2
View File
@@ -790,7 +790,10 @@
<ClCompile Include="IOS\Network\ICMPLin.cpp">
<Filter>IOS\Network</Filter>
</ClCompile>
<ClCompile Include="IOS\IPC.cpp">
<ClCompile Include="IOS\IOS.cpp">
<Filter>IOS</Filter>
</ClCompile>
<ClCompile Include="IOS\MemoryValues.cpp">
<Filter>IOS</Filter>
</ClCompile>
<ClCompile Include="IOS\MIOS.cpp">
@@ -1504,7 +1507,10 @@
<ClInclude Include="IOS\Device.h">
<Filter>IOS</Filter>
</ClInclude>
<ClInclude Include="IOS\IPC.h">
<ClInclude Include="IOS\IOS.h">
<Filter>IOS</Filter>
</ClInclude>
<ClInclude Include="IOS\MemoryValues.h">
<Filter>IOS</Filter>
</ClInclude>
<ClInclude Include="IOS\MIOS.h">
+2 -2
View File
@@ -28,7 +28,7 @@
#include "Core/HW/StreamADPCM.h"
#include "Core/HW/SystemTimers.h"
#include "Core/IOS/DI/DI.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
#include "Core/Movie.h"
#include "DiscIO/Enums.h"
@@ -1136,7 +1136,7 @@ void FinishExecutingCommand(ReplyType reply_type, DIInterruptType interrupt_type
case ReplyType::IOS:
{
auto di = IOS::HLE::GetDeviceByName("/dev/di");
auto di = IOS::HLE::GetIOS()->GetDeviceByName("/dev/di");
if (di)
std::static_pointer_cast<IOS::HLE::Device::DI>(di)->FinishIOCtl(interrupt_type);
break;
+2 -2
View File
@@ -21,7 +21,7 @@
#include "Core/HW/SystemTimers.h"
#include "Core/HW/VideoInterface.h"
#include "Core/HW/WII_IPC.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
#include "Core/Movie.h"
#include "Core/State.h"
#include "Core/WiiRoot.h"
@@ -102,7 +102,7 @@ void DoState(PointerWrap& p)
{
IOS::DoState(p);
p.DoMarker("IOS");
IOS::HLE::DoState(p);
IOS::HLE::GetIOS()->DoState(p);
p.DoMarker("IOS::HLE");
}
+15 -13
View File
@@ -11,7 +11,7 @@
#include "Core/HW/MMIO.h"
#include "Core/HW/ProcessorInterface.h"
#include "Core/HW/SystemTimers.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
#include "Core/IOS/STM/STM.h"
#include "Core/PowerPC/PowerPC.h"
@@ -210,22 +210,24 @@ static void ToggleResetButtonCallback(u64 userdata, s64 cyclesLate)
static void IOSNotifyResetButtonCallback(u64 userdata, s64 cyclesLate)
{
if (SConfig::GetInstance().bWii)
{
auto stm = IOS::HLE::GetDeviceByName("/dev/stm/eventhook");
if (stm)
std::static_pointer_cast<IOS::HLE::Device::STMEventHook>(stm)->ResetButton();
}
const auto ios = IOS::HLE::GetIOS();
if (!ios)
return;
auto stm = ios->GetDeviceByName("/dev/stm/eventhook");
if (stm)
std::static_pointer_cast<IOS::HLE::Device::STMEventHook>(stm)->ResetButton();
}
static void IOSNotifyPowerButtonCallback(u64 userdata, s64 cyclesLate)
{
if (SConfig::GetInstance().bWii)
{
auto stm = IOS::HLE::GetDeviceByName("/dev/stm/eventhook");
if (stm)
std::static_pointer_cast<IOS::HLE::Device::STMEventHook>(stm)->PowerButton();
}
const auto ios = IOS::HLE::GetIOS();
if (!ios)
return;
auto stm = ios->GetDeviceByName("/dev/stm/eventhook");
if (stm)
std::static_pointer_cast<IOS::HLE::Device::STMEventHook>(stm)->PowerButton();
}
void ResetButton_Tap()
+2 -2
View File
@@ -57,7 +57,7 @@ IPC_HLE_PERIOD: For the Wii Remote this is the call schedule:
#include "Core/HW/DSP.h"
#include "Core/HW/EXI/EXI_DeviceIPL.h"
#include "Core/HW/VideoInterface.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
#include "Core/PatchEngine.h"
#include "Core/PowerPC/PowerPC.h"
#include "VideoCommon/Fifo.h"
@@ -112,7 +112,7 @@ static void IPC_HLE_UpdateCallback(u64 userdata, s64 cyclesLate)
{
if (SConfig::GetInstance().bWii)
{
IOS::HLE::UpdateDevices();
IOS::HLE::GetIOS()->UpdateDevices();
CoreTiming::ScheduleEvent(s_ipc_hle_period - cyclesLate, et_IPC_HLE);
}
}
+5 -5
View File
@@ -9,7 +9,7 @@
#include "Core/CoreTiming.h"
#include "Core/HW/MMIO.h"
#include "Core/HW/ProcessorInterface.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
// This is the intercommunication between ARM and PPC. Currently only PPC actually uses it, because
// of the IOS HLE
@@ -153,8 +153,8 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
MMIO::ComplexWrite<u32>([](u32, u32 val) {
ctrl.ppc(val);
if (ctrl.X1)
HLE::EnqueueRequest(ppc_msg);
HLE::Update();
HLE::GetIOS()->EnqueueIPCRequest(ppc_msg);
HLE::GetIOS()->UpdateIPC();
CoreTiming::ScheduleEvent(0, updateInterrupts, 0);
}));
@@ -163,7 +163,7 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
mmio->Register(base | PPC_IRQFLAG, MMIO::InvalidRead<u32>(),
MMIO::ComplexWrite<u32>([](u32, u32 val) {
ppc_irq_flags &= ~val;
HLE::Update();
HLE::GetIOS()->UpdateIPC();
CoreTiming::ScheduleEvent(0, updateInterrupts, 0);
}));
@@ -172,7 +172,7 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
ppc_irq_masks = val;
if (ppc_irq_masks & INT_CAUSE_IPC_BROADWAY) // wtf?
Reset();
HLE::Update();
HLE::GetIOS()->UpdateIPC();
CoreTiming::ScheduleEvent(0, updateInterrupts, 0);
}));
+2 -2
View File
@@ -24,7 +24,7 @@ namespace HLE
{
namespace Device
{
DI::DI(u32 device_id, const std::string& device_name) : Device(device_id, device_name)
DI::DI(Kernel& ios, const std::string& device_name) : Device(ios, device_name)
{
}
@@ -76,7 +76,7 @@ void DI::FinishIOCtl(DVDInterface::DIInterruptType interrupt_type)
// This command has been executed, so it's removed from the queue
u32 command_address = m_commands_to_execute.front();
m_commands_to_execute.pop_front();
EnqueueReply(IOCtlRequest{command_address}, interrupt_type);
m_ios.EnqueueIPCReply(IOCtlRequest{command_address}, interrupt_type);
// DVDInterface is now ready to execute another command,
// so we start executing a command from the queue if there is one
+2 -2
View File
@@ -9,7 +9,7 @@
#include "Common/CommonTypes.h"
#include "Core/IOS/Device.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
class PointerWrap;
@@ -27,7 +27,7 @@ namespace Device
class DI : public Device
{
public:
DI(u32 device_id, const std::string& device_name);
DI(Kernel& ios, const std::string& device_name);
void DoState(PointerWrap& p) override;
+9 -6
View File
@@ -10,7 +10,7 @@
#include "Core/HW/Memmap.h"
#include "Core/HW/SystemTimers.h"
#include "Core/IOS/Device.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
namespace IOS
{
@@ -26,8 +26,12 @@ OpenRequest::OpenRequest(const u32 address_) : Request(address_)
{
path = Memory::GetString(Memory::Read_U32(address + 0xc));
flags = static_cast<OpenMode>(Memory::Read_U32(address + 0x10));
uid = GetUIDForPPC();
gid = GetGIDForPPC();
const Kernel* ios = GetIOS();
if (ios)
{
uid = ios->GetUidForPPC();
gid = ios->GetGidForPPC();
}
}
ReadWriteRequest::ReadWriteRequest(const u32 address_) : Request(address_)
@@ -129,8 +133,8 @@ void IOCtlVRequest::DumpUnknown(const std::string& description, LogTypes::LOG_TY
namespace Device
{
Device::Device(const u32 device_id, const std::string& device_name, const DeviceType type)
: m_name(device_name), m_device_id(device_id), m_device_type(type)
Device::Device(Kernel& ios, const std::string& device_name, const DeviceType type)
: m_ios(ios), m_name(device_name), m_device_type(type)
{
}
@@ -143,7 +147,6 @@ void Device::DoState(PointerWrap& p)
void Device::DoStateShared(PointerWrap& p)
{
p.Do(m_name);
p.Do(m_device_id);
p.Do(m_device_type);
p.Do(m_is_active);
}
+4 -4
View File
@@ -11,7 +11,7 @@
#include "Common/ChunkFile.h"
#include "Common/CommonTypes.h"
#include "Common/Logging/Log.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
namespace IOS
{
@@ -172,7 +172,7 @@ public:
OH0, // OH0 child devices which are created dynamically.
};
Device(u32 device_id, const std::string& device_name, DeviceType type = DeviceType::Static);
Device(Kernel& ios, const std::string& device_name, DeviceType type = DeviceType::Static);
virtual ~Device() = default;
// Release any resources which might interfere with savestating.
@@ -181,7 +181,6 @@ public:
void DoStateShared(PointerWrap& p);
const std::string& GetDeviceName() const { return m_name; }
u32 GetDeviceID() const { return m_device_id; }
// Replies to Open and Close requests are sent by the IPC request handler (HandleCommand),
// not by the devices themselves.
virtual ReturnCode Open(const OpenRequest& request);
@@ -199,9 +198,10 @@ public:
static IPCCommandResult GetNoReply();
protected:
Kernel& m_ios;
std::string m_name;
// STATE_TO_SAVE
u32 m_device_id;
DeviceType m_device_type;
bool m_is_active = false;
-4
View File
@@ -11,10 +11,6 @@ namespace HLE
{
namespace Device
{
Stub::Stub(u32 device_id, const std::string& device_name) : Device(device_id, device_name)
{
}
ReturnCode Stub::Open(const OpenRequest& request)
{
WARN_LOG(IOS, "%s faking Open()", m_name.c_str());
+3 -3
View File
@@ -8,7 +8,7 @@
#include "Common/CommonTypes.h"
#include "Core/IOS/Device.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
namespace IOS
{
@@ -19,8 +19,8 @@ namespace Device
class Stub final : public Device
{
public:
Stub(u32 device_id, const std::string& device_name);
// Inherit the constructor from the Device class, since we don't need to do anything special.
using Device::Device;
ReturnCode Open(const OpenRequest& request) override;
IPCCommandResult IOCtl(const IOCtlRequest& request) override;
IPCCommandResult IOCtlV(const IOCtlVRequest& request) override;
+13 -16
View File
@@ -55,7 +55,7 @@ static void FinishAllStaleImports()
File::CreateDir(import_dir);
}
ES::ES(u32 device_id, const std::string& device_name) : Device(device_id, device_name)
ES::ES(Kernel& ios, const std::string& device_name) : Device(ios, device_name)
{
FinishAllStaleImports();
@@ -155,7 +155,7 @@ IPCCommandResult ES::GetTitleID(const IOCtlVRequest& request)
return GetDefaultReply(IPC_SUCCESS);
}
static bool UpdateUIDAndGID(const IOS::ES::TMDReader& tmd)
static bool UpdateUIDAndGID(Kernel& kernel, const IOS::ES::TMDReader& tmd)
{
IOS::ES::UIDSys uid_sys{Common::FromWhichRoot::FROM_SESSION_ROOT};
const u64 title_id = tmd.GetTitleId();
@@ -165,8 +165,8 @@ static bool UpdateUIDAndGID(const IOS::ES::TMDReader& tmd)
ERROR_LOG(IOS_ES, "Failed to get UID for title %016" PRIx64, title_id);
return false;
}
SetUIDForPPC(uid);
SetGIDForPPC(tmd.GetGroupId());
kernel.SetUidForPPC(uid);
kernel.SetGidForPPC(tmd.GetGroupId());
return true;
}
@@ -197,7 +197,7 @@ IPCCommandResult ES::SetUID(u32 uid, const IOCtlVRequest& request)
if (!tmd.IsValid())
return GetDefaultReply(FS_ENOENT);
if (!UpdateUIDAndGID(tmd))
if (!UpdateUIDAndGID(m_ios, tmd))
{
ERROR_LOG(IOS_ES, "SetUID: Failed to get UID for title %016" PRIx64, title_id);
return GetDefaultReply(ES_SHORT_READ);
@@ -225,7 +225,7 @@ bool ES::LaunchTitle(u64 title_id, bool skip_reload)
bool ES::LaunchIOS(u64 ios_title_id)
{
return Reload(ios_title_id);
return m_ios.BootIOS(ios_title_id);
}
bool ES::LaunchPPCTitle(u64 title_id, bool skip_reload)
@@ -266,14 +266,14 @@ bool ES::LaunchPPCTitle(u64 title_id, bool skip_reload)
// Note: the UID/GID is also updated for IOS titles, but since we have no guarantee IOS titles
// are installed, we can only do this for PPC titles.
if (!UpdateUIDAndGID(s_title_context.tmd))
if (!UpdateUIDAndGID(m_ios, s_title_context.tmd))
{
s_title_context.Clear();
INFO_LOG(IOS_ES, "LaunchPPCTitle: Title context changed: (none)");
return false;
}
return BootstrapPPC(content_loader);
return m_ios.BootstrapPPC(content_loader);
}
void ES::Context::DoState(PointerWrap& p)
@@ -555,11 +555,9 @@ IPCCommandResult ES::Launch(const IOCtlVRequest& request)
if (!LaunchTitle(TitleID))
return GetDefaultReply(FS_ENOENT);
// Generate a "reply" to the IPC command. ES_LAUNCH is unique because it
// involves restarting IOS; IOS generates two acknowledgements in a row.
// Note: If the launch succeeded, we should not write anything to the command buffer as
// IOS does not even reply unless it failed.
EnqueueCommandAcknowledgement(request.address, 0);
// ES_LAUNCH involves restarting IOS, which results in two acknowledgements in a row
// (one from the previous IOS for this IPC request, and one from the new one as it boots).
// Nothing should be written to the command buffer if the launch succeeded for obvious reasons.
return GetNoReply();
}
@@ -570,13 +568,12 @@ IPCCommandResult ES::LaunchBC(const IOCtlVRequest& request)
// Here, IOS checks the clock speed and prevents ioctlv 0x25 from being used in GC mode.
// An alternative way to do this is to check whether the current active IOS is MIOS.
if (GetVersion() == 0x101)
if (m_ios.GetVersion() == 0x101)
return GetDefaultReply(ES_EINVAL);
if (!LaunchTitle(0x0000000100000100))
return GetDefaultReply(FS_ENOENT);
EnqueueCommandAcknowledgement(request.address, 0);
return GetNoReply();
}
@@ -633,7 +630,7 @@ s32 ES::DIVerify(const IOS::ES::TMDReader& tmd, const IOS::ES::TicketReader& tic
// clear the cache to avoid content access mismatches.
DiscIO::CNANDContentManager::Access().ClearCache();
if (!UpdateUIDAndGID(s_title_context.tmd))
if (!UpdateUIDAndGID(*GetIOS(), s_title_context.tmd))
{
return ES_SHORT_READ;
}
+5 -5
View File
@@ -12,7 +12,7 @@
#include "Common/CommonTypes.h"
#include "Core/IOS/Device.h"
#include "Core/IOS/ES/Formats.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
class PointerWrap;
@@ -43,11 +43,11 @@ struct TitleContext
class ES final : public Device
{
public:
ES(u32 device_id, const std::string& device_name);
ES(Kernel& ios, const std::string& device_name);
static s32 DIVerify(const IOS::ES::TMDReader& tmd, const IOS::ES::TicketReader& ticket);
static void LoadWAD(const std::string& _rContentFile);
static bool LaunchTitle(u64 title_id, bool skip_reload = false);
bool LaunchTitle(u64 title_id, bool skip_reload = false);
// Internal implementation of the ES_DECRYPT ioctlv.
static void DecryptContent(u32 key_index, u8* iv, u8* input, u32 size, u8* new_iv, u8* output);
@@ -265,8 +265,8 @@ private:
ContextArray::iterator FindActiveContext(u32 fd);
ContextArray::iterator FindInactiveContext();
static bool LaunchIOS(u64 ios_title_id);
static bool LaunchPPCTitle(u64 title_id, bool skip_reload);
bool LaunchIOS(u64 ios_title_id);
bool LaunchPPCTitle(u64 title_id, bool skip_reload);
static TitleContext& GetTitleContext();
static const DiscIO::CNANDContentLoader& AccessContentDevice(u64 title_id);

Some files were not shown because too many files have changed in this diff Show More