arch-x86, mem: Add support to tag tlb entries with PCID

This change adds support to tag tlb entries with PCID to
avoid the conflict between different processes with same
virtual addresses sharing a tlb. This eventually is required
to enable smt support for x86.

Change-Id: Ia91dc371482793962e3fc83afe7a3fd2cdb60eab
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/35836
Maintainer: Bobby Bruce <bbruce@ucdavis.edu>
Reviewed-by: Bobby Bruce <bbruce@ucdavis.edu>
Tested-by: kokoro <noreply+kokoro@google.com>
diff --git a/src/arch/x86/pagetable_walker.cc b/src/arch/x86/pagetable_walker.cc
index f4831b3..bb1ccdb 100644
--- a/src/arch/x86/pagetable_walker.cc
+++ b/src/arch/x86/pagetable_walker.cc
@@ -504,8 +504,22 @@
     }
     if (doEndWalk) {
         if (doTLBInsert)
-            if (!functional)
-                walker->tlb->insert(entry.vaddr, entry);
+            if (!functional) {
+
+                // Check if PCIDE is set in CR4
+                CR4 cr4 = tc->readMiscRegNoEffect(misc_reg::Cr4);
+                if (cr4.pcide){
+                    CR3 cr3 = tc->readMiscRegNoEffect(misc_reg::Cr3);
+                    walker->tlb->insert(entry.vaddr, entry, cr3.pcid);
+                }
+                else{
+                    // The current PCID is always 000H if PCIDE
+                    // is not set [sec 4.10.1 of Intel's Software
+                    // Developer Manual]
+                    walker->tlb->insert(entry.vaddr, entry, 0x000);
+                }
+            }
+
         endWalk();
     } else {
         PacketPtr oldRead = read;
diff --git a/src/arch/x86/tlb.cc b/src/arch/x86/tlb.cc
index 9d26653..5ccd3e8 100644
--- a/src/arch/x86/tlb.cc
+++ b/src/arch/x86/tlb.cc
@@ -97,8 +97,14 @@
 }
 
 TlbEntry *
-TLB::insert(Addr vpn, const TlbEntry &entry)
+TLB::insert(Addr vpn, const TlbEntry &entry, uint64_t pcid)
 {
+    //Adding pcid to the page address so
+    //that multiple processes using the same
+    //tlb do not conflict when using the same
+    //virtual addresses
+    vpn = concAddrPcid(vpn, pcid);
+
     // If somebody beat us to it, just use that existing entry.
     TlbEntry *newEntry = trie.lookup(vpn);
     if (newEntry) {
@@ -115,8 +121,14 @@
     *newEntry = entry;
     newEntry->lruSeq = nextSeq();
     newEntry->vaddr = vpn;
-    newEntry->trieHandle =
-    trie.insert(vpn, TlbEntryTrie::MaxBits - entry.logBytes, newEntry);
+    if (FullSystem) {
+        newEntry->trieHandle =
+        trie.insert(vpn, TlbEntryTrie::MaxBits-entry.logBytes, newEntry);
+    }
+    else {
+        newEntry->trieHandle =
+        trie.insert(vpn, TlbEntryTrie::MaxBits, newEntry);
+    }
     return newEntry;
 }
 
@@ -390,7 +402,22 @@
         if (m5Reg.paging) {
             DPRINTF(TLB, "Paging enabled.\n");
             // The vaddr already has the segment base applied.
-            TlbEntry *entry = lookup(vaddr);
+
+            //Appending the pcid (last 12 bits of CR3) to the
+            //page aligned vaddr if pcide is set
+            CR4 cr4 = tc->readMiscRegNoEffect(misc_reg::Cr4);
+            Addr pageAlignedVaddr = vaddr & (~mask(X86ISA::PageShift));
+            CR3 cr3 = tc->readMiscRegNoEffect(misc_reg::Cr3);
+            uint64_t pcid;
+
+            if (cr4.pcide)
+                pcid = cr3.pcid;
+            else
+                pcid = 0x000;
+
+            pageAlignedVaddr = concAddrPcid(pageAlignedVaddr, pcid);
+            TlbEntry *entry = lookup(pageAlignedVaddr);
+
             if (mode == BaseMMU::Read) {
                 stats.rdAccesses++;
             } else {
@@ -412,7 +439,7 @@
                         delayedResponse = true;
                         return fault;
                     }
-                    entry = lookup(vaddr);
+                    entry = lookup(pageAlignedVaddr);
                     assert(entry);
                 } else {
                     Process *p = tc->getProcessPtr();
@@ -428,7 +455,8 @@
                         entry = insert(alignedVaddr, TlbEntry(
                                 p->pTable->pid(), alignedVaddr, pte->paddr,
                                 pte->flags & EmulationPageTable::Uncacheable,
-                                pte->flags & EmulationPageTable::ReadOnly));
+                                pte->flags & EmulationPageTable::ReadOnly),
+                                pcid);
                     }
                     DPRINTF(TLB, "Miss was serviced.\n");
                 }
diff --git a/src/arch/x86/tlb.hh b/src/arch/x86/tlb.hh
index 68fe259..95c3482 100644
--- a/src/arch/x86/tlb.hh
+++ b/src/arch/x86/tlb.hh
@@ -76,6 +76,11 @@
         TlbEntry *lookup(Addr va, bool update_lru = true);
 
         void setConfigAddress(uint32_t addr);
+        //concatenate Page Addr and pcid
+        inline Addr concAddrPcid(Addr vpn, uint64_t pcid)
+        {
+          return (vpn | pcid);
+        }
 
       protected:
 
@@ -156,7 +161,7 @@
         Fault finalizePhysical(const RequestPtr &req, ThreadContext *tc,
                                BaseMMU::Mode mode) const override;
 
-        TlbEntry *insert(Addr vpn, const TlbEntry &entry);
+        TlbEntry *insert(Addr vpn, const TlbEntry &entry, uint64_t pcid);
 
         // Checkpointing
         void serialize(CheckpointOut &cp) const override;