[PATCH] target/i386: Change CR4 before CR0 in SVM
Resend as attachment as the previous version gots corrupted.From abea41b457aff4c04c3aa397b88847b66aaff1ad Mon Sep 17 00:00:00 2001 From: Bernhard Kauer Date: Fri, 20 Jan 2023 21:33:04 + Subject: [PATCH 2/2] target/i386: Change CR4 before CR0 in SVM There is a dependency in cpu_x86_update_cr0() to the current value of CR4 to enable or disable long-mode. This value is outdated when switching into or out of SVM. This leads to invalid CPU state when returning from an unpaged VM when EFER.LME is set. Signed-off-by: Bernhard Kauer --- target/i386/tcg/sysemu/svm_helper.c | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/target/i386/tcg/sysemu/svm_helper.c b/target/i386/tcg/sysemu/svm_helper.c index 2d27731b60..229a22816e 100644 --- a/target/i386/tcg/sysemu/svm_helper.c +++ b/target/i386/tcg/sysemu/svm_helper.c @@ -312,8 +312,8 @@ void helper_vmrun(CPUX86State *env, int aflag, int next_eip_addend) x86_stq_phys(cs, env->vm_vmcb + offsetof(struct vmcb, control.exit_info_2), 0); -cpu_x86_update_cr0(env, new_cr0); cpu_x86_update_cr4(env, new_cr4); +cpu_x86_update_cr0(env, new_cr0); cpu_x86_update_cr3(env, new_cr3); env->cr[2] = x86_ldq_phys(cs, env->vm_vmcb + offsetof(struct vmcb, save.cr2)); @@ -812,13 +812,13 @@ void do_vmexit(CPUX86State *env) env->idt.limit = x86_ldl_phys(cs, env->vm_hsave + offsetof(struct vmcb, save.idtr.limit)); +cpu_x86_update_cr4(env, x86_ldq_phys(cs, + env->vm_hsave + offsetof(struct vmcb, + save.cr4))); cpu_x86_update_cr0(env, x86_ldq_phys(cs, env->vm_hsave + offsetof(struct vmcb, save.cr0)) | CR0_PE_MASK); -cpu_x86_update_cr4(env, x86_ldq_phys(cs, - env->vm_hsave + offsetof(struct vmcb, - save.cr4))); cpu_x86_update_cr3(env, x86_ldq_phys(cs, env->vm_hsave + offsetof(struct vmcb, save.cr3))); -- 2.39.0
[PATCH] target/i386: translate GPA to HPA even in unpaged mode
Guest to host page translation is missing if the guest runs in unpaged mode. See last sentence in AMD SDM rev 3.40 section 15.25.5. Signed-off-by: Bernhard Kauer --- target/i386/tcg/sysemu/excp_helper.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/target/i386/tcg/sysemu/excp_helper.c b/target/i386/tcg/sysemu/excp_helper.c index 55bd1194d3..8d9152245b 100644 --- a/target/i386/tcg/sysemu/excp_helper.c +++ b/target/i386/tcg/sysemu/excp_helper.c @@ -576,6 +576,9 @@ static bool get_physical_address(CPUX86State *env, vaddr addr, } return mmu_translate(env, , out, err); } +if (use_stage2) { +return get_physical_address(env, addr, access_type, MMU_NESTED_IDX, out, err); +} break; }
[PATCH] target/i386: translate GPA to HPA even in unpaged mode
Guest to host page translation should be done even if the guest runs in unpaged mode. See last sentence in AMD SDM rev 3.40 section 15.25.5. Signed-off-by: Bernhard Kauer --- target/i386/tcg/sysemu/excp_helper.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/target/i386/tcg/sysemu/excp_helper.c b/target/i386/tcg/sysemu/excp_helper.c index 55bd1194d3..8d9152245b 100644 --- a/target/i386/tcg/sysemu/excp_helper.c +++ b/target/i386/tcg/sysemu/excp_helper.c @@ -576,6 +576,9 @@ static bool get_physical_address(CPUX86State *env, vaddr addr, } return mmu_translate(env, , out, err); } + if (use_stage2) { + return get_physical_address(env, addr, access_type, MMU_NESTED_IDX, out, err); + } break; }
Patch: target/i386: Change CR4 before CR0 in SVM
There is a dependency in cpu_x86_update_cr0() to the current value of CR4 to enable or disable long-mode. This value is outdated when switching into or out of SVM. This leads to invalid CPU state when returning from an unpaged VM when EFER.LME is set. Signed-off-by: Bernhard Kauer diff --git a/target/i386/tcg/sysemu/svm_helper.c b/target/i386/tcg/sysemu/svm_helper.c index 2d27731b60..229a22816e 100644 --- a/target/i386/tcg/sysemu/svm_helper.c +++ b/target/i386/tcg/sysemu/svm_helper.c @@ -312,8 +312,8 @@ void helper_vmrun(CPUX86State *env, int aflag, int next_eip_addend) x86_stq_phys(cs, env->vm_vmcb + offsetof(struct vmcb, control.exit_info_2), 0); - cpu_x86_update_cr0(env, new_cr0); cpu_x86_update_cr4(env, new_cr4); + cpu_x86_update_cr0(env, new_cr0); cpu_x86_update_cr3(env, new_cr3); env->cr[2] = x86_ldq_phys(cs, env->vm_vmcb + offsetof(struct vmcb, save.cr2)); @@ -812,13 +812,13 @@ void do_vmexit(CPUX86State *env) env->idt.limit = x86_ldl_phys(cs, env->vm_hsave + offsetof(struct vmcb, save.idtr.limit)); + cpu_x86_update_cr4(env, x86_ldq_phys(cs, + env->vm_hsave + offsetof(struct vmcb, + save.cr4))); cpu_x86_update_cr0(env, x86_ldq_phys(cs, env->vm_hsave + offsetof(struct vmcb, save.cr0)) | CR0_PE_MASK); - cpu_x86_update_cr4(env, x86_ldq_phys(cs, - env->vm_hsave + offsetof(struct vmcb, - save.cr4))); cpu_x86_update_cr3(env, x86_ldq_phys(cs, env->vm_hsave + offsetof(struct vmcb, save.cr3)));
Re: [Qemu-devel] [PATCH] fix curses update - v2
On Fri, May 21, 2010 at 02:02:43PM +0200, andrzej zaborowski wrote: I pushed a modified patch to preserve attributes such as background colour. Good idea. Please check if this works for you. Yes, this works. Thanks, Bernhard Kauer
[Qemu-devel] [PATCH] fix curses update - v2
On Mon, May 03, 2010 at 01:06:46PM -0500, Anthony Liguori wrote: On 04/22/2010 09:08 AM, Bernhard Kauer wrote: Hi, I believe this issue has come up before with a similar patch but well i've submitted such a patch more than two years ago. Unfortunatelly it got never applied, so that I have to patch my Qemu on every update... someone checked their ncurses and they didn't see the same issue. I just checked and here mvwaddchnstr() does not expect a null-terminated string either, but it skips the \0 characters. This is not conforming to the Single UNIX Specification, which states that the string is shown until a null chtype is encountered. See for example: http://www.opengroup.org/onlinepubs/007908775/xcurses/addchstr.html So probably we should replace them with spaces or something else, I wouldn't like to replace a single library call with 80 calls, it's better to go through the string and replace them, maybe in console_write_ch or somewhere else. That would be a one-liner. Should I send such a patch? Yes. Replace the \0 character with a space to allow to use mvwaddchnstr for full-screen updates in curses mode. Signed-off-by: Bernhard Kauer ka...@tudos.org diff --git a/console.h b/console.h index 6def115..42ff822 100644 --- a/console.h +++ b/console.h @@ -306,6 +306,7 @@ static inline int ds_get_bytes_per_pixel(DisplayState *ds) typedef unsigned long console_ch_t; static inline void console_write_ch(console_ch_t *dest, uint32_t ch) { +if (!(ch 0xff)) ch = 0x20; cpu_to_le32wu((uint32_t *) dest, ch); }
Re: [Qemu-devel] [PATCH] fix curses update
Hi, I believe this issue has come up before with a similar patch but well i've submitted such a patch more than two years ago. Unfortunatelly it got never applied, so that I have to patch my Qemu on every update... someone checked their ncurses and they didn't see the same issue. I just checked and here mvwaddchnstr() does not expect a null-terminated string either, but it skips the \0 characters. This is not conforming to the Single UNIX Specification, which states that the string is shown until a null chtype is encountered. See for example: http://www.opengroup.org/onlinepubs/007908775/xcurses/addchstr.html So probably we should replace them with spaces or something else, I wouldn't like to replace a single library call with 80 calls, it's better to go through the string and replace them, maybe in console_write_ch or somewhere else. That would be a one-liner. Should I send such a patch? Thanks, Bernhard
[Qemu-devel] [PATCH] fix curses update
If a terminal is resized or the VGA model issues a full refresh, curses_update() is called, which uses mvwaddchnstr() to draw a full line of characters. Unfortunatelly this routine expects a null-terminated string and early aborts if a null is present in the line. When booting an OS that zeros the VGA text buffer and later pokes single characters, the console output can become unreadable. The attached patch corrects this bug. Bernhard Kauer Signed-off-by: Bernhard Kauer ka...@tudos.org diff --git a/curses.c b/curses.c index ed3165e..9bf9265 100644 --- a/curses.c +++ b/curses.c @@ -48,10 +48,12 @@ static int px, py, sminx, sminy, smaxx, smaxy; static void curses_update(DisplayState *ds, int x, int y, int w, int h) { chtype *line; +int i; line = ((chtype *) screen) + y * width; for (h += y; y h; y ++, line += width) -mvwaddchnstr(screenpad, y, 0, line, width); + for (i = 0; i width; i++) + mvwaddch(screenpad, y, i, (line[i] 0xff) ? line[i] : ' '); pnoutrefresh(screenpad, py, px, sminy, sminx, smaxy - 1, smaxx - 1); refresh();
Re: [Qemu-devel] [PATCH] allow update of MSR_EFER_SVM
On Wed, Feb 27, 2008 at 06:03:49PM +0100, Alexander Graf wrote: MSR_EFER_SVM is not defined in my qemu version. What does the bit change if set? The AMD vol2 reads like this: Secure Virtual Machine Enable (SVME) Bit. Bit 12. Enables the SVM extensions. When this bit is zero, the SVM instructions cause #UD exceptions. The bit was called MSR_EFER_SVME_MASK in svm.h before, I renamed it in the attached patch to MSR_EFER_SVME to match the style of the other definitions in cpu.h. BTW, triggering the above mentioned #UD is missing in the code... Bernhard Kauer Index: target-i386/helper.c === RCS file: /sources/qemu/qemu/target-i386/helper.c,v retrieving revision 1.101 diff -u -r1.101 helper.c --- target-i386/helper.c 3 Feb 2008 03:26:30 - 1.101 +++ target-i386/helper.c 29 Feb 2008 09:33:41 - @@ -2802,6 +2802,8 @@ update_mask |= MSR_EFER_FFXSR; if (env-cpuid_ext2_features CPUID_EXT2_NX) update_mask |= MSR_EFER_NXE; + if (env-cpuid_ext3_features CPUID_EXT3_SVM) + update_mask |= MSR_EFER_SVME; env-efer = (env-efer ~update_mask) | (val update_mask); } Index: target-i386/svm.h === RCS file: /sources/qemu/qemu/target-i386/svm.h,v retrieving revision 1.1 diff -u -r1.1 svm.h --- target-i386/svm.h 23 Sep 2007 15:30:28 - 1.1 +++ target-i386/svm.h 29 Feb 2008 09:33:41 - @@ -179,7 +179,7 @@ #define SVM_CPUID_FEATURE_SHIFT 2 #define SVM_CPUID_FUNC 0x800a -#define MSR_EFER_SVME_MASK (1ULL 12) +#define MSR_EFER_SVME (1ULL 12) #define SVM_SELECTOR_S_SHIFT 4 #define SVM_SELECTOR_DPL_SHIFT 5
Re: [Qemu-devel] [PATCH] allow update of MSR_EFER_SVM
On Fri, Feb 29, 2008 at 11:20:24AM +0100, Alexander Graf wrote: Keep in mind that updating the bit should fail within a virtual machine. I found the following sentence in the manual: The effect of turning off EFER.SVME while a guest is running is undefined; therefore, the VMM should always prevent guests from writing EFER. Therefore i think the wrmsr-code is just fine, as it is in my patch. Bernhard Kauer
[Qemu-devel] [PATCH] allow update of MSR_EFER_SVM
The wrmsr_helper should allow to set the SVM flag in EFER. Bernhard Kauer Index: target-i386/helper.c === RCS file: /sources/qemu/qemu/target-i386/helper.c,v retrieving revision 1.101 diff -u -r1.101 helper.c --- target-i386/helper.c 3 Feb 2008 03:26:30 - 1.101 +++ target-i386/helper.c 27 Feb 2008 16:05:33 - @@ -2802,6 +2802,8 @@ update_mask |= MSR_EFER_FFXSR; if (env-cpuid_ext2_features CPUID_EXT2_NX) update_mask |= MSR_EFER_NXE; + if (env-cpuid_ext3_features CPUID_EXT3_SVM) + update_mask |= MSR_EFER_SVM; env-efer = (env-efer ~update_mask) | (val update_mask); }
[Qemu-devel] [PATCH] fix ncurses output
The ncurses console uses mvwaddchnstr() to print a line of output to a ncurses pad. Unfortunately this routine stops to print further chars if a zero-char is seen in the line. This has the effect that parts of a line are never redraw. The following patch puts spaces instead of the zeros into the line-buffer. Please note that this change affects other consoles as well and is perhaps undesirable. Comments? Bernhard Kauer Index: console.h --- console.h 10 Feb 2008 16:33:13 - 1.2 +++ console.h 25 Feb 2008 17:25:53 - @@ -104,7 +104,8 @@ typedef unsigned long console_ch_t; static inline void console_write_ch(console_ch_t *dest, uint32_t ch) { -cpu_to_le32wu((uint32_t *) dest, ch); + if (!(ch 0xff)) ch = 0x20; + cpu_to_le32wu((uint32_t *) dest, ch); } typedef void (*vga_hw_update_ptr)(void *);
[Qemu-devel] [PATCH] fix SVM event injection
The SVM event injection mechanism for NMI and INTRs should not be handled as software interrupts. Bernhard Kauer Index: target-i386/helper.c --- target-i386/helper.c 24 Dec 2007 13:36:00 - 1.98 +++ target-i386/helper.c 23 Jan 2008 22:37:49 - @@ -4124,7 +4193,7 @@ case SVM_EVTINJ_TYPE_INTR: env-exception_index = vector; env-error_code = event_inj_err; -env-exception_is_int = 1; +env-exception_is_int = 0; env-exception_next_eip = -1; if (loglevel CPU_LOG_TB_IN_ASM) fprintf(logfile, INTR); @@ -4132,7 +4201,7 @@ case SVM_EVTINJ_TYPE_NMI: env-exception_index = vector; env-error_code = event_inj_err; -env-exception_is_int = 1; +env-exception_is_int = 0; env-exception_next_eip = EIP; if (loglevel CPU_LOG_TB_IN_ASM) fprintf(logfile, NMI);
Re: [Qemu-devel] [PATCH]SVM CR8 undefined bug fix
On Thu, Jan 17, 2008 at 05:13:31PM +0100, Alexander Graf wrote: Their only difference is, that the TPR is implemented as an MSR, whereas the CR8 is a CPU register. The TPR is currently a memory mapped local Apic register. The default address is 0xfee00080, according to Intel vol3a chapter 8... Bernhard Kauer
[Qemu-devel] [PATCH] fix cmpxchg8b translation
The cmpxchg8b opcode is only valid if the nnn bits in the mod/rm byte are 001, otherwise an #UD should be generated. The attached patch fixes this. Bernhard Kauer Index: target-i386/translate.c --- target-i386/translate.c 8 Nov 2007 14:25:03 - 1.74 +++ target-i386/translate.c 18 Dec 2007 12:14:08 - @@ -3887,7 +3887,7 @@ case 0x1c7: /* cmpxchg8b */ modrm = ldub_code(s-pc++); mod = (modrm 6) 3; -if (mod == 3) +if ((mod == 3) || ((modrm 0x38) != 0x8)) goto illegal_op; gen_jmp_im(pc_start - s-cs_base); if (s-cc_op != CC_OP_DYNAMIC)
[Qemu-devel] [PATCH] SVM enabled processor should provide cpuid Fn8000_000A
An SVM enabled processor should provide the CPUID extended leaf Fn8000_000A (see AMD documentation #25481). The attached patch add this feature. Bernhard Kauer Index: target-i386/helper.c === RCS file: /sources/qemu/qemu/target-i386/helper.c,v retrieving revision 1.97 diff -u -r1.97 helper.c --- target-i386/helper.c 9 Dec 2007 23:39:22 - 1.97 +++ target-i386/helper.c 18 Dec 2007 12:40:06 - @@ -1751,6 +1819,12 @@ ECX = 0; EDX = 0; break; +case 0x800A: +EAX = 0x0001; +EBX = 0; +ECX = 0; +EDX = 0; + break; default: /* reserved values: zero */ EAX = 0; Index: target-i386/helper2.c === RCS file: /sources/qemu/qemu/target-i386/helper2.c,v retrieving revision 1.60 diff -u -r1.60 helper2.c --- target-i386/helper2.c 9 Dec 2007 02:43:19 - 1.60 +++ target-i386/helper2.c 18 Dec 2007 12:40:06 - @@ -150,7 +150,7 @@ .ext2_features = (PPRO_FEATURES 0x0183F3FF) | CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX, .ext3_features = CPUID_EXT3_SVM, -.xlevel = 0x8008, +.xlevel = 0x800A, }, #endif {
Re: [Qemu-devel] [PATCH] SVM IOIO intercept does not check all bits
On Fri, Dec 07, 2007 at 04:16:00PM +0100, Alexander Graf wrote: For IN/OUT instructions that access more than a single byte, the permission bits for all bytes are checked; if any bit is set to 1, the I/O operation is intercepted. That was the one. Thank you. Unfortunately there is another bug in this line. As there is only a single byte read from the permission bitmap, an unaligned 4-byte access to port 0x7 would be possible even when the access to port 0x8-0xa is not allowed. The updated patch fixes also this case. Bernhard Kauer Index: target-i386/helper.c === RCS file: /sources/qemu/qemu/target-i386/helper.c,v retrieving revision 1.95 diff -u -r1.95 helper.c --- target-i386/helper.c 18 Nov 2007 01:44:38 - 1.95 +++ target-i386/helper.c 8 Dec 2007 20:44:28 - @@ -4250,7 +4332,8 @@ uint64_t addr = ldq_phys(env-vm_vmcb + offsetof(struct vmcb, control.iopm_base_pa)); uint16_t port = (uint16_t) (param 16); -if(ldub_phys(addr + port / 8) (1 (port % 8))) +uint16_t mask = (1 ((param 4) 7)) - 1; +if(lduw_phys(addr + port / 8) (mask (port 7))) vmexit(type, param); } break;
Re: [Qemu-devel] [PATCH] SVM IOIO intercept does not check all bits
On Fri, Dec 07, 2007 at 02:10:35PM +0100, Alexander Graf wrote: Could you please make this more readable? Not easy by a one liner. I splitted the mask calculation in a separate line. Is it better now? Apart from that the patch is fine if the highest bit in the IOIO vector is to be set. I could not find that in the documentation. I did not understand your comment. Perhaps you mean the following sentence from the AMD vol. 2: For IN/OUT instructions that access more than a single byte, the permission bits for all bytes are checked; if any bit is set to 1, the I/O operation is intercepted. Greetings, Bernhard Index: target-i386/helper.c === RCS file: /sources/qemu/qemu/target-i386/helper.c,v retrieving revision 1.95 diff -u -r1.95 helper.c --- target-i386/helper.c 18 Nov 2007 01:44:38 - 1.95 +++ target-i386/helper.c 7 Dec 2007 14:10:57 - @@ -4250,7 +4331,8 @@ uint64_t addr = ldq_phys(env-vm_vmcb + offsetof(struct vmcb, control.iopm_base_pa)); uint16_t port = (uint16_t) (param 16); -if(ldub_phys(addr + port / 8) (1 (port % 8))) + uint8_t mask = (1 ((param 4) 0x7)) - 1; + if(ldub_phys(addr + port / 8) (mask (port % 8))) vmexit(type, param); } break;
[Qemu-devel] [PATCH] SVM IOIO intercept does not check all bits
The SVM IOIO intercept does not check all bits in the IO permission map for in/outs with word or long operand size. The attached patch fix this. Bernhard Kauer Index: target-i386/helper.c --- target-i386/helper.c 18 Nov 2007 01:44:38 - 1.95 +++ target-i386/helper.c 6 Dec 2007 19:22:55 - @@ -4250,8 +4331,8 @@ uint64_t addr = ldq_phys(env-vm_vmcb + offsetof(struct vmcb, control.iopm_base_pa)); uint16_t port = (uint16_t) (param 16); -if(ldub_phys(addr + port / 8) (1 (port % 8))) -vmexit(type, param); + if(ldub_phys(addr + port / 8) (((1 ((param 4) 0x7)) - 1) (port % 8))) + vmexit(type, param); } break;
[Qemu-devel] [PATCH] add rdpmc intercept for SVM
The attached patch adds an SVM intercept for rdpmc to qemu, thus allowing a VMM to virtualize them. Please note that performance counters are currently unimplemented in qemu. Bernhard Kauer Index: target-i386/helper.c --- target-i386/helper.c 18 Nov 2007 01:44:38 - 1.95 +++ target-i386/helper.c 5 Dec 2007 19:31:31 - @@ -2743,6 +2816,19 @@ EDX = (uint32_t)(val 32); } +void helper_rdpmc() +{ + if ((env-cr[4] CR4_PCE_MASK) ((env-hflags HF_CPL_MASK) != 0)) { +raise_exception(EXCP0D_GPF); + } + + if (!svm_check_intercept_param(SVM_EXIT_RDPMC, 0)) +{ + // currently unimplemented + raise_exception_err(EXCP06_ILLOP, 0); +} +} + #if defined(CONFIG_USER_ONLY) void helper_wrmsr(void) { Index: target-i386/op.c --- target-i386/op.c 23 Sep 2007 15:28:04 - 1.51 +++ target-i386/op.c 5 Dec 2007 19:31:32 - @@ -953,6 +953,11 @@ helper_rdtsc(); } +void OPPROTO op_rdpmc(void) +{ +helper_rdpmc(); +} + void OPPROTO op_cpuid(void) { helper_cpuid(); Index: target-i386/translate.c --- target-i386/translate.c 8 Nov 2007 14:25:03 - 1.74 +++ target-i386/translate.c 5 Dec 2007 19:31:38 - @@ -5653,5 +5653,9 @@ gen_op_rdtsc(); break; +case 0x133: /* rdpmc */ +gen_jmp_im(pc_start - s-cs_base); +gen_op_rdpmc(); +break; case 0x134: /* sysenter */ if (CODE64(s)) goto illegal_op;
Re: [Qemu-devel] [Patch] set boot sequence from command line
It is perhaps not the best idea to read behind the end of the boot_device string. It would be safer to declare boot_device as 'static char boot_device[4]' and use a strncpy. Bernhard diff --git a/hw/pc.c b/hw/pc.c index a0c824f..3c552ff 100644 --- a/hw/pc.c +++ b/hw/pc.c +/* set boot devices, and disable floppy signature check if requested */ +rtc_set_memory(s, 0x3d, +boot_device2nible(boot_device[1]) 4 | +boot_device2nible(boot_device[0]) ); +rtc_set_memory(s, 0x38, +boot_device2nible(boot_device[2]) 4 | (fd_bootchk ? 0x0 : 0x1)); /* floppy type */ diff --git a/vl.c b/vl.c index 6d8fe35..be0e06a 100644 --- a/vl.c +++ b/vl.c +if (strlen(optarg) 3) { +fprintf(stderr, qemu: too many boot devices\n); +exit(1); +} +boot_device = strdup(optarg); +if (!strchr(boot_device, 'a')
Re: [Qemu-devel] BIOS: ACPI Tables: wrong memory pointer
On Fri, Sep 14, 2007 at 02:55:22PM +0200, Chris wrote: There is an error in the bios code (I haven´t found it) with the address which gets insert into the acpi tables (rsdt address) and the address which is inserted into the smap tables when the memory of the emulated machine is under 19MiB RAM! From 19MiB RAM on the address in the smap tables and the address of the rsdt in the acpi tables is correct. Maybe someone with more experience with the bios code can look on this? It's a Bochs Bios bug. See my mail [EMAIL PROTECTED] from Sep 10 on the Bochs developer mailinglist for a patch. Bernhard Kauer
Re: [Qemu-devel] [PATCH] SVM support
On Thu, Aug 30, 2007 at 04:54:15PM +0200, Alexander Graf wrote: Hi, after a lot of struggling I finally got everything working smoothly (special thanks to Fabrice and Avi), so I believe this patch is ready to be taken upstream. CC_DST was never a problem, as everything I did in the eflags area already worked. I managed to clobber the segment attributes though, so that was the real problem here. Nevertheless there is still a lot of functionality missing, whereas none of that is used in kvm by now, so that works already. So there are still missing parts that I will list here: - NPT support - Everything related to device virtualisation - The Secure part of the extension (would need TPM emulation for that) I backported Xen's TPM emulation to Qemu for exactly that purpose. I also started to implement skinit, but did not had the time to finish that work, yet. Please note that this patch requires a two line patch to the tpm-emulator to understand the localities. Bernhard Kauer Index: Makefile.target === RCS file: /sources/qemu/qemu/Makefile.target,v retrieving revision 1.191 diff -u -r1.191 Makefile.target --- Makefile.target 31 Jul 2007 23:44:21 - 1.191 +++ Makefile.target 7 Aug 2007 03:43:28 - @@ -429,6 +429,7 @@ VL_OBJS+= fdc.o mc146818rtc.o serial.o i8259.o i8254.o pcspk.o pc.o VL_OBJS+= cirrus_vga.o apic.o parallel.o acpi.o piix_pci.o VL_OBJS+= usb-uhci.o smbus_eeprom.o vmmouse.o vmware_vga.o +VL_OBJS+= tpm_tis.o CPPFLAGS += -DHAS_AUDIO -DHAS_AUDIO_CHOICE endif ifeq ($(TARGET_BASE_ARCH), ppc) Index: hw/pc.c === RCS file: /sources/qemu/qemu/hw/pc.c,v retrieving revision 1.81 diff -u -r1.81 pc.c --- hw/pc.c 6 Jun 2007 16:26:13 - 1.81 +++ hw/pc.c 7 Aug 2007 03:43:37 - @@ -914,6 +917,9 @@ if (i440fx_state) { i440fx_init_memory_mappings(i440fx_state); } + +tpm_tis_init(); + #if 0 /* ??? Need to figure out some way for the user to specify SCSI devices. */ --- /dev/null 2007-08-06 15:49:45.580307540 +0200 +++ hw/tpm_tis.c 2007-08-07 05:39:41.0 +0200 @@ -0,0 +1,890 @@ +/* + * tpm_tis.c - QEMU emulator for a 1.2 TPM with TIS interface + * + * Copyright (C) 2006 IBM Corporation + * + * Author: Stefan Berger [EMAIL PROTECTED] + * David Safford [EMAIL PROTECTED] + * Bernhard Kauer [EMAIL PROTECTED] + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, version 2 of the + * License. + * + * + * Implementation of the TIS interface according to specs at + * https://www.trustedcomputinggroup.org/groups/pc_client/TCG_PCClientTPMSpecification_1-20_1-00_FINAL.pdf + * + */ + +#include sys/types.h +#include sys/stat.h +#include sys/socket.h +#include sys/un.h +#include fcntl.h +#include errno.h +#include assert.h +#include vl.h + + +#define DEBUG_TPM +#define logfile stderr +#define LOCAL_SOCKET_PATH tpmd +/* if the connection to the vTPM should be closed after a successfully + received response; set to '0' to allow keeping the connection */ +#define FORCE_CLOSE 0 + + + +#define TPM_MAX_PKT 4096 +#define TIS_ADDR_BASE 0xFED4 + +/* tis registers */ +#define TPM_REG_ACCESS0x00 +#define TPM_REG_INT_ENABLE0x08 +#define TPM_REG_INT_VECTOR0x0c +#define TPM_REG_INT_STATUS0x10 +#define TPM_REG_INTF_CAPABILITY 0x14 +#define TPM_REG_STS 0x18 +#define TPM_REG_HASH_END 0x20 +#define TPM_REG_DATA_FIFO 0x24 +#define TPM_REG_HASH_START0x28 +#define TPM_REG_DID_VID 0xf00 +#define TPM_REG_RID 0xf04 + +#define STS_VALID(1 7) +#define STS_COMMAND_READY(1 6) +#define STS_TPM_GO (1 5) +#define STS_DATA_AVAILABLE (1 4) +#define STS_EXPECT (1 3) +#define STS_RESPONSE_RETRY (1 1) + +#define ACCESS_TPM_REG_VALID_STS (1 7) +#define ACCESS_ACTIVE_LOCALITY (1 5) +#define ACCESS_BEEN_SEIZED (1 4) +#define ACCESS_SEIZE (1 3) +#define ACCESS_PENDING_REQUEST (1 2) +#define ACCESS_REQUEST_USE (1 1) +#define ACCESS_TPM_ESTABLISHMENT (1 0) + +#define INT_ENABLED (1 31) +#define INT_DATA_AVAILABLE (1 0) +#define INT_LOCALITY_CHANGED (1 2) +#define INT_COMMAND_READY(1 7) + +#define INTERRUPTS_SUPPORTED (INT_LOCALITY_CHANGED | \ + INT_DATA_AVAILABLE | \ + INT_COMMAND_READY) +#define CAPABILITIES_SUPPORTED ((1 4) |\ + INTERRUPTS_SUPPORTED) + +enum { + STATE_IDLE
Re: [Qemu-devel] Patch: let qemu work with latest bochsbios
Has somebody besides me tested the patch? Bernhard Kauer On Wed, Aug 01, 2007 at 05:42:17PM +0200, Bernhard Kauer wrote: The boot_device is not communicated to the bochsbios through the CMOS. The following patch allows to boot via network on the newest bochsbios.
Re: [Qemu-devel] Why not use exit() instead of abort()?
On Mon, Aug 06, 2007 at 07:21:21AM +0930, Dan Shearer wrote: On Sun, Aug 05, 2007 at 11:13:55PM +0200, Bernhard Kauer wrote: There are a couple of places in qemu, where abort() is called. The most commonly used one is perhaps cpu_abort() which is called e.g. when a triple fault occures. As abort() does not call any atexit() function, cleanup is not performed. Tiny correction: abort() and _exit don't call atexit(), however unix-like OSs still cleanup memory and file descriptors and other transient resources anyway no matter how the program ended. So lack of cleanup isn't quite as big an issue as it might seem. This leaves for example the terminal in a state where the cursor is invisible. Non-transient resources such as DSOs and domain sockets are not cleaned up by the OS, which accounts for the terminal problem you noticed. Well, the problem is here that the function term_exit() is never called, which would restore the terminal state to the old version via a tcsetattr(). Are there any reasons not to use exit(1) in cpu_abort()? Speed. I used to use abort() or _exit() for speed, ie they didn't hang around while atexit() waited politely for timeouts. I thought if I told the program to stop it should stop immediately :-) I would use a 'kill -TERM' for that. Bernhard
[Qemu-devel] Why not use exit() instead of abort()?
There are a couple of places in qemu, where abort() is called. The most commonly used one is perhaps cpu_abort() which is called e.g. when a triple fault occures. As abort() does not call any atexit() function, cleanup is not performed. This leaves for example the terminal in a state where the cursor is invisible. Are there any reasons not to use exit(1) in cpu_abort()? Bernhard Kauer Index: exec.c === RCS file: /sources/qemu/qemu/exec.c,v retrieving revision 1.103 diff -u -r1.103 exec.c --- exec.c 1 Jul 2007 18:21:11 - 1.103 +++ exec.c 4 Aug 2007 13:07:52 - @@ -1301,7 +1301,7 @@ fflush(logfile); fclose(logfile); } -abort(); +exit(1); } CPUState *cpu_copy(CPUState *env)
[Qemu-devel] Patch: let qemu work with latest bochsbios
The boot_device is not communicated to the bochsbios through the CMOS. The following patch allows to boot via network on the newest bochsbios. Bernhard Kauer
[Qemu-devel] Patch: let qemu work with latest bochsbios
The boot_device is not communicated to the bochsbios through the CMOS. The following patch allows to boot via network on the newest bochsbios. Bernhard Kauer Index: vl.c === RCS file: /sources/qemu/qemu/vl.c,v retrieving revision 1.323 diff -u -r1.323 vl.c --- vl.c 29 Jul 2007 17:57:25 - 1.323 +++ vl.c 1 Aug 2007 15:36:31 - @@ -7828,7 +7828,7 @@ fprintf(stderr, No valid PXE rom found for network device\n); exit(1); } - boot_device = 'c'; /* to prevent confusion by the BIOS */ + //boot_device = 'c'; /* to prevent confusion by the BIOS */ } #endif Index: hw/pc.c === RCS file: /sources/qemu/qemu/hw/pc.c,v retrieving revision 1.81 diff -u -r1.81 pc.c --- hw/pc.c 6 Jun 2007 16:26:13 - 1.81 +++ hw/pc.c 1 Aug 2007 15:36:31 - @@ -197,6 +197,9 @@ case 'd': rtc_set_memory(s, 0x3d, 0x03); /* CD-ROM boot */ break; +case 'n': +rtc_set_memory(s, 0x3d, 0x04); /* Network boot */ +break; } /* floppy type */
[Qemu-devel] Patch: fix init of old_exception
The old_exception field is initialized on startup with 0. Therefore the very first fault (e.g. #GP) could be converted to a double fault on an application processor. The attached patch initialize old_exception on every CPU reset with -1. Bernhard Kauer Index: target-i386/helper2.c === RCS file: /sources/qemu/qemu/target-i386/helper2.c,v retrieving revision 1.47 diff -u -r1.47 helper2.c --- target-i386/helper2.c 17 Apr 2007 23:08:56 - 1.47 +++ target-i386/helper2.c 31 Jul 2007 14:30:55 - @@ -155,6 +155,8 @@ tlb_flush(env, 1); +env-old_exception = -1; + /* init to reset state */ #ifdef CONFIG_SOFTMMU
[Qemu-devel] Patch: PIC-i8259 mode transition wrong
The PIC initilization should respect the fourth byte init bit in single mode. Bernhard Kauer Index: hw/i8259.c === RCS file: /sources/qemu/qemu/hw/i8259.c,v retrieving revision 1.22 diff -u -r1.22 i8259.c --- hw/i8259.c 7 Apr 2007 18:14:41 - 1.22 +++ hw/i8259.c 31 Jul 2007 14:31:14 - @@ -351,7 +351,7 @@ break; case 1: s-irq_base = val 0xf8; -s-init_state = s-single_mode s-init4 ? 3 : 2; +s-init_state = s-single_mode ? (s-init4 ? 3 : 0) : 2; break; case 2: if (s-init4) {
Re: [Qemu-devel] Qemu / KQemu on 64-bit (x86_64) host systems
On Mon, Apr 16, 2007 at 08:47:07AM +0200, Werner Dittmann wrote: My general thought about the problem: running 32bit code on a 64bit host with similar architecture as this is the case of x86 / x86_64 could easily result in problems with signedness, sign bit extension, different pointer/word/interger sizes... qemu-system-x86_64 has indeed some signedness problem. I posted a patch [EMAIL PROTECTED] a couple of days ago for the problem that the pagefault address gets incorrectly sign extended when running 32-bit code. Nevertheless its just a workaround, the place where this wrong sign extension happend needs still to be found. Bernhard Kauer
[Qemu-devel] Patch: ptable calculation broken for 32bit code under x86_64
The calculation of pdpe and pde addresses is broken, when running 32bit code under x86_64-qemu. The code assumes that the addr parameter is 32bit wide. This assumption does not hold for x86_64 as target. Bernhard Kauer Index: target-i386/helper2.c === RCS file: /sources/qemu/qemu/target-i386/helper2.c,v retrieving revision 1.46 diff -u -r1.46 helper2.c --- target-i386/helper2.c 7 Apr 2007 11:21:28 - 1.46 +++ target-i386/helper2.c 10 Apr 2007 13:28:02 - @@ -670,7 +670,7 @@ #endif { /* XXX: load them when cr3 is loaded ? */ -pdpe_addr = ((env-cr[3] ~0x1f) + ((addr 30) 3)) +pdpe_addr = ((env-cr[3] ~0x1f) + ((addr 27) 0x18)) env-a20_mask; pdpe = ldq_phys(pdpe_addr); if (!(pdpe PG_PRESENT_MASK)) { @@ -765,7 +765,7 @@ uint32_t pde; /* page directory entry */ -pde_addr = ((env-cr[3] ~0xfff) + ((addr 20) ~3)) +pde_addr = ((env-cr[3] ~0xfff) + ((addr 20) 0xffc)) env-a20_mask; pde = ldl_phys(pde_addr); if (!(pde PG_PRESENT_MASK)) { @@ -910,7 +910,7 @@ } else #endif { -pdpe_addr = ((env-cr[3] ~0x1f) + ((addr 30) 3)) +pdpe_addr = ((env-cr[3] ~0x1f) + ((addr 27) 0x18)) env-a20_mask; pdpe = ldl_phys(pdpe_addr); if (!(pdpe PG_PRESENT_MASK)) @@ -940,7 +940,7 @@ page_size = 4096; } else { /* page directory entry */ -pde_addr = ((env-cr[3] ~0xfff) + ((addr 20) ~3)) env-a20_mask; +pde_addr = ((env-cr[3] ~0xfff) + ((addr 20) 0xffc)) env-a20_mask; pde = ldl_phys(pde_addr); if (!(pde PG_PRESENT_MASK)) return -1;
[Qemu-devel] Patch: generate double and triple faults
On Wed, Mar 28, 2007 at 02:39:31PM +0200, Bernhard Kauer wrote: On Wed, Mar 28, 2007 at 10:13:49AM +0200, Sebastian Kaliszewski wrote: Bernhard Kauer wrote: Qemu does not generate a double fault (DBF) on x86, if a general protection fault could not be delivered. Instead it hangs in a loop. The patch fix this bug by checking whether we are already in a GPF exception. If you're at it, maybe add triple fault handling (ie exception if DBF handler) -- it should reset CPU. There are many things missing in the x86 exception handling. For example the case PF - PF is also not handled. The attached patch implements double andd triple fault handling and makes the last patch obsolete. It does not generate a reset on triple fault, but it aborts qemu. The same happen currently if the TSS is bogous. Greetings, Bernhard Kauer Index: cpu-exec.c === RCS file: /sources/qemu/qemu/cpu-exec.c,v retrieving revision 1.97 diff -u -r1.97 cpu-exec.c --- cpu-exec.c 30 Mar 2007 16:44:53 - 1.97 +++ cpu-exec.c 31 Mar 2007 11:59:52 - @@ -360,6 +360,7 @@ env-exception_is_int, env-error_code, env-exception_next_eip, 0); + env-old_exception = -1; // successful delivered #elif defined(TARGET_PPC) do_interrupt(env); #elif defined(TARGET_MIPS) Index: target-i386/helper.c === RCS file: /sources/qemu/qemu/target-i386/helper.c,v retrieving revision 1.74 diff -u -r1.74 helper.c --- target-i386/helper.c1 Feb 2007 22:12:19 - 1.74 +++ target-i386/helper.c31 Mar 2007 11:59:58 - @@ -1192,6 +1193,37 @@ } } + +/** + * Check nested exceptions and change to double or triple fault if + * needed. It should only be called, if this is not an + * interrrupt. Returns the new exception number. + */ +int check_exception(int intno, int *error_code) +{ + if (loglevel CPU_LOG_INT) +fprintf(logfile, %s() old: %x new %x\n,__func__, env-old_exception, intno); + + + if (env-old_exception == EXCP08_DBLE) + cpu_abort(env, triple fault); + + char first_contributory = env-old_exception == 0 || (env-old_exception = 10 env-old_exception = 13); + char second_contributory = intno == 0 || (intno = 10 intno = 13); + + if ((first_contributory second_contributory) + || (env-old_exception == EXCP0E_PAGE (second_contributory || (intno == EXCP0E_PAGE + { + intno = EXCP08_DBLE; + *error_code = 0; + } + + if (second_contributory || (intno == EXCP0E_PAGE) || (intno == EXCP08_DBLE)) + env-old_exception = intno; + return intno; +} + + /* * Signal an interruption. It is executed in the main CPU loop. * is_int is TRUE if coming from the int instruction. next_eip is the @@ -1201,6 +1233,9 @@ void raise_interrupt(int intno, int is_int, int error_code, int next_eip_addend) { +if (!is_int) +intno = check_exception(intno, error_code); + env-exception_index = intno; env-error_code = error_code; env-exception_is_int = is_int; @@ -1211,6 +1246,8 @@ /* same as raise_exception_err, but do not restore global registers */ static void raise_exception_err_norestore(int exception_index, int error_code) { +exception_index = check_exception(exception_index, error_code); + env-exception_index = exception_index; env-error_code = error_code; env-exception_is_int = 0; Index: target-i386/cpu.h === RCS file: /sources/qemu/qemu/target-i386/cpu.h,v retrieving revision 1.41 diff -u -r1.41 cpu.h --- target-i386/cpu.h 5 Feb 2007 22:06:27 - 1.41 +++ target-i386/cpu.h 31 Mar 2007 11:59:56 - @@ -515,6 +515,7 @@ uint32_t smbase; int interrupt_request; int user_mode_only; /* user mode only simulation */ +int old_exception; /* exception in flight */ CPU_COMMON
[Qemu-devel] Patch: PIC-i8259 does not work in single mode
The PIC-i8259 does not work in single mode, where only the master PIC is used. The attached patch fixes the initialization part for single mode. Bernhard Kauer Index: i8259.c === RCS file: /sources/qemu/qemu/hw/i8259.c,v retrieving revision 1.20 diff -u -r1.20 i8259.c --- i8259.c 24 Jan 2007 01:47:51 - 1.20 +++ i8259.c 26 Mar 2007 17:01:18 - @@ -44,6 +44,7 @@ uint8_t rotate_on_auto_eoi; uint8_t special_fully_nested_mode; uint8_t init4; /* true if 4 byte init */ +uint8_t single_mode; /* true if slave pic is not initialized */ uint8_t elcr; /* PIIX edge/trigger selection*/ uint8_t elcr_mask; PicState2 *pics_state; @@ -278,6 +279,7 @@ s-rotate_on_auto_eoi = 0; s-special_fully_nested_mode = 0; s-init4 = 0; +s-single_mode = 0; /* Note: ELCR is not reset */ } @@ -298,8 +300,7 @@ s-pics_state-irq_request(s-pics_state-irq_request_opaque, 0); s-init_state = 1; s-init4 = val 1; -if (val 0x02) -hw_error(single mode not supported); +s-single_mode = val 2; if (val 0x08) hw_error(level sensitive irq not supported); } else if (val 0x08) { @@ -356,7 +357,7 @@ break; case 1: s-irq_base = val 0xf8; -s-init_state = 2; +s-init_state = s-single_mode s-init4 ? 3 : 2; break; case 2: if (s-init4) { @@ -468,6 +469,7 @@ qemu_put_8s(f, s-rotate_on_auto_eoi); qemu_put_8s(f, s-special_fully_nested_mode); qemu_put_8s(f, s-init4); +qemu_put_8s(f, s-single_mode); qemu_put_8s(f, s-elcr); } @@ -492,6 +494,7 @@ qemu_get_8s(f, s-rotate_on_auto_eoi); qemu_get_8s(f, s-special_fully_nested_mode); qemu_get_8s(f, s-init4); +qemu_get_8s(f, s-single_mode); qemu_get_8s(f, s-elcr); return 0; }
Re: [Qemu-devel] Patch: generate a DBF when a GPF could not be delivered on x86
On Wed, Mar 28, 2007 at 10:13:49AM +0200, Sebastian Kaliszewski wrote: Bernhard Kauer wrote: Qemu does not generate a double fault (DBF) on x86, if a general protection fault could not be delivered. Instead it hangs in a loop. The patch fix this bug by checking whether we are already in a GPF exception. If you're at it, maybe add triple fault handling (ie exception if DBF handler) -- it should reset CPU. There are many things missing in the x86 exception handling. For example the case PF - PF is also not handled. Bernhard Kauer
[Qemu-devel] Patch: generate a DBF when a GPF could not be delivered on x86
Qemu does not generate a double fault (DBF) on x86, if a general protection fault could not be delivered. Instead it hangs in a loop. The patch fix this bug by checking whether we are already in a GPF exception. Bernhard Kauer Index: helper.c === RCS file: /sources/qemu/qemu/target-i386/helper.c,v retrieving revision 1.74 diff -u -r1.74 helper.c --- helper.c1 Feb 2007 22:12:19 - 1.74 +++ helper.c27 Mar 2007 11:33:34 - @@ -592,6 +592,16 @@ sp += 4;\ } +void +raise_gpf(int intno, int is_int, int is_hw, int error) +{ + if (!is_int !is_hw intno == EXCP0D_GPF) +raise_exception_err(EXCP08_DBLE, 0); + else +raise_exception_err(EXCP0D_GPF, error = 0 ? error : intno * TARGET_LONG_SIZE + 2); +} + + /* protected mode interrupt */ static void do_interrupt_protected(int intno, int is_int, int error_code, unsigned int next_eip, int is_hw) @@ -624,7 +634,7 @@ dt = env-idt; if (intno * 8 + 7 dt-limit) -raise_exception_err(EXCP0D_GPF, intno * 8 + 2); +raise_gpf(intno, is_int, is_hw, -1); ptr = dt-base + intno * 8; e1 = ldl_kernel(ptr); e2 = ldl_kernel(ptr + 4); @@ -661,29 +671,30 @@ case 15: /* 386 trap gate */ break; default: -raise_exception_err(EXCP0D_GPF, intno * 8 + 2); +raise_gpf(intno, is_int, is_hw, -1); break; } dpl = (e2 DESC_DPL_SHIFT) 3; cpl = env-hflags HF_CPL_MASK; /* check privledge if software int */ if (is_int dpl cpl) -raise_exception_err(EXCP0D_GPF, intno * 8 + 2); +raise_gpf(intno, is_int, is_hw, -1); + /* check valid bit */ if (!(e2 DESC_P_MASK)) raise_exception_err(EXCP0B_NOSEG, intno * 8 + 2); selector = e1 16; offset = (e2 0x) | (e1 0x); if ((selector 0xfffc) == 0) -raise_exception_err(EXCP0D_GPF, 0); +raise_gpf(intno, is_int, is_hw, 0); if (load_segment(e1, e2, selector) != 0) -raise_exception_err(EXCP0D_GPF, selector 0xfffc); +raise_gpf(intno, is_int, is_hw, selector 0xfffc); if (!(e2 DESC_S_MASK) || !(e2 (DESC_CS_MASK))) -raise_exception_err(EXCP0D_GPF, selector 0xfffc); +raise_gpf(intno, is_int, is_hw, selector 0xfffc); dpl = (e2 DESC_DPL_SHIFT) 3; if (dpl cpl) -raise_exception_err(EXCP0D_GPF, selector 0xfffc); +raise_gpf(intno, is_int, is_hw, selector 0xfffc); if (!(e2 DESC_P_MASK)) raise_exception_err(EXCP0B_NOSEG, selector 0xfffc); if (!(e2 DESC_C_MASK) dpl cpl) { @@ -710,14 +721,14 @@ } else if ((e2 DESC_C_MASK) || dpl == cpl) { /* to same priviledge */ if (env-eflags VM_MASK) -raise_exception_err(EXCP0D_GPF, selector 0xfffc); + raise_gpf(intno, is_int, is_hw, selector 0xfffc); new_stack = 0; sp_mask = get_sp_mask(env-segs[R_SS].flags); ssp = env-segs[R_SS].base; esp = ESP; dpl = cpl; } else { -raise_exception_err(EXCP0D_GPF, selector 0xfffc); +raise_gpf(intno, is_int, is_hw, selector 0xfffc); new_stack = 0; /* avoid warning */ sp_mask = 0; /* avoid warning */ ssp = 0; /* avoid warning */ @@ -860,7 +871,7 @@ dt = env-idt; if (intno * 16 + 15 dt-limit) -raise_exception_err(EXCP0D_GPF, intno * 16 + 2); +raise_gpf(intno, is_int, is_hw, -1); ptr = dt-base + intno * 16; e1 = ldl_kernel(ptr); e2 = ldl_kernel(ptr + 4); @@ -872,14 +883,13 @@ case 15: /* 386 trap gate */ break; default: -raise_exception_err(EXCP0D_GPF, intno * 16 + 2); -break; +raise_gpf(intno, is_int, is_hw, -1); } dpl = (e2 DESC_DPL_SHIFT) 3; cpl = env-hflags HF_CPL_MASK; /* check privledge if software int */ if (is_int dpl cpl) -raise_exception_err(EXCP0D_GPF, intno * 16 + 2); +raise_gpf(intno, is_int, is_hw, -1); /* check valid bit */ if (!(e2 DESC_P_MASK)) raise_exception_err(EXCP0B_NOSEG, intno * 16 + 2); @@ -887,19 +897,19 @@ offset = ((target_ulong)e3 32) | (e2 0x) | (e1 0x); ist = e2 7; if ((selector 0xfffc) == 0) -raise_exception_err(EXCP0D_GPF, 0); +raise_gpf(intno, is_int, is_hw, 0); if (load_segment(e1, e2, selector) != 0) -raise_exception_err(EXCP0D_GPF, selector 0xfffc); +raise_gpf(intno, is_int, is_hw, selector 0xfffc); if (!(e2 DESC_S_MASK) || !(e2 (DESC_CS_MASK))) -raise_exception_err(EXCP0D_GPF, selector 0xfffc); +raise_gpf(intno, is_int, is_hw, selector 0xfffc); dpl = (e2 DESC_DPL_SHIFT) 3; if (dpl cpl) -raise_exception_err(EXCP0D_GPF, selector 0xfffc); +raise_gpf(intno, is_int, is_hw, selector 0xfffc); if (!(e2 DESC_P_MASK
[Qemu-devel] Patch: ltr for x86_64 should check the upper descriptor type
The Intel manual states for LTR and 64-Bit Exceptions: #GP(selector) If the descriptor type of the upper 8-byte of the 16-byte descriptor is non-zero. Qemu currently does not check this. The attached patch fixes the bug. Bernhard Kauer --- helper.c.orig 2007-03-26 15:39:11.0 +0200 +++ helper.c2007-03-26 15:40:27.0 +0200 @@ -1825,8 +1825,11 @@ raise_exception_err(EXCP0B_NOSEG, selector 0xfffc); #ifdef TARGET_X86_64 if (env-hflags HF_LMA_MASK) { -uint32_t e3; +uint32_t e3, e4; e3 = ldl_kernel(ptr + 8); + e4 = ldl_kernel(ptr + 12); + if ((e4 DESC_TYPE_SHIFT) 0xf) + raise_exception_err(EXCP0D_GPF, selector 0xfffc); load_seg_cache_raw_dt(env-tr, e1, e2); env-tr.base |= (target_ulong)e3 32; } else
Re: [Qemu-devel] Patch: ltr for x86_64 should check the upper descriptor type
On Mon, Mar 26, 2007 at 01:54:43PM +, Julian Seward wrote: Does this fix some specific bug you encountered? I have some code here that runs on Qemu but not on real hardware due to this missing check. Bernhard On Monday 26 March 2007 14:53, Bernhard Kauer wrote: The Intel manual states for LTR and 64-Bit Exceptions: #GP(selector) If the descriptor type of the upper 8-byte of the 16-byte descriptor is non-zero. Qemu currently does not check this. The attached patch fixes the bug.
[Qemu-devel] [PATCH] TPM TIS device model
This patch adds a TIS device model for a v1.2 TPM to qemu. It is based on the Xen patch from IBM and adopted by removing the Xen-specific stuff. It works with the tpmd daemon of the tpm-emulator package. The following things are still missing: * locality support * cmdline option for the socket name Greetings, Bernhard Kauer diff -N -r -u qemu.old/Makefile.target qemu/Makefile.target --- qemu.old/Makefile.target2007-03-09 02:46:14.024009410 +0100 +++ qemu/Makefile.target2007-03-09 01:03:53.0 +0100 @@ -372,6 +372,7 @@ VL_OBJS+= fdc.o mc146818rtc.o serial.o i8259.o i8254.o pcspk.o pc.o VL_OBJS+= cirrus_vga.o mixeng.o apic.o parallel.o acpi.o piix_pci.o VL_OBJS+= usb-uhci.o smbus_eeprom.o +VL_OBJS+= tpm_tis.o CPPFLAGS += -DHAS_AUDIO endif ifeq ($(TARGET_BASE_ARCH), ppc) diff -N -r -u qemu.old/hw/pc.c qemu/hw/pc.c --- qemu.old/hw/pc.c2007-03-09 02:46:14.424026396 +0100 +++ qemu/hw/pc.c2007-03-09 01:14:26.507262699 +0100 @@ -734,6 +734,9 @@ if (i440fx_state) { i440fx_init_memory_mappings(i440fx_state); } + +tpm_tis_init(); + #if 0 /* ??? Need to figure out some way for the user to specify SCSI devices. */ diff -N -r -u qemu.old/hw/tpm_tis.c qemu/hw/tpm_tis.c --- qemu.old/hw/tpm_tis.c 1970-01-01 01:00:00.0 +0100 +++ qemu/hw/tpm_tis.c 2007-03-09 02:59:13.801196995 +0100 @@ -0,0 +1,992 @@ +/* + * tpm_tis.c - QEMU emulator for a 1.2 TPM with TIS interface + * + * Copyright (C) 2006 IBM Corporation + * + * Author: Stefan Berger [EMAIL PROTECTED] + * David Safford [EMAIL PROTECTED] + * Adopted for Qemu: Bernhard Kauer [EMAIL PROTECTED] + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, version 2 of the + * License. + * + * + * Implementation of the TIS interface according to specs at + * https://www.trustedcomputinggroup.org/groups/pc_client/TCG_PCClientTPMSpecification_1-20_1-00_FINAL.pdf + * + */ + +#include sys/types.h +#include sys/stat.h +#include sys/socket.h +#include sys/un.h +#include fcntl.h +#include errno.h +#include vl.h + +#define DEBUG_TPM +#define logfile stderr + +#define TPM_MAX_PKT 4096 + +#define VTPM_BAD_INSTANCE (uint32_t)0x + +#define TIS_ADDR_BASE 0xFED4 + +/* tis registers */ +#define TPM_REG_ACCESS0x00 +#define TPM_REG_INT_ENABLE0x08 +#define TPM_REG_INT_VECTOR0x0c +#define TPM_REG_INT_STATUS0x10 +#define TPM_REG_INTF_CAPABILITY 0x14 +#define TPM_REG_STS 0x18 +#define TPM_REG_DATA_FIFO 0x24 +#define TPM_REG_DID_VID 0xf00 +#define TPM_REG_RID 0xf04 + +#define STS_VALID(1 7) +#define STS_COMMAND_READY(1 6) +#define STS_TPM_GO (1 5) +#define STS_DATA_AVAILABLE (1 4) +#define STS_EXPECT (1 3) +#define STS_RESPONSE_RETRY (1 1) + +#define ACCESS_TPM_REG_VALID_STS (1 7) +#define ACCESS_ACTIVE_LOCALITY (1 5) +#define ACCESS_BEEN_SEIZED (1 4) +#define ACCESS_SEIZE (1 3) +#define ACCESS_PENDING_REQUEST (1 2) +#define ACCESS_REQUEST_USE (1 1) +#define ACCESS_TPM_ESTABLISHMENT (1 0) + +#define INT_ENABLED (1 31) +#define INT_DATA_AVAILABLE (1 0) +#define INT_LOCALITY_CHANGED (1 2) +#define INT_COMMAND_READY(1 7) + +#define INTERRUPTS_SUPPORTED (INT_LOCALITY_CHANGED | \ + INT_DATA_AVAILABLE | \ + INT_COMMAND_READY) +#define CAPABILITIES_SUPPORTED ((1 4) |\ + INTERRUPTS_SUPPORTED) + +enum { + STATE_IDLE = 0, + STATE_READY, + STATE_COMPLETION, + STATE_EXECUTION, + STATE_RECEPTION +}; + +#define NUM_LOCALITIES 5 +#define NO_LOCALITY 0xff + +#define IS_VALID_LOC(x) ((x) NUM_LOCALITIES) + +#define TPM_DID 0x0001 +#define TPM_VID 0x0001 +#define TPM_RID 0x0001 + +/* if the connection to the vTPM should be closed after a successfully + received response; set to '0' to allow keeping the connection */ +#define FORCE_CLOSE 0 + +/* local data structures */ + +typedef struct TPMTx { +int fd[2]; +} tpmTx; + +typedef struct TPMBuffer { +uint8_t instance[4]; /* instance number in network byte order */ +uint8_t buf[TPM_MAX_PKT]; +} __attribute__((packed)) tpmBuffer; + +/* locality data */ +typedef struct TPMLocal { +uint32_t state; +uint8_t access; +uint8_t sts; +uint32_t inte; +uint32_t ints; +} tpmLoc; + +/* overall state of the TPM interface; 's' marks as save upon suspension */ +typedef struct TPMState { +uint32_t offset;/* s */ +tpmBuffer buffer
[Qemu-devel] [PATCH] i386 return APIC ID with cpuid
Hi, cpuid(01H) on i386 does not return the initial APIC id. The following patch correct this. Bernhard Kauer Index: hw/apic.c === RCS file: /sources/qemu/qemu/hw/apic.c,v retrieving revision 1.12 diff -u -r1.12 apic.c --- hw/apic.c 31 Jan 2007 12:22:18 - 1.12 +++ hw/apic.c 20 Mar 2007 22:13:09 - @@ -816,6 +816,7 @@ env-apic_state = s; apic_init_ipi(s); s-id = last_apic_id++; +env-cpuid_apic_id = s-id; s-cpu_env = env; s-apicbase = 0xfee0 | (s-id ? 0 : MSR_IA32_APICBASE_BSP) | MSR_IA32_APICBASE_ENABLE; Index: target-i386/cpu.h === RCS file: /sources/qemu/qemu/target-i386/cpu.h,v retrieving revision 1.41 diff -u -r1.41 cpu.h --- target-i386/cpu.h 5 Feb 2007 22:06:27 - 1.41 +++ target-i386/cpu.h 20 Mar 2007 22:13:09 - @@ -529,6 +529,7 @@ uint32_t cpuid_xlevel; uint32_t cpuid_model[12]; uint32_t cpuid_ext2_features; +uint32_t cpuid_apic_id; #ifdef USE_KQEMU int kqemu_enabled; Index: target-i386/helper.c === RCS file: /sources/qemu/qemu/target-i386/helper.c,v retrieving revision 1.74 diff -u -r1.74 helper.c --- target-i386/helper.c1 Feb 2007 22:12:19 - 1.74 +++ target-i386/helper.c20 Mar 2007 22:13:10 - @@ -1614,7 +1614,7 @@ break; case 1: EAX = env-cpuid_version; -EBX = 8 8; /* CLFLUSH size in quad words, Linux wants it. */ +EBX = (env-cpuid_apic_id 24) | 8 8; /* CLFLUSH size in quad words, Linux wants it. */ ECX = env-cpuid_ext_features; EDX = env-cpuid_features; break; ___ Qemu-devel mailing list Qemu-devel@nongnu.org http://lists.nongnu.org/mailman/listinfo/qemu-devel
[Qemu-devel] [PATCH] TPM TIS device model
This patch adds a TIS device model for a v1.2 TPM to qemu. It is based on the Xen patch from IBM and adopted by removing the Xen-specific stuff. It works with the tpmd daemon of the tpm-emulator package. The following things are still missing: * locality support * cmdline option for the socket name Greetings, Bernhard Kauer diff -N -r -u qemu.old/Makefile.target qemu/Makefile.target --- qemu.old/Makefile.target2007-03-09 02:46:14.024009410 +0100 +++ qemu/Makefile.target2007-03-09 01:03:53.0 +0100 @@ -372,6 +372,7 @@ VL_OBJS+= fdc.o mc146818rtc.o serial.o i8259.o i8254.o pcspk.o pc.o VL_OBJS+= cirrus_vga.o mixeng.o apic.o parallel.o acpi.o piix_pci.o VL_OBJS+= usb-uhci.o smbus_eeprom.o +VL_OBJS+= tpm_tis.o CPPFLAGS += -DHAS_AUDIO endif ifeq ($(TARGET_BASE_ARCH), ppc) diff -N -r -u qemu.old/hw/pc.c qemu/hw/pc.c --- qemu.old/hw/pc.c2007-03-09 02:46:14.424026396 +0100 +++ qemu/hw/pc.c2007-03-09 01:14:26.507262699 +0100 @@ -734,6 +734,9 @@ if (i440fx_state) { i440fx_init_memory_mappings(i440fx_state); } + +tpm_tis_init(); + #if 0 /* ??? Need to figure out some way for the user to specify SCSI devices. */ diff -N -r -u qemu.old/hw/tpm_tis.c qemu/hw/tpm_tis.c --- qemu.old/hw/tpm_tis.c 1970-01-01 01:00:00.0 +0100 +++ qemu/hw/tpm_tis.c 2007-03-09 02:59:13.801196995 +0100 @@ -0,0 +1,992 @@ +/* + * tpm_tis.c - QEMU emulator for a 1.2 TPM with TIS interface + * + * Copyright (C) 2006 IBM Corporation + * + * Author: Stefan Berger [EMAIL PROTECTED] + * David Safford [EMAIL PROTECTED] + * Adopted for Qemu: Bernhard Kauer [EMAIL PROTECTED] + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, version 2 of the + * License. + * + * + * Implementation of the TIS interface according to specs at + * https://www.trustedcomputinggroup.org/groups/pc_client/TCG_PCClientTPMSpecification_1-20_1-00_FINAL.pdf + * + */ + +#include sys/types.h +#include sys/stat.h +#include sys/socket.h +#include sys/un.h +#include fcntl.h +#include errno.h +#include vl.h + +#define DEBUG_TPM +#define logfile stderr + +#define TPM_MAX_PKT 4096 + +#define VTPM_BAD_INSTANCE (uint32_t)0x + +#define TIS_ADDR_BASE 0xFED4 + +/* tis registers */ +#define TPM_REG_ACCESS0x00 +#define TPM_REG_INT_ENABLE0x08 +#define TPM_REG_INT_VECTOR0x0c +#define TPM_REG_INT_STATUS0x10 +#define TPM_REG_INTF_CAPABILITY 0x14 +#define TPM_REG_STS 0x18 +#define TPM_REG_DATA_FIFO 0x24 +#define TPM_REG_DID_VID 0xf00 +#define TPM_REG_RID 0xf04 + +#define STS_VALID(1 7) +#define STS_COMMAND_READY(1 6) +#define STS_TPM_GO (1 5) +#define STS_DATA_AVAILABLE (1 4) +#define STS_EXPECT (1 3) +#define STS_RESPONSE_RETRY (1 1) + +#define ACCESS_TPM_REG_VALID_STS (1 7) +#define ACCESS_ACTIVE_LOCALITY (1 5) +#define ACCESS_BEEN_SEIZED (1 4) +#define ACCESS_SEIZE (1 3) +#define ACCESS_PENDING_REQUEST (1 2) +#define ACCESS_REQUEST_USE (1 1) +#define ACCESS_TPM_ESTABLISHMENT (1 0) + +#define INT_ENABLED (1 31) +#define INT_DATA_AVAILABLE (1 0) +#define INT_LOCALITY_CHANGED (1 2) +#define INT_COMMAND_READY(1 7) + +#define INTERRUPTS_SUPPORTED (INT_LOCALITY_CHANGED | \ + INT_DATA_AVAILABLE | \ + INT_COMMAND_READY) +#define CAPABILITIES_SUPPORTED ((1 4) |\ + INTERRUPTS_SUPPORTED) + +enum { + STATE_IDLE = 0, + STATE_READY, + STATE_COMPLETION, + STATE_EXECUTION, + STATE_RECEPTION +}; + +#define NUM_LOCALITIES 5 +#define NO_LOCALITY 0xff + +#define IS_VALID_LOC(x) ((x) NUM_LOCALITIES) + +#define TPM_DID 0x0001 +#define TPM_VID 0x0001 +#define TPM_RID 0x0001 + +/* if the connection to the vTPM should be closed after a successfully + received response; set to '0' to allow keeping the connection */ +#define FORCE_CLOSE 0 + +/* local data structures */ + +typedef struct TPMTx { +int fd[2]; +} tpmTx; + +typedef struct TPMBuffer { +uint8_t instance[4]; /* instance number in network byte order */ +uint8_t buf[TPM_MAX_PKT]; +} __attribute__((packed)) tpmBuffer; + +/* locality data */ +typedef struct TPMLocal { +uint32_t state; +uint8_t access; +uint8_t sts; +uint32_t inte; +uint32_t ints; +} tpmLoc; + +/* overall state of the TPM interface; 's' marks as save upon suspension */ +typedef struct TPMState { +uint32_t offset;/* s */ +tpmBuffer buffer