CP0


Todos

  • tracking tlbLookupData.request/response for TLB hit/miss handling

    • MIPS.bsv: CP0Ifc declaration, contains subinterface of TranslationIfc tlbLookupData;
    • COP0.bsv: mkCP0: definition of TranslationIfc tlbLookupData: .request(reqIn) and .response()
    • invokes tlb.lookup[1/2].request(reqIn) and .response(), which is defined in mkTLB module
    • in TLB.bsv: lookup = lookups. see [../tlb], Do TLB search
  • tracking cache for hit/miss handling


Reference 1

File: cheri/trunk/CP0.bsv

Module mkCP0

mkCP0#(Bit#(16) coreId)(CP0Ifc)

Interfaces

interface CP0Ifc, in cheri/trunk/MIPS.bsv:

  • methods:
    • method for register read: readReq
    • method for register writePending bool flag writePending;
    • method for register write: writeReg;
    • method for reading current address space identifier: getAsid // a method to get current code/data page tags???
  • subinterfaces

    • interface TranslationIfc tlbLookupInstruction; // Initiate an instruction TLB lookup
    • interface TranslationIfc tlbLookupData; // Initiate a data TLB lookup
    • interface Vector#(2, TranslationIfc) tlbs; // For the DMA

      // cheri/trunk/MIPS.bsv
      
      // The CPOIfc interface is the interface for the system control processor, or coprocessor 0 (CP0).
      interface CP0Ifc;
      method Action                             readReq(RegNum rn, Bit#(3) sel);  // Initiate a CP0 register read
      method Bool writePending; // Report whether there is a write pending in CP0
      method ActionValue#(Word)                 readGet(Bool goingToWrite); // Deliver a read CP0 register to the main pipeline
      method Action                             writeReg(RegNum rn, Bit#(3) sel, Word data, Bool forceKernelMode, Bool writeBack); // Write a CP0 register
      method Cp0ExceptionReport                 getException(); // Get an exception report from CP0 (in writeback)
      method Action                             putException(ExceptionWriteback exp, Address ivaddr, MIPSReg dvaddr); // Report the final exception to CP0 from writeback
      method ActionValue#(Bool)                 setLlScReg(Address matchAddress, Bool link, Bool store); // Set the load linked address
      method Action                             interrupts(Bit#(5) interruptLines); // Put the external interrupt line state into CP0
      method CoProEn                            getCoprocessorEnables(); // Report the current state of the coprocessor enable signals.
      method HWREna                             getHardwareRegisterEnables();
      method Bit#(8)                            getAsid(); // Report the current address space identifier.
      method Action                             putCount(Bit#(48) commonCount); // Put the common count register for all cores.
      method Action                             putCacheConfiguration(L1ChCfg iCacheConfig, L1ChCfg dCacheConfig); // Recieve a report of 
                                                                   // the L1 cache configurations.  This allows the caches to define their
                                                                   // own configurations.
      method Action                             putDeterministicCycleCount(Bool cycleCount);
      // Whether the CP0 thinks tracing should be turned on
      method Bool                               shouldTrace();
      `ifndef CHERIOS
      interface TranslationIfc tlbLookupInstruction; // Initiate an instruction TLB lookup
      interface TranslationIfc tlbLookupData;        // Initiate a data TLB lookup
      `endif // CHERIOS
      `ifdef DMA_VIRT
      interface Vector#(2, TranslationIfc) tlbs; // For the DMA
      `endif
      
      endinterface

States

States includes:

  • FIFOs:

    • readRegs
    • tlbReads
    • tlbProbes
    • tlbProbeResponses
    • eretHappened

    • rnUpdate // store register write request in writeReg sand do it in rule updateCP0Registers

    • dataUpdate

    • foreUpdate

    • expectWrites

    • deqExpectWrites

  • RWries, write then read in same cycle:

    • RWire#(Bit#(41)) pteWire <- mkRWire;
    • RWire#(Bit#(31)) xpteWire <- mkRWire;
  • default values

    • Registers:
    • StatusRegister defaultSR = StatusRegister{…};
    • PRId defaultProcID; // processor ID

    • TlbEntryLo defaulttlbEntryLo; //

    • TlbEntryHi defaultTlbEntryHi; //

    • TlbResponse defaultTlbResponse;

    • Config0 defaultConfig0; // cache coherency algorithm; MMU type; Little/Big endian; …

    • LxChCfg l2ChCfg, l3ChCfg; // cache associativity; cache line size; …

    • Config1 defaultConfig1; // coprocessor 2; size of TLB entry. (MMU has mmuSize +1 entries)

    • Config2 defaultConfig2; // l2 config, l3 config

    • Config3 defaultConfig3; // …

    • Config6 defaultConfig6; // inferred from nlm’s source code in FreeBSD; tlbSize 271, …

  • Registers: 30 different categories

    • tlbIndex: index into the TLB
    • tlbEntryLo0: entry Lo of even virtual address of a pair
    • tlbEntryLo1: entry Hi of odd virtual address of a pair ???
    • tlsPointer: ??? 64 bits,
    • tlbPageMask: 12 bits,
    • status register Reg#(StatusRegister) sr <- mkConfigReg(defaultSR);
  • TLB module: TLBIfc tlb <- mkTLB(coreid.coreID);

rules

  • readTlb;
  • reportWiredToTLB;
  • probeStart;
  • updateContextRegisters_And_Count
  • updateCP0Registers (!tlbReads.notEmpty && !tlbProbeResponses.notEmpty)

Interface tlbLookupData

(ifndef MICRO && ifndef CHERIOS)

declaration: in cheri/trunk/MIPS.bsv:

// cheri/trunk/MIPS.bsv:

interface TranslationIfc;
  method ActionValue#(TlbResponse) request(TlbRequest reqIn);
  method ActionValue#(TlbResponse) response();

definition:

request(reqIn)

Steps: query tlb using tlb.lookup[2].requets(reqIn) and return result that contains success/failure/exception info

  • lookup tlb according to request reqIn: TlbResponse retVal <- tlb.lookup[2].request(reqIn);
  • check the return value for exceptions;
    • check Kernel/User mode matches current kernelMode or debug mode.
    • update retVal if exceptions.
  • return the retVal

Code:

// cheri/trunk/CP0.bsv

method ActionValue#(TlbResponse) request(TlbRequest reqIn);
    TlbResponse retVal <- tlb.lookup[2].request(reqIn);
    if (!kernelMode && !retVal.fromDebug) begin// && retVal.exception==None) begin
    if (retVal.priv==Kernel) retVal.exception = (retVal.write) ? DADES : DADEL;
    else if (retVal.priv == Supervisor && !supervisorMode) retVal.exception = (retVal.write) ? DADES : DADEL;
    end
    if (retVal.addr[35:0] == {watchHi,watchLo[31:3],3'b0} &&     // If there has not been an exception and the address matches
    ((watchLo[1]==1'b1 && !retVal.write) || (watchLo[0]==1'b1 && retVal.write))) begin  // and the address is watching for a read or a write and the operation matches.
    if (retVal.exception == None) retVal.exception = Watch;
    end
    return retVal;
endmethod

response()

Steps: query response info via tlb.lookup[2].response() and return result with failure/success/exception info

  • get response from tlb: TlbResponse retVal <- tlb.lookup[2].response();
  • check and update the TlbResponse;
  • return the TlbResponse.

interface tlbLookupInstruction

request(TlbRequest reqIn)

TlbResponse retVal <- tlb.lookup[1].request(reqIn);

response()

tlb.lookup[1].response()


  1. reference ↩
Created May 4, 2020 // Last Updated May 18, 2021

If you could revise
the fundmental principles of
computer system design
to improve security...

... what would you change?