Author: stepan Date: 2009-11-19 20:26:18 +0100 (Thu, 19 Nov 2009) New Revision: 52
Removed: trunk/SerialICE/TODO Modified: trunk/SerialICE/README.SHELL trunk/SerialICE/io.h trunk/SerialICE/serialice.c trunk/qemu-0.11.0/serialice.c trunk/qemu-0.11.0/serialice.h trunk/qemu-0.11.0/target-i386/op_helper.c Log: * shell: pass %edi to rdmsr and wrmsr calls (MSR unlock key) * shell: unify implementations of rdmsr/wrmsr in io.h * shell: fix cpuid asm() code * shell: fix up README.SHELL documentation of rdmsr/wrmsr * shell: drop (unneeded) TODO * qemu: call rdmsr/wrmsr with %edi * qemu: use a single command buffer instead of one per command * add license to header file.
Modified: trunk/SerialICE/README.SHELL =================================================================== --- trunk/SerialICE/README.SHELL 2009-11-19 18:46:51 UTC (rev 51) +++ trunk/SerialICE/README.SHELL 2009-11-19 19:26:18 UTC (rev 52) @@ -99,20 +99,20 @@ 5. MSR reads
Syntax: - *rc<addr> + *rc<addr>.<key>
Example: - > *rc000000cd + > *rc000000cd.9c5a203a 00000000.00000933
6. MSR Writes
Syntax: - *wc<addr>=<high>.<low> + *wc<addr>.<key>=<high>.<low>
Example: - > *wc00000000=00000000.00000000 + > *wc00000000.9c5a203a=00000000.00000000
7. CPUID
Deleted: trunk/SerialICE/TODO =================================================================== --- trunk/SerialICE/TODO 2009-11-19 18:46:51 UTC (rev 51) +++ trunk/SerialICE/TODO 2009-11-19 19:26:18 UTC (rev 52) @@ -1,5 +0,0 @@ - -- Better implementation of AMD style MSRs (with an unlock key in a specific register) -- CPUID takes ECX as input on some EAX values (See patches/serialice-cpuid-ecx.diff) -- USB debug console support (theoretical max of ca. 60MBit instead of 115.2KBit) -
Modified: trunk/SerialICE/io.h =================================================================== --- trunk/SerialICE/io.h 2009-11-19 18:46:51 UTC (rev 51) +++ trunk/SerialICE/io.h 2009-11-19 19:26:18 UTC (rev 52) @@ -121,88 +121,71 @@
/* MSR functions */
-#ifdef __GNUC__ typedef struct { u32 lo, hi; } msr_t;
-static inline msr_t rdmsr(unsigned index) +static inline msr_t rdmsr(u32 index, u32 key) { msr_t result; __asm__ __volatile__ ( "rdmsr" : "=a" (result.lo), "=d" (result.hi) - : "c" (index), "D" (0x9c5a203a) + : "c" (index), "D" (key) ); return result; }
-static inline void wrmsr(unsigned index, msr_t msr) +static inline void wrmsr(u32 index, msr_t msr, u32 key) { __asm__ __volatile__ ( "wrmsr" : /* No outputs */ - : "c" (index), "a" (msr.lo), "d" (msr.hi), "D" (0x9c5a203a) + : "c" (index), "a" (msr.lo), "d" (msr.hi), "D" (key) ); }
-#else - -/* Since we use romcc, we're also going to use romcc's builtin functions */ -typedef __builtin_msr_t msr_t; - -static inline msr_t rdmsr(unsigned long index) -{ - return __builtin_rdmsr(index); -} - -static inline void wrmsr(unsigned long index, msr_t msr) -{ - __builtin_wrmsr(index, msr.lo, msr.hi); -} -#endif - /* CPUID functions */
-static inline unsigned int cpuid_eax(unsigned int op, unsigned op2) +static inline u32 cpuid_eax(u32 op, u32 op2) { - unsigned int eax; + u32 eax;
__asm__("cpuid" : "=a" (eax) - : "0" (op), "2" (op2) - : "ebx", "ecx", "edx"); + : "a" (op), "c" (op2) + : "ebx", "edx" ); return eax; }
-static inline unsigned int cpuid_ebx(unsigned int op, unsigned op2) +static inline u32 cpuid_ebx(u32 op, u32 op2) { - unsigned int eax, ebx; + u32 eax, ebx;
__asm__("cpuid" - : "=a" (eax), "=b" (ebx) - : "0" (op), "2" (op2) - : "ecx", "edx" ); + : "=b" (ebx) + : "a" (op), "c" (op2) + : "edx"); return ebx; }
-static inline unsigned int cpuid_ecx(unsigned int op, unsigned int op2) +static inline u32 cpuid_ecx(u32 op, u32 op2) { - unsigned int eax, ecx; + u32 eax, ecx;
__asm__("cpuid" - : "=a" (eax), "=c" (ecx) - : "0" (op), "2" (op2) + : "=c" (ecx) + : "a" (op), "c" (op2) : "ebx", "edx" ); return ecx; }
-static inline unsigned int cpuid_edx(unsigned int op, unsigned int op2) +static inline u32 cpuid_edx(u32 op, u32 op2) { - unsigned int eax, edx; + u32 eax, edx;
__asm__("cpuid" - : "=a" (eax), "=d" (edx) - : "0" (op), "2" (op2) - : "ebx", "ecx"); + : "=d" (edx) + : "a" (op), "c" (op2) + : "ebx"); return edx; }
Modified: trunk/SerialICE/serialice.c =================================================================== --- trunk/SerialICE/serialice.c 2009-11-19 18:46:51 UTC (rev 51) +++ trunk/SerialICE/serialice.c 2009-11-19 19:26:18 UTC (rev 52) @@ -112,16 +112,18 @@
static void serialice_read_msr(void) { - u32 addr; + u32 addr, key; msr_t msr;
// Format: - // *rc00000000 + // *rc00000000.9c5a203a addr = sio_get32(); + sio_getc(); // skip . + key = sio_get32(); // key in %edi
sio_putc('\r'); sio_putc('\n');
- msr = rdmsr(addr); + msr = rdmsr(addr, key); sio_put32(msr.hi); sio_putc('.'); sio_put32(msr.lo); @@ -129,18 +131,25 @@
static void serialice_write_msr(void) { - u32 addr; + u32 addr, key; msr_t msr;
// Format: - // *wc00000000=00000000.00000000 + // *wc00000000.9c5a203a=00000000.00000000 addr = sio_get32(); + sio_getc(); // skip . + key = sio_get32(); // read key in %edi sio_getc(); // skip = msr.hi = sio_get32(); sio_getc(); // skip . msr.lo = sio_get32();
- wrmsr(addr, msr); +#ifdef __ROMCC__ + /* Cheat to avoid register outage */ + wrmsr(addr, msr, 0x9c5a203a); +#else + wrmsr(addr, msr, key); +#endif }
static void serialice_cpuinfo(void)
Modified: trunk/qemu-0.11.0/serialice.c =================================================================== --- trunk/qemu-0.11.0/serialice.c 2009-11-19 18:46:51 UTC (rev 51) +++ trunk/qemu-0.11.0/serialice.c 2009-11-19 19:26:18 UTC (rev 52) @@ -57,6 +57,7 @@ int fd; #endif char *buffer; + char *command; } SerialICEState;
static SerialICEState *s; @@ -483,15 +484,14 @@ 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); + sprintf(s->command, "*ri%04x.b", port); // command read back: "\n00" (3 characters) - serialice_command(command, 3); + serialice_command(s->command, 3); ret = (uint8_t)strtoul(s->buffer + 1, (char **)NULL, 16);
serialice_log(LOG_READ|LOG_IO, ret, port, 1); @@ -502,15 +502,14 @@ 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); + sprintf(s->command, "*ri%04x.w", port); // command read back: "\n0000" (5 characters) - serialice_command(command, 5); + serialice_command(s->command, 5); ret = (uint16_t)strtoul(s->buffer + 1, (char **)NULL, 16);
serialice_log(LOG_READ|LOG_IO, ret, port, 2); @@ -521,15 +520,14 @@ 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); + sprintf(s->command, "*ri%04x.l", port); // command read back: "\n00000000" (9 characters) - serialice_command(command, 9); + serialice_command(s->command, 9); ret = (uint32_t)strtoul(s->buffer + 1, (char **)NULL, 16);
serialice_log(LOG_READ|LOG_IO, ret, port, 4); @@ -539,7 +537,6 @@
void serialice_outb(uint8_t data, uint16_t port) { - char command[19]; uint32_t filtered_data = (uint32_t)data;
serialice_log(LOG_WRITE|LOG_IO, data, port, 1); @@ -549,13 +546,12 @@ }
data = (uint8_t)filtered_data; - sprintf(command, "*wi%04x.b=%02x", port, data); - serialice_command(command, 0); + sprintf(s->command, "*wi%04x.b=%02x", port, data); + serialice_command(s->command, 0); }
void serialice_outw(uint16_t data, uint16_t port) { - char command[21]; uint32_t filtered_data = (uint32_t)data;
serialice_log(LOG_WRITE|LOG_IO, data, port, 2); @@ -565,13 +561,12 @@ }
data = (uint16_t)filtered_data; - sprintf(command, "*wi%04x.w=%04x", port, data); - serialice_command(command, 0); + sprintf(s->command, "*wi%04x.w=%04x", port, data); + serialice_command(s->command, 0); }
void serialice_outl(uint32_t data, uint16_t port) { - char command[25]; uint32_t filtered_data = data;
serialice_log(LOG_WRITE|LOG_IO, data, port, 4); @@ -581,17 +576,16 @@ }
data = filtered_data; - sprintf(command, "*wi%04x.l=%08x", port, data); - serialice_command(command, 0); + sprintf(s->command, "*wi%04x.l=%08x", port, data); + serialice_command(s->command, 0); }
uint8_t serialice_readb(uint32_t addr) { uint8_t ret; - char command[20]; - sprintf(command, "*rm%08x.b", addr); + sprintf(s->command, "*rm%08x.b", addr); // command read back: "\n00" (3 characters) - serialice_command(command, 3); + serialice_command(s->command, 3); ret = (uint8_t)strtoul(s->buffer + 1, (char **)NULL, 16); return ret; } @@ -599,10 +593,9 @@ uint16_t serialice_readw(uint32_t addr) { uint16_t ret; - char command[20]; - sprintf(command, "*rm%08x.w", addr); + sprintf(s->command, "*rm%08x.w", addr); // command read back: "\n0000" (5 characters) - serialice_command(command, 5); + serialice_command(s->command, 5); ret = (uint16_t)strtoul(s->buffer + 1, (char **)NULL, 16); return ret; } @@ -610,36 +603,32 @@ uint32_t serialice_readl(uint32_t addr) { uint32_t ret; - char command[20]; - sprintf(command, "*rm%08x.l", addr); + sprintf(s->command, "*rm%08x.l", addr); // command read back: "\n00000000" (9 characters) - serialice_command(command, 9); + serialice_command(s->command, 9); 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); - serialice_command(command, 0); + sprintf(s->command, "*wm%08x.b=%02x", addr, data); + serialice_command(s->command, 0); }
void serialice_writew(uint16_t data, uint32_t addr) { - char command[25]; - sprintf(command, "*wm%08x.w=%04x", addr, data); - serialice_command(command, 0); + sprintf(s->command, "*wm%08x.w=%04x", addr, data); + serialice_command(s->command, 0); }
void serialice_writel(uint32_t data, uint32_t addr) { - char command[29]; - sprintf(command, "*wm%08x.l=%08x", addr, data); - serialice_command(command, 0); + sprintf(s->command, "*wm%08x.l=%08x", addr, data); + serialice_command(s->command, 0); }
-uint64_t serialice_rdmsr(uint32_t addr) +uint64_t serialice_rdmsr(uint32_t addr, uint32_t key) { uint32_t hi, lo; uint64_t ret; @@ -647,12 +636,10 @@
filtered = serialice_msr_filter(FILTER_READ, addr, &hi, &lo); if (!filtered) { - char command[18]; + sprintf(s->command, "*rc%08x.%08x", addr, key);
- sprintf(command, "*rc%08x", addr); - // command read back: "\n00000000.00000000" (18 characters) - serialice_command(command, 18); + serialice_command(s->command, 18);
s->buffer[9] = 0; // . -> \0 hi = (uint32_t)strtoul(s->buffer + 1, (char **)NULL, 16); @@ -668,7 +655,7 @@ return ret; }
-void serialice_wrmsr(uint64_t data, uint32_t addr) +void serialice_wrmsr(uint64_t data, uint32_t addr, uint32_t key) { uint32_t hi, lo; int filtered; @@ -679,9 +666,8 @@ filtered = serialice_msr_filter(FILTER_WRITE, addr, &hi, &lo);
if (!filtered) { - char command[30]; - sprintf(command, "*wc%08x=%08x.%08x", addr, hi, lo); - serialice_command(command, 0); + sprintf(s->command, "*wc%08x.%08x=%08x.%08x", addr, key, hi, lo); + serialice_command(s->command, 0); }
serialice_msr_log(LOG_WRITE, addr, hi, lo, filtered); @@ -699,13 +685,11 @@
filtered = serialice_cpuid_filter(&ret); if (!filtered) { - char command[27]; + sprintf(s->command, "*ci%08x.%08x", eax, ecx);
- sprintf(command, "*ci%08x.%08x", eax, ecx); - // command read back: "\n000006f2.00000000.00001234.12340324" // (36 characters) - serialice_command(command, 36); + serialice_command(s->command, 36);
s->buffer[9] = 0; // . -> \0 s->buffer[18] = 0; // . -> \0 @@ -911,6 +895,7 @@ #endif
s->buffer = qemu_mallocz(BUFFER_SIZE); + s->command = qemu_mallocz(BUFFER_SIZE);
printf("SerialICE: Waiting for handshake with target... ");
@@ -937,5 +922,8 @@ void serialice_exit(void) { serialice_lua_exit(); + qemu_free(s->command); + qemu_free(s->buffer); + qemu_free(s); }
Modified: trunk/qemu-0.11.0/serialice.h =================================================================== --- trunk/qemu-0.11.0/serialice.h 2009-11-19 18:46:51 UTC (rev 51) +++ trunk/qemu-0.11.0/serialice.h 2009-11-19 19:26:18 UTC (rev 52) @@ -1,6 +1,30 @@ -#ifndef HW_SERIALICE_H -#define HW_SERIALICE_H +/* + * 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. + */
+#ifndef SERIALICE_H +#define SERIALICE_H + #include "config-host.h"
extern const char *serialice_device; @@ -25,8 +49,8 @@ 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); +uint64_t serialice_rdmsr(uint32_t addr, uint32_t key); +void serialice_wrmsr(uint64_t data, uint32_t addr, uint32_t key);
typedef struct { uint32_t eax, ebx, ecx, edx;
Modified: trunk/qemu-0.11.0/target-i386/op_helper.c =================================================================== --- trunk/qemu-0.11.0/target-i386/op_helper.c 2009-11-19 18:46:51 UTC (rev 51) +++ trunk/qemu-0.11.0/target-i386/op_helper.c 2009-11-19 19:26:18 UTC (rev 52) @@ -3078,7 +3078,7 @@
#ifdef CONFIG_SERIALICE if (serialice_active) { - serialice_wrmsr(val, (uint32_t)ECX); + serialice_wrmsr(val, (uint32_t)ECX, (uint32_t)EDI); return; } #endif @@ -3215,7 +3215,7 @@
#ifdef CONFIG_SERIALICE if (serialice_active) { - val = serialice_rdmsr((uint32_t)ECX); + val = serialice_rdmsr((uint32_t)ECX, (uint32_t)EDI); EAX = (uint32_t)(val); EDX = (uint32_t)(val >> 32); return;