From: "Natalia Portillo" <claunia@claunia.com>
To: qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] expose host CPU features to guests: Take 2
Date: Mon, 10 Sep 2007 12:47:51 +0100 [thread overview]
Message-ID: <op.tyfsd1uusigcfk@hermes> (raw)
In-Reply-To: <20070910074005.GA26869@karma.qumranet.com>
I don't see in what is it useful without KVM/KQEMU.
And even with them there are some instructions that can't be accesible
without KQEMU/KVM prepared for them.
And, the -cpu option, should be enabled in x86 and x86_64 to
enable/disable emulation of instructions (and them cpuid adjusted to
indicate them).
Regards
On Mon, 10 Sep 2007 08:40:05 +0100, Dan Kenigsberg <danken@qumranet.com>
wrote:
> As with Take 1 of this patch, its purpose is to expose host CPU features
> to
> guests. It proved rather helpful to KVM in various benchmarks, and it
> should
> similarly speed kqemu up. Note that it does not extend the set of
> emulated
> opcodes, only exposes what's supported by the host CPU.
>
> I changed the patch according to the comments on these mailing lists.
> Thanks
> for your suggestions. Changes since "take 1" are:
> - Use the new -cpu option to specify cpu features.
> - Read host cpuid directly, instead of parsing /proc/cpuinfo. This
> approach is
> less Linux-centric and should work with other OSs too. It means
> however, that
> the cpuid is not checked for old CPU bugs. In the future, qemu should
> negotiate the actually-supported features with the virutalizing kernel
> module.
>
> Index: hw/pc.c
> ===================================================================
> RCS file: /sources/qemu/qemu/hw/pc.c,v
> retrieving revision 1.83
> diff -u -r1.83 pc.c
> --- hw/pc.c 26 Aug 2007 17:51:39 -0000 1.83
> +++ hw/pc.c 10 Sep 2007 06:54:00 -0000
> @@ -666,7 +666,7 @@
> DisplayState *ds, const char **fd_filename, int
> snapshot,
> const char *kernel_filename, const char
> *kernel_cmdline,
> const char *initrd_filename,
> - int pci_enabled)
> + int pci_enabled, char *cpu_model)
> {
> char buf[1024];
> int ret, linux_boot, i;
> @@ -683,7 +683,9 @@
> /* init CPUs */
> for(i = 0; i < smp_cpus; i++) {
> + void apply_i386_cpu_model(CPUX86State *env, char *cpu_model);
> env = cpu_init();
> + apply_i386_cpu_model(env, cpu_model);
> if (i != 0)
> env->hflags |= HF_HALTED_MASK;
> if (smp_cpus > 1) {
> @@ -948,7 +950,7 @@
> pc_init1(ram_size, vga_ram_size, boot_device,
> ds, fd_filename, snapshot,
> kernel_filename, kernel_cmdline,
> - initrd_filename, 1);
> + initrd_filename, 1, cpu_model);
> }
> static void pc_init_isa(int ram_size, int vga_ram_size, int boot_device,
> @@ -962,7 +964,7 @@
> pc_init1(ram_size, vga_ram_size, boot_device,
> ds, fd_filename, snapshot,
> kernel_filename, kernel_cmdline,
> - initrd_filename, 0);
> + initrd_filename, 0, cpu_model);
> }
> QEMUMachine pc_machine = {
> Index: target-i386/cpu.h
> ===================================================================
> RCS file: /sources/qemu/qemu/target-i386/cpu.h,v
> retrieving revision 1.45
> diff -u -r1.45 cpu.h
> --- target-i386/cpu.h 11 Jul 2007 22:48:58 -0000 1.45
> +++ target-i386/cpu.h 10 Sep 2007 06:54:00 -0000
> @@ -267,21 +267,44 @@
> #define CPUID_CMOV (1 << 15)
> #define CPUID_PAT (1 << 16)
> #define CPUID_PSE36 (1 << 17)
> +#define CPUID_PN (1 << 18)
> #define CPUID_CLFLUSH (1 << 19)
> -/* ... */
> +#define CPUID_DTS (1 << 21)
> +#define CPUID_ACPI (1 << 22)
> #define CPUID_MMX (1 << 23)
> #define CPUID_FXSR (1 << 24)
> #define CPUID_SSE (1 << 25)
> #define CPUID_SSE2 (1 << 26)
> +#define CPUID_SS (1 << 27)
> +#define CPUID_HT (1 << 28)
> +#define CPUID_TM (1 << 29)
> +#define CPUID_IA64 (1 << 30)
> +#define CPUID_PBE (1 << 31)
> #define CPUID_EXT_SSE3 (1 << 0)
> #define CPUID_EXT_MONITOR (1 << 3)
> +#define CPUID_EXT_DSCPL (1 << 4)
> +#define CPUID_EXT_VMX (1 << 5)
> +#define CPUID_EXT_SMX (1 << 6)
> +#define CPUID_EXT_EST (1 << 7)
> +#define CPUID_EXT_TM2 (1 << 8)
> +#define CPUID_EXT_SSSE3 (1 << 9)
> +#define CPUID_EXT_CID (1 << 10)
> #define CPUID_EXT_CX16 (1 << 13)
> +#define CPUID_EXT_XTPR (1 << 14)
> +#define CPUID_EXT_DCA (1 << 17)
> +#define CPUID_EXT_POPCNT (1 << 22)
> #define CPUID_EXT2_SYSCALL (1 << 11)
> +#define CPUID_EXT2_MP (1 << 19)
> #define CPUID_EXT2_NX (1 << 20)
> +#define CPUID_EXT2_MMXEXT (1 << 22)
> #define CPUID_EXT2_FFXSR (1 << 25)
> +#define CPUID_EXT2_PDPE1GB (1 << 26)
> +#define CPUID_EXT2_RDTSCP (1 << 27)
> #define CPUID_EXT2_LM (1 << 29)
> +#define CPUID_EXT2_3DNOWEXT (1 << 30)
> +#define CPUID_EXT2_3DNOW (1 << 31)
> #define EXCP00_DIVZ 0
> #define EXCP01_SSTP 1
> Index: target-i386/helper2.c
> ===================================================================
> RCS file: /sources/qemu/qemu/target-i386/helper2.c,v
> retrieving revision 1.48
> diff -u -r1.48 helper2.c
> --- target-i386/helper2.c 31 Jul 2007 23:09:18 -0000 1.48
> +++ target-i386/helper2.c 10 Sep 2007 06:54:00 -0000
> @@ -45,40 +45,8 @@
> #endif
> #endif /* USE_CODE_COPY */
> -CPUX86State *cpu_x86_init(void)
> +static int set_guest_cpu_basic(CPUX86State *env)
> {
> - CPUX86State *env;
> - static int inited;
> -
> - env = qemu_mallocz(sizeof(CPUX86State));
> - if (!env)
> - return NULL;
> - cpu_exec_init(env);
> -
> - /* init various static tables */
> - if (!inited) {
> - inited = 1;
> - optimize_flags_init();
> - }
> -#ifdef USE_CODE_COPY
> - /* testing code for code copy case */
> - {
> - struct modify_ldt_ldt_s ldt;
> -
> - ldt.entry_number = 1;
> - ldt.base_addr = (unsigned long)env;
> - ldt.limit = (sizeof(CPUState) + 0xfff) >> 12;
> - ldt.seg_32bit = 1;
> - ldt.contents = MODIFY_LDT_CONTENTS_DATA;
> - ldt.read_exec_only = 0;
> - ldt.limit_in_pages = 1;
> - ldt.seg_not_present = 0;
> - ldt.useable = 1;
> - modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */
> -
> - asm volatile ("movl %0, %%fs" : : "r" ((1 << 3) | 7));
> - }
> -#endif
> {
> int family, model, stepping;
> #ifdef TARGET_X86_64
> @@ -114,19 +82,7 @@
> env->cpuid_ext_features = CPUID_EXT_SSE3;
> env->cpuid_features |= CPUID_FXSR | CPUID_MMX | CPUID_SSE |
> CPUID_SSE2 | CPUID_PAE | CPUID_SEP;
> env->cpuid_features |= CPUID_APIC;
> - env->cpuid_xlevel = 0;
> - {
> - const char *model_id = "QEMU Virtual CPU version "
> QEMU_VERSION;
> - int c, len, i;
> - len = strlen(model_id);
> - for(i = 0; i < 48; i++) {
> - if (i >= len)
> - c = '\0';
> - else
> - c = model_id[i];
> - env->cpuid_model[i >> 2] |= c << (8 * (i & 3));
> - }
> - }
> + env->cpuid_xlevel = 0x80000006;
> #ifdef TARGET_X86_64
> /* currently not enabled for std i386 because not fully tested
> */
> env->cpuid_ext2_features = (env->cpuid_features & 0x0183F3FF);
> @@ -139,6 +95,239 @@
> env->cpuid_features |= CPUID_PSE36;
> #endif
> }
> +}
> +
> +static int host_cpuid (uint32_t function, uint32_t *ax,uint32_t *bx,
> uint32_t *cx, uint32_t *dx)
> +{
> + asm("cpuid"
> + : "=a" (*ax),
> + "=b" (*bx),
> + "=c" (*cx),
> + "=d" (*dx)
> + : "a" (function));
> +}
> +
> +static int set_guest_cpu_hostlike(CPUX86State *env) {
> + uint32_t ax, bx, cx, dx;
> + host_cpuid(0, &ax, &bx, &cx, &dx);
> + env->cpuid_level = 2; /* host real level is ax */
> + env->cpuid_vendor1 = bx;
> + env->cpuid_vendor2 = dx;
> + env->cpuid_vendor3 = cx;
> +
> + host_cpuid(1, &ax, &bx, &cx, &dx);
> + env->cpuid_version = ax;
> + env->cpuid_features = dx & ~CPUID_ACPI; /* acpi panics linux guests
> */
> + env->cpuid_ext_features = cx & ~CPUID_EXT_VMX; /* vmx is not
> recursive */
> +
> + /* cpuid(0x80000000, &ax, &bx, &cx, &dx); */
> + env->cpuid_xlevel = 0x80000008;
> +
> + host_cpuid(0x80000001, &ax, &bx, &cx, &dx);
> + env->cpuid_ext2_features = dx;
> +
> + return 0;
> +}
> +
> +/* x86_cap_flags taken from Linux's arch/i386/kernel/cpu/proc.c */
> +static const char * const x86_cap_flags[] = {
> + /* Intel-defined */
> + "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
> + "cx8", "apic", NULL, "sep", "mtrr", "pge", "mca", "cmov",
> + "pat", "pse36", "pn", "clflush", NULL, "dts", "acpi", "mmx",
> + "fxsr", "sse", "sse2", "ss", "ht", "tm", "ia64", "pbe",
> +
> + /* AMD-defined */
> + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
> + NULL, NULL, NULL, "syscall", NULL, NULL, NULL, NULL,
> + NULL, NULL, NULL, "mp", "nx", NULL, "mmxext", NULL,
> + NULL, "fxsr_opt", "pdpe1gb", "rdtscp", NULL, "lm", "3dnowext", "3dnow",
> +
> + /* Transmeta-defined */
> + "recovery", "longrun", NULL, "lrti", NULL, NULL, NULL, NULL,
> + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
> + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
> + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
> +
> + /* Other (Linux-defined) */
> + "cxmmx", "k6_mtrr", "cyrix_arr", "centaur_mcr",
> + NULL, NULL, NULL, NULL,
> + "constant_tsc", "up", NULL, NULL, NULL, NULL, NULL, NULL,
> + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
> + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
> +
> + /* Intel-defined (#2) */
> + "pni", NULL, NULL, "monitor", "ds_cpl", "vmx", "smx", "est",
> + "tm2", "ssse3", "cid", NULL, NULL, "cx16", "xtpr", NULL,
> + NULL, NULL, "dca", NULL, NULL, NULL, NULL, "popcnt",
> + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
> +
> + /* VIA/Cyrix/Centaur-defined */
> + NULL, NULL, "rng", "rng_en", NULL, NULL, "ace", "ace_en",
> + "ace2", "ace2_en", "phe", "phe_en", "pmm", "pmm_en", NULL, NULL,
> + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
> + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
> +
> + /* AMD-defined (#2) */
> + "lahf_lm", "cmp_legacy", "svm", "extapic", "cr8legacy", "abm",
> + "sse4a", "misalignsse",
> + "3dnowprefetch", "osvw", "ibs", NULL, NULL, NULL, NULL, NULL,
> + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
> + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
> +};
> +
> +void add_flagname_to_bitmaps(char *flagname, int *features, int
> *ext_features, int *ext2_features)
> +{
> + int i;
> + for ( i = 0 ; i < 32 ; i++ )
> + if (x86_cap_flags[i] && !strcmp (flagname, x86_cap_flags[i])) {
> + *features |= 1 << i;
> + return;
> + }
> + for ( i = 0 ; i < 32 ; i++ )
> + if (x86_cap_flags[32*4+i] && !strcmp (flagname,
> x86_cap_flags[32*4+i])) {
> + *ext_features |= 1 << i;
> + return;
> + }
> + for ( i = 0 ; i < 32 ; i++ )
> + if (x86_cap_flags[32*1+i] && !strcmp (flagname,
> x86_cap_flags[32*1+i])) {
> + *ext2_features |= 1 << i;
> + return;
> + }
> + /* Silently ignore Linux-defined features */
> + for ( i = 0 ; i < 32 ; i++ )
> + if (x86_cap_flags[32*3+i] && !strcmp (flagname,
> x86_cap_flags[32*3+i])) {
> + return;
> + }
> + fprintf(stderr, "CPU feature %s not found\n", flagname);
> +}
> +
> +
> +void apply_i386_cpu_model(CPUX86State *env, char *cpu_model)
> +{
> + int plus_features = 0, plus_ext_features = 0, plus_ext2_features =
> 0;
> + int minus_features = 0, minus_ext_features = 0, minus_ext2_features
> = 0;
> + int family = -1, model = -1, stepping = -1;
> +
> + char *s, *featurestr;
> +
> + if (!cpu_model)
> + cpu_model = "host";
> +
> + s = strdup(cpu_model);
> +
> + strtok(s, ",");
> + if (!strcmp(s, "basic"))
> + set_guest_cpu_basic(env);
> + else if (!strcmp(s, "host"))
> + set_guest_cpu_hostlike(env);
> + else {
> + printf("Available CPUs:\n");
> + printf("(basic|host)[,(+feature|-feature|feature=xyz)]...\n");
> + exit(1);
> + }
> +
> + featurestr = strtok(NULL, ",");
> + while (featurestr) {
> + char *val;
> + if (featurestr[0] == '+') {
> + add_flagname_to_bitmaps(featurestr + 1, &plus_features,
> &plus_ext_features, &plus_ext2_features);
> + }
> + else if (featurestr[0] == '-') {
> + add_flagname_to_bitmaps(featurestr + 1, &minus_features,
> &minus_ext_features, &minus_ext2_features);
> + }
> + else if ((val = strchr(featurestr, '='))) {
> + *val = 0; val++;
> + if (!strcmp(featurestr, "family")) {
> + family = atoi(val);
> + if (family <= 0) {
> + fprintf(stderr, "bad numerical value %s\n", val);
> + exit(1);
> + }
> + env->cpuid_version &= 0xFF;
> + env->cpuid_version |= (family << 8);
> + } else if (!strcmp(featurestr, "model")) {
> + model = atoi(val);
> + if (model <= 0) {
> + fprintf(stderr, "bad numerical value %s\n", val);
> + exit(1);
> + }
> + env->cpuid_version &= 0xFFFFFF0F;
> + env->cpuid_version |= (model << 4);
> + } else if (!strcmp(featurestr, "stepping")) {
> + stepping = atoi(val);
> + if (stepping <= 0) {
> + fprintf(stderr, "bad numerical value %s\n", val);
> + exit(1);
> + }
> + env->cpuid_version &= 0xFFFFFFF0;
> + env->cpuid_version |= stepping;
> + } else {
> + fprintf(stderr, "unknown feature %s\n", featurestr);
> + exit(1);
> + }
> + } else {
> + fprintf(stderr, "feature string `%s' not in format
> (+feature|-feature|feature=xyz)\n", featurestr);
> + exit(1);
> + }
> + featurestr = strtok(NULL, ",");
> + }
> + free(s);
> + env->cpuid_features |= plus_features;
> + env->cpuid_ext_features |= plus_ext_features;
> + env->cpuid_ext2_features |= plus_ext2_features;
> + env->cpuid_features &= ~minus_features;
> + env->cpuid_ext_features &= ~minus_ext_features;
> + env->cpuid_ext2_features &= ~minus_ext2_features;
> +
> + {
> + const char *model_id = "QEMU Virtual CPU version " QEMU_VERSION;
> + int c, len, i;
> + len = strlen(model_id);
> + for(i = 0; i < 48; i++) {
> + if (i >= len)
> + c = '\0';
> + else
> + c = model_id[i];
> + env->cpuid_model[i >> 2] |= c << (8 * (i & 3));
> + }
> + }
> +}
> +
> +CPUX86State *cpu_x86_init(void)
> +{
> + CPUX86State *env;
> + static int inited;
> +
> + env = qemu_mallocz(sizeof(CPUX86State));
> + if (!env)
> + return NULL;
> + cpu_exec_init(env);
> +
> + /* init various static tables */
> + if (!inited) {
> + inited = 1;
> + optimize_flags_init();
> + }
> +#ifdef USE_CODE_COPY
> + /* testing code for code copy case */
> + {
> + struct modify_ldt_ldt_s ldt;
> +
> + ldt.entry_number = 1;
> + ldt.base_addr = (unsigned long)env;
> + ldt.limit = (sizeof(CPUState) + 0xfff) >> 12;
> + ldt.seg_32bit = 1;
> + ldt.contents = MODIFY_LDT_CONTENTS_DATA;
> + ldt.read_exec_only = 0;
> + ldt.limit_in_pages = 1;
> + ldt.seg_not_present = 0;
> + ldt.useable = 1;
> + modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */
> +
> + asm volatile ("movl %0, %%fs" : : "r" ((1 << 3) | 7));
> + }
> +#endif
> cpu_reset(env);
> #ifdef USE_KQEMU
> kqemu_init(env);
>
>
>
--
Using Opera's revolutionary e-mail client: http://www.opera.com/mail/
next prev parent reply other threads:[~2007-09-10 11:48 UTC|newest]
Thread overview: 43+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-09-05 17:45 [Qemu-devel] expose host CPU features to guests danken
2007-09-05 19:26 ` [Qemu-devel] Re: [kvm-devel] " Anthony Liguori
2007-09-05 19:34 ` Avi Kivity
2007-09-05 19:44 ` Daniel P. Berrange
2007-09-06 0:30 ` Paul Brook
2007-09-06 8:46 ` Avi Kivity
2007-09-07 10:47 ` Jamie Lokier
2007-09-09 7:51 ` [kvm-devel] [Qemu-devel] " Avi Kivity
2007-09-09 12:47 ` Jamie Lokier
2007-09-09 12:55 ` Avi Kivity
2007-09-09 13:07 ` Jamie Lokier
2007-09-09 13:14 ` Avi Kivity
2007-09-09 15:25 ` Paul Brook
2007-09-09 15:29 ` Avi Kivity
2007-09-09 15:47 ` Jamie Lokier
2007-09-09 16:12 ` Paul Brook
2007-09-09 16:38 ` Avi Kivity
2007-09-10 16:53 ` Jamie Lokier
2007-09-10 7:40 ` [Qemu-devel] expose host CPU features to guests: Take 2 Dan Kenigsberg
2007-09-10 11:47 ` Natalia Portillo [this message]
2007-09-10 12:01 ` Dan Kenigsberg
2007-09-07 16:18 ` Natalia Portillo
2007-09-11 19:48 ` Luke -Jr
2007-09-10 17:16 ` Jamie Lokier
2007-09-24 17:41 ` [Qemu-devel] expose host CPU features to guests: Take 3 Dan Kenigsberg
2007-09-25 1:28 ` andrzej zaborowski
2007-09-25 8:48 ` [kvm-devel] " Dan Kenigsberg
2007-09-25 9:01 ` Avi Kivity
2007-09-25 9:19 ` J. Mayer
2007-09-25 9:31 ` Avi Kivity
2007-09-25 10:40 ` Avi Kivity
2007-09-25 11:09 ` J. Mayer
2007-09-25 11:36 ` Avi Kivity
2007-09-25 12:05 ` Fabrice Bellard
2007-09-25 13:07 ` Jocelyn Mayer
2007-09-25 13:12 ` Avi Kivity
2007-09-25 13:27 ` Dan Kenigsberg
2007-09-25 15:54 ` Jamie Lokier
2007-09-25 16:15 ` Avi Kivity
2007-09-25 12:51 ` Paul Brook
2007-09-25 13:13 ` Avi Kivity
2007-09-25 9:29 ` Fabrice Bellard
2007-10-07 12:38 ` [Qemu-devel] x86 -cpu option: Take 4 Dan Kenigsberg
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=op.tyfsd1uusigcfk@hermes \
--to=claunia@claunia.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).