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

Fetch dosen't performed correctly in the simulation of Murax SOC.(+Custom instructions are executed in unexpected time.) #385

Open
nohahanon opened this issue Dec 15, 2023 · 1 comment

Comments

@nohahanon
Copy link

nohahanon commented Dec 15, 2023

Hi there! I appreciate your involvement in this project.

I'm developing a plugin to add shadow stack functionality to VexRiscv. I've implemented instructions, 'sspush' for pushing onto the shadow stack and 'sspop' for popping from it. However, these instructions are being executed at unintended timings.

Upon checking the waveform, at 128223900ns, it's evident that 3A646A29 is confirmed as an instruction sspop in the execute stage, reducing ShadowStackPlugin_ssp by -1. However, this instruction clearly doesn't match the key = M"00000000000000000100-----0101011" of the custom instruction sspop (listed below), and comparing this with the disassembled C program shows that 800005d4 should have nop as 00000013. Is this some sort of bug? I couldn't find such an instruction in the C program. This 3A646A29 instruction appeared unexpectedly as if interrupting.

I would appreciate any insights from anyone familiar with this phenomenon. Thank you in advance!

The 'sspush' and 'sspop' instructions are defined as follows:

package vexriscv.plugin

import vexriscv.plugin.Plugin
import vexriscv.{Stageable, DecoderService, VexRiscv}
import spinal.core._
import spinal.lib._

class  ShadowStackPlugin extends Plugin[VexRiscv] {

    object IS_SS_POP extends Stageable(Bool)
    object IS_SS_PUSH extends Stageable(Bool)
    object IS_SS_GET extends Stageable(Bool)

    override def setup(pipeline: VexRiscv): Unit = {
        import pipeline.config._
        val decoderService = pipeline.service(classOf[DecoderService])

        // add sspop
        decoderService.addDefault(IS_SS_POP, False)
        decoderService.add(
            key = M"00000000000000000100-----0101011",
            List(
                IS_SS_POP                -> True,
                REGFILE_WRITE_VALID      -> True
            )
        )

        // add sspush
        decoderService.addDefault(IS_SS_PUSH, False)
        decoderService.add(
            key = M"000000000000-----010000000001011",
            List(
                IS_SS_PUSH               -> True,
                RS1_USE                  -> True
            )
        )
    }

    override def build(pipeline: VexRiscv): Unit = {
        import pipeline._
        import pipeline.config._

        val ssgetStage = execute
        val sspopStage = execute
        val sspushStage = execute
        
        val global = pipeline plug new Area {
            val width = 32
            val depth = 32
            val bottom = 1
            val ssp = Reg(UInt(log2Up(depth) + 1 bits)) init (bottom)
            val shadowStack = Mem(UInt(width bits), depth)
            shadowStack.init(List.fill(depth)(U"32'd8"))
        }

        // sspop
        sspopStage plug new Area {
            import sspopStage._

            when(input(IS_SS_POP).rise() && global.bottom < global.ssp){
                output(REGFILE_WRITE_DATA) := global.shadowStack((global.ssp - 1).resized).asBits
                global.ssp := global.ssp - 1
            }
        }

        // sspush
        sspushStage plug new Area {
            import sspushStage._

            when(input(IS_SS_PUSH).rise() && global.ssp < global.depth){
                val rs1 = input(RS1).asUInt
                global.shadowStack(global.ssp.resized) := rs1
                global.ssp := global.ssp + 1
            }
        }
    }
}

202312151718_1

@Dolu1990
Copy link
Member

Dolu1990 commented Dec 18, 2023

Hi ^^^
the PC value isn't enough, you also have to check if the execute_arbitration_isValid is high, else there is no valid instruction in the stage

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