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

Reply via email to