Gabe Black has uploaded this change for review. ( https://gem5-review.googlesource.com/c/public/gem5/+/57200 )

Change subject: arch-x86: Add a check for setting data segments.
......................................................................

arch-x86: Add a check for setting data segments.

Also mask the selector value in the chks microop, and mask out
the RPL when using it as an error code.

Change-Id: I2aca3020e3288186fe87b785b8f2343dede7f132
---
M src/arch/x86/isa/microops/regop.isa
M src/arch/x86/microcode/general_purpose/data_transfer/move.ucode
M src/arch/x86/ucasmlib/arch/x86/microops/regop.py
M src/arch/x86/ucasmlib/arch/x86/symbols.py
4 files changed, 56 insertions(+), 23 deletions(-)



diff --git a/src/arch/x86/isa/microops/regop.isa b/src/arch/x86/isa/microops/regop.isa
index 36884c5..93ba2c4 100644
--- a/src/arch/x86/isa/microops/regop.isa
+++ b/src/arch/x86/isa/microops/regop.isa
@@ -138,6 +138,7 @@
     {
         SegNoCheck,
         SegCSCheck,
+        SegDataCheck,
         SegCallGateCheck,
         SegIntGateCheck,
         SegSoftIntGateCheck,
diff --git a/src/arch/x86/microcode/general_purpose/data_transfer/move.ucode b/src/arch/x86/microcode/general_purpose/data_transfer/move.ucode
index 0b35f08..157af16 100644
--- a/src/arch/x86/microcode/general_purpose/data_transfer/move.ucode
+++ b/src/arch/x86/microcode/general_purpose/data_transfer/move.ucode
@@ -266,7 +266,7 @@
 def macroop MOV {
     .args 'S', 'R'
     m_read_descriptor desc="t3", selector="regm"
-    chks t0, regm, t3, NoCheck, dataSize=8
+    chks t0, regm, t3, DataCheck, dataSize=8
     wrdl sr, t3, regm
     wrsel sr, regm
 };
@@ -275,7 +275,7 @@
     .args 'S', 'M'
     ld t1, seg, sib, disp, dataSize=2
     m_read_descriptor desc="t3", selector="t1"
-    chks t0, t1, t3, NoCheck, dataSize=8
+    chks t0, t1, t3, DataCheck, dataSize=8
     wrdl sr, t3, t1
     wrsel sr, t1
 };
@@ -285,7 +285,7 @@
     rdip t7
     ld t1, seg, riprel, disp, dataSize=2
     m_read_descriptor desc="t3", selector="t1"
-    chks t0, t1, t3, NoCheck, dataSize=8
+    chks t0, t1, t3, DataCheck, dataSize=8
     wrdl sr, t3, t1
     wrsel sr, t1
 };
diff --git a/src/arch/x86/ucasmlib/arch/x86/microops/regop.py b/src/arch/x86/ucasmlib/arch/x86/microops/regop.py
index aab033d..9927bf7 100644
--- a/src/arch/x86/ucasmlib/arch/x86/microops/regop.py
+++ b/src/arch/x86/ucasmlib/arch/x86/microops/regop.py
@@ -1244,10 +1244,12 @@
         self.ext = check
     code = '''
         // The selector is in source 1 and can be at most 16 bits.
-        SegSelector selector = SrcReg1;
+        SegSelector selector = SrcReg1 & mask(16);
         SegDescriptor desc = SrcReg2;
         HandyM5Reg m5reg = M5Reg;

+        uint32_t seg_error_code = selector & ~mask(2);
+
         switch (ext) {
           case SegNoCheck:
             break;
@@ -1259,16 +1261,30 @@
                 fault = std::make_shared<GeneralProtection>(0);
             }
             break;
+          case SegDataCheck:
+            if (!selector.si && !selector.ti) {
+                // Null selector, no fault unless the segment is used.
+            } else if ((desc.s == 0 ||
+                        (desc.type.codeOrData == 1 && desc.type.r == 0))) {
+                // Wrong type.
+ fault = std::make_shared<GeneralProtection>(seg_error_code);
+            } else if ((desc.type.codeOrData == 0 || desc.type.c == 0) &&
+                    (desc.dpl < m5reg.cpl || desc.dpl < selector.rpl)) {
+                // Data or non-conforming code segment, but RPL or CPL was
+                // greater than the DPL.
+ fault = std::make_shared<GeneralProtection>(seg_error_code);
+            }
+            break;
           case SegCallGateCheck:
             if (desc.s != 0 || (desc.type & mask(3)) != 0x4 ||
                     desc.dpl < m5reg.cpl || desc.dpl < selector.rpl) {
-                fault = std::make_shared<GeneralProtection>(selector);
+ fault = std::make_shared<GeneralProtection>(seg_error_code);
             }
             break;
           case SegSoftIntGateCheck:
             // Check permissions.
             if (desc.dpl < m5reg.cpl) {
-                fault = std::make_shared<GeneralProtection>(selector);
+ fault = std::make_shared<GeneralProtection>(seg_error_code);
                 break;
             }
             [[fallthrough]];
@@ -1286,16 +1302,17 @@
           case SegSSCheck:
             if (selector.si || selector.ti) {
                 if (!desc.p) {
-                    fault = std::make_shared<StackFault>(selector);
+                    fault = std::make_shared<StackFault>(seg_error_code);
                 } else if (!(desc.s == 1 && desc.type.codeOrData == 0 &&
                             desc.type.w) ||
                         (desc.dpl != m5reg.cpl) ||
                         (selector.rpl != m5reg.cpl)) {
-                    fault = std::make_shared<GeneralProtection>(selector);
+                    fault = std::make_shared<GeneralProtection>(
+                            seg_error_code);
                 }
             } else if (m5reg.submode != SixtyFourBitMode ||
                     m5reg.cpl == 3) {
-                fault = std::make_shared<GeneralProtection>(selector);
+ fault = std::make_shared<GeneralProtection>(seg_error_code);
             }
             break;
           case SegIretCheck:
@@ -1305,23 +1322,26 @@
                         !(desc.s == 1 && desc.type.codeOrData == 1) ||
                         (!desc.type.c && desc.dpl != selector.rpl) ||
                         (desc.type.c && desc.dpl > selector.rpl)) {
-                    fault = std::make_shared<GeneralProtection>(selector);
+                    fault = std::make_shared<GeneralProtection>(
+                            seg_error_code);
                 } else if (!desc.p) {
-                    fault = std::make_shared<SegmentNotPresent>(selector);
+                    fault = std::make_shared<SegmentNotPresent>(
+                            seg_error_code);
                 }
                 break;
             }
           case SegIntCSCheck:
             if (desc.type.codeOrData != 1) {
-                fault = std::make_shared<GeneralProtection>(selector);
+ fault = std::make_shared<GeneralProtection>(seg_error_code);
             } else if (m5reg.mode == LongMode) {
                 if (desc.l != 1 || desc.d != 0) {
-                    fault = std::make_shared<GeneralProtection>(selector);
+                    fault = std::make_shared<GeneralProtection>(
+                            seg_error_code);
                 }
             }

             if (m5reg.cpl < desc.dpl) {
-                fault = std::make_shared<GeneralProtection>(selector);
+ fault = std::make_shared<GeneralProtection>(seg_error_code);
             }
             if (desc.type.c) {
                 selector.rpl = m5reg.cpl;
@@ -1332,28 +1352,28 @@
             break;
           case SegTRCheck:
             if (!selector.si || selector.ti) {
-                fault = std::make_shared<GeneralProtection>(selector);
+ fault = std::make_shared<GeneralProtection>(seg_error_code);
             }
             break;
           case SegTSSCheck:
             if (!desc.p) {
-                fault = std::make_shared<SegmentNotPresent>(selector);
+ fault = std::make_shared<SegmentNotPresent>(seg_error_code);
             } else if (!(desc.type == 0x9 ||
                     (desc.type == 1 &&
                      m5reg.mode != LongMode))) {
-                fault = std::make_shared<GeneralProtection>(selector);
+ fault = std::make_shared<GeneralProtection>(seg_error_code);
             }
             break;
           case SegInGDTCheck:
             if (selector.ti) {
-                fault = std::make_shared<GeneralProtection>(selector);
+ fault = std::make_shared<GeneralProtection>(seg_error_code);
             }
             break;
           case SegLDTCheck:
             if (!desc.p) {
-                fault = std::make_shared<SegmentNotPresent>(selector);
+ fault = std::make_shared<SegmentNotPresent>(seg_error_code);
             } else if (desc.type != 0x2) {
-                fault = std::make_shared<GeneralProtection>(selector);
+ fault = std::make_shared<GeneralProtection>(seg_error_code);
             }
             break;
           default:
diff --git a/src/arch/x86/ucasmlib/arch/x86/symbols.py b/src/arch/x86/ucasmlib/arch/x86/symbols.py
index 6421aa2..7c9d5db 100644
--- a/src/arch/x86/ucasmlib/arch/x86/symbols.py
+++ b/src/arch/x86/ucasmlib/arch/x86/symbols.py
@@ -67,9 +67,9 @@
     symbols[f'{letter.lower()}s'] = segRegIdx(f'SEGMENT_REG_{letter}S')

 # Add in symbols for the various checks of segment selectors.
-for check in ('NoCheck', 'CSCheck', 'CallGateCheck', 'IntGateCheck',
-              'SoftIntGateCheck', 'SSCheck', 'IretCheck', 'IntCSCheck',
-              'TRCheck', 'TSSCheck', 'InGDTCheck', 'LDTCheck'):
+for check in ('NoCheck', 'CSCheck', 'DataCheck', 'CallGateCheck',
+              'IntGateCheck', 'SoftIntGateCheck', 'SSCheck', 'IretCheck',
+              'IntCSCheck', 'TRCheck', 'TSSCheck', 'InGDTCheck', 'LDTCheck'):
     symbols[check] = f'Seg{check}'

 for reg in ('TR', 'IDTR'):

--
To view, visit https://gem5-review.googlesource.com/c/public/gem5/+/57200
To unsubscribe, or for help writing mail filters, visit https://gem5-review.googlesource.com/settings

Gerrit-Project: public/gem5
Gerrit-Branch: develop
Gerrit-Change-Id: I2aca3020e3288186fe87b785b8f2343dede7f132
Gerrit-Change-Number: 57200
Gerrit-PatchSet: 1
Gerrit-Owner: Gabe Black <[email protected]>
Gerrit-MessageType: newchange
_______________________________________________
gem5-dev mailing list -- [email protected]
To unsubscribe send an email to [email protected]
%(web_page_url)slistinfo%(cgiext)s/%(_internal_name)s

Reply via email to