]> rtime.felk.cvut.cz Git - jailhouse.git/commitdiff
x86: Add i8042 moderation
authorJan Kiszka <jan.kiszka@siemens.com>
Sun, 24 Aug 2014 18:53:10 +0000 (20:53 +0200)
committerJan Kiszka <jan.kiszka@siemens.com>
Thu, 28 Aug 2014 06:36:10 +0000 (08:36 +0200)
To avoid that a cell can trigger a system reset or fiddle with the A20
gate via the keyboard controller i8042, intercept the command register
access. This happens for all cells, even when port access is granted.
The filter will only perform the access on behalf of the cell if port
access is granted in the cell's PIO bitmap - and the output port of the
i8042 is not touched as well.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
hypervisor/arch/x86/Makefile
hypervisor/arch/x86/i8042.c [new file with mode: 0644]
hypervisor/arch/x86/include/asm/i8042.h [new file with mode: 0644]
hypervisor/arch/x86/vmx.c

index 54757c0db22cbc6eaa872b4ffc32eab71cc5183e..976bb8c1eaca19e4ed4c4e5236d015b049d4861d 100644 (file)
@@ -13,4 +13,4 @@
 always := built-in.o
 
 obj-y := apic.o dbg-write.o entry.o setup.o vmx.o control.o mmio.o \
-        vtd.o paging.o ../../pci.o pci.o ioapic.o
+        vtd.o paging.o ../../pci.o pci.o ioapic.o i8042.o
diff --git a/hypervisor/arch/x86/i8042.c b/hypervisor/arch/x86/i8042.c
new file mode 100644 (file)
index 0000000..bdf7329
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Jailhouse, a Linux-based partitioning hypervisor
+ *
+ * Copyright (c) Siemens AG, 2014
+ *
+ * Authors:
+ *  Jan Kiszka <jan.kiszka@siemens.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ */
+
+#include <jailhouse/printk.h>
+#include <jailhouse/utils.h>
+#include <asm/i8042.h>
+#include <asm/io.h>
+#include <asm/percpu.h>
+
+#include <jailhouse/cell-config.h>
+
+int i8042_access_handler(struct registers *guest_regs, u16 port, bool dir_in,
+                        unsigned int size)
+{
+       const struct jailhouse_cell_desc *config = this_cell()->config;
+       const u8 *pio_bitmap = jailhouse_cell_pio_bitmap(config);
+       u8 val;
+
+       if (port == I8042_CMD_REG &&
+           config->pio_bitmap_size >= (I8042_CMD_REG + 7) / 8 &&
+           !(pio_bitmap[I8042_CMD_REG / 8] & (1 << (I8042_CMD_REG % 8)))) {
+               if (size != 1)
+                       goto invalid_access;
+               if (dir_in) {
+                       guest_regs->rax &= ~BYTE_MASK(1);
+                       guest_regs->rax |= inb(I8042_CMD_REG);
+               } else {
+                       val = (u8)guest_regs->rax;
+                       if (size != 1 || val == I8042_CMD_WRITE_CTRL_PORT ||
+                           (val & I8042_CMD_PULSE_CTRL_PORT) ==
+                           I8042_CMD_PULSE_CTRL_PORT)
+                               goto invalid_access;
+                       outb(val, I8042_CMD_REG);
+               }
+               return 1;
+       }
+       return 0;
+
+invalid_access:
+       panic_printk("FATAL: Invalid write to i8042 controller port\n");
+       return -1;
+}
diff --git a/hypervisor/arch/x86/include/asm/i8042.h b/hypervisor/arch/x86/include/asm/i8042.h
new file mode 100644 (file)
index 0000000..9fb5e27
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Jailhouse, a Linux-based partitioning hypervisor
+ *
+ * Copyright (c) Siemens AG, 2014
+ *
+ * Authors:
+ *  Jan Kiszka <jan.kiszka@siemens.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ */
+
+#ifndef _JAILHOUSE_ASM_I8042_H
+#define _JAILHOUSE_ASM_I8042_H
+
+#include <asm/processor.h>
+
+#define I8042_CMD_REG                  0x64
+# define I8042_CMD_WRITE_CTRL_PORT     0xd1
+# define I8042_CMD_PULSE_CTRL_PORT     0xf0
+
+int i8042_access_handler(struct registers *guest_regs, u16 port, bool dir_in,
+                        unsigned int size);
+
+#endif /* !_JAILHOUSE_ASM_I8042_H */
index 4fcec5fc5f926191c5d59554cc557f0b2c2c61fb..b4d6eb0a5e87106efbff62c3691e8a5649ca3268 100644 (file)
@@ -21,6 +21,7 @@
 #include <jailhouse/pci.h>
 #include <asm/apic.h>
 #include <asm/control.h>
+#include <asm/i8042.h>
 #include <asm/io.h>
 #include <asm/ioapic.h>
 #include <asm/pci.h>
@@ -299,6 +300,9 @@ int vmx_cell_init(struct cell *cell)
                pio_bitmap_size -= size;
        }
 
+       /* moderation access to i8042 command register */
+       cell->vmx.io_bitmap[I8042_CMD_REG / 8] |= 1 << (I8042_CMD_REG % 8);
+
        if (cell != &root_cell) {
                /*
                 * Shrink PIO access of root cell corresponding to new cell's
@@ -1032,6 +1036,8 @@ static bool vmx_handle_io_access(struct registers *guest_regs,
 
        result = x86_pci_config_handler(guest_regs, cpu_data->cell, port,
                                        dir_in, size);
+       if (result == 0)
+               result = i8042_access_handler(guest_regs, port, dir_in, size);
 
        if (result == 1) {
                vmx_skip_emulated_instruction(