Gabe Black has uploaded this change for review. (
https://gem5-review.googlesource.com/c/public/gem5/+/57021 )
Change subject: arch-x86: Fill out the implementation of IN/OUT/INS/OUTS
insts.
......................................................................
arch-x86: Fill out the implementation of IN/OUT/INS/OUTS insts.
Implement IOPL and IO-permission bitmap checks, and the virtual 8086 mode
versions. The difference is that in virtual 8086 mode, the IOPL is not
checked, and the IO-permission bitmap is always checked.
Change-Id: Id836a482493c06a14e08993ead1e4ab7d630e078
---
M src/arch/x86/microcode/general_purpose/input_output/general_io.ucode
M src/arch/x86/microcode/general_purpose/input_output/string_io.ucode
A src/arch/x86/microcode/macros/ioports.ucode
3 files changed, 261 insertions(+), 23 deletions(-)
diff --git
a/src/arch/x86/microcode/general_purpose/input_output/general_io.ucode
b/src/arch/x86/microcode/general_purpose/input_output/general_io.ucode
index 58df96e..e01f9f6 100644
--- a/src/arch/x86/microcode/general_purpose/input_output/general_io.ucode
+++ b/src/arch/x86/microcode/general_purpose/input_output/general_io.ucode
@@ -36,55 +36,116 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+include "macros/ioports.ucode"
+
def macroop IN {
.args 'R', 'I'
.adjust_imm trimImm(8)
limm t1, imm, dataSize=8
+ m_check_iopl iopl_temp="t2", cpl_temp="t3"
+
mfence
+
+ # Do we need to check the IO-permission bitmap?
+ br "iopl_ok", flags=(nCECF,)
+
+ m_check_iopb io_port="t1", temp1="t2", temp2="t3"
+
+iopl_ok:
ldio reg, t1
mfence
};
def macroop IN_VIRT {
.args 'R', 'I'
- panic "Virtual mode in isn't implemented!"
+ .adjust_imm trimImm(8)
+ limm t1, imm, dataSize=8
+ mfence
+
+ m_check_iopb io_port="t1", temp1="t2", temp2="t3"
+
+ ldio reg, t1
+ mfence
};
def macroop IN {
.args 'R', 'R'
+ m_check_iopl iopl_temp="t1", cpl_temp="t2"
+
mfence
+
+ # Do we need to check the IO-permission bitmap?
+ br "iopl_ok", flags=(nCECF,)
+
+ m_check_iopb io_port="regm", temp1="t1", temp2="t2"
+
+iopl_ok:
ldio reg, regm
mfence
};
def macroop IN_VIRT {
.args 'R', 'R'
- panic "Virtual mode in isn't implemented!"
+ mfence
+
+ m_check_iopb io_port="regm", temp1="t1", temp2="t2"
+
+ ldio reg, regm
+ mfence
};
def macroop OUT {
.args 'I', 'R'
.adjust_imm trimImm(8)
limm t1, imm, dataSize=8
+ m_check_iopl iopl_temp="t2", cpl_temp="t3"
+
mfence
+
+ # Do we need to check the IO-permission bitmap?
+ br "iopl_ok", flags=(nCECF,)
+
+ m_check_iopb io_port="t1", temp1="t2", temp2="t3"
+
+iopl_ok:
stio reg, t1
mfence
};
def macroop OUT_VIRT {
.args 'I', 'R'
- panic "Virtual mode out isn't implemented!"
+ .adjust_imm trimImm(8)
+ limm t1, imm, dataSize=8
+ mfence
+
+ m_check_iopb io_port="t1", temp1="t2", temp2="t3"
+
+ stio reg, t1
+ mfence
};
def macroop OUT {
.args 'R', 'R'
- zexti t2, reg, 15, dataSize=8
+ m_check_iopl iopl_temp="t1", cpl_temp="t2"
+
mfence
+
+ # Do we need to check the IO-permission bitmap?
+ br "iopl_ok", flags=(nCECF,)
+
+ m_check_iopb io_port="reg", temp1="t1", temp2="t2"
+
+iopl_ok:
stio regm, reg
mfence
};
def macroop OUT_VIRT {
.args 'R', 'R'
- panic "Virtual mode out isn't implemented!"
+ mfence
+
+ m_check_iopb io_port="reg", temp1="t1", temp2="t2"
+
+ stio regm, reg
+ mfence
};
diff --git
a/src/arch/x86/microcode/general_purpose/input_output/string_io.ucode
b/src/arch/x86/microcode/general_purpose/input_output/string_io.ucode
index 40157fc..fffae9d 100644
--- a/src/arch/x86/microcode/general_purpose/input_output/string_io.ucode
+++ b/src/arch/x86/microcode/general_purpose/input_output/string_io.ucode
@@ -33,18 +33,27 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+include "macros/ioports.ucode"
+
def macroop INS {
.args 'Y', 'R'
+
# Find the constant we need to either add or subtract from rdi
ruflag t0, 10
movi t3, t3, dsz, flags=(CEZF,), dataSize=asz
subi t4, t0, dsz, dataSize=asz
mov t3, t3, t4, flags=(nCEZF,), dataSize=asz
- zexti t2, reg, 15, dataSize=8
+ m_check_iopl iopl_temp="t8", cpl_temp="t9"
mfence
- ldio t6, t2
+ # Do we need to check the IO-permission bitmap?
+ br "iopl_ok", flags=(nCECF,)
+
+ m_check_iopb io_port="reg", temp1="t8", temp2="t9"
+
+iopl_ok:
+ ldio t6, reg
st t6, es, [1, t0, rdi]
mfence
@@ -53,7 +62,22 @@
def macroop INS_VIRT {
.args 'Y', 'R'
- panic "Virtual mode ins isn't implemented!"
+
+ # Find the constant we need to either add or subtract from rdi
+ ruflag t0, 10
+ movi t3, t3, dsz, flags=(CEZF,), dataSize=asz
+ subi t4, t0, dsz, dataSize=asz
+ mov t3, t3, t4, flags=(nCEZF,), dataSize=asz
+
+ mfence
+
+ m_check_iopb io_port="reg", temp1="t8", temp2="t9"
+
+ ldio t6, reg
+ st t6, es, [1, t0, rdi]
+ mfence
+
+ add rdi, rdi, t3, dataSize=asz
};
def macroop INS_E {
@@ -66,24 +90,49 @@
subi t4, t0, dsz, dataSize=asz
mov t3, t3, t4, flags=(nCEZF,), dataSize=asz
- zexti t2, reg, 15, dataSize=8
+ m_check_iopl iopl_temp="t8", cpl_temp="t9"
mfence
-topOfLoop:
- ldio t6, t2
+ # Do we need to check the IO-permission bitmap?
+ br "top_of_loop", flags=(nCECF,)
+
+ m_check_iopb io_port="reg", temp1="t8", temp2="t9"
+
+top_of_loop:
+ ldio t6, reg
st t6, es, [1, t0, rdi]
subi rcx, rcx, 1, flags=(EZF,), dataSize=asz
add rdi, rdi, t3, dataSize=asz
- br "topOfLoop", flags=(nCEZF,)
+ br "top_of_loop", flags=(nCEZF,)
+
end:
mfence
- fault "NoFault"
};
def macroop INS_VIRT_E {
.args 'Y', 'R'
- panic "Virtual mode ins isn't implemented!"
+ and t0, rcx, rcx, flags=(EZF,), dataSize=asz
+ br "end", flags=(CEZF,)
+ # Find the constant we need to either add or subtract from rdi
+ ruflag t0, 10
+ movi t3, t3, dsz, flags=(CEZF,), dataSize=asz
+ subi t4, t0, dsz, dataSize=asz
+ mov t3, t3, t4, flags=(nCEZF,), dataSize=asz
+
+ mfence
+ m_check_iopb io_port="reg", temp1="t8", temp2="t9"
+
+top_of_loop:
+ ldio t6, reg
+ st t6, es, [1, t0, rdi]
+
+ subi rcx, rcx, 1, flags=(EZF,), dataSize=asz
+ add rdi, rdi, t3, dataSize=asz
+ br "top_of_loop", flags=(nCEZF,)
+
+end:
+ mfence
};
def macroop OUTS {
@@ -94,11 +143,17 @@
subi t4, t0, dsz, dataSize=asz
mov t3, t3, t4, flags=(nCEZF,), dataSize=asz
- zexti t2, reg, 15, dataSize=8
+ m_check_iopl iopl_temp="t8", cpl_temp="t9"
mfence
+ # Do we need to check the IO-permission bitmap?
+ br "iopl_ok", flags=(nCECF,)
+
+ m_check_iopb io_port="reg", temp1="t8", temp2="t9"
+
+iopl_ok:
ld t6, ds, [1, t0, rsi]
- stio t6, t2
+ stio t6, reg
mfence
add rsi, rsi, t3, dataSize=asz
@@ -106,7 +161,21 @@
def macroop OUTS_VIRT {
.args 'R', 'X'
- panic "Virtual mode outs isn't implemented!"
+ # Find the constant we need to either add or subtract from rdi
+ ruflag t0, 10
+ movi t3, t3, dsz, flags=(CEZF,), dataSize=asz
+ subi t4, t0, dsz, dataSize=asz
+ mov t3, t3, t4, flags=(nCEZF,), dataSize=asz
+
+ mfence
+ m_check_iopb io_port="reg", temp1="t8", temp2="t9"
+
+iopl_ok:
+ ld t6, ds, [1, t0, rsi]
+ stio t6, reg
+ mfence
+
+ add rsi, rsi, t3, dataSize=asz
};
def macroop OUTS_E {
@@ -119,22 +188,47 @@
subi t4, t0, dsz, dataSize=asz
mov t3, t3, t4, flags=(nCEZF,), dataSize=asz
- zexti t2, reg, 15, dataSize=8
+ m_check_iopl iopl_temp="t8", cpl_temp="t9"
mfence
-topOfLoop:
+ # Do we need to check the IO-permission bitmap?
+ br "top_of_loop", flags=(nCECF,)
+
+ m_check_iopb io_port="reg", temp1="t8", temp2="t9"
+
+top_of_loop:
ld t6, ds, [1, t0, rsi]
- stio t6, t2
+ stio t6, reg
subi rcx, rcx, 1, flags=(EZF,), dataSize=asz
add rsi, rsi, t3, dataSize=asz
- br "topOfLoop", flags=(nCEZF,)
+ br "top_of_loop", flags=(nCEZF,)
+
end:
mfence
- fault "NoFault"
};
def macroop OUTS_VIRT_E {
.args 'R', 'X'
- panic "Virtual mode outs isn't implemented!"
+ and t0, rcx, rcx, flags=(EZF,), dataSize=asz
+ br "end", flags=(CEZF,)
+ # Find the constant we need to either add or subtract from rdi
+ ruflag t0, 10
+ movi t3, t3, dsz, flags=(CEZF,), dataSize=asz
+ subi t4, t0, dsz, dataSize=asz
+ mov t3, t3, t4, flags=(nCEZF,), dataSize=asz
+
+ mfence
+ m_check_iopb io_port="reg", temp1="t8", temp2="t9"
+
+top_of_loop:
+ ld t6, ds, [1, t0, rsi]
+ stio t6, reg
+
+ subi rcx, rcx, 1, flags=(EZF,), dataSize=asz
+ add rsi, rsi, t3, dataSize=asz
+ br "top_of_loop", flags=(nCEZF,)
+
+end:
+ mfence
};
diff --git a/src/arch/x86/microcode/macros/ioports.ucode
b/src/arch/x86/microcode/macros/ioports.ucode
new file mode 100644
index 0000000..87ee164
--- /dev/null
+++ b/src/arch/x86/microcode/macros/ioports.ucode
@@ -0,0 +1,70 @@
+# Copyright 2022 Google Inc.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met: redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer;
+# redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution;
+# neither the name of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# Check if CPL is greater than the IOPL. ECF will be set if the bitmap
needs
+# to be checked.
+def macro m_check_iopl iopl_temp, cpl_temp {
+ # Extract the IOPL
+ rflags {iopl_temp}, dataSize=8
+ srli {iopl_temp}, {iopl_temp}, 12, dataSize=8
+ andi {iopl_temp}, {iopl_temp}, 0x3, dataSize=8
+
+ # Extract the CPL
+ rdm5reg {cpl_temp}, dataSize=8
+ srli {cpl_temp}, {cpl_temp}, 4, dataSize=8
+ andi {cpl_temp}, {cpl_temp}, 0x3, dataSize=8
+
+ # Compare them.
+ sub t0, {iopl_temp}, {cpl_temp}, flags=(ECF,)
+};
+
+# Check if bits related to an IO port are set in the IO permissions bitmap,
+# and raise a #GP if they are.
+def macro m_check_iopb io_port, temp1, temp2 {
+ # Get the IO-permission bitmap base address.
+ ld {temp1}, tr, [1, t0, t0], 0x66, dataSize=2, addressSize=8,
atCPL0=True
+
+ # Figure out what bytes the bits we want are in.
+ srli {temp2}, {io_port}, 3, dataSize=8
+
+ # Load those bytes from the bitmap. Even if it's only one bit, we still
+ # always read two bytes.
+ ld {temp1}, tr, [1, {temp2}, {temp1}], dataSize=2, addressSize=8, \
+ atCPL0=True
+
+ # Shift the bits into place.
+ andi {temp2}, {io_port}, 0x7, dataSize=8
+ srl {temp1}, {temp1}, {temp2}, dataSize=8
+
+ # Construct a mask to compare the bits with.
+ limm {temp2}, 0x1, dataSize=8
+ slli {temp2}, {temp2}, dsz, dataSize=8
+
+ # Check if any bits are set.
+ and t0, {temp1}, {temp2}, dataSize=8, flags=(EZF,)
+
+ # If yes, then GP
+ fault "std::make_shared<GeneralProtection>(0)", flags=(nCEZF,)
+};
--
To view, visit https://gem5-review.googlesource.com/c/public/gem5/+/57021
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: Id836a482493c06a14e08993ead1e4ab7d630e078
Gerrit-Change-Number: 57021
Gerrit-PatchSet: 1
Gerrit-Owner: Gabe Black <gabe.bl...@gmail.com>
Gerrit-MessageType: newchange
_______________________________________________
gem5-dev mailing list -- gem5-dev@gem5.org
To unsubscribe send an email to gem5-dev-le...@gem5.org
%(web_page_url)slistinfo%(cgiext)s/%(_internal_name)s