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
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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 */
#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>
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
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(