Rollback

From Msim

(Difference between revisions)
Jump to: navigation, search
Jloew (Talk | contribs)
(New page: A bug in the rollback code allows speculative instructions to alter simulator memory and not be corrected. == Problem == Quadword accesses that are not aligned on quadword boundaries used...)
Newer edit →

Revision as of 21:09, 19 September 2009

A bug in the rollback code allows speculative instructions to alter simulator memory and not be corrected.

Problem

Quadword accesses that are not aligned on quadword boundaries used repair information that was generated from a quadword boundary (and the repairs were made to a quadword boundary). This meant that a quadword access that crossed two aligned quadwords could not be recovered properly.

stq r0, 4(r31) - store quadword r0 to address 4

This is technically ok (alignment checks only cared about word boundaries).
The rollback code forced aligned and stored the following:

previous_mem = memory[4 & ~7] - stored the quadword at address 0

Then repaired the incorrect address on a rollback:

memory[4 & ~7] = previous_mem

In this case, the word at address 8 was not repaired.

Fix

The forced alignment only mattered in the case of quadwords.
Old code: sim-outorder.c

               //If this is a store, retain the old memory data so that we can rollback.
               //This must be done before the "switch" below.
               qword_t previous_mem(0);
               if((MD_OP_FLAGS(op) & (F_MEM|F_STORE)) == (F_MEM|F_STORE))
               {
                       enum md_fault_type prev_fault;
                       previous_mem = READ_QWORD((GPR(RB) + SEXT(OFS)) & (~7), prev_fault);
                       //Change this to remove the fault, we don't need to check for a fault
               }

New code:

               //If this is a store, retain the old memory data so that we can rollback.
               //This must be done before the "switch" below.
               qword_t previous_mem(0);
               if((MD_OP_FLAGS(op) & (F_MEM|F_STORE)) == (F_MEM|F_STORE))
               {
                       enum md_fault_type prev_fault;
                       md_addr_t addr = (GPR(RB) + SEXT(OFS));

                       if((op==LDQ_U) || (op==STQ_U))
                       {
                               addr &= ~7;
                       }
                       previous_mem = READ_QWORD(addr, prev_fault);
                       //Change this to remove the fault, we don't need to check for a fault
               }

Then, the fix in the rollback code itself:
Old code: cmp.c

                       //Here is where we perform memory rollback
                       if(target.LSQ[LSQ_index].is_store)
                       {
                               qword_t temp = MD_SWAPQ(target.LSQ[LSQ_index].previous_mem);
                               mem_access(target.mem,Write,target.LSQ[LSQ_index].addr & ~7,&temp,sizeof(qword_t));
                       }

New code:

                       //Here is where we perform memory rollback
                       if(target.LSQ[LSQ_index].is_store)
                       {
                               qword_t temp = MD_SWAPQ(target.LSQ[LSQ_index].previous_mem);
                               md_addr_t addr = target.LSQ[LSQ_index].addr;
                               if((target.LSQ[LSQ_index].op == LDQ_U) || (target.LSQ[LSQ_index].op == STQ_U))
                               {
                                       addr &= ~7;
                               }
                               mem_access(target.mem,Write,addr,&temp,sizeof(qword_t));
                       }
Personal tools