Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

crash while executing "ldmxcsr" instruction in bochscpu backend #140

Closed
Micky-Thongam opened this issue Nov 10, 2022 · 4 comments
Closed

Comments

@Micky-Thongam
Copy link

while this particular instruction(ldmxcsr) executes successfully on whv backend, it crashes on bochscpu backend.

crash detail: raises GP
CoolType!CTInit+0x2c167 (ldmxcsr)
nt!KiGeneralProtectionFault+0x0

crash instruction:
ldmxcsr dword ptr [rsp+8]

@0vercl0k
Copy link
Owner

0vercl0k commented Nov 11, 2022

Okay, according to the manual, ldmxcsr #GPs when it's trying to set reserved bits. If we check Bochs' code, we see the below:

void BX_CPP_AttrRegparmN(1) BX_CPU_C::LDMXCSR(bxInstruction_c *i)
{
#if BX_CPU_LEVEL >= 6
  bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);

  Bit32u new_mxcsr = read_virtual_dword(i->seg(), eaddr);
  if(new_mxcsr & ~MXCSR_MASK)
      exception(BX_GP_EXCEPTION, 0);

  BX_MXCSR_REGISTER = new_mxcsr;
#endif

  BX_NEXT_INSTR(i);
}

This is MXCSR_MASK:

#define MXCSR_MASK        (BX_CPU_THIS_PTR mxcsr_mask)

And this is how it looks like it gets initialized (init.cc):

void BX_CPU_C::reset(unsigned source)
{
// ...
    BX_CPU_THIS_PTR mxcsr_mask = 0x0000ffbf;
    if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_SSE2))
      BX_CPU_THIS_PTR mxcsr_mask |= MXCSR_DAZ;
    if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_MISALIGNED_SSE))
      BX_CPU_THIS_PTR mxcsr_mask |= MXCSR_MISALIGNED_EXCEPTION_MASK;

Could you dump the value that's getting loaded?

Cheers

@Micky-Thongam
Copy link
Author

state of mxcsr (mem.dmp) :
kd> r mxcsr
mxcsr=00001fa1

here: ldmxcsr dword ptr [rsp+8]
I dumped rsp+8 and its
[rsp+8] == 0x000000000000BFA1

@0vercl0k
Copy link
Owner

Okay, I made a mistake; the mxcsr_mask is actually set by bxcpu when we initialize the register via cpu_set_mxcsr_mask:

BOCHSAPI void cpu_set_mxcsr_mask(unsigned id, Bit32u v) {
    BX_CPU(id)->mxcsr_mask = v;
}

So in your case, mxcsr_mask is 0b0001111110100001 and you are trying to load 0b1011111110100001 into it; but 0b1011111110100001 has two bits set (1<<13 & 1<<15) that aren't set in the mask, so you take a #GP:

mask =0b0001111110100001
value=0b1011111110100001
        ^ ^
        | |

Here's the description of those two bits:

/* 31|30|29|28|27|26|25|24|23|22|21|20|19|18|17|16
 * ==|==|=====|==|==|==|==|==|==|==|==|==|==|==|==  (reserved)
 *  0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0|MM| 0
 *
 * 15|14|13|12|11|10| 9| 8| 7| 6| 5| 4| 3| 2| 1| 0
 * ==|==|=====|==|==|==|==|==|==|==|==|==|==|==|==
 * FZ| R C |PM|UM|OM|ZM|DM|IM|DZ|PE|UE|OE|ZE|DE|IE
 */

/* MXCSR REGISTER FIELDS DESCRIPTION */

/*
 * RC 13-14 Floating-Point Rounding Control         00
 * FZ 15    Flush-to-Zero for Masked Underflow      0
 */

To verify all of the above, can you change your regs.json so that mxcsr_mask is 0xbfa1 and not 0x1fa1, and re-run your testcase?

Cheers

@0vercl0k
Copy link
Owner

Okay, we talked about the above and the suggestion didn't work. I did some digging today and I think I understand why; basically there might be a bug in bochscpu/mod.rs:

    pub unsafe fn set_state(&self, s: &State) {
        // ...
        self.set_mxcsr(s.mxcsr);
        self.set_mxcsr_mask(s.mxcsr);
    }

So editing the regs.json['mxcsr_mask'] would be a no op. What it also means is that your initial mxcsr_mask is 0x1fa1 which means both bits 1<<13 / 1<<15 are set in the new value you are loading but aren't in your mask so you get a #GP.

I'll talk to yrp604 about the above to verify that it is a bug, but to unblock you try to update regs.json['mxcsr'] to 0xBFA1 and re-launch your testcase to see if you get passed the ldmxcsr issue.

Cheers

0vercl0k added a commit to clslgrnc/wtf that referenced this issue Dec 15, 2022
…is used to have no effect.

This was fixed in bx (see 0vercl0k#140), so old dumps running w/ newer version of wtf will fire #GPs on `ldmscxr` instructions.
To avoid that issue, let's detect screwed up values and fix them up ourselves.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants