From aff0c8d5c709dc02669fbaa4b5ff2cfdda122a61 Mon Sep 17 00:00:00 2001
From: Frans Kaashoek <kaashoek@mit.edu>
Date: Fri, 26 Aug 2016 08:20:11 -0400
Subject: [PATCH] set iomb to forbid i/o instructions from user space add to
 test that they indeed trap in user space thanks to pablogventura@gmail.com
 and nwolovick@gmail.com

---
 usertests.c | 32 ++++++++++++++++++++++++++++++++
 vm.c        |  1 +
 2 files changed, 33 insertions(+)

diff --git a/usertests.c b/usertests.c
index 458f8ed..93f656b 100644
--- a/usertests.c
+++ b/usertests.c
@@ -1695,6 +1695,35 @@ fsfull()
   printf(1, "fsfull test finished\n");
 }
 
+void
+uio()
+{
+  #define RTC_ADDR 0x70
+  #define RTC_DATA 0x71
+
+  ushort port = 0;
+  uchar val = 0;
+  int pid;
+
+  printf(1, "uio test\n");
+  pid = fork();
+  if(pid == 0){
+    port = RTC_ADDR;
+    val = 0x09;  /* year */
+    /* http://wiki.osdev.org/Inline_Assembly/Examples */
+    asm volatile("outb %0,%1"::"a"(val), "d" (port));
+    port = RTC_DATA;
+    asm volatile("inb %1,%0" : "=a" (val) : "d" (port));
+    printf(1, "uio: uio succeeded; test FAILED\n");
+    exit();
+  } else if(pid < 0){
+    printf (1, "fork failed\n");
+    exit();
+  }
+  wait();
+  printf(1, "uio test done\n");
+}
+
 unsigned long randstate = 1;
 unsigned int
 rand()
@@ -1751,6 +1780,9 @@ main(int argc, char *argv[])
   iref();
   forktest();
   bigdir(); // slow
+
+  uio();
+
   exectest();
 
   exit();
diff --git a/vm.c b/vm.c
index 16fb03b..d4982ee 100644
--- a/vm.c
+++ b/vm.c
@@ -168,6 +168,7 @@ switchuvm(struct proc *p)
   cpu->gdt[SEG_TSS].s = 0;
   cpu->ts.ss0 = SEG_KDATA << 3;
   cpu->ts.esp0 = (uint)proc->kstack + KSTACKSIZE;
+  cpu->ts.iomb = (ushort) 0xFFFF;  // forbid I/O instructions from user space
   ltr(SEG_TSS << 3);
   if(p->pgdir == 0)
     panic("switchuvm: no pgdir");