--- qemu-0.11.0/serialice.c
+++ qemu-0.11.0/serialice.c
@@ -0,0 +1,830 @@
+/*
+ * QEMU PC System Emulator
+ *
+ * Copyright (c) 2009 coresystems GmbH
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+/* System includes */
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <termios.h>
+#include <sys/ioctl.h>
+
+/* LUA includes */
+#include <lua.h>
+#include <lauxlib.h>
+#include <lualib.h>
+
+/* Local includes */
+#include "hw/hw.h"
+#include "hw/pc.h"
+#include "serialice.h"
+#include "sysemu.h"
+
+#define SERIALICE_DEBUG 3
+#define BUFFER_SIZE 1024
+typedef struct {
+	int fd;
+	char *buffer;
+} SerialICEState;
+
+static SerialICEState *s;
+
+int serialice_active = 0;
+const char *serialice_lua_script="serialice.lua";
+
+static struct termios options;
+
+static lua_State *L;
+
+// **************************************************************************
+// LUA scripting interface and callbacks
+
+static int serialice_register_physical(lua_State *luastate)
+{
+	int n = lua_gettop(luastate);
+	uint32_t addr, size;
+	ram_addr_t phys;
+
+	if (n != 2) {
+		fprintf(stderr, "ERROR: Not called as SerialICE_register_physical(<addr> <size>)\n");
+		return 0;
+	}
+
+	addr = lua_tointeger(luastate, 1);
+	size = lua_tointeger(luastate, 2);
+
+	printf("Registering physical memory at 0x%08x (0x%08x bytes)\n", addr, size);
+	phys = qemu_ram_alloc(size);
+	cpu_register_physical_memory(addr, size, phys);
+
+	return 0;
+}
+
+static int serialice_lua_init(void)
+{
+    int status;
+
+    /* Create a LUA context and load LUA libraries */
+    L = luaL_newstate();
+    luaL_openlibs(L);
+
+    /* Register C function callbacks */
+    lua_register(L, "SerialICE_register_physical", serialice_register_physical);
+
+    /* Load the script file */
+    status = luaL_loadfile(L, serialice_lua_script);
+    if (status) {
+        fprintf(stderr, "Couldn't load SerialICE script: %s\n", lua_tostring(L, -1));
+        exit(1);
+    }
+
+    /* Ask Lua to run our little script */
+    status = lua_pcall(L, 0, 1, 0);
+    if (status) {
+        fprintf(stderr, "Failed to run script: %s\n", lua_tostring(L, -1));
+        exit(1);
+    }
+    lua_pop(L, 1);
+
+    return 0;
+}
+
+static int serialice_lua_exit(void)
+{
+        lua_close(L);
+	return 0;
+}
+
+static int serialice_io_read_filter(uint32_t *data, uint16_t port, int size)
+{
+    int ret, result;
+
+    lua_getfield(L, LUA_GLOBALSINDEX, "SerialICE_io_read_filter");
+    lua_pushinteger(L, port); // port
+    lua_pushinteger(L, size); // datasize
+    result = lua_pcall(L, 2, 2, 0);
+    if (result) {
+        fprintf(stderr, "Failed to run function SerialICE_io_read_filter: %s\n", lua_tostring(L, -1));
+        exit(1);
+    }
+    *data = lua_tointeger(L, -1);
+    ret = lua_toboolean(L, -2);
+    lua_pop(L, 2);
+
+    return ret;
+} 
+
+static int serialice_io_write_filter(uint32_t data, uint16_t port, int size)
+{
+    int ret, result;
+
+    lua_getfield(L, LUA_GLOBALSINDEX, "SerialICE_io_write_filter");
+    lua_pushinteger(L, port); // port
+    lua_pushinteger(L, size); // datasize
+    lua_pushinteger(L, data); // data
+    result = lua_pcall(L, 3, 1, 0);
+    if (result) {
+        fprintf(stderr, "Failed to run function SerialICE_io_write_filter: %s\n", lua_tostring(L, -1));
+        exit(1);
+    }
+    ret = lua_toboolean(L, -1);
+    lua_pop(L, 1);
+
+    return ret;
+} 
+
+static int serialice_memory_read_filter(uint32_t addr, int size)
+{
+    int ret, result;
+
+    lua_getfield(L, LUA_GLOBALSINDEX, "SerialICE_memory_read_filter");
+    lua_pushinteger(L, addr); // addr
+    lua_pushinteger(L, size); // datasize
+    result = lua_pcall(L, 2, 1, 0);
+    if (result) {
+        fprintf(stderr, "Failed to run function SerialICE_memory_read_filter: %s\n", lua_tostring(L, -1));
+        exit(1);
+    }
+    ret = lua_toboolean(L, -1);
+    lua_pop(L, 1);
+
+    return ret;
+} 
+
+#define WRITE_TO_QEMU		(1 << 0)
+#define WRITE_TO_SERIALICE	(1 << 1)
+
+static int serialice_memory_write_filter(uint32_t addr, int size)
+{
+    int ret = 0, result;
+    int write_to_qemu, write_to_serialice;
+
+    lua_getfield(L, LUA_GLOBALSINDEX, "SerialICE_memory_write_filter");
+    lua_pushinteger(L, addr); // address
+    lua_pushinteger(L, size); // datasize
+    result = lua_pcall(L, 2, 2, 0);
+    if (result) {
+        fprintf(stderr, "Failed to run function SerialICE_memory_write_filter: %s\n", lua_tostring(L, -1));
+        exit(1);
+    }
+    write_to_qemu = lua_toboolean(L, -1);
+    write_to_serialice = lua_toboolean(L, -2);
+    lua_pop(L, 2);
+
+    // ugly
+    if (write_to_qemu) ret |= WRITE_TO_QEMU;
+    if (write_to_serialice) ret |= WRITE_TO_SERIALICE;
+
+    return ret;
+} 
+
+#define FILTER_READ	0
+#define FILTER_WRITE	1
+
+static int serialice_msr_filter(int flags, uint32_t addr, uint32_t *hi, uint32_t *lo)
+{
+    int ret, result;
+
+    if (flags & FILTER_WRITE)
+    	lua_getfield(L, LUA_GLOBALSINDEX, "SerialICE_msr_write_filter");
+    else
+    	lua_getfield(L, LUA_GLOBALSINDEX, "SerialICE_msr_read_filter");
+
+    lua_pushinteger(L, addr); // port
+    lua_pushinteger(L, *hi);  // high
+    lua_pushinteger(L, *lo);  // low
+    result = lua_pcall(L, 3, 3, 0);
+    if (result) {
+        fprintf(stderr, "Failed to run function SerialICE_msr_read_filter: %s\n", lua_tostring(L, -1));
+        exit(1);
+    }
+    ret = lua_toboolean(L, -3);
+    if (ret) {
+     	*hi = lua_tointeger(L, -1);
+    	*lo = lua_tointeger(L, -2);
+    }
+    lua_pop(L, 3);
+
+    return ret;
+} 
+
+static int serialice_cpuid_filter(cpuid_regs_t *regs)
+{
+    int ret, result;
+
+    lua_getfield(L, LUA_GLOBALSINDEX, "SerialICE_cpuid_filter");
+
+    lua_pushinteger(L, regs->eax); // eax
+    lua_pushinteger(L, regs->ecx); // ecx
+    result = lua_pcall(L, 2, 5, 0);
+    if (result) {
+        fprintf(stderr, "Failed to run function SerialICE_msr_read_filter: %s\n", lua_tostring(L, -1));
+        exit(1);
+    }
+
+    ret = lua_toboolean(L, -5);
+    if (ret) {
+    	regs->eax = lua_tointeger(L, -1);
+    	regs->ebx = lua_tointeger(L, -2);
+    	regs->ecx = lua_tointeger(L, -3);
+    	regs->edx = lua_tointeger(L, -4);
+    }
+    lua_pop(L, 5);
+
+    return ret;
+} 
+
+
+/* SerialICE output loggers */
+
+#define LOG_IO		0
+#define LOG_MEMORY	1
+#define LOG_READ	0
+#define LOG_WRITE	2
+// these two are separate
+#define LOG_QEMU	4
+#define LOG_TARGET	8
+
+static void serialice_log(int flags, uint32_t data, uint32_t addr, int size)
+{
+    int result;
+
+    if ((flags & LOG_WRITE) && (flags & LOG_MEMORY))
+    	lua_getfield(L, LUA_GLOBALSINDEX, "SerialICE_memory_write_log");
+    else if (!(flags & LOG_WRITE) && (flags & LOG_MEMORY))
+    	lua_getfield(L, LUA_GLOBALSINDEX, "SerialICE_memory_read_log");
+    else if ((flags & LOG_WRITE) && !(flags & LOG_MEMORY))
+    	lua_getfield(L, LUA_GLOBALSINDEX, "SerialICE_io_write_log");
+    else // if (!(flags & LOG_WRITE) && !(flags & LOG_MEMORY))
+    	lua_getfield(L, LUA_GLOBALSINDEX, "SerialICE_io_read_log");
+
+    lua_pushinteger(L, addr); // addr/port
+    lua_pushinteger(L, size); // datasize
+    lua_pushinteger(L, data); // data
+    result = lua_pcall(L, 3, 0, 0);
+    if (result) {
+        fprintf(stderr, "Failed to run function SerialICE_%s_%s_log: %s\n",
+			(flags & LOG_MEMORY)?"memory":"io", 
+			(flags & LOG_WRITE)?"write":"read",
+			lua_tostring(L, -1));
+        exit(1);
+    }
+
+    // TODO
+#if 0
+	if (caught) {
+		printf(" *");
+	}
+
+	printf("\n");
+#endif
+} 
+
+static void serialice_msr_log(int flags, uint32_t addr, uint32_t hi, uint32_t lo, int filtered)
+{
+    int result;
+
+    if (flags & LOG_WRITE)
+    	lua_getfield(L, LUA_GLOBALSINDEX, "SerialICE_msr_write_log");
+    else // if (!(flags & LOG_WRITE))
+    	lua_getfield(L, LUA_GLOBALSINDEX, "SerialICE_msr_read_log");
+
+    lua_pushinteger(L, addr); // addr/port
+    lua_pushinteger(L, hi); // datasize
+    lua_pushinteger(L, lo); // data
+    lua_pushboolean(L, filtered); // data
+    result = lua_pcall(L, 4, 0, 0);
+    if (result) {
+        fprintf(stderr, "Failed to run function SerialICE_msr_%s_log: %s\n",
+			(flags & LOG_WRITE)?"write":"read",
+			lua_tostring(L, -1));
+        exit(1);
+    }
+}
+
+static void serialice_cpuid_log(uint32_t eax, uint32_t ecx, cpuid_regs_t res, int filtered)
+{
+    int result;
+
+
+    lua_getfield(L, LUA_GLOBALSINDEX, "SerialICE_cpuid_log");
+
+    lua_pushinteger(L, eax); // input: eax
+    lua_pushinteger(L, ecx); // input: ecx
+    lua_pushinteger(L, res.eax); // output: eax
+    lua_pushinteger(L, res.ebx); // output: ebx
+    lua_pushinteger(L, res.ecx); // output: ecx
+    lua_pushinteger(L, res.edx); // output: edx
+    lua_pushboolean(L, filtered); // data
+    result = lua_pcall(L, 7, 0, 0);
+    if (result) {
+        fprintf(stderr, "Failed to run function SerialICE_cpuid_log: %s\n",
+			lua_tostring(L, -1));
+        exit(1);
+    }
+}
+
+
+// **************************************************************************
+// low level communication with the SerialICE shell (serial communication)
+
+static int serialice_read(int fd, void *buf, size_t nbyte)
+{
+	int bytes_read = 0;
+
+	while (1) {
+		int ret = read(fd, buf, nbyte);
+
+		if (ret == -1 && errno == EINTR)
+			continue;
+
+		if (ret == -1)
+			break;
+
+		bytes_read += ret;
+		buf += ret;
+
+		if (bytes_read >= (int)nbyte)
+			break;
+	}
+
+	return bytes_read;
+}
+
+static int serialice_write(int fd, const void *buf, size_t nbyte)
+{
+	char *buffer = (char *) buf;
+	char c;
+	int i;
+
+	for (i = 0; i < (int)nbyte; i++) {
+		while (write(fd, buffer + i, 1) != 1) ;
+		while (read(fd, &c, 1) != 1) ;
+		if (c != buffer[i]) {
+			printf("Readback error! %x/%x\n", c, buffer[i]);
+		}
+	}
+
+	return nbyte;
+}
+
+static void serialice_command(const char *command, int reply_len)
+{
+#if SERIALICE_DEBUG > 5
+	int i;
+#endif
+	int l;
+
+	serialice_write(s->fd, command, strlen(command));
+	
+	memset(s->buffer, 0, reply_len + 1); // clear enough of the buffer
+
+	l = serialice_read(s->fd, s->buffer, reply_len);
+
+	if (l == -1) {
+		perror("SerialICE: Could not read from target");
+		exit(1);
+	}
+
+	if (l != reply_len) {
+		printf("SerialICE: command was not answered sufficiently: "
+				"(%d/%d bytes)\n'%s'\n", l, reply_len, s->buffer);
+		exit(1);
+	}
+
+#if SERIALICE_DEBUG > 5
+	for (i=0; i < reply_len; i++)
+		printf("%02x ", s->buffer[i]);
+	printf("\n");
+#endif
+}
+
+
+// **************************************************************************
+// high level communication with the SerialICE shell
+
+uint8_t serialice_inb(uint16_t port)
+{
+	uint8_t ret;
+	char command[16];
+
+	uint32_t data;
+	if (serialice_io_read_filter(&data, port, 1))
+		return data & 0xff;
+
+	sprintf(command, "*ri%04x.b", port);
+	// command read back: "\n00\n> " (6 characters)
+	serialice_command(command, 6);
+	ret = (uint8_t)strtoul(s->buffer + 1, (char **)NULL, 16);
+
+	serialice_log(LOG_READ|LOG_IO, ret, port, 1);
+
+	return ret;
+}
+
+uint16_t serialice_inw(uint16_t port)
+{
+	uint16_t ret;
+	char command[16];
+
+	uint32_t data;
+	if (serialice_io_read_filter(&data, port, 1))
+		return data & 0xffff;
+
+	sprintf(command, "*ri%04x.w", port);
+	// command read back: "\n0000\n> " (8 characters)
+	serialice_command(command, 8);
+	ret = (uint16_t)strtoul(s->buffer + 1, (char **)NULL, 16);
+
+	serialice_log(LOG_READ|LOG_IO, ret, port, 2);
+
+	return ret;
+}
+
+uint32_t serialice_inl(uint16_t port)
+{
+	uint32_t ret;
+	char command[16];
+
+	uint32_t data;
+	if (serialice_io_read_filter(&data, port, 1))
+		return data;
+
+	sprintf(command, "*ri%04x.l", port);
+	// command read back: "\n00000000\n> " (12 characters)
+	serialice_command(command, 12);
+	ret = (uint32_t)strtoul(s->buffer + 1, (char **)NULL, 16);
+
+	serialice_log(LOG_READ|LOG_IO, ret, port, 4);
+
+	return ret;
+}
+
+void serialice_outb(uint8_t data, uint16_t port)
+{
+	char command[19];
+
+	serialice_log(LOG_WRITE|LOG_IO, data, port, 1);
+
+	if (serialice_io_write_filter(data, port, 1)) {
+		return;
+	}
+
+	sprintf(command, "*wi%04x.b=%02x", port, data);
+	// command read back: "\n> " (3 characters)
+	serialice_command(command, 3);
+}
+
+void serialice_outw(uint16_t data, uint16_t port)
+{
+	char command[21];
+
+	serialice_log(LOG_WRITE|LOG_IO, data, port, 2);
+
+	if (serialice_io_write_filter(data, port, 2)) {
+		return;
+	}
+
+	sprintf(command, "*wi%04x.w=%04x", port, data);
+	// command read back: "\n> " (3 characters)
+	serialice_command(command, 3);
+}
+
+void serialice_outl(uint32_t data, uint16_t port)
+{
+	char command[25];
+
+	serialice_log(LOG_WRITE|LOG_IO, data, port, 4);
+
+	if (serialice_io_write_filter(data, port, 4)) {
+		return;
+	}
+
+	sprintf(command, "*wi%04x.l=%08x", port, data);
+	// command read back: "\n> " (3 characters)
+	serialice_command(command, 3);
+}
+
+uint8_t serialice_readb(uint32_t addr)
+{
+	uint8_t ret;
+	char command[20];
+	sprintf(command, "*rm%08x.b", addr);
+	// command read back: "\n00\n> " (6 characters)
+	serialice_command(command, 6);
+	ret = (uint8_t)strtoul(s->buffer + 1, (char **)NULL, 16);
+	return ret;
+}
+
+uint16_t serialice_readw(uint32_t addr)
+{
+	uint16_t ret;
+	char command[20];
+	sprintf(command, "*rm%08x.w", addr);
+	// command read back: "\n0000\n> " (8 characters)
+	serialice_command(command, 8);
+	ret = (uint16_t)strtoul(s->buffer + 1, (char **)NULL, 16);
+	return ret;
+}
+
+uint32_t serialice_readl(uint32_t addr)
+{
+	uint32_t ret;
+	char command[20];
+	sprintf(command, "*rm%08x.l", addr);
+	// command read back: "\n00000000\n> " (12 characters)
+	serialice_command(command, 12);
+	ret = (uint32_t)strtoul(s->buffer + 1, (char **)NULL, 16);
+	return ret;
+}
+
+void serialice_writeb(uint8_t data, uint32_t addr)
+{
+	char command[24];
+	sprintf(command, "*wm%08x.b=%02x", addr, data);
+	// command read back: "\n> " (3 characters)
+	serialice_command(command, 3);
+}
+
+void serialice_writew(uint16_t data, uint32_t addr)
+{
+	char command[25];
+	sprintf(command, "*wm%08x.w=%04x", addr, data);
+	// command read back: "\n> " (3 characters)
+	serialice_command(command, 3);
+}
+
+void serialice_writel(uint32_t data, uint32_t addr)
+{
+	char command[29];
+	sprintf(command, "*wm%08x.l=%08x", addr, data);
+	// command read back: "\n> " (3 characters)
+	serialice_command(command, 3);
+}
+
+uint64_t serialice_rdmsr(uint32_t addr)
+{
+	uint32_t hi, lo;
+	uint64_t ret;
+	int filtered;
+
+	filtered = serialice_msr_filter(FILTER_READ, addr, &hi, &lo);
+	if (!filtered) {
+		char command[18];
+
+		sprintf(command, "*rc%08x", addr);
+
+		// command read back: "\n00000000.00000000\n> " (21 characters)
+		serialice_command(command, 21);
+
+		s->buffer[9] = 0; // . -> \0
+		hi = (uint32_t)strtoul(s->buffer + 1, (char **)NULL, 16);
+		lo = (uint32_t)strtoul(s->buffer + 10, (char **)NULL, 16);
+	}
+
+	ret = hi;
+	ret <<= 32;
+	ret |= lo;
+
+	serialice_msr_log(LOG_READ, addr, hi, lo, filtered);
+
+	return ret;
+}
+
+void serialice_wrmsr(uint64_t data, uint32_t addr)
+{
+	uint32_t hi, lo;
+	int filtered;
+
+	hi = (data >> 32);
+	lo = (data & 0xffffffff);
+
+	filtered = serialice_msr_filter(FILTER_WRITE, addr, &hi, &lo);
+
+	if (!filtered) {
+		char command[30];
+		sprintf(command, "*wc%08x=%08x.%08x", addr, hi, lo);
+		// command read back: "\n> " (3 characters)
+		serialice_command(command, 3);
+	}
+
+	serialice_msr_log(LOG_WRITE, addr, hi, lo, filtered);
+}
+
+cpuid_regs_t serialice_cpuid(uint32_t eax, uint32_t ecx)
+{
+	cpuid_regs_t ret;
+	int filtered;
+
+	ret.eax = eax;
+	ret.ebx = 0; // either set by filter or by target
+	ret.ecx = ecx;
+	ret.edx = 0; // either set by filter or by target
+
+	filtered = serialice_cpuid_filter(&ret);
+	if (!filtered) {
+		char command[27];
+
+		sprintf(command, "*ci%08x.%08x", eax, ecx);
+
+		// command read back: "\n000006f2.00000000.00001234.12340324\n> "
+		// (39 characters)
+		serialice_command(command, 39);
+
+		s->buffer[9] = 0; // . -> \0
+		s->buffer[18] = 0; // . -> \0
+		s->buffer[27] = 0; // . -> \0
+		ret.eax = (uint32_t)strtoul(s->buffer +  1, (char **)NULL, 16);
+		ret.ebx = (uint32_t)strtoul(s->buffer + 10, (char **)NULL, 16);
+		ret.ecx = (uint32_t)strtoul(s->buffer + 19, (char **)NULL, 16);
+		ret.edx = (uint32_t)strtoul(s->buffer + 28, (char **)NULL, 16);
+	}
+
+	serialice_cpuid_log(eax, ecx, ret, filtered);
+
+	return ret;
+}
+
+// **************************************************************************
+// memory load handling
+
+static uint32_t serialice_load_wrapper(uint32_t addr, unsigned int size)
+{
+	switch (size) {
+	case 1: return (uint32_t)serialice_readb(addr);
+	case 2: return (uint32_t)serialice_readw(addr);
+	case 4: return (uint32_t)serialice_readl(addr);
+	default: printf("WARNING: unknown read access size %d @%08x\n", size, addr);
+	}
+	return 0;
+}
+
+/**
+ * This function is called by the softmmu engine to update the status
+ * of a load cycle
+ */
+void serialice_log_load(int caught, uint32_t addr, uint32_t result, unsigned int data_size)
+{
+	if (caught)
+		serialice_log(LOG_READ|LOG_MEMORY|LOG_TARGET, result, addr, data_size);
+	else
+		serialice_log(LOG_READ|LOG_MEMORY, result, addr, data_size);
+}
+
+/* This function can grab Qemu load ops and forward them to the SerialICE
+ * target. 
+ *
+ * @return 0: Qemu exclusive or shared; 1: SerialICE exclusive.
+ */
+int serialice_handle_load(uint32_t addr, uint32_t *result, unsigned int data_size)
+{
+	int read_from_target;
+
+	read_from_target = serialice_memory_read_filter(addr, data_size);
+	if (read_from_target) {
+		*result = serialice_load_wrapper(addr, data_size);
+		return 1;
+	}
+	return 0;
+}
+
+
+// **************************************************************************
+// memory store handling
+
+static void serialice_store_wrapper(uint32_t addr, unsigned int size, uint32_t data)
+{
+	switch (size) {
+	case 1: serialice_writeb((uint8_t)data, addr); break;
+	case 2: serialice_writew((uint16_t)data, addr); break;
+	case 4: serialice_writel((uint32_t)data, addr); break;
+	default: printf("WARNING: unknown write access size %d @%08x\n", size, addr);
+	}
+}
+
+static void serialice_log_store(int caught, uint32_t addr, uint32_t val, unsigned int data_size)
+{
+	if (caught)
+		serialice_log(LOG_WRITE|LOG_MEMORY|LOG_TARGET, val, addr, data_size);
+	else
+		serialice_log(LOG_WRITE|LOG_MEMORY, val, addr, data_size);
+}
+
+/* This function can grab Qemu store ops and forward them to the SerialICE
+ * target
+ *
+ * @return 0: Qemu exclusive or shared; 1: SerialICE exclusive.
+ */
+
+int serialice_handle_store(uint32_t addr, uint32_t val, unsigned int data_size)
+{
+	int write_to_target, write_to_qemu, ret;
+
+	ret = serialice_memory_write_filter(addr, data_size);
+
+	write_to_target = ((ret & WRITE_TO_SERIALICE) != 0);
+	write_to_qemu = ((ret & WRITE_TO_QEMU) != 0);
+
+	serialice_log_store(write_to_target, addr, val, data_size);
+
+	if (write_to_target)
+		serialice_store_wrapper(addr, data_size, val);
+
+	return (write_to_qemu == 0);
+}
+
+// **************************************************************************
+// external initialization and exit
+
+void serialice_init(void)
+{
+	printf("SerialICE: Open connection to target hardware...\n");
+
+	if (serialice_device == NULL) {
+		printf("You need to specify a serial device to use SerialICE.\n");
+		exit(1);
+	}
+
+	s =  qemu_mallocz(sizeof(SerialICEState));
+
+	s->fd = open(serialice_device, O_RDWR | O_NOCTTY | O_NONBLOCK);
+
+	if (s->fd == -1) {
+		perror("SerialICE: Could not connect to target TTY");
+		exit(1);
+	}
+
+	if (ioctl(s->fd, TIOCEXCL) == -1) {
+		perror("SerialICE: TTY not exclusively available");
+		exit(1);
+	}
+
+	if (fcntl(s->fd, F_SETFL, 0) == -1) {
+		perror("SerialICE: Could not switch to blocking I/O");
+		exit(1);
+	}
+
+	if (tcgetattr(s->fd, &options) == -1) {
+		perror("SerialICE: Could not get TTY attributes");
+		exit(1);
+	}
+
+	cfsetispeed(&options, B115200);
+	cfsetospeed(&options, B115200);
+
+	/* set raw input, 1 second timeout */
+	options.c_cflag     |= (CLOCAL | CREAD);
+	options.c_lflag     &= ~(ICANON | ECHO | ECHOE | ISIG);
+	options.c_oflag     &= ~OPOST;
+	options.c_iflag     |= IGNCR;
+	options.c_cc[VMIN]  = 0;
+	options.c_cc[VTIME] = 100;
+
+	tcsetattr(s->fd, TCSANOW, &options);
+
+	tcflush(s->fd, TCIOFLUSH);
+
+	s->buffer = qemu_mallocz(BUFFER_SIZE);
+
+	printf("SerialICE: Waiting for handshake with target... ");
+	serialice_command("\n", 3);
+
+	if (!strncmp("\n> ", s->buffer, 3)) {
+		printf("target alife!\n");
+	} else {
+		printf("target not ok! (%s)\n", s->buffer );
+		exit(1);
+	}
+
+	printf("SerialICE: LUA init...\n");
+	serialice_lua_init();
+}
+
+void serialice_exit(void)
+{
+	serialice_lua_exit();
+}
+
--- qemu-0.11.0/serialice.h
+++ qemu-0.11.0/serialice.h
@@ -0,0 +1,42 @@
+#ifndef HW_SERIALICE_H
+#define HW_SERIALICE_H
+
+#include "config-host.h"
+
+extern const char *serialice_device;
+extern int serialice_active;
+
+void serialice_init(void);
+void serialice_exit(void);
+
+uint8_t serialice_inb(uint16_t port);
+uint16_t serialice_inw(uint16_t port);
+uint32_t serialice_inl(uint16_t port);
+
+void serialice_outb(uint8_t data, uint16_t port);
+void serialice_outw(uint16_t data, uint16_t port);
+void serialice_outl(uint32_t data, uint16_t port);
+
+uint8_t serialice_readb(uint32_t addr);
+uint16_t serialice_readw(uint32_t addr);
+uint32_t serialice_readl(uint32_t addr);
+
+void serialice_writeb(uint8_t data, uint32_t addr);
+void serialice_writew(uint16_t data, uint32_t addr);
+void serialice_writel(uint32_t data, uint32_t addr);
+
+uint64_t serialice_rdmsr(uint32_t addr);
+void serialice_wrmsr(uint64_t data, uint32_t addr);
+
+typedef struct {
+	uint32_t eax, ebx, ecx, edx;
+} cpuid_regs_t;
+
+
+cpuid_regs_t serialice_cpuid(uint32_t eax, uint32_t ecx);
+
+int serialice_handle_load(uint32_t addr, uint32_t *result, unsigned int data_size);
+void serialice_log_load(int caught, uint32_t addr, uint32_t result, unsigned int data_size);
+int serialice_handle_store(uint32_t addr, uint32_t val, unsigned int data_size);
+
+#endif
--- qemu-0.11.0/build.sh
+++ qemu-0.11.0/build.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+./configure --disable-kvm --disable-sdl --enable-serialice \
+	    --target-list="x86_64-softmmu, i386-softmmu"
+
+make
--- qemu-0.11.0/Makefile.target
+++ qemu-0.11.0/Makefile.target
@@ -488,6 +488,13 @@
 # Generic watchdog support and some watchdog devices
 obj-y += wdt_ib700.o wdt_i6300esb.o
 
+# Generic SerialICE support
+ifdef CONFIG_SERIALICE
+CPPFLAGS += $(CONFIG_SERIALICE_CFLAGS)
+LIBS += $(CONFIG_SERIALICE_LIBS)
+endif
+obj-$(CONFIG_SERIALICE) += serialice.o
+
 # Hardware support
 obj-i386-y = ide.o pckbd.o vga.o $(sound-obj-y) dma.o
 obj-i386-y += fdc.o mc146818rtc.o serial.o i8259.o i8254.o pcspk.o pc.o
--- qemu-0.11.0/vl.c
+++ qemu-0.11.0/vl.c
@@ -221,6 +221,9 @@
 int win2k_install_hack = 0;
 int rtc_td_hack = 0;
 #endif
+#ifdef CONFIG_SERIALICE
+const char *serialice_device = NULL;
+#endif
 int usb_enabled = 0;
 int singlestep = 0;
 int smp_cpus = 1;
@@ -5108,6 +5111,11 @@
                 display_type = DT_CURSES;
                 break;
 #endif
+#ifdef CONFIG_SERIALICE
+	   case QEMU_OPTION_serialice:
+		serialice_device = optarg;
+		break;
+#endif
             case QEMU_OPTION_portrait:
                 graphic_rotate = 1;
                 break;
--- qemu-0.11.0/qemu-char.c
+++ qemu-0.11.0/qemu-char.c
@@ -821,7 +821,7 @@
 #endif
 
 #if defined(__linux__) || defined(__sun__) || defined(__FreeBSD__) \
-    || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
+    || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__APPLE__)
 
 typedef struct {
     int fd;
@@ -2262,7 +2262,7 @@
     } else
 #endif
 #if defined(__linux__) || defined(__sun__) || defined(__FreeBSD__) \
-    || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
+    || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__APPLE__)
     if (strstart(filename, "/dev/", NULL)) {
         chr = qemu_chr_open_tty(filename);
     } else
--- qemu-0.11.0/softmmu_template.h
+++ qemu-0.11.0/softmmu_template.h
@@ -16,6 +16,9 @@
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
+
+#include "serialice.h"
+
 #define DATA_SIZE (1 << SHIFT)
 
 #if DATA_SIZE == 8
@@ -91,6 +94,16 @@
     target_phys_addr_t addend;
     void *retaddr;
 
+#ifdef CONFIG_SERIALICE
+    uint32_t result;
+    int caught = 0;
+    if (serialice_active && serialice_handle_load((uint32_t)addr, &result, (unsigned int) DATA_SIZE)) {
+	res = (DATA_TYPE)result;
+	caught=1;
+	goto leave_ld;
+    }
+#endif
+
     /* test if there is match for unaligned or IO access */
     /* XXX: could done more in memory macro in a non portable way */
     index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
@@ -134,6 +147,12 @@
         tlb_fill(addr, READ_ACCESS_TYPE, mmu_idx, retaddr);
         goto redo;
     }
+
+#ifdef CONFIG_SERIALICE
+leave_ld:
+    if (serialice_active)
+        serialice_log_load(caught, addr, (uint32_t)res, (unsigned int)DATA_SIZE);
+#endif
     return res;
 }
 
@@ -234,6 +253,15 @@
     void *retaddr;
     int index;
 
+#ifdef CONFIG_SERIALICE
+    if (serialice_active && serialice_handle_store((uint32_t)addr, (uint32_t)val, (unsigned int) DATA_SIZE)) {
+	// For now, we just always keep a backup of _all_ writes in qemu's
+	// memory. At this point we can later decide what to do, if it becomes
+	// necessary.
+	// return;
+    }
+#endif
+
     index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
  redo:
     tlb_addr = env->tlb_table[mmu_idx][index].addr_write;
--- qemu-0.11.0/Makefile
+++ qemu-0.11.0/Makefile
@@ -212,6 +212,10 @@
 
 bt-host.o: CFLAGS += $(CONFIG_BLUEZ_CFLAGS)
 
+serialice.o: serialice.c serialice.h
+
+serialice.o: CFLAGS += $(CONFIG_SERIALICE_CFLAGS)
+
 libqemu_common.a: $(obj-y)
 
 #######################################################################
--- qemu-0.11.0/qemu-options.hx
+++ qemu-0.11.0/qemu-options.hx
@@ -1661,3 +1661,14 @@
 DEF("old-param", 0, QEMU_OPTION_old_param,
     "-old-param      old param mode\n")
 #endif
+
+#ifdef CONFIG_SERIALICE
+DEF("serialice", HAS_ARG, QEMU_OPTION_serialice,
+    "-serialice dev  Enable SerialICE debugging on serial device 'dev'\n")
+STEXI
+@item -serialice @var{dev}
+Enable SerialICE debugging on serial device @var{dev}.
+ETEXI
+#endif
+
+
--- qemu-0.11.0/exec-all.h
+++ qemu-0.11.0/exec-all.h
@@ -21,6 +21,7 @@
 #define _EXEC_ALL_H_
 
 #include "qemu-common.h"
+#include "serialice.h"
 
 /* allow to see translation results - the slowdown should be negligible, so we leave it */
 #define DEBUG_DISAS
@@ -328,6 +329,9 @@
 #if defined(TARGET_SPARC) || defined(TARGET_MIPS)
         do_unassigned_access(addr, 0, 1, 0, 4);
 #else
+#if defined(CONFIG_SERIALICE)
+    if (!serialice_active)
+#endif
         cpu_abort(env1, "Trying to execute code outside RAM or ROM at 0x" TARGET_FMT_lx "\n", addr);
 #endif
     }
--- qemu-0.11.0/configure
+++ qemu-0.11.0/configure
@@ -193,6 +193,7 @@
 io_thread="no"
 nptl="yes"
 mixemu="no"
+serialice="no"
 bluez="yes"
 kvm="no"
 kerneldir=""
@@ -491,6 +492,8 @@
   ;;
   --enable-mixemu) mixemu="yes"
   ;;
+  --enable-serialice) serialice="yes"
+  ;;
   --disable-pthread) pthread="no"
   ;;
   --disable-aio) aio="no"
@@ -624,6 +627,7 @@
 echo "  --audio-card-list=LIST   set list of emulated audio cards [$audio_card_list]"
 echo "                           Available cards: $audio_possible_cards"
 echo "  --enable-mixemu          enable mixer emulation"
+echo "  --enable-serialice       enable SerialICE debugger support"
 echo "  --disable-xen            disable xen backend driver support"
 echo "  --disable-brlapi         disable BrlAPI"
 echo "  --disable-vnc-tls        disable TLS encryption for VNC server"
@@ -1064,6 +1068,40 @@
 done
 
 ##########################################
+# LUA probe
+
+if test "$serialice" = "yes" ; then
+  serialice=no
+  cat > $TMPC << EOF
+#include <stdint.h>
+#include <lua.h>
+#include <lauxlib.h>
+#include <stdlib.h>
+#include <stdio.h>
+static lua_State *L;
+int main(void) { L=luaL_newstate(); return 0; }
+EOF
+  
+  LUA_CFLAGS="-I/usr/local/include"
+  LUA_LDFLAGS="-L/usr/local/lib -llua"
+  if $cc $EXTRA_CFLAGS $EXTRA_LDFLAGS $ARCH_CFLAGS $LUA_CFLAGS $LUA_LDFLAGS -o $TMPE $TMPC -llua > /dev/null 2> /dev/null ; then
+    serialice=yes
+  else
+    LUA_CFLAGS=`pkg-config --cflags lua`
+    LUA_LDFLAGS=`pkg-config --libs lua`
+    if $cc $EXTRA_CFLAGS $EXTRA_LDFLAGS $ARCH_CFLAGS $LUA_CFLAGS $LUA_LDFLAGS -o $TMPE $TMPC -llua > /dev/null 2> /dev/null ; then
+      serialice=yes
+    else
+      echo
+      echo "Error LUA not found, can't build with SerialICE support."
+      echo
+      exit 1
+    fi
+  fi
+fi # test "$serialice"
+
+
+##########################################
 # BrlAPI probe
 
 if test -z "$brlapi" ; then
@@ -1426,6 +1464,7 @@
 echo "Audio drivers     $audio_drv_list"
 echo "Extra audio cards $audio_card_list"
 echo "Mixer emulation   $mixemu"
+echo "SerialICE support $serialice"
 echo "VNC TLS support   $vnc_tls"
 if test "$vnc_tls" = "yes" ; then
     echo "    TLS CFLAGS    $vnc_tls_cflags"
@@ -1620,6 +1659,12 @@
   echo "CONFIG_MIXEMU=y" >> $config_host_mak
   echo "#define CONFIG_MIXEMU 1" >> $config_host_h
 fi
+if test "$serialice" = "yes" ; then
+  echo "CONFIG_SERIALICE=y" >> $config_host_mak
+  echo "CONFIG_SERIALICE_CFLAGS=$LUA_CFLAGS" >> $config_host_mak
+  echo "CONFIG_SERIALICE_LIBS=$LUA_LDFLAGS" >> $config_host_mak
+  echo "#define CONFIG_SERIALICE 1" >> $config_host_h
+fi
 if test "$vnc_tls" = "yes" ; then
   echo "CONFIG_VNC_TLS=y" >> $config_host_mak
   echo "CONFIG_VNC_TLS_CFLAGS=$vnc_tls_cflags" >> $config_host_mak
--- qemu-0.11.0/target-i386/op_helper.c
+++ qemu-0.11.0/target-i386/op_helper.c
@@ -23,6 +23,7 @@
 
 //#define DEBUG_PCALL
 
+#include "serialice.h"
 
 #ifdef DEBUG_PCALL
 #  define LOG_PCALL(...) qemu_log_mask(CPU_LOG_PCALL, ## __VA_ARGS__)
@@ -558,31 +559,64 @@
 
 void helper_outb(uint32_t port, uint32_t data)
 {
+#ifdef CONFIG_SERIALICE
+    if (serialice_active) {
+	    serialice_outb(data & 0xff, port);
+	    return;
+    }
+#endif
     cpu_outb(env, port, data & 0xff);
 }
 
 target_ulong helper_inb(uint32_t port)
 {
+#ifdef CONFIG_SERIALICE
+    if (serialice_active) {
+	    return (target_ulong)serialice_inb(port);
+    }
+#endif
     return cpu_inb(env, port);
 }
 
 void helper_outw(uint32_t port, uint32_t data)
 {
+#ifdef CONFIG_SERIALICE
+    if (serialice_active) {
+	    serialice_outw(data & 0xffff, port);
+	    return;
+    }
+#endif
     cpu_outw(env, port, data & 0xffff);
 }
 
 target_ulong helper_inw(uint32_t port)
 {
+#ifdef CONFIG_SERIALICE
+    if (serialice_active) {
+	    return (target_ulong)serialice_inw(port);
+    }
+#endif
     return cpu_inw(env, port);
 }
 
 void helper_outl(uint32_t port, uint32_t data)
 {
+#ifdef CONFIG_SERIALICE
+    if (serialice_active) {
+	    serialice_outl(data & 0xffffffff, port);
+	    return;
+    }
+#endif
     cpu_outl(env, port, data);
 }
 
 target_ulong helper_inl(uint32_t port)
 {
+#ifdef CONFIG_SERIALICE
+    if (serialice_active) {
+	    return (target_ulong)serialice_inl(port);
+    }
+#endif
     return cpu_inl(env, port);
 }
 
@@ -1940,6 +1974,18 @@
 
     helper_svm_check_intercept_param(SVM_EXIT_CPUID, 0);
 
+#ifdef CONFIG_SERIALICE
+    if (serialice_active) {
+        cpuid_regs_t ret;
+        ret = serialice_cpuid((uint32_t)EAX, (uint32_t)ECX);
+        EAX = ret.eax;
+        EBX = ret.ebx;
+        ECX = ret.ecx;
+        EDX = ret.edx;
+        return;
+    }
+#endif
+
     cpu_x86_cpuid(env, (uint32_t)EAX, (uint32_t)ECX, &eax, &ebx, &ecx, &edx);
     EAX = eax;
     EBX = ebx;
@@ -3030,6 +3076,13 @@
 
     val = ((uint32_t)EAX) | ((uint64_t)((uint32_t)EDX) << 32);
 
+#ifdef CONFIG_SERIALICE
+    if (serialice_active) {
+        serialice_wrmsr(val, (uint32_t)ECX);
+        return;
+    }
+#endif
+
     switch((uint32_t)ECX) {
     case MSR_IA32_SYSENTER_CS:
         env->sysenter_cs = val & 0xffff;
@@ -3160,6 +3213,15 @@
 
     helper_svm_check_intercept_param(SVM_EXIT_MSR, 0);
 
+#ifdef CONFIG_SERIALICE
+    if (serialice_active) {
+	val = serialice_rdmsr((uint32_t)ECX);
+        EAX = (uint32_t)(val);
+        EDX = (uint32_t)(val >> 32);
+	return;
+    }
+#endif
+
     switch((uint32_t)ECX) {
     case MSR_IA32_SYSENTER_CS:
         val = env->sysenter_cs;
--- qemu-0.11.0/hw/pc.c
+++ qemu-0.11.0/hw/pc.c
@@ -23,6 +23,7 @@
  */
 #include "hw.h"
 #include "pc.h"
+#include "serialice.h"
 #include "fdc.h"
 #include "pci.h"
 #include "block.h"
@@ -1152,6 +1153,10 @@
 
     /* allocate RAM */
     ram_addr = qemu_ram_alloc(0xa0000);
+#ifdef CONFIG_SERIALICE
+    if (serialice_active)
+        ram_addr |= IO_MEM_UNASSIGNED;
+#endif
     cpu_register_physical_memory(0, 0xa0000, ram_addr);
 
     /* Allocate, even though we won't register, so we don't break the
@@ -1160,6 +1165,10 @@
      */
     ram_addr = qemu_ram_alloc(0x100000 - 0xa0000);
     ram_addr = qemu_ram_alloc(below_4g_mem_size - 0x100000);
+#ifdef CONFIG_SERIALICE
+    if (serialice_active)
+        ram_addr |= IO_MEM_UNASSIGNED;
+#endif
     cpu_register_physical_memory(0x100000,
                  below_4g_mem_size - 0x100000,
                  ram_addr);
@@ -1170,6 +1179,10 @@
         hw_error("To much RAM for 32-bit physical address");
 #else
         ram_addr = qemu_ram_alloc(above_4g_mem_size);
+#ifdef CONFIG_SERIALICE
+        if (serialice_active)
+            ram_addr |= IO_MEM_UNASSIGNED;
+#endif
         cpu_register_physical_memory(0x100000000ULL,
                                      above_4g_mem_size,
                                      ram_addr);
@@ -1468,6 +1481,24 @@
              initrd_filename, cpu_model, 0);
 }
 
+#ifdef CONFIG_SERIALICE
+static void serialice_init_pci(ram_addr_t ram_size,
+                        const char *boot_device,
+                        const char *kernel_filename,
+                        const char *kernel_cmdline,
+                        const char *initrd_filename,
+                        const char *cpu_model)
+{
+    serialice_active = 1;
+
+    pc_init1(ram_size, boot_device,
+             kernel_filename, kernel_cmdline,
+             initrd_filename, cpu_model, 1);
+
+    serialice_init();
+}
+#endif
+
 /* set CMOS shutdown status register (index 0xF) as S3_resume(0xFE)
    BIOS will read it and start S3 resume at POST Entry */
 void cmos_set_s3_resume(void)
@@ -1515,11 +1546,23 @@
     .max_cpus = 1,
 };
 
+#ifdef CONFIG_SERIALICE
+static QEMUMachine serialice_machine = {
+    .name = "serialice",
+    .desc = "SerialICE",
+    .init = serialice_init_pci,
+    .max_cpus = 255,
+};
+#endif
+
 static void pc_machine_init(void)
 {
     qemu_register_machine(&pc_machine);
     qemu_register_machine(&pc_machine_v0_10);
     qemu_register_machine(&isapc_machine);
+#ifdef CONFIG_SERIALICE
+    qemu_register_machine(&serialice_machine);
+#endif
 }
 
 machine_init(pc_machine_init);
