Author: stepan
Date: 2009-12-13 00:43:38 +0100 (Sun, 13 Dec 2009)
New Revision: 91
Modified:
trunk/qemu-0.11.0/softmmu_template.h
Log:
It would appear that not returning in case a store is supposed to be filtered
would be a bad thing. It is not, because the filter only runs reliably in case
the memory region is IO_MEM_UNASSIGNED, so letting the write through is a NOP.
Signed-off-by: Stefan Reinauer <stepan(a)coresystems.de>
Modified: trunk/qemu-0.11.0/softmmu_template.h
===================================================================
--- trunk/qemu-0.11.0/softmmu_template.h 2009-12-07 17:05:07 UTC (rev 90)
+++ trunk/qemu-0.11.0/softmmu_template.h 2009-12-12 23:43:38 UTC (rev 91)
@@ -254,11 +254,16 @@
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;
+ if (serialice_active && serialice_handle_store((uint32_t)addr,
+ (uint32_t)val, (unsigned int) DATA_SIZE)) {
+ /* The memory catch mechanism does not work particularly well
+ * because of the softmmu is optimizing all accesses to Qemu
+ * "memory". Because of this we need to leave RAM "unassigned"
+ * until RAM init is done, and can't freely switch around.
+ *
+ * It's the right thing, however, to return here.
+ */
+ return;
}
#endif
Author: stepan
Date: 2009-12-07 18:05:07 +0100 (Mon, 07 Dec 2009)
New Revision: 90
Modified:
trunk/SerialICE/scripts/serialice.lua
Log:
Update SerialICE LUA script. It is really time that we start
using the device model.
- add global variable "ip_logging" to enable/disable logging
[CS:IP] for every access.
- only register physical memory for RAM if it did not happen before
- reset Qemu CPU when target is reset with 0xcf9
- Implement Intel CPU microcode update faking in the MSR read/write filters.
It would be a relatively easy hack to add microcodes to the SerialICE image
and even run them, by having the msr write point to the correct address, in
case that should ever be needed.
- add a lot of automation triggers to increase SerialICE speed on my
test hardware.
Signed-off-by: Stefan Reinauer <stepan(a)coresystems.de>
Modified: trunk/SerialICE/scripts/serialice.lua
===================================================================
--- trunk/SerialICE/scripts/serialice.lua 2009-12-05 16:37:58 UTC (rev 89)
+++ trunk/SerialICE/scripts/serialice.lua 2009-12-07 17:05:07 UTC (rev 90)
@@ -41,10 +41,14 @@
ram_is_initialized = false
--- Whether to log read access (code fetches) to 0xe0000 to 0xfffff
+-- Set to "true" to log read access (code fetches) to 0xe0000 to 0xfffff
log_rom_access = false
+-- Set to "true" to log CS:IP for each access
+
+ip_logging = false
+
-- Remember the PCI device selected via IO CF8
SerialICE_pci_device = 0
@@ -84,6 +88,15 @@
-- **********************************************************
--
+ if ( port == 0x60 and data_size == 1 ) then
+ if ( regs.eip == 0xbd6d and regs.eax == 0x8aa and regs.ecx == 0x00fffff0 ) then
+ -- f000:bd6d
+ printf("Skipping keyboard timeout...\n")
+ regs.eax = 0x01aa
+ regs.ecx = 0x0010
+ end
+ end
+
return caught, data
end
@@ -227,15 +240,40 @@
-- permanently from the target (several reads/writes per
-- decompressed byte).
- if port == 0x80 and data == 0xff37 then
+ if port == 0x80 and data == 0xff37 and ram_is_initialized == false then
ram_is_initialized = true
-- Register low RAM 0x00000000 - 0x000dffff
SerialICE_register_physical(0x00000000, 0xa0000)
-- SMI/VGA memory should go to the target...
SerialICE_register_physical(0x000c0000, 0x20000)
printf("\nLow RAM accesses are now directed to Qemu.\n")
+
+ return false, data
end
+ if port == 0xcf9 and data == 0x06 then
+ SerialICE_system_reset()
+ return false, data
+ end
+
+ if ( port == 0xed and data == 0x40 ) then
+ if ( regs.eip == 0x3ed and regs.ecx == 0x00000290 ) then
+ printf("Skipping IO delay...\n")
+ -- f100:03ed
+ regs.ecx = 0x05
+ end
+ end
+
+ if ( port == 0xed and data == 0x83 )
+ then
+ if ( regs.eip == 0x1bb and regs.ecx == 0x0000fff0 ) then
+ printf("Skipping IO delay...\n")
+ -- e002:01bb
+ regs.ecx = 0x10
+ regs.ebx = 0x01
+ end
+ end
+
return false, data
end
@@ -384,6 +422,17 @@
-- Don't send writes to the target for speed reasons.
return false, true, data
elseif addr >= 0x00100000 and addr <= 0xcfffffff then
+ if addr == 0x00100000 then
+ if regs.cs == 0xe002 and regs.eip == 0x07fb then
+ -- skip high memory wipe
+ regs.ecx = 0x10
+ end
+ if regs.cs == 0xe002 and regs.eip == 0x076c and regs.edi == 0x3f then
+ -- skip high memory test
+ regs.edi=1;
+ end
+ end
+
-- 3.25 GB RAM ... This is handled by SerialICE
return true, false, data
else
@@ -394,16 +443,31 @@
return true, false, data
end
+
+function log_cs_ip()
+ if (ip_logging) then printf("[%04x:%04x] -- ", regs.cs, regs.eip) end
+end
+
function SerialICE_msr_read_filter(addr, hi, lo)
+ -- Intel CPU microcode revision check.
+ if addr == 0x8b then
+ -- fake microcode revision of my 0x6f6 Core 2 Duo Mobile
+ return true, 0xc7, 0x00
+ end
+
return false, hi, lo
end
function SerialICE_msr_write_filter(addr, hi, lo)
+ -- Intel CPU microcode update
+ if addr == 0x79 then
+ return true, 0, 0xffff0000
+ end
+
return false, hi, lo
end
function SerialICE_cpuid_filter(in_eax, in_ecx, eax, ebx, ecx, edx)
-
-- Set number of cores to 1 on Core Duo and Atom to trick the
-- firmware into not trying to wake up non-BSP nodes.
if in_eax == 1 then
@@ -428,6 +492,8 @@
return
end
+ log_cs_ip()
+
if size == 1 then printf("MEM: writeb %08x <= %02x", addr, data)
elseif size == 2 then printf("MEM: writew %08x <= %04x", addr, data)
elseif size == 4 then printf("MEM: writel %08x <= %08x", addr, data)
@@ -463,6 +529,8 @@
return
end
+ log_cs_ip()
+
if size == 1 then printf("MEM: readb %08x => %02x", addr, data)
elseif size == 2 then printf("MEM: readw %08x => %04x", addr, data)
elseif size == 4 then printf("MEM: readl %08x => %08x", addr, data)
@@ -485,6 +553,8 @@
end
function SerialICE_io_write_log(port, size, data, target)
+ log_cs_ip()
+
if size == 1 then printf("IO: outb %04x <= %02x\n", port, data)
elseif size == 2 then printf("IO: outw %04x <= %04x\n", port, data)
elseif size == 4 then printf("IO: outl %04x <= %08x\n", port, data)
@@ -500,9 +570,18 @@
bit.band(0x7,bit.rshift(SerialICE_pci_device, 8)),
bit.band(0xff,SerialICE_pci_device + (port - 0xcfc) ))
end
+
+ -- **********************************************************
+ --
+
+ if port == 0xcf9 then
+ printf("Reset triggered at %04x:%04x\n", regs.cs, regs.eip);
+ end
end
function SerialICE_io_read_log(port, size, data, target)
+ log_cs_ip()
+
if size == 1 then printf("IO: inb %04x => %02x\n", port, data)
elseif size == 2 then printf("IO: inw %04x => %04x\n", port, data)
elseif size == 4 then printf("IO: inl %04x => %08x\n", port, data)
@@ -521,14 +600,17 @@
end
function SerialICE_msr_write_log(addr, hi, lo, filtered)
+ log_cs_ip()
printf("CPU: wrmsr %08x <= %08x.%08x\n", addr, hi, lo)
end
function SerialICE_msr_read_log(addr, hi, lo, filtered)
+ log_cs_ip()
printf("CPU: rdmsr %08x => %08x.%08x\n", addr, hi, lo)
end
function SerialICE_cpuid_log(in_eax, in_ecx, out_eax, out_ebx, out_ecx, out_edx, filtered)
+ log_cs_ip()
printf("CPU: CPUID eax: %08x; ecx: %08x => %08x.%08x.%08x.%08x\n",
in_eax, in_ecx, out_eax, out_ebx, out_ecx, out_edx)
end
joe(a)settoplinux.org wrote:
> What does Qemu do when 0xcf9 is sent to bios Stefan?
>
>
Hi Joe,
The I/O 0xcf9 is the "reset register" on most x86 systems. Writing
certain values to it will cause a hard or soft reset.
Qemu however does not emulate this behavior - as far as I can tell - it
certainly does not while SerialICE is active, because all IO accesses go
to the target (or are caught by LUA)
Basically what's missing in the LUA script to make resets via cf9 work
properly is adding the following to SerialICE_IO_write_filter:
if port == 0xcf9 and data == 0x06 then
SerialICE_system_reset()
return false, data
end
The serial communication code has been rewritten for the last release to
be quite hick-up safe.. This means Qemu does not get out of sync if the
target reboots, so all that needs to happen after a reboot of the target
is to reboot the VM on the host, too, to let it start at the reset
vector again... Otherwise it'll just try to execute code right after the
out to cf9.. which is usually an endless loop as a safe guard.
Stefan
--
coresystems GmbH • Brahmsstr. 16 • D-79104 Freiburg i. Br.
Tel.: +49 761 7668825 • Fax: +49 761 7664613
Email: info(a)coresystems.de • http://www.coresystems.de/
Registergericht: Amtsgericht Freiburg • HRB 7656
Geschäftsführer: Stefan Reinauer • Ust-IdNr.: DE245674866
On December 5, 2009 at 3:02 PM svn(a)coresystems.de wrote:
> Author: stepan
> Date: 2009-12-05 16:02:29 +0100 (Sat, 05 Dec 2009)
> New Revision: 87
>
> Modified:
> trunk/qemu-0.11.0/serialice.c
> Log:
> Add SerialICE_system_reset to trigger a VM side reset.
> This is needed to keep Qemu from running code after an outb to 0xcf9 has been
> encountered.
What does Qemu do when 0xcf9 is sent to bios Stefan?
Thanks,
Joseph Smith
Set-Top-Linux
www.settoplinux.org
Author: stepan
Date: 2009-12-05 16:02:29 +0100 (Sat, 05 Dec 2009)
New Revision: 87
Modified:
trunk/qemu-0.11.0/serialice.c
Log:
Add SerialICE_system_reset to trigger a VM side reset.
This is needed to keep Qemu from running code after an outb to 0xcf9 has been
encountered.
Signed-off-by: Stefan Reinauer <stepan(a)coresystems.de>
Modified: trunk/qemu-0.11.0/serialice.c
===================================================================
--- trunk/qemu-0.11.0/serialice.c 2009-12-03 16:15:19 UTC (rev 86)
+++ trunk/qemu-0.11.0/serialice.c 2009-12-05 15:02:29 UTC (rev 87)
@@ -110,11 +110,17 @@
return 0;
}
+static int serialice_system_reset(lua_State * luastate)
+{
+ printf("Rebooting the emulated host CPU\n");
+ qemu_system_reset_request();
+ return 0;
+}
+
// **************************************************************************
// LUA register access
-// copied from target-i386/exec.h
-//CPUX86State *env;
+// some macros from target-i386/exec.h, which we can't include directly
#define env first_cpu
#define EAX (env->regs[R_EAX])
#define ECX (env->regs[R_ECX])
@@ -220,6 +226,7 @@
/* Register C function callbacks */
lua_register(L, "SerialICE_register_physical", serialice_register_physical);
+ lua_register(L, "SerialICE_system_reset", serialice_system_reset);
/* Set global variable SerialICE_mainboard */
lua_pushstring(L, serialice_mainboard);
@@ -1224,6 +1231,7 @@
for (i = 0; i < smp_cpus; i++) {
env = cpu_init(cpu_model);
+ qemu_register_reset((QEMUResetHandler*)cpu_reset, env);
}
/* Must not happen before CPUs are initialized */
Am 03.12.2009 19:05, schrieb joe(a)settoplinux.org:
> Ah, 230k isn't so bad and serialice is small enough so there is plenty of space
> left over. The only time it may be a problem is if you only have a 128k chip. I
> was just looking at the 1.4mb attachment to r80 but I guess that was the raw hex
> data.
>
It's also 230k on the host, not on the target...
Patrick
On 12/2/09 11:59 PM, joe(a)settoplinux.org wrote:
> This is awsome :-)
> I can't wait to try it out.
>
> It seems to be a rather large (file size) banner though. Any way to scale it
> down a bit?
>
> Thanks - Joe
>
Not so easily...
I made the graphics 320x200, so it's around 230KiB raw image data.
Options:
- use a compressed format.. This would mean adding a (i.e. JPG)
decompressor to Qemu..
Either by requiring to link against libjpeg, or by adding a jpg
decompressor in an extra file.
- load the PPM file from the filesystem instead of including it in the
source. Doesn't make it
smaller but then it's not possible to make a single diff against the
Qemu source tree anymore.
- paint something funky with a nice and small algorithm. Suggestions?
Stefan