From patchwork Sun Jan 15 15:39:38 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josh Triplett X-Patchwork-Id: 136191 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [140.186.70.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 50621B6F68 for ; Mon, 16 Jan 2012 02:40:26 +1100 (EST) Received: from localhost ([::1]:54311 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RmSBz-0001Xa-I7 for incoming@patchwork.ozlabs.org; Sun, 15 Jan 2012 10:40:23 -0500 Received: from eggs.gnu.org ([140.186.70.92]:43002) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RmSBl-0001Vr-Ny for qemu-devel@nongnu.org; Sun, 15 Jan 2012 10:40:15 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1RmSBe-0007JG-RN for qemu-devel@nongnu.org; Sun, 15 Jan 2012 10:40:09 -0500 Received: from relay4-d.mail.gandi.net ([217.70.183.196]:55622) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RmSBe-0007EE-CD for qemu-devel@nongnu.org; Sun, 15 Jan 2012 10:40:02 -0500 Received: from leaf (unknown [IPv6:2405:4600:3004:0:f2de:f1ff:fea1:dfe7]) (Authenticated sender: josh@joshtriplett.org) by relay4-d.mail.gandi.net (Postfix) with ESMTPSA id DF51A17209C; Sun, 15 Jan 2012 16:39:42 +0100 (CET) Date: Mon, 16 Jan 2012 02:39:38 +1100 From: Josh Triplett To: qemu-devel@nongnu.org Message-ID: <97b7217405af678e1dda6836b25b38e0cf0bbcf2.1326641605.git.josh@joshtriplett.org> References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.5.21 (2010-09-15) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6 (newer, 3) X-Received-From: 217.70.183.196 Cc: Anthony Liguori , Paul Brook Subject: [Qemu-devel] [PATCH 1/3] Add cpudef option to GPF on unknown MSRs X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org qemu normally returns 0 for rdmsr of an unknown MSR, and silently ignores wrmsr of an unknown MSR. Add a new msr_gpf option to cpudef, which when enabled causes qemu to generate a GPF on any access to an unknown MSR. This option allows qemu to better support software which detects the availability of MSRs and their associated features by handling GPFs. Signed-off-by: Josh Triplet --- qemu-config.c | 3 +++ target-i386/cpu.h | 1 + target-i386/cpuid.c | 9 +++++++++ target-i386/op_helper.c | 16 ++++++++++++---- 4 files changed, 25 insertions(+), 4 deletions(-) diff --git a/qemu-config.c b/qemu-config.c index ecc88e8..8f9f16e 100644 --- a/qemu-config.c +++ b/qemu-config.c @@ -416,6 +416,9 @@ static QemuOptsList qemu_cpudef_opts = { },{ .name = "vendor_override", .type = QEMU_OPT_NUMBER, + },{ + .name = "msr_gpf", + .type = QEMU_OPT_BOOL, }, { /* end of list */ } }, diff --git a/target-i386/cpu.h b/target-i386/cpu.h index 37dde79..c37cb30 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -734,6 +734,7 @@ typedef struct CPUX86State { /* Store the results of Centaur's CPUID instructions */ uint32_t cpuid_xlevel2; uint32_t cpuid_ext4_features; + bool msr_gpf; /* MTRRs */ uint64_t mtrr_fixed[11]; diff --git a/target-i386/cpuid.c b/target-i386/cpuid.c index 91a104b..8cbbe9b 100644 --- a/target-i386/cpuid.c +++ b/target-i386/cpuid.c @@ -234,6 +234,7 @@ typedef struct x86_def_t { /* Store the results of Centaur's CPUID instructions */ uint32_t ext4_features; uint32_t xlevel2; + bool msr_gpf; } x86_def_t; #define I486_FEATURES (CPUID_FP87 | CPUID_VME | CPUID_PSE) @@ -547,6 +548,8 @@ static int cpu_x86_fill_host(x86_def_t *x86_cpu_def) */ x86_cpu_def->svm_features = -1; + x86_cpu_def->msr_gpf = false; + return 0; } @@ -842,6 +845,8 @@ void x86_cpu_list(FILE *f, fprintf_function cpu_fprintf, const char *optarg) 0); (*cpu_fprintf)(f, " extfeature_ecx %08x (%s)\n", def->ext3_features, buf); + if (def->msr_gpf) + (*cpu_fprintf)(f, " GPF on unknown MSRs\n"); (*cpu_fprintf)(f, "\n"); } } @@ -884,6 +889,7 @@ int cpu_x86_register (CPUX86State *env, const char *cpu_model) env->cpuid_svm_features = def->svm_features; env->cpuid_ext4_features = def->ext4_features; env->cpuid_xlevel2 = def->xlevel2; + env->msr_gpf = def->msr_gpf; env->tsc_khz = def->tsc_khz; if (!kvm_enabled()) { env->cpuid_features &= TCG_FEATURES; @@ -995,6 +1001,8 @@ static int cpudef_setfield(const char *name, const char *str, void *opaque) setfeatures(&def->ext3_features, str, ext3_feature_name, &err); } else if (!strcmp(name, "xlevel")) { setscalar(&def->xlevel, str, &err) + } else if (!strcmp(name, "msr_gpf")) { + /* Handled in cpudef_register */ } else { fprintf(stderr, "error: unknown option [%s = %s]\n", name, str); return (1); @@ -1013,6 +1021,7 @@ static int cpudef_register(QemuOpts *opts, void *opaque) x86_def_t *def = g_malloc0(sizeof (x86_def_t)); qemu_opt_foreach(opts, cpudef_setfield, def, 1); + def->msr_gpf = qemu_opt_get_bool(opts, "msr_gpf", false); def->next = x86_defs; x86_defs = def; return (0); diff --git a/target-i386/op_helper.c b/target-i386/op_helper.c index 2aea71b..f782f03 100644 --- a/target-i386/op_helper.c +++ b/target-i386/op_helper.c @@ -3292,7 +3292,10 @@ void helper_wrmsr(void) env->mce_banks[offset] = val; break; } - /* XXX: exception ? */ + if (env->msr_gpf) { + raise_exception(EXCP0D_GPF); + return; + } break; } } @@ -3400,8 +3403,10 @@ void helper_rdmsr(void) case MSR_MTRRcap: if (env->cpuid_features & CPUID_MTRR) val = MSR_MTRRcap_VCNT | MSR_MTRRcap_FIXRANGE_SUPPORT | MSR_MTRRcap_WC_SUPPORTED; - else - /* XXX: exception ? */ + else if (env->msr_gpf) { + raise_exception(EXCP0D_GPF); + return; + } else val = 0; break; case MSR_MCG_CAP: @@ -3426,7 +3431,10 @@ void helper_rdmsr(void) val = env->mce_banks[offset]; break; } - /* XXX: exception ? */ + if (env->msr_gpf) { + raise_exception(EXCP0D_GPF); + return; + } val = 0; break; }