[lldb][debugserver] Save and restore the SVE/SME register state (#134184)
debugserver isn't saving and restoring the SVE/SME register state around inferior function calls. Making arbitrary function calls while in Streaming SVE mode is generally a poor idea because a NEON instruction can be hit and crash the expression execution, which is how I missed this, but they should be handled correctly if the user knows it is safe to do. rdar://146886210
This commit is contained in:
@@ -2952,8 +2952,15 @@ kern_return_t DNBArchMachARM64::SetRegisterState(int set) {
|
||||
return err;
|
||||
|
||||
switch (set) {
|
||||
case e_regSetALL:
|
||||
return SetGPRState() | SetVFPState() | SetEXCState() | SetDBGState(false);
|
||||
case e_regSetALL: {
|
||||
kern_return_t ret =
|
||||
SetGPRState() | SetVFPState() | SetEXCState() | SetDBGState(false);
|
||||
if (CPUHasSME()) {
|
||||
ret |= SetSVEState();
|
||||
ret |= SetSMEState();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
case e_regSetGPR:
|
||||
return SetGPRState();
|
||||
case e_regSetVFP:
|
||||
@@ -3119,9 +3126,20 @@ uint32_t DNBArchMachARM64::SaveRegisterState() {
|
||||
"error: GPR regs failed to read: %u ",
|
||||
kret);
|
||||
} else if ((kret = GetVFPState(force)) != KERN_SUCCESS) {
|
||||
DNBLogThreadedIf(LOG_THREAD, "DNBArchMachARM64::SaveRegisterState () "
|
||||
"error: %s regs failed to read: %u",
|
||||
DNBLogThreadedIf(LOG_THREAD,
|
||||
"DNBArchMachARM64::SaveRegisterState () "
|
||||
"error: %s regs failed to read: %u",
|
||||
"VFP", kret);
|
||||
} else if (CPUHasSME() && (kret = SetSVEState() != KERN_SUCCESS)) {
|
||||
DNBLogThreadedIf(LOG_THREAD,
|
||||
"DNBArchMachARM64::SaveRegisterState () "
|
||||
"error: %s regs failed to read: %u",
|
||||
"SVE", kret);
|
||||
} else if (CPUHasSME() && (kret = SetSMEState() != KERN_SUCCESS)) {
|
||||
DNBLogThreadedIf(LOG_THREAD,
|
||||
"DNBArchMachARM64::SaveRegisterState () "
|
||||
"error: %s regs failed to read: %u",
|
||||
"SME", kret);
|
||||
} else {
|
||||
const uint32_t save_id = GetNextRegisterStateSaveID();
|
||||
m_saved_register_states[save_id] = m_state.context;
|
||||
@@ -3144,11 +3162,26 @@ bool DNBArchMachARM64::RestoreRegisterState(uint32_t save_id) {
|
||||
save_id, kret);
|
||||
success = false;
|
||||
} else if ((kret = SetVFPState()) != KERN_SUCCESS) {
|
||||
DNBLogThreadedIf(LOG_THREAD, "DNBArchMachARM64::RestoreRegisterState "
|
||||
"(save_id = %u) error: %s regs failed to "
|
||||
"write: %u",
|
||||
DNBLogThreadedIf(LOG_THREAD,
|
||||
"DNBArchMachARM64::RestoreRegisterState "
|
||||
"(save_id = %u) error: %s regs failed to "
|
||||
"write: %u",
|
||||
save_id, "VFP", kret);
|
||||
success = false;
|
||||
} else if ((kret = SetSVEState()) != KERN_SUCCESS) {
|
||||
DNBLogThreadedIf(LOG_THREAD,
|
||||
"DNBArchMachARM64::RestoreRegisterState "
|
||||
"(save_id = %u) error: %s regs failed to "
|
||||
"write: %u",
|
||||
save_id, "SVE", kret);
|
||||
success = false;
|
||||
} else if ((kret = SetSMEState()) != KERN_SUCCESS) {
|
||||
DNBLogThreadedIf(LOG_THREAD,
|
||||
"DNBArchMachARM64::RestoreRegisterState "
|
||||
"(save_id = %u) error: %s regs failed to "
|
||||
"write: %u",
|
||||
save_id, "SME", kret);
|
||||
success = false;
|
||||
}
|
||||
m_saved_register_states.erase(pos);
|
||||
return success;
|
||||
|
||||
Reference in New Issue
Block a user