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